You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
⚠️ 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
packages/loopover-engine/src/focus-manifest-validation.ts's focusManifestToNormalizedJson
(lines 63-115) serializes every sub-config of a parsed FocusManifest into a plain JSON object,
using each sub-config's own *ConfigToJson function and only including it when non-null:
Every sub-config declared on FocusManifest goes through this pattern — gate, settings, review, features, contentLane, repoDocGeneration, reviewRecap, maintainerRecap, ops, publicStats, draftFlow, upstreamDriftIssues, sweepWatchdog, prReconciliation, activeReviewReconciliation, loopEscalation, federatedIntelligence, experimental, fairnessAnalytics — except publicProof. publicProofConfigToJson (exported from focus-manifest.ts at line 2535, the exact same { present, enabled } → JsonValue | null shape as
its sibling publicStatsConfigToJson) is never imported into focus-manifest-validation.ts and
never called. Grepping the file for publicProof returns zero matches.
focusManifestToNormalizedJson backs buildFocusManifestValidation — the offline validator behind
the loopover_validate_config MCP tool, the config-lint route, and the admin dry-run write path
(confirmed via focus-manifest-validation.ts's own imports/exports). Today, when an operator
configures publicProof: in their manifest and runs the validator to check what the manifest
actually resolves to, the publicProof block is silently absent from the normalized output — even
though parseFocusManifest parsed it correctly — giving the operator no visibility that the field
was recognized at all. Note this is distinct from config-lint.ts's lintManifestText, which uses
a separate known-field-name list that DOES include "publicProof" (line 4431 of focus-manifest.ts)
— so the warning-level check is unaffected; this issue is specifically about the normalized-JSON
output being incomplete.
Requirements
In packages/loopover-engine/src/focus-manifest-validation.ts, import publicProofConfigToJson
from ./focus-manifest.js alongside the other *ConfigToJson imports (lines 1-20).
In focusManifestToNormalizedJson, add the same pattern used for every other sub-config:
placed alongside the other sub-config serializations (position doesn't matter functionally, but
keep it grouped with the others for readability).
Do not change any other sub-config's serialization, and do not change publicProofConfigToJson/parsePublicProofConfig in focus-manifest.ts.
Deliverables
A manifest with publicProof: { enabled: true } produces a focusManifestToNormalizedJson
result whose publicProof field equals { enabled: true }.
A manifest with no publicProof block (or an invalid one that falls back to { present: false, enabled: false }) produces a result with no publicProof key at all — matching how every
other absent sub-config is already omitted rather than emitted as null/false.
Both Deliverables are required in this one PR — there is no narrower scope for this issue.
Test Coverage Requirements
packages/loopover-engine/src/** is measured by Codecov via two separate uploads whose hits are
unioned — root test/** AND packages/loopover-engine/test/**. Add the regression test to test/unit/focus-manifest-validation.test.ts (root-level, this file's existing test location),
asserting both Deliverables above against buildFocusManifestValidation's (or focusManifestToNormalizedJson's, whichever is exported/testable) actual output. Target 100% branch
coverage of the new serialization branch.
Expected Outcome
focusManifestToNormalizedJson's output includes publicProof whenever it is configured, matching
every other sub-config, so the offline validator (loopover_validate_config, the config-lint route,
the admin dry-run write path) gives an operator accurate visibility into a configured publicProof:
block.
packages/loopover-engine/src/focus-manifest.ts (line 2535 publicProofConfigToJson, line 4431
the separate known-field-name list already including "publicProof")
test/unit/focus-manifest-validation.test.ts
Related/adjacent gap in the same feature area: the issue filed alongside this one for parseFocusManifest's "no recognized fields" fallback also missing publicProof
Context
packages/loopover-engine/src/focus-manifest-validation.ts'sfocusManifestToNormalizedJson(lines 63-115) serializes every sub-config of a parsed
FocusManifestinto a plain JSON object,using each sub-config's own
*ConfigToJsonfunction and only including it when non-null:Every sub-config declared on
FocusManifestgoes through this pattern —gate,settings,review,features,contentLane,repoDocGeneration,reviewRecap,maintainerRecap,ops,publicStats,draftFlow,upstreamDriftIssues,sweepWatchdog,prReconciliation,activeReviewReconciliation,loopEscalation,federatedIntelligence,experimental,fairnessAnalytics— exceptpublicProof.publicProofConfigToJson(exported fromfocus-manifest.tsat line 2535, the exact same{ present, enabled } → JsonValue | nullshape asits sibling
publicStatsConfigToJson) is never imported intofocus-manifest-validation.tsandnever called. Grepping the file for
publicProofreturns zero matches.focusManifestToNormalizedJsonbacksbuildFocusManifestValidation— the offline validator behindthe
loopover_validate_configMCP tool, the config-lint route, and the admin dry-run write path(confirmed via
focus-manifest-validation.ts's own imports/exports). Today, when an operatorconfigures
publicProof:in their manifest and runs the validator to check what the manifestactually resolves to, the
publicProofblock is silently absent from thenormalizedoutput — eventhough
parseFocusManifestparsed it correctly — giving the operator no visibility that the fieldwas recognized at all. Note this is distinct from
config-lint.ts'slintManifestText, which usesa separate known-field-name list that DOES include
"publicProof"(line 4431 offocus-manifest.ts)— so the warning-level check is unaffected; this issue is specifically about the normalized-JSON
output being incomplete.
Requirements
packages/loopover-engine/src/focus-manifest-validation.ts, importpublicProofConfigToJsonfrom
./focus-manifest.jsalongside the other*ConfigToJsonimports (lines 1-20).focusManifestToNormalizedJson, add the same pattern used for every other sub-config:keep it grouped with the others for readability).
publicProofConfigToJson/parsePublicProofConfiginfocus-manifest.ts.Deliverables
publicProof: { enabled: true }produces afocusManifestToNormalizedJsonresult whose
publicProoffield equals{ enabled: true }.publicProofblock (or an invalid one that falls back to{ present: false, enabled: false }) produces a result with nopublicProofkey at all — matching how everyother absent sub-config is already omitted rather than emitted as
null/false.Both Deliverables are required in this one PR — there is no narrower scope for this issue.
Test Coverage Requirements
packages/loopover-engine/src/**is measured by Codecov via two separate uploads whose hits areunioned — root
test/**ANDpackages/loopover-engine/test/**. Add the regression test totest/unit/focus-manifest-validation.test.ts(root-level, this file's existing test location),asserting both Deliverables above against
buildFocusManifestValidation's (orfocusManifestToNormalizedJson's, whichever is exported/testable) actual output. Target 100% branchcoverage of the new serialization branch.
Expected Outcome
focusManifestToNormalizedJson's output includespublicProofwhenever it is configured, matchingevery other sub-config, so the offline validator (
loopover_validate_config, the config-lint route,the admin dry-run write path) gives an operator accurate visibility into a configured
publicProof:block.
Links & Resources
packages/loopover-engine/src/focus-manifest-validation.ts(lines 1-20 imports, lines 63-115focusManifestToNormalizedJson)packages/loopover-engine/src/focus-manifest.ts(line 2535publicProofConfigToJson, line 4431the separate known-field-name list already including
"publicProof")test/unit/focus-manifest-validation.test.tsparseFocusManifest's "no recognized fields" fallback also missingpublicProof