@cad0p/pi-subagents-tintinweb 0.14.2 → 0.22.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.
@@ -0,0 +1,132 @@
1
+ # PR Verification Checklist
2
+
3
+ Automated checks are necessary but not sufficient. This checklist is what a PR
4
+ author runs before requesting review. Record the evidence in the PR body so a
5
+ reviewer can see what was verified, on which setup. Skip a section only when it
6
+ does not apply, and say so explicitly.
7
+
8
+ ## Workspace
9
+
10
+ Keep the main checkout on `main`. Do the branch work in an isolated git worktree
11
+ in a sibling folder (`git worktree add ../<repo>-<slug> <branch>`), install its
12
+ dependencies there, and run every gate and live check from it. Remove the
13
+ worktree after merge.
14
+
15
+ ## Automated gates
16
+
17
+ Run all four from the repository root; all must pass (mirrors `CONTRIBUTING.md`'s
18
+ "Before Submitting a PR"):
19
+
20
+ ```bash
21
+ npm run lint # biome
22
+ npm run typecheck # tsc --noEmit
23
+ npm run test # vitest, including the *-e2e.test.ts suites
24
+ npm run build # tsc
25
+ ```
26
+
27
+ `npm run lint:fix` auto-fixes most style issues. If the change touches the
28
+ end-to-end surface, also run the scripted suite directly:
29
+
30
+ ```bash
31
+ npm run test:e2e
32
+ ```
33
+
34
+ `PI_E2E_LIVE=1 npm run test:e2e` swaps the scripted faux suite for the live one
35
+ and exercises a real model through your local `pi` login (`PI_PROVIDER` /
36
+ `PI_MODEL` can pin the provider and model). Run it by hand before publishing.
37
+
38
+ ## Manual TUI checks
39
+
40
+ Run these in a live pi session with the extension installed from the branch, and
41
+ note the pi version in the PR body. Renderer behavior differs across pi
42
+ versions; when the change targets a newer runtime, verify on that version too.
43
+
44
+ Maintainer reference setup: `claude-bridge/claude-haiku-5-5` at thinking
45
+ `xhigh`; fall back to `opencode-go/deepseek-v4.1-flash` at `max` when the bridge
46
+ is unavailable. Load the branch build instead of the installed package so the two
47
+ don't collide:
48
+
49
+ ```bash
50
+ pi --no-extensions -e <pi-claude-bridge>/src/index.ts -e <repo>/src/index.ts \
51
+ --provider claude-bridge --model claude-haiku-5-5 --thinking xhigh
52
+ ```
53
+
54
+ - Exercise the changed surface end to end in a real session — spawn, steer,
55
+ render, resume, or whatever the PR touches.
56
+ - Toggle collapsed/expanded states with ctrl+o and, on pi 0.87.1+, per-row
57
+ click; confirm both paths reach the same state and the marker and hint update.
58
+ - Check theme and color rendering in at least one dark theme; confirm wrapped or
59
+ clipped text stays within the intended box.
60
+ - Feed long and edge inputs (empty, whitespace-only, multi-line, large) and
61
+ confirm the collapsed row stays bounded while the expanded view shows the full
62
+ content.
63
+ - Confirm terminal control characters (ESC/OSC/CSI, newlines, tabs) in untrusted
64
+ text cannot forge rows or leak into the terminal: display copies are
65
+ sanitized, model-facing payloads are not.
66
+
67
+ ## Session-level checks
68
+
69
+ Run these when the change touches session data, rendering, or persistence:
70
+
71
+ - Load and replay an existing session containing the affected entry or tool
72
+ call; the old data must render without throwing.
73
+ - Run `/export` and confirm the HTML renders without a crash and the affected
74
+ content appears where expected.
75
+ - If the change touches cross-extension RPC or events, verify the RPC surface
76
+ still answers.
77
+
78
+ ## Independent agent review
79
+
80
+ Every PR, docs included, needs a fresh read-only review agent on each pushed
81
+ head before merge (plus any escalation). This section has no skip; the
82
+ author's own checks don't count as review. Record every round in the PR body,
83
+ under Evidence. A verdict counts only for the SHA it reviewed.
84
+
85
+ - Spawn a new `general-purpose` agent with `max_turns: 20`. Don't
86
+ use `resume`, `inherit_context`, `isolation` (a worktree branches from the
87
+ caller's committed `HEAD`, not the PR head), or `steer_subagent`.
88
+ - Brief it with the linked issue (the guarantees), the head SHA and the
89
+ worktree path holding it, the diff range `origin/main...<head-sha>`, and this
90
+ checklist. Leave out your own conclusions, test results, the PR body's
91
+ verification notes, and earlier verdicts. Frame it as a completeness
92
+ question: which inputs, callers, settings, or runtime versions would break
93
+ the guarantees while the gates stay green?
94
+ - The brief forbids edits, commits, pushes, branch switches, and auto-fixers
95
+ (`npm run lint:fix`). It states the turn budget and the way out: reply
96
+ `NO VERDICT` with what was tested if the budget runs out, `HEAD` differs from
97
+ the head SHA, or the diff is empty.
98
+ - The first line of the final message is `CLEAN`, `FINDINGS(n)`, or
99
+ `NO VERDICT`; then what it checked, and each finding tagged must-fix,
100
+ should-fix, or nit. A run that hit its turn limit, was aborted, or ends
101
+ without a first-line verdict counts as `NO VERDICT`.
102
+ - After a `NO VERDICT`, retry `general-purpose` once with a narrower brief,
103
+ or a higher `max_turns` if the task needs it.
104
+ - Escalate to the user-defined `smart` agent only when the review makes claims
105
+ that are easily shown wrong by facts (a misread API, code that doesn't exist,
106
+ behaviour the source contradicts). Don't escalate over opinionated findings
107
+ you disagree with. Confirm the result reports the escalated type: an unknown
108
+ `subagent_type` silently runs `general-purpose`, which is not an escalation.
109
+ - A must-fix finding blocks its head until it is folded into a new head
110
+ (reviewed by a new `general-purpose` agent) or dismissed with the
111
+ maintainer's reason recorded in the PR body, citing the facts for a wrong
112
+ finding. A later verdict on the same head does not clear it by itself.
113
+ Should-fix and nit findings may stay open if recorded.
114
+ - Merge only when the current head has a `CLEAN` or `FINDINGS(n)` verdict with
115
+ no undismissed must-fix findings.
116
+
117
+ ## Fork release rules
118
+
119
+ - Do not edit `CHANGELOG.md` on non-release branches; the fork's
120
+ `validate-package-version` CI gate rejects it.
121
+ - Release notes go in the PR body under `## Release notes`, with attribution
122
+ where one applies.
123
+
124
+ ## Evidence
125
+
126
+ In the PR body, record:
127
+
128
+ - the pi version and platform used for the live checks;
129
+ - each command you ran and its result;
130
+ - the manual observations (what you saw, not just "works");
131
+ - every review round: the head it reviewed, the agent type, and the verdict;
132
+ - any check that does not apply, and why.
@@ -14,18 +14,12 @@ If the target is already known, use a direct tool — `read` for a known path, `
14
14
  ## Usage notes
15
15
 
16
16
  - Always include a short (3-5 word) description summarizing what the agent will do (shown in UI).
17
- - When you launch multiple agents for independent work, send them in a single message with multiple tool uses, with run_in_background: true on each, so they run concurrently. If the user specifies that they want agents run "in parallel", you MUST send a single message with multiple tool calls. Foreground calls run sequentially — only one executes at a time.
18
- - When the agent is done, it returns a single message back to you. The result is not visible to the user — to show the user, send a text message with a concise summary.
17
+ - When an agent finishes or fails, you will be notified on subagent completion/failure — do NOT poll or sleep waiting for it.
19
18
  - Trust but verify: an agent's summary describes what it intended to do, not necessarily what it did. When an agent writes or edits code, check the actual changes before reporting work as done.
20
- - Use run_in_background for work you don't need immediately. You will be notified when it completes — do NOT poll or sleep waiting for it. Continue with other work or respond to the user instead.
21
- - Foreground vs background: use foreground (default) when you need the agent's results before you can proceed. Use background when you have genuinely independent work to do in parallel.
22
19
  - Use resume with an agent ID to continue a previous agent's work. A new (non-resume) Agent call starts a fresh agent with no memory of prior runs, so the prompt must be self-contained.
23
- - Use steer_subagent to send mid-run messages to a running background agent.
20
+ - Use steer_subagent to send mid-run messages to a running subagent.
24
21
  - Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, etc.), since it is not aware of the user's intent.
25
- - If an agent's description says it should be used proactively, try to use it without the user having to ask for it first.
26
- - Use thinking to control extended thinking level.
27
- - Use inherit_context if the agent needs the parent conversation history.
28
- - Use isolation: "worktree" to run the agent in an isolated git worktree (safe parallel file modifications). The worktree is automatically cleaned up if the agent makes no changes; otherwise the path and branch are returned in the result.{{scheduleGuideline}}
22
+ - Use inherit_context if the agent needs the parent conversation history.{{isolationGuideline}}{{scheduleGuideline}}
29
23
 
30
24
  ## Writing the prompt
31
25
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cad0p/pi-subagents-tintinweb",
3
- "version": "0.14.2",
3
+ "version": "0.22.0",
4
4
  "description": "A pi extension extension that brings smart Claude Code-style autonomous sub-agents to pi.",
5
5
  "author": "tintinweb",
6
6
  "publishConfig": {
@@ -25,18 +25,17 @@
25
25
  "autonomous"
26
26
  ],
27
27
  "peerDependencies": {
28
- "@earendil-works/pi-ai": ">=0.80.0",
29
- "@earendil-works/pi-coding-agent": ">=0.80.0",
30
- "@earendil-works/pi-tui": ">=0.80.0"
28
+ "@earendil-works/pi-ai": ">=1.0.4",
29
+ "@earendil-works/pi-coding-agent": ">=1.0.4",
30
+ "@earendil-works/pi-tui": ">=1.0.4",
31
+ "@sinclair/typebox": "*"
31
32
  },
32
33
  "dependencies": {
33
- "@sinclair/typebox": "^0.34.49",
34
34
  "croner": "^10.0.1",
35
35
  "nanoid": "^5.0.0"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsc",
39
- "prepublishOnly": "npm run lint && npm run typecheck && npm run test && npm run build",
40
39
  "test": "vitest run",
41
40
  "test:watch": "vitest",
42
41
  "test:e2e": "vitest run e2e --reporter=verbose",
@@ -46,16 +45,19 @@
46
45
  },
47
46
  "devDependencies": {
48
47
  "@biomejs/biome": "^2.4.14",
48
+ "@earendil-works/pi-ai": "1.0.4",
49
+ "@earendil-works/pi-coding-agent": "1.0.4",
50
+ "@earendil-works/pi-tui": "1.0.4",
49
51
  "@types/node": "^25.5.0",
50
52
  "typescript": "^6.0.0",
51
- "vitest": "^4.0.18",
52
- "@earendil-works/pi-ai": ">=0.80.0"
53
+ "vitest": "^4.0.18"
53
54
  },
54
55
  "pi": {
55
56
  "extensions": [
56
57
  "./src/index.ts"
57
- ],
58
- "video": "https://github.com/tintinweb/pi-subagents/raw/master/media/demo.mp4",
59
- "image": "https://github.com/tintinweb/pi-subagents/raw/master/media/screenshot.png"
58
+ ]
59
+ },
60
+ "engines": {
61
+ "node": ">=22.19.0"
60
62
  }
61
63
  }
@@ -10,3 +10,12 @@ allowBuilds:
10
10
  esbuild: true
11
11
  koffi: false
12
12
  protobufjs: true
13
+ minimumReleaseAgeExclude:
14
+ - "@earendil-works/chord@1.0.4"
15
+ - "@earendil-works/pi-agent-core@1.0.4"
16
+ - "@earendil-works/pi-ai@1.0.4"
17
+ - "@earendil-works/pi-codemode@1.0.4"
18
+ - "@earendil-works/pi-coding-agent@1.0.4"
19
+ - "@earendil-works/pi-mcp@1.0.4"
20
+ - "@earendil-works/pi-telemetry@1.0.4"
21
+ - "@earendil-works/pi-tui@1.0.4"
@@ -0,0 +1,43 @@
1
+ /**
2
+ * abortable.ts — race a promise against an AbortSignal without cancelling the
3
+ * underlying work.
4
+ *
5
+ * Used by the nested `get_subagent_result` wait path: pressing Esc cancels only
6
+ * the caller's wait; the background child keeps running and its result stays
7
+ * unconsumed. The listener is removed on every settle path so the signal
8
+ * accumulates no handlers, and a late settlement of the wrapped promise after
9
+ * an abort is absorbed as a no-op (no unhandled rejection).
10
+ */
11
+
12
+ /** Await a promise until it settles or the caller cancels, without aborting the underlying work. */
13
+ export function abortable<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {
14
+ if (!signal) return promise;
15
+ if (signal.aborted) return Promise.reject(signal.reason);
16
+
17
+ return new Promise<T>((resolve, reject) => {
18
+ let settled = false;
19
+ const cleanup = () => signal.removeEventListener("abort", onAbort);
20
+ const onAbort = () => {
21
+ if (settled) return;
22
+ settled = true;
23
+ cleanup();
24
+ reject(signal.reason);
25
+ };
26
+
27
+ signal.addEventListener("abort", onAbort, { once: true });
28
+ promise.then(
29
+ (value) => {
30
+ if (settled) return;
31
+ settled = true;
32
+ cleanup();
33
+ resolve(value);
34
+ },
35
+ (error: unknown) => {
36
+ if (settled) return;
37
+ settled = true;
38
+ cleanup();
39
+ reject(error);
40
+ },
41
+ );
42
+ });
43
+ }