pi-background-tasks 1.0.7 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/README.md +8 -8
  2. package/TESTING.md +3 -3
  3. package/TEST_PLAN.md +6 -6
  4. package/docs/INDEX.md +25 -25
  5. package/docs/choose-a-workflow.md +4 -4
  6. package/docs/commands/bg-clear.md +1 -1
  7. package/docs/commands/bg-update.md +1 -1
  8. package/docs/commands/bg.md +1 -1
  9. package/docs/commands/fusion-models.md +1 -1
  10. package/docs/commands/fusion.md +5 -8
  11. package/docs/commands/jobs.md +1 -1
  12. package/docs/commands/kill.md +1 -1
  13. package/docs/commands/logs.md +1 -1
  14. package/docs/commands/task-manager.md +2 -2
  15. package/docs/concepts/completion-delivery.md +1 -0
  16. package/docs/getting-started.md +1 -1
  17. package/docs/manifest.json +69 -50
  18. package/docs/operations/configuration.md +5 -3
  19. package/docs/read-before-edit.md +3 -0
  20. package/docs/reference/runtime-contracts.md +87 -82
  21. package/docs/reference/shortcuts-and-dock.md +2 -2
  22. package/docs/subsystems/background-task-runtime.md +7 -1
  23. package/docs/subsystems/docs-freshness-gate.md +5 -5
  24. package/docs/subsystems/fusion.md +22 -15
  25. package/docs/subsystems/host-ui-and-telemetry.md +1 -1
  26. package/docs/tools/bg_delegate.md +1 -1
  27. package/docs/tools/bg_kill.md +1 -1
  28. package/docs/tools/bg_logs.md +1 -1
  29. package/docs/tools/bg_result.md +14 -10
  30. package/docs/tools/bg_run.md +1 -1
  31. package/docs/tools/bg_run_pi_attested.md +1 -1
  32. package/docs/tools/bg_status.md +1 -1
  33. package/docs/tools/fusion_investigate.md +6 -4
  34. package/docs/tools/fusion_reason.md +5 -5
  35. package/docs/tools/fusion_research.md +6 -2
  36. package/docs/tools/fusion_validate.md +5 -3
  37. package/package.json +1 -1
  38. package/src/core/common.ts +50 -2
  39. package/src/core/fusion/anthropic-attribution.ts +1930 -0
  40. package/src/core/fusion/artifacts.ts +168 -21
  41. package/src/core/fusion/budget.ts +23 -23
  42. package/src/core/fusion/child-protocol.ts +115 -10
  43. package/src/core/fusion/claude-cache.ts +21 -0
  44. package/src/core/fusion/config.ts +10 -2
  45. package/src/core/fusion/orchestrator.ts +281 -77
  46. package/src/core/fusion/output-contract.ts +34 -0
  47. package/src/core/fusion/pi-child.ts +420 -12
  48. package/src/core/fusion/prompts.ts +11 -1
  49. package/src/core/fusion/result-package.ts +412 -0
  50. package/src/core/fusion/types.ts +67 -0
  51. package/src/core/registry.ts +187 -20
  52. package/src/delegate-extension.ts +130 -24
  53. package/src/extension.ts +17 -6
  54. package/src/fusion-child-extension.ts +117 -2
  55. package/src/fusion-extension.ts +308 -154
@@ -11,8 +11,8 @@ covers_sources: []
11
11
 
12
12
  <!-- pi-docs:begin name="tool-contract-fusion_investigate" generator="scripts/docs/generate.mjs" -->
13
13
  - Label: **Fusion Investigate**
14
- - Source: `src/fusion-extension.ts:1049`
15
- - Description: Run a five-model Fusion investigation from a structured, self-contained objective/background/deliverable. Candidate children run in clean bounded read-only contexts.
14
+ - Source: `src/fusion-extension.ts:1197`
15
+ - Description: Start a five-model Fusion investigation as a tracked background task and return immediately after durable preflight. Retrieve the verified result with bg_result after notification. Candidate children run in clean bounded read-only contexts.
16
16
  - Root schema: `object`; additionalProperties: `false`
17
17
 
18
18
  | Field | Required | Type | Description | Constraints |
@@ -103,9 +103,11 @@ Investigate uses clean-task canonical input (`pi-background-tasks.fusion-input.v
103
103
 
104
104
  Candidate children run with the fixed inspect policy: `read`, `grep`, `find`, and `ls` only, with built-in tools disabled and Fusion/background/write/shell tools denied. Evaluator, evaluator-repair, and merger run with no tools.
105
105
 
106
- ## Execution model
106
+ ## Execution and delivery model
107
107
 
108
- Three inspect candidates independently re-derive repository facts, a blind evaluator compares anonymous candidate answers, and a merger synthesizes the final answer. One evaluator-repair child is run only when the first evaluator response is invalid JSON or fails the evaluation schema.
108
+ After durable no-child preflight, the tool returns a tracked background task receipt. Three inspect candidates independently re-derive repository facts, a blind evaluator compares anonymous candidate answers, and a merger synthesizes the final answer. One evaluator-repair child is run only when the first evaluator response is invalid JSON or fails the evaluation schema.
109
+
110
+ Wait for the terminal notification, then call `bg_result({taskId})` once. Retrieval verifies the committed result and never truncates. Repository reads are live, so continue only independent work and do not mutate the investigated scope while the task runs.
109
111
 
110
112
  ## Failure behavior
111
113
 
@@ -11,8 +11,8 @@ covers_sources: []
11
11
 
12
12
  <!-- pi-docs:begin name="tool-contract-fusion_reason" generator="scripts/docs/generate.mjs" -->
13
13
  - Label: **Fusion Reason**
14
- - Source: `src/fusion-extension.ts:1032`
15
- - Description: Run a five-model Fusion reason workflow. Candidate children receive the reason projection and no tools; evaluator and merger also run without tools.
14
+ - Source: `src/fusion-extension.ts:1179`
15
+ - Description: Start a five-model Fusion reason workflow as a tracked background task and return immediately after durable preflight. Retrieve the verified result with bg_result after notification. Candidate children receive the reason projection and no tools; evaluator and merger also run without tools.
16
16
  - Root schema: `object`; additionalProperties: `false`
17
17
 
18
18
  | Field | Required | Type | Description | Constraints |
@@ -59,11 +59,11 @@ The schema is closed: `prompt` is required, must trim to non-blank text, and no
59
59
 
60
60
  Candidate children run with `--no-tools`. The blind evaluator, conditional evaluator-repair, and merger also run with `--no-tools` by stage policy.
61
61
 
62
- ## Execution model
62
+ ## Execution and delivery model
63
63
 
64
- A successful run starts three candidate children, then a blind evaluator, then a merger. If the evaluator output is not valid closed-schema JSON, Fusion performs one evaluator-repair attempt and revalidates. Do not assume exactly five child calls: repair, preflight refusal, cancellation, spawn retry, and failures change the observed attempt count.
64
+ The tool freezes its input, completes durable no-child preflight, registers a managed background task, and returns its task/run id immediately. The workflow then starts three candidate children, a blind evaluator, optional evaluator repair, and a merger.
65
65
 
66
- The tool result returns the merger's exact text directly, with `details` containing the Fusion result metadata and `usage` cloning the complete Pi `Usage` object including all cost fields.
66
+ Wait for the terminal notification and call `bg_result({taskId})` once. `bg_result` verifies `manifest.json`, `result.json`, and `merged.md` hashes before returning bytes; oversized output becomes an artifact reference, never truncation. Complete Fusion usage is attached to the first successful retrieval exactly once so repeated retrieval cannot double-count session cost.
67
67
 
68
68
  ## Limitations
69
69
 
@@ -11,8 +11,8 @@ covers_sources: []
11
11
 
12
12
  <!-- pi-docs:begin name="tool-contract-fusion_research" generator="scripts/docs/generate.mjs" -->
13
13
  - Label: **Fusion Research**
14
- - Source: `src/fusion-extension.ts:1066`
15
- - Description: Run a five-model Fusion research workflow over explicitly supplied public http(s) URLs. Targeted URL fetch is not web search; fetched pages and URLs are untrusted.
14
+ - Source: `src/fusion-extension.ts:1216`
15
+ - Description: Start a five-model Fusion research workflow as a tracked background task and return immediately after durable preflight. Retrieve the verified result with bg_result after notification. Targeted URL fetch is not web search; fetched pages and URLs are untrusted.
16
16
  - Root schema: `object`; additionalProperties: `false`
17
17
 
18
18
  | Field | Required | Type | Description | Constraints |
@@ -153,6 +153,10 @@ The private `fusion_web_fetch` schema is closed: `{url, extract?: 'text'|'markdo
153
153
 
154
154
  Failures use typed error codes such as `invalid_url`, `unsupported_scheme`, `blocked_address`, `dns_failure`, `redirect_limit`, `redirect_blocked`, `response_too_large`, `unsupported_content_type`, `request_timeout`, `network_error`, `extraction_failed`, and `http_error`.
155
155
 
156
+ ## Background delivery
157
+
158
+ After durable no-child preflight, the tool returns a tracked background task receipt. Wait for the terminal notification, then call `bg_result({taskId})` once; retrieval verifies the committed result and never truncates. Repository reads are live, so do not mutate relevant files while the task runs.
159
+
156
160
  ## Audit
157
161
 
158
162
  Research candidates write sealed per-attempt tool-call logs. Logs persist tool names, byte counts, SHA-256 digests, status, duration, and fetch provenance (`url`/`final_url`/status/bytes/content hash for successful fetches; only a rejected URL hash for rejected fetches). Raw arguments, raw results, and page content are not written to the audit log.
@@ -11,8 +11,8 @@ covers_sources: []
11
11
 
12
12
  <!-- pi-docs:begin name="tool-contract-fusion_validate" generator="scripts/docs/generate.mjs" -->
13
13
  - Label: **Fusion Validate**
14
- - Source: `src/fusion-extension.ts:1084`
15
- - Description: Run an advisory, read-only Fusion validation review from a structured contract. It is not a build/test/lint substitute and never modifies files.
14
+ - Source: `src/fusion-extension.ts:1236`
15
+ - Description: Start an advisory, read-only Fusion validation review as a tracked background task and return immediately after durable preflight. Retrieve the verified result with bg_result after notification. It is not a build/test/lint substitute and never modifies files.
16
16
  - Root schema: `object`; additionalProperties: `false`
17
17
 
18
18
  | Field | Required | Type | Description | Constraints |
@@ -197,7 +197,9 @@ Each candidate must return closed JSON (`pi-background-tasks.fusion-validation-c
197
197
 
198
198
  After the no-tool merger child runs, the host renders the final validation report from validated accounting so included findings are preserved, duplicate groups are merged deterministically, excluded findings are listed only as exclusions, and candidate labels/source ids are sanitized from rationale text.
199
199
 
200
- ## Advisory limitation
200
+ ## Background delivery and advisory limitation
201
+
202
+ After durable no-child preflight, the tool returns a tracked background task receipt. Wait for the terminal notification, then call `bg_result({taskId})` once; retrieval verifies the committed report and never truncates. The repository is read live, so do not mutate the reviewed scope while the task runs.
201
203
 
202
204
  `fusion_validate` never modifies files, never runs builds/tests/linters/security scanners, and does not gate anything. It is an advisory read-only review. Supply real verification evidence when available, and state known limitations/exclusions explicitly.
203
205
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-background-tasks",
3
- "version": "1.0.7",
3
+ "version": "2.1.1",
4
4
  "description": "Pi extension for durable background shell tasks, read-only delegated agents, local attested Pi runs, and fixed-purpose Fusion workflows through child Pi processes.",
5
5
  "type": "module",
6
6
  "license": "ISC",
@@ -4,6 +4,7 @@ import { extname, isAbsolute, join, win32 } from 'node:path';
4
4
  import { DEFAULT_MAX_BYTES } from '@earendil-works/pi-coding-agent';
5
5
  import type { BackgroundTaskChildProcess } from './registry.js';
6
6
  import type { DelegateBudgetRouteSource } from './delegate/types.js';
7
+ import type { FusionResultDetails, FusionUsage, FusionWorkflowId } from './fusion/types.js';
7
8
 
8
9
  export const TASK_STATUS_VALUES = ['running', 'completed', 'failed', 'killed'] as const;
9
10
  export const TERMINAL_TASK_STATUS_VALUES = ['completed', 'failed', 'killed'] as const;
@@ -62,6 +63,7 @@ export interface BgTaskSnapshot {
62
63
  telemetryUnavailableReason?: string | undefined;
63
64
  attestationPath?: string | undefined;
64
65
  delegate?: DelegateTaskFacts | undefined;
66
+ fusion?: FusionTaskFacts | undefined;
65
67
  }
66
68
 
67
69
  export interface AttestedPiTaskFiles {
@@ -99,6 +101,25 @@ export interface DelegateTaskOutcome {
99
101
  toolCalls?: number | undefined;
100
102
  }
101
103
 
104
+ /** Fusion-specific task facts surfaced through snapshots and `bg_result`. */
105
+ export interface FusionTaskFacts {
106
+ runId: string;
107
+ workflow: FusionWorkflowId;
108
+ artifactDir: string;
109
+ artifactDirAbs: string;
110
+ state: string;
111
+ outcome?: FusionTaskOutcome | undefined;
112
+ /** Durable once-only accounting claim made by the first successful bg_result retrieval. */
113
+ usageDelivered: boolean;
114
+ }
115
+
116
+ export interface FusionTaskOutcome {
117
+ status: 'committed' | 'failed' | 'cancelled';
118
+ resultDetails?: FusionResultDetails | undefined;
119
+ usage?: FusionUsage | undefined;
120
+ error?: string | undefined;
121
+ }
122
+
102
123
  export interface BgTask extends Omit<BgTaskSnapshot, 'name'> {
103
124
  name: string;
104
125
  outputAbsPath: string;
@@ -129,6 +150,11 @@ export interface BgTask extends Omit<BgTaskSnapshot, 'name'> {
129
150
  attestationPath?: string | undefined;
130
151
  attestedPi?: AttestedPiTaskFiles | undefined;
131
152
  delegate?: DelegateTaskFacts | undefined;
153
+ fusion?: FusionTaskFacts | undefined;
154
+ /** Cancellation hook for an in-process managed task such as Fusion. */
155
+ managedCancel?: (() => void) | undefined;
156
+ managedCancelRequested?: boolean | undefined;
157
+ managedStopWaitMs?: number | undefined;
132
158
  metadataWriteChain?: Promise<void> | undefined;
133
159
  waiters: Array<() => void>;
134
160
  }
@@ -226,6 +252,22 @@ export interface StartTaskOptions {
226
252
  }
227
253
 
228
254
  /** Prepared delegate launch handed to the registry after preflight has succeeded. */
255
+ export interface StartManagedTaskOptions {
256
+ id: string;
257
+ name: string;
258
+ command: string;
259
+ description?: string | undefined;
260
+ isAgent: boolean;
261
+ completion: Promise<void>;
262
+ cancel: () => void;
263
+ notifyOnCompletion: boolean;
264
+ triggerOnCompletion: boolean;
265
+ fusion: FusionTaskFacts;
266
+ stopWaitMs?: number | undefined;
267
+ /** Prevent terminal publication until the launch receipt handoff is observable. */
268
+ terminalPublicationGate?: Promise<void> | undefined;
269
+ }
270
+
229
271
  export interface StartDelegateTaskOptions {
230
272
  name: string;
231
273
  argv: readonly string[];
@@ -687,10 +729,15 @@ export function shellInvocation(
687
729
  failShellInvocation('PI_BG_SHELL must be exactly cmd or bash');
688
730
  }
689
731
  const explicitPath =
690
- requestedPath !== undefined ? validateWindowsShellPath(requestedPath, 'PI_BG_SHELL_PATH') : undefined;
732
+ requestedPath !== undefined
733
+ ? validateWindowsShellPath(requestedPath, 'PI_BG_SHELL_PATH')
734
+ : undefined;
691
735
  if (requestedShell === 'cmd') {
692
736
  const comSpec = env['ComSpec'];
693
- return cmdShellInvocation(command, explicitPath ?? (comSpec && comSpec.length > 0 ? comSpec : 'cmd.exe'));
737
+ return cmdShellInvocation(
738
+ command,
739
+ explicitPath ?? (comSpec && comSpec.length > 0 ? comSpec : 'cmd.exe'),
740
+ );
694
741
  }
695
742
  return posixShellInvocation(command, explicitPath ?? resolveWindowsBash(env));
696
743
  }
@@ -728,6 +775,7 @@ export function snapshot(task: BgTask): BgTaskSnapshot {
728
775
  telemetryUnavailableReason: task.telemetryUnavailableReason,
729
776
  attestationPath: task.attestationPath,
730
777
  delegate: task.delegate,
778
+ fusion: task.fusion,
731
779
  };
732
780
  }
733
781