@junghanacs/entwurf 0.21.0 → 0.23.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 (122) hide show
  1. package/AGENTS.md +3 -2
  2. package/BASELINE.md +3 -1
  3. package/CHANGELOG.md +658 -0
  4. package/DELIVERY.md +167 -29
  5. package/README.md +104 -14
  6. package/VERIFY.md +73 -11
  7. package/docs/external-mcp-host.md +16 -6
  8. package/docs/setup-clean-host.md +73 -22
  9. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +54 -31
  10. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-caller-seat.js +174 -0
  11. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-declaration.js +609 -0
  12. package/mcp/entwurf-bridge/dist/pi-extensions/lib/codex-fresh-preflight.js +289 -57
  13. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-control-rpc.js +40 -0
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-fact-provider.js +6 -2
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-facts.js +7 -1
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peer-observe.js +67 -2
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-peers-render.js +9 -1
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-self-address.js +24 -0
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-runner.js +3 -2
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-send.js +8 -4
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-composition.js +423 -0
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +98 -0
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +1018 -0
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-placement.js +213 -0
  25. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-fresh-call.js +171 -263
  26. package/mcp/entwurf-bridge/dist/scripts/codex-socket-path.js +30 -0
  27. package/mcp/entwurf-bridge/dist/scripts/peer-facts.js +109 -0
  28. package/mcp/entwurf-bridge/src/index.ts +65 -31
  29. package/mcp/entwurf-bridge/tsconfig.build.json +10 -0
  30. package/package.json +4 -4
  31. package/pi-extensions/entwurf-control.ts +91 -52
  32. package/pi-extensions/lib/codex-caller-seat.ts +204 -0
  33. package/pi-extensions/lib/codex-declaration.js +612 -0
  34. package/pi-extensions/lib/codex-fresh-preflight.ts +325 -52
  35. package/pi-extensions/lib/entwurf-control-rpc.ts +46 -0
  36. package/pi-extensions/lib/entwurf-fact-provider.ts +13 -2
  37. package/pi-extensions/lib/entwurf-facts.ts +14 -1
  38. package/pi-extensions/lib/entwurf-peer-observe.ts +72 -2
  39. package/pi-extensions/lib/entwurf-peers-render.ts +9 -1
  40. package/pi-extensions/lib/entwurf-self-address.ts +33 -0
  41. package/pi-extensions/lib/entwurf-v2-runner.ts +3 -2
  42. package/pi-extensions/lib/entwurf-v2-send.ts +16 -11
  43. package/pi-extensions/lib/fresh-call-composition.ts +493 -0
  44. package/pi-extensions/lib/fresh-call-dispatch.ts +142 -0
  45. package/pi-extensions/lib/herdr-fresh-call.ts +1378 -0
  46. package/pi-extensions/lib/herdr-placement.ts +276 -0
  47. package/pi-extensions/lib/mux-fresh-call.ts +257 -304
  48. package/run.sh +522 -10
  49. package/scripts/check-codex-app-server-launch.ts +445 -0
  50. package/scripts/check-codex-birth-hook.ts +187 -0
  51. package/scripts/check-entwurf-control-rpc.ts +138 -0
  52. package/scripts/check-entwurf-fact-provider.ts +4 -2
  53. package/scripts/check-entwurf-facts.ts +12 -6
  54. package/scripts/check-entwurf-peers-surface.ts +3 -1
  55. package/scripts/check-entwurf-self-address.ts +68 -0
  56. package/scripts/check-entwurf-v2-production.ts +42 -1
  57. package/scripts/check-entwurf-v2-send.ts +26 -7
  58. package/scripts/check-fresh-call-dispatch.ts +301 -0
  59. package/scripts/check-gate-qualification.ts +19 -5
  60. package/scripts/check-herdr-activation.ts +1293 -0
  61. package/scripts/check-herdr-fresh-call.ts +1250 -0
  62. package/scripts/check-herdr-placement.ts +383 -0
  63. package/scripts/check-herdr-plugin-build.ts +842 -0
  64. package/scripts/check-herdr-plugin-profile.ts +371 -0
  65. package/scripts/check-herdr-plugin.ts +523 -0
  66. package/scripts/check-herdr-runtime-bootstrap.ts +1264 -0
  67. package/scripts/check-herdr-sandbox.ts +456 -0
  68. package/scripts/check-herdr-supply.ts +184 -0
  69. package/scripts/check-mux-launch-tmux.ts +331 -35
  70. package/scripts/check-mux-launcher-fence.ts +138 -0
  71. package/scripts/check-peer-facts.ts +331 -0
  72. package/scripts/check-release-gate-outcomes.ts +12 -0
  73. package/scripts/check-typing-call-fence.ts +296 -0
  74. package/scripts/codex-app-server-launch.sh +275 -0
  75. package/scripts/codex-birth-doctor.sh +159 -16
  76. package/scripts/codex-birth-install.sh +178 -72
  77. package/scripts/codex-birth-uninstall.sh +162 -7
  78. package/scripts/codex-socket-path.ts +33 -0
  79. package/scripts/codex-terminal-title-config.py +500 -0
  80. package/scripts/codex_toml_io.py +121 -0
  81. package/scripts/fixtures/herdr-supply.json +29 -0
  82. package/scripts/herdr-activation.mjs +536 -0
  83. package/scripts/herdr-plugin-activate.mjs +270 -0
  84. package/scripts/herdr-plugin-deactivate.mjs +193 -0
  85. package/scripts/herdr-runtime.mjs +1203 -0
  86. package/scripts/install-herdr-ci.sh +96 -0
  87. package/scripts/lib/codex-fresh-live-protocol.ts +13 -5
  88. package/scripts/lib/codex-fresh-source-receipts.ts +29 -2
  89. package/scripts/lib/tree-digest.ts +97 -0
  90. package/scripts/meta-bridge-install.sh +19 -2
  91. package/scripts/meta-bridge-state.py +167 -11
  92. package/scripts/mutants/codex-app-server-launch.json +157 -0
  93. package/scripts/mutants/codex-caller-seat.json +334 -0
  94. package/scripts/mutants/codex-native.json +195 -29
  95. package/scripts/mutants/control-socket-disconnect.json +57 -0
  96. package/scripts/mutants/fresh-call-dispatch.json +154 -0
  97. package/scripts/mutants/herdr-activation.json +305 -0
  98. package/scripts/mutants/herdr-fresh-call.json +448 -0
  99. package/scripts/mutants/herdr-placement.json +161 -0
  100. package/scripts/mutants/herdr-plugin-build.json +160 -0
  101. package/scripts/mutants/herdr-plugin-profile.json +202 -0
  102. package/scripts/mutants/herdr-plugin.json +133 -0
  103. package/scripts/mutants/herdr-runtime-bootstrap.json +411 -0
  104. package/scripts/mutants/herdr-supply.json +133 -0
  105. package/scripts/mutants/meta-hook-session-switch.json +2 -2
  106. package/scripts/mutants/mux-fresh-call.json +184 -25
  107. package/scripts/mutants/mux-launcher-fence.json +13 -0
  108. package/scripts/mutants/omp-fresh.json +4 -4
  109. package/scripts/mutants/peer-facts.json +98 -0
  110. package/scripts/mutants/self-address.json +33 -0
  111. package/scripts/mutants/typing-call-fence.json +17 -0
  112. package/scripts/mutants/v2-surface.json +22 -0
  113. package/scripts/peer-facts.ts +120 -0
  114. package/scripts/register-pi-package.py +8 -0
  115. package/scripts/register-pi-provider.py +88 -12
  116. package/scripts/smoke-codex-birth.sh +281 -12
  117. package/scripts/smoke-codex-config-state.sh +192 -3
  118. package/scripts/smoke-codex-fresh-live.ts +277 -37
  119. package/scripts/smoke-entwurf-chain-live.ts +50 -0
  120. package/scripts/smoke-herdr-fresh-call-live.ts +1027 -0
  121. package/scripts/smoke-herdr-plugin-build-live.ts +543 -0
  122. package/scripts/smoke-setup-verdict.sh +13 -11
@@ -0,0 +1,305 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "herdr-activation",
4
+ "mutants": [
5
+ {
6
+ "claim": "HAC-PI-USER-SCOPE-ONLY",
7
+ "title": "composing the generic install for a plugin activation writes a project `.pi/settings.json` the plugin has no project for — a second package identity that `--entwurf-control` then has to arbitrate, on a host the operator never asked to have a project registered in",
8
+ "subject": "run.sh",
9
+ "find": [" register_user_scope_citizen \"$plugin_runtime\""],
10
+ "replace": [" install_local_package \"${HOME}/plugin-has-no-project\""],
11
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
12
+ "timeoutSeconds": 300,
13
+ "signature": "[QK:HAC-PI-USER-SCOPE-ONLY]",
14
+ "signatureSource": "scripts/check-herdr-activation.ts"
15
+ },
16
+ {
17
+ "claim": "HAC-COMMAND-IS-DERIVED",
18
+ "title": "accepting any absolute directory as 'the plugin runtime' is a way to point every pi session at an executable of the caller's choosing — 'absolute' was never the contract, 'this host's stable runtime' was",
19
+ "subject": "scripts/register-pi-provider.py",
20
+ "find": [" if runtime_root != expected:"],
21
+ "replace": [" if False:"],
22
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
23
+ "timeoutSeconds": 300,
24
+ "signature": "[QK:HAC-COMMAND-IS-DERIVED]",
25
+ "signatureSource": "scripts/check-herdr-activation.ts"
26
+ },
27
+ {
28
+ "claim": "HAC-DEFAULT-MODE-UNCHANGED",
29
+ "title": "letting the plugin mode leak into the default branch rewrites the Claude wiring of every host that never asked for it — adding a mode is only safe while the hosts that do not use it keep their bytes",
30
+ "subject": "scripts/meta-bridge-state.py",
31
+ "find": [
32
+ " if PLUGIN_RUNTIME is not None:",
33
+ " return {\"type\": \"stdio\", \"command\": plugin_bin(\"entwurf-bridge\"), \"args\": [], \"env\": env}"
34
+ ],
35
+ "replace": [
36
+ " if True:",
37
+ " return {\"type\": \"stdio\", \"command\": plugin_bin(\"entwurf-bridge\"), \"args\": [], \"env\": env}"
38
+ ],
39
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
40
+ "timeoutSeconds": 300,
41
+ "signature": "[QK:HAC-DEFAULT-MODE-UNCHANGED]",
42
+ "signatureSource": "scripts/check-herdr-activation.ts"
43
+ },
44
+ {
45
+ "claim": "HAC-INVERSE-REFUSES-DRIFT",
46
+ "title": "the user-scope inverse is admitted by the ownership record, so without the drift check it deletes whatever now sits at our key — an operator who replaced the command with their own loses it to our uninstall",
47
+ "subject": "scripts/register-pi-provider.py",
48
+ "find": [" if isinstance(recorded_cmd, str) and live_cmd is not None and live_cmd != recorded_cmd:"],
49
+ "replace": [" if False:"],
50
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
51
+ "timeoutSeconds": 300,
52
+ "signature": "[QK:HAC-INVERSE-REFUSES-DRIFT]",
53
+ "signatureSource": "scripts/check-herdr-activation.ts"
54
+ },
55
+ {
56
+ "claim": "HAC-LEDGER-CERTIFIED",
57
+ "title": "a ledger that may name an atom outside P is a teardown aimed at a harness this lane promised to never write — OpenCode is installed on real hosts and the whole product boundary is that it receives nothing",
58
+ "subject": "scripts/herdr-activation.mjs",
59
+ "find": ["\t\tif (!ACTIVATABLE_BACKENDS.includes(backend)) {"],
60
+ "replace": ["\t\tif (false) {"],
61
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
62
+ "timeoutSeconds": 300,
63
+ "signature": "[QK:HAC-LEDGER-CERTIFIED]",
64
+ "signatureSource": "scripts/check-herdr-activation.ts"
65
+ },
66
+ {
67
+ "claim": "HAC-ADD-ONLY",
68
+ "title": "inferring removal from a shrinking request makes an unrelated Herdr integration uninstall silently tear down Entwurf wiring the operator still uses — Herdr's reinstall is the refresh trigger, not a statement of intent to remove",
69
+ "subject": "scripts/herdr-activation.mjs",
70
+ "find": ["\tconst retained = ACTIVATABLE_BACKENDS.filter((b) => already.includes(b) && !requested.includes(b));"],
71
+ "replace": ["\tconst retained = [];"],
72
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
73
+ "timeoutSeconds": 300,
74
+ "signature": "[QK:HAC-ADD-ONLY]",
75
+ "signatureSource": "scripts/check-herdr-activation.ts"
76
+ },
77
+ {
78
+ "claim": "HAC-ROOTS-CERTIFIED",
79
+ "title": "acting on a ledger whose recorded harness roots differ from this environment's undoes an activation against a config that was never ours — the override that decided where the bytes went is the same override the inverse needs",
80
+ "subject": "scripts/herdr-activation.mjs",
81
+ "find": ["\tif (mismatches.length > 0) {"],
82
+ "replace": ["\tif (false) {"],
83
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
84
+ "timeoutSeconds": 300,
85
+ "signature": "[QK:HAC-ROOTS-CERTIFIED]",
86
+ "signatureSource": "scripts/check-herdr-activation.ts"
87
+ },
88
+ {
89
+ "claim": "HAC-TEARDOWN-ORDER",
90
+ "title": "retiring the ledger before the artifacts it authorised leaves a half-removed host with no record of what remains, and removing the runtime first leaves both harnesses' configs naming a directory that is already gone",
91
+ "subject": "scripts/herdr-activation.mjs",
92
+ "find": [
93
+ "\tsteps.push(\"runtime\");",
94
+ "\t// The ledger is the retry authority, so it is retired after everything it authorised.",
95
+ "\tsteps.push(\"ledger\");"
96
+ ],
97
+ "replace": [
98
+ "\tsteps.push(\"ledger\");",
99
+ "\t// The ledger is the retry authority, so it is retired after everything it authorised.",
100
+ "\tsteps.push(\"runtime\");"
101
+ ],
102
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
103
+ "timeoutSeconds": 300,
104
+ "signature": "[QK:HAC-TEARDOWN-ORDER]",
105
+ "signatureSource": "scripts/check-herdr-activation.ts"
106
+ },
107
+ {
108
+ "claim": "HAC-PREFLIGHT-ALL-OR-NOTHING",
109
+ "title": "mutating before every authority is green is how a Claude failure strands a half-removed Pi: the teardown starts on a promise nobody checked and stops somewhere no record describes",
110
+ "subject": "scripts/herdr-plugin-deactivate.mjs",
111
+ "find": ["\tif (refused.length > 0) {"],
112
+ "replace": ["\tif (false) {"],
113
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
114
+ "timeoutSeconds": 300,
115
+ "signature": "[QK:HAC-PREFLIGHT-ALL-OR-NOTHING]",
116
+ "signatureSource": "scripts/check-herdr-activation.ts"
117
+ },
118
+ {
119
+ "claim": "HAC-NO-DEFERRED-IMPORT",
120
+ "title": "one lazy import on this path is unrecoverable: the process has already deleted the runtime it is executing from, so the load fails with ERR_MODULE_NOT_FOUND and the host is left with no runtime, an unretired ledger, and nothing to run the rest",
121
+ "subject": "scripts/herdr-plugin-deactivate.mjs",
122
+ "find": ["import { removeOwnedRuntime, resolveRuntimeLayout } from \"./herdr-runtime.mjs\";"],
123
+ "replace": ["const { removeOwnedRuntime, resolveRuntimeLayout } = await import(\"./herdr-runtime.mjs\");"],
124
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
125
+ "timeoutSeconds": 300,
126
+ "signature": "[QK:HAC-NO-DEFERRED-IMPORT]",
127
+ "signatureSource": "scripts/check-herdr-activation.ts"
128
+ },
129
+ {
130
+ "claim": "HAC-ENTRY-GUARD-REALPATH",
131
+ "title": "comparing argv[1] to import.meta.url unresolved makes the entry guard silently FALSE under a package manager that symlinks the package — pnpm links node_modules/@junghanacs/entwurf into its store — so the verb runs, prints nothing, exits 0, and every caller reads a teardown that never happened",
132
+ "subject": "scripts/herdr-plugin-deactivate.mjs",
133
+ "find": ["\t\treturn fs.realpathSync(a) === fs.realpathSync(b);"],
134
+ "replace": ["\t\treturn path.resolve(a) === path.resolve(b);"],
135
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
136
+ "timeoutSeconds": 300,
137
+ "signature": "[QK:HAC-ENTRY-GUARD-REALPATH]",
138
+ "signatureSource": "scripts/check-herdr-activation.ts"
139
+ },
140
+ {
141
+ "claim": "HAC-DEACTIVATE-ROUNDTRIP",
142
+ "title": "a teardown that retires the ledger while leaving the runtime behind reports a host as clean while its stable address still holds a runtime nothing records — the operator has no verb left that will find it",
143
+ "subject": "scripts/herdr-plugin-deactivate.mjs",
144
+ "find": ["\t\t} else if (step === \"runtime\") {"],
145
+ "replace": ["\t\t} else if (step === \"never\") {"],
146
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
147
+ "timeoutSeconds": 300,
148
+ "signature": "[QK:HAC-DEACTIVATE-ROUNDTRIP]",
149
+ "signatureSource": "scripts/check-herdr-activation.ts"
150
+ },
151
+ {
152
+ "claim": "HAC-LEDGER-STATE-MACHINE",
153
+ "subject": "scripts/herdr-activation.mjs",
154
+ "title": "a phase that may contradict its own component rows is a ledger that says 'active' over a component it already removed — every later decision reads it, and the retry that trusts it re-runs an inverse whose ownership state is gone",
155
+ "find": ["\t\tif (!PHASE_ALLOWS[parsed.phase].includes(component.state)) {"],
156
+ "replace": ["\t\tif (false) {"],
157
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
158
+ "timeoutSeconds": 600,
159
+ "signature": "[QK:HAC-LEDGER-STATE-MACHINE]",
160
+ "signatureSource": "scripts/check-herdr-activation.ts"
161
+ },
162
+ {
163
+ "claim": "HAC-TWO-STAGE-ADD-ONLY",
164
+ "subject": "scripts/herdr-plugin-activate.mjs",
165
+ "title": "not handing the installer the plugin mode wires Claude to the bare/clone command on a host where nothing entwurf is on PATH — the install reports success and every MCP call it configured cannot resolve",
166
+ "find": [
167
+ "\t\t\t\t: run(\"bash\", [path.join(PACKAGE_ROOT, \"scripts\", \"meta-bridge-install.sh\")], {",
168
+ "\t\t\t\t\t\t...env,",
169
+ "\t\t\t\t\t\tENTWURF_PLUGIN_RUNTIME: runtime.activeDir,",
170
+ "\t\t\t\t\t});"
171
+ ],
172
+ "replace": [
173
+ "\t\t\t\t: run(\"bash\", [path.join(PACKAGE_ROOT, \"scripts\", \"meta-bridge-install.sh\")], {",
174
+ "\t\t\t\t\t\t...env,",
175
+ "\t\t\t\t\t});"
176
+ ],
177
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
178
+ "timeoutSeconds": 600,
179
+ "signature": "[QK:HAC-TWO-STAGE-ADD-ONLY]",
180
+ "signatureSource": "scripts/check-herdr-activation.ts"
181
+ },
182
+ {
183
+ "claim": "HAC-RETRY-RESUMES",
184
+ "subject": "scripts/herdr-activation.mjs",
185
+ "title": "re-running a component inverse the ledger already recorded as removed is a permanent refusal, not an idempotent no-op: its ownership state is gone, its preflight fails, and one partial teardown becomes a host nobody can finish",
186
+ "find": ["\t\tif (states[backend] === \"active\") steps.push(backend);"],
187
+ "replace": ["\t\tsteps.push(backend);"],
188
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
189
+ "timeoutSeconds": 600,
190
+ "signature": "[QK:HAC-RETRY-RESUMES]",
191
+ "signatureSource": "scripts/check-herdr-activation.ts"
192
+ },
193
+ {
194
+ "claim": "HAC-XDG-RESOLUTION-SHARED",
195
+ "subject": "scripts/herdr-activation.mjs",
196
+ "title": "resolving the data root as `XDG_DATA_HOME || ''` builds `/entwurf/...` on a host with XDG unset while every writer uses `$HOME/.local/share/entwurf` — a preflight that looks at a file nobody writes and passes for the wrong reason",
197
+ "find": [
198
+ "\tconst dataHome = env.XDG_DATA_HOME || (home ? path.join(home, \".local\", \"share\") : null);\n\tif (!dataHome) {\n\t\tthrow new ActivationError(\"activation-xdg-root-unresolvable\", \"neither XDG_DATA_HOME nor HOME is set\");\n\t}\n\treturn path.join(dataHome, \"entwurf\");"
199
+ ],
200
+ "replace": ["\treturn path.join(env.XDG_DATA_HOME || \"\", \"entwurf\");"],
201
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
202
+ "timeoutSeconds": 600,
203
+ "signature": "[QK:HAC-XDG-RESOLUTION-SHARED]",
204
+ "signatureSource": "scripts/check-herdr-activation.ts"
205
+ },
206
+ {
207
+ "claim": "HAC-CLAUDE-PLAN-CERTIFIED",
208
+ "subject": "scripts/meta-bridge-state.py",
209
+ "title": "a preflight that re-implements the restore rules knows only the entry shapes whoever wrote it remembered — the first cut demanded `original` on every entry while `snapshot_array_items` writes `{originalExisted, added}`, so every real Claude activation failed its own preflight and the aggregate could never honestly claim preflight-all",
210
+ "find": [" if kind == \"array-items\":\n if \"originalExisted\" not in entry:"],
211
+ "replace": [" if kind == \"array-items-never\":\n if \"originalExisted\" not in entry:"],
212
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
213
+ "timeoutSeconds": 600,
214
+ "signature": "[QK:HAC-CLAUDE-PLAN-CERTIFIED]",
215
+ "signatureSource": "scripts/check-herdr-activation.ts"
216
+ },
217
+ {
218
+ "claim": "HAC-PHASE-TRANSITIONS",
219
+ "subject": "scripts/herdr-activation.mjs",
220
+ "title": "a forward run over a `deactivating` ledger re-wires components a teardown is midway through removing and overwrites the only record of where it stopped — the host ends up half-wired with nothing that describes it",
221
+ "find": ["\tif (ledger.phase === \"deactivating\") {"],
222
+ "replace": ["\tif (false) {"],
223
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
224
+ "timeoutSeconds": 600,
225
+ "signature": "[QK:HAC-PHASE-TRANSITIONS]",
226
+ "signatureSource": "scripts/check-herdr-activation.ts"
227
+ },
228
+ {
229
+ "claim": "HAC-CLAUDE-ROOTS-COMPLETE",
230
+ "subject": "scripts/herdr-activation.mjs",
231
+ "title": "a ledger that records only CLAUDE_CONFIG_DIR misses `$HOME/.claude.json`, where the user-scope MCP entry lives: measured, a moved HOME passes the root check and the MCP entry is left behind in the old home",
232
+ "find": ["\t\tclaudeUserConfig: Object.freeze({ path: path.join(home, \".claude.json\"), source: \"HOME\" }),"],
233
+ "replace": [
234
+ "\t\tclaudeUserConfig: Object.freeze({ path: path.join(home, \".claude.json\"), source: \"default\" }),"
235
+ ],
236
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
237
+ "timeoutSeconds": 600,
238
+ "signature": "[QK:HAC-CLAUDE-ROOTS-COMPLETE]",
239
+ "signatureSource": "scripts/check-herdr-activation.ts"
240
+ },
241
+ {
242
+ "claim": "HAC-AGGREGATE-PREFLIGHT-COMPLETE",
243
+ "subject": "scripts/herdr-plugin-activate.mjs",
244
+ "title": "preflighting only the provider half lets the first ledger write land on a host the pi PACKAGE writer was always going to refuse — the aggregate claims preflight-all while one of the two ownership records was never asked",
245
+ "find": ["\t\tpreflights.push([", "\t\t\t\"pi-package\","],
246
+ "replace": ["\t\tif (false) preflights.push([", "\t\t\t\"pi-package\","],
247
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
248
+ "timeoutSeconds": 600,
249
+ "signature": "[QK:HAC-AGGREGATE-PREFLIGHT-COMPLETE]",
250
+ "signatureSource": "scripts/check-herdr-activation.ts"
251
+ },
252
+ {
253
+ "claim": "HAC-RUNTIME-EXACT-VERSION",
254
+ "subject": "scripts/herdr-plugin-activate.mjs",
255
+ "title": "checking only that SOME usable tree of that name is present wires two harnesses at an address whose contents disagree with the journal that certified it — the provenance line then describes something else",
256
+ "find": ["\t\tverifyInstalledRuntime(runtime.activeDir, artifactCompleteness(journal.artifactIdentity));"],
257
+ "replace": [
258
+ "\t\tconst certifiedName = artifactCompleteness(journal.artifactIdentity).name;",
259
+ "\t\tverifyInstalledRuntime(runtime.activeDir, {",
260
+ "\t\t\tname: certifiedName,",
261
+ "\t\t\tversion: JSON.parse(",
262
+ "\t\t\t\tfs.readFileSync(path.join(runtime.activeDir, \"node_modules\", certifiedName, \"package.json\"), \"utf8\"),",
263
+ "\t\t\t).version,",
264
+ "\t\t});"
265
+ ],
266
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
267
+ "timeoutSeconds": 600,
268
+ "signature": "[QK:HAC-RUNTIME-EXACT-VERSION]",
269
+ "signatureSource": "scripts/check-herdr-activation.ts"
270
+ },
271
+ {
272
+ "claim": "HAC-LEDGER-IDENTITY-CERTIFIED",
273
+ "title": "letting the ledger carry a REQUESTED identity records an activation against an artifact nothing observed, and the teardown that reads it back has no digest or completeness pair to check the disk against",
274
+ "subject": "scripts/herdr-activation.mjs",
275
+ "find": ["\t\tcertifyArtifactIdentity(\"artifactIdentity\", parsed.artifactIdentity, \"ready\");"],
276
+ "replace": ["\t\tcertifyArtifactIdentity(\"artifactIdentity\", parsed.artifactIdentity, \"either\");"],
277
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
278
+ "timeoutSeconds": 420,
279
+ "signature": "[QK:HAC-LEDGER-IDENTITY-CERTIFIED]",
280
+ "signatureSource": "scripts/check-herdr-activation.ts"
281
+ },
282
+ {
283
+ "claim": "HAC-REBIND-LEGALITY",
284
+ "title": "treating a SOURCE change as an ordinary reinstall lets one acquisition authority inherit the other's activation without the operator ever asking — the npm branch would silently adopt a candidate's wiring, or the reverse",
285
+ "subject": "scripts/herdr-activation.mjs",
286
+ "find": ["\tif (ledger.artifactIdentity.kind !== target.kind) {"],
287
+ "replace": ["\tif (false && ledger.artifactIdentity.kind !== target.kind) {"],
288
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
289
+ "timeoutSeconds": 420,
290
+ "signature": "[QK:HAC-REBIND-LEGALITY]",
291
+ "signatureSource": "scripts/check-herdr-activation.ts"
292
+ },
293
+ {
294
+ "claim": "HAC-REBIND-ATOMIC-CHECKPOINT",
295
+ "title": "leaving already-active components labelled `active` through a rebind claims work the run has not redone: the ledger says those components are wired to the new artifact while nothing has re-pointed them",
296
+ "subject": "scripts/herdr-plugin-activate.mjs",
297
+ "find": ["\t\tif (disposition === \"rebind\" || states[backend] !== \"active\") states[backend] = \"pending\";"],
298
+ "replace": ["\t\tif (states[backend] !== \"active\") states[backend] = \"pending\";"],
299
+ "gate": ["bash", "run.sh", "check-herdr-activation"],
300
+ "timeoutSeconds": 420,
301
+ "signature": "[QK:HAC-REBIND-ATOMIC-CHECKPOINT]",
302
+ "signatureSource": "scripts/check-herdr-activation.ts"
303
+ }
304
+ ]
305
+ }