pi-background-tasks 2.4.2 → 2.5.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.
package/README.md CHANGED
@@ -27,7 +27,7 @@
27
27
  | Fact | Value |
28
28
  | --- | --- |
29
29
  | Package | `pi-background-tasks` |
30
- | Version | `2.4.2` |
30
+ | Version | `2.5.0` |
31
31
  | Node engine | `>=22.19.0` |
32
32
  | Pi entrypoints | `./extensions/anthropic-attribution.ts`, `./extensions/background-tasks.ts` |
33
33
  | Package image | [logo.png](https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png) |
package/TEST_PLAN.md CHANGED
@@ -77,7 +77,7 @@ SDK/RPC/scripted-provider/package/compatibility coverage asserts exactly four to
77
77
  | Stop task from LLM tool | `bg_kill` | | yes | | | | | | Covers running kill and already-finished loud failure. |
78
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. |
79
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
+ | Global Anthropic attribution and sanitization | package-owned `extensions/anthropic-attribution.ts`, `/claude-cache`, isolated child `--extension` argv | yes | | | | | yes | local SSE + subscription handoff | 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. BUG-192 coverage pins provider/api/model-aware Codex/ZAI signature removal, foreign-redacted omission, lineage-proven empty/redacted/non-BMP Claude replay, directional older-Claude→Fable 5.1 compatibility, long→short→long signature-epoch isolation plus stale-prefix/reverse denial, canonical collision-checked tool IDs, stable text-tool-result prefixes, deterministic repeated payloads, official Fable binding/cache-diagnostics betas, fail-before-network profile drift, one-shot hash-bound compaction epochs, one-hour controls, away/back model lanes, exact official HTTPS endpoint/no-redirect policy, strict error/EOF/`message_stop` SSE completion, and official $0.25/M cache-read accounting. BUG-193 coverage proves hookless compaction/branch-summary requests derive mandatory attribution from Pi's fresh request-scoped `options.sessionId`, retain zero cache markers, isolate concurrent IDs, expose an already-attributed payload to optional middleware exactly once, preserve a frozen ordinary-turn payload hash, and reject route, metadata, system-identity, cache-topology, and excess-breakpoint tampering before fetch. The stubbed-fetch no-network loop exercises the real custom transport without weakening its production endpoint policy; release evidence uses subscription OAuth only. 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. |
81
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. |
82
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. |
83
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. |
package/docs/INDEX.md CHANGED
@@ -132,7 +132,7 @@ Generated navigation for every package-local documentation page. This index inte
132
132
  | command | `bg-clear` | `command:bg-clear` | `src/extension.ts:559` |
133
133
  | command | `bg-tasks` | `command:bg-tasks` | `src/extension.ts:551` |
134
134
  | command | `bg-update` | `command:bg-update` | `src/extension.ts:567` |
135
- | command | `claude-cache` | `command:claude-cache` | `src/core/anthropic-attribution.ts:1928` |
135
+ | command | `claude-cache` | `command:claude-cache` | `src/core/anthropic-attribution.ts:3026` |
136
136
  | command | `fusion` | `command:fusion` | `src/fusion-extension.ts:996` |
137
137
  | command | `fusion-models` | `command:fusion-models` | `src/fusion-extension.ts:1029` |
138
138
  | command | `jobs` | `command:jobs` | `src/extension.ts:605` |
@@ -12,7 +12,7 @@ covers_sources: []
12
12
  <!-- pi-docs:begin name="command-contract-claude-cache" generator="scripts/docs/generate.mjs" -->
13
13
  | Command | Description | Provenance |
14
14
  | --- | --- | --- |
15
- | `/claude-cache` | Show or set Claude cache retention for this session (short, long, default) | `src/core/anthropic-attribution.ts:1928` |
15
+ | `/claude-cache` | Show or set Claude cache retention for this session (short, long, default) | `src/core/anthropic-attribution.ts:3026` |
16
16
  <!-- pi-docs:end name="command-contract-claude-cache" -->
17
17
 
18
18
  Show or change the Anthropic cache-retention preference for the current session.
@@ -32,11 +32,11 @@ Show or change the Anthropic cache-retention preference for the current session.
32
32
  - No argument and `status` show the effective preference.
33
33
  - `short` requests normal ephemeral retention.
34
34
  - `long` requests one-hour retention where the selected model supports it.
35
- - `default` removes the session override and returns to process/package policy.
35
+ - `default` removes the session override and returns to the package's one-hour subscription policy unless `PI_CACHE_RETENTION` says otherwise.
36
36
 
37
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
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.
39
+ Pi's generic five-minute provider default does not override this package's one-hour subscription policy. Use `/claude-cache short` or `PI_CACHE_RETENTION=short` for an intentional short lane. An explicit call-level `none` remains authoritative, so Pi compaction and branch-summary requests are not re-marked by the session default. Those standalone requests still receive complete subscription attribution from Pi's fresh request-scoped routing ID.
40
40
 
41
41
  ## Errors and boundaries
42
42
 
@@ -26,7 +26,7 @@
26
26
  "state": "stale-authored-prose"
27
27
  },
28
28
  {
29
- "authored_body_sha256": "sha256:72c53dcc104f9b5efa57e38bcb21a4c3c620d5caf1571af82348f94dcafbe941",
29
+ "authored_body_sha256": "sha256:d74e15a5d9c67a6602e341a68a08d8ed06edb0769cc114e689d5702ebab2b575",
30
30
  "covers_sources": [
31
31
  "extensions/anthropic-attribution.ts",
32
32
  "src/core/anthropic-attribution-path.ts",
@@ -832,7 +832,7 @@
832
832
  "image": "https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png",
833
833
  "name": "pi-background-tasks",
834
834
  "type": "module",
835
- "version": "2.4.2"
835
+ "version": "2.5.0"
836
836
  },
837
837
  "public_surface_ids": [
838
838
  "command:bg",
@@ -902,7 +902,7 @@
902
902
  "id": "command:claude-cache",
903
903
  "kind": "command",
904
904
  "name": "claude-cache",
905
- "source": "src/core/anthropic-attribution.ts:1928"
905
+ "source": "src/core/anthropic-attribution.ts:3026"
906
906
  },
907
907
  {
908
908
  "description": "Start fixed-purpose Fusion reason in the background and return immediately.",
@@ -48,7 +48,7 @@ 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:722` |
50
50
  | `PI_BG_SHELL_PATH` | read | `src/core/common.ts:723` |
51
- | `PI_CACHE_RETENTION` | read, write | `src/core/anthropic-attribution.ts:587`<br>`src/core/fusion/claude-cache.ts:57`<br>`src/core/fusion/pi-child.ts:273`<br>`src/core/fusion/pi-child.ts:274` |
51
+ | `PI_CACHE_RETENTION` | read, write | `src/core/anthropic-attribution.ts:635`<br>`src/core/anthropic-attribution.ts:646`<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
52
  | `PI_FUSION_CANDIDATE_OUTPUT_RECOVERY_PATH` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:1879`<br>`src/fusion-child-extension.ts:599` |
53
53
  | `PI_FUSION_RESEARCH_ENABLED` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:1902`<br>`src/fusion-child-extension.ts:608` |
54
54
  | `PI_FUSION_SOURCE_POLICY_PATH` | read, remove, write | `src/core/fusion/pi-child.ts:100`<br>`src/core/fusion/pi-child.ts:1903`<br>`src/fusion-child-extension.ts:555` |
@@ -61,7 +61,7 @@ This generated registry lists production environment-variable references, runtim
61
61
  | `PI_SESSION_FILE` | remove | `src/core/delegate/launch.ts:330`<br>`src/core/fusion/pi-child.ts:100` |
62
62
  | `PI_SESSION_ID` | remove | `src/core/delegate/launch.ts:330`<br>`src/core/fusion/pi-child.ts:100` |
63
63
  | `PI_SKIP_VERSION_CHECK` | write | `src/core/delegate/launch.ts:352`<br>`src/core/fusion/pi-child.ts:272` |
64
- | `PIPELINE_ANTHROPIC_ATTRIBUTION_AUDIT_PATH` | read | `src/core/anthropic-attribution.ts:1013` |
64
+ | `PIPELINE_ANTHROPIC_ATTRIBUTION_AUDIT_PATH` | read | `src/core/anthropic-attribution.ts:1124` |
65
65
  | `SHELL` | read | `src/core/common.ts:718` |
66
66
  | `SystemRoot` | read | `src/core/windows-taskkill.ts:96` |
67
67
  | `WINDIR` | read | `src/core/windows-taskkill.ts:101` |
@@ -15,17 +15,27 @@ This subsystem owns the package-wide Anthropic subscription attribution provider
15
15
 
16
16
  `package.json.pi.extensions` loads `extensions/anthropic-attribution.ts` for every normal `pi-background-tasks` installation, before the background-task entrypoint. The extension is provider-gated: non-Anthropic sessions and payloads are unchanged.
17
17
 
18
- For Anthropic sessions it registers the package-owned `anthropic` provider transport and applies the Claude Code subscription request contract:
18
+ For Anthropic sessions it registers the package-owned `anthropic` provider transport. Mandatory attribution is owned inside that transport from each request's Pi-supplied `options.sessionId`; `before_provider_request` remains optional middleware and is never an identity initializer. The transport applies the Claude Code subscription request contract:
19
19
 
20
- - subscription OAuth token transport only; metered Anthropic credentials are refused;
20
+ - subscription OAuth token transport only; metered Anthropic credentials are refused, the bearer token is sent only to the exact official Anthropic HTTPS origin, and HTTP redirects are disabled;
21
21
  - Claude Code session, account, device, beta, user-agent, and system-identity attribution;
22
22
  - model-specific fixed/adaptive thinking policy;
23
23
  - the conservative 200K subscription context policy;
24
+ - provenance-aware cross-provider history projection and Fable 5.1 thinking binding;
24
25
  - system, final-tool, and final-conversation cache surfaces;
25
- - provider-authoritative usage and one-hour cache-write accounting when reported.
26
+ - provider-authoritative usage, cache diagnostics, and one-hour cache-write accounting when reported;
27
+ - strict SSE completion: matching event names, one `message_start`, closed content blocks, a recognized terminal stop reason, and one `message_stop` are required before success or lineage persistence.
26
28
 
27
29
  The extension reads `userID` and `oauthAccount.accountUuid` from `~/.claude.json` without writing it. Missing/malformed account data, unsupported model policy, malformed payload/cache controls, and non-OAuth transport fail loudly.
28
30
 
31
+ ## Cross-provider history and cache lineage
32
+
33
+ Assistant messages carry their producing `provider`, `api`, and `model`. The transport never parses an opaque reasoning signature. Foreign visible thinking is projected deterministically as text; foreign opaque, redacted, and signature-only blocks are omitted. Claude thinking is replayed only when a successful direct-Anthropic response carries a matching `anthropic-cache-lineage` diagnostic binding response ID, source tuple, assistant-content hash, system/tools attribution profile, effective cache retention, request-message count, and request-prefix hash. Empty, redacted, and valid non-BMP Unicode Claude blocks are preserved byte-for-byte. Fable 5.1 accepts lineage-proven earlier Claude blocks; reverse replay is denied.
34
+
35
+ Every target model has an independent append-only lane. Before transport, the adapter proves the prior successful wire history remains an exact prefix and that model, sanitized system, canonical tools, thinking/effort, beta profile, and effective retention are unchanged. Unexpected drift fails before network. An intentional TTL change starts a cryptographically named signature epoch and suppresses prior-epoch signed thinking permanently, including after a later short→long return. A canonical leading Pi compaction summary likewise opens one hash-bound signature epoch only; retaining that old marker cannot excuse later unrelated history drift. Tool IDs, schemas, arguments, user messages, and text-only tool results have deterministic block-shaped serialization, so advancing the final cache marker does not rewrite prior content. Optional payload middleware runs exactly once after transport-owned attribution and cannot change the protected model/stream route, account/device/session metadata, billing identity, cache-control placement/value topology, four-breakpoint limit, or already-authorized message/static/profile/retention lineage.
36
+
37
+ Fable 5.1 always sends `thinking-binding-controls-2026-08-01` with prefix mismatch set to `error`, plus `cache-diagnosis-2026-04-07`. The previous successful response ID is chained within the same model lane; provider diagnostics and `input_transformations` are persisted outside model context. There is no automatic signature retry or silent thinking drop.
38
+
29
39
  ## Sanitization
30
40
 
31
41
  The package has no runtime dependency on `@ravshansbox/pi-anthropic-sps`. Its three reviewed exact-match prompt-line rules are implemented locally in `src/core/anthropic-attribution.ts`, with the upstream MIT notice retained in `THIRD_PARTY_NOTICES.md`.
@@ -52,7 +62,7 @@ Arbitrary shell commands started through `bg_run` are not rewritten. An Anthropi
52
62
 
53
63
  ## Cache retention
54
64
 
55
- `PI_CACHE_RETENTION=none|short|long` selects process/provider policy. `/claude-cache status|short|long|default` stores a branch-local session override as a custom entry that does not enter model context. Call-level `cacheRetention` remains highest precedence, notably preserving Pi's compaction opt-out.
65
+ `PI_CACHE_RETENTION=none|short|long` selects process/provider policy. `/claude-cache status|short|long|default` stores a branch-local session override as a custom entry that does not enter model context. Registered subscription sessions default to one hour even when Pi supplies its generic five-minute provider default; an intentional short policy must come from the session command or environment. Call-level `cacheRetention:none` remains authoritative for one-off compaction and branch-summary requests and emits no cache markers. Pi gives those standalone requests a fresh routing `options.sessionId`; that exact ID is used consistently in metadata, headers, and request-local lineage without coupling the one-off request to the parent cache lane.
56
66
 
57
67
  ## Related docs
58
68
 
@@ -12,7 +12,7 @@ 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.4.2`
15
+ - Canonical package version: `2.5.0`
16
16
  - Governed markdown docs: 42
17
17
  - Public surfaces extracted: 31
18
18
  - Governed production sources: 50
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-background-tasks",
3
- "version": "2.4.2",
3
+ "version": "2.5.0",
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",