specpi 0.15.0 → 0.16.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 +6 -0
- package/README.md +8 -8
- package/SECURITY_MODEL.md +4 -4
- package/docs/delegation/README.md +13 -6
- package/docs/delegation/design.md +1 -1
- package/docs/delegation/protocol.md +9 -5
- package/extensions/delegation/extension.mjs +26 -6
- package/extensions/delegation/native.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.16.0 - 2026-09-05
|
|
4
|
+
|
|
5
|
+
- Enable experimental read-only delegation by default at the first session start of each Pi process, including TUI, RPC, print and JSON modes. Startup preflights the host without launching workers or model inference; selective review/scout admission, Guard checks, source restrictions and resource ceilings remain unchanged.
|
|
6
|
+
- Keep `/delegate off` and safety revocations effective through reloads and session switches. `/delegate on` explicitly re-enables dispatch; restarting Pi reapplies the on default. Invalid settings, unsupported providers and locked, unready or ambiguous Guard policies still block activation.
|
|
7
|
+
- Update delegation guidance and release references, and add startup/default-on regression coverage alongside real-Pi lifecycle checks. Restart Pi after updating SpecPi to load the changed delegation runtime.
|
|
8
|
+
|
|
3
9
|
## 0.15.0 - 2026-09-05
|
|
4
10
|
|
|
5
11
|
- Add **SpecPi Chat 0.3.1**, a separately packaged VS Code sidebar with streamed Pi replies, safe Markdown, expanded thinking and collapsed tool output by default, model/thinking controls, exact approvals, and a compact composer. It reuses the user's Pi configuration without managing credentials or installing the harness.
|
package/README.md
CHANGED
|
@@ -24,19 +24,19 @@ 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
|
-
Version `0.
|
|
27
|
+
Version `0.16.0` enables bounded read-only delegation by default at Pi startup. One agent still owns edits and verification; worker use remains selective. SpecPi Chat, browser checks, and the human-selected improvement workflow remain available. See the [release notes](CHANGELOG.md) for the change list.
|
|
28
28
|
|
|
29
29
|
## SpecPi Chat for VS Code
|
|
30
30
|
|
|
31
|
-
The `vscode/` source contains **SpecPi Chat 0.3.
|
|
31
|
+
The `vscode/` source contains **SpecPi Chat 0.3.2**, a separately packaged native sidebar with streamed replies, tool results, file and image attachments, model/thinking controls, Pi approvals, and searchable workspace conversation history. Rename or archive chats, switch between independent live conversations, branch or edit an earlier prompt, search and export visible messages, inspect usage, and review changes through VS Code's native diff tools. Switching chats preserves background work, approvals, drafts, and attachments. Connected conversations share workspace files; use separate worktrees for isolated writers. Opening the sidebar does not start Pi.
|
|
32
32
|
|
|
33
|
-
From a repository checkout, build a local VSIX with `npm --prefix vscode run package`, then install `.specpi-test/vscode/specpi-chat-0.3.
|
|
33
|
+
From a repository checkout, build a local VSIX with `npm --prefix vscode run package`, then install `.specpi-test/vscode/specpi-chat-0.3.2.vsix` through **Extensions: Install from VSIX…**. See the [extension guide](https://github.com/TannerMidd/SpecPi/blob/main/vscode/README.md) for prerequisites, image/provider limits, commands, privacy, and testing. Pi owns provider authentication and tool execution. Stop and Disconnect affect the selected conversation only; branching does not undo code changes. The extension is separate from the SpecPi npm package and has not been published to a marketplace.
|
|
34
34
|
|
|
35
|
-
##
|
|
35
|
+
## Selective delegation
|
|
36
36
|
|
|
37
37
|
One agent owns edits and verifies results. Experimental delegation adds up to two read-only Pi workers: `review` checks a frozen artifact; `scout` answers a focused question using selected sources. Workers cannot write, run shell commands, browse the web, or delegate further.
|
|
38
38
|
|
|
39
|
-
Delegation is **
|
|
39
|
+
Delegation is **on by default at Pi startup**, subject to compatibility, settings, and Guard checks. Startup does not launch workers or model inference. Use `/delegate status` to inspect work and limits, `/delegate off` to revoke it, and `/delegate on` to re-enable it. Off and safety revocations survive reloads and session switches; restarting Pi reapplies the on default. Research informed the design; SpecPi quality, speed, and cost gains remain unmeasured.
|
|
40
40
|
|
|
41
41
|
See [setup and limits](docs/delegation/README.md) or [how the research shaped the architecture](https://tannermidd.github.io/SpecPi/single-agent/).
|
|
42
42
|
|
|
@@ -61,14 +61,14 @@ specpi doctor
|
|
|
61
61
|
Pin the reusable CLI when installing a reviewed release, or inspect its plan without retaining a global CLI installation:
|
|
62
62
|
|
|
63
63
|
```bash
|
|
64
|
-
npm install --global specpi@0.
|
|
65
|
-
npx --package specpi@0.
|
|
64
|
+
npm install --global specpi@0.16.0
|
|
65
|
+
npx --package specpi@0.16.0 specpi plan
|
|
66
66
|
```
|
|
67
67
|
|
|
68
68
|
For a source-audited installation, clone the exact release:
|
|
69
69
|
|
|
70
70
|
```bash
|
|
71
|
-
git clone --branch v0.
|
|
71
|
+
git clone --branch v0.16.0 --depth 1 https://github.com/TannerMidd/SpecPi.git
|
|
72
72
|
cd SpecPi
|
|
73
73
|
./specpi plan
|
|
74
74
|
./specpi install
|
package/SECURITY_MODEL.md
CHANGED
|
@@ -6,19 +6,19 @@ This document describes SpecPi's architecture-level security assumptions, enforc
|
|
|
6
6
|
|
|
7
7
|
### Experimental native delegation
|
|
8
8
|
|
|
9
|
-
Delegation is a native extension discovered through the ordinary Pi package and SpecPi lifecycle. Start `pi` normally;
|
|
9
|
+
Delegation is a native extension discovered through the ordinary Pi package and SpecPi lifecycle. Start `pi` normally; delegation is enabled by default at the first session start of each Pi process, including TUI, RPC, print and JSON modes, after settings, host and Guard checks. Startup launches no workers or model inference, but Pi-owned authentication/OAuth preparation may occur. The model-facing schema is present only while dispatch is enabled. 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
10
|
|
|
11
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
12
|
|
|
13
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
14
|
|
|
15
|
-
|
|
15
|
+
The startup default activates the documented experimental calls/time policy. Human `/delegate off` revokes it and `/delegate on` re-enables it. Off and safety revocations survive reloads and session switches; restarting Pi reapplies the on default. No on/off preference is persisted. 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
16
|
|
|
17
|
-
Command Guard is optional for delegation.
|
|
17
|
+
Command Guard is optional for delegation. 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
18
|
|
|
19
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
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.
|
|
21
|
+
The default or 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
22
|
|
|
23
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
24
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bounded delegation
|
|
2
2
|
|
|
3
|
-
Status: experimental in SpecPi 0.
|
|
3
|
+
Status: experimental in SpecPi 0.16.0. Enabled by default at Pi startup.
|
|
4
4
|
The package remains `specpi`; no separate npm package or background service is required.
|
|
5
5
|
|
|
6
6
|
SpecPi keeps one agent responsible for changes and acceptance. This extension adds
|
|
@@ -62,12 +62,16 @@ those inherited controls for every request must keep delegation disabled. Receip
|
|
|
62
62
|
bind supported model and source descriptors; they cannot certify an unchanged remote
|
|
63
63
|
service or every configuration change behind a stable provider identity.
|
|
64
64
|
|
|
65
|
-
##
|
|
65
|
+
## Control delegation
|
|
66
66
|
|
|
67
|
-
|
|
67
|
+
The first session start of each Pi process enables delegation after settings, host and
|
|
68
|
+
Guard checks, in TUI, RPC, print and JSON modes. Startup does not launch workers or
|
|
69
|
+
model inference. Preflight may perform Pi-owned authentication/OAuth preparation.
|
|
70
|
+
Use one agent for small or sequential work; delegate only a justified independent question.
|
|
71
|
+
|
|
72
|
+
In an interactive session:
|
|
68
73
|
|
|
69
74
|
```text
|
|
70
|
-
/delegate on
|
|
71
75
|
/delegate status
|
|
72
76
|
/delegate limits
|
|
73
77
|
/delegate cancel <batchId>
|
|
@@ -93,7 +97,10 @@ it does not retain or display live child reasoning. RPC and print mode keep the
|
|
|
93
97
|
structured tool responses and do not mount terminal widgets. The UI uses Pi's public
|
|
94
98
|
[widget and tool-rendering APIs](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md).
|
|
95
99
|
|
|
96
|
-
|
|
100
|
+
The startup default enables the documented experimental calls/time envelope. Use
|
|
101
|
+
`/delegate off` to revoke it and `/delegate on` to explicitly re-enable it. Off and
|
|
102
|
+
safety revocations survive `/reload` and session switches; restarting Pi reapplies the
|
|
103
|
+
on default. No on/off preference is written to disk. There is no model-call
|
|
97
104
|
permission toggle in the model-facing tool. `limits` is read-only; prompts cannot
|
|
98
105
|
change timeouts or raise other ceilings. Turning delegation off, changing guard policy, switching
|
|
99
106
|
sessions or models, navigating branches, and changing task/scope bindings revoke the
|
|
@@ -108,7 +115,7 @@ unsettled slots and consumed quotas, and checks the new host before resuming dis
|
|
|
108
115
|
Old jobs are not retried. An unsupported selection pauses delegation with a reason;
|
|
109
116
|
selecting a compatible model resumes it automatically. `/delegate off` remains off
|
|
110
117
|
through later model changes. Guard, task/scope and session lifecycle changes still
|
|
111
|
-
revoke activation. Status separates the
|
|
118
|
+
revoke activation. Status separates the default or human `requested` choice from `enabled`
|
|
112
119
|
dispatch, with `updating` and `pauseReason` for model setup.
|
|
113
120
|
|
|
114
121
|
While delegation is off, its tool is removed from the parent's active tool list.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Status: archived target architecture, not the implemented runtime contract.
|
|
4
4
|
|
|
5
|
-
The experimental implementation is part of `specpi` and is
|
|
5
|
+
The experimental implementation is part of `specpi` and is enabled by default at Pi startup.
|
|
6
6
|
Read the [implemented guide](README.md) and [calls/time protocol](protocol.md) for
|
|
7
7
|
supported commands, tested API compatibility, limits and trust assumptions. This
|
|
8
8
|
document preserves the original broader proposal, including unimplemented live-web,
|
|
@@ -4,8 +4,12 @@ This is the implemented in-process API. It has no HTTP listener, daemon, child p
|
|
|
4
4
|
or child session store. The broader [target protocol](design-protocol.md) remains a
|
|
5
5
|
proposal; its stronger transport/attempt/cost gates are not supplied by this version.
|
|
6
6
|
|
|
7
|
-
The extension loads through normal `pi` package discovery and
|
|
8
|
-
the
|
|
7
|
+
The extension loads through normal `pi` package discovery and enables delegation at
|
|
8
|
+
the first session start of each Pi process, including noninteractive modes. Startup
|
|
9
|
+
preflights the host but launches no workers or model inference; Pi-owned authentication
|
|
10
|
+
preparation may occur. `/delegate off` and safety revocations survive reloads and session
|
|
11
|
+
switches; `/delegate on` re-enables it, and restarting Pi reapplies the on default.
|
|
12
|
+
Compatibility is checked through required public SDK
|
|
9
13
|
capabilities; there is no exact-version allowlist. Missing APIs prevent activation and
|
|
10
14
|
are named in the error. The runtime also verifies the created session's thinking,
|
|
11
15
|
tools and streaming interface. Tested versions are evidence, not an activation gate.
|
|
@@ -18,7 +22,7 @@ overrides, model-specific headers, startup proxy configuration and safe model-de
|
|
|
18
22
|
mismatches fail preflight. Parent request hooks,
|
|
19
23
|
ephemeral runtime settings, session affinity and ambient resources are not inherited.
|
|
20
24
|
|
|
21
|
-
Command Guard is optional. Absent and Off states permit
|
|
25
|
+
Command Guard is optional. Absent and Off states permit activation; an installed
|
|
22
26
|
Guard's Strict approvals and explicit locks remain enforced. Unready or duplicate
|
|
23
27
|
Guard responders prevent activation with a specific error. Guard state changes revoke
|
|
24
28
|
the current delegation generation. Snapshot tools and resource limits are enforced
|
|
@@ -51,7 +55,7 @@ policy rather than assuming the shipped default.
|
|
|
51
55
|
|
|
52
56
|
## Submit a batch
|
|
53
57
|
|
|
54
|
-
|
|
58
|
+
When delegation is enabled, the parent calls the `delegate` tool:
|
|
55
59
|
|
|
56
60
|
```json
|
|
57
61
|
{
|
|
@@ -248,7 +252,7 @@ maximum. These are experiment limits, not research-derived optimal values.
|
|
|
248
252
|
Human off/on, task changes,
|
|
249
253
|
branch navigation, model selection, guard changes and reloads revoke old generations;
|
|
250
254
|
they do not create a new resource allowance. Normal parent turns do not revoke a job.
|
|
251
|
-
Model and thinking selections retain the human
|
|
255
|
+
Model and thinking selections retain the default or human activation choice. The extension
|
|
252
256
|
preflights the latest selected host and resumes dispatch automatically, without
|
|
253
257
|
replaying old jobs. Unsupported selections pause dispatch and report `pauseReason`;
|
|
254
258
|
a compatible selection resumes it. Status exposes `requested`, `updating` and
|
|
@@ -104,6 +104,7 @@ export function createDelegationExtension(
|
|
|
104
104
|
let detach = () => {};
|
|
105
105
|
|
|
106
106
|
let requested = false;
|
|
107
|
+
let startupActivation = true;
|
|
107
108
|
let requestedGuard;
|
|
108
109
|
let boundHost;
|
|
109
110
|
let pending;
|
|
@@ -166,7 +167,11 @@ export function createDelegationExtension(
|
|
|
166
167
|
panel?.update();
|
|
167
168
|
}
|
|
168
169
|
|
|
169
|
-
function invalidate(reason) {
|
|
170
|
+
function invalidate(reason, preserveStartupDefault = false) {
|
|
171
|
+
if (!preserveStartupDefault) {
|
|
172
|
+
startupActivation = false;
|
|
173
|
+
}
|
|
174
|
+
|
|
170
175
|
requested = false;
|
|
171
176
|
pending = undefined;
|
|
172
177
|
boundHost = undefined;
|
|
@@ -197,7 +202,7 @@ export function createDelegationExtension(
|
|
|
197
202
|
const isBound = () => issuedEpoch === bindingEpoch;
|
|
198
203
|
toolsReady = false;
|
|
199
204
|
prepareContext(undefined, true);
|
|
200
|
-
invalidate("runtime factory rebound");
|
|
205
|
+
invalidate("runtime factory rebound", true);
|
|
201
206
|
currentPi = pi;
|
|
202
207
|
currentContext = undefined;
|
|
203
208
|
const refreshSelection = async (ctx) => {
|
|
@@ -336,7 +341,7 @@ export function createDelegationExtension(
|
|
|
336
341
|
});
|
|
337
342
|
}
|
|
338
343
|
|
|
339
|
-
pi.on("session_start", (_event, ctx) => {
|
|
344
|
+
pi.on("session_start", async (_event, ctx) => {
|
|
340
345
|
if (!isBound()) {
|
|
341
346
|
return;
|
|
342
347
|
}
|
|
@@ -344,13 +349,27 @@ export function createDelegationExtension(
|
|
|
344
349
|
currentContext = ctx;
|
|
345
350
|
toolsReady = true;
|
|
346
351
|
panel?.bind(ctx);
|
|
347
|
-
invalidate("session started or resources reloaded");
|
|
352
|
+
invalidate("session started or resources reloaded", true);
|
|
348
353
|
try {
|
|
349
354
|
loadTimeout();
|
|
350
355
|
prepareContext(ctx, true);
|
|
356
|
+
// Consume the default only after synchronous preparation, which
|
|
357
|
+
// may revoke it. Off and safety events cancel it even before startup.
|
|
358
|
+
const activate = startupActivation;
|
|
359
|
+
startupActivation = false;
|
|
360
|
+
if (activate && isBound()) {
|
|
361
|
+
requested = true;
|
|
362
|
+
requestedGuard = getGuard();
|
|
363
|
+
await refreshSelection(ctx);
|
|
364
|
+
if (isBound() && requested && pauseReason) {
|
|
365
|
+
ctx.ui.notify(`Delegation paused: ${pauseReason}`, "warning");
|
|
366
|
+
}
|
|
367
|
+
}
|
|
351
368
|
} catch (error) {
|
|
352
369
|
pauseReason = publicErrorMessage(error);
|
|
353
370
|
ctx.ui.notify(`Delegation unavailable: ${pauseReason}`, "warning");
|
|
371
|
+
} finally {
|
|
372
|
+
startupActivation = false;
|
|
354
373
|
}
|
|
355
374
|
});
|
|
356
375
|
pi.on("session_shutdown", () => {
|
|
@@ -380,7 +399,8 @@ export function createDelegationExtension(
|
|
|
380
399
|
}
|
|
381
400
|
});
|
|
382
401
|
pi.registerCommand("delegate", {
|
|
383
|
-
description:
|
|
402
|
+
description:
|
|
403
|
+
"Control read-only delegation (on at Pi startup), inspect limits, or save timeout <minutes> (1–60; reset: 10)",
|
|
384
404
|
getArgumentCompletions: (prefix) =>
|
|
385
405
|
[
|
|
386
406
|
"on",
|
|
@@ -496,7 +516,7 @@ export function createDelegationExtension(
|
|
|
496
516
|
name: "delegate",
|
|
497
517
|
label: "Delegate",
|
|
498
518
|
description:
|
|
499
|
-
"Delegate an independent frozen review or substantial selected-source analysis to a real Pi child session.
|
|
519
|
+
"Delegate an independent frozen review or substantial selected-source analysis to a real Pi child session. Enabled by default at Pi startup; respect /delegate off and safety revocations. review: check artifacts against assigned requirements in fresh context; scout: answer a distinct evidence question over selected sources. Prefer one worker and parent-only execution for small, sequential or routine work. No shell, edits or live web. run returns immediately; collect waits for advisory evidence, then resolve findings after verification. One changed-input follow_up shares the original budget/deadline. Never grants permission or proves task completion.",
|
|
500
520
|
parameters: DELEGATE_SCHEMA,
|
|
501
521
|
...(presentation ? createToolRenderers(presentation) : {}),
|
|
502
522
|
execute: async (_id, input, signal, _update, ctx) => {
|
|
@@ -7,7 +7,7 @@ import { DelegationError } from "./errors.mjs";
|
|
|
7
7
|
import { createTimeoutStore } from "./settings.mjs";
|
|
8
8
|
|
|
9
9
|
const stateKey = Symbol.for("specpi.delegation.native.v1");
|
|
10
|
-
const revision =
|
|
10
|
+
const revision = 9;
|
|
11
11
|
|
|
12
12
|
export async function withPiCompatibility(sdk, loadCompatibility) {
|
|
13
13
|
if (typeof sdk.clampThinkingLevel === "function") {
|