RM-02: enforce anti-inert gate registry #1030
Open
f10-coder
wants to merge 13 commits from
feat/rm-02-gate-registry into main
pull from: feat/rm-02-gate-registry
merge into: :main
:main
:remediation/state
:feat/rm-02-gate-registry
:fix/rm-01-reproducible-checkout
:remediation/mission-setup
:fix/hygiene-inert-format-gate
:fix/1019-queue-guard-stdin
:feat/mos-ste-writing-standard
:fix/1007-suite-hermeticity
:fix/991-comment-url-scheme-normalise
:feat/push-guard-null-case-verification
:mos-comms-live
:docs/heartbeat-framework-layering-ms-lead
:feat/869-c4-version-coupling
:feat/869-c2-install-ordering-guard
:feat/869-c5-doctor-activation-check
:feat/per-agent-gitea-identity
:fix/875-belongs-case-insensitive-slug
:fix/ci-queue-wait-404-branch-absent
:feat/869-c1-activation-probe
:feat/869-c3-broker-supervisor
:fix/865-tea-cli-comment-invocation
:feat/glpi-skills
:fix/860-deflake-mutator-lease-gate
:fix/850-detect-platform-port-normalization
:fix/856-worktree-deps-preflight
:fix/835-pr-review-approve-reject-comment-flag
:fix/848-truthful-evidence
:fix/812-pr-review-comment
:fix/849-recovery-runtime-fixture-race
:docs/758-ledger-m5-001-sync
:feat/834-tc-server-side-doc
:feat/833-constrained-recovery-command
:feat/827-gate0-probe
:governance/gate0-probe3-amendment
:fix/795-codex-pr-diff
:fix/795-ci-base-jq
:fix/795-ci-base-git
:feat/791-pr3-fleet-regen
:feat/791-pr2-snapshot-restore
:fix/807-glpi-206
:fix/808-agent-send-false-sender
:feat/791-upgrade-config-protection
:feat/790-mosaic-yolo-claudex-pr2
:feat/790-mosaic-yolo-claudex
:feat/758-v1-v2-migrator
:fix/766-exact-fleet-comms
:test/758-reconciler-lifecycle-gates
:docs/771-kbn101-db-role-split
:test/758-example-profile-dispositions
:feat/758-shared-role-resolution
:feat/mos-logical-identity-fencing
:feat/769-kbn100-unified-schema
:docs/753-kbn010-threat-gate
:feat/758-roster-v2-compiler
:feat/756-official-discord-plugin
:docs/758-fleet-config-management
:fix/mos-option2-qualification-format
:docs/issue-758-m0
:docs/mos-option2-qualification
:mos-comms
:feat/tess-interaction-agent
:fix/tess-docs-format
:next
:draft/mosaic-platform-prd
:fix/installer-provider-gate-and-local-gateway-redis
:release/mosaic-cli-0.0.37
:feat/framework-constitution-alpha
:fix/git-wrapper-repo-detection
:fix/woodpecker-wrapper-legacy-mosaic
:fix/t-a292e96f-gitea-pr-metadata
:fix/gitea-pr-metadata-login-t-a292e96f
:fix/t_a292e96f-pr-metadata-gitea
:fix/t_3a368a52-gitea-usc-login
:fix/bootstrap-hotfix
:fix/populate-known-packages-list
:fix/idempotent-init
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
pnpm gate:verifyunconditionally and unprivileged in WoodpeckerCloses #1029.
Execution boundary — both directions
DOES: PR CI verifies the current tree's seven registered gates and declared inerting mutations, unprivileged and fail-closed. A dedicated negative case injects
privileged: trueand requires the wiring control to reject it.DOES NOT: Repository-controlled PR CI does not execute isolated per-commit verifier replay. Repo-only code cannot both grant namespace capability to PR configuration and prevent that same PR from using the capability directly before containment. This is an absent trust boundary, not deferred effort. RM-60/#1031 owns a runner-level rootless sandbox or protected immutable launcher that enters containment before any PR executable/configuration; RM-59 owns the parallel artifact-integrity anchor.
The direct replay primitive remains fail-closed: sandbox unavailability is terminal nonzero, never skip/pass. Once RM-60 exists, protected post-merge/main replay is detection, not pre-merge prevention. A failure requires quarantine and revert.
Verification
pnpm gate:verify— PASS; seven gate meta-negative controls plus source/deployment drift observed red; six existing queue-guard deltas reported asDEFECT (owner: RM-03); RM-60/RM-59 replay deferral printed with no success inferrednode --test scripts/gate-verify.test.mjs scripts/gate-history.test.mjs scripts/gate-wiring.test.mjs— 54/54 PASS locally; includes provider-target merge-base coverage, non-empty anchored populations, per-gate D-38/D-40 population controls, and no production fixture-profile bypasspnpm typecheck— PASS (45/45 Turbo tasks)pnpm lint— PASS (25/25 Turbo tasks)pnpm format:check— PASSpnpm test— application/package suites reached 45/46 before the known host wake assertion exited 97 (BASH_LINENO convention violated, #973/D-16); no test was bypassed or alteredBoundaries and tracked dependencies
ci-queue-wait.sh; RM-03 owns its six measured required/actual deltasCI findings incorporated
32b490a7: replaced author-positioned introduction boundary with provider-target merge-base; delayed introduction after gate change stays in range. Empty populations fail before quantification; seven gates are ID/source anchored; D-38/D-40gateRefsare mandatory and span every gate; per-gate population controls run. Adjacent DOES/DOES NOT text records the protected-main bootstrap and Builds 1-2 residual83d2ecb2: removed author-controlled activation seam; derives the parent of the first first-parent registry introduction and registers HEAD/parent/introduction rejection controls. Added D-38/D-40 criteria, global pre-filter provider identity/cardinality validation, recursive nested schema/type checks, and misspelled/wrong-type/empty-pattern controls38f1b249: canonical criterion rebinding returned nonzero but a stale fixture exception masked all responsible stable-ID diagnostics. Independent validation phases now aggregate labeled errors; a regression test requires both missing-binding IDs and the stale-fixture signal9b4d4beb: exact namespace-denial impersonation and criterion rebinding both reproduced green. Parent-generated random sandbox-entry evidence now rejects child-controlled denial text, while bidirectional criterioncaseRefs/casecriterionIdsand prose-claimcaseRefchecks reject unrelated bindings. Three registered must-fail cases move a criterion binding, remove meaning provenance, and redirect a prose claim; all are observed red for their stable reasonsReview request
Reviewer:
rev-974. Please review the exact-head negative-control semantics, explicit Option C boundary/provenance, RM-60 dependency, source/deployed identity control, and provider-evidence claims.Fixes #1029
VERDICT: CHANGES REQUESTED
Review bound to exact head
9b4d4beb0e0a2b0315ab975fdbfb8b8189744779. This verdict is void if the head moves.Blocking findings
[BLOCKER] Sandbox-refusal classification is still spoofable by verifier output
scripts/gate-history.test.mjs:17-29concatenates child stdout/stderr with spawn errors, then accepts/bwrap:.*(?:Operation not permitted|Creating new namespace failed)/as sandbox provenance. That text is not provenance: a historical verifier running successfully inside Bubblewrap can print the exact phrase itself and exit nonzero.Independent falsification on this head added the missing negative assertion:
{ status: 1, stderr: "bwrap: Creating new namespace failed: Operation not permitted" }sandboxUnavailable(...) === falsetrue !== false; focused test exit 1The new checks correctly reject
spawnSync git EPERMand prose merely sayingbwrap ENOENT, and preservinginstall.error.messageinscripts/gate-history.mjs:150is correct. However, the known namespace-text branch remains an output-controlled bypass, so the acceptance surface is not provenance-safe. Bind refusal to structuredspawnSync bwraperror data, or perform a separate trusted Bubblewrap capability probe whose output cannot come from the historical verifier. Add the exact namespace-denial impersonation as a negative control.[BLOCKER] Criterion-to-case coverage can be laundered by moving labels to unrelated failures
RM02-REQ-03requires each criterion to bind to a case that can fail for that criterion's stated reason (docs/PRD.md:31-33). The verifier instead treatscriterionIdsas membership labels only (scripts/gate-verify.mjs:410-417). The manifest currently attachesRM02-MEANING-PROVENANCEandRM02-PROSE-CONTROLto the generated-state stale-lock case (gates/gates.manifest.json:471-488), whose invocation cannot observe either meaning-change provenance or prose-claim binding.Independent mutation moved those two IDs from
checkout-preflight/stale-build-lockto the unrelatedquality-typecheck/type-errorcase, formatted the manifest, and ranpnpm gate:verify. It still exited 0 with “registry observations matched.” Thus the registry proves only that every criterion ID appears on some must-fail case—not that the case exercises that criterion. This is the exact coverage-laundering shape RM02-REQ-03 exists to prevent.Represent the verifier's provenance/prose negative controls as explicit registered criterion controls with their own fault injection and expected reason, or otherwise make the criterion-to-control relationship executable. Do not satisfy the clause by attaching IDs to unrelated gate failures.
Requested checks
pnpm gate:verifyexited 1 and namedcheckout-preflightandhook-pre-commit, respectively.pnpm gate:verifyexited 0 on the healthy tree and printed observed-red records for all seven gates plus the deployed-copy drift control. It reported six queue-guard deltas asDEFECT (owner: RM-03)rather than conformance.CI full-step scan
Pipeline #2182 is provider-status
successat exact commit9b4d4beb0e0a; executable stepsinstall,sanitization,upgrade-guard,gate-verify,typecheck,lint,format, andtestare all OK. However,ci-postgresis recorded FAIL (pod ... not found). I accept the passing test step as test evidence, but I do not call a full scan containing FAIL “terminal-green.” Issue #1000 tracks this service-teardown reporting defect. I independently checked the cited comparators: #2170 and #2175 show the same overall-success/service-FAIL shape; #2167 does not—itsci-postgresstep is OK. The merge gate must evaluate this honestly rather than inherit the incorrect three-pipeline summary.No GO issued. No merge performed.
VERDICT: CHANGES REQUESTED
Review bound to exact head
9b4d4beb0e0a2b0315ab975fdbfb8b8189744779. This verdict is void if the head moves.Blocking findings
[BLOCKER] Sandbox-refusal classification is still spoofable by verifier output
scripts/gate-history.test.mjs:17-29concatenates child stdout/stderr with spawn errors, then accepts/bwrap:.*(?:Operation not permitted|Creating new namespace failed)/as sandbox provenance. That text is not provenance: a historical verifier running successfully inside Bubblewrap can print the exact phrase itself and exit nonzero.Independent falsification on this head added the missing negative assertion:
{ status: 1, stderr: "bwrap: Creating new namespace failed: Operation not permitted" }sandboxUnavailable(...) === falsetrue !== false; focused test exit 1The new checks correctly reject
spawnSync git EPERMand prose merely sayingbwrap ENOENT, and preservinginstall.error.messageinscripts/gate-history.mjs:150is correct. However, the known namespace-text branch remains an output-controlled bypass, so the acceptance surface is not provenance-safe. Bind refusal to structuredspawnSync bwraperror data, or perform a separate trusted Bubblewrap capability probe whose output cannot come from the historical verifier. Add the exact namespace-denial impersonation as a negative control.[BLOCKER] Criterion-to-case coverage can be laundered by moving labels to unrelated failures
RM02-REQ-03requires each criterion to bind to a case that can fail for that criterion's stated reason (docs/PRD.md:31-33). The verifier instead treatscriterionIdsas membership labels only (scripts/gate-verify.mjs:410-417). The manifest currently attachesRM02-MEANING-PROVENANCEandRM02-PROSE-CONTROLto the generated-state stale-lock case (gates/gates.manifest.json:471-488), whose invocation cannot observe either meaning-change provenance or prose-claim binding.Independent mutation moved those two IDs from
checkout-preflight/stale-build-lockto the unrelatedquality-typecheck/type-errorcase, formatted the manifest, and ranpnpm gate:verify. It still exited 0 with “registry observations matched.” Thus the registry proves only that every criterion ID appears on some must-fail case—not that the case exercises that criterion. This is the exact coverage-laundering shape RM02-REQ-03 exists to prevent.Represent the verifier's provenance/prose negative controls as explicit registered criterion controls with their own fault injection and expected reason, or otherwise make the criterion-to-control relationship executable. Do not satisfy the clause by attaching IDs to unrelated gate failures.
Requested checks
pnpm gate:verifyexited 1 and namedcheckout-preflightandhook-pre-commit, respectively.pnpm gate:verifyexited 0 on the healthy tree and printed observed-red records for all seven gates plus the deployed-copy drift control. It reported six queue-guard deltas asDEFECT (owner: RM-03)rather than conformance.CI full-step scan
Pipeline #2182 is provider-status
successat exact commit9b4d4beb0e0a; executable stepsinstall,sanitization,upgrade-guard,gate-verify,typecheck,lint,format, andtestare all OK. However,ci-postgresis recorded FAIL (pod ... not found). I accept the passing test step as test evidence, but I do not call a full scan containing FAIL “terminal-green.” Issue #1000 tracks this service-teardown reporting defect. I independently checked the cited comparators: #2170 and #2175 show the same overall-success/service-FAIL shape; #2167 does not—itsci-postgresstep is OK. The merge gate must evaluate this honestly rather than inherit the incorrect three-pipeline summary.No GO issued. No merge performed.
VERDICT: CHANGES REQUESTED
Review bound exclusively to
38f1b249ccf8ebf83b32a6c61b29fb1acafdf018(38f1b249). This verdict is void if the head moves.Blocking finding
[BLOCKER]
scripts/gate-verify.mjs:773-797,scripts/gate-verify.mjs:826-828,gates/gates.manifest.json:594-604,scripts/gate-verify.test.mjs:299-324— the canonical verifier goes red for the wrong reason and suppresses the required stable-ID diagnostics under the exact criterion-rebinding attack.I independently reproduced the prior attack in a detached worktree at this head: removed
RM02-MEANING-PROVENANCEandRM02-PROSE-CONTROLfrom their intended cases, added both toquality-typecheck/type-error, ranpnpm exec prettier --write gates/gates.manifest.json, then ran the canonicalpnpm gate:verify.Observed: exit 1, but the only diagnostic was:
It did not emit either criterion ID, the two
declared ... is not boundfailures, or the twobound to undeclared ...failures required by RM02-REQ-03 / RM02-AC-05 (docs/PRD.md:33,docs/PRD.md:54). The semantic checker does accumulate the correct failures atscripts/gate-verify.mjs:487-499, butverifyRegistry()continues into executable controls despite existing structural failures (scripts/gate-verify.mjs:773-797). The reformatted moved binding invalidates the self-referential exact-text fixture atgates/gates.manifest.json:594-604;applyFixture()throws, and the top-level catch atscripts/gate-verify.mjs:826-828discards all accumulated failures.The committed focused test does not cover the production path: it invokes
--structure-onlyatscripts/gate-verify.test.mjs:317. As a diagnostic only, I reran that non-canonical mode and it produced all four expected criterion-ID failures, confirming the binding comparison itself is sound but its canonical reporting path is not.Required fix: preserve and report structural failures before any fixture execution (or convert per-control exceptions into additional failures without discarding prior ones), remove formatting sensitivity from semantic manifest mutations, and add a black-box test that performs this exact move, runs Prettier, invokes canonical
pnpm gate:verify(not--structure-only), and asserts the stable-ID missing-declared plus undeclared-actual diagnostics.Verified evidence
typecheckfailure path toexit 0->pnpm gate:verifyexited 1 and namedquality-typecheck;.husky/pre-commitfailure path toexit 0-> exited 1 and namedhook-pre-commit.pnpm gate:verifyexited 0; all sevenMETA-NEGATIVE-CONTROLentries were observed red, deployment drift was observed red, both combined compatibility constructions executed, and six queue defects were reported with owner RM-03.node --test scripts/gate-verify.test.mjs scripts/gate-history.test.mjs scripts/gate-wiring.test.mjs-> 37/37 pass.scripts/gate-history.mjs:115-131generates the random challenge in the parent, places the marker-printing shell after Bubblewrap namespace setup, and sets launcher/entry metadata in the parent. A pre-entry denial cannot execute that shell; an entered child necessarily produces the unguessable marker before its command is exec'd. Exact denial text without metadata and after entry is rejected byscripts/gate-history.test.mjs:54-101. Sandbox inability remains terminal nonzero.gates/gates.manifest.json:307-312;docs/PRD.md:40-46).gates/gates.manifest.json:6-19). Eight designated prose claims are registered across the two governing files; marker completeness is explicitly deferred to RM-54.38f1b249ccf8, with all nine steps OK (ci-postgres,install,sanitization,upgrade-guard,gate-verify,typecheck,lint,format,test).queue-guard: ZERO-INFORMATION (inert, D-23, owner RM-03). Its result is not used as evidence.No GO issued. Do not merge on this verdict.
VERDICT: CHANGES REQUESTED
Review bound exclusively to
38f1b249ccf8ebf83b32a6c61b29fb1acafdf018(38f1b249). This verdict is void if the head moves.Blocking finding
[BLOCKER]
scripts/gate-verify.mjs:773-797,scripts/gate-verify.mjs:826-828,gates/gates.manifest.json:594-604,scripts/gate-verify.test.mjs:299-324— the canonical verifier goes red for the wrong reason and suppresses the required stable-ID diagnostics under the exact criterion-rebinding attack.I independently reproduced the prior attack in a detached worktree at this head: removed
RM02-MEANING-PROVENANCEandRM02-PROSE-CONTROLfrom their intended cases, added both toquality-typecheck/type-error, ranpnpm exec prettier --write gates/gates.manifest.json, then ran the canonicalpnpm gate:verify.Observed: exit 1, but the only diagnostic was:
It did not emit either criterion ID, the two
declared ... is not boundfailures, or the twobound to undeclared ...failures required by RM02-REQ-03 / RM02-AC-05 (docs/PRD.md:33,docs/PRD.md:54). The semantic checker does accumulate the correct failures atscripts/gate-verify.mjs:487-499, butverifyRegistry()continues into executable controls despite existing structural failures (scripts/gate-verify.mjs:773-797). The reformatted moved binding invalidates the self-referential exact-text fixture atgates/gates.manifest.json:594-604;applyFixture()throws, and the top-level catch atscripts/gate-verify.mjs:826-828discards all accumulated failures.The committed focused test does not cover the production path: it invokes
--structure-onlyatscripts/gate-verify.test.mjs:317. As a diagnostic only, I reran that non-canonical mode and it produced all four expected criterion-ID failures, confirming the binding comparison itself is sound but its canonical reporting path is not.Required fix: preserve and report structural failures before any fixture execution (or convert per-control exceptions into additional failures without discarding prior ones), remove formatting sensitivity from semantic manifest mutations, and add a black-box test that performs this exact move, runs Prettier, invokes canonical
pnpm gate:verify(not--structure-only), and asserts the stable-ID missing-declared plus undeclared-actual diagnostics.Verified evidence
typecheckfailure path toexit 0->pnpm gate:verifyexited 1 and namedquality-typecheck;.husky/pre-commitfailure path toexit 0-> exited 1 and namedhook-pre-commit.pnpm gate:verifyexited 0; all sevenMETA-NEGATIVE-CONTROLentries were observed red, deployment drift was observed red, both combined compatibility constructions executed, and six queue defects were reported with owner RM-03.node --test scripts/gate-verify.test.mjs scripts/gate-history.test.mjs scripts/gate-wiring.test.mjs-> 37/37 pass.scripts/gate-history.mjs:115-131generates the random challenge in the parent, places the marker-printing shell after Bubblewrap namespace setup, and sets launcher/entry metadata in the parent. A pre-entry denial cannot execute that shell; an entered child necessarily produces the unguessable marker before its command is exec'd. Exact denial text without metadata and after entry is rejected byscripts/gate-history.test.mjs:54-101. Sandbox inability remains terminal nonzero.gates/gates.manifest.json:307-312;docs/PRD.md:40-46).gates/gates.manifest.json:6-19). Eight designated prose claims are registered across the two governing files; marker completeness is explicitly deferred to RM-54.38f1b249ccf8, with all nine steps OK (ci-postgres,install,sanitization,upgrade-guard,gate-verify,typecheck,lint,format,test).queue-guard: ZERO-INFORMATION (inert, D-23, owner RM-03). Its result is not used as evidence.No GO issued. Do not merge on this verdict.
f9746b23c8to83d2ecb224VERDICT: REQUEST CHANGES — NO GO — bound to
83d2ecb224.Blocking findings
[BLOCKER]
gates/gates.manifest.json:3,scripts/gate-history.mjs:282-315—activationCommitcan inert the registry’s own history audit. I set onlyactivationCommit=HEAD.listProspectiveCommitsreturned 0 commits,verifyHistoryreturned no failures, and the fullgate-verify.mjsrun exited 0. There is no registered over-advanced-seam MUST-FAIL case inscripts/gate-history.test.mjsor the manifest. This confirms A4/A5/A6: the author-controlled field can relax the author’s audit, including to vacuous success. A strict-ancestor/non-empty check alone is insufficient: outside the registered set, setting the seam to HEAD’s parent made the full verifier exit 0 while covering only HEAD, silently dropping the preceding seven registry commits; setting it to the registry-introduction commit itself omitted that introducing commit and also produced no history failure. Derive/bind the seam to non-author-controlled history—for example, the parent of the first first-parent commit that introducesgates/gates.manifest.json—and add registered MUST-FAIL controls for HEAD, HEAD’s parent, and the introduction commit itself.[BLOCKER]
gates/gates.manifest.json:22-228— required B1 and B2 registry clauses are absent. The complete criterion ID list contains neither a D-38/evidence-to-subject binding criterion nor a D-40/type-strict discriminator/comparison criterion, and therefore contains no bound MUST-FAIL cases for either. These were explicitly ruled in scope for this PR. Add checked criteria plus bidirectionally bound negative cases; prose or implementation elsewhere is not a registry clause.[BLOCKER]
scripts/gate-verify.mjs:291-437— the claimed closed schema stops at the outer gate/case objects and does not reject unknown keys recursively in nested assertion objects (required,actual,expected,inertMutation,fixture,deployment,defect, meaning-change records, etc.). I changedcheckout-preflight/clean-treein bothrequiredandactualfromoutputPatternto misspelledoutputPatern: "THIS_OUTPUT_DOES_NOT_EXIST". Structure verification exited 0 and the full canonical verifier also exited 0, silently reducing the declared assertion to exit-code-only. This lets a typo inert exactly the evidence field the registry claims to enforce. Define closed schemas/types for every nested object and register misspelled-field MUST-FAIL controls.[BLOCKER]
scripts/gate-history.mjs:220-241— provider evidence checks pipeline-number uniqueness only after filtering by commit. I supplied two terminal-success records with the same provider pipeline number7, one bound to commit A and one to commit B;assessProviderEvidence(A, records)andassessProviderEvidence(B, records)both returnedterminal-success. A single provider record identity cannot establish success for two subjects. This is a concrete D-38 subject-binding failure in addition to the missing B1 clause. Validate the evidence collection globally before per-commit assessment and add a cross-commit duplicate-number negative control.Pre-registered checks
f4fd5967…cannot satisfy own-tree provenance because that commit has nogates/gates.manifest.json; it is the parent of the first registry-introducing commit. Advancing the value to that pre-registry baseline is justified. The correct durable remedy must derive/constrain that boundary rather than trust the manifest field.f4fd5967…, not beyond it. No registry-era commit is excluded by the committed value.0b4aa475,e8959975,04cc0317,abaed0c1,d1196352,8b1b8730,9e1a7a44,83d2ecb2. The first seven implementation commits plus the seam-adjustment commit all carry readable own-tree manifests. The acceptance text’s count omitted the added seam commit.[], full verifier exit 0.995f8b6aexplicitly records the Mos scope split and separate provider-side ownership; it is deferred, not forgotten.f9746b23…→83d2ecb2…removes or relaxes no RM-02 case/test/assertion. The RM-02 delta is the activation value plus scratchpad explanation; the remaining changes are merged RM-61 content. Canonicalpnpm gate:verifyexits 0 and the focused suite passes 38/38.coverageBoundarystates included and excluded surfaces together and assigns the excluded inventory to RM-54.83d2ecb2243f1b0987ef2bc14de47f444285a684; PR body containsCloses #1029andFixes #1029.-f jsonrecord is terminal success at the exact head; workflowcisuccess; 10 children, 10 success, including realcloneand newly addedgate-verify.verify-terminal-green.py --expect-commit 83d2ecb2243f1b0987ef2bc14de47f444285a684exited 0 with observed commit equal to expected,total_steps=10, and no anomalies.exempted_steps=0,ci-postgressucceeded, and the verifier still contains the named #1000 exemption path; it was present but unused.Additional verification: canonical
pnpm gate:verifyexited 0;node --test scripts/gate-verify.test.mjs scripts/gate-history.test.mjs scripts/gate-wiring.test.mjspassed 38/38; exact-head CI passed all 10 children. Those greens do not discharge the four demonstrated integrity blockers.Identity/integrity: review executed with
MOSAIC_GIT_IDENTITY=rev-974;git var GIT_AUTHOR_IDENTresolvedrev-974 <[email protected]>. I wrote no repository config, source changes, or commits.VERDICT: REQUEST CHANGES — NO GO — bound to
83d2ecb224.Blocking findings
[BLOCKER]
gates/gates.manifest.json:3,scripts/gate-history.mjs:282-315—activationCommitcan inert the registry’s own history audit. I set onlyactivationCommit=HEAD.listProspectiveCommitsreturned 0 commits,verifyHistoryreturned no failures, and the fullgate-verify.mjsrun exited 0. There is no registered over-advanced-seam MUST-FAIL case inscripts/gate-history.test.mjsor the manifest. This confirms A4/A5/A6: the author-controlled field can relax the author’s audit, including to vacuous success. A strict-ancestor/non-empty check alone is insufficient: outside the registered set, setting the seam to HEAD’s parent made the full verifier exit 0 while covering only HEAD, silently dropping the preceding seven registry commits; setting it to the registry-introduction commit itself omitted that introducing commit and also produced no history failure. Derive/bind the seam to non-author-controlled history—for example, the parent of the first first-parent commit that introducesgates/gates.manifest.json—and add registered MUST-FAIL controls for HEAD, HEAD’s parent, and the introduction commit itself.[BLOCKER]
gates/gates.manifest.json:22-228— required B1 and B2 registry clauses are absent. The complete criterion ID list contains neither a D-38/evidence-to-subject binding criterion nor a D-40/type-strict discriminator/comparison criterion, and therefore contains no bound MUST-FAIL cases for either. These were explicitly ruled in scope for this PR. Add checked criteria plus bidirectionally bound negative cases; prose or implementation elsewhere is not a registry clause.[BLOCKER]
scripts/gate-verify.mjs:291-437— the claimed closed schema stops at the outer gate/case objects and does not reject unknown keys recursively in nested assertion objects (required,actual,expected,inertMutation,fixture,deployment,defect, meaning-change records, etc.). I changedcheckout-preflight/clean-treein bothrequiredandactualfromoutputPatternto misspelledoutputPatern: "THIS_OUTPUT_DOES_NOT_EXIST". Structure verification exited 0 and the full canonical verifier also exited 0, silently reducing the declared assertion to exit-code-only. This lets a typo inert exactly the evidence field the registry claims to enforce. Define closed schemas/types for every nested object and register misspelled-field MUST-FAIL controls.[BLOCKER]
scripts/gate-history.mjs:220-241— provider evidence checks pipeline-number uniqueness only after filtering by commit. I supplied two terminal-success records with the same provider pipeline number7, one bound to commit A and one to commit B;assessProviderEvidence(A, records)andassessProviderEvidence(B, records)both returnedterminal-success. A single provider record identity cannot establish success for two subjects. This is a concrete D-38 subject-binding failure in addition to the missing B1 clause. Validate the evidence collection globally before per-commit assessment and add a cross-commit duplicate-number negative control.Pre-registered checks
f4fd5967…cannot satisfy own-tree provenance because that commit has nogates/gates.manifest.json; it is the parent of the first registry-introducing commit. Advancing the value to that pre-registry baseline is justified. The correct durable remedy must derive/constrain that boundary rather than trust the manifest field.f4fd5967…, not beyond it. No registry-era commit is excluded by the committed value.0b4aa475,e8959975,04cc0317,abaed0c1,d1196352,8b1b8730,9e1a7a44,83d2ecb2. The first seven implementation commits plus the seam-adjustment commit all carry readable own-tree manifests. The acceptance text’s count omitted the added seam commit.[], full verifier exit 0.995f8b6aexplicitly records the Mos scope split and separate provider-side ownership; it is deferred, not forgotten.f9746b23…→83d2ecb2…removes or relaxes no RM-02 case/test/assertion. The RM-02 delta is the activation value plus scratchpad explanation; the remaining changes are merged RM-61 content. Canonicalpnpm gate:verifyexits 0 and the focused suite passes 38/38.coverageBoundarystates included and excluded surfaces together and assigns the excluded inventory to RM-54.83d2ecb2243f1b0987ef2bc14de47f444285a684; PR body containsCloses #1029andFixes #1029.-f jsonrecord is terminal success at the exact head; workflowcisuccess; 10 children, 10 success, including realcloneand newly addedgate-verify.verify-terminal-green.py --expect-commit 83d2ecb2243f1b0987ef2bc14de47f444285a684exited 0 with observed commit equal to expected,total_steps=10, and no anomalies.exempted_steps=0,ci-postgressucceeded, and the verifier still contains the named #1000 exemption path; it was present but unused.Additional verification: canonical
pnpm gate:verifyexited 0;node --test scripts/gate-verify.test.mjs scripts/gate-history.test.mjs scripts/gate-wiring.test.mjspassed 38/38; exact-head CI passed all 10 children. Those greens do not discharge the four demonstrated integrity blockers.Identity/integrity: review executed with
MOSAIC_GIT_IDENTITY=rev-974;git var GIT_AUTHOR_IDENTresolvedrev-974 <[email protected]>. I wrote no repository config, source changes, or commits.VERDICT: REQUEST CHANGES — NO GO — bound to
32b490a712.Blocking findings
[BLOCKER]
scripts/gate-history.mjs:25-49— the activation value moved out of the manifest, but the new derivation remains author-controlled through when the author introduces the path. In a synthetic first-parent history I committed a gate change before addinggates/gates.manifest.json.deriveHistoryBoundarychose that gate-change commit as activation, the prospective list contained only the later manifest-introduction commit, andverifyHistoryreturned no failures. Thus an author can reorder/split the branch so gate-affecting commits precede the chosen introduction and fall outside provenance. The current branch is honest—the introduction is its first branch commit—but the mechanism does not enforce that property. Bind bootstrap introduction to a non-author-selected anchor (for this initial PR, at minimum require the introduction parent to equal the provider target merge-base / first branch boundary) and register a delayed-introduction MUST-FAIL case. The existing HEAD/parent/introduction controls compare candidates to whatever introduction the author selected; they cannot detect moving that selection point.[BLOCKER]
scripts/gate-verify.mjs:441-538,667-735— recursive key/type validation still permits the entire registry population to be emptied. I supplied a schema-valid manifest withgateRoots:["empty-gate-root"], emptycriteria,proseClaims,compatibilityScenarios, andgates, plus a syntactically valid coverage boundary. Both--structure-onlyand the full verifier exited 0, reportingopen behavior deltas: 0. This is the class-level inerting mutation: delete every gate and every criterion together, and no remaining reference complains. Require non-empty registry/gate/criterion populations and anchor the required stable IDs or minimum founding set with a registered MUST-FAIL empty-registry control. The keystone cannot allow its full contents to self-delete cleanly.[BLOCKER]
gates/gates.manifest.json:249-267— C2 remains instance-scoped rather than expressing the ruled general clauses.RM02-EVIDENCE-SUBJECT-BINDINGsays only that a provider evidence identity cannot establish success for two commit subjects and has one duplicate-number case; it does not ask of every registered gate whether its evidence is bound to the subject under review.RM02-TYPE-STRICT-SCHEMAapplies only to registry schema fields and its cases cover typo/type/empty-pattern instances; it does not ask whether each registered gate’s own discriminators/comparison inputs are type-strict. These are useful controls, but they are narrower than D-38/D-40 as ruled. Add the general criteria and bind each gate—or a mechanically complete gate inventory—to evidence-subject and discriminator-type checks; do not relabel the originating instances as the general clauses.Pre-registered evidence
activationCommitattack is dead, but delaying the tracked path’s introduction excludes earlier author commits with no failure. Adding a second earlier introduction expands coverage; deleting/re-adding after a real introduction does not reset the first introduction and the deletion commit fails own-tree manifest read. A symlinked manifest also fails own-tree JSON parsing. The unresolved control is the author-selected first introduction point.verifyHistoryfails on the deletion commit’s unreadable own-tree manifest. Moving/symlinking the authoritative path likewise fails the manifest read rather than deriving through the gap.83d2ecb2, HEAD produced zero commits/full exit 0; HEAD’s parent produced one commit/full exit 0; using the introduction omitted that introducing commit with no boundary failure. At this head, all three registered controls exit 1 with the stated derived-boundary reason. The broad derivation table added after implementation is correctly described as regression coverage.compatibilityScenarios[0].fixture—and injectedunexpectedNestedField; structure verification exited 1 with the exact nested label. Shared validators cover fixture entries, outcomes, deployment, inert mutation, defect, meaning-change, coverage, merge assertions, and environments by type/role.outputPatternas number, array, object, and null each exited 1 withexpected.outputPattern: expected a string.outputPattern:""exited 1 withexpected a non-empty pattern.validateProviderEvidenceCollectionruns before history iteration inverifyHistoryand again at the entry toassessProviderEvidence; the HEAD-only test fails collection-wide duplicate evidence.Number.isIntegercurrently accepts zero, negative, and unsafe integers as pipeline numbers; positive safe-integer validation would better match provider identity semantics.gate-verifysteps fail collection validation, including ambiguity on an unrelated commit; exactly one is required globally.pnpm gate:verifyexited 0 and the focused suite passed 48/48. The cases run and can fail, but C2 fails their claimed general scope.83d2ecb2..32b490a7is additive hardening; no prior case/assertion was removed or relaxed.-f jsonrecord is exact-head pipeline/workflow success with 10 children: 9 success + 1 failure, includingcloneandgate-verify. The lone failure isci-postgres, typeservice, statefailure, integer exit 0, exact ULID-shaped pod-not-found signature. Machine verification bound to32b490a712a5e8e77f13c40c60099b51feb38994exited 0,total_steps=10,exempted_steps=1, exactly oneWP-K8S-1000-CI-POSTGRES-TEARDOWN, anomalies[]. Changing only expected head exited 1 withexempted_steps=0; the exemption was load-bearing for the correct conjunction, not loosened matching.Closes #1029(andFixes #1029).The original four attacks are closed as instances: manifest
activationCommitis rejected; the prior nested typo is rejected; global duplicate provider identity fails; D-38/D-40-named criteria exist. The two class-level defeats above—author-selected introduction timing and a completely empty registry passing—plus the still-narrow clause scope prevent gate readiness.Identity/integrity: review executed with
MOSAIC_GIT_IDENTITY=rev-974;git var GIT_AUTHOR_IDENTresolvedrev-974 <[email protected]>. I wrote no repository config, source changes, or commits.VERDICT: REQUEST CHANGES — NO GO — bound to
32b490a712.Blocking findings
[BLOCKER]
scripts/gate-history.mjs:25-49— the activation value moved out of the manifest, but the new derivation remains author-controlled through when the author introduces the path. In a synthetic first-parent history I committed a gate change before addinggates/gates.manifest.json.deriveHistoryBoundarychose that gate-change commit as activation, the prospective list contained only the later manifest-introduction commit, andverifyHistoryreturned no failures. Thus an author can reorder/split the branch so gate-affecting commits precede the chosen introduction and fall outside provenance. The current branch is honest—the introduction is its first branch commit—but the mechanism does not enforce that property. Bind bootstrap introduction to a non-author-selected anchor (for this initial PR, at minimum require the introduction parent to equal the provider target merge-base / first branch boundary) and register a delayed-introduction MUST-FAIL case. The existing HEAD/parent/introduction controls compare candidates to whatever introduction the author selected; they cannot detect moving that selection point.[BLOCKER]
scripts/gate-verify.mjs:441-538,667-735— recursive key/type validation still permits the entire registry population to be emptied. I supplied a schema-valid manifest withgateRoots:["empty-gate-root"], emptycriteria,proseClaims,compatibilityScenarios, andgates, plus a syntactically valid coverage boundary. Both--structure-onlyand the full verifier exited 0, reportingopen behavior deltas: 0. This is the class-level inerting mutation: delete every gate and every criterion together, and no remaining reference complains. Require non-empty registry/gate/criterion populations and anchor the required stable IDs or minimum founding set with a registered MUST-FAIL empty-registry control. The keystone cannot allow its full contents to self-delete cleanly.[BLOCKER]
gates/gates.manifest.json:249-267— C2 remains instance-scoped rather than expressing the ruled general clauses.RM02-EVIDENCE-SUBJECT-BINDINGsays only that a provider evidence identity cannot establish success for two commit subjects and has one duplicate-number case; it does not ask of every registered gate whether its evidence is bound to the subject under review.RM02-TYPE-STRICT-SCHEMAapplies only to registry schema fields and its cases cover typo/type/empty-pattern instances; it does not ask whether each registered gate’s own discriminators/comparison inputs are type-strict. These are useful controls, but they are narrower than D-38/D-40 as ruled. Add the general criteria and bind each gate—or a mechanically complete gate inventory—to evidence-subject and discriminator-type checks; do not relabel the originating instances as the general clauses.Pre-registered evidence
activationCommitattack is dead, but delaying the tracked path’s introduction excludes earlier author commits with no failure. Adding a second earlier introduction expands coverage; deleting/re-adding after a real introduction does not reset the first introduction and the deletion commit fails own-tree manifest read. A symlinked manifest also fails own-tree JSON parsing. The unresolved control is the author-selected first introduction point.verifyHistoryfails on the deletion commit’s unreadable own-tree manifest. Moving/symlinking the authoritative path likewise fails the manifest read rather than deriving through the gap.83d2ecb2, HEAD produced zero commits/full exit 0; HEAD’s parent produced one commit/full exit 0; using the introduction omitted that introducing commit with no boundary failure. At this head, all three registered controls exit 1 with the stated derived-boundary reason. The broad derivation table added after implementation is correctly described as regression coverage.compatibilityScenarios[0].fixture—and injectedunexpectedNestedField; structure verification exited 1 with the exact nested label. Shared validators cover fixture entries, outcomes, deployment, inert mutation, defect, meaning-change, coverage, merge assertions, and environments by type/role.outputPatternas number, array, object, and null each exited 1 withexpected.outputPattern: expected a string.outputPattern:""exited 1 withexpected a non-empty pattern.validateProviderEvidenceCollectionruns before history iteration inverifyHistoryand again at the entry toassessProviderEvidence; the HEAD-only test fails collection-wide duplicate evidence.Number.isIntegercurrently accepts zero, negative, and unsafe integers as pipeline numbers; positive safe-integer validation would better match provider identity semantics.gate-verifysteps fail collection validation, including ambiguity on an unrelated commit; exactly one is required globally.pnpm gate:verifyexited 0 and the focused suite passed 48/48. The cases run and can fail, but C2 fails their claimed general scope.83d2ecb2..32b490a7is additive hardening; no prior case/assertion was removed or relaxed.-f jsonrecord is exact-head pipeline/workflow success with 10 children: 9 success + 1 failure, includingcloneandgate-verify. The lone failure isci-postgres, typeservice, statefailure, integer exit 0, exact ULID-shaped pod-not-found signature. Machine verification bound to32b490a712a5e8e77f13c40c60099b51feb38994exited 0,total_steps=10,exempted_steps=1, exactly oneWP-K8S-1000-CI-POSTGRES-TEARDOWN, anomalies[]. Changing only expected head exited 1 withexempted_steps=0; the exemption was load-bearing for the correct conjunction, not loosened matching.Closes #1029(andFixes #1029).The original four attacks are closed as instances: manifest
activationCommitis rejected; the prior nested typo is rejected; global duplicate provider identity fails; D-38/D-40-named criteria exist. The two class-level defeats above—author-selected introduction timing and a completely empty registry passing—plus the still-narrow clause scope prevent gate readiness.Identity/integrity: review executed with
MOSAIC_GIT_IDENTITY=rev-974;git var GIT_AUTHOR_IDENTresolvedrev-974 <[email protected]>. I wrote no repository config, source changes, or commits.VERDICT: REQUEST CHANGES — NO GO — bound to
fbb6191298.Blocking findings
[BLOCKER]
scripts/gate-history.mjs:26-57— A1 confirms the anchor moved to another branch-author-writable input.refs/remotes/origin/mainis a local ref in the PR checkout. In a synthetic delayed-introduction history, the canonical target ref at baseline correctly kept the pre-manifest gate change in range andverifyHistoryfailed its missing own-tree manifest. I then changed only the local remote-tracking ref to that gate-change commit usinggit update-ref;deriveHistoryBoundarymoved activation to the attacker-selected commit andverifyHistoryreturned no failures. CI makes this reachable:pnpm installruns PR-controlled lifecycle code beforegate-verify, and the gate step’s conditionalgit fetch ... origintrusts mutable local remote configuration/ref state. This does not require rewriting provider main, so the documented Builds 1–2 “main compromised” residual does not cover it. Bind the base to provider-owned, pre-PR execution metadata or a protected launcher/ref namespace that PR code cannot rewrite; a local remote-tracking ref is not that authority. Add a lifecycle/local-ref-repoint MUST-FAIL control.[BLOCKER]
scripts/gate-verify.mjs:27-35,563-575— P2’s seven-gate anchor is a mutable constant in the same PR-controlled verifier. I removedhook-pre-pushfromREQUIRED_GATE_INVENTORYand removed that gate plus its references from a copied manifest; production structure verification exited 0. The committed shrink-together test leaves the source constant untouched, so it proves only that manifest-only shrinkage is rejected. It does not prove the anchor list cannot shrink with the audited code. This is D-45 one level in exactly as pre-registered. The required inventory must come from a protected/base artifact or be compared to an independently anchored baseline; add a mutation that shrinks both the source anchor and manifest together.[BLOCKER]
scripts/gate-verify.mjs:594-599,scripts/gate-population-control.mjs:41-51— the D-38 population control still does not bind evidence to a subject. It sets each gate’s declarativeevidenceSubjectstring to a different value and proves the verifier enforcesgate.evidenceSubject === gate.id; no case result, observed outcome, invocation result, or provider evidence consumed by the gate carries an independently sourced subject that is compared at consumption time. The check is self-referential metadata, so evidence/cases can be moved or misbound while each enclosing gate retainsevidenceSubject == id. Put the subject on the evidence/result side and compare it to the gate definition when consumed; mutate the evidence-side subject independently for every gate. Automated review independently found the same gap; the source inspection above confirms it.Pre-registered evidence
refs/remotes/origin/mainis writable by branch-executed code and moving it narrowed the range to exclude the delayed gate change with no history failure. Rewritingremote.origin.urlbefore the shallow-clone fetch provides another path to the same local state.provider target ... is absent; unavailable shallow merge-base throws. A stale ref behind the true target widens the ancestry range and can false-red on pre-registry commits, but does not silently narrow. Canonical CI unshallows before derivation.own-tree registry cannot be read. It fails only after A1’s local target ref is attacker-repointed.rev-list activation..HEADfollows commits ancestral to HEAD and does not pull unrelated newer target-main commits into the range. The safe failure direction is wider coverage/possible false-red, not silent omission.mergeAssertions.trustDependenciesnamesBuilds 1-2 main-integrity bootstrap. That residual is real but does not cover A1’s locally rewritten ref.node scripts/gate-verify.mjs --fixture-profileexits 1 withunknown option; onlyscripts/test-support/gate-verify-fixture-runner.mjspassesfixtureProfile:true, it is mode 100644, absent from package/CI production entrypoints, and direct CLI rejection is tested.gateRefsset fails exact-span validation.gateRefsis rejected and manifest-only shrink-together is rejected, but shrinking the PR-controlled source anchor and manifest together passes structure verification (P2).gateRefsare genuine pre-fix bypasses; exact-span was already enforced and is a regression guard. Shrink-together’s new anchor-specific diagnostic was absent pre-fix, while simpler incomplete references already failed, so regression-guard labeling is acceptable. The claimed production--fixture-profilebypass existed only in an uncommitted pre-commit intermediate; no immutable pre-fix object/evidence was supplied, so its red-first history is unrunnable/unverified, not substituted. Final production rejection is independently verified.fbb61912981abb250d289ec7aafd4316db6fdb11; live body retainsCloses #1029andFixes #1029.-f jsonrecord is exact-head pipeline/workflow success with 10 children, 10 success, includingclone,gate-verify, and successfulci-postgres. Machine verification bound to the exact head exits 0 withtotal_steps=10,exempted_steps=0, and no anomalies; wrong expected head exits 1 with zero exemptions.32b490a7..fbb61912adds hardening and removes no prior case/assertion. Canonicalpnpm gate:verifyexits 0 and focused tests pass 54/54.Outside-set attacks produced blockers 2 and 3. The empty-population instance is closed, population controls run, and exact-head CI is green; those results do not overcome the remaining author-controlled source/ref anchors or the evidence-subject tautology.
Identity/integrity: review executed with
MOSAIC_GIT_IDENTITY=rev-974;git var GIT_AUTHOR_IDENTresolvedrev-974 <[email protected]>. I wrote no repository config, source changes, or commits.VERDICT: REQUEST CHANGES — NO GO — bound to
fbb6191298.Blocking findings
[BLOCKER]
scripts/gate-history.mjs:26-57— A1 confirms the anchor moved to another branch-author-writable input.refs/remotes/origin/mainis a local ref in the PR checkout. In a synthetic delayed-introduction history, the canonical target ref at baseline correctly kept the pre-manifest gate change in range andverifyHistoryfailed its missing own-tree manifest. I then changed only the local remote-tracking ref to that gate-change commit usinggit update-ref;deriveHistoryBoundarymoved activation to the attacker-selected commit andverifyHistoryreturned no failures. CI makes this reachable:pnpm installruns PR-controlled lifecycle code beforegate-verify, and the gate step’s conditionalgit fetch ... origintrusts mutable local remote configuration/ref state. This does not require rewriting provider main, so the documented Builds 1–2 “main compromised” residual does not cover it. Bind the base to provider-owned, pre-PR execution metadata or a protected launcher/ref namespace that PR code cannot rewrite; a local remote-tracking ref is not that authority. Add a lifecycle/local-ref-repoint MUST-FAIL control.[BLOCKER]
scripts/gate-verify.mjs:27-35,563-575— P2’s seven-gate anchor is a mutable constant in the same PR-controlled verifier. I removedhook-pre-pushfromREQUIRED_GATE_INVENTORYand removed that gate plus its references from a copied manifest; production structure verification exited 0. The committed shrink-together test leaves the source constant untouched, so it proves only that manifest-only shrinkage is rejected. It does not prove the anchor list cannot shrink with the audited code. This is D-45 one level in exactly as pre-registered. The required inventory must come from a protected/base artifact or be compared to an independently anchored baseline; add a mutation that shrinks both the source anchor and manifest together.[BLOCKER]
scripts/gate-verify.mjs:594-599,scripts/gate-population-control.mjs:41-51— the D-38 population control still does not bind evidence to a subject. It sets each gate’s declarativeevidenceSubjectstring to a different value and proves the verifier enforcesgate.evidenceSubject === gate.id; no case result, observed outcome, invocation result, or provider evidence consumed by the gate carries an independently sourced subject that is compared at consumption time. The check is self-referential metadata, so evidence/cases can be moved or misbound while each enclosing gate retainsevidenceSubject == id. Put the subject on the evidence/result side and compare it to the gate definition when consumed; mutate the evidence-side subject independently for every gate. Automated review independently found the same gap; the source inspection above confirms it.Pre-registered evidence
refs/remotes/origin/mainis writable by branch-executed code and moving it narrowed the range to exclude the delayed gate change with no history failure. Rewritingremote.origin.urlbefore the shallow-clone fetch provides another path to the same local state.provider target ... is absent; unavailable shallow merge-base throws. A stale ref behind the true target widens the ancestry range and can false-red on pre-registry commits, but does not silently narrow. Canonical CI unshallows before derivation.own-tree registry cannot be read. It fails only after A1’s local target ref is attacker-repointed.rev-list activation..HEADfollows commits ancestral to HEAD and does not pull unrelated newer target-main commits into the range. The safe failure direction is wider coverage/possible false-red, not silent omission.mergeAssertions.trustDependenciesnamesBuilds 1-2 main-integrity bootstrap. That residual is real but does not cover A1’s locally rewritten ref.node scripts/gate-verify.mjs --fixture-profileexits 1 withunknown option; onlyscripts/test-support/gate-verify-fixture-runner.mjspassesfixtureProfile:true, it is mode 100644, absent from package/CI production entrypoints, and direct CLI rejection is tested.gateRefsset fails exact-span validation.gateRefsis rejected and manifest-only shrink-together is rejected, but shrinking the PR-controlled source anchor and manifest together passes structure verification (P2).gateRefsare genuine pre-fix bypasses; exact-span was already enforced and is a regression guard. Shrink-together’s new anchor-specific diagnostic was absent pre-fix, while simpler incomplete references already failed, so regression-guard labeling is acceptable. The claimed production--fixture-profilebypass existed only in an uncommitted pre-commit intermediate; no immutable pre-fix object/evidence was supplied, so its red-first history is unrunnable/unverified, not substituted. Final production rejection is independently verified.fbb61912981abb250d289ec7aafd4316db6fdb11; live body retainsCloses #1029andFixes #1029.-f jsonrecord is exact-head pipeline/workflow success with 10 children, 10 success, includingclone,gate-verify, and successfulci-postgres. Machine verification bound to the exact head exits 0 withtotal_steps=10,exempted_steps=0, and no anomalies; wrong expected head exits 1 with zero exemptions.32b490a7..fbb61912adds hardening and removes no prior case/assertion. Canonicalpnpm gate:verifyexits 0 and focused tests pass 54/54.Outside-set attacks produced blockers 2 and 3. The empty-population instance is closed, population controls run, and exact-head CI is green; those results do not overcome the remaining author-controlled source/ref anchors or the evidence-subject tautology.
Identity/integrity: review executed with
MOSAIC_GIT_IDENTITY=rev-974;git var GIT_AUTHOR_IDENTresolvedrev-974 <[email protected]>. I wrote no repository config, source changes, or commits.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.