@zhuxixi/pi-agent-board 0.5.2 → 0.6.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 (48) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/README.md +41 -3
  3. package/docs/superpowers/plans/2026-09-03-code-refs-pr-backlink-narrow.md +551 -0
  4. package/docs/superpowers/plans/2026-09-04-evidence-outputpreview.md +209 -0
  5. package/docs/superpowers/plans/2026-09-04-warm-host-reclaim.md +796 -0
  6. package/docs/superpowers/plans/2026-09-05-issue-13-drainnextfollowup-pty-probe.md +114 -0
  7. package/docs/superpowers/plans/2026-09-05-issue-38-windows-wezterm-ime-cursor.md +73 -0
  8. package/docs/superpowers/plans/2026-09-05-issue-39-truncate-codepoint-boundary.md +143 -0
  9. package/docs/superpowers/plans/2026-09-05-issue-61-mention-fallback-guards.md +226 -0
  10. package/docs/superpowers/plans/2026-09-05-issue-63-flaky-manual-completion.md +87 -0
  11. package/docs/superpowers/plans/2026-09-05-issue-64-changelog-release-helper.md +53 -0
  12. package/docs/superpowers/plans/2026-09-05-pty-host-stacking-sock-race.md +731 -0
  13. package/docs/superpowers/specs/2026-08-29-code-refs-badges-design.md +1 -1
  14. package/docs/superpowers/specs/2026-09-03-code-refs-pr-backlink-narrow-design.md +92 -0
  15. package/docs/superpowers/specs/2026-09-04-evidence-outputpreview-design.md +50 -0
  16. package/docs/superpowers/specs/2026-09-04-warm-host-reclaim-design.md +106 -0
  17. package/docs/superpowers/specs/2026-09-05-issue-13-drainnextfollowup-pty-probe-design.md +64 -0
  18. package/docs/superpowers/specs/2026-09-05-issue-38-windows-wezterm-ime-design.md +48 -0
  19. package/docs/superpowers/specs/2026-09-05-issue-39-truncate-codepoint-boundary-design.md +64 -0
  20. package/docs/superpowers/specs/2026-09-05-issue-61-mention-fallback-design.md +71 -0
  21. package/docs/superpowers/specs/2026-09-05-issue-63-flaky-manual-completion-design.md +49 -0
  22. package/docs/superpowers/specs/2026-09-05-issue-64-changelog-helper-design.md +76 -0
  23. package/docs/superpowers/specs/2026-09-05-pty-host-stacking-sock-race-design.md +510 -0
  24. package/package.json +83 -81
  25. package/runner/job-runner.mjs +2 -2
  26. package/runner/pty-runner.mjs +573 -2
  27. package/runner/state-runner.mjs +3 -0
  28. package/runner/title-runner.mjs +1 -1
  29. package/scripts/release_helper.mjs +277 -0
  30. package/src/commands/agent-board.ts +38 -35
  31. package/src/commands/attach-decision.mjs +66 -0
  32. package/src/commands/attach-flow.ts +45 -39
  33. package/src/core/code-refs.mjs +85 -33
  34. package/src/core/evidence.mjs +2 -2
  35. package/src/core/heuristics.mjs +40 -2
  36. package/src/core/host-coordination.mjs +159 -0
  37. package/src/core/host-crash.mjs +43 -3
  38. package/src/core/host-probe.mjs +196 -0
  39. package/src/core/launch.mjs +3 -1
  40. package/src/core/locks.mjs +196 -1
  41. package/src/core/paths.mjs +24 -0
  42. package/src/core/store.mjs +164 -5
  43. package/src/core/types.mjs +17 -1
  44. package/src/core/warm-host-sweeper.mjs +150 -0
  45. package/src/index.ts +29 -1
  46. package/src/runtime/service.mjs +967 -109
  47. package/src/ui/dashboard-decisions.mjs +55 -0
  48. package/src/ui/dashboard.ts +26 -12
@@ -0,0 +1,209 @@
1
+ # Evidence outputPreview Extraction Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Fix `evidence.json` `commands[].outputPreview` storing `[object Object]` for bash tool results by extracting text from pi's `AgentToolResult.content` blocks (issue #41).
6
+
7
+ **Architecture:** New pure function `toolResultText(result)` in `src/core/heuristics.mjs` (symmetric with existing `assistantText`); `reduceEvidence` bash branch swaps `String(event.result ?? "")` for it. No data-structure changes, no migration.
8
+
9
+ **Tech Stack:** Node.js ESM, `node:test`, JSDoc types checked by `tsc --noEmit`.
10
+
11
+ **Spec:** `docs/superpowers/specs/2026-09-04-evidence-outputpreview-design.md` (acceptance IDs A1/A2/A3/U1 referenced below).
12
+
13
+ ## Global Constraints
14
+
15
+ - All edits under worktree `$WT=/home/elling/git-repo/github/pi-agent-board/.pi/worktrees/issue-41-evidence-outputpreview-object`; git via `git -C $WT` — never touch main checkout.
16
+ - `toolResultText` must stay a pure function with zero side effects; do NOT inline it into `reduceEvidence` (spec §3 hard constraint).
17
+ - Unknown-shaped objects must yield `""`, never `"[object Object]"` (spec D2, #40's 宁可不显示也不错显示 principle).
18
+ - Legacy string `result` must keep passing through unchanged (spec D5).
19
+ - Do NOT change the 500-char truncate, `EvidenceCommand` shape, other tools' branches, or powershell handling (spec §5 non-goals).
20
+ - Stage files individually with `git -C $WT add <file>`; never `git add -A`.
21
+ - Full gate per task end: `npm run verify` (typecheck + test + coverage + pack:dry). Never `npm test -- <file>` (glob expands to full suite anyway).
22
+
23
+ ---
24
+
25
+ ### Task 1: `toolResultText` pure function (acceptance: A1)
26
+
27
+ **Files:**
28
+ - Modify: `src/core/heuristics.mjs` (after `assistantText`, line ~26)
29
+ - Test: `test/heuristics.test.mjs`
30
+
31
+ **Interfaces:**
32
+ - Produces: `toolResultText(result: any): string` — exported from `src/core/heuristics.mjs`. Task 2 imports it in `src/core/evidence.mjs`.
33
+ - Behavior table (spec D2): `null/undefined → ""`; `string → passthrough`; object with `content` array → text blocks `join("\n")` trimmed; object without content/text → `""`; number/bool → `String()`.
34
+
35
+ - [ ] **Step 1: Write the failing tests**
36
+
37
+ Append to `test/heuristics.test.mjs`, and add `toolResultText` to the existing import block from `../src/core/heuristics.mjs`:
38
+
39
+ ```js
40
+ test("toolResultText extracts text blocks from AgentToolResult", () => {
41
+ const result = {
42
+ content: [
43
+ { type: "text", text: "line1" },
44
+ { type: "image", data: "AAAA", mimeType: "image/png" },
45
+ { type: "text", text: "line2" },
46
+ ],
47
+ details: { fullOutputPath: "/tmp/pi-bash-x.log" },
48
+ };
49
+ assert.equal(toolResultText(result), "line1\nline2");
50
+ });
51
+
52
+ test("toolResultText returns empty string for image-only content", () => {
53
+ assert.equal(toolResultText({ content: [{ type: "image", data: "AAAA", mimeType: "image/png" }] }), "");
54
+ });
55
+
56
+ test("toolResultText returns empty string for object without content array", () => {
57
+ assert.equal(toolResultText({ details: {} }), "");
58
+ assert.equal(toolResultText({}), "");
59
+ });
60
+
61
+ test("toolResultText passes through plain strings (legacy events)", () => {
62
+ assert.equal(toolResultText("ok"), "ok");
63
+ });
64
+
65
+ test("toolResultText handles nullish and scalar inputs", () => {
66
+ assert.equal(toolResultText(null), "");
67
+ assert.equal(toolResultText(undefined), "");
68
+ assert.equal(toolResultText(42), "42");
69
+ assert.equal(toolResultText(true), "true");
70
+ });
71
+ ```
72
+
73
+ - [ ] **Step 2: Run tests to verify they fail**
74
+
75
+ Run: `cd $WT && node --test test/heuristics.test.mjs`
76
+ Expected: FAIL — `toolResultText is not defined` / import error.
77
+
78
+ - [ ] **Step 3: Implement `toolResultText` in `src/core/heuristics.mjs`**
79
+
80
+ Insert after the existing `assistantText` function:
81
+
82
+ ```js
83
+ /**
84
+ * Extract text from a pi AgentToolResult object
85
+ * ({ content: [{ type: "text", text }, ...], details, ... }), or, defensively,
86
+ * a plain string. Unknown-shaped objects yield "" — never "[object Object]"
87
+ * (issue #41; mirrors pi's own convertToolResultOutput join("\n") semantics).
88
+ * @param {any} result
89
+ * @returns {string}
90
+ */
91
+ export function toolResultText(result) {
92
+ if (result == null) return "";
93
+ if (typeof result === "string") return result;
94
+ if (typeof result !== "object") return String(result);
95
+ const content = result.content;
96
+ if (!Array.isArray(content)) return "";
97
+ return content
98
+ .filter((b) => b && b.type === "text" && typeof b.text === "string")
99
+ .map((b) => b.text)
100
+ .join("\n")
101
+ .trim();
102
+ }
103
+ ```
104
+
105
+ - [ ] **Step 4: Run tests to verify they pass**
106
+
107
+ Run: `cd $WT && node --test test/heuristics.test.mjs`
108
+ Expected: PASS (all 5 new tests + pre-existing suite).
109
+
110
+ - [ ] **Step 5: Commit**
111
+
112
+ ```bash
113
+ git -C $WT add test/heuristics.test.mjs src/core/heuristics.mjs
114
+ git -C $WT commit -m "feat: add toolResultText extractor for AgentToolResult content (issue #41)"
115
+ ```
116
+
117
+ ---
118
+
119
+ ### Task 2: `reduceEvidence` bash branch uses `toolResultText` (acceptance: A2, A3)
120
+
121
+ **Files:**
122
+ - Modify: `src/core/evidence.mjs` (import line 2; bash branch line ~196)
123
+ - Test: `test/evidence.test.mjs`
124
+
125
+ **Interfaces:**
126
+ - Consumes: `toolResultText(result: any): string` from Task 1.
127
+ - Produces: unchanged `EvidenceCommand` shape; `outputPreview` now carries extracted text.
128
+
129
+ - [ ] **Step 1: Write the failing test (real AgentToolResult shape)**
130
+
131
+ In `test/evidence.test.mjs`, inside the existing top-level test that builds `snap` (after the current `b1` end event at line ~24), append:
132
+
133
+ ```js
134
+ reduceEvidence(snap, { type: "tool_execution_end", toolCallId: "b2", toolName: "bash", isError: false, result: { content: [{ type: "text", text: "https://github.com/zhuxixi/pi-agent-board/pull/45" }] } }, 31);
135
+ ```
136
+
137
+ and alongside the existing assertions:
138
+
139
+ ```js
140
+ assert.equal(snap.commands.find((c) => c.id === "b2").outputPreview, "https://github.com/zhuxixi/pi-agent-board/pull/45");
141
+ ```
142
+
143
+ (The pre-existing `b1` fixture with `result: "ok"` stays untouched — its `outputPreview` passthrough is the D5 regression guard.)
144
+
145
+ **Assertion ripple:** the new `b2` command raises the command count. In the same test, update the tail assertion:
146
+
147
+ ```js
148
+ assert.equal(summary.commandCount, 2);
149
+ ```
150
+
151
+ (was `assert.equal(summary.commandCount, 1);`)
152
+
153
+ - [ ] **Step 2: Run test to verify it fails**
154
+
155
+ Run: `cd $WT && node --test test/evidence.test.mjs`
156
+ Expected: FAIL — `outputPreview` is `"[object Object]"` instead of the URL.
157
+
158
+ - [ ] **Step 3: Modify `src/core/evidence.mjs`**
159
+
160
+ Import line (currently):
161
+
162
+ ```js
163
+ import { assistantText, classifyCommand, toolFileOperation, truncate } from "./heuristics.mjs";
164
+ ```
165
+
166
+ becomes:
167
+
168
+ ```js
169
+ import { assistantText, classifyCommand, toolFileOperation, toolResultText, truncate } from "./heuristics.mjs";
170
+ ```
171
+
172
+ In `reduceEvidence`, `tool_execution_end` → `name === "bash"` branch, replace exactly this line:
173
+
174
+ ```js
175
+ outputPreview: truncate(String(event.result ?? ""), 500),
176
+ ```
177
+
178
+ with:
179
+
180
+ ```js
181
+ outputPreview: truncate(toolResultText(event.result), 500),
182
+ ```
183
+
184
+ - [ ] **Step 4: Run tests to verify they pass**
185
+
186
+ Run: `cd $WT && node --test test/evidence.test.mjs`
187
+ Expected: PASS — new assertion green AND legacy `"ok"` fixture still green (D5).
188
+
189
+ - [ ] **Step 5: Full verify gate**
190
+
191
+ Run: `cd $WT && npm run verify`
192
+ Expected: PASS — typecheck, full test suite, coverage, pack:dry all green.
193
+
194
+ - [ ] **Step 6: Commit**
195
+
196
+ ```bash
197
+ git -C $WT add src/core/evidence.mjs test/evidence.test.mjs
198
+ git -C $WT commit -m "fix: extract evidence outputPreview from AgentToolResult content (issue #41)"
199
+ ```
200
+
201
+ ---
202
+
203
+ ### Task 3: Post-merge manual verification (acceptance: U1, user-verified)
204
+
205
+ **Trigger:** after PR merge + board reloads the new extension on next pi session start.
206
+
207
+ - [ ] **Step 1:** In a real pi session, run a few bash commands (e.g. `gh pr create`, `git log`).
208
+ - [ ] **Step 2:** Inspect `~/.pi/agent/agent-board/views/<view>/evidence.json`.
209
+ - [ ] **Step 3:** Pass criteria: newly recorded bash commands show real output text in `outputPreview` (e.g. the `gh pr create` URL); no new `[object Object]` entries. Record observation result back on issue #41.