⚠️ Definition of Done: this issue must be completed in full, in a single PR. Do not split this
work across multiple PRs, and do not defer any Deliverable below to a follow-up issue. A PR that
satisfies only some of the Deliverables, stubs a required test, or leaves a checkbox
partially-done does NOT resolve this issue and will be closed.
Context
resolveAmsPolicy() (packages/loopover-miner/lib/ams-policy.ts:18-22,53-63,74-88) returns a warnings: string[] specifically to surface a malformed .loopover-ams.yml field (per-field messages generated at packages/loopover-engine/src/ams-policy-spec.ts:163,170,179,188,195,213, e.g. AmsPolicySpec field "capLimits" must be a mapping; falling back to defaults.). .loopover-ams.yml.example explicitly documents "a single malformed field falls back to its default with a warning." But the only two real callers, packages/loopover-miner/lib/attempt-cli.ts (lines 693,758,775,874-875,995) and packages/loopover-miner/lib/loop-cli.ts (lines 309,434-437), read only .spec and discard .warnings/.source entirely -- never logged or printed. This contradicts the package's own stated design philosophy, honored elsewhere in the same package: discover-cli.ts:406 prints ai-policy warnings: ${result.warnings.length} and line 424 explicitly surfaces a goal-spec fallback rather than staying silent (README:43-44's documented rationale, "explicit rather than silent"). Additionally, readLocalAmsPolicyContent (ams-policy.ts:53-63) treats an unreadable existing file identically to an absent one (source: "default", warnings: [] either way), so a permissions error on an operator's real policy file is indistinguishable from never having configured one.
Requirements
Print amsPolicy.warnings (and .source) in both attempt's and loop's human-readable and --json output whenever .warnings is non-empty, matching discover-cli.ts's existing convention exactly (same phrasing style, same conditional-only-when-non-empty behavior).
Deliverables
All of the above Deliverables are required in the same PR unless the deliverable text itself states otherwise.
Test Coverage Requirements
packages/loopover-miner/** -- 99%+ patch coverage on both changed files, covering the non-empty-warnings branch in both human and JSON modes.
Expected Outcome
An operator with a malformed .loopover-ams.yml field sees an explicit warning in attempt/loop output instead of silently getting default behavior with no indication anything was wrong.
Links & Resources
packages/loopover-miner/lib/ams-policy.ts:18-22,53-63,74-88
packages/loopover-miner/lib/attempt-cli.ts:693,758,775,874-875,995
packages/loopover-miner/lib/loop-cli.ts:309,434-437
packages/loopover-miner/lib/discover-cli.ts:406,424
Context
resolveAmsPolicy()(packages/loopover-miner/lib/ams-policy.ts:18-22,53-63,74-88) returns awarnings: string[]specifically to surface a malformed.loopover-ams.ymlfield (per-field messages generated atpackages/loopover-engine/src/ams-policy-spec.ts:163,170,179,188,195,213, e.g.AmsPolicySpec field "capLimits" must be a mapping; falling back to defaults.)..loopover-ams.yml.exampleexplicitly documents "a single malformed field falls back to its default with a warning." But the only two real callers,packages/loopover-miner/lib/attempt-cli.ts(lines 693,758,775,874-875,995) andpackages/loopover-miner/lib/loop-cli.ts(lines 309,434-437), read only.specand discard.warnings/.sourceentirely -- never logged or printed. This contradicts the package's own stated design philosophy, honored elsewhere in the same package:discover-cli.ts:406printsai-policy warnings: ${result.warnings.length}and line 424 explicitly surfaces a goal-spec fallback rather than staying silent (README:43-44's documented rationale, "explicit rather than silent"). Additionally,readLocalAmsPolicyContent(ams-policy.ts:53-63) treats an unreadable existing file identically to an absent one (source: "default", warnings: []either way), so a permissions error on an operator's real policy file is indistinguishable from never having configured one.Requirements
Print
amsPolicy.warnings(and.source) in bothattempt's andloop's human-readable and--jsonoutput whenever.warningsis non-empty, matchingdiscover-cli.ts's existing convention exactly (same phrasing style, same conditional-only-when-non-empty behavior).Deliverables
attempt-cli.tsprints non-emptyamsPolicy.warningsin both human and--jsonoutput modesloop-cli.tsprints non-emptyamsPolicy.warningsin both human and--jsonoutput modes.loopover-ams.ymlfixture produces visible warning output (not just a silently-defaulted policy)All of the above Deliverables are required in the same PR unless the deliverable text itself states otherwise.
Test Coverage Requirements
packages/loopover-miner/**-- 99%+ patch coverage on both changed files, covering the non-empty-warnings branch in both human and JSON modes.Expected Outcome
An operator with a malformed
.loopover-ams.ymlfield sees an explicit warning inattempt/loopoutput instead of silently getting default behavior with no indication anything was wrong.Links & Resources
packages/loopover-miner/lib/ams-policy.ts:18-22,53-63,74-88packages/loopover-miner/lib/attempt-cli.ts:693,758,775,874-875,995packages/loopover-miner/lib/loop-cli.ts:309,434-437packages/loopover-miner/lib/discover-cli.ts:406,424