pi-background-tasks 0.7.7 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/BACKGROUND-TASKS-INSTRUCTIONS.md +63 -0
  2. package/PUBLISHING.md +43 -29
  3. package/README.md +234 -385
  4. package/TESTING.md +15 -9
  5. package/TEST_PLAN.md +46 -13
  6. package/docs/INDEX.md +157 -0
  7. package/docs/api/eventbus-v1.md +166 -0
  8. package/docs/assets/architecture.svg +78 -0
  9. package/docs/assets/footer-dock.svg +47 -0
  10. package/docs/assets/logo.svg +49 -0
  11. package/docs/attestations.json +189 -0
  12. package/docs/choose-a-workflow.md +98 -0
  13. package/docs/commands/bg-clear.md +70 -0
  14. package/docs/commands/bg-update.md +82 -0
  15. package/docs/commands/bg.md +90 -0
  16. package/docs/commands/fusion-models.md +70 -0
  17. package/docs/commands/fusion.md +69 -0
  18. package/docs/commands/jobs.md +74 -0
  19. package/docs/commands/kill.md +82 -0
  20. package/docs/commands/logs.md +90 -0
  21. package/docs/commands/task-manager.md +109 -0
  22. package/docs/concepts/completion-delivery.md +66 -0
  23. package/docs/concepts/context-projection-and-budgeting.md +79 -0
  24. package/docs/getting-started.md +122 -0
  25. package/docs/manifest.json +1825 -0
  26. package/docs/operations/configuration.md +110 -0
  27. package/docs/operations/releasing.md +67 -0
  28. package/docs/operations/testing.md +101 -0
  29. package/docs/operations/troubleshooting.md +38 -0
  30. package/docs/read-before-edit.md +94 -0
  31. package/docs/reference/runtime-contracts.md +213 -0
  32. package/docs/reference/shortcuts-and-dock.md +70 -0
  33. package/docs/subsystems/attested-pi-runs.md +141 -0
  34. package/docs/subsystems/background-task-runtime.md +85 -0
  35. package/docs/subsystems/child-launch-durability-and-safety.md +57 -0
  36. package/docs/subsystems/delegation.md +190 -0
  37. package/docs/subsystems/docs-freshness-gate.md +26 -0
  38. package/docs/subsystems/fusion.md +121 -0
  39. package/docs/subsystems/host-ui-and-telemetry.md +83 -0
  40. package/docs/tools/bg_delegate.md +193 -0
  41. package/docs/tools/bg_kill.md +114 -0
  42. package/docs/tools/bg_logs.md +133 -0
  43. package/docs/tools/bg_result.md +120 -0
  44. package/docs/tools/bg_run.md +168 -0
  45. package/docs/tools/bg_run_pi_attested.md +170 -0
  46. package/docs/tools/bg_status.md +111 -0
  47. package/docs/tools/fusion_investigate.md +116 -0
  48. package/docs/tools/fusion_reason.md +75 -0
  49. package/docs/tools/fusion_research.md +162 -0
  50. package/docs/tools/fusion_validate.md +206 -0
  51. package/logo.png +0 -0
  52. package/package.json +29 -6
  53. package/src/core/delegate/budget.ts +1 -1
  54. package/src/core/delegate/launch.ts +6 -0
  55. package/src/core/fusion/artifacts.ts +80 -5
  56. package/src/core/fusion/budget.ts +129 -28
  57. package/src/core/fusion/child-protocol.ts +82 -0
  58. package/src/core/fusion/clean-context.ts +91 -0
  59. package/src/core/fusion/config.ts +124 -35
  60. package/src/core/fusion/context.ts +33 -6
  61. package/src/core/fusion/evaluation.ts +392 -15
  62. package/src/core/fusion/orchestrator.ts +274 -25
  63. package/src/core/fusion/pi-child.ts +635 -10
  64. package/src/core/fusion/prompts.ts +167 -6
  65. package/src/core/fusion/source-policy.ts +257 -0
  66. package/src/core/fusion/types.ts +232 -5
  67. package/src/core/fusion/web-fetch.ts +993 -0
  68. package/src/core/fusion/workflows.ts +184 -0
  69. package/src/extension.ts +3 -3
  70. package/src/fusion-child-extension.ts +370 -54
  71. package/src/fusion-extension.ts +625 -125
  72. package/src/testing/normalize.ts +0 -22
@@ -0,0 +1,120 @@
1
+ ---
2
+ doc_id: tools/bg_result
3
+ audience: agent
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: stable
7
+ covers_surfaces: [tool:bg_result]
8
+ covers_sources: []
9
+ ---
10
+ # `bg_result`
11
+
12
+ <!-- pi-docs:begin name="tool-contract-bg_result" generator="scripts/docs/generate.mjs" -->
13
+ - Label: **Delegate Result**
14
+ - Source: `src/delegate-extension.ts:428`
15
+ - Description: Retrieve the hash-verified answer from a bg_delegate task. Never blocks: a running task returns a typed not-ready result. A completed answer is verified against its recorded SHA-256 before it is returned, and an oversized answer is never truncated.
16
+ - Root schema: `object`; additionalProperties: `false`
17
+
18
+ | Field | Required | Type | Description | Constraints |
19
+ | --- | --- | --- | --- | --- |
20
+ | `delivery` | no | `string` | inline returns the verified answer text; artifact returns metadata plus the artifact reference. Oversized answers are never truncated. | |
21
+ | `taskId` | yes | `string` | Delegate task id returned by bg_delegate. | |
22
+
23
+ <details>
24
+ <summary>Normalized TypeBox contract</summary>
25
+
26
+
27
+ ```json
28
+ {
29
+ "additionalProperties": false,
30
+ "properties": {
31
+ "delivery": {
32
+ "description": "inline returns the verified answer text; artifact returns metadata plus the artifact reference. Oversized answers are never truncated.",
33
+ "type": "string"
34
+ },
35
+ "taskId": {
36
+ "description": "Delegate task id returned by bg_delegate.",
37
+ "type": "string"
38
+ }
39
+ },
40
+ "required": [
41
+ "taskId"
42
+ ],
43
+ "type": "object"
44
+ }
45
+ ```
46
+
47
+ </details>
48
+ <!-- pi-docs:end name="tool-contract-bg_result" -->
49
+
50
+ `bg_result` retrieves the result of a `bg_delegate` task. It never blocks: a running task returns a typed not-ready view, and a terminal task is verified before any answer bytes are returned.
51
+
52
+ ## Public arguments
53
+
54
+ Required:
55
+
56
+ - `taskId: string` — task id or unambiguous prefix resolved by the background-task registry. Must be non-empty after trimming.
57
+
58
+ Optional:
59
+
60
+ - `delivery: "inline" | "artifact"` — if omitted, answers at or below `48 KiB` are returned inline and larger answers are returned as an artifact reference. `artifact` always returns metadata/reference. `inline` for an oversized answer fails loudly.
61
+
62
+ The TypeBox schema is closed (`additionalProperties: false`).
63
+
64
+ ## Not-ready behavior
65
+
66
+ If the delegate task is still running, `bg_result` returns successfully with details:
67
+
68
+ - `schema_version: "pi-background-tasks.delegate-result-view.v1"`;
69
+ - `state: "running"`;
70
+ - `delivery: "none"`;
71
+ - artifact dir and budget facts when available.
72
+
73
+ This is not an error and does not wait. End the turn or do other independent work until the terminal notification arrives.
74
+
75
+ ## Verification before return
76
+
77
+ For terminal tasks, the parent evaluates the child artifacts. `result.json` is the child-written commit point. If it is absent, the task has no accepted answer even if the child exited `0`.
78
+
79
+ A present package is accepted only after verifying:
80
+
81
+ 1. JSON shape and schema version;
82
+ 2. `task_id` and `launch_nonce`;
83
+ 3. `seed_sha256`;
84
+ 4. route object and every route attestation against the pinned provider/model;
85
+ 5. answer encoding (`utf-8`);
86
+ 6. strict base64 for every answer block;
87
+ 7. every block byte length and SHA-256;
88
+ 8. aggregate answer byte length and SHA-256;
89
+ 9. well-formed UTF-8 round trip.
90
+
91
+ The returned text is decoded from the same aggregate buffer that was hashed. Corruption, stale packages, missing attestations, route drift, or invalid UTF-8 produce typed failures and no answer bytes.
92
+
93
+ ## Inline/artifact delivery and no truncation
94
+
95
+ `bg_result` never truncates an answer.
96
+
97
+ - Default delivery: inline when `answer.byte_length <= 48 KiB`, artifact reference otherwise.
98
+ - `delivery: "artifact"`: returns metadata and points to `.pi/delegate/.../result.json` even for small answers.
99
+ - `delivery: "inline"`: returns the full verified answer only if it fits the inline cap; otherwise fails with `result_too_large_for_inline` and names the preserved artifact.
100
+
101
+ Large answers remain complete in `result.json` as base64 blocks plus aggregate hash.
102
+
103
+ ## Failure classes users see
104
+
105
+ Common retrieval outcomes:
106
+
107
+ - `task_unknown` — unknown id/prefix or not a delegate task.
108
+ - `result_unavailable` / `child_exited_without_commit` — terminal task produced no committed result package.
109
+ - `child_cancelled`, `child_timeout`, `child_turn_limit`, `child_tool_call_limit` — child did not complete cleanly.
110
+ - `provider_context_budget_exhausted`, `aggregate_tool_output_cap`, `child_model_output_limit` — budget/limit refusal.
111
+ - `route_attestation_missing`, `route_mismatch` — route evidence missing or not the pinned route.
112
+ - `seed_hash_mismatch`, `answer_hash_mismatch`, `child_result_invalid`, `child_result_encoding_invalid` — integrity or encoding failure.
113
+ - `artifact_read_failed`, `artifact_spill_failed`, `artifact_error` — artifact I/O failure.
114
+ - `result_too_large_for_inline` — explicit inline request exceeded the inline cap.
115
+
116
+ Delegate errors include whether a child process was created, preserved artifact hints when known, and remediation text. Usage missing from the provider is reported as `unavailable`, not synthesized as zero.
117
+
118
+ ## Parent outcome separation
119
+
120
+ After evaluation, the parent attempts a durable `outcome.json` write separately from child-written `result.json`. This avoids either writer overwriting the other's evidence, but the write is best-effort: its failure is ignored and does not change the returned adjudication, so `outcome.json` may be absent.
@@ -0,0 +1,168 @@
1
+ ---
2
+ doc_id: tools/bg_run
3
+ audience: agent
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: stable
7
+ covers_surfaces: [tool:bg_run]
8
+ covers_sources: []
9
+ ---
10
+ # `bg_run`
11
+
12
+ <!-- pi-docs:begin name="tool-contract-bg_run" generator="scripts/docs/generate.mjs" -->
13
+ - Label: **Background Run**
14
+ - Source: `src/extension.ts:671`
15
+ - 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.
16
+ - Root schema: `object`
17
+
18
+ | Field | Required | Type | Description | Constraints |
19
+ | --- | --- | --- | --- | --- |
20
+ | `command` | yes | `string` | Shell command to start in the background | |
21
+ | `description` | no | `string` | Optional longer human-readable context for the task | |
22
+ | `isAgent` | yes | `boolean` | Required. Set true only when this background task launches an LLM/agent process, such as a child `pi -p ...` or `pi --mode json ...`, so Pi-agent telemetry can be collected. Set false for scripts, tests, servers, sleeps, and ordinary shell commands. | |
23
+ | `name` | yes | `string` | Short human-readable task name shown in the bg footer dock. Required; use 2-6 words, not the raw command. | |
24
+ | `notifyOnCompletion` | no | `boolean` | Whether to deliver the durable terminal notification. Default: true; disable only when deliberately taking over completion monitoring. | |
25
+ | `timeoutSeconds` | no | `number` | Optional timeout; task is failed and killed when exceeded | |
26
+ | `triggerOnCompletion` | no | `boolean` | Whether that notification should automatically trigger a follow-up agent turn. Default: true for bg_run; requires notifyOnCompletion. | |
27
+
28
+ <details>
29
+ <summary>Normalized TypeBox contract</summary>
30
+
31
+
32
+ ```json
33
+ {
34
+ "properties": {
35
+ "command": {
36
+ "description": "Shell command to start in the background",
37
+ "type": "string"
38
+ },
39
+ "description": {
40
+ "description": "Optional longer human-readable context for the task",
41
+ "type": "string"
42
+ },
43
+ "isAgent": {
44
+ "description": "Required. Set true only when this background task launches an LLM/agent process, such as a child `pi -p ...` or `pi --mode json ...`, so Pi-agent telemetry can be collected. Set false for scripts, tests, servers, sleeps, and ordinary shell commands.",
45
+ "type": "boolean"
46
+ },
47
+ "name": {
48
+ "description": "Short human-readable task name shown in the bg footer dock. Required; use 2-6 words, not the raw command.",
49
+ "type": "string"
50
+ },
51
+ "notifyOnCompletion": {
52
+ "description": "Whether to deliver the durable terminal notification. Default: true; disable only when deliberately taking over completion monitoring.",
53
+ "type": "boolean"
54
+ },
55
+ "timeoutSeconds": {
56
+ "description": "Optional timeout; task is failed and killed when exceeded",
57
+ "type": "number"
58
+ },
59
+ "triggerOnCompletion": {
60
+ "description": "Whether that notification should automatically trigger a follow-up agent turn. Default: true for bg_run; requires notifyOnCompletion.",
61
+ "type": "boolean"
62
+ }
63
+ },
64
+ "required": [
65
+ "command",
66
+ "isAgent",
67
+ "name"
68
+ ],
69
+ "type": "object"
70
+ }
71
+ ```
72
+
73
+ </details>
74
+ <!-- pi-docs:end name="tool-contract-bg_run" -->
75
+
76
+ Start a named long-running shell command in the background and return immediately.
77
+
78
+ ## Schema
79
+
80
+
81
+ Required public fields:
82
+
83
+ - `name: string` — concise 2-6 word task name for the footer dock.
84
+ - `command: string` — shell command to run.
85
+ - `isAgent: boolean` — explicit telemetry control; `true` only for LLM/agent processes such as child `pi -p ...` or `pi --mode json ...`.
86
+
87
+ Optional fields:
88
+
89
+ - `description: string`
90
+ - `timeoutSeconds: number`
91
+ - `notifyOnCompletion: boolean`
92
+ - `triggerOnCompletion: boolean`
93
+
94
+ Legacy argument preparation can derive a missing `name` from `description` or `command`, but the public schema remains strict and requires `name`, `command`, and `isAgent`.
95
+
96
+ ## When to use
97
+
98
+ Use for long-running tests, builds, servers, watchers, sleeps, and child agent work. Do not use normal foreground shell tools for commands expected to outlive the current turn.
99
+
100
+ ## Defaults
101
+
102
+ - `notifyOnCompletion`: `true`.
103
+ - `triggerOnCompletion`: `true`.
104
+ - `timeoutSeconds`: absent means no timeout.
105
+ - `isAgent`: no default in the tool contract; callers must provide a boolean. It is not inferred from command text.
106
+
107
+ ## Lifecycle
108
+
109
+ The tool returns a task id, current `running` status, pid if known, output path, and completion-delivery guidance. Terminal statuses are exactly `completed`, `failed`, or `killed`. With default delivery, terminal state is sent as `<background-task-notification>` and starts a follow-up agent turn; after launching, do not sleep or poll merely to wait.
110
+
111
+ ## Examples
112
+
113
+ ```json
114
+ {"name":"Docs build","command":"npm run docs","isAgent":false}
115
+ ```
116
+
117
+ ```json
118
+ {"name":"Child summary","command":"pi -p 'summarize changes'","isAgent":true,"timeoutSeconds":600}
119
+ ```
120
+
121
+ ```json
122
+ {"name":"Manual server","command":"npm run dev","isAgent":false,"notifyOnCompletion":false,"triggerOnCompletion":false}
123
+ ```
124
+
125
+ ## Output/result
126
+
127
+ Text result:
128
+
129
+ ```text
130
+ Started background task <name> (<id>)
131
+ Status: running
132
+ PID: <pid|unknown>
133
+ Output: .pi/tasks/.../<id>.output
134
+ Terminal notification: enabled.
135
+ Automatic follow-up turn: enabled.
136
+ ...
137
+ ```
138
+
139
+ Structured details include `task`, a snapshot with command, status, output path, cwd, timing, pid, byte count, `isAgent`, delivery flags, telemetry fields when available, and error when present.
140
+
141
+ ## Errors
142
+
143
+ - Missing/non-object args in preparation: `bg_run arguments must be an object`.
144
+ - Missing command: `bg_run requires command string`.
145
+ - Missing `isAgent`: loud error explaining true/false use.
146
+ - Empty command at execution: `Background command is empty`.
147
+ - Shell/spawn/timeout/output-cap failures become loud task failures.
148
+
149
+ ## Runtime artifacts
150
+
151
+ Creates `.pi/tasks/<session-id>-<pid>/<task-id>.output` and `.json`. If `isAgent:true` and the command matches an interceptable POSIX `pi -p`, `pi --print`, or `pi --mode json` invocation, a temporary telemetry wrapper file is also written in the task directory.
152
+
153
+ ## Safety boundaries
154
+
155
+ The command runs through the platform shell and is not sandboxed. Use `isAgent:true` only to request Pi-agent telemetry wrapping; setting it does not make execution safer. Model-visible logs are bounded and point to the full output path.
156
+
157
+ ## Related docs
158
+
159
+ - [Completion delivery](../concepts/completion-delivery.md)
160
+ - [`bg_status`](bg_status.md)
161
+ - [`bg_logs`](bg_logs.md)
162
+ - [`bg_kill`](bg_kill.md)
163
+ - [`/bg`](../commands/bg.md)
164
+ - [Background task runtime](../subsystems/background-task-runtime.md)
165
+
166
+ ## Source ownership/reference
167
+
168
+ Tool registration lives in `src/extension.ts`; runtime lifecycle is owned by [background-task-runtime](../subsystems/background-task-runtime.md).
@@ -0,0 +1,170 @@
1
+ ---
2
+ doc_id: tools/bg_run_pi_attested
3
+ audience: agent
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: stable
7
+ covers_surfaces: [tool:bg_run_pi_attested]
8
+ covers_sources: []
9
+ ---
10
+ # `bg_run_pi_attested`
11
+
12
+ <!-- pi-docs:begin name="tool-contract-bg_run_pi_attested" generator="scripts/docs/generate.mjs" -->
13
+ - Label: **Attested Pi Run**
14
+ - Source: `src/extension.ts:756`
15
+ - Description: Opt-in evidence-oriented direct Pi spawn. Launches exactly one `pi --mode json` child, records raw Pi events/stderr, hashes prompt/report/output, observes OAuth through ModelRegistry, and emits a strict attestation sidecar only after successful completion.
16
+ - Root schema: `object`
17
+
18
+ | Field | Required | Type | Description | Constraints |
19
+ | --- | --- | --- | --- | --- |
20
+ | `extraPiArgs` | no | `string[]` | | |
21
+ | `model` | yes | `string` | Exact provider-local Pi model id to launch. | |
22
+ | `name` | yes | `string` | Short human-readable name for this attested Pi task. | |
23
+ | `prompt` | yes | `string` | Prompt bytes passed as the single user prompt to Pi. | |
24
+ | `provider` | yes | `string` | Exact Pi provider to launch, for example openai-codex or anthropic. | |
25
+ | `reportPath` | yes | `string` | Relative path, inside the task cwd, that the child Pi run must write as its report. | |
26
+ | `thinking` | no | `string` | Optional Pi thinking level argument. | |
27
+ | `timeoutSeconds` | no | `number` | Optional timeout; task is failed and killed when exceeded | |
28
+
29
+ <details>
30
+ <summary>Normalized TypeBox contract</summary>
31
+
32
+
33
+ ```json
34
+ {
35
+ "properties": {
36
+ "extraPiArgs": {
37
+ "items": {
38
+ "description": "Additional literal Pi argv entries; mode/provider/model/api-key args are rejected.",
39
+ "type": "string"
40
+ },
41
+ "type": "array"
42
+ },
43
+ "model": {
44
+ "description": "Exact provider-local Pi model id to launch.",
45
+ "type": "string"
46
+ },
47
+ "name": {
48
+ "description": "Short human-readable name for this attested Pi task.",
49
+ "type": "string"
50
+ },
51
+ "prompt": {
52
+ "description": "Prompt bytes passed as the single user prompt to Pi.",
53
+ "type": "string"
54
+ },
55
+ "provider": {
56
+ "description": "Exact Pi provider to launch, for example openai-codex or anthropic.",
57
+ "type": "string"
58
+ },
59
+ "reportPath": {
60
+ "description": "Relative path, inside the task cwd, that the child Pi run must write as its report.",
61
+ "type": "string"
62
+ },
63
+ "thinking": {
64
+ "description": "Optional Pi thinking level argument.",
65
+ "type": "string"
66
+ },
67
+ "timeoutSeconds": {
68
+ "description": "Optional timeout; task is failed and killed when exceeded",
69
+ "type": "number"
70
+ }
71
+ },
72
+ "required": [
73
+ "model",
74
+ "name",
75
+ "prompt",
76
+ "provider",
77
+ "reportPath"
78
+ ],
79
+ "type": "object"
80
+ }
81
+ ```
82
+
83
+ </details>
84
+ <!-- pi-docs:end name="tool-contract-bg_run_pi_attested" -->
85
+
86
+ `bg_run_pi_attested` is an opt-in evidence-producing Pi run. It is separate from `bg_run`: it never accepts a shell command and launches exactly one direct child Pi invocation in JSON mode.
87
+
88
+ ## Public arguments
89
+
90
+ Required:
91
+
92
+ - `name: string` — concise task name; later validation rejects blank names.
93
+ - `provider: string` — exact Pi provider; later validation rejects blank provider.
94
+ - `model: string` — provider-local model id; later validation rejects blank model.
95
+ - `prompt: string` — prompt passed as the single Pi user prompt; empty string is rejected.
96
+ - `reportPath: string` — relative path inside task cwd that the child prompt/run is expected to write; blank, absolute, escaping, `.git/...`, and `.pi/tasks/...` targets are rejected.
97
+
98
+ Optional:
99
+
100
+ - `extraPiArgs: string[]` — literal extra Pi argv entries. Entries must be strings.
101
+ - `thinking: string` — structured Pi thinking level; if non-blank, emitted as `--thinking <value>`.
102
+ - `timeoutSeconds: number` — optional timeout; positive finite values are floored by the registry, non-positive/non-finite values are effectively not used as a timeout.
103
+
104
+ There are no provider/model/prompt defaults and no notification parameters on this tool. The registry creates attested tasks with background completion notification/wake disabled (`notifyOnCompletion:false`, `triggerOnCompletion:false`) while still publishing terminal snapshots through the task system. The current TypeBox declaration does not set `additionalProperties:false`; preparation reads only the fields above and validates their types.
105
+
106
+ Forbidden in `extraPiArgs`: `--api-key`, `--auth-file`, `-p`, `--print`, `--mode`, structured duplicates of `--provider`, `--model`, and `--thinking`.
107
+
108
+ ## Launch shape
109
+
110
+ The logical argv is:
111
+
112
+ ```text
113
+ pi --mode json --provider <provider> --model <model> [--thinking <thinking>] [...extraPiArgs] <prompt>
114
+ ```
115
+
116
+ The registry resolves the platform-specific Pi executable and spawns without a shell (`shell:false`). On POSIX this is normally the `pi` executable; on Windows the package may launch Pi through the resolved Node/CLI path while the attested logical argv remains `['pi', ...]`.
117
+
118
+ The child environment strips metered/direct API variables including OpenAI, Anthropic, OpenRouter, `PI_API_KEY`, base URL overrides, and `PI_AUTH_FILE`. Authentication is not accepted from tool arguments.
119
+
120
+ ## OAuth and route observation
121
+
122
+ Before spawn, the producer asks the model registry for the exact `provider/model` and requires `ModelRegistry.isUsingOAuth`. Supported observed OAuth classes are:
123
+
124
+ - `openai-codex` → `pi-codex-oauth`, channel `subscription-codex`;
125
+ - `anthropic` → `pi-anthropic-oauth`, channel `subscription-anthropic`.
126
+
127
+ The child Pi JSON event stream must later contain exactly one session, one `agent_start`, at least one assistant message, and one `agent_end`; assistant messages must report a stable provider/model, and the last assistant `stopReason` value reported in the stream must be `stop`. A later assistant message that omits `stopReason` does not clear an earlier reported value. The observed provider/model must match the selected registry model before attestation is accepted.
128
+
129
+ ## Runtime files
130
+
131
+ Files live under the background task runtime directory:
132
+
133
+ ```text
134
+ .pi/tasks/<session-id>-<pid>/<task-id>.output
135
+ .pi/tasks/<session-id>-<pid>/<task-id>.json
136
+ .pi/tasks/<session-id>-<pid>/<task-id>.pi-events.jsonl
137
+ .pi/tasks/<session-id>-<pid>/<task-id>.stderr
138
+ .pi/tasks/<session-id>-<pid>/<task-id>.pi-telemetry-wrapper.cjs
139
+ .pi/tasks/<session-id>-<pid>/<task-id>.attestation.json
140
+ ```
141
+
142
+ For attested runs the wrapper file is an evidence note (`direct-spawn attested Pi task; no shell telemetry wrapper is used`), not a shell wrapper. Raw child stdout is captured as Pi JSON events; raw stderr is captured separately. Human-readable task output is reconstructed from assistant/tool events on success, or from stderr/error text on failure.
143
+
144
+ ## Sidecar contents
145
+
146
+ Successful attestation sidecars use schema `phase2.pi_task_attestation.v1` and include:
147
+
148
+ - locator: session dir, task id, metadata/output/events/stderr/wrapper refs;
149
+ - source hashes for metadata, output, events, stderr, wrapper;
150
+ - lifecycle: status, agent flag, times, exit code/signal, bytes written;
151
+ - invocation: Pi session id, logical argv, cwd realpath, provider, model id, provider-scoped model id, API identity, auth class, credential kind, route class, channel, `direct_api_key:false`, final stop reason;
152
+ - authority: repo root realpath, start/finish commit and tree OIDs, clean-worktree booleans;
153
+ - artifacts: prompt hash, task output hash, stderr hash, transcript hash, report hash;
154
+ - `attestation_sha256`: hash of the canonical sidecar without that self field.
155
+
156
+ The worktree must be clean at start and finish, and the commit/tree must not change during the task.
157
+
158
+ ## Durability and failure behavior
159
+
160
+ The sidecar is written only after successful child completion, event parsing, report hashing, git authority checks, and attestation construction. The final sidecar write uses durable same-directory replacement. In-memory terminal completion (`task.status = completed` plus terminal publication) happens after the sidecar write returns; the metadata file may have a completed snapshot staged earlier as part of the sidecar construction path.
161
+
162
+ If the child fails, times out, is killed, emits malformed/incomplete events, writes no required report, changes git authority, uses non-OAuth/unsupported auth, or fails attestation construction, the task is failed/killed and no successful sidecar is emitted. Existing raw evidence files (`*.pi-events.jsonl`, `*.stderr`, `*.output`, metadata) remain for diagnosis.
163
+
164
+ ## Trust boundary
165
+
166
+ This is local, unsigned, same-user-writable evidence. It is useful for local auditability and reproducibility of what this extension observed, but it is not a remote cryptographic proof, not a signature, and not tamper-resistant against a user or process that can write the working tree or `.pi/tasks` directory.
167
+
168
+ ## Intended use
169
+
170
+ Use `bg_run_pi_attested` when the user explicitly asks for an evidence-producing Pi child with local hashes and route/auth observation. Use ordinary `bg_run` for normal background commands or agent jobs that do not need this sidecar contract.
@@ -0,0 +1,111 @@
1
+ ---
2
+ doc_id: tools/bg_status
3
+ audience: agent
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: stable
7
+ covers_surfaces: [tool:bg_status]
8
+ covers_sources: []
9
+ ---
10
+ # `bg_status`
11
+
12
+ <!-- pi-docs:begin name="tool-contract-bg_status" generator="scripts/docs/generate.mjs" -->
13
+ - Label: **Background Status**
14
+ - Source: `src/extension.ts:821`
15
+ - Description: Inspect one background task or list all running/recent background tasks. This is a point-in-time inspection tool, not a waiting primitive.
16
+ - Root schema: `object`
17
+
18
+ | Field | Required | Type | Description | Constraints |
19
+ | --- | --- | --- | --- | --- |
20
+ | `taskId` | no | `string` | Optional task ID or unambiguous prefix. If omitted, all running/recent tasks are returned. | |
21
+
22
+ <details>
23
+ <summary>Normalized TypeBox contract</summary>
24
+
25
+
26
+ ```json
27
+ {
28
+ "properties": {
29
+ "taskId": {
30
+ "description": "Optional task ID or unambiguous prefix. If omitted, all running/recent tasks are returned.",
31
+ "type": "string"
32
+ }
33
+ },
34
+ "required": [],
35
+ "type": "object"
36
+ }
37
+ ```
38
+
39
+ </details>
40
+ <!-- pi-docs:end name="tool-contract-bg_status" -->
41
+
42
+ Inspect one background task or list all running/recent tasks.
43
+
44
+ ## Schema
45
+
46
+
47
+ Optional fields:
48
+
49
+ - `taskId: string` — exact task id or unambiguous prefix. If omitted, all retained tasks are returned.
50
+
51
+ ## When to use
52
+
53
+ Use for deliberate point-in-time inspection: the user asks for an update, completion handling was disabled, or there is concrete evidence a task is hung.
54
+
55
+ Do **not** use `bg_status` as a polling or waiting primitive. A `running` result is not an instruction to call it again, and a terminal notification does not need reconfirmation.
56
+
57
+ ## Defaults
58
+
59
+ No `taskId` means list all tasks retained by this extension runtime.
60
+
61
+ ## Lifecycle
62
+
63
+ Returns current snapshots. Status values are exactly `running`, `completed`, `failed`, and `killed`.
64
+
65
+ ## Examples
66
+
67
+ ```json
68
+ {}
69
+ ```
70
+
71
+ ```json
72
+ {"taskId":"b1234"}
73
+ ```
74
+
75
+ ## Output/result
76
+
77
+ Text content uses the same snapshot formatting as [`/jobs`](../commands/jobs.md), including output path. Structured details are:
78
+
79
+ ```ts
80
+ { tasks: BgTaskSnapshot[] }
81
+ ```
82
+
83
+ Each snapshot includes delivery flags, notification state, optional telemetry reported by the task, and optional error.
84
+
85
+ ## Errors
86
+
87
+ - Missing id is only possible when an empty string is supplied: `Task ID is required`.
88
+ - Unknown id/prefix: `Unknown background task ID: <id>`.
89
+ - Ambiguous prefix: lists matching task ids.
90
+
91
+ Tool execution rejects loudly; there is no silent fallback to an empty list.
92
+
93
+ ## Runtime artifacts
94
+
95
+ Read-only in-memory snapshots. It does not read or write `.pi/tasks` files.
96
+
97
+ ## Safety boundaries
98
+
99
+ Inspection only. Not a polling primitive, not a wait loop, and not a task-control operation.
100
+
101
+ ## Related docs
102
+
103
+ - [`/jobs`](../commands/jobs.md)
104
+ - [`bg_logs`](bg_logs.md)
105
+ - [`bg_run`](bg_run.md)
106
+ - [Completion delivery](../concepts/completion-delivery.md)
107
+ - [Background task runtime](../subsystems/background-task-runtime.md)
108
+
109
+ ## Source ownership/reference
110
+
111
+ Tool registration lives in `src/extension.ts`; snapshots and task resolution are owned by [background-task-runtime](../subsystems/background-task-runtime.md).