@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,103 @@
1
+ # THE ADVERSARIAL PLAN-REVIEW CHECKLIST (kernel plan M3, M3-P7 step 2).
2
+ #
3
+ # Run against a PLAN, before any of it is dispatched. The three canonical
4
+ # probes are R-026b, R-027 and R-028a, and each one is written to be
5
+ # unanswerable without opening something: R-027 carries the process document's
6
+ # own zero-amount-rows illustration, and R-028a names the artifact that counts
7
+ # as proof so a testability claim cannot be admired instead of tested.
8
+ kind: checklist
9
+ id: plan-review
10
+ applies-to: >-
11
+ a plan document before dispatch, read adversarially: the reviewer is looking
12
+ for the phase that cannot be built as written, not for reasons to approve.
13
+
14
+ probes:
15
+ # R-026b. Hidden dependencies and semantic coupling ABOVE the file-overlap
16
+ # floor. File overlap is what the M5 pre-pass computes mechanically; this
17
+ # probe is the part no pre-pass reaches.
18
+ - id: hidden-dependency-above-file-overlap
19
+ probe: >-
20
+ Which phases share MEANING rather than files? Two phases with disjoint
21
+ file lists still collide when one renames a key the other reads, changes
22
+ a value's vocabulary, moves an ordering another relies on, or changes
23
+ what a shared registry row means. The file-overlap pre-pass computes the
24
+ floor and cannot see any of those. Name each pair you found, the shared
25
+ concept, and the phase whose assumption breaks; then name the pairs you
26
+ examined and cleared, because a list of collisions with no stated scope
27
+ is indistinguishable from a search that looked in the wrong place.
28
+ applies-to: plan-structure
29
+ evidence-required: true
30
+
31
+ - id: grounding-names-a-real-artifact
32
+ probe: >-
33
+ Does each phase's `grounding` name artifacts that will EXIST when it
34
+ starts, and does its `blocked-by` follow from that rather than from
35
+ habit? A `blocked-by` naming a phase whose artifacts the grounding never
36
+ mentions is an ordering habit serialising work that could run in
37
+ parallel; the reverse, a grounding consuming a phase the `blocked-by`
38
+ does not name, is a phase that will be dispatched before its inputs
39
+ exist. Check both directions per phase and say which you found.
40
+ applies-to: plan-structure
41
+ evidence-required: true
42
+
43
+ # R-027. Probe every fix shape for THE STATE THAT CAN NO LONGER EXIT, with
44
+ # the process document's own illustration carried in the probe text so the
45
+ # question cannot be answered from the phrase alone.
46
+ - id: fix-shape-state-that-cannot-exit
47
+ probe: >-
48
+ For every fix this plan proposes, what state does it create that can no
49
+ longer be exited? The process document's own illustration: a repair that
50
+ writes rows with a ZERO amount leaves records that are structurally
51
+ valid, that every later query counts, and that no reconciliation can
52
+ distinguish from real ones, so the system can enter that state and never
53
+ leave it. Walk each fix and name the state, the transition INTO it, and
54
+ the transition OUT of it. A fix with no stated exit is the finding.
55
+ applies-to: fix-shapes
56
+ evidence-required: true
57
+
58
+ - id: fix-shape-partial-application
59
+ probe: >-
60
+ What does each fix leave behind if it is interrupted halfway? Name the
61
+ point of no return in each one, and whether re-running it from the start
62
+ is safe. A fix that is only correct when it completes is a fix that has
63
+ not been designed for the case it exists to handle.
64
+ applies-to: fix-shapes
65
+ evidence-required: true
66
+
67
+ # R-028a. TEST THE TESTABILITY CLAIMS. The accepted evidence is the M2-P2
68
+ # red-witness harness's own evidence file, not the plan's assertion that
69
+ # something is testable.
70
+ - id: testability-claim-tested
71
+ probe: >-
72
+ For every claim in this plan that something is testable, guarded or
73
+ witnessed, what is the accepted proof? The harness's captured evidence
74
+ file (`witness-records.json`, whose per-member `runs[].exitCode` and
75
+ `failedNamedTests` record what actually ran) is the proof; the plan's
76
+ own sentence is not. Where no such file can exist yet because the
77
+ behaviour is not built, say so in those words and mark the claim as
78
+ owed, rather than letting an untested assertion pass as a tested one.
79
+ applies-to: testability
80
+ evidence-required: true
81
+
82
+ - id: acceptance-criterion-is-falsifiable
83
+ probe: >-
84
+ Is each acceptance criterion FALSIFIABLE? "Works correctly" is banned;
85
+ the register is a command, its exit code and a count ("node --test exits
86
+ 0 and reports N tests, N greater than zero"). Quote every criterion that
87
+ names no command, no observable output and no count, and propose the
88
+ falsifiable form. A criterion nobody can fail is a criterion nobody has
89
+ to meet.
90
+ applies-to: testability
91
+ evidence-required: true
92
+
93
+ - id: hazard-class-is-not-the-criteria-reworded
94
+ probe: >-
95
+ Does each phase's declared hazard class name something its own
96
+ acceptance criteria CANNOT reach? T-007 records a phase meeting fifteen
97
+ of fifteen executed criteria while live-locking every supervision
98
+ command. A hazard class that is the criteria list reworded reproduces
99
+ that failure while appearing to fix it. For each class, name the
100
+ criterion that reaches it or state that none does and name the
101
+ instrument that does.
102
+ applies-to: plan-structure
103
+ evidence-required: true
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,92 @@
1
+ #!/usr/bin/env node
2
+ import { run, usageLine } from "../src/cli.js";
3
+ /**
4
+ * THE TOP-LEVEL ERROR PRESENTATION HANDLER (kernel plan M3, M3-P1 step 8b;
5
+ * D-M3-21).
6
+ *
7
+ * `delivery/STATE.md` carried this as an unowned seam: "clean presentation of
8
+ * a load-time configuration error ... a seam no M1 phase owns". M3-P1 owns it
9
+ * because M3-P1 is the first phase to add commands whose ordinary input is a
10
+ * HAND-AUTHORED FILE that will routinely be malformed, and a validator that
11
+ * answers malformed YAML with a stack trace is a validator nobody trusts
12
+ * (DR-0013 YAML clause 4).
13
+ *
14
+ * The rule: a thrown error from any subcommand is ONE diagnostic line on
15
+ * stderr and a nonzero exit. Never a stack trace, on either stream.
16
+ *
17
+ * THE DOCUMENTED USAGE-MARKING MECHANISM IS GONE, and its removal is the
18
+ * fix rather than the loss. This docblock used to promise that "an `Error`
19
+ * carrying `usage: true` exits 64", with an `UsageMarkedError` interface
20
+ * beside it, and a grep over `src/` and `bin/` found ZERO code that ever set
21
+ * the field: every command reaches EX_USAGE by returning it from its own
22
+ * handler. A comment describing a contract nothing implements is how the
23
+ * next implementer reaches for a mechanism that silently does nothing, so
24
+ * the branch and the sentence are removed together and `EX_USAGE` stays the
25
+ * value handlers return.
26
+ *
27
+ * SCOPE IS EXACTLY THIS HANDLER, THE HELP AFFORDANCE, AND EPIPE (D-M3-21
28
+ * plus the DR-0047 sweep's two CLI findings). Nothing else in this file
29
+ * changes, because a dispatcher is the last place to accumulate incidental
30
+ * edits.
31
+ */
32
+ function singleLine(text) {
33
+ return text.replace(/\s+/g, " ").trim();
34
+ }
35
+ /**
36
+ * AN EXIT CODE MUST NOT CONTRADICT THE STATE THE COMMAND LEFT BEHIND.
37
+ *
38
+ * Measured before this handler existed: `tiphys lock acquire --duration 900 |
39
+ * head -1` printed the acquired line, exited 1 on an unhandled EPIPE, and
40
+ * left BOTH layers mutated, the local lease on disk and the shared register
41
+ * advanced to the next counter. A wrapper of the shape
42
+ * `if ! tiphys lock acquire | grep -q acquired` therefore took its failure
43
+ * branch while holding the fleet, which is the one wrong conclusion the
44
+ * exclusion commands must never produce.
45
+ *
46
+ * EPIPE ONLY, and that word is load-bearing. A consumer closing the pipe is
47
+ * not a failure of the command; any OTHER write error still surfaces, so
48
+ * this does not become a blanket swallow of output failures. Both streams
49
+ * are covered because a short consumer of stderr is the same hazard as a
50
+ * short consumer of stdout.
51
+ */
52
+ function ignoreEpipe(stream) {
53
+ stream.on("error", (error) => {
54
+ if (error.code === "EPIPE") {
55
+ return;
56
+ }
57
+ throw error;
58
+ });
59
+ }
60
+ ignoreEpipe(process.stdout);
61
+ ignoreEpipe(process.stderr);
62
+ /**
63
+ * THE HELP AFFORDANCE (DR-0047 sweep, group cli, CR-F04).
64
+ *
65
+ * `tiphys --help` exited 64 with ZERO bytes on stdout and the usage line on
66
+ * stderr, so `tiphys --help | less` showed nothing, while this project's own
67
+ * evidence uses `tiphys --help` as a probe. That satisfied M1-P1 criterion 4
68
+ * to the letter, because `--help` is an unknown subcommand, and it is still
69
+ * the first thing a consumer types.
70
+ *
71
+ * The usage text is `usageLine()`, which src/cli.ts DERIVES from the dispatch
72
+ * table, so this cannot drift from the commands that exist. M1-P1 criterion
73
+ * 4's contract is untouched: an unknown subcommand still prints usage to
74
+ * STDERR with an EMPTY stdout and exit 64, and the help words alone print to
75
+ * STDOUT with exit 0.
76
+ */
77
+ const HELP_WORDS = new Set(["--help", "-h", "help"]);
78
+ const argv = process.argv.slice(2);
79
+ if (argv.length === 1 && HELP_WORDS.has(argv[0])) {
80
+ process.stdout.write(`${usageLine()}\n`);
81
+ process.exitCode = 0;
82
+ }
83
+ else {
84
+ try {
85
+ process.exitCode = await run(argv);
86
+ }
87
+ catch (error) {
88
+ const message = error instanceof Error ? error.message : String(error);
89
+ process.stderr.write(`tiphys: ${singleLine(message)}\n`);
90
+ process.exitCode = 1;
91
+ }
92
+ }
@@ -0,0 +1,202 @@
1
+ import type { Fleet } from "../fleet.ts";
2
+ import type { ExecutorAdapter } from "../spawn.ts";
3
+ /**
4
+ * ADAPTER SELECTION AND LOADING (kernel plan M4, M4-P4; M4-D-03 at
5
+ * delivery/plan/m4-intake.md:729).
6
+ *
7
+ * THE RESOLUTION ROOT IS THE WHOLE SECURITY PROPERTY, and it is the reason
8
+ * this module exists rather than a one-line `await import(specifier)` at the
9
+ * spawn call site. Loading an adapter executes third-party code INSIDE the
10
+ * orchestrator process, the same process that holds delegated merge
11
+ * authority under DR-0012. DR-0029 Part 2c's untrusted-project-content
12
+ * boundary does not exist and M4-D-23 recommends it is not built in M4, so
13
+ * the only mitigation available is WHERE the code is resolved from:
14
+ *
15
+ * - the FLEET HOME is owner-controlled and already pins `@tiphys/kernel`
16
+ * exactly, which is what makes it a boundary at all;
17
+ * - the PROJECT CLONE is the thing under review and may contain anything
18
+ * a contributor pushed, including a `node_modules/` directory.
19
+ *
20
+ * So resolution is rooted at `<fleet home>/package.json` rather than at this
21
+ * module or at `process.cwd()`. A plain `await import(specifier)` resolves
22
+ * relative to THIS MODULE's URL, which is the kernel checkout, and
23
+ * `import.meta.resolve(specifier, parent)` silently ignores its second
24
+ * argument unless Node is started with `--experimental-import-meta-resolve`
25
+ * (measured on v26.6.0, 2026-09-17: the parent was ignored and the specifier
26
+ * resolved from the CALLER's file). Both of those are the shape this module
27
+ * refuses to be.
28
+ *
29
+ * THE ROOTING IS NOT BY ITSELF THE PROPERTY, AND THE SENTENCE THAT STOOD HERE
30
+ * SAID IT WAS (CR-B-004, re-raised as CR-F-CRED-002 and CH-002).
31
+ *
32
+ * Until this round this paragraph asserted, without qualification, that
33
+ * "NOTHING here ever consults the project clone". That is true of BARE
34
+ * specifiers, which is the only shape M4-P4 criterion 2's witness exercises:
35
+ * `createRequire` walks the fleet home and its PARENTS looking for
36
+ * `node_modules`, and the project clone sits BELOW the fleet home at
37
+ * `<fleet>/projects/<name>`, so no such walk reaches it. It was FALSE of the
38
+ * module. Measured at `ad2428b`, with a module in the project clone that drops
39
+ * a sentinel on import: a bare specifier did not evaluate it, an ABSOLUTE
40
+ * specifier did, and the fleet-relative `./projects/demo/evil.mjs` did,
41
+ * because a relative path does not walk up looking for `node_modules`, it
42
+ * walks DOWN the tree the rooting chose.
43
+ *
44
+ * The mechanism is a constraint that holds for one INPUT SHAPE, documented as
45
+ * holding for the module. Both halves are now checked against the RESOLVED
46
+ * REAL PATH, which is the only thing that describes where the code actually
47
+ * comes from, rather than against the specifier's spelling:
48
+ *
49
+ * - a resolved path inside `<fleet>/projects/` is refused WHATEVER the
50
+ * specifier's shape, because the project tree is the thing under review;
51
+ * - a PATH-SHAPED specifier (absolute, or beginning `./` or `../`) whose
52
+ * resolved path is outside the fleet home is refused, because an absolute
53
+ * specifier can point anywhere and a relative one can climb out with
54
+ * `../`. A BARE specifier is exempt from the second check only, because
55
+ * `createRequire`'s parent walk legitimately finds a hoisted
56
+ * `node_modules` above the fleet home, and refusing that would break an
57
+ * ordinary install rather than a hazard.
58
+ *
59
+ * `realpathSync` is used for both, so a symlink planted inside the fleet home
60
+ * pointing into the project clone is refused by the same check rather than by
61
+ * a second one.
62
+ *
63
+ * WHAT IS STILL NOT DEFENDED, said here so the next reader does not re-derive
64
+ * it: an operator who types an absolute path INTO the fleet home gets what
65
+ * they typed, and the fleet home is owner-controlled by assumption. This moves
66
+ * the boundary to the fleet home for every specifier shape; it does not defend
67
+ * inside it.
68
+ *
69
+ * WHAT THIS MODULE DOES NOT DEFEND. Once a specifier resolves inside the
70
+ * fleet home, its code runs. A legitimate fleet-home adapter that is later
71
+ * compromised is not covered by anything here, and no criterion of this
72
+ * phase claims otherwise: this phase MOVES the boundary to the fleet home,
73
+ * it does not defend inside it. That residue is M4-D-23's, stated rather
74
+ * than implied.
75
+ */
76
+ /**
77
+ * The built-in adapter's name, and the one name a loaded adapter may not
78
+ * claim (M4-P4 criterion 5).
79
+ *
80
+ * IT LIVES HERE RATHER THAN IN `src/spawn.ts` so that the runtime import
81
+ * edge runs one way only: `src/spawn.ts` imports this value, and this module
82
+ * imports nothing but a TYPE back. A value-level cycle between the launch
83
+ * module and the loader would evaluate one of them inside the other's
84
+ * temporal dead zone the first time an import order changed, which is a
85
+ * failure nothing in the suite would predict.
86
+ *
87
+ * The launch record's `adapter` field (src/spawn.ts:113) is the only thing
88
+ * that ever says what ran. A loaded adapter naming itself after the built-in
89
+ * one makes every later record ambiguous, and the ambiguity is unresolvable
90
+ * after the fact because the record is the only witness. This is the
91
+ * misattribution guard src/gates/schemas/release-record.schema.json:26
92
+ * already instantiates for release records, applied one layer down.
93
+ */
94
+ export declare const BUILT_IN_ADAPTER_NAME = "subprocess";
95
+ /**
96
+ * The fleet-home `package.json` field that names a default adapter, as a
97
+ * JSON pointer written out in the one place that reads it.
98
+ *
99
+ * `tiphys.adapter` rather than a top-level key: the kernel's own
100
+ * `package.json` already namespaces its configuration under `tiphys`
101
+ * (package.json:52), so a fleet home carrying kernel configuration uses the
102
+ * same namespace rather than inventing a second convention.
103
+ */
104
+ export declare const FLEET_ADAPTER_FIELD = "tiphys.adapter";
105
+ export type AdapterSelection = {
106
+ ok: true;
107
+ adapter: ExecutorAdapter | undefined;
108
+ origin: string;
109
+ } | {
110
+ ok: false;
111
+ reason: string;
112
+ };
113
+ export type AdapterLoad = {
114
+ ok: true;
115
+ adapter: ExecutorAdapter;
116
+ } | {
117
+ ok: false;
118
+ reason: string;
119
+ };
120
+ /**
121
+ * The specifier the fleet home declares as its default, if any.
122
+ *
123
+ * READ THROUGH `readRegularFileIfPresent`, never `readFileSync`: the fleet
124
+ * home is a directory this process does not own the contents of, and a FIFO
125
+ * at `package.json` would hang the spawn rather than refuse it. That is the
126
+ * hazard CR-520 records for `meta.json`, one path along.
127
+ *
128
+ * A fleet home with no `package.json`, no `tiphys` object, or no `adapter`
129
+ * key declares NOTHING, which is a different fact from declaring something
130
+ * unusable: the first yields `undefined` and the built-in default, the
131
+ * second is a refusal naming the field.
132
+ */
133
+ export declare function fleetAdapterSpecifier(fleet: Fleet): {
134
+ ok: true;
135
+ specifier: string | undefined;
136
+ } | {
137
+ ok: false;
138
+ reason: string;
139
+ };
140
+ /**
141
+ * THE CONTAINMENT RULES, applied to the RESOLVED REAL PATH (CR-F-CRED-002,
142
+ * CH-002). Exported so a test can drive both rules directly without staging a
143
+ * module on disk for every member; `loadAdapter` is the only caller in `src/`.
144
+ *
145
+ * Returns a refusal reason, or undefined to allow. Both rules name the
146
+ * resolved path, because an operator reading the refusal has to be able to see
147
+ * WHERE the specifier landed, which is precisely the thing the specifier's own
148
+ * spelling hides.
149
+ */
150
+ export declare function refuseResolvedAdapterPath(fleet: Fleet, specifier: string, origin: string, resolved: string): string | undefined;
151
+ export declare function loadAdapter(fleet: Fleet, specifier: string, origin: string): Promise<AdapterLoad>;
152
+ /**
153
+ * IS THIS AN ADAPTER (M4-P4 criterion 4)?
154
+ *
155
+ * The three shapes the criterion names are three ways a module can be
156
+ * IMPORTABLE and not be an adapter, and each of them is silent at the import
157
+ * itself: a module with no default export, a default export with no `launch`,
158
+ * and a `launch` that is not callable. Left unchecked, the first two surface
159
+ * as `TypeError: adapter.launch is not a function` thrown out of `spawnTask`
160
+ * AFTER pool create has made a worktree, a branch and a pool record, which is
161
+ * the same "refusal that arrives as a crash, after creation" shape M4-P3's
162
+ * requirement checks exist to prevent (src/spawn.ts's checkAdapterRequirements).
163
+ *
164
+ * A FOURTH CHECK IS HERE THAT THE CRITERION DOES NOT NAME, and it is declared
165
+ * rather than smuggled: the adapter's `name` must be a non-empty string.
166
+ * Criterion 5 refuses one particular name, and `undefined` written into the
167
+ * launch record's `adapter` field would defeat the whole point of that
168
+ * criterion by making the record say nothing at all. A guard on the value of
169
+ * a field that may be absent is a guard that cannot go red for the absent
170
+ * case.
171
+ *
172
+ * Every refusal names the SPECIFIER and the member, because an operator
173
+ * reading it has a module to go and fix and needs to know which one.
174
+ */
175
+ export declare function checkAdapterShape(module: unknown, specifier: string, origin: string, resolved: string): AdapterLoad;
176
+ /**
177
+ * WHICH ADAPTER THIS SPAWN USES, AND WHY (M4-P4 criteria 1 and 6).
178
+ *
179
+ * WHICH SOURCE WINS, and it is explicit in the record rather than silent:
180
+ * the `--adapter` FLAG outranks the fleet-home default, and the fleet-home
181
+ * default outranks the built-in one.
182
+ *
183
+ * THE WORDING IS DELIBERATE AND IS NOT A STYLE CHOICE. The word this sentence
184
+ * would naturally use is claimed by four rows of
185
+ * delivery/plan/cutover/retirement-inventory.json, which assert that no kernel
186
+ * artifact states an authority order among charter, plan and decision records
187
+ * and enumerate BY NAME the `src/` files allowed to carry the token. A new
188
+ * file carrying it reddens `scripts/check-retirement-inventory.mjs`, correctly,
189
+ * because the checker cannot tell a benign use from a refuting one without a
190
+ * human reading it. This use is benign and incidental, so the token is not
191
+ * used here rather than the rows being widened from a phase that does not own
192
+ * that document. A flag is a per-spawn instruction and
193
+ * a fleet-home field is a standing one, so the narrower statement wins; the
194
+ * opposite order would make the flag unusable on any fleet that declared a
195
+ * default.
196
+ *
197
+ * `undefined` for the adapter means USE THE BUILT-IN ONE, and it is returned
198
+ * as `undefined` rather than as `subprocessAdapter` so that this module
199
+ * imports nothing but a type from `src/spawn.ts`. See BUILT_IN_ADAPTER_NAME
200
+ * above for why the import edge runs one way.
201
+ */
202
+ export declare function selectAdapter(fleet: Fleet, flagSpecifier: string | undefined): Promise<AdapterSelection>;