1627 lines
60 KiB
JSON
1627 lines
60 KiB
JSON
{
|
|
"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"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|