pi-background-tasks 0.9.0 → 1.0.4
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/BACKGROUND-TASKS-INSTRUCTIONS.md +63 -0
- package/PUBLISHING.md +43 -29
- package/README.md +233 -441
- package/TESTING.md +16 -10
- package/TEST_PLAN.md +43 -17
- package/docs/INDEX.md +157 -0
- package/docs/api/eventbus-v1.md +166 -0
- package/docs/assets/architecture.svg +78 -0
- package/docs/assets/footer-dock.svg +47 -0
- package/docs/assets/logo.svg +49 -0
- package/docs/attestations.json +189 -0
- package/docs/choose-a-workflow.md +98 -0
- package/docs/commands/bg-clear.md +70 -0
- package/docs/commands/bg-update.md +82 -0
- package/docs/commands/bg.md +90 -0
- package/docs/commands/fusion-models.md +70 -0
- package/docs/commands/fusion.md +69 -0
- package/docs/commands/jobs.md +74 -0
- package/docs/commands/kill.md +82 -0
- package/docs/commands/logs.md +90 -0
- package/docs/commands/task-manager.md +109 -0
- package/docs/concepts/completion-delivery.md +66 -0
- package/docs/concepts/context-projection-and-budgeting.md +79 -0
- package/docs/getting-started.md +122 -0
- package/docs/manifest.json +1825 -0
- package/docs/operations/configuration.md +110 -0
- package/docs/operations/releasing.md +67 -0
- package/docs/operations/testing.md +101 -0
- package/docs/operations/troubleshooting.md +38 -0
- package/docs/read-before-edit.md +94 -0
- package/docs/reference/runtime-contracts.md +213 -0
- package/docs/reference/shortcuts-and-dock.md +70 -0
- package/docs/subsystems/attested-pi-runs.md +141 -0
- package/docs/subsystems/background-task-runtime.md +85 -0
- package/docs/subsystems/child-launch-durability-and-safety.md +57 -0
- package/docs/subsystems/delegation.md +190 -0
- package/docs/subsystems/docs-freshness-gate.md +26 -0
- package/docs/subsystems/fusion.md +123 -0
- package/docs/subsystems/host-ui-and-telemetry.md +83 -0
- package/docs/tools/bg_delegate.md +193 -0
- package/docs/tools/bg_kill.md +114 -0
- package/docs/tools/bg_logs.md +133 -0
- package/docs/tools/bg_result.md +120 -0
- package/docs/tools/bg_run.md +168 -0
- package/docs/tools/bg_run_pi_attested.md +170 -0
- package/docs/tools/bg_status.md +111 -0
- package/docs/tools/fusion_investigate.md +116 -0
- package/docs/tools/fusion_reason.md +75 -0
- package/docs/tools/fusion_research.md +162 -0
- package/docs/tools/fusion_validate.md +206 -0
- package/logo.png +0 -0
- package/package.json +27 -9
- package/src/core/delegate/budget.ts +1 -1
- package/src/core/delegate/launch.ts +5 -0
- package/src/core/fusion/artifacts.ts +34 -4
- package/src/core/fusion/budget.ts +112 -20
- package/src/core/fusion/child-protocol.ts +82 -0
- package/src/core/fusion/clean-context.ts +91 -0
- package/src/core/fusion/config.ts +124 -35
- package/src/core/fusion/context.ts +29 -7
- package/src/core/fusion/evaluation.ts +392 -15
- package/src/core/fusion/orchestrator.ts +217 -23
- package/src/core/fusion/pi-child.ts +227 -24
- package/src/core/fusion/prompts.ts +39 -26
- package/src/core/fusion/source-policy.ts +257 -0
- package/src/core/fusion/types.ts +156 -11
- package/src/core/fusion/web-fetch.ts +104 -15
- package/src/core/fusion/workflows.ts +119 -65
- package/src/extension.ts +3 -3
- package/src/fusion-child-extension.ts +375 -141
- package/src/fusion-extension.ts +585 -240
- package/src/testing/normalize.ts +0 -22
package/README.md
CHANGED
|
@@ -1,533 +1,325 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
Claude-Code-like explicit background shell task manager for [Pi](https://pi.dev/).
|
|
4
|
-
|
|
5
|
-
This package adds named, tracked background shell jobs with durable output files, bounded log reads, kill/timeout safety, task-owned context-window/token/tool-use/model telemetry, explicit Pi-agent telemetry wrapping for tasks marked as agents, a focused footer-dock task manager, `/tasks` fallback UI, and completion notifications that can wake the agent when LLM-launched work finishes. It also ships Fusion: a direct child-Pi five-call synthesis workflow exposed as `/fusion`, `/fusion-models`, and the always-active `fusion_brainstorm` and `fusion_validate` tools. A terminal task status is published only after trailing wrapped-agent telemetry is consumed and final output plus terminal metadata have completed their durability writes.
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
From npm after publish:
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
pi install npm:pi-background-tasks@0.9.0
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
From git after pushing this package to its standalone repository and tagging:
|
|
16
|
-
|
|
17
|
-
```bash
|
|
18
|
-
pi install git:github.com/ismailsaleekh/pi-background-tasks@v0.9.0
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
For project-local install:
|
|
22
|
-
|
|
23
|
-
```bash
|
|
24
|
-
pi install -l npm:pi-background-tasks@0.9.0
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
## Commands
|
|
28
|
-
|
|
29
|
-
- `/bg [--agent] [--name "Task name"] <command>` — start a named tracked background shell command. Use `--agent` only when the command launches an LLM/agent.
|
|
30
|
-
- `/jobs` — list running and recent completed/failed/killed tasks.
|
|
31
|
-
- `/logs <id> [maxBytes]` — show bounded tail output and full output path.
|
|
32
|
-
- `/kill <id>` — stop a running task.
|
|
33
|
-
- `/tasks` or `/bg-tasks` — fallback command to open the task manager UI.
|
|
34
|
-
- `/bg-clear` — clear finished background-task footer notices.
|
|
35
|
-
- `/bg-update` — print update instructions when a newer published version exists (instruct-only; never self-installs).
|
|
36
|
-
- `/fusion <prompt>` — run three candidate child Pi final-text calls, one blind evaluator, and one merger, then append the merged answer directly as a visible `fusion-result` custom message without asking the parent model to rewrite it. Running `/fusion` without arguments opens a multiline editor in UI-capable modes; cancelling the editor does not spawn children.
|
|
37
|
-
- `/fusion-models` — TUI-only five-slot global model selector (`Candidate 1`, `Candidate 2`, `Candidate 3`, `Evaluator`, `Merger`). It supports duplicate selections, `$current` defaults, slash-containing model ids, atomic saves to `fusion-models.json`, and rejects non-TUI modes immediately.
|
|
38
|
-
|
|
39
|
-
## Footer dock UX
|
|
40
|
-
|
|
41
|
-
When tasks are active or unseen completions/failures exist, Pi shows a compact footer status:
|
|
42
|
-
|
|
43
|
-
```text
|
|
44
|
-
bg 2 running · Shift↓
|
|
45
|
-
bg 1 running · 1 failed · Shift↓ · /bg-clear
|
|
46
|
-
bg 2 done · Shift↓ · /bg-clear
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
Press `Shift+Down` to open the focused bottom dock. Arrow keys are captured only while the dock is focused. Each task row shows the latest context-window usage reported by that specific background task, for example `ctx 21.0%/200k`; tasks that do not report their own context show `ctx —` rather than the parent Pi session's usage. Background Pi-agent tasks also surface the LLM model they ran (`model gpt-5.5` in the compact row, fully-qualified such as `openai-codex/gpt-5.5` in the detail view), cumulative token usage (`tok 1.6k`), and tool-use counts (`tools 2/1 failed`) in the dock and detail view; missing model/token/tool telemetry is omitted in rows and shown as “not reported by this background task” in details. When a background command is explicitly marked as an agent and invokes a print/json child agent such as `pi -p ...` through the normal shell command name, the extension wraps that child Pi process with `--mode json`, parses real assistant usage/tool execution events, and emits task-owned telemetry automatically — including the model reported by the child assistant turns.
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="logo.png" alt="pi-background-tasks logo: a futuristic dispatcher coordinating parallel work nodes into a completed result" width="144" height="144">
|
|
50
3
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
For those wrapped background Pi agents, the task output file and the dock's detail **Output tail** show a live, human-readable transcript of what the agent is actually doing — assistant messages, `→ tool args` calls, `… reasoning`, and `✗ tool failed` errors — as the agent loop runs. The machine telemetry (context/token/tool/model) is parsed out of the child stream and surfaced only as the metrics above and in `bg_status`/metadata, so the focused window reflects the agent's real activity rather than its raw instrumentation JSON. Child stderr is passed through to the transcript verbatim. Non-agent tasks and agent commands that cannot be wrapped (for example a path-qualified `pi`) keep streaming their raw stdout/stderr unchanged.
|
|
54
|
-
|
|
55
|
-
Finished-task badges intentionally remain visible until acknowledged. The reliable clear path is `/bg-clear`, which works in every terminal and clears finished background-task footer notices without opening the dock. `Ctrl+Alt+C` is still registered as an optional terminal-dependent fallback shortcut, but the footer advertises `/bg-clear` because some macOS terminals do not transmit `Ctrl+Alt+C` distinctly.
|
|
56
|
-
|
|
57
|
-
Dock controls:
|
|
58
|
-
|
|
59
|
-
| Key | Action |
|
|
60
|
-
|---|---|
|
|
61
|
-
| `Shift+Down` | Open focused background-task dock |
|
|
62
|
-
| `/bg-clear` | Clear finished-task footer notices from the main UI |
|
|
63
|
-
| `Ctrl+Alt+C` | Optional terminal-dependent shortcut for `/bg-clear` |
|
|
64
|
-
| `↑` / `↓` | Select task (list) · scroll the output tail (detail) |
|
|
65
|
-
| `PageUp` / `PageDown` | Page the task list (list) · page the output tail (detail) |
|
|
66
|
-
| `Enter` / `→` | Inspect logs/details |
|
|
67
|
-
| `←` | Return from details to list |
|
|
68
|
-
| `h` | Toggle recent history |
|
|
69
|
-
| `k` | Stop selected running task |
|
|
70
|
-
| `a` / `K` | Stop all running tasks, with confirmation |
|
|
71
|
-
| `r` | Refresh detail tail |
|
|
72
|
-
| `R` | Rerun selected command |
|
|
73
|
-
| `c` | Show copyable output path |
|
|
74
|
-
| `x` / `Esc` / `q` | Close dock |
|
|
75
|
-
| `/bg-update` | Print update instructions when a newer version is published |
|
|
4
|
+
# pi-background-tasks
|
|
76
5
|
|
|
77
|
-
|
|
6
|
+
**Keep Pi moving while long jobs, delegated investigations, and fixed-purpose multi-model Fusion work run in the background.**
|
|
78
7
|
|
|
79
|
-
|
|
8
|
+
[](https://www.npmjs.com/package/pi-background-tasks)
|
|
9
|
+
[](https://github.com/earendil-works/pi-coding-agent)
|
|
10
|
+
[](package.json)
|
|
11
|
+
[](LICENSE)
|
|
80
12
|
|
|
81
|
-
|
|
13
|
+
</div>
|
|
82
14
|
|
|
83
|
-
|
|
84
|
-
bg 1 running · 1 failed · Shift↓ · /bg-clear · ⬆ v0.7.0 /bg-update
|
|
85
|
-
```
|
|
15
|
+
`pi-background-tasks` adds background jobs, delegated agents, and multi-model Fusion for Pi:
|
|
86
16
|
|
|
87
|
-
|
|
17
|
+
- **Run long work without blocking**: start named shell jobs, keep talking to Pi, and get durable completion notifications when they finish.
|
|
18
|
+
- **Delegate context-aware investigation**: launch one route-pinned, inspect-only child Pi agent seeded with a frozen projection of the current conversation, then retrieve a hash-verified result.
|
|
19
|
+
- **Combine model perspectives through fixed-purpose Fusion**: run three candidate children, blind evaluation, optional bounded evaluator repair, and merger for reasoning, investigation, targeted URL research, or validation review.
|
|
88
20
|
|
|
89
|
-
|
|
21
|
+
<p align="center">
|
|
22
|
+
<img src="docs/assets/architecture.svg" alt="Architecture diagram showing Pi session, background task registry, delegated child agent, and Fusion candidate/evaluator/merger flow" width="760">
|
|
23
|
+
</p>
|
|
90
24
|
|
|
91
|
-
|
|
25
|
+
<!-- pi-docs:begin name="readme-package-facts" generator="scripts/docs/generate.mjs" -->
|
|
26
|
+
| Fact | Value |
|
|
27
|
+
| --- | --- |
|
|
28
|
+
| Package | `pi-background-tasks` |
|
|
29
|
+
| Version | `1.0.4` |
|
|
30
|
+
| Node engine | `>=22.19.0` |
|
|
31
|
+
| Pi entrypoint | `./extensions/background-tasks.ts` |
|
|
32
|
+
| Package image | [logo.png](https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png) |
|
|
33
|
+
<!-- pi-docs:end name="readme-package-facts" -->
|
|
92
34
|
|
|
93
|
-
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
35
|
+
<!-- pi-docs:begin name="readme-public-surfaces" generator="scripts/docs/generate.mjs" -->
|
|
36
|
+
| Surface kind | Count |
|
|
37
|
+
| --- | --- |
|
|
38
|
+
| command | 10 |
|
|
39
|
+
| tool | 11 |
|
|
40
|
+
| shortcut | 2 |
|
|
41
|
+
| renderer | 2 |
|
|
42
|
+
| eventbus | 1 |
|
|
43
|
+
| workflow | 4 |
|
|
102
44
|
|
|
103
|
-
|
|
45
|
+
Public commands: `/bg`, `/bg-clear`, `/bg-tasks`, `/bg-update`, `/fusion`, `/fusion-models`, `/jobs`, `/kill`, `/logs`, `/tasks`.
|
|
104
46
|
|
|
105
|
-
|
|
47
|
+
Public tools: `bg_delegate`, `bg_kill`, `bg_logs`, `bg_result`, `bg_run`, `bg_run_pi_attested`, `bg_status`, `fusion_investigate`, `fusion_reason`, `fusion_research`, `fusion_validate`.
|
|
106
48
|
|
|
107
|
-
|
|
49
|
+
Full owner map and generated contracts live in [docs/INDEX.md](docs/INDEX.md).
|
|
50
|
+
<!-- pi-docs:end name="readme-public-surfaces" -->
|
|
108
51
|
|
|
109
52
|
|
|
110
|
-
## Delegated background agents
|
|
111
53
|
|
|
112
|
-
`bg_delegate` fills the gap between `bg_run` (a background agent with a **fresh,
|
|
113
|
-
empty** context) and `fusion_brainstorm` (your current context, but synchronous
|
|
114
|
-
and five-model). It is one agent, one prompt, seeded with the current session's
|
|
115
|
-
context, non-blocking. `bg_result` retrieves its answer safely. They ship
|
|
116
|
-
together: a delegate without a safe retrieval path could not return its work.
|
|
117
54
|
|
|
118
|
-
|
|
119
|
-
bg_delegate({ name, prompt }) → launch receipt, immediately
|
|
120
|
-
… the parent keeps working; the terminal notification wakes it …
|
|
121
|
-
bg_result({ taskId }) → hash-verified answer
|
|
122
|
-
```
|
|
55
|
+
## Why use it?
|
|
123
56
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
The child does **not** share the parent's live session. The parent conversation
|
|
127
|
-
is projected with the same frozen `visible-conversation-ledger-v2` transform
|
|
128
|
-
Fusion uses (see [Conversation context policy](#conversation-context-policy)),
|
|
129
|
-
frozen as an immutable seed, and the child is given its **own** `--session-id`
|
|
130
|
-
and a task-owned `--session-dir`. Conceptually it has your context; physically it
|
|
131
|
-
can never open or mutate the parent session.
|
|
132
|
-
|
|
133
|
-
| Content | Disposition |
|
|
57
|
+
| You want to... | Use this package because... |
|
|
134
58
|
|---|---|
|
|
135
|
-
|
|
|
136
|
-
|
|
|
137
|
-
|
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
| Tool-result payloads | excluded; recorded as a hash-accounted omission receipt |
|
|
141
|
-
| The in-flight `bg_delegate` call and its sibling calls | scope-excluded from the branch |
|
|
142
|
-
|
|
143
|
-
The assistant message carrying the in-flight call is excluded as a whole, so when
|
|
144
|
-
several `bg_delegate` calls share one assistant message **every** sibling call is
|
|
145
|
-
excluded for **every** child: two delegates launched together receive identical
|
|
146
|
-
projected history and neither can observe the other's arguments.
|
|
147
|
-
|
|
148
|
-
The seed is canonical-JSON, SHA-256'd, and persisted. The persisted bytes are the
|
|
149
|
-
exact bytes the child reads, and the child re-verifies that hash **before its
|
|
150
|
-
first model call**. Repeated construction from the same session is
|
|
151
|
-
byte-identical.
|
|
152
|
-
|
|
153
|
-
**Documented limitation:** facts that exist only inside omitted parent tool
|
|
154
|
-
output are **not** available to the child. The child is told this explicitly and
|
|
155
|
-
instructed to say so plainly rather than guess. Restate any such finding in the
|
|
156
|
-
`prompt`.
|
|
157
|
-
|
|
158
|
-
### Route pinning
|
|
159
|
-
|
|
160
|
-
The route is pinned at launch — by default the parent's current effective
|
|
161
|
-
provider/model, or an explicit `route {provider, model}`. It is **never**
|
|
162
|
-
substituted, never falls back, and is never retried on a different route. An
|
|
163
|
-
unavailable route or one with no declared context window is a typed refusal
|
|
164
|
-
before anything is created. The child additionally asserts that every assistant
|
|
165
|
-
message it produced came from the pinned route; a mismatch prevents the run from
|
|
166
|
-
committing an answer at all.
|
|
167
|
-
|
|
168
|
-
### Inspect-only capability boundary
|
|
169
|
-
|
|
170
|
-
v1 supports exactly one capability, `inspect`. The child is launched with
|
|
171
|
-
`--tools read,grep,find,ls,delegate_read_artifact`, `--no-builtin-tools`, an
|
|
172
|
-
explicit `--exclude-tools` denylist, and no ambient extensions, skills, prompt
|
|
173
|
-
templates, themes, or context files. **The boundary is enforced by argv and the
|
|
174
|
-
child's tool registry, not by prompt text.** There is no shell, no network, no
|
|
175
|
-
edit/write, no recursive delegation, and no Fusion from the child. Writable
|
|
176
|
-
profiles are deliberately out of scope.
|
|
177
|
-
|
|
178
|
-
### Budgets, spilling, and limits
|
|
179
|
-
|
|
180
|
-
Admission is checked **before** the child process, the child session, or the
|
|
181
|
-
artifact directory exists, so a refusal leaves **zero** children and **zero**
|
|
182
|
-
artifacts. Inside the child, every model call is measured before dispatch; a call
|
|
183
|
-
that would exceed the pinned route's allowance is refused and the run terminates
|
|
184
|
-
with a typed `provider_context_budget_exhausted`.
|
|
185
|
-
|
|
186
|
-
A tool result larger than the per-result transcript cap is written **in full** to
|
|
187
|
-
a hashed artifact and replaced in the transcript by an explicit receipt naming
|
|
188
|
-
the artifact, its exact byte count, its SHA-256, and how to read a bounded range.
|
|
189
|
-
The raw payload never enters the transcript and **nothing is truncated**. The
|
|
190
|
-
bounded `delegate_read_artifact` tool returns exactly the requested range or
|
|
191
|
-
fails; a request past end-of-file is refused rather than silently shortened.
|
|
192
|
-
Turn, tool-call, aggregate-output, and wall-clock limits are enforced and
|
|
193
|
-
reported.
|
|
194
|
-
|
|
195
|
-
### Retrieving the answer
|
|
196
|
-
|
|
197
|
-
The child commits exactly one self-contained result package by temp-write,
|
|
198
|
-
`fsync`, rename, directory `fsync`. **The rename is the commit point**: a package
|
|
199
|
-
present under its final name is complete, and its absence means no answer was
|
|
200
|
-
accepted — whatever the process exit code was. A child that exits `0` without
|
|
201
|
-
committing is a typed `child_exited_without_commit`, never a silent empty
|
|
202
|
-
success. A run that degraded anything latches terminal state and **cannot**
|
|
203
|
-
commit a success package, so a hash-valid answer can never be built on silently
|
|
204
|
-
mutilated context.
|
|
205
|
-
|
|
206
|
-
`bg_result` verifies the package identity, seed hash, route, every per-block
|
|
207
|
-
SHA-256, and the aggregate SHA-256 before returning a single byte, and returns
|
|
208
|
-
bytes from the buffer it verified. A running task returns a typed *not ready*
|
|
209
|
-
result and **never blocks or polls**. An answer over the inline cap degrades to
|
|
210
|
-
an artifact reference **explicitly**; requesting `delivery:"inline"` for it is a
|
|
211
|
-
typed `result_too_large_for_inline` failure naming the artifact. It is **never**
|
|
212
|
-
truncated to fit. `autoDeliver` (`never` | `when_small` | `always`) defaults to
|
|
213
|
-
`never`: completion notifications carry metadata, and the answer is fetched
|
|
214
|
-
deliberately with `bg_result`.
|
|
215
|
-
|
|
216
|
-
### Failure taxonomy
|
|
217
|
-
|
|
218
|
-
Every delegate failure is typed and states what happened, what was preserved, and
|
|
219
|
-
what the operator can do. Admission codes
|
|
220
|
-
(`delegate_hook_contract_unsupported`, `delegate_isolation_unsupported`,
|
|
221
|
-
`route_unresolved`, `route_capacity_unknown`, `seed_projection_failed`,
|
|
222
|
-
`seed_budget_exceeded`, `seed_persist_failed`, `invalid_arguments`) always report
|
|
223
|
-
`childCreated: false`. Execution and integrity codes include `child_spawn_failed`,
|
|
224
|
-
`child_timeout`, `child_cancelled`, `child_turn_limit`, `child_tool_call_limit`,
|
|
225
|
-
`child_exited_without_commit`, `provider_context_budget_exhausted`,
|
|
226
|
-
`aggregate_tool_output_cap`, `child_result_invalid`,
|
|
227
|
-
`child_result_encoding_invalid`, `route_attestation_missing`, `route_mismatch`,
|
|
228
|
-
`seed_hash_mismatch`, `answer_hash_mismatch`, `artifact_spill_failed`, and
|
|
229
|
-
`artifact_read_failed`. Retrieval states are `result_not_ready`,
|
|
230
|
-
`result_unavailable`, `result_too_large_for_inline`, and `task_unknown`.
|
|
231
|
-
|
|
232
|
-
Usage that the provider did not report is recorded as explicitly `unavailable`,
|
|
233
|
-
never as zero.
|
|
234
|
-
|
|
235
|
-
### Proven Pi hook contract
|
|
236
|
-
|
|
237
|
-
The child-side guard depends on runtime Pi behaviour, which is **proven by
|
|
238
|
-
execution** rather than read from type declarations. The
|
|
239
|
-
`npm run test:hook-contract` gate drives a real Pi agent loop and records what it
|
|
240
|
-
observed. On Pi 0.83 it establishes that `context` fires once before every model
|
|
241
|
-
call in extension load order and that returned messages reach the provider; that
|
|
242
|
-
**throwing** from a `context` handler does **not** block the call (Pi catches it
|
|
243
|
-
and dispatches anyway); that `ctx.abort()` does not skip the provider call site
|
|
244
|
-
but hands it an already-aborted signal and terminates the run; and that
|
|
245
|
-
`tool_result` fires before the result enters the transcript, chains in load order,
|
|
246
|
-
and preserves tool-call id, role, and error flag across replacement.
|
|
247
|
-
|
|
248
|
-
Because neither a throw nor an abort is a hard admission gate on its own, the
|
|
249
|
-
guard uses abort as the barrier **and** removes the oversized content from the
|
|
250
|
-
outgoing message set, so the request cannot carry it even if a provider ignored
|
|
251
|
-
the aborted signal. If a Pi build cannot provide the required guarantees,
|
|
252
|
-
`bg_delegate` refuses to spawn with a typed
|
|
253
|
-
`delegate_hook_contract_unsupported`; the guard is never weakened to fit.
|
|
254
|
-
|
|
255
|
-
Delegate artifacts are written under:
|
|
256
|
-
|
|
257
|
-
```text
|
|
258
|
-
.pi/delegate/<session-id>-<pid>/<task-id>/
|
|
259
|
-
```
|
|
59
|
+
| Start a dev server, watch build, migration dry run, or long check | `bg_run` and `/bg` return immediately, write durable output files, show a footer dock, and notify on terminal state. |
|
|
60
|
+
| Let Pi keep working instead of sleeping or polling | Default `bg_run` completion delivery sends a durable terminal notification and can wake a follow-up turn. |
|
|
61
|
+
| Ask a second agent to inspect the repo with the current conversation as context | `bg_delegate` starts one isolated child with read/search/list tools only; `bg_result` verifies the committed result before returning it. |
|
|
62
|
+
| Compare model perspectives without exposing arbitrary parent context | Fusion children receive only the workflow input and fixed tool policy; no silent route substitution or fallback is used on delegate/Fusion paths. |
|
|
63
|
+
| Produce local evidence for a direct Pi run | `bg_run_pi_attested` records local same-user-writable artifacts and hashes after a successful structured child Pi task. |
|
|
260
64
|
|
|
261
|
-
|
|
262
|
-
child over stdin, never a shell or positional argument),
|
|
263
|
-
`context-omission-ledger.json`, `budget-plan.json`, `manifest.json`, the
|
|
264
|
-
task-owned `child-session/`, any `spill/` artifacts, `result.json` once the child
|
|
265
|
-
commits, and `outcome.json` once the parent adjudicates the run.
|
|
65
|
+
## Install
|
|
266
66
|
|
|
267
|
-
`
|
|
268
|
-
neither writer can claim a state it did not observe. `manifest.state` records only
|
|
269
|
-
what the parent knew at launch and is never used to decide success.
|
|
67
|
+
Version information comes from [`package.json`](package.json). Use npm `@latest` for normal installs; use git `main` only when you intentionally want the current repository state.
|
|
270
68
|
|
|
271
|
-
|
|
69
|
+
```bash
|
|
70
|
+
# Global install from npm
|
|
71
|
+
pi install npm:pi-background-tasks@latest
|
|
272
72
|
|
|
273
|
-
|
|
73
|
+
# Project-local install from npm
|
|
74
|
+
pi install npm:pi-background-tasks@latest -l
|
|
274
75
|
|
|
275
|
-
|
|
76
|
+
# Git main branch; not a release tag
|
|
77
|
+
pi install git:github.com/ismailsaleekh/pi-background-tasks@main
|
|
276
78
|
|
|
277
|
-
|
|
79
|
+
# Project-local git main install
|
|
80
|
+
pi install git:github.com/ismailsaleekh/pi-background-tasks@main -l
|
|
278
81
|
|
|
279
|
-
|
|
280
|
-
|
|
82
|
+
# Local checkout/package path, run from this package directory
|
|
83
|
+
pi install .
|
|
84
|
+
pi install . -l
|
|
281
85
|
```
|
|
282
86
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
`fusion_validate` is the same orchestrator, artifact store, budget engine, conversation projection, and evaluation schema as `fusion_brainstorm`, with different stage framing. A workflow profile selects the four system prompts and the capability policy; it never changes the canonical input schema, which remains `pi-background-tasks.fusion-input.v4` for both tools. Canonical input bytes and the omission ledger are provably identical across workflows for the same conversation, and that equality is asserted by the golden-bytes gate rather than assumed.
|
|
87
|
+
Local paths are loaded from disk without copying; use the path to this package from your current directory.
|
|
286
88
|
|
|
287
|
-
|
|
288
|
-
|---|---|---|
|
|
289
|
-
| Parameters | `{prompt, capability?}` | `{prompt}` — capability rejected |
|
|
290
|
-
| Candidate capability | caller-selected, default `reason` | always `inspect` |
|
|
291
|
-
| Evaluator / merger capability | `reason` by stage policy | `reason` by stage policy |
|
|
292
|
-
| Run id prefix | `f` | `v` |
|
|
293
|
-
| Output | prose answer | prose review |
|
|
294
|
-
| Evaluation schema | `fusion-evaluation.v1` | `fusion-evaluation.v1` (identical) |
|
|
89
|
+
## Quick start: useful in under five minutes
|
|
295
90
|
|
|
296
|
-
|
|
91
|
+
1. Install and start Pi in a project.
|
|
92
|
+
2. Launch a background command:
|
|
297
93
|
|
|
298
|
-
|
|
94
|
+
```text
|
|
95
|
+
/bg --name "Typecheck watch" npm run typecheck -- --watch
|
|
96
|
+
```
|
|
299
97
|
|
|
300
|
-
`
|
|
98
|
+
`/bg` starts a tracked shell task and returns the task id plus output path. User-launched `/bg` tasks notify in the UI but do not automatically wake a follow-up model turn.
|
|
301
99
|
|
|
302
|
-
|
|
100
|
+
3. Open the footer dock with **Shift↓** or list tasks:
|
|
303
101
|
|
|
304
|
-
|
|
102
|
+
```text
|
|
103
|
+
/jobs
|
|
104
|
+
```
|
|
305
105
|
|
|
306
|
-
|
|
106
|
+
4. Read bounded output only when you need it:
|
|
307
107
|
|
|
308
|
-
|
|
108
|
+
```text
|
|
109
|
+
/logs b12ab34c 20000
|
|
110
|
+
```
|
|
309
111
|
|
|
310
|
-
|
|
112
|
+
5. Let a child agent inspect while you continue:
|
|
311
113
|
|
|
312
|
-
|
|
114
|
+
```json
|
|
115
|
+
{"name":"Config reader","prompt":"Inspect the repository configuration files and report where background task settings are documented. Include file paths and quote only the relevant lines.","capability":"inspect"}
|
|
116
|
+
```
|
|
313
117
|
|
|
314
|
-
|
|
118
|
+
Call this with `bg_delegate`. When its terminal notification arrives, retrieve the answer deliberately:
|
|
315
119
|
|
|
316
|
-
|
|
120
|
+
```json
|
|
121
|
+
{"taskId":"<task id from bg_delegate>","delivery":"inline"}
|
|
122
|
+
```
|
|
317
123
|
|
|
318
|
-
|
|
124
|
+
Call this with `bg_result`. Retrieval is hash-verified and never silently truncated.
|
|
319
125
|
|
|
320
|
-
|
|
126
|
+
6. For a self-contained synthesis, ask Fusion:
|
|
321
127
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
| Schemes | `http:` and `https:` only |
|
|
326
|
-
| Timeout | 60 seconds |
|
|
327
|
-
| Response body cap | 2 MiB |
|
|
328
|
-
| Returned content cap | 32 KiB |
|
|
329
|
-
| Redirect cap | 5 hops |
|
|
128
|
+
```json
|
|
129
|
+
{"prompt":"Compare the tradeoffs between a watcher, a one-shot build, and a delegated repo inspection for a large refactor."}
|
|
130
|
+
```
|
|
330
131
|
|
|
331
|
-
|
|
132
|
+
Call this with `fusion_reason`, or use `/fusion <prompt>` interactively.
|
|
332
133
|
|
|
333
|
-
|
|
134
|
+
More walkthrough detail: [Getting started](docs/getting-started.md).
|
|
334
135
|
|
|
335
|
-
|
|
136
|
+
## Pick the right workflow
|
|
336
137
|
|
|
337
|
-
|
|
138
|
+
| Workflow | Blocking? | Context | Tools/network/write boundary | Best for | Expected behavior |
|
|
139
|
+
|---|---:|---|---|---|---|
|
|
140
|
+
| Ordinary foreground Pi work | Yes | Full current session | Whatever tools the active session has | Short reads/edits/commands where you want live back-and-forth | Pi waits for the work before responding. |
|
|
141
|
+
| `/bg` | No | No model child unless your command starts one | Runs your shell command; **not sandboxed** | User-started local commands, servers, watches | UI notification and footer tracking; `/bg` uses notification-only by default. |
|
|
142
|
+
| `bg_run` | No | No model child unless command starts one | Runs your shell command; **not sandboxed** | Agent-started long commands | Returns task id/output path; defaults to notification plus automatic follow-up wake. |
|
|
143
|
+
| `bg_delegate` + `bg_result` | No launch; retrieval is point-in-time | Frozen visible conversation projection | Inspect-only child: read, grep, find, ls, artifact read; no shell, writes, network, recursion | Context-aware read-only investigation while parent continues | Launch returns immediately; result is committed by child and hash-verified by retrieval. |
|
|
144
|
+
| `bg_run_pi_attested` | No | Prompt passed to one direct child Pi run | Direct `pi --mode json`; no shell command; writes requested report path | Evidence-oriented direct Pi task | Emits local attestation sidecar only after successful completion. |
|
|
145
|
+
| `/fusion` / `fusion_reason` | Synchronous | Versioned conversation projection plus prompt | Candidates/evaluator/repair/merger run with no tools | Self-contained reasoning and synthesis | Three candidates → blind evaluator → optional bounded repair if evaluator JSON is invalid → merger. |
|
|
146
|
+
| `fusion_investigate` | Synchronous | Clean task input only | Candidate read-only repo tools; evaluator/repair/merger no tools | Independent repo investigation | Restate all needed facts in fields; parent hidden/tool context is not visible. |
|
|
147
|
+
| `fusion_research` | Synchronous | Clean task input only | Candidate read-only repo tools plus targeted fetch of caller-supplied public URLs only | URL-backed synthesis | Targeted URL retrieval, **not web search**. |
|
|
148
|
+
| `fusion_validate` | Synchronous | Clean task input only | Advisory read-only validation review | Second-opinion review of completed work | Not a replacement for tests, builds, linters, security scans, or human review. |
|
|
338
149
|
|
|
339
|
-
|
|
150
|
+
See [Choose a workflow](docs/choose-a-workflow.md) for a decision tree and tradeoffs.
|
|
340
151
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
### Conversation context policy
|
|
344
|
-
|
|
345
|
-
Fusion children receive a **versioned conversation projection**, not a raw execution transcript. The canonical input schema is `pi-background-tasks.fusion-input.v4` and every run states exactly what was included and what was omitted.
|
|
346
|
-
|
|
347
|
-
The projection transform (`visible-conversation-ledger-v2`) is shared by both entry points:
|
|
348
|
-
|
|
349
|
-
| Content | Disposition |
|
|
350
|
-
|---|---|
|
|
351
|
-
| User text | included verbatim, never clipped |
|
|
352
|
-
| Assistant text | included verbatim, never clipped |
|
|
353
|
-
| User image blocks | `[Image omitted from fusion text transcript: <mime-type>]` marker |
|
|
354
|
-
| Assistant thinking | excluded; recorded as an omission receipt |
|
|
355
|
-
| Tool-call arguments | excluded; recorded as an omission receipt |
|
|
356
|
-
| Tool-result payloads | excluded; recorded as an omission receipt |
|
|
357
|
-
| Tool-result images | excluded; recorded as an omission receipt (never raw bytes) |
|
|
358
|
-
| Active `fusion_brainstorm` call and its sibling calls | scope-excluded from the branch |
|
|
152
|
+
## Copy-paste examples
|
|
359
153
|
|
|
360
|
-
|
|
154
|
+
### `bg_run`: start long shell work
|
|
361
155
|
|
|
362
156
|
```json
|
|
363
|
-
|
|
364
|
-
|
|
157
|
+
{
|
|
158
|
+
"name": "Docs preview",
|
|
159
|
+
"command": "npm run docs:dev",
|
|
160
|
+
"isAgent": false,
|
|
161
|
+
"timeoutSeconds": 3600
|
|
162
|
+
}
|
|
365
163
|
```
|
|
366
164
|
|
|
367
|
-
|
|
165
|
+
Expected: returns immediately with a task id, PID when available, and `.pi/tasks/...output`. The command runs as an ordinary local shell command with your user permissions; it can invoke networked tools or paid services if the command itself does so.
|
|
368
166
|
|
|
369
|
-
|
|
167
|
+
### `bg_delegate`: context-seeded read-only investigation
|
|
370
168
|
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
Every prompt-expansion stage — candidate, evaluator, evaluation repair, and merger — is size-checked **before any child process is created**, and each stage is checked against **its own configured route**, so a large-context slot cannot hide a small-context sibling and a small slot cannot veto stages it never serves.
|
|
381
|
-
|
|
382
|
-
Input forecasting uses the shared affine estimator `estimateInputTokens({family, segments})`: additive integer byte-class accounting plus a 512-token affine intercept. Calibrated normal-ASCII rates are used only for backed exact model IDs, measured prompts at or above 50 KiB, and prompts that pass the low-whitespace dense-ASCII gate. That gate records the measured whitespace fraction in `budget-plan.json` and falls back conservatively for out-of-distribution near-zero-whitespace payloads; it is a heuristic token-density proxy, not a bound. Multibyte UTF-8 uses the conservative 2.0 B/tok fatal rate while persisting the provable 1.00 B/tok ceiling as advisory. The calibration basis is 882 real large Fusion prompts: Anthropic observed floor 2.047 B/tok (shipped `r=1.73`) and Codex observed floor 3.400 B/tok (shipped `r=2.89`); unknown providers and unbacked model IDs use the unbacked 1.00 B/tok floor and are surfaced in artifacts and result details.
|
|
383
|
-
|
|
384
|
-
Each stage is forecast with its **real prompt builder**, rendered with empty embedded-output slots, plus the enforced output contracts for whatever that stage will embed:
|
|
385
|
-
|
|
386
|
-
| Stage | Embeds | Mandatory |
|
|
387
|
-
|---|---|---|
|
|
388
|
-
| `candidate` | canonical input only | yes, once per slot |
|
|
389
|
-
| `evaluation` | + 3 candidate answers | yes |
|
|
390
|
-
| `evaluation_repair` | + 3 candidates, invalid evaluator output, diagnostics | conditional, still budgeted |
|
|
391
|
-
| `merge` | + 3 candidates, validated evaluation | yes |
|
|
392
|
-
|
|
393
|
-
`evaluation_repair` only runs when the evaluator returns schema-invalid JSON, but it is budgeted unconditionally: "uncommon" is not a reliability contract.
|
|
394
|
-
|
|
395
|
-
Output sizes are guaranteed by **enforced contracts**, not assumptions. Each stage has a maximum response size measured in *JSON-rendered transfer bytes* — the bytes the response actually costs once a later stage embeds it, escaping included (candidate 48 KiB, evaluator 64 KiB, merger 64 KiB, repair diagnostics 8 KiB). Measuring the rendered form removes any escaping guess: quotes, backslashes, and newlines expand 2x and control characters up to 6x. A response over its contract is a loud `child_output_cap` failure; it is preserved in the run artifacts and is never sliced, truncated, or forwarded.
|
|
396
|
-
|
|
397
|
-
When a workflow cannot fit, the error names the **first failing mandatory stage** in deterministic order (candidate slots, then evaluation, then merge), lists every other blocking stage, and labels conditional ones. It never blames a stage that would have succeeded.
|
|
398
|
-
|
|
399
|
-
Remediation is derived, not guessed: Fusion re-plans the entire workflow **with the request removed**. If it still fails, the error says plainly that shortening the request cannot help and points at starting a fresh conversation or raising the route's context window. If it then fits, the request is what determines feasibility, and the error states the exact minimum byte reduction and the maximum safe request size.
|
|
400
|
-
|
|
401
|
-
Preflight is two-tiered: input-only forecasts are fatal (`prompt_budget_exceeded_forecast`), while worst-case downstream output reservations are warning-only and recorded in `budget-plan.json`. Exact rendered per-stage checks remain fatal (`prompt_budget_exceeded_measured`). Runs that fit still emit advisory warnings for tight utilization or reservation overage. The warning never alters behaviour.
|
|
402
|
-
|
|
403
|
-
Every configured route must also satisfy a documented minimum capacity; smaller routes are rejected at configuration time with an actionable error naming the requirement, rather than being accepted and failing later at the provider. All route capacities, per-stage forecasts, headroom, utilization, the byte composition of the blocking stage, and the blockers list are persisted as `budget-plan.json`.
|
|
404
|
-
|
|
405
|
-
If an input still exceeds the safe budget, Fusion fails with `prompt_budget_exceeded_forecast` for input-only preflight or `prompt_budget_exceeded_measured` for exact rendered prompts. The error names the stage, measured bytes, measured token upper bound, allowed tokens, the limiting configured model and its context window, estimator source, and concrete remediation. **Zero children are launched** when preflight rejects. Provider context-window failures remain loud child failures; there is no hidden local truncation and no silent fallback anywhere in this path.
|
|
406
|
-
|
|
407
|
-
## Extension EventBus API
|
|
408
|
-
|
|
409
|
-
Version `0.7.0` exposes a real extension-to-extension service over Pi's documented `pi.events` bus. This is not a `ctx` method and it does not call a second task manager: requests route to the same `BackgroundTaskRegistry` used by `bg_run`, `bg_status`, `bg_logs`, and `bg_kill`.
|
|
169
|
+
```json
|
|
170
|
+
{
|
|
171
|
+
"name": "Route audit",
|
|
172
|
+
"prompt": "Inspect the package source and identify where delegate route pinning is enforced. Return file paths, function names, and a short explanation. If a fact exists only in omitted parent tool output, say it is unavailable rather than guessing.",
|
|
173
|
+
"capability": "inspect",
|
|
174
|
+
"autoDeliver": "never"
|
|
175
|
+
}
|
|
176
|
+
```
|
|
410
177
|
|
|
411
|
-
|
|
178
|
+
Then retrieve:
|
|
412
179
|
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
| Response schema | `pi-background-tasks.extension-response.v1` |
|
|
420
|
-
| Terminal schema | `pi-background-tasks.extension-terminal.v1` |
|
|
180
|
+
```json
|
|
181
|
+
{
|
|
182
|
+
"taskId": "<delegate task id>",
|
|
183
|
+
"delivery": "inline"
|
|
184
|
+
}
|
|
185
|
+
```
|
|
421
186
|
|
|
422
|
-
|
|
187
|
+
Expected: `bg_delegate` returns a launch receipt immediately. `bg_result` returns a typed not-ready result while running; after commit it verifies package identity, seed hash, route, block hashes, and aggregate hash before returning bytes. Oversized answers become explicit artifact references, not truncated inline text.
|
|
423
188
|
|
|
424
|
-
`
|
|
189
|
+
### `bg_run_pi_attested`: local evidence for one Pi child
|
|
425
190
|
|
|
426
191
|
```json
|
|
427
|
-
{
|
|
192
|
+
{
|
|
193
|
+
"name": "Migration report",
|
|
194
|
+
"provider": "openai-codex",
|
|
195
|
+
"model": "gpt-5.5",
|
|
196
|
+
"prompt": "Inspect the repository and write a concise migration report to reports/migration.md.",
|
|
197
|
+
"reportPath": "reports/migration.md",
|
|
198
|
+
"timeoutSeconds": 1800
|
|
199
|
+
}
|
|
428
200
|
```
|
|
429
201
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
Terminal events keep the strict paired-consumer frame `{ schema_version: "pi-background-tasks.extension-terminal.v1", task }`. They are correlated by `task.id`, published exactly once per task after final output and terminal metadata durability, and for EventBus `run`/`kill` requests they are held behind a response barrier so even an immediately exiting or immediately killed child cannot emit its terminal event until the correlated response has been delivered and one microtask turn has allowed consumers to bind the returned task id. Terminal EventBus delivery exceptions are logged loudly and retried; a task is marked terminal-published only after the EventBus emit returns successfully.
|
|
202
|
+
Expected: launches exactly one direct `pi --mode json` child using structured provider/model fields. It rejects direct API-key/auth-file launch arguments and only writes the attestation sidecar after successful completion and durable hashes. The attestation is local evidence, not cryptographic proof against a compromised machine or provider.
|
|
433
203
|
|
|
434
|
-
|
|
204
|
+
### Fusion tools
|
|
435
205
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
```text
|
|
439
|
-
.pi/tasks/<session-id>-<pid>/<task-id>.output
|
|
440
|
-
.pi/tasks/<session-id>-<pid>/<task-id>.json
|
|
206
|
+
```json
|
|
207
|
+
{"prompt":"Design a rollback strategy for a risky database migration. Include assumptions and failure modes."}
|
|
441
208
|
```
|
|
442
209
|
|
|
443
|
-
|
|
210
|
+
Use with `fusion_reason` for self-contained synthesis.
|
|
444
211
|
|
|
445
|
-
```
|
|
446
|
-
|
|
212
|
+
```json
|
|
213
|
+
{
|
|
214
|
+
"objective": "Find how background task output is capped and surfaced.",
|
|
215
|
+
"background": ["We are evaluating pi-background-tasks behavior for long-running commands."],
|
|
216
|
+
"deliverable": "File paths, constants, defaults, and user-visible behavior.",
|
|
217
|
+
"scope": ["src"],
|
|
218
|
+
"constraints": ["Read-only inspection only."]
|
|
219
|
+
}
|
|
447
220
|
```
|
|
448
221
|
|
|
449
|
-
|
|
222
|
+
Use with `fusion_investigate`.
|
|
450
223
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
.
|
|
455
|
-
.
|
|
456
|
-
|
|
457
|
-
.
|
|
224
|
+
```json
|
|
225
|
+
{
|
|
226
|
+
"objective": "Summarize the installation syntax Pi documents for packages.",
|
|
227
|
+
"background": ["We need package README install examples to match Pi package docs."],
|
|
228
|
+
"deliverable": "A short summary with caveats.",
|
|
229
|
+
"sources": [
|
|
230
|
+
{"url":"https://github.com/earendil-works/pi-coding-agent","purpose":"Pi package documentation repository"}
|
|
231
|
+
]
|
|
232
|
+
}
|
|
458
233
|
```
|
|
459
234
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
## Durability model
|
|
463
|
-
|
|
464
|
-
All task metadata, task output/events/stderr, attestation sidecars, Fusion artifacts, and the global `fusion-models.json` are written through one shared primitive in `src/core/durable-fs.ts`.
|
|
465
|
-
|
|
466
|
-
The invariant is: **open the file once with write intent, write and `fsync` through that same writable handle, then close.** A pathname is never reopened merely to flush it. This is required for Windows correctness — `FlushFileBuffers` needs a handle with write access, so flushing through a reopened read-only handle fails with `EPERM: operation not permitted, fsync` and previously broke every background task on Windows.
|
|
467
|
-
|
|
468
|
-
Two write modes are provided:
|
|
235
|
+
Use with `fusion_research`. Only declared public `http(s)` URLs may be fetched; this is not a search tool.
|
|
469
236
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
237
|
+
```json
|
|
238
|
+
{
|
|
239
|
+
"objective": "Review whether a documentation-only change is ready to ship.",
|
|
240
|
+
"background": ["The change edits README and package-local docs only."],
|
|
241
|
+
"changeSummary": "Replaced monolithic README with landing page and moved operational details into docs.",
|
|
242
|
+
"scope": ["README.md", "docs/getting-started.md", "docs/choose-a-workflow.md"],
|
|
243
|
+
"acceptanceCriteria": ["Install commands are accurate", "Safety limitations are explicit", "Examples match public schemas"],
|
|
244
|
+
"verification": {
|
|
245
|
+
"status": "provided",
|
|
246
|
+
"evidence": [{"check":"Focused link check", "outcome":"All local README links resolve"}]
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
```
|
|
478
250
|
|
|
479
|
-
|
|
251
|
+
Use with `fusion_validate` for advisory read-only review.
|
|
480
252
|
|
|
481
|
-
|
|
482
|
-
- Fusion inference is isolated to direct child `pi --mode text` invocations with tools/skills/session/context files disabled and only the package-owned compact metadata extension explicitly loaded; no direct completion API, API-key argument, or model fallback is used.
|
|
483
|
-
- Attested Pi tasks are a local, unsigned, same-user-writable attestation path for downstream gates. They bind source bytes and observed Pi/ModelRegistry facts; they are not cryptographic proof against a malicious local user, compromised Pi binary, or compromised provider.
|
|
484
|
-
- stdout/stderr are captured to task output files.
|
|
485
|
-
- Model-visible logs are bounded and point to full output files.
|
|
486
|
-
- POSIX process groups are used for process-tree kill where possible, with child-process fallback.
|
|
487
|
-
- On Windows, process-tree termination uses `%SystemRoot%\\System32\\taskkill.exe` directly (never `PATH`) with a two-stage `/T` then `/T /F` flow. Stage one is a logical Windows termination request, not SIGTERM and not a guaranteed graceful shutdown: console processes may ignore it, and re-parented descendants can escape the tree. Strong containment would require Windows Job Objects via a native component, which is out of scope.
|
|
488
|
-
- Running tasks are cleaned up on Pi session shutdown/reload.
|
|
489
|
-
- Child Pi processes are never launched through a shell. On Windows the npm `pi.cmd` shim is deliberately not executed, because a batch shim cannot preserve argument bytes safely; the package resolves the Pi package's own CLI entry and launches it with `process.execPath` instead. Batch, PowerShell, and extensionless launch targets are rejected loudly rather than executed, and a launch target resolving outside the Pi package root is rejected.
|
|
490
|
-
- Cross-Pi-restart process reattachment and Ctrl+B backgrounding of already-running foreground tools are intentionally out of scope.
|
|
253
|
+
## Footer dock
|
|
491
254
|
|
|
492
|
-
|
|
255
|
+
<p align="center">
|
|
256
|
+
<img src="docs/assets/footer-dock.svg" alt="Illustration of the pi-background-tasks footer dock with running and completed tasks" width="760">
|
|
257
|
+
</p>
|
|
493
258
|
|
|
494
|
-
|
|
259
|
+
When tasks are running or unseen completions exist, the footer shows a compact `bg ...` segment. Press **Shift↓** to open the focused bottom dock. Use `/bg-clear` to acknowledge finished-task footer notices in any terminal.
|
|
495
260
|
|
|
496
|
-
|
|
261
|
+
| Control | Action |
|
|
262
|
+
|---|---|
|
|
263
|
+
| `Shift↓` | Open the dock |
|
|
264
|
+
| `/bg-clear` | Clear finished-task notices |
|
|
265
|
+
| `↑` / `↓`, `PageUp` / `PageDown` | Move through list or scroll output tail |
|
|
266
|
+
| `Enter` / `→` | Inspect details |
|
|
267
|
+
| `←` | Return to list |
|
|
268
|
+
| `k` | Stop selected running task |
|
|
269
|
+
| `R` | Rerun selected command |
|
|
270
|
+
| `c` | Show copyable output path |
|
|
271
|
+
| `x` / `Esc` / `q` | Close dock |
|
|
497
272
|
|
|
498
|
-
|
|
273
|
+
Agent tasks launched through `pi -p ...` or `pi --mode json ...` and marked `isAgent:true` can show task-owned model/context/token/tool telemetry. Missing child telemetry is shown as unavailable, not synthesized as zero.
|
|
499
274
|
|
|
500
|
-
|
|
275
|
+
<a id="commands"></a>
|
|
276
|
+
<a id="footer-dock-ux"></a>
|
|
277
|
+
<a id="update-available-notice"></a>
|
|
278
|
+
<a id="llm-tools"></a>
|
|
279
|
+
<a id="delegated-background-agents"></a>
|
|
280
|
+
<a id="fusion-workflow"></a>
|
|
281
|
+
<a id="conversation-context-policy"></a>
|
|
282
|
+
<a id="extension-eventbus-api"></a>
|
|
283
|
+
<a id="runtime-files"></a>
|
|
284
|
+
<a id="durability-model"></a>
|
|
285
|
+
<a id="safety-model"></a>
|
|
286
|
+
<a id="windows-shell-and-telemetry"></a>
|
|
501
287
|
|
|
502
|
-
##
|
|
288
|
+
## Architecture, trust, and safety
|
|
503
289
|
|
|
504
|
-
|
|
290
|
+
- Runtime task files live under `.pi/tasks/<session-id>-<pid>/`; Fusion artifacts under `.pi/fusion/...`; delegate artifacts under `.pi/delegate/...`.
|
|
291
|
+
- Shell jobs are tracked by the package, but they are not sandboxed. Treat commands as local processes with your permissions and credentials.
|
|
292
|
+
- Delegate and Fusion child Pi processes are route-pinned where applicable; delegate/Fusion paths do not silently substitute routes.
|
|
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
|
+
- Fusion research fetches only caller-supplied public `http(s)` URLs with bounded retrieval. It is not web search and not a secret-exfiltration boundary.
|
|
295
|
+
- 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.
|
|
296
|
+
- 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.
|
|
505
297
|
|
|
506
|
-
|
|
507
|
-
npm run test
|
|
508
|
-
```
|
|
298
|
+
Detailed operations: [Configuration](docs/operations/configuration.md).
|
|
509
299
|
|
|
510
|
-
|
|
300
|
+
## EventBus and Autopilot integration
|
|
511
301
|
|
|
512
|
-
|
|
513
|
-
npm run smoke
|
|
514
|
-
npm run pack:dry-run
|
|
515
|
-
npm run test:compat
|
|
516
|
-
```
|
|
302
|
+
Other Pi extensions can control the same `BackgroundTaskRegistry` through Pi's `events` bus instead of shelling out or maintaining a second task manager. The public channels are:
|
|
517
303
|
|
|
518
|
-
|
|
304
|
+
| Purpose | Channel |
|
|
305
|
+
|---|---|
|
|
306
|
+
| Request | `pi-background-tasks:request:v1` |
|
|
307
|
+
| Response | `pi-background-tasks:response:v1` |
|
|
308
|
+
| Terminal task event | `pi-background-tasks:terminal:v1` |
|
|
519
309
|
|
|
520
|
-
|
|
521
|
-
npm run test:full
|
|
522
|
-
```
|
|
310
|
+
Operations are `capabilities`, `run`, `status`, `logs`, and `kill`. This is the integration point for orchestrators such as Autopilot that need non-blocking package-managed work with bounded logs and correlated terminal events. Consumers must deduplicate terminal frames by `task.id`: an EventBus listener failure can cause a retried publication.
|
|
523
311
|
|
|
524
|
-
|
|
312
|
+
## Documentation map
|
|
525
313
|
|
|
526
|
-
|
|
314
|
+
| Need | Read |
|
|
315
|
+
|---|---|
|
|
316
|
+
| First install and first task | [Getting started](docs/getting-started.md) |
|
|
317
|
+
| Which workflow/tool to choose | [Choose a workflow](docs/choose-a-workflow.md) |
|
|
318
|
+
| Environment variables, shells, output caps, model config, offline behavior | [Configuration](docs/operations/configuration.md) |
|
|
319
|
+
| Package QA expectations | [TESTING.md](TESTING.md) and [TEST_PLAN.md](TEST_PLAN.md) |
|
|
320
|
+
| Publishing notes | [PUBLISHING.md](PUBLISHING.md) |
|
|
321
|
+
| License | [LICENSE](LICENSE) |
|
|
527
322
|
|
|
528
|
-
|
|
323
|
+
## Contributing
|
|
529
324
|
|
|
530
|
-
-
|
|
531
|
-
- [`../EXTENSION_TESTING_PLAYBOOK.md`](../EXTENSION_TESTING_PLAYBOOK.md)
|
|
532
|
-
- [`TEST_PLAN.md`](TEST_PLAN.md)
|
|
533
|
-
- [`TESTING.md`](TESTING.md)
|
|
325
|
+
Keep user-facing claims tied to source. If you change public schemas, command behavior, durability, model routing, or environment variables, update these package-local docs in the same change and run focused checks appropriate to the edit.
|