specpi 0.11.2 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -1
- package/NPM_RELEASE.md +3 -1
- package/README.md +38 -28
- package/SECURITY_MODEL.md +30 -0
- package/THIRD_PARTY.md +14 -0
- package/docs/delegation/README.md +264 -0
- package/docs/delegation/design-protocol.md +382 -0
- package/docs/delegation/design.md +525 -0
- package/docs/delegation/evaluation.md +307 -0
- package/docs/delegation/protocol.md +271 -0
- package/docs/delegation/research.md +216 -0
- package/extensions/command-guard/index.ts +118 -33
- package/extensions/delegation/core.mjs +772 -0
- package/extensions/delegation/errors.mjs +8 -0
- package/extensions/delegation/extension.mjs +475 -0
- package/extensions/delegation/index.ts +9 -0
- package/extensions/delegation/managed-files.mjs +13 -0
- package/extensions/delegation/native.mjs +155 -0
- package/extensions/delegation/presentation.mjs +315 -0
- package/extensions/delegation/protocol.mjs +296 -0
- package/extensions/delegation/provider.mjs +689 -0
- package/extensions/delegation/snapshot.mjs +532 -0
- package/extensions/delegation/worker.mjs +218 -0
- package/extensions/workflow-controls/index.ts +5 -1
- package/package.json +4 -2
- package/scripts/check-package.mjs +21 -3
- package/scripts/check-pi-package.mjs +4 -0
- package/scripts/check-syntax.mjs +61 -0
- package/scripts/specpi.mjs +6 -0
- package/site/logo.svg +1 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.12.0 - 2026-09-05
|
|
4
|
+
|
|
5
|
+
- Add experimental, opt-in delegation for independent reviews and selected-source analysis through native Pi sessions. The parent remains the sole writer; workers have no shell, edits, live web, nested delegation or ambient extensions.
|
|
6
|
+
- Show live worker state, elapsed time and call counts above the editor, with expandable findings and evidence in tool results.
|
|
7
|
+
- Follow parent model and thinking changes after one activation. Check public SDK capabilities, preserve process budgets and cancellation settlement, and document unsupported parent hooks and provider overrides.
|
|
8
|
+
- Bound snapshot retention, source-tool responses and replay records. Preserve spending receipts while pruning recent cancellation and nonfinal assessment responses.
|
|
9
|
+
- Fix Command Guard state notifications across reused sessions, stale approval dialogs and session locking. Keep Guard optional for delegation while respecting active policy and locks.
|
|
10
|
+
- Share the delegation install inventory across installer and package checks, test imports from the installed tree, and exclude nested dependencies from source syntax checks.
|
|
11
|
+
- Rebuild the technical site with a dark default theme, workflow documentation, and a sourced architecture article with comparison charts explaining the single-agent default and selective delegation.
|
|
12
|
+
|
|
13
|
+
After updating the npm CLI, run `specpi update` and restart Pi to load the new delegation runtime. See [the delegation guide](docs/delegation/README.md) for its experimental limits.
|
|
14
|
+
|
|
3
15
|
## 0.11.2 - 2026-09-04
|
|
4
16
|
|
|
5
17
|
- Publish the validated tarball through an absolute local path. npm interpreted the previous relative path as a GitHub repository, so 0.11.1 stopped before npm publication despite passing artifact validation.
|
|
@@ -93,7 +105,7 @@
|
|
|
93
105
|
- Match every PowerShell parameter prefix, not only full spellings: `-enc` runs the same code as `-EncodedCommand`, so an abbreviated flag used to carry a base64 payload past the guard with no approval when the invocation arrived through the Bash or cmd parser. Bash- and cmd-hosted `powershell`/`pwsh` invocations now decode and classify their `-Command`/`-EncodedCommand` payload instead of seeing one opaque argument, including recursive `cmd /c powershell.exe` dispatch, and an absent PowerShell parser downgrades to an approval rather than locking the session over an interpreter the command could not have used.
|
|
94
106
|
- Remove routine Guard approvals for determinate non-catastrophic work, including project or user-data deletion, force push, publication, installation, network transfer, process termination, service and registry changes, and out-of-workspace targets. Keep those broader prompts in Strict. Narrow Guard's protected mutation boundary to host-root/key system targets and, inside the installed agent, command-guard enforcement sources, `settings.json`, and `specpi/manifest.json`.
|
|
95
107
|
- Identify Pi and SpecPi private state by location rather than by name. `specpi/manifest.json`, `specpi/backups`, `specpi/wishlist` and `extensions/command-guard` were matched as bare relative segments, so reviewing SpecPi's own repository denied a file read critically and locked the session, and `guard.self-tamper` fired on any mutation whose arguments merely contained "specpi" or "command-guard" — `mkdir specpi-experiment` was a critical denial. On POSIX the rule was an unanchored `/(?:specpi|pi).*(?:auth|session|…)/`, so everyday files such as `src/api/session.ts` and `lib/api/auth.py` ("pi" inside "api") were denied critically too. These now key on the resolved `PI_CODING_AGENT_DIR`; Guard protects only enforcement-critical installed state while Strict retains the wider private-path policy.
|
|
96
|
-
- Stop latching the session lock when a
|
|
108
|
+
- Stop latching the session lock when a _read_ is refused. Blocking the read is the protection; locking additionally refused every later call — including read-only ones — until `/guard unlock`, so one blocked file ended the session. Critical mutation attempts still lock.
|
|
97
109
|
- Stop treating a plain `find` as a deletion. `find` sits in the delete family for `-delete`/`-exec`, but `hasRecursiveFlag` matches any predicate containing an "r", so `find src -type f -print` was reported as "Recursive deletion needs approval", `find /etc -name '*.conf'` denied critically, and `find . -name specpi` tripped guard self-tamper. Mutating `find` now reaches `filesystem.find-mutation`, which was unreachable behind the delete-family branch, and `clearlyReadOnly` shares the same predicate list.
|
|
98
110
|
- Classify complete environment enumeration however it is spelled (`printenv`, `declare -x`, `export -p`, `compgen -v`, bare `declare`) and recognize `/proc/<pid>/environ` and `/proc/<pid>/mem` shell reads. Strict asks about those findings; Guard does not claim comprehensive credential-read protection.
|
|
99
111
|
- Protect macOS system roots (`/System`, `/Library`, `/Applications`, `/Users/<name>`, `/Volumes/<name>`, `/private/etc`, `/cores`) and `.bash_profile`/`.zshenv`/`.zlogin`, without capturing the firmlinked `/System/Volumes/Data` user tree.
|
package/NPM_RELEASE.md
CHANGED
|
@@ -21,7 +21,7 @@ Verify the registry bytes and metadata immediately, then configure trusted publi
|
|
|
21
21
|
## Prepare a release
|
|
22
22
|
|
|
23
23
|
1. Select a version that has never appeared on npm. npm versions are immutable.
|
|
24
|
-
2. Update `package.json`, `CHANGELOG.md`, `README.md`, `site/index.html`,
|
|
24
|
+
2. Update `package.json`, `CHANGELOG.md`, `README.md`, `site/index.html`, `site/wiki/index.html`, `site/single-agent/index.html`, and the delegation guide to the same version. Keep historical changelog entries intact and remove stale unreleased-status wording.
|
|
25
25
|
3. For a stable release, add a dated changelog heading. Use a prerelease version when the package should not receive the `latest` dist-tag.
|
|
26
26
|
4. Install the pinned development tools without lifecycle scripts or peers:
|
|
27
27
|
|
|
@@ -92,6 +92,8 @@ specpi update
|
|
|
92
92
|
specpi doctor
|
|
93
93
|
```
|
|
94
94
|
|
|
95
|
+
Restart Pi after updating managed resources so it loads the new delegation runtime.
|
|
96
|
+
|
|
95
97
|
Remove managed resources before removing the CLI:
|
|
96
98
|
|
|
97
99
|
```bash
|
package/README.md
CHANGED
|
@@ -24,7 +24,17 @@ SpecPi adds task contracts, workflow controls, and a local improvement loop to P
|
|
|
24
24
|
|
|
25
25
|
Collection is disabled until explicitly enabled. Reports are sanitized, bounded, deduplicated by task, and never uploaded. Later evidence can reopen an item for review, but never restarts implementation automatically.
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
Version `0.12.0` adds experimental native delegation and a new technical site. Task cards, verification receipts and human outcome assessments remain part of the single-agent workflow. See the [release notes](CHANGELOG.md) for the change list.
|
|
28
|
+
|
|
29
|
+
## Optional delegation
|
|
30
|
+
|
|
31
|
+
The native extension creates actual Pi `AgentSession` subagents while the parent remains the sole writer. Use normal `pi` startup and the existing SpecPi install/update lifecycle. Delegation starts disabled, with its tool schema absent from model requests; human `/delegate on` enables the displayed envelope and `/delegate off` revokes outstanding work. Delegation checks required public SDK capabilities rather than an exact Pi version list, so compatible Pi updates do not require a SpecPi release. The installer bootstrap remains pinned to 0.84.4, and runtime validation is recorded separately.
|
|
32
|
+
|
|
33
|
+
Only `review` of a frozen artifact and `scout` analysis of a bounded evidence question are supported. Both can list, read and search exact selected text snapshots. Children have in-memory sessions and no ambient extensions, skills, AGENTS files, parent history, shell, writes, recursive delegation or live web access. Each receives assigned requirements and fixed constraints. There are at most two active workers, two jobs per batch, four batches and 32 SDK model invocations per Pi process. Reloads, session switches and off/on preserve counters; cancellation holds slots through SDK-visible stream/result and prompt settlement. Restart Pi to change the fixed working root or load a changed delegation runtime.
|
|
34
|
+
|
|
35
|
+
Pi owns the agent loop, authentication and OAuth. A fresh child `ModelRuntime` uses standard environment and `models.json` resolution; child transport/thinking budgets come from configured global settings, without project settings. Parent model/thinking are explicit with Pi clamping. Runtime-only authentication, selected extension-provider overrides, model-specific headers, startup proxy configuration and safe descriptor mismatches fail preflight without changing parent setup. Parent hooks, ephemeral settings and session affinity are not inherited. Each SDK invocation is admitted before dispatch; retries and compaction are disabled. SDK-visible streaming checks do not establish raw-transport, hidden-provider-attempt, invoice or memory caps, or prove remote execution has ended. Cost is unavailable. Research supports testing these purposes; no measured SpecPi quality, cost or speed advantage is claimed.
|
|
36
|
+
|
|
37
|
+
See the [delegation guide](docs/delegation/README.md), [tool protocol](docs/delegation/protocol.md), [research](docs/delegation/research.md), and [evaluation plan](docs/delegation/evaluation.md) for setup, examples, boundaries and evidence.
|
|
28
38
|
|
|
29
39
|
## Install
|
|
30
40
|
|
|
@@ -39,7 +49,7 @@ specpi install
|
|
|
39
49
|
specpi doctor
|
|
40
50
|
```
|
|
41
51
|
|
|
42
|
-
`plan` does not mutate the system. Install, update, and uninstall require confirmation unless `--yes` is supplied.
|
|
52
|
+
`plan` does not mutate the system. Install, update, and uninstall require confirmation unless `--yes` is supplied. Restart Pi after installation or updating SpecPi to load the delegation runtime.
|
|
43
53
|
|
|
44
54
|
<details>
|
|
45
55
|
<summary><strong>Pin a release or install from audited source</strong></summary>
|
|
@@ -47,14 +57,14 @@ specpi doctor
|
|
|
47
57
|
Pin the reusable CLI when installing a reviewed release, or inspect its plan without retaining a global CLI installation:
|
|
48
58
|
|
|
49
59
|
```bash
|
|
50
|
-
npm install --global specpi@0.
|
|
51
|
-
npx --package specpi@0.
|
|
60
|
+
npm install --global specpi@0.12.0
|
|
61
|
+
npx --package specpi@0.12.0 specpi plan
|
|
52
62
|
```
|
|
53
63
|
|
|
54
64
|
For a source-audited installation, clone the exact release:
|
|
55
65
|
|
|
56
66
|
```bash
|
|
57
|
-
git clone --branch v0.
|
|
67
|
+
git clone --branch v0.12.0 --depth 1 https://github.com/TannerMidd/SpecPi.git
|
|
58
68
|
cd SpecPi
|
|
59
69
|
./specpi plan
|
|
60
70
|
./specpi install
|
|
@@ -91,30 +101,30 @@ Direct `pi install npm:specpi` loads extensions, skills, and themes only. It doe
|
|
|
91
101
|
|
|
92
102
|
### Define and review work
|
|
93
103
|
|
|
94
|
-
| Interface
|
|
95
|
-
|
|
|
96
|
-
| `/task`
|
|
97
|
-
| `/scope`
|
|
98
|
-
| `/files`
|
|
99
|
-
| `/experiment` | Create detached worktrees with keep, binary patch export, and confirmed discard outcomes.
|
|
100
|
-
| `/challenge`
|
|
104
|
+
| Interface | Purpose |
|
|
105
|
+
| ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
106
|
+
| `/task` | Record the objective, fixed requirements, acceptance checks, expected paths, hypothesis, rollback, and non-goals on the current session branch. |
|
|
107
|
+
| `/scope` | Declare expected paths and report unacknowledged drift. |
|
|
108
|
+
| `/files` | Browse source, rendered Markdown, Git diffs, and bounded review comments. |
|
|
109
|
+
| `/experiment` | Create detached worktrees with keep, binary patch export, and confirmed discard outcomes. |
|
|
110
|
+
| `/challenge` | Review readiness through structured evidence, gaps, contradictions, and residual risk. |
|
|
101
111
|
|
|
102
112
|
### Improve from evidence
|
|
103
113
|
|
|
104
|
-
| Interface
|
|
105
|
-
|
|
|
106
|
-
| `/wishlist`
|
|
114
|
+
| Interface | Purpose |
|
|
115
|
+
| ---------------------- | ------------------------------------------------------------------------------------ |
|
|
116
|
+
| `/wishlist` | Store and curate privacy-minimized local capability-gap reports. |
|
|
107
117
|
| `/harness-improvement` | Select one qualified or review-needed item and authorize its bounded implementation. |
|
|
108
118
|
|
|
109
119
|
### Work inside Pi
|
|
110
120
|
|
|
111
|
-
| Interface
|
|
112
|
-
|
|
|
113
|
-
| `/spec`
|
|
114
|
-
| `/guard`
|
|
115
|
-
| Browser tools
|
|
116
|
-
| `specpi-spec` theme | Bring blueprint blue, technical greys, layered surfaces, and restrained semantic states into Pi.
|
|
117
|
-
| `specpi` CLI
|
|
121
|
+
| Interface | Purpose |
|
|
122
|
+
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
|
+
| `/spec` | Replace normal chrome with a technical run panel, seal live reasoning, hold streaming prose until complete, and keep tools collapsed. |
|
|
124
|
+
| `/guard` | Deny confirmed host-wide destructive calls and request approval for bounded risk classes. |
|
|
125
|
+
| Browser tools | Open an isolated Chromium context for rendered inspection and screenshots. |
|
|
126
|
+
| `specpi-spec` theme | Bring blueprint blue, technical greys, layered surfaces, and restrained semantic states into Pi. |
|
|
127
|
+
| `specpi` CLI | Plan, install, update, verify, and uninstall managed state with backups and rollback. |
|
|
118
128
|
|
|
119
129
|
`specpi-spec` is the default Pi theme, carrying the site's specification design through message surfaces, tools, Markdown, diffs, syntax highlighting, search, and the full thinking-level scale. **Existing valid theme preferences survive installation and updates.** The original `tea-house` theme remains bundled and selectable from `/settings`.
|
|
120
130
|
|
|
@@ -159,7 +169,7 @@ Use `/task clear` before recording an unrelated task. Within a session, repeated
|
|
|
159
169
|
|
|
160
170
|
Use `/experiment start` when an independent review or trial justifies a separate worktree. Open the reported path in another Pi session. SpecPi does not launch an agent, copy dirty base changes, commit, merge, or touch remotes.
|
|
161
171
|
|
|
162
|
-
SpecPi
|
|
172
|
+
SpecPi keeps one writer per working directory. Its experimental delegation adds bounded read-only Pi sessions. A parent determines what context a child receives and verifies what returns, so either handoff can omit a material constraint. Parallel writers also introduce conflicting assumptions and increase review work.
|
|
163
173
|
|
|
164
174
|
## Improvement loop
|
|
165
175
|
|
|
@@ -190,11 +200,11 @@ With collection enabled, `/wishlist outcome <gap-id>` records an explicit human
|
|
|
190
200
|
|
|
191
201
|
Every supported model-initiated Pi tool call is classified before execution. Select one mode at session start:
|
|
192
202
|
|
|
193
|
-
| Mode
|
|
194
|
-
|
|
|
195
|
-
| **Guard**
|
|
196
|
-
| **Strict** | Adds approval requests for mutation, execution, sensitive reads, and network activity.
|
|
197
|
-
| **Off**
|
|
203
|
+
| Mode | Behavior |
|
|
204
|
+
| ---------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
205
|
+
| **Guard** | Denies confirmed host-wide catastrophe and guard tampering, asks before Git destroys work, and otherwise remains quiet. |
|
|
206
|
+
| **Strict** | Adds approval requests for mutation, execution, sensitive reads, and network activity. |
|
|
207
|
+
| **Off** | Requires confirmation and applies only to the current session. |
|
|
198
208
|
|
|
199
209
|
Approvals apply to one exact call and one session. Only a structurally proven critical mutation locks the session. Parser uncertainty and invalid cleanup syntax are denied without locking later work.
|
|
200
210
|
|
package/SECURITY_MODEL.md
CHANGED
|
@@ -4,6 +4,36 @@ This document describes SpecPi's architecture-level security assumptions, enforc
|
|
|
4
4
|
|
|
5
5
|
## Threat model
|
|
6
6
|
|
|
7
|
+
### Experimental native delegation
|
|
8
|
+
|
|
9
|
+
Delegation is a native extension discovered through the ordinary Pi package and SpecPi lifecycle. Start `pi` normally; workers remain disabled and the model-facing schema absent until human activation. It adds no launcher, separate host process, service or trust override. Parent Pi retains normal resource discovery, trust decisions and proxy policy. Delegation checks required public SDK capabilities, not exact version identifiers. Missing session/runtime/settings/thinking APIs prevent activation; session construction and every request still enforce the tool, model and resource policy. API presence is not proof of every future SDK behavior or a passing integration receipt. Normal installation's minimum Pi version and 0.84.4 bootstrap pin are separate contracts.
|
|
10
|
+
|
|
11
|
+
Each worker is an SDK `createAgentSession` instance with in-memory session storage. Pi owns its model/tool loop. A fresh Pi `ModelRuntime` uses standard authentication, environment and `models.json` resolution. Child transport and thinking budgets come from configured global settings; project settings are not loaded. Parent model/thinking are explicit with Pi's supported-level clamping. SpecPi does not extract credentials, copy authentication state or inspect private runtime fields. Preflight rejects runtime-only authentication, selected extension-registered provider overrides, model-specific headers, startup proxy configuration and mismatched safe model descriptors because those routes cannot be faithfully reconstructed. These rejections leave parent configuration unchanged.
|
|
12
|
+
|
|
13
|
+
This is not full parent inference parity: parent request hooks, ephemeral runtime settings and session affinity are not automatically inherited. Keep delegation disabled if those inherited controls are required for every request. Children load no ambient extensions, skills, AGENTS files or parent transcript. Their only tools are selected-source list/read/literal-search; shell, write, arbitrary plugin, live-web and nested delegation tools are absent. Trusted parent extensions remain privileged in the same process. This is an application boundary, not an OS sandbox against malicious extensions.
|
|
14
|
+
|
|
15
|
+
Human `/delegate on` activates the displayed experimental calls/time policy. Admission supports only frozen `review` and bounded `scout` analysis. Each job receives its assigned requirement IDs and fixed global constraints. Review needs inline context or selected files; scouts need selected files. A declared parallel benefit requires useful parent work. Structural checks reject unsupported mode/benefit combinations and duplicate normalized questions; they do not prove semantic independence or improved outcomes. Command Guard still intercepts the parent tool; Strict approval binds its capability summary to the exact call and policy generation. Guard, task, scope, model, session and branch changes revoke old generations; normal leaf advancement does not. Model requests cannot enable delegation, change models, raise ceilings or grant tools. Parent acceptance does not mint human authorization, actual verification or wishlist selection.
|
|
16
|
+
|
|
17
|
+
Command Guard is optional for delegation. Human activation works when Guard is absent or Off; read-only snapshot tools, admission policy and resource limits are enforced by delegation itself. An installed Guard's Strict approvals and explicit locks still apply. A responder with an unready policy, or multiple responders, blocks activation with a specific error. Guard installation, removal or mode changes invalidate the enabled generation before further worker calls.
|
|
18
|
+
|
|
19
|
+
Guard responders reattach on each session startup, including reuse of an extension instance. Invalid commands, declined confirmations and no-op mode requests do not revoke delegation. Accepted changes and critical locks do; an asynchronous confirmation must still match the active Guard generation before it can commit.
|
|
20
|
+
|
|
21
|
+
The human activation choice follows subsequent parent provider/model and thinking selections. A selection revokes old generations and preflights the new host before automatically resuming dispatch; unsupported selections pause without falling back to the previous model. No job is automatically retried and no quota or settling slot is reset. New model generations invalidate old Strict approval fingerprints. Concurrent setup is bound to the latest selection and extension instance; completion cannot undo explicit off, Guard revocation or session/task/scope changes. Status distinguishes the requested on/off choice from whether dispatch is ready.
|
|
22
|
+
|
|
23
|
+
The broker reads only explicitly selected, bounded regular text files under the fixed canonical working root captured for the Pi process, with private-path, traversal, symlink/junction, hardlink, binary and size checks. Restart Pi to change this root or load a new delegation runtime version. It rechecks source identity/content and validates evidence line ranges. Each job sees only its selected IDs. These checks assume a trusted local filesystem: portable Node APIs do not establish an atomic OS snapshot against hostile filesystem races, and filenames cannot reveal secrets embedded in ordinary source files. No live web adapter is included.
|
|
24
|
+
|
|
25
|
+
Snapshot tool calls check canonical paths, identity and change metadata without rereading and hashing the entire selection. Capture, publication, collect, follow-up and resolve also verify content digests. Metadata-evasive changes are detected at the next digest boundary. Stream events use cheap epoch/model/context identity checks; full root, safe model-descriptor and provider-policy validation still precede requests, tools and accepted results. An in-place change during a dispatched stream may be detected at that next protected boundary.
|
|
26
|
+
|
|
27
|
+
Quotas cover SDK model invocations, logical deadlines, tool calls/bytes, snapshot bytes and observed responses. Admission occurs before each SDK dispatch. Provider/session retries and automatic compaction are disabled; one changed-input follow-up keeps original allowances and deadlines. Requested output is 8,192 tokens clamped to the model maximum. SDK streaming exposes response content for checks while the child runs, but bytes may already be buffered before an event. There are no hard raw-transport, hidden-provider-attempt, invoice or process-memory caps. Missing usage is explicit and cost is unavailable. Cancellation revokes broker grants and requests SDK abort; slots remain held through SDK-visible stream/result and prompt settlement. That does not prove physical remote execution has ended. A non-cooperative SDK/provider can require ending Pi; late results do not revive a job.
|
|
28
|
+
|
|
29
|
+
Incremental stream checks count recognized delta bytes and bound event structures, with exact full response checks at content/terminal boundaries. This trusts Pi's parsed event contract; it is not an exact per-event bound for arbitrary inconsistent SDK partials or a peak-memory guarantee. Usage preserves valid fields independently, reports never-supplied fields as null, and counts reporting coverage per field. Unknown SDK/setup/tool errors expose only generic diagnostics; code-owned policy failures retain specific messages. Synchronous and asynchronous teardown failures are contained without freeing unsettled slots.
|
|
30
|
+
|
|
31
|
+
The same controller and bounded idempotency journal remain in memory for the Pi process lifetime, including `/reload`, session switches and off/on. Successful spending and final-disposition receipts are retained (at most 20 under the fixed ceilings); cancellation and nonfinal assessments have a separate 128-entry oldest-first cache. Failures reserve no keys. Cache churn cannot evict spending receipts, reset quotas or disable cancellation. Limits are two active workers, four batches and 32 SDK invocations per process; two jobs and 8 invocations per batch; four invocations per logical job including follow-up. Invalidation does not reset these counters or release settling work. Completed reports retain their source bindings after the deadline, but child sessions are released at the deadline and later follow-up is rejected. These numeric limits are engineering choices, not empirical optima.
|
|
32
|
+
|
|
33
|
+
Shared snapshot text is destroyed once no job can continue; failed attempts retain original expiry cleanup. Packet/job-input references are dropped after owned workers settle. Metadata and digests remain for completed receipt freshness. Starting the next accepted batch retires previous reports; invalidation retires old generations after settlement. Retired batch objects are pruned, leaving only bounded state summaries and idempotency/usage counters. Replay cannot restore their reports, inputs, sessions or allowances. JavaScript strings, provider buffers and values already returned to Pi cannot be securely erased.
|
|
34
|
+
|
|
35
|
+
Selected context reaches the configured provider; normal parent tool results may be retained by Pi. Child sessions use memory only, with no child session database, raw metrics journal, credential copy, automatic resume or policy learning, or secure memory-erasure guarantee. See the [implemented protocol](docs/delegation/protocol.md) for states and receipts. SDK integration and synthetic-provider fixtures concern the runtime contract; their existence does not establish full parent inference parity or measured outcome gains.
|
|
36
|
+
|
|
7
37
|
### Assets
|
|
8
38
|
|
|
9
39
|
SpecPi aims to preserve:
|
package/THIRD_PARTY.md
CHANGED
|
@@ -1,7 +1,21 @@
|
|
|
1
1
|
# Third-party components
|
|
2
2
|
|
|
3
|
+
Delegation loads `clampThinkingLevel` from the Pi SDK when exported there, otherwise
|
|
4
|
+
from the public `@earendil-works/pi-ai/compat` subpath declared in Pi's
|
|
5
|
+
[package exports](https://github.com/earendil-works/pi/blob/main/packages/ai/package.json).
|
|
6
|
+
That fallback is guarded: a missing module or function leaves `/delegate` registered
|
|
7
|
+
and produces a capability error on activation, rather than an extension-load failure.
|
|
8
|
+
|
|
3
9
|
When Pi is absent, SpecPi can install the reviewed `@earendil-works/pi-coding-agent@0.84.4` npm package globally after confirmation. The package provides the `pi` executable, is installed with lifecycle scripts disabled, retains its upstream license, and remains external system state after SpecPi uninstall.
|
|
4
10
|
|
|
11
|
+
The experimental delegation extension uses native discovery and public Pi SDK `createAgentSession`, in-memory sessions and a fresh `ModelRuntime`, with **public SDK capability checks instead of an exact-version allowlist**. Compatible Pi updates can activate without a SpecPi release. Missing APIs are named in the activation error; actual SDK/provider behavior remains subject to runtime checks and regression testing. The installer floor and pinned 0.84.4 bootstrap package are unchanged. Pi supplies the conversation/tool loop, standard configuration, authentication and OAuth. The child receives the parent model and thinking level with Pi clamping; unsupported runtime-only authentication, selected extension-provider overrides and safe descriptor mismatches fail preflight. Children load no ambient extensions, skills, AGENTS files or parent history. Parent hooks, ephemeral settings and session affinity are not inherited. Each SDK invocation is admitted before dispatch, retries and compaction are disabled, and SDK-visible streams are checked without claiming hard raw-transport, hidden-attempt, memory or invoice bounds. SpecPi does not install or vendor another runtime, add a launcher/service, or introduce a direct `pi-agent-core` dependency or additional runtime library. Parent Pi startup, resources and trust remain unchanged.
|
|
12
|
+
|
|
13
|
+
The [Pi 0.85.0 release](https://github.com/earendil-works/pi/releases/tag/v0.85.0), published 4 September 2026, prompted the additional compatibility review. It does not change the installer pin or imply that every provider/setup has passed. The [compatibility record](docs/delegation/research.md#pi-compatibility-evidence) records completed validation independently of activation. Pi 0.85.1 also passes the isolated native/provider fixtures; its SDK session, agent-session and model-runtime modules match 0.85.0.
|
|
14
|
+
|
|
15
|
+
The child uses configured global transport/thinking budgets without loading project settings. Startup proxy configuration and model-specific headers are unsupported and fail preflight; parent configuration stays unchanged. These limits are part of the experimental SDK integration, not claims about what Pi itself supports.
|
|
16
|
+
|
|
17
|
+
Architecture charts are committed static SVG/CSV/JSON assets. Their optional authoring script uses ReportLab 4.4.9 (BSD license); it is not installed by SpecPi or shipped as a runtime dependency. The site runs without a plotting library or remote chart service.
|
|
18
|
+
|
|
5
19
|
SpecPi pins but does not vendor these Pi packages:
|
|
6
20
|
|
|
7
21
|
- `pi-web-access@0.25.0`
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
# Bounded delegation
|
|
2
|
+
|
|
3
|
+
Status: experimental in SpecPi 0.12.0. Disabled by default.
|
|
4
|
+
The package remains `specpi`; no separate npm package or background service is required.
|
|
5
|
+
|
|
6
|
+
SpecPi keeps one agent responsible for changes and acceptance. This extension adds
|
|
7
|
+
bounded, read-only workers for independent questions. It does not add a second writer,
|
|
8
|
+
an automatic planner, or a permanent team. The [research](research.md) supports testing
|
|
9
|
+
selective delegation; it does not establish that this implementation improves outcomes.
|
|
10
|
+
|
|
11
|
+
## Use normal Pi startup
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pi
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
The native extension is discovered through the ordinary Pi package and SpecPi
|
|
18
|
+
install/update lifecycle. Existing Pi startup, UI, resources, trust decisions and
|
|
19
|
+
proxy configuration remain Pi-owned. Delegation needs no alternate launcher, extra
|
|
20
|
+
SDK host, separate runtime process or new setup path.
|
|
21
|
+
|
|
22
|
+
Delegation checks **SDK capabilities, not an exact Pi version list**. New Pi versions
|
|
23
|
+
can activate when the required public session, runtime, settings and thinking APIs are
|
|
24
|
+
available. Missing APIs produce an error naming the unavailable capability; session
|
|
25
|
+
construction and each request still enforce the tool, model and resource policy.
|
|
26
|
+
The [compatibility record](research.md#pi-compatibility-evidence) records tested versions
|
|
27
|
+
separately; API presence does not prove every future SDK behavior. Normal SpecPi installation
|
|
28
|
+
keeps its separately documented host floor and 0.84.4 bootstrap pin.
|
|
29
|
+
Restart Pi after updating SpecPi to load a changed delegation
|
|
30
|
+
runtime version or change its working root. The broker uses the canonical working
|
|
31
|
+
directory captured for this Pi process.
|
|
32
|
+
|
|
33
|
+
Workers are actual SDK `createAgentSession` instances with in-memory session storage.
|
|
34
|
+
Pi runs their model/tool loop. SpecPi supplies admission, selected-source tools and
|
|
35
|
+
result checks; it does not implement a second conversation loop. Children load no
|
|
36
|
+
ambient extensions, skills, AGENTS files or parent session history.
|
|
37
|
+
|
|
38
|
+
```mermaid
|
|
39
|
+
flowchart LR
|
|
40
|
+
parent["Parent Pi agent · sole writer"] -->|bounded question| controller["SpecPi admission and receipts"]
|
|
41
|
+
controller --> child["Pi AgentSession · memory only"]
|
|
42
|
+
child -->|admitted SDK invocation| runtime["Pi ModelRuntime"]
|
|
43
|
+
child -->|selected list/read/search| broker["Snapshot broker"]
|
|
44
|
+
child -->|claims and evidence| parent
|
|
45
|
+
parent --> checks["Verification and final decision"]
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The child uses a fresh Pi `ModelRuntime` with standard authentication, environment
|
|
49
|
+
and `models.json` resolution. Its settings take transport and thinking budgets from
|
|
50
|
+
Pi's configured global settings; project settings are not loaded. The parent model and
|
|
51
|
+
thinking level are explicit. Pi's public thinking-level clamp determines the effective
|
|
52
|
+
child level, which the adapter verifies. Pi handles authentication
|
|
53
|
+
and OAuth; SpecPi does not copy credentials or inspect private runtime fields.
|
|
54
|
+
Preflight rejects runtime-only authentication, selected extension-registered provider
|
|
55
|
+
overrides, model-specific headers, startup proxy configuration and mismatched safe
|
|
56
|
+
model descriptors because the fresh runtime cannot faithfully reproduce those parent
|
|
57
|
+
routes. Parent configuration is left unchanged; an unsupported route disables delegation.
|
|
58
|
+
|
|
59
|
+
This is **not full parent inference parity**. Parent request hooks, ephemeral runtime
|
|
60
|
+
settings and session affinity are not automatically transferred. A workflow requiring
|
|
61
|
+
those inherited controls for every request must keep delegation disabled. Receipts
|
|
62
|
+
bind supported model and source descriptors; they cannot certify an unchanged remote
|
|
63
|
+
service or every configuration change behind a stable provider identity.
|
|
64
|
+
|
|
65
|
+
## Enable deliberately
|
|
66
|
+
|
|
67
|
+
In the interactive session:
|
|
68
|
+
|
|
69
|
+
```text
|
|
70
|
+
/delegate on
|
|
71
|
+
/delegate status
|
|
72
|
+
/delegate limits
|
|
73
|
+
/delegate cancel <batchId>
|
|
74
|
+
/delegate off
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
In Pi's terminal UI, a small panel above the editor shows each worker's ID, role,
|
|
78
|
+
state, elapsed time, model calls and source-tool calls. `1/2 workers` means one of
|
|
79
|
+
two slots is occupied; it is not a completion percentage. Model calls are SDK
|
|
80
|
+
invocations, not tokens. Completed jobs remain visible as **ready for review** until
|
|
81
|
+
the parent resolves them. A cancelled worker shows **stopping** while its SDK request
|
|
82
|
+
still occupies a slot. The panel disappears when no work needs attention.
|
|
83
|
+
|
|
84
|
+
Tool output uses compact summaries. Expand it with Pi's normal tool-output shortcut
|
|
85
|
+
to read answers, findings, evidence references and missing context. These remain
|
|
86
|
+
advisory worker reports. `/delegate status` shows the selected model, process budgets
|
|
87
|
+
and batch IDs; use an ID with `/delegate cancel <batchId>` to cancel that batch.
|
|
88
|
+
|
|
89
|
+
The panel follows Pi's theme and adapts to terminal width. It refreshes at most once
|
|
90
|
+
per second between lifecycle changes, stops its timer when workers settle and is
|
|
91
|
+
removed on shutdown or reload. It reads counters without checking files or providers;
|
|
92
|
+
it does not retain or display live child reasoning. RPC and print mode keep the same
|
|
93
|
+
structured tool responses and do not mount terminal widgets. The UI uses Pi's public
|
|
94
|
+
[widget and tool-rendering APIs](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md).
|
|
95
|
+
|
|
96
|
+
`on` grants the displayed experimental calls/time envelope. There is no model-call
|
|
97
|
+
permission toggle in the model-facing tool. `limits` is read-only; the shipped ceilings
|
|
98
|
+
cannot be raised by prompts. Turning delegation off, changing guard policy, switching
|
|
99
|
+
sessions or models, navigating branches, and changing task/scope bindings revoke the
|
|
100
|
+
current generation. Off/on, `/reload` and session switches do not reset the Pi process's
|
|
101
|
+
counters or free requests that are still settling. The same in-memory controller remains
|
|
102
|
+
in use; restart Pi to load changed runtime code. Normal conversation leaf advancement
|
|
103
|
+
does not invalidate workers.
|
|
104
|
+
|
|
105
|
+
Once enabled, delegation follows changes to the parent's provider, model and thinking
|
|
106
|
+
level without another `/delegate on`. Each change revokes old worker results, retains
|
|
107
|
+
unsettled slots and consumed quotas, and checks the new host before resuming dispatch.
|
|
108
|
+
Old jobs are not retried. An unsupported selection pauses delegation with a reason;
|
|
109
|
+
selecting a compatible model resumes it automatically. `/delegate off` remains off
|
|
110
|
+
through later model changes. Guard, task/scope and session lifecycle changes still
|
|
111
|
+
revoke activation. Status separates the user's `requested` choice from `enabled`
|
|
112
|
+
dispatch, with `updating` and `pauseReason` for model setup.
|
|
113
|
+
|
|
114
|
+
While delegation is off, its tool is removed from the parent's active tool list.
|
|
115
|
+
The command remains available, but the delegation tool schema is included in model
|
|
116
|
+
requests only after activation. Other active tools are preserved.
|
|
117
|
+
|
|
118
|
+
Command Guard is optional: delegation can run when Guard is absent or Off. When
|
|
119
|
+
active, Command Guard continues to intercept the parent `delegate` tool. Strict mode presents
|
|
120
|
+
the effective capability envelope and binds approval to its policy fingerprint and
|
|
121
|
+
the exact call. A locked, unready or ambiguous installed Guard still blocks activation;
|
|
122
|
+
the error identifies that state. `/delegate status` reports the observed Guard state.
|
|
123
|
+
Worker tool restrictions and resource limits are enforced independently of Guard. A worker result
|
|
124
|
+
cannot authorize a write, a commit, a deployment, or an improvement.
|
|
125
|
+
|
|
126
|
+
## Admit a specific purpose
|
|
127
|
+
|
|
128
|
+
| Mode | Required structure | Context and tools |
|
|
129
|
+
| -------- | ------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
|
|
130
|
+
| `review` | A frozen artifact, original requirements, relevant constraints and actual validation facts. The parent checks findings before acting. | Nonempty inline context or selected files; selected-source tools when files are supplied. |
|
|
131
|
+
| `scout` | A bounded evidence question with an independently checkable answer and a reason to separate the analysis. | At least one selected file; list/read/literal-search only, with no live web access. |
|
|
132
|
+
|
|
133
|
+
The packet declares one benefit: `independent_review` for review jobs, or
|
|
134
|
+
`parallel_analysis` / `context_isolation` for scout jobs. It includes a nonempty `why`.
|
|
135
|
+
`parallel_analysis` also requires useful `parentWork`; this may be empty for the other
|
|
136
|
+
benefits. A final review can be useful even when the parent waits. The controller checks
|
|
137
|
+
this structure, not whether the claimed benefit will materialize. Duplicate questions
|
|
138
|
+
after trimming and case normalization are rejected; distinct text is not proof of
|
|
139
|
+
independent work.
|
|
140
|
+
|
|
141
|
+
Each job names its assigned global requirement IDs and receives only those requirements,
|
|
142
|
+
plus the fixed decisions and non-goals. Transfer original constraints and evidence,
|
|
143
|
+
not the parent's reasoning or verdict. Do not delegate routine lookups, small understood
|
|
144
|
+
edits, coupled mutable work, generic second opinions or repeated role-based answers.
|
|
145
|
+
Use parallel parent tool calls when retrieval alone answers the question.
|
|
146
|
+
|
|
147
|
+
Workers have no shell, writes, arbitrary plugin tools or recursive delegation.
|
|
148
|
+
The parent obtains and selects source material. Model routing, automatic retries,
|
|
149
|
+
live-web access, monetary admission and automatic policy tuning remain unimplemented.
|
|
150
|
+
|
|
151
|
+
`/task` remains optional. Changes to an active task contract invalidate delegation,
|
|
152
|
+
but the parent is still responsible for faithfully transferring the task into the packet.
|
|
153
|
+
|
|
154
|
+
Use `delegate run`, continue useful parent work, then `collect`. Collection can wait
|
|
155
|
+
up to 30 seconds without another model request. Do not poll on a fixed schedule.
|
|
156
|
+
Check the referenced evidence and `resolve` each report, including per-finding
|
|
157
|
+
dispositions. One changed-input `follow_up` is available under the original deadline
|
|
158
|
+
and counters. [Protocol and executable examples](protocol.md) define the exact fields.
|
|
159
|
+
|
|
160
|
+
## Enforced resource envelope
|
|
161
|
+
|
|
162
|
+
| Resource | Ceiling |
|
|
163
|
+
| ------------------------- | ---------------------------------------------------------------------------- |
|
|
164
|
+
| Active worker requests | 2 per Pi process, including cancelled requests still settling |
|
|
165
|
+
| Batches / jobs | 4 batches per Pi process; one unresolved batch; 2 jobs per batch |
|
|
166
|
+
| SDK model invocations | 32 per Pi process, 8 per batch; 4 per logical job including follow-up |
|
|
167
|
+
| Follow-ups / retries | 1 changed-input follow-up per job; provider and session retries disabled |
|
|
168
|
+
| Time | 120 seconds per logical job; 300 seconds per batch, including follow-up time |
|
|
169
|
+
| Packet / child context | 256 KiB, checked before dispatch |
|
|
170
|
+
| Selected sources | 200 files and 8 MiB per batch |
|
|
171
|
+
| Tools | 12 calls and 64 KiB total returned JSON per logical job |
|
|
172
|
+
| Tool response | Bounded reads/search; 16 KiB per snapshot read/search response |
|
|
173
|
+
| Final report | 16 KiB; 8 findings; coverage for each assigned requirement |
|
|
174
|
+
| Requested provider output | 8,192 tokens, clamped to the model maximum |
|
|
175
|
+
| SDK-visible response | 256 KiB acceptance limit on observed response content |
|
|
176
|
+
|
|
177
|
+
These are conservative experiment limits, not empirically optimal values. Each SDK
|
|
178
|
+
invocation is admitted before dispatch. Automatic provider/session retries and
|
|
179
|
+
compaction are disabled, so they cannot silently create another SDK request.
|
|
180
|
+
Pi authentication preflight occurs before the model-invocation counter; these quotas
|
|
181
|
+
do not count or bound Pi's authentication/OAuth preparation.
|
|
182
|
+
|
|
183
|
+
The native SDK stream is observed while the child runs. Its response checks are not
|
|
184
|
+
hard bounds on raw transport, hidden provider attempts, billing or process memory.
|
|
185
|
+
Bytes may already be buffered before an SDK event becomes visible. Stream checks count
|
|
186
|
+
recognized deltas incrementally; full response validation occurs at content/terminal
|
|
187
|
+
boundaries, before tool execution and before publication. This relies on Pi's parsed
|
|
188
|
+
stream contract, not arbitrary inconsistent partial objects. Cheap lease checks run
|
|
189
|
+
per event; full root, model and provider-policy checks run at protected boundaries.
|
|
190
|
+
The parsed stream allows at most 64 content blocks, 512 structural nodes per partial,
|
|
191
|
+
65,536 events and 130 non-delta boundaries per invocation. These are implementation
|
|
192
|
+
ceilings, not empirically optimal values.
|
|
193
|
+
Cost is unavailable; available token fields are retained even when others are missing.
|
|
194
|
+
Never-reported fields are `null`, and per-field `usageReportedCalls` distinguishes
|
|
195
|
+
partial totals from complete accounting. This version cannot satisfy a policy
|
|
196
|
+
requiring those unsupported guarantees.
|
|
197
|
+
|
|
198
|
+
Cancellation revokes broker access and requests SDK abort. Slots remain held through
|
|
199
|
+
SDK-visible stream/result and prompt settlement; that does not prove physical remote
|
|
200
|
+
execution has ended. Late content is discarded. A non-cooperative SDK/provider can
|
|
201
|
+
require ending Pi; a timeout does not launch a replacement behind its back. Completed
|
|
202
|
+
reports keep their original source bindings after the deadline, but child sessions are
|
|
203
|
+
released at the deadline and later follow-up is rejected.
|
|
204
|
+
|
|
205
|
+
## Evidence and retention
|
|
206
|
+
|
|
207
|
+
Snapshots contain only exact selected regular text files under the fixed canonical
|
|
208
|
+
working root of the Pi process. The broker rejects traversal, symlinks/junctions,
|
|
209
|
+
hardlinks, binary content, private path
|
|
210
|
+
names, unknown source IDs, and oversized reads. Each worker can search only its own
|
|
211
|
+
selection. Capture verifies content digests. Each tool call checks canonical paths,
|
|
212
|
+
file identity and change metadata against the immutable capture, without rereading
|
|
213
|
+
all selected bytes. Publication, collection, follow-up and disposition also recheck
|
|
214
|
+
content digests. Changed source bindings require a fresh batch. A content change that
|
|
215
|
+
evades filesystem metadata is detected at the next digest check, not by each tool call.
|
|
216
|
+
|
|
217
|
+
This is a trusted-local-filesystem contract, not an operating-system sandbox or an
|
|
218
|
+
atomic filesystem snapshot. Filename restrictions cannot detect secrets embedded in
|
|
219
|
+
an ordinary source file. The parent must select appropriate material for the configured
|
|
220
|
+
model provider. Trusted Pi extensions remain privileged in the shared process despite
|
|
221
|
+
being absent from the child's resource loader. Only the submitted packet is inherited
|
|
222
|
+
automatically, not the parent transcript.
|
|
223
|
+
|
|
224
|
+
Each report separates worker claims from a host receipt: job/attempt identity, packet
|
|
225
|
+
digest, generation, result revision, route, state, counters and usage completeness.
|
|
226
|
+
Source references are validated for identity and line range; their truth is still a
|
|
227
|
+
verification question for the parent. `accept` records a parent assessment, not human
|
|
228
|
+
approval or verified task completion.
|
|
229
|
+
|
|
230
|
+
Child conversations use in-memory sessions. A final disposition, cancellation, exhausted
|
|
231
|
+
follow-up or original deadline releases the child; active SDK work retains its slot until
|
|
232
|
+
settlement. Teardown failures do not escape into Pi's event loop. Shared snapshot text
|
|
233
|
+
is destroyed once no job can continue, including failed jobs at their original deadline.
|
|
234
|
+
Packet and job-input references are dropped when owned workers settle. Source metadata
|
|
235
|
+
and digests still validate completed reports after text is destroyed. Starting the next
|
|
236
|
+
accepted batch retires the previous batch's reports; invalidation retires old generations
|
|
237
|
+
after their workers settle. Retired batches cannot be collected or followed up.
|
|
238
|
+
Only bounded state summaries, quota counters and the idempotency journal remain for
|
|
239
|
+
the Pi process lifetime, including `/reload` and session switches. They cannot recreate
|
|
240
|
+
retired work. SDK setup errors are replaced with generic diagnostics before reaching
|
|
241
|
+
status, command notices or model-facing errors; code-owned policy errors stay specific.
|
|
242
|
+
There is no child session database, raw metrics log,
|
|
243
|
+
credential copy, automatic resume, or secure memory-erasure claim. Normal Pi parent
|
|
244
|
+
tool results may be retained in its ordinary session. Turning delegation off does not
|
|
245
|
+
remove results already retained by Pi; review the session before sharing it.
|
|
246
|
+
|
|
247
|
+
## Implementation and evaluation
|
|
248
|
+
|
|
249
|
+
The modules under `extensions/delegation/` integrate Pi AgentSession with admission,
|
|
250
|
+
snapshot tools and closed result validation. There are no additional runtime dependencies
|
|
251
|
+
or separate host process. Compatibility requires verification against the supported
|
|
252
|
+
Pi SDK and ordinary package discovery, not merely a passing mock provider.
|
|
253
|
+
|
|
254
|
+
The evaluation plan separates deterministic runtime/security fixtures from comparative
|
|
255
|
+
task outcomes. Use isolated state and synthetic providers for contract tests; live
|
|
256
|
+
inference needs separate authorization. Such fixtures do not establish parity with
|
|
257
|
+
the parent's full inference pipeline or every production provider.
|
|
258
|
+
|
|
259
|
+
The [evaluation plan](evaluation.md) compares selective delegation with strong single
|
|
260
|
+
agents, serial workflows and always-delegate baselines using matched resource budgets.
|
|
261
|
+
No production quality, speed or cost improvement is claimed until those experiments run.
|
|
262
|
+
The [original design](design.md) and [target protocol](design-protocol.md) preserve the
|
|
263
|
+
broader proposal and its currently unimplemented proof obligations. The implemented
|
|
264
|
+
[calls/time protocol](protocol.md) is the source of truth for this release's behavior.
|