specpi 0.12.0 → 0.15.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 +27 -0
- package/NPM_RELEASE.md +2 -0
- package/README.md +20 -12
- package/SECURITY_MODEL.md +36 -0
- package/THIRD_PARTY.md +10 -2
- package/docs/browser-testing.md +76 -0
- package/docs/delegation/README.md +40 -4
- package/docs/delegation/protocol.md +13 -0
- package/extensions/browser/core.d.mts +64 -0
- package/extensions/browser/diagnostics.ts +275 -0
- package/extensions/browser/index.ts +349 -57
- package/extensions/browser/interactions.ts +118 -0
- package/extensions/browser/lifecycle.ts +28 -0
- package/extensions/command-guard/index.ts +4 -1
- package/extensions/delegation/core.mjs +13 -2
- package/extensions/delegation/extension.mjs +64 -7
- package/extensions/delegation/managed-files.mjs +1 -0
- package/extensions/delegation/native.mjs +8 -2
- package/extensions/delegation/presentation.mjs +2 -1
- package/extensions/delegation/protocol.mjs +13 -2
- package/extensions/delegation/provider.mjs +3 -2
- package/extensions/delegation/settings.mjs +140 -0
- package/extensions/spec.ts +9 -0
- package/extensions/tool-wishlist/index.ts +7 -1
- package/extensions/tool-wishlist/verification.mjs +2 -0
- package/extensions/workflow-controls/index.ts +2 -2
- package/package.json +15 -4
- package/scripts/check-package.mjs +47 -23
- package/scripts/check-pi-package.mjs +1 -0
- package/scripts/check-syntax.mjs +5 -0
- package/scripts/run-browser-tests.mjs +61 -0
- package/scripts/setup-browser-tests.mjs +38 -0
- package/scripts/site-browser.mjs +272 -0
- package/scripts/specpi.mjs +18 -0
- package/templates/AGENTS.md +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,32 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.15.0 - 2026-09-05
|
|
4
|
+
|
|
5
|
+
- 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.
|
|
6
|
+
- Add searchable extension-owned history, rename and reversible archive, and independent live conversations. Switching chats or folders preserves background work, approvals, drafts, attachments, usage, and view position. Stop/Disconnect target the selected conversation; parallel chats share workspace files rather than isolated worktrees.
|
|
7
|
+
- Add validated file/image attachment, screenshot paste/drop, bounded inline images, workspace code links and image previews, explicit queued-image recovery, visible transcript search/copy/export, usage/cost reporting, and native Git diff review. Branching and earlier-prompt editing preserve the source conversation and never undo code files or automatically send restored drafts.
|
|
8
|
+
- Start Command Guard in Guard mode in RPC without an unreadable startup selector; retain explicit `/guard` choices after readiness. Route task handoffs, challenge reports, and wishlist reports through RPC-capable dialogs, and disclose terminal-only display controls.
|
|
9
|
+
- Wait for legacy Pi startup fallbacks without approving early dialogs. Reset interrupted-run state on reconnect and never restore accepted prompts after a later refresh failure.
|
|
10
|
+
- Show installed Codex Usage and pi-usage (including Anthropic) reports in Chat's compact, expandable Limits row, separate from conversation tokens/cost. Reuse bounded Pi status events without provider queries, credential/cache reads, or changes to the default package list.
|
|
11
|
+
- Scope Chat's Pi-state filename restrictions to Pi/Chat storage so ordinary authentication, session, and history source files remain usable; retain global credential/key protection and canonical-path checks.
|
|
12
|
+
- Fix composer `/model` selection, read-only usage during active work, and stale Stop cleanup errors after reconnect. Align README and Pages installation examples with the separately versioned Chat artifact.
|
|
13
|
+
- Add dependency-free local VSIX packaging, isolated real-Pi and native VS Code tests, rendered Chat checks in CI, and editor-extension syntax/source-inventory coverage. No npm/Marketplace publication or automatic editor installation is included.
|
|
14
|
+
|
|
15
|
+
## 0.14.0 - 2026-09-05
|
|
16
|
+
|
|
17
|
+
- Raise delegation's default job timeout from 2 to 10 minutes, including the provider adapter. Add `/delegate timeout <minutes>` (1–60) and `reset` with an atomic, backed-up preference across restarts. Batch timeouts scale with the job window; call quotas, original follow-up deadlines and settling ownership remain unchanged. Restart Pi after updating the delegation runtime.
|
|
18
|
+
- Support platform aliases in the selected Pi agent-directory path while rejecting links inside preference state. Bound encoded backups separately so every accepted settings file can be saved repeatedly.
|
|
19
|
+
- Keep `.mts` declarations on LF checkouts and validate Pages permissions with either LF or CRLF input so release checks remain portable on Windows.
|
|
20
|
+
- Run timeout persistence fixtures across release platforms, isolate the package help probe, and verify that settings survive failed updates and every managed delegation file is removed on uninstall.
|
|
21
|
+
|
|
22
|
+
## 0.13.0 - 2026-09-05
|
|
23
|
+
|
|
24
|
+
- Add bounded, best-effort sanitized browser exceptions, console errors, failed requests, and HTTP error diagnostics with explicit cursor/loss/clear semantics and ephemeral retention.
|
|
25
|
+
- Add keyboard/chord input, native dropdown selection, and deadline-bounded page-condition waits; invalidate snapshot refs on application-driven navigation and preserve isolated cancellation cleanup.
|
|
26
|
+
- Strictly type-check the browser extension against pinned development Pi, TypeBox, Node, and Playwright declarations without eagerly loading the browser runtime or changing production optional peers.
|
|
27
|
+
- Add real registered-tool Chromium fixtures, repeatable responsive-site checks with fault-injection tests, and a shared CI browser gate required before Pages deployment. Preserve the pinned-Pi no-skips coverage gate.
|
|
28
|
+
- Document privacy/testing contracts and an evidence-backed decision to retain project-native TypeScript semantic navigation rather than add an LSP tool now.
|
|
29
|
+
|
|
3
30
|
## 0.12.0 - 2026-09-05
|
|
4
31
|
|
|
5
32
|
- 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.
|
package/NPM_RELEASE.md
CHANGED
|
@@ -22,6 +22,8 @@ Verify the registry bytes and metadata immediately, then configure trusted publi
|
|
|
22
22
|
|
|
23
23
|
1. Select a version that has never appeared on npm. npm versions are immutable.
|
|
24
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
|
+
If Chat changes are included, increment its independent version in `vscode/package.json` and `vscode/CHANGELOG.md`, and align the VSIX filenames and feature descriptions in the root README, extension README, and Pages guides. Build it with `npm --prefix vscode run package`, run `npm --prefix vscode run test:render` and the isolated `npm --prefix vscode run test:vsix`, and inspect the VSIX allowlist. The editor extension is not part of the npm tarball; creating this local artifact does not publish it or authorize a Marketplace release.
|
|
26
|
+
|
|
25
27
|
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
28
|
4. Install the pinned development tools without lifecycle scripts or peers:
|
|
27
29
|
|
package/README.md
CHANGED
|
@@ -24,17 +24,21 @@ 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.15.0` adds the separately packaged SpecPi Chat sidebar and RPC-compatible Guard startup and report dialogs. The terminal harness, optional read-only delegation, browser checks, and 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
|
+
|
|
31
|
+
The `vscode/` source contains **SpecPi Chat 0.3.1**, 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
|
+
|
|
33
|
+
From a repository checkout, build a local VSIX with `npm --prefix vscode run package`, then install `.specpi-test/vscode/specpi-chat-0.3.1.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.
|
|
30
34
|
|
|
31
|
-
|
|
35
|
+
## Optional delegation
|
|
32
36
|
|
|
33
|
-
|
|
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.
|
|
34
38
|
|
|
35
|
-
|
|
39
|
+
Delegation is **off by default**. In Pi, use `/delegate on` to enable it, `/delegate status` to inspect work, and `/delegate off` to revoke it. Research informed the design; SpecPi quality, speed, and cost gains remain unmeasured.
|
|
36
40
|
|
|
37
|
-
See
|
|
41
|
+
See [setup and limits](docs/delegation/README.md) or [how the research shaped the architecture](https://tannermidd.github.io/SpecPi/single-agent/).
|
|
38
42
|
|
|
39
43
|
## Install
|
|
40
44
|
|
|
@@ -57,14 +61,14 @@ specpi doctor
|
|
|
57
61
|
Pin the reusable CLI when installing a reviewed release, or inspect its plan without retaining a global CLI installation:
|
|
58
62
|
|
|
59
63
|
```bash
|
|
60
|
-
npm install --global specpi@0.
|
|
61
|
-
npx --package specpi@0.
|
|
64
|
+
npm install --global specpi@0.15.0
|
|
65
|
+
npx --package specpi@0.15.0 specpi plan
|
|
62
66
|
```
|
|
63
67
|
|
|
64
68
|
For a source-audited installation, clone the exact release:
|
|
65
69
|
|
|
66
70
|
```bash
|
|
67
|
-
git clone --branch v0.
|
|
71
|
+
git clone --branch v0.15.0 --depth 1 https://github.com/TannerMidd/SpecPi.git
|
|
68
72
|
cd SpecPi
|
|
69
73
|
./specpi plan
|
|
70
74
|
./specpi install
|
|
@@ -122,7 +126,7 @@ Direct `pi install npm:specpi` loads extensions, skills, and themes only. It doe
|
|
|
122
126
|
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
123
127
|
| `/spec` | Replace normal chrome with a technical run panel, seal live reasoning, hold streaming prose until complete, and keep tools collapsed. |
|
|
124
128
|
| `/guard` | Deny confirmed host-wide destructive calls and request approval for bounded risk classes. |
|
|
125
|
-
| Browser tools |
|
|
129
|
+
| Browser tools | Inspect isolated Chromium, diagnose errors, exercise keyboard/select/wait flows, and capture screenshots. |
|
|
126
130
|
| `specpi-spec` theme | Bring blueprint blue, technical greys, layered surfaces, and restrained semantic states into Pi. |
|
|
127
131
|
| `specpi` CLI | Plan, install, update, verify, and uninstall managed state with backups and rollback. |
|
|
128
132
|
|
|
@@ -169,7 +173,7 @@ Use `/task clear` before recording an unrelated task. Within a session, repeated
|
|
|
169
173
|
|
|
170
174
|
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.
|
|
171
175
|
|
|
172
|
-
SpecPi
|
|
176
|
+
SpecPi's default workflow uses one writer per working directory. Its experimental delegation adds bounded read-only Pi sessions. SpecPi Chat also supports independent conversations that you start explicitly; connected chats can continue concurrently in the same workspace. They share workspace files rather than receiving separate worktrees. A parent determines what context a delegated child receives and verifies what returns, so either handoff can omit a material constraint. Parallel writers also introduce conflicting assumptions and increase review work.
|
|
173
177
|
|
|
174
178
|
## Improvement loop
|
|
175
179
|
|
|
@@ -228,6 +232,10 @@ npm run format
|
|
|
228
232
|
npm run check
|
|
229
233
|
```
|
|
230
234
|
|
|
231
|
-
JavaScript and TypeScript use four-space indentation, explicit braced control flow, and one statement per line. The repository check enforces formatting, validates syntax, runs the Node test suite, executes registry-linked validators, and installs the exact npm tarball through an isolated lifecycle. Maintainers should follow [NPM_RELEASE.md](NPM_RELEASE.md) for release preparation and protected publication.
|
|
235
|
+
JavaScript and TypeScript use four-space indentation, explicit braced control flow, and one statement per line. The repository check enforces formatting, validates syntax, strictly type-checks the browser extension, runs the Node test suite, executes registry-linked validators, and installs the exact npm tarball through an isolated lifecycle. Maintainers should follow [NPM_RELEASE.md](NPM_RELEASE.md) for release preparation and protected publication.
|
|
236
|
+
|
|
237
|
+
For application testing, use `browser_diagnostics` alongside rendered inspection, and `browser_press`, `browser_select_option`, and `browser_wait_for` for keyboard, native dropdown, and asynchronous flows. Diagnostics are bounded and best-effort sanitized, not guaranteed secret-free or proof of application health.
|
|
238
|
+
|
|
239
|
+
Provision repository-local Chromium with `npm run setup:browser`, then run `npm run test:browser` and `npm run test:site:browser`. The required CI browser commands reject skipped coverage; Pages deployment waits for the same rendered check. See [browser testing](docs/browser-testing.md) for tool contracts, privacy limits, type-check scope, and the semantic-navigation assessment.
|
|
232
240
|
|
|
233
241
|
MIT licensed.
|
package/SECURITY_MODEL.md
CHANGED
|
@@ -30,6 +30,10 @@ Incremental stream checks count recognized delta bytes and bound event structure
|
|
|
30
30
|
|
|
31
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
32
|
|
|
33
|
+
Logical jobs default to 10 minutes and batches to 20 minutes. Human `/delegate timeout <minutes>` persists a whole-minute value from 1–60 while delegation is off; the batch window is twice the job window. Queue and follow-up time count from admission. SDK request timeouts and adapter abort timers use the remaining job window, with a 60-minute ceiling. Changes revoke old policy bindings, never extend old jobs or reset quotas/settling slots, and are absent from the model-facing schema. The effective time policy is included in Guard fingerprints and packet digests. Longer windows also allow longer in-memory input/child retention; they do not add calls, retries or billing guarantees.
|
|
34
|
+
|
|
35
|
+
Only the numeric timeout preference is persisted under `<agent-dir>/specpi/delegation/settings.json`; its previous content and SHA-256 are backed up in `settings.json.bak`. The human-selected agent directory is canonicalized once, including platform aliases; owned SpecPi subdirectories and preference files still reject links. Reads reject malformed/nonregular settings and are bounded to 4 KiB; the encoded backup has a separate 32 KiB bound. Saves use exclusive staging and atomic promotion. Invalid settings block activation. This store does not read Pi authentication, settings or sessions. The process loads it once; manual or other-process edits require restart, and concurrent saves are last-writer-wins. As with snapshots, this is a trusted-local-filesystem contract, not protection against hostile filesystem races. User-owned preferences survive uninstall. Requested file/directory modes are 0600/0700; Windows relies on profile ACLs.
|
|
36
|
+
|
|
33
37
|
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
38
|
|
|
35
39
|
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.
|
|
@@ -138,14 +142,46 @@ SpecPi launches managed Chromium in a fresh Playwright context. It does not atta
|
|
|
138
142
|
|
|
139
143
|
Snapshots, screenshots, page text, downloads, console output, and visual baselines may contain sensitive information. Default artifacts remain in SpecPi's private state directory. Explicit output publication is bounded and atomic, and existing artifacts or baselines are not replaced without explicit overwrite authorization.
|
|
140
144
|
|
|
145
|
+
Browser diagnostics collect active-page exceptions, error-level console messages, request failures, and HTTP error statuses before navigation. They retain only best-effort sanitized strings/metadata in memory: at most 200 records, 2 KiB per record, and 256 KiB total. Reads return at most 100 records and 30,000 serialized characters, with explicit truncation/loss/context metadata. Close, shutdown, and cancellation discard this buffer. Explicit clear discards all retained records, including filtered or unreturned ones. No headers, bodies, cookies, storage, console object expansion, raw stack dumps, HAR, or traces are captured. URL credentials/query/fragment and common sensitive strings/control sequences are removed before retention, but arbitrary secrets in free text or URL paths cannot be guaranteed detectable. Returned diagnostics are untrusted page output and enter the Pi conversation/model-provider boundary; ephemeral capture does not erase conversation evidence. No diagnostic files or uploads are created by the tool.
|
|
146
|
+
|
|
147
|
+
Keyboard, native-selection, and condition-wait tools accept bounded declarative inputs rather than arbitrary page scripts. Their whole-operation deadlines default to five seconds and cannot exceed thirty seconds. Deadlines include queue wait; cancellation (including pre-aborted calls) detaches the context and diagnostics, then allows at most one additional second for teardown settlement. Failed/stalled teardown warns that a process may remain and blocks new page operations until an explicit close retry succeeds. Failure messages do not echo Playwright call logs or entered values. They can still submit forms and trigger application effects, so use dedicated test data and authorization appropriate to the application.
|
|
148
|
+
|
|
141
149
|
The browser is not an operating-system or network sandbox. Use a container or VM for hostile applications and dedicated test accounts instead of personal authenticated sessions.
|
|
142
150
|
|
|
143
151
|
## Website and automation
|
|
144
152
|
|
|
153
|
+
The GitHub Pages workflow publishes the checked-in `site/` directory only after the shared browser test job succeeds for that checked-out revision. The loopback rendered-site server rejects traversal and symlink escapes. Tests block third-party requests, use a synthetic clipboard, and upload only public-site failure screenshots with three-day retention; no visual baselines are created automatically. Required browser commands fail rather than skip when prerequisites are unavailable. Strict no-emit browser type checking uses local pinned development declarations; third-party declaration bodies and other extension implementations are outside that scoped gate.
|
|
154
|
+
|
|
145
155
|
The GitHub Pages workflow publishes the checked-in `site/` directory. Its deploy job uses read-only repository contents access plus the Pages and identity-token permissions required for deployment. The local installer does not invoke that workflow or upload local configuration or state.
|
|
146
156
|
|
|
147
157
|
Repository checks, smoke tests, checksums, closed capability validators, and browser comparisons provide evidence for documented behavior. They reduce regression risk but do not prove the absence of vulnerabilities or establish cryptographic provenance for dependencies and releases.
|
|
148
158
|
|
|
159
|
+
## SpecPi Chat editor integration
|
|
160
|
+
|
|
161
|
+
The optional `vscode/` extension is distributed separately from the SpecPi npm installation. It runs in the VS Code workspace extension host and requires a trusted filesystem workspace before launching Pi or collecting file context. Only application-level settings choose executable paths; the launcher resolves native executables or known adjacent Pi JavaScript entry points and never executes a shell command string. Pi runs in the explicitly selected workspace with its normal installed extensions and provider configuration. VS Code trust does not replace Pi project trust, and the extension does not pass a flag to bypass Pi's trust decisions or Command Guard.
|
|
162
|
+
|
|
163
|
+
The sidebar uses Pi's documented JSONL RPC protocol. Pi owns provider authentication and tool execution; the extension does not read, copy, or manage authentication files. RPC model metadata is projected to display fields. Approvals and selection/input/editor requests are displayed as text and require an exact response for the requesting conversation's active request. Switching the displayed conversation preserves outstanding requests; background requests appear as needing input and never receive automatic approval. Stop, disconnect, runtime session transitions, and expiry cancel the affected conversation's requests. Expired or wrong-conversation responses cannot authorize later requests. In RPC, Command Guard starts in Guard mode without an initial selection dialog because Pi cannot read dialog responses until its startup handlers return; explicit `/guard` commands remain available after startup. Unsupported terminal-only components are disclosed rather than treated as functional editor controls.
|
|
164
|
+
|
|
165
|
+
Chat allows up to 90 seconds for an initial read-only RPC readiness probe before sending normal requests. This accommodates the 30-second startup fallback in older installed Guard versions without extending later request deadlines. Dialogs arriving before readiness receive cancellation only, never an approval or mode selection; the sidebar explains the limitation and retains a notice after connection. An extension with an unbounded startup dialog can still prevent readiness. Chat times out with recovery guidance instead of bypassing that extension or changing the user's installed harness.
|
|
166
|
+
|
|
167
|
+
The webview loads only packaged scripts/styles under a strict content security policy, forbids network resources, and renders model/tool/file text without interpreting embedded HTML. Images use validated data URLs under `img-src data:`; remote image URLs are never fetched by the webview. HTTP(S) links, including external image links, require a human click and pass through VS Code's external-link API. Clicked code references use a separate host action: paths are parsed, checked against the selected workspace, canonicalized, and restricted to regular non-sensitive files before VS Code opens the file and reveals a clamped line/range. Clicked workspace Markdown image references use the same path boundary and the image validator before a preview is returned. Arbitrary command and URI handlers are not executed. Raw paths preserve literal percent signs; Markdown link destinations and explicit local file URLs are decoded once before filesystem validation.
|
|
168
|
+
|
|
169
|
+
Text/code context requires an explicit file/selection action, is size-bounded, rejects binary and known sensitive paths, and checks canonical workspace containment. Workspace file suggestions enumerate a bounded set of names; choosing a suggestion invokes the same attachment validation before reading contents. Dropped workspace URIs are validated independently of their browser representation. Native image selection, clipboard images, and dropped image files are explicit attachment actions and may supply images from outside the selected workspace; filesystem image sources still require ordinary files and pass sensitive-path checks. Pi-state names such as `auth`, `trust`, `sessions`, `missions`, and `history` are reserved inside `.pi`, Chat-owned storage, and the configured Pi agent directory (including its canonical target), not arbitrary source directories. Global credential/key patterns remain blocked, including `auth.json`. Relative `PI_CODING_AGENT_DIR` overrides retain conservative name blocking because they resolve in the child workspace; use an absolute path or `~/…` to obtain directory-scoped filtering. These filename checks and format validators are not content-based secret detectors. Manually typed messages, ordinary files, and images may contain sensitive content, and the extension does not promise image metadata removal. Prompts and attachments are sent to the provider selected in Pi when the user sends them.
|
|
170
|
+
|
|
171
|
+
Image content is checked for supported PNG, JPEG, GIF, or WebP structure, declared MIME agreement, dimensions, and bounded base64 size. Each image is limited to 5 MiB, 16,384 pixels per side, and 40 million pixels. A prompt permits eight mixed attachments and 20 MiB of image bytes. The display retains at most 32 images / 20 MiB and reports omitted content; this is separate from Pi's persisted history. RPC records and buffered writes have independent 64 MiB caps. Recognized oversized history responses with a matching pending request are drained without accumulating the remaining bytes, then rejected without terminating Pi. The sidebar reports omitted history and remains usable; other oversized protocol records terminate the connection. A large historical transcript can exceed the RPC cap even when its original prompts were individually valid. Media caches remain in memory, are referenced by opaque identifiers while streaming, and are released as content is no longer retained. No remote image fetch, image processing service, or new image dependency is introduced. Pi/provider image limits and behavior remain upstream contracts.
|
|
172
|
+
|
|
173
|
+
Connection teardown resets transient run bookkeeping without discarding displayed partial text. An accepted prompt is never restored because a later status refresh failed, and the Refresh status action performs read-only RPC queries instead of replaying work. RPC request IDs correlate replies; they do not make retries idempotent. A lost connection before acknowledgement leaves the prompt outcome uncertain.
|
|
174
|
+
|
|
175
|
+
Image prompts require a model advertising image input. Rejection retains the unsent draft and attachments. Image-bearing slash commands are rejected because Pi extension commands can acknowledge execution without consuming image arguments. Stop clears queued work before aborting. Pi's queue-clear response contains text only, so Chat retains bounded in-memory image snapshots for its accepted queued submissions and restores them only after an exact, unambiguous match and an explicit user action. It does not attach discarded or unmatched images to a later prompt, automatically resend recovered work, or treat a missing acknowledgement as proof of failure.
|
|
176
|
+
|
|
177
|
+
Pi persists chats, including sent image blocks, in a workspace-specific directory under the extension's VS Code storage. A bounded atomic catalog stores only identifiers, titles, timestamps, archive flags, and paths of conversations created there. It never scans or opens terminal Pi history or writes transcripts to VS Code settings, logs, telemetry, or persistent webview state. Each conversation's live projection, draft, and attachment snapshots stay in memory with per-conversation bounds. Resume is limited to catalogued regular files inside the owned session directory. Renaming and reversible archiving change catalog metadata without opening transcripts; archiving neither deletes files nor stops a live process. Uninstalling the extension does not promise secure deletion of VS Code storage. POSIX permissions are requested where supported; Windows relies on the profile's ACLs. As elsewhere in SpecPi, local filesystem races, a compromised extension host, an untrusted Pi executable, or same-user tampering are outside the isolation guarantee.
|
|
178
|
+
|
|
179
|
+
Conversation edits select entries from the active Pi tree, revalidate the selection before mutation, and fork before the chosen user prompt. Exact original text and validated image blocks are captured before forking because Pi's fork response returns text only. The original conversation is retained, restored drafts require another send action, and conversation forks/clones do not restore or checkpoint workspace files. Actions are scoped to the active workspace, connection, and session revision. Export opens an unsaved Markdown document and Copy Conversation writes the visible Markdown to the OS clipboard only on explicit request. Both omit image bytes and represent images as placeholders; they do not reconstruct truncated or hidden history. Usage displays report Pi measurements, preserving unavailable values rather than inventing totals. The separate provider Limits row projects bounded strings from the known Codex Usage and pi-usage status keys, strips terminal/control sequences, and inserts text only. It does not parse numeric quotas, combine budgets with conversation cost, read provider credentials or usage-cache files, or add provider requests. Reports stay with their live connection and are cleared on disconnect, exit, and reconnect; refreshing and cache age remain upstream plugin responsibilities. Opening the details has no RPC or provider side effect. Existing `/usage` notifications and exact confirmation dialogs continue through the normal UI protocol; no automatic reset consumption or terminal-footer emulation is added.
|
|
180
|
+
|
|
181
|
+
Native change review reads VS Code's Git API, validates selected workspace paths, and opens the corresponding working-tree or staged view through the built-in diff/editor actions. It does not execute a shell command, stage, commit, discard, or restore files. Git integration availability and the filesystem race boundary still apply. The sidebar coordinator keeps independent Pi connections for explicitly opened conversations. Switching conversations or folders only changes the selected view. Stop and Disconnect target the selected process; extension-host shutdown stops all owned processes. User-initiated parallel conversations share their workspace files and are not isolated worktrees. Branching uses Pi's pre-runtime `--fork` to copy into a new owned session before extensions can write, then performs any active-branch or prompt selection there; the original process and session remain unchanged.
|
|
182
|
+
|
|
183
|
+
The extension introduces no network server, telemetry, runtime package dependency, or automatic model request when a view opens. Pi itself may contact its configured services when connected. Tests use synthetic homes, agent directories, providers, workspaces and profiles, plus an installed VS Code extension host; they do not access the user's live Pi credentials or conversations. Live provider availability and billing are outside the offline test evidence.
|
|
184
|
+
|
|
149
185
|
## Supply-chain assumptions
|
|
150
186
|
|
|
151
187
|
SpecPi pins reviewed executable package versions and the browser dependency graph. These controls improve repeatability and make version changes reviewable. They do not prove that a registry, publisher account, package artifact, downloaded browser, GitHub Action tag, or invoking host is uncompromised. Releases are not described as reproducible or cryptographically signed unless a future release adds and documents those mechanisms.
|
package/THIRD_PARTY.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# Third-party components
|
|
2
2
|
|
|
3
|
+
SpecPi Chat is a separate VS Code extension built with the public VS Code Webview View API and Pi `0.84.4`'s documented RPC protocol. VS Code and the installed Pi runtime retain their upstream licenses; neither is bundled in the VSIX. The extension and its ZIP/VSIX packager use Node built-ins and first-party source only, with no added runtime or development dependency. Its tests reuse the repository's pinned Playwright and Pi packages. Provider authentication, requests, billing, and normal Pi background behavior remain owned by the configured Pi runtime.
|
|
4
|
+
|
|
5
|
+
Chat's provider Limits row recognizes the public RPC `setStatus` presentation contracts of `@llblab/pi-codex-usage` **0.9.3** (`aa-codex-usage`) and `@sreetej510/pi-usage` **0.9.9** (`provider-usage`). Public source was checked at commits `1a97ee5560c5d7dd3b99ce34e2dcfe456592f8a0` and `9dee3b590f736c723011e3bc3717b3f0d6e8072b`, respectively. Tests reproduce their status/notification contracts through synthetic local Pi RPC, not live accounts or upstream provider requests. Text retains each plugin's quota semantics rather than converting or aggregating measurements. Neither plugin is bundled in the VSIX; this compatibility change does not install pi-usage or change SpecPi's existing package pins. Plugins retain ownership of authentication, caching, refresh/backoff, and explicit reset-consumption confirmation.
|
|
6
|
+
|
|
7
|
+
Chat uses Pi's image content blocks, conversation tree/fork/clone operations, and session statistics, plus the installed VS Code Git extension's public API for diff review. Version 0.3.0 retains a separate Pi process for each connected conversation and uses Pi's `--fork <session>` CLI option to copy branch history before runtime extensions initialize; the original live session remains untouched. Image container validation and base64 framing are first-party code; display uses VS Code's embedded browser image decoders. No image codec, provider SDK, export package, or remote image service is added. Local acceptance of PNG, JPEG, GIF, or WebP does not establish that every configured provider accepts the same formats or animation behavior. RPC records and buffered writes are capped at 64 MiB; image prompts and rendered media have separate, smaller limits documented in the extension guide.
|
|
8
|
+
|
|
3
9
|
Delegation loads `clampThinkingLevel` from the Pi SDK when exported there, otherwise
|
|
4
10
|
from the public `@earendil-works/pi-ai/compat` subpath declared in Pi's
|
|
5
11
|
[package exports](https://github.com/earendil-works/pi/blob/main/packages/ai/package.json).
|
|
@@ -33,7 +39,7 @@ The published `specpi` npm package declares the Pi host runtime modules its exte
|
|
|
33
39
|
- `@earendil-works/pi-tui` — terminal component, key, and width primitives
|
|
34
40
|
- `typebox` — the unscoped TypeBox package Pi bundles, used for tool input schemas
|
|
35
41
|
|
|
36
|
-
They retain their own copyright and license terms. SpecPi never vendors, bundles, or installs them; the Pi host supplies them at extension load time through loader aliases. Pi disables peer resolution for managed package installs, so a peer range would not enforce the host version there. Marking the peers optional also keeps an ordinary npm CLI installation from adding a second copy beside or inside SpecPi. The full managed installation enforces its supported Pi floor through the installer's `MIN_PI_VERSION` compatibility check, and the limited direct Pi mode documents the same host prerequisite.
|
|
42
|
+
They retain their own copyright and license terms. SpecPi never vendors, bundles, or installs them for end users; the Pi host supplies them at extension load time through loader aliases. Repository development additionally pins local copies for type checking and isolated test launches, as listed below. Pi disables peer resolution for managed package installs, so a peer range would not enforce the host version there. Marking the peers optional also keeps an ordinary npm CLI installation from adding a second copy beside or inside SpecPi. The full managed installation enforces its supported Pi floor through the installer's `MIN_PI_VERSION` compatibility check, and the limited direct Pi mode documents the same host prerequisite.
|
|
37
43
|
|
|
38
44
|
SpecPi also installs these exact browser-runtime packages from the reviewed `browser-runtime/package-lock.json`:
|
|
39
45
|
|
|
@@ -52,7 +58,9 @@ Repository development uses these exact, project-local formatting and linting pa
|
|
|
52
58
|
- `@typescript-eslint/parser@8.68.0` — MIT
|
|
53
59
|
- `typescript@6.0.3` — Apache-2.0
|
|
54
60
|
|
|
55
|
-
They are development-only dependencies, are not shipped by the SpecPi installer, and enforce the repository's JavaScript and TypeScript readability rules.
|
|
61
|
+
They are development-only dependencies, are not shipped by the SpecPi installer, and enforce the repository's JavaScript and TypeScript readability rules. TypeScript also runs strict no-emit checking for the browser extension and a bounded semantic-navigation fixture.
|
|
62
|
+
|
|
63
|
+
Browser type checking and registered-tool tests additionally use exact project-local development dependencies: `@earendil-works/pi-coding-agent@0.84.4`, `@earendil-works/pi-ai@0.84.4`, `@earendil-works/pi-tui@0.84.4` (MIT), `typebox@1.3.7` (MIT), `@types/node@22.20.1` (MIT), and `playwright@1.62.1` (Apache-2.0). These reuse the reviewed Pi/runtime versions, do not alter the optional production-peer contract, and are not bundled or installed by SpecPi. Direct development dependencies are pinned; this is not a claim that the development transitive graph is locked. The browser executable test runtime still uses the separately reviewed lockfile. `setup:browser` provisions only `.specpi-test/browser-runtime/`; its explicit `--with-deps` option invokes Playwright OS dependency setup on disposable Linux CI runners. No language-server executable or additional automation framework was added.
|
|
56
64
|
|
|
57
65
|
The GitHub Pages site vendors the Latin subsets of IBM Plex Sans and IBM Plex Mono. Copyright © 2017 IBM Corp. with Reserved Font Name "Plex". The font files are distributed under the SIL Open Font License 1.1; the required license text is included at `site/fonts/LICENSE.txt`.
|
|
58
66
|
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Browser application testing
|
|
2
|
+
|
|
3
|
+
## Agent workflow
|
|
4
|
+
|
|
5
|
+
1. `browser_open` opens an HTTP(S) page in isolated Chromium; `browser_snapshot` exposes bounded rendered text and namespaced control references.
|
|
6
|
+
2. Use click/fill and the tools below to exercise the application. Refresh snapshots after mutations or navigation (including application-initiated navigation). Targets use CSS, exact `text=`, or current snapshot refs; the first matching element is used.
|
|
7
|
+
3. Inspect `browser_diagnostics` after navigation and interactions, wait for explicit expected states, and capture screenshots at relevant viewports. No errors alone does not establish correct behavior.
|
|
8
|
+
4. `browser_close` discards the context and diagnostic buffer. No personal browser profile is attached.
|
|
9
|
+
|
|
10
|
+
| Tool | Examples and limits |
|
|
11
|
+
| --- | --- |
|
|
12
|
+
| `browser_press` | `{ "key": "Tab" }`, `{ "target": "#search", "key": "Enter" }`, `{ "key": "Shift+Tab" }`. A single key/chord on the target or current focus, not a script or macro. |
|
|
13
|
+
| `browser_select_option` | `{ "target": "#region", "options": [{ "label": "Europe" }] }`. Each of up to 50 options specifies exactly one value, label, or index. Multiple options require a native multiple select. Custom dropdowns use click/keyboard tools. |
|
|
14
|
+
| `browser_wait_for` | `{ "condition": "text", "target": "#status", "text": "Saved" }`, `{ "condition": "hidden", "target": "#spinner" }`, or `{ "condition": "url", "url": "http://localhost:3000/done" }`. Element conditions: attached, detached, visible, hidden, or exact text. Text is treated literally, not as a regular expression. URL matching is exact after HTTP(S) normalization, not glob matching. |
|
|
15
|
+
| `browser_diagnostics` | `{ "maxEntries": 50, "maxChars": 12000 }`. Optional category: pageerror, console, requestfailed, or http; cursor for incremental reads; explicit clear. Does not launch a browser just to read an empty buffer. |
|
|
16
|
+
|
|
17
|
+
Press, selection, and waits have an operation `timeoutMs` of 5,000 by default, bounded to 1–30,000, starting at admission (including queued time). Timeouts throw instead of returning success. Cancellation, including already-aborted calls, discards diagnostics and initiates browser close; teardown settlement has an additional one-second bound. A rejected/stalled close explicitly warns that a process may remain and blocks new page operations until an explicit `browser_close` retry succeeds. After normal cleanup the next browser operation can create a fresh context. New interaction failure messages omit Playwright call logs because those logs may echo entered values or selectors. There is no arbitrary page evaluation, automatic submission retry, or sleep-only tool. Existing open/click/fill/capture timeout behavior is unchanged.
|
|
18
|
+
|
|
19
|
+
## Diagnostic evidence and privacy
|
|
20
|
+
|
|
21
|
+
Listeners attach before first navigation. The active page supplies JavaScript exceptions, error-level console messages, transport failures, and HTTP responses with status at least 400. A 404/500 response is not a transport failure; these remain separate categories. Benign console logs are not collected. Coverage is not browser-wide: popup orchestration, workers not observed by the active page, and other contexts are outside this contract. Service workers remain blocked.
|
|
22
|
+
|
|
23
|
+
The in-memory buffer retains at most 200 records, 2 KiB per serialized record, and 256 KiB total. A read returns at most 100 records and 30,000 characters of serialized JSON. Metadata reports truncation, dropped records, cursor gaps, context changes, and whether more matching records remain. Returned structured details contain no duplicate raw records. A cursor includes a context identity and sequence; navigation preserves records with navigation numbers, while close/shutdown/abort reset the identity. A cursor from an old context reports a gap, not complete coverage.
|
|
24
|
+
|
|
25
|
+
`clear: true` atomically reads and clears **all** retained records, including filtered or unreturned records; `clearedRecords` reports that count. Do not clear until needed evidence has been consumed. Cursors older than cleared or evicted records report gaps.
|
|
26
|
+
|
|
27
|
+
Sanitation happens before retention: URL userinfo/query/fragment, common sensitive key/value patterns, authorization strings, terminal escape sequences and control characters are removed/redacted. No request headers, cookies, bodies, storage, console object expansion, or raw stack dumps are collected. Messages, URLs, fields, processing input, and serialized output are bounded. **Redaction is best-effort**, not a guarantee against arbitrary secrets in free-form messages or URL paths. Use dedicated test data/accounts. Returned records are untrusted page output, not instructions, and enter the agent conversation/model-provider boundary. Ephemeral capture is not a promise that tool results disappear from the conversation.
|
|
28
|
+
|
|
29
|
+
No diagnostic file, HAR, trace, telemetry, or upload is produced by the agent tool. Existing screenshots/baselines may contain sensitive content and keep their explicit publication/overwrite rules. Diagnostics and correct appearance are complementary evidence, not proof of application health or network/OS isolation.
|
|
30
|
+
|
|
31
|
+
## Reproducing development checks
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
npm install --ignore-scripts --omit=peer --no-package-lock
|
|
35
|
+
npm run check:types
|
|
36
|
+
node --test tests/browser-diagnostics.test.mjs tests/type-check.test.mjs tests/site-server.test.mjs
|
|
37
|
+
npm run setup:browser
|
|
38
|
+
npm run test:browser
|
|
39
|
+
npm run test:site:browser
|
|
40
|
+
npm run check
|
|
41
|
+
npm run check:pi-package
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
`setup:browser` copies the reviewed runtime manifests to `.specpi-test/browser-runtime/`, runs locked `npm ci` with scripts disabled, and explicitly downloads matching Chromium there. Linux CI additionally uses `npm run setup:browser -- --with-deps` to provision OS packages on its disposable runner. This does not change the installer or install dependencies globally on a user's machine. Run setup explicitly; browser tests do not acquire dependencies automatically. Missing prerequisites fail the required browser commands with setup guidance.
|
|
45
|
+
|
|
46
|
+
`npm test` retains explicit skips for the two opt-in Chromium suites so fast checks do not require browser binaries. Required CI commands activate those suites and reject any skipped coverage. The Pi registration test needs only project-local pinned Pi, not Chromium. `check:pi-package` reruns it through the separately provisioned pinned host and preserves its existing no-skips gate for selected Pi suites.
|
|
47
|
+
|
|
48
|
+
### Scoped types
|
|
49
|
+
|
|
50
|
+
`tsconfig.browser.json` checks exactly `extensions/browser/index.ts`, `diagnostics.ts`, `interactions.ts`, `lifecycle.ts`, and the `core.d.mts` boundary, with strict checking and no emit. It uses real pinned Pi, TypeBox, Playwright and Node declaration packages from development dependencies. Browser runtime imports remain lazy; Playwright imports in the extension are type-only. The `.mjs` image/runtime helper has narrow declarations backed by existing helper/runtime tests and an export-inventory regression; its JavaScript implementation is **not** fully type-checked. `skipLibCheck` skips third-party declarations, not first-party browser implementation errors. Other extensions remain syntax-checked, not advertised as type-checked. A negative fixture proves invalid key and Playwright API argument types fail without generated JavaScript.
|
|
51
|
+
|
|
52
|
+
### Rendered site
|
|
53
|
+
|
|
54
|
+
The committed loopback server serves only `site/` under `/SpecPi/`, on an ephemeral port, rejects traversal/symlink escapes, and is closed with the browser after tests. To inspect manually, run `node scripts/site-browser.mjs` and use the printed local URL; Ctrl+C closes the server.
|
|
55
|
+
|
|
56
|
+
The rendered matrix covers the home, wiki, and architecture pages at 1440×900, 834×1112, and 390×844. It tests local navigation, keyboard skip links, guard/cycle tabs and their ARIA states, disclosures, copy success/failure with a synthetic clipboard, loaded images/fonts, horizontal overflow, and unexpected runtime/network errors. Remote requests are rejected. Controlled page-local fault injection demonstrates that runtime exceptions, broken interactions, and overflow fail the same assertions without committing broken site content.
|
|
57
|
+
|
|
58
|
+
The shared browser workflow runs for CI and is a prerequisite of Pages deployment for the same revision. It uploads only public-site failure screenshots, retained for three days, from `.specpi-test/browser-artifacts/`. Tests never automatically create or replace visual baselines. A green DOM/interaction check is not a pixel-regression proof; screenshots still require visual review.
|
|
59
|
+
|
|
60
|
+
### Capability-registry boundary
|
|
61
|
+
|
|
62
|
+
The existing `local-browser-automation` registry entry and `browser-runtime-smoke` prove their historical rendering/image-comparison contract only. They are not expanded into claims that diagnostics or keyboard behavior have passed that closed validator. Browser diagnostics and interactions in SpecPi 0.13.0 are evidenced by dedicated registered-tool/Chromium tests and CI; no wishlist item is automatically selected or retired and no invented shipped version is entered in the registry.
|
|
63
|
+
|
|
64
|
+
## Semantic navigation assessment (R6)
|
|
65
|
+
|
|
66
|
+
**Decision: no new agent-facing semantic tool in this delivery.** Keep project-native compiler/tooling as the default and reassess after concrete larger-refactor friction.
|
|
67
|
+
|
|
68
|
+
Run `node --test tests/semantic-navigation.test.mjs`. The existing pinned TypeScript language service resolves an aliased cross-file definition, finds four related symbol references while excluding a shadowed name, and reports diagnostic 2345 after an on-disk argument-type mutation. The fixture creates temporary source files, supplies an explicit language-service host, and disposes it afterward. No language server, plugin, project configuration script, or new executable dependency is loaded. Windows path normalization was necessary when comparing compiler-returned reference paths; the test retains that check.
|
|
69
|
+
|
|
70
|
+
| Approach | Assessment |
|
|
71
|
+
| --- | --- |
|
|
72
|
+
| Project-native compiler and shell tools | Adequate baseline for this TypeScript fixture and the browser refactor. Text search is easy but cannot distinguish aliases/shadowing; compiler APIs can, at the cost of writing a small explicit host. No measured productivity improvement is claimed. |
|
|
73
|
+
| Narrow TypeScript adapter | Could expose bounded path/line/column results and reuse this compiler if repeated refactor work justifies a maintained tool contract. Not justified by this small fixture alone. |
|
|
74
|
+
| Broad LSP integration | Adds server acquisition/trust, process cleanup, language-specific configuration, and protocol complexity without evidence of a current need. Deferred, not implemented. |
|
|
75
|
+
|
|
76
|
+
Any later adapter proposal must define supported languages/projects, on-disk versus unsaved buffers, canonical project-root and symlink boundaries, out-of-root declaration references, generated/vendor exclusions, result/time limits, cancellation/subprocess cleanup, and a no-auto-edit/no-auto-install policy. Definitions in dependencies may need an explicit read-only opt-in. Repository plugins/config scripts are executable trust boundaries, not automatically safe navigation inputs.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bounded delegation
|
|
2
2
|
|
|
3
|
-
Status: experimental in SpecPi 0.
|
|
3
|
+
Status: experimental in SpecPi 0.15.0. Disabled by default.
|
|
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
|
|
@@ -94,8 +94,8 @@ structured tool responses and do not mount terminal widgets. The UI uses Pi's pu
|
|
|
94
94
|
[widget and tool-rendering APIs](https://github.com/earendil-works/pi/blob/main/packages/coding-agent/docs/extensions.md).
|
|
95
95
|
|
|
96
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;
|
|
98
|
-
|
|
97
|
+
permission toggle in the model-facing tool. `limits` is read-only; prompts cannot
|
|
98
|
+
change timeouts or raise other ceilings. Turning delegation off, changing guard policy, switching
|
|
99
99
|
sessions or models, navigating branches, and changing task/scope bindings revoke the
|
|
100
100
|
current generation. Off/on, `/reload` and session switches do not reset the Pi process's
|
|
101
101
|
counters or free requests that are still settling. The same in-memory controller remains
|
|
@@ -123,6 +123,42 @@ the error identifies that state. `/delegate status` reports the observed Guard s
|
|
|
123
123
|
Worker tool restrictions and resource limits are enforced independently of Guard. A worker result
|
|
124
124
|
cannot authorize a write, a commit, a deployment, or an improvement.
|
|
125
125
|
|
|
126
|
+
## Configure the timeout
|
|
127
|
+
|
|
128
|
+
The default is **10 minutes per logical job** (previously 2 minutes). In Pi:
|
|
129
|
+
|
|
130
|
+
```text
|
|
131
|
+
/delegate off
|
|
132
|
+
/delegate timeout 15
|
|
133
|
+
/delegate on
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`/delegate timeout` shows the current value; `/delegate timeout reset` saves the
|
|
137
|
+
10-minute default. Tab completion suggests common values. Use whole minutes from
|
|
138
|
+
**1 to 60**; there is no unlimited setting. The batch deadline is twice the job
|
|
139
|
+
timeout (20 minutes by default), so it does not truncate the configured job window.
|
|
140
|
+
Both deadlines start at batch admission and include queue and follow-up time; a
|
|
141
|
+
follow-up never gets a fresh timeout. Provider requests use the remaining job window,
|
|
142
|
+
not a separate two-minute cap. Provider-side limits may still end requests sooner.
|
|
143
|
+
|
|
144
|
+
Changes require delegation to be off, including when model setup is pending or paused.
|
|
145
|
+
They apply to this process and future Pi starts; they cannot extend old jobs, reset
|
|
146
|
+
call quotas or free requests still settling. `/delegate on`, `status`, `limits` and
|
|
147
|
+
Strict Guard policy summaries display the effective timeout. Only the human command
|
|
148
|
+
can configure it; the model-facing tool has no timeout-setting operation.
|
|
149
|
+
|
|
150
|
+
The preference is stored in `<agent-dir>/specpi/delegation/settings.json`, where
|
|
151
|
+
`<agent-dir>` is `PI_CODING_AGENT_DIR` or `~/.pi/agent`. It contains only
|
|
152
|
+
`{"schema":1,"timeoutMinutes":15}`. Saves atomically replace this file and keep the
|
|
153
|
+
previous contents plus their SHA-256 in `settings.json.bak`. No Pi settings,
|
|
154
|
+
authentication, sessions or history are read or changed by this preference store.
|
|
155
|
+
The human-selected agent directory is resolved once, supporting platform path aliases.
|
|
156
|
+
Preference files and SpecPi subdirectories must not be links. Malformed, oversized or
|
|
157
|
+
unreadable settings block activation rather than silently using another timeout. Repair them manually
|
|
158
|
+
and restart Pi. Manual edits and changes from another Pi process take effect on
|
|
159
|
+
restart; `/reload` preserves the current process policy and counters. The preference
|
|
160
|
+
survives uninstall as user-owned configuration.
|
|
161
|
+
|
|
126
162
|
## Admit a specific purpose
|
|
127
163
|
|
|
128
164
|
| Mode | Required structure | Context and tools |
|
|
@@ -165,7 +201,7 @@ and counters. [Protocol and executable examples](protocol.md) define the exact f
|
|
|
165
201
|
| Batches / jobs | 4 batches per Pi process; one unresolved batch; 2 jobs per batch |
|
|
166
202
|
| SDK model invocations | 32 per Pi process, 8 per batch; 4 per logical job including follow-up |
|
|
167
203
|
| Follow-ups / retries | 1 changed-input follow-up per job; provider and session retries disabled |
|
|
168
|
-
| Time |
|
|
204
|
+
| Time | 10 minutes per job by default (human configurable 1–60); batch twice that; queue/follow-up included |
|
|
169
205
|
| Packet / child context | 256 KiB, checked before dispatch |
|
|
170
206
|
| Selected sources | 200 files and 8 MiB per batch |
|
|
171
207
|
| Tools | 12 calls and 64 KiB total returned JSON per logical job |
|
|
@@ -36,6 +36,19 @@ data are rejected. The host creates identities and receipts; workers cannot supp
|
|
|
36
36
|
The protocol identifier `bounded-pi-sessions-v1` and inference contract
|
|
37
37
|
`pi-agent-session-v1` describe the host implementation, not model-selected options.
|
|
38
38
|
|
|
39
|
+
## Human timeout preference
|
|
40
|
+
|
|
41
|
+
Logical jobs default to 10 minutes; batches default to 20 minutes. Human
|
|
42
|
+
`/delegate timeout <minutes>` saves a whole-minute value from 1 to 60 while delegation
|
|
43
|
+
is off; `timeout reset` saves 10. The batch window is twice the job window.
|
|
44
|
+
Deadlines start at admission and include queue and the single follow-up. Provider
|
|
45
|
+
request timeouts and the adapter abort timer honor the remaining job window, capped
|
|
46
|
+
at 60 minutes. Settings changes invalidate old policy bindings without resetting
|
|
47
|
+
quotas or settling slots. No tool operation or packet field can change the timeout.
|
|
48
|
+
See the [configuration guide](README.md#configure-the-timeout) for persistence and
|
|
49
|
+
recovery. Status limits, packet digests and Guard fingerprints bind the effective
|
|
50
|
+
policy rather than assuming the shipped default.
|
|
51
|
+
|
|
39
52
|
## Submit a batch
|
|
40
53
|
|
|
41
54
|
After the human runs `/delegate on`, the parent calls the `delegate` tool:
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type * as Playwright from "playwright";
|
|
2
|
+
|
|
3
|
+
export type Viewport = { width: number; height: number };
|
|
4
|
+
export type ViewportInput = { preset?: "desktop" | "tablet" | "mobile"; width?: number; height?: number };
|
|
5
|
+
export type PngImage = Viewport & { data: Buffer };
|
|
6
|
+
export type BrowserRuntime = {
|
|
7
|
+
playwright: typeof Playwright;
|
|
8
|
+
PNG: {
|
|
9
|
+
new (size: Viewport): PngImage;
|
|
10
|
+
sync: { read(data: Buffer): PngImage; write(image: PngImage): Buffer };
|
|
11
|
+
};
|
|
12
|
+
pixelmatch: (
|
|
13
|
+
a: Buffer,
|
|
14
|
+
b: Buffer,
|
|
15
|
+
output: Buffer,
|
|
16
|
+
width: number,
|
|
17
|
+
height: number,
|
|
18
|
+
options: { threshold: number },
|
|
19
|
+
) => number;
|
|
20
|
+
};
|
|
21
|
+
export declare const MAX_CAPTURE_DIMENSION: number;
|
|
22
|
+
export declare const MAX_CAPTURE_PIXELS: number;
|
|
23
|
+
export declare const MAX_INLINE_IMAGE_BYTES: number;
|
|
24
|
+
export declare const MAX_PNG_BYTES: number;
|
|
25
|
+
export declare const VIEWPORT_PRESETS: Readonly<Record<"desktop" | "tablet" | "mobile", Viewport>>;
|
|
26
|
+
export declare const DEFAULT_DIFF_THRESHOLD: number;
|
|
27
|
+
export declare const DEFAULT_MAX_DIFF_PIXEL_RATIO: number;
|
|
28
|
+
export declare const MAX_VIEWPORT_PIXELS: number;
|
|
29
|
+
export declare function assertDistinctPaths(entries: Array<[string, string]>): void;
|
|
30
|
+
export declare function assertPngResourceBounds(data: Buffer, label?: string): Viewport;
|
|
31
|
+
export declare function readPngDimensions(data: Buffer, label?: string): Viewport;
|
|
32
|
+
export declare function comparePngBuffers(
|
|
33
|
+
a: Buffer,
|
|
34
|
+
b: Buffer,
|
|
35
|
+
runtime: Pick<BrowserRuntime, "PNG" | "pixelmatch">,
|
|
36
|
+
options?: { threshold?: number; maxDiffPixelRatio?: number },
|
|
37
|
+
): {
|
|
38
|
+
pass: boolean;
|
|
39
|
+
dimensionsMatch: boolean;
|
|
40
|
+
baseline: Viewport;
|
|
41
|
+
current: Viewport;
|
|
42
|
+
diffPixels: number;
|
|
43
|
+
diffPixelRatio: number;
|
|
44
|
+
diffBuffer: Buffer;
|
|
45
|
+
threshold: number;
|
|
46
|
+
maxDiffPixelRatio: number;
|
|
47
|
+
};
|
|
48
|
+
export declare function getAgentDir(extensionUrl: string): string;
|
|
49
|
+
export declare function loadBrowserRuntime(runtimeDir: string): Promise<BrowserRuntime>;
|
|
50
|
+
export declare function makeArtifactPath(
|
|
51
|
+
agentDir: string,
|
|
52
|
+
sessionId: string | undefined,
|
|
53
|
+
kind: string,
|
|
54
|
+
extension?: string,
|
|
55
|
+
): string;
|
|
56
|
+
export declare function sanitizeArtifactSegment(value: string): string;
|
|
57
|
+
export declare function normalizeBrowserUrl(value: string): string;
|
|
58
|
+
export declare function publishBuffer(
|
|
59
|
+
file: string,
|
|
60
|
+
data: Buffer,
|
|
61
|
+
options?: { overwrite?: boolean; signal?: AbortSignal },
|
|
62
|
+
): Promise<void>;
|
|
63
|
+
export declare function resolveUserPath(cwd: string, value: string, label?: string): string;
|
|
64
|
+
export declare function resolveViewport(input?: ViewportInput): Viewport;
|