pi-crew 0.9.64 → 0.9.65

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 (36) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/README.md +46 -1
  3. package/dist/index.mjs +316 -299
  4. package/package.json +3 -2
  5. package/scripts/analyze-run.mjs +1333 -0
  6. package/scripts/pty_probe.py +10 -8
  7. package/scripts/resource-sampler.mjs +482 -0
  8. package/skills/real-test-pi-crew/SKILL.md +6 -6
  9. package/src/observability/event-to-metric.ts +29 -0
  10. package/src/observability/metrics-primitives.ts +41 -3
  11. package/src/runtime/README.md +1 -1
  12. package/src/runtime/broker/crew-broker.ts +0 -16
  13. package/src/runtime/effectiveness.ts +23 -1
  14. package/src/runtime/merge-gate.ts +202 -0
  15. package/src/runtime/model/model-fallback.ts +11 -0
  16. package/src/runtime/model/provider-extensions.ts +31 -12
  17. package/src/runtime/output/progress-tracker.ts +3 -33
  18. package/src/runtime/scratchpad/engine.ts +40 -2
  19. package/src/runtime/scratchpad/snapshot-hmac.ts +161 -0
  20. package/src/runtime/team-runner.ts +128 -203
  21. package/src/schema/team-tool-schema.ts +2 -0
  22. package/src/teams/discover-teams.ts +2 -0
  23. package/src/teams/team-config.ts +7 -0
  24. package/src/teams/team-serializer.ts +1 -0
  25. package/src/ui/mascot.ts +1 -14
  26. package/teams/default.team.md +1 -0
  27. package/teams/fast-fix.team.md +1 -0
  28. package/src/observability/event-bus.ts +0 -86
  29. package/src/plugins/plugin-define.ts +0 -6
  30. package/src/plugins/plugin-registry.ts +0 -32
  31. package/src/plugins/plugins/index.ts +0 -3
  32. package/src/plugins/plugins/nextjs.ts +0 -19
  33. package/src/plugins/plugins/vite.ts +0 -10
  34. package/src/plugins/plugins/vitest.ts +0 -9
  35. package/src/runtime/child-pi/child-pi-pool.ts +0 -68
  36. package/src/runtime/iteration-hooks.ts +0 -305
package/CHANGELOG.md CHANGED
@@ -2,6 +2,19 @@
2
2
 
3
3
  > **Note:** `atomic-write-v2.ts` / `AtomicWriter` mentioned in historical entries below was consolidated into `atomic-write.ts` as of v0.9.42. This changelog is preserved as historical record — the migration was completed (the v2 class was never adopted; v1 won on simplicity + symlink-safety + link+unlink atomicity). See `docs/migration/atomic-write-v2-migration.md` for the decision rationale.
4
4
 
5
+ ## [0.9.65] — team-tool schema empty-string guard (budgetTotal) + effectiveness empty-result guard + skill drift fix (2026-08-10)
6
+
7
+ ### Fixes
8
+ - **`budgetTotal` empty-string unset marker accepted** (`src/schema/team-tool-schema.ts`): `budgetTotal` was the only numeric `TeamToolParams` field missing the `Literal("")` union branch that its siblings (`budgetWarning`, `budgetAbort`, `tokenBudget`, `interval`, `replyDeadline`) already had. Calling models that emit every schema key with defaults (documented behavior in `normalizeTeamParams`) were rejected by pi-ai's pre-handler `validateToolArguments` → `Validation failed for tool "team"` on every action. The `MISCONFIGURATION GUARD` (rejects 1-999) is preserved — only the unset marker is added. Caught by the Tier 9 feature battery in the `real-test-pi-crew` skill (Tiers 1-8 stayed green while the team tool was broken for emitting models).
9
+ - **Effectiveness empty-result guard** (`src/runtime/effectiveness.ts`): a completed task with an EMPTY result artifact (`resultArtifact.sizeBytes === 0`) is now treated as no-observed-work, closing the monitoring gap where a child worker absorbed by a 429 rate-limit or model-not-found failure still emitted transcript/usage events and the run completed with `consistency=1` (zero real work). Empty-result tasks flow through the existing `noObservedWork` escalation (warn → blocked for mutating roles). New regression tests: `test/unit/runtime/core/effectiveness-guard.test.ts` (8 tests).
10
+ - **`real-test-pi-crew` skill drift fix**: `PI_CREW_BROKER_DIAG_UI` / `src/ui/run-dashboard.ts:831` citation removed from `skills/real-test-pi-crew/SKILL.md` Tier 6 (the env var was removed in `e3ee6fe2`); Tier 6 now documents the screen-change-evidence replacement. `scripts/pty_probe.py` no longer sets the dead env var.
11
+
12
+ ### Verified
13
+ - `npm run test:critical`: 101/101 pass (default, `PI_CREW_BROKER=0`, `PI_CREW_BROKER=1`).
14
+ - New `effectiveness-guard.test.ts`: 8/8 pass.
15
+ - `npm run typecheck` + `npm run build:bundle` exit 0; bundle md5 `e39373498d618de7e233c361ebb03b03`.
16
+ - Full 9-tier real-test re-run (2026-08-10): Tiers 1-8 + 9a (10/10) + 9b (5/5 spawn paths) pass; the previous run's failure modes (model-not-found spawn loop, 429-absorbed empty output) did not reproduce. Report: `docs/real-test/reports/real-test-2026-08-10-full-9-tier-f4-effectiveness-guard.md`.
17
+
5
18
  ## [0.9.64] — pi-rlm→pi-crew pattern transfer: worker scratchpad + crash-resume + cancellation + quick wins (2026-08-09)
6
19
 
7
20
  ### Quick Wins (patterns 17/19/20/11 + spike CI)
package/README.md CHANGED
@@ -71,7 +71,8 @@ repo: https://github.com/baphuongna/pi-crew
71
71
  - **Inter-pi broker** (v0.9.47, default-on) — a Unix-domain-socket message bus that lets concurrently-running Pi sessions pass messages, steering notes, and task-status events to each other. **On by default** on Linux + macOS; auto-disabled on native Windows (no unix socket). Three independent kill switches: `broker.enabled: false` (config), `PI_CREW_BROKER=0` (env, always wins), Windows auto-disable. See [docs/decisions/2026-07-22-broker-phase4-gated-on.md](docs/decisions/2026-07-22-broker-phase4-gated-on.md).
72
72
  - **Worker stateful scratchpad** (experimental, opt-in per role) — `executor` / `test-engineer` / `verifier` workers get a `scratchpad` tool: a persistent Bun-free JS evaluator whose namespace **compounds across calls within a task attempt** (variables set in one cell are visible in the next), so intermediate results live in memory instead of being re-derived from the transcript. Snapshots are flushed (redacted, atomic) per-attempt into the artifact store; the next attempt (retry / crash-recovery re-queue / re-run) **automatically revives the namespace** from the latest snapshot. Dormant by default (armed only when the spawner sets `PI_CREW_SCRATCHPAD=1`); zero behavior change for non-opt-in workers. Ported from the `@shift-labs/pi-rlm` pattern. See [src/runtime/scratchpad/README.md](src/runtime/scratchpad/README.md) (Phase 1-3 design, env keys, guards, threat model).
73
73
  - **`test:critical` + `real-test-pi-crew` skill** (v0.9.47) — a curated 14-file / 97-test subset (`npm run test:critical`, ~20s) for fast in-loop verification, plus a bundled skill distilling the full 8-tier end-to-end verification discipline (unit → 3-path kill-switch proof → typecheck/bundle → live TUI probing → smoke team run). Prevents the verifier-worker hang that full `npm test` (>4 min) caused against the 300s worker timeout.
74
- - **Provider extensions in subagents** (v0.9.57) — pi-crew spawns child-pi workers with `--no-extensions` (security posture), which made extension-registered providers (e.g. `pi-commandcode-provider`) unresolvable inside subagents. pi-crew now **auto-discovers provider packages** from `~/.pi/agent/settings.json` `packages` (npm: specs) and loads them via `--extension` in every builtin/user subagent — so **all provider models work in subagents**. An explicit `runtime.agentExtensions: string[]` config is an optional extra allowlist on top of auto-discovery. **SEC-1 preserved:** project/project-pi agents never receive these (env-gate unchanged).
74
+ - **Provider extensions in subagents** (v0.9.57, local-path support v0.9.63) — pi-crew spawns child-pi workers with `--no-extensions` (security posture), which made extension-registered providers (e.g. `pi-commandcode-provider`, `pi-other-provider`) unresolvable inside subagents. pi-crew now **auto-discovers provider packages** from `~/.pi/agent/settings.json` `packages` — both `npm:` specs (v0.9.57) and **local-path specs** like `../../source/foo` (v0.9.63) — and loads them via `--extension` in every builtin/user subagent, so **all provider models work in subagents**. An explicit `runtime.agentExtensions: string[]` config is an optional extra allowlist on top of auto-discovery. **SEC-1 preserved:** project/project-pi agents never receive these (env-gate unchanged).
75
+ - **Built-in performance observability** (v0.9.63) — every team run auto-attaches a detached resource sampler (per-PID CPU/RSS via ppid-tree attribution, 6 live warning categories) and auto-generates a markdown performance report on completion (22 anomaly categories, per-subagent timeline, token/cost/model attribution). Toggle per-team via frontmatter `observability: true|false`. Overhead ≈ 0 (sampler ~0.05% CPU / 56MB RSS; analyzer ~72ms post-run). See [Built-in performance observability](#built-in-performance-observability) below.
75
76
 
76
77
  ---
77
78
 
@@ -288,6 +289,18 @@ The advisory is **informational only** — there is no `force:true` flag needed
288
289
 
289
290
  ## Recent changes
290
291
 
292
+ ### v0.9.65: team-tool schema empty-string guard + effectiveness empty-result guard (2026-08-10)
293
+
294
+ - **`budgetTotal` empty-string unset marker accepted**: `budgetTotal` was the only numeric `TeamToolParams` field missing the `Literal("")` union branch its siblings had. Calling models that emit every schema key with defaults were rejected by pi-ai's pre-handler validation → `Validation failed for tool "team"` on every action. The `MISCONFIGURATION GUARD` (rejects 1-999) is preserved. Caught by the Tier 9 feature battery — Tiers 1-8 stayed green while the team tool was broken for emitting models.
295
+ - **Effectiveness empty-result guard**: a completed task with an empty result artifact (`sizeBytes === 0`) is now treated as no-observed-work — closing the monitoring gap where a 429-absorbed / model-not-found worker produced zero real content but the run still completed with `consistency=1`. Empty-result tasks flow through the existing `noObservedWork` escalation. Regression tests: `test/unit/runtime/core/effectiveness-guard.test.ts` (8 tests).
296
+ - Full 9-tier real-test re-run (2026-08-10): Tiers 1-8 + 9a (10/10) + 9b (5/5) pass; previous failure modes did not reproduce. See [CHANGELOG.md](CHANGELOG.md) §0.9.65 and `docs/real-test/reports/real-test-2026-08-10-full-9-tier-f4-effectiveness-guard.md`.
297
+
298
+ ### v0.9.63: built-in performance observability + local-path provider-extension discovery
299
+
300
+ - **Built-in performance observability (always-on, toggle per team)**: every team run now auto-attaches a detached resource sampler (`scripts/resource-sampler.mjs` — per-PID CPU/RSS via ppid-tree attribution, 6 live warning categories: high_cpu / rss_jump / rss_high / rss_leak / proc_died / proc_zombie) and auto-generates a markdown performance report (`scripts/analyze-run.mjs` → `docs/perf-report-<runId>.md` — 22 anomaly categories, per-subagent launch/respawn/active/drain timeline, token/cost/model attribution). Runtime wiring in `src/runtime/team-runner.ts`: `startPerfSampler` (detached + `unref`'d; death never affects the run) + `schedulePerfAnalyze` (+3s after `after_run_complete`, `unref`'d `setTimeout`). Toggle: team frontmatter `observability: true|false` (default `true`). **Overhead ≈ 0** (A/B verified: sampler ~0.05% CPU / 56MB RSS, analyzer ~72ms post-run, ~32KB artifacts/run). New scripts: `scripts/resource-sampler.mjs`, `scripts/analyze-run.mjs`. Tests: `test/unit/scripts/{analyze-run,resource-sampler}-audit.test.ts`.
301
+ - **Local-path provider extensions now discovered for child workers**: `discoverProviderExtensions` previously resolved only `npm:` specs from `~/.pi/agent/settings.json` `packages`, skipping local-path specs on the assumption they were the pi-crew extension itself. That broke local provider extensions (e.g. `pi-other-provider` installed via `pi install <local-path>`) — every model from such a provider hit `Error: Model "…" not found` in child workers and burned ~10s/task of fallback churn. Fix: resolve `./`, `../`, and absolute specs relative to the settings.json dir (same sanctioned trust level as `npm:`), and skip pi-crew itself via `packageRoot()`. **SEC-1 preserved** (project/project-pi AGENT extensions stay gated). Tests in `test/unit/runtime/model/provider-extensions.test.ts`.
302
+ - See [CHANGELOG.md](CHANGELOG.md) §0.9.63 and `docs/real-test/reports/real-test-2026-08-08-provider-ext-local-path.md`.
303
+
291
304
  ### v0.9.57: team-tool schema repair + provider-extension auto-discovery + post-reorg repo-layout consolidation
292
305
 
293
306
  - **Team tool repaired (was broken live while tests stayed green)**: calling models emit empty-string/boolean defaults for every schema key, which pi-ai's pre-handler `validateToolArguments` rejected (`Validation failed for tool team`) and `Type.Unsafe` schema fields without `[TypeBox.Kind]` made `Value.Check` throw (`Unknown type`). Schema now accepts unset markers natively; `SkillOverride`/`FreeformConfig` switched to TypeBox-native constructors; `normalizeTeamParams` drops empties in the handler. Chain-runner also fixed (quote-aware step splitting). Caught by a new **Tier 9 feature battery** in the [`real-test-pi-crew`](skills/real-test-pi-crew/SKILL.md) skill (live team-tool action coverage).
@@ -364,6 +377,38 @@ pi-crew supports multiple runtime modes for task execution:
364
377
  { "executeWorkers": false }
365
378
  ```
366
379
 
380
+ ## Built-in performance observability
381
+
382
+ Every team run auto-attaches a **detached resource sampler** and auto-generates a **performance report** on completion — measuring real resource usage and surfacing anomalies from the run's actual events/transcripts, not a synthetic benchmark.
383
+
384
+ ### Artifacts produced (per run, under `.crew/artifacts/<runId>/`)
385
+
386
+ | File | Contents |
387
+ |------|----------|
388
+ | `resources.jsonl` | Per-PID CPU/RSS samples every 2s (root runner + all child workers via ppid-tree attribution, including respawns). PID-reuse guarded by `/proc` starttime; first-sample CPU excluded from averages. |
389
+ | `perf-obs.log` | Sampler diagnostics: spawn marker, live warnings, terminal-stop confirmation. |
390
+ | `docs/perf-report-<runId>.md` | Markdown report: 22 anomaly categories, per-subagent timeline (launch/respawn/startup/active-work/drain/finalize), token/cost/model attribution. |
391
+
392
+ ### Live warnings (written to `perf-obs.log` during the run)
393
+
394
+ `high_cpu` (≥300% one core) · `rss_jump` (+200MB/interval) · `rss_high` (≥1GB) · `rss_leak` (window-30 monotonic +100MB) · `proc_died` · `proc_zombie`. Rate-limited (10s/pid/category).
395
+
396
+ ### Toggle
397
+
398
+ ```yaml
399
+ # teams/my-team.team.md
400
+ ---
401
+ name: my-team
402
+ observability: false # default: true — set false to skip sampler + report
403
+ ---
404
+ ```
405
+
406
+ `observability: true` is the default for parsed team files; direct-object `TeamConfig` fixtures (unit tests) stay unset so they never spawn the sampler. `schedulePerfAnalyze` runs the analyzer `+3s` after `after_run_complete` via an `unref`'d `setTimeout` — it never blocks run completion. The sampler auto-stops when the run manifest reaches a terminal status.
407
+
408
+ ### Overhead
409
+
410
+ Measured A/B (same team/goal, observability on vs off): **no detectable wall-time difference** (delta inside the 429-storm noise). Sampler: ~0.05% of one core, 56MB RSS fixed, detached + `unref`'d. Analyzer: ~72ms one-shot after run. ~32KB artifacts/run. See `docs/real-test/reports/real-test-2026-08-07-perf-obs-overhead.md`.
411
+
367
412
  ## Async Runs
368
413
 
369
414
  Async runs are **detached** from the session — they survive session switches and reloads. Pi-crew notifies when complete.