pi-background-tasks 0.9.0 → 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 +233 -441
  4. package/TESTING.md +15 -9
  5. package/TEST_PLAN.md +43 -17
  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 +25 -7
  53. package/src/core/delegate/budget.ts +1 -1
  54. package/src/core/delegate/launch.ts +5 -0
  55. package/src/core/fusion/artifacts.ts +34 -4
  56. package/src/core/fusion/budget.ts +112 -20
  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 +29 -7
  61. package/src/core/fusion/evaluation.ts +392 -15
  62. package/src/core/fusion/orchestrator.ts +217 -23
  63. package/src/core/fusion/pi-child.ts +183 -23
  64. package/src/core/fusion/prompts.ts +39 -26
  65. package/src/core/fusion/source-policy.ts +257 -0
  66. package/src/core/fusion/types.ts +156 -11
  67. package/src/core/fusion/web-fetch.ts +104 -15
  68. package/src/core/fusion/workflows.ts +119 -65
  69. package/src/extension.ts +3 -3
  70. package/src/fusion-child-extension.ts +159 -120
  71. package/src/fusion-extension.ts +585 -240
  72. package/src/testing/normalize.ts +0 -22
@@ -0,0 +1,116 @@
1
+ ---
2
+ doc_id: tools/fusion_investigate
3
+ audience: agent
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: stable
7
+ covers_surfaces: [tool:fusion_investigate]
8
+ covers_sources: []
9
+ ---
10
+ # `fusion_investigate`
11
+
12
+ <!-- pi-docs:begin name="tool-contract-fusion_investigate" generator="scripts/docs/generate.mjs" -->
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.
16
+ - Root schema: `object`; additionalProperties: `false`
17
+
18
+ | Field | Required | Type | Description | Constraints |
19
+ | --- | --- | --- | --- | --- |
20
+ | `background` | yes | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
21
+ | `constraints` | no | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
22
+ | `deliverable` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
23
+ | `objective` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
24
+ | `scope` | no | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
25
+
26
+ <details>
27
+ <summary>Normalized TypeBox contract</summary>
28
+
29
+
30
+ ```json
31
+ {
32
+ "additionalProperties": false,
33
+ "properties": {
34
+ "background": {
35
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
36
+ "items": {
37
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
38
+ "minLength": 1,
39
+ "type": "string"
40
+ },
41
+ "type": "array"
42
+ },
43
+ "constraints": {
44
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
45
+ "items": {
46
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
47
+ "minLength": 1,
48
+ "type": "string"
49
+ },
50
+ "type": "array"
51
+ },
52
+ "deliverable": {
53
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
54
+ "minLength": 1,
55
+ "type": "string"
56
+ },
57
+ "objective": {
58
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
59
+ "minLength": 1,
60
+ "type": "string"
61
+ },
62
+ "scope": {
63
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
64
+ "items": {
65
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
66
+ "minLength": 1,
67
+ "type": "string"
68
+ },
69
+ "type": "array"
70
+ }
71
+ },
72
+ "required": [
73
+ "background",
74
+ "deliverable",
75
+ "objective"
76
+ ],
77
+ "type": "object"
78
+ }
79
+ ```
80
+
81
+ </details>
82
+ <!-- pi-docs:end name="tool-contract-fusion_investigate" -->
83
+
84
+ Fixed-purpose public Fusion tool for bounded read-only repository investigation.
85
+
86
+ ## Signature
87
+
88
+ ```ts
89
+ fusion_investigate({
90
+ objective: string,
91
+ background: string[],
92
+ deliverable: string,
93
+ scope?: string[],
94
+ constraints?: string[]
95
+ })
96
+ ```
97
+
98
+ The schema is closed. `objective`, `background`, and `deliverable` are required; every string trims to non-blank text. Optional `scope` and `constraints` normalize to `[]` when omitted. Unknown keys are rejected. There is no public capability or mode argument.
99
+
100
+ ## Context and tools
101
+
102
+ Investigate uses clean-task canonical input (`pi-background-tasks.fusion-input.v5`) with policy `fusion-clean-task-v1`. Children receive only `workflow`, `cwd`, `request`, and clean context. They do **not** receive the parent transcript, parent system prompt, conversation projection, omission ledger, or hidden tool payloads.
103
+
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
+
106
+ ## Execution model
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.
109
+
110
+ ## Failure behavior
111
+
112
+ Malformed structured input fails before child creation. Prompt-budget failures name the blocking stage and remediation. Tool-enabled children must produce a sealed tool-call audit; missing, partial, unsealed, non-contiguous, over-budget, or non-allowlisted tool traces fail loudly.
113
+
114
+ ## Related
115
+
116
+ - Behavioral owner/troubleshooting: [`../subsystems/fusion.md`](../subsystems/fusion.md)
@@ -0,0 +1,75 @@
1
+ ---
2
+ doc_id: tools/fusion_reason
3
+ audience: agent
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: stable
7
+ covers_surfaces: [tool:fusion_reason]
8
+ covers_sources: []
9
+ ---
10
+ # `fusion_reason`
11
+
12
+ <!-- pi-docs:begin name="tool-contract-fusion_reason" generator="scripts/docs/generate.mjs" -->
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.
16
+ - Root schema: `object`; additionalProperties: `false`
17
+
18
+ | Field | Required | Type | Description | Constraints |
19
+ | --- | --- | --- | --- | --- |
20
+ | `prompt` | yes | `string` | Reasoning request. Candidate children run without tools over the reason workflow's projected conversation context. | minLength 1 |
21
+
22
+ <details>
23
+ <summary>Normalized TypeBox contract</summary>
24
+
25
+
26
+ ```json
27
+ {
28
+ "additionalProperties": false,
29
+ "properties": {
30
+ "prompt": {
31
+ "description": "Reasoning request. Candidate children run without tools over the reason workflow's projected conversation context.",
32
+ "minLength": 1,
33
+ "type": "string"
34
+ }
35
+ },
36
+ "required": [
37
+ "prompt"
38
+ ],
39
+ "type": "object"
40
+ }
41
+ ```
42
+
43
+ </details>
44
+ <!-- pi-docs:end name="tool-contract-fusion_reason" -->
45
+
46
+ Fixed-purpose public Fusion tool for self-contained no-tool reasoning.
47
+
48
+ ## Signature
49
+
50
+ ```ts
51
+ fusion_reason({ prompt: string })
52
+ ```
53
+
54
+ The schema is closed: `prompt` is required, must trim to non-blank text, and no other keys are accepted. There is no public `capability`, mode, provider, model, or tool-policy argument.
55
+
56
+ ## Context and tools
57
+
58
+ `fusion_reason` receives a versioned session-projection input (`pi-background-tasks.fusion-input.v5`): visible user/assistant text is retained verbatim, while assistant thinking and tool traffic are replaced by deterministic omission receipts and a local omission ledger artifact. Tool-call invocations exclude the active Fusion tool-call leaf and sibling calls from the projected branch.
59
+
60
+ Candidate children run with `--no-tools`. The blind evaluator, conditional evaluator-repair, and merger also run with `--no-tools` by stage policy.
61
+
62
+ ## Execution model
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.
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.
67
+
68
+ ## Limitations
69
+
70
+ Omitted tool payloads are not available to children. Restate required facts from prior tool output inside `prompt` before calling.
71
+
72
+ ## Related
73
+
74
+ - Command shorthand: [`../commands/fusion.md`](../commands/fusion.md)
75
+ - Behavioral owner/troubleshooting: [`../subsystems/fusion.md`](../subsystems/fusion.md)
@@ -0,0 +1,162 @@
1
+ ---
2
+ doc_id: tools/fusion_research
3
+ audience: agent
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: stable
7
+ covers_surfaces: [tool:fusion_research]
8
+ covers_sources: []
9
+ ---
10
+ # `fusion_research`
11
+
12
+ <!-- pi-docs:begin name="tool-contract-fusion_research" generator="scripts/docs/generate.mjs" -->
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.
16
+ - Root schema: `object`; additionalProperties: `false`
17
+
18
+ | Field | Required | Type | Description | Constraints |
19
+ | --- | --- | --- | --- | --- |
20
+ | `background` | yes | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
21
+ | `constraints` | no | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
22
+ | `deliverable` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
23
+ | `objective` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
24
+ | `scope` | no | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
25
+ | `sources` | yes | `object[]` | | minItems 1 |
26
+ | `sources[].purpose` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
27
+ | `sources[].url` | yes | `string` | Public http(s) URL to fetch exactly; targeted URL fetch only, not web search. Do not include credentials, tokens, secrets, private data, or repository content in URLs. | minLength 1 |
28
+
29
+ <details>
30
+ <summary>Normalized TypeBox contract</summary>
31
+
32
+
33
+ ```json
34
+ {
35
+ "additionalProperties": false,
36
+ "properties": {
37
+ "background": {
38
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
39
+ "items": {
40
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
41
+ "minLength": 1,
42
+ "type": "string"
43
+ },
44
+ "type": "array"
45
+ },
46
+ "constraints": {
47
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
48
+ "items": {
49
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
50
+ "minLength": 1,
51
+ "type": "string"
52
+ },
53
+ "type": "array"
54
+ },
55
+ "deliverable": {
56
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
57
+ "minLength": 1,
58
+ "type": "string"
59
+ },
60
+ "objective": {
61
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
62
+ "minLength": 1,
63
+ "type": "string"
64
+ },
65
+ "scope": {
66
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
67
+ "items": {
68
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
69
+ "minLength": 1,
70
+ "type": "string"
71
+ },
72
+ "type": "array"
73
+ },
74
+ "sources": {
75
+ "items": {
76
+ "additionalProperties": false,
77
+ "properties": {
78
+ "purpose": {
79
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
80
+ "minLength": 1,
81
+ "type": "string"
82
+ },
83
+ "url": {
84
+ "description": "Public http(s) URL to fetch exactly; targeted URL fetch only, not web search. Do not include credentials, tokens, secrets, private data, or repository content in URLs.",
85
+ "minLength": 1,
86
+ "type": "string"
87
+ }
88
+ },
89
+ "required": [
90
+ "purpose",
91
+ "url"
92
+ ],
93
+ "type": "object"
94
+ },
95
+ "minItems": 1,
96
+ "type": "array"
97
+ }
98
+ },
99
+ "required": [
100
+ "background",
101
+ "deliverable",
102
+ "objective",
103
+ "sources"
104
+ ],
105
+ "type": "object"
106
+ }
107
+ ```
108
+
109
+ </details>
110
+ <!-- pi-docs:end name="tool-contract-fusion_research" -->
111
+
112
+ Fixed-purpose public Fusion tool for targeted caller-declared public URL fetch plus synthesis.
113
+
114
+ ## Signature
115
+
116
+ ```ts
117
+ fusion_research({
118
+ objective: string,
119
+ background: string[],
120
+ deliverable: string,
121
+ scope?: string[],
122
+ constraints?: string[],
123
+ sources: Array<{ url: string, purpose: string }>
124
+ })
125
+ ```
126
+
127
+ The schema is closed. Required strings trim to non-blank text. Optional arrays normalize to `[]`. `sources` must be non-empty; each URL must be a canonical public `http(s)` URL with no credentials, and duplicate canonical URLs are rejected. There is no public capability or mode argument.
128
+
129
+ ## Not search
130
+
131
+ Fusion research is **not web search**. It never discovers sources, queries a search engine, opens a browser, follows page-suggested links as instructions, reads PDFs through a PDF pipeline, caches pages, or applies a domain allowlist. The caller supplies the exact initial public URLs and the child may fetch only those declared canonical URLs through the private child-only `fusion_web_fetch` tool.
132
+
133
+ ## Context and tools
134
+
135
+ Research uses clean-task canonical input with no parent transcript, parent system prompt, conversation projection, or omission ledger. Candidate children receive read-only file tools (`read`, `grep`, `find`, `ls`) plus `fusion_web_fetch`; evaluator, evaluator-repair, and merger receive no tools.
136
+
137
+ This is an accepted read+network tradeoff: a research candidate can inspect repository files and perform network fetches to caller-declared public URLs in the same child process. Do not include credentials, tokens, secrets, private data, or repository content in URLs. The package blocks credential-bearing URLs and common private, loopback, metadata, and reserved targets, but the deny rules are not an exhaustive network sandbox. In particular, source declaration rejects literal Azure service virtual IP `168.63.129.16`, while the transport's DNS/redirect address classifier does not currently special-case a public hostname resolving to that address. Fetched content remains untrusted, and caller-declared URLs can still disclose access through remote logs or timing.
138
+
139
+ ## Fetch hygiene
140
+
141
+ The private `fusion_web_fetch` schema is closed: `{url, extract?: 'text'|'markdown'}`; `extract` defaults to Markdown and there is no per-fetch prompt. The fetcher:
142
+
143
+ - supports only absolute `http:` and `https:` URLs;
144
+ - strips fragments, rejects credentials, and canonicalizes host/default port casing;
145
+ - blocks localhost and known metadata hostnames plus enumerated private/reserved IPv4 and IPv6 ranges, IPv4-mapped IPv6, multicast, link-local, documentation, and similar non-public classes;
146
+ - source-policy admission additionally rejects literal `168.63.129.16`, but DNS/redirect transport classification does not explicitly include that Azure service address;
147
+ - vets every DNS answer against the transport classifier, pins the request to a vetted address, and verifies the response socket address;
148
+ - follows at most five redirects, revalidating each hop;
149
+ - accepts only HTML/XHTML, plain text, and Markdown content;
150
+ - caps response bytes at 2 MiB and extracted output at 32 KiB;
151
+ - uses a 60 second deadline;
152
+ - strips script/style/noscript blocks and extracts text or Markdown with table preservation.
153
+
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
+
156
+ ## Audit
157
+
158
+ 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.
159
+
160
+ ## Related
161
+
162
+ - Behavioral owner/troubleshooting: [`../subsystems/fusion.md`](../subsystems/fusion.md)
@@ -0,0 +1,206 @@
1
+ ---
2
+ doc_id: tools/fusion_validate
3
+ audience: agent
4
+ mode: mixed
5
+ review_policy: contract
6
+ stability: stable
7
+ covers_surfaces: [tool:fusion_validate]
8
+ covers_sources: []
9
+ ---
10
+ # `fusion_validate`
11
+
12
+ <!-- pi-docs:begin name="tool-contract-fusion_validate" generator="scripts/docs/generate.mjs" -->
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.
16
+ - Root schema: `object`; additionalProperties: `false`
17
+
18
+ | Field | Required | Type | Description | Constraints |
19
+ | --- | --- | --- | --- | --- |
20
+ | `acceptanceCriteria` | yes | `string[]` | | minItems 1 |
21
+ | `background` | yes | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
22
+ | `changeSummary` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
23
+ | `exclusions` | no | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
24
+ | `knownLimitations` | no | `string[]` | Array of non-empty strings. Runtime normalization trims every item. | |
25
+ | `objective` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
26
+ | `scope` | yes | `string[]` | | minItems 1 |
27
+ | `verification` | yes | `object` | | additionalProperties: false |
28
+ | `verification.evidence` | no | `object[]` | | |
29
+ | `verification.evidence[].check` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
30
+ | `verification.evidence[].outcome` | yes | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
31
+ | `verification.reason` | no | `string` | Non-empty string. Runtime normalization trims and rejects whitespace-only text. | minLength 1 |
32
+ | `verification.status` | yes | `string` | Google-compatible enum. Use 'provided' only with evidence; use 'not_run' only with reason and no evidence. | enum `provided` \| `not_run` |
33
+
34
+ <details>
35
+ <summary>Normalized TypeBox contract</summary>
36
+
37
+
38
+ ```json
39
+ {
40
+ "additionalProperties": false,
41
+ "properties": {
42
+ "acceptanceCriteria": {
43
+ "items": {
44
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
45
+ "minLength": 1,
46
+ "type": "string"
47
+ },
48
+ "minItems": 1,
49
+ "type": "array"
50
+ },
51
+ "background": {
52
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
53
+ "items": {
54
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
55
+ "minLength": 1,
56
+ "type": "string"
57
+ },
58
+ "type": "array"
59
+ },
60
+ "changeSummary": {
61
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
62
+ "minLength": 1,
63
+ "type": "string"
64
+ },
65
+ "exclusions": {
66
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
67
+ "items": {
68
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
69
+ "minLength": 1,
70
+ "type": "string"
71
+ },
72
+ "type": "array"
73
+ },
74
+ "knownLimitations": {
75
+ "description": "Array of non-empty strings. Runtime normalization trims every item.",
76
+ "items": {
77
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
78
+ "minLength": 1,
79
+ "type": "string"
80
+ },
81
+ "type": "array"
82
+ },
83
+ "objective": {
84
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
85
+ "minLength": 1,
86
+ "type": "string"
87
+ },
88
+ "scope": {
89
+ "items": {
90
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
91
+ "minLength": 1,
92
+ "type": "string"
93
+ },
94
+ "minItems": 1,
95
+ "type": "array"
96
+ },
97
+ "verification": {
98
+ "additionalProperties": false,
99
+ "properties": {
100
+ "evidence": {
101
+ "items": {
102
+ "additionalProperties": false,
103
+ "properties": {
104
+ "check": {
105
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
106
+ "minLength": 1,
107
+ "type": "string"
108
+ },
109
+ "outcome": {
110
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
111
+ "minLength": 1,
112
+ "type": "string"
113
+ }
114
+ },
115
+ "required": [
116
+ "check",
117
+ "outcome"
118
+ ],
119
+ "type": "object"
120
+ },
121
+ "type": "array"
122
+ },
123
+ "reason": {
124
+ "description": "Non-empty string. Runtime normalization trims and rejects whitespace-only text.",
125
+ "minLength": 1,
126
+ "type": "string"
127
+ },
128
+ "status": {
129
+ "description": "Google-compatible enum. Use 'provided' only with evidence; use 'not_run' only with reason and no evidence.",
130
+ "enum": [
131
+ "provided",
132
+ "not_run"
133
+ ],
134
+ "type": "string"
135
+ }
136
+ },
137
+ "required": [
138
+ "status"
139
+ ],
140
+ "type": "object"
141
+ }
142
+ },
143
+ "required": [
144
+ "acceptanceCriteria",
145
+ "background",
146
+ "changeSummary",
147
+ "objective",
148
+ "scope",
149
+ "verification"
150
+ ],
151
+ "type": "object"
152
+ }
153
+ ```
154
+
155
+ </details>
156
+ <!-- pi-docs:end name="tool-contract-fusion_validate" -->
157
+
158
+ Fixed-purpose public Fusion tool for advisory read-only validation of completed work.
159
+
160
+ ## Signature
161
+
162
+ ```ts
163
+ fusion_validate({
164
+ objective: string,
165
+ background: string[],
166
+ changeSummary: string,
167
+ scope: string[],
168
+ acceptanceCriteria: string[],
169
+ verification: {
170
+ status: 'provided' | 'not_run',
171
+ evidence?: Array<{ check: string, outcome: string }>,
172
+ reason?: string
173
+ },
174
+ knownLimitations?: string[],
175
+ exclusions?: string[]
176
+ })
177
+ ```
178
+
179
+ The schema is closed. `scope` and `acceptanceCriteria` must be non-empty arrays. Optional `knownLimitations` and `exclusions` normalize to `[]`. Legacy `{prompt}` calls fail with an actionable migration error. There is no public capability or mode argument.
180
+
181
+ ## Verification cross-field contract
182
+
183
+ `verification` is intentionally strict:
184
+
185
+ - `status: 'provided'` requires non-empty `evidence:[{check,outcome}]` and forbids `reason`.
186
+ - `status: 'not_run'` requires `reason` and forbids non-empty evidence.
187
+
188
+ The enum strings are Google-compatible and the runtime enforces the cross-field contract after schema preparation.
189
+
190
+ ## Context and tools
191
+
192
+ Validate uses clean-task canonical input with no parent transcript, parent system prompt, conversation projection, or omission ledger. Candidate reviewers always use the inspect policy (`read`, `grep`, `find`, `ls`) so they can verify the repository as it exists. Evaluator, evaluator-repair, and merger always run with no tools.
193
+
194
+ ## Validation workflow
195
+
196
+ Each candidate must return closed JSON (`pi-background-tasks.fusion-validation-candidate.v1`) listing findings, verified statements, and limitations. The host assigns stable source finding ids after anonymization. The blind evaluator must copy the host-assigned source findings exactly into `validation_accounting`, then account for every source finding exactly once as included or excluded. Included decisions require a group; excluded decisions forbid a group. Groups must exactly match included decisions.
197
+
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
+
200
+ ## Advisory limitation
201
+
202
+ `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
+
204
+ ## Related
205
+
206
+ - Behavioral owner/troubleshooting: [`../subsystems/fusion.md`](../subsystems/fusion.md)
package/logo.png ADDED
Binary file
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pi-background-tasks",
3
- "version": "0.9.0",
4
- "description": "Pi extension package for background shell tasks plus five-model fusion brainstorming and validation: bg_run tools, bg_delegate, /bg commands, /fusion, fusion_brainstorm, fusion_validate, model selector UI, bounded logs, kill/timeout safety, and completion wakeups.",
3
+ "version": "1.0.3",
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",
7
7
  "author": "Ismail <ismailsalikhodjaev@gmail.com>",
@@ -16,9 +16,15 @@
16
16
  "coding-agent",
17
17
  "shell",
18
18
  "tasks",
19
+ "delegate",
20
+ "attestation",
19
21
  "fusion",
20
- "brainstorm",
21
- "multi-model"
22
+ "reason",
23
+ "investigate",
24
+ "research",
25
+ "multi-model",
26
+ "task-manager",
27
+ "pi-dev"
22
28
  ],
23
29
  "homepage": "https://github.com/ismailsaleekh/pi-background-tasks#readme",
24
30
  "repository": {
@@ -35,7 +41,10 @@
35
41
  "TESTING.md",
36
42
  "TEST_PLAN.md",
37
43
  "PUBLISHING.md",
38
- "LICENSE"
44
+ "LICENSE",
45
+ "docs/",
46
+ "BACKGROUND-TASKS-INSTRUCTIONS.md",
47
+ "logo.png"
39
48
  ],
40
49
  "scripts": {
41
50
  "typecheck": "tsc --noEmit",
@@ -56,9 +65,18 @@
56
65
  "lint": "cd ../.. && npm run quality:ts:lint",
57
66
  "format:check": "cd ../.. && npm run quality:ts:format",
58
67
  "test:compat": "tsx scripts/test-compat.ts",
59
- "test:hook-contract": "tsx --test --test-concurrency=1 tests/scripted-provider/pi-hook-contract.test.ts"
68
+ "test:hook-contract": "tsx --test --test-concurrency=1 tests/scripted-provider/pi-hook-contract.test.ts",
69
+ "docs:generate": "node scripts/docs/generate.mjs",
70
+ "docs:verify": "node scripts/docs/verify.mjs",
71
+ "docs:attest/record": "node scripts/docs/attest.mjs",
72
+ "docs:attest": "npm run docs:attest/record",
73
+ "test:docs": "tsx --test tests/unit/docs-gate.test.ts tests/package/docs-contract.test.ts",
74
+ "payload:check": "node scripts/check-package-payload.mjs",
75
+ "release:check-version": "node scripts/check-release-version.mjs",
76
+ "prepack": "npm run docs:verify && npm run payload:check"
60
77
  },
61
78
  "pi": {
79
+ "image": "https://raw.githubusercontent.com/ismailsaleekh/pi-background-tasks/main/logo.png",
62
80
  "extensions": [
63
81
  "./extensions/background-tasks.ts"
64
82
  ]
@@ -72,7 +90,6 @@
72
90
  "@earendil-works/pi-ai": "^0.83.0",
73
91
  "@earendil-works/pi-coding-agent": "^0.83.0",
74
92
  "@earendil-works/pi-tui": "^0.83.0",
75
- "@ravshansbox/pi-anthropic-sps": "github:ravshansbox/pi-anthropic-sps",
76
93
  "@types/node": "^24.0.0",
77
94
  "@types/turndown": "5.0.6",
78
95
  "tsx": "^4.19.0",
@@ -83,6 +100,7 @@
83
100
  "node": ">=22.19.0"
84
101
  },
85
102
  "dependencies": {
103
+ "@ravshansbox/pi-anthropic-sps": "https://codeload.github.com/ravshansbox/pi-anthropic-sps/tar.gz/17409b5615f0ec0625776bc5434f92f2c55e3fd0",
86
104
  "turndown": "7.2.4"
87
105
  }
88
106
  }
@@ -50,7 +50,7 @@ export const DELEGATE_MIN_CONTEXT_WINDOW_TOKENS =
50
50
 
51
51
  export const DELEGATE_DEFAULT_MAX_TURNS = 24;
52
52
  export const DELEGATE_DEFAULT_MAX_TOOL_CALLS = 120;
53
- export const DELEGATE_DEFAULT_TIMEOUT_SECONDS = 900;
53
+ export const DELEGATE_DEFAULT_TIMEOUT_SECONDS = 1200;
54
54
  export const DELEGATE_MAX_TOOL_RESULT_BYTES = 64 * 1024;
55
55
  export const DELEGATE_MAX_TOTAL_TOOL_OUTPUT_BYTES = 64 * 1024 * 1024;
56
56
  export const DELEGATE_MAX_ANSWER_BYTES = 4 * 1024 * 1024;
@@ -220,8 +220,13 @@ export const DELEGATE_FORBIDDEN_TOOLS: readonly string[] = [
220
220
  'bg_delegate',
221
221
  'bg_result',
222
222
  'bg_kill',
223
+ 'bg_status',
224
+ 'bg_logs',
223
225
  'bg_run_pi_attested',
224
226
  'fusion_brainstorm',
227
+ 'fusion_reason',
228
+ 'fusion_investigate',
229
+ 'fusion_research',
225
230
  'fusion_validate',
226
231
  ];
227
232