@junghanacs/entwurf 0.45.0 → 0.50.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 (105) hide show
  1. package/AGENTS.md +3 -2
  2. package/BASELINE.md +110 -1
  3. package/CHANGELOG.md +169 -0
  4. package/CONTRIBUTING.md +1 -1
  5. package/ENTWURF-CLI.json +1229 -0
  6. package/ENTWURF.json +63 -15
  7. package/FAQ.md +4 -4
  8. package/README.md +124 -188
  9. package/VERIFY.md +2 -2
  10. package/docs/external-mcp-host.md +3 -3
  11. package/docs/setup-clean-host.md +37 -12
  12. package/mcp/entwurf-bridge/dist/ENTWURF.json +63 -15
  13. package/mcp/entwurf-bridge/dist/mcp/entwurf-bridge/src/index.js +19 -8
  14. package/mcp/entwurf-bridge/dist/pi-extensions/lib/entwurf-v2-visible-resume.js +483 -18
  15. package/mcp/entwurf-bridge/dist/pi-extensions/lib/fresh-call-dispatch.js +47 -10
  16. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-fresh-call.js +613 -33
  17. package/mcp/entwurf-bridge/dist/pi-extensions/lib/herdr-resume-call.js +497 -0
  18. package/mcp/entwurf-bridge/dist/pi-extensions/lib/meta-session.js +3 -1
  19. package/mcp/entwurf-bridge/dist/pi-extensions/lib/mux-resume-call.js +50 -5
  20. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-fresh-preflight.js +7 -1
  21. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-location.js +347 -0
  22. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-owner-fence.js +1132 -0
  23. package/mcp/entwurf-bridge/dist/pi-extensions/lib/pi-durable-runtime.js +1 -0
  24. package/mcp/entwurf-bridge/dist/pi-extensions/lib/resume-launch-identity.js +18 -11
  25. package/mcp/entwurf-bridge/dist/pi-extensions/meta-bridge-pi-durable.js +30 -15
  26. package/mcp/entwurf-bridge/dist/scripts/herdr-rails.mjs +40 -7
  27. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-fresh-cut.js +1 -27
  28. package/mcp/entwurf-bridge/dist/scripts/meta-bridge-prune.js +1 -1
  29. package/mcp/entwurf-bridge/dist/scripts/meta-facts.js +1 -1
  30. package/mcp/entwurf-bridge/dist/scripts/peer-facts.js +1 -1
  31. package/mcp/entwurf-bridge/src/index.ts +28 -8
  32. package/mcp/entwurf-bridge/tsconfig.build.json +7 -1
  33. package/native/win32-x64/manifest.json +1 -1
  34. package/package.json +6 -3
  35. package/pi/pi-durable/bootstrap.mjs +179 -6
  36. package/pi/pi-durable/carrier/runtime.js +108 -9
  37. package/pi/pi-durable/carrier/session-name.js +11 -0
  38. package/pi/pi-durable/carrier/sessions.js +96 -20
  39. package/pi/pi-durable/overlay/upstream-pin.json +11 -5
  40. package/pi-extensions/lib/entwurf-v2-visible-resume.ts +710 -38
  41. package/pi-extensions/lib/fresh-call-dispatch.ts +64 -12
  42. package/pi-extensions/lib/herdr-fresh-call.ts +919 -40
  43. package/pi-extensions/lib/herdr-resume-call.ts +810 -0
  44. package/pi-extensions/lib/meta-session.ts +13 -8
  45. package/pi-extensions/lib/mux-resume-call.ts +77 -4
  46. package/pi-extensions/lib/pi-durable-fresh-preflight.ts +9 -2
  47. package/pi-extensions/lib/pi-durable-location.ts +446 -0
  48. package/pi-extensions/lib/pi-durable-owner-fence.ts +1461 -0
  49. package/pi-extensions/lib/pi-durable-runtime.ts +4 -0
  50. package/pi-extensions/lib/resume-launch-identity.ts +31 -12
  51. package/pi-extensions/meta-bridge-pi-durable.ts +29 -15
  52. package/run.sh +411 -657
  53. package/scripts/check-claude-launch.ts +341 -0
  54. package/scripts/check-entwurf-v2-surface.ts +2 -2
  55. package/scripts/check-fresh-call-dispatch.ts +70 -9
  56. package/scripts/check-fresh-cut-gate.sh +23 -9
  57. package/scripts/check-gate-qualification.ts +18 -13
  58. package/scripts/check-herdr-activation.ts +301 -23
  59. package/scripts/check-herdr-fresh-call.ts +161 -25
  60. package/scripts/check-herdr-plugin-build.ts +173 -1
  61. package/scripts/check-herdr-plugin.ts +28 -2
  62. package/scripts/check-herdr-runtime-bootstrap.ts +136 -0
  63. package/scripts/check-install-surface.ts +1236 -6
  64. package/scripts/check-meta-doctor-oracle.sh +1 -1
  65. package/scripts/check-meta-facts.ts +20 -1
  66. package/scripts/check-mux-resume-call.ts +28 -0
  67. package/scripts/check-peer-facts.ts +39 -2
  68. package/scripts/cli-help.mjs +222 -0
  69. package/scripts/dev-bin.sh +39 -2
  70. package/scripts/herdr-activation.mjs +28 -6
  71. package/scripts/herdr-operator-link.mjs +389 -0
  72. package/scripts/herdr-plugin-activate.mjs +5 -0
  73. package/scripts/herdr-plugin-deactivate.mjs +18 -5
  74. package/scripts/herdr-rails.mjs +43 -7
  75. package/scripts/herdr-runtime.mjs +27 -0
  76. package/scripts/meta-bridge-fresh-cut.ts +1 -27
  77. package/scripts/meta-bridge-prune.ts +1 -1
  78. package/scripts/meta-facts.ts +1 -1
  79. package/scripts/mutants/agent-guidance.json +4 -4
  80. package/scripts/mutants/claude-launch.json +142 -0
  81. package/scripts/mutants/cli-help-source.json +420 -0
  82. package/scripts/mutants/dev-gate-dispatch.json +109 -0
  83. package/scripts/mutants/fresh-call-dispatch.json +38 -2
  84. package/scripts/mutants/fresh-cut.json +15 -0
  85. package/scripts/mutants/herdr-activation.json +128 -0
  86. package/scripts/mutants/herdr-fresh-call.json +278 -5
  87. package/scripts/mutants/herdr-operator-link.json +318 -0
  88. package/scripts/mutants/herdr-plugin-build.json +55 -0
  89. package/scripts/mutants/herdr-plugin.json +17 -0
  90. package/scripts/mutants/herdr-resume-call.json +288 -0
  91. package/scripts/mutants/herdr-runtime-bootstrap.json +48 -0
  92. package/scripts/mutants/meta-facts.json +15 -0
  93. package/scripts/mutants/mux-resume-call.json +63 -2
  94. package/scripts/mutants/peer-facts.json +15 -0
  95. package/scripts/mutants/pi-durable.json +979 -1
  96. package/scripts/mutants/source-install.json +35 -0
  97. package/scripts/mutants/v2-surface.json +2 -2
  98. package/scripts/mutants/v2-visible-resume.json +255 -6
  99. package/scripts/peer-facts.ts +1 -1
  100. package/scripts/smoke-agy-install-state.sh +66 -0
  101. package/scripts/smoke-meta-prune.sh +23 -0
  102. package/scripts/smoke-omp-fresh-live.ts +12 -3
  103. package/scripts/smoke-omp-receive-live.ts +7 -1
  104. package/scripts/smoke-pi-durable-fresh-live.ts +12 -2
  105. package/team.json.example +39 -0
@@ -6,8 +6,8 @@
6
6
  "claim": "GUIDANCE-REVIEWED-REVISION",
7
7
  "title": "a valid Root revision advances beyond the independently reviewed payload revision while every history entry and decoded tool string remains valid",
8
8
  "subject": "ENTWURF.json",
9
- "find": ["\t\"revision\": 11,", "\t\"history\": ["],
10
- "replace": ["\t\"revision\": 12,", "\t\"history\": ["],
9
+ "find": ["\t\"revision\": 19,", "\t\"history\": ["],
10
+ "replace": ["\t\"revision\": 20,", "\t\"history\": ["],
11
11
  "gate": ["bash", "run.sh", "check-agent-guidance-beside"],
12
12
  "timeoutSeconds": 120,
13
13
  "signature": "[QK:GUIDANCE-REVIEWED-REVISION]",
@@ -39,8 +39,8 @@
39
39
  "claim": "GUIDANCE-RESUME-REJECT-HINTS-ORIGINAL",
40
40
  "title": "a valid static visible-resume reject hint gains one space in the real JSON, which the reader and the visible-resume wiring both carry faithfully, so only the C0 byte oracle can disagree",
41
41
  "subject": "ENTWURF.json",
42
- "find": ["tmux was never asked to open a window"],
43
- "replace": ["tmux was never asked to open a window"],
42
+ "find": ["no tmux window and no herdr tab was opened"],
43
+ "replace": ["no tmux window and no herdr tab was opened"],
44
44
  "gate": ["bash", "run.sh", "check-agent-guidance-beside"],
45
45
  "timeoutSeconds": 120,
46
46
  "signature": "[QK:GUIDANCE-RESUME-REJECT-HINTS-ORIGINAL]",
@@ -0,0 +1,142 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "claude-launch",
4
+ "mutants": [
5
+ {
6
+ "claim": "CLAUDELAUNCH-VERB-DROPPED",
7
+ "title": "without the shift the dispatcher verb stays in the forwarded argv and `claude` arrives at Claude Code as a prompt argument",
8
+ "subject": "run.sh",
9
+ "find": [" shift || true\n if [ -n \"${ENTWURF_CLAUDE_LAUNCH_ACTIVE:-}\" ]; then"],
10
+ "replace": [" if [ -n \"${ENTWURF_CLAUDE_LAUNCH_ACTIVE:-}\" ]; then"],
11
+ "gate": ["bash", "run.sh", "check-claude-launch"],
12
+ "timeoutSeconds": 300,
13
+ "signature": "[QK:CLAUDELAUNCH-VERB-DROPPED]",
14
+ "signatureSource": "scripts/check-claude-launch.ts"
15
+ },
16
+ {
17
+ "claim": "CLAUDELAUNCH-ARGV-UNTOUCHED",
18
+ "title": "a launcher that adds an argument of its own stops being a spelling and starts deciding the session (Rule 9)",
19
+ "subject": "run.sh",
20
+ "find": [" exec \"$entwurf_claude_bin\" \"$@\""],
21
+ "replace": [" exec \"$entwurf_claude_bin\" --verbose \"$@\""],
22
+ "gate": ["bash", "run.sh", "check-claude-launch"],
23
+ "timeoutSeconds": 300,
24
+ "signature": "[QK:CLAUDELAUNCH-ARGV-UNTOUCHED]",
25
+ "signatureSource": "scripts/check-claude-launch.ts"
26
+ },
27
+ {
28
+ "claim": "CLAUDELAUNCH-VENDOR-HELP",
29
+ "title": "the help preflight intercepts `entwurf claude --help`, so Claude Code's own help is replaced by an Entwurf page",
30
+ "subject": "run.sh",
31
+ "find": ["[ \"$cmd\" != claude ] && "],
32
+ "replace": [""],
33
+ "gate": ["bash", "run.sh", "check-claude-launch"],
34
+ "timeoutSeconds": 300,
35
+ "signature": "[QK:CLAUDELAUNCH-VENDOR-HELP]",
36
+ "signatureSource": "scripts/check-claude-launch.ts"
37
+ },
38
+ {
39
+ "claim": "CLAUDELAUNCH-CWD-KEPT",
40
+ "title": "a launch that moves to the package directory opens Claude Code in the wrong project and session scope",
41
+ "subject": "run.sh",
42
+ "find": [" exec \"$entwurf_claude_bin\" \"$@\""],
43
+ "replace": [" cd \"$REPO_DIR\"; exec \"$entwurf_claude_bin\" \"$@\""],
44
+ "gate": ["bash", "run.sh", "check-claude-launch"],
45
+ "timeoutSeconds": 300,
46
+ "signature": "[QK:CLAUDELAUNCH-CWD-KEPT]",
47
+ "signatureSource": "scripts/check-claude-launch.ts"
48
+ },
49
+ {
50
+ "claim": "CLAUDELAUNCH-SENTINEL-EXPORTED",
51
+ "title": "an unexported sentinel is invisible to a PATH `claude` that shells back here, so the wrapper loop spins",
52
+ "subject": "run.sh",
53
+ "find": [" export ENTWURF_CLAUDE_LAUNCH_ACTIVE=1"],
54
+ "replace": [" ENTWURF_CLAUDE_LAUNCH_ACTIVE=1"],
55
+ "gate": ["bash", "run.sh", "check-claude-launch"],
56
+ "timeoutSeconds": 300,
57
+ "signature": "[QK:CLAUDELAUNCH-SENTINEL-EXPORTED]",
58
+ "signatureSource": "scripts/check-claude-launch.ts"
59
+ },
60
+ {
61
+ "claim": "CLAUDELAUNCH-CARRIERS-SCRUBBED",
62
+ "title": "clearing only half of an inherited pi identity pair leaves another citizen's carrier for a partial reader",
63
+ "subject": "run.sh",
64
+ "find": [" unset PI_SESSION_ID PI_AGENT_ID"],
65
+ "replace": [" unset PI_AGENT_ID"],
66
+ "gate": ["bash", "run.sh", "check-claude-launch"],
67
+ "timeoutSeconds": 300,
68
+ "signature": "[QK:CLAUDELAUNCH-CARRIERS-SCRUBBED]",
69
+ "signatureSource": "scripts/check-claude-launch.ts"
70
+ },
71
+ {
72
+ "claim": "CLAUDELAUNCH-ENV-EXACT",
73
+ "title": "a launcher that sets a variable of its own decides something Claude Code owns",
74
+ "subject": "run.sh",
75
+ "find": [" export ENTWURF_CLAUDE_LAUNCH_ACTIVE=1"],
76
+ "replace": [" export ENTWURF_CLAUDE_LAUNCH_ACTIVE=1 ENTWURF_CLAUDE_EXTRA=1"],
77
+ "gate": ["bash", "run.sh", "check-claude-launch"],
78
+ "timeoutSeconds": 300,
79
+ "signature": "[QK:CLAUDELAUNCH-ENV-EXACT]",
80
+ "signatureSource": "scripts/check-claude-launch.ts"
81
+ },
82
+ {
83
+ "claim": "CLAUDELAUNCH-EXEC-KEEPS-PID",
84
+ "title": "without exec run.sh stays as a parent between Claude Code and the terminal, owning nothing",
85
+ "subject": "run.sh",
86
+ "find": [" exec \"$entwurf_claude_bin\" \"$@\""],
87
+ "replace": [" \"$entwurf_claude_bin\" \"$@\""],
88
+ "gate": ["bash", "run.sh", "check-claude-launch"],
89
+ "timeoutSeconds": 300,
90
+ "signature": "[QK:CLAUDELAUNCH-EXEC-KEEPS-PID]",
91
+ "signatureSource": "scripts/check-claude-launch.ts"
92
+ },
93
+ {
94
+ "claim": "CLAUDELAUNCH-VENDOR-ABSENT",
95
+ "title": "with the absent-vendor refusal gone an empty PATH hit falls through to a refusal that names the wrong cause",
96
+ "subject": "run.sh",
97
+ "find": [" if [ -z \"$entwurf_claude_bin\" ]; then"],
98
+ "replace": [" if false; then"],
99
+ "gate": ["bash", "run.sh", "check-claude-launch"],
100
+ "timeoutSeconds": 300,
101
+ "signature": "[QK:CLAUDELAUNCH-VENDOR-ABSENT]",
102
+ "signatureSource": "scripts/check-claude-launch.ts"
103
+ },
104
+ {
105
+ "claim": "CLAUDELAUNCH-NOT-REGULAR",
106
+ "title": "a non-regular PATH hit is handed to exec, which fails with the shell's own error instead of a named refusal",
107
+ "subject": "run.sh",
108
+ "find": [" if [ ! -f \"$entwurf_claude_bin\" ] || [ ! -x \"$entwurf_claude_bin\" ]; then"],
109
+ "replace": [" if false; then"],
110
+ "gate": ["bash", "run.sh", "check-claude-launch"],
111
+ "timeoutSeconds": 300,
112
+ "signature": "[QK:CLAUDELAUNCH-NOT-REGULAR]",
113
+ "signatureSource": "scripts/check-claude-launch.ts"
114
+ },
115
+ {
116
+ "claim": "CLAUDELAUNCH-RECURSION-FENCE",
117
+ "title": "with the sentinel fence removed a PATH `claude` that shells back here spins forever behind a hung terminal",
118
+ "subject": "run.sh",
119
+ "find": [
120
+ " if [ -n \"${ENTWURF_CLAUDE_LAUNCH_ACTIVE:-}\" ]; then\n echo \"entwurf: recursive managed launch detected (ENTWURF_CLAUDE_LAUNCH_ACTIVE is already set).\" >&2"
121
+ ],
122
+ "replace": [
123
+ " if false; then\n echo \"entwurf: recursive managed launch detected (ENTWURF_CLAUDE_LAUNCH_ACTIVE is already set).\" >&2"
124
+ ],
125
+ "gate": ["bash", "run.sh", "check-claude-launch"],
126
+ "timeoutSeconds": 300,
127
+ "signature": "[QK:CLAUDELAUNCH-RECURSION-FENCE]",
128
+ "signatureSource": "scripts/check-claude-launch.ts"
129
+ },
130
+ {
131
+ "claim": "CLAUDELAUNCH-SELF-EXEC-FENCE",
132
+ "title": "with the resolved-path fence removed a PATH `claude` that is run.sh re-enters with the operator's argv as an entwurf verb",
133
+ "subject": "run.sh",
134
+ "find": [" if [ \"$entwurf_claude_real\" = \"$REPO_DIR/run.sh\" ]; then"],
135
+ "replace": [" if false; then"],
136
+ "gate": ["bash", "run.sh", "check-claude-launch"],
137
+ "timeoutSeconds": 300,
138
+ "signature": "[QK:CLAUDELAUNCH-SELF-EXEC-FENCE]",
139
+ "signatureSource": "scripts/check-claude-launch.ts"
140
+ }
141
+ ]
142
+ }
@@ -0,0 +1,420 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "lane": "cli-help-source",
4
+ "mutants": [
5
+ {
6
+ "claim": "CLI-HELP-ALL-BYTES",
7
+ "title": "the renderer drops the blank line before Notes, so `entwurf help all` no longer prints the usage it replaced",
8
+ "subject": "scripts/cli-help.mjs",
9
+ "find": ["out.push(\"\", line(notes.title, \"usage.notes.title\"));"],
10
+ "replace": ["out.push(line(notes.title, \"usage.notes.title\"));"],
11
+ "gate": ["bash", "run.sh", "check-install-surface"],
12
+ "timeoutSeconds": 120,
13
+ "signature": "[QK:CLI-HELP-ALL-BYTES]",
14
+ "signatureSource": "scripts/check-install-surface.ts"
15
+ },
16
+ {
17
+ "claim": "CLI-HELP-MODULE-RELATIVE",
18
+ "title": "the renderer reads the help source from the caller's cwd, so whatever ENTWURF-CLI.json sits where `entwurf` was run describes the CLI",
19
+ "subject": "scripts/cli-help.mjs",
20
+ "find": ["const SOURCE = new URL(\"../ENTWURF-CLI.json\", import.meta.url);"],
21
+ "replace": ["const SOURCE = `${process.cwd()}/ENTWURF-CLI.json`;"],
22
+ "gate": ["bash", "run.sh", "check-install-surface"],
23
+ "timeoutSeconds": 120,
24
+ "signature": "[QK:CLI-HELP-MODULE-RELATIVE]",
25
+ "signatureSource": "scripts/check-install-surface.ts"
26
+ },
27
+ {
28
+ "claim": "CLI-HELP-ONLY-RENDERER",
29
+ "title": "usage() asks git for the checkout state before rendering, so reading the help starts a tool the description never needed",
30
+ "subject": "run.sh",
31
+ "find": [" node \"$REPO_DIR/scripts/cli-help.mjs\"\n}"],
32
+ "replace": [
33
+ " git -C \"$REPO_DIR\" rev-parse HEAD >/dev/null 2>&1 || true\n node \"$REPO_DIR/scripts/cli-help.mjs\"\n}"
34
+ ],
35
+ "gate": ["bash", "run.sh", "check-install-surface"],
36
+ "timeoutSeconds": 120,
37
+ "signature": "[QK:CLI-HELP-ONLY-RENDERER]",
38
+ "signatureSource": "scripts/check-install-surface.ts"
39
+ },
40
+ {
41
+ "claim": "CLI-HELP-FAIL-LOUD",
42
+ "title": "usage() swallows the renderer's failure, so a missing or broken help source answers `entwurf --help` with exit 0 and an empty page",
43
+ "subject": "run.sh",
44
+ "find": [" node \"$REPO_DIR/scripts/cli-help.mjs\"\n}"],
45
+ "replace": [" node \"$REPO_DIR/scripts/cli-help.mjs\" || true\n}"],
46
+ "gate": ["bash", "run.sh", "check-install-surface"],
47
+ "timeoutSeconds": 120,
48
+ "signature": "[QK:CLI-HELP-FAIL-LOUD]",
49
+ "signatureSource": "scripts/check-install-surface.ts"
50
+ },
51
+ {
52
+ "claim": "CLI-HELP-STRICT-FIELDS",
53
+ "title": "the renderer stops checking key sets, so an entry can carry a field nobody reviewed — a handler, an argv, a command to run — and still render",
54
+ "subject": "scripts/cli-help.mjs",
55
+ "find": ["\tif (got.length !== want.length || got.some((k, i) => k !== want[i])) {"],
56
+ "replace": ["\tif (false) {"],
57
+ "gate": ["bash", "run.sh", "check-install-surface"],
58
+ "timeoutSeconds": 120,
59
+ "signature": "[QK:CLI-HELP-STRICT-FIELDS]",
60
+ "signatureSource": "scripts/check-install-surface.ts"
61
+ },
62
+ {
63
+ "claim": "CLI-HELP-UNIQUE",
64
+ "title": "the renderer stops refusing a command described twice, so two descriptions of one command both print and neither owns it",
65
+ "subject": "scripts/cli-help.mjs",
66
+ "find": ["\t\tif (entries.has(name)) fail("],
67
+ "replace": ["\t\tif (false) fail("],
68
+ "gate": ["bash", "run.sh", "check-install-surface"],
69
+ "timeoutSeconds": 120,
70
+ "signature": "[QK:CLI-HELP-UNIQUE]",
71
+ "signatureSource": "scripts/check-install-surface.ts"
72
+ },
73
+ {
74
+ "claim": "CLI-HELP-CANONICAL",
75
+ "title": "a duplicated JSON property rides into the committed help source; JSON.parse keeps the later value and every runtime check stays green",
76
+ "subject": "ENTWURF-CLI.json",
77
+ "find": ["\t\"schemaVersion\": 4,"],
78
+ "replace": ["\t\"schemaVersion\": 4,\n\t\"schemaVersion\": 4,"],
79
+ "gate": ["bash", "run.sh", "check-install-surface"],
80
+ "timeoutSeconds": 120,
81
+ "signature": "[QK:CLI-HELP-CANONICAL]",
82
+ "signatureSource": "scripts/check-install-surface.ts"
83
+ },
84
+ {
85
+ "claim": "CLI-HELP-NO-ORPHAN",
86
+ "title": "the help describes a command that no dispatch arm or gate function provides — `entwurf --help` advertises something that does not exist",
87
+ "subject": "ENTWURF-CLI.json",
88
+ "find": ["\t\t\t\t\t\"synopsis\": \"menu\","],
89
+ "replace": ["\t\t\t\t\t\"synopsis\": \"menu-retired\","],
90
+ "gate": ["bash", "run.sh", "check-install-surface"],
91
+ "timeoutSeconds": 120,
92
+ "signature": "[QK:CLI-HELP-NO-ORPHAN]",
93
+ "signatureSource": "scripts/check-install-surface.ts"
94
+ },
95
+ {
96
+ "claim": "CLI-HELP-DEBT-EXACT",
97
+ "title": "a new dispatch arm lands with no description, and the help silently stops covering a command run.sh answers",
98
+ "subject": "run.sh",
99
+ "find": [" -h|--help|help|\"\")"],
100
+ "replace": [" zz-undescribed)\n :\n ;;\n -h|--help|help|\"\")"],
101
+ "gate": ["bash", "run.sh", "check-install-surface"],
102
+ "timeoutSeconds": 120,
103
+ "signature": "[QK:CLI-HELP-DEBT-EXACT]",
104
+ "signatureSource": "scripts/check-install-surface.ts"
105
+ },
106
+ {
107
+ "claim": "CLI-HELP-DISPATCH-REVIEWED",
108
+ "title": "the dispatch changes after its labels were reviewed, and the help coverage keeps trusting labels nobody re-read",
109
+ "subject": "run.sh",
110
+ "find": [" -h|--help|help|\"\")"],
111
+ "replace": [" # an unreviewed edit inside the dispatch\n -h|--help|help|\"\")"],
112
+ "gate": ["bash", "run.sh", "check-install-surface"],
113
+ "timeoutSeconds": 120,
114
+ "signature": "[QK:CLI-HELP-DISPATCH-REVIEWED]",
115
+ "signatureSource": "scripts/check-install-surface.ts"
116
+ },
117
+ {
118
+ "claim": "CLI-HELP-REAL-OWNER",
119
+ "title": "the gate inventory goes back to reading definition-shaped text, so a gate deleted from run.sh but left in a heredoc still counts as a command and keeps its description",
120
+ "subject": "scripts/check-install-surface.ts",
121
+ "find": ["\t\t\tconst names = new Set<string>();"],
122
+ "replace": [
123
+ "\t\t\tconst names = new Set<string>(\n\t\t\t\t[...text.matchAll(/^((?:check|smoke)_[a-z0-9_]+)\\(\\)\\s*\\{/gm)].map((m) => (m[1] as string).replace(/_/g, \"-\")),\n\t\t\t);"
124
+ ],
125
+ "gate": ["bash", "run.sh", "check-install-surface"],
126
+ "timeoutSeconds": 120,
127
+ "signature": "[QK:CLI-HELP-REAL-OWNER]",
128
+ "signatureSource": "scripts/check-install-surface.ts"
129
+ },
130
+ {
131
+ "claim": "CLI-HELP-AMENDMENTS",
132
+ "title": "the tool count goes back to eight, a number the bridge has not shipped since entwurf_callback joined",
133
+ "subject": "ENTWURF-CLI.json",
134
+ "find": ["EXACTLY the nine shipped garden verbs"],
135
+ "replace": ["EXACTLY the eight shipped garden verbs"],
136
+ "gate": ["bash", "run.sh", "check-install-surface"],
137
+ "timeoutSeconds": 120,
138
+ "signature": "[QK:CLI-HELP-AMENDMENTS]",
139
+ "signatureSource": "scripts/check-install-surface.ts"
140
+ },
141
+ {
142
+ "claim": "CLI-HELP-PREFLIGHT-PLACEMENT",
143
+ "title": "a heredoc lands between the help preflight and the dispatch case, where the text pin no longer watches",
144
+ "subject": "run.sh",
145
+ "find": [" exec node \"$REPO_DIR/scripts/cli-help.mjs\" --command \"$cmd\"\nfi\n"],
146
+ "replace": [" exec node \"$REPO_DIR/scripts/cli-help.mjs\" --command \"$cmd\"\nfi\n: <<'NOTE'\nNOTE\n"],
147
+ "gate": ["bash", "run.sh", "check-install-surface"],
148
+ "timeoutSeconds": 120,
149
+ "signature": "[QK:CLI-HELP-PREFLIGHT-PLACEMENT]",
150
+ "signatureSource": "scripts/check-install-surface.ts"
151
+ },
152
+ {
153
+ "claim": "CLI-HELP-COMMAND",
154
+ "title": "`<command> --help` prints the whole root page instead of that command's own help",
155
+ "subject": "run.sh",
156
+ "find": [" exec node \"$REPO_DIR/scripts/cli-help.mjs\" --command \"$cmd\""],
157
+ "replace": [" exec node \"$REPO_DIR/scripts/cli-help.mjs\""],
158
+ "gate": ["bash", "run.sh", "check-install-surface"],
159
+ "timeoutSeconds": 120,
160
+ "signature": "[QK:CLI-HELP-COMMAND]",
161
+ "signatureSource": "scripts/check-install-surface.ts"
162
+ },
163
+ {
164
+ "claim": "CLI-HELP-NO-DISPATCH",
165
+ "title": "the preflight stops catching `<command> --help`, so asking an argv-ignoring command for help runs it",
166
+ "subject": "run.sh",
167
+ "find": ["elif [ \"$#\" -ge 2 ] && { [ \"$2\" = -h ] || [ \"$2\" = --help ]; } \\"],
168
+ "replace": ["elif false \\"],
169
+ "gate": ["bash", "run.sh", "check-install-surface"],
170
+ "timeoutSeconds": 120,
171
+ "signature": "[QK:CLI-HELP-NO-DISPATCH]",
172
+ "signatureSource": "scripts/check-install-surface.ts"
173
+ },
174
+ {
175
+ "claim": "CLI-HELP-FORMS",
176
+ "title": "`entwurf help <command>` looks up the word help instead of the command it names",
177
+ "subject": "run.sh",
178
+ "find": ["--name \"$2\""],
179
+ "replace": ["--name \"$cmd\""],
180
+ "gate": ["bash", "run.sh", "check-install-surface"],
181
+ "timeoutSeconds": 120,
182
+ "signature": "[QK:CLI-HELP-FORMS]",
183
+ "signatureSource": "scripts/check-install-surface.ts"
184
+ },
185
+ {
186
+ "claim": "CLI-HELP-EXTRA-REFUSED",
187
+ "title": "a help flag followed by more argv is answered as help, guessing past what was typed",
188
+ "subject": "run.sh",
189
+ "find": [
190
+ " if [ \"$#\" -gt 2 ]; then\n echo 'entwurf: a help request takes nothing after -h/--help; nothing was run' >&2"
191
+ ],
192
+ "replace": [
193
+ " if false; then\n echo 'entwurf: a help request takes nothing after -h/--help; nothing was run' >&2"
194
+ ],
195
+ "gate": ["bash", "run.sh", "check-install-surface"],
196
+ "timeoutSeconds": 120,
197
+ "signature": "[QK:CLI-HELP-EXTRA-REFUSED]",
198
+ "signatureSource": "scripts/check-install-surface.ts"
199
+ },
200
+ {
201
+ "claim": "CLI-HELP-ALIAS-REFUSED",
202
+ "title": "`--help <command>` stops being refused and falls through to the dispatch",
203
+ "subject": "run.sh",
204
+ "find": ["elif { [ \"$cmd\" = -h ] || [ \"$cmd\" = --help ]; } && [ \"$#\" -ge 2 ]; then"],
205
+ "replace": ["elif false; then"],
206
+ "gate": ["bash", "run.sh", "check-install-surface"],
207
+ "timeoutSeconds": 120,
208
+ "signature": "[QK:CLI-HELP-ALIAS-REFUSED]",
209
+ "signatureSource": "scripts/check-install-surface.ts"
210
+ },
211
+ {
212
+ "claim": "CLI-HELP-VENDOR-PASSTHROUGH",
213
+ "title": "the preflight intercepts `entwurf pi --help`, so pi's own help is replaced by a refusal",
214
+ "subject": "run.sh",
215
+ "find": ["[ \"$cmd\" != pi ] && "],
216
+ "replace": [""],
217
+ "gate": ["bash", "run.sh", "check-install-surface"],
218
+ "timeoutSeconds": 120,
219
+ "signature": "[QK:CLI-HELP-VENDOR-PASSTHROUGH]",
220
+ "signatureSource": "scripts/check-install-surface.ts"
221
+ },
222
+ {
223
+ "claim": "CLI-HELP-NOT-HELP-POSITION",
224
+ "title": "the preflight treats --help anywhere in argv as a help request, rewriting commands whose own argv carries it",
225
+ "subject": "run.sh",
226
+ "find": ["{ [ \"$2\" = -h ] || [ \"$2\" = --help ]; }"],
227
+ "replace": ["[[ \" ${*:2} \" == *\" --help \"* ]]"],
228
+ "gate": ["bash", "run.sh", "check-install-surface"],
229
+ "timeoutSeconds": 120,
230
+ "signature": "[QK:CLI-HELP-NOT-HELP-POSITION]",
231
+ "signatureSource": "scripts/check-install-surface.ts"
232
+ },
233
+ {
234
+ "claim": "CLI-HELP-ONE-LINE",
235
+ "title": "an unknown name is printed raw, so a newline in it splits the one-line refusal",
236
+ "subject": "scripts/cli-help.mjs",
237
+ "find": ["no help for ${JSON.stringify(wanted)}"],
238
+ "replace": ["no help for ${wanted}"],
239
+ "gate": ["bash", "run.sh", "check-install-surface"],
240
+ "timeoutSeconds": 120,
241
+ "signature": "[QK:CLI-HELP-ONE-LINE]",
242
+ "signatureSource": "scripts/check-install-surface.ts"
243
+ },
244
+ {
245
+ "claim": "CLI-HELP-COMMAND-TRACE",
246
+ "title": "a command help asks git for checkout state before answering, starting a tool the description never needed",
247
+ "subject": "run.sh",
248
+ "find": [" exec node \"$REPO_DIR/scripts/cli-help.mjs\" --command \"$cmd\""],
249
+ "replace": [
250
+ " git -C \"$REPO_DIR\" rev-parse HEAD >/dev/null 2>&1 || true\n exec node \"$REPO_DIR/scripts/cli-help.mjs\" --command \"$cmd\""
251
+ ],
252
+ "gate": ["bash", "run.sh", "check-install-surface"],
253
+ "timeoutSeconds": 120,
254
+ "signature": "[QK:CLI-HELP-COMMAND-TRACE]",
255
+ "signatureSource": "scripts/check-install-surface.ts"
256
+ },
257
+ {
258
+ "claim": "CLI-HELP-DETAILS-ORACLE",
259
+ "title": "fresh-cut's longer help is reworded in the data and silently drifts from the text the verb shipped",
260
+ "subject": "ENTWURF-CLI.json",
261
+ "find": [" live dirs. No migration, no restore: the archive is forensic bytes only."],
262
+ "replace": [" live dirs. No migration, no restore: the archive is forensic only."],
263
+ "gate": ["bash", "run.sh", "check-install-surface"],
264
+ "timeoutSeconds": 120,
265
+ "signature": "[QK:CLI-HELP-DETAILS-ORACLE]",
266
+ "signatureSource": "scripts/check-install-surface.ts"
267
+ },
268
+ {
269
+ "claim": "CLI-HELP-EPIPE-QUIET",
270
+ "title": "a reader that stops early (`entwurf --help | head`) gets a node EPIPE stack trace on stderr",
271
+ "subject": "scripts/cli-help.mjs",
272
+ "find": ["\tif (err.code === \"EPIPE\") process.exit(0);"],
273
+ "replace": ["\tif (false) process.exit(0);"],
274
+ "gate": ["bash", "run.sh", "check-install-surface"],
275
+ "timeoutSeconds": 120,
276
+ "signature": "[QK:CLI-HELP-EPIPE-QUIET]",
277
+ "signatureSource": "scripts/check-install-surface.ts"
278
+ },
279
+ {
280
+ "claim": "CLI-HELP-METADATA-EXIT",
281
+ "title": "a broken help source exits 2, the same status as a refused help request, so a caller can no longer tell a damaged install from a typo",
282
+ "subject": "scripts/cli-help.mjs",
283
+ "find": ["\tprocess.exit(1);"],
284
+ "replace": ["\tprocess.exit(2);"],
285
+ "gate": ["bash", "run.sh", "check-install-surface"],
286
+ "timeoutSeconds": 120,
287
+ "signature": "[QK:CLI-HELP-METADATA-EXIT]",
288
+ "signatureSource": "scripts/check-install-surface.ts"
289
+ },
290
+ {
291
+ "claim": "CLI-HELP-EPIPE-EXIT",
292
+ "title": "the early-closed pipe is reported as a failure exit, so `set -o pipefail; entwurf --help | head` fails a script that only wanted the first lines",
293
+ "subject": "scripts/cli-help.mjs",
294
+ "find": ["\tif (err.code === \"EPIPE\") process.exit(0);"],
295
+ "replace": ["\tif (err.code === \"EPIPE\") process.exit(1);"],
296
+ "gate": ["bash", "run.sh", "check-install-surface"],
297
+ "timeoutSeconds": 120,
298
+ "signature": "[QK:CLI-HELP-EPIPE-EXIT]",
299
+ "signatureSource": "scripts/check-install-surface.ts"
300
+ },
301
+ {
302
+ "claim": "PRUNE-HELP-POINTER",
303
+ "title": "the prune leaf's --help and unknown-flag refusal point at another command's description, so an operator who followed them reads help for the wrong verb (#153)",
304
+ "subject": "scripts/meta-bridge-prune.ts",
305
+ "find": [
306
+ "\t\t\"meta-bridge-prune: see `entwurf help meta-bridge-prune` (from that checkout's root: `./run.sh help meta-bridge-prune`)\","
307
+ ],
308
+ "replace": [
309
+ "\t\t\"meta-bridge-prune: see `entwurf help meta-bridge-fresh-cut` (from that checkout's root: `./run.sh help meta-bridge-fresh-cut`)\","
310
+ ],
311
+ "gate": ["bash", "run.sh", "smoke-meta-prune"],
312
+ "timeoutSeconds": 120,
313
+ "signature": "[QK:PRUNE-HELP-POINTER]",
314
+ "signatureSource": "scripts/smoke-meta-prune.sh"
315
+ },
316
+ {
317
+ "claim": "CLI-HELP-PI-DESCRIBED",
318
+ "title": "pi's description drops the flag the launch adds, so `entwurf help pi` no longer says what the arm execs",
319
+ "subject": "ENTWURF-CLI.json",
320
+ "find": [
321
+ "\t\t\t\t\t\"summary\": \"#118: the MANAGED pi launch. exec()s the pi that `type -P` finds on PATH (a file, never a shell function or alias) in THIS terminal, with --entwurf-control added ahead of your argv, which passes through untouched. Refuses by name when ENTWURF_PI_LAUNCH_ACTIVE is non-empty (it exports that to the pi it starts), when no pi is on PATH (it launches the pi coding agent, it does not install one), or when that path is not an executable regular file\""
322
+ ],
323
+ "replace": [
324
+ "\t\t\t\t\t\"summary\": \"#118: the MANAGED pi launch. exec()s the pi that `type -P` finds on PATH (a file, never a shell function or alias) in THIS terminal, with your argv, which passes through untouched. Refuses by name when ENTWURF_PI_LAUNCH_ACTIVE is non-empty (it exports that to the pi it starts), when no pi is on PATH (it launches the pi coding agent, it does not install one), or when that path is not an executable regular file\""
325
+ ],
326
+ "gate": ["bash", "run.sh", "check-install-surface"],
327
+ "timeoutSeconds": 120,
328
+ "signature": "[QK:CLI-HELP-PI-DESCRIBED]",
329
+ "signatureSource": "scripts/check-install-surface.ts"
330
+ },
331
+ {
332
+ "claim": "CLI-HELP-ROOT-COMPACT",
333
+ "title": "the root page prints the whole catalog again, so a bare `entwurf` buries the few commands an operator needs under every gate",
334
+ "subject": "scripts/cli-help.mjs",
335
+ "find": ["\tprocess.stdout.write(`${(all ? out : compact).join(\"\\n\")}\\n`);"],
336
+ "replace": ["\tprocess.stdout.write(`${out.join(\"\\n\")}\\n`);"],
337
+ "gate": ["bash", "run.sh", "check-install-surface"],
338
+ "timeoutSeconds": 120,
339
+ "signature": "[QK:CLI-HELP-ROOT-COMPACT]",
340
+ "signatureSource": "scripts/check-install-surface.ts"
341
+ },
342
+ {
343
+ "claim": "CLI-HELP-ALL-ROUTE",
344
+ "title": "`entwurf help all` no longer reaches the catalog: it is read as help for a command named `all` and refused, so the full list has no door",
345
+ "subject": "run.sh",
346
+ "find": ["if [ \"$cmd\" = help ] && [ \"$#\" -eq 2 ] && [ \"$2\" = all ]; then"],
347
+ "replace": ["if false; then"],
348
+ "gate": ["bash", "run.sh", "check-install-surface"],
349
+ "timeoutSeconds": 120,
350
+ "signature": "[QK:CLI-HELP-ALL-ROUTE]",
351
+ "signatureSource": "scripts/check-install-surface.ts"
352
+ },
353
+ {
354
+ "claim": "CLI-HELP-ROOT-NAMES-REAL",
355
+ "title": "the renderer stops checking that an example names a described command, so the root page advertises a command that does not exist",
356
+ "subject": "scripts/cli-help.mjs",
357
+ "find": ["\tif (!helpItself && !entries.has(named))"],
358
+ "replace": ["\tif (false)"],
359
+ "gate": ["bash", "run.sh", "check-install-surface"],
360
+ "timeoutSeconds": 120,
361
+ "signature": "[QK:CLI-HELP-ROOT-NAMES-REAL]",
362
+ "signatureSource": "scripts/check-install-surface.ts"
363
+ },
364
+ {
365
+ "claim": "CLI-HELP-TOPIC-BYTES",
366
+ "title": "a guide topic loses the blank line under its title, so `entwurf help team` no longer prints the reviewed page",
367
+ "subject": "scripts/cli-help.mjs",
368
+ "find": ["\t\tprocess.stdout.write(`${[topic.title, \"\", ...topic.lines].join(\"\\n\")}\\n`);"],
369
+ "replace": ["\t\tprocess.stdout.write(`${[topic.title, ...topic.lines].join(\"\\n\")}\\n`);"],
370
+ "gate": ["bash", "run.sh", "check-install-surface"],
371
+ "timeoutSeconds": 120,
372
+ "signature": "[QK:CLI-HELP-TOPIC-BYTES]",
373
+ "signatureSource": "scripts/check-install-surface.ts"
374
+ },
375
+ {
376
+ "claim": "CLI-HELP-TOPIC-ROUTE",
377
+ "title": "`entwurf help <name>` asks the renderer in the commands-only mode, so the guides have no door and `help team` is refused",
378
+ "subject": "run.sh",
379
+ "find": ["--name \"$2\""],
380
+ "replace": ["--command \"$2\""],
381
+ "gate": ["bash", "run.sh", "check-install-surface"],
382
+ "timeoutSeconds": 120,
383
+ "signature": "[QK:CLI-HELP-TOPIC-ROUTE]",
384
+ "signatureSource": "scripts/check-install-surface.ts"
385
+ },
386
+ {
387
+ "claim": "CLI-HELP-TOPIC-NOT-COMMAND",
388
+ "title": "a guide topic answers `<topic> --help` as if it were a command, so asking about running `team` prints a page instead of the refusal",
389
+ "subject": "scripts/cli-help.mjs",
390
+ "find": ["const topicsToo = argv[0] === \"--name\";"],
391
+ "replace": ["const topicsToo = true;"],
392
+ "gate": ["bash", "run.sh", "check-install-surface"],
393
+ "timeoutSeconds": 120,
394
+ "signature": "[QK:CLI-HELP-TOPIC-NOT-COMMAND]",
395
+ "signatureSource": "scripts/check-install-surface.ts"
396
+ },
397
+ {
398
+ "claim": "CLI-HELP-TOPIC-DISJOINT",
399
+ "title": "the renderer stops checking topic names, so a guide can take a command's name, `all` or another guide's and one word answers with two pages",
400
+ "subject": "scripts/cli-help.mjs",
401
+ "find": ["\tif (name === \"all\" || entries.has(name) || topics.has(name))"],
402
+ "replace": ["\tif (false)"],
403
+ "gate": ["bash", "run.sh", "check-install-surface"],
404
+ "timeoutSeconds": 120,
405
+ "signature": "[QK:CLI-HELP-TOPIC-DISJOINT]",
406
+ "signatureSource": "scripts/check-install-surface.ts"
407
+ },
408
+ {
409
+ "claim": "CLI-HELP-TOPIC-SHIPPED",
410
+ "title": "team.json.example leaves the package files, so `entwurf help team` sends an installed reader to a file the install does not have",
411
+ "subject": "package.json",
412
+ "find": ["\t\t\"ENTWURF-CLI.json\",", "\t\t\"team.json.example\","],
413
+ "replace": ["\t\t\"ENTWURF-CLI.json\","],
414
+ "gate": ["bash", "run.sh", "check-install-surface"],
415
+ "timeoutSeconds": 120,
416
+ "signature": "[QK:CLI-HELP-TOPIC-SHIPPED]",
417
+ "signatureSource": "scripts/check-install-surface.ts"
418
+ }
419
+ ]
420
+ }