pi-background-tasks 2.3.0 → 2.4.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 +2 -1
- package/TESTING.md +8 -4
- package/TEST_PLAN.md +3 -3
- package/docs/INDEX.md +1 -1
- package/docs/concepts/context-projection-and-budgeting.md +4 -2
- package/docs/manifest.json +5 -6
- package/docs/operations/troubleshooting.md +3 -1
- package/docs/reference/runtime-contracts.md +18 -18
- package/docs/subsystems/delegation.md +22 -13
- package/docs/subsystems/docs-freshness-gate.md +3 -3
- package/docs/tools/bg_delegate.md +12 -7
- package/docs/tools/bg_result.md +2 -2
- package/package.json +1 -1
- package/src/core/context/token-budget.ts +16 -3
- package/src/core/delegate/artifacts.ts +14 -12
- package/src/core/delegate/budget.ts +78 -33
- package/src/core/delegate/launch.ts +4 -2
- package/src/core/delegate/result-package.ts +16 -0
- package/src/core/delegate/runner.ts +21 -2
- package/src/core/delegate/types.ts +12 -1
- package/src/delegate-child-extension.ts +368 -69
- package/src/delegate-extension.ts +5 -2
package/README.md
CHANGED
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
| Fact | Value |
|
|
28
28
|
| --- | --- |
|
|
29
29
|
| Package | `pi-background-tasks` |
|
|
30
|
-
| Version | `2.
|
|
30
|
+
| Version | `2.4.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) |
|
|
@@ -295,6 +295,7 @@ Agent tasks launched through `pi -p ...` or `pi --mode json ...` and marked `isA
|
|
|
295
295
|
## Architecture, trust, and safety
|
|
296
296
|
|
|
297
297
|
- Runtime task files live under `.pi/tasks/<session-id>-<pid>/`; Fusion artifacts under `.pi/fusion/...`; delegate artifacts under `.pi/delegate/...`.
|
|
298
|
+
- Delegate launch budgeting uses backed route-family calibration for eligible large prompts and records a provable conservative counter-forecast across every byte class. During investigation, text and image-bearing tool output spill losslessly when retaining them would consume protected final-answer runway—even below the normal 64 KiB per-result threshold. Exact artifact ranges return as base64, final capture excludes intermediate tool-use narration, and near the runway boundary tools are disabled for graceful finalization. Runtime token estimates are advisory; Pi/provider own live context admission, avoiding Fusion BUG-185-style false refusals.
|
|
298
299
|
- Shell jobs are tracked by the package, but they are not sandboxed. Treat commands as local processes with your permissions and credentials.
|
|
299
300
|
- Delegate and Fusion child Pi processes are route-pinned where applicable; delegate/Fusion paths do not silently substitute routes.
|
|
300
301
|
- 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.
|
package/TESTING.md
CHANGED
|
@@ -114,8 +114,7 @@ Two unit gates protect Fusion's persisted artifact bytes, which are a frozen for
|
|
|
114
114
|
- `tests/unit/delegate-seed.test.ts` — verbatim visible text, thinking/tool-payload
|
|
115
115
|
exclusion, marker-only images, sibling-batch exclusion, byte-identical construction
|
|
116
116
|
across repeated builds and separate processes, and receive-side seed verification.
|
|
117
|
-
- `tests/unit/delegate-budget.test.ts` — reserve arithmetic, boundary accept/reject,
|
|
118
|
-
and the total runtime governor.
|
|
117
|
+
- `tests/unit/delegate-budget.test.ts` — reserve arithmetic, backed-family versus conservative launch policy, incident byte-class fixture replay, provable multibyte counter-forecast, retained-growth runway, boundary accept/reject, and advisory runtime measurement.
|
|
119
118
|
- `tests/unit/delegate-result-package.test.ts` — hash verification, strict base64,
|
|
120
119
|
encoding refusal for lone surrogates, route-mismatch and missing-attestation
|
|
121
120
|
detection, and explicitly unavailable usage.
|
|
@@ -132,8 +131,13 @@ Two unit gates protect Fusion's persisted artifact bytes, which are a frozen for
|
|
|
132
131
|
resolves the exact pinned provider, retains the package guard, and commits.
|
|
133
132
|
- `tests/scripted-provider/delegate-child-guard.test.ts` — the child guard inside a
|
|
134
133
|
real Pi agent loop: a 2 MB tool result spilled to a hashed artifact with the payload
|
|
135
|
-
kept out of the transcript,
|
|
136
|
-
|
|
134
|
+
kept out of the transcript, structured preservation of image-bearing results,
|
|
135
|
+
repeated sub-64-KiB results spilling against protected route runway, BUG-185
|
|
136
|
+
regression coverage proving advisory estimates do not abort a valid live request,
|
|
137
|
+
graceful no-tool finalization, byte-exact base64 range reads including a split UTF-8
|
|
138
|
+
sequence, malformed-Unicode spill refusal, exclusion of intermediate tool-use
|
|
139
|
+
narration from the committed answer, multi-turn usage accumulation, route-drift
|
|
140
|
+
refusal, answer capture, and turn-limit enforcement.
|
|
137
141
|
- `tests/sdk/delegate-sdk.test.ts` — the full public loop through the shipped
|
|
138
142
|
entrypoint with a fake child `pi`: launch receipt, projected context actually
|
|
139
143
|
reaching the child, default isolated argv, explicit ambient argv/warning/metadata,
|
package/TEST_PLAN.md
CHANGED
|
@@ -91,9 +91,9 @@ SDK/RPC/scripted-provider/package/compatibility coverage asserts exactly four to
|
|
|
91
91
|
| Pi hook contract | `npm run test:hook-contract`, `tests/scripted-provider/pi-hook-contract-evidence.json`, `src/core/delegate/hook-contract-evidence.json` | | | | | | evidence parity | yes | Executes real Pi agent loops and records, rather than assumes: Fusion `before_provider_request` transformations chain in extension load order through the Codex transport adapter and abort before local HTTP transport; Delegate `context` fires once before every model call in load order; returned messages reach the provider; **throwing** in `context` does NOT block dispatch (Pi catches and continues); `ctx.abort()` either skips provider invocation (Pi 0.84) or delivers an already-aborted signal (older supported lines), blocks transport, and terminates the run; `tool_result` fires before the transcript entry, chains in load order, replacement reaches the provider while the original does not, and toolCallId/role/`isError` survive. Handler ordering across two separate probe extensions is pinned. The evidence file is compared, never silently regenerated, and a package test asserts the shipped copy is byte-identical. |
|
|
92
92
|
| Delegate context seeding | `bg_delegate` seed `pi-background-tasks.delegate-seed.v2`, `seed.json`, `context-omission-ledger.json` | yes | yes | | | | mutation guard | yes | Unit covers verbatim visible user/assistant text, complete exclusion of thinking/tool-call arguments/tool-result payloads, marker-only images with no raw bytes anywhere in the seed, exclusion of the in-flight `bg_delegate` call **and every sibling call in the same assistant message** (two delegates launched together get byte-identical projected history), the prompt preserved exactly and marked `explicit_text` authority, hash-bound `extension_mode`, zero payload-preview bytes, byte-identical construction across repeated builds and across separate processes via a fixed-leaf fixture, and refusal of a blank prompt. Receive-side verification rejects a single mutated byte, a foreign task identity, a structurally malformed seed whose hash matches, a directive whose hash disagrees with its text, an unknown extension mode, and an unsupported capability. SDK proves the projected parent text actually reaches the child. |
|
|
93
93
|
| Delegate route pinning | `bg_delegate` `route`, `route_attestations` | yes | yes | | | | mutation guard | yes | Unit covers defaulting to the parent current model, explicit pinning, refusal of an unavailable route with `route_unresolved` and no substitution, refusal of a route with no declared context window with `route_capacity_unknown` rather than assuming one, and refusal when neither is available. The result package rejects a mismatched route, a mismatched attestation, and a package carrying no attestation at all. The scripted-provider gate proves an observed route drift prevents a success commit entirely. The mutation guard fails if a fallback list or first-available selection appears. |
|
|
94
|
-
| Delegate budget and guard | `budget-plan.json`, typed `seed_budget_exceeded`
|
|
95
|
-
| Delegate tool-result spilling | `spill/` artifacts, `pi-background-tasks.delegate-receipt.v1`, `delegate_read_artifact` | yes | yes | | | | mutation guard | yes | Unit proves a 2 MB payload is written in full, hashed, and represented by a receipt carrying `(turn_sequence, source_call_index, tool_call_id)` assigned before execution, so parallel spills completing out of order cannot be mis-associated; an aggregate-cap refusal writes nothing and emits no receipt; bounded range reads return exactly the requested bytes; a range past end-of-file, a path
|
|
96
|
-
| Delegate result commit and `bg_result` | `result.json` (`pi-background-tasks.delegate-result.v1`), `bg_result` | yes | yes | | | | mutation guard | yes | The single atomically-committed package is the sole answer data plane: temp-write, file fsync, and rename, with the rename as the commit point; POSIX additionally fsyncs the parent directory
|
|
94
|
+
| Delegate budget and guard | `budget-plan.json` v3, `runtime-budget.json`, typed `seed_budget_exceeded` | yes | yes | | | | mutation guard | yes | Unit covers reserve subtraction, exact-boundary accept and one-byte-past reject, backed large-prompt family calibration with a provable every-byte-class counter-forecast, the 173,740-byte compacted-session incident byte-class fixture, protected retained-growth/finalization runway, child system prompt input, multi-byte UTF-8, and conservative fallback for small/unbacked routes. Preflight refusal creates **zero** children and **zero** artifacts. Scripted-provider coverage pins Fusion BUG-185, image-bearing structured spill fidelity, base64 range fidelity across split UTF-8, final-answer-only capture, and truthful diagnostics. An advisory overage does not self-report provider exhaustion or abort valid transport; it disables tools for graceful finalization. Runtime evidence records retained/spilled bytes, context estimates, first-request usage, and calibration underforecast. |
|
|
95
|
+
| Delegate tool-result spilling | `spill/` artifacts, `pi-background-tasks.delegate-receipt.v1`, `delegate_read_artifact` | yes | yes | | | | mutation guard | yes | Unit proves a 2 MB payload is written in full, hashed, and represented by a receipt carrying `(turn_sequence, source_call_index, tool_call_id)` assigned before execution, so parallel spills completing out of order cannot be mis-associated; an aggregate-cap refusal writes nothing and emits no receipt; bounded range reads return exactly the requested bytes; a range past end-of-file, a path escape, and non-positive lengths are refused. Scripted-provider coverage additionally proves repeated 32 KiB results—each below the fixed 64 KiB cap—spill proactively when retaining them would consume protected final-answer runway, while the child still commits a complete answer. |
|
|
96
|
+
| Delegate result commit and `bg_result` | `result.json` (`pi-background-tasks.delegate-result.v1`), `bg_result` | yes | yes | | | | mutation guard | yes | The single atomically-committed package is the sole answer data plane: temp-write, file fsync, and rename, with the rename as the commit point; POSIX additionally fsyncs the parent directory. Unit covers round-trip verification, exact encoding, corruption/identity/route rejection, explicitly unavailable usage, answer capture enforcement, zero-exit/no-commit, child-recorded failure, and cancellation. SDK covers not-ready, completed, corrupted, route-drift, unknown-task, and no-truncation delivery. Terminal diagnostics dynamically advertise only paths that exist: the merged `.pi/tasks/...output` path is reported when available, while absent delegate-local `child.stdout.txt`/`child.stderr.txt` files are never claimed. |
|
|
97
97
|
| Delegate extension/isolation boundary | `extensionMode`, child argv, `--session-id`, `--session-dir`, `--tools` | yes | yes | | | | mutation guard | yes | Unit proves default/explicit isolated mode sets `--no-extensions`; ambient mode omits only that flag; both modes retain separate task-owned session identity, inspect-only model tools, the explicit denylist, disabled skills/prompt templates/themes/context files, and the package guard; Anthropic keeps attribution-before-guard in both modes. Public schema/preparation rejects unknown modes, arbitrary `extensions`/`extensionPaths`, and route substitution. Seed/task facts/launch details/manifest bind the selected mode, and ambient receipt text warns that arbitrary extension code executes outside the tool sandbox. SDK verifies argv, warning, and metadata. A fresh-process scripted-provider regression installs a provider only in a temp global extension directory: isolated mode fails unknown-provider with no result, while ambient mode resolves that exact pinned provider and commits under the guard. |
|
|
98
98
|
| Fusion artifact byte immutability | `canonical-input.json`, `context-omission-ledger.json`, `budget-plan.json` | yes | | | | | shared-source guard | | A 28-case differential corpus is rendered to raw bytes and compared against a committed golden file that is never auto-updated once present, and separately against `tests/oracle/fusion-context-pre-extraction.ts`, a verbatim pre-extraction copy of the projection engine used as an **independent oracle**. Equivalence covers canonical input, ledger, and budget-plan bytes, `Object.is` comparison of budget floats including `utilization`, field-for-field accounting parity, ledger root hashes, and identical error type and message for unknown blocks and blank requests. The package guard now scans the shared `context/` modules, not only the Fusion facade, and pins both the shared divisor definition and Fusion's binding to it. |
|
|
99
99
|
| Fusion model selector | `/fusion-models`, `fusion-models.json`, `FusionModelSelector` | yes | yes | yes | yes | yes | yes | | Unit covers strict config parsing, duplicates, slash-containing model IDs, stale model failures, `$current`, atomic save, inter-process lock/revision compare-and-swap, and deterministic concurrent-save conflict. Component covers all five slots, duplicate selection, searchable model list, stale display, reset/save/cancel, persistence errors, and width safety. SDK drives the real command in a synthetic TUI context without `ctx.mode` to cover old Pi compatibility and verifies duplicate `$current`/explicit model persistence; SDK also verifies headless no-UI rejection. RPC verifies non-TUI notification without hanging, PTY verifies the real selector opens in a TUI, and compatibility smoke verifies print-mode rejection for every supported Pi version. |
|
package/docs/INDEX.md
CHANGED
|
@@ -142,7 +142,7 @@ Generated navigation for every package-local documentation page. This index inte
|
|
|
142
142
|
| tool | `bg_delegate` | `tool:bg_delegate` | `src/delegate-extension.ts:340` |
|
|
143
143
|
| tool | `bg_kill` | `tool:bg_kill` | `src/extension.ts:908` |
|
|
144
144
|
| tool | `bg_logs` | `tool:bg_logs` | `src/extension.ts:863` |
|
|
145
|
-
| tool | `bg_result` | `tool:bg_result` | `src/delegate-extension.ts:
|
|
145
|
+
| tool | `bg_result` | `tool:bg_result` | `src/delegate-extension.ts:516` |
|
|
146
146
|
| tool | `bg_run` | `tool:bg_run` | `src/extension.ts:682` |
|
|
147
147
|
| tool | `bg_run_pi_attested` | `tool:bg_run_pi_attested` | `src/extension.ts:767` |
|
|
148
148
|
| tool | `bg_status` | `tool:bg_status` | `src/extension.ts:832` |
|
|
@@ -62,7 +62,8 @@ Calibration facts in code:
|
|
|
62
62
|
- observed large Fusion prompt corpus: 882 prompts, dated 2026-08-02;
|
|
63
63
|
- Anthropic configured rate: 1.73 B/token after haircut;
|
|
64
64
|
- OpenAI Codex configured rate: 2.89 B/token after haircut;
|
|
65
|
-
-
|
|
65
|
+
- delegate launch uses backed family calibration only for large prompts on routes that can hold the calibration domain; small prompts/routes, unbacked models, unknown providers, and dense-ASCII out-of-domain cases use conservative/floor rates;
|
|
66
|
+
- delegate runtime context estimates are advisory, while a separate provable `1.00 B/token` retained-growth budget drives explicit spilling and no-tool finalization.
|
|
66
67
|
|
|
67
68
|
The dense-ASCII gate is explicitly a low-whitespace heuristic proxy, not a tokenizer guarantee. Calibration applies only when the input is in the measured domain and the route capacity can hold that domain.
|
|
68
69
|
|
|
@@ -70,9 +71,10 @@ The dense-ASCII gate is explicitly a low-whitespace heuristic proxy, not a token
|
|
|
70
71
|
|
|
71
72
|
- `allowedInputTokens()` returns a signed number and never clamps unusable routes to zero.
|
|
72
73
|
- Callers must reject unusable or too-small context windows before spawning children.
|
|
73
|
-
- Multibyte bytes cannot bypass accounting.
|
|
74
|
+
- Multibyte bytes cannot bypass accounting; delegate's published provable counter-forecast charges them at the same `1.00 B/token` ceiling as every other byte class.
|
|
74
75
|
- Unknown output contracts are charged separately; future output cannot be assumed to be cheap.
|
|
75
76
|
- Rate-source warnings are part of the contract and should be surfaced in refusal details.
|
|
77
|
+
- A package-local estimate must not reject a live provider payload by subtracting hypothetical output; Fusion BUG-185 established this as a false-refusal shape. Use conservative estimates for lossless spill decisions, where a false positive preserves bytes rather than failing work.
|
|
76
78
|
|
|
77
79
|
## No silent truncation
|
|
78
80
|
|
package/docs/manifest.json
CHANGED
|
@@ -13,18 +13,17 @@
|
|
|
13
13
|
"state": "pass"
|
|
14
14
|
},
|
|
15
15
|
{
|
|
16
|
-
"authored_body_sha256": "sha256:
|
|
16
|
+
"authored_body_sha256": "sha256:810591c82ced086e1622be9b037db88c8a667856580895dc90cd5af54c6e2107",
|
|
17
17
|
"covers_sources": [
|
|
18
18
|
"src/core/context/parent-snapshot.ts",
|
|
19
19
|
"src/core/context/token-budget.ts",
|
|
20
20
|
"src/core/context/visible-conversation-v2.ts"
|
|
21
21
|
],
|
|
22
22
|
"doc_id": "concepts/context-projection-and-budgeting",
|
|
23
|
-
"notes": "Reviewed visible conversation transform identity, active-branch snapshotting, omission receipts and hashes, text/tool/thinking/image dispositions, token estimators, calibration, reserves, warnings, and fail-loud no-truncation behavior.",
|
|
24
23
|
"rel": "docs/concepts/context-projection-and-budgeting.md",
|
|
25
24
|
"required": true,
|
|
26
25
|
"reviewer": "gpt-5.5-final-context-projection-reviewer",
|
|
27
|
-
"state": "
|
|
26
|
+
"state": "stale-authored-prose"
|
|
28
27
|
},
|
|
29
28
|
{
|
|
30
29
|
"authored_body_sha256": "sha256:72c53dcc104f9b5efa57e38bcb21a4c3c620d5caf1571af82348f94dcafbe941",
|
|
@@ -75,7 +74,7 @@
|
|
|
75
74
|
"state": "stale-authored-prose"
|
|
76
75
|
},
|
|
77
76
|
{
|
|
78
|
-
"authored_body_sha256": "sha256:
|
|
77
|
+
"authored_body_sha256": "sha256:67fbb232e66bf0b9f4c1a81b54ec5476c0aae929ed0f0777d57601afcac8e08b",
|
|
79
78
|
"covers_sources": [
|
|
80
79
|
"extensions/delegate-child.ts",
|
|
81
80
|
"src/core/delegate/artifacts.ts",
|
|
@@ -833,7 +832,7 @@
|
|
|
833
832
|
"image": "https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png",
|
|
834
833
|
"name": "pi-background-tasks",
|
|
835
834
|
"type": "module",
|
|
836
|
-
"version": "2.
|
|
835
|
+
"version": "2.4.0"
|
|
837
836
|
},
|
|
838
837
|
"public_surface_ids": [
|
|
839
838
|
"command:bg",
|
|
@@ -1172,7 +1171,7 @@
|
|
|
1172
1171
|
],
|
|
1173
1172
|
"type": "object"
|
|
1174
1173
|
},
|
|
1175
|
-
"source": "src/delegate-extension.ts:
|
|
1174
|
+
"source": "src/delegate-extension.ts:516"
|
|
1176
1175
|
},
|
|
1177
1176
|
{
|
|
1178
1177
|
"description": "Start a named long-running shell command in the background and return immediately with a task ID and output path. By default, completed, failed, or killed terminal state is delivered automatically as <background-task-notification> and starts a follow-up agent turn; do not sleep or poll merely to wait. Output is written to .pi/tasks and model-visible logs are bounded to 50.0KB.",
|
|
@@ -24,7 +24,9 @@ Start from the symptom, verify the source-owned doc, then apply the remediation.
|
|
|
24
24
|
| Terminal metadata/output durability failure | Fsync/close/metadata write failed | Treat terminal state as failed; inspect `DurableFileError` operation/path/cause. See `docs/subsystems/child-launch-durability-and-safety.md`. |
|
|
25
25
|
| Delegate refuses with `delegate_hook_contract_unsupported` | Current Pi hook behavior does not match committed evidence | Re-run the hook characterization gate during release work and re-review the guard; do not weaken the guard. See `docs/operations/testing.md`. |
|
|
26
26
|
| Delegate refuses with `route_unresolved` or `route_capacity_unknown` | Requested/default route unavailable or lacks usable context window | Pin an available provider/model with declared context window; no substitute route is selected. |
|
|
27
|
-
| Delegate refuses with `seed_budget_exceeded` |
|
|
27
|
+
| Delegate refuses with `seed_budget_exceeded` | Exact child prompt plus system prompt exceeds allowed input under the backed route-family policy or conservative fallback | Use a larger-context subscription route, delegate earlier, or reduce visible parent text. Nothing was clipped. |
|
|
28
|
+
| Delegate spills many individually small tool results | Retaining them would consume protected final-answer runway | This is expected lossless pressure control. The full bytes are in `spill/`; inspect `runtime-budget.json`. Narrow the investigation only if receipt-driven range reads become excessive. |
|
|
29
|
+
| Delegate enters finalization runway | Advisory context/runway pressure disabled tools so the child can answer from gathered evidence | Let the child finish. Do not re-enable tools or treat the advisory estimate as a provider context rejection. |
|
|
28
30
|
| `bg_result` says not ready | Child has not committed `result.json` yet | Wait for terminal notification or inspect later; do not poll tightly. |
|
|
29
31
|
| Delegate result corruption/hash/identity mismatch | Result package does not match task/seed/route/hash contract | Treat as invalid; inspect artifact bytes. Do not synthesize an answer. |
|
|
30
32
|
| Fusion model unavailable or metered route refusal | Frontier route is not admitted as a Pi subscription/OAuth route, or configured model is stale | Fix `/fusion-models` config to available subscription routes. Never route GPT/Claude-class work through metered APIs. |
|
|
@@ -37,11 +37,11 @@ This generated registry lists production environment-variable references, runtim
|
|
|
37
37
|
| `PI_API_BASE_URL` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:98` |
|
|
38
38
|
| `PI_API_KEY` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:98` |
|
|
39
39
|
| `PI_AUTH_FILE` | remove | `src/core/attested-pi-run.ts:135`<br>`src/core/fusion/pi-child.ts:98` |
|
|
40
|
-
| `PI_BG_DELEGATE_ARTIFACT_DIR` | read, write | `src/core/delegate/launch.ts:353`<br>`src/delegate-child-extension.ts:
|
|
41
|
-
| `PI_BG_DELEGATE_LAUNCH_NONCE` | read, write | `src/core/delegate/launch.ts:357`<br>`src/delegate-child-extension.ts:
|
|
42
|
-
| `PI_BG_DELEGATE_SEED_PATH` | read, write | `src/core/delegate/launch.ts:354`<br>`src/delegate-child-extension.ts:
|
|
43
|
-
| `PI_BG_DELEGATE_SEED_SHA256` | read, write | `src/core/delegate/launch.ts:355`<br>`src/delegate-child-extension.ts:
|
|
44
|
-
| `PI_BG_DELEGATE_TASK_ID` | read, write | `src/core/delegate/launch.ts:356`<br>`src/delegate-child-extension.ts:
|
|
40
|
+
| `PI_BG_DELEGATE_ARTIFACT_DIR` | read, write | `src/core/delegate/launch.ts:353`<br>`src/delegate-child-extension.ts:384` |
|
|
41
|
+
| `PI_BG_DELEGATE_LAUNCH_NONCE` | read, write | `src/core/delegate/launch.ts:357`<br>`src/delegate-child-extension.ts:388` |
|
|
42
|
+
| `PI_BG_DELEGATE_SEED_PATH` | read, write | `src/core/delegate/launch.ts:354`<br>`src/delegate-child-extension.ts:385` |
|
|
43
|
+
| `PI_BG_DELEGATE_SEED_SHA256` | read, write | `src/core/delegate/launch.ts:355`<br>`src/delegate-child-extension.ts:386` |
|
|
44
|
+
| `PI_BG_DELEGATE_TASK_ID` | read, write | `src/core/delegate/launch.ts:356`<br>`src/delegate-child-extension.ts:387` |
|
|
45
45
|
| `PI_BG_DISABLE_PI_TELEMETRY` | read | `src/core/registry.ts:195` |
|
|
46
46
|
| `PI_BG_DISABLE_UPDATE_CHECK` | read | `src/extension.ts:455` |
|
|
47
47
|
| `PI_BG_MAX_OUTPUT_BYTES` | read | `src/core/registry.ts:69` |
|
|
@@ -71,16 +71,14 @@ This generated registry lists production environment-variable references, runtim
|
|
|
71
71
|
| Kind | Path/artifact | Provenance |
|
|
72
72
|
| --- | --- | --- |
|
|
73
73
|
| config | `fusion-models.json` | `src/core/fusion/config.ts:21` |
|
|
74
|
-
| delegate-artifact | `budget-plan.json` | `src/core/delegate/artifacts.ts:
|
|
75
|
-
| delegate-artifact | `child-prompt.txt` | `src/core/delegate/artifacts.ts:
|
|
76
|
-
| delegate-artifact | `
|
|
77
|
-
| delegate-artifact | `child.stdout.txt` | `src/core/delegate/artifacts.ts:49` |
|
|
78
|
-
| delegate-artifact | `context-omission-ledger.json` | `src/core/delegate/artifacts.ts:42` |
|
|
74
|
+
| delegate-artifact | `budget-plan.json` | `src/core/delegate/artifacts.ts:44` |
|
|
75
|
+
| delegate-artifact | `child-prompt.txt` | `src/core/delegate/artifacts.ts:48` |
|
|
76
|
+
| delegate-artifact | `context-omission-ledger.json` | `src/core/delegate/artifacts.ts:43` |
|
|
79
77
|
| delegate-artifact | `error.json` | `src/core/delegate/artifacts.ts:50` |
|
|
80
|
-
| delegate-artifact | `manifest.json` | `src/core/delegate/artifacts.ts:
|
|
81
|
-
| delegate-artifact | `outcome.json` | `src/core/delegate/artifacts.ts:
|
|
78
|
+
| delegate-artifact | `manifest.json` | `src/core/delegate/artifacts.ts:45` |
|
|
79
|
+
| delegate-artifact | `outcome.json` | `src/core/delegate/artifacts.ts:46` |
|
|
82
80
|
| delegate-artifact | `result.json` | `src/core/delegate/result-package.ts:28` |
|
|
83
|
-
| delegate-artifact | `seed.json` | `src/core/delegate/artifacts.ts:
|
|
81
|
+
| delegate-artifact | `seed.json` | `src/core/delegate/artifacts.ts:42` |
|
|
84
82
|
| delegate-artifact | `spill/<receipt-named-file>` | `src/core/delegate/artifacts.ts:54` |
|
|
85
83
|
| directory | `.pi/delegate/<session-id>-<pid>/<task-id>/` | `src/core/delegate/artifacts.ts:160` |
|
|
86
84
|
| directory | `.pi/fusion/<session-id>-<pid>/<run-id>/` | `src/core/fusion/artifacts.ts:563` |
|
|
@@ -116,17 +114,19 @@ This generated registry lists production environment-variable references, runtim
|
|
|
116
114
|
| Schema | Provenance |
|
|
117
115
|
| --- | --- |
|
|
118
116
|
| `phase2.pi_task_attestation.v1` | `src/core/attested-pi-run.ts:20` |
|
|
119
|
-
| `pi-background-tasks.delegate-budget-plan.
|
|
120
|
-
| `pi-background-tasks.delegate-child-terminal.v1` | `src/delegate-child-extension.ts:
|
|
117
|
+
| `pi-background-tasks.delegate-budget-plan.v3` | `src/core/delegate/types.ts:21` |
|
|
118
|
+
| `pi-background-tasks.delegate-child-terminal.v1` | `src/delegate-child-extension.ts:584` |
|
|
121
119
|
| `pi-background-tasks.delegate-hook-contract.v1` | `src/core/delegate/hook-contract.ts:15` |
|
|
122
120
|
| `pi-background-tasks.delegate-launch.v1` | `src/delegate-extension.ts:458` |
|
|
123
121
|
| `pi-background-tasks.delegate-ledger.v1` | `src/core/delegate/types.ts:16` |
|
|
124
122
|
| `pi-background-tasks.delegate-manifest.v2` | `src/core/delegate/types.ts:22` |
|
|
125
|
-
| `pi-background-tasks.delegate-outcome.v1` | `src/core/delegate/runner.ts:
|
|
123
|
+
| `pi-background-tasks.delegate-outcome.v1` | `src/core/delegate/runner.ts:228` |
|
|
126
124
|
| `pi-background-tasks.delegate-receipt.v1` | `src/core/delegate/types.ts:19` |
|
|
127
|
-
| `pi-background-tasks.delegate-result-view.v1` | `src/delegate-extension.ts:
|
|
125
|
+
| `pi-background-tasks.delegate-result-view.v1` | `src/delegate-extension.ts:734` |
|
|
128
126
|
| `pi-background-tasks.delegate-result.v1` | `src/core/delegate/types.ts:18` |
|
|
127
|
+
| `pi-background-tasks.delegate-runtime-budget.v1` | `src/delegate-child-extension.ts:489` |
|
|
129
128
|
| `pi-background-tasks.delegate-seed.v2` | `src/core/delegate/types.ts:15` |
|
|
129
|
+
| `pi-background-tasks.delegate-tool-result-content.v1` | `src/delegate-child-extension.ts:190` |
|
|
130
130
|
| `pi-background-tasks.extension-request.v1` | `src/core/extension-api.ts:15` |
|
|
131
131
|
| `pi-background-tasks.extension-response.v1` | `src/core/extension-api.ts:16` |
|
|
132
132
|
| `pi-background-tasks.extension-terminal.v1` | `src/core/extension-api.ts:17` |
|
|
@@ -149,7 +149,7 @@ This generated registry lists production environment-variable references, runtim
|
|
|
149
149
|
| `pi-background-tasks.fusion-merge-input.v1` | `src/core/fusion/prompts.ts:336` |
|
|
150
150
|
| `pi-background-tasks.fusion-models.v1` | `src/core/fusion/types.ts:13` |
|
|
151
151
|
| `pi-background-tasks.fusion-progress.v1` | `src/fusion-extension.ts:59` |
|
|
152
|
-
| `pi-background-tasks.fusion-result-view.v1` | `src/delegate-extension.ts:
|
|
152
|
+
| `pi-background-tasks.fusion-result-view.v1` | `src/delegate-extension.ts:775` |
|
|
153
153
|
| `pi-background-tasks.fusion-result.v4` | `src/core/fusion/types.ts:19` |
|
|
154
154
|
| `pi-background-tasks.fusion-result.v5` | `src/core/fusion/types.ts:20` |
|
|
155
155
|
| `pi-background-tasks.fusion-runtime-guard.v2` | `src/core/fusion/child-protocol.ts:24` |
|
|
@@ -82,43 +82,52 @@ Routes are pinned once:
|
|
|
82
82
|
- unavailable/unknown-capacity routes fail;
|
|
83
83
|
- no substitution, fallback, or retry on a different route.
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
Budgeting separates admission from package-owned runtime growth. Constants currently documented by source/tests:
|
|
86
86
|
|
|
87
87
|
- reserved output: `16,384` tokens;
|
|
88
88
|
- framing reserve: `8,192` tokens;
|
|
89
89
|
- safety reserve: `4,096` tokens;
|
|
90
90
|
- minimum usable input: `8,192` tokens;
|
|
91
|
+
- protected finalization input runway: `32,768` tokens;
|
|
92
|
+
- finalization trigger inside retained-growth runway: `8,192` tokens;
|
|
91
93
|
- default turns/tools/timeout: `24` / `120` / `1200s`;
|
|
92
94
|
- per-result transcript cap: `64 KiB`;
|
|
93
|
-
- aggregate tool-output cap: `64 MiB`;
|
|
94
|
-
- answer capture cap
|
|
95
|
+
- aggregate raw tool-output cap: `64 MiB`;
|
|
96
|
+
- answer capture cap: `4 MiB`, enforced before result packaging;
|
|
95
97
|
- inline answer cap: `48 KiB`.
|
|
96
98
|
|
|
97
|
-
Launch admission measures the child system prompt plus the
|
|
99
|
+
Launch admission measures the child system prompt plus the exact child prompt carrying the seed. Backed large prompts use the shared family calibration; prompts or routes below the calibration domain and unknown/unbacked routes use the provable `1.00 B/token` profile. `budget-plan.json` v3 also records the provable conservative counter-forecast, protected finalization reserve, and retained-growth budget.
|
|
100
|
+
|
|
101
|
+
After launch, token measurements are advisory. Fusion BUG-185 proved that a package-local estimate must not reject a live provider payload after subtracting hypothetical output. Delegate therefore does not self-report provider exhaustion from that estimate. Pi and the provider own live context handling; a genuine provider context error remains loud. Package-owned growth is controlled before transcript entry: a tool result spills whenever it exceeds the per-result cap **or** retaining it would consume protected final-answer runway. Conservative false positives therefore create explicit hash receipts rather than failed tasks. Near the end of the runway the child disables tools and injects one finalization instruction so it can answer from evidence already gathered.
|
|
98
102
|
|
|
99
103
|
## Child guard and commit discipline
|
|
100
104
|
|
|
101
105
|
The child verifies seed hash, task id, and launch nonce at extension load before the first model call. It then enforces:
|
|
102
106
|
|
|
103
|
-
- context
|
|
104
|
-
- per-result spill receipts before tool output enters the transcript;
|
|
105
|
-
-
|
|
107
|
+
- advisory retained-context measurement before every provider call, without a BUG-185-style token abort;
|
|
108
|
+
- route-runway-aware and per-result spill receipts before tool output enters the transcript, including structured preservation of image-bearing results;
|
|
109
|
+
- bounded artifact range reads returned as lossless base64 against remaining inline runway;
|
|
110
|
+
- aggregate raw tool-output cap;
|
|
111
|
+
- protected no-tool finalization when retained-growth runway becomes low;
|
|
106
112
|
- turn and tool-call limits;
|
|
107
113
|
- route attestation for assistant messages;
|
|
108
|
-
-
|
|
114
|
+
- per-turn usage accumulation across the full agent loop; if any turn is missing/partial, aggregate usage is `unavailable` rather than understated or replaced by a later record;
|
|
109
115
|
- accepted final stop reason `stop` only, so provider `length` stops become `child_model_output_limit` rather than partial success;
|
|
116
|
+
- answer capture from only the final clean-stop assistant message, never intermediate tool-use narration;
|
|
110
117
|
- non-empty, non-whitespace answer text;
|
|
111
|
-
-
|
|
118
|
+
- the declared answer capture cap, with no partial result on overflow;
|
|
119
|
+
- well-formed UTF-8 answer blocks;
|
|
120
|
+
- durable `runtime-budget.json` evidence containing context measurements, retained/spilled bytes, finalization state, first-request observed usage, and calibration-underforecast evidence.
|
|
112
121
|
|
|
113
122
|
A terminal latch prevents later success commit after any degraded/refused condition. This avoids a hash-valid result built on silently modified context.
|
|
114
123
|
|
|
115
124
|
`result.json` is the single answer data plane. It is child-written by temp file, file fsync, and rename; POSIX then fsyncs the parent directory, while Windows skips directory fsync because Node does not provide the same portable guarantee there. Final-name presence is the child commit point. No final `result.json` means no accepted answer, regardless of process exit code. `child-terminal.json` records child-side terminal failures when no success package is committed.
|
|
116
125
|
|
|
117
|
-
After adjudication, the parent makes a best-effort durable write of `outcome.json`. This is separate from `result.json` so child and parent cannot race over one state field. An `outcome.json` write failure is currently ignored and does not change the returned adjudication, so the artifact may be absent even though evaluation completed. Child stdout/stderr are
|
|
126
|
+
After adjudication, the parent makes a best-effort durable write of `outcome.json`. This is separate from `result.json` so child and parent cannot race over one state field. An `outcome.json` write failure is currently ignored and does not change the returned adjudication, so the artifact may be absent even though evaluation completed. Child stdout/stderr are captured in the background task output file. Delegate-local `child.stdout.txt` and `child.stderr.txt` are not currently populated, and terminal reporting now lists only diagnostic paths that actually exist.
|
|
118
127
|
|
|
119
128
|
## Spill artifacts and `delegate_read_artifact`
|
|
120
129
|
|
|
121
|
-
Oversized tool results are durably written in full under `spill/` and replaced with receipts. A failed spill withholds the original payload and latches a terminal failure; no uncommitted artifact is claimed by receipt.
|
|
130
|
+
Oversized tool results are durably written in full under `spill/` and replaced with receipts. A single text block is stored as exact UTF-8; malformed lone-surrogate text is rejected rather than silently converted to U+FFFD. Multi-block or image-bearing content is stored in a closed JSON envelope that preserves block boundaries, MIME types, text, and complete base64 image data. New receipts record `content_format`; historical v1 receipts without that optional field remain readable. A failed spill withholds the original payload and latches a terminal failure; no uncommitted artifact is claimed by receipt.
|
|
122
131
|
|
|
123
132
|
`delegate_read_artifact` requires:
|
|
124
133
|
|
|
@@ -126,7 +135,7 @@ Oversized tool results are durably written in full under `spill/` and replaced w
|
|
|
126
135
|
- `offset: non-negative safe integer`;
|
|
127
136
|
- `length: positive safe integer`.
|
|
128
137
|
|
|
129
|
-
It reads the whole artifact file, verifies the requested range is in bounds, and returns
|
|
138
|
+
It reads the whole artifact file, verifies the requested range is in bounds, and returns the exact bytes as base64 plus offset/length metadata. Arbitrary ranges are never decoded as UTF-8, so a range that splits a multibyte sequence remains byte-exact rather than becoming U+FFFD. Path escape and short reads fail loudly.
|
|
130
139
|
|
|
131
140
|
## Retrieval contract
|
|
132
141
|
|
|
@@ -163,7 +172,7 @@ Launch / execution:
|
|
|
163
172
|
|
|
164
173
|
Budget / limits:
|
|
165
174
|
|
|
166
|
-
- `provider_context_budget_exhausted`
|
|
175
|
+
- `provider_context_budget_exhausted` (legacy terminal records only; current children do not infer provider exhaustion from an advisory estimate)
|
|
167
176
|
- `aggregate_tool_output_cap`
|
|
168
177
|
- `child_model_output_limit`
|
|
169
178
|
- `child_capture_limit`
|
|
@@ -12,14 +12,14 @@ 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.4.0`
|
|
16
16
|
- Governed markdown docs: 42
|
|
17
17
|
- Public surfaces extracted: 31
|
|
18
18
|
- Governed production sources: 50
|
|
19
19
|
- Tool contracts extracted: 11
|
|
20
|
-
- Schema IDs extracted:
|
|
20
|
+
- Schema IDs extracted: 46
|
|
21
21
|
- Environment variable references extracted: 49
|
|
22
|
-
- Behavioral attestation receipts not passing:
|
|
22
|
+
- Behavioral attestation receipts not passing: 8
|
|
23
23
|
- Receipt store: `docs/attestations.json`
|
|
24
24
|
|
|
25
25
|
`npm run docs:verify` is read-only: it renders generated files twice in memory and compares them with committed bytes. `npm run docs:generate` is the only docs writer.
|
|
@@ -186,19 +186,24 @@ Budgets and limits:
|
|
|
186
186
|
- route capacity is the declared context window minus reserves: `16,384` output, `8,192` framing, `4,096` safety tokens;
|
|
187
187
|
- minimum usable input is `8,192` tokens;
|
|
188
188
|
- launch admission measures the child system prompt plus the exact child prompt bytes that carry the seed;
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
-
|
|
192
|
-
-
|
|
189
|
+
- backed large prompts use route-family calibration; the plan also records a provable `1.00 B/token` counter-forecast for every byte class, including multibyte input;
|
|
190
|
+
- `32,768` input tokens are protected for finalization, with an `8,192`-token low-runway trigger;
|
|
191
|
+
- runtime context estimates are advisory and never masquerade as provider context truth;
|
|
192
|
+
- tool results spill above `64 KiB` or earlier when retaining them would consume protected runway;
|
|
193
|
+
- artifact range reads are bounded by remaining inline runway;
|
|
194
|
+
- aggregate raw tool-output cap: `64 MiB`;
|
|
195
|
+
- answer capture cap: `4 MiB`, enforced without committing a prefix;
|
|
193
196
|
- timeout defaults to `1200s`.
|
|
194
197
|
|
|
195
|
-
|
|
198
|
+
When protected runway becomes low, the child disables tools and is instructed to answer immediately from evidence already gathered. Pi and the provider—not the package estimator—own final live context admission. A genuine provider context rejection remains a loud failure and is never retried on another route.
|
|
199
|
+
|
|
200
|
+
Artifacts are under `.pi/delegate/<session-id>-<pid>/<task-id>/` and include `seed.json`, `child-prompt.txt`, `context-omission-ledger.json`, `budget-plan.json`, `manifest.json`, `child-session/`, `spill/`, `runtime-budget.json`, and later `result.json` / `outcome.json` when produced. Child stdout/stderr are captured through the background task output path; terminal failures report that real merged output path when it exists and do not claim absent delegate-local stream files.
|
|
196
201
|
|
|
197
202
|
## Spilled tool output
|
|
198
203
|
|
|
199
|
-
Oversized child tool results are written in full to `spill/...` artifacts and replaced in the transcript by receipts carrying path, byte length, SHA-256, tool name, call id, turn sequence, and source call index. The raw oversized payload is not forwarded as a fallback and is not truncated.
|
|
204
|
+
Oversized child tool results are written in full to `spill/...` artifacts and replaced in the transcript by receipts carrying path, byte length, SHA-256, content format, tool name, call id, turn sequence, and source call index. Single text blocks retain their exact UTF-8 bytes; malformed lone-surrogate text fails loudly instead of being substituted. Multi-block and image-bearing results use a structured JSON envelope preserving text, block boundaries, MIME type, and complete base64 image data. The raw oversized payload is not forwarded as a fallback and is not truncated.
|
|
200
205
|
|
|
201
|
-
Inside the child, `delegate_read_artifact({artifact, offset, length})` reads an exact byte range. It refuses path escape, negative/non-integer offsets, non-positive lengths, and reads past EOF rather than returning a short/clamped range.
|
|
206
|
+
Inside the child, `delegate_read_artifact({artifact, offset, length})` reads an exact byte range and returns those bytes as base64. It refuses path escape, negative/non-integer offsets, non-positive lengths, and reads past EOF rather than returning a short/clamped range. Base64 prevents a range that splits a UTF-8 sequence from being silently changed to replacement characters.
|
|
202
207
|
|
|
203
208
|
## Completion
|
|
204
209
|
|
package/docs/tools/bg_result.md
CHANGED
|
@@ -11,7 +11,7 @@ covers_sources: []
|
|
|
11
11
|
|
|
12
12
|
<!-- pi-docs:begin name="tool-contract-bg_result" generator="scripts/docs/generate.mjs" -->
|
|
13
13
|
- Label: **Background Result**
|
|
14
|
-
- Source: `src/delegate-extension.ts:
|
|
14
|
+
- Source: `src/delegate-extension.ts:516`
|
|
15
15
|
- Description: Retrieve a hash-verified result from a bg_delegate or background Fusion task. Never blocks: a running task returns a typed not-ready result. Oversized answers are never truncated.
|
|
16
16
|
- Root schema: `object`; additionalProperties: `false`
|
|
17
17
|
|
|
@@ -124,7 +124,7 @@ Common delegate retrieval outcomes:
|
|
|
124
124
|
- `result_too_large_for_inline` — explicit inline request exceeded the inline cap.
|
|
125
125
|
- Fusion `summary_status:"integrity_failed"` — a terminal summary or its manifest binding failed verification; no summary metadata is trusted.
|
|
126
126
|
|
|
127
|
-
Delegate errors include whether a child process was created, preserved artifact hints when
|
|
127
|
+
Delegate errors include whether a child process was created, preserved artifact hints that are checked for existence, the real merged task output path when available, and remediation text. Usage missing from the provider is reported as `unavailable`, not synthesized as zero. Fusion retrieval additionally fails on non-completed manifests, identity/schema drift, malformed usage/details, invalid UTF-8, or any manifest/result/merged hash or byte-length mismatch; failed/cancelled runs return their preserved terminal error rather than partial output.
|
|
128
128
|
|
|
129
129
|
## Parent outcome separation
|
|
130
130
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-background-tasks",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.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",
|
|
@@ -45,7 +45,11 @@ export const TOKEN_BUDGET_SEGMENT_KINDS = [
|
|
|
45
45
|
] as const;
|
|
46
46
|
export type TokenBudgetSegmentKind = (typeof TOKEN_BUDGET_SEGMENT_KINDS)[number];
|
|
47
47
|
|
|
48
|
-
export type TokenBudgetEstimatorScope =
|
|
48
|
+
export type TokenBudgetEstimatorScope =
|
|
49
|
+
| 'fusion'
|
|
50
|
+
| 'delegate_launch'
|
|
51
|
+
| 'delegate'
|
|
52
|
+
| 'conservative';
|
|
49
53
|
export type TokenBudgetDominantByteClass =
|
|
50
54
|
| 'normal'
|
|
51
55
|
| 'dense_ascii'
|
|
@@ -526,7 +530,7 @@ function rateSourceWarning(input: {
|
|
|
526
530
|
return `model is not in the exact calibration backing set for family ${input.family}; using the provable 1.00 B/tok floor`;
|
|
527
531
|
}
|
|
528
532
|
if (input.source === 'delegate_conservative') {
|
|
529
|
-
return 'delegate
|
|
533
|
+
return 'delegate launch/runtime uses the provable 1.00 B/tok profile when the prompt or route is below the backed large-prompt calibration domain';
|
|
530
534
|
}
|
|
531
535
|
if (input.source === 'explicit_conservative') {
|
|
532
536
|
return 'explicit conservative scope uses the provable 1.00 B/tok profile';
|
|
@@ -569,7 +573,16 @@ function effectiveRateSource(input: {
|
|
|
569
573
|
? 'unbacked_model_floor'
|
|
570
574
|
: 'unknown_provider_floor';
|
|
571
575
|
effective = TOKEN_BUDGET_PROVABLE_RATE_X100;
|
|
572
|
-
} else if (
|
|
576
|
+
} else if (
|
|
577
|
+
input.scope === 'delegate' ||
|
|
578
|
+
(input.scope === 'delegate_launch' &&
|
|
579
|
+
(input.profile.concrete_known_bytes < TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES ||
|
|
580
|
+
(input.allowedInputTokens !== undefined &&
|
|
581
|
+
Math.floor(
|
|
582
|
+
(input.allowedInputTokens * TOKEN_BUDGET_DELEGATE_CONSERVATIVE_RATE_X100) /
|
|
583
|
+
TOKEN_BUDGET_RATE_SCALE,
|
|
584
|
+
) < TOKEN_BUDGET_LARGE_PROMPT_MIN_BYTES)))
|
|
585
|
+
) {
|
|
573
586
|
source = 'delegate_conservative';
|
|
574
587
|
effective = Math.min(configured, TOKEN_BUDGET_DELEGATE_CONSERVATIVE_RATE_X100);
|
|
575
588
|
} else if (input.scope === 'conservative') {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync } from 'node:fs';
|
|
2
3
|
import { chmod, mkdir, open, readFile, rename, rm } from 'node:fs/promises';
|
|
3
4
|
import { basename, isAbsolute, join, relative, sep } from 'node:path';
|
|
4
5
|
import { canonicalJson } from '../attested-pi-run.js';
|
|
@@ -45,8 +46,7 @@ export const DELEGATE_ARTIFACT_NAMES = {
|
|
|
45
46
|
outcome: 'outcome.json',
|
|
46
47
|
result: DELEGATE_RESULT_PACKAGE_FILENAME,
|
|
47
48
|
childPrompt: 'child-prompt.txt',
|
|
48
|
-
|
|
49
|
-
childStdout: 'child.stdout.txt',
|
|
49
|
+
runtimeBudget: 'runtime-budget.json',
|
|
50
50
|
error: 'error.json',
|
|
51
51
|
} as const;
|
|
52
52
|
|
|
@@ -232,11 +232,6 @@ export class DelegateArtifactStore {
|
|
|
232
232
|
return this.write(DELEGATE_ARTIFACT_NAMES.budgetPlan, `${canonicalJson(plan)}\n`);
|
|
233
233
|
}
|
|
234
234
|
|
|
235
|
-
async writeChildStreams(stdout: Buffer, stderr: Buffer): Promise<void> {
|
|
236
|
-
await this.write(DELEGATE_ARTIFACT_NAMES.childStdout, stdout);
|
|
237
|
-
await this.write(DELEGATE_ARTIFACT_NAMES.childStderr, stderr);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
235
|
/** Commit the run. The rename performed here is the single success point. */
|
|
241
236
|
async commitResult(pkg: DelegateResultPackageV1): Promise<DelegateArtifactRef> {
|
|
242
237
|
const ref = await this.write(
|
|
@@ -251,17 +246,23 @@ export class DelegateArtifactStore {
|
|
|
251
246
|
try {
|
|
252
247
|
return await readFile(this.resultPathAbs, 'utf8');
|
|
253
248
|
} catch (error) {
|
|
249
|
+
const diagnosticNames = [
|
|
250
|
+
DELEGATE_ARTIFACT_NAMES.error,
|
|
251
|
+
DELEGATE_ARTIFACT_NAMES.outcome,
|
|
252
|
+
DELEGATE_ARTIFACT_NAMES.runtimeBudget,
|
|
253
|
+
DELEGATE_ARTIFACT_NAMES.manifest,
|
|
254
|
+
].filter((name) => existsSync(join(this.rootAbs, name)));
|
|
254
255
|
throw new DelegateError(
|
|
255
|
-
`delegate result package
|
|
256
|
+
`delegate result package could not be read at ${join(this.rootDisplay, DELEGATE_ARTIFACT_NAMES.result)}; no committed answer is available (${error instanceof Error ? error.message : String(error)})`,
|
|
256
257
|
{
|
|
257
258
|
code: 'result_unavailable',
|
|
258
259
|
childCreated: true,
|
|
259
260
|
taskId: this.manifest.task_id,
|
|
260
261
|
artifactDir: this.rootDisplay,
|
|
261
|
-
preserved:
|
|
262
|
-
remediation:
|
|
263
|
-
'
|
|
264
|
-
|
|
262
|
+
preserved: diagnosticNames,
|
|
263
|
+
remediation: diagnosticNames.length === 0
|
|
264
|
+
? ['No diagnostic control artifact exists; inspect the background task merged output if one was created.']
|
|
265
|
+
: [`Inspect the existing delegate control artifacts: ${diagnosticNames.join(', ')}.`],
|
|
265
266
|
},
|
|
266
267
|
);
|
|
267
268
|
}
|
|
@@ -353,6 +354,7 @@ export class DelegateArtifactStore {
|
|
|
353
354
|
source_call_index: input.sourceCallIndex,
|
|
354
355
|
byte_length: input.payload.length,
|
|
355
356
|
sha256: sha256Bytes(input.payload),
|
|
357
|
+
content_format: 'opaque_bytes',
|
|
356
358
|
};
|
|
357
359
|
}
|
|
358
360
|
|