fix(quality): prove criterion binding semantics
ci/woodpecker/pr/ci Pipeline was successful

This commit is contained in:
2026-08-01 00:17:50 -05:00
parent 9b4d4beb0e
commit 38f1b249cc
9 changed files with 414 additions and 79 deletions
+195 -46
View File
@@ -25,7 +25,20 @@
"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": []
"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",
"ci-queue-wait/no-status-required",
"ci-queue-wait/unknown-option",
"hook-pre-commit/lint-staged-failure",
"hook-pre-push/typecheck-failure"
]
},
{
"id": "RM02-SET-COVERS",
@@ -33,7 +46,8 @@
"currentText": "Every acceptance criterion is bound to the specific case that exercises it.",
"claimType": "integrity",
"source": "docs/remediation/TASKS.md#d-17",
"meaningChanges": []
"meaningChanges": [],
"caseRefs": ["checkout-preflight/criterion-misbinding"]
},
{
"id": "RM02-MODELED-CONSISTENCY",
@@ -50,6 +64,14 @@
"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"
]
},
{
@@ -58,7 +80,8 @@
"currentText": "A restated criterion retains original text, restatement, and reason.",
"claimType": "integrity",
"source": "docs/remediation/TASKS.md#d-18",
"meaningChanges": []
"meaningChanges": [],
"caseRefs": ["checkout-preflight/missing-meaning-provenance"]
},
{
"id": "RM02-PROSE-CONTROL",
@@ -75,24 +98,26 @@
"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.",
"originalText": "assert that every merged commit passed every required gate, evaluated AGAINST THAT COMMIT'S OWN TREE \u2014 not against current main.",
"currentText": "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.",
"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.",
"originalText": "assert that every merged commit passed every required gate, evaluated AGAINST THAT COMMIT'S OWN TREE \u2014 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"
}
]
],
"caseRefs": ["checkout-preflight/privileged-pr-gate"]
},
{
"id": "QUALITY-TYPECHECK",
@@ -100,7 +125,8 @@
"currentText": "The root typecheck rejects a TypeScript type error.",
"claimType": "quality",
"source": "package.json#scripts.typecheck",
"meaningChanges": []
"meaningChanges": [],
"caseRefs": ["quality-typecheck/clean-tree", "quality-typecheck/type-error"]
},
{
"id": "QUALITY-LINT",
@@ -108,7 +134,8 @@
"currentText": "The root lint gate rejects invalid TypeScript syntax.",
"claimType": "quality",
"source": "package.json#scripts.lint",
"meaningChanges": []
"meaningChanges": [],
"caseRefs": ["quality-lint/clean-tree", "quality-lint/invalid-syntax"]
},
{
"id": "QUALITY-FORMAT",
@@ -116,7 +143,8 @@
"currentText": "The root format gate rejects an unformatted tracked-format input.",
"claimType": "quality",
"source": "package.json#scripts.format:check",
"meaningChanges": []
"meaningChanges": [],
"caseRefs": ["quality-format/clean-tree", "quality-format/unformatted-json"]
},
{
"id": "CHECKOUT-PREFLIGHT",
@@ -133,7 +161,8 @@
"task": "RM-59",
"date": "2026-07-31"
}
]
],
"caseRefs": ["checkout-preflight/clean-tree", "checkout-preflight/stale-build-lock"]
},
{
"id": "QUEUE-GUARD",
@@ -150,6 +179,15 @@
"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"
]
},
{
@@ -158,7 +196,8 @@
"currentText": "The pre-commit hook propagates lint-staged failure.",
"claimType": "workflow",
"source": ".husky/pre-commit",
"meaningChanges": []
"meaningChanges": [],
"caseRefs": ["hook-pre-commit/clean-staged-input", "hook-pre-commit/lint-staged-failure"]
},
{
"id": "HOOK-PRE-PUSH",
@@ -166,7 +205,8 @@
"currentText": "The pre-push hook propagates each required gate failure.",
"claimType": "workflow",
"source": ".husky/pre-push",
"meaningChanges": []
"meaningChanges": [],
"caseRefs": ["hook-pre-push/all-subgates-succeed", "hook-pre-push/typecheck-failure"]
},
{
"id": "GATE-SOURCE-DEPLOYMENT",
@@ -183,41 +223,50 @@
"task": "RM-02",
"date": "2026-08-01"
}
]
],
"caseRefs": ["ci-queue-wait/terminal-success", "ci-queue-wait/unknown-option"]
}
],
"proseClaims": [
{
"id": "OBSERVE-PROPERTY",
"criterionId": "RM02-CHECK-RIGHT"
"criterionId": "RM02-CHECK-RIGHT",
"caseRef": "checkout-preflight/criterion-misbinding"
},
{
"id": "PREREGISTRATION-BOUNDARY",
"criterionId": "RM02-SET-COVERS"
"criterionId": "RM02-SET-COVERS",
"caseRef": "checkout-preflight/criterion-misbinding"
},
{
"id": "ARTIFACT-INTEGRITY-BOUNDARY",
"criterionId": "GATE-SOURCE-DEPLOYMENT"
"criterionId": "GATE-SOURCE-DEPLOYMENT",
"caseRef": "ci-queue-wait/unknown-option"
},
{
"id": "IMPOSSIBLE-LAYER-BOUNDARY",
"criterionId": "CHECKOUT-PREFLIGHT"
"criterionId": "CHECKOUT-PREFLIGHT",
"caseRef": "checkout-preflight/stale-build-lock"
},
{
"id": "PROSE-IS-A-CLAIM",
"criterionId": "RM02-PROSE-CONTROL"
"criterionId": "RM02-PROSE-CONTROL",
"caseRef": "checkout-preflight/prose-claim-misbinding"
},
{
"id": "GENERATED-STATE-SCOPE",
"criterionId": "CHECKOUT-PREFLIGHT"
"criterionId": "CHECKOUT-PREFLIGHT",
"caseRef": "checkout-preflight/stale-build-lock"
},
{
"id": "EXECUTION-TRUST-BOUNDARY",
"criterionId": "RM02-CURRENT-TREE-BOUNDARY"
"criterionId": "RM02-CURRENT-TREE-BOUNDARY",
"caseRef": "checkout-preflight/privileged-pr-gate"
},
{
"id": "CRITERION-RESTATEMENT",
"criterionId": "RM02-MEANING-PROVENANCE"
"criterionId": "RM02-MEANING-PROVENANCE",
"caseRef": "checkout-preflight/missing-meaning-provenance"
}
],
"compatibilityScenarios": [
@@ -296,7 +345,7 @@
},
{
"id": "type-error",
"criterionIds": ["QUALITY-TYPECHECK", "RM02-CHECK-RIGHT", "RM02-SET-COVERS"],
"criterionIds": ["QUALITY-TYPECHECK", "RM02-CHECK-RIGHT"],
"mustFail": true,
"required": {
"exitCode": 2,
@@ -354,7 +403,7 @@
},
{
"id": "invalid-syntax",
"criterionIds": ["QUALITY-LINT", "RM02-CHECK-RIGHT", "RM02-SET-COVERS"],
"criterionIds": ["QUALITY-LINT", "RM02-CHECK-RIGHT"],
"mustFail": true,
"required": {
"exitCode": 1,
@@ -412,7 +461,7 @@
},
{
"id": "unformatted-json",
"criterionIds": ["QUALITY-FORMAT", "RM02-CHECK-RIGHT", "RM02-SET-COVERS"],
"criterionIds": ["QUALITY-FORMAT", "RM02-CHECK-RIGHT"],
"mustFail": true,
"required": {
"exitCode": 1,
@@ -469,13 +518,7 @@
},
{
"id": "stale-build-lock",
"criterionIds": [
"CHECKOUT-PREFLIGHT",
"RM02-CHECK-RIGHT",
"RM02-SET-COVERS",
"RM02-MEANING-PROVENANCE",
"RM02-PROSE-CONTROL"
],
"criterionIds": ["CHECKOUT-PREFLIGHT", "RM02-CHECK-RIGHT"],
"mustFail": true,
"required": {
"exitCode": 43,
@@ -519,6 +562,122 @@
}
]
}
},
{
"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",
"scripts/gate-history.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\"],"
}
]
}
},
{
"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",
"scripts/gate-history.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\","
}
]
}
},
{
"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",
"scripts/gate-history.mjs"
],
"replaceFiles": [
{
"path": "gates/gates.manifest.json",
"find": "\"caseRef\": \"checkout-preflight/prose-claim-misbinding\"",
"replace": "\"caseRef\": \"quality-typecheck/type-error\""
}
]
}
}
]
},
@@ -607,7 +766,7 @@
},
{
"id": "no-status-required",
"criterionIds": ["QUEUE-GUARD", "RM02-CHECK-RIGHT", "RM02-SET-COVERS"],
"criterionIds": ["QUEUE-GUARD", "RM02-CHECK-RIGHT"],
"mustFail": true,
"required": {
"exitCode": 1,
@@ -669,7 +828,7 @@
},
{
"id": "unknown-state",
"criterionIds": ["QUEUE-GUARD", "RM02-SET-COVERS"],
"criterionIds": ["QUEUE-GUARD"],
"mustFail": true,
"required": {
"exitCode": 1,
@@ -946,12 +1105,7 @@
},
{
"id": "lint-staged-failure",
"criterionIds": [
"HOOK-PRE-COMMIT",
"RM02-CHECK-RIGHT",
"RM02-SET-COVERS",
"RM02-MODELED-CONSISTENCY"
],
"criterionIds": ["HOOK-PRE-COMMIT", "RM02-CHECK-RIGHT", "RM02-MODELED-CONSISTENCY"],
"mustFail": true,
"required": {
"exitCode": 19,
@@ -1027,12 +1181,7 @@
},
{
"id": "typecheck-failure",
"criterionIds": [
"HOOK-PRE-PUSH",
"RM02-CHECK-RIGHT",
"RM02-SET-COVERS",
"RM02-MODELED-CONSISTENCY"
],
"criterionIds": ["HOOK-PRE-PUSH", "RM02-CHECK-RIGHT", "RM02-MODELED-CONSISTENCY"],
"mustFail": true,
"required": {
"exitCode": 19,