@prestyj/cli 5.2.0 → 5.3.1

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 (192) hide show
  1. package/dist/app-sidecar.js +856 -91
  2. package/dist/app-sidecar.js.map +1 -1
  3. package/dist/core/agent-session-compaction.test.js +89 -0
  4. package/dist/core/agent-session-compaction.test.js.map +1 -1
  5. package/dist/core/agent-session-queue.test.d.ts +2 -0
  6. package/dist/core/agent-session-queue.test.d.ts.map +1 -0
  7. package/dist/core/agent-session-queue.test.js +122 -0
  8. package/dist/core/agent-session-queue.test.js.map +1 -0
  9. package/dist/core/agent-session.d.ts +79 -3
  10. package/dist/core/agent-session.d.ts.map +1 -1
  11. package/dist/core/agent-session.js +268 -47
  12. package/dist/core/agent-session.js.map +1 -1
  13. package/dist/core/autopilot-cycle.d.ts +119 -0
  14. package/dist/core/autopilot-cycle.d.ts.map +1 -0
  15. package/dist/core/autopilot-cycle.js +119 -0
  16. package/dist/core/autopilot-cycle.js.map +1 -0
  17. package/dist/core/autopilot-cycle.test.d.ts +2 -0
  18. package/dist/core/autopilot-cycle.test.d.ts.map +1 -0
  19. package/dist/core/autopilot-cycle.test.js +375 -0
  20. package/dist/core/autopilot-cycle.test.js.map +1 -0
  21. package/dist/core/autopilot-gate.d.ts +109 -0
  22. package/dist/core/autopilot-gate.d.ts.map +1 -0
  23. package/dist/core/autopilot-gate.js +205 -0
  24. package/dist/core/autopilot-gate.js.map +1 -0
  25. package/dist/core/autopilot-gate.test.d.ts +2 -0
  26. package/dist/core/autopilot-gate.test.d.ts.map +1 -0
  27. package/dist/core/autopilot-gate.test.js +295 -0
  28. package/dist/core/autopilot-gate.test.js.map +1 -0
  29. package/dist/core/autopilot-verdict.d.ts +20 -2
  30. package/dist/core/autopilot-verdict.d.ts.map +1 -1
  31. package/dist/core/autopilot-verdict.js +94 -3
  32. package/dist/core/autopilot-verdict.js.map +1 -1
  33. package/dist/core/autopilot-verdict.test.js +73 -0
  34. package/dist/core/autopilot-verdict.test.js.map +1 -1
  35. package/dist/core/bash-spawn-benchmark.d.ts +2 -0
  36. package/dist/core/bash-spawn-benchmark.d.ts.map +1 -0
  37. package/dist/core/bash-spawn-benchmark.js +139 -0
  38. package/dist/core/bash-spawn-benchmark.js.map +1 -0
  39. package/dist/core/hashline-edit-benchmark.d.ts +33 -1
  40. package/dist/core/hashline-edit-benchmark.d.ts.map +1 -1
  41. package/dist/core/hashline-edit-benchmark.js +193 -21
  42. package/dist/core/hashline-edit-benchmark.js.map +1 -1
  43. package/dist/core/hashline-edit-benchmark.test.js +51 -2
  44. package/dist/core/hashline-edit-benchmark.test.js.map +1 -1
  45. package/dist/core/json-mode-flag-parity.test.d.ts +2 -0
  46. package/dist/core/json-mode-flag-parity.test.d.ts.map +1 -0
  47. package/dist/core/json-mode-flag-parity.test.js +66 -0
  48. package/dist/core/json-mode-flag-parity.test.js.map +1 -0
  49. package/dist/core/mcp/deferred-catalog.d.ts +28 -0
  50. package/dist/core/mcp/deferred-catalog.d.ts.map +1 -0
  51. package/dist/core/mcp/deferred-catalog.js +72 -0
  52. package/dist/core/mcp/deferred-catalog.js.map +1 -0
  53. package/dist/core/mcp/resolve-stdio.d.ts +19 -3
  54. package/dist/core/mcp/resolve-stdio.d.ts.map +1 -1
  55. package/dist/core/mcp/resolve-stdio.js +136 -5
  56. package/dist/core/mcp/resolve-stdio.js.map +1 -1
  57. package/dist/core/mcp/resolve-stdio.test.js +82 -1
  58. package/dist/core/mcp/resolve-stdio.test.js.map +1 -1
  59. package/dist/core/nolan-context.d.ts +43 -2
  60. package/dist/core/nolan-context.d.ts.map +1 -1
  61. package/dist/core/nolan-context.js +91 -8
  62. package/dist/core/nolan-context.js.map +1 -1
  63. package/dist/core/nolan-context.test.js +167 -5
  64. package/dist/core/nolan-context.test.js.map +1 -1
  65. package/dist/core/nolan-model.d.ts +46 -0
  66. package/dist/core/nolan-model.d.ts.map +1 -0
  67. package/dist/core/nolan-model.js +30 -0
  68. package/dist/core/nolan-model.js.map +1 -0
  69. package/dist/core/nolan-model.test.d.ts +2 -0
  70. package/dist/core/nolan-model.test.d.ts.map +1 -0
  71. package/dist/core/nolan-model.test.js +51 -0
  72. package/dist/core/nolan-model.test.js.map +1 -0
  73. package/dist/core/nolan-prompt.d.ts +5 -18
  74. package/dist/core/nolan-prompt.d.ts.map +1 -1
  75. package/dist/core/nolan-prompt.js +112 -19
  76. package/dist/core/nolan-prompt.js.map +1 -1
  77. package/dist/core/nolan-prompt.test.d.ts +2 -0
  78. package/dist/core/nolan-prompt.test.d.ts.map +1 -0
  79. package/dist/core/nolan-prompt.test.js +138 -0
  80. package/dist/core/nolan-prompt.test.js.map +1 -0
  81. package/dist/core/persistent-shell.d.ts +27 -0
  82. package/dist/core/persistent-shell.d.ts.map +1 -0
  83. package/dist/core/persistent-shell.js +150 -0
  84. package/dist/core/persistent-shell.js.map +1 -0
  85. package/dist/core/persistent-shell.test.d.ts +2 -0
  86. package/dist/core/persistent-shell.test.d.ts.map +1 -0
  87. package/dist/core/persistent-shell.test.js +84 -0
  88. package/dist/core/persistent-shell.test.js.map +1 -0
  89. package/dist/core/process-manager-dev-server-repro.test.js +34 -6
  90. package/dist/core/process-manager-dev-server-repro.test.js.map +1 -1
  91. package/dist/core/progress/engine.d.ts +23 -0
  92. package/dist/core/progress/engine.d.ts.map +1 -0
  93. package/dist/core/progress/engine.js +131 -0
  94. package/dist/core/progress/engine.js.map +1 -0
  95. package/dist/core/progress/engine.test.d.ts +2 -0
  96. package/dist/core/progress/engine.test.d.ts.map +1 -0
  97. package/dist/core/progress/engine.test.js +136 -0
  98. package/dist/core/progress/engine.test.js.map +1 -0
  99. package/dist/core/progress/git-xp.d.ts +16 -0
  100. package/dist/core/progress/git-xp.d.ts.map +1 -0
  101. package/dist/core/progress/git-xp.js +106 -0
  102. package/dist/core/progress/git-xp.js.map +1 -0
  103. package/dist/core/progress/git-xp.test.d.ts +2 -0
  104. package/dist/core/progress/git-xp.test.d.ts.map +1 -0
  105. package/dist/core/progress/git-xp.test.js +88 -0
  106. package/dist/core/progress/git-xp.test.js.map +1 -0
  107. package/dist/core/progress/ranks.d.ts +21 -0
  108. package/dist/core/progress/ranks.d.ts.map +1 -0
  109. package/dist/core/progress/ranks.js +141 -0
  110. package/dist/core/progress/ranks.js.map +1 -0
  111. package/dist/core/progress/ranks.test.d.ts +2 -0
  112. package/dist/core/progress/ranks.test.d.ts.map +1 -0
  113. package/dist/core/progress/ranks.test.js +59 -0
  114. package/dist/core/progress/ranks.test.js.map +1 -0
  115. package/dist/core/progress/rebuild.d.ts +7 -0
  116. package/dist/core/progress/rebuild.d.ts.map +1 -0
  117. package/dist/core/progress/rebuild.js +106 -0
  118. package/dist/core/progress/rebuild.js.map +1 -0
  119. package/dist/core/progress/rebuild.test.d.ts +2 -0
  120. package/dist/core/progress/rebuild.test.d.ts.map +1 -0
  121. package/dist/core/progress/rebuild.test.js +72 -0
  122. package/dist/core/progress/rebuild.test.js.map +1 -0
  123. package/dist/core/progress/store.d.ts +35 -0
  124. package/dist/core/progress/store.d.ts.map +1 -0
  125. package/dist/core/progress/store.js +200 -0
  126. package/dist/core/progress/store.js.map +1 -0
  127. package/dist/core/progress/store.test.d.ts +2 -0
  128. package/dist/core/progress/store.test.d.ts.map +1 -0
  129. package/dist/core/progress/store.test.js +108 -0
  130. package/dist/core/progress/store.test.js.map +1 -0
  131. package/dist/core/progress/types.d.ts +108 -0
  132. package/dist/core/progress/types.d.ts.map +1 -0
  133. package/dist/core/progress/types.js +3 -0
  134. package/dist/core/progress/types.js.map +1 -0
  135. package/dist/core/project-discovery.d.ts.map +1 -1
  136. package/dist/core/project-discovery.js +40 -9
  137. package/dist/core/project-discovery.js.map +1 -1
  138. package/dist/core/project-discovery.test.d.ts +2 -0
  139. package/dist/core/project-discovery.test.d.ts.map +1 -0
  140. package/dist/core/project-discovery.test.js +104 -0
  141. package/dist/core/project-discovery.test.js.map +1 -0
  142. package/dist/core/session-history.d.ts +51 -0
  143. package/dist/core/session-history.d.ts.map +1 -0
  144. package/dist/core/session-history.js +156 -0
  145. package/dist/core/session-history.js.map +1 -0
  146. package/dist/core/session-history.test.d.ts +2 -0
  147. package/dist/core/session-history.test.d.ts.map +1 -0
  148. package/dist/core/session-history.test.js +101 -0
  149. package/dist/core/session-history.test.js.map +1 -0
  150. package/dist/core/session-manager.d.ts +34 -0
  151. package/dist/core/session-manager.d.ts.map +1 -1
  152. package/dist/core/session-manager.js +67 -0
  153. package/dist/core/session-manager.js.map +1 -1
  154. package/dist/core/session-manager.test.js +140 -1
  155. package/dist/core/session-manager.test.js.map +1 -1
  156. package/dist/core/settings-manager.d.ts +1 -0
  157. package/dist/core/settings-manager.d.ts.map +1 -1
  158. package/dist/core/settings-manager.js +4 -0
  159. package/dist/core/settings-manager.js.map +1 -1
  160. package/dist/core/speed-benchmark.test.js +2 -3
  161. package/dist/core/speed-benchmark.test.js.map +1 -1
  162. package/dist/system-prompt.d.ts.map +1 -1
  163. package/dist/system-prompt.js +12 -8
  164. package/dist/system-prompt.js.map +1 -1
  165. package/dist/system-prompt.test.js +15 -20
  166. package/dist/system-prompt.test.js.map +1 -1
  167. package/dist/tools/bash.d.ts +1 -0
  168. package/dist/tools/bash.d.ts.map +1 -1
  169. package/dist/tools/bash.js +27 -2
  170. package/dist/tools/bash.js.map +1 -1
  171. package/dist/tools/edit.d.ts +9 -2
  172. package/dist/tools/edit.d.ts.map +1 -1
  173. package/dist/tools/edit.js +91 -10
  174. package/dist/tools/edit.js.map +1 -1
  175. package/dist/tools/edit.test.js +97 -0
  176. package/dist/tools/edit.test.js.map +1 -1
  177. package/dist/tools/plan-mode.test.js +25 -0
  178. package/dist/tools/plan-mode.test.js.map +1 -1
  179. package/dist/tools/prompt-hints.d.ts.map +1 -1
  180. package/dist/tools/prompt-hints.js +3 -0
  181. package/dist/tools/prompt-hints.js.map +1 -1
  182. package/dist/tools/subagent.d.ts.map +1 -1
  183. package/dist/tools/subagent.js +24 -1
  184. package/dist/tools/subagent.js.map +1 -1
  185. package/dist/tools/tool-search.d.ts +15 -0
  186. package/dist/tools/tool-search.d.ts.map +1 -0
  187. package/dist/tools/tool-search.js +35 -0
  188. package/dist/tools/tool-search.js.map +1 -0
  189. package/dist/ui/hooks/useAgentLoop.d.ts.map +1 -1
  190. package/dist/ui/hooks/useAgentLoop.js +22 -9
  191. package/dist/ui/hooks/useAgentLoop.js.map +1 -1
  192. package/package.json +5 -5
@@ -2,7 +2,7 @@
2
2
  * Autopilot Nolan's verdict contract.
3
3
  *
4
4
  * In autopilot mode Nolan never talks to the user — he auto-reviews EZ Coder's
5
- * work and replies with exactly one of three machine-parseable verdicts. The
5
+ * work and replies with exactly one of four machine-parseable verdicts. The
6
6
  * first non-empty line carries the keyword; anything after is the payload.
7
7
  *
8
8
  * PROMPT
@@ -10,11 +10,27 @@
10
10
  *
11
11
  * ALL_CLEAR
12
12
  *
13
+ * IGNORE
14
+ *
13
15
  * HUMAN
14
16
  * <one short reason the human is needed>
15
17
  *
18
+ * ALL_CLEAR and IGNORE both stop the cycle with nothing left to do, but they
19
+ * mean different things to the UI: ALL_CLEAR is a verdict on real work ("GG
20
+ * Coder built/changed something and it checks out") and renders a one-line Nolan
21
+ * marker. IGNORE means the turn was never worth reviewing in the first place
22
+ * (small talk, a question, an ack, a mechanical operation with no code
23
+ * changes) — it renders NOTHING, not even a marker, so trivial turns don't
24
+ * spam the transcript with a Nolan bubble that adds no information.
25
+ *
16
26
  * Parsing is forgiving and safe-by-default: any reply we can't confidently map
17
- * to PROMPT or ALL_CLEAR becomes a HUMAN stop, never a blind loop.
27
+ * to PROMPT, ALL_CLEAR, or IGNORE becomes a HUMAN stop, never a blind loop.
28
+ *
29
+ * Recovery order for prose-then-keyword drift (Nolan writing commentary before
30
+ * the verdict despite the contract): bare trailing ALL_CLEAR/IGNORE → buried
31
+ * HUMAN → buried line-start PROMPT (uppercase, line-start only, so prose like
32
+ * "prompt the user" can never match). HUMAN wins over PROMPT when both appear
33
+ * — recovering a stop is always safe, recovering an action must lose ties.
18
34
  */
19
35
  /** Cap on the raw-reply text we echo back as a HUMAN reason when Nolan's output
20
36
  * is unrecognized — keeps a garbage/huge reply from bloating the transcript. */
@@ -37,6 +53,37 @@ function cap(text, max = RAW_REASON_CAP) {
37
53
  return text;
38
54
  return `${text.slice(0, max)} […${text.length - max} more chars]`;
39
55
  }
56
+ /** Same keyword normalization as the primary line check: uppercase, drop a
57
+ * trailing colon/period, collapse "ALL CLEAR" → "ALL_CLEAR". */
58
+ function normalizeKeywordLine(line) {
59
+ return line
60
+ .trim()
61
+ .toUpperCase()
62
+ .replace(/[:.]+\s*$/, "")
63
+ .trim()
64
+ .replace(/\s+/g, "_");
65
+ }
66
+ /**
67
+ * Fallback for when Nolan ignores the "keyword-first, nothing before it"
68
+ * instruction and buries a bare ALL_CLEAR/IGNORE/SKIP line after a recap or
69
+ * explanation (a real drift pattern models fall into despite the system
70
+ * prompt). Only matches a line that is EXACTLY one of these bare keywords.
71
+ * PROMPT/HUMAN carry payloads and get their own dedicated recovery passes in
72
+ * parseAutopilotVerdict. Returns the LAST such line (the verdict
73
+ * conventionally lands at the end of the drift), or null if none/ambiguous
74
+ * multiple different keywords are present.
75
+ */
76
+ function findTrailingBareVerdict(lines) {
77
+ let found = null;
78
+ for (const line of lines) {
79
+ const normalized = normalizeKeywordLine(line);
80
+ if (normalized === "ALL_CLEAR")
81
+ found = "all_clear";
82
+ else if (normalized === "IGNORE" || normalized === "SKIP")
83
+ found = "ignore";
84
+ }
85
+ return found;
86
+ }
40
87
  /**
41
88
  * Parse Autopilot Nolan's raw reply into a verdict. Never throws.
42
89
  */
@@ -66,6 +113,13 @@ export function parseAutopilotVerdict(reply) {
66
113
  if (collapsed === "ALL_CLEAR" || collapsed.startsWith("ALL_CLEAR")) {
67
114
  return { kind: "all_clear" };
68
115
  }
116
+ // IGNORE / SKIP: the turn wasn't real work — nothing to say, nothing to show.
117
+ if (collapsed === "IGNORE" ||
118
+ collapsed.startsWith("IGNORE") ||
119
+ collapsed === "SKIP" ||
120
+ collapsed.startsWith("SKIP")) {
121
+ return { kind: "ignore" };
122
+ }
69
123
  if (collapsed === "PROMPT" || collapsed.startsWith("PROMPT")) {
70
124
  // Prefer the body on the following lines; if the keyword line itself carried
71
125
  // inline text after "PROMPT:", fall back to that.
@@ -87,7 +141,44 @@ export function parseAutopilotVerdict(reply) {
87
141
  }
88
142
  return { kind: "human", reason: cap(reason) || DEFAULT_HUMAN_REASON };
89
143
  }
90
- // Unrecognized stop and ask the human, echoing the raw reply for context.
144
+ // Unrecognized first line before giving up, check for a bare verdict Nolan
145
+ // buried later in the reply (prose-then-keyword drift). This is the exact
146
+ // shape that used to leak raw commentary + "ALL_CLEAR" into a HUMAN bubble
147
+ // instead of rendering the normal all-clear/ignore marker.
148
+ const trailing = findTrailingBareVerdict(lines);
149
+ if (trailing === "all_clear")
150
+ return { kind: "all_clear" };
151
+ if (trailing === "ignore")
152
+ return { kind: "ignore" };
153
+ // A buried bare HUMAN line (Nolan wrote his reasoning first, THEN the verdict).
154
+ // Take the lines after the LAST exact-"HUMAN" line as the reason and drop the
155
+ // leading prose. Safe to recover unlike a buried PROMPT: HUMAN stops the cycle
156
+ // either way, so this can't trigger autonomous action — it only keeps Nolan's
157
+ // internal reasoning out of the human-facing reason bubble (the drift that
158
+ // dumped his whole recap into the transcript alongside the real reason).
159
+ for (let i = lines.length - 1; i >= 0; i--) {
160
+ if (normalizeKeywordLine(lines[i]) === "HUMAN") {
161
+ const reason = lines
162
+ .slice(i + 1)
163
+ .join("\n")
164
+ .trim();
165
+ return { kind: "human", reason: cap(reason) || DEFAULT_HUMAN_REASON };
166
+ }
167
+ }
168
+ // Buried PROMPT (the drift that used to dump a valid runnable prompt into a
169
+ // HUMAN bubble): recover a line that STARTS with the uppercase keyword and
170
+ // re-parse from there, so both `PROMPT <inline body>` and `PROMPT\n<body>`
171
+ // shapes work. Uppercase + line-start (never mid-line, never lowercase)
172
+ // keeps prose like "prompt the user" or "a prompt for EZ Coder" from ever
173
+ // matching. Takes the LAST such line, and runs AFTER the HUMAN recovery so
174
+ // a reply carrying both stops instead of acting.
175
+ const BURIED_PROMPT_RE = /^PROMPT(?=$|[\s:.,])/;
176
+ for (let i = lines.length - 1; i >= 0; i--) {
177
+ if (BURIED_PROMPT_RE.test(lines[i].trim())) {
178
+ return parseAutopilotVerdict(lines.slice(i).join("\n"));
179
+ }
180
+ }
181
+ // Truly unrecognized → stop and ask the human, echoing the raw reply for context.
91
182
  return { kind: "human", reason: cap(raw) };
92
183
  }
93
184
  //# sourceMappingURL=autopilot-verdict.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"autopilot-verdict.js","sourceRoot":"","sources":["../../src/core/autopilot-verdict.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"autopilot-verdict.js","sourceRoot":"","sources":["../../src/core/autopilot-verdict.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,16 @@ describe("parseAutopilotVerdict", () => {
8
8
  expect(parseAutopilotVerdict("all clear")).toEqual({ kind: "all_clear" });
9
9
  expect(parseAutopilotVerdict("All Clear\nlooks good")).toEqual({ kind: "all_clear" });
10
10
  });
11
+ it("parses IGNORE", () => {
12
+ expect(parseAutopilotVerdict("IGNORE")).toEqual({ kind: "ignore" });
13
+ });
14
+ it("parses fuzzy IGNORE (lowercase, trailing colon, extra text)", () => {
15
+ expect(parseAutopilotVerdict("ignore")).toEqual({ kind: "ignore" });
16
+ expect(parseAutopilotVerdict("Ignore:\nnothing to review")).toEqual({ kind: "ignore" });
17
+ });
18
+ it("parses SKIP as an alias for IGNORE", () => {
19
+ expect(parseAutopilotVerdict("SKIP")).toEqual({ kind: "ignore" });
20
+ });
11
21
  it("parses PROMPT with a multi-line body", () => {
12
22
  const reply = "PROMPT\nAdd a test for the login flow.\nRun it and confirm it passes.";
13
23
  expect(parseAutopilotVerdict(reply)).toEqual({
@@ -76,5 +86,68 @@ describe("parseAutopilotVerdict", () => {
76
86
  it("skips leading blank lines before the keyword", () => {
77
87
  expect(parseAutopilotVerdict("\n\nALL_CLEAR")).toEqual({ kind: "all_clear" });
78
88
  });
89
+ it("recovers ALL_CLEAR when Nolan adds commentary before a trailing bare keyword line", () => {
90
+ const reply = "The label is now a plain non-clickable <span>, model name is the separate " +
91
+ "clickable button. Matches the request exactly. Typecheck passed.\nALL_CLEAR";
92
+ expect(parseAutopilotVerdict(reply)).toEqual({ kind: "all_clear" });
93
+ });
94
+ it("recovers IGNORE from a trailing bare keyword line after commentary", () => {
95
+ const reply = "Just a formatting fix, nothing to review here.\nIGNORE";
96
+ expect(parseAutopilotVerdict(reply)).toEqual({ kind: "ignore" });
97
+ });
98
+ it("recovers a buried PROMPT with the body on following lines", () => {
99
+ const reply = "Some commentary about the change.\nPROMPT\nFix the bug.";
100
+ expect(parseAutopilotVerdict(reply)).toEqual({ kind: "prompt", body: "Fix the bug." });
101
+ });
102
+ it("recovers a buried PROMPT with an inline body (the real drift shape)", () => {
103
+ // The exact drift that stalled a live autopilot cycle: reasoning prose
104
+ // first, then `PROMPT <body>` on one line — used to parse as a HUMAN stop
105
+ // and dump the whole reply into the chat as a Nolan bubble.
106
+ const reply = "The diagnosis is solid and confirmed on disk. The fix is mechanically " +
107
+ "implied by the original ask. Safe to proceed without new user input.\n" +
108
+ "PROMPT Apply the fix: guard AgentSession.compact() on this.opts.transient.";
109
+ const v = parseAutopilotVerdict(reply);
110
+ expect(v.kind).toBe("prompt");
111
+ if (v.kind === "prompt") {
112
+ expect(v.body).toBe("Apply the fix: guard AgentSession.compact() on this.opts.transient.");
113
+ }
114
+ });
115
+ it("never matches lowercase or mid-line 'prompt' prose as a buried PROMPT", () => {
116
+ // Buried recovery is uppercase + line-start only — casual prose mentioning
117
+ // "prompt" after an unrecognized first line must stay a HUMAN stop.
118
+ expect(parseAutopilotVerdict("Waiting on input.\nprompt the user for their API key first.").kind).toBe("human");
119
+ expect(parseAutopilotVerdict("Unclear ask.\nWe should write a prompt for EZ Coder here.").kind).toBe("human");
120
+ });
121
+ it("prefers a buried HUMAN over a buried PROMPT — stops beat actions on ties", () => {
122
+ const reply = "Recap first.\nPROMPT Fix the thing.\nHUMAN\nActually the user must decide.";
123
+ const v = parseAutopilotVerdict(reply);
124
+ expect(v.kind).toBe("human");
125
+ if (v.kind === "human")
126
+ expect(v.reason).toBe("Actually the user must decide.");
127
+ });
128
+ it("downgrades a buried bare PROMPT with no body to human", () => {
129
+ const v = parseAutopilotVerdict("Recap of what happened.\nPROMPT");
130
+ expect(v.kind).toBe("human");
131
+ });
132
+ it("recovers a buried HUMAN, dropping the leading reasoning prose", () => {
133
+ // Nolan drifted: he wrote his whole recap first, THEN the verdict. Recover the
134
+ // reason after the keyword and drop the prose — HUMAN stops either way.
135
+ const reply = "The screenshot shows a clean squared inward spiral that matches the " +
136
+ "reference. Tests green. EZ Coder asked whether to dress it up with art — " +
137
+ "that's a taste/product call the user should own.\nHUMAN\nStructural spiral " +
138
+ "is done; dressing it up with art is a taste call only you can make.";
139
+ const v = parseAutopilotVerdict(reply);
140
+ expect(v.kind).toBe("human");
141
+ if (v.kind === "human") {
142
+ expect(v.reason).toBe("Structural spiral is done; dressing it up with art is a taste call only you can make.");
143
+ expect(v.reason).not.toContain("The screenshot shows");
144
+ }
145
+ });
146
+ it("gives a buried bare HUMAN with no trailing reason the default reason", () => {
147
+ const v = parseAutopilotVerdict("Long recap of the work with no verdict payload.\nHUMAN");
148
+ expect(v.kind).toBe("human");
149
+ if (v.kind === "human")
150
+ expect(v.reason.length).toBeGreaterThan(0);
151
+ });
79
152
  });
80
153
  //# sourceMappingURL=autopilot-verdict.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"autopilot-verdict.test.js","sourceRoot":"","sources":["../../src/core/autopilot-verdict.test.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"autopilot-verdict.test.js","sourceRoot":"","sources":["../../src/core/autopilot-verdict.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=bash-spawn-benchmark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-spawn-benchmark.d.ts","sourceRoot":"","sources":["../../src/core/bash-spawn-benchmark.ts"],"names":[],"mappings":""}
@@ -0,0 +1,139 @@
1
+ /**
2
+ * Per-call spawn (what tools/bash.ts does today) vs a persistent shell session
3
+ * (what oh-my-pi's embedded "brush" bash gives them) — local measurement, no
4
+ * LLM calls needed.
5
+ *
6
+ * Strategy A — SPAWN (current): every command is `spawn("bash", ["-c", cmd])`,
7
+ * a fresh process with fresh env/cwd. Cost = fork/exec + shell startup per call.
8
+ *
9
+ * Strategy B — PERSISTENT: one long-lived `bash` process; commands are written
10
+ * to stdin and delimited with a sentinel echo. Cost ≈ pipe round-trip.
11
+ * Bonus property (qualitative): cd / env / shell state survive across calls.
12
+ *
13
+ * We run the same command list through both and report total + per-call wall
14
+ * time. Commands are trivial on purpose — we are measuring HARNESS overhead,
15
+ * not the commands themselves.
16
+ *
17
+ * Usage:
18
+ * npx tsx src/core/bash-spawn-benchmark.ts
19
+ *
20
+ * Env overrides:
21
+ * GG_BASH_BENCH_N (commands per strategy, default 30)
22
+ */
23
+ import { spawn } from "node:child_process";
24
+ import { randomUUID } from "node:crypto";
25
+ const COMMANDS = ["echo hello", "pwd", "ls / > /dev/null", "printf '%s' done", "true"];
26
+ function buildCommandList(n) {
27
+ const out = [];
28
+ for (let i = 0; i < n; i++)
29
+ out.push(COMMANDS[i % COMMANDS.length]);
30
+ return out;
31
+ }
32
+ // ── Strategy A: fresh spawn per call (mirrors tools/bash.ts) ──
33
+ function runSpawned(cmd) {
34
+ return new Promise((resolve, reject) => {
35
+ const start = performance.now();
36
+ const child = spawn("bash", ["-c", cmd], { stdio: ["ignore", "pipe", "pipe"] });
37
+ child.stdout.on("data", () => { });
38
+ child.stderr.on("data", () => { });
39
+ child.on("error", reject);
40
+ child.on("close", () => resolve(performance.now() - start));
41
+ });
42
+ }
43
+ // ── Strategy B: one persistent bash, sentinel-delimited ──
44
+ class PersistentShell {
45
+ child = spawn("bash", ["--norc", "--noprofile"], {
46
+ stdio: ["pipe", "pipe", "pipe"],
47
+ });
48
+ buffer = "";
49
+ waiter = null;
50
+ constructor() {
51
+ this.child.stdout.on("data", (d) => {
52
+ this.buffer += d.toString();
53
+ if (this.waiter && this.buffer.includes(this.waiter.sentinel)) {
54
+ const w = this.waiter;
55
+ this.waiter = null;
56
+ this.buffer = "";
57
+ w.resolve();
58
+ }
59
+ });
60
+ this.child.stderr.on("data", () => { });
61
+ }
62
+ run(cmd) {
63
+ const start = performance.now();
64
+ const sentinel = `__GG_DONE_${randomUUID()}__`;
65
+ return new Promise((resolve) => {
66
+ this.waiter = { sentinel, resolve: () => resolve(performance.now() - start) };
67
+ this.child.stdin.write(`${cmd}\necho ${sentinel}\n`);
68
+ });
69
+ }
70
+ /** Prove state persistence: cd + env var survive across run() calls. */
71
+ async statePersists() {
72
+ await this.run("cd /tmp && export GG_BENCH_STATE=alive");
73
+ const sentinel = `__GG_STATE_${randomUUID()}__`;
74
+ const out = await new Promise((resolve) => {
75
+ let acc = "";
76
+ const onData = (d) => {
77
+ acc += d.toString();
78
+ if (acc.includes(sentinel)) {
79
+ this.child.stdout.off("data", onData);
80
+ resolve(acc);
81
+ }
82
+ };
83
+ this.child.stdout.on("data", onData);
84
+ this.child.stdin.write(`pwd; echo "$GG_BENCH_STATE"; echo ${sentinel}\n`);
85
+ });
86
+ return out.includes("/tmp") && out.includes("alive");
87
+ }
88
+ close() {
89
+ this.child.stdin.end();
90
+ this.child.kill();
91
+ }
92
+ }
93
+ // ── Stats ──
94
+ function stats(samples) {
95
+ const sorted = [...samples].sort((a, b) => a - b);
96
+ const total = samples.reduce((s, x) => s + x, 0);
97
+ const at = (q) => sorted[Math.min(sorted.length - 1, Math.floor(q * sorted.length))];
98
+ return { total, mean: total / samples.length, p50: at(0.5), p95: at(0.95) };
99
+ }
100
+ function fmt(s) {
101
+ return (`total ${s.total.toFixed(0)}ms | mean ${s.mean.toFixed(1)}ms | ` +
102
+ `p50 ${s.p50.toFixed(1)}ms | p95 ${s.p95.toFixed(1)}ms`);
103
+ }
104
+ async function main() {
105
+ const n = Math.max(5, parseInt(process.env.GG_BASH_BENCH_N ?? "30", 10));
106
+ const cmds = buildCommandList(n);
107
+ console.log(`\n🐚 Bash harness overhead — ${n} commands per strategy\n`);
108
+ // Warm both paths once so first-touch costs don't skew either side.
109
+ await runSpawned("true");
110
+ const shell = new PersistentShell();
111
+ await shell.run("true");
112
+ const spawnTimes = [];
113
+ for (const c of cmds)
114
+ spawnTimes.push(await runSpawned(c));
115
+ const persistTimes = [];
116
+ for (const c of cmds)
117
+ persistTimes.push(await shell.run(c));
118
+ const persists = await shell.statePersists();
119
+ shell.close();
120
+ const a = stats(spawnTimes);
121
+ const b = stats(persistTimes);
122
+ console.log(`SPAWN-PER-CALL (current): ${fmt(a)}`);
123
+ console.log(`PERSISTENT SHELL (theirs): ${fmt(b)}`);
124
+ const saved = a.mean - b.mean;
125
+ console.log(`\nPer-call overhead saved: ${saved.toFixed(1)}ms ` +
126
+ `(${((saved / a.mean) * 100).toFixed(0)}% of mean call cost)`);
127
+ console.log(`State persistence across calls (cd/env): ${persists ? "YES" : "NO"}`);
128
+ console.log(`\nVerdict: persistent shell wins if per-call saving is meaningful at agent scale ` +
129
+ `(a long session runs hundreds of bash calls) AND state persistence is a UX win.\n`);
130
+ }
131
+ const isDirectRun = process.argv[1]?.endsWith("bash-spawn-benchmark.ts") ||
132
+ process.argv[1]?.endsWith("bash-spawn-benchmark.js");
133
+ if (isDirectRun) {
134
+ main().catch((err) => {
135
+ console.error("Benchmark failed:", err);
136
+ process.exit(1);
137
+ });
138
+ }
139
+ //# sourceMappingURL=bash-spawn-benchmark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bash-spawn-benchmark.js","sourceRoot":"","sources":["../../src/core/bash-spawn-benchmark.ts"],"names":[],"mappings":"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"}
@@ -21,11 +21,16 @@
21
21
  * the edit applied cleanly + produced the correct file, and an anchor-uniqueness
22
22
  * / safety check. Edits are graded deterministically — no second model needed.
23
23
  *
24
+ * The BASELINE apply path runs ezcoder's REAL edit ladder (fuzzy match +
25
+ * indent-flex + blank-edge strip + dotdotdots — the same edit-diff functions
26
+ * tools/edit.ts uses), so baseline numbers reflect what our tool actually
27
+ * recovers, not a naive exact-replace.
28
+ *
24
29
  * Usage:
25
30
  * npx tsx src/core/hashline-edit-benchmark.ts
26
31
  *
27
32
  * Env overrides:
28
- * GG_HL_PROVIDER / GG_HL_MODEL (default openai / gpt-5.5)
33
+ * GG_HL_PROVIDER / GG_HL_MODEL (default anthropic / claude-sonnet-5)
29
34
  * GG_HL_REPEAT (runs per task, default 1 — raise to average noise)
30
35
  */
31
36
  import { type AnchoredFile } from "./hashline.js";
@@ -38,8 +43,12 @@ export interface EditTask {
38
43
  mustContain: string[];
39
44
  /** Substrings that MUST still be present (unchanged anchors far from the edit). */
40
45
  mustPreserve: string[];
46
+ /** Optional extra validator for tasks where substring checks are too weak. */
47
+ validate?: (file: string) => boolean;
41
48
  }
42
49
  export declare function genFile(lines: number): string;
50
+ /** Near-identical handler blocks — uniqueness pressure for string matching. */
51
+ export declare function genRepetitiveFile(blocks: number): string;
43
52
  export declare function buildTasks(): EditTask[];
44
53
  export interface ApplyOutcome {
45
54
  applied: boolean;
@@ -49,7 +58,30 @@ export interface ApplyOutcome {
49
58
  parsedEdits: number;
50
59
  }
51
60
  export declare function stripFence(s: string): string;
61
+ /**
62
+ * Parse the model's JSON envelope, tolerating literal (unescaped) newlines and
63
+ * tabs inside string values. In production, edits arrive as STRUCTURED
64
+ * tool-call arguments — the JSON envelope is a benchmark artifact — so both
65
+ * strategies get the same repair to keep the comparison about the EDIT FORMAT,
66
+ * not about JSON string-escaping discipline.
67
+ */
68
+ export declare function parseEnvelope<T>(raw: string): T | null;
52
69
  export declare function checkAnchors(file: string, task: EditTask): boolean;
70
+ /**
71
+ * ezcoder's REAL apply ladder, mirroring tools/edit.ts:
72
+ * 1. exact + smart-quote/dash fuzzy
73
+ * 2. indent-flex
74
+ * 3. blank-edge strip, retry 1+2
75
+ * 4. dotdotdots elision
76
+ * Returns the new working buffer or a failure reason.
77
+ */
78
+ export declare function applyLadder(working: string, oldText: string, newText: string): {
79
+ ok: true;
80
+ working: string;
81
+ } | {
82
+ ok: false;
83
+ reason: "not_found" | "ambiguous";
84
+ };
53
85
  export declare function applyBaseline(raw: string, task: EditTask): ApplyOutcome;
54
86
  export declare function applyHashline(raw: string, task: EditTask, anchored: AnchoredFile): ApplyOutcome;
55
87
  //# sourceMappingURL=hashline-edit-benchmark.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"hashline-edit-benchmark.d.ts","sourceRoot":"","sources":["../../src/core/hashline-edit-benchmark.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAIH,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAI9D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mFAAmF;IACnF,YAAY,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqC7C;AAED,wBAAgB,UAAU,IAAI,QAAQ,EAAE,CAiBvC;AA2CD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAIlE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,YAAY,CA2BvE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,GAAG,YAAY,CAmC/F"}
1
+ {"version":3,"file":"hashline-edit-benchmark.d.ts","sourceRoot":"","sources":["../../src/core/hashline-edit-benchmark.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAIH,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,eAAe,CAAC;AAW9D,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;IACpB,gEAAgE;IAChE,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,mFAAmF;IACnF,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;CACtC;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAqC7C;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAmBxD;AAED,wBAAgB,UAAU,IAAI,QAAQ,EAAE,CAwDvC;AA2CD,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,wFAAwF;IACxF,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,CAM5C;AAED;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,IAAI,CAkDtD;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAKlE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,MAAM,GACd;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,WAAW,GAAG,WAAW,CAAA;CAAE,CAiClF;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,YAAY,CA0BvE;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,GAAG,YAAY,CAmC/F"}