pi-daddy 0.15.0 → 0.16.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 (66) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +27 -12
  3. package/dist/cli.js +0 -0
  4. package/dist/executor.d.ts +38 -0
  5. package/dist/executor.d.ts.map +1 -0
  6. package/dist/executor.js +93 -0
  7. package/dist/executor.js.map +1 -0
  8. package/dist/herdr-cli.d.ts +78 -0
  9. package/dist/herdr-cli.d.ts.map +1 -0
  10. package/dist/herdr-cli.js +113 -0
  11. package/dist/herdr-cli.js.map +1 -0
  12. package/dist/herdr-name.d.ts +37 -0
  13. package/dist/herdr-name.d.ts.map +1 -0
  14. package/dist/herdr-name.js +59 -0
  15. package/dist/herdr-name.js.map +1 -0
  16. package/dist/herdr-poll.d.ts +104 -0
  17. package/dist/herdr-poll.d.ts.map +1 -0
  18. package/dist/herdr-poll.js +150 -0
  19. package/dist/herdr-poll.js.map +1 -0
  20. package/dist/herdr-stage.d.ts +40 -0
  21. package/dist/herdr-stage.d.ts.map +1 -0
  22. package/dist/herdr-stage.js +54 -0
  23. package/dist/herdr-stage.js.map +1 -0
  24. package/dist/ledger-report.d.ts +18 -0
  25. package/dist/ledger-report.d.ts.map +1 -1
  26. package/dist/ledger-report.js +10 -0
  27. package/dist/ledger-report.js.map +1 -1
  28. package/dist/ledger.d.ts +17 -0
  29. package/dist/ledger.d.ts.map +1 -1
  30. package/dist/ledger.js +1 -0
  31. package/dist/ledger.js.map +1 -1
  32. package/dist/pane-reaper.d.ts +66 -4
  33. package/dist/pane-reaper.d.ts.map +1 -1
  34. package/dist/pane-reaper.js +131 -9
  35. package/dist/pane-reaper.js.map +1 -1
  36. package/dist/progress.d.ts +96 -0
  37. package/dist/progress.d.ts.map +1 -0
  38. package/dist/progress.js +167 -0
  39. package/dist/progress.js.map +1 -0
  40. package/dist/run-child.d.ts +27 -0
  41. package/dist/run-child.d.ts.map +1 -1
  42. package/dist/run-child.js +84 -7
  43. package/dist/run-child.js.map +1 -1
  44. package/dist/run-herdr.d.ts +41 -28
  45. package/dist/run-herdr.d.ts.map +1 -1
  46. package/dist/run-herdr.js +150 -167
  47. package/dist/run-herdr.js.map +1 -1
  48. package/extensions/delegation.ts +94 -2
  49. package/extensions/grants-command.ts +26 -1
  50. package/extensions/grants.ts +85 -163
  51. package/extensions/run-delegation.ts +70 -8
  52. package/extensions/session-report.ts +231 -0
  53. package/extensions/session.ts +63 -11
  54. package/extensions/tripwire.ts +44 -0
  55. package/package.json +17 -1
  56. package/src/executor.ts +122 -0
  57. package/src/herdr-cli.ts +125 -0
  58. package/src/herdr-name.ts +61 -0
  59. package/src/herdr-poll.ts +185 -0
  60. package/src/herdr-stage.ts +55 -0
  61. package/src/ledger-report.ts +21 -0
  62. package/src/ledger.ts +18 -0
  63. package/src/pane-reaper.ts +147 -9
  64. package/src/progress.ts +206 -0
  65. package/src/run-child.ts +96 -7
  66. package/src/run-herdr.ts +170 -174
package/dist/run-child.js CHANGED
@@ -9,7 +9,36 @@
9
9
  * It lives here, out of `extensions/grants.ts`, so it can be tested against real processes without pi.
10
10
  */
11
11
  import { spawn } from "node:child_process";
12
+ import { StringDecoder } from "node:string_decoder";
12
13
  import { parseBound } from "./propagation.js";
14
+ /**
15
+ * The longest prefix of `text` that fits in `budget` BYTES, never splitting a character.
16
+ *
17
+ * Both halves matter. Truncating by `String.prototype.slice` counts UTF-16 code units against a byte budget,
18
+ * which overruns by the encoding width of whatever the child printed. Truncating the *buffer* instead would
19
+ * respect the budget and split a multi-byte character or a surrogate pair, putting a lone `\ud83d` in the
20
+ * result. So the walk is by code POINT (`for…of` iterates code points, keeping surrogate pairs whole) and the
21
+ * budget is checked in bytes before each one is admitted.
22
+ *
23
+ * Exported for the test that feeds it CJK and emoji: an ASCII-only test cannot fail on any of this, which is
24
+ * exactly why the original defect survived a test named for it.
25
+ */
26
+ export function takeBytes(text, budget) {
27
+ if (budget <= 0)
28
+ return "";
29
+ if (Buffer.byteLength(text) <= budget)
30
+ return text;
31
+ let out = "";
32
+ let used = 0;
33
+ for (const character of text) {
34
+ const size = Buffer.byteLength(character);
35
+ if (used + size > budget)
36
+ break;
37
+ out += character;
38
+ used += size;
39
+ }
40
+ return out;
41
+ }
13
42
  /**
14
43
  * Operator override for the child wall-clock limit, in seconds.
15
44
  *
@@ -54,6 +83,9 @@ export function runChild(request) {
54
83
  settle({ code: null, text: "", truncated: false, timedOut: false, aborted: false, spawnError: String(error) });
55
84
  return;
56
85
  }
86
+ // One decoder for BOTH streams is deliberate: they are already interleaved into one `text`, and two
87
+ // decoders would each hold their own partial character, so a split byte could surface out of order.
88
+ const decoder = new StringDecoder("utf8");
57
89
  let text = "";
58
90
  let bytes = 0;
59
91
  let truncated = false;
@@ -67,21 +99,66 @@ export function runChild(request) {
67
99
  child.kill("SIGTERM");
68
100
  timers.push(setTimeout(() => child.kill("SIGKILL"), killGraceMs));
69
101
  };
102
+ /** How much of `text` the progress display has already been shown. */
103
+ let emittedUpTo = 0;
104
+ /**
105
+ * Stream whatever `text` has gained since the last call.
106
+ *
107
+ * **Derived from `text` rather than from the incoming chunk**, and that is the whole correctness argument:
108
+ * what gets streamed is then *by construction* a prefix of what gets returned, so the output cap bounds the
109
+ * parent's transcript exactly as it bounds the result. The first version emitted the raw chunk and pushed
110
+ * 1924 bytes through a 1024-byte cap on the truncating write — the cap bounded memory and not the screen
111
+ * it had just been extended to protect. Found by the test, not by reading it.
112
+ *
113
+ * Swallowing is deliberate: `onOutput` renders, and a renderer that throws must not become a way to kill a
114
+ * governed child. Nothing downstream depends on it having run.
115
+ */
116
+ const flush = () => {
117
+ if (!request.onOutput || text.length <= emittedUpTo)
118
+ return;
119
+ const chunk = text.slice(emittedUpTo);
120
+ emittedUpTo = text.length;
121
+ try {
122
+ request.onOutput(chunk);
123
+ }
124
+ catch {
125
+ /* display only */
126
+ }
127
+ };
70
128
  const capture = (chunk) => {
71
129
  if (truncated)
72
130
  return;
73
- const s = String(chunk);
74
- bytes += Buffer.byteLength(s);
75
- if (bytes > maxOutputBytes) {
76
- // Keep what fits, mark it, and stop the child: an unbounded producer must not be able to
77
- // exhaust the orchestrator's memory just because it was granted a tool that prints.
78
- text += s;
79
- text = text.slice(0, maxOutputBytes);
131
+ // **Decoded through a StringDecoder, not `String(chunk)`.** A pipe splits on byte boundaries, not
132
+ // character ones, so a multi-byte character straddling two `data` events was decoded as two invalid
133
+ // halves and became U+FFFD — in the child's ANSWER, not merely the display. Measured: 300,000 bytes of
134
+ // CJK produced **twelve** replacement characters, because 65536 % 3 == 1. Emoji happened to survive
135
+ // (65536 % 4 == 0), which is why width-dependent corruption went unnoticed. The decoder holds the
136
+ // partial bytes until the rest arrives.
137
+ const s = decoder.write(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
138
+ if (s.length === 0)
139
+ return;
140
+ const size = Buffer.byteLength(s);
141
+ if (bytes + size > maxOutputBytes) {
142
+ // Keep what fits, mark it, and stop the child: an unbounded producer must not be able to exhaust the
143
+ // orchestrator's memory just because it was granted a tool that prints.
144
+ //
145
+ // **Trimmed by BYTES, and that is a fix rather than a refinement.** This was
146
+ // `text.slice(0, maxOutputBytes)` — a count of UTF-16 code units against a budget measured in bytes,
147
+ // so any non-ASCII output overran the cap by its own encoding width: 300 bytes of CJK through a
148
+ // 100-byte cap, and a measured **2048 bytes through the real 1024 default**. It is the same defect as
149
+ // the 1924-byte one already fixed here, one layer down: that fix bounded the *unit* count, and the
150
+ // budget was never in units. An odd cap also split a surrogate pair, putting a lone `\ud83d` into
151
+ // both the transcript and the returned answer.
152
+ text += takeBytes(s, maxOutputBytes - bytes);
153
+ bytes = maxOutputBytes;
80
154
  truncated = true;
155
+ flush();
81
156
  stop();
82
157
  return;
83
158
  }
159
+ bytes += size;
84
160
  text += s;
161
+ flush();
85
162
  };
86
163
  child.stdout?.on("data", capture);
87
164
  child.stderr?.on("data", capture);
@@ -1 +1 @@
1
- {"version":3,"file":"run-child.js","sourceRoot":"","sources":["../src/run-child.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run-child.js","sourceRoot":"","sources":["../src/run-child.ts"],"names":[],"mappings":"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"}
@@ -21,12 +21,25 @@
21
21
  * child. Humans are not this project's threat model, but nothing here should be read as containing one.
22
22
  */
23
23
  import type { ChildRunResult } from "./run-child.ts";
24
- /** One herdr CLI invocation. Injectable so every rule below is testable without herdr installed. */
25
- export type HerdrExec = (args: string[]) => Promise<{
26
- code: number | null;
27
- stdout: string;
28
- stderr: string;
29
- }>;
24
+ import { type HerdrExec } from "./herdr-cli.ts";
25
+ /**
26
+ * Re-exported so importers of the executor still reach the protocol at the name they always used.
27
+ *
28
+ * Deliberate rather than lazy: `test/run-herdr.test.ts` imports `HerdrExec` from here and must pass
29
+ * **unmodified** across this extraction — that is the only available proof the move changed no behaviour.
30
+ */
31
+ export { type HerdrExec, parseReply } from "./herdr-cli.ts";
32
+ /** Re-exported: `splitSystemPrompt` moved to `./herdr-stage.ts` under the ceiling, its tests import it here. */
33
+ export { splitSystemPrompt, stageSystemPrompt } from "./herdr-stage.ts";
34
+ /** Re-exported: the name rules moved to `./herdr-name.ts` under the ceiling; tests import them here. */
35
+ export { uniqueAgentName } from "./herdr-name.ts";
36
+ /**
37
+ * Re-exported so `test/run-herdr.test.ts` and any importer keep reaching these where they always were.
38
+ *
39
+ * `POLL_INTERVAL_MS` and `newSuffix` moved to `./herdr-poll.ts` under the 400-line ceiling; the names are part
40
+ * of this module's surface and moving a file should not move an export.
41
+ */
42
+ export { DEFAULT_SNAPSHOT_LINES, POLL_INTERVAL_MS, readPane, tailLines, waitForSettled, type PollTarget } from "./herdr-poll.ts";
30
43
  export interface HerdrRunRequest {
31
44
  /** `planSpawn` args **without** the prompt — see `prompt`. */
32
45
  args: string[];
@@ -56,29 +69,29 @@ export interface HerdrRunRequest {
56
69
  */
57
70
  keepPane?: boolean;
58
71
  exec?: HerdrExec;
72
+ /**
73
+ * The pane's last few lines, re-reported every poll — a SNAPSHOT the consumer REPLACES, not appends.
74
+ *
75
+ * **Display only**, exactly as in `runChild`: the child's answer is still the returned `text`. Unlike
76
+ * `runChild`'s `onOutput`, this is not a stream: `agent read` returns a snapshot of a bounded terminal, and
77
+ * the previous append-shaped design produced an 89,000× amplification once a pane scrolled or passed the
78
+ * output cap. See `tailLines` in `./herdr-poll.ts`.
79
+ *
80
+ * Exceptions are swallowed; a renderer must not be able to break a governed run.
81
+ */
82
+ onSnapshot?: (lines: string[]) => void;
83
+ /** How many pane lines to report per poll. Defaults to `DEFAULT_SNAPSHOT_LINES`. */
84
+ snapshotLines?: number;
85
+ /**
86
+ * The pane id, reported as soon as `tab create` returns it.
87
+ *
88
+ * Separate from `onOutput` because it arrives once and arrives *early*: it is what lets the parent print a
89
+ * name a human can switch to **while the child is alive**, which is the whole point of the pane surviving.
90
+ */
91
+ onPane?: (paneId: string, agentName: string) => void;
92
+ /** Poll cadence override. Exists so tests do not wait `POLL_INTERVAL_MS` per state transition. */
93
+ pollIntervalMs?: number;
59
94
  }
60
- /**
61
- * Move a multi-line `--append-system-prompt` out of argv, because herdr cannot encode it.
62
- *
63
- * **Measured.** `herdr agent start` types the argv into the pane's shell, so a value containing newlines
64
- * is rejected outright: `invalid_agent_argument — agent arguments cannot be encoded safely for the target
65
- * shell`. A definition's `SKILL.md` body is always multi-line, so every `delegate({agent})` spawn would
66
- * fail on this path.
67
- *
68
- * pi accepts a **file path** there as readily as literal text (`resolvePromptInput` + `existsSync` in
69
- * `dist/core/resource-loader.js`), so the fix is to write the body to a temp file and pass its path — one
70
- * short, shell-safe argument.
71
- *
72
- * The split lives here rather than in `planSpawn` because the constraint is **herdr's**, not pi's: the
73
- * direct executor passes the same text inline with no trouble, and a plan builder that pre-emptively wrote
74
- * temp files for everybody would be paying one executor's tax on both paths.
75
- */
76
- export declare function splitSystemPrompt(args: string[]): {
77
- args: string[];
78
- systemPrompt?: string;
79
- };
80
- /** How often to poll `agent get` while waiting for the child to settle. */
81
- export declare const POLL_INTERVAL_MS = 750;
82
95
  /** How often to retry `agent start` while a freshly created pane is still reaching its shell prompt. */
83
96
  export declare const PANE_READY_POLL_MS = 300;
84
97
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"run-herdr.d.ts","sourceRoot":"","sources":["../src/run-herdr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAIrD,oGAAoG;AACpG,MAAM,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE7G,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG;IAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAAE,CAI3F;AAKD,2EAA2E;AAC3E,eAAO,MAAM,gBAAgB,MAAM,CAAC;AACpC,wGAAwG;AACxG,eAAO,MAAM,kBAAkB,MAAM,CAAC;AA8BtC;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA8HpF"}
1
+ {"version":3,"file":"run-herdr.d.ts","sourceRoot":"","sources":["../src/run-herdr.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAGH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,EAA2B,KAAK,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAKzE;;;;;GAKG;AACH,OAAO,EAAE,KAAK,SAAS,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAC5D,gHAAgH;AAChH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AACxE,wGAAwG;AACxG,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD;;;;;GAKG;AACH,OAAO,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,QAAQ,EAAE,SAAS,EAAE,cAAc,EAAE,KAAK,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAEjI,MAAM,WAAW,eAAe;IAC9B,8DAA8D;IAC9D,IAAI,EAAE,MAAM,EAAE,CAAC;IACf;;;;;;OAMG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,uFAAuF;IACvF,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;;;;;;OASG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC;IACvC,oFAAoF;IACpF,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACrD,kGAAkG;IAClG,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAGD,wGAAwG;AACxG,eAAO,MAAM,kBAAkB,MAAM,CAAC;AAGtC;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CA2MpF"}