pi-crew 0.9.57 → 0.9.58

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/dist/index.mjs +22456 -21301
  3. package/package.json +1 -1
  4. package/src/agents/discover-agents.ts +6 -0
  5. package/src/config/config.ts +13 -2
  6. package/src/config/markers.ts +9 -1
  7. package/src/extension/action-suggestions.ts +1 -1
  8. package/src/extension/async-notifier.ts +3 -3
  9. package/src/extension/registration/runtime-cleanup.ts +5 -0
  10. package/src/extension/run-import.ts +19 -2
  11. package/src/extension/run-maintenance.ts +25 -9
  12. package/src/extension/team-tool/destructive-gate.ts +12 -6
  13. package/src/extension/team-tool/health-monitor.ts +7 -5
  14. package/src/extension/team-tool/intent-policy.ts +9 -0
  15. package/src/extension/team-tool/lifecycle-actions.ts +27 -4
  16. package/src/extension/team-tool/run-deadline.ts +7 -2
  17. package/src/extension/team-tool/run.ts +23 -4
  18. package/src/extension/team-tool/status.ts +2 -2
  19. package/src/extension/team-tool.ts +126 -51
  20. package/src/runtime/background-runner.ts +36 -2
  21. package/src/runtime/foreground-watchdog.ts +2 -2
  22. package/src/runtime/model/model-fallback.ts +3 -1
  23. package/src/runtime/model/provider-extensions.ts +36 -0
  24. package/src/runtime/model/runtime-warmup.ts +41 -0
  25. package/src/runtime/peer-dep.ts +35 -8
  26. package/src/runtime/skill-instructions.ts +1 -1
  27. package/src/runtime/stale-reconciler.ts +11 -19
  28. package/src/runtime/subagent-manager.ts +8 -5
  29. package/src/runtime/task-packet.ts +26 -4
  30. package/src/runtime/task-runner/run-projection.ts +4 -1
  31. package/src/runtime/team-runner.ts +94 -72
  32. package/src/runtime/verification/completion-guard.ts +10 -1
  33. package/src/schema/team-tool-schema.ts +152 -38
  34. package/src/skills/validate.ts +28 -2
  35. package/src/state/atomic-write.ts +23 -12
  36. package/src/state/contracts.ts +1 -0
  37. package/src/state/coordination/locks.ts +20 -7
  38. package/src/state/coordination/mailbox.ts +20 -2
  39. package/src/state/gitignore-manager.ts +5 -1
  40. package/src/state/stores/artifact-store.ts +5 -5
  41. package/src/state/stores/run-cache.ts +9 -1
  42. package/src/state/stores/state-store.ts +64 -10
  43. package/src/ui/deploy-bundled-themes.ts +11 -0
  44. package/src/ui/syntax-highlight.ts +31 -12
  45. package/src/utils/env-filter.ts +25 -11
  46. package/src/utils/paths.ts +20 -1
  47. package/src/utils/redaction.ts +22 -1
  48. package/src/worktree/worktree-manager.ts +2 -2
package/CHANGELOG.md CHANGED
@@ -3,6 +3,38 @@
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
5
 
6
+ ## [0.9.58] — fix load crash on stale hoisted typebox: defensive guard + bundle vendoring (survives `pi update`) + round-1/round-2 fixes (2026-08-04)
7
+
8
+ ### Bug fixes
9
+
10
+ - **CRITICAL — extension failed to load after 0.9.57 update (`Cannot read properties of undefined (reading 'Set')`)**. `src/schema/team-tool-schema.ts` called `TypeRegistry.Set("StringEnum", …)` at module top-level. `TypeRegistry` only exists in `@sinclair/typebox@0.34.50+`, but pi-crew declared `^0.34.50`. Pi installs **all** extensions into **one** shared npm store with hoisted deps, and on update it only re-checks the extension's own `package.json` version — if pi-crew is already latest, it does **not** re-resolve transitive deps. So an install could land pi-crew@0.9.57 (needs `TypeRegistry`) over a stale hoisted `@sinclair/typebox@0.34.49` (no `TypeRegistry`). Under ESM↔CJS interop, `import { TypeRegistry }` then resolved to `undefined`, and the unguarded top-level `TypeRegistry.Set(…)` crashed extension load (the bundle path swallowed it and fell through to strip-types, where it was uncaught). `--force` only applies to self-update, not extensions, so the dirty dep tree was never healed.
11
+ - **Fix 1 — defensive guard (src / strip-types path)**: feature-detect `TypeRegistry` (`HAS_TYPE_REGISTRY`) and skip registration when absent. `buildStringEnum()` (renamed from the internal `stringEnum`, now exported) takes an injectable `hasRegistry` flag and falls back to a verbose-but-validating `Type.Union` of `Type.Literal`s when `TypeRegistry` is missing — so the extension **always loads** regardless of the store's typebox version. `Value.Check` works natively in both branches.
12
+ - **Fix 2 — vendor `@sinclair/typebox` into the bundle (`scripts/build-bundle.mjs`, removed from `external`)**: this is what makes pi-crew **run the correct/optimal version after `pi update --all|--extensions`**. The bundle now ships its own typebox (built-in ≥0.34.50) with **zero external `@sinclair/typebox` imports**, so pi-crew is fully immune to whatever stale typebox the shared store holds — under ANY update mechanism. The compact `StringEnum` path (not the verbose fallback) is always active. SAFE to bundle: host pi/pi-ai validate tools with the *unscoped* `typebox` package (not `@sinclair/typebox`), so pi-crew's vendored copy never overlaps pi-ai's instance — they were already separate. (Fix 1 stays as a safety net for the strip-types dev fallback.)
13
+ - Verified: `test/unit/schema/stringenum-typebox-guard.test.ts` exercises both `buildStringEnum` branches against real typebox `Value.Check`; all 95 `test/unit/schema/**` + 245 blast-radius tests green; `tsc --noEmit` clean; bundle-load 2/2; bundle has **zero external `@sinclair/typebox` imports** (self-contained); bundle 2.99 MB (budget 3.5 MB).
14
+ - User remedy: once 0.9.58 is published, just `pi update --extensions` (or `pi update --all`). The 0.9.57→0.9.58 version bump forces a reinstall, and the new bundle carries its own typebox — no manual store cleanup needed. (On an already-broken machine: start once with `pi -ne`, run the update, then restart normally.)
15
+
16
+ ### Also bundled in 0.9.58 (already on main, unreleased)
17
+
18
+ - **Round-1 security hardening** (`ea03dd88`): strip `runtime.agentExtensions` from untrusted project config, harden untrusted-data fence injection (no `</untrusted-…>` escape), filter `PI_CREW_*` secrets from child-Pi env.
19
+ - **Round-2 locking fixes** (`6a5d8d16`): PID-guarded `releaseOwnLock` (LOCK-1 — no longer deletes a stolen lock in the `finally`), and `handleResume` releases the resume `withRunLock` before the minutes-long `executeTeamRun` (LOCK-2).
20
+ - **Round-3 correctness** (`ae36cd2a`): `taskTimeoutMs` no longer capped at 10s by the wrong `runtimeMaxTurns` ceiling (RT-NEW-1 — 5-minute timeouts silently disabled before); worktree dirty-snapshots pass `-c core.quotePath=false` so non-ASCII filenames are no longer silently dropped before `git clean -fd` (STATE-8 data-loss fix).
21
+ - **Round-4 state recovery** (`7b7968d5`): corrupt `manifest.json`/`tasks.json` are now quarantined (`.corrupt-<ts>`) + logged instead of silently making a run invisible (STATE-3); the stale-reconciler and health-monitor use the recovery loaders instead of bare `JSON.parse` that silently skipped corrupt runs (NEW-R1/R2).
22
+ - **Round-5 batch** (`59505265`, `26d07b76`, `a0fa1cb2`, `135dfc8b`): state/atomic (async `mode` option, compact `tasks.json`, hash-on-memory, atomic mailbox/subagent/gitignore writes, async-twin manifest quarantine), defense-in-depth (DI-1..DI-4, lazy yaml, bundle-mode warmup skip), TOCTOU `existsSync`+`readFileSync` fixes (NEW-P4), budget-abort drains in-flight units via shared `terminaliseRunWithDrain` (RT-NEW-2), benign signals no longer write terminal `async.failed` (RT-NEW-3), event-log tail-read for notifier/status (STATE-5), lazy `cli-highlight` + lazy `npm root -g` probe + provider-extension cache (PERF-1/2/3), themes mtime fast-path (PERF-7), `userPiRoot` cache keyed on home (NEW-P2 isolation fix).
23
+ - **Bundle rebuild note**: `dist/index.mjs` was rebuilt after R3–R5 — the earlier 13:35 build contained only R1/R2 + the typebox vendoring. Verify the shipped bundle includes the R3+ markers before publishing.
24
+
25
+ ### Note on postinstall "bundle build FAILED" message
26
+
27
+ - Harmless and expected on published installs: `scripts/build-bundle.mjs` is intentionally omitted from the npm tarball (`files` list) so the committed `dist/index.mjs` is used as-is. `postinstall.mjs` reports the script's absence as a red FAILED line; the install succeeds via the committed bundle. (No code change — documenting so the red line is not mistaken for the load crash.)
28
+
29
+ ### Late-0.9.58 additions — schema validation repair, prune dryRun, cleanup (post round-6)
30
+
31
+ - **Schema — empty-string unset markers** (`9173c6c4`, `bb47191e`): `replyDeadline`, `interval`, `budgetWarning`, `budgetAbort`, `tokenBudget` now accept `""`. Calling models emit `""` for unset optional fields, and pi-ai `validateToolArguments` runs BEFORE the pi-crew handler — a bare `Type.Integer`/`Type.Number` rejected `""` → every team action returned `Validation failed for tool team` and the model looped. Added `Type.Literal("")` to each union.
32
+ - **Schema — stringified numbers** (`9064343b`): pi-ai's tool-argument coercion stringifies a numeric value when the schema `Union` has a string-literal branch (e.g. `interval:0` arrived as `"0"`). Broadened the 5 numeric-union fields to also accept a numeric-string pattern branch, and added `normalizeLooseNumericFields()` in `handleTeamTool` to coerce the string form back to a real number (and treat `""` as unset) before domain routers read params. Without this, `team prune` and any call sending these optional numeric fields with value `0` failed validation.
33
+ - **prune dryRun now a true non-destructive preview** (`85f657c6`, `d5d42032`): `handlePrune` ignored `params.dryRun` entirely — it only checked `confirm`, then deleted. A caller requesting a preview (`dryRun:true`) with `confirm:true` got runs DELETED instead of listed (data-safety bug). `pruneFinishedRuns` now takes a `dryRun` option (stops after the read-only safety check — no deletion, no worktree cleanup, no audit); `handlePrune` lets `dryRun` bypass `confirm`; the `tool_call` destructive gate now allows `prune dryRun=true` (previously only `cleanup` was exempt).
34
+ - **forget resurrect fix** (`672a3d4d`): a still-alive background runner could land one final heartbeat write after the first `rmSync` in `handleForget` — `atomicWriteFile`'s `mkdirSync(recursive)` re-created the state dir, resurrecting `heartbeat.json` in a dir we just forgot. Now drains briefly (250ms) and re-removes any resurrected residue.
35
+ - **Round-6 resource cleanup** (`9f81a081`): `stopAllWatchdogs()` exported + called in `cleanupRuntime`; `RunDeadline.timer` cleared in all 4 run paths (dwf/async/fg/inline); foreground-abort `removeEventListener`.
36
+ - **CI green**: lint + format:check + full `npm test` pass on ubuntu/windows/macos (3 OSes). `2db4c6bc` fixed biome lint/format gaps; `9808f3b0` fixed a macOS-only path-divergence bug in the corrupt-index test.
37
+
6
38
  ## [0.9.57] — provider-extension auto-discovery + team-tool schema repair + whole-project reorganization (2026-08-03)
7
39
 
8
40
  ### New: provider extensions work in subagents (no hardcoding)