pi-crew 0.11.7 → 0.11.9
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.
- package/.githooks/pre-commit +22 -0
- package/.githooks/pre-push +56 -0
- package/CHANGELOG.md +196 -1
- package/dist/index.mjs +533 -515
- package/docs/publishing.md +29 -0
- package/docs/usage.md +1 -1
- package/index.ts +3 -3
- package/install.mjs +4 -1
- package/package.json +8 -5
- package/scripts/install-hooks.mjs +32 -0
- package/skills/real-test-pi-crew/SKILL.md +57 -18
- package/src/config/config-validation.ts +8 -1
- package/src/config/defaults.ts +8 -1
- package/src/config/env-vars.ts +16 -1
- package/src/config/types.ts +28 -4
- package/src/extension/command-completions.ts +44 -22
- package/src/extension/registration/foreground-run-controller.ts +19 -10
- package/src/extension/registration/lifecycle-handlers.ts +6 -491
- package/src/extension/registration/lifecycle.ts +7 -90
- package/src/extension/registration/render-loop.ts +532 -0
- package/src/extension/team-tool/doctor.ts +6 -0
- package/src/extension/team-tool/handle-settings.ts +4 -1
- package/src/runtime/child-pi/child-pi-spawn.ts +7 -0
- package/src/runtime/child-pi/child-pi.ts +37 -2
- package/src/runtime/child-pi/pi-version.ts +187 -0
- package/src/runtime/classifier/classifier-service.ts +298 -0
- package/src/runtime/dispatch-batch.ts +4 -0
- package/src/runtime/live-session/live-session-runtime.ts +31 -0
- package/src/runtime/model/pi-args.ts +62 -3
- package/src/runtime/process/zombie-scanner.ts +168 -7
- package/src/runtime/rpc/README.md +64 -25
- package/src/runtime/rpc/rpc-worker.ts +146 -26
- package/src/runtime/run-worker.ts +89 -15
- package/src/runtime/scheduling/run-coalesced-task-group.ts +3 -0
- package/src/runtime/skill-instructions.ts +66 -1
- package/src/runtime/surface/resolve-surface.ts +34 -19
- package/src/runtime/task-runner/child-executor.ts +132 -0
- package/src/runtime/task-runner/pre-execution.ts +8 -0
- package/src/runtime/task-runner.ts +6 -0
- package/src/schema/config-schema.ts +20 -8
- package/src/schema/team-tool-schema.ts +4 -2
- package/src/state/contracts.ts +5 -0
- package/src/ui/dashboard-panes/agents-pane.ts +3 -2
- package/src/ui/dashboard-panes/health-pane.ts +6 -1
- package/src/ui/dashboard-panes/mailbox-pane.ts +12 -7
- package/src/ui/dashboard-panes/plan-pane.ts +5 -2
- package/src/ui/dashboard-panes/progress-pane.ts +8 -2
- package/src/ui/format-helpers.ts +11 -0
- package/src/ui/live-conversation-overlay.ts +5 -3
- package/src/ui/live-duration.ts +5 -4
- package/src/ui/live-run-sidebar.ts +90 -20
- package/src/ui/overlays/mailbox-compose-overlay.ts +31 -1
- package/src/ui/rail.ts +14 -1
- package/src/ui/run-action-dispatcher.ts +2 -1
- package/src/ui/run-dashboard.ts +62 -22
- package/src/ui/run-snapshot-cache.ts +32 -0
- package/src/ui/settings-overlay.ts +36 -3
- package/src/ui/tool-renderers/brief-mode.ts +2 -2
- package/src/ui/transcript-viewer.ts +4 -1
- package/src/ui/widget/index.ts +10 -2
- package/src/ui/widget/task-list.ts +22 -7
- package/src/ui/widget/widget-model.ts +5 -4
- package/src/ui/widget/widget-renderer.ts +212 -37
- package/src/utils/relative-time.ts +11 -3
- package/src/utils/socket-path.ts +48 -8
- package/src/utils/visual.ts +32 -2
package/docs/publishing.md
CHANGED
|
@@ -76,6 +76,35 @@ Users can install the published package with:
|
|
|
76
76
|
pi install npm:pi-crew
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
### Pre-push hook (local release gate, D3)
|
|
80
|
+
|
|
81
|
+
The repo ships committed git hooks under `.githooks/`. A plain
|
|
82
|
+
`npm install` activates them via the `prepare` script
|
|
83
|
+
(`scripts/install-hooks.mjs` sets `git config core.hooksPath .githooks` —
|
|
84
|
+
idempotent, and a no-op when git or a repo is absent). Manual activation
|
|
85
|
+
in an existing clone:
|
|
86
|
+
|
|
87
|
+
```bash
|
|
88
|
+
git config core.hooksPath .githooks
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Scope of `pre-push` (the release-gate broadening; `pre-commit` handles
|
|
92
|
+
lockfile drift):
|
|
93
|
+
|
|
94
|
+
- **push to `refs/heads/main`** — `check:conflict-markers` + `typecheck`,
|
|
95
|
+
then the **FULL unit suite** (`npm run test:unit`, the same gate CI
|
|
96
|
+
runs). Any failure blocks the push. This closes the 2026-10 gap where
|
|
97
|
+
local pushes ran only `test:critical` (~120 tests) while CI ran the full
|
|
98
|
+
suite — three waves shipped red that way.
|
|
99
|
+
- **push to any other ref** — fast gates only (`check:conflict-markers` +
|
|
100
|
+
`typecheck`).
|
|
101
|
+
|
|
102
|
+
Emergency bypass (CI still gates `main`):
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
git push --no-verify
|
|
106
|
+
```
|
|
107
|
+
|
|
79
108
|
### Postinstall
|
|
80
109
|
|
|
81
110
|
`npm install` / `pi install` triggers `scripts/postinstall.mjs`, which:
|
package/docs/usage.md
CHANGED
package/index.ts
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Resolution order:
|
|
5
5
|
* 1. dist/index.mjs (bundle) when present AND not explicitly disabled.
|
|
6
|
-
* Default since v0.9.17 close-out —
|
|
7
|
-
* ~
|
|
8
|
-
*
|
|
6
|
+
* Default since v0.9.17 close-out — re-measured 2026-10-01 (deep review
|
|
7
|
+
* §10/V7): ~36% faster cold-start on a cold Node cache; the gap narrows
|
|
8
|
+
* with a warm NODE_COMPILE_CACHE. The bundle's primary
|
|
9
9
|
* value is correctness (vendored typebox) and deterministic startup,
|
|
10
10
|
* not raw speed.
|
|
11
11
|
* See `scripts/bench-cold-start.mjs` for reproducible numbers.
|
package/install.mjs
CHANGED
|
@@ -54,7 +54,10 @@ export const defaultConfig = {
|
|
|
54
54
|
widgetPlacement: "bottom",
|
|
55
55
|
widgetMaxLines: 8,
|
|
56
56
|
powerbar: true,
|
|
57
|
-
|
|
57
|
+
// L3 (2026-10-07 real-test review): tracks DEFAULT_UI.dashboardPlacement —
|
|
58
|
+
// enforced by test/unit/install-defaults-sync.test.ts (mutation: edit
|
|
59
|
+
// DEFAULT_UI without this file and that test goes red).
|
|
60
|
+
dashboardPlacement: "right",
|
|
58
61
|
dashboardWidth: 72,
|
|
59
62
|
dashboardLiveRefreshMs: 1000,
|
|
60
63
|
autoOpenDashboard: false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-crew",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.9",
|
|
4
4
|
"description": "Pi extension for coordinated AI teams, workflows, worktrees, and async task orchestration",
|
|
5
5
|
"author": "baphuongna",
|
|
6
6
|
"license": "MIT",
|
|
@@ -45,6 +45,8 @@
|
|
|
45
45
|
"assets/crew-vibes.ttf",
|
|
46
46
|
"scripts/clean-strip-types.mjs",
|
|
47
47
|
"scripts/postinstall.mjs",
|
|
48
|
+
"scripts/install-hooks.mjs",
|
|
49
|
+
".githooks/",
|
|
48
50
|
"scripts/install-crew-vibes-font.mjs",
|
|
49
51
|
"scripts/build-crew-vibes-font.py",
|
|
50
52
|
"scripts/pty_probe.py",
|
|
@@ -101,6 +103,7 @@
|
|
|
101
103
|
"build:bundle:once": "node scripts/watch-bundle.mjs --once",
|
|
102
104
|
"dev": "node scripts/dev-runner.mjs",
|
|
103
105
|
"postinstall": "node scripts/postinstall.mjs",
|
|
106
|
+
"prepare": "node scripts/install-hooks.mjs",
|
|
104
107
|
"install:crew-font": "node scripts/install-crew-vibes-font.mjs",
|
|
105
108
|
"build:crew-font": "python scripts/build-crew-vibes-font.py",
|
|
106
109
|
"bench": "node scripts/run-bench.mjs",
|
|
@@ -147,10 +150,10 @@
|
|
|
147
150
|
},
|
|
148
151
|
"devDependencies": {
|
|
149
152
|
"@biomejs/biome": "^2.5.14",
|
|
150
|
-
"@earendil-works/pi-agent-core": "^1.0.
|
|
151
|
-
"@earendil-works/pi-ai": "^1.0.
|
|
152
|
-
"@earendil-works/pi-coding-agent": "^1.0.
|
|
153
|
-
"@earendil-works/pi-tui": "^1.0.
|
|
153
|
+
"@earendil-works/pi-agent-core": "^1.0.4",
|
|
154
|
+
"@earendil-works/pi-ai": "^1.0.4",
|
|
155
|
+
"@earendil-works/pi-coding-agent": "^1.0.4",
|
|
156
|
+
"@earendil-works/pi-tui": "^1.0.4",
|
|
154
157
|
"@sinclair/typebox": "^0.34.52",
|
|
155
158
|
"@types/node": "^25.9.8",
|
|
156
159
|
"tsx": "^4.23.15",
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// install-hooks.mjs — D3: point git at the committed .githooks directory.
|
|
3
|
+
//
|
|
4
|
+
// Idempotent + environment-tolerant: exits 0 when git is absent, when the
|
|
5
|
+
// cwd is not a git repo, or when `git config` fails for any reason — a
|
|
6
|
+
// developer convenience must never break `npm install` (the same reason
|
|
7
|
+
// postinstall.mjs is best-effort). Wired as the package.json `prepare`
|
|
8
|
+
// script so a plain `npm install` activates BOTH committed hooks:
|
|
9
|
+
// .githooks/pre-commit — lockfile-drift gate (check-lockfile-sync)
|
|
10
|
+
// .githooks/pre-push — release gate (conflict markers + typecheck,
|
|
11
|
+
// + FULL test:unit when pushing to refs/heads/main)
|
|
12
|
+
import { spawnSync } from "node:child_process";
|
|
13
|
+
|
|
14
|
+
function git(args) {
|
|
15
|
+
return spawnSync("git", args, { encoding: "utf8" });
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function main() {
|
|
19
|
+
const probe = git(["rev-parse", "--is-inside-work-tree"]);
|
|
20
|
+
if (probe.error || probe.status !== 0) {
|
|
21
|
+
console.log("[install-hooks] no usable git here — skipping core.hooksPath setup");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const set = git(["config", "core.hooksPath", ".githooks"]);
|
|
25
|
+
if (set.error || set.status !== 0) {
|
|
26
|
+
console.warn("[install-hooks] could not set core.hooksPath (non-fatal):", set.stderr?.trim() ?? set.error?.message);
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
console.log("[install-hooks] git core.hooksPath → .githooks (pre-commit + pre-push active)");
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
main();
|
|
@@ -3,11 +3,15 @@ name: real-test-pi-crew
|
|
|
3
3
|
description: >
|
|
4
4
|
LIVE end-to-end battery for pi-crew changes — unit-green ≠ works in a real Pi session; this skill proves the latter.
|
|
5
5
|
USE WHEN: you changed src/runtime/broker|child-pi|surface|prompt|state, src/ui, src/config, src/schema/team-tool-schema.ts, agents/*.md, workflows, CI, or dist/ — before committing; a worker hung/died/"no output for 600000ms"; a run went green but panes/UI/ask/steer look wrong; someone says "verify it really works".
|
|
6
|
-
TIERS AT A GLANCE: T1 critical (
|
|
6
|
+
TIERS AT A GLANCE: T1 critical (~19s) · T2 kill-switch · T3 bundle+md5 · T4/T8 live-session sync · T5/T6 TUI probes · T7 smoke run · T9 team-tool feature battery · T10 surface panes (tmux + herdr) · T11 regression battery (a–j) · T12 agent-frontmatter contracts · T13 real-run UI render. A decision table at the TOP of the file maps changed-path → required tiers.
|
|
7
7
|
When NOT to use: unit tests for isolated modules (use the test runner directly); pure test execution.
|
|
8
8
|
|
|
9
9
|
origin: pi-crew
|
|
10
10
|
triggers:
|
|
11
|
+
- "pi crashed"
|
|
12
|
+
- "tmux server died"
|
|
13
|
+
- "crashes.json"
|
|
14
|
+
- "completion popup"
|
|
11
15
|
- "test the change"
|
|
12
16
|
- "verify it works"
|
|
13
17
|
- "is it really working"
|
|
@@ -86,7 +90,7 @@ End-to-end verification discipline for pi-crew changes. Distilled from the broke
|
|
|
86
90
|
|
|
87
91
|
| Tier | Chứng minh gì | Chi phí | Section |
|
|
88
92
|
|---|---|---|---|
|
|
89
|
-
| 1 | critical suites xanh (broker/UI) |
|
|
93
|
+
| 1 | critical suites xanh (broker/UI) | ~19s | Tier 1 |
|
|
90
94
|
| 2 | kill-switch tắt đúng qua 3 đường | 75s | Tier 2 |
|
|
91
95
|
| 3 | typecheck + rebuild bundle + md5 sync | 25s | Tier 3 |
|
|
92
96
|
| 4 | session sống nhận được bundle mới | <1s + restart | Tier 4 |
|
|
@@ -105,6 +109,7 @@ End-to-end verification discipline for pi-crew changes. Distilled from the broke
|
|
|
105
109
|
| Đổi… | Tier bắt buộc (thứ tự) |
|
|
106
110
|
|---|---|
|
|
107
111
|
| `src/runtime/broker/` | T1 → T7 → T9b-W |
|
|
112
|
+
| `src/extension/command-completions.ts` / `src/extension/registration/commands/*.ts` (autocomplete providers + slash-command handlers) | T1 + pinned `test/unit/extension/core/command-completions*.test.ts` → **T5 completion-popup probe**: trong tmux session thật, gõ `/team-transcript <runId> ` + 1 ký tự nữa cho popup fire — assert (a) pi CÒN SỐNG, (b) gợi ý task id hiện với runId hợp lệ, (c) KHÔNG crash entry mới trong `~/.pi/agent/crashes.json`. Completion callbacks chạy trong `CombinedAutocompleteProvider.getSuggestions` của pi core — nơi KHÔNG catch lỗi extension: một throw = chết cả pi process (P0 live-caught 2026-10-08: `Invalid runId: team_x/team-transcript`, crashes.json có full stack) |
|
|
108
113
|
| `src/ui/` | T1 → (T5|T6) → T13 |
|
|
109
114
|
| `src/config/` (kể cả migration-validator) | T1 → T11c |
|
|
110
115
|
| `src/runtime/child-pi/` (spawn/kill/steer) | T7 → T9g |
|
|
@@ -123,6 +128,11 @@ End-to-end verification discipline for pi-crew changes. Distilled from the broke
|
|
|
123
128
|
| `scripts/test-runner.mjs` (the runner itself) | T1 (exercises it) + `test/unit/scripts/test-runner-exit.test.ts` (21 tests: exit codes, cancelled-guard red-green, missing-file pre-check, batch shard empirical) + ONE batch-mode run (`PI_CREW_TEST_BATCH_SIZE=2 node scripts/test-runner.mjs --shard=0/1 <3 small files>`). Dev script — NOT bundled, no T3/T4 needed |
|
|
124
129
|
| `scripts/check-lazy-imports.mjs` | Run the gate on a clean tree (`node scripts/check-lazy-imports.mjs` exit 0) + re-probe the pattern battery vs the KNOWN GAPS comment (round-3 lesson: a skip-rule fix can OPEN a new false-skip hole — probe both directions). NOT bundled |
|
|
125
130
|
| `dist/` (bundle) | T3 → T4 → T8 → T11j |
|
|
131
|
+
| `src/runtime/rpc/**` (worker transport seam — RPC vẫn EXPERIMENTAL) | Pinned suites `test/unit/runtime/rpc/rpc-worker.test.ts` (10) + `test/unit/runtime/run-worker-rpc-seam.test.ts` (8, gồm DR1/DR5 exit-race) + **T7 smoke với `PI_CREW_WORKER_TRANSPORT=rpc`** khi đụng transport wiring; stdio fallback phải giữ structured warn |
|
|
132
|
+
| `src/runtime/classifier/**` + config ceremony (`classifierEnabled` / `classifierModel`) | `classifier-service.test.ts` (14) + `child-executor-retry-triage.test.ts` (6) + `npm run check:env-vars` — unit-only, KHÔNG live tier (seam DORMANT default off; chỉ live khi `PI_CREW_CLASSIFIER_ENABLED=1`) |
|
|
133
|
+
| `src/runtime/child-pi/pi-version.ts` / version-floor wiring (U9) | `test/unit/runtime/child-pi/pi-version.test.ts` (11) + `test/unit/runtime/model/pi-args-version-floor.test.ts` (7) + `test/unit/runtime/child-pi/pi-version-floor-wiring.test.ts` (2) |
|
|
134
|
+
| `.githooks/` + `scripts/install-hooks.mjs` | `bash -n .githooks/pre-push` + MỘT push thật quan sát hook (main → full `test:unit` + fast gates; ref khác → fast gates; kỳ vọng dòng `[pre-push] gates green.`) |
|
|
135
|
+
| `src/config/**` (env-vars keys MỚI) | `test/unit/config/config-schema-sync.test.ts` + `npm run check:env-vars` (mọi `PI_CREW_*` mới phải registered + routed qua `getCrewEnv`) — không cần live tier |
|
|
126
136
|
| bất kỳ đường dẫn trên, trước khi commit | gates đầy đủ: critical + unit + tsc + biome + md5 |
|
|
127
137
|
|
|
128
138
|
**When to use**: after any change to `src/runtime/broker/*.ts` (broker + tokens + issuer), `src/ui/`, `src/config/` (incl. `src/config/migration-validator.ts`), `src/extension/registration/lifecycle-handlers.ts`, `src/runtime/child-pi/*.ts` (worker spawn/kill/steering), `src/runtime/mcp-proxy.ts` + `src/runtime/model/pi-args.ts` (worker argv build + MCP role-gate — G2/G3, SDD-2), `src/runtime/async-runner.ts` + `src/runtime/background-runner.ts` (detached spawn + allowlist + entry-guarded `executeBackgroundRun` core — async dispatch, xem quy tắc tier ở decision table), `src/runtime/heartbeat/*` + `src/ui/heartbeat-aggregator.ts` (ambient heartbeat — guest `gc-*` skip), `src/runtime/surface/*.ts` (MuxSurface providers, degrade, launch script), `src/prompt/*.ts` (worker-side tools: ask / message / delegate / surface-worker recorder), `src/runtime/goal-workflow/plan-templates.ts`, `src/runtime/team-runner.ts` or `src/runtime/task-runner/**` (scheduler / execution — Tier 7 smoke), `src/state/**` (durable state — Tier 7 + 9a events/status + **Tier 11a read-your-writes**), `src/utils/paths.ts` + `src/utils/project-markers.ts` + `src/runtime/stale-reconciler.ts` + `src/extension/team-tool/health-monitor.ts` (run-state layout + symlink defense — pinned suites listed in the 2026-09-20 update), `src/runtime/live-session/**` + `src/runtime/custom-tools/*` (live-session mode + worker custom tools), `src/schema/team-tool-schema.ts` (or any `Type.Unsafe({...})` schema definition), `src/extension/registration/team-tool.ts`, `workflows/*.workflow.md`, `.github/workflows/*.yml` (CI env — Tier 11e), `scripts/wc-gate.mjs` (Tier 11b), or before any commit touching these paths. Schema changes additionally require Tier 9 (feature battery) because the team tool's TypeBox schema is validated by pi-ai BEFORE the handler runs — a too-strict or malformed schema breaks every action silently. Surface changes additionally require Tier 10 (surface-mode battery) because surface is fail-closed: every failure degrades to headless and the run still goes green — only pane-level evidence proves the panes engaged. Resource `.md` changes (agent bodies/frontmatter, skill metadata, discovery, frontmatter parsing) additionally require **Tier 12** (resource-contract battery) because the agent/team/workflow frontmatter parser is line-based, not YAML — a folded scalar parses as `">"` for every consumer while all other tiers stay green.
|
|
@@ -140,6 +150,8 @@ End-to-end verification discipline for pi-crew changes. Distilled from the broke
|
|
|
140
150
|
> **2026-09-29 update (RR-021 optimization wave + 4 review rounds, baseline `79a758d2`..`4393858c`, 37 commits; story `docs/stories/RR-021.md`; audit `pi-crew-optimization-audit.md`)**: (1) **Correctness/hang-risks** — `classifyReviewOutcome` word-boundary fix (the `\baccept\b` string-literal bug + negation guard), git/rg probe timeouts, `withRunLockSync`→`withRunLock` rerouting (lock family v0.9.26 intact), `reconcileAllStaleRuns` concurrent (`mapConcurrent` bound 4, per-run error isolation), sleeps→waitFor. (2) **Bundle hygiene** — esbuild/acorn/diff load via lazy sync-createRequire shims, ajv external, dead code −767 lines: bundle 3360 KB → **1575.2 KB**; NEW gates `check:lazy-imports` (ci.yml:142; src-side `// LAZY:` marker enforcement + dist-side no-hoisted-heavy-import assertion) and `check:bundle-size` (ci.yml:169). (3) **Test-gate integrity (review rounds 2–4)** — the runner now fails LOUDLY on `# cancelled N>0` (dual reporter: stdout UX unchanged, full TAP to a temp file, scraped in BOTH single-run and batch paths — `parseCancelledCount` + 21-test `test-runner-exit.test.ts`), on explicitly-listed files that do not exist (node:test v22 silently skipped them → exit 0; round-3 MAJOR B1), and `test:bundle` routes through the guarded runner (was the only CI gate bypassing it). Incremental tsc: typecheck ~20s → **~3.5s warm**. Suite anchors @ 2026-09-29: unit **8204 tests / 8201 pass / 0 fail / 3 skipped** (909 files), integration **136 / 132 pass / 4 skipped** (35 files incl. 3 slow), `test:critical` **116** (~18s), bundle **1575.2 KB** md5 `35ca335a90da01ac631493f220aaf121` (`--committed-hash` OK). Line refs moved: `PI_CREW_TEST_RUNNER_TIMEOUT_MS` now `scripts/test-runner.mjs:419`; crash-recovery design comment `:228`.
|
|
141
151
|
|
|
142
152
|
> **2026-10-01 update (SDD-2 W-B — G2 MCP role-gate + G3 spill-always + Phase D bump 0.99.1, commits `66f37875`→`f0b343ed`, execution record §13 `pi-crew-sdd-2026-09-30-buoi1.md`)**: (1) **G2 flips full-loadout sanity semantics** — MCP presence in workers is now ROLE- and PATH-dependent: the live-session SDK path strips MCP (`DefaultResourceLoader({ extensionsOverride: stripMcpExtensions })`) cho read-only roles (`mcpPermittedForRole` — explorer/reviewer/security-reviewer/analyst/critic/planner + unknown default-deny); a read-only worker WITHOUT MCP is CORRECT, a write-role worker without MCP is a regression; nếu strip không arm được (SDK hết export `DefaultResourceLoader`…) → fail-open + warning event `task.mcp_enforcement_degraded` (registry 168 → 169, `check:event-types --enforce` clean). CLI child-process path CHƯA cover (WI-4 defer: `~/.pi/agent/mcp.json` trống + `-ne` giết provider `oc-go` — read-only roles vẫn discover adapter MCP trên đường đó). (2) **G3 spill-always**: MỌI task text qua `task.md` 0600 — argv worker KHÔNG bao giờ chứa task text; probe đọc argv phải expect `@<temp>/task.md`, task ngắn mất prefix `Task: `; `TASK_ARG_LIMIT` đã xóa. (3) Phase D bump `@earendil-works/*` → 0.99.x: SDK bỏ option `enableMCP`, tool seam cần `ExtensionToolContext` (export mới `src/extension/pi-api.ts`). Decision table thêm row `mcp-proxy.ts`/`model/pi-args.ts`; D5 loadout line refs dời `:283-330` → `:280-336`.
|
|
153
|
+
> **2026-10-07 update (0.11.6 → 0.11.7/0.11.8-pre stack, GH#61/#62 + pi 1.0.4 adoption + RPC hardening, HEAD `11e717f5`)**: (1) **GH#61 (0.11.6)** — directory `pi.extensions` entries được normalize sang entry-file identity (`resolveExtensionDirEntry`): child worker không còn double-load directory extension (`Tool "…" conflicts … exit 1` — CHANGELOG 0.11.6 block, `CHANGELOG.md:207`). (2) **pi 1.0.4 adoption** — devDeps `@earendil-works/*` ^1.0.4 (`package.json:153-156`; peerDeps `:136-139` giữ `*`), host pi 1.0.4. (3) **U2-lite MCP parity cut** — parity spawns fold `mcp__*` vào disallow list trên MỌI host (`pi-args.ts:414`) + `--no-mcp` khi host ≥ `PI_NO_MCP_FLOOR="1.0.4"` (`pi-version.ts:76`, gate `pi-args.ts:430`); hermetic spawns MCP-clean qua `--no-extensions` — probe loadout: worker KHÔNG thấy `mcp__*` là ĐÚNG trên cả parity lẫn hermetic path (verdict `docs/reviews/pi-1.0.4-upgrade-notes-2026-10-06.md`). (4) **RPC transport wired (W7)** — `PI_CREW_WORKER_TRANSPORT=rpc` chọn RPC transport tại run-worker seam (`runWorker`, `src/runtime/run-worker.ts:138`; env names `src/runtime/rpc/rpc-worker.ts:43-49`), precedence **env > `runtime.workerTransport` config > stdio**, invalid → stdio (`config-schema.ts:157`); probe recipe = T7 smoke với `PI_CREW_WORKER_TRANSPORT=rpc`; DR1/DR5 exit-race hardening + `PI_CREW_RPC_TURN_TIMEOUT_MS` (default 600_000; dialog policy `PI_CREW_RPC_DIALOG_ANSWER` default `cancel`) — suite `run-worker-rpc-seam.test.ts` (8) có 3 scenario MỚI: DR1 exit-race `:223`, DR5 started-then-fail KHÔNG fallback `:266`, DR1 turn-timeout `:298` (+ truth table `:328`); pin kèm `test/unit/runtime/rpc/rpc-worker.test.ts` (10). RPC vẫn EXPERIMENTAL — fail trước agent output → stdio fallback (structured warn). (5) **Classifier seam DORMANT (P2-1)** — default OFF (`config-schema.ts:95`; `resolveClassifierEnabled`: env `PI_CREW_CLASSIFIER_ENABLED` > config > FALSE, `classifier-service.ts:158`); battery KHÔNG dính trừ khi set `PI_CREW_CLASSIFIER_ENABLED=1` (+ `PI_CREW_CLASSIFIER_MODEL`, default `opencode/jev-1.13-free`) — unit-only (`classifier-service.test.ts` 14 + `child-executor-retry-triage.test.ts` 6), KHÔNG live tier. (6) **Pre-push hook (D3)** — `.githooks/pre-push` qua `git config core.hooksPath .githooks` (wired `package.json` `prepare` → `scripts/install-hooks.mjs`): MỌI push chạy `check:conflict-markers` + typecheck; push `refs/heads/main` TỰ chạy FULL `test:unit` (~13-14 phút) rồi mới in `[pre-push] gates green.`; bypass `git push --no-verify` CHỈ khẩn cấp (CI vẫn gate main). (7) **GH#62 foreground completion** (`62c9ed0d`→`51adb1e1`→`3ed0067e`→`c956b2d4`→`af462d7b`) — foreground-run completion path sống sót qua spread-copy contexts; suite `test/unit/extension/registration/foreground-run-completion.test.ts` (4 tests). (8) **hermeticWorkers DEFAULT ON** (`config-schema.ts:89`; env `PI_CREW_HERMETIC_WORKERS`; `resolveHermeticWorkers` `pi-args.ts:149` — `explicit ?? true`). (9) **U9 version-floor wiring** — suites `test/unit/runtime/child-pi/pi-version.test.ts` (11) + `test/unit/runtime/model/pi-args-version-floor.test.ts` (7) + `test/unit/runtime/child-pi/pi-version-floor-wiring.test.ts` (2). (10) **RT-11 lesson (`48cc088d`)** — static spawn-site scan (`child-pi-spawn-registration.test.ts:33`) đếm CẢ prose trong comment (`spawn (`); khi dash vì comment → **reword comment, KHÔNG relax test**. Suite anchors @ 2026-10-07: unit **8711 tests / 8707 pass / 1 flaky-under-load / 3 skipped** (968 files, ~13 min; flaky = `team-tool-resume-liveness` F1 liveness race — 6/6 pass isolated ×3, KHÔNG phải regression), integration **139 / 135 pass / 4 skipped** (exit 0 — CHỈ khi scrub ĐỦ `PI_CREW_*`/`PI_TEAMS_*`, xem Failure-symptoms row MAX_DEPTH), `test:critical` **120** (~19-20s), bundle **1620.1 KB** (1,658,985 B) md5 `20544cf9ea436c69b0b434462def91b9` (`--committed-hash` OK), event registry **176 registered / 141 emitted** (`check:event-types --enforce` clean), devDeps `@earendil-works/*` ^1.0.4 / host pi **1.0.4**.
|
|
154
|
+
> **2026-10-08 update (L-wave UI instability review + L10 plan flicker + P0 completion crash, commits `28e0d58d`+`c068fc4a`+`c89c759a`, report `docs/real-test/reports/real-test-2026-10-07-ui-instability-review.md` + fix-wave addenda)**: (1) **P0 — completion throw giết cả pi**: `/team-transcript` popup race làm input dính `/<cmd>` suffix vào runId token → `assertSafePathId` throw bên trong `CombinedAutocompleteProvider.getSuggestions` (pi core KHÔNG catch lỗi extension) → uncaught_exception chết cả process. Fix: MỌI completion provider (`suggestTaskIds`, `suggestRunIds`…) try/catch → null; pin test + mutation. **Evidence source mới: `~/.pi/agent/crashes.json`** — khi pi/tmux chết bất ngờ giữa probe, đọc file này TRƯỚC khi đoán (có kind/message/stack qua dist). Decision table có row mới cho command-completions. (2) **L10 — plan card flicker**: tasks variant không được paint spinner động (comment thiết kế của chính nó); signature phải strip `:spin=`. Dock giữ đúng MỘT dòng spinner (chủ ý). (3) **Probe-hygiene lessons** (đều tốn điều tra giả session này): tmux `new-session -t <sess>` tạo GROUPED session (cùng process — vô dụng cho bystander probe; phải `new-session -d -s <tên> "cd … && exec pi"`); `pkill -f <pattern>` từ bash của assistant TỰ MATCH command line của chính nó (chuỗi literal nằm trong args/heredoc — bracket-trick không đủ; kill bằng PID hoặc tên script riêng); so sánh frame theo row-index bị transcript-scroll làm nhiễu — so BLOCK theo marker `┏ NAME ▸`…`┗`, và dock có HAI dạng render (`┏ CREW ▸` mở rộng / `┃ CREW ▸` thu gọn — marker phải match cả hai, từng gây báo động giả "dock biến mất"); dispatch sync run khi có run khác đang chạy → assistant có thể join/wait run cũ thay vì tạo run mới (luôn verify runId mới trong `.crew/state/runs/` trước khi probe). (4) **Load-flake rule**: `test:critical` đỏ 1 suite lạ + treo isolation dưới load 82+ (build song song của user) = starvation, KHÔNG phải regression — check `uptime` TRƯỚC, re-run khi máy êm (session này: symlink-steering treo dưới load 82, 120/120 xanh khi load 0.8). Suite anchors @ 2026-10-08: `test:critical` **120**, bundle **1622.6 KB** md5 `4f76457497bd20779e298cee4d8d982e`.
|
|
143
155
|
> **2026-09-21 update (F-L2 — steer boot-window loss, found by the live feature battery)**: a steer written to `<artifactsRoot>/steering/<taskId>.jsonl` while the worker extension is still LOADING was silently lost forever — `registerPiTeamsPromptRuntime` starts the file poll at load time, pi's loader gates action methods until bind (`sendMessage: notInitialized` THROWS), and the old poll advanced `lastOffset` to `stat.size` BEFORE the line loop while its per-line catch swallowed the throw as "malformed line" (run `team_20260921035840`, root-caused by watcher-driven bisection probes R7-R9: +0.65s post-boot = lost, +2.5s+ = delivered). Fix (`src/prompt/prompt-runtime.ts`): walk the buffer by byte offset, advance only past terminal verdicts (delivered/non-steer/rejected/malformed), rewind to the failing line on a DELIVERY failure, `createSeenSteerIdSet.unmark()` releases the dedup id so the retry is not skipped. Regression suite `test/unit/prompt/prompt-runtime-steer-boot-window.test.ts` (4 tests) — mutation-checked both layers (offset-revert → 4 fail; unmark-removal → exactly the id-bearing test fails). Note: `dist/index.mjs` is UNCHANGED by this fix — child workers load prompt-runtime from the SOURCE path (`pi-args.ts PROMPT_RUNTIME_EXTENSION_PATH`), so the fix is live without a bundle bump.
|
|
144
156
|
>
|
|
145
157
|
> **F-L2 live re-verification (post-restart, 2026-09-21 afternoon)** — two independent proofs: (a) **lab**: pre-write the steer, then `PI_CREW_STEERING_FILE=<file> pi --extension <repo>/src/prompt/prompt-runtime.ts -p '<long task>'` — stderr shows `[pi-crew:prompt-runtime.steer-delivery-failed] Extension runtime not initialized…` ×2 (pre-bind ticks now LOGGED instead of swallowed) then the post-bind tick delivers and the model complies; (b) **real team run**: watcher writes at **+0.51s** after the steering dir appears (the previously-lost window) → worker session log gains the `custom_message` and the probe token lands in `results/<taskId>.txt`. Suite anchors @ 2026-09-21 (post-fix): unit **8006 tests / 8003 pass / 0 fail / 3 skipped** (875 files; 1088s under load), integration **134 / 130 pass / 4 skipped**, `test:critical` **116**, bundle **3360.1 KB** md5 `2f45df91ed0580ee5bb5b9b57a8a8c3f` (UNCHANGED — see the source-path note above).
|
|
@@ -202,11 +214,11 @@ The skill maps to existing CI gates as follows:
|
|
|
202
214
|
| Bundle-staleness check (incl. **ARCH-7 path-leak scan** since `7d18508b` — line-scans `dist/index.mjs` + structural sourcemap check for tracked-source leaks) | Tier 3 last step | `scripts/check-bundle-staleness.mjs`; `--committed-hash` mode = Tier 11j release gate |
|
|
203
215
|
| `npm run test:bundle` (bundle import smoke, 2 tests) | Tier 3 post-build sanity | `test/unit/bundle-load.test.ts` — routed through the guarded `scripts/test-runner.mjs` since RR-021 round-3 (was a bare `node --test` bypass, the only CI gate without the wrappers) |
|
|
204
216
|
| `node scripts/release-smoke.mjs` (manual, release cut) | Tier 3/11j companion | ARCH-6: installs pi-* peer deps, `import()`s the tarball-installed bundle (`:77`), shape-checks exports |
|
|
205
|
-
| Full `npm test` (= unit
|
|
217
|
+
| Full `npm test` (= unit 968 files + integration 32 + 3 slow @ 2026-10-07) | n/a — too slow for in-loop | CI only; slow tier (3 files) is a SEPARATE glob `test:integration:slow` — only `npm run test:full` includes it |
|
|
206
218
|
| `PI_CREW_SMOKE=1` env | Tier 11e | set ONLY in `weekly-smoke.yml` (auth-gated); nightly.yml deliberately does NOT (comment at `:24`) |
|
|
207
219
|
| `npm run check:decision-drift` | Tier 11 (doc↔code) | **build-blocking in `.github/workflows/ci.yml` since 2026-09-17** (review-remediation baseline): every `PI_CREW_*` token cited in `docs/decisions/*.md` must exist in `src/` |
|
|
208
220
|
| `npm run check:env-vars` | Tier 11 | **build-blocking in `ci.yml` since 2026-09-17**: every `PI_CREW_*` read must be routed via `getCrewEnv` + registered |
|
|
209
|
-
| `npm run check:event-types -- --enforce` | Tier 9a/11 | **build-blocking in `ci.yml` since 2026-09-17**: event registry (`src/state/contracts.ts`) must cover every emitted type — 168 registered / 0 drift @ 2026-09-17 (was 89, drift silent); **169 @ 2026-10-01** sau SDD-2 (+`task.mcp_enforcement_degraded`) |
|
|
221
|
+
| `npm run check:event-types -- --enforce` | Tier 9a/11 | **build-blocking in `ci.yml` since 2026-09-17**: event registry (`src/state/contracts.ts`) must cover every emitted type — 168 registered / 0 drift @ 2026-09-17 (was 89, drift silent); **169 @ 2026-10-01** sau SDD-2 (+`task.mcp_enforcement_degraded`); **176 registered / 141 emitted @ 2026-10-07** — đếm bằng chính enforcement script (trong `TEAM_EVENT_TYPES` có 1 token trùng: 177 tokens / 176 unique) |
|
|
210
222
|
| `npm run check:lazy-imports` | Tier 3 companion (RR-021 WI-2.3 + review rounds 2-4) | `scripts/check-lazy-imports.mjs` — src-side: every runtime `import()` position needs a `// LAZY:` marker (known gaps: ternary-else / object-property / case-label / runtime member-access after same-line colon — documented in-script); dist-side: no module-scope hoisted heavy import (esbuild/acorn/diff/jiti/cli-highlight/yaml/ajv). Build-blocking at `ci.yml:142` |
|
|
211
223
|
| `npm run check:bundle-size` | Tier 3 companion | `scripts/check-bundle-size.mjs` — committed bundle ≤ budget (Sprint 6 gate, `ci.yml:169`; budget re-anchored when RR-021 shrank the bundle 3360→1575 KB) |
|
|
212
224
|
| `PI_CREW_TEST_RUNNER_TIMEOUT_MS` env | Tier 1 companion | overrides the test-runner spawn deadline (`scripts/test-runner.mjs:419` since RR-021; was :206); default **1_500_000 ms** since 2026-09-17 (was 900_000 — sized for a 5800-test suite; the full suite outgrew it and the ETIMEDOUT became a false green pre-F05). Since RR-021 rounds 2-3 the runner ALSO fail-closes on `# cancelled N>0` (TAP dual-reporter scrape) and on explicitly-listed missing files — see `test/unit/scripts/test-runner-exit.test.ts` (21 tests) |
|
|
@@ -235,11 +247,11 @@ To add Tier 1 to CI as a fast-feedback gate (under 30s):
|
|
|
235
247
|
|
|
236
248
|
---
|
|
237
249
|
|
|
238
|
-
## Tier 1 — Critical unit tests (~
|
|
250
|
+
## Tier 1 — Critical unit tests (~19s, 120 tests, the only suite you need for broker/UI changes)
|
|
239
251
|
|
|
240
|
-
**What**: run the curated
|
|
252
|
+
**What**: run the curated 15-file fast subset.
|
|
241
253
|
|
|
242
|
-
**Why this exists**: full `npm run test:unit` runs
|
|
254
|
+
**Why this exists**: full `npm run test:unit` runs 968 files (was 642 at skill-writing time — it keeps growing), several minutes. Verifier worker response timeout would kill the worker mid-run → run = "hang". The fix (introduced in commit `1cb2dca`) splits out a `test:critical` subset covering exactly what changed in the broker/UI work.
|
|
243
255
|
|
|
244
256
|
**How**:
|
|
245
257
|
|
|
@@ -247,16 +259,16 @@ To add Tier 1 to CI as a fast-feedback gate (under 30s):
|
|
|
247
259
|
time npm run test:critical
|
|
248
260
|
```
|
|
249
261
|
|
|
250
|
-
Expected output: `# tests
|
|
262
|
+
Expected output: `# tests 120 # pass 120 # fail 0 # cancelled 0 # duration_ms ~19965`. (Count was 97 at v0.9.46, 101 at v0.9.66, 102 at the waitMethodsEnabled flip, 116 since 2026-09-20, **120 @ 2026-10-07** (+`child-executor-heartbeat-pulse.test.ts` → 15 files) — verify with the actual run; the skill's hard-coded numbers drift between releases.) **Since RR-021 round-2 the runner itself fails loudly on `# cancelled N>0`** (dual-reporter TAP scrape — the round-1 unref incident shipped green with 2 cancelled tests), and **round-3 added the missing-file pre-check**: an explicitly-listed file that does not exist now exits 1 naming the path instead of being silently skipped by node:test.
|
|
251
263
|
|
|
252
264
|
**References**:
|
|
253
265
|
|
|
254
266
|
| What | Where |
|
|
255
267
|
|---|---|
|
|
256
|
-
| Script definition | `package.json:
|
|
268
|
+
| Script definition | `package.json:91` — list of 15 files passed to `node scripts/test-runner.mjs` |
|
|
257
269
|
| Introduced in commit | `1cb2dca fix(verifier): use test:critical instead of test:unit to avoid worker timeout` |
|
|
258
270
|
| Runner wrapper | `scripts/test-runner.mjs` — injects `--test-force-exit`, forwards to `tsx --test` |
|
|
259
|
-
| The
|
|
271
|
+
| The 15 files | broker: `test/unit/runtime/broker/crew-broker-{handshake,stale-socket,feature-flag,server-gate,client-fallback,mailbox-observer,close-during-reconnect,steer-dedup,symlink-steering}.test.ts`; UI: `test/unit/ui/keybinding-map.parity.test.ts`, `test/unit/ui/pi-tui-dispatch-probe.test.ts`; utils: `test/unit/utils/session-utils-extract.test.ts`; config: `test/unit/config/config-schema-sync.test.ts`; spawn env: `test/unit/runtime/child-pi/child-pi-env-spread.test.ts`; heartbeat: `test/unit/runtime/task-runner/child-executor-heartbeat-pulse.test.ts` (15th file @ 2026-10-07) |
|
|
260
272
|
| Failure mode that motivates it | Worker timeout in `src/runtime/child-pi/child-pi-constants.ts:23` (`RESPONSE_TIMEOUT_MS = DEFAULT_CHILD_PI.responseTimeoutMs` — 300000 at the time, now 600000); verifier LLM ran `npm test` and got killed with exit 143 (SIGTERM) |
|
|
261
273
|
|
|
262
274
|
**Run after**: any edit to `src/runtime/broker/*.ts`, `src/ui/`, `src/config/`, `src/extension/registration/lifecycle-handlers.ts`, or `src/runtime/child-pi/*.ts`.
|
|
@@ -287,7 +299,7 @@ PI_CREW_BROKER=0 npm run test:critical
|
|
|
287
299
|
PI_CREW_BROKER=1 npm run test:critical
|
|
288
300
|
```
|
|
289
301
|
|
|
290
|
-
All three must show `# pass
|
|
302
|
+
All three must show `# pass 120 # fail 0`. Measured times in this session (2026-08-11): ~26s for default, ~26s for `PI_CREW_BROKER=0`, ~26s for `PI_CREW_BROKER=1` (varies ±1-2s run-to-run).
|
|
291
303
|
|
|
292
304
|
**References**:
|
|
293
305
|
|
|
@@ -328,7 +340,7 @@ Compare the printed md5 against what the user's Pi session loaded. If they diffe
|
|
|
328
340
|
| Bundle builder | `scripts/build-bundle.mjs` (esbuild-based, bundles `index.bundle.ts` → `dist/index.mjs`) |
|
|
329
341
|
| Bundle resolution rule | `index.ts:1-25` (entrypoint docstring); also `scripts/build-bundle.mjs:14-20` (entrypoint preference); **symlink is live for source files but the bundled `dist/index.mjs` is loaded** |
|
|
330
342
|
| Postinstall hook | `scripts/postinstall.mjs:43` — best-effort bundle rebuild; falls back to strip-types if esbuild missing |
|
|
331
|
-
| Bundle md5 anchors | `1cc4d55e18add7b9a036c569143320b6` (Phase-4 flip, ~2.78 MB) → `16e29d053bd370e24f40df147dadcb79` (v0.9.66, 2026-08-11) → `9b557ac106b82e1ee33d39dd0d6c7dd7` (post-MuxSurface-A1 main, 2026-08-27) → `945720b1ad25673d86e263cdd834532f` (post-Batch-10 branch tip `aa899a1e`, 2026-09-11, ~3.30 MB) → `25ffc88e9a13611f61871b4c4a5b17ab` (review-remediation F01–F20 wave, 2026-09-17, 3357.3 KB) → `3860c0264940e7df91511da493fa375e` (2026-09-26, 1677.8 KB) → **`35ca335a90da01ac631493f220aaf121`** (RR-021 wave, 2026-09-29, **1575.2 KB** — lazy esbuild/acorn/diff shims + ajv external + −767 dead lines). **Always check current**: `md5sum dist/index.mjs` |
|
|
343
|
+
| Bundle md5 anchors | `1cc4d55e18add7b9a036c569143320b6` (Phase-4 flip, ~2.78 MB) → `16e29d053bd370e24f40df147dadcb79` (v0.9.66, 2026-08-11) → `9b557ac106b82e1ee33d39dd0d6c7dd7` (post-MuxSurface-A1 main, 2026-08-27) → `945720b1ad25673d86e263cdd834532f` (post-Batch-10 branch tip `aa899a1e`, 2026-09-11, ~3.30 MB) → `25ffc88e9a13611f61871b4c4a5b17ab` (review-remediation F01–F20 wave, 2026-09-17, 3357.3 KB) → `3860c0264940e7df91511da493fa375e` (2026-09-26, 1677.8 KB) → **`35ca335a90da01ac631493f220aaf121`** (RR-021 wave, 2026-09-29, **1575.2 KB** — lazy esbuild/acorn/diff shims + ajv external + −767 dead lines) → **`20544cf9ea436c69b0b434462def91b9`** (2026-10-07, **1620.1 KB** / 1,658,985 B — pi 1.0.4 adoption + RPC transport wiring + U2-lite MCP cut). **Always check current**: `md5sum dist/index.mjs` |
|
|
332
344
|
|
|
333
345
|
---
|
|
334
346
|
|
|
@@ -402,6 +414,20 @@ tmux capture-pane -t pi -p > /tmp/screen-after-up.txt
|
|
|
402
414
|
| App-cursor-mode | `\x1bOA` | `\x1bOB` | vim, less, full-screen apps |
|
|
403
415
|
| Kitty protocol | `\x1b[1;2A` (Shift+Up) etc. | — | modern terminals (kitty, foot, ghostty) |
|
|
404
416
|
|
|
417
|
+
**Completion-popup probe (P0 2026-10-08 — dùng khi đụng `command-completions.ts` / slash-command handlers)**: completion callbacks chạy trong `CombinedAutocompleteProvider.getSuggestions` của pi core — nơi KHÔNG catch lỗi extension, một throw = chết cả pi process. Probe:
|
|
418
|
+
|
|
419
|
+
```bash
|
|
420
|
+
# (a) input từng gây crash: runId token dính suffix "/<cmd>" + trailing space cho popup fire
|
|
421
|
+
tmux -S /tmp/sock send-keys -t pi '/team-transcript team_20261008_xxx/team-transcript '
|
|
422
|
+
sleep 2.5; tmux -S /tmp/sock ls >/dev/null && echo ALIVE # phải sống
|
|
423
|
+
# crashes.json phải KHÔNG có entry mới (đọc ~/.pi/agent/crashes.json, lọc timestamp > thời điểm probe)
|
|
424
|
+
# (b) flow hợp lệ: runId thật + space + 1 ký tự → popup gợi ý task id
|
|
425
|
+
tmux -S /tmp/sock send-keys -t pi C-c
|
|
426
|
+
tmux -S /tmp/sock send-keys -t pi '/team-transcript <runId-thật> '
|
|
427
|
+
sleep 2; tmux -S /tmp/sock send-keys -t pi '0'; sleep 2
|
|
428
|
+
tmux -S /tmp/sock capture-pane -t pi -p | grep -aE '0[123]_' | head -3 # kỳ vọng 01_explore/02_execute…
|
|
429
|
+
```
|
|
430
|
+
|
|
405
431
|
**References**:
|
|
406
432
|
|
|
407
433
|
| What | Where |
|
|
@@ -474,7 +500,7 @@ else:
|
|
|
474
500
|
|
|
475
501
|
**What**: prove the verifier worker completes within `RESPONSE_TIMEOUT_MS` (**600s since the stuck-worker hardening — was 300s when this skill was distilled; `DEFAULT_CHILD_PI.responseTimeoutMs = 10 * 60_000`**).
|
|
476
502
|
|
|
477
|
-
**Why this is its own tier**: `test:critical` covers unit-level invariants, but the verifier LLM is a separate failure mode — it reads the verifier prompt from `src/runtime/goal-workflow/plan-templates.ts:144, 147` (taskTemplate strings) or from `workflows/*.workflow.md` (workflow verifier sections), then decides which bash command to run. If the prompt says "Run tests" without specifying which, the LLM runs `npm test` (
|
|
503
|
+
**Why this is its own tier**: `test:critical` covers unit-level invariants, but the verifier LLM is a separate failure mode — it reads the verifier prompt from `src/runtime/goal-workflow/plan-templates.ts:144, 147` (taskTemplate strings) or from `workflows/*.workflow.md` (workflow verifier sections), then decides which bash command to run. If the prompt says "Run tests" without specifying which, the LLM runs `npm test` (968 files) and the worker gets killed by the response timeout with exit 143.
|
|
478
504
|
|
|
479
505
|
**How** (from parent Pi session — `team` is a tool, not a shell command):
|
|
480
506
|
|
|
@@ -788,7 +814,7 @@ grep -n "Log the event first" src/runtime/recovery/crash-recovery.ts # design
|
|
|
788
814
|
# 3. buffered-site census — snapshot & audit:
|
|
789
815
|
grep -rln "appendEventBuffered" src/ | wc -l # 15 files @ 2026-09-29 (16 at v0.10.5; RR-021 WI-4.2 dead-code sweep removed one); audited live conversions = 43; EVERY new site needs the reader-audit
|
|
790
816
|
# 4. the full gate — test:critical has NO stores/dwf/recovery coverage:
|
|
791
|
-
npm run test:unit #
|
|
817
|
+
npm run test:unit # 968 files, ~8711 tests @ 2026-10-07, ~13 min (785s node measured 2026-10-07; 1088s under load 2026-09-21) — MANDATORY after any delayed-write conversion program
|
|
792
818
|
```
|
|
793
819
|
|
|
794
820
|
### 11b. wc-gate enforcement (M4 done-gate)
|
|
@@ -1088,7 +1114,7 @@ PY
|
|
|
1088
1114
|
| Test using real `loadConfig()` to mock config | Flaky when env / disk config changes | `612e18b` | `test/unit/runtime/broker/crew-broker-server-gate.test.ts:78` (use `brokerEnv: "0"` instead of `flagOn: false`) |
|
|
1089
1115
|
| Source edit seen immediately | No, requires bundle rebuild + reload | n/a (permanent) | `index.ts:1-25` — bundle resolution rules |
|
|
1090
1116
|
| Skip disabled-path proof | `effectiveEnabled()` regression slips through | n/a (permanent) | Tier 2 above |
|
|
1091
|
-
| `npm run test:unit` against the full suite (
|
|
1117
|
+
| `npm run test:unit` against the full suite (968 files now, 642 then) | several minutes; mis-judges verifier runtime | n/a (permanent) | Tier 1 above |
|
|
1092
1118
|
| Skip typecheck | TS errors slip past `test:critical` (which uses `--test-timeout=30000`) | n/a (permanent) | Tier 3 above |
|
|
1093
1119
|
| Run `pi` from a stale bundle | Session shows old behavior despite src/ edits | n/a (permanent) | `scripts/check-bundle-staleness.mjs` — CI gate |
|
|
1094
1120
|
| Test by reading code | Proves nothing about runtime | n/a (permanent) | All tiers above |
|
|
@@ -1124,6 +1150,11 @@ PY
|
|
|
1124
1150
|
| **Declaring a red gate "pre-existing" (or "my regression") from reasoning alone** (2026-09-16): `check:env-vars` was red; the file was untouched, but that is an argument, not evidence. | n/a (process) | Prove it in a clean-HEAD worktree: `git worktree add -q /tmp/pc-head HEAD && (cd /tmp/pc-head && node scripts/check-env-vars.mjs); git worktree remove --force /tmp/pc-head` | Same recipe as the broker-flake proof (Tier 1 / Failure symptoms) |
|
|
1125
1151
|
| **Shipping a catalog PNG with tofu boxes** (2026-09-16): the catalog rendered the braille spinner + `⟳` + `⎿` as `□` — invisible in the `.txt` captures, obvious the moment the image was opened. | `docs/ui-samples/render_png.py` glyph self-check | Make the renderer FAIL on any character it cannot paint (compare against the `.notdef` box), then map the offender | Tier 13 "Catalog" + `render_png.py` (`_has_glyph`, `BRAILLE_TO`) |
|
|
1126
1152
|
| **Treating `wait-request-broker.test.ts` load-timeout as a product bug**: the test runner's per-file 180s timeout is below this file's full-suite runtime under parallel load — fails only with the whole suite, passes in isolation. Pre-existing flake, NOT a regression from your change. | n/a (test infra) | Re-run the single file before fixing anything: `node scripts/test-runner.mjs test/unit/runtime/broker/wait-request-broker.test.ts`. Green in isolation = infra flake; move on. |
|
|
1153
|
+
| **Pipe nuốt exit code của gate** (GH#62 wave, `51adb1e1`): `npm run typecheck \| tail -1` trả về exit của `tail` (0) — một type error từng được ship vì gate chạy qua pipe. | n/a (process) | KHÔNG bao giờ pipe một gate qua `tail`/`head`; chạy thẳng, hoặc `set -o pipefail` khi bắt buộc. Commit `51adb1e1` "pipe-swallowed gates in the previous commit" |
|
|
1154
|
+
| **Fake cache shape sai** (GH#62 CI-shard catch, `3ed0067e`): fake `new Map()` thiếu `.list()` → crash ở manifestCache path khi test chạm code thật. | `3ed0067e` | Dùng factory thật `createManifestCache(tmpdir)` (`src/runtime/manifest-cache.ts:218`, `.list()` :306) thay vì hand-rolled Map giả |
|
|
1155
|
+
| **URL win32 không đối xứng**: path Windows (`C:\…`) không phải URL hợp lệ khi truyền qua argv/env giữa process | n/a (permanent) | Luôn `pathToFileURL()` phía gửi + `fileURLToPath()` phía nhận, đối xứng với nguồn — tham chiếu cặp đang dùng: `src/runtime/peer-dep.ts:40,90,211` |
|
|
1156
|
+
| **RT-11 scan đếm cả comment prose** (`48cc088d`): static spawn-site scan regex `spawn\s*\(` match CẢ text trong comment — một comment "spawn (and…" thành call-site thứ 4 trong khi chỉ có 3 call thật + register | `48cc088d` | **Reword COMMENT, KHÔNG relax test** — enforcer là `test/unit/runtime/child-pi/child-pi-spawn-registration.test.ts:33` (regex cố ý lỏng) |
|
|
1157
|
+
| **Stale-test-after-refactor class — 3 vòng CI đỏ liền 2026-10-04/05**: test pin layout/text cũ không theo kịp refactor lành tính (literal-count 4→5 subsections sau khi chia section — `test/unit/runtime/core/task-handoff-template.test.ts`, commit `d7923d38`; OSC-8 dock-link regex — `test/unit/ui/widget-osc8-link.test.ts`, commit `db70cc82`; T-6b storm tick — `test/unit/runtime/task-runner/state-helpers-cas-contention.test.ts`, commit `57f1bbf8`). Hook header gọi đúng: "three waves in a row shipped red" | n/a (process) | Full suite trước push — giờ `.githooks/pre-push` enforce trên push main (update 2026-10-07); refactor layout/text → cập nhật pin test CÙNG commit |
|
|
1127
1158
|
|
|
1128
1159
|
---
|
|
1129
1160
|
|
|
@@ -1133,6 +1164,12 @@ When a tier fails, the recovery is usually quick. Match the symptom to the cause
|
|
|
1133
1164
|
|
|
1134
1165
|
| Symptom | Likely cause | Recovery |
|
|
1135
1166
|
|---|---|---|
|
|
1167
|
+
| Pi process / tmux server chết bất ngờ giữa probe (capture-pane báo "no server running") | **Extension giết pi bằng uncaught exception** — pi core không catch lỗi extension trong autocomplete provider / async callback. P0 2026-10-08: `Invalid runId: team_x/team-transcript` từ `assertSafePathId` qua `suggestTaskIds` | Đọc `~/.pi/agent/crashes.json` TRƯỚC khi đoán gì khác — có `kind`/`message`/`stack` (symbol qua `dist/index.mjs` → map lại src). Session mới mở cũng hiện banner "pi crashed on …" kèm message. Fix pattern: callback phải try/catch → degrade, KHÔNG bao giờ throw ra ngoài |
|
|
1168
|
+
| `test:critical` đỏ đúng 1 suite lạ (broker/steering) + treo cả khi chạy isolated, trong khi xanh hoàn toàn vài giờ trước | **Starvation dưới load cao** (build song song, load 80+): broker handshake/timeout-based tests chết đói CPU, KHÔNG phải regression từ thay đổi UI — session 2026-10-08 đỏ symlink-steering dưới load 82, 120/120 xanh lại khi load 0.8 | `uptime` + `ps -eo pcpu --sort=-pcpu | head` TRƯỚC; đợi/re-run khi máy êm; chỉ chẩn đoán regression khi đỏ lại trên máy sạch |
|
|
1169
|
+
| Probe session thứ 2 (bystander) hiển thị y hệt session 1, keystroke session này ảnh hưởng session kia | `tmux new-session -t <sess>` tạo **GROUPED session** — cùng window/cùng process, không phải pi riêng | Bystander phải STANDALONE: `tmux -S <sock> new-session -d -x 150 -y 50 -s by "cd <cwd> && exec pi 2>&1"` (KHÔNG dùng `-t`); verify bằng 2 PID pi riêng trong `ps` |
|
|
1170
|
+
| Bash của assistant tự chết exit 143 ngay sau lệnh `pkill -f <pattern>` | **pkill tự match**: command line của chính bash chứa chuỗi pattern (trong heredoc/args) — bracket-trick `pat[.]tern` KHÔNG đủ khi chuỗi literal nằm trong tham số | Đặt tên script capture riêng (capV7.sh…), kill bằng `pkill -f loopV7` với tên KHÔNG xuất hiện trong lệnh hiện tại, hoặc kill theo PID ghi sẵn |
|
|
1171
|
+
| So sánh frame theo row-index cho hàng trăm "diff" giả (mọi row "đổi" liên tục) | **Transcript scroll**: output worker/stream làm mọi dòng dịch chuyển row — so row-index đếm toàn bộ là đổi | So BLOCK theo marker biên: `┏ PLAN`…`┗`, `┏ DASHBOARD`…, và LƯU Ý dock có 2 dạng: mở rộng `┏ CREW ▸` (có progress bar) / thu gọn `┃ CREW ▸` (1 dòng) — match cả hai, từng gây báo động giả "dock biến mất" |
|
|
1172
|
+
| Dispatch sync run nhưng không có run mới trong `.crew/state/runs/`, transcript nói "ran synchronously despite async=true" | Assistant/agent JOIN hoặc WAIT vào run đang chạy thay vì tạo run mới | Luôn verify runId mới xuất hiện (`ls -t .crew/state/runs/`) sau lệnh dispatch trước khi probe; dispatch khi không run nào active |
|
|
1136
1173
|
| `test:critical` returns `# fail N>0` | Regression in touched source | Read the failing test's name + assertion; fix the source; rerun |
|
|
1137
1174
|
| `test:critical` hangs >60s | One test opened a socket/pty that didn't close | Run individual file: `node --import tsx/esm --test --test-force-exit test/unit/<file>.test.ts`; check for missing `await` or unclosed handle |
|
|
1138
1175
|
| `typecheck` fails with `TS2xxx` | TS type drift after src/ edit | Fix the type error; do not commit until exit 0 |
|
|
@@ -1158,6 +1195,8 @@ When a tier fails, the recovery is usually quick. Match the symptom to the cause
|
|
|
1158
1195
|
| Ambient "N dead worker(s)" notification for a run that already reached a terminal status | Stale health marker re-firing on a terminal run — no live process behind it | Verify before acting: `ps -p <pid>` (dead), `manifest.status` (failed/done), `exit-code.txt`. Nothing to recover; marker clears via `/team-dashboard → health → K` (kill stale). Never kill a pid on a stale heartbeat alone — check pid + log first |
|
|
1159
1196
|
| Ambient "heartbeat dead"/"missing heartbeat" cho task guest `gc-*` (depth-2 delegate) trên run ĐANG CHẠY | Guest tasks không có kênh heartbeat (lifecycle do `delegate.requested/admitted/completed` sở hữu) — fixed 2026-09-26: watcher `73790eaa` + aggregator `b7ab5ef2` skip `agent==="delegate"` ở CẢ HAI lớp | Nếu tái xuất hiện trên build ≥ `b7ab5ef2`: check skip marker còn nguyên ở cả 2 nơi (watcher task-loop + `summarizeHeartbeats`). KHÔNG bao giờ kết luận worker thật chết chỉ từ notification của guest task — verify pid/manifest như row trên |
|
|
1160
1197
|
| Battery async run "xanh" nhưng event `async.spawned` có `data.inline:true`, hoặc không có process runner detached nào trong `ps` | **Seam leak**: shell có `PI_CREW_TEST_ASYNC_INLINE=1` (thường + `PI_CREW_ALLOW_MOCK=1`) export từ phiên test trước — async dispatch chạy in-process, battery đang chứng minh đường SAI (seam là unit-test tool) | Preflight battery: `env | grep PI_CREW_TEST_ASYNC_INLINE` phải RỖNG; sau mỗi async run trong T7/T9b: assert `async.spawned` KHÔNG có `data.inline`. Nếu dính: `unset` cả 2 biến rồi chạy lại tier |
|
|
1198
|
+
| Integration đỏ macOS/Node-24 `phase6` "argv must not contain task text" với task NGẮN (empty task vẫn xanh) — code giống hệt run xanh trước | **Random-path collision flake** (CI 2026-10-07): `@<mkdtemp-path>` argv arg chứa suffix ngẫu nhiên 6 ký tự [a-zA-Z0-9]; task 3 ký tự có P ≈ 1/15k bị substring-collision với suffix → assert `arg.includes(task)` tưởng là leak | Scan argv LOẠI arg `@<taskPath>` chính nó (fix `f67cf62d`) — path là random mkdtemp, không phải nội dung task; never "fix" bằng đổi task text dài hơn để trốn collision |
|
|
1199
|
+
| `phase6-runtime-hardening.test.ts` "depth guard blocks child workers at max depth before mock execution" fails 2/2 khi chạy từ worker shell dù xanh trong CI | **Env leak, không phải regression**: worker shell export sẵn `PI_CREW_MAX_DEPTH=4`/`PI_TEAMS_MAX_DEPTH=4` và `resolveCrewMaxDepth` ưu tiên ENV hơn `inputMaxDepth` tường minh (`src/runtime/model/pi-args.ts:128` — `env.PI_CREW_MAX_DEPTH ?? env.PI_TEAMS_MAX_DEPTH` check TRƯỚC input) → test set `maxDepth:2` vẫn thấy 4, `blocked:false` | Scrub ĐỦ biến (danh sách `-u` tĩnh KHÔNG đủ — biến thể của gotcha 2026-08-15): `SCRUB=$(env \| grep -oE '^(PI_CREW\|PI_TEAMS)_[A-Z_]+' \| sed 's/^/-u /' \| tr '\n' ' '); env $SCRUB npm run test:integration` |
|
|
1161
1200
|
| Steer written during worker BOOT never reaches the model (no error, no log; later steers work) | F-L2 (fixed 2026-09-21): poll advanced its offset past an entry whose `pi.sendMessage` threw pre-bind ("not initialized") and the per-line catch ate the throw — one-shot silent loss | Fixed in `prompt-runtime.ts` (offset rewind + dedup unmark); pinned by `prompt-runtime-steer-boot-window.test.ts`. On older builds: re-send the steer after ~5s — a steer that lands post-bind delivers fine |
|
|
1162
1201
|
| Steer "lost" but the file you wrote is FULL while a 0-byte `<taskId>.jsonl` sits beside it | **Probe bug, not a product bug** — the steering filename depends on run kind: team runs poll `<taskId>.jsonl`, crew_agent/subagent runs use `<slot>-agent.jsonl`; you wrote the wrong channel (no component reads it) | Re-run writing every `*.jsonl` in the steering dir (Tier 9g), or derive the name from the run kind. Cross-check `results/<taskId>.txt` + the worker session's `custom_message` before calling it a loss |
|
|
1163
1202
|
| Fix verified in unit tests but a live probe still fails | Live path ≠ unit path: wrong filename (above), wrong role/tool for the probe instruction, or the session did not cold-start the changed module | Confirm the loaded artifact (`--extension <path>` resolution for workers is the SOURCE file, so a restart is enough; parent-side needs bundle+restart), then re-run Tier 9g with text-only compliance |
|
|
@@ -1352,7 +1391,7 @@ The skill mentions specific commits, line numbers, and version pins. As the code
|
|
|
1352
1391
|
| Verify line refs after each `src/` commit | Every commit touching the cited file | `git log -p -- src/extension/registration/lifecycle-handlers.ts \| grep effectiveEnabled` — if line moved, update the skill |
|
|
1353
1392
|
| Verify commit hashes still exist | Quarterly or before major edits | `git log --oneline -1 <hash>` — if gone, find the equivalent newer commit |
|
|
1354
1393
|
| Verify version pins (v0.9.46, etc.) | Each release | `git log --oneline -- src/ui/run-dashboard.ts \| head -5` — confirm diag removal history (e3ee6fe2) still accurate |
|
|
1355
|
-
| Verify `test:critical` still has
|
|
1394
|
+
| Verify `test:critical` still has 15 files | Each `src/runtime/broker/*.ts` edit | `grep test:critical package.json` — adjust the file list |
|
|
1356
1395
|
| Verify Tier 7 verifier prompts still say `test:critical` | Each workflow file edit | `grep "Run FAST checks" workflows/*.workflow.md` |
|
|
1357
1396
|
| Verify Tier 10 surface refs | Each `src/runtime/surface/**` edit | `ls test/system/surface-*.e2e.test.ts` + grep `MAX_SURFACE_WORKERS` in resolve-surface.ts — cap/config shape may drift between A1 → A2 |
|
|
1358
1397
|
| Verify herdr wire details | Each herdr release bump | `herdr api schema --json` vs `src/runtime/surface/herdr-provider.ts` (envelope/pane.read source/1-conn-per-request were verified on herdr 0.8.2) |
|
|
@@ -1373,7 +1412,7 @@ The skill does NOT need to be updated for every commit — only when the cited l
|
|
|
1373
1412
|
## Quick reference — exact commands
|
|
1374
1413
|
|
|
1375
1414
|
```bash
|
|
1376
|
-
# Tier 1 (critical unit, ~
|
|
1415
|
+
# Tier 1 (critical unit, ~19s, 120 tests)
|
|
1377
1416
|
npm run test:critical
|
|
1378
1417
|
# Tier 2 (3-path proof, broker changes only)
|
|
1379
1418
|
PI_CREW_BROKER=0 npm run test:critical
|
|
@@ -1457,7 +1496,7 @@ PY
|
|
|
1457
1496
|
|
|
1458
1497
|
Before claiming "tested":
|
|
1459
1498
|
|
|
1460
|
-
- [ ] Tier 1: `test:critical` fresh-run, all pass (<25s). Count varies by release — was 97 at v0.9.46, 101 at v0.9.66, 102 at the waitMethodsEnabled flip,
|
|
1499
|
+
- [ ] Tier 1: `test:critical` fresh-run, all pass (<25s). Count varies by release — was 97 at v0.9.46, 101 at v0.9.66, 102 at the waitMethodsEnabled flip, 116 @ 2026-09-20, **120 @ 2026-10-07**; record the actual count in the report.
|
|
1461
1500
|
- [ ] Tier 2: 3-path proof all pass — **required if you touched `src/config/defaults.ts` or `src/extension/registration/lifecycle-handlers.ts`**
|
|
1462
1501
|
- [ ] Tier 3: `npm run typecheck` exit 0, `npm run build:bundle` exit 0
|
|
1463
1502
|
- [ ] Tier 4: bundle md5 matches what the session loaded (or user has `/quit`-ed + reopened)
|
|
@@ -390,10 +390,17 @@ function parseRuntimeConfig(value: unknown): CrewRuntimeConfig | undefined {
|
|
|
390
390
|
// F19-1 discipline: every key declared in types.ts + schema MUST be
|
|
391
391
|
// emitted here or the config key is dead (runtime.sessionRecovery —
|
|
392
392
|
// W2/P1-1; runtime.workerTransport — W7/P2-3, experimental;
|
|
393
|
-
// runtime.hermeticWorkers — R3-19/D5 reversal, hermetic spawns
|
|
393
|
+
// runtime.hermeticWorkers — R3-19/D5 reversal, hermetic spawns;
|
|
394
|
+
// runtime.classifierEnabled/classifierModel — P2-1 dormant classifier
|
|
395
|
+
// seam, consumed at child-executor's retry triage).
|
|
396
|
+
// Necessary but NOT sufficient: emission still needs a CONSUMER at the
|
|
397
|
+
// seam — workerTransport was parse+emit-only dead until D1/DR2 threaded
|
|
398
|
+
// it to resolveWorkerTransport (run-worker seam).
|
|
394
399
|
sessionRecovery: parseWithSchema(Type.Boolean(), obj.sessionRecovery),
|
|
395
400
|
hermeticWorkers: parseWithSchema(Type.Boolean(), obj.hermeticWorkers),
|
|
396
401
|
workerTransport: parseWithSchema(Type.Union([Type.Literal("stdio"), Type.Literal("rpc")]), obj.workerTransport),
|
|
402
|
+
classifierEnabled: parseWithSchema(Type.Boolean(), obj.classifierEnabled),
|
|
403
|
+
classifierModel: parseWithSchema(Type.String({ minLength: 1 }), obj.classifierModel),
|
|
397
404
|
};
|
|
398
405
|
return Object.values(runtime).some((entry) => entry !== undefined) ? runtime : undefined;
|
|
399
406
|
}
|
package/src/config/defaults.ts
CHANGED
|
@@ -138,7 +138,14 @@ export const DEFAULT_UI = {
|
|
|
138
138
|
widgetMaxLines: 8,
|
|
139
139
|
inlinePanel: true,
|
|
140
140
|
powerbar: true,
|
|
141
|
-
|
|
141
|
+
// L3 (2026-10-07 real-test review): default "right" — the centered 90%
|
|
142
|
+
// overlay leaves both margins showing chopped background words (pi-tui's
|
|
143
|
+
// compositeTuiLine keeps base.before/base.after visible outside overlay
|
|
144
|
+
// bounds by design); the right-anchored panel covers them. Mirror updates:
|
|
145
|
+
// install.mjs + the two EFFECTIVE_DEFAULTS maps (handle-settings.ts,
|
|
146
|
+
// settings-overlay.ts) — install-defaults-sync.test.ts enforces the first,
|
|
147
|
+
// G17 lesson enforces the rest.
|
|
148
|
+
dashboardPlacement: "right" as const,
|
|
142
149
|
dashboardWidth: 72,
|
|
143
150
|
dashboardLiveRefreshMs: 1000,
|
|
144
151
|
autoOpenDashboard: false,
|
package/src/config/env-vars.ts
CHANGED
|
@@ -457,12 +457,27 @@ export const CREW_ENV_VARS: Record<string, CrewEnvVarSpec> = {
|
|
|
457
457
|
},
|
|
458
458
|
PI_CREW_WORKER_TRANSPORT: {
|
|
459
459
|
name: "PI_CREW_WORKER_TRANSPORT",
|
|
460
|
-
doc: "W7 EXPERIMENTAL worker transport
|
|
460
|
+
doc: "W7 EXPERIMENTAL worker transport override: 'rpc' selects the prototype RPC frame-client (src/runtime/rpc/) at the run-worker seam (wired e2728f68; D1/DR2 also plumbs config runtime.workerTransport to the same seam — env WINS over config when set, invalid env fails safe to stdio); anything else/unset → config value, default stdio child-pi path (rpc-worker.ts resolveWorkerTransport)",
|
|
461
|
+
},
|
|
462
|
+
PI_CREW_CLASSIFIER_ENABLED: {
|
|
463
|
+
name: "PI_CREW_CLASSIFIER_ENABLED",
|
|
464
|
+
parser: "boolean",
|
|
465
|
+
doc: "P2-1 (pi 1.0.4 adoption) host-process retry-triage classifier override: '1' enables transient-vs-permanent classification before a queued re-attempt in the child-executor retry loop, '0' forces it off — beats runtime.classifierEnabled; default OFF / dormant (classifier-service.ts:resolveClassifierEnabled). Fallback decision is used on every classifier failure mode, never an error",
|
|
466
|
+
},
|
|
467
|
+
PI_CREW_CLASSIFIER_MODEL: {
|
|
468
|
+
name: "PI_CREW_CLASSIFIER_MODEL",
|
|
469
|
+
doc: "P2-1 classifier model id override ('provider/id', catalog ids only — availability depends on provider credentials at runtime): beats runtime.classifierModel; unset/blank → config value, default 'opencode/jev-1.13-free' (classifier-service.ts:resolveClassifierModel)",
|
|
461
470
|
},
|
|
462
471
|
PI_CREW_RPC_DIALOG_ANSWER: {
|
|
463
472
|
name: "PI_CREW_RPC_DIALOG_ANSWER",
|
|
464
473
|
doc: "W7 EXPERIMENTAL dialog auto-answer policy for RPC-mode extension_ui_request dialogs (select/confirm/input/editor): 'cancel' (default) answers {cancelled:true} — universal safe answer; 'block' leaves the server promise pending (debug). Auto-confirm deliberately NOT implemented (security); invalid → 'cancel' (rpc-worker.ts resolveDialogAnswerPolicy)",
|
|
465
474
|
},
|
|
475
|
+
PI_CREW_RPC_TURN_TIMEOUT_MS: {
|
|
476
|
+
name: "PI_CREW_RPC_TURN_TIMEOUT_MS",
|
|
477
|
+
parser: "int",
|
|
478
|
+
default: "600000",
|
|
479
|
+
doc: "W7/DR1 belt-and-suspenders turn timeout for the EXPERIMENTAL RPC worker transport: max ms a prompt-accepted turn may run without agent_settled before the transport fails with the early-failure shape (DR5 guard still blocks the stdio fallback once a session event was seen). Env-only while RPC stays experimental. Invalid/≤0 → 600000 (rpc-worker.ts resolveRpcTurnTimeoutMs)",
|
|
480
|
+
},
|
|
466
481
|
PI_CREW_AUTO_EXIT: {
|
|
467
482
|
name: "PI_CREW_AUTO_EXIT",
|
|
468
483
|
doc: "'1' → the worker shuts its session down after the final settled turn — spec §5.2 D7 (written by prepareSurfaceSpawn, read by surface-worker.ts)",
|
package/src/config/types.ts
CHANGED
|
@@ -89,6 +89,29 @@ export interface CrewRuntimeConfig {
|
|
|
89
89
|
* the flag — panes keep the full interactive session.
|
|
90
90
|
*/
|
|
91
91
|
hermeticWorkers?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* P2-1 (pi 1.0.4 adoption, 2026-10-07): host-process retry-triage
|
|
94
|
+
* classifier seam (src/runtime/classifier/classifier-service.ts —
|
|
95
|
+
* wrapper around ctx.modelRegistry.classify(), host process only).
|
|
96
|
+
* DORMANT by design: default false, and the consumer (child-executor
|
|
97
|
+
* retry loop) falls back to the pre-existing retry behavior on every
|
|
98
|
+
* classifier failure mode (unavailable / threw / stopReason!=='stop').
|
|
99
|
+
* Enabling opts INTO transient-vs-permanent classification before a
|
|
100
|
+
* queued re-attempt burns a full worker spawn. Env
|
|
101
|
+
* PI_CREW_CLASSIFIER_ENABLED overrides in either direction
|
|
102
|
+
* (resolveClassifierEnabled). Behavior pick, not authority — no
|
|
103
|
+
* sensitive mark.
|
|
104
|
+
*/
|
|
105
|
+
classifierEnabled?: boolean;
|
|
106
|
+
/**
|
|
107
|
+
* P2-1: classifier model id ("provider/id" form) for the seam above.
|
|
108
|
+
* Availability is credential-dependent at runtime (getAvailableOfType);
|
|
109
|
+
* a configured-but-uncredentialed id degrades to the fallback decision,
|
|
110
|
+
* never to an error. Default "opencode/jev-1.13-free"
|
|
111
|
+
* (DEFAULT_CLASSIFIER_MODEL); env PI_CREW_CLASSIFIER_MODEL overrides
|
|
112
|
+
* (resolveClassifierModel).
|
|
113
|
+
*/
|
|
114
|
+
classifierModel?: string;
|
|
92
115
|
promptMode?: "replace" | "append";
|
|
93
116
|
groupJoin?: "off" | "group" | "smart";
|
|
94
117
|
groupJoinAckTimeoutMs?: number;
|
|
@@ -126,10 +149,11 @@ export interface CrewRuntimeConfig {
|
|
|
126
149
|
/**
|
|
127
150
|
* W7 (P2-3) EXPERIMENTAL: transport used to spawn child-pi workers.
|
|
128
151
|
* "stdio" (default) — the production print-mode path, unchanged.
|
|
129
|
-
* "rpc" — prototype RPC frame-client (src/runtime/rpc/)
|
|
130
|
-
* seam
|
|
131
|
-
*
|
|
132
|
-
*
|
|
152
|
+
* "rpc" — prototype RPC frame-client (src/runtime/rpc/), wired at the
|
|
153
|
+
* run-worker seam since e2728f68 (D1/DR2 plumbing, 2026-10-06): callers
|
|
154
|
+
* carrying runtimeConfig thread it to the seam. Env
|
|
155
|
+
* PI_CREW_WORKER_TRANSPORT=rpc overrides this config (env wins —
|
|
156
|
+
* established precedence; invalid env fails safe to stdio).
|
|
133
157
|
*/
|
|
134
158
|
workerTransport?: "stdio" | "rpc";
|
|
135
159
|
/**
|