specpi 0.11.2 → 0.13.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.
Files changed (41) hide show
  1. package/CHANGELOG.md +21 -1
  2. package/NPM_RELEASE.md +3 -1
  3. package/README.md +41 -29
  4. package/SECURITY_MODEL.md +36 -0
  5. package/THIRD_PARTY.md +18 -2
  6. package/docs/browser-testing.md +76 -0
  7. package/docs/delegation/README.md +264 -0
  8. package/docs/delegation/design-protocol.md +382 -0
  9. package/docs/delegation/design.md +525 -0
  10. package/docs/delegation/evaluation.md +307 -0
  11. package/docs/delegation/protocol.md +271 -0
  12. package/docs/delegation/research.md +216 -0
  13. package/extensions/browser/core.d.mts +64 -0
  14. package/extensions/browser/diagnostics.ts +275 -0
  15. package/extensions/browser/index.ts +349 -57
  16. package/extensions/browser/interactions.ts +118 -0
  17. package/extensions/browser/lifecycle.ts +28 -0
  18. package/extensions/command-guard/index.ts +118 -33
  19. package/extensions/delegation/core.mjs +772 -0
  20. package/extensions/delegation/errors.mjs +8 -0
  21. package/extensions/delegation/extension.mjs +475 -0
  22. package/extensions/delegation/index.ts +9 -0
  23. package/extensions/delegation/managed-files.mjs +13 -0
  24. package/extensions/delegation/native.mjs +155 -0
  25. package/extensions/delegation/presentation.mjs +315 -0
  26. package/extensions/delegation/protocol.mjs +296 -0
  27. package/extensions/delegation/provider.mjs +689 -0
  28. package/extensions/delegation/snapshot.mjs +532 -0
  29. package/extensions/delegation/worker.mjs +218 -0
  30. package/extensions/tool-wishlist/verification.mjs +1 -0
  31. package/extensions/workflow-controls/index.ts +5 -1
  32. package/package.json +17 -4
  33. package/scripts/check-package.mjs +29 -3
  34. package/scripts/check-pi-package.mjs +5 -0
  35. package/scripts/check-syntax.mjs +61 -0
  36. package/scripts/run-browser-tests.mjs +61 -0
  37. package/scripts/setup-browser-tests.mjs +38 -0
  38. package/scripts/site-browser.mjs +272 -0
  39. package/scripts/specpi.mjs +24 -0
  40. package/site/logo.svg +1 -9
  41. package/templates/AGENTS.md +1 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.13.0 - 2026-09-05
4
+
5
+ - Add bounded, best-effort sanitized browser exceptions, console errors, failed requests, and HTTP error diagnostics with explicit cursor/loss/clear semantics and ephemeral retention.
6
+ - 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.
7
+ - 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.
8
+ - 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.
9
+ - Document privacy/testing contracts and an evidence-backed decision to retain project-native TypeScript semantic navigation rather than add an LSP tool now.
10
+
11
+ ## 0.12.0 - 2026-09-05
12
+
13
+ - 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.
14
+ - Show live worker state, elapsed time and call counts above the editor, with expandable findings and evidence in tool results.
15
+ - 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.
16
+ - Bound snapshot retention, source-tool responses and replay records. Preserve spending receipts while pruning recent cancellation and nonfinal assessment responses.
17
+ - 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.
18
+ - Share the delegation install inventory across installer and package checks, test imports from the installed tree, and exclude nested dependencies from source syntax checks.
19
+ - 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.
20
+
21
+ 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.
22
+
3
23
  ## 0.11.2 - 2026-09-04
4
24
 
5
25
  - 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 +113,7 @@
93
113
  - 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
114
  - 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
115
  - 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 *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.
116
+ - 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
117
  - 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
118
  - 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
119
  - 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`, and `site/wiki/index.html` to the same version.
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,15 @@ 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
- This README documents `0.11.2`, including task cards, verification receipts, and human outcome assessments. See the [release notes](CHANGELOG.md#0112---2026-09-04) for the complete change list.
27
+ Version `0.13.0` adds browser diagnostics, keyboard and native dropdown interactions, bounded condition waits, scoped TypeScript checking, and repeatable rendered-site tests. Experimental delegation, 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
+ 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.
32
+
33
+ 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.
34
+
35
+ See [setup and limits](docs/delegation/README.md) or [how the research shaped the architecture](https://tannermidd.github.io/SpecPi/single-agent/).
28
36
 
29
37
  ## Install
30
38
 
@@ -39,7 +47,7 @@ specpi install
39
47
  specpi doctor
40
48
  ```
41
49
 
42
- `plan` does not mutate the system. Install, update, and uninstall require confirmation unless `--yes` is supplied. After installation, run `/reload` in Pi.
50
+ `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
51
 
44
52
  <details>
45
53
  <summary><strong>Pin a release or install from audited source</strong></summary>
@@ -47,14 +55,14 @@ specpi doctor
47
55
  Pin the reusable CLI when installing a reviewed release, or inspect its plan without retaining a global CLI installation:
48
56
 
49
57
  ```bash
50
- npm install --global specpi@0.11.2
51
- npx --package specpi@0.11.2 specpi plan
58
+ npm install --global specpi@0.13.0
59
+ npx --package specpi@0.13.0 specpi plan
52
60
  ```
53
61
 
54
62
  For a source-audited installation, clone the exact release:
55
63
 
56
64
  ```bash
57
- git clone --branch v0.11.2 --depth 1 https://github.com/TannerMidd/SpecPi.git
65
+ git clone --branch v0.13.0 --depth 1 https://github.com/TannerMidd/SpecPi.git
58
66
  cd SpecPi
59
67
  ./specpi plan
60
68
  ./specpi install
@@ -91,30 +99,30 @@ Direct `pi install npm:specpi` loads extensions, skills, and themes only. It doe
91
99
 
92
100
  ### Define and review work
93
101
 
94
- | Interface | Purpose |
95
- | --- | --- |
96
- | `/task` | Record the objective, fixed requirements, acceptance checks, expected paths, hypothesis, rollback, and non-goals on the current session branch. |
97
- | `/scope` | Declare expected paths and report unacknowledged drift. |
98
- | `/files` | Browse source, rendered Markdown, Git diffs, and bounded review comments. |
99
- | `/experiment` | Create detached worktrees with keep, binary patch export, and confirmed discard outcomes. |
100
- | `/challenge` | Review readiness through structured evidence, gaps, contradictions, and residual risk. |
102
+ | Interface | Purpose |
103
+ | ------------- | ----------------------------------------------------------------------------------------------------------------------------------------------- |
104
+ | `/task` | Record the objective, fixed requirements, acceptance checks, expected paths, hypothesis, rollback, and non-goals on the current session branch. |
105
+ | `/scope` | Declare expected paths and report unacknowledged drift. |
106
+ | `/files` | Browse source, rendered Markdown, Git diffs, and bounded review comments. |
107
+ | `/experiment` | Create detached worktrees with keep, binary patch export, and confirmed discard outcomes. |
108
+ | `/challenge` | Review readiness through structured evidence, gaps, contradictions, and residual risk. |
101
109
 
102
110
  ### Improve from evidence
103
111
 
104
- | Interface | Purpose |
105
- | --- | --- |
106
- | `/wishlist` | Store and curate privacy-minimized local capability-gap reports. |
112
+ | Interface | Purpose |
113
+ | ---------------------- | ------------------------------------------------------------------------------------ |
114
+ | `/wishlist` | Store and curate privacy-minimized local capability-gap reports. |
107
115
  | `/harness-improvement` | Select one qualified or review-needed item and authorize its bounded implementation. |
108
116
 
109
117
  ### Work inside Pi
110
118
 
111
- | Interface | Purpose |
112
- | --- | --- |
113
- | `/spec` | Replace normal chrome with a technical run panel, seal live reasoning, hold streaming prose until complete, and keep tools collapsed. |
114
- | `/guard` | Deny confirmed host-wide destructive calls and request approval for bounded risk classes. |
115
- | Browser tools | Open an isolated Chromium context for rendered inspection and screenshots. |
116
- | `specpi-spec` theme | Bring blueprint blue, technical greys, layered surfaces, and restrained semantic states into Pi. |
117
- | `specpi` CLI | Plan, install, update, verify, and uninstall managed state with backups and rollback. |
119
+ | Interface | Purpose |
120
+ | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
121
+ | `/spec` | Replace normal chrome with a technical run panel, seal live reasoning, hold streaming prose until complete, and keep tools collapsed. |
122
+ | `/guard` | Deny confirmed host-wide destructive calls and request approval for bounded risk classes. |
123
+ | Browser tools | Inspect isolated Chromium, diagnose errors, exercise keyboard/select/wait flows, and capture screenshots. |
124
+ | `specpi-spec` theme | Bring blueprint blue, technical greys, layered surfaces, and restrained semantic states into Pi. |
125
+ | `specpi` CLI | Plan, install, update, verify, and uninstall managed state with backups and rollback. |
118
126
 
119
127
  `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
128
 
@@ -159,7 +167,7 @@ Use `/task clear` before recording an unrelated task. Within a session, repeated
159
167
 
160
168
  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
169
 
162
- SpecPi does not install subagent orchestration. Keep one writer per working directory. A parent agent determines what context a child receives and summarizes what returns, so either handoff can omit a material constraint. Parallel writers also introduce conflicting assumptions and increase review work.
170
+ 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
171
 
164
172
  ## Improvement loop
165
173
 
@@ -190,11 +198,11 @@ With collection enabled, `/wishlist outcome <gap-id>` records an explicit human
190
198
 
191
199
  Every supported model-initiated Pi tool call is classified before execution. Select one mode at session start:
192
200
 
193
- | Mode | Behavior |
194
- | --- | --- |
195
- | **Guard** | Denies confirmed host-wide catastrophe and guard tampering, asks before Git destroys work, and otherwise remains quiet. |
196
- | **Strict** | Adds approval requests for mutation, execution, sensitive reads, and network activity. |
197
- | **Off** | Requires confirmation and applies only to the current session. |
201
+ | Mode | Behavior |
202
+ | ---------- | ----------------------------------------------------------------------------------------------------------------------- |
203
+ | **Guard** | Denies confirmed host-wide catastrophe and guard tampering, asks before Git destroys work, and otherwise remains quiet. |
204
+ | **Strict** | Adds approval requests for mutation, execution, sensitive reads, and network activity. |
205
+ | **Off** | Requires confirmation and applies only to the current session. |
198
206
 
199
207
  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
208
 
@@ -218,6 +226,10 @@ npm run format
218
226
  npm run check
219
227
  ```
220
228
 
221
- 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.
229
+ 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.
230
+
231
+ 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.
232
+
233
+ 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.
222
234
 
223
235
  MIT licensed.
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:
@@ -108,10 +138,16 @@ SpecPi launches managed Chromium in a fresh Playwright context. It does not atta
108
138
 
109
139
  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.
110
140
 
141
+ 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.
142
+
143
+ 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.
144
+
111
145
  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.
112
146
 
113
147
  ## Website and automation
114
148
 
149
+ 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.
150
+
115
151
  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.
116
152
 
117
153
  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.
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`
@@ -19,7 +33,7 @@ The published `specpi` npm package declares the Pi host runtime modules its exte
19
33
  - `@earendil-works/pi-tui` — terminal component, key, and width primitives
20
34
  - `typebox` — the unscoped TypeBox package Pi bundles, used for tool input schemas
21
35
 
22
- 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.
36
+ 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.
23
37
 
24
38
  SpecPi also installs these exact browser-runtime packages from the reviewed `browser-runtime/package-lock.json`:
25
39
 
@@ -38,7 +52,9 @@ Repository development uses these exact, project-local formatting and linting pa
38
52
  - `@typescript-eslint/parser@8.68.0` — MIT
39
53
  - `typescript@6.0.3` — Apache-2.0
40
54
 
41
- They are development-only dependencies, are not shipped by the SpecPi installer, and enforce the repository's JavaScript and TypeScript readability rules.
55
+ 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.
56
+
57
+ 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.
42
58
 
43
59
  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`.
44
60
 
@@ -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.