pi-background-tasks 2.1.3 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/BACKGROUND-TASKS-INSTRUCTIONS.md +1 -1
  2. package/PUBLISHING.md +2 -0
  3. package/README.md +16 -9
  4. package/TESTING.md +15 -10
  5. package/TEST_PLAN.md +12 -11
  6. package/THIRD_PARTY_NOTICES.md +30 -0
  7. package/docs/INDEX.md +8 -4
  8. package/docs/choose-a-workflow.md +5 -2
  9. package/docs/commands/claude-cache.md +50 -0
  10. package/docs/getting-started.md +3 -0
  11. package/docs/manifest.json +84 -19
  12. package/docs/operations/configuration.md +15 -1
  13. package/docs/operations/releasing.md +6 -3
  14. package/docs/read-before-edit.md +4 -1
  15. package/docs/reference/runtime-contracts.md +72 -71
  16. package/docs/subsystems/anthropic-attribution.md +63 -0
  17. package/docs/subsystems/attested-pi-runs.md +2 -2
  18. package/docs/subsystems/child-launch-durability-and-safety.md +3 -3
  19. package/docs/subsystems/delegation.md +12 -4
  20. package/docs/subsystems/docs-freshness-gate.md +6 -6
  21. package/docs/subsystems/fusion.md +6 -2
  22. package/docs/tools/bg_delegate.md +21 -9
  23. package/docs/tools/bg_result.md +8 -1
  24. package/docs/tools/bg_run.md +5 -0
  25. package/extensions/anthropic-attribution.ts +1 -0
  26. package/package.json +4 -2
  27. package/src/core/anthropic-attribution-path.ts +26 -0
  28. package/src/core/{fusion/anthropic-attribution.ts → anthropic-attribution.ts} +61 -8
  29. package/src/core/attested-pi-run.ts +10 -1
  30. package/src/core/common.ts +2 -1
  31. package/src/core/delegate/artifacts.ts +4 -0
  32. package/src/core/delegate/launch.ts +44 -14
  33. package/src/core/delegate/runner.ts +24 -0
  34. package/src/core/delegate/seed.ts +12 -0
  35. package/src/core/delegate/types.ts +10 -2
  36. package/src/core/fusion/artifacts.ts +265 -3
  37. package/src/core/fusion/config.ts +1 -1
  38. package/src/core/fusion/orchestrator.ts +47 -57
  39. package/src/core/fusion/pi-child.ts +7 -124
  40. package/src/core/fusion/result-package.ts +550 -3
  41. package/src/core/fusion/types.ts +87 -0
  42. package/src/core/registry.ts +4 -1
  43. package/src/delegate-child-extension.ts +9 -2
  44. package/src/delegate-extension.ts +119 -9
@@ -46,7 +46,7 @@ Current authored ownership map:
46
46
  - Fusion runtime: `.pi/fusion/<session-id>-<pid>/<run-id>/` under the active project cwd.
47
47
  - Delegate artifacts: task-owned artifact directories referenced from task metadata/result packages.
48
48
  - Fusion model config: `fusion-models.json` under Pi's agent directory (`getAgentDir()`), not the project `.pi/tasks` tree.
49
- - Package entrypoint: `extensions/background-tasks.ts` via `package.json.pi.extensions`.
49
+ - Package entrypoints, in load order: `extensions/anthropic-attribution.ts`, then `extensions/background-tasks.ts`, via `package.json.pi.extensions`.
50
50
 
51
51
  ---
52
52
 
package/PUBLISHING.md CHANGED
@@ -37,6 +37,8 @@ npm run docs:verify
37
37
  npm run payload:check
38
38
  # On a tag ref only: GITHUB_REF_TYPE=tag GITHUB_REF_NAME=v$VERSION npm run release:check-version
39
39
  npm run pack:dry-run
40
+ # With pnpm 11.18.0 on PATH:
41
+ npm run test:pnpm-pack
40
42
  npm run test:compat
41
43
  npm view pi-background-tasks name version --json
42
44
  ```
package/README.md CHANGED
@@ -17,6 +17,7 @@
17
17
  - **Run long work without blocking**: start named shell jobs, keep talking to Pi, and get durable completion notifications when they finish.
18
18
  - **Delegate context-aware investigation**: launch one route-pinned, inspect-only child Pi agent seeded with a frozen projection of the current conversation, then retrieve a hash-verified result.
19
19
  - **Combine model perspectives through fixed-purpose Fusion**: run three candidate children, blind evaluation, optional bounded evaluator repair, and merger for reasoning, investigation, targeted URL research, or validation review.
20
+ - **Keep Anthropic subscription traffic attributed and compatible**: globally apply the package-owned Claude Code OAuth attribution, cache policy, and exact-match prompt sanitization to Anthropic routes without an external sanitizer dependency.
20
21
 
21
22
  <p align="center">
22
23
  <img src="docs/assets/architecture.svg" alt="Architecture diagram showing Pi session, background task registry, delegated child agent, and Fusion candidate/evaluator/merger flow" width="760">
@@ -26,23 +27,23 @@
26
27
  | Fact | Value |
27
28
  | --- | --- |
28
29
  | Package | `pi-background-tasks` |
29
- | Version | `2.1.3` |
30
+ | Version | `2.3.0` |
30
31
  | Node engine | `>=22.19.0` |
31
- | Pi entrypoint | `./extensions/background-tasks.ts` |
32
+ | Pi entrypoints | `./extensions/anthropic-attribution.ts`, `./extensions/background-tasks.ts` |
32
33
  | Package image | [logo.png](https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png) |
33
34
  <!-- pi-docs:end name="readme-package-facts" -->
34
35
 
35
36
  <!-- pi-docs:begin name="readme-public-surfaces" generator="scripts/docs/generate.mjs" -->
36
37
  | Surface kind | Count |
37
38
  | --- | --- |
38
- | command | 10 |
39
+ | command | 11 |
39
40
  | tool | 11 |
40
41
  | shortcut | 2 |
41
42
  | renderer | 2 |
42
43
  | eventbus | 1 |
43
44
  | workflow | 4 |
44
45
 
45
- Public commands: `/bg`, `/bg-clear`, `/bg-tasks`, `/bg-update`, `/fusion`, `/fusion-models`, `/jobs`, `/kill`, `/logs`, `/tasks`.
46
+ Public commands: `/bg`, `/bg-clear`, `/bg-tasks`, `/bg-update`, `/claude-cache`, `/fusion`, `/fusion-models`, `/jobs`, `/kill`, `/logs`, `/tasks`.
46
47
 
47
48
  Public tools: `bg_delegate`, `bg_kill`, `bg_logs`, `bg_result`, `bg_run`, `bg_run_pi_attested`, `bg_status`, `fusion_investigate`, `fusion_reason`, `fusion_research`, `fusion_validate`.
48
49
 
@@ -58,9 +59,10 @@ Full owner map and generated contracts live in [docs/INDEX.md](docs/INDEX.md).
58
59
  |---|---|
59
60
  | Start a dev server, watch build, migration dry run, or long check | `bg_run` and `/bg` return immediately, write durable output files, show a footer dock, and notify on terminal state. |
60
61
  | Let Pi keep working instead of sleeping or polling | Default `bg_run` completion delivery sends a durable terminal notification and can wake a follow-up turn. |
61
- | Ask a second agent to inspect the repo with the current conversation as context | `bg_delegate` starts one isolated child with read/search/list tools only; `bg_result` verifies the committed result before returning it. |
62
+ | Ask a second agent to inspect the repo with the current conversation as context | `bg_delegate` starts one read/search/list child, isolated from ambient extensions by default; `bg_result` verifies the committed result before returning it. |
62
63
  | Compare model perspectives without exposing arbitrary parent context | Fusion children receive only the workflow input and fixed tool policy; no silent route substitution or fallback is used on delegate/Fusion paths. |
63
64
  | Produce local evidence for a direct Pi run | `bg_run_pi_attested` records local same-user-writable artifacts and hashes after a successful structured child Pi task. |
65
+ | Use Anthropic subscription OAuth consistently | The globally loaded provider applies attribution and exact-match sanitization; `/claude-cache` shows or changes session cache retention. |
64
66
 
65
67
  ## Install
66
68
 
@@ -139,7 +141,7 @@ More walkthrough detail: [Getting started](docs/getting-started.md).
139
141
  |---|---:|---|---|---|---|
140
142
  | Ordinary foreground Pi work | Yes | Full current session | Whatever tools the active session has | Short reads/edits/commands where you want live back-and-forth | Pi waits for the work before responding. |
141
143
  | `/bg` | No | No model child unless your command starts one | Runs your shell command; **not sandboxed** | User-started local commands, servers, watches | UI notification and footer tracking; `/bg` uses notification-only by default. |
142
- | `bg_run` | No | No model child unless command starts one | Runs your shell command; **not sandboxed** | Agent-started long commands | Returns task id/output path; defaults to notification plus automatic follow-up wake. |
144
+ | `bg_run` | No | No model child unless command starts one | Runs your shell command; **not sandboxed** | Agent-started long commands | Returns task id/output path; defaults to notification plus automatic follow-up wake. For an Anthropic child `pi`, do not pass `--no-extensions` unless you also explicitly load this package's attribution extension. |
143
145
  | `bg_delegate` + `bg_result` | No launch; retrieval is point-in-time | Frozen visible conversation projection | Inspect-only child: read, grep, find, ls, artifact read; no shell, writes, network, recursion | Context-aware read-only investigation while parent continues | Launch returns immediately; result is committed by child and hash-verified by retrieval. |
144
146
  | `bg_run_pi_attested` | No | Prompt passed to one direct child Pi run | Direct `pi --mode json`; no shell command; writes requested report path | Evidence-oriented direct Pi task | Emits local attestation sidecar only after successful completion. |
145
147
  | `/fusion` / `fusion_reason` | Background launch; point-in-time `bg_result` retrieval | Versioned conversation projection plus prompt | Candidates/evaluator/repair/merger run with no tools | Self-contained reasoning and synthesis | Returns after durable preflight; three candidates → blind evaluator → optional bounded repair → merger. |
@@ -164,6 +166,8 @@ See [Choose a workflow](docs/choose-a-workflow.md) for a decision tree and trade
164
166
 
165
167
  Expected: returns immediately with a task id, PID when available, and `.pi/tasks/...output`. The command runs as an ordinary local shell command with your user permissions; it can invoke networked tools or paid services if the command itself does so.
166
168
 
169
+ If `bg_run` starts an Anthropic child `pi`, keep normal extension discovery enabled. Do not add `--no-extensions` unless the command also supplies this package's `extensions/anthropic-attribution.ts` via `-e`/`--extension`; `bg_run` does not rewrite arbitrary shell argv.
170
+
167
171
  ### `bg_delegate`: context-seeded read-only investigation
168
172
 
169
173
  ```json
@@ -171,6 +175,7 @@ Expected: returns immediately with a task id, PID when available, and `.pi/tasks
171
175
  "name": "Route audit",
172
176
  "prompt": "Inspect the package source and identify where delegate route pinning is enforced. Return file paths, function names, and a short explanation. If a fact exists only in omitted parent tool output, say it is unavailable rather than guessing.",
173
177
  "capability": "inspect",
178
+ "extensionMode": "isolated",
174
179
  "autoDeliver": "never"
175
180
  }
176
181
  ```
@@ -186,6 +191,8 @@ Then retrieve:
186
191
 
187
192
  Expected: `bg_delegate` returns a launch receipt immediately. `bg_result` returns a typed not-ready result while running; after commit it verifies package identity, seed hash, route, block hashes, and aggregate hash before returning bytes. Oversized answers become explicit artifact references, not truncated inline text.
188
193
 
194
+ `extensionMode` defaults to `"isolated"`, which disables ambient extension discovery. If the pinned provider exists only because a user/project Pi extension registers it, opt into `"ambient"`. Ambient mode still loads the delegate guard and keeps the inspect tool allowlist plus skill/template/theme/context restrictions, but it executes arbitrary discovered extension code. Tool allowlists do not sandbox that code, so ambient mode weakens inspect-only process isolation. The call never accepts extension paths and never substitutes the pinned route.
195
+
189
196
  ### `bg_run_pi_attested`: local evidence for one Pi child
190
197
 
191
198
  ```json
@@ -291,10 +298,10 @@ Agent tasks launched through `pi -p ...` or `pi --mode json ...` and marked `isA
291
298
  - Shell jobs are tracked by the package, but they are not sandboxed. Treat commands as local processes with your permissions and credentials.
292
299
  - Delegate and Fusion child Pi processes are route-pinned where applicable; delegate/Fusion paths do not silently substitute routes.
293
300
  - Fusion uses direct child `pi --mode text` processes, not direct completion APIs. Frontier Fusion routes are admitted only through Pi Anthropic or Codex subscription OAuth; metered frontier API credentials are rejected before child creation.
294
- - Claude Fusion children load the package-owned Claude Code OAuth attribution provider shared with the repo spawn path, request `ttl: "1h"` on system/tool/conversation cache breakpoints before serialization, and preserve provider-reported `cacheWrite1h` evidence. Set `PI_CACHE_RETENTION=short|none|long` to choose explicitly; malformed attribution, policy, or cache evidence fails before transport. Provider usage is preserved verbatim, but subscription OAuth can report `cacheWrite1h = 0` even when a unique cache remains readable beyond five minutes; treat positive `cacheWrite1h` as definitive and zero as inconclusive on that channel. Anthropic budgeting follows the provider's 200K subscription policy.
301
+ - Normal installations globally load the package-owned Claude Code OAuth attribution/sanitization provider for Anthropic sessions; non-Anthropic sessions are unchanged. Isolated Fusion, delegate, and attested Anthropic children load the same package entrypoint explicitly. It requests `ttl: "1h"` on system/tool/conversation cache breakpoints before serialization and preserves provider-reported `cacheWrite1h` evidence. Set `PI_CACHE_RETENTION=short|none|long` or use `/claude-cache` to choose explicitly; malformed attribution, policy, cache evidence, or non-OAuth credentials fail before transport. Provider usage is preserved verbatim, but subscription OAuth can report `cacheWrite1h = 0` even when a unique cache remains readable beyond five minutes; treat positive `cacheWrite1h` as definitive and zero as inconclusive on that channel. Anthropic budgeting follows the provider's 200K subscription policy.
295
302
  - Fusion research fetches only caller-supplied public `http(s)` URLs with bounded retrieval. It is not web search and not a secret-exfiltration boundary.
296
303
  - Attestation sidecars are local, unsigned, same-user-writable evidence. They are useful for downstream local gates, but not cryptographic proof against local compromise, a compromised Pi binary, or a compromised provider.
297
- - Metadata, attestations, delegate/Fusion artifacts, and configuration replacements use write/fsync/rename durability patterns. Ordinary task output is closed and drained before terminal publication but is not explicitly fsynced. POSIX directory entries are fsynced after atomic replacement; Windows lacks the same portable directory-entry crash-durability guarantee.
304
+ - Metadata, attestations, delegate/Fusion artifacts, and configuration replacements use write/fsync/rename durability patterns. Failed/cancelled stored Fusion runs also have a manifest-bound `failure-summary.json` containing bounded no-answer evidence metadata and artifact refs only; `bg_result` returns it as an answer-free typed terminal view after integrity checks. Ordinary task output is closed and drained before terminal publication but is not explicitly fsynced. POSIX directory entries are fsynced after atomic replacement; Windows lacks the same portable directory-entry crash-durability guarantee.
298
305
 
299
306
  Detailed operations: [Configuration](docs/operations/configuration.md).
300
307
 
@@ -319,7 +326,7 @@ Operations are `capabilities`, `run`, `status`, `logs`, and `kill`. This is the
319
326
  | Environment variables, shells, output caps, model config, offline behavior | [Configuration](docs/operations/configuration.md) |
320
327
  | Package QA expectations | [TESTING.md](TESTING.md) and [TEST_PLAN.md](TEST_PLAN.md) |
321
328
  | Publishing notes | [PUBLISHING.md](PUBLISHING.md) |
322
- | License | [LICENSE](LICENSE) |
329
+ | License and derived-rule notice | [LICENSE](LICENSE) and [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md) |
323
330
 
324
331
  ## Contributing
325
332
 
package/TESTING.md CHANGED
@@ -122,18 +122,23 @@ Two unit gates protect Fusion's persisted artifact bytes, which are a frozen for
122
122
  - `tests/unit/delegate-artifacts.test.ts` — spill/receipt coordinates under
123
123
  out-of-order completion, aggregate caps, exact bounded range reads, and terminal
124
124
  evaluation including a zero-exit child that never committed.
125
- - `tests/unit/delegate-launch.test.ts` — route pinning without substitution, argv-level
126
- isolation, the hook-contract gate, and the property that a refused launch creates
127
- **zero** children and **zero** artifacts.
125
+ - `tests/unit/delegate-launch.test.ts` — route pinning without substitution, isolated
126
+ versus ambient extension argv, invariant inspect-tool/resource restrictions, the
127
+ hook-contract gate, and the property that a refused launch creates **zero** children
128
+ and **zero** artifacts.
129
+ - `tests/scripted-provider/delegate-ambient-provider.test.ts` — a fresh real Pi child
130
+ with a provider available only through temp-agent ambient extension discovery:
131
+ isolated mode fails with an unknown provider and no result, while ambient mode
132
+ resolves the exact pinned provider, retains the package guard, and commits.
128
133
  - `tests/scripted-provider/delegate-child-guard.test.ts` — the child guard inside a
129
134
  real Pi agent loop: a 2 MB tool result spilled to a hashed artifact with the payload
130
135
  kept out of the transcript, a blocked over-budget model call, exact bounded range
131
136
  reads, route-drift refusal, and turn-limit enforcement.
132
137
  - `tests/sdk/delegate-sdk.test.ts` — the full public loop through the shipped
133
138
  entrypoint with a fake child `pi`: launch receipt, projected context actually
134
- reaching the child, child session isolation, not-ready retrieval, corruption
135
- detection, and oversized answers degrading to an artifact reference without
136
- truncation.
139
+ reaching the child, default isolated argv, explicit ambient argv/warning/metadata,
140
+ child session isolation, not-ready retrieval, corruption detection, and oversized
141
+ answers degrading to an artifact reference without truncation.
137
142
  - `tests/package/delegate-mutation-guard.test.ts` — fails if silent truncation, a
138
143
  silent fallback, a route substitution, an unbounded inline answer, a dropped
139
144
  preflight, a synthesized zero usage, a fail-open guard hook, or an undelivered
@@ -187,24 +192,24 @@ npm run test:rpc
187
192
  npm run test:agent-loop
188
193
  ```
189
194
 
190
- The Fusion SDK/RPC/scripted-provider tests install a deterministic fake child `pi` in a temp `PATH` from `tests/helpers/fusion-fake-pi.ts`. Parent Pi remains the real SDK/RPC runtime; only direct child `pi --mode text` calls with the package-owned private compact metadata extension are intercepted. SDK coverage proves the Fusion tools return after durable no-child preflight without waiting for delayed children, transfer cancellation ownership away from the completed tool call, remain tracked through status/dock/kill/notification, verify manifest-bound `result.json` plus `merged.md`, and attach complete usage on the first `bg_result` retrieval exactly once. The scripted provider proves launch → no-poll parent response → terminal wake → `bg_result` → verified answer. `PI_CODING_AGENT_DIR` is pointed at the temp agent directory so `fusion-models.json` is never read from the user's real global Pi directory. Fusion v1 public-surface coverage asserts exactly four tools (`fusion_reason`, `fusion_investigate`, `fusion_research`, `fusion_validate`), no public capability argument, retired-tool active-tool removal, `/fusion` mapping to reason/no-tool candidates, closed schemas with Google-compatible enum status, targeted URL fetch not search, URL exfiltration warnings, strict validation verification rules, historical v4 rendering without old-tool activation, and actionable migration errors for `fusion_validate({prompt})`. Fusion context coverage covers both reason conversation projection and clean-task non-interference invariants, including parent-sentinel absence from every clean downstream prompt/artifact and byte-identical clean inputs across unrelated parent sessions. `tests/unit/fusion-context-prompts.test.ts` verifies that a synthetic session carrying more than 1 MB of tool arguments/results still yields a small canonical input, that user and assistant text survive verbatim, that thinking and tool payloads never appear (including no head/tail/preview sentinel), that omission counts, byte totals, and hashes are exact and stable, that repeated construction is byte-identical, that the active Fusion tool leaf and sibling calls stay scope-excluded, that images remain marker-only or ledger-only with no raw base64 in child prompts, and that every retained source block receives exactly one disposition. `tests/unit/fusion-high-cardinality.test.ts` covers the receipt-cardinality regression: a session of many short interleaved tool events (rather than a few enormous results) pins per-receipt cost, proves the compact `omitted_activity` fields are the only model-facing ones, reconciles every receipt against the ledger through `projection_map`, and proves the whole workflow fits a real route budget. `tests/unit/fusion-budget.test.ts` covers stage budgets and stage-local refusal wording; orchestrator coverage derives terminal run progress from durable attempts after usage persistence so late evaluator/merge refusal reports completed, failed, cancelled, and not-started truth instead of claiming zero children. Each route reserves the larger of Fusion's output contract and the model's declared maximum output, the limiting model is selected by conservative byte capacity (including when it is the evaluator rather than a candidate), unknown or too-small capacities fail before spawn, boundary prompts pass at exactly the limit and fail one byte past it, the child system prompt counts as input, dense multi-byte UTF-8 cannot bypass byte accounting, and candidate, evaluator, evaluation-repair, and merger expansions are each rejected before their child is spawned with zero partial launches. `tests/unit/fusion-pi-child.test.ts` covers the post-launch `fusion-runtime-guard.v2` protocol, BUG-185 removal of live token/output-reservation admission, stable payload normalization, 128-request/192-tool limits, malformed or duplicate evidence rejection, typed parent errors, and failed audit sealing. `tests/unit/fusion-claude-cache.test.ts` pins native pre-serialization `ttl: "1h"` requests, explicit short/none/long policy, call-level compaction opt-out, model compatibility fallback, non-mutation, the four-breakpoint ceiling, subscription prompt-caching-scope beta idempotence, malformed-control refusal, and distinct `child_cache_policy_invalid` parent errors. Child argv tests pin the shared attribution provider sanitizer → runtime-governor order; root attribution tests pin linked OAuth account/device/session metadata, beta-resource request shape, cache surfaces, one-hour provider usage pricing, and the 200K subscription policy. Compact/result usage tests preserve Anthropic `cacheWrite1h` and provider `reasoning` subsets, and child metadata binds each requested/effective payload observation plus JSON-rendered output accounting in `fusion-child-result.v4`. Live subscription-OAuth acceptance on 2026-08-04 proved cold writes plus exact-repeat reads on Sonnet 4.5 and Opus 5 while both reported `cacheWrite1h = 0`. Separate normal-spawn and exact Fusion-child Opus 5 controls—with unique prompts—still read their caches after 370 idle seconds; the Fusion control wrote and reread 9,922 tokens through the attribution → sanitizer → governor path. Documentation therefore treats positive `cacheWrite1h` as definitive but zero as inconclusive on subscription OAuth; payload intent, provider itemization, and behavioral lifetime remain separate evidence. Terminal `fusion-child-settlement.v3` is published only at `agent_settled`; recovered non-final provider errors must be zero-content/zero-usage retry markers named by that settlement, and one non-final candidate `stop` is accepted only when it is a hash-bound oversized original immediately followed by a same-session replacement. `tests/scripted-provider/fusion-output-recovery.test.ts` drives a real Pi print-mode process and proves one PID/session context, one queued continuation before settlement, tool removal on turn two, original-artifact preservation, and replacement-only stdout. Missing/duplicate/tampered/failed settlements or substantive error records remain fatal. `tests/scripted-provider/fusion-runtime-guard.test.ts` drives a real Pi agent loop through Pi's `openai-codex-responses` adapter against local HTTP and proves provider-payload transforms chain in load order and `ctx.abort()` prevents transport for the execution/cache-policy refusals that remain. `tests/package/typebox-compat.test.ts` pins the TypeBox posture and compiles nullable-array schemas. The release-only `npm run test:compat` packs the package, installs exact supported Pi versions, runs `/jobs`, runs `/fusion` through the installed package entrypoint with the fake child Pi, verifies five child invocations, verifies `/fusion-models` rejects non-TUI mode, requires each supported Pi line to declare terminal `agent_settled` and `before_provider_request`, verifies the installed Anthropic adapter exposes cache breakpoints plus long/tool compatibility controls, asserts the resolved `typebox` is Pi's bundled peer rather than a private or nested copy, and scans the installed package bytes for TypeBox APIs removed in the 1.3.x line. Pi 0.75.5 is intentionally unsupported because it lacks the terminal event required to seal a Fusion audit after retries and compaction. It then drives the current host Pi through a real RPC `fusion_reason` parent-agent loop, checks the persisted tool result carries the complete Pi `Usage.cost` object, invokes `get_session_stats` (the same aggregation boundary used by the TUI footer), reopens the durable session, and verifies identical token/cost totals. All parent and child inference remains deterministic and local.
195
+ The Fusion SDK/RPC/scripted-provider tests install a deterministic fake child `pi` in a temp `PATH` from `tests/helpers/fusion-fake-pi.ts`. Parent Pi remains the real SDK/RPC runtime; only direct child `pi --mode text` calls with the package-owned private compact metadata extension are intercepted. SDK coverage proves the Fusion tools return after durable no-child preflight without waiting for delayed children, transfer cancellation ownership away from the completed tool call, remain tracked through status/dock/kill/notification, verify manifest-bound `result.json` plus `merged.md`, and attach complete usage on the first `bg_result` retrieval exactly once. The scripted provider proves launch → no-poll parent response → terminal wake → `bg_result` → verified answer. `PI_CODING_AGENT_DIR` is pointed at the temp agent directory so `fusion-models.json` is never read from the user's real global Pi directory. Fusion v1 public-surface coverage asserts exactly four tools (`fusion_reason`, `fusion_investigate`, `fusion_research`, `fusion_validate`), no public capability argument, retired-tool active-tool removal, `/fusion` mapping to reason/no-tool candidates, closed schemas with Google-compatible enum status, targeted URL fetch not search, URL exfiltration warnings, strict validation verification rules, historical v4 rendering without old-tool activation, and actionable migration errors for `fusion_validate({prompt})`. Fusion context coverage covers both reason conversation projection and clean-task non-interference invariants, including parent-sentinel absence from every clean downstream prompt/artifact and byte-identical clean inputs across unrelated parent sessions. `tests/unit/fusion-context-prompts.test.ts` verifies that a synthetic session carrying more than 1 MB of tool arguments/results still yields a small canonical input, that user and assistant text survive verbatim, that thinking and tool payloads never appear (including no head/tail/preview sentinel), that omission counts, byte totals, and hashes are exact and stable, that repeated construction is byte-identical, that the active Fusion tool leaf and sibling calls stay scope-excluded, that images remain marker-only or ledger-only with no raw base64 in child prompts, and that every retained source block receives exactly one disposition. `tests/unit/fusion-high-cardinality.test.ts` covers the receipt-cardinality regression: a session of many short interleaved tool events (rather than a few enormous results) pins per-receipt cost, proves the compact `omitted_activity` fields are the only model-facing ones, reconciles every receipt against the ledger through `projection_map`, and proves the whole workflow fits a real route budget. `tests/unit/fusion-budget.test.ts` covers stage budgets and stage-local refusal wording; orchestrator coverage derives terminal run progress from durable attempts after usage persistence so late evaluator/merge refusal reports completed, failed, cancelled, and not-started truth instead of claiming zero children. Each route reserves the larger of Fusion's output contract and the model's declared maximum output, the limiting model is selected by conservative byte capacity (including when it is the evaluator rather than a candidate), unknown or too-small capacities fail before spawn, boundary prompts pass at exactly the limit and fail one byte past it, the child system prompt counts as input, dense multi-byte UTF-8 cannot bypass byte accounting, and candidate, evaluator, evaluation-repair, and merger expansions are each rejected before their child is spawned with zero partial launches. `tests/unit/fusion-pi-child.test.ts` covers the post-launch `fusion-runtime-guard.v2` protocol, BUG-185 removal of live token/output-reservation admission, stable payload normalization, 128-request/192-tool limits, malformed or duplicate evidence rejection, typed parent errors, and failed audit sealing. `tests/unit/fusion-claude-cache.test.ts` pins native pre-serialization `ttl: "1h"` requests, explicit short/none/long policy, call-level compaction opt-out, model compatibility fallback, non-mutation, the four-breakpoint ceiling, subscription prompt-caching-scope beta idempotence, malformed-control refusal, and distinct `child_cache_policy_invalid` parent errors. Child argv tests pin the package attribution/sanitization → runtime-governor order; root attribution tests pin linked OAuth account/device/session metadata, all exact-match sanitizer variants, beta-resource request shape, cache surfaces, one-hour provider usage pricing, duplicate-owner suppression, and the 200K subscription policy. Compact/result usage tests preserve Anthropic `cacheWrite1h` and provider `reasoning` subsets, and child metadata binds each requested/effective payload observation plus JSON-rendered output accounting in `fusion-child-result.v4`. Live subscription-OAuth acceptance on 2026-08-04 proved cold writes plus exact-repeat reads on Sonnet 4.5 and Opus 5 while both reported `cacheWrite1h = 0`. Separate normal-spawn and exact Fusion-child Opus 5 controls—with unique prompts—still read their caches after 370 idle seconds; the Fusion control wrote and reread 9,922 tokens through the attribution/sanitization → governor path. Documentation therefore treats positive `cacheWrite1h` as definitive but zero as inconclusive on subscription OAuth; payload intent, provider itemization, and behavioral lifetime remain separate evidence. Terminal `fusion-child-settlement.v3` is published only at `agent_settled`; recovered non-final provider errors must be zero-content/zero-usage retry markers named by that settlement, and one non-final candidate `stop` is accepted only when it is a hash-bound oversized original immediately followed by a same-session replacement. Failed/cancelled Fusion coverage also verifies canonical manifest-bound `failure-summary.json` evidence with no stage-output bodies, truthful classifications/omission receipts, subordinate one-shot summary persistence after `writeError`, and typed answer-free `bg_result` terminal views that never claim usage or expose partial output. `tests/scripted-provider/fusion-output-recovery.test.ts` drives a real Pi print-mode process and proves one PID/session context, one queued continuation before settlement, tool removal on turn two, original-artifact preservation, and replacement-only stdout. Missing/duplicate/tampered/failed settlements or substantive error records remain fatal. `tests/scripted-provider/fusion-runtime-guard.test.ts` drives a real Pi agent loop through Pi's `openai-codex-responses` adapter against local HTTP and proves provider-payload transforms chain in load order and `ctx.abort()` prevents transport for the execution/cache-policy refusals that remain. `tests/package/typebox-compat.test.ts` pins the TypeBox posture and compiles nullable-array schemas. The release-only `npm run test:compat` packs the package, installs exact supported Pi versions, runs `/jobs`, runs `/fusion` through the installed package entrypoint with the fake child Pi, verifies five child invocations, verifies `/fusion-models` rejects non-TUI mode, requires each supported Pi line to declare terminal `agent_settled` and `before_provider_request`, verifies the installed Anthropic adapter exposes cache breakpoints plus long/tool compatibility controls, asserts the resolved `typebox` is Pi's bundled peer rather than a private or nested copy, and scans the installed package bytes for TypeBox APIs removed in the 1.3.x line. Pi 0.75.5 is intentionally unsupported because it lacks the terminal event required to seal a Fusion audit after retries and compaction. It then drives the current host Pi through a real RPC `fusion_reason` parent-agent loop, checks the persisted tool result carries the complete Pi `Usage.cost` object, invokes `get_session_stats` (the same aggregation boundary used by the TUI footer), reopens the durable session, and verifies identical token/cost totals. All parent and child inference remains deterministic and local.
191
196
 
192
197
  ## Coverage summary
193
198
 
194
199
  Implemented coverage includes:
195
200
 
196
201
  - tools: `bg_run`, `bg_run_pi_attested`, `bg_status`, `bg_logs`, `bg_kill`, `fusion_reason`, `fusion_investigate`, `fusion_research`, `fusion_validate`, including required `isAgent` schema/runtime validation, the event-driven no-sleep/no-poll system-prompt contract, truthful launch receipts for all four notification/wake combinations, non-terminating `bg_run` compatibility, point-in-time status/log guidance, durable terminal-notification authority, attested direct Pi spawn validation, Fusion immediate launch receipts, managed progress, hash-verified `bg_result` delivery, exactly-once usage, and context exclusion, reason versioned conversation projection with explicit hash-accounted tool/thinking omissions, clean-task context isolation, pre-spawn stage budget rejection for all four expansion stages, image omission markers with raw image data excluded from child prompts, unknown/ambiguous IDs, completed-kill failure, legacy no-name preparation, head/tail truncation, and notification on/off behavior
197
- - commands: `/bg`, `/jobs`, `/logs`, `/kill`, `/tasks`, `/bg-tasks`, `/bg-clear`, `/bg-update`, `/fusion`, `/fusion-models` discovery, happy paths, `/fusion` non-blocking managed-task launch and terminal notification, `/fusion` editor/cancel flow, `/fusion-models` TUI save and non-TUI rejection, `/bg --agent` parsing, finished-notice clearing, malformed `/bg`, unknown/ambiguous IDs, completed-task `/kill`, byte-limit normalization, and RPC no-hang fallback behavior
202
+ - commands: `/bg`, `/jobs`, `/logs`, `/kill`, `/tasks`, `/bg-tasks`, `/bg-clear`, `/bg-update`, `/claude-cache`, `/fusion`, `/fusion-models` discovery, happy paths, `/fusion` non-blocking managed-task launch and terminal notification, `/fusion` editor/cancel flow, `/fusion-models` TUI save and non-TUI rejection, `/bg --agent` parsing, finished-notice clearing, malformed `/bg`, unknown/ambiguous IDs, completed-task `/kill`, byte-limit normalization, and RPC no-hang fallback behavior
198
203
  - update-available notice: semver parse/compare/precedence, `formatUpdateSegment`, npm/`package.json` payload narrowing, and injected-fetch success/404/throw/timeout (unit); localhost-registry footer segment (idle + appended to an active footer), `/bg-update` non-installing instructions, and opt-out/offline/already-current/registry-failure no-segment-and-no-throw paths (SDK); `/bg-update` discovery and offline instructions (RPC). The check is one-shot on `session_start`, time-boxed, offline-safe, gated by `PI_OFFLINE`/`PI_BG_DISABLE_UPDATE_CHECK`, and `PI_BG_REGISTRY_URL` overrides the registry endpoint
199
204
  - shortcut/UI: component coverage for focused dock list/detail/key handling, detail output-tail scrolling (arrow/page scroll, follow-pause-on-scroll, `lines X–Y of N` position indicator, resume-follow-at-bottom, and no-scroll when output fits), empty/history/unread states, paging, close aliases, stop/stop-all/rerun/path actions, missing output files; SDK coverage for explicit `/bg-clear` finished-notice clearing, `/bg-clear` footer hinting, optional `Ctrl+Alt+C` fallback shortcut registration, and mixed failed/stopped/done/focused footer status; RPC coverage that `/bg-clear` works as a terminal-independent clear path; and PTY coverage for `/tasks`, `/bg-tasks`, real `Shift+Down`, arrows, page keys, detail/back/history/stop/stop-all/rerun/path/close, failed unread badges, and running/completed/failed/killed rerun paths
200
205
  - runtime files: output and metadata files under `.pi/tasks/`, Fusion private `.pi/fusion/<session-id>-<pid>/<run-id>/` artifacts plus global `fusion-models.json`, persisted `isAgent` classification, task-owned context-window telemetry snapshots, cumulative background Pi-agent token usage, tool-use counts, agent model identifier (preferring the fully-qualified `provider/model` form), explicit `isAgent:true` telemetry wrapping for background `pi` agents, `isAgent:false` non-wrapping for scripts, attested Pi flat siblings (`.pi-events.jsonl`, `.stderr`, `.pi-telemetry-wrapper.cjs`, `.attestation.json`), real child `pi --mode json` tool-event parsing for background-agent telemetry, split/large telemetry ingestion, metadata after completion/failure, Fusion v2 compact final-only metadata and explicitly marked partial-response artifacts, and Fusion manifest token plus complete cost-component aggregates equal to the sum of successful and observed failed/cancelled attempts
201
206
  - extension EventBus API: unit coverage for `pi-background-tasks:request:v1`/`response:v1` closed-frame validation, exact capability handshake, malformed payload rejection, unknown keys, unknown operations, duplicate request IDs, missing `session_start`, shutdown refusal, unsubscribe, strict terminal frame shape, and response-barrier ordering; registry coverage for one terminal publication after durable metadata when emit succeeds plus loud/retriable delivery failure. A retry after a listener throws can redeliver to an earlier listener, so consumers deduplicate by task id. SDK coverage uses a shared real `createEventBus()`, starts `printf api-ok`, reads bounded logs, observes one terminal event after the run response, and kills a real sleep task without model/provider calls
202
- - attested Pi producer: unit/SDK coverage for 128-bit attested task ids, exact direct argv/cwd, ModelRegistry OAuth observation without secrets, raw Pi session/message events, separate stderr, prompt/report/source hashes, authority start/finish commit/tree/clean checks, atomic metadata serialization, completion visibility only after the sidecar is durable, malformed event rejection, and no attestation sidecar for ordinary tasks
207
+ - attested Pi producer: unit/SDK coverage for 128-bit attested task ids, exact direct argv/cwd, explicit package attribution on Anthropic routes only, ModelRegistry OAuth observation without secrets, raw Pi session/message events, separate stderr, prompt/report/source hashes, authority start/finish commit/tree/clean checks, atomic metadata serialization, completion visibility only after the sidecar is durable, malformed event rejection, and no attestation sidecar for ordinary tasks
203
208
  - agent activity transcript: pure `parseAgentActivity`/`formatAgentActivityLine` coverage (assistant text, reasoning, tool start with arg summary, silent successful tool end, `✗ tool failed` errors, truncation, invalid/non-activity narrowing); registry-unit coverage that wrapped-agent stdout is reconstructed across split chunks into the human-readable transcript while telemetry/activity control JSON is stripped from the output file (telemetry fields still updated), stderr passes through, and the trailing partial line is flushed on finalize; SDK coverage that fake and real child `pi --mode json` runs surface `→ tool`/`✗ tool failed`/assistant text in `bg_logs` with no control JSON leaking into the visible output
204
209
  - durability: `tests/unit/durable-fs.test.ts` covers the shared `src/core/durable-fs.ts` primitive used for metadata, event/stderr buffers, attestations, delegate/Fusion artifacts, and configuration — single-open write/sync/close ordering, exclusive `wx` temp creation at `0o600`, direct `w` writes with inherited mode, never reopening a pathname merely to flush it, temp ownership, primary-versus-cleanup error precedence, `renameCompleted` after a post-rename directory failure, the Windows directory-sync skip, atomic replacement, and fatal `fsync` failures. Ordinary task `.output` is a streaming file ended/drained before terminal metadata and is not explicitly fsynced. `tests/package/package.test.ts` mutation guards pin the durable-helper invariants
205
210
  - safety: kill, already-finished kill failure, timeout failure, spawn failure, low output-cap failure, multi-task shutdown cleanup, POSIX process-group kill fallback, Windows `taskkill /T` then `/T /F` tree termination with shared soft attempts, soft-abort-on-force, exit-128 race tolerance, loud force failures, no root-only fallback, SIGKILL escalation that terminates instead of re-arming (a SIGKILL never schedules a further escalation, and concurrent stop requests share exactly one escalation timer that is cleared on finalize), duplicate finalization/notification races, metadata/notification failure handling, and pruning
206
211
  - agent loop: deterministic scripted-provider coverage against `extensions/background-tasks.ts` for actual event-driven `bg_run` behavior. The provider observes the effective system prompt, public tool descriptions, and real launch receipt and deliberately emits the pre-fix `bg_status` poll if any contract layer is absent; the passing path proves one launch, no sleep/status/log polling, one durable terminal notification, and exactly one follow-up turn. It also covers notification-only `triggerOnCompletion:false`, `/bg` display-only behavior, `notifyOnCompletion:false`, failed-task notification error fields, and parent-model `fusion_reason` tool use followed by normal parent response
207
- - package: manifest, docs, `pi.extensions`, exported `src/core/extension-api.ts`, peer dependency/import parity, packed runtime files, tarball-install smoke, direct-completion import bans, test/helper/script/artifact exclusion, isolated offline npm installation, exact-version compatibility, and current-host persisted/replayed tool-usage safety
212
+ - package: manifest, docs, ordered `pi.extensions`, exported `src/core/extension-api.ts`, registry-only production dependencies, peer dependency/import parity, packed runtime files/notices, tarball-install smoke, direct-completion import bans, test/helper/script/artifact exclusion, isolated offline npm installation, exact-version compatibility, and current-host persisted/replayed tool-usage safety
208
213
 
209
214
  ## PTY notes
210
215
 
package/TEST_PLAN.md CHANGED
@@ -13,14 +13,14 @@ The table below remains the exhaustive acceptance source. Do not replace it with
13
13
  | Field | Value |
14
14
  |---|---|
15
15
  | Package | `pi-background-tasks` |
16
- | Extension entrypoint | `extensions/background-tasks.ts` |
17
- | Public commands | `/bg`, `/jobs`, `/logs`, `/kill`, `/tasks`, `/bg-tasks`, `/bg-clear`, `/bg-update`, `/fusion`, `/fusion-models` |
16
+ | Extension entrypoints | `extensions/anthropic-attribution.ts`, `extensions/background-tasks.ts` |
17
+ | Public commands | `/bg`, `/jobs`, `/logs`, `/kill`, `/tasks`, `/bg-tasks`, `/bg-clear`, `/bg-update`, `/claude-cache`, `/fusion`, `/fusion-models` |
18
18
  | Public tools | `bg_run`, `bg_delegate`, `bg_result`, `bg_run_pi_attested`, `bg_status`, `bg_logs`, `bg_kill`, `fusion_reason`, `fusion_investigate`, `fusion_research`, `fusion_validate` |
19
19
  | Extension EventBus API | `pi-background-tasks:request:v1`, `pi-background-tasks:response:v1`, `pi-background-tasks:terminal:v1`; schemas exported from `src/core/extension-api.ts` |
20
20
  | Shortcuts | `Shift+Down`; optional fallback `Ctrl+Alt+C` |
21
21
  | Custom UI | footer status + focused bottom dock overlay |
22
- | Custom provider | no |
23
- | Runtime files/state | `.pi/tasks/<session-id>-<pid>/<task-id>.output`, `.pi/tasks/<session-id>-<pid>/<task-id>.json`; attested Pi opt-in adds `.pi-events.jsonl`, `.stderr`, `.pi-telemetry-wrapper.cjs`, `.attestation.json`; Fusion adds private `.pi/fusion/<session-id>-<pid>/<run-id>/` manifests/prompts/events/stderr/responses/evaluation/merged/error artifacts plus `context-omission-ledger.json` and `budget-plan.json` plus global `fusion-models.json` |
22
+ | Custom provider | package-owned `anthropic` subscription-OAuth attribution transport; provider-gated, no non-Anthropic override |
23
+ | Runtime files/state | `.pi/tasks/<session-id>-<pid>/<task-id>.output`, `.pi/tasks/<session-id>-<pid>/<task-id>.json`; attested Pi opt-in adds `.pi-events.jsonl`, `.stderr`, `.pi-telemetry-wrapper.cjs`, `.attestation.json`; Fusion adds private `.pi/fusion/<session-id>-<pid>/<run-id>/` manifests/prompts/events/stderr/responses/evaluation/merged/error artifacts, plus manifest-bound `failure-summary.json` only for failed/cancelled stored runs, `context-omission-ledger.json`, `budget-plan.json`, and global `fusion-models.json` |
24
24
  | Maintainer docs/gateway | `BACKGROUND-TASKS-INSTRUCTIONS.md`, `docs/api/eventbus-v1.md`, `docs/concepts/context-projection-and-budgeting.md`, `docs/subsystems/child-launch-durability-and-safety.md`, `docs/reference/runtime-contracts.md`, `docs/operations/{troubleshooting,testing,releasing}.md`, `TESTING.md`, `TEST_PLAN.md`, `PUBLISHING.md` |
25
25
 
26
26
  ## Required gates
@@ -37,6 +37,7 @@ The table below remains the exhaustive acceptance source. Do not replace it with
37
37
  | Scripted provider | `npm run test:agent-loop` | full gate | implemented |
38
38
  | Hook contract | `npm run test:hook-contract` | yes | implemented; drives a real Pi agent loop and compares observed `context`/`tool_result` behaviour against committed evidence. Fails loudly if Pi's hook semantics change rather than regenerating them |
39
39
  | Pack dry run | `npm run pack:dry-run` | release gate | implemented |
40
+ | Pnpm exotic-subdependency regression | `npm run test:pnpm-pack` with pnpm 11.18.0 | Linux CI/release gate | implemented; installs the packed tarball with `blockExoticSubdeps: true` and rejects exotic production specifiers |
40
41
  | Smoke | `npm run smoke` | no | implemented; isolated load-only |
41
42
  | Large-context smoke | `npm run smoke:large-context` | release gate | implemented; rebuilds the production failure byte composition, proves the pre-fix input is rejected and the post-fix projection fits all four stages against the smallest configured route, with no inference and no child spawn |
42
43
  | Live subscription evidence | `npx tsx scripts/delegate-live-run.ts` | release gate | implemented; one real subscription-OAuth child on the parent's current route, large seeded session, hash-verified answer, and explicit leak checks. Caught two defects no offline gate did (undelivered prompt, seed-not-prompt budgeting), both now pinned by unit and mutation tests |
@@ -75,8 +76,8 @@ SDK/RPC/scripted-provider/package/compatibility coverage asserts exactly four to
75
76
  | Read task logs | `bg_logs` | yes | yes | | | | | yes | SDK verifies bounded content and the model-facing no-wait-loop contract. Scripted-provider ordinary waiting makes zero log calls. |
76
77
  | Stop task from LLM tool | `bg_kill` | | yes | | | | | | Covers running kill and already-finished loud failure. |
77
78
  | Fusion command background launch | `/fusion`, managed task, terminal notification, `bg_result` | yes | yes | yes | | yes | yes | | Core unit covers deterministic projection, child argv/stdin/metadata parsing, artifacts, pre-abort handling, and orchestration. SDK verifies `/fusion` returns after durable preflight, all five child invocations continue in the managed task, terminal notification is emitted without a parent rewrite, editor/cancel behavior remains correct, and malformed config launches zero children. RPC verifies command discovery, Unicode request preservation, background terminal delivery, no parent `agent_start`, editor protocol, malformed-config admission failure, child failure notification, and child isolation flags. |
78
- | Fusion v1 background result | `fusion_reason`, `fusion_investigate`, `fusion_research`, `fusion_validate`, `bg_result` | yes | yes | | | current-host stats/replay | yes | yes | Exactly four workflow tools remain registered; each returns a managed-task receipt after durable no-child preflight. `bg_result` verifies manifest-bound `result.json`/`merged.md`, never truncates, and attaches complete `Usage` exactly once. SDK pins non-blocking launch under delayed children, tool-signal ownership handoff, clean-context isolation, failure coordinates, shutdown cancellation, and repeated-retrieval no-double-counting. Scripted-provider coverage proves no polling between launch and terminal wake. |
79
- | Fusion Anthropic attribution and sanitization | package-owned `anthropic-attribution.ts`, `@ravshansbox/pi-anthropic-sps`, child `--extension` argv | yes | | | | | yes | | Unit proves a Claude route receives exactly three explicit extensions in fixed order: the package-owned Claude Code OAuth attribution provider, sanitizer, then runtime governor/metadata extension. The repo-local `spawn-anthropic-attribution` entrypoint re-exports the same implementation. Attribution tests pin linked session/account/device metadata, exact model beta policy, beta-resource transport, cache surfaces, one-hour pricing, and the 200K subscription contract; the governor therefore observes and validates the final attributed and sanitized payload. Every non-Anthropic provider still receives exactly one extension and resolves neither Claude dependency. Resolution failures remain loud, and package guards require the sanitizer dependency plus provider gate. |
79
+ | Fusion v1 background result | `fusion_reason`, `fusion_investigate`, `fusion_research`, `fusion_validate`, `bg_result` | yes | yes | | | current-host stats/replay | yes | yes | Exactly four workflow tools remain registered; each returns a managed-task receipt after durable no-child preflight. `bg_result` verifies manifest-bound `result.json`/`merged.md`, never truncates, and attaches complete `Usage` exactly once. Failed/cancelled retrieval returns `delivery:"none"` and a closed no-answer view backed only by verified, bounded `failure-summary.json` metadata/refs; it cannot claim usage or expose partial text. SDK pins non-blocking launch under delayed children, tool-signal ownership handoff, clean-context isolation, failure coordinates, shutdown cancellation, and repeated-retrieval no-double-counting. Scripted-provider coverage proves no polling between launch and terminal wake. |
80
+ | Global Anthropic attribution and sanitization | package-owned `extensions/anthropic-attribution.ts`, `/claude-cache`, isolated child `--extension` argv | yes | | | | | yes | | Package discovery loads attribution before background tasks for every installation. Unit pins all three exact SPS-derived sanitization variants, non-Anthropic non-mutation, provider/session/account/device metadata, beta-resource transport, cache surfaces, one-hour pricing, the 200K subscription contract, and EventBus duplicate-owner suppression. Fusion Anthropic routes receive exactly two explicit extensions in order: global attribution/sanitization, then runtime governor. Delegate and attested Anthropic routes also load attribution explicitly because attribution cannot rely on ambient discovery; delegates do so in both isolated and ambient modes. Non-Anthropic argv does not resolve or add attribution. Missing bytes fail loudly; the package has no exotic/URL sanitizer dependency. The independent repo-local spawn extension is byte-parity tested but imports nothing from this package. |
80
81
  | Fusion validation workflow | structured `fusion_validate`, workflow profiles, `fusion-manifest.v4`, `fusion-result.v5` | yes | yes | | | | yes | | Public validation rejects legacy `{prompt}` with a migration error, enforces non-empty `scope`/`acceptanceCriteria`, and loudly validates `verification` cross-fields (`provided` ↔ evidence, `not_run` ↔ reason). Core validate orchestration is clean/read-only/advisory, enforces source-finding accounting including singleton, duplicate, exclusion, and merger add/drop cases, and remains no build/test substitute claim. |
81
82
  | Fusion context boundaries | canonical input `fusion-input.v5`, reason `context-omission-ledger.json`, clean-task inputs | yes | yes | yes | | | yes | | Unit covers reason/session projection for a >1 MB synthetic tool-heavy session, verbatim user/assistant text, thinking exclusion, zero tool-payload preview bytes, exact and stable omission counts/byte totals/hashes, compact tuple round-trip, receipt-to-ledger reconciliation, active-tool-call-leaf and sibling-call exclusion, and byte-identical repeated construction. Clean-task tests assert investigate/research/validate inputs omit parent system prompt, conversation projection, and omission ledger, stay byte-identical across unrelated parent sessions, and keep parent sentinels out of every clean downstream prompt and artifact. SDK/RPC verify clean validate stdin has no `conversation_projection` or transcript while `/fusion`/reason preserve the projected-conversation path. |
82
83
  | Fusion stage budgets | `budget-plan.json` (v4 per-stage forecasts), typed `prompt_budget_exceeded_forecast` / `prompt_budget_exceeded_measured` | yes | | | | | | | Unit covers stage-local launch-refusal wording plus terminal progress derived from durable attempts and persisted usage, so late evaluator/repair/merger budget failures report completed, failed, cancelled, and not-started run truth. Unit also covers the per-family affine estimator, additive segment accounting, multibyte 1.0-token/byte charging, unknown-provider floor visibility, per-route reservation of `max(Fusion output contract, model maximum output)`, byte-capacity route selection, scope guards for small windows, input-only fatal preflight versus warning-only reservations, rejection of unknown/zero/negative/too-small context windows, boundary accept at exactly the limit and reject one byte past, the child system prompt counted as input, per-stage forecasts built from the real prompt builders against each stage's own route, reservation warnings, breach-detector artifacts, safe prompts completing all five calls, persisted route/plan snapshots including negative slack on fatal rejection, and the reproduced 1 MB failure shape now fitting the smallest configured budget. Errors carry stage, measured size, allowed size, limiting model, estimator source, and remediation in both structured detail and message text. |
@@ -88,15 +89,15 @@ SDK/RPC/scripted-provider/package/compatibility coverage asserts exactly four to
88
89
  | Fusion candidate tool-call audit log | `candidate-<slot>.attempt-<n>.tool-calls.jsonl`, `*.seal.json`, `pi-background-tasks.fusion-tool-call.v1` | yes | | | | | | | Unit proves completed tool calls are logged with tool name, byte counts, and hashes while raw arguments/results containing a secret never appear. Children are independently bounded to 192 attempted tool calls and 8 MiB aggregate tool-result bytes; a limit refusal emits structured evidence, aborts, and cannot publish a complete seal. Repeated low-level `agent_end` boundaries publish no seal; terminal `agent_settled` exclusively seals the complete log after all retry/compaction/follow-up work. The 46-call incident regression proves a 22-call prefix is never sealed and duplicate settlement fails without replacement. Shutdown before settlement writes failed evidence and latches process failure. The parent rejects extension diagnostics and missing/failed/mismatched seals and independently rejects aggregate result bytes above 8 MiB. A trailing partial line, ordinal gap, duplicate ordinal, wrong schema version, and inspect-child partial log all fail loudly. |
89
90
  | Pi/TypeBox compatibility | `peerDependencies`, packed bytes | yes | | | | | yes | | Unit pins typebox as a `"*"` peer that is neither a runtime nor bundled dependency, requires the resolved TypeBox to be Pi 0.83/0.84's 1.3.x line, requires all four supported Pi/TUI lines in the peer range, scans all package TypeScript for the seven removed TypeBox APIs, and compiles the shipped tool schema plus nullable-array/nullable-string and optional-field shapes under TypeBox 1.3. The release compat gate repeats the removed-API scan against installed package bytes per Pi version. |
90
91
  | Pi hook contract | `npm run test:hook-contract`, `tests/scripted-provider/pi-hook-contract-evidence.json`, `src/core/delegate/hook-contract-evidence.json` | | | | | | evidence parity | yes | Executes real Pi agent loops and records, rather than assumes: Fusion `before_provider_request` transformations chain in extension load order through the Codex transport adapter and abort before local HTTP transport; Delegate `context` fires once before every model call in load order; returned messages reach the provider; **throwing** in `context` does NOT block dispatch (Pi catches and continues); `ctx.abort()` either skips provider invocation (Pi 0.84) or delivers an already-aborted signal (older supported lines), blocks transport, and terminates the run; `tool_result` fires before the transcript entry, chains in load order, replacement reaches the provider while the original does not, and toolCallId/role/`isError` survive. Handler ordering across two separate probe extensions is pinned. The evidence file is compared, never silently regenerated, and a package test asserts the shipped copy is byte-identical. |
91
- | Delegate context seeding | `bg_delegate` seed `pi-background-tasks.delegate-seed.v1`, `seed.json`, `context-omission-ledger.json` | yes | yes | | | | mutation guard | yes | Unit covers verbatim visible user/assistant text, complete exclusion of thinking/tool-call arguments/tool-result payloads, marker-only images with no raw bytes anywhere in the seed, exclusion of the in-flight `bg_delegate` call **and every sibling call in the same assistant message** (two delegates launched together get byte-identical projected history), the prompt preserved exactly and marked `explicit_text` authority, zero payload-preview bytes, byte-identical construction across repeated builds and across separate processes via a fixed-leaf fixture, and refusal of a blank prompt. Receive-side verification rejects a single mutated byte, a foreign task identity, a structurally malformed seed whose hash matches, a directive whose hash disagrees with its text, and an unsupported capability. SDK proves the projected parent text actually reaches the child. |
92
+ | Delegate context seeding | `bg_delegate` seed `pi-background-tasks.delegate-seed.v2`, `seed.json`, `context-omission-ledger.json` | yes | yes | | | | mutation guard | yes | Unit covers verbatim visible user/assistant text, complete exclusion of thinking/tool-call arguments/tool-result payloads, marker-only images with no raw bytes anywhere in the seed, exclusion of the in-flight `bg_delegate` call **and every sibling call in the same assistant message** (two delegates launched together get byte-identical projected history), the prompt preserved exactly and marked `explicit_text` authority, hash-bound `extension_mode`, zero payload-preview bytes, byte-identical construction across repeated builds and across separate processes via a fixed-leaf fixture, and refusal of a blank prompt. Receive-side verification rejects a single mutated byte, a foreign task identity, a structurally malformed seed whose hash matches, a directive whose hash disagrees with its text, an unknown extension mode, and an unsupported capability. SDK proves the projected parent text actually reaches the child. |
92
93
  | Delegate route pinning | `bg_delegate` `route`, `route_attestations` | yes | yes | | | | mutation guard | yes | Unit covers defaulting to the parent current model, explicit pinning, refusal of an unavailable route with `route_unresolved` and no substitution, refusal of a route with no declared context window with `route_capacity_unknown` rather than assuming one, and refusal when neither is available. The result package rejects a mismatched route, a mismatched attestation, and a package carrying no attestation at all. The scripted-provider gate proves an observed route drift prevents a success commit entirely. The mutation guard fails if a fallback list or first-available selection appears. |
93
94
  | Delegate budget and guard | `budget-plan.json`, typed `seed_budget_exceeded` / `provider_context_budget_exhausted` | yes | yes | | | | mutation guard | yes | Unit covers reserve subtraction, exact-boundary accept and one-byte-past reject, the child system prompt counted as input, multi-byte UTF-8 measured by bytes, refusal of unusable windows without defaulting, and a total runtime governor that cannot throw from inside a hook. Preflight rejection is proven to create **zero** children and **zero** artifacts for hook-contract, budget, and blank-prompt refusals, with the artifact directory verified absent. The scripted-provider gate proves an over-budget model call is blocked in a real agent loop and produces a typed terminal record with no committed result. |
94
95
  | Delegate tool-result spilling | `spill/` artifacts, `pi-background-tasks.delegate-receipt.v1`, `delegate_read_artifact` | yes | yes | | | | mutation guard | yes | Unit proves a 2 MB payload is written in full, hashed, and represented by a receipt carrying `(turn_sequence, source_call_index, tool_call_id)` assigned before execution, so parallel spills completing out of order cannot be mis-associated; an aggregate-cap refusal writes nothing and emits no receipt; bounded range reads return exactly the requested bytes; a range past end-of-file, a path escaping the artifact directory, and non-positive lengths are refused rather than shortened. The scripted-provider gate proves in a real agent loop that the raw payload never enters the transcript, the transcript instead carries a receipt naming the hash and stating nothing was truncated, and an over-long range read fails loudly. |
95
96
  | Delegate result commit and `bg_result` | `result.json` (`pi-background-tasks.delegate-result.v1`), `bg_result` | yes | yes | | | | mutation guard | yes | The single atomically-committed package is the sole answer data plane: temp-write, file fsync, and rename, with the rename as the commit point; POSIX additionally fsyncs the parent directory while Windows explicitly lacks that portable directory-entry guarantee. Unit covers round-trip verification, multi-block concatenation, exact preservation of U+2028/U+2029/emoji/unnormalized sequences, refusal of lone surrogates rather than U+FFFD substitution, detection of block-hash, aggregate-hash, declared-length, and non-strict-base64 corruption, foreign identity/seed rejection, and explicitly unavailable usage that is never reported as zero. Terminal evaluation treats a zero-exit child with no committed package as typed `child_exited_without_commit`, reports the child-recorded reason when present, and classifies a killed task as cancelled. SDK covers not-ready (non-blocking), completed, corrupted, route-drift, and unknown-task paths, and proves an oversized answer degrades to an artifact reference while an explicit inline request fails with `result_too_large_for_inline` and is never truncated. |
96
- | Delegate isolation boundary | child argv, `--session-id`, `--session-dir`, `--tools` | yes | yes | | | | mutation guard | yes | Unit proves the child receives its own session id and a task-owned session directory, no `--continue`/`--resume`/`--session`/`--fork`, only the inspect tool set, an explicit denylist covering `bash`/`edit`/`write`/`bg_delegate` and all current/retired Fusion tools, disabled discovery of extensions/skills/prompt templates/themes/context files, exactly one explicitly loaded package guard extension, explicit provider/model with no `--api-key`, and parent session identity stripped from the child environment. SDK verifies the same facts from the argv and environment the child actually observed. |
97
+ | Delegate extension/isolation boundary | `extensionMode`, child argv, `--session-id`, `--session-dir`, `--tools` | yes | yes | | | | mutation guard | yes | Unit proves default/explicit isolated mode sets `--no-extensions`; ambient mode omits only that flag; both modes retain separate task-owned session identity, inspect-only model tools, the explicit denylist, disabled skills/prompt templates/themes/context files, and the package guard; Anthropic keeps attribution-before-guard in both modes. Public schema/preparation rejects unknown modes, arbitrary `extensions`/`extensionPaths`, and route substitution. Seed/task facts/launch details/manifest bind the selected mode, and ambient receipt text warns that arbitrary extension code executes outside the tool sandbox. SDK verifies argv, warning, and metadata. A fresh-process scripted-provider regression installs a provider only in a temp global extension directory: isolated mode fails unknown-provider with no result, while ambient mode resolves that exact pinned provider and commits under the guard. |
97
98
  | Fusion artifact byte immutability | `canonical-input.json`, `context-omission-ledger.json`, `budget-plan.json` | yes | | | | | shared-source guard | | A 28-case differential corpus is rendered to raw bytes and compared against a committed golden file that is never auto-updated once present, and separately against `tests/oracle/fusion-context-pre-extraction.ts`, a verbatim pre-extraction copy of the projection engine used as an **independent oracle**. Equivalence covers canonical input, ledger, and budget-plan bytes, `Object.is` comparison of budget floats including `utilization`, field-for-field accounting parity, ledger root hashes, and identical error type and message for unknown blocks and blank requests. The package guard now scans the shared `context/` modules, not only the Fusion facade, and pins both the shared divisor definition and Fusion's binding to it. |
98
99
  | Fusion model selector | `/fusion-models`, `fusion-models.json`, `FusionModelSelector` | yes | yes | yes | yes | yes | yes | | Unit covers strict config parsing, duplicates, slash-containing model IDs, stale model failures, `$current`, atomic save, inter-process lock/revision compare-and-swap, and deterministic concurrent-save conflict. Component covers all five slots, duplicate selection, searchable model list, stale display, reset/save/cancel, persistence errors, and width safety. SDK drives the real command in a synthetic TUI context without `ctx.mode` to cover old Pi compatibility and verifies duplicate `$current`/explicit model persistence; SDK also verifies headless no-UI rejection. RPC verifies non-TUI notification without hanging, PTY verifies the real selector opens in a TUI, and compatibility smoke verifies print-mode rejection for every supported Pi version. |
99
- | Fusion child isolation/lifecycle | child `pi --mode text`, private compact metadata extension, shutdown cleanup, `.pi/fusion` artifacts | yes | yes | yes | | current-host stats/replay | yes | real Pi output recovery | BUG-180 coverage proves final-text transport, reasoning exclusion, strict response reconstruction, unchanged caps, isolation, process cleanup, failure artifacts, and lifecycle semantics. Candidate prompts disclose the exact 49,152 JSON-rendered-byte cap. One oversized candidate answer is durably preserved and receives one same-process/session, same-route, tool-disabled compression follow-up before terminal settlement; a second oversize fails without truncation or another child. Unit coverage pins success, second-oversize failure, validation JSON, cancellation, usage, artifact hashing/tampering, and original/replacement artifacts; scripted-provider coverage proves the real Pi print-mode lifecycle. BUG-182 preserves all token and cost components—including optional `cacheWrite1h` and `reasoning` subsets—and proves successful plus failed/cancelled attempt costs aggregate exactly once. Claude cache coverage pins native pre-serialization `ttl: "1h"` requests, explicit short/none/long and call-level-none precedence, model fallback, no-marker compaction preservation, four-breakpoint enforcement, attribution→sanitizer→normalizer ordering, prompt-caching-scope beta idempotence, 200K attributed route capacity, and hash-bound payload observations plus provider-authoritative `cacheWrite1h` usage in child-result v4/settlement v3 artifacts. SDK/RPC verify public child isolation; session shutdown tracks initializing and live runs. |
100
+ | Fusion child isolation/lifecycle | child `pi --mode text`, private compact metadata extension, shutdown cleanup, `.pi/fusion` artifacts | yes | yes | yes | | current-host stats/replay | yes | real Pi output recovery | BUG-180 coverage proves final-text transport, reasoning exclusion, strict response reconstruction, unchanged caps, isolation, process cleanup, failure artifacts, and lifecycle semantics. Candidate prompts disclose the exact 49,152 JSON-rendered-byte cap. One oversized candidate answer is durably preserved and receives one same-process/session, same-route, tool-disabled compression follow-up before terminal settlement; a second oversize fails without truncation or another child. Unit coverage pins success, second-oversize failure, validation JSON, cancellation, usage, artifact hashing/tampering, and original/replacement artifacts; scripted-provider coverage proves the real Pi print-mode lifecycle. BUG-182 preserves all token and cost components—including optional `cacheWrite1h` and `reasoning` subsets—and proves successful plus failed/cancelled attempt costs aggregate exactly once. Claude cache coverage pins native pre-serialization `ttl: "1h"` requests, explicit short/none/long and call-level-none precedence, model fallback, no-marker compaction preservation, four-breakpoint enforcement, attribution/sanitization→normalizer ordering, prompt-caching-scope beta idempotence, 200K attributed route capacity, and hash-bound payload observations plus provider-authoritative `cacheWrite1h` usage in child-result v4/settlement v3 artifacts. SDK/RPC verify public child isolation; session shutdown tracks initializing and live runs. |
100
101
  | Extension request/response service | `pi-background-tasks:request:v1` → `pi-background-tasks:response:v1` | yes | yes | | | | yes | | Unit covers closed-frame validation, capability handshake, unknown keys, unknown operation, duplicate request IDs, missing `session_start`, shutdown refusal, strict `run.payload`, strict malformed frames, and unsubscribe. SDK loads the real extension with a shared `createEventBus()`, starts `printf api-ok`, reads bounded logs, lists status, starts and kills a real sleep task, and checks malformed/unknown/duplicate controls without model/provider calls. Package tests assert `src/core/extension-api.ts` ships. |
101
102
  | Terminal EventBus publication | `pi-background-tasks:terminal:v1` | yes | yes | | | | yes | | Registry unit proves one terminal snapshot after durable metadata when EventBus emit succeeds and loud/retriable delivery failure. Because retry after a listener throws may redeliver to an earlier listener, consumers must deduplicate by task id. Extension API unit proves one strict terminal frame correlated by task id after the run response for immediate, normal, failed, timeout, and killed tasks; SDK observes one terminal event for a completed task and one for a killed task through the real extension service. |
102
103
  | Completion notification | custom message `background-task-notification` | yes | yes | | renderer via typecheck | | | yes | BUG-181 unit/SDK coverage pins the durable-terminal guidance and truthful effective delivery receipts. Scripted provider loads the shipped extension, conditionally attempts the old `bg_status` poll when the real system prompt/descriptions/receipt are incomplete, and proves the fixed contract instead yields with exactly one `bg_run`, one terminal notification, and one default follow-up. Notification-only, notification-disabled, failed-task, and display-only `/bg` paths remain covered. |
@@ -123,8 +124,8 @@ SDK/RPC/scripted-provider/package/compatibility coverage asserts exactly four to
123
124
  | Output cap kills task | `PI_BG_MAX_OUTPUT_BYTES` | | | yes | | | | | RPC runs with a low cap and asserts failed status/log notice. |
124
125
  | Shutdown cleanup | `session_shutdown` | yes | yes | | | | | | SDK asserts multiple running tasks become killed; registry tests cover shared stop/wait behavior. |
125
126
  | Process lifecycle/races | registry core | yes | yes | yes | | yes | | yes | Unit tests cover POSIX process-group fallback, Windows `taskkill /T` then `/T /F` tree termination, SIGKILL escalation, duplicate finalization/notification races, notification/metadata failures, pruning, malformed telemetry, split telemetry chunks, large telemetry records above the old 16KiB buffer, and wrapped-agent transcript/telemetry separation with split-chunk and trailing-partial flush; SDK/RPC cover runtime spawn/timeout/output-cap/shutdown; scripted provider covers wakeup integration. |
126
- | Package manifest | `package.json` | | | | | | yes | | Keywords, `pi.extensions`, files, local smoke/compat scripts, and direct-completion import bans. |
127
- | Pack contents | `npm pack --dry-run` | | | | | | yes | | Runtime files included; tests, fake child helpers, release-only scripts, artifacts, nested tarballs, and `node_modules` excluded. Default tarball install test uses isolated HOME/XDG/npm cache and offline peer-ignore install from the local tarball. |
127
+ | Package manifest | `package.json` | | | | | | yes | | Keywords, ordered `pi.extensions`, files/notices, registry-only production dependencies, local smoke/compat scripts, and direct-completion import bans. |
128
+ | Pack contents | `npm pack --dry-run`, `npm run test:pnpm-pack` | | | | | | yes | | Runtime files and third-party notice included; tests, fake child helpers, release-only scripts, artifacts, nested tarballs, and `node_modules` excluded. Default npm tarball install uses isolated HOME/XDG/npm cache and offline peer-ignore installation. Linux CI separately installs the tarball with pnpm 11.18.0 and `blockExoticSubdeps: true`. |
128
129
  | Maintainer docs gateway | `BACKGROUND-TASKS-INSTRUCTIONS.md` | docs focused | | | | | | | Gateway requires INDEX → read-before-edit → owning-doc navigation, records current docs generate/verify/attestation workflow, preserves subscription-only frontier routing, parent/child tool separation, durability/integrity, and no self-certification. Logo reference is package-local (`docs/assets/logo.svg`) when the asset-owner file is present. |
129
130
  | Shared architecture/API/runtime/operations docs | `docs/api`, `docs/concepts`, `docs/subsystems`, `docs/reference`, `docs/operations` | docs focused | | | | | | | The active docs engine validates frontmatter, package-local links/reference links, INDEX reachability, exact behavioral source ownership, generated runtime contracts, deterministic generated regions, and manifest freshness. Semantic receipt state is reported by default and enforced only by the optional strict attestation command. Unsupported extraction and legacy placeholders fail closed. |
130
131
  | Package maintenance version/tag wording | `PUBLISHING.md`, `docs/operations/releasing.md` | docs focused | | | | | | | Release commands derive `VERSION` from `package.json`; observed git tags stop at `v0.6.0`, so git install/tag certification is separate from npm publishing and no nonexistent v1 tag is advertised. |
@@ -0,0 +1,30 @@
1
+ # Third-party notices
2
+
3
+ ## Anthropic system-prompt sanitization rules
4
+
5
+ The exact-match Anthropic system-prompt sanitization rules in
6
+ `src/core/anthropic-attribution.ts` are derived from
7
+ [`ravshansbox/pi-anthropic-sps`](https://github.com/ravshansbox/pi-anthropic-sps)
8
+ at commit `17409b5615f0ec0625776bc5434f92f2c55e3fd0`.
9
+
10
+ Copyright (c) 2026 Ravshan
11
+
12
+ Licensed under the MIT License:
13
+
14
+ > Permission is hereby granted, free of charge, to any person obtaining a copy
15
+ > of this software and associated documentation files (the "Software"), to deal
16
+ > in the Software without restriction, including without limitation the rights
17
+ > to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
18
+ > copies of the Software, and to permit persons to whom the Software is
19
+ > furnished to do so, subject to the following conditions:
20
+ >
21
+ > The above copyright notice and this permission notice shall be included in all
22
+ > copies or substantial portions of the Software.
23
+ >
24
+ > THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25
+ > IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26
+ > FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27
+ > AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28
+ > LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29
+ > OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30
+ > SOFTWARE.
package/docs/INDEX.md CHANGED
@@ -49,6 +49,7 @@ Generated navigation for every package-local documentation page. This index inte
49
49
  | [operations/testing](./operations/testing.md) | authored | contract | evolving |
50
50
  | [operations/troubleshooting](./operations/troubleshooting.md) | authored | contract | evolving |
51
51
  | [reference/runtime-contracts](./reference/runtime-contracts.md) | mixed | contract | evolving |
52
+ | [subsystems/anthropic-attribution](./subsystems/anthropic-attribution.md) | authored | behavioral | evolving |
52
53
  | [subsystems/attested-pi-runs](./subsystems/attested-pi-runs.md) | authored | behavioral | evolving |
53
54
  | [subsystems/background-task-runtime](./subsystems/background-task-runtime.md) | authored | behavioral | stable |
54
55
  | [subsystems/child-launch-durability-and-safety](./subsystems/child-launch-durability-and-safety.md) | authored | behavioral | evolving |
@@ -65,6 +66,7 @@ Generated navigation for every package-local documentation page. This index inte
65
66
  | [commands/bg](./commands/bg.md) | mixed | contract | stable |
66
67
  | [commands/bg-clear](./commands/bg-clear.md) | mixed | contract | stable |
67
68
  | [commands/bg-update](./commands/bg-update.md) | mixed | contract | stable |
69
+ | [commands/claude-cache](./commands/claude-cache.md) | mixed | contract | evolving |
68
70
  | [commands/fusion](./commands/fusion.md) | mixed | contract | stable |
69
71
  | [commands/fusion-models](./commands/fusion-models.md) | mixed | contract | stable |
70
72
  | [commands/jobs](./commands/jobs.md) | mixed | contract | stable |
@@ -78,12 +80,12 @@ Generated navigation for every package-local documentation page. This index inte
78
80
  ## Docs by category
79
81
 
80
82
  - **api**: [api/eventbus-v1](./api/eventbus-v1.md)
81
- - **commands**: [commands/bg](./commands/bg.md), [commands/bg-clear](./commands/bg-clear.md), [commands/bg-update](./commands/bg-update.md), [commands/fusion](./commands/fusion.md), [commands/fusion-models](./commands/fusion-models.md), [commands/jobs](./commands/jobs.md), [commands/kill](./commands/kill.md), [commands/logs](./commands/logs.md), [commands/task-manager](./commands/task-manager.md)
83
+ - **commands**: [commands/bg](./commands/bg.md), [commands/bg-clear](./commands/bg-clear.md), [commands/bg-update](./commands/bg-update.md), [commands/claude-cache](./commands/claude-cache.md), [commands/fusion](./commands/fusion.md), [commands/fusion-models](./commands/fusion-models.md), [commands/jobs](./commands/jobs.md), [commands/kill](./commands/kill.md), [commands/logs](./commands/logs.md), [commands/task-manager](./commands/task-manager.md)
82
84
  - **concepts**: [concepts/completion-delivery](./concepts/completion-delivery.md), [concepts/context-projection-and-budgeting](./concepts/context-projection-and-budgeting.md)
83
85
  - **operations**: [operations/configuration](./operations/configuration.md), [operations/releasing](./operations/releasing.md), [operations/testing](./operations/testing.md), [operations/troubleshooting](./operations/troubleshooting.md)
84
86
  - **reference**: [reference/runtime-contracts](./reference/runtime-contracts.md), [reference/shortcuts-and-dock](./reference/shortcuts-and-dock.md)
85
87
  - **root**: [choose-a-workflow](./choose-a-workflow.md), [getting-started](./getting-started.md), [INDEX](./INDEX.md), [read-before-edit](./read-before-edit.md)
86
- - **subsystems**: [subsystems/attested-pi-runs](./subsystems/attested-pi-runs.md), [subsystems/background-task-runtime](./subsystems/background-task-runtime.md), [subsystems/child-launch-durability-and-safety](./subsystems/child-launch-durability-and-safety.md), [subsystems/delegation](./subsystems/delegation.md), [subsystems/docs-freshness-gate](./subsystems/docs-freshness-gate.md), [subsystems/fusion](./subsystems/fusion.md), [subsystems/host-ui-and-telemetry](./subsystems/host-ui-and-telemetry.md)
88
+ - **subsystems**: [subsystems/anthropic-attribution](./subsystems/anthropic-attribution.md), [subsystems/attested-pi-runs](./subsystems/attested-pi-runs.md), [subsystems/background-task-runtime](./subsystems/background-task-runtime.md), [subsystems/child-launch-durability-and-safety](./subsystems/child-launch-durability-and-safety.md), [subsystems/delegation](./subsystems/delegation.md), [subsystems/docs-freshness-gate](./subsystems/docs-freshness-gate.md), [subsystems/fusion](./subsystems/fusion.md), [subsystems/host-ui-and-telemetry](./subsystems/host-ui-and-telemetry.md)
87
89
  - **tools**: [tools/bg_delegate](./tools/bg_delegate.md), [tools/bg_kill](./tools/bg_kill.md), [tools/bg_logs](./tools/bg_logs.md), [tools/bg_result](./tools/bg_result.md), [tools/bg_run](./tools/bg_run.md), [tools/bg_run_pi_attested](./tools/bg_run_pi_attested.md), [tools/bg_status](./tools/bg_status.md), [tools/fusion_investigate](./tools/fusion_investigate.md), [tools/fusion_reason](./tools/fusion_reason.md), [tools/fusion_research](./tools/fusion_research.md), [tools/fusion_validate](./tools/fusion_validate.md)
88
90
 
89
91
  ## Public surface owners
@@ -94,6 +96,7 @@ Generated navigation for every package-local documentation page. This index inte
94
96
  | `command:bg-clear` | [commands/bg-clear](./commands/bg-clear.md) |
95
97
  | `command:bg-tasks` | [commands/task-manager](./commands/task-manager.md) |
96
98
  | `command:bg-update` | [commands/bg-update](./commands/bg-update.md) |
99
+ | `command:claude-cache` | [commands/claude-cache](./commands/claude-cache.md) |
97
100
  | `command:fusion` | [commands/fusion](./commands/fusion.md) |
98
101
  | `command:fusion-models` | [commands/fusion-models](./commands/fusion-models.md) |
99
102
  | `command:jobs` | [commands/jobs](./commands/jobs.md) |
@@ -129,16 +132,17 @@ Generated navigation for every package-local documentation page. This index inte
129
132
  | command | `bg-clear` | `command:bg-clear` | `src/extension.ts:559` |
130
133
  | command | `bg-tasks` | `command:bg-tasks` | `src/extension.ts:551` |
131
134
  | command | `bg-update` | `command:bg-update` | `src/extension.ts:567` |
135
+ | command | `claude-cache` | `command:claude-cache` | `src/core/anthropic-attribution.ts:1928` |
132
136
  | command | `fusion` | `command:fusion` | `src/fusion-extension.ts:996` |
133
137
  | command | `fusion-models` | `command:fusion-models` | `src/fusion-extension.ts:1029` |
134
138
  | command | `jobs` | `command:jobs` | `src/extension.ts:605` |
135
139
  | command | `kill` | `command:kill` | `src/extension.ts:649` |
136
140
  | command | `logs` | `command:logs` | `src/extension.ts:618` |
137
141
  | command | `tasks` | `command:tasks` | `src/extension.ts:543` |
138
- | tool | `bg_delegate` | `tool:bg_delegate` | `src/delegate-extension.ts:292` |
142
+ | tool | `bg_delegate` | `tool:bg_delegate` | `src/delegate-extension.ts:340` |
139
143
  | tool | `bg_kill` | `tool:bg_kill` | `src/extension.ts:908` |
140
144
  | tool | `bg_logs` | `tool:bg_logs` | `src/extension.ts:863` |
141
- | tool | `bg_result` | `tool:bg_result` | `src/delegate-extension.ts:453` |
145
+ | tool | `bg_result` | `tool:bg_result` | `src/delegate-extension.ts:515` |
142
146
  | tool | `bg_run` | `tool:bg_run` | `src/extension.ts:682` |
143
147
  | tool | `bg_run_pi_attested` | `tool:bg_run_pi_attested` | `src/extension.ts:767` |
144
148
  | tool | `bg_status` | `tool:bg_status` | `src/extension.ts:832` |
@@ -24,7 +24,7 @@ covers_sources: []
24
24
  | Foreground work | Synchronous | Current session | Depends on active tools | Depends on active tools | Depends on active tools | Current session route | You need live interaction. |
25
25
  | `/bg` | Async | None by package | Command decides | Command decides | Command decides | Not a model route unless command invokes one | You manually start a long local command. |
26
26
  | `bg_run` | Async | None by package | Command decides | Command decides | Command decides | Not a model route unless command invokes one | Pi should launch a long command and resume later. |
27
- | `bg_delegate` + `bg_result` | Async launch, point-in-time retrieval | Frozen visible conversation projection | Yes, inspect-only | No | No | Pinned at launch; no substitution | Context-aware read-only investigation. |
27
+ | `bg_delegate` + `bg_result` | Async launch, point-in-time retrieval | Frozen visible conversation projection | Yes, inspect-only model tools; ambient extension code is not sandboxed | No | No | Pinned at launch; no substitution | Context-aware read-only investigation; isolated extension discovery by default. |
28
28
  | `bg_run_pi_attested` | Async | Prompt only | Child Pi decides from prompt/tools | Child Pi route/tools decide | Report path requested | Structured provider/model; OAuth observed for supported subscription routes | Local evidence-producing Pi run. |
29
29
  | `fusion_reason` / `/fusion` | Async launch, point-in-time `bg_result` retrieval | Versioned conversation projection plus prompt | No | No | No | Configured Fusion slots; no silent fallback | Self-contained reasoning/synthesis. |
30
30
  | `fusion_investigate` | Async launch, point-in-time `bg_result` retrieval | Clean task input only | Candidate read-only tools | No | No | Configured Fusion slots; no silent fallback | Independent repository investigation. |
@@ -53,6 +53,8 @@ Defaults are `notifyOnCompletion:true` and `triggerOnCompletion:true`. With thos
53
53
 
54
54
  `bg_delegate` supports only `capability:"inspect"`. The child is seeded with a deterministic visible-conversation projection, but omitted parent tool payloads are not available. Restate any needed facts in the delegate prompt.
55
55
 
56
+ Extension discovery defaults to `extensionMode:"isolated"`. Select `"ambient"` only for a provider registered by an ambient user/project extension. Ambient mode executes arbitrary extension code, so its process is not inspect-only sandboxed even though its model-visible tools remain read/search/list only. It accepts no extension paths and never substitutes the route.
57
+
56
58
  Use `bg_result` for retrieval. It verifies hashes before returning content and reports oversized answers as artifacts instead of silently truncating.
57
59
 
58
60
  ### Fusion boundaries
@@ -80,7 +82,8 @@ Fusion is a fixed workflow, not a free-form mode switch:
80
82
  {
81
83
  "name": "Docs locator",
82
84
  "prompt": "Find the docs that explain shell selection and update checks. Return exact file paths and a concise summary.",
83
- "capability": "inspect"
85
+ "capability": "inspect",
86
+ "extensionMode": "isolated"
84
87
  }
85
88
  ```
86
89
 
@@ -0,0 +1,50 @@
1
+ ---
2
+ doc_id: commands/claude-cache
3
+ audience: user
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: evolving
7
+ covers_surfaces: [command:claude-cache]
8
+ covers_sources: []
9
+ ---
10
+ # `/claude-cache`
11
+
12
+ <!-- pi-docs:begin name="command-contract-claude-cache" generator="scripts/docs/generate.mjs" -->
13
+ | Command | Description | Provenance |
14
+ | --- | --- | --- |
15
+ | `/claude-cache` | Show or set Claude cache retention for this session (short, long, default) | `src/core/anthropic-attribution.ts:1928` |
16
+ <!-- pi-docs:end name="command-contract-claude-cache" -->
17
+
18
+ Show or change the Anthropic cache-retention preference for the current session.
19
+
20
+ ## Synopsis
21
+
22
+ ```text
23
+ /claude-cache
24
+ /claude-cache status
25
+ /claude-cache short
26
+ /claude-cache long
27
+ /claude-cache default
28
+ ```
29
+
30
+ ## Behavior
31
+
32
+ - No argument and `status` show the effective preference.
33
+ - `short` requests normal ephemeral retention.
34
+ - `long` requests one-hour retention where the selected model supports it.
35
+ - `default` removes the session override and returns to process/package policy.
36
+
37
+ The decision is persisted as a branch-local custom session entry and restored after reload, resume, and tree navigation. It does not enter model context.
38
+
39
+ An explicit call-level cache posture remains authoritative. In particular, Pi compaction calls that request no cache markers are not re-marked by the session default.
40
+
41
+ ## Errors and boundaries
42
+
43
+ Unknown arguments fail with the accepted values. Malformed persisted entries and invalid `PI_CACHE_RETENTION` values fail loudly.
44
+
45
+ The command controls the package-owned Anthropic subscription provider only. It does not enable metered API credentials, alter non-Anthropic routes, or change isolated Fusion children; set `PI_CACHE_RETENTION` for isolated child processes.
46
+
47
+ ## Related docs
48
+
49
+ - [Anthropic attribution subsystem](../subsystems/anthropic-attribution.md)
50
+ - [Configuration](../operations/configuration.md)
@@ -82,6 +82,7 @@ Use `bg_delegate` when the worker needs the current conversation as background b
82
82
  "name": "Config audit",
83
83
  "prompt": "Inspect package configuration and report where background-task output limits are defined. Include file paths and concise evidence.",
84
84
  "capability": "inspect",
85
+ "extensionMode": "isolated",
85
86
  "autoDeliver": "never"
86
87
  }
87
88
  ```
@@ -90,6 +91,8 @@ The child receives a frozen visible-conversation projection, its own session id/
90
91
 
91
92
  After the completion notification, retrieve the committed answer:
92
93
 
94
+ `extensionMode:"isolated"` is the default and disables ambient extension discovery. If the pinned provider is registered only by a user/project extension, use `extensionMode:"ambient"` explicitly. Ambient mode executes arbitrary discovered extension code; the inspect tool allowlist does not sandbox it, so process isolation is weakened. No caller-supplied extension path or route fallback is supported.
95
+
93
96
  ```json
94
97
  {
95
98
  "taskId": "<task id from bg_delegate>",