pi-background-tasks 2.0.0 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/TESTING.md +1 -1
- package/TEST_PLAN.md +4 -4
- package/docs/manifest.json +12 -2
- package/docs/operations/configuration.md +5 -3
- package/docs/read-before-edit.md +2 -0
- package/docs/reference/runtime-contracts.md +58 -56
- package/docs/subsystems/docs-freshness-gate.md +3 -3
- package/docs/subsystems/fusion.md +10 -7
- package/package.json +1 -1
- package/src/core/fusion/anthropic-attribution.ts +1930 -0
- package/src/core/fusion/artifacts.ts +96 -1
- package/src/core/fusion/budget.ts +23 -23
- package/src/core/fusion/child-protocol.ts +115 -10
- package/src/core/fusion/claude-cache.ts +21 -0
- package/src/core/fusion/config.ts +10 -2
- package/src/core/fusion/orchestrator.ts +128 -10
- package/src/core/fusion/output-contract.ts +34 -0
- package/src/core/fusion/pi-child.ts +420 -12
- package/src/core/fusion/prompts.ts +11 -1
- package/src/core/fusion/result-package.ts +30 -3
- package/src/core/fusion/types.ts +58 -0
- package/src/fusion-child-extension.ts +117 -2
package/README.md
CHANGED
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
| Fact | Value |
|
|
27
27
|
| --- | --- |
|
|
28
28
|
| Package | `pi-background-tasks` |
|
|
29
|
-
| Version | `2.
|
|
29
|
+
| Version | `2.1.1` |
|
|
30
30
|
| Node engine | `>=22.19.0` |
|
|
31
31
|
| Pi entrypoint | `./extensions/background-tasks.ts` |
|
|
32
32
|
| Package image | [logo.png](https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png) |
|
|
@@ -291,7 +291,7 @@ Agent tasks launched through `pi -p ...` or `pi --mode json ...` and marked `isA
|
|
|
291
291
|
- Shell jobs are tracked by the package, but they are not sandboxed. Treat commands as local processes with your permissions and credentials.
|
|
292
292
|
- Delegate and Fusion child Pi processes are route-pinned where applicable; delegate/Fusion paths do not silently substitute routes.
|
|
293
293
|
- 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
|
|
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.
|
|
295
295
|
- 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
296
|
- 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
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.
|
package/TESTING.md
CHANGED
|
@@ -186,7 +186,7 @@ npm run test:rpc
|
|
|
186
186
|
npm run test:agent-loop
|
|
187
187
|
```
|
|
188
188
|
|
|
189
|
-
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
|
|
189
|
+
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.v1` protocol, exact final-payload measurement, 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 the governor's `ctx.abort()` prevents network transport. `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.
|
|
190
190
|
|
|
191
191
|
## Coverage summary
|
|
192
192
|
|
package/TEST_PLAN.md
CHANGED
|
@@ -76,13 +76,13 @@ SDK/RPC/scripted-provider/package/compatibility coverage asserts exactly four to
|
|
|
76
76
|
| Stop task from LLM tool | `bg_kill` | | yes | | | | | | Covers running kill and already-finished loud failure. |
|
|
77
77
|
| 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
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
|
|
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 measures 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. |
|
|
80
80
|
| 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
81
|
| 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
|
-
| Fusion stage budgets | `budget-plan.json` (v4 per-stage forecasts), typed `prompt_budget_exceeded_forecast` / `prompt_budget_exceeded_measured` | yes | | | | | | | Unit 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. |
|
|
82
|
+
| 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. |
|
|
83
83
|
| Fusion fixed-purpose profiles | `/fusion`, `fusion_reason`, `fusion_investigate`, `fusion_research`, `fusion_validate`, candidate child argv | yes | yes | yes | | | yes | | Public surface has no caller-selected capability. SDK/RPC pin `/fusion` to reason/no-tool candidates; investigate is read-only, research is targeted URL fetch with public http(s) source validation, and evaluator/merger remain no-tools by stage policy. Package guards reject extra keys and verify schemas are closed. |
|
|
84
84
|
| Fusion research web fetch | `fusion_web_fetch({ url, extract? })`, `candidate-<slot>.attempt-<n>.tool-calls.jsonl` | yes | | | | | yes | live child | Unit covers the closed schema surface through the child extension, registration only when research mode is enabled, unsupported schemes and URL credentials failing before network access, blocked DNS classes, a mixed public-plus-blocked DNS answer failing loudly, a redirect to a blocked address failing loudly, redirect-loop limit failure, Content-Length and streamed-body response caps, unsupported content types, Markdown extraction preserving links/headings/tables/code blocks, script/style stripping, text/plain passthrough with hash and byte count, UTF-8-safe output truncation, and typed timeout. Unit also proves the resolver is consulted once and the connection is pinned to that vetted address, undeclared research URLs are rejected before fetch with only the attempted URL hash audited, and that audit metadata records `url`, `final_url`, `http_status`, `response_bytes`, and `content_sha256` without raw page content. Package guards require `fusion_web_fetch` registration behind the research env flag. Live verification fetched `https://example.com/`, reported the page H1, read a repository constant, and refused instruction-like text from both a repo file and the fetched page. |
|
|
85
|
-
| Fusion multi-message transcript validation | `*.events.jsonl`, `fusion-child-settlement.
|
|
85
|
+
| Fusion multi-message transcript validation | `*.events.jsonl`, `fusion-child-result.v4`, `fusion-child-settlement.v3`, stop reasons `toolUse`/`stop` plus recovered retry/output-cap markers | yes | | | | | | real Pi print mode | Unit accepts a multi-message tool loop, validates increasing cache-observation request ordinals, reconstructs stdout from the final assistant message only, and sums usage across all compact metadata records. Terminal `agent_settled` emits exactly one settlement binding ordered record bytes/count/final hash. Non-final `toolUse` remains normal; non-final `error` is accepted only when it has zero content and usage, is followed by final `stop`, and its ordinal is hash-bound in the settlement. Exactly one non-final `stop` is accepted only as a hash-bound candidate response over 49,152 JSON-rendered bytes immediately followed by its same-session replacement. A real Pi print-mode characterization proves the queued continuation remains in one PID/conversation, disables tools, delays settlement, and outputs only the replacement. Final/non-zero errors, unbound non-final `stop`, `length`, `aborted`, `pending`, missing/duplicate/tampered/failed settlements, and pre-settlement shutdown fail loudly. |
|
|
86
86
|
| Fusion runtime context governor | `pi-background-tasks.fusion-runtime-guard.v1`, typed `child_runtime_budget_exceeded` | yes | | | | | | scripted provider | Unit proves every exact final provider payload is serialized, hashed, and conservatively estimated against `contextWindow - max(32,768, model.maxTokens) - 4,096`; request 128/tool call 192 are allowed and the next is refused; malformed/duplicate frames and clean-looking post-refusal output fail closed; parent errors preserve observed usage. A real local-HTTP Pi loop through the production `openai-codex-responses` adapter proves earlier payload transforms reach the later governor and `ctx.abort()` prevents network transport. |
|
|
87
87
|
| Fusion stale-action watchdog | `FUSION_CHILD_IDLE_TIMEOUT_MS`, child process lifecycle | yes | | | | | | | Unit proves a child with no stdout or stderr activity fails as `child_timeout` with the stalled-child message and is terminated; stderr activity resets the watchdog and allows success; the 30-minute absolute timeout path remains distinct and is not reported as a stalled child. |
|
|
88
88
|
| 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. |
|
|
@@ -96,7 +96,7 @@ SDK/RPC/scripted-provider/package/compatibility coverage asserts exactly four to
|
|
|
96
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
97
|
| 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
98
|
| 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 |
|
|
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
100
|
| 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
101
|
| 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
102
|
| 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. |
|
package/docs/manifest.json
CHANGED
|
@@ -87,9 +87,10 @@
|
|
|
87
87
|
"state": "stale-sources"
|
|
88
88
|
},
|
|
89
89
|
{
|
|
90
|
-
"authored_body_sha256": "sha256:
|
|
90
|
+
"authored_body_sha256": "sha256:200168b5db6e14947b5dbee9aef51c4e14d57de0df7716776250193b26b57289",
|
|
91
91
|
"covers_sources": [
|
|
92
92
|
"extensions/fusion-child.ts",
|
|
93
|
+
"src/core/fusion/anthropic-attribution.ts",
|
|
93
94
|
"src/core/fusion/artifacts.ts",
|
|
94
95
|
"src/core/fusion/budget.ts",
|
|
95
96
|
"src/core/fusion/child-protocol.ts",
|
|
@@ -99,6 +100,7 @@
|
|
|
99
100
|
"src/core/fusion/context.ts",
|
|
100
101
|
"src/core/fusion/evaluation.ts",
|
|
101
102
|
"src/core/fusion/orchestrator.ts",
|
|
103
|
+
"src/core/fusion/output-contract.ts",
|
|
102
104
|
"src/core/fusion/pi-child.ts",
|
|
103
105
|
"src/core/fusion/prompts.ts",
|
|
104
106
|
"src/core/fusion/result-package.ts",
|
|
@@ -433,6 +435,7 @@
|
|
|
433
435
|
"audience": "maintainer",
|
|
434
436
|
"covers_sources": [
|
|
435
437
|
"extensions/fusion-child.ts",
|
|
438
|
+
"src/core/fusion/anthropic-attribution.ts",
|
|
436
439
|
"src/core/fusion/artifacts.ts",
|
|
437
440
|
"src/core/fusion/budget.ts",
|
|
438
441
|
"src/core/fusion/child-protocol.ts",
|
|
@@ -442,6 +445,7 @@
|
|
|
442
445
|
"src/core/fusion/context.ts",
|
|
443
446
|
"src/core/fusion/evaluation.ts",
|
|
444
447
|
"src/core/fusion/orchestrator.ts",
|
|
448
|
+
"src/core/fusion/output-contract.ts",
|
|
445
449
|
"src/core/fusion/pi-child.ts",
|
|
446
450
|
"src/core/fusion/prompts.ts",
|
|
447
451
|
"src/core/fusion/result-package.ts",
|
|
@@ -787,7 +791,7 @@
|
|
|
787
791
|
"image": "https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png",
|
|
788
792
|
"name": "pi-background-tasks",
|
|
789
793
|
"type": "module",
|
|
790
|
-
"version": "2.
|
|
794
|
+
"version": "2.1.1"
|
|
791
795
|
},
|
|
792
796
|
"public_surface_ids": [
|
|
793
797
|
"command:bg",
|
|
@@ -1661,6 +1665,9 @@
|
|
|
1661
1665
|
"src/core/extension-api.ts": [
|
|
1662
1666
|
"api/eventbus-v1"
|
|
1663
1667
|
],
|
|
1668
|
+
"src/core/fusion/anthropic-attribution.ts": [
|
|
1669
|
+
"subsystems/fusion"
|
|
1670
|
+
],
|
|
1664
1671
|
"src/core/fusion/artifacts.ts": [
|
|
1665
1672
|
"subsystems/fusion"
|
|
1666
1673
|
],
|
|
@@ -1688,6 +1695,9 @@
|
|
|
1688
1695
|
"src/core/fusion/orchestrator.ts": [
|
|
1689
1696
|
"subsystems/fusion"
|
|
1690
1697
|
],
|
|
1698
|
+
"src/core/fusion/output-contract.ts": [
|
|
1699
|
+
"subsystems/fusion"
|
|
1700
|
+
],
|
|
1691
1701
|
"src/core/fusion/pi-child.ts": [
|
|
1692
1702
|
"subsystems/fusion"
|
|
1693
1703
|
],
|
|
@@ -77,17 +77,19 @@ Use `/fusion-models` in TUI mode to configure five slots:
|
|
|
77
77
|
|
|
78
78
|
Missing config means all five slots are `$current`. Config entries are qualified `provider/model` selections or `$current`; malformed config, stale explicit models, unavailable current models, and concurrent selector conflicts fail loudly before child inference.
|
|
79
79
|
|
|
80
|
-
Fusion accepts frontier-model routes only through Pi Anthropic or Codex subscription OAuth where `ModelRegistry.isUsingOAuth` confirms the route. Metered frontier API-key/base-URL paths are rejected before child creation, and relevant metered environment variables are stripped from Fusion children.
|
|
80
|
+
Fusion accepts frontier-model routes only through Pi Anthropic or Codex subscription OAuth where `ModelRegistry.isUsingOAuth` confirms the route. Metered frontier API-key/base-URL paths are rejected before child creation, and relevant metered environment variables are stripped from Fusion children. Anthropic children additionally use the package-owned Claude Code attribution provider shared with the repo-local `spawn-anthropic-attribution` entrypoint. It reads `userID` and `oauthAccount.accountUuid` from `~/.claude.json` read-only; missing or malformed attribution data fails loudly before Anthropic transport. Its subscription request policy is 200K, so Fusion clamps Anthropic budget capacity to 200K even when Pi's model catalog advertises a larger context.
|
|
81
81
|
|
|
82
82
|
## Fusion Claude prompt caching
|
|
83
83
|
|
|
84
84
|
| Variable | Effect |
|
|
85
85
|
|---|---|
|
|
86
|
-
| `PI_CACHE_RETENTION=long` |
|
|
86
|
+
| `PI_CACHE_RETENTION=long` | Request `ttl: "1h"` on Pi-selected Anthropic cache breakpoints. This is Fusion's default when the variable is unset. |
|
|
87
87
|
| `PI_CACHE_RETENTION=short` | Use normal ephemeral retention without a `ttl` field (approximately five minutes). |
|
|
88
88
|
| `PI_CACHE_RETENTION=none` | Remove Anthropic cache breakpoints from normal Fusion provider payloads. Pi compaction payloads that already contain no breakpoints remain unmarked under every policy. |
|
|
89
89
|
|
|
90
|
-
Fusion children are isolated with `--no-session --no-extensions`, so a parent session's `/claude-cache` override
|
|
90
|
+
Fusion children are isolated with `--no-session --no-extensions`, so a parent session's persisted `/claude-cache` override is not inherited; use `PI_CACHE_RETENTION` for Fusion. When the variable is absent, Fusion sets `long` in the Anthropic child environment before provider serialization. The shared attribution provider therefore creates `ttl: "1h"` cache controls on the system prompt, final tool, and final conversation surface rather than relying only on a late payload rewrite. Explicit call-level `cacheRetention="none"` still takes precedence for compaction. The final governor validates the controls, preserves at most Anthropic's four supported breakpoints, adds the subscription prompt-caching-scope beta idempotently, and records requested/effective **payload** policy in each child result event. Invalid values fail before provider transport, and models that explicitly reject long retention use short retention instead.
|
|
91
|
+
|
|
92
|
+
Provider usage is preserved without inventing one-hour tokens. Positive `cacheWrite1h` is definitive evidence of a one-hour write, but zero is inconclusive on subscription OAuth: 2026-08-04 normal-spawn and Fusion-child controls accepted `ttl: "1h"`, reported `cacheWrite1h = 0`, and still returned their unique cache hits after 370 idle seconds—beyond the documented five-minute lifetime. The payload observation proves what was sent; `cacheRead` proves reuse; neither alone proves a full hour. One-hour cache creation, when itemized by the provider, has a higher write price than short retention.
|
|
91
93
|
|
|
92
94
|
## Fusion runtime limits
|
|
93
95
|
|
package/docs/read-before-edit.md
CHANGED
|
@@ -34,6 +34,7 @@ Every production file under `src/**` and `extensions/**` has exactly one primary
|
|
|
34
34
|
| `src/core/delegate/types.ts` | [subsystems/delegation](./subsystems/delegation.md) |
|
|
35
35
|
| `src/core/durable-fs.ts` | [subsystems/child-launch-durability-and-safety](./subsystems/child-launch-durability-and-safety.md) |
|
|
36
36
|
| `src/core/extension-api.ts` | [api/eventbus-v1](./api/eventbus-v1.md) |
|
|
37
|
+
| `src/core/fusion/anthropic-attribution.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
37
38
|
| `src/core/fusion/artifacts.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
38
39
|
| `src/core/fusion/budget.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
39
40
|
| `src/core/fusion/child-protocol.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
@@ -43,6 +44,7 @@ Every production file under `src/**` and `extensions/**` has exactly one primary
|
|
|
43
44
|
| `src/core/fusion/context.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
44
45
|
| `src/core/fusion/evaluation.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
45
46
|
| `src/core/fusion/orchestrator.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
47
|
+
| `src/core/fusion/output-contract.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
46
48
|
| `src/core/fusion/pi-child.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
47
49
|
| `src/core/fusion/prompts.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
48
50
|
| `src/core/fusion/result-package.ts` | [subsystems/fusion](./subsystems/fusion.md) |
|
|
@@ -16,27 +16,27 @@ This generated registry lists production environment-variable references, runtim
|
|
|
16
16
|
|
|
17
17
|
| Name | Access | Provenance |
|
|
18
18
|
| --- | --- | --- |
|
|
19
|
-
| `ANTHROPIC_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
20
|
-
| `ANTHROPIC_AUTH_TOKEN` | remove | `src/core/fusion/pi-child.ts:
|
|
21
|
-
| `ANTHROPIC_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
22
|
-
| `AZURE_OPENAI_AD_TOKEN` | remove | `src/core/fusion/pi-child.ts:
|
|
23
|
-
| `AZURE_OPENAI_API_KEY` | remove | `src/core/fusion/pi-child.ts:
|
|
24
|
-
| `AZURE_OPENAI_API_VERSION` | remove | `src/core/fusion/pi-child.ts:
|
|
25
|
-
| `AZURE_OPENAI_BASE_URL` | remove | `src/core/fusion/pi-child.ts:
|
|
26
|
-
| `AZURE_OPENAI_DEPLOYMENT_NAME_MAP` | remove | `src/core/fusion/pi-child.ts:
|
|
27
|
-
| `AZURE_OPENAI_ENDPOINT` | remove | `src/core/fusion/pi-child.ts:
|
|
28
|
-
| `AZURE_OPENAI_RESOURCE_NAME` | remove | `src/core/fusion/pi-child.ts:
|
|
19
|
+
| `ANTHROPIC_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
20
|
+
| `ANTHROPIC_AUTH_TOKEN` | remove | `src/core/fusion/pi-child.ts:100` |
|
|
21
|
+
| `ANTHROPIC_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
22
|
+
| `AZURE_OPENAI_AD_TOKEN` | remove | `src/core/fusion/pi-child.ts:100` |
|
|
23
|
+
| `AZURE_OPENAI_API_KEY` | remove | `src/core/fusion/pi-child.ts:100` |
|
|
24
|
+
| `AZURE_OPENAI_API_VERSION` | remove | `src/core/fusion/pi-child.ts:100` |
|
|
25
|
+
| `AZURE_OPENAI_BASE_URL` | remove | `src/core/fusion/pi-child.ts:100` |
|
|
26
|
+
| `AZURE_OPENAI_DEPLOYMENT_NAME_MAP` | remove | `src/core/fusion/pi-child.ts:100` |
|
|
27
|
+
| `AZURE_OPENAI_ENDPOINT` | remove | `src/core/fusion/pi-child.ts:100` |
|
|
28
|
+
| `AZURE_OPENAI_RESOURCE_NAME` | remove | `src/core/fusion/pi-child.ts:100` |
|
|
29
29
|
| `ComSpec` | read | `src/core/common.ts:725`<br>`src/core/common.ts:736` |
|
|
30
|
-
| `OPENAI_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
31
|
-
| `OPENAI_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
32
|
-
| `OPENROUTER_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
33
|
-
| `OPENROUTER_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
30
|
+
| `OPENAI_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
31
|
+
| `OPENAI_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
32
|
+
| `OPENROUTER_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
33
|
+
| `OPENROUTER_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
34
34
|
| `path` | read | `src/core/common.ts:680` |
|
|
35
35
|
| `Path` | read | `src/core/common.ts:680` |
|
|
36
36
|
| `PATH` | read | `src/core/common.ts:680` |
|
|
37
|
-
| `PI_API_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
38
|
-
| `PI_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
39
|
-
| `PI_AUTH_FILE` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:
|
|
37
|
+
| `PI_API_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
38
|
+
| `PI_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
39
|
+
| `PI_AUTH_FILE` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:100` |
|
|
40
40
|
| `PI_BG_DELEGATE_ARTIFACT_DIR` | read, write | `src/core/delegate/launch.ts:324`<br>`src/delegate-child-extension.ts:277` |
|
|
41
41
|
| `PI_BG_DELEGATE_LAUNCH_NONCE` | read, write | `src/core/delegate/launch.ts:328`<br>`src/delegate-child-extension.ts:281` |
|
|
42
42
|
| `PI_BG_DELEGATE_SEED_PATH` | read, write | `src/core/delegate/launch.ts:325`<br>`src/delegate-child-extension.ts:278` |
|
|
@@ -48,18 +48,20 @@ This generated registry lists production environment-variable references, runtim
|
|
|
48
48
|
| `PI_BG_REGISTRY_URL` | read | `src/extension.ts:464` |
|
|
49
49
|
| `PI_BG_SHELL` | read | `src/core/common.ts:721` |
|
|
50
50
|
| `PI_BG_SHELL_PATH` | read | `src/core/common.ts:722` |
|
|
51
|
-
| `PI_CACHE_RETENTION` | read | `src/core/fusion/claude-cache.ts:
|
|
52
|
-
| `
|
|
53
|
-
| `
|
|
54
|
-
| `
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
51
|
+
| `PI_CACHE_RETENTION` | read, write | `src/core/fusion/anthropic-attribution.ts:577`<br>`src/core/fusion/claude-cache.ts:57`<br>`src/core/fusion/pi-child.ts:273`<br>`src/core/fusion/pi-child.ts:274` |
|
|
52
|
+
| `PI_FUSION_CANDIDATE_OUTPUT_RECOVERY_PATH` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:2060`<br>`src/fusion-child-extension.ts:707` |
|
|
53
|
+
| `PI_FUSION_RESEARCH_ENABLED` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:2083`<br>`src/fusion-child-extension.ts:716` |
|
|
54
|
+
| `PI_FUSION_SOURCE_POLICY_PATH` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:2084`<br>`src/fusion-child-extension.ts:663` |
|
|
55
|
+
| `PI_FUSION_SOURCE_POLICY_SHA256` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:2085`<br>`src/fusion-child-extension.ts:664` |
|
|
56
|
+
| `PI_FUSION_TOOL_CALL_LOG_PATH` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:2072`<br>`src/fusion-child-extension.ts:706` |
|
|
57
|
+
| `PI_MODEL` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:100` |
|
|
57
58
|
| `PI_OFFLINE` | read | `src/extension.ts:456` |
|
|
58
|
-
| `PI_PROVIDER` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:
|
|
59
|
-
| `PI_REASONING_LEVEL` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:
|
|
60
|
-
| `PI_SESSION_FILE` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:
|
|
61
|
-
| `PI_SESSION_ID` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:
|
|
62
|
-
| `PI_SKIP_VERSION_CHECK` | write | `src/core/delegate/launch.ts:323`<br>`src/core/fusion/pi-child.ts:
|
|
59
|
+
| `PI_PROVIDER` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:100` |
|
|
60
|
+
| `PI_REASONING_LEVEL` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:100` |
|
|
61
|
+
| `PI_SESSION_FILE` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:100` |
|
|
62
|
+
| `PI_SESSION_ID` | remove | `src/core/delegate/launch.ts:301`<br>`src/core/fusion/pi-child.ts:100` |
|
|
63
|
+
| `PI_SKIP_VERSION_CHECK` | write | `src/core/delegate/launch.ts:323`<br>`src/core/fusion/pi-child.ts:272` |
|
|
64
|
+
| `PIPELINE_ANTHROPIC_ATTRIBUTION_AUDIT_PATH` | read | `src/core/fusion/anthropic-attribution.ts:1003` |
|
|
63
65
|
| `SHELL` | read | `src/core/common.ts:717` |
|
|
64
66
|
| `SystemRoot` | read | `src/core/windows-taskkill.ts:96` |
|
|
65
67
|
| `WINDIR` | read | `src/core/windows-taskkill.ts:101` |
|
|
@@ -68,7 +70,7 @@ This generated registry lists production environment-variable references, runtim
|
|
|
68
70
|
|
|
69
71
|
| Kind | Path/artifact | Provenance |
|
|
70
72
|
| --- | --- | --- |
|
|
71
|
-
| config | `fusion-models.json` | `src/core/fusion/config.ts:
|
|
73
|
+
| config | `fusion-models.json` | `src/core/fusion/config.ts:21` |
|
|
72
74
|
| delegate-artifact | `budget-plan.json` | `src/core/delegate/artifacts.ts:42` |
|
|
73
75
|
| delegate-artifact | `child-prompt.txt` | `src/core/delegate/artifacts.ts:46` |
|
|
74
76
|
| delegate-artifact | `child.stderr.txt` | `src/core/delegate/artifacts.ts:47` |
|
|
@@ -81,27 +83,27 @@ This generated registry lists production environment-variable references, runtim
|
|
|
81
83
|
| delegate-artifact | `seed.json` | `src/core/delegate/artifacts.ts:40` |
|
|
82
84
|
| delegate-artifact | `spill/<receipt-named-file>` | `src/core/delegate/artifacts.ts:53` |
|
|
83
85
|
| directory | `.pi/delegate/<session-id>-<pid>/<task-id>/` | `src/core/delegate/artifacts.ts:157` |
|
|
84
|
-
| directory | `.pi/fusion/<session-id>-<pid>/<run-id>/` | `src/core/fusion/artifacts.ts:
|
|
86
|
+
| directory | `.pi/fusion/<session-id>-<pid>/<run-id>/` | `src/core/fusion/artifacts.ts:353` |
|
|
85
87
|
| directory | `.pi/tasks/<session-id>-<pid>/` | `src/core/registry.ts:783` |
|
|
86
|
-
| fusion-artifact | `<attempt-prefix> = candidate-<slot>.attempt-<n> \| evaluation.attempt-<n> \| merge.attempt-<n>` | `src/core/fusion/artifacts.ts:
|
|
87
|
-
| fusion-artifact | `<attempt-prefix>.calibration-violation.json` | `src/core/fusion/artifacts.ts:
|
|
88
|
-
| fusion-artifact | `<attempt-prefix>.events.jsonl` | `src/core/fusion/artifacts.ts:
|
|
89
|
-
| fusion-artifact | `<attempt-prefix>.prompt.txt` | `src/core/fusion/artifacts.ts:
|
|
90
|
-
| fusion-artifact | `<attempt-prefix>.stderr.txt` | `src/core/fusion/artifacts.ts:
|
|
91
|
-
| fusion-artifact | `blind-candidates.json` | `src/core/fusion/artifacts.ts:
|
|
92
|
-
| fusion-artifact | `budget-plan.json` | `src/core/fusion/artifacts.ts:
|
|
93
|
-
| fusion-artifact | `candidate-<slot>.attempt-<n>.response.md \| candidate-<slot>.attempt-<n>.response.partial.md` | `src/core/fusion/artifacts.ts:
|
|
94
|
-
| fusion-artifact | `candidate-<slot>.attempt-<n>.tool-calls.jsonl` | `src/core/fusion/artifacts.ts:
|
|
95
|
-
| fusion-artifact | `candidate-<slot>.attempt-<n>.tool-calls.jsonl.seal.json` | `src/core/fusion/child-protocol.ts:
|
|
96
|
-
| fusion-artifact | `canonical-input.json` | `src/core/fusion/artifacts.ts:
|
|
97
|
-
| fusion-artifact | `context-omission-ledger.json` | `src/core/fusion/artifacts.ts:
|
|
98
|
-
| fusion-artifact | `error.json` | `src/core/fusion/artifacts.ts:
|
|
99
|
-
| fusion-artifact | `evaluation.attempt-<n>.response.txt \| evaluation.attempt-<n>.response.partial.txt` | `src/core/fusion/artifacts.ts:
|
|
100
|
-
| fusion-artifact | `evaluation.json` | `src/core/fusion/artifacts.ts:
|
|
101
|
-
| fusion-artifact | `merge.attempt-<n>.response.md \| merge.attempt-<n>.response.partial.md` | `src/core/fusion/artifacts.ts:
|
|
102
|
-
| fusion-artifact | `merged.md` | `src/core/fusion/artifacts.ts:
|
|
103
|
-
| fusion-artifact | `result.json` | `src/core/fusion/artifacts.ts:
|
|
104
|
-
| fusion-artifact | `source-policy.private.json` | `src/core/fusion/artifacts.ts:
|
|
88
|
+
| fusion-artifact | `<attempt-prefix> = candidate-<slot>.attempt-<n> \| evaluation.attempt-<n> \| merge.attempt-<n>` | `src/core/fusion/artifacts.ts:242` |
|
|
89
|
+
| fusion-artifact | `<attempt-prefix>.calibration-violation.json` | `src/core/fusion/artifacts.ts:257` |
|
|
90
|
+
| fusion-artifact | `<attempt-prefix>.events.jsonl` | `src/core/fusion/artifacts.ts:541` |
|
|
91
|
+
| fusion-artifact | `<attempt-prefix>.prompt.txt` | `src/core/fusion/artifacts.ts:540` |
|
|
92
|
+
| fusion-artifact | `<attempt-prefix>.stderr.txt` | `src/core/fusion/artifacts.ts:542` |
|
|
93
|
+
| fusion-artifact | `blind-candidates.json` | `src/core/fusion/artifacts.ts:498` |
|
|
94
|
+
| fusion-artifact | `budget-plan.json` | `src/core/fusion/artifacts.ts:494` |
|
|
95
|
+
| fusion-artifact | `candidate-<slot>.attempt-<n>.response.md \| candidate-<slot>.attempt-<n>.response.partial.md` | `src/core/fusion/artifacts.ts:252` |
|
|
96
|
+
| fusion-artifact | `candidate-<slot>.attempt-<n>.tool-calls.jsonl` | `src/core/fusion/artifacts.ts:413` |
|
|
97
|
+
| fusion-artifact | `candidate-<slot>.attempt-<n>.tool-calls.jsonl.seal.json` | `src/core/fusion/child-protocol.ts:22` |
|
|
98
|
+
| fusion-artifact | `canonical-input.json` | `src/core/fusion/artifacts.ts:464` |
|
|
99
|
+
| fusion-artifact | `context-omission-ledger.json` | `src/core/fusion/artifacts.ts:473` |
|
|
100
|
+
| fusion-artifact | `error.json` | `src/core/fusion/artifacts.ts:523` |
|
|
101
|
+
| fusion-artifact | `evaluation.attempt-<n>.response.txt \| evaluation.attempt-<n>.response.partial.txt` | `src/core/fusion/artifacts.ts:252` |
|
|
102
|
+
| fusion-artifact | `evaluation.json` | `src/core/fusion/artifacts.ts:502` |
|
|
103
|
+
| fusion-artifact | `merge.attempt-<n>.response.md \| merge.attempt-<n>.response.partial.md` | `src/core/fusion/artifacts.ts:252` |
|
|
104
|
+
| fusion-artifact | `merged.md` | `src/core/fusion/artifacts.ts:436` |
|
|
105
|
+
| fusion-artifact | `result.json` | `src/core/fusion/artifacts.ts:437` |
|
|
106
|
+
| fusion-artifact | `source-policy.private.json` | `src/core/fusion/artifacts.ts:480` |
|
|
105
107
|
| task-file | `.pi/tasks/<session-id>-<pid>/<task-id>.attestation.json` | `src/core/attested-pi-run.ts:583` |
|
|
106
108
|
| task-file | `.pi/tasks/<session-id>-<pid>/<task-id>.json` | `src/core/registry.ts:811` |
|
|
107
109
|
| task-file | `.pi/tasks/<session-id>-<pid>/<task-id>.output` | `src/core/registry.ts:810` |
|
|
@@ -128,30 +130,30 @@ This generated registry lists production environment-variable references, runtim
|
|
|
128
130
|
| `pi-background-tasks.extension-request.v1` | `src/core/extension-api.ts:15` |
|
|
129
131
|
| `pi-background-tasks.extension-response.v1` | `src/core/extension-api.ts:16` |
|
|
130
132
|
| `pi-background-tasks.extension-terminal.v1` | `src/core/extension-api.ts:17` |
|
|
131
|
-
| `pi-background-tasks.fusion-blind-candidates.v1` | `src/core/fusion/prompts.ts:
|
|
133
|
+
| `pi-background-tasks.fusion-blind-candidates.v1` | `src/core/fusion/prompts.ts:309` |
|
|
132
134
|
| `pi-background-tasks.fusion-budget-plan.v4` | `src/core/fusion/types.ts:27` |
|
|
133
135
|
| `pi-background-tasks.fusion-calibration-violation.v2` | `src/core/fusion/types.ts:29` |
|
|
134
|
-
| `pi-background-tasks.fusion-child-result.
|
|
135
|
-
| `pi-background-tasks.fusion-child-settlement.
|
|
136
|
+
| `pi-background-tasks.fusion-child-result.v4` | `src/core/fusion/child-protocol.ts:10` |
|
|
137
|
+
| `pi-background-tasks.fusion-child-settlement.v3` | `src/core/fusion/child-protocol.ts:13` |
|
|
136
138
|
| `pi-background-tasks.fusion-claude-cache-observation.v1` | `src/core/fusion/claude-cache.ts:4` |
|
|
137
139
|
| `pi-background-tasks.fusion-committed-result.v1` | `src/core/fusion/types.ts:22` |
|
|
138
140
|
| `pi-background-tasks.fusion-context-ledger.v2` | `src/core/fusion/types.ts:25` |
|
|
139
|
-
| `pi-background-tasks.fusion-evaluation-repair-input.v1` | `src/core/fusion/prompts.ts:
|
|
141
|
+
| `pi-background-tasks.fusion-evaluation-repair-input.v1` | `src/core/fusion/prompts.ts:289` |
|
|
140
142
|
| `pi-background-tasks.fusion-evaluation.v1` | `src/core/fusion/types.ts:16` |
|
|
141
143
|
| `pi-background-tasks.fusion-input.v4` | `src/core/fusion/types.ts:14` |
|
|
142
144
|
| `pi-background-tasks.fusion-input.v5` | `src/core/fusion/types.ts:15` |
|
|
143
145
|
| `pi-background-tasks.fusion-launch.v1` | `src/fusion-extension.ts:1125` |
|
|
144
146
|
| `pi-background-tasks.fusion-manifest.v3` | `src/core/fusion/types.ts:23` |
|
|
145
147
|
| `pi-background-tasks.fusion-manifest.v4` | `src/core/fusion/types.ts:24` |
|
|
146
|
-
| `pi-background-tasks.fusion-merge-input.v1` | `src/core/fusion/prompts.ts:
|
|
148
|
+
| `pi-background-tasks.fusion-merge-input.v1` | `src/core/fusion/prompts.ts:336` |
|
|
147
149
|
| `pi-background-tasks.fusion-models.v1` | `src/core/fusion/types.ts:13` |
|
|
148
150
|
| `pi-background-tasks.fusion-progress.v1` | `src/fusion-extension.ts:59` |
|
|
149
151
|
| `pi-background-tasks.fusion-result-view.v1` | `src/delegate-extension.ts:669` |
|
|
150
152
|
| `pi-background-tasks.fusion-result.v4` | `src/core/fusion/types.ts:19` |
|
|
151
153
|
| `pi-background-tasks.fusion-result.v5` | `src/core/fusion/types.ts:20` |
|
|
152
|
-
| `pi-background-tasks.fusion-runtime-guard.v1` | `src/core/fusion/child-protocol.ts:
|
|
154
|
+
| `pi-background-tasks.fusion-runtime-guard.v1` | `src/core/fusion/child-protocol.ts:24` |
|
|
153
155
|
| `pi-background-tasks.fusion-source-policy.v1` | `src/core/fusion/types.ts:26` |
|
|
154
|
-
| `pi-background-tasks.fusion-tool-call-seal.v1` | `src/core/fusion/child-protocol.ts:
|
|
156
|
+
| `pi-background-tasks.fusion-tool-call-seal.v1` | `src/core/fusion/child-protocol.ts:21` |
|
|
155
157
|
| `pi-background-tasks.fusion-tool-call.v1` | `src/core/fusion/types.ts:32` |
|
|
156
158
|
| `pi-background-tasks.fusion-validation-candidate-contract-event.v1` | `src/core/fusion/types.ts:31` |
|
|
157
159
|
| `pi-background-tasks.fusion-validation-candidate.v1` | `src/core/fusion/types.ts:18` |
|
|
@@ -12,13 +12,13 @@ covers_sources: []
|
|
|
12
12
|
This authored section defines the boundary: documentation facts are extracted from package metadata and TypeScript ASTs, then generated into docs and the manifest. Unsupported syntax fails the gate rather than falling back to regex or stale hand-maintained inventories. Public registrations must remain unconditional top-level direct calls or use the one validated local tool-wrapper shape; host/method aliases, computed access, nested or conditional registration, wrapper chaining/passing, constructor helpers, ambiguous public metadata, destructured Pi parameters, and repeated imported registrars are rejected.
|
|
13
13
|
|
|
14
14
|
<!-- pi-docs:begin name="docs-freshness-gate" generator="scripts/docs/generate.mjs" -->
|
|
15
|
-
- Canonical package version: `2.
|
|
15
|
+
- Canonical package version: `2.1.1`
|
|
16
16
|
- Governed markdown docs: 40
|
|
17
17
|
- Public surfaces extracted: 30
|
|
18
|
-
- Governed production sources:
|
|
18
|
+
- Governed production sources: 48
|
|
19
19
|
- Tool contracts extracted: 11
|
|
20
20
|
- Schema IDs extracted: 43
|
|
21
|
-
- Environment variable references extracted:
|
|
21
|
+
- Environment variable references extracted: 49
|
|
22
22
|
- Behavioral attestation receipts not passing: 4
|
|
23
23
|
- Receipt store: `docs/attestations.json`
|
|
24
24
|
|
|
@@ -5,7 +5,7 @@ mode: mixed
|
|
|
5
5
|
review_policy: behavioral
|
|
6
6
|
stability: stable
|
|
7
7
|
covers_surfaces: [renderer:fusion-result, workflow:investigate, workflow:reason, workflow:research, workflow:validate]
|
|
8
|
-
covers_sources: [extensions/fusion-child.ts, src/core/fusion/artifacts.ts, src/core/fusion/budget.ts, src/core/fusion/child-protocol.ts, src/core/fusion/claude-cache.ts, src/core/fusion/clean-context.ts, src/core/fusion/config.ts, src/core/fusion/context.ts, src/core/fusion/evaluation.ts, src/core/fusion/orchestrator.ts, src/core/fusion/pi-child.ts, src/core/fusion/prompts.ts, src/core/fusion/result-package.ts, src/core/fusion/source-policy.ts, src/core/fusion/types.ts, src/core/fusion/web-fetch.ts, src/core/fusion/workflows.ts, src/fusion-child-extension.ts, src/fusion-extension.ts, src/ui/fusion-model-selector.ts]
|
|
8
|
+
covers_sources: [extensions/fusion-child.ts, src/core/fusion/anthropic-attribution.ts, src/core/fusion/artifacts.ts, src/core/fusion/budget.ts, src/core/fusion/child-protocol.ts, src/core/fusion/claude-cache.ts, src/core/fusion/clean-context.ts, src/core/fusion/config.ts, src/core/fusion/context.ts, src/core/fusion/evaluation.ts, src/core/fusion/orchestrator.ts, src/core/fusion/output-contract.ts, src/core/fusion/pi-child.ts, src/core/fusion/prompts.ts, src/core/fusion/result-package.ts, src/core/fusion/source-policy.ts, src/core/fusion/types.ts, src/core/fusion/web-fetch.ts, src/core/fusion/workflows.ts, src/fusion-child-extension.ts, src/fusion-extension.ts, src/ui/fusion-model-selector.ts]
|
|
9
9
|
---
|
|
10
10
|
|
|
11
11
|
# Fusion subsystem
|
|
@@ -88,27 +88,29 @@ Inspect/research candidates write sealed tool-call audit logs. The log contains
|
|
|
88
88
|
|
|
89
89
|
## Child process isolation
|
|
90
90
|
|
|
91
|
-
Fusion never calls direct completion APIs. It launches direct child `pi --mode text` processes and writes the prompt over stdin. Child argv includes `--no-session`, `--no-extensions`, `--no-skills`, `--no-prompt-templates`, `--no-themes`, and `--no-context-files`; explicit extensions still load
|
|
91
|
+
Fusion never calls direct completion APIs. It launches direct child `pi --mode text` processes and writes the prompt over stdin. Child argv includes `--no-session`, `--no-extensions`, `--no-skills`, `--no-prompt-templates`, `--no-themes`, and `--no-context-files`; explicit extensions still load. Non-Anthropic children receive only the package-owned compact metadata/runtime-governor extension. Anthropic children receive, in fixed order, the package-owned Claude Code attribution provider, `@ravshansbox/pi-anthropic-sps`, and the runtime governor. The repo-local `spawn-anthropic-attribution` entrypoint re-exports that same package-owned implementation, so normal agent spawns and Fusion cannot drift into different OAuth/cache request shapes. Attribution adds the Claude Code OAuth session header, linked account/device/session metadata, model-policy beta headers, system identity, beta-resource transport, cache surfaces, and model-aware cache usage pricing. It reads `userID` and `oauthAccount.accountUuid` from `~/.claude.json` without writing the file and fails loudly when required attribution data is absent or malformed. The sanitizer then removes only known rejected prompt lines while preserving attribution and cache controls.
|
|
92
92
|
|
|
93
|
-
Child text mode writes the final full answer to stdout. The private child extension emits compact reasoning-free metadata frames to stderr for finalized assistant messages: provider/model, stop reason, text block byte counts and hashes, aggregate text hash, the complete Pi `Usage` object, and a closed cache-policy observation. It
|
|
93
|
+
Child text mode writes the final full answer to stdout. The private child extension emits compact reasoning-free metadata frames to stderr for finalized assistant messages: provider/model, stop reason, text block byte counts and hashes, aggregate text hash, the complete Pi `Usage` object (including Anthropic `cacheWrite1h` and provider-reported reasoning subsets), and a closed cache-policy observation. It governs every final `before_provider_request` payload after attribution and sanitization. For Anthropic routes, the child environment defaults `PI_CACHE_RETENTION` to `long` before provider serialization, so the attribution/Pi adapter creates system, final-tool, and final-conversation breakpoints with `ttl: "1h"`; inherited `PI_CACHE_RETENTION=short|none|long` remains explicit, and call-level `cacheRetention="none"` still wins for compaction. The final governor validates and normalizes those upstream-selected breakpoints, falls back to short when model compatibility rejects long retention, preserves no-marker compaction payloads, enforces Anthropic's four-breakpoint ceiling, and appends the subscription prompt-caching-scope beta idempotently. Its `effective_retention` field describes the final payload, not provider acceptance. Provider usage is preserved verbatim: `cacheWrite1h > 0` proves a one-hour write, but zero is inconclusive on subscription OAuth. Live normal-spawn and exact Fusion-child controls each observed a unique cache read after 370 idle seconds despite `cacheWrite1h = 0`; therefore payload observations prove request intent and `cacheRead` proves reuse, while neither zero telemetry nor a six-minute hit alone proves the full one-hour lifetime. Malformed controls or policy values abort before transport. Non-Anthropic payloads and child environments remain unchanged apart from the governor's existing JSON normalization.
|
|
94
94
|
|
|
95
|
-
After cache normalization, the governor serializes and hashes the exact payload, applies the shared conservative estimator, reserves the model's declared maximum output plus 4,096 safety tokens, and aborts before transport if the payload cannot fit or if the child exceeds 128 provider requests. Pi's provider-hook behavior is characterized through the same `openai-codex-responses` transport adapter used by subscription Codex routes in a real local HTTP agent loop: transforms chain in extension load order and `ctx.abort()` prevents network transport. Cache observations use `pi-background-tasks.fusion-claude-cache-observation.v1`, state requested/effective retention, source, breakpoint count, and provider-request ordinal, and are hash-bound inside `pi-background-tasks.fusion-child-result.
|
|
95
|
+
After cache normalization, the governor serializes and hashes the exact payload, applies the shared conservative estimator, reserves the model's declared maximum output plus 4,096 safety tokens, and aborts before transport if the payload cannot fit or if the child exceeds 128 provider requests. Pi's provider-hook behavior is characterized through the same `openai-codex-responses` transport adapter used by subscription Codex routes in a real local HTTP agent loop: transforms chain in extension load order and `ctx.abort()` prevents network transport. Cache observations use `pi-background-tasks.fusion-claude-cache-observation.v1`, state requested/effective retention, source, breakpoint count, and provider-request ordinal, and are hash-bound inside `pi-background-tasks.fusion-child-result.v4` attempt event artifacts. At terminal `agent_settled`, the extension emits exactly one `pi-background-tasks.fusion-child-settlement.v3` frame binding the complete ordered metadata stream by count and SHA-256, the final record/hash, recovered retry-marker ordinals, and any one recovered oversized-original ordinal. The parent validates closed cache/output-contract evidence and increasing request ordinals, reconstructs stdout against the final metadata, requires final stop reason `stop`, verifies model identity, and preserves usage/cost exactly. Non-final `toolUse` records remain normal. A non-final `error` is accepted only when it is a zero-content, empty-hash, zero-usage retry marker, a later final `stop` exists, and the terminal settlement hash/accounts for that exact ordinal. Exactly one non-final `stop` is accepted only as a hash-bound oversized candidate original immediately followed by its same-session replacement. `length`, `aborted`, `pending`, final `error`, error records carrying text or usage, unbound non-final `stop`, missing/duplicate/tampered settlement, and settlement before terminal idleness all fail loudly.
|
|
96
96
|
|
|
97
97
|
Fusion child environments strip session/model/provider variables plus metered credential/base-url variables for OpenRouter, OpenAI, Anthropic, Azure OpenAI, and generic Pi API credentials before launch. Frontier model routes are admitted only when the registry reports subscription OAuth for trusted `anthropic` or `openai-codex` endpoints. There is no fallback, model substitution, endpoint override, or metered API-key route.
|
|
98
98
|
|
|
99
99
|
## Budgets and output contracts
|
|
100
100
|
|
|
101
|
-
Budget planning is per route and per stage. Every configured candidate, evaluator, and merger route must have a usable context window. The affine estimator from the shared token-budget layer accounts for byte classes plus a 512-token intercept; backed model-family calibrations are used only where applicable, unknown/unbacked providers are reported in artifacts/result details, and multibyte/dense ASCII diagnostics are preserved. Post-run calibration compares that one-request forecast only with the first provider request; cumulative agent-loop and cache usage is retained as total usage but is never misclassified as a prompt under-forecast.
|
|
101
|
+
Budget planning is per route and per stage. Every configured candidate, evaluator, and merger route must have a usable context window. Anthropic routes are conservatively capped to the attribution provider's 200K subscription request policy even when Pi's catalog advertises a larger window; Fusion never budgets against a 1M mode that its attributed transport does not request. The affine estimator from the shared token-budget layer accounts for byte classes plus a 512-token intercept; backed model-family calibrations are used only where applicable, unknown/unbacked providers are reported in artifacts/result details, and multibyte/dense ASCII diagnostics are preserved. Post-run calibration compares that one-request forecast only with the first provider request; cumulative agent-loop and cache usage is retained as total usage but is never misclassified as a prompt under-forecast.
|
|
102
102
|
|
|
103
103
|
`budget-plan.json` uses `pi-background-tasks.fusion-budget-plan.v4` and records route capacities, stage forecasts for candidate/evaluation/evaluation-repair/merge, conditional repair reservation, warnings, blockers, empty-request counterfactuals, and remediation. Each route reserves the larger of Fusion's 32,768-token output contract reserve and the resolved model's declared maximum output; a model advertising a 128,000-token maximum therefore receives the full 128,000-token reserve. Fatal preflight blockers launch zero children. High utilization or worst-case reservation pressure is a warning when input still fits. Exact rendered prompt checks happen again immediately before candidate, evaluation, repair, and merge launches.
|
|
104
104
|
|
|
105
|
-
Output contracts are checked after durable attempt recording: candidate responses up to 48 KiB JSON-rendered bytes, evaluator up to 64 KiB, merger/final report up to 64 KiB, diagnostics contract 8 KiB, child stdout cap 32 MiB, child stderr cap 4 MiB.
|
|
105
|
+
Every candidate system prompt discloses the exact 49,152 JSON-rendered UTF-8 byte hard maximum and requires explicit limitations when the requested scope cannot fit. Output contracts are checked after durable attempt recording: candidate responses up to 48 KiB JSON-rendered bytes, evaluator up to 64 KiB, merger/final report up to 64 KiB, diagnostics contract 8 KiB, child stdout cap 32 MiB, child stderr cap 4 MiB.
|
|
106
|
+
|
|
107
|
+
When a candidate's first complete `stop` response exceeds 48 KiB, the private child extension durably preserves that full original, removes all active tools, and queues one `followUp` user message before `agent_settled`. The same live Pi process, route, model, and in-memory conversation may only compress/restructure its immediately previous answer; it may not investigate again. Pi text mode then emits only the replacement to stdout. A conforming replacement proceeds normally. A second oversized response hard-fails as `child_output_cap`, preserves both the original artifact and replacement partial response, and never queues another continuation. Cancellation during compression preserves any hash-verified original already written. Fusion never clips, silently forwards, or repairs output in a new child session.
|
|
106
108
|
|
|
107
109
|
## Artifacts, usage, and lifecycle
|
|
108
110
|
|
|
109
111
|
Run artifacts are private local evidence under `.pi/fusion/<session-id>-<pid>/<run-id>/`. They include `manifest.json`, `canonical-input.json`, `budget-plan.json`, per-attempt prompts/events/stderr/responses, optional partial responses for failed attempts, optional tool-call logs/seals, `blind-candidates.json`, `evaluation.json`, `merged.md`, manifest-bound `result.json`, `error.json`, and workflow-specific context/source-policy artifacts. `bg_result` verifies manifest state, fixed artifact references, byte lengths, SHA-256 values, UTF-8, run/workflow identity, and result details before returning merged bytes.
|
|
110
112
|
|
|
111
|
-
Artifact writes use durable private temp-file/fsync/rename. Manifests enforce legal state transitions and record config, resolved models, fixed capabilities, context policy, tool policy, anonymous map, attempts, artifact refs, cumulative usage, and errors. Successful, failed, and cancelled observed attempts preserve complete Pi usage/cost components; public tool results clone the same `Usage` shape.
|
|
113
|
+
Artifact writes use durable private temp-file/fsync/rename. Manifests enforce legal state transitions and record config, resolved models, fixed capabilities, context policy, tool policy, anonymous map, attempts, artifact refs, cumulative usage, and errors. Successful, failed, and cancelled observed attempts preserve complete Pi usage/cost components, including optional `cacheWrite1h` and `reasoning` subsets; same-session compression includes both provider turns in that one attempt's aggregate; public tool results clone the same `Usage` shape without counting either subset as additional tokens. Terminal failures enrich their stage-local cause from the durable manifest after usage persistence: candidate/evaluator/merger progress reports completed, failed, cancelled, and not-started child facts plus exact usage so far. A late evaluator or merger budget refusal never claims that no child anywhere in the run was created.
|
|
112
114
|
|
|
113
115
|
For tool-enabled children, the private audit journal remains open across every low-level `agent_end`, because Pi may still retry, compact and retry, or process a queued continuation. Only terminal `agent_settled` can exclusively publish the complete hash/count/byte seal. Runtime-guard refusal latches process failure, makes that seal incomplete, and forces the result settlement to failed. The child emits one closed `pi-background-tasks.fusion-runtime-guard.v1` stderr frame containing the refusal code, route capacities, request/tool ordinals, exact payload byte count and SHA-256, conservative token estimate, and a bounded message; it never emits the payload itself. The parent validates this frame and reports typed `child_runtime_budget_exceeded` for runtime capacity/loop refusals or `child_cache_policy_invalid` for Claude cache-policy refusal, instead of accepting a later clean-looking result or reducing it to an unexplained exit code. Tool activity after finalization, duplicate settlement, pre-settlement shutdown, extension diagnostics, malformed/duplicate runtime-guard frames, and missing/failed/stale seals are fatal. This lifecycle requires Pi 0.81.1 or newer; older Pi lines do not expose the required terminal event and are not claimed as compatible.
|
|
114
116
|
|
|
@@ -125,6 +127,7 @@ Cancellation and shutdown are loud and durable when a run store exists. The exte
|
|
|
125
127
|
- `prompt_budget_exceeded_measured`: an exact rendered prompt exceeded capacity after upstream output was known; split the workflow or choose a larger-context subscription route.
|
|
126
128
|
- `child_runtime_budget_exceeded`: a later provider payload, provider-request loop, or tool-call loop crossed a child runtime guard after launch. Inspect the attempt stderr guard frame and failed tool seal; narrow the task or select a subscription route with more safe input headroom. Do not ignore intermediate provider errors or weaken the guard.
|
|
127
129
|
- `child_cache_policy_invalid`: `PI_CACHE_RETENTION` or Claude cache-control evidence was malformed. Use exactly `none`, `short`, or `long`; do not remove the final-payload guard.
|
|
130
|
+
- `child_output_cap` after candidate compression: inspect the final candidate response, its `response.oversized.*` original, and v4/v3 child protocol evidence. The single same-session no-tool compression attempt also exceeded 49,152 JSON-rendered bytes; split the task rather than truncating or starting a repair child.
|
|
128
131
|
- `evaluation schema repair failed`: both evaluator attempts failed the closed JSON contract; inspect `evaluation.attempt-*.response.txt` and errors.
|
|
129
132
|
- `tool-call log invalid`: inspect the candidate `*.tool-calls.jsonl` and `*.seal.json`; missing/partial/unsealed logs, non-allowlisted tools, hash/count mismatches, and over-budget tool output fail by design.
|
|
130
133
|
- Research fetch failures are typed and do not retry via other URLs or extraction modes; verify the declared URL is public, reachable, supported content, and within caps.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-background-tasks",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "Pi extension for durable background shell tasks, read-only delegated agents, local attested Pi runs, and fixed-purpose Fusion workflows through child Pi processes.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "ISC",
|