@tiphys/kernel 0.0.0 → 0.2.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 (207) hide show
  1. package/AGENTS.md +663 -0
  2. package/LICENSE +202 -0
  3. package/assurance-modes.yaml +299 -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 +92 -0
  11. package/dist/src/adapters/load.d.ts +202 -0
  12. package/dist/src/adapters/load.js +440 -0
  13. package/dist/src/brief.d.ts +32 -0
  14. package/dist/src/brief.js +66 -0
  15. package/dist/src/checklists.d.ts +169 -0
  16. package/dist/src/checklists.js +310 -0
  17. package/dist/src/checks.d.ts +1539 -0
  18. package/dist/src/checks.js +5025 -0
  19. package/dist/src/cli.d.ts +9 -0
  20. package/dist/src/cli.js +68 -0
  21. package/dist/src/commands/brief.d.ts +92 -0
  22. package/dist/src/commands/brief.js +343 -0
  23. package/dist/src/commands/checklist.d.ts +42 -0
  24. package/dist/src/commands/checklist.js +168 -0
  25. package/dist/src/commands/cutover.d.ts +35 -0
  26. package/dist/src/commands/cutover.js +448 -0
  27. package/dist/src/commands/doctor.d.ts +264 -0
  28. package/dist/src/commands/doctor.js +1546 -0
  29. package/dist/src/commands/gates.d.ts +9 -0
  30. package/dist/src/commands/gates.js +360 -0
  31. package/dist/src/commands/init.d.ts +30 -0
  32. package/dist/src/commands/init.js +177 -0
  33. package/dist/src/commands/lock.d.ts +34 -0
  34. package/dist/src/commands/lock.js +340 -0
  35. package/dist/src/commands/mode.d.ts +40 -0
  36. package/dist/src/commands/mode.js +134 -0
  37. package/dist/src/commands/next.d.ts +130 -0
  38. package/dist/src/commands/next.js +597 -0
  39. package/dist/src/commands/plan.d.ts +20 -0
  40. package/dist/src/commands/plan.js +105 -0
  41. package/dist/src/commands/pool.d.ts +1 -0
  42. package/dist/src/commands/pool.js +139 -0
  43. package/dist/src/commands/resume.d.ts +1 -0
  44. package/dist/src/commands/resume.js +88 -0
  45. package/dist/src/commands/spawn.d.ts +1 -0
  46. package/dist/src/commands/spawn.js +195 -0
  47. package/dist/src/commands/status.d.ts +21 -0
  48. package/dist/src/commands/status.js +122 -0
  49. package/dist/src/commands/sync.d.ts +47 -0
  50. package/dist/src/commands/sync.js +341 -0
  51. package/dist/src/commands/teardown.d.ts +1 -0
  52. package/dist/src/commands/teardown.js +87 -0
  53. package/dist/src/commands/tuition.d.ts +21 -0
  54. package/dist/src/commands/tuition.js +218 -0
  55. package/dist/src/commands/validate.d.ts +78 -0
  56. package/dist/src/commands/validate.js +430 -0
  57. package/dist/src/commands/watch.d.ts +1 -0
  58. package/dist/src/commands/watch.js +172 -0
  59. package/dist/src/cutover.d.ts +584 -0
  60. package/dist/src/cutover.js +1444 -0
  61. package/dist/src/exclusion.d.ts +389 -0
  62. package/dist/src/exclusion.js +843 -0
  63. package/dist/src/exec/env.d.ts +278 -0
  64. package/dist/src/exec/env.js +334 -0
  65. package/dist/src/fleet.d.ts +223 -0
  66. package/dist/src/fleet.js +298 -0
  67. package/dist/src/gates/adapters/http-json.d.ts +5 -0
  68. package/dist/src/gates/adapters/http-json.js +283 -0
  69. package/dist/src/gates/adapters/migrations-command.d.ts +1 -0
  70. package/dist/src/gates/adapters/migrations-command.js +373 -0
  71. package/dist/src/gates/citations.d.ts +408 -0
  72. package/dist/src/gates/citations.js +1169 -0
  73. package/dist/src/gates/coverage.d.ts +375 -0
  74. package/dist/src/gates/coverage.js +836 -0
  75. package/dist/src/gates/credentials.d.ts +233 -0
  76. package/dist/src/gates/credentials.js +752 -0
  77. package/dist/src/gates/deploy.d.ts +1 -0
  78. package/dist/src/gates/deploy.js +33 -0
  79. package/dist/src/gates/gate-classes.d.ts +56 -0
  80. package/dist/src/gates/gate-classes.js +633 -0
  81. package/dist/src/gates/manifest.d.ts +99 -0
  82. package/dist/src/gates/manifest.js +208 -0
  83. package/dist/src/gates/merge-preconditions.d.ts +319 -0
  84. package/dist/src/gates/merge-preconditions.js +932 -0
  85. package/dist/src/gates/migrations.d.ts +1 -0
  86. package/dist/src/gates/migrations.js +36 -0
  87. package/dist/src/gates/pin.d.ts +114 -0
  88. package/dist/src/gates/pin.js +154 -0
  89. package/dist/src/gates/red-witness.d.ts +22 -0
  90. package/dist/src/gates/red-witness.js +482 -0
  91. package/dist/src/gates/release.d.ts +283 -0
  92. package/dist/src/gates/release.js +820 -0
  93. package/dist/src/gates/result.d.ts +116 -0
  94. package/dist/src/gates/result.js +91 -0
  95. package/dist/src/gates/run.d.ts +614 -0
  96. package/dist/src/gates/run.js +1614 -0
  97. package/dist/src/gates/schemas/citation-config.schema.json +59 -0
  98. package/dist/src/gates/schemas/coverage-config.schema.json +77 -0
  99. package/dist/src/gates/schemas/gate-manifest.schema.json +125 -0
  100. package/dist/src/gates/schemas/gate-result.schema.json +160 -0
  101. package/dist/src/gates/schemas/phase-declaration.schema.json +87 -0
  102. package/dist/src/gates/schemas/release-record.schema.json +119 -0
  103. package/dist/src/gates/schemas/verifier-config.schema.json +101 -0
  104. package/dist/src/gates/schemas/witness-spec.schema.json +110 -0
  105. package/dist/src/gates/scope.d.ts +131 -0
  106. package/dist/src/gates/scope.js +1018 -0
  107. package/dist/src/gates/suite.d.ts +217 -0
  108. package/dist/src/gates/suite.js +968 -0
  109. package/dist/src/gates/validate.d.ts +121 -0
  110. package/dist/src/gates/validate.js +414 -0
  111. package/dist/src/hooks.d.ts +84 -0
  112. package/dist/src/hooks.js +125 -0
  113. package/dist/src/index.d.ts +31 -0
  114. package/dist/src/index.js +30 -0
  115. package/dist/src/liveness.d.ts +321 -0
  116. package/dist/src/liveness.js +396 -0
  117. package/dist/src/lock.d.ts +256 -0
  118. package/dist/src/lock.js +792 -0
  119. package/dist/src/model-resolution.d.ts +159 -0
  120. package/dist/src/model-resolution.js +307 -0
  121. package/dist/src/modes.d.ts +149 -0
  122. package/dist/src/modes.js +258 -0
  123. package/dist/src/path-identity.d.ts +34 -0
  124. package/dist/src/path-identity.js +48 -0
  125. package/dist/src/plan.d.ts +73 -0
  126. package/dist/src/plan.js +153 -0
  127. package/dist/src/pool.d.ts +326 -0
  128. package/dist/src/pool.js +988 -0
  129. package/dist/src/roles.d.ts +461 -0
  130. package/dist/src/roles.js +776 -0
  131. package/dist/src/spawn.d.ts +482 -0
  132. package/dist/src/spawn.js +1003 -0
  133. package/dist/src/status.d.ts +116 -0
  134. package/dist/src/status.js +148 -0
  135. package/dist/src/task.d.ts +504 -0
  136. package/dist/src/task.js +307 -0
  137. package/dist/src/teardown.d.ts +39 -0
  138. package/dist/src/teardown.js +422 -0
  139. package/dist/src/tuition.d.ts +159 -0
  140. package/dist/src/tuition.js +311 -0
  141. package/dist/src/validate.d.ts +263 -0
  142. package/dist/src/validate.js +742 -0
  143. package/dist/src/version.d.ts +3 -0
  144. package/dist/src/version.js +38 -0
  145. package/dist/src/watcher.d.ts +275 -0
  146. package/dist/src/watcher.js +849 -0
  147. package/dist/src/witness/run.d.ts +299 -0
  148. package/dist/src/witness/run.js +1373 -0
  149. package/dist/src/witness/spec.d.ts +270 -0
  150. package/dist/src/witness/spec.js +475 -0
  151. package/dist/tsconfig.src.tsbuildinfo +1 -0
  152. package/gate-registry.yaml +526 -0
  153. package/gates.manifest.json +257 -0
  154. package/package.json +72 -3
  155. package/role-model-config.yaml +88 -0
  156. package/roles/README.md +128 -0
  157. package/roles/_shared-dispatch-contract.md +87 -0
  158. package/roles/adversarial-plan-reviewer.md +80 -0
  159. package/roles/clean-room-reviewer.md +140 -0
  160. package/roles/implementer.md +463 -0
  161. package/roles/investigator.md +138 -0
  162. package/roles/plan-writer.md +95 -0
  163. package/schemas/README.md +82 -0
  164. package/schemas/assurance-modes.schema.json +264 -0
  165. package/schemas/charter.schema.json +185 -0
  166. package/schemas/checklist.schema.json +114 -0
  167. package/schemas/cutover-state.schema.json +64 -0
  168. package/schemas/decision-record.schema.json +88 -0
  169. package/schemas/executor-record.schema.json +36 -0
  170. package/schemas/final-report.schema.json +90 -0
  171. package/schemas/finding.schema.json +106 -0
  172. package/schemas/gate-registry.schema.json +260 -0
  173. package/schemas/mechanism-index.schema.json +94 -0
  174. package/schemas/model-resolution.schema.json +362 -0
  175. package/schemas/plan.schema.json +300 -0
  176. package/schemas/report.schema.json +579 -0
  177. package/schemas/role-brief.schema.json +105 -0
  178. package/schemas/role-model-config.schema.json +90 -0
  179. package/schemas/status-line.schema.json +40 -0
  180. package/schemas/tuition.schema.json +191 -0
  181. package/schemas/verdict.schema.json +295 -0
  182. package/schemas/work-history.schema.json +183 -0
  183. package/schemas/write-bypass.schema.json +69 -0
  184. package/templates/charter.example.yaml +54 -0
  185. package/templates/decision-record.example.yaml +27 -0
  186. package/templates/final-report.example.yaml +80 -0
  187. package/templates/plan.example.yaml +87 -0
  188. package/templates/report.example.yaml +236 -0
  189. package/templates/warnings.md +74 -0
  190. package/templates/work-history.example.yaml +185 -0
  191. package/tuition/README.md +76 -0
  192. package/tuition/T-001.yaml +48 -0
  193. package/tuition/T-002.yaml +51 -0
  194. package/tuition/T-003.yaml +100 -0
  195. package/tuition/T-004.yaml +52 -0
  196. package/tuition/T-005.yaml +72 -0
  197. package/tuition/T-006.yaml +81 -0
  198. package/tuition/T-007.yaml +56 -0
  199. package/tuition/T-008.yaml +111 -0
  200. package/tuition/T-009.yaml +50 -0
  201. package/tuition/T-015.yaml +36 -0
  202. package/tuition/T-016.yaml +36 -0
  203. package/tuition/T-017.yaml +46 -0
  204. package/tuition/T-018.yaml +84 -0
  205. package/tuition/T-021.yaml +40 -0
  206. package/tuition/T-022.yaml +36 -0
  207. package/tuition/mechanism-index.yaml +256 -0
@@ -0,0 +1,106 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tiphys.dev/schemas/finding.schema.json",
4
+ "title": "Tiphys finding set",
5
+ "$comment": "R-029. Kernel plan M3, M3-P5 step 5. THE OUTPUT OF A REVIEW: a verdict, the model family that produced it, and a severity-ranked list of findings each of which names the plan edit it demands. THE HAZARD THIS DOCUMENT EXISTS AGAINST is the one the phase's hazard-class table names: a schema that admits an EMPTY review as a thorough one. A review that found nothing and a review that looked at nothing produce the same JSON unless the empty case is made to say so, and `no-findings-statement` plus the `oneOf` below is what makes them different documents. WHAT THIS SCHEMA CANNOT DO. (1) It cannot tell a real `concrete-edit` from a restatement of the finding; that is M3-P7's probe territory, and what is bought here is that the field cannot be absent or blank. (2) It cannot tell a real `produced-by` from a guess; T-001's ask was that the family be RECORDED, and recorded is what `required` buys. (3) It cannot rank severities: `enum` is an unordered set and the rank is stated in this comment, low < medium < high < critical, the same four names schemas/plan.schema.json uses so the two documents do not carry two vocabularies. (4) It cannot see whether the same finding id appears twice; comparing array elements to each other is Kind B and this phase adds no Kind B row (criterion 5).",
6
+ "description": "A finding set: the artifact an adversarial plan review or a clean-room review outputs.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": ["kind", "verdict", "produced-by", "findings"],
10
+ "properties": {
11
+ "kind": {
12
+ "$comment": "R-016's discriminator, so `tiphys validate --type auto` resolves this document without being told, and M3R-001's rule that a type is registered with the validator in the same step that ships its schema is satisfied in both halves rather than one. A finding set is a YAML or JSON document, so unlike a role brief it CAN carry a kind.",
13
+ "type": "string",
14
+ "const": "finding"
15
+ },
16
+ "verdict": {
17
+ "$comment": "R-029's `verdict`, required. A NON-EMPTY STRING rather than an enum, deliberately: M3-P7 ships the verdict contract and its closed vocabulary, and inventing a second one here would be the two-vocabularies failure this file's kind field exists to avoid. `pattern: \\S` because `required` alone is satisfied by the empty string.",
18
+ "type": "string",
19
+ "minLength": 1,
20
+ "pattern": "\\S"
21
+ },
22
+ "produced-by": {
23
+ "$comment": "T-001's second ask, recorded in delivery/tuition/T-001-cross-model-review-catches.md: record in the review header which family produced it. DR-0012 condition 1 then makes the two clean-room reviews of one head differ in this field, and that comparison is between two DOCUMENTS and is therefore not reachable from inside either of them. What is reachable is that the field cannot be absent, which is what this is.",
24
+ "type": "string",
25
+ "minLength": 1,
26
+ "pattern": "\\S"
27
+ },
28
+ "findings": {
29
+ "type": "array",
30
+ "items": {
31
+ "$ref": "#/$defs/finding"
32
+ }
33
+ },
34
+ "no-findings-statement": {
35
+ "$comment": "The empty review's own sentence: what was looked at, and why nothing was found. Required exactly when `findings` is empty, by the `oneOf` below.",
36
+ "type": "string",
37
+ "minLength": 1,
38
+ "pattern": "\\S"
39
+ }
40
+ },
41
+ "oneOf": [
42
+ {
43
+ "$comment": "Branch A: the set carries at least one finding. `type: array` is RESTATED here and that is not redundancy: measured against ajv 8.20.0 under this validator's `strict: true`, a `minItems` inside a subschema whose type is declared only at the outer level is refused with `schema uses keyword minItems without declaring type array`.",
44
+ "properties": {
45
+ "findings": {
46
+ "type": "array",
47
+ "minItems": 1
48
+ }
49
+ }
50
+ },
51
+ {
52
+ "$comment": "Branch B: the set carries no finding and therefore must say what was looked at. `no-findings-statement` is RESTATED in a sibling `properties` here and that is not redundancy either: measured against the same engine, a `required` naming a property not declared in `properties` at the same level fails COMPILATION under strictRequired with `strict mode: required property \"no-findings-statement\" is not defined`. WHY `oneOf` AND NOT THE `if`/`then` THE PLAN'S PARENTHETICAL NAMES. The obligation is `findings` EMPTY implies a sibling required, so the `if` would have to match emptiness. The closed authoring vocabulary (schemas/README.md) has no `not` and no `maxItems`; `minItems: 1` and `contains` both match the NON-empty case, which is the wrong polarity, and `then` cannot remove an obligation. `oneOf` is in the vocabulary and does express it. The declared deviation and its captured probe output are in delivery/work-history/m3-p5.md. ONE CONSEQUENCE BEYOND WHAT CRITERION 5(b) ASKED FOR, recorded rather than discovered: a set carrying BOTH findings and a no-findings statement matches both branches and is therefore invalid too. That is the same both-directions property M3-P4's report contract reaches with a derived check.",
53
+ "required": ["no-findings-statement"],
54
+ "properties": {
55
+ "no-findings-statement": {
56
+ "type": "string",
57
+ "minLength": 1,
58
+ "pattern": "\\S"
59
+ }
60
+ }
61
+ }
62
+ ],
63
+ "$defs": {
64
+ "finding": {
65
+ "$comment": "R-029's severity-ranked findings with concrete plan edits.",
66
+ "type": "object",
67
+ "additionalProperties": false,
68
+ "required": ["id", "severity", "evidence", "concrete-edit"],
69
+ "properties": {
70
+ "id": {
71
+ "$comment": "The stable id the arbitration and the fix round cite. The identifier schemes are CLAUDE.md's; this schema does not pick one, because CR-nnn, PR-nnn and EXT-F-nn are all real and all cited.",
72
+ "type": "string",
73
+ "minLength": 1,
74
+ "pattern": "\\S"
75
+ },
76
+ "severity": {
77
+ "$comment": "Ranked low < medium < high < critical. Same four names as schemas/plan.schema.json's phase severity.",
78
+ "type": "string",
79
+ "enum": ["low", "medium", "high", "critical"]
80
+ },
81
+ "evidence": {
82
+ "$comment": "Evidence beats assertion: exit codes, counts, file paths with line numbers, captured output, URLs. `minItems: 1` is the whole point, because a finding with no evidence is an opinion and this repository treats an agent's claim with no verifiable artifact behind it as unknown.",
83
+ "type": "array",
84
+ "minItems": 1,
85
+ "items": {
86
+ "type": "string",
87
+ "minLength": 1,
88
+ "pattern": "\\S"
89
+ }
90
+ },
91
+ "concrete-edit": {
92
+ "$comment": "R-029's `concrete plan edits`. The edit the finding DEMANDS, not a description of the problem. Required on EVERY finding regardless of severity, which is strictly stronger than criterion 5(a)'s dangerous instance (a `severity: high` finding with no `concrete-edit`) and is stronger on purpose: a low finding with no proposed edit is a remark, and a review made of remarks is the empty review with extra steps.",
93
+ "type": "string",
94
+ "minLength": 1,
95
+ "pattern": "\\S"
96
+ },
97
+ "analysis": {
98
+ "$comment": "Section 1.5's finding-set row: what is not enumerable is the ARGUMENT behind one finding, which is why it lives inside a field rather than becoming structure. Optional, and non-empty when present.",
99
+ "type": "string",
100
+ "minLength": 1,
101
+ "pattern": "\\S"
102
+ }
103
+ }
104
+ }
105
+ }
106
+ }
@@ -0,0 +1,260 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tiphys.dev/schemas/gate-registry.schema.json",
4
+ "title": "Tiphys canonical gate registry",
5
+ "$comment": "R-094: the canonical list of gates per assurance mode, intended as the single source consumed by CI and by the role briefs. As delivered by M3-P2 the BRIEFS half is real (CLAUDE.md's gate section is rendered from the registry) and the CI half is not (CI invokes the runner with --manifest gates.manifest.json); gate-registry.yaml's own header states the divergence and test/gate-registry.test.ts asserts it in both directions. Kernel plan M3, M3-P2 step 2. A SUPERSET of the M2-P1 gate manifest (src/gates/schemas/gate-manifest.schema.json): every field that schema defines is defined here with the same meaning, and this document adds four, `modes` (made live from the field M2 reserved), `events`, `verified-by` and `probe`, plus the top-level `preflight` list. SC-011 is carried over unchanged: a gate whose precondition is unmet reports not-applicable and NEVER green.",
6
+ "description": "One registry per repository. Which gates exist, how each is invoked, which assurance modes select it, which CI events evaluate it, whether a script or a clean-room checklist probe verifies it, and which commands can destroy work.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": ["kind", "version", "preflight", "gates", "destructiveCommands"],
10
+ "properties": {
11
+ "kind": {
12
+ "description": "The artifact type, so `tiphys validate --type auto` resolves this document without being told. Every M3-P1 artifact type carries one and this mirrors them.",
13
+ "type": "string",
14
+ "const": "gate-registry"
15
+ },
16
+ "note": {
17
+ "description": "Free prose for the registry's own readers.",
18
+ "type": "string"
19
+ },
20
+ "version": {
21
+ "$comment": "A closed set rather than a minimum, because the authoring vocabulary of schemas/README.md has no `minimum` keyword and a bare `type: integer` would admit 0 and negatives.",
22
+ "type": "integer",
23
+ "enum": [1]
24
+ },
25
+ "preflight": {
26
+ "$comment": "R-094. The ordered local commands every change must pass before any registry gate means anything. They live IN the registry rather than beside it because CLAUDE.md's gate section is rendered from this document IN FULL (M3-P2 criterion 6, scripts/render-agent-rules-gates.mjs), and a step left outside the registry would be exactly the hand-maintained gate list criterion 6 forbids.",
27
+ "type": "array",
28
+ "minItems": 1,
29
+ "items": {
30
+ "$ref": "#/$defs/preflightStep"
31
+ }
32
+ },
33
+ "gates": {
34
+ "description": "Append-only registry keyed by id. No minItems, matching the M2 manifest: a registry with zero gates must reach the runner and be reported as no applicable gate, not rejected at load.",
35
+ "type": "array",
36
+ "items": {
37
+ "$ref": "#/$defs/gate"
38
+ }
39
+ },
40
+ "destructiveCommands": {
41
+ "description": "CLI commands and module paths whose operations can destroy work. Carried over from the M2 manifest unchanged; M2-P2 rule (e) DERIVES a witness class from it rather than trusting an implementer's declaration.",
42
+ "type": "array",
43
+ "items": {
44
+ "type": "string"
45
+ }
46
+ }
47
+ },
48
+ "$defs": {
49
+ "commandArray": {
50
+ "description": "argv array. The runner appends --result and --evidence, plus one flag per declared parameter. Defined once in $defs because strict mode requires every `required` name to be declared in `properties` at the SAME level, so the conditional rules below must restate it and a second copy of the constraint would be a second thing to keep in sync.",
51
+ "type": "array",
52
+ "minItems": 1,
53
+ "items": {
54
+ "type": "string"
55
+ }
56
+ },
57
+ "probeId": {
58
+ "description": "The checklist probe id M3-P7 must supply. Required exactly when verified-by is clean-room-checklist.",
59
+ "type": "string",
60
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
61
+ },
62
+ "preflightStep": {
63
+ "type": "object",
64
+ "additionalProperties": false,
65
+ "required": ["command", "note"],
66
+ "properties": {
67
+ "command": {
68
+ "description": "argv array, run in the repository root.",
69
+ "type": "array",
70
+ "minItems": 1,
71
+ "items": {
72
+ "type": "string"
73
+ }
74
+ },
75
+ "note": {
76
+ "type": "string",
77
+ "minLength": 1
78
+ }
79
+ }
80
+ },
81
+ "gate": {
82
+ "$comment": "THREE conditional rules, chained through $ref rather than stacked in one object, because JSON Schema allows one `if`/`then` pair per schema object and `allOf` is outside the authoring vocabulary of schemas/README.md. Each link adds exactly one rule and each rule has its own acceptance criterion. This link: M3-P2 criterion 4. A gate declared `conditional` is one that MAY report not-applicable, and SC-011 says not-applicable ASSERTS an evaluated, unmet precondition; a conditional gate with no precondition can therefore report not-applicable with nothing evaluated, which is the vacuous pass this registry exists to make impossible. `deploy` and `migrations` are the two conditional entries this rule binds.",
83
+ "$ref": "#/$defs/gateProbeRule",
84
+ "if": {
85
+ "type": "object",
86
+ "required": ["applicability"],
87
+ "properties": {
88
+ "applicability": {
89
+ "const": "conditional"
90
+ }
91
+ }
92
+ },
93
+ "then": {
94
+ "type": "object",
95
+ "required": ["precondition"],
96
+ "properties": {
97
+ "precondition": {
98
+ "$ref": "#/$defs/precondition"
99
+ }
100
+ }
101
+ }
102
+ },
103
+ "gateProbeRule": {
104
+ "$comment": "M3-P2 criterion 2. A clean-room-checklist entry with no probe names no question, so nothing can ever verify it and the entry is a gate id with nothing behind it. D-11 settles that R-043 and R-044 are verified this way.",
105
+ "$ref": "#/$defs/gateCommandRule",
106
+ "if": {
107
+ "type": "object",
108
+ "required": ["verified-by"],
109
+ "properties": {
110
+ "verified-by": {
111
+ "const": "clean-room-checklist"
112
+ }
113
+ }
114
+ },
115
+ "then": {
116
+ "type": "object",
117
+ "required": ["probe"],
118
+ "properties": {
119
+ "probe": {
120
+ "$ref": "#/$defs/probeId"
121
+ }
122
+ }
123
+ }
124
+ },
125
+ "gateCommandRule": {
126
+ "$comment": "A `script` gate is verified by running a process, so it must say which one. A `clean-room-checklist` gate has no process and carries no command, which is why `command` is not in the base required list.",
127
+ "$ref": "#/$defs/gateShape",
128
+ "if": {
129
+ "type": "object",
130
+ "required": ["verified-by"],
131
+ "properties": {
132
+ "verified-by": {
133
+ "const": "script"
134
+ }
135
+ }
136
+ },
137
+ "then": {
138
+ "type": "object",
139
+ "required": ["command"],
140
+ "properties": {
141
+ "command": {
142
+ "$ref": "#/$defs/commandArray"
143
+ }
144
+ }
145
+ }
146
+ },
147
+ "gateShape": {
148
+ "type": "object",
149
+ "additionalProperties": false,
150
+ "required": ["id", "unitLabel", "applicability", "verified-by", "modes", "events"],
151
+ "properties": {
152
+ "$comment": {
153
+ "description": "Clause ids this entry discharges, per schemas/README.md.",
154
+ "type": "string"
155
+ },
156
+ "id": {
157
+ "type": "string",
158
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
159
+ },
160
+ "command": {
161
+ "$ref": "#/$defs/commandArray"
162
+ },
163
+ "unitLabel": {
164
+ "type": "string",
165
+ "minLength": 1
166
+ },
167
+ "applicability": {
168
+ "description": "required: an unmet precondition fails the run. conditional: an unmet precondition does not.",
169
+ "type": "string",
170
+ "enum": ["required", "conditional"]
171
+ },
172
+ "verified-by": {
173
+ "$comment": "D-11. R-043 and R-044 are not reliably computable from a diff, so their gate is a clean-room checklist probe rather than a script, and the registry SAYS which of the two a reader is looking at instead of leaving it to be inferred from whether a command happens to be present.",
174
+ "type": "string",
175
+ "enum": ["script", "clean-room-checklist"]
176
+ },
177
+ "probe": {
178
+ "$ref": "#/$defs/probeId"
179
+ },
180
+ "modes": {
181
+ "$comment": "The field the M2 manifest schema RESERVED (src/gates/schemas/gate-manifest.schema.json line 70, validated if present and ignored by the M2 runner), made LIVE here. Blueprint section 5: the canonical list of gates PER ASSURANCE MODE. The item enum is the three mode ids M3-P3 defines.",
182
+ "type": "array",
183
+ "minItems": 1,
184
+ "uniqueItems": true,
185
+ "items": {
186
+ "type": "string",
187
+ "enum": ["full", "direct-pr", "local-only"]
188
+ }
189
+ },
190
+ "events": {
191
+ "$comment": "T-009, D-M3-34. A gate result is evidence only for the configuration that produced it, and this repository's workflow runs DIFFERENT bundles on `pull_request` and on `push` to `main`. An entry that does not say which events evaluate it carries a claim nobody can check. For every entry PROMOTED from gates.manifest.json the value is derived from the two bundle definitions in scripts/m2-exit-test.sh and never assigned by judgment; for an entry that is not in that manifest it is derived from whatever mechanism does evaluate it, which for agent-rules-drift is a workflow step carrying no `if:`. Both derivations are asserted in test/gate-registry.test.ts.",
192
+ "type": "array",
193
+ "minItems": 1,
194
+ "uniqueItems": true,
195
+ "items": {
196
+ "type": "string",
197
+ "enum": ["pull_request", "push"]
198
+ }
199
+ },
200
+ "parameters": {
201
+ "description": "Run parameters this gate's command REQUIRES. Declared rather than inferred. An absent declared parameter makes the gate error, never not-applicable (M2-C-3).",
202
+ "type": "array",
203
+ "items": {
204
+ "type": "string",
205
+ "enum": ["base", "head", "phase"]
206
+ }
207
+ },
208
+ "precondition": {
209
+ "$ref": "#/$defs/precondition"
210
+ }
211
+ }
212
+ },
213
+ "precondition": {
214
+ "$comment": "SC-011, carried over from the M2-P1 manifest schema UNCHANGED, field for field. A gate whose precondition is unmet reports not-applicable and never green; not-applicable ASSERTS that a precondition was evaluated and found unmet.",
215
+ "type": "object",
216
+ "additionalProperties": false,
217
+ "required": ["id", "kind"],
218
+ "properties": {
219
+ "id": {
220
+ "type": "string"
221
+ },
222
+ "kind": {
223
+ "description": "The closed set. Kind-specific required fields are checked by src/gates/manifest.ts, which emits the same INVALID <pointer> <message> diagnostics.",
224
+ "type": "string",
225
+ "enum": [
226
+ "file-exists",
227
+ "file-absent",
228
+ "branch-matches",
229
+ "diff-touches",
230
+ "command-exit-zero"
231
+ ]
232
+ },
233
+ "path": {
234
+ "description": "file-exists and file-absent.",
235
+ "type": "string"
236
+ },
237
+ "pattern": {
238
+ "description": "branch-matches. A JavaScript regular expression source that is ANCHORED: it is compiled as ^(?:<pattern>)$ and must match the WHOLE branch name. The token {phase} is replaced by the --phase value, REGEX-ESCAPED.",
239
+ "type": "string"
240
+ },
241
+ "paths": {
242
+ "description": "diff-touches. Path prefixes; the precondition is met when the diff changes a path under any of them.",
243
+ "type": "array",
244
+ "minItems": 1,
245
+ "items": {
246
+ "type": "string"
247
+ }
248
+ },
249
+ "command": {
250
+ "description": "command-exit-zero. argv array, run in the runner's working directory.",
251
+ "type": "array",
252
+ "minItems": 1,
253
+ "items": {
254
+ "type": "string"
255
+ }
256
+ }
257
+ }
258
+ }
259
+ }
260
+ }
@@ -0,0 +1,94 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://tiphys.dev/schemas/mechanism-index.schema.json",
4
+ "title": "Tiphys mechanism index",
5
+ "$comment": "Kernel plan M3, M3-P6 criterion 8 and D-M3-23. T-005's structural consequence: a rule M1-P3 paid for in a multi-hour investigation did not reach M1-P5, which reimplemented the same claim-file mechanism silently and produced the most severe defect found in M1. The implementer there had read the plan, the agent-rules file, the constraint list, the environment warnings and three work histories, and NONE of them carried the rule, because a rule about a MECHANISM has no home in a document organised by phase. This document is that home. THE SCHEMA SHIPS HERE AND THE GENERATOR SHIPS AT M3-P8, which is the only forward reference in M3-P6 and is why D-M3-23 exists: M3-P8 EDITS this document to add `machine-readable-form` and does not create it. WHAT THIS SCHEMA CANNOT DO. It cannot tell a rule from a platitude: `rule` is a string, and whether its text is something an implementer can obey or a sentiment they can agree with is judgment. It cannot check that `evidence[]` resolves; entries are prose citations of artifacts that may live in delivery/, which the kernel does not ship, so resolution is not computable from an installed package. And it cannot tell whether the index is COMPLETE, which is the property M3-P6's registered superset test and M3-P8 criterion 4c cover from the two ends.",
6
+ "description": "One document per project. Every mechanism this project has already learned something about, the rule that learning established, the sibling implementations that share the mechanism, and the artifacts that paid for it. Read the row before you use the mechanism.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": ["kind", "version", "mechanisms"],
10
+ "properties": {
11
+ "kind": {
12
+ "type": "string",
13
+ "const": "mechanism-index"
14
+ },
15
+ "version": {
16
+ "$comment": "Document format version, not a project version. A closed set rather than a minimum, for the reason schemas/gate-registry.schema.json:21 already records: the authoring vocabulary has no `minimum` keyword, so a bare `type: integer` would admit 0 and negatives.",
17
+ "type": "integer",
18
+ "enum": [1]
19
+ },
20
+ "supersedes": {
21
+ "$comment": "The interim artifact this index replaces, by path, when there is one. Carried so a reader of the index can find what it was converted FROM, and so M3-P8's generated projection can be checked against the same source rather than against a memory of it. Optional: a project with no interim file omits it.",
22
+ "type": "string",
23
+ "minLength": 1,
24
+ "pattern": "\\S"
25
+ },
26
+ "mechanisms": {
27
+ "$comment": "minItems 1, because an index with no mechanisms is a file that satisfies every lookup obligation by having nothing to look up. That is the third row of M3-P6's own hazard table ('the index it names is the stub nobody replaced'), and the schema closes the degenerate end of it; the other end is the registered superset test, which no schema can express.",
28
+ "type": "array",
29
+ "minItems": 1,
30
+ "items": {
31
+ "type": "object",
32
+ "additionalProperties": false,
33
+ "required": ["key", "name", "rule", "evidence"],
34
+ "properties": {
35
+ "key": {
36
+ "$comment": "The stable id, and the thing a citation elsewhere names. DERIVED FROM `name` rather than invented: lowercase, every run of characters outside [a-z0-9] replaced by a single hyphen, leading and trailing hyphens removed. M3-P6's registered test applies that derivation to `name` and compares, so a key that drifts from its name is red rather than merely odd. Ids are never renumbered and a retired key is never reused, which is the rule CLAUDE.md's identifier-schemes section states for every scheme in this project.",
37
+ "type": "string",
38
+ "minLength": 1,
39
+ "pattern": "^[a-z0-9]+(-[a-z0-9]+)*$"
40
+ },
41
+ "name": {
42
+ "$comment": "The mechanism in the words a reader would search for. For a row converted from an interim index, this is the interim table's own first column VERBATIM, which is what makes the conversion checkable against the file it came from instead of against a paraphrase of it.",
43
+ "type": "string",
44
+ "minLength": 1,
45
+ "pattern": "\\S"
46
+ },
47
+ "rule": {
48
+ "$comment": "What this project learned, stated as something to DO or NOT DO. Not a description of the mechanism: an implementer who reads this row and changes nothing has read a description, and the row has failed.",
49
+ "type": "string",
50
+ "minLength": 1,
51
+ "pattern": "\\S"
52
+ },
53
+ "siblings": {
54
+ "$comment": "The other implementations that share this mechanism, by path. The `mechanism-sibling` clause in roles/implementer.md is the instruction that keeps this list current: a phase establishing a rule about a mechanism records it here AND names the siblings, because the recorded cost of not doing so is one silent reimplementation two phases later. Optional, and an EMPTY list is meaningful: it says the mechanism has exactly one implementation today.",
55
+ "type": "array",
56
+ "items": {
57
+ "type": "string",
58
+ "minLength": 1,
59
+ "pattern": "\\S"
60
+ }
61
+ },
62
+ "machine-readable-form": {
63
+ "$comment": "ADDED BY M3-P8 (D-M3-23's forward reference, step 2). Where the SAME rule exists as data: a path plus the key inside it. The `destructive-git-operation` row is the worked example and the reason the field exists: its prose rule and the `destructiveCommands` list in `gates.manifest.json` are two views of one thing (M2 plan section 2 item 10), and a citation is what stops them drifting apart silently. PROJECTED, NEVER AUTHORED HERE: this document is generated from the tuition feed's `mechanisms[]` by `tiphys tuition index`, so the field is written in the entry that established the rule. The derived check mechanism-rule-evidence-resolves resolves both halves against the real document, so a key M2 renames reddens rather than rotting. Optional: most rules exist only as prose, which is a fact about the rule and not a defect.",
64
+ "type": "object",
65
+ "additionalProperties": false,
66
+ "required": ["path", "key"],
67
+ "properties": {
68
+ "path": {
69
+ "type": "string",
70
+ "minLength": 1,
71
+ "pattern": "\\S"
72
+ },
73
+ "key": {
74
+ "type": "string",
75
+ "minLength": 1,
76
+ "pattern": "\\S"
77
+ }
78
+ }
79
+ },
80
+ "evidence": {
81
+ "$comment": "What paid for the rule: a defect, a fix round, an investigation, a review finding, a tuition entry. minItems 1 is the load-bearing constraint of this whole document. The interim index states it in prose ('a rule with no citation is not a rule'), and prose is what this project has recorded three times as not surviving; here it is a validation failure.",
82
+ "type": "array",
83
+ "minItems": 1,
84
+ "items": {
85
+ "type": "string",
86
+ "minLength": 1,
87
+ "pattern": "\\S"
88
+ }
89
+ }
90
+ }
91
+ }
92
+ }
93
+ }
94
+ }