@tiphys/kernel 0.0.0 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. package/AGENTS.md +611 -0
  2. package/LICENSE +202 -0
  3. package/assurance-modes.yaml +278 -0
  4. package/checklists/clean-room.yaml +325 -0
  5. package/checklists/env-failure-diagnosis.yaml +68 -0
  6. package/checklists/flake-playbook.yaml +68 -0
  7. package/checklists/hazard-review.yaml +144 -0
  8. package/checklists/plan-review.yaml +103 -0
  9. package/dist/bin/tiphys.d.ts +2 -0
  10. package/dist/bin/tiphys.js +14 -0
  11. package/dist/src/brief.d.ts +32 -0
  12. package/dist/src/brief.js +59 -0
  13. package/dist/src/checklists.d.ts +169 -0
  14. package/dist/src/checklists.js +310 -0
  15. package/dist/src/checks.d.ts +828 -0
  16. package/dist/src/checks.js +3314 -0
  17. package/dist/src/cli.d.ts +9 -0
  18. package/dist/src/cli.js +57 -0
  19. package/dist/src/commands/brief.d.ts +92 -0
  20. package/dist/src/commands/brief.js +320 -0
  21. package/dist/src/commands/checklist.d.ts +42 -0
  22. package/dist/src/commands/checklist.js +168 -0
  23. package/dist/src/commands/doctor.d.ts +35 -0
  24. package/dist/src/commands/doctor.js +605 -0
  25. package/dist/src/commands/gates.d.ts +9 -0
  26. package/dist/src/commands/gates.js +360 -0
  27. package/dist/src/commands/init.d.ts +30 -0
  28. package/dist/src/commands/init.js +128 -0
  29. package/dist/src/commands/lock.d.ts +1 -0
  30. package/dist/src/commands/lock.js +229 -0
  31. package/dist/src/commands/mode.d.ts +40 -0
  32. package/dist/src/commands/mode.js +134 -0
  33. package/dist/src/commands/plan.d.ts +20 -0
  34. package/dist/src/commands/plan.js +105 -0
  35. package/dist/src/commands/pool.d.ts +1 -0
  36. package/dist/src/commands/pool.js +128 -0
  37. package/dist/src/commands/spawn.d.ts +1 -0
  38. package/dist/src/commands/spawn.js +146 -0
  39. package/dist/src/commands/status.d.ts +19 -0
  40. package/dist/src/commands/status.js +120 -0
  41. package/dist/src/commands/teardown.d.ts +1 -0
  42. package/dist/src/commands/teardown.js +79 -0
  43. package/dist/src/commands/tuition.d.ts +21 -0
  44. package/dist/src/commands/tuition.js +218 -0
  45. package/dist/src/commands/validate.d.ts +78 -0
  46. package/dist/src/commands/validate.js +360 -0
  47. package/dist/src/commands/watch.d.ts +1 -0
  48. package/dist/src/commands/watch.js +172 -0
  49. package/dist/src/exec/env.d.ts +128 -0
  50. package/dist/src/exec/env.js +190 -0
  51. package/dist/src/fleet.d.ts +51 -0
  52. package/dist/src/fleet.js +80 -0
  53. package/dist/src/gates/adapters/http-json.d.ts +5 -0
  54. package/dist/src/gates/adapters/http-json.js +283 -0
  55. package/dist/src/gates/adapters/migrations-command.d.ts +1 -0
  56. package/dist/src/gates/adapters/migrations-command.js +373 -0
  57. package/dist/src/gates/citations.d.ts +408 -0
  58. package/dist/src/gates/citations.js +1163 -0
  59. package/dist/src/gates/coverage.d.ts +284 -0
  60. package/dist/src/gates/coverage.js +701 -0
  61. package/dist/src/gates/credentials.d.ts +74 -0
  62. package/dist/src/gates/credentials.js +533 -0
  63. package/dist/src/gates/deploy.d.ts +1 -0
  64. package/dist/src/gates/deploy.js +33 -0
  65. package/dist/src/gates/manifest.d.ts +99 -0
  66. package/dist/src/gates/manifest.js +208 -0
  67. package/dist/src/gates/migrations.d.ts +1 -0
  68. package/dist/src/gates/migrations.js +36 -0
  69. package/dist/src/gates/pin.d.ts +114 -0
  70. package/dist/src/gates/pin.js +154 -0
  71. package/dist/src/gates/red-witness.d.ts +22 -0
  72. package/dist/src/gates/red-witness.js +390 -0
  73. package/dist/src/gates/release.d.ts +283 -0
  74. package/dist/src/gates/release.js +820 -0
  75. package/dist/src/gates/result.d.ts +116 -0
  76. package/dist/src/gates/result.js +91 -0
  77. package/dist/src/gates/run.d.ts +566 -0
  78. package/dist/src/gates/run.js +1536 -0
  79. package/dist/src/gates/schemas/citation-config.schema.json +59 -0
  80. package/dist/src/gates/schemas/coverage-config.schema.json +77 -0
  81. package/dist/src/gates/schemas/gate-manifest.schema.json +125 -0
  82. package/dist/src/gates/schemas/gate-result.schema.json +160 -0
  83. package/dist/src/gates/schemas/phase-declaration.schema.json +42 -0
  84. package/dist/src/gates/schemas/release-record.schema.json +119 -0
  85. package/dist/src/gates/schemas/verifier-config.schema.json +101 -0
  86. package/dist/src/gates/schemas/witness-spec.schema.json +110 -0
  87. package/dist/src/gates/scope.d.ts +131 -0
  88. package/dist/src/gates/scope.js +1018 -0
  89. package/dist/src/gates/suite.d.ts +217 -0
  90. package/dist/src/gates/suite.js +927 -0
  91. package/dist/src/gates/validate.d.ts +121 -0
  92. package/dist/src/gates/validate.js +414 -0
  93. package/dist/src/hooks.d.ts +32 -0
  94. package/dist/src/hooks.js +62 -0
  95. package/dist/src/liveness.d.ts +321 -0
  96. package/dist/src/liveness.js +396 -0
  97. package/dist/src/lock.d.ts +178 -0
  98. package/dist/src/lock.js +500 -0
  99. package/dist/src/modes.d.ts +149 -0
  100. package/dist/src/modes.js +258 -0
  101. package/dist/src/path-identity.d.ts +2 -0
  102. package/dist/src/path-identity.js +10 -0
  103. package/dist/src/plan.d.ts +73 -0
  104. package/dist/src/plan.js +153 -0
  105. package/dist/src/pool.d.ts +130 -0
  106. package/dist/src/pool.js +721 -0
  107. package/dist/src/roles.d.ts +430 -0
  108. package/dist/src/roles.js +734 -0
  109. package/dist/src/spawn.d.ts +177 -0
  110. package/dist/src/spawn.js +332 -0
  111. package/dist/src/status.d.ts +91 -0
  112. package/dist/src/status.js +119 -0
  113. package/dist/src/task.d.ts +264 -0
  114. package/dist/src/task.js +305 -0
  115. package/dist/src/teardown.d.ts +32 -0
  116. package/dist/src/teardown.js +314 -0
  117. package/dist/src/tuition.d.ts +159 -0
  118. package/dist/src/tuition.js +311 -0
  119. package/dist/src/validate.d.ts +230 -0
  120. package/dist/src/validate.js +732 -0
  121. package/dist/src/version.d.ts +3 -0
  122. package/dist/src/version.js +38 -0
  123. package/dist/src/watcher.d.ts +275 -0
  124. package/dist/src/watcher.js +859 -0
  125. package/dist/src/witness/run.d.ts +274 -0
  126. package/dist/src/witness/run.js +1327 -0
  127. package/dist/src/witness/spec.d.ts +102 -0
  128. package/dist/src/witness/spec.js +253 -0
  129. package/dist/tsconfig.src.tsbuildinfo +1 -0
  130. package/gate-registry.yaml +390 -0
  131. package/gates.manifest.json +195 -0
  132. package/package.json +57 -3
  133. package/role-model-config.yaml +88 -0
  134. package/roles/README.md +128 -0
  135. package/roles/_shared-dispatch-contract.md +87 -0
  136. package/roles/adversarial-plan-reviewer.md +80 -0
  137. package/roles/clean-room-reviewer.md +140 -0
  138. package/roles/implementer.md +460 -0
  139. package/roles/investigator.md +138 -0
  140. package/roles/plan-writer.md +95 -0
  141. package/schemas/README.md +81 -0
  142. package/schemas/assurance-modes.schema.json +264 -0
  143. package/schemas/charter.schema.json +166 -0
  144. package/schemas/checklist.schema.json +114 -0
  145. package/schemas/decision-record.schema.json +88 -0
  146. package/schemas/final-report.schema.json +90 -0
  147. package/schemas/finding.schema.json +106 -0
  148. package/schemas/gate-registry.schema.json +260 -0
  149. package/schemas/mechanism-index.schema.json +94 -0
  150. package/schemas/plan.schema.json +300 -0
  151. package/schemas/report.schema.json +579 -0
  152. package/schemas/role-brief.schema.json +105 -0
  153. package/schemas/role-model-config.schema.json +90 -0
  154. package/schemas/status-line.schema.json +40 -0
  155. package/schemas/tuition.schema.json +191 -0
  156. package/schemas/verdict.schema.json +289 -0
  157. package/schemas/work-history.schema.json +183 -0
  158. package/templates/charter.example.yaml +54 -0
  159. package/templates/decision-record.example.yaml +27 -0
  160. package/templates/final-report.example.yaml +80 -0
  161. package/templates/plan.example.yaml +87 -0
  162. package/templates/report.example.yaml +236 -0
  163. package/templates/warnings.md +74 -0
  164. package/templates/work-history.example.yaml +185 -0
  165. package/tuition/README.md +76 -0
  166. package/tuition/T-001.yaml +48 -0
  167. package/tuition/T-002.yaml +51 -0
  168. package/tuition/T-003.yaml +100 -0
  169. package/tuition/T-004.yaml +52 -0
  170. package/tuition/T-005.yaml +72 -0
  171. package/tuition/T-006.yaml +81 -0
  172. package/tuition/T-007.yaml +56 -0
  173. package/tuition/T-008.yaml +111 -0
  174. package/tuition/T-009.yaml +50 -0
  175. package/tuition/T-015.yaml +36 -0
  176. package/tuition/T-016.yaml +36 -0
  177. package/tuition/T-017.yaml +46 -0
  178. package/tuition/T-018.yaml +84 -0
  179. package/tuition/T-021.yaml +40 -0
  180. package/tuition/T-022.yaml +36 -0
  181. package/tuition/mechanism-index.yaml +256 -0
@@ -0,0 +1,36 @@
1
+ # T-016: an acknowledged alarm says nothing new when the state actually
2
+ # changes. Promoted by M3-P8.
3
+ kind: tuition
4
+ version: 1
5
+ id: T-016
6
+ project: tiphys-kernel
7
+ date: 2026-08-12
8
+ stage: orchestrator supervision, one session
9
+ kernel-relevant: true
10
+ what-happened: >-
11
+ A staleness alarm fired, was checked, and was correctly judged a false
12
+ positive against a live agent. The alarm kept reporting the same condition in
13
+ the same words afterwards, so when the underlying state actually changed there
14
+ was nothing new to notice: the message for "still quiet and known healthy" and
15
+ the message for "was alive when last checked, is not now" were identical. An
16
+ acknowledged alarm that repeats itself is a silence with extra steps.
17
+ lesson:
18
+ - >-
19
+ A guard should report a TRANSITION, not a level. Only the transition is
20
+ worth waking someone for.
21
+ - >-
22
+ An acknowledged alarm should be latched with the state it was acknowledged
23
+ AT, and re-fire when the state CHANGES from that, in different words.
24
+ - >-
25
+ The liveness signal has to be part of the guard rather than a separate
26
+ manual step, because a guard that cannot see what the operator saw cannot
27
+ tell the two states apart.
28
+ structural-consequence:
29
+ - target: src/liveness.ts
30
+ status: proposed
31
+ change: >-
32
+ The guard's verdict should carry the transition rather than the level, and
33
+ an acknowledged verdict should be latched at the state it was acknowledged
34
+ at, so the next report differs when the state does.
35
+ evidence:
36
+ - delivery/tuition/T-016-an-acknowledged-alarm-says-nothing-new-when-the-state-changes.md, the session it was measured in
@@ -0,0 +1,46 @@
1
+ # T-017: the beacon instruction asks for a habit, and habits do not survive a
2
+ # working agent. Promoted by M3-P8.
3
+ kind: tuition
4
+ version: 1
5
+ id: T-017
6
+ project: tiphys-kernel
7
+ date: 2026-08-12
8
+ stage: dispatch contract, four instances in one session
9
+ kernel-relevant: true
10
+ what-happened: >-
11
+ The dispatch contract tells every agent to create its work history early and
12
+ append as it works, because the file's mtime is the beacon its supervisor
13
+ watches. Four times in one session an agent working hard went quiet for long
14
+ enough to read as possibly dead, twice with the same number of minutes, because
15
+ "append as you work" names no moment at which to append. A second, sharper
16
+ instance came from fusing two acts in one instruction: an agent told to commit
17
+ and push on every append pushed six times, cancelling five in-flight CI runs
18
+ and leaving the critical-path branch with no completed evidence for two hours.
19
+ lesson:
20
+ - >-
21
+ An instruction that asks for a habit names no moment. A per-action trigger
22
+ ("append after each command whose output you will cite, before running the
23
+ next one") names one, which is a fact about the two texts rather than a
24
+ prediction that rewording will hold.
25
+ - >-
26
+ Committing locally satisfies durability; pushing is a separate act that
27
+ cancels in-flight CI, and fusing them into one instruction is how an
28
+ obedient agent destroys its own evidence.
29
+ - >-
30
+ The watcher should be able to distinguish "alive and not appending" from
31
+ "possibly dead", which is a distinction that belongs in the guard rather
32
+ than in one session's scripts.
33
+ structural-consequence:
34
+ - target: roles/implementer.md
35
+ status: applied
36
+ change: >-
37
+ The incremental-output clause carries the per-action trigger rather than
38
+ the habit, so the brief names a moment at which to append.
39
+ - target: src/watcher.ts
40
+ status: proposed
41
+ change: >-
42
+ The guard cannot today tell "alive and not appending" from "possibly
43
+ dead"; carrying the agent's own liveness signal rather than only mtimes is
44
+ what would separate them.
45
+ evidence:
46
+ - delivery/tuition/T-017-the-beacon-instruction-asks-for-a-habit.md, the four instances and the postscript on the fused instruction
@@ -0,0 +1,84 @@
1
+ # T-018: two checks that catch the same input make each other unwitnessable.
2
+ # Promoted by M3-P8, which also carries this entry's mechanism into the index.
3
+ kind: tuition
4
+ version: 1
5
+ id: T-018
6
+ project: tiphys-kernel
7
+ date: 2026-08-12
8
+ stage: M3-P6 fix round 2 (the brief drift check)
9
+ kernel-relevant: true
10
+ what-happened: >-
11
+ A red-witness member mutated one of two checks that reject the same input.
12
+ Neither check is individually necessary, so the mutation left the other one
13
+ covering the arm and no named test could reach the mutated line. The harness
14
+ correctly reported that nothing reddened, and the instruction derived from
15
+ reading that message literally ("write a test that reaches this line") was
16
+ impossible to satisfy. The round tried the instructed fix first, watched it
17
+ stay red, and then read the runner. The same phase's reviews found the wider
18
+ version of the same shape: a check that renders an artifact and compares the
19
+ artifact to that rendering can only see drift BETWEEN the two, so a narrowing
20
+ INSIDE the loop is a fixed point of it and is silent.
21
+ lesson:
22
+ - >-
23
+ Redundancy that cannot be observed is indistinguishable from dead code. A
24
+ line can be un-reddenable not because no test exercises the feature, but
25
+ because a second line in front of it rejects every input that would reach
26
+ it.
27
+ - >-
28
+ Reordering does not dissolve it; it only changes which of the two is
29
+ shadowed.
30
+ - >-
31
+ A gate message that names a line is naming a symptom. The reading is the
32
+ part that has to be earned, and the wrong reading was tried first here.
33
+ mechanisms:
34
+ - mechanism: Checking a generated artifact against its own generator
35
+ rule: >-
36
+ A check that renders an artifact and then compares the artifact to that
37
+ rendering can only see drift BETWEEN the two, so any narrowing INSIDE the
38
+ loop is a fixed point of it and is silent. Three seats can choose what
39
+ gets compared and all three have now been occupied by a real finding: the
40
+ MODE, when it is read out of the artifact being audited; the UNIT COUNT,
41
+ when the generator computes it; and the SELECTION, inside the generator
42
+ itself. Two rules follow. A CHECK WHOSE SUBJECT IS SELECTED BY A VALUE
43
+ READ FROM THE ARTIFACT IT AUDITS CAN BE SILENTLY NARROWED BY EDITING THAT
44
+ ARTIFACT, so pin the subject OUTSIDE the artifact and refuse a
45
+ disagreement in every mode, `--write` included, because `--write` is the
46
+ command that launders a narrowing into the shipped bytes. And A UNIT COUNT
47
+ THAT DOES NOT MEASURE WHAT WAS COMPARED CANNOT MAKE THE VACUITY GUARD
48
+ FIRE, so count the rows actually compared and never add a mode-independent
49
+ term, which gives the count a floor it can never fall below. Closing the
50
+ third seat needs a SECOND, INDEPENDENT statement of what the artifact must
51
+ contain, derived from the AUTHORITY and never routed through the
52
+ generator; nothing that calls the generator can close it. Make that
53
+ statement SET EQUALITY AND FIELD PRESENCE, not containment: dropping rows
54
+ and dropping a column from rows that all survive are structurally
55
+ different members, and each is invisible to the assertion that catches the
56
+ other. State it in two places that fail independently, and derive per item
57
+ at run time rather than pinning a count, because these registries are
58
+ append-only.
59
+ siblings:
60
+ - scripts/check-brief-drift.mjs
61
+ - scripts/render-agent-rules-gates.mjs
62
+ - src/roles.ts
63
+ - test/implementer-brief.test.ts
64
+ evidence:
65
+ - CV-1 and contract A finding 3 in delivery/review/clean-room-m3-p6-criteria.md, two clean-room contracts reaching the mode seat from different directions on one head
66
+ - DV-1 in delivery/review/verification-m3-p6-fix-round.md, the selection seat, silent to the whole suite and to every gate in the PR bundle
67
+ - "M3-P6 fix round 2 measured `scripts/render-agent-rules-gates.mjs` carrying the same defect UNFIXED: its rowCount is registry-derived, so the check reports 15 gates over a CLAUDE.md block holding 13, with the suite green"
68
+ structural-consequence:
69
+ - target: scripts/check-brief-drift.mjs
70
+ status: applied
71
+ change: >-
72
+ The drift check pins its subject outside the artifact it audits and counts
73
+ the rows actually compared, so a narrowing inside the loop cannot be
74
+ silent.
75
+ - target: test/implementer-brief.test.ts
76
+ status: applied
77
+ change: >-
78
+ A second, independent statement of what the brief must contain is derived
79
+ from the authority rather than from the generator, and it asserts set
80
+ equality and field presence rather than containment.
81
+ evidence:
82
+ - delivery/tuition/T-018-two-checks-catching-the-same-input-make-each-other-unwitnessable.md, the round's account and the correction
83
+ - delivery/review/verification-m3-p6-fix-round.md, the delta verification that found the selection seat
84
+ - delivery/work-history/m3-p6.md, the round that tried the instructed fix first
@@ -0,0 +1,40 @@
1
+ # T-021: MIGRATION TICKET, not an incident. Plan v1 section 11 item 7 parked
2
+ # two L1 enforcement items for the tuition flow to carry; this is the first.
3
+ # Recorded here at M3-P8 and executed post-M3.
4
+ kind: tuition
5
+ version: 1
6
+ id: T-021
7
+ project: tiphys-kernel
8
+ date: 2026-08-12
9
+ stage: M3-P8, recorded as a migration ticket
10
+ kernel-relevant: true
11
+ what-happened: >-
12
+ Plan v1 decision D-9 places "a review is never skipped" in Layer 1, meaning
13
+ enforced by the substrate rather than by an agent obeying a brief. The
14
+ substrate half is branch protection whose required checks depend on the
15
+ delivery mode: full mode requires the review gates, local-only mode cannot
16
+ require a pull request at all. None of it is built. Today the rule lives in
17
+ the orchestrator's brief and in the gate registry's applicability, which is
18
+ Layer 2: it holds while every agent obeys, and it has no floor under it if one
19
+ does not. This entry exists so the gap is a tracked artifact rather than a
20
+ sentence in a plan nobody re-reads.
21
+ lesson:
22
+ - >-
23
+ A rule enforced only by a brief is enforced by whoever is reading the
24
+ brief. Recording the intended enforcement layer next to the rule is what
25
+ makes the gap visible.
26
+ - >-
27
+ Mode-awareness is the hard half. A protection rule that assumes a pull
28
+ request breaks local-only mode, so the enforcement has to be derived from
29
+ the charter's delivery mode rather than fixed.
30
+ structural-consequence:
31
+ - target: gate-registry.yaml
32
+ status: ticketed
33
+ change: >-
34
+ Mode-aware branch-protection enforcement of the never-skipped review, so
35
+ the rule has a Layer 1 floor rather than living only in a brief. Executed
36
+ post-M3, per plan v1 section 11 item 7.
37
+ record: delivery/plan/kernel-plan-v1.md section 11 item 7 (D-9)
38
+ evidence:
39
+ - delivery/plan/kernel-plan-v1.md, section 11 item 7, which parks both L1 items for the tuition flow to carry
40
+ - delivery/decisions/DR-0012-delegated-merge-authority.md, the delegation this rule protects
@@ -0,0 +1,36 @@
1
+ # T-022: MIGRATION TICKET, not an incident. The second of the two L1 items plan
2
+ # v1 section 11 item 7 parked for this moment. Recorded at M3-P8, executed
3
+ # post-M3.
4
+ kind: tuition
5
+ version: 1
6
+ id: T-022
7
+ project: tiphys-kernel
8
+ date: 2026-08-12
9
+ stage: M3-P8, recorded as a migration ticket
10
+ kernel-relevant: true
11
+ what-happened: >-
12
+ Plan v1 decision D-10 places "validate before you push" in Layer 1: a push
13
+ that has not been through the validator is refused by the substrate, not by
14
+ the agent remembering. Nothing enforces it today. The validator exists as of
15
+ M3-P1 and the gates run in CI, which means the failure is caught AFTER the
16
+ push rather than before it, and the cost of that ordering is a red run, a
17
+ cancelled bundle and a round trip for something a pre-push check would have
18
+ named in a second.
19
+ lesson:
20
+ - >-
21
+ A check that runs after the act it was supposed to prevent is a report,
22
+ not an enforcement.
23
+ - >-
24
+ The pre-validation check must be derivable from the same registry CI uses,
25
+ or it becomes a second list that drifts from the first.
26
+ structural-consequence:
27
+ - target: gate-registry.yaml
28
+ status: ticketed
29
+ change: >-
30
+ A pre-push validation check derived from the registry's local-only mode,
31
+ so the same declarations drive both the pre-push refusal and the CI
32
+ bundle. Executed post-M3, per plan v1 section 11 item 7.
33
+ record: delivery/plan/kernel-plan-v1.md section 11 item 7 (D-10)
34
+ evidence:
35
+ - delivery/plan/kernel-plan-v1.md, section 11 item 7, which parks both L1 items for the tuition flow to carry
36
+ - delivery/work-history/m3-p1.md, the validator this check would call
@@ -0,0 +1,256 @@
1
+ # THE MECHANISM INDEX (kernel plan M3; T-005, D-M3-23).
2
+ #
3
+ # GENERATED BY `tiphys tuition index`. DO NOT EDIT THIS FILE. It is a
4
+ # PROJECTION of the `mechanisms[]` field of every entry in the tuition feed
5
+ # beside it, so a rule is recorded once, in the entry that paid for it, and
6
+ # read from here. `tiphys tuition index --check` compares this file against a
7
+ # fresh projection and exits nonzero on any drift, which is what stops the two
8
+ # from becoming two sources.
9
+ #
10
+ # READ THE ROW BEFORE YOU USE THE MECHANISM. Every rule here was paid for with
11
+ # a defect, a fix round, or an investigation, which is why `evidence` is a
12
+ # required field with at least one entry: a rule with no citation is not a
13
+ # rule.
14
+ #
15
+ # WHY THIS FILE EXISTS AT ALL. T-005 records a rule M1-P3 paid for in a
16
+ # multi-hour investigation that did not reach M1-P5, which reimplemented the
17
+ # same claim-file mechanism silently and produced the most severe defect found
18
+ # in that milestone. The implementer there had read the plan, the agent-rules
19
+ # file, the constraint list, the accumulated environment warnings and three
20
+ # work histories. None of them carried the rule, because a rule about a
21
+ # MECHANISM has no home in a set of documents organised by phase. This is that
22
+ # home, and the obligation to consult it is the `mechanism-lookup` clause in
23
+ # roles/implementer.md.
24
+ #
25
+ # `key` IS DERIVED FROM `name`, NOT INVENTED: lowercase, every run of
26
+ # characters outside [a-z0-9] collapsed to one hyphen, ends trimmed.
27
+
28
+ kind: mechanism-index
29
+ version: 1
30
+
31
+ mechanisms:
32
+ - key: a-guard-s-own-failure-path
33
+ name: A guard's own failure path
34
+ rule: >-
35
+ A guard whose correctness depends on a crash is not a guard. Make the
36
+ success path total, so removing the explicit failure is visible.
37
+ siblings:
38
+ - test/exit-test-local.test.ts
39
+ evidence:
40
+ - M1-P6 fix round 2, the D3 defang the implementer caught in its own fix
41
+
42
+ - key: append-only-log
43
+ name: Append-only log
44
+ rule: >-
45
+ Never read current state from the tail of a log (constraint C-1).
46
+ Currency comes from `meta.json` and turn-end files only.
47
+ siblings:
48
+ - src/task.ts
49
+ evidence:
50
+ - plan v1 section 3, C-1 (FM-052)
51
+
52
+ - key: asserting-a-ci-step-is-wired
53
+ name: Asserting a CI step is wired
54
+ rule: >-
55
+ Assert BEHAVIOUR, not text. A text assertion catches deletion and misses
56
+ defanging. Extract the step and execute it against stubs. A witness for
57
+ a class must redden under at least two structurally different members.
58
+ siblings:
59
+ - test/exit-test-local.test.ts
60
+ - test/m2-exit-test.test.ts
61
+ - test/implementer-brief.test.ts
62
+ evidence:
63
+ - CR-640, CR-661, CR-681
64
+ - delivery/verification/cr-661-orchestrator-reproduction.md
65
+
66
+ - key: atomic-file-replacement
67
+ name: Atomic file replacement
68
+ rule: >-
69
+ Stage under a name no other pass can collide with. A fixed
70
+ `${path}.stage` lets two concurrent passes share one temporary; the
71
+ loser dies on ENOENT after advancing its seen state, dropping a signal
72
+ in a protocol whose rule is duplicate-rather-than-drop.
73
+ siblings:
74
+ - src/lock.ts
75
+ - src/watch.ts
76
+ evidence:
77
+ - M1-P5 round 4, verified pre-existing against a pristine build
78
+
79
+ - key: checking-a-generated-artifact-against-its-own-generator
80
+ name: Checking a generated artifact against its own generator
81
+ rule: >-
82
+ A check that renders an artifact and then compares the artifact to that
83
+ rendering can only see drift BETWEEN the two, so any narrowing INSIDE
84
+ the loop is a fixed point of it and is silent. Three seats can choose
85
+ what gets compared and all three have now been occupied by a real
86
+ finding: the MODE, when it is read out of the artifact being audited;
87
+ the UNIT COUNT, when the generator computes it; and the SELECTION,
88
+ inside the generator itself. Two rules follow. A CHECK WHOSE SUBJECT IS
89
+ SELECTED BY A VALUE READ FROM THE ARTIFACT IT AUDITS CAN BE SILENTLY
90
+ NARROWED BY EDITING THAT ARTIFACT, so pin the subject OUTSIDE the
91
+ artifact and refuse a disagreement in every mode, `--write` included,
92
+ because `--write` is the command that launders a narrowing into the
93
+ shipped bytes. And A UNIT COUNT THAT DOES NOT MEASURE WHAT WAS COMPARED
94
+ CANNOT MAKE THE VACUITY GUARD FIRE, so count the rows actually compared
95
+ and never add a mode-independent term, which gives the count a floor it
96
+ can never fall below. Closing the third seat needs a SECOND, INDEPENDENT
97
+ statement of what the artifact must contain, derived from the AUTHORITY
98
+ and never routed through the generator; nothing that calls the generator
99
+ can close it. Make that statement SET EQUALITY AND FIELD PRESENCE, not
100
+ containment: dropping rows and dropping a column from rows that all
101
+ survive are structurally different members, and each is invisible to the
102
+ assertion that catches the other. State it in two places that fail
103
+ independently, and derive per item at run time rather than pinning a
104
+ count, because these registries are append-only.
105
+ siblings:
106
+ - scripts/check-brief-drift.mjs
107
+ - scripts/render-agent-rules-gates.mjs
108
+ - src/roles.ts
109
+ - test/implementer-brief.test.ts
110
+ evidence:
111
+ - CV-1 and contract A finding 3 in delivery/review/clean-room-m3-p6-criteria.md, two clean-room contracts reaching the mode seat from different directions on one head
112
+ - DV-1 in delivery/review/verification-m3-p6-fix-round.md, the selection seat, silent to the whole suite and to every gate in the PR bundle
113
+ - "M3-P6 fix round 2 measured `scripts/render-agent-rules-gates.mjs` carrying the same defect UNFIXED: its rowCount is registry-derived, so the check reports 15 gates over a CLAUDE.md block holding 13, with the suite green"
114
+
115
+ - key: claim-file-mutual-exclusion-by-o-excl
116
+ name: Claim file (mutual exclusion by O_EXCL)
117
+ rule: >-
118
+ A claim that cannot be taken must fail LOUDLY and name the stuck file. A
119
+ silent timeout is indistinguishable from an absence of contention. There
120
+ are now THREE claim-file users (the lock, the watcher seen-state, and
121
+ M2-P1's evidence-directory run claim); the next one reads `src/lock.ts`
122
+ first, and the M2-P1 instance is the worked example of doing that and
123
+ stating the one difference (no expiry, because an evidence directory
124
+ must not have a lease that lapses).
125
+ siblings:
126
+ - src/lock.ts
127
+ - src/watch.ts
128
+ - src/gates/run.ts
129
+ evidence:
130
+ - delivery/verification/u2-race-flake-investigation.md D-3
131
+ - delivery/tuition/T-005, the silent reimplementation two phases later that became M1's most severe defect
132
+
133
+ - key: classifying-another-program-s-errors
134
+ name: Classifying another program's errors
135
+ rule: >-
136
+ Derive the signature from REAL captured output under forced conditions,
137
+ never from hand-written examples chosen to match the implementation. 312
138
+ captured contention failures, every one of the dropped shape.
139
+ siblings:
140
+ - src/pool.ts
141
+ evidence:
142
+ - V-2 in delivery/review/verification-m1-p3-fix-round.md
143
+ - CLAUDE.md environment warning 10
144
+
145
+ - key: deciding-what-another-program-will-do-by-pattern-matching-the-text-of-a-file-it-consumes
146
+ name: Deciding what another program will do by pattern-matching the text of a file it consumes
147
+ rule: >-
148
+ A regex over a file and the consuming program's evaluation of that file
149
+ are DIFFERENT FUNCTIONS, so every finding is another input where they
150
+ differ, and rounds close instances forever. Three tiers instead, each
151
+ labelled by what enforces it: execute the extractable part against
152
+ stubs; PIN the accepted shapes and fail closed on anything else, never
153
+ widen the pattern; and where a denylist is unavoidable, DERIVE it by
154
+ walking the consuming program's closed documented vocabulary once,
155
+ publishing the walk. Name what remains unguarded rather than chasing it.
156
+ siblings:
157
+ - test/exit-test-local.test.ts
158
+ - test/m2-exit-test.test.ts
159
+ evidence:
160
+ - Four M1-P6 rounds, CR-640, CR-661, CR-681, CR-720 to CR-725
161
+ - the derived walk found two members no reviewer had named (`working-directory`, a custom `shell` template)
162
+ - "the widen-the-regex approach produced a guard that both missed real defangs and rejected `needs: [test, lint]`, an edit that STRENGTHENS the guarded property"
163
+
164
+ - key: lease-compare-and-swap
165
+ name: Lease compare-and-swap
166
+ rule: >-
167
+ Liveness is lease freshness, never pid, process probing or signals
168
+ (constraint C-2). Expiry does not block a release, but it DOES block a
169
+ renew and it DOES block teardown's holdership check, which fails closed.
170
+ siblings:
171
+ - src/lock.ts
172
+ - src/task.ts
173
+ evidence:
174
+ - src/lock.ts
175
+ - checkHoldership in src/task.ts
176
+ - CR-680 in delivery/review/clean-room-m1-p6-round3-hazard.md
177
+
178
+ - key: parsing-another-program-s-reporter-output
179
+ name: Parsing another program's reporter output
180
+ rule: >-
181
+ PIN the format as a controlled input rather than widening the parse. A
182
+ format-agnostic regex is a union of formats known on the day, and the
183
+ default already differs between the two toolchains this project runs.
184
+ siblings:
185
+ - src/gates/suite.ts
186
+ evidence:
187
+ - M1-P6 floor defect
188
+ - "`NODE_OPTIONS=--test-reporter=tap` scoped to the child"
189
+
190
+ - key: reading-a-path-whose-type-is-not-established
191
+ name: Reading a path whose type is not established
192
+ rule: >-
193
+ lstat the link, stat what it resolves to, open ONLY a regular file. A
194
+ block is not an exception, so try/catch does not touch it.
195
+ siblings:
196
+ - src/task.ts
197
+ - src/lock.ts
198
+ - src/pool.ts
199
+ - src/brief.ts
200
+ - src/hooks.ts
201
+ evidence:
202
+ - CR-520 and the four M1-P5 rounds
203
+ - delivery/verification/cr-520-orchestrator-reproduction.md
204
+
205
+ - key: shared-worktree
206
+ name: Shared worktree
207
+ rule: >-
208
+ A verification lens works in its OWN clone, never in a tree another
209
+ agent is editing, and a run that cannot pin the source it ran against is
210
+ not evidence and must label itself so.
211
+ siblings:
212
+ - src/pool.ts
213
+ evidence:
214
+ - delivery/verification/u2-race-flake-investigation.md, the U-2 phantom and the four hypotheses each run in a private clone
215
+ - delivery/review/verification-m1-p3-fix-round.md, the round whose lenses shared a tree
216
+
217
+ - key: supervising-a-dispatched-agent
218
+ name: Supervising a dispatched agent
219
+ rule: >-
220
+ Supervision is a FRESHNESS watchdog armed in the same turn as the
221
+ dispatch, never a wait for a completion notification and never a probe
222
+ of process liveness (constraint C-2). The watchdog must test freshness,
223
+ never existence and never completion, must watch the union of the paths
224
+ the agent actually writes (measured, not predicted), and must exclude
225
+ the supervisor's own trees, because a watchdog that cannot go red is
226
+ worse than none.
227
+ siblings:
228
+ - src/watcher.ts
229
+ - src/liveness.ts
230
+ evidence:
231
+ - delivery/tuition/T-008-the-orchestrator-had-no-beacon.md, nine hours and eleven minutes measured
232
+ - delivery/tuition/T-014-the-watchdog-watched-the-wrong-place-six-times.md, six wrong applications of the same rule in one session
233
+
234
+ - key: verifying-access-to-a-remote
235
+ name: Verifying access to a remote
236
+ rule: >-
237
+ `git push --dry-run` authenticates against receive-pack and updates no
238
+ ref. `clone` and `ls-remote` are READ operations and witness nothing
239
+ about write access.
240
+ evidence:
241
+ - delivery/tuition/T-006-unexecuted-claims-about-the-world.md, the orchestrator's own instance
242
+
243
+ - key: worktree-removal-and-force-branch-delete
244
+ name: Worktree removal and force branch delete
245
+ rule: >-
246
+ Resolve, evaluate, then apply. No policy decision may be taken after a
247
+ destructive action has begun, and destructive authority is never
248
+ inherited from a component that does not exist yet.
249
+ siblings:
250
+ - src/pool.ts
251
+ - src/teardown.ts
252
+ machine-readable-form:
253
+ path: gates.manifest.json
254
+ key: destructiveCommands
255
+ evidence:
256
+ - delivery/review/verification-m1-p3-fix-round.md V-1 and V-3