{ "schemaVersion": 1, "gateRoots": ["gates"], "governingClaimFiles": ["docs/remediation/MISSION.md", "docs/remediation/GATE-CLAIMS.md"], "coverageBoundary": { "included": [ "root typecheck, lint, and format scripts", "RM-01 checkout preflight", "Mosaic CI queue guard", "root Husky pre-commit and pre-push hooks" ], "excluded": [ "framework quality scripts other than ci-queue-wait.sh", "package-local test and build scripts", "template hooks and generated Husky dispatcher files", "deployment and release scripts" ], "trackedBy": "RM-54" }, "criteria": [ { "id": "RM02-CHECK-RIGHT", "originalText": "Every registered check is observed red for its own stated reason before its green counts.", "currentText": "Every registered check is observed red for its own stated reason before its green counts.", "claimType": "integrity", "source": "docs/remediation/MISSION.md#first-class-principle-pre-registration", "meaningChanges": [], "caseRefs": [ "quality-typecheck/type-error", "quality-lint/invalid-syntax", "quality-format/unformatted-json", "checkout-preflight/stale-build-lock", "checkout-preflight/criterion-misbinding", "checkout-preflight/missing-meaning-provenance", "checkout-preflight/prose-claim-misbinding", "checkout-preflight/misspelled-outcome-field", "checkout-preflight/wrong-outcome-field-type", "checkout-preflight/empty-outcome-pattern", "checkout-preflight/empty-registry-populations", "checkout-preflight/all-gates-evidence-subject-bound", "checkout-preflight/all-gates-type-strict", "ci-queue-wait/no-status-required", "ci-queue-wait/unknown-option", "hook-pre-commit/lint-staged-failure", "hook-pre-push/typecheck-failure", "checkout-preflight/history-provenance-exclusion", "checkout-preflight/inventory-source-and-manifest-shrink", "checkout-preflight/inventory-claim-overstatement" ] }, { "id": "RM02-SET-COVERS", "originalText": "Every acceptance criterion is bound to the specific case that exercises it.", "currentText": "Every acceptance criterion is bound to the specific case that exercises it.", "claimType": "integrity", "source": "docs/remediation/TASKS.md#d-17", "meaningChanges": [], "caseRefs": ["checkout-preflight/criterion-misbinding"] }, { "id": "RM02-MODELED-CONSISTENCY", "originalText": "No two declared finite scenarios require mutually unsatisfiable outcomes.", "currentText": "No two declared finite scenarios require mutually unsatisfiable outcomes; arbitrary English consistency is outside this model.", "claimType": "integrity", "source": "docs/remediation/TASKS.md#d-18", "meaningChanges": [ { "originalText": "No two criteria conflict.", "restatement": "No two declared finite scenarios require mutually unsatisfiable outcomes; arbitrary English consistency is outside this model.", "reason": "Semantic satisfiability of arbitrary natural language is undecidable at this layer.", "finding": "D-18", "task": "RM-54/RM-55", "date": "2026-08-01" } ], "caseRefs": [ "quality-typecheck/clean-tree", "quality-lint/clean-tree", "quality-format/clean-tree", "checkout-preflight/clean-tree", "hook-pre-commit/lint-staged-failure", "hook-pre-push/typecheck-failure" ] }, { "id": "RM02-MEANING-PROVENANCE", "originalText": "A restated criterion retains original text, restatement, and reason.", "currentText": "A restated criterion retains original text, restatement, and reason.", "claimType": "integrity", "source": "docs/remediation/TASKS.md#d-18", "meaningChanges": [], "caseRefs": ["checkout-preflight/missing-meaning-provenance"] }, { "id": "RM02-PROSE-CONTROL", "originalText": "Security and integrity claims in governing prose require a bound negative control.", "currentText": "Marked security and integrity claims in designated governing prose require a bound negative control; RM-54 audits marker completeness.", "claimType": "security", "source": "docs/remediation/TASKS.md#d-20", "meaningChanges": [ { "originalText": "Security and integrity claims in governing prose require a bound negative control.", "restatement": "Marked security and integrity claims in designated governing prose require a bound negative control; RM-54 audits marker completeness.", "reason": "A local verifier cannot safely infer every semantic claim in arbitrary English.", "finding": "D-20", "task": "RM-54", "date": "2026-08-01" } ], "caseRefs": ["checkout-preflight/prose-claim-misbinding"] }, { "id": "RM02-CURRENT-TREE-BOUNDARY", "originalText": "assert that every merged commit passed every required gate, evaluated AGAINST THAT COMMIT'S OWN TREE — not against current main.", "currentText": "PR CI performs unprivileged, fail-closed current-tree verification only and makes no history-provenance assertion; RM-60 owns that external protected property.", "claimType": "security", "source": "docs/PRD.md#rm02-req-10-meaning-change-provenance", "meaningChanges": [ { "originalText": "assert that every merged commit passed every required gate, evaluated AGAINST THAT COMMIT'S OWN TREE — not against current main.", "restatement": "PR CI performs unprivileged, fail-closed current-tree verification only; isolated per-commit replay is deferred to a protected post-merge/main authority as detection with quarantine/revert, not pre-merge prevention.", "reason": "PR-controlled code would otherwise receive and could directly use the namespace capability intended to contain it; the pre-execution trust boundary is absent at the repository layer.", "finding": "D-25", "task": "RM-60/RM-59", "date": "2026-08-01" }, { "originalText": "PR CI performs unprivileged, fail-closed current-tree verification only; isolated per-commit replay is deferred to RM-60's protected post-merge/main authority as detection with quarantine/revert, not pre-merge prevention.", "restatement": "PR CI performs unprivileged, fail-closed current-tree verification only and makes no history-provenance assertion; RM-60 owns that external protected property.", "reason": "D-48 proved PR lifecycle code can rewrite every local git anchor before gate execution, so the repository history claim is removed rather than annotated as unverifiable.", "finding": "D-48", "task": "RM-60", "date": "2026-08-01" } ], "caseRefs": ["checkout-preflight/privileged-pr-gate"] }, { "id": "QUALITY-TYPECHECK", "originalText": "The root typecheck rejects a TypeScript type error.", "currentText": "The root typecheck rejects a TypeScript type error.", "claimType": "quality", "source": "package.json#scripts.typecheck", "meaningChanges": [], "caseRefs": ["quality-typecheck/clean-tree", "quality-typecheck/type-error"] }, { "id": "QUALITY-LINT", "originalText": "The root lint gate rejects invalid TypeScript syntax.", "currentText": "The root lint gate rejects invalid TypeScript syntax.", "claimType": "quality", "source": "package.json#scripts.lint", "meaningChanges": [], "caseRefs": ["quality-lint/clean-tree", "quality-lint/invalid-syntax"] }, { "id": "QUALITY-FORMAT", "originalText": "The root format gate rejects an unformatted tracked-format input.", "currentText": "The root format gate rejects an unformatted tracked-format input.", "claimType": "quality", "source": "package.json#scripts.format:check", "meaningChanges": [], "caseRefs": ["quality-format/clean-tree", "quality-format/unformatted-json"] }, { "id": "CHECKOUT-PREFLIGHT", "originalText": "The RM-01 preflight rejects stale or independently mutated generated state within its documented threat model.", "currentText": "The RM-01 preflight rejects stale or independently mutated generated state, but not a same-UID consistent rewrite; RM-59 owns the external trust anchor.", "claimType": "integrity", "source": "scripts/preflight.mjs", "meaningChanges": [ { "originalText": "The generated-state manifest turns integrity from a claim into a property.", "restatement": "The preflight detects accidental, independent, stale, and foreign-residue mutation, but not a same-UID consistent rewrite.", "reason": "D-19 established CWE-345 self-authentication and D-20 recorded the empirical disproof.", "finding": "D-19/D-20", "task": "RM-59", "date": "2026-07-31" } ], "caseRefs": ["checkout-preflight/clean-tree", "checkout-preflight/stale-build-lock"] }, { "id": "QUEUE-GUARD", "originalText": "The queue guard distinguishes ready, pending, indeterminate, and failed CI states without silently accepting indeterminate or failed states.", "currentText": "The queue guard is measured against its current behavior while required-versus-actual deltas remain owned by RM-03.", "claimType": "integrity", "source": "packages/mosaic/framework/tools/git/ci-queue-wait.sh", "meaningChanges": [ { "originalText": "The required queue guard blocks unsafe push and merge states.", "restatement": "The registry measures current fail-open states and reports each as DEFECT until RM-03 changes the gate and registry together.", "reason": "D-6/D-10 observed unknown, no-status, malformed, terminal-failure, and wrong-branch behavior.", "finding": "D-6/D-10", "task": "RM-03", "date": "2026-08-01" } ], "caseRefs": [ "ci-queue-wait/terminal-success", "ci-queue-wait/no-status-required", "ci-queue-wait/unknown-state", "ci-queue-wait/malformed-status", "ci-queue-wait/terminal-failure", "ci-queue-wait/push-defaults-to-main", "ci-queue-wait/unknown-option" ] }, { "id": "HOOK-PRE-COMMIT", "originalText": "The pre-commit hook propagates lint-staged failure.", "currentText": "The pre-commit hook propagates lint-staged failure.", "claimType": "workflow", "source": ".husky/pre-commit", "meaningChanges": [], "caseRefs": ["hook-pre-commit/clean-staged-input", "hook-pre-commit/lint-staged-failure"] }, { "id": "HOOK-PRE-PUSH", "originalText": "The pre-push hook propagates each required gate failure.", "currentText": "The pre-push hook propagates each required gate failure.", "claimType": "workflow", "source": ".husky/pre-push", "meaningChanges": [], "caseRefs": ["hook-pre-push/all-subgates-succeed", "hook-pre-push/typecheck-failure"] }, { "id": "GATE-SOURCE-DEPLOYMENT", "originalText": "A registered gate with a deployed counterpart verifies the artifact that actually enforces.", "currentText": "A registered gate with a deployed counterpart requires byte equality and a deployed-copy drift negative control.", "claimType": "integrity", "source": "docs/PRD.md#rm-02-gate-registry-and-negative-control-verifier-1029", "meaningChanges": [ { "originalText": "The registry verifies repository gate sources.", "restatement": "The registry also verifies byte identity with each declared deployed counterpart.", "reason": "A source-only check can certify a file that is not the installed enforcing artifact.", "finding": "D-1/P-ACTIVATION-001", "task": "RM-02", "date": "2026-08-01" } ], "caseRefs": ["ci-queue-wait/terminal-success", "ci-queue-wait/unknown-option"] }, { "id": "RM02-HISTORY-PROVENANCE-EXCLUDED", "originalText": "The audited branch range begins at the provider target merge-base, sound against a branch author who cannot rewrite main but not against main compromise; Builds 1-2 own the residual.", "currentText": "This repository verifier is structurally incapable of asserting history provenance; RM-60 owns the provider-controlled protected pre-execution boundary required to establish it.", "claimType": "integrity", "source": "docs/remediation/MISSION.md#first-class-principle-the-anchor-must-live-outside-the-audited-partys-authority", "meaningChanges": [ { "originalText": "The audited branch range begins at the provider target merge-base, sound against a branch author who cannot rewrite main but not against main compromise; Builds 1-2 own the residual.", "restatement": "This repository verifier is structurally incapable of asserting history provenance; RM-60 owns the provider-controlled protected pre-execution boundary required to establish it.", "reason": "PR-controlled lifecycle code executes before gate verification, so no local ref, config, remote URL, constant, or author-positioned path is trustworthy enough to anchor history provenance.", "finding": "D-48", "task": "RM-60", "date": "2026-08-01" } ], "caseRefs": ["checkout-preflight/history-provenance-exclusion"] }, { "id": "RM02-EVIDENCE-SUBJECT-BINDING", "originalText": "For every registered gate, consumed evidence carries an independently declared evidence-side subject that must match the gate definition.", "currentText": "For every registered gate, consumed evidence carries an independently declared evidence-side subject that must match the gate definition.", "claimType": "integrity", "source": "docs/remediation/TASKS.md#d-38", "meaningChanges": [], "caseRefs": ["checkout-preflight/all-gates-evidence-subject-bound"], "gateRefs": [ "quality-typecheck", "quality-lint", "quality-format", "checkout-preflight", "ci-queue-wait", "hook-pre-commit", "hook-pre-push" ] }, { "id": "RM02-TYPE-STRICT-SCHEMA", "originalText": "For every registered gate, each discriminator and comparison input is recursively closed and type-strict so malformed values cannot disable its assertion.", "currentText": "For every registered gate, each discriminator and comparison input is recursively closed and type-strict so malformed values cannot disable its assertion.", "claimType": "integrity", "source": "docs/remediation/TASKS.md#d-40", "meaningChanges": [], "caseRefs": [ "checkout-preflight/misspelled-outcome-field", "checkout-preflight/wrong-outcome-field-type", "checkout-preflight/empty-outcome-pattern", "checkout-preflight/all-gates-type-strict" ], "gateRefs": [ "quality-typecheck", "quality-lint", "quality-format", "checkout-preflight", "ci-queue-wait", "hook-pre-commit", "hook-pre-push" ] }, { "id": "RM02-NONEMPTY-ANCHORED-QUANTIFICATION", "originalText": "No universally quantified registry check runs until its population is proven non-empty and anchored.", "currentText": "No universally quantified registry check runs over an empty population. Detects accidental and incompetent inventory drift within a checkout; does NOT survive an adversary who rewrites baseline, manifest, and verifier consistently — that guarantee requires RM-60's external boundary.", "claimType": "integrity", "source": "docs/remediation/TASKS.md#d-46", "meaningChanges": [ { "originalText": "No universally quantified registry check runs until its population is proven non-empty and anchored.", "restatement": "No universally quantified registry check runs over an empty population. Detects accidental and incompetent inventory drift within a checkout; does NOT survive an adversary who rewrites baseline, manifest, and verifier consistently — that guarantee requires RM-60's external boundary.", "reason": "D-48/CWE-353 established that a same-checkout baseline detects drift but is not an adversarial trust anchor.", "finding": "D-48", "task": "RM-60", "date": "2026-08-01" } ], "caseRefs": [ "checkout-preflight/empty-registry-populations", "checkout-preflight/inventory-source-and-manifest-shrink", "checkout-preflight/inventory-claim-overstatement" ], "gateRefs": [ "quality-typecheck", "quality-lint", "quality-format", "checkout-preflight", "ci-queue-wait", "hook-pre-commit", "hook-pre-push" ] } ], "proseClaims": [ { "id": "OBSERVE-PROPERTY", "criterionId": "RM02-CHECK-RIGHT", "caseRef": "checkout-preflight/criterion-misbinding" }, { "id": "PREREGISTRATION-BOUNDARY", "criterionId": "RM02-SET-COVERS", "caseRef": "checkout-preflight/criterion-misbinding" }, { "id": "ARTIFACT-INTEGRITY-BOUNDARY", "criterionId": "GATE-SOURCE-DEPLOYMENT", "caseRef": "ci-queue-wait/unknown-option" }, { "id": "IMPOSSIBLE-LAYER-BOUNDARY", "criterionId": "CHECKOUT-PREFLIGHT", "caseRef": "checkout-preflight/stale-build-lock" }, { "id": "PROSE-IS-A-CLAIM", "criterionId": "RM02-PROSE-CONTROL", "caseRef": "checkout-preflight/prose-claim-misbinding" }, { "id": "GENERATED-STATE-SCOPE", "criterionId": "CHECKOUT-PREFLIGHT", "caseRef": "checkout-preflight/stale-build-lock" }, { "id": "EXECUTION-TRUST-BOUNDARY", "criterionId": "RM02-CURRENT-TREE-BOUNDARY", "caseRef": "checkout-preflight/privileged-pr-gate" }, { "id": "CRITERION-RESTATEMENT", "criterionId": "RM02-MEANING-PROVENANCE", "caseRef": "checkout-preflight/missing-meaning-provenance" }, { "id": "INVENTORY-DRIFT-BOUNDARY", "criterionId": "RM02-NONEMPTY-ANCHORED-QUANTIFICATION", "caseRef": "checkout-preflight/inventory-claim-overstatement" } ], "compatibilityScenarios": [ { "id": "QUALITY-AND-PREFLIGHT", "construction": "clean-current-tree", "caseRefs": [ "quality-typecheck/clean-tree", "quality-lint/clean-tree", "quality-format/clean-tree", "checkout-preflight/clean-tree" ], "invocation": [ "sh", "-c", "pnpm typecheck && pnpm lint && pnpm format:check && node scripts/preflight.mjs" ], "expected": { "exitCode": 0, "outputPattern": "checkout preflight passed" } }, { "id": "HOOK-CHAIN", "construction": "hook-propagation-model", "caseRefs": ["hook-pre-commit/lint-staged-failure", "hook-pre-push/typecheck-failure"], "invocation": [ "sh", "-c", "sh .husky/pre-commit; pre_commit=$?; sh .husky/pre-push; pre_push=$?; test \"$pre_commit\" = 19 && test \"$pre_push\" = 19" ], "expected": { "exitCode": 0, "outputPattern": "FAKE_NPX_EXIT=19[\\s\\S]*FAKE_PNPM_FAILURE=typecheck" } } ], "mergeAssertions": { "mode": "unprivileged-current-tree-verification-with-history-provenance-excluded", "deferredReplayOwner": "RM-60", "trustDependencies": ["RM-60"], "postMergeResponse": "RM-60 defines provider-owned protected execution, quarantine, and revert behavior" }, "gates": [ { "id": "quality-typecheck", "source": "package.json", "invocation": ["pnpm", "typecheck"], "deployment": { "kind": "none", "reason": "The package script in this checkout is the invoked artifact." }, "inertMutation": { "file": "package.json", "find": "\"typecheck\": \"pnpm preflight && turbo run typecheck\"", "replace": "\"typecheck\": \"exit 0\"", "caseId": "type-error", "expected": { "exitCode": 0, "notOutputPattern": "__gate_typecheck__\\.ts" } }, "cases": [ { "id": "clean-tree", "criterionIds": ["QUALITY-TYPECHECK", "RM02-MODELED-CONSISTENCY"], "mustFail": false, "required": { "exitCode": 0 }, "actual": { "exitCode": 0 }, "reasonPattern": "", "evidence": { "subject": "quality-typecheck" } }, { "id": "type-error", "criterionIds": ["QUALITY-TYPECHECK", "RM02-CHECK-RIGHT"], "mustFail": true, "required": { "exitCode": 2, "outputPattern": "Type 'number' is not assignable to type 'string'" }, "actual": { "exitCode": 2, "outputPattern": "Type 'number' is not assignable to type 'string'" }, "reasonPattern": "__gate_typecheck__\\.ts", "environment": { "TURBO_FORCE": "true" }, "fixture": { "writeFiles": [ { "path": "packages/types/src/__gate_typecheck__.ts", "content": "export const gateTypeError: string = 42;\n" } ] }, "evidence": { "subject": "quality-typecheck" } } ] }, { "id": "quality-lint", "source": "package.json", "invocation": ["pnpm", "lint"], "deployment": { "kind": "none", "reason": "The package script in this checkout is the invoked artifact." }, "inertMutation": { "file": "package.json", "find": "\"lint\": \"turbo run lint\"", "replace": "\"lint\": \"exit 0\"", "caseId": "invalid-syntax", "expected": { "exitCode": 0, "notOutputPattern": "__gate_lint__\\.ts" } }, "cases": [ { "id": "clean-tree", "criterionIds": ["QUALITY-LINT", "RM02-MODELED-CONSISTENCY"], "mustFail": false, "required": { "exitCode": 0 }, "actual": { "exitCode": 0 }, "reasonPattern": "", "evidence": { "subject": "quality-lint" } }, { "id": "invalid-syntax", "criterionIds": ["QUALITY-LINT", "RM02-CHECK-RIGHT"], "mustFail": true, "required": { "exitCode": 1, "outputPattern": "Parsing error" }, "actual": { "exitCode": 1, "outputPattern": "Parsing error" }, "reasonPattern": "__gate_lint__\\.ts", "environment": { "TURBO_FORCE": "true" }, "fixture": { "writeFiles": [ { "path": "packages/types/src/__gate_lint__.ts", "content": "export const = ;\n" } ] }, "evidence": { "subject": "quality-lint" } } ] }, { "id": "quality-format", "source": "package.json", "invocation": ["pnpm", "format:check"], "deployment": { "kind": "none", "reason": "The package script in this checkout is the invoked artifact." }, "inertMutation": { "file": "package.json", "find": "\"format:check\": \"prettier --check \\\"**/*.{ts,tsx,js,jsx,json,md}\\\"\"", "replace": "\"format:check\": \"exit 0\"", "caseId": "unformatted-json", "expected": { "exitCode": 0, "notOutputPattern": "__gate_format__\\.json" } }, "cases": [ { "id": "clean-tree", "criterionIds": ["QUALITY-FORMAT", "RM02-MODELED-CONSISTENCY"], "mustFail": false, "required": { "exitCode": 0 }, "actual": { "exitCode": 0 }, "reasonPattern": "", "evidence": { "subject": "quality-format" } }, { "id": "unformatted-json", "criterionIds": ["QUALITY-FORMAT", "RM02-CHECK-RIGHT"], "mustFail": true, "required": { "exitCode": 1, "outputPattern": "__gate_format__\\.json" }, "actual": { "exitCode": 1, "outputPattern": "__gate_format__\\.json" }, "reasonPattern": "Code style issues found", "fixture": { "writeFiles": [ { "path": "gates/__gate_format__.json", "content": "{\"bad\":true,\"spacing\":[1,2,3]}\n" } ] }, "evidence": { "subject": "quality-format" } } ] }, { "id": "checkout-preflight", "source": "scripts/preflight.mjs", "invocation": ["node", "scripts/preflight.mjs"], "deployment": { "kind": "none", "reason": "The checkout source is the directly invoked runtime artifact." }, "inertMutation": { "file": "scripts/preflight.mjs", "find": "code: GENERATED_STATE_EXIT,\n message: `MOSAIC_PREFLIGHT_GENERATED_STATE: web build is in progress", "replace": "code: 0,\n message: `MOSAIC_PREFLIGHT_GENERATED_STATE: web build is in progress", "caseId": "stale-build-lock", "expected": { "exitCode": 0, "outputPattern": "MOSAIC_PREFLIGHT_GENERATED_STATE" } }, "cases": [ { "id": "clean-tree", "criterionIds": ["CHECKOUT-PREFLIGHT", "RM02-MODELED-CONSISTENCY"], "mustFail": false, "required": { "exitCode": 0, "outputPattern": "checkout preflight passed" }, "actual": { "exitCode": 0, "outputPattern": "checkout preflight passed" }, "reasonPattern": "", "evidence": { "subject": "checkout-preflight" } }, { "id": "stale-build-lock", "criterionIds": ["CHECKOUT-PREFLIGHT", "RM02-CHECK-RIGHT"], "mustFail": true, "required": { "exitCode": 43, "outputPattern": "web build is in progress or interrupted" }, "actual": { "exitCode": 43, "outputPattern": "web build is in progress or interrupted" }, "reasonPattern": "MOSAIC_PREFLIGHT_GENERATED_STATE", "fixture": { "writeFiles": [ { "path": ".mosaic-test-work/web-build.lock", "content": "negative control\n" } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "privileged-pr-gate", "criterionIds": ["RM02-CURRENT-TREE-BOUNDARY"], "mustFail": true, "invocation": ["node", "--test", "scripts/gate-wiring.test.mjs"], "required": { "exitCode": 1, "outputPattern": "privileged" }, "actual": { "exitCode": 1, "outputPattern": "privileged" }, "reasonPattern": "privileged", "fixture": { "copyPaths": [".woodpecker/ci.yml", "scripts/gate-wiring.test.mjs", "package.json"], "replaceFiles": [ { "path": ".woodpecker/ci.yml", "find": " gate-verify:\n image: *node_image\n", "replace": " gate-verify:\n image: *node_image\n privileged: true\n" } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "criterion-misbinding", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-SET-COVERS"], "mustFail": true, "invocation": [ "node", "scripts/gate-verify.mjs", "--root", ".", "--manifest", "gates/gates.manifest.json", "--structure-only" ], "required": { "exitCode": 1, "outputPattern": "RM02-SET-COVERS: declared exercising case checkout-preflight/criterion-misbinding is not bound" }, "actual": { "exitCode": 1, "outputPattern": "RM02-SET-COVERS: declared exercising case checkout-preflight/criterion-misbinding is not bound" }, "reasonPattern": "RM02-SET-COVERS: declared exercising case checkout-preflight/criterion-misbinding is not bound", "fixture": { "copyPaths": ["gates/gates.manifest.json", "scripts/gate-verify.mjs"], "replaceFiles": [ { "path": "gates/gates.manifest.json", "find": "\"criterionIds\": [\"QUALITY-TYPECHECK\", \"RM02-CHECK-RIGHT\"],", "replace": "\"criterionIds\": [\"QUALITY-TYPECHECK\", \"RM02-CHECK-RIGHT\", \"RM02-SET-COVERS\"]," }, { "path": "gates/gates.manifest.json", "find": "\"criterionIds\": [\"RM02-CHECK-RIGHT\", \"RM02-SET-COVERS\"],", "replace": "\"criterionIds\": [\"RM02-CHECK-RIGHT\"]," } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "missing-meaning-provenance", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-MEANING-PROVENANCE"], "mustFail": true, "invocation": [ "node", "scripts/gate-verify.mjs", "--root", ".", "--manifest", "gates/gates.manifest.json", "--structure-only" ], "required": { "exitCode": 1, "outputPattern": "RM02-MEANING-PROVENANCE: missing meaning-change provenance" }, "actual": { "exitCode": 1, "outputPattern": "RM02-MEANING-PROVENANCE: missing meaning-change provenance" }, "reasonPattern": "RM02-MEANING-PROVENANCE: missing meaning-change provenance", "fixture": { "copyPaths": ["gates/gates.manifest.json", "scripts/gate-verify.mjs"], "replaceFiles": [ { "path": "gates/gates.manifest.json", "find": "\"currentText\": \"A restated criterion retains original text, restatement, and reason.\",", "replace": "\"currentText\": \"A restated criterion changed without provenance\"," } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "prose-claim-misbinding", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-PROSE-CONTROL"], "mustFail": true, "invocation": [ "node", "scripts/gate-verify.mjs", "--root", ".", "--manifest", "gates/gates.manifest.json", "--structure-only" ], "required": { "exitCode": 1, "outputPattern": "GATE-CLAIM:PROSE-IS-A-CLAIM exercising case quality-typecheck/type-error does not exercise criterion RM02-PROSE-CONTROL" }, "actual": { "exitCode": 1, "outputPattern": "GATE-CLAIM:PROSE-IS-A-CLAIM exercising case quality-typecheck/type-error does not exercise criterion RM02-PROSE-CONTROL" }, "reasonPattern": "GATE-CLAIM:PROSE-IS-A-CLAIM exercising case quality-typecheck/type-error does not exercise criterion RM02-PROSE-CONTROL", "fixture": { "copyPaths": ["gates/gates.manifest.json", "scripts/gate-verify.mjs"], "replaceFiles": [ { "path": "gates/gates.manifest.json", "find": "\"caseRef\": \"checkout-preflight/prose-claim-misbinding\"", "replace": "\"caseRef\": \"quality-typecheck/type-error\"" } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "misspelled-outcome-field", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-TYPE-STRICT-SCHEMA"], "mustFail": true, "invocation": [ "node", "scripts/gate-verify.mjs", "--root", ".", "--manifest", "gates/gates.manifest.json", "--structure-only" ], "required": { "exitCode": 1, "outputPattern": "required: unknown field outputPatern" }, "actual": { "exitCode": 1, "outputPattern": "required: unknown field outputPatern" }, "reasonPattern": "required: unknown field outputPatern", "fixture": { "copyPaths": ["gates/gates.manifest.json", "scripts/gate-verify.mjs"], "replaceFiles": [ { "path": "gates/gates.manifest.json", "find": "\"required\": {\n \"exitCode\": 0,\n \"outputPattern\": \"checkout preflight passed\"\n },\n \"actual\":", "replace": "\"required\": {\n \"exitCode\": 0,\n \"outputPatern\": \"checkout preflight passed\"\n },\n \"actual\":" } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "wrong-outcome-field-type", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-TYPE-STRICT-SCHEMA"], "mustFail": true, "invocation": [ "node", "scripts/gate-verify.mjs", "--root", ".", "--manifest", "gates/gates.manifest.json", "--structure-only" ], "required": { "exitCode": 1, "outputPattern": "required.exitCode: expected an integer" }, "actual": { "exitCode": 1, "outputPattern": "required.exitCode: expected an integer" }, "reasonPattern": "required.exitCode: expected an integer", "fixture": { "copyPaths": ["gates/gates.manifest.json", "scripts/gate-verify.mjs"], "replaceFiles": [ { "path": "gates/gates.manifest.json", "find": "\"required\": {\n \"exitCode\": 0,\n \"outputPattern\": \"checkout preflight passed\"\n },\n \"actual\":", "replace": "\"required\": {\n \"exitCode\": \"0\",\n \"outputPattern\": \"checkout preflight passed\"\n },\n \"actual\":" } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "empty-outcome-pattern", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-TYPE-STRICT-SCHEMA"], "mustFail": true, "invocation": [ "node", "scripts/gate-verify.mjs", "--root", ".", "--manifest", "gates/gates.manifest.json", "--structure-only" ], "required": { "exitCode": 1, "outputPattern": "required.outputPattern: expected a non-empty pattern" }, "actual": { "exitCode": 1, "outputPattern": "required.outputPattern: expected a non-empty pattern" }, "reasonPattern": "required.outputPattern: expected a non-empty pattern", "fixture": { "copyPaths": ["gates/gates.manifest.json", "scripts/gate-verify.mjs"], "replaceFiles": [ { "path": "gates/gates.manifest.json", "find": "\"required\": {\n \"exitCode\": 0,\n \"outputPattern\": \"checkout preflight passed\"\n },\n \"actual\":", "replace": "\"required\": {\n \"exitCode\": 0,\n \"outputPattern\": \" \"\n },\n \"actual\":" } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "empty-registry-populations", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-NONEMPTY-ANCHORED-QUANTIFICATION"], "mustFail": true, "invocation": ["node", "scripts/gate-empty-population-control.mjs"], "required": { "exitCode": 1, "outputPattern": "empty universally quantified registry populations rejected" }, "actual": { "exitCode": 1, "outputPattern": "empty universally quantified registry populations rejected" }, "reasonPattern": "empty universally quantified registry populations rejected", "evidence": { "subject": "checkout-preflight" } }, { "id": "all-gates-evidence-subject-bound", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-EVIDENCE-SUBJECT-BINDING"], "mustFail": true, "invocation": ["node", "scripts/gate-population-control.mjs", "evidence-subject"], "required": { "exitCode": 1, "outputPattern": "evidence-subject population control rejected every registered gate" }, "actual": { "exitCode": 1, "outputPattern": "evidence-subject population control rejected every registered gate" }, "reasonPattern": "evidence-subject population control rejected every registered gate", "evidence": { "subject": "checkout-preflight" } }, { "id": "all-gates-type-strict", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-TYPE-STRICT-SCHEMA"], "mustFail": true, "invocation": ["node", "scripts/gate-population-control.mjs", "type-strict"], "required": { "exitCode": 1, "outputPattern": "type-strict population control rejected every registered gate" }, "actual": { "exitCode": 1, "outputPattern": "type-strict population control rejected every registered gate" }, "reasonPattern": "type-strict population control rejected every registered gate", "evidence": { "subject": "checkout-preflight" } }, { "id": "history-provenance-exclusion", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-HISTORY-PROVENANCE-EXCLUDED"], "mustFail": true, "invocation": ["node", "scripts/gate-history-exclusion-control.mjs"], "required": { "exitCode": 79, "outputPattern": "HISTORY_PROVENANCE_FORBIDDEN" }, "actual": { "exitCode": 79, "outputPattern": "HISTORY_PROVENANCE_FORBIDDEN" }, "reasonPattern": "HISTORY_PROVENANCE_FORBIDDEN", "fixture": { "copyPaths": ["scripts/gate-history-exclusion-control.mjs", "scripts/gate-verify.mjs"], "replaceFiles": [ { "path": "scripts/gate-verify.mjs", "find": "const CURRENT_TREE_OBSERVATION_PATTERNS = [\n /^META-NEGATIVE-CONTROL /,", "replace": "const CURRENT_TREE_OBSERVATION_PATTERNS = [\n /^COMMIT ANCESTRY VERIFIED /,\n /^META-NEGATIVE-CONTROL /," } ] }, "evidence": { "subject": "checkout-preflight" } }, { "id": "inventory-source-and-manifest-shrink", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-NONEMPTY-ANCHORED-QUANTIFICATION"], "mustFail": true, "invocation": ["node", "scripts/gate-inventory-shrink-control.mjs"], "required": { "exitCode": 83, "outputPattern": "INVENTORY_SHRINK_REJECTED" }, "actual": { "exitCode": 83, "outputPattern": "INVENTORY_SHRINK_REJECTED" }, "reasonPattern": "INVENTORY_SHRINK_REJECTED", "evidence": { "subject": "checkout-preflight" } }, { "id": "inventory-claim-overstatement", "criterionIds": ["RM02-CHECK-RIGHT", "RM02-NONEMPTY-ANCHORED-QUANTIFICATION"], "mustFail": true, "invocation": ["node", "scripts/gate-inventory-claim-control.mjs"], "required": { "exitCode": 84, "outputPattern": "INVENTORY_CLAIM_OVERSTATED" }, "actual": { "exitCode": 84, "outputPattern": "INVENTORY_CLAIM_OVERSTATED" }, "reasonPattern": "INVENTORY_CLAIM_OVERSTATED", "fixture": { "copyPaths": [ "scripts/gate-inventory-claim-control.mjs", "gates/required-gates.baseline.json", "gates/gates.manifest.json", "docs/PRD.md", "docs/ADMIN-GUIDE/quality-gate-registry.md", "docs/DEVELOPER-GUIDE/quality-gate-registry.md", "docs/remediation/GATE-CLAIMS.md", "docs/plans/2026-08-01-rm-02-gate-registry.md", "docs/SITEMAP.md" ], "replaceFiles": [ { "path": "gates/required-gates.baseline.json", "find": "Detects accidental and incompetent inventory drift within a checkout; does NOT survive an adversary who rewrites baseline, manifest, and verifier consistently — that guarantee requires RM-60's external boundary.", "replace": "Provides an independent seven-gate baseline comparison." } ] }, "evidence": { "subject": "checkout-preflight" } } ] }, { "id": "ci-queue-wait", "source": "packages/mosaic/framework/tools/git/ci-queue-wait.sh", "invocation": [ "bash", "packages/mosaic/framework/tools/git/ci-queue-wait.sh", "--purpose", "push", "-B", "gate-fixture", "-t", "1", "-i", "0" ], "deployment": { "kind": "file", "source": "packages/mosaic/framework/tools/git/ci-queue-wait.sh", "path": "${HOME}/.config/mosaic/tools/git/ci-queue-wait.sh", "observedSha256": "19cda2f7009c536eb4da9a8df0e7a62f3db0277c9a577bdae5db003f4da3f3cb", "unavailableOwner": "RM-04" }, "inertMutation": { "file": "packages/mosaic/framework/tools/git/ci-queue-wait.sh", "find": "echo \"Unknown option: $1\" >&2\n usage >&2\n exit 1", "replace": "echo \"Unknown option: $1\" >&2\n usage >&2\n exit 0", "caseId": "unknown-option", "sandboxFiles": ["packages/mosaic/framework/tools/git"], "expected": { "exitCode": 0, "outputPattern": "Unknown option: --definitely-unknown" } }, "cases": [ { "id": "terminal-success", "criterionIds": ["QUEUE-GUARD", "GATE-SOURCE-DEPLOYMENT"], "mustFail": false, "required": { "exitCode": 0, "outputPattern": "state=terminal-success.*branch=gate-fixture" }, "actual": { "exitCode": 0, "outputPattern": "state=unknown.*branch=gate-fixture" }, "reasonPattern": "", "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "GITEA_TOKEN": "gate-fixture-token", "GATE_STATUS_JSON": "{\"state\":\"success\",\"statuses\":[]}" }, "fixture": { "copyPaths": ["packages/mosaic/framework/tools/git"], "writeFiles": [ { "path": ".git/config", "content": "[core]\n\trepositoryformatversion = 0\n\tbare = false\n[remote \"origin\"]\n\turl = https://git.mosaicstack.dev/mosaicstack/stack.git\n" }, { "path": ".git/HEAD", "content": "ref: refs/heads/main\n" }, { "path": ".git/objects/.keep", "content": "" }, { "path": ".git/refs/heads/.keep", "content": "" }, { "path": "gate-bin/curl", "mode": 493, "content": "#!/bin/sh\ncase \"$*\" in\n *'/branches/'*) printf '{\"commit\":{\"id\":\"gate-sha\"}}\\n200' ;;\n *'/commits/'*) printf '%s' \"$GATE_STATUS_JSON\" ;;\nesac\n" } ] }, "defect": { "owner": "RM-03", "reason": "The status classifier consumes its Python program from stdin, so piped provider JSON is not read and even terminal success becomes unknown." }, "evidence": { "subject": "ci-queue-wait" } }, { "id": "no-status-required", "criterionIds": ["QUEUE-GUARD", "RM02-CHECK-RIGHT"], "mustFail": true, "required": { "exitCode": 1, "outputPattern": "No CI status contexts" }, "actual": { "exitCode": 0, "outputPattern": "state=unknown" }, "reasonPattern": "state=unknown", "invocation": [ "bash", "packages/mosaic/framework/tools/git/ci-queue-wait.sh", "--purpose", "push", "-B", "gate-fixture", "--require-status", "-t", "1", "-i", "0" ], "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "GITEA_TOKEN": "gate-fixture-token", "GATE_STATUS_JSON": "{\"statuses\":[]}" }, "fixture": { "copyPaths": ["packages/mosaic/framework/tools/git"], "writeFiles": [ { "path": ".git/config", "content": "[core]\n\trepositoryformatversion = 0\n\tbare = false\n[remote \"origin\"]\n\turl = https://git.mosaicstack.dev/mosaicstack/stack.git\n" }, { "path": ".git/HEAD", "content": "ref: refs/heads/main\n" }, { "path": ".git/objects/.keep", "content": "" }, { "path": ".git/refs/heads/.keep", "content": "" }, { "path": "gate-bin/curl", "mode": 493, "content": "#!/bin/sh\ncase \"$*\" in\n *'/branches/'*) printf '{\"commit\":{\"id\":\"gate-sha\"}}\\n200' ;;\n *'/commits/'*) printf '%s' \"$GATE_STATUS_JSON\" ;;\nesac\n" } ] }, "defect": { "owner": "RM-03", "reason": "The status classifier does not read the provider payload, so --require-status never reaches no-status." }, "evidence": { "subject": "ci-queue-wait" } }, { "id": "unknown-state", "criterionIds": ["QUEUE-GUARD"], "mustFail": true, "required": { "exitCode": 1, "outputPattern": "state=unknown" }, "actual": { "exitCode": 0, "outputPattern": "state=unknown" }, "defect": { "owner": "RM-03", "reason": "Unknown state currently exits zero (D-6/D-10)." }, "reasonPattern": "state=unknown", "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "GITEA_TOKEN": "gate-fixture-token", "GATE_STATUS_JSON": "{\"state\":\"mystery\",\"statuses\":[]}" }, "fixture": { "copyPaths": ["packages/mosaic/framework/tools/git"], "writeFiles": [ { "path": ".git/config", "content": "[core]\n\trepositoryformatversion = 0\n\tbare = false\n[remote \"origin\"]\n\turl = https://git.mosaicstack.dev/mosaicstack/stack.git\n" }, { "path": ".git/HEAD", "content": "ref: refs/heads/main\n" }, { "path": ".git/objects/.keep", "content": "" }, { "path": ".git/refs/heads/.keep", "content": "" }, { "path": "gate-bin/curl", "mode": 493, "content": "#!/bin/sh\ncase \"$*\" in\n *'/branches/'*) printf '{\"commit\":{\"id\":\"gate-sha\"}}\\n200' ;;\n *'/commits/'*) printf '%s' \"$GATE_STATUS_JSON\" ;;\nesac\n" } ] }, "evidence": { "subject": "ci-queue-wait" } }, { "id": "malformed-status", "criterionIds": ["QUEUE-GUARD"], "mustFail": true, "required": { "exitCode": 1, "outputPattern": "state=unknown" }, "actual": { "exitCode": 0, "outputPattern": "state=unknown" }, "defect": { "owner": "RM-03", "reason": "Malformed provider payload currently becomes unknown and exits zero." }, "reasonPattern": "state=unknown", "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "GITEA_TOKEN": "gate-fixture-token", "GATE_STATUS_JSON": "not-json" }, "fixture": { "copyPaths": ["packages/mosaic/framework/tools/git"], "writeFiles": [ { "path": ".git/config", "content": "[core]\n\trepositoryformatversion = 0\n\tbare = false\n[remote \"origin\"]\n\turl = https://git.mosaicstack.dev/mosaicstack/stack.git\n" }, { "path": ".git/HEAD", "content": "ref: refs/heads/main\n" }, { "path": ".git/objects/.keep", "content": "" }, { "path": ".git/refs/heads/.keep", "content": "" }, { "path": "gate-bin/curl", "mode": 493, "content": "#!/bin/sh\ncase \"$*\" in\n *'/branches/'*) printf '{\"commit\":{\"id\":\"gate-sha\"}}\\n200' ;;\n *'/commits/'*) printf '%s' \"$GATE_STATUS_JSON\" ;;\nesac\n" } ] }, "evidence": { "subject": "ci-queue-wait" } }, { "id": "terminal-failure", "criterionIds": ["QUEUE-GUARD"], "mustFail": true, "required": { "exitCode": 1, "outputPattern": "state=terminal-failure" }, "actual": { "exitCode": 0, "outputPattern": "state=unknown" }, "defect": { "owner": "RM-03", "reason": "The classifier does not read the provider payload; terminal failure becomes unknown and exits zero." }, "reasonPattern": "state=unknown", "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "GITEA_TOKEN": "gate-fixture-token", "GATE_STATUS_JSON": "{\"state\":\"failure\",\"statuses\":[]}" }, "fixture": { "copyPaths": ["packages/mosaic/framework/tools/git"], "writeFiles": [ { "path": ".git/config", "content": "[core]\n\trepositoryformatversion = 0\n\tbare = false\n[remote \"origin\"]\n\turl = https://git.mosaicstack.dev/mosaicstack/stack.git\n" }, { "path": ".git/HEAD", "content": "ref: refs/heads/main\n" }, { "path": ".git/objects/.keep", "content": "" }, { "path": ".git/refs/heads/.keep", "content": "" }, { "path": "gate-bin/curl", "mode": 493, "content": "#!/bin/sh\ncase \"$*\" in\n *'/branches/'*) printf '{\"commit\":{\"id\":\"gate-sha\"}}\\n200' ;;\n *'/commits/'*) printf '%s' \"$GATE_STATUS_JSON\" ;;\nesac\n" } ] }, "evidence": { "subject": "ci-queue-wait" } }, { "id": "push-defaults-to-main", "criterionIds": ["QUEUE-GUARD"], "mustFail": true, "required": { "exitCode": 0, "outputPattern": "branch=feat/rm-02-gate-registry" }, "actual": { "exitCode": 0, "outputPattern": "branch=main" }, "defect": { "owner": "RM-03", "reason": "Push purpose defaults to main instead of the acted-on branch." }, "reasonPattern": "purpose=push.*branch=main", "invocation": [ "bash", "packages/mosaic/framework/tools/git/ci-queue-wait.sh", "--purpose", "push", "-t", "1", "-i", "0" ], "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "GITEA_TOKEN": "gate-fixture-token", "GATE_STATUS_JSON": "{\"state\":\"success\",\"statuses\":[]}" }, "fixture": { "copyPaths": ["packages/mosaic/framework/tools/git"], "writeFiles": [ { "path": ".git/config", "content": "[core]\n\trepositoryformatversion = 0\n\tbare = false\n[remote \"origin\"]\n\turl = https://git.mosaicstack.dev/mosaicstack/stack.git\n" }, { "path": ".git/HEAD", "content": "ref: refs/heads/main\n" }, { "path": ".git/objects/.keep", "content": "" }, { "path": ".git/refs/heads/.keep", "content": "" }, { "path": "gate-bin/curl", "mode": 493, "content": "#!/bin/sh\ncase \"$*\" in\n *'/branches/'*) printf '{\"commit\":{\"id\":\"gate-sha\"}}\\n200' ;;\n *'/commits/'*) printf '%s' \"$GATE_STATUS_JSON\" ;;\nesac\n" } ] }, "evidence": { "subject": "ci-queue-wait" } }, { "id": "unknown-option", "criterionIds": ["QUEUE-GUARD", "RM02-CHECK-RIGHT", "GATE-SOURCE-DEPLOYMENT"], "mustFail": true, "invocation": [ "bash", "packages/mosaic/framework/tools/git/ci-queue-wait.sh", "--definitely-unknown" ], "required": { "exitCode": 1, "outputPattern": "Unknown option" }, "actual": { "exitCode": 1, "outputPattern": "Unknown option" }, "reasonPattern": "--definitely-unknown", "fixture": { "copyPaths": ["packages/mosaic/framework/tools/git"], "writeFiles": [] }, "evidence": { "subject": "ci-queue-wait" } } ] }, { "id": "hook-pre-commit", "source": ".husky/pre-commit", "invocation": ["sh", ".husky/pre-commit"], "deployment": { "kind": "none", "reason": "Husky dispatches the repository .husky/pre-commit file directly; no copied counterpart exists." }, "inertMutation": { "file": ".husky/pre-commit", "find": "npx lint-staged", "replace": "exit 0", "caseId": "lint-staged-failure", "sandboxFiles": [".husky/pre-commit"], "expected": { "exitCode": 0, "notOutputPattern": "FAKE_NPX_EXIT=19" } }, "cases": [ { "id": "clean-staged-input", "criterionIds": ["HOOK-PRE-COMMIT"], "mustFail": false, "required": { "exitCode": 0 }, "actual": { "exitCode": 0 }, "reasonPattern": "", "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "FAKE_EXIT": "0" }, "fixture": { "copyPaths": [".husky/pre-commit"], "writeFiles": [ { "path": "gate-bin/npx", "mode": 493, "content": "#!/bin/sh\necho FAKE_NPX_EXIT=$FAKE_EXIT >&2\nexit \"$FAKE_EXIT\"\n" } ] }, "evidence": { "subject": "hook-pre-commit" } }, { "id": "lint-staged-failure", "criterionIds": ["HOOK-PRE-COMMIT", "RM02-CHECK-RIGHT", "RM02-MODELED-CONSISTENCY"], "mustFail": true, "required": { "exitCode": 19, "outputPattern": "FAKE_NPX_EXIT=19" }, "actual": { "exitCode": 19, "outputPattern": "FAKE_NPX_EXIT=19" }, "reasonPattern": "FAKE_NPX_EXIT=19", "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "FAKE_EXIT": "19" }, "fixture": { "copyPaths": [".husky/pre-commit"], "writeFiles": [ { "path": "gate-bin/npx", "mode": 493, "content": "#!/bin/sh\necho FAKE_NPX_EXIT=$FAKE_EXIT >&2\nexit \"$FAKE_EXIT\"\n" } ] }, "evidence": { "subject": "hook-pre-commit" } } ] }, { "id": "hook-pre-push", "source": ".husky/pre-push", "invocation": ["sh", ".husky/pre-push"], "deployment": { "kind": "none", "reason": "Husky dispatches the repository .husky/pre-push file directly; no copied counterpart exists." }, "inertMutation": { "file": ".husky/pre-push", "find": "pnpm preflight && pnpm typecheck && pnpm lint && pnpm format:check", "replace": "exit 0", "caseId": "typecheck-failure", "sandboxFiles": [".husky/pre-push"], "expected": { "exitCode": 0, "notOutputPattern": "FAKE_PNPM_FAILURE=typecheck" } }, "cases": [ { "id": "all-subgates-succeed", "criterionIds": ["HOOK-PRE-PUSH"], "mustFail": false, "required": { "exitCode": 0 }, "actual": { "exitCode": 0 }, "reasonPattern": "", "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "FAIL_PNPM_COMMAND": "none" }, "fixture": { "copyPaths": [".husky/pre-push"], "writeFiles": [ { "path": "gate-bin/pnpm", "mode": 493, "content": "#!/bin/sh\nif [ \"$1\" = \"$FAIL_PNPM_COMMAND\" ]; then echo FAKE_PNPM_FAILURE=$1 >&2; exit 19; fi\nexit 0\n" } ] }, "evidence": { "subject": "hook-pre-push" } }, { "id": "typecheck-failure", "criterionIds": ["HOOK-PRE-PUSH", "RM02-CHECK-RIGHT", "RM02-MODELED-CONSISTENCY"], "mustFail": true, "required": { "exitCode": 19, "outputPattern": "FAKE_PNPM_FAILURE=typecheck" }, "actual": { "exitCode": 19, "outputPattern": "FAKE_PNPM_FAILURE=typecheck" }, "reasonPattern": "FAKE_PNPM_FAILURE=typecheck", "environment": { "PATH": "${ROOT}/gate-bin:${PATH}", "FAIL_PNPM_COMMAND": "typecheck" }, "fixture": { "copyPaths": [".husky/pre-push"], "writeFiles": [ { "path": "gate-bin/pnpm", "mode": 493, "content": "#!/bin/sh\nif [ \"$1\" = \"$FAIL_PNPM_COMMAND\" ]; then echo FAKE_PNPM_FAILURE=$1 >&2; exit 19; fi\nexit 0\n" } ] }, "evidence": { "subject": "hook-pre-push" } } ] } ] }