Item 4 of #9860, scoped to the one claim that is currently unverified. Filed separately because #9860 explicitly asks for one independently-checkable change per PR rather than one big one.
The claim
packages/loopover-engine/src/focus-manifest.ts:
// Every top-level key `parseFocusManifest` below actually reads. Single source of truth for "unknown
// top-level field" detection (#9065) ...
export const FOCUS_MANIFEST_TOP_LEVEL_FIELDS = [ ... 28 entries ... ] as const;
That first sentence is a fact about the code twenty lines below it, and nothing enforces it. It is the same shape as the turbo.json inputs comment #9860 calls out as the tell — a snapshot presented as a guarantee.
Why it matters, in both directions
The list is the single source of truth for unknown-field detection, so drift is silent and asymmetric:
- Declared but never read → the parser accepts a field, reports no warning, and ignores it entirely. An operator writes it into
.loopover.yml, gets no error, and the setting does nothing. This is the worse direction: it looks configured.
- Read but not declared → the parser consumes the field while
parseFocusManifest warns "unknown top-level field" about it, and config-lint's recognizedFieldsFor omits it from the recognized count. A working field reported as a mistake.
Adding a top-level field means editing two places twenty lines apart, and #9813 and #9821 each shipped a bug from missing one touchpoint of a multi-touchpoint field.
It holds today
Computed over the current file: 28 declared, 28 read, empty in both directions. So this lands green and guards forward — the right moment to add it, rather than after the next drift.
Acceptance
Item 4 of #9860, scoped to the one claim that is currently unverified. Filed separately because #9860 explicitly asks for one independently-checkable change per PR rather than one big one.
The claim
packages/loopover-engine/src/focus-manifest.ts:That first sentence is a fact about the code twenty lines below it, and nothing enforces it. It is the same shape as the
turbo.jsoninputs comment #9860 calls out as the tell — a snapshot presented as a guarantee.Why it matters, in both directions
The list is the single source of truth for unknown-field detection, so drift is silent and asymmetric:
.loopover.yml, gets no error, and the setting does nothing. This is the worse direction: it looks configured.parseFocusManifestwarns "unknown top-level field" about it, andconfig-lint'srecognizedFieldsForomits it from the recognized count. A working field reported as a mistake.Adding a top-level field means editing two places twenty lines apart, and #9813 and #9821 each shipped a bug from missing one touchpoint of a multi-touchpoint field.
It holds today
Computed over the current file: 28 declared, 28 read, empty in both directions. So this lands green and guards forward — the right moment to add it, rather than after the next drift.
Acceptance
parseFocusManifestactually reads and compares them to the declared list, failing on either direction with the specific missing/extra field named.checkers-wired:checkwill enforce that).