@arnilo/prism 0.0.10 → 0.0.96

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 CHANGED
@@ -5,19 +5,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
5
5
 
6
6
  All notable changes to this project will be documented in this file.
7
7
 
8
- ## [0.0.10] - 2026-07-21
9
-
10
- ### Changed
11
-
12
- - Coding harness workspace modes (Phase 5): required `workspaceMode` on `@arnilo/prism-coding-security` composition; sandbox mode unifies shell/FS on one disposable tree; host mode never claims containment; fail-closed mixed wiring + `allowMixedWorkspaceWiring` escape hatch; import/export tree identity; `scripts/benchmark-0.0.10.mjs` evidence.
13
- - Versioned all 32 first-party manifests and exact internal ranges from the post-ship `0.0.96` graph to `0.0.10` for the roadmap Phase 5 release line.
14
-
15
8
  ## [0.0.96] - 2026-07-21
16
9
 
17
10
  ### Changed
18
11
 
19
12
  - Package graph and runtime version pins bumped from 0.0.9 to 0.0.96 for a clean publish tag after the mistaken `v0.0.95` tag and TypeScript 7 / workspace-order CI fixes.
20
13
 
14
+ ## Unreleased
15
+
21
16
  ## [0.0.9] - 2026-07-21
22
17
 
23
18
  ### Added
package/dist/index.d.ts CHANGED
@@ -83,5 +83,5 @@ export type { DispatchToolCallOptions, ToolArgumentValidationError, ToolArgument
83
83
  export type { DuplicateRegistrationOptions, DuplicateRegistrationPolicy } from "./registry-options.js";
84
84
  export { dispatchToolCallsInOrder, generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, resolveToolConcurrency, singleShotLoop } from "./agent-loops.js";
85
85
  export declare const name = "prism";
86
- export declare const version = "0.0.10";
86
+ export declare const version = "0.0.96";
87
87
  export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
package/dist/index.js CHANGED
@@ -45,6 +45,6 @@ export { assertGuardrailsAllowed, GuardrailError, MAX_GUARDRAIL_CONCURRENCY, run
45
45
  export { createRunLimitTracker, DEFAULT_RUN_LIMITS, HARD_MAX_RUN_COST, HARD_RUN_LIMITS, RunLimitError, RunLimitTracker, resolveRunLimits } from "./run-limits.js";
46
46
  export { dispatchToolCallsInOrder, generateValidateReviseLoop, isAgentLoopOptions, resolveLoop, resolveToolConcurrency, singleShotLoop } from "./agent-loops.js";
47
47
  export const name = "prism";
48
- export const version = "0.0.10";
48
+ export const version = "0.0.96";
49
49
  export const description = "Agent harness for AI providers, agents, sessions, and tools.";
50
50
  //# sourceMappingURL=index.js.map
@@ -315,7 +315,7 @@ const remoteWrite = createWriteTool("/repo", {
315
315
  - **Pluggable operation backends.** Every tool accepts an `operations` seam. Custom `ReadOperations` must implement bounded `readText` plus `statFile`; custom `EditOperations` must implement `statFile`; read/write methods receive caps/signals. `BashOperations` must stream through `onData` and honor `signal`/`timeout`. Custom `RepositoryOperations` must honor depth/entry/file/match/scan/time caps and abort. A hostile custom backend can still violate its host-owned contract, so isolate it separately.
316
316
  - **Per-tool options.** `ShellToolOptions` adds `timeout` and `maxTotalOutputBytes`; `ReadToolOptions` adds `maxScanBytes`; `WriteToolOptions` adds `maxInputBytes`; `EditToolOptions` adds `maxFileBytes`, `maxInputBytes`, and `maxEdits`; list/search accept `repository` limits and shared aggregator `ToolsOptions.repository`.
317
317
  - **Aggregator options.** `ToolsOptions` (`{ executionPolicy?, shell?, read?, write?, edit?, list?, search?, repository? }`) threads each sub-object to the matching tool. `createCodingTools()`, `createAllTools()`, and `createReadOnlyTools()` apply the shared policy unless that tool has an explicit per-tool override. Read-only membership is deliberately `read` + `repo_list` + `repo_search` (0.0.9 behavior change).
318
- - **Sandbox composition.** Prefer `@arnilo/prism-coding-security` `createSandboxCodingComposition(cwd, { workspaceMode, sandbox, ... })` (or tools-only wrappers). `workspaceMode` is required: `"sandbox"` keeps shell/read/write/edit/list/search on one disposable tree; `"host"` runs against host cwd and never claims containment. Mixed sandbox-shell + host-FS wiring throws unless `allowMixedWorkspaceWiring: true`. Same-tree Git: `createGitTools(composition.workspaceRoot, { execFile: sandbox.execFile, commitIdentity })`.
318
+ - **Sandbox composition.** Prefer `@arnilo/prism-coding-security` `createSandboxCodingTools(cwd, { sandbox, ... })` to wire shell through a `SandboxAdapter` while sharing repository options. Filesystem tools still use the host `cwd` unless custom operations are supplied; Docker tmpfs workspace mutations stay inside the container until export.
319
319
  - **`ToolsOptions`** and the per-tool option types are exported from the package barrel for host configuration.
320
320
  - No auto-discovery or manifest registration: import and register explicitly. This package registers no extensions and owns no globals (the mutation queue is a process-wide per-path map — see `ponytail:` note in the source).
321
321
 
@@ -8,10 +8,8 @@
8
8
  | --- | --- |
9
9
  | `createCodingApprovalPolicy(options)` | Returns an `ExecutionPolicy` with trusted roots, read-only mode, command allow/deny rules, approval caching, and timeout/abort-aware approval waits. |
10
10
  | `createSandboxBashOperations(adapter)` | Maps a host-owned `SandboxAdapter` to coding-agent `BashOperations` for delegated shell execution. |
11
- | `createSandboxCodingComposition(cwd, options)` | Authoritative construction: returns `{ tools, composition }` with required `workspaceMode` (`"host"` \| `"sandbox"`), fail-closed mixed wiring, and containment metadata. |
12
- | `createSandboxReadOnlyComposition(cwd, options)` | Same contract for read-only tools (`read`/`repo_list`/`repo_search`). |
13
- | `createSandboxCodingTools` / `createSandboxReadOnlyTools` | Thin wrappers that return `tools` only (compat); still require `workspaceMode`. |
14
- | `createSandboxFilesystemOperations` / `createSandboxRepositoryOperations` | Optional execFile-backed FS/list/search backends for a disposable sandbox tree. |
11
+ | `createSandboxCodingTools(cwd, options)` | One construction path: full coding tools with shell wired to `options.sandbox` and shared repository options. |
12
+ | `createSandboxReadOnlyTools(cwd, options)` | Read-only coding tools (`read`/`repo_list`/`repo_search`) with shared repository options. |
15
13
  | `createDockerSandbox(options)` | Creates one disposable non-root Docker container with read-only root/source, bounded tmpfs workspace, typed `execFile`, import/export, and stop/kill/cleanup. |
16
14
  | `assertPathInsideRoots`, `isPathInsideReal` | Symlink-aware path containment helpers. |
17
15
  | `evaluateCommandRules`, `hasShellMetacharacters` | Command classification helpers. |
@@ -54,25 +52,11 @@ Use `createDockerSandbox()` when the host wants a production-reference containme
54
52
  | `secrets` | `[]` | Canaries redacted from CLI/adapter errors. |
55
53
  | `limits` | package defaults | CPU/memory/PID/FD/tmpfs/command/export/time caps validated before create. |
56
54
 
57
- ### Workspace mode inputs (`createSandboxCodingComposition`)
58
-
59
- | Option | Default | Purpose |
60
- | --- | --- | --- |
61
- | `workspaceMode` | **required** | `"host"` (all tools on host cwd; never claims containment) or `"sandbox"` (shell + FS/list/search share one disposable tree). |
62
- | `sandbox` | optional in host; required for sandbox unless custom ops supplied | `SandboxAdapter` / `DisposableSandbox`. |
63
- | `workspaceRoot` | `"/workspace"` in sandbox mode | Tree root used as tool cwd when sandbox backends are bound. |
64
- | `allowMixedWorkspaceWiring` | `false` | Escape hatch: allow sandbox shell + host FS backends. Records `composition.warnings`; forces `containmentClaim: false`. Missing hatch throws. |
65
- | `read`/`write`/`edit`/`repository.operations` | auto-wired from `DisposableSandbox` in sandbox mode | Host may supply custom tree backends instead of auto-wire. |
66
-
67
- `0.0.9` silent split (sandbox shell + host FS) is **superseded**. Mixed wiring is never the default.
68
-
69
55
  ## Outputs / response / events
70
56
 
71
57
  `createCodingApprovalPolicy()` returns an `ExecutionPolicy`. Allowed checks return `ExecutionDecision { allowed: true }`; denied checks include a stable reason; shell decisions set `exclusive: true`. Sandbox adapters return coding-agent-compatible `BashOperations`, receive `onData(Buffer)` for ordered stdout/stderr forwarding through the shell tool's existing bounded accumulator, and never grant policy approval themselves.
72
58
 
73
- `createSandboxCodingComposition()` returns `{ tools, composition }` where `SandboxCodingComposition` carries `workspaceMode`, `containmentClaim`, `mixedWiringAllowed`, `warnings`, `workspaceRoot`, and optional `treeIdentity` (from `importIdentity` / `lastExportIdentity`). `containmentClaim` is `true` only for sandbox mode with tree backends bound and mixed wiring denied. Host mode and escape-hatch mixed wiring always set `containmentClaim: false` — never treat host mode as contained execution.
74
-
75
- `createDockerSandbox()` returns a `DisposableSandbox`: typed `execFile(file, args)`, shell-compatible `exec`, `status`, cooperative `stop`, forced `kill`, and idempotent `close`. Import may surface `importIdentity`; successful export updates `lastExportIdentity`. `close({ export })` can stream a bounded workspace tar plus SHA-256/entry/byte metadata through a host callback; checkpoints should retain only host artifact references/hashes, never whole workspaces.
59
+ `createDockerSandbox()` returns a `DisposableSandbox`: typed `execFile(file, args)`, shell-compatible `exec`, `status`, cooperative `stop`, forced `kill`, and idempotent `close`. `close({ export })` can stream a bounded workspace tar plus SHA-256/entry/byte metadata through a host callback; checkpoints should retain only host artifact references/hashes, never whole workspaces.
76
60
 
77
61
  ## Request/response example
78
62
 
@@ -89,9 +73,8 @@ Use `createDockerSandbox()` when the host wants a production-reference containme
89
73
  import {
90
74
  createCodingApprovalPolicy,
91
75
  createDockerSandbox,
92
- createSandboxCodingComposition,
76
+ createSandboxCodingTools,
93
77
  } from "@arnilo/prism-coding-security";
94
- import { createGitTools } from "@arnilo/prism-coding-agent";
95
78
 
96
79
  const policy = createCodingApprovalPolicy({
97
80
  roots: [workspaceRoot],
@@ -110,24 +93,12 @@ const sandbox = await createDockerSandbox({
110
93
  limits: { cpus: 2, memoryBytes: 2 * 1024 ** 3, maxPids: 256, workspaceBytes: 1024 ** 3 },
111
94
  });
112
95
 
113
- // Sandbox mode: shell/read/write/edit/list/search share one disposable tree.
114
- const { tools, composition } = createSandboxCodingComposition("/srv/jobs/task-1/source", {
115
- workspaceMode: "sandbox",
96
+ // Host cwd is the inspected workspace; shell runs inside the sandbox.
97
+ const tools = createSandboxCodingTools("/srv/jobs/task-1/source", {
116
98
  sandbox,
117
99
  executionPolicy: policy,
118
100
  repository: { exclude: [".git", "node_modules", "dist"] },
119
101
  });
120
- // composition.containmentClaim === true when backends are bound
121
-
122
- // Same-tree Git/check (opt-in; not folded into coding tools):
123
- const gitTools = createGitTools(composition.workspaceRoot, {
124
- execFile: sandbox.execFile.bind(sandbox),
125
- commitIdentity: { name: "bot", email: "bot@example.com" },
126
- });
127
-
128
- // Host mode (explicit non-contained): omit sandbox; never claim containment.
129
- const host = createSandboxCodingComposition(hostCwd, { workspaceMode: "host", executionPolicy: policy });
130
- // host.composition.containmentClaim === false
131
102
 
132
103
  await sandbox.execFile({ file: "npm", args: ["test"], cwd: "/workspace" });
133
104
  await sandbox.close({
@@ -137,9 +108,7 @@ await sandbox.close({
137
108
 
138
109
  ## Extension and configuration notes
139
110
 
140
- Policies are ordinary host values: attach one globally through `createCodingTools()`/`createReadOnlyTools()`/`createSandboxCodingComposition()` or per tool. A per-tool policy overrides the shared policy. `SandboxAdapter` / `DisposableSandbox` are replaceable and host-owned; approval policy and sandboxing are separate layers. Custom remote sandboxes can implement `DisposableSandbox` without using Docker.
141
-
142
- `createSandboxCodingComposition()` requires `workspaceMode`. Sandbox mode auto-wires FS/list/search through `DisposableSandbox.execFile` (or host-supplied custom operations) so mutations stay on the disposable tree until export. Host mode runs every coding tool against the host cwd and never sets `containmentClaim`. Sandbox shell + host FS throws unless `allowMixedWorkspaceWiring: true` (warnings + `containmentClaim: false`). Opt-in structured Git tools (`createGitTools(composition.workspaceRoot, { execFile: sandbox.execFile, commitIdentity })`) share the same tree/cwd; Prism still never pushes or opens PRs. Optional `@arnilo/prism-browser` can share the same disposable boundary: use `assertBrowserSandboxNetwork()` before browse-ready custom networks, and `createSharedSandboxBrowserOptions({ workspaceRoot, downloadsRoot, containedProxyAttestation })` so uploads/downloads align with `/workspace` and `/downloads`. Close the browser context before disposing the sandbox.
111
+ Policies are ordinary host values: attach one globally through `createCodingTools()`/`createReadOnlyTools()`/`createSandboxCodingTools()` or per tool. A per-tool policy overrides the shared policy. `SandboxAdapter` / `DisposableSandbox` are replaceable and host-owned; approval policy and sandboxing are separate layers. Custom remote sandboxes can implement `DisposableSandbox` without using Docker. `createSandboxCodingTools()` wires shell through the adapter while list/search/read/write/edit keep the host `cwd` unless custom operations are supplied — Docker tmpfs mutations remain inside the container until export. Opt-in structured Git tools from `@arnilo/prism-coding-agent` (`createGitTools`) can target the same disposable sandbox by passing `execFile: sandbox.execFile` and a host `commitIdentity`; Prism still never pushes or opens PRs. Optional `@arnilo/prism-browser` can share the same disposable boundary: use `assertBrowserSandboxNetwork()` before browse-ready custom networks, and `createSharedSandboxBrowserOptions({ workspaceRoot, downloadsRoot, containedProxyAttestation })` so uploads/downloads align with `/workspace` and `/downloads`. Close the browser context before disposing the sandbox.
143
112
 
144
113
  The Docker reference adapter starts by recorded container ID/label, uses argument arrays only, mounts source read-only, populates a size-bounded tmpfs `/workspace`, drops all capabilities, enables `no-new-privileges`, runs with `--init`, and never exposes the Docker socket, privileged mode, or host PID/IPC namespaces. Image pull/build/update stays outside Prism. Protected real-Docker checks are opt-in via `PRISM_TEST_DOCKER_SANDBOX=1` with host-supplied `PRISM_TEST_DOCKER_BIN` and digest-pinned `PRISM_TEST_DOCKER_IMAGE`.
145
114
 
@@ -149,7 +118,7 @@ Callback approval remains process-local. For approval that must survive restart,
149
118
 
150
119
  Containment resolves symlinks and rejects paths outside roots. Command rules are not a shell parser; shell metacharacters require approval. Approval waits and subprocess execution honor abort/timeouts. Coding-agent resource ceilings independently bound text scans, image/edit target reads, write/edit payloads, edit counts, repository list/search walks, shell wall time, and retained/spilled output. Those ceilings reduce exhaustion risk but do not grant path/command authority or make an unsandboxed shell safe.
151
120
 
152
- Docker sandbox containment—not command regexes—enforces filesystem/network/process boundaries for the reference adapter. Network defaults to none; a custom Docker network still requires a host firewall/proxy for DNS/egress claims. Import rejects symlink escapes, devices, FIFOs, and sockets; export counts entries/bytes and hashes before host retention. Secrets in `secrets` are redacted from adapter errors and never exported as environment metadata. Unified workspace mode reuses existing sandbox/repo/coding hard caps and does not introduce unbounded host↔container sync loops. Host mode and `allowMixedWorkspaceWiring` never claim disposable containment. Durable workflow denial/cancellation is terminal and attributable; approved resume still fails if roots, command rules, read-only mode, or other policy changed while suspended. Cache keys are fixed-size SHA-256 digests of selected identity plus action shape; caches remain process-local, retain at most 1,000 decisions with oldest-entry eviction, and have no default/global mode. Path checks and cache lookup are local; sandbox latency belongs to the supplied adapter and Docker daemon.
121
+ Docker sandbox containment—not command regexes—enforces filesystem/network/process boundaries for the reference adapter. Network defaults to none; a custom Docker network still requires a host firewall/proxy for DNS/egress claims. Import rejects symlink escapes, devices, FIFOs, and sockets; export counts entries/bytes and hashes before host retention. Secrets in `secrets` are redacted from adapter errors and never exported as environment metadata. Durable workflow denial/cancellation is terminal and attributable; approved resume still fails if roots, command rules, read-only mode, or other policy changed while suspended. Cache keys are fixed-size SHA-256 digests of selected identity plus action shape; caches remain process-local, retain at most 1,000 decisions with oldest-entry eviction, and have no default/global mode. Path checks and cache lookup are local; sandbox latency belongs to the supplied adapter and Docker daemon.
153
122
 
154
123
  ## Related APIs
155
124
 
@@ -152,5 +152,5 @@ Fixtures reuse `@arnilo/prism-evals` (`defineDataset` / `defineScorer` / `scoreR
152
152
  - [Runs and usage ledger](runs-and-usage.md): run/session identity for score linkage
153
153
  - [Observability](observability.md): use `onTraceReference` or bounded `traceId(runId)` to supply `ScoreRunOptions.traceId`; evaluation telemetry emits no reason/explanation content
154
154
  - [Coding agent tools](coding-agent-tools.md) / [Browser automation](browser-automation.md) / [Workflows](workflows.md): network-free coding-task composition at `examples/durable-coding-workflow.ts`; adversarial coding/browser eval example at `examples/coding-browser-evaluation.ts`
155
- - [Performance limits](performance.md): `scripts/benchmark-0.0.10.mjs` workspace-mode evidence and `scripts/benchmark-0.0.9.mjs` coding/browser evidence fields
155
+ - [Performance limits](performance.md): `scripts/benchmark-0.0.9.mjs` coding/browser evidence fields
156
156
  - [Release and install](release-and-install.md): optional package install and protected sandbox-browser workflow
@@ -137,7 +137,7 @@ Wire those values where they matter: provider adapters receive the resolved cred
137
137
  - Prism-generated session/run/tool/workflow/evaluation IDs use Node cryptographic UUIDs. Keep host-provided IDs authorization-scoped and validate them as untrusted identifiers; do not substitute timestamps or `Math.random()` for durable/security-relevant IDs.
138
138
  - MCP client tools from `@arnilo/prism-mcp` are untrusted remote servers. Stdio remains an explicit host executable. Streamable HTTP requires exact HTTPS origins, rejects credentials/fragments/redirects/private or mixed DNS, pins a validated address on every SDK request/reconnect, and bounds each response; plaintext is explicit loopback-only development mode. Discovery has finite page/tool/cursor/metadata/schema totals and commits atomically. Every result branch shares byte/depth/property bounds before core dispatch; supply a known-secret `SecretRedactor`, `PermissionPolicy`, and `ToolValidator` there. MCP server direction exposes only passed tools/commands/resources/prompts, requires per-operation `authorize`, and retains core gates. Sampling, roots, model/credential selection, and elicitation consent stay host-owned; URL elicitation is never opened automatically. Stateful web mode requires host `resolveAuthInfo` plus `resolveIdentity`, exact origin policy, and binds every POST/GET/DELETE/SSE request to one non-secret principal; mismatches return 404. Handler still needs TLS and edge rate limiting. See [MCP client/server exposure](mcp-tools.md).
139
139
  - `@arnilo/prism-server` exposes no agent/workflow by default and requires `authorize()` for every matched operation. Derive complete tenant/account/user ownership from validated host identity, never request JSON. Workflow active identity and cancellation compare exact ownership; a tenant-only scope intentionally cannot cancel a checkpoint/run carrying account or user identity. Pass the current explicitly revised workflow definition so recursive hash mismatch fails before abort or durable mutation. Configure exact host/origin allow-lists where needed, wire redaction before execution, retain tool/workflow policy checks, and adapt the Web handler behind host TLS/rate limits. Disconnect abort is default; persistent reconnect/status belongs to durable workflow checkpoints, not an invented in-memory agent result cache.
140
- - Coding tools from `@arnilo/prism-coding-agent` accept an optional `ExecutionPolicy` checked inside each tool before side effects; shared policy propagation includes `createReadOnlyTools()`. They enforce finite text-scan/image/edit/write/shell limits, repository list/search depth/entry/match/scan/time caps, structured Git path/ref/message/output/patch/worktree caps, named-check concurrency/output caps, a 600-second default shell wall time, and a 64 MiB default total-output ceiling. Opt-in `createGitTools()` uses argument arrays with hooks/credential prompts/external diff disabled, requires host `commitIdentity` for commits, and never pushes or opens PRs. Successful truncated shell output leaves a host-owned exclusive `0600` temp file; delete `metadata.fullOutputPath` after use. Error/abort/timeout/overflow removes unpublished spills. Custom read/edit/shell/repository backends must honor supplied caps/signals. Use `@arnilo/prism-coding-security` for path roots, command rules, identity-scoped approval caching, required `workspaceMode` on `createSandboxCodingComposition()` / `createSandboxCodingTools()`, and the optional `createDockerSandbox()` reference adapter. **Host mode is never contained execution** (`containmentClaim: false`). Sandbox mode claims containment only when FS backends target the disposable tree; mixed wiring requires `allowMixedWorkspaceWiring` and still does not claim containment. Limits alone are not containment: construct the Docker adapter (absolute CLI, digest-pinned image, network none by default) or an equivalent host sandbox before treating coding execution as production-safe. Docker daemon/image trust, egress firewall/proxy, and artifact retention remain host-owned.
140
+ - Coding tools from `@arnilo/prism-coding-agent` accept an optional `ExecutionPolicy` checked inside each tool before side effects; shared policy propagation includes `createReadOnlyTools()`. They enforce finite text-scan/image/edit/write/shell limits, repository list/search depth/entry/match/scan/time caps, structured Git path/ref/message/output/patch/worktree caps, named-check concurrency/output caps, a 600-second default shell wall time, and a 64 MiB default total-output ceiling. Opt-in `createGitTools()` uses argument arrays with hooks/credential prompts/external diff disabled, requires host `commitIdentity` for commits, and never pushes or opens PRs. Successful truncated shell output leaves a host-owned exclusive `0600` temp file; delete `metadata.fullOutputPath` after use. Error/abort/timeout/overflow removes unpublished spills. Custom read/edit/shell/repository backends must honor supplied caps/signals. Use `@arnilo/prism-coding-security` for path roots, command rules, identity-scoped approval caching, `createSandboxCodingTools()`, and the optional `createDockerSandbox()` reference adapter. Limits alone are not containment: construct the Docker adapter (absolute CLI, digest-pinned image, network none by default) or an equivalent host sandbox before treating coding execution as production-safe. Docker daemon/image trust, egress firewall/proxy, and artifact retention remain host-owned.
141
141
  - Optional `@arnilo/prism-browser` requires a host-supplied Playwright Browser (`playwright-core@1.61.0` peer). Import is inert. One non-persistent context belongs to one run; actions serialize; refs are snapshot-scoped; CSS/evaluate/CDP/persistent profiles are denied. Context routing + `serviceWorkers: "block"` deny file/data/blob/devtools/private/loopback by default and require contained-proxy attestation for external egress (Playwright routing is defense in depth, not DNS containment). Uploads are realpath-rooted; downloads quarantine with hash/MIME until host `approveRelease`; screenshots return bounded `ImageContent`. Observation vs mutation/high-impact actions map to `ExecutionPolicy`. Treat snapshot/page text as untrusted external content. Close contexts with `browser_close` or `manager.closeRun(runId)` on abort/terminal. Browser control endpoint, binary/image pin, and real egress firewall/proxy remain host-owned. Shared sandbox: `createSharedSandboxBrowserOptions()` + `assertBrowserSandboxNetwork()`.
142
142
  - `@arnilo/prism-credentials-node` rejects oversized/malformed envelopes and excessive scrypt work before KDF allocation, uses async scrypt, and requires restrictive existing/new Unix vault modes. Keep vault ownership and parent-directory access host-controlled; review before `chmod 600`, never auto-weaken a file policy. Keychain calls use abort-aware native async work with finite timeout/payload caps and sanitized errors. OS prompts, service availability, and whether a native backend promptly honors cancellation remain host/platform boundaries; no plaintext fallback is attempted.
143
143
  - LLM compaction always sends finite summary `maxTokens`, retains bounded deltas/events, and bounds/redacts provider/factory/policy error detail. Observational-memory workers cap turns, calls, arguments, results, transcript, and surfaced errors; unknown tools fail before execution, while invalid results can only be rejected after a host tool returns and may therefore follow side effects. Pass all known provider/credential/tool secrets into compaction/runtime options; exact replacement is not secret discovery.
package/docs/index.md CHANGED
@@ -14,7 +14,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
14
14
  - [Observability](observability.md): OTel GenAI agent/provider/tool hierarchy, host context parenting, bounded trace linkage, safe evaluation events, controlled metrics, and exporter isolation.
15
15
  - [Evaluations](evaluations.md): deterministic and bounded trace/model-judge/pairwise scoring, CI thresholds, OTel trace-reference linkage, coding/browser adversarial fixtures, and ID-only linkage to immutable owned run feedback.
16
16
  - [Runs and usage ledger](runs-and-usage.md): durable run/event/tool/usage persistence, optional bounded FIFO durability policies, session snapshot caching, and immutable run/trace feedback.
17
- - [Performance limits](performance.md): bounded evaluation traces/judges/reports, 0.0.10 workspace-mode and 0.0.9 coding/browser benchmark evidence, security scan/live-canary backstops, live subscriber queues, branch-read pagination expectations, JSONL/dev-store limits, and production sizing assumptions.
17
+ - [Performance limits](performance.md): bounded evaluation traces/judges/reports, 0.0.9 coding/browser benchmark evidence, security scan/live-canary backstops, live subscriber queues, branch-read pagination expectations, JSONL/dev-store limits, and production sizing assumptions.
18
18
  - [Structured output](structured-output.md): the `Artifact*` seam plus provider-native `StructuredOutputOptions` / `structuredOutputMode` for capable models.
19
19
 
20
20
  ## Compaction/session memory
@@ -27,7 +27,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
27
27
  - [Database persistence](database-persistence.md): production persistence contracts, shared checksummed migration/full-shape catalog primitives (`@arnilo/prism/testing/persistence-schema`), conditional append, indexes, `readBranchPath`, reference relational schema, retention, and NoSQL mapping.
28
28
  - [SQLite persistence](sqlite-persistence.md): optional `better-sqlite3` adapter with session/run storage, checkpoints/leases, feedback, and transactionally verified/backfilled migration-v3 metadata.
29
29
  - [PostgreSQL persistence](postgres-persistence.md): optional pooled `pg` adapter with session/run/checkpoint/lease/feedback storage, advisory-locked checksummed/full-shape migrations, and opt-in live conformance.
30
- - [Migration guide](migration.md): 0.0.3 compatibility through 0.0.10 workspace modes (required `workspaceMode`, fail-closed mixed wiring) and 0.0.9 coding/browser sandbox, repository/Git, durable plans, and Playwright automation changes.
30
+ - [Migration guide](migration.md): 0.0.3 compatibility through 0.0.9 coding/browser sandbox, repository/Git, durable plans, and Playwright automation changes.
31
31
  - [Node JSONL session store](node-jsonl-session-store.md): development-only JSONL file adapter for single-process Node hosts; no cross-process safety.
32
32
  - [Persistence, credentials, and multimodality primitives](persistence-credentials-multimodality-primitives.md): Plan 056 inventory — session/run-ledger/persistence contracts, credential/OAuth seams, content/resource/model capabilities, package dependency matrix, conformance matrix, and threat model for production adapters.
33
33
 
@@ -61,7 +61,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
61
61
  - [Web search, fetch, and extraction](web-tools.md): optional host-selected Brave/Exa discovery and Firecrawl Markdown/schema tools with native fetch, stable citations, late credentials, finite limits, and explicit untrusted-content boundaries.
62
62
  - [Browser automation](browser-automation.md): optional `@arnilo/prism-browser` with host-supplied Playwright contexts, AI-mode snapshots/refs, ordered `browser_open`/`browser_snapshot`/`browser_act`/`browser_close`, egress/side-effect/upload/download/screenshot policy, and finite page/action/snapshot/network/artifact caps.
63
63
  - [Coding agent tools](coding-agent-tools.md): optional `shell`, `read`, `write`, `edit`, `repo_list`, and `repo_search` definitions plus opt-in `createGitTools()` / `coding_check` for structured Git status/diff/branch/worktree/apply/commit/PR-handoff and named checks; durable plan/todo Markdown helpers with workflow `state.coding` checkpoint metadata; streamed text pages, bounded repository list/search, finite Git/check/plan caps, bounded image/edit reads and write/edit payloads, finite shell wall/total-output limits, secure host-owned spill cleanup, pluggable bounded operation contracts, per-path mutation serialization, and optional `ExecutionPolicy`. Limits do not sandbox host access—gate with permission/trust policy and `@arnilo/prism-coding-security`.
64
- - [Coding execution approval and sandboxing](coding-security.md): path/command approval, identity-scoped caching, shell-turn exclusivity, required `workspaceMode` (`host`/`sandbox`) with fail-closed mixed wiring, `createSandboxCodingComposition()` containment metadata, and the disposable Docker/OCI sandbox reference with bounded workspace import/export.
64
+ - [Coding execution approval and sandboxing](coding-security.md): path/command approval, identity-scoped caching, shell-turn exclusivity, abort-aware streaming sandbox adapters, `createSandboxCodingTools()` composition, and the disposable Docker/OCI sandbox reference with bounded workspace import/export.
65
65
 
66
66
  ## Extensions/plugins
67
67
  - [Contribution discovery (workspace)](contribution-discovery.md): opt-in, realpath-contained directory scanner turning `SKILL.md`/`manifest.json` into inert `DiscoveredContribution` envelopes the host registers — no `import()`, no auto-activate, no provider scanning. Per-agent bundles remain app-controlled and are documented under Agent/session runtime.
@@ -106,7 +106,6 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
106
106
 
107
107
  ## Release and install
108
108
  - [Release and install](release-and-install.md): 32-package graph (including optional browser), install/tarball rules, pinned CodeQL/dependency/SBOM/license/secret/attestation gates, deterministic resumable publication, offline tests, protected live canaries, and sandbox-browser Docker/Playwright gates.
109
- - [Review coverage (2026-07-21 Phase 5)](review-coverage-2026-07-21-phase-5.md): Plan 073 evidence freeze — unified workspace modes, primitive ownership, reused finite limits, threats, and 0.0.10 release gates.
110
109
  - [Review coverage (2026-07-20 Phase 4)](review-coverage-2026-07-20-phase-4.md): Plan 072 evidence freeze — revised coding/browser-only scope, external revisions, primitive ownership, finite limits, threats, and 0.0.9 release gates.
111
110
  - [Review coverage (2026-07-19 Phase 3)](review-coverage-2026-07-19-phase-3.md): Plan 070 evidence freeze — exact protocol/vendor references, capability/primitive/limit matrices, supported boundaries, and 0.0.8 release evidence.
112
111
  - [Review coverage (2026-07-17 provider validation)](review-coverage-2026-07-17-provider-validation.md): Plan 067 evidence freeze — P0–P2 re-verification owners, seven first-party provider packages mapped to official-doc URLs, Pi secondary refs, cache/thinking/discovery surfaces, credential canaries, and use-case model-binding inventory.
package/docs/migration.md CHANGED
@@ -7,42 +7,6 @@ Prism 0.0.6 preserves documented 0.0.3 agent construction except for two intenti
7
7
  1. **`session.run()` / `session.prompt()` return `AgentRunResult`** and `session.stream()` starts one owned run after subscribing. Callers that ignored the previous `Promise<void>` keep working; failed/aborted runs reject with `AgentRunError` (`.result` attached).
8
8
  2. **`AgentConfig.extensions` / `settings` / `credentials` are removed.** Wire extensions through `createExtensionKernel()`, read settings in the host, and pass credential resolvers to the provider edge.
9
9
 
10
- ## 0.0.9 / 0.0.96 → 0.0.10 coding workspace modes (breaking composition)
11
-
12
- `@arnilo/prism-coding-security` composition now requires explicit `workspaceMode: "host" | "sandbox"`. Missing mode throws at construction. The `0.0.9` default that wired sandbox shell while keeping read/write/edit/list/search on the host cwd is **superseded** and fail-closed.
13
-
14
- | Before (0.0.9) | After (0.0.10) |
15
- | --- | --- |
16
- | `createSandboxCodingTools(cwd, { sandbox })` — shell in sandbox, FS on host | Must pass `workspaceMode`. Prefer `createSandboxCodingComposition(...)`. |
17
- | Silent split-brain treated as normal | Throws unless `allowMixedWorkspaceWiring: true` (warnings; `containmentClaim: false`). |
18
- | No containment metadata | `composition.containmentClaim` / `warnings` / optional `treeIdentity`. Host mode never claims containment. |
19
-
20
- ```ts
21
- // Contained: one disposable tree
22
- const { tools, composition } = createSandboxCodingComposition(sourceRoot, {
23
- workspaceMode: "sandbox",
24
- sandbox, // DisposableSandbox auto-wires FS backends
25
- });
26
-
27
- // Explicit host (non-contained)
28
- createSandboxCodingTools(cwd, { workspaceMode: "host" });
29
-
30
- // Escape hatch (documented split; no containment claim)
31
- createSandboxCodingTools(cwd, {
32
- workspaceMode: "sandbox",
33
- sandbox,
34
- allowMixedWorkspaceWiring: true,
35
- });
36
-
37
- // Same-tree Git
38
- createGitTools(composition.workspaceRoot, {
39
- execFile: sandbox.execFile.bind(sandbox),
40
- commitIdentity: { name: "bot", email: "bot@example.com" },
41
- });
42
- ```
43
-
44
- Docker defaults unchanged: digest-pinned image, non-root user, network none, absolute Docker CLI, no host-env inheritance. Unified mode adds no unbounded sync; caps stay in `sandbox-limits.ts` / coding-agent limits. Benchmark evidence: `scripts/benchmark-0.0.10.mjs`.
45
-
46
10
  ## 0.0.8 → 0.0.9 release overview
47
11
 
48
12
  All 32 first-party manifests and exact internal ranges move together to `0.0.9`; mixed first-party versions are unsupported. Core remains dependency-free at runtime and existing low-level agent/session APIs remain compatible. New coding sandbox, repository/Git, durable coding-plan, and browser surfaces are opt-in. `@arnilo/prism-browser` is included by `@arnilo/prism-all` but not by `@arnilo/prism-code` — install it explicitly when interactive browser automation is required. Office execution remains outside Prism packaging (host-selected skills/instructions only). No tag or publication is automatic from this migration.
@@ -65,7 +29,7 @@ Tool-call deltas missing `id` and/or `name` at stream end no longer throw a bare
65
29
 
66
30
  ## 0.0.9 coding-agent repository list/search (additive behavior change)
67
31
 
68
- `@arnilo/prism-coding-agent` adds native `repo_list` / `repo_search` tools. `createCodingTools()` / `createAllTools()` now return six tools. **`createReadOnlyTools()` deliberately expands from `[read]` to `[read, repo_list, repo_search]`** — update hosts that asserted the previous read-only membership. Prefer `createSandboxCodingComposition(cwd, { workspaceMode, sandbox, repository })` (or the tools-only wrappers) from `@arnilo/prism-coding-security`. Pass required `workspaceMode`; sandbox mode keeps shell and FS/list/search on one disposable tree. The 0.0.9 split (sandbox shell + host FS) is superseded — see **0.0.9 / 0.0.96 → 0.0.10 coding workspace modes** above.
32
+ `@arnilo/prism-coding-agent` adds native `repo_list` / `repo_search` tools. `createCodingTools()` / `createAllTools()` now return six tools. **`createReadOnlyTools()` deliberately expands from `[read]` to `[read, repo_list, repo_search]`** — update hosts that asserted the previous read-only membership. Prefer `createSandboxCodingTools(cwd, { sandbox, repository })` from `@arnilo/prism-coding-security` when shell must run inside a sandbox adapter while list/search inspect a host workspace path.
69
33
 
70
34
  Opt-in structured Git/check tools are available via `createGitTools(cwd, { commitIdentity, checks? })` and are **not** added to `createCodingTools()`/`createAllTools()`. Commits require an explicit host `commitIdentity`; PR handoff returns bounded metadata/artifacts only and never pushes.
71
35
 
@@ -6,10 +6,6 @@ Evaluation defaults are finite: 100 trace rows × 20 pages and 4 MiB aggregate t
6
6
 
7
7
  This page states Prism runtime limits that keep slow consumers and long sessions from becoming unbounded memory or latency problems.
8
8
 
9
- ## Release 0.0.10 reproducible workspace-mode evidence
10
-
11
- Run `node scripts/benchmark-0.0.10.mjs`; `PRISM_BENCH_ITERATIONS` accepts 10–100,000 (default 100). Schema/bounds test: `node --test scripts/benchmark-0.0.10.test.mjs`. Default mode is network-free: host-composition write/read/list plus sandbox-fake composition write/read/list/search (in-memory `DisposableSandbox`). Emits environment, scenario mode, throughput, p50/p95 latency, heap, disk bytes, process counts, zero external cost, backpressure, and resource-limit signals. Optional `PRISM_BENCH_DOCKER=1` (with `PRISM_TEST_DOCKER_*`) appends real local Docker composition rows. Unified workspace mode reuses existing sandbox/repo hard caps and adds no unbounded host↔container sync. These are evidence fields, not CI timing gates.
12
-
13
9
  ## Release 0.0.9 reproducible coding/browser evidence
14
10
 
15
11
  Run `node scripts/benchmark-0.0.9.mjs`; `PRISM_BENCH_ITERATIONS` accepts 10–100,000 (default 100). Schema/bounds test: `node --test scripts/benchmark-0.0.9.test.mjs`. Default mode is network-free fake/in-process only and emits environment, scenario mode, throughput, p50/p95 latency, heap, disk bytes, process counts, zero external cost, backpressure, and resource-limit signals for repository list/search, Git status, and browser open/snapshot/action/close. Optional `PRISM_BENCH_DOCKER=1` (with `PRISM_TEST_DOCKER_*`) and `PRISM_BENCH_PLAYWRIGHT=1` append real local Docker / protected Playwright rows. These are evidence fields, not CI timing gates.
@@ -8,7 +8,7 @@ Core package:
8
8
 
9
9
  - `@arnilo/prism` — the runtime, contracts, registries, streaming events, CLI (including `prism init`), and the `/docs` hub. `files`: `dist` (with `!dist/__tests__` and `!dist/**/*.map` negations), `docs`, `templates`, `CHANGELOG.md`. `bin`: `prism` -> `dist/cli.js`. `sideEffects`: `["dist/cli.js"]`.
10
10
 
11
- First-party workspace packages (each has non-optional `@arnilo/prism@0.0.10` peer and `sideEffects: false`; RAG also peers on memory, and server also peers on workflows):
11
+ First-party workspace packages (each has non-optional `@arnilo/prism@0.0.96` peer and `sideEffects: false`; RAG also peers on memory, and server also peers on workflows):
12
12
 
13
13
  - `@arnilo/prism-provider-openai`, `@arnilo/prism-provider-openrouter`, `@arnilo/prism-provider-kimi`, `@arnilo/prism-provider-zai`, `@arnilo/prism-provider-opencode-go`, `@arnilo/prism-provider-neuralwatt` — provider adapters.
14
14
  - `@arnilo/prism-provider-ai-sdk` — optional AI SDK `LanguageModelV4` adapter; included by the provider and all umbrellas.
@@ -67,9 +67,9 @@ Consumers install the core package for the runtime and add first-party packages
67
67
  | Run the default (network-free) test suite | `npm test` |
68
68
  | Dry-run pack core + every package | `npm run pack:dry-run` |
69
69
  | Local mirror of the release verify gate | `npm run release:dry-run` |
70
- | Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.10` |
71
- | Preview deterministic publish order | `npm run release:publish -- --version 0.0.10 --dry-run --allow-dirty --allow-untagged` |
72
- | Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.10 --resume --report release-artifacts/publish-report.json` |
70
+ | Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.96` |
71
+ | Preview deterministic publish order | `npm run release:publish -- --version 0.0.96 --dry-run --allow-dirty --allow-untagged` |
72
+ | Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.96 --resume --report release-artifacts/publish-report.json` |
73
73
  | Full SDK readiness gate (typecheck + offline tests + pack) | `npm run sdk:ready` |
74
74
 
75
75
  Public core import specifiers (from the root `exports` map):
@@ -106,7 +106,7 @@ A packed tarball contains only public compiled output and release files:
106
106
  - Code packages ship `README.md`, `LICENSE`, and `CHANGELOG.md`; family/profile packages ship `README.md` and `CHANGELOG.md`.
107
107
  - The core tarball additionally ships the full `docs/` directory (the docs hub) and `templates/init/` used by `prism init`.
108
108
  - `dist/cli.js` and the `bin` link in core.
109
- - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.10.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.10.tgz` / `arnilo-prism-compaction-<name>-0.0.10.tgz` / `arnilo-prism-coding-agent-0.0.10.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.10.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
109
+ - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.96.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.96.tgz` / `arnilo-prism-compaction-<name>-0.0.96.tgz` / `arnilo-prism-coding-agent-0.0.96.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.96.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
110
110
 
111
111
  Excluded from every tarball by `files` negation:
112
112
 
@@ -125,9 +125,9 @@ Excluded from every tarball by `files` negation:
125
125
  "name": "host-app",
126
126
  "type": "module",
127
127
  "dependencies": {
128
- "@arnilo/prism": "0.0.10",
129
- "@arnilo/prism-provider-openai": "0.0.10",
130
- "@arnilo/prism-compaction-observational-memory": "0.0.10"
128
+ "@arnilo/prism": "0.0.96",
129
+ "@arnilo/prism-provider-openai": "0.0.96",
130
+ "@arnilo/prism-compaction-observational-memory": "0.0.96"
131
131
  }
132
132
  }
133
133
  ```
@@ -137,7 +137,7 @@ Installing the provider/compaction packages without `@arnilo/prism` present prod
137
137
  ```text
138
138
  npm error code ERESOLVE
139
139
  npm error Could not resolve dependency:
140
- npm error peer @arnilo/prism@"0.0.10" from @arnilo/prism-provider-openai@0.0.10
140
+ npm error peer @arnilo/prism@"0.0.96" from @arnilo/prism-provider-openai@0.0.96
141
141
  ```
142
142
 
143
143
  ## Implementation example
@@ -170,11 +170,11 @@ For SDK readiness, run the same one-command gate directly. It composes existing
170
170
  npm run sdk:ready
171
171
  ```
172
172
 
173
- Release publication derives all 32 packages from the workspace once, validates exact `0.0.10` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.10` and rejects any existing registry version. `release:publish --resume` skips only registry versions whose internal dependency fingerprint matches the local manifest; conflicting versions fail closed. Each attempted package is written immediately to the JSON report, so a failed job can rerun safely. `--dry-run` still performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag.
173
+ Release publication derives all 32 packages from the workspace once, validates exact `0.0.96` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.96` and rejects any existing registry version. `release:publish --resume` skips only registry versions whose internal dependency fingerprint matches the local manifest; conflicting versions fail closed. Each attempted package is written immediately to the JSON report, so a failed job can rerun safely. `--dry-run` still performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag.
174
174
 
175
175
  ```bash
176
- npm run release:check -- --version 0.0.10
177
- npm run release:publish -- --version 0.0.10 --dry-run --allow-dirty --allow-untagged
176
+ npm run release:check -- --version 0.0.96
177
+ npm run release:publish -- --version 0.0.96 --dry-run --allow-dirty --allow-untagged
178
178
  ```
179
179
 
180
180
  `--allow-dirty` and `--allow-untagged` exist only for local preview; real publication and CI never pass them. npm registry calls occur only in these release preflight/publication commands, never build/test/package discovery.
@@ -185,9 +185,9 @@ Optional live smoke tests stay separate from SDK readiness because they require
185
185
  PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
186
186
  ```
187
187
 
188
- ### 0.0.10 publish handoff
188
+ ### 0.0.96 publish handoff
189
189
 
190
- **Decision: GO after operator prerequisites below.** Phase 5 coding-harness unified workspace: required `workspaceMode`, fail-closed mixed wiring, sandbox FS auto-wire, tree identity, adversarial consistency tests, and `scripts/benchmark-0.0.10.mjs` evidence. Code, tests, exact `0.0.10` package graph (retargeted from post-ship `0.0.96`), packed artifacts, security gates, and dependency-ordered publication dry-run passed from the Phase 5 release-candidate tree. Clean protected-branch CI, signed commit/tag, npm authentication, OIDC attestation, protected Docker/Playwright live gates (when host-provisioned), and actual publication remain operator/workflow prerequisites. No package was published during readiness work. Scope is coding-harness P0 only; **no Office** package, binary, SDK, wrapper, docs page, test, or release gate exists. Host mode never claims disposable containment.
190
+ **Decision: GO after operator prerequisites below.** Code, tests, package graph, protected PostgreSQL CI, registry availability, packed artifacts, security gates, coding/browser adversarial fixtures, Synapta Defects 1a/1b/2 (tool-call stream recovery / typed incomplete deltas / empty-candidate rejection), and dependency-ordered publication dry-run passed from the Phase 4 release-candidate tree. Clean protected-branch CI, signed commit/tag, npm authentication, OIDC attestation, protected Docker/Playwright live gates (when host-provisioned), and actual publication remain operator/workflow prerequisites. No package was published during readiness work. Scope includes coding and browser execution only; **no Office** package, binary, SDK, wrapper, docs page, test, or release gate exists.
191
191
 
192
192
  #### npm authentication prerequisite
193
193
 
@@ -195,7 +195,7 @@ The existing GitHub Actions secret `NPM_TOKEN` is used only by the publish step
195
195
 
196
196
  #### Release commit and tag
197
197
 
198
- Merge through the protected release branch, then run these commands from a clean checkout of the protected merge commit. `git push origin v0.0.10` is the workflow dispatch; there is no manual publish command.
198
+ Merge through the protected release branch, then run these commands from a clean checkout of the protected merge commit. `git push origin v0.0.96` is the workflow dispatch; there is no manual publish command.
199
199
 
200
200
  ```bash
201
201
  # Prepare and push the release commit.
@@ -204,22 +204,22 @@ npm ci
204
204
  npm run sdk:ready
205
205
  git add -A
206
206
  git diff --cached --check
207
- git commit -S -m "Release 0.0.10"
207
+ git commit -S -m "Release 0.0.96"
208
208
  git push origin HEAD
209
209
 
210
210
  # Merge/confirm protected branch CI, then check out that exact clean merge commit.
211
211
  test -z "$(git status --porcelain)"
212
212
  npm ci
213
- npm run release:check -- --version 0.0.10 --allow-untagged --report /tmp/prism-0.0.10-preflight.json
213
+ npm run release:check -- --version 0.0.96 --allow-untagged --report /tmp/prism-0.0.96-preflight.json
214
214
 
215
- git tag -s v0.0.10 -m "Prism 0.0.10"
216
- git verify-tag v0.0.10
217
- test "$(git rev-parse HEAD)" = "$(git rev-list -n 1 v0.0.10)"
218
- npm run release:check -- --version 0.0.10 --report /tmp/prism-0.0.10-tagged-preflight.json
219
- git push origin v0.0.10
215
+ git tag -s v0.0.96 -m "Prism 0.0.96"
216
+ git verify-tag v0.0.96
217
+ test "$(git rev-parse HEAD)" = "$(git rev-list -n 1 v0.0.96)"
218
+ npm run release:check -- --version 0.0.96 --report /tmp/prism-0.0.96-tagged-preflight.json
219
+ git push origin v0.0.96
220
220
  ```
221
221
 
222
- The tag workflow's only publication command is `npm run release:publish -- --version "${GITHUB_REF_NAME#v}" --resume --report release-artifacts/publish-report.json`. Latest registry preflight returned `available` for all 32 `0.0.10` versions at handoff. Publisher order is stable and dependency-safe:
222
+ The tag workflow's only publication command is `npm run release:publish -- --version "${GITHUB_REF_NAME#v}" --resume --report release-artifacts/publish-report.json`. Latest registry preflight returned `available` for all 32 `0.0.96` versions at handoff (including first publication of `@arnilo/prism-browser`). Publisher order is stable and dependency-safe:
223
223
 
224
224
  ```text
225
225
  1 @arnilo/prism
@@ -258,7 +258,7 @@ The tag workflow's only publication command is `npm run release:publish -- --ver
258
258
 
259
259
  #### Interruption and resume
260
260
 
261
- Do not create another tag or rerun packages manually. Re-run failed jobs for the same tag in GitHub Actions. The workflow invokes `release:publish --resume`: registry versions with matching names, versions, and internal dependency fingerprints are skipped; any mismatch stops the job. Retain `release-artifacts-v0.0.10` and `publish-report-v0.0.10` for audit.
261
+ Do not create another tag or rerun packages manually. Re-run failed jobs for the same tag in GitHub Actions. The workflow invokes `release:publish --resume`: registry versions with matching names, versions, and internal dependency fingerprints are skipped; any mismatch stops the job. Retain `release-artifacts-v0.0.96` and `publish-report-v0.0.96` for audit.
262
262
 
263
263
  #### Bounded post-publish smoke
264
264
 
@@ -266,9 +266,9 @@ Download the workflow artifact and run `sha256sum -c SHA256SUMS`. Then verify al
266
266
 
267
267
  ```bash
268
268
  while read -r package; do
269
- test "$(npm view "$package@0.0.10" version)" = "0.0.10"
270
- test "$(npm view "$package" dist-tags.latest)" = "0.0.10"
271
- npm view "$package@0.0.10" dist.integrity >/dev/null
269
+ test "$(npm view "$package@0.0.96" version)" = "0.0.96"
270
+ test "$(npm view "$package" dist-tags.latest)" = "0.0.96"
271
+ npm view "$package@0.0.96" dist.integrity >/dev/null
272
272
  done <<'PACKAGES'
273
273
  @arnilo/prism
274
274
  @arnilo/prism-coding-agent
@@ -307,7 +307,7 @@ PACKAGES
307
307
  consumer="$(mktemp -d)"
308
308
  cd "$consumer"
309
309
  npm init -y >/dev/null
310
- npm install --no-audit --no-fund @arnilo/prism-all@0.0.10
310
+ npm install --no-audit --no-fund @arnilo/prism-all@0.0.96
311
311
  node --input-type=module <<'NODE'
312
312
  for (const name of [
313
313
  "@arnilo/prism", "@arnilo/prism-coding-agent", "@arnilo/prism-coding-security",
@@ -330,11 +330,11 @@ This smoke is bounded to registry metadata, imports, CLI startup, checksums, sig
330
330
 
331
331
  #### Rollback limitations
332
332
 
333
- npm publication is not transactional and published versions are immutable. Partial publication is a resume case, not rollback. For a confirmed systemic defect after completion, deprecate every affected `@0.0.10`; restore `latest` to the previous good release only where that tag already existed. Exact `0.0.10` installs remain possible, so publish a fixed version promptly. Do not unpublish except for a security/legal emergency under npm policy.
333
+ npm publication is not transactional and published versions are immutable. Partial publication is a resume case, not rollback. For a confirmed systemic defect after completion, deprecate every affected `@0.0.96`; restore `latest` to the previous good release only where that tag already existed. Exact `0.0.96` installs remain possible, so publish a fixed version promptly. Do not unpublish except for a security/legal emergency under npm policy.
334
334
 
335
335
  ## Extension and configuration notes
336
336
 
337
- - **Required `@arnilo/prism` peer.** Every first-party package declares a non-optional `@arnilo/prism@0.0.10` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.10` for the 0.x series and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
337
+ - **Required `@arnilo/prism` peer.** Every first-party package declares a non-optional `@arnilo/prism@0.0.96` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.96` for the 0.x series and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
338
338
  - **Public access.** All 32 manifests (26 code packages + 6 family/profile packages) declare `"publishConfig": { "access": "public" }`; the publisher also passes `--access public` explicitly because scoped packages otherwise default to restricted on first publish.
339
339
  - **Map retention knob.** Source maps are emitted locally but stripped from tarballs by `!dist/**/*.map`. Removing that `files` negation ships maps in releases (larger tarballs, better consumer stack traces).
340
340
  - **Release workflow.** `.github/workflows/release.yml` has six jobs. `verify` runs network-free SDK readiness on Node 24; `node20-compat` builds/imports every public root `exports` default target on Node 20 for declared `engines.node >=20` (docs examples need Node >=22.6 native TypeScript stripping); `postgres-integration` uses `pgvector/pgvector:pg16`; `supply-chain` runs high-severity audit, SPDX/license policy, and tracked-source secret scanning; and tag-only `codeql-release` runs SAST. Tag-only `publish` needs all five gates, preserves clean exact-tag/version/topological publication, and alone receives `NPM_TOKEN`, `id-token: write`, and `attestations: write`. Before npm publish it packs all current tarballs, generates checksums plus SPDX, scans unpacked public artifacts, creates GitHub attestations for tarballs and SBOM, then retains artifacts for 30 days. Registry state remains the resumable journal. Local `npm run release:dry-run` remains network-free SDK readiness; local PostgreSQL coverage is `PRISM_TEST_POSTGRES_URL=... npm run test:postgres`.
@@ -367,24 +367,6 @@ npm publication is not transactional and published versions are immutable. Parti
367
367
  - **Install smoke is offline.** The install-smoke test packs core + every package into a temp dir and installs tarballs with `--offline --no-audit --no-fund` into a fresh project. External dependencies are satisfied from the lockfile-backed npm cache prepared by `npm ci`; any attempted uncached registry fetch fails the gate.
368
368
  - **Offline test budget.** The default `npm test` (no `PRISM_LIVE_PROVIDER_TESTS`) is pinned at **< 60s on Node 20** with a measured local baseline of ~45s (build ~18s + network-free tests/workspace tests/packaging smoke ~27s). The full CI `sdk:ready` gate runs on Node 24 because docs tests execute `examples/*.ts` via native TypeScript stripping. `npm run sdk:ready` also runs typecheck and pack dry-run, so it is allowed to exceed the `npm test` budget while remaining network-free. The CI `sdk:ready` step has `timeout-minutes: 5` as a hang backstop; the separate Node 20 compatibility step has `timeout-minutes: 3`. The budget was raised from 30s after the default suite grew to include every first-party package, offline install smoke, packaging guards, docs examples, and workspace tests; optimize before raising it again.
369
369
 
370
- ### 0.0.10 dependency audit decision (2026-07-21)
371
-
372
- `npm audit --audit-level=high` reports 0 vulnerabilities and `npm ls --all --depth=0` resolves the exact 32-package `0.0.10` graph (including `@arnilo/prism-browser`). Locked-install SPDX and `scripts/verify-sbom.mjs` pass. Browser keeps `playwright-core@1.61.0` as an optional peer and ships no browser binary/image; no Office package/binary enters the graph. Host mode never claims disposable containment.
373
-
374
- ### 0.0.10 release-candidate verification — 2026-07-21
375
-
376
- | Gate | Result |
377
- | --- | --- |
378
- | Package graph | Root + 31 workspaces = 32 publishable manifests at exact `0.0.10` with exact internal peer/dependency ranges (retargeted from post-ship `0.0.96`); `@arnilo/prism-browser` in `@arnilo/prism-all` only (not `@arnilo/prism-code`). |
379
- | Deterministic suites | `npm run sdk:ready` passed: 1,963 tests (1,934 pass, 29 explicit live skips, 0 fail), full typecheck/build/examples, docs/export/package/install smoke, and 32 dry-run packs. |
380
- | Workspace modes | Required `workspaceMode`; sandbox FS auto-wire; fail-closed mixed wiring; host non-containment; tree identity; adversarial consistency + `benchmark-0.0.10` schema green. |
381
- | Coding/browser | Network-free coding-agent + browser adversarial fixtures retained; `scripts/benchmark-0.0.10.mjs` host/sandbox-fake evidence (10-iter schema run green); protected Docker/Playwright remain operator P0 gates. |
382
- | Supply chain | `npm audit --audit-level=high` = 0 vulnerabilities; SPDX SBOM 186 packages / 8 approved licenses; working-tree secret scan 2,418 files / 0 findings; `git diff --check` clean. |
383
- | Artifacts | Packed review: 988,020 bytes compressed / 3,820,326 unpacked / 850 files across 32 tarballs; core 527,333 / 1,848,113 / 248 files; no Playwright binary/image and no Office package/binary. |
384
- | Registry/order | Public `release:check` found all 32 `@arnilo/*@0.0.10` versions available. Dependency-ordered `release:publish --dry-run --allow-dirty --allow-untagged` completed 32/32 dry-run with explicit public/latest/provenance; no commit, tag, or publication created. |
385
- | Office exclusion | No Office package, binary, SDK, wrapper, docs page, test, or release gate. |
386
- | Containment claims | Host mode and mixed-wiring escape hatch never claim disposable containment in docs/release notes. |
387
-
388
370
  ### 0.0.9 dependency audit decision (2026-07-21)
389
371
 
390
372
  `npm audit --audit-level=high` reports 0 vulnerabilities and `npm ls --all --depth=0` resolves the exact 32-package `0.0.96` graph (including `@arnilo/prism-browser`). Locked-install SPDX contains 185 packages and eight approved license expressions; `scripts/verify-sbom.mjs` passed. Browser keeps `playwright-core@1.61.0` as an optional peer and ships no browser binary/image; no Office package/binary enters the graph.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.0.10",
3
+ "version": "0.0.96",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,172 +0,0 @@
1
- # Review coverage — 2026-07-21 Phase 5
2
-
3
- Working evidence for Plan 073 Task 0. Freezes Phase 5 / Release **0.0.10** scope, workspace-mode contract, primitive ownership, reused finite limits, threats, tests, docs, and release gates before implementation.
4
-
5
- **Evidence frozen:** 2026-07-21. **Prism source:** `5fc05437224f347b00fb6124d1783eb2cd3a9b25` (Task 0 freeze). **Release target:** 0.0.10 (Task 7 retargeted graph from post-ship `0.0.96` → exact `0.0.10`). **Default test rule:** network-free fakes/fixtures; real Docker remains `PRISM_TEST_DOCKER_SANDBOX=1` protected gate.
6
-
7
- ## Status legend
8
-
9
- | Status | Meaning |
10
- | --- | --- |
11
- | `existing` | Current public contract covers the requirement. |
12
- | `extend` | Owning task extends an existing optional package/contract. |
13
- | `compose` | Existing public primitives suffice; package-local glue / docs / examples only. |
14
- | `out-of-scope` | Coding-harness P1/P2 or later release; must not land in 0.0.10 tasks. |
15
-
16
- ## Frozen product decision
17
-
18
- 0.0.10 closes **coding-harness P0 correctness** only: one explicit workspace mode so disposable sandbox shell and filesystem tools share one tree, fail-closed mixed wiring, tree-identity metadata on import/export/resume, docs that forbid treating host mode as containment.
19
-
20
- **Not in 0.0.10** (owned by later phases — do not implement here):
21
-
22
- | Deferred item | Owner phase |
23
- | --- | --- |
24
- | Session search/index | 0.0.11 Phase 6 |
25
- | Token/context budgeting + omission reporting | 0.0.11 Phase 6 |
26
- | Native Anthropic provider | 0.0.11 Phase 6 |
27
- | Native Google provider | 0.0.11 Phase 6 |
28
- | Goal→verify coding loop helper/example | 0.0.11 Phase 6 |
29
- | Additional subscription OAuth adapters | 0.0.12 Phase 7 |
30
- | AG-UI/ACP-facing event adapter | 0.0.12 Phase 7 |
31
- | Coding-aware compaction preset | 0.0.12 Phase 7 |
32
- | Enterprise identity / work connectors | 0.0.13+ |
33
- | New sandbox runtime, K8s/remote scheduler, automatic image pull, writable bind-mount as a third named mode | never in 0.0.10 |
34
-
35
- ## Frozen external revisions
36
-
37
- | Surface | Frozen reference | Compatibility decision |
38
- | --- | --- | --- |
39
- | Prism | [`5fc05437224f347b00fb6124d1783eb2cd3a9b25`](../plans/073-release-0-0-10-coding-harness-unified-workspace.md) | Caller/limit claims below checked against post-0.0.9 tree. |
40
- | Node.js | Local reference `v24.18.0`; release support remains Node 20 and current | FS/exec backends use `node:child_process` argument arrays, streams, `AbortSignal`, path, crypto hashes only. |
41
- | Docker CLI/Engine | Local reference client/server `29.6.1`; same Phase 4 docs | Reuse `createDockerSandbox` flags/limits; no new daemon features required for FS backends. |
42
- | Git | Local reference `git version 2.55.0` | Reuse `createGitTools` + `execFile` binder; same cwd/tree as sandbox mode. |
43
-
44
- ## Frozen workspace-mode contract
45
-
46
- | Decision | Frozen choice |
47
- | --- | --- |
48
- | Modes in 0.0.10 | Exactly `"host" \| "sandbox"`. No `"shared_mount"` / future aliases until a later release updates this page. |
49
- | `workspaceMode` default | **Required.** Missing/undefined throws at construction. No soft-default to host (would preserve the footgun for Docker users). |
50
- | Escape hatch | `allowMixedWorkspaceWiring: true` (name frozen). Without it, sandbox shell + host-mutating FS/list/search backends throw. With it, composition records explicit warnings; containment claim is false. |
51
- | Sandbox auto-wire prerequisite | Auto FS/repo backends (Task 2) require `DisposableSandbox` (`execFile`). Bare `SandboxAdapter` (exec-only) may be used in sandbox mode **only** when the host supplies agreeing custom `read`/`write`/`edit`/`repository.operations`. |
52
- | Host mode shell | May still use `options.sandbox` for shell only when FS backends are local host ops — that is **mixed wiring** and needs the escape hatch, **or** host mode with **no** sandbox (local shell + local FS). Preferred host mode: no sandbox adapter. |
53
- | Same-tree bind-mount | Host responsibility under escape hatch; Prism does **not** claim disposable containment for that wiring in 0.0.10. |
54
- | Construction API | Package-local `createSandboxCodingComposition(cwd, options) → { tools, composition }` is the authoritative path. `createSandboxCodingTools` / `createSandboxReadOnlyTools` remain thin wrappers returning `tools` only (compat). |
55
- | Composition metadata | `ToolDefinition` has **no** metadata field. Warnings/mode/containment live on `SandboxCodingComposition` (`workspaceMode`, `containmentClaim: boolean`, `mixedWiringAllowed: boolean`, `warnings: readonly string[]`, `workspaceRoot`, optional `treeIdentity`). Do not add core `ToolDefinition.metadata`. |
56
- | Containment claim | `containmentClaim === true` only when `workspaceMode === "sandbox"`, mixed wiring is denied, and FS/repo backends target the disposable tree. Host mode and escape-hatch mixed wiring always `false`. |
57
-
58
- ## Capability traceability matrix
59
-
60
- | Phase 5 roadmap criterion | Current 0.0.9 surface | Minimum 0.0.10 gap | Status / owner | Required proof | Docs | Release gate |
61
- | --- | --- | --- | --- | --- | --- | --- |
62
- | Explicit workspace mode; default sandboxed composition no longer silently pairs container shell with host FS mutations | `createSandboxCodingTools` wires shell via `createSandboxBashOperations`; read/write/edit/list/search keep host `cwd` (documented split) | Required `workspaceMode`; sandbox mode auto-wires FS/repo or fails closed | `extend` / Task 1 (+ Task 2 backends) | construction matrix: missing mode throws; sandbox without capable backends throws | `coding-security.md`, `migration.md` | offline coding-security tests |
63
- | Sandbox mode: shell + read/write/edit/repo_list/repo_search share one tree | Pluggable `*Operations` exist; no sandbox FS/repo defaults | Exec-backed (or host-supplied) FS + repository ops rooted at sandbox workspace | `extend` / Task 2 | write↔shell byte agreement; list/search agree with shell on same tree | `coding-security.md`, `coding-agent-tools.md` | fake sandbox + opt-in Docker |
64
- | Host mode: all tools on host workspace; no containment claim | `createCodingTools` local defaults; sandbox helper still claims “sandbox” by name while FS is host | Host mode local ops + `containmentClaim: false` | `extend` / Task 1 | host mutations land on host cwd; composition metadata non-isolating | `coding-security.md`, `host-security.md` | offline tests |
65
- | Import/export/close/resume preserve tree identity | `SandboxExportMetadata` `{ sha256, entryCount, byteCount, format }`; export two-pass; import tar summarize; no import hash retained on session; composition cannot refuse unbound FS | Retain/import identity on disposable session/status; composition refuses containment claim when backends unbound | `extend` / Task 4 | import→mutate→export hash change; export continuity; unbound backends fail closed | `coding-security.md`, `host-security.md` | fake CLI + protected Docker |
66
- | Reject unsafe mixed wiring unless escape hatch + surfaced metadata | Split composition is the silent default; no guard | Fail-closed check + `allowMixedWorkspaceWiring` + `composition.warnings` | `extend` / Task 1 | throw without hatch; warn with hatch | `coding-security.md`, `migration.md` | offline tests |
67
- | Performance: no unbounded host↔container sync; reuse entry/byte/time caps; host vs sandbox benchmarks | Existing sandbox/repo/coding hard caps; `scripts/benchmark-0.0.9.mjs` | Reuse caps for FS backends; forbid sync loops; `benchmark-0.0.10` both modes | `extend` / Task 5 | schema/bounds + consistency under caps; concurrent exec still enforced | `performance.md` | benchmark schema test + offline suite |
68
- | One construction path; pluggable backends; no second coding runtime | Aggregators + `*Operations` seams | Composition helper only; no new agent/runtime | `compose` / Tasks 1–3 | package stays optional; core dependency-free | `coding-security.md` | pack/install |
69
- | Git/check runners same tree/cwd in sandbox mode | `createGitTools({ execFile: sandbox.execFile })` documented; not auto-bundled | Documented/binder wiring + consistency test | `compose` / Task 3 | write then git status/diff sees file in sandbox | `coding-agent-tools.md`, `coding-security.md` | offline + fake execFile |
70
- | Security: path containment, policy, digest-pinned non-root Docker remain mandatory for advertised sandbox mode; forbid host-as-contained | Phase 4 Docker reference + approval policy | Docs + `containmentClaim` enforcement; host mode language | `extend` / Tasks 1, 6 | escape/path tests; docs assert host ≠ contained | `host-security.md`, `coding-security.md` | offline + protected Docker |
71
- | Docs/migration: 0.0.9 split superseded | Docs describe split as current | Replace guidance; migration note | `extend` / Task 6 | docs.test / migration assertions | `migration.md`, index summaries | docs tests |
72
- | Version/release 0.0.10 evidence | 32-package `0.0.9` (working tree may show `0.0.10`) | Bump graph, changelogs, `sdk:ready`, release dry-run | `extend` / Task 7 | full release gate | `release-and-install.md` | `sdk:ready` + dry-run |
73
-
74
- ## Primitive and caller inventory
75
-
76
- Frozen at `5fc05437224f347b00fb6124d1783eb2cd3a9b25` (+ this evidence page).
77
-
78
- | Primitive / symbol | Existing contract / callers | Phase 5 disposition |
79
- | --- | --- | --- |
80
- | `createSandboxCodingTools` / `createSandboxReadOnlyTools` | Defined `packages/coding-security/src/sandbox-coding-operations.ts`; exported from package index; **callers:** package tests only (no examples/src production caller yet) | Extend with required `workspaceMode`, mixed-wiring guard, sandbox auto-wire; wrappers over composition helper |
81
- | `createSandboxBashOperations` | `sandbox.ts`; used by composition, approval tests, sandbox-coding tests | Reuse for shell wiring; unchanged contract |
82
- | `SandboxAdapter` / `DisposableSandbox` / `createDockerSandbox` | `sandbox.ts`, `docker-sandbox.ts`; Docker tests | Reuse. Sandbox-mode auto FS requires `DisposableSandbox.execFile`. No new core sandbox type |
83
- | `SandboxExportMetadata` | `{ sha256, entryCount, byteCount, format: "tar" }` on close export | Reuse shape for tree identity; Task 4 may expose import/last-export on status/composition |
84
- | `ReadOperations` / `WriteOperations` / `EditOperations` | `packages/coding-agent/src/{read,write,edit}.ts`; local defaults; custom ops optional | Reuse contracts. Task 2 implements sandbox-backed adapters in **coding-security** only |
85
- | `RepositoryOperations` / `createLocalRepositoryOperations` | `repository.ts`; list/search tools | Reuse. Task 2 adds sandbox-backed repo ops in coding-security |
86
- | `BashOperations` / `createLocalBashOperations` | `shell.ts` | Reuse |
87
- | `createGitTools` / `resolveGitRunner` / `execFile` option | `git-tools.ts`, `git-exec.ts`; coding-agent git tests | Reuse. Task 3 documents/binds same workspace root; optional thin coding-security binder only if ≥2 non-test call sites |
88
- | `ExecutionPolicy` / path containment / approval | coding-security + coding-agent | Reuse; mandatory for advertised sandbox mode |
89
- | `ToolDefinition` | Core `src/contracts.ts` — name/description/parameters/exclusive/execute only | **No** new metadata field. Composition descriptor stays package-local |
90
- | Core agent/session/workflow runtimes | Unchanged | **No** second coding runtime; no core primitive promotion |
91
-
92
- ### Primitive decision
93
-
94
- **No new core primitive authorized.**
95
-
96
- Authorized package-local work (`@arnilo/prism-coding-security` unless noted):
97
-
98
- 1. `workspaceMode` + `allowMixedWorkspaceWiring` + `SandboxCodingComposition` + `createSandboxCodingComposition`.
99
- 2. `createSandboxFilesystemOperations` / `createSandboxRepositoryOperations` (names may shorten in impl; stay package-local).
100
- 3. Optional `bindSandboxGitOptions` only if examples + package tests both need identical wiring (else docs-only).
101
- 4. Minimal `DisposableSandbox` status/identity fields for import/export continuity (Task 4) — still coding-security local.
102
-
103
- Promote to core only with ≥2 non-test consumers outside coding-security **and** migration/conformance evidence. One-consumer interfaces, sync daemons, Merkle indexes, and third workspace modes are rejected for 0.0.10.
104
-
105
- ## Frozen capability boundary
106
-
107
- | Surface | Supported in 0.0.10 | Explicitly unsupported |
108
- | --- | --- | --- |
109
- | Workspace modes | `host`, `sandbox`; required option; fail-closed mixed wiring; escape hatch with warnings | Soft-default mode; silent split-brain; named `shared_mount` mode; claiming containment for host/escape-hatch |
110
- | Sandbox FS | ExecFile-backed read/write/edit/list/search against disposable tree; host-supplied custom ops | Unbounded bidirectional sync loops; new transport protocol; automatic host write-back |
111
- | Docker reference | Existing digest-pinned, non-root, network-none, finite tmpfs, import/export | Image pull/build, daemon provisioning, K8s, Docker socket exposure |
112
- | Git/checks | Same-tree via `execFile` + cwd; optional binder | Auto-include Git in default coding tool set; push/PR/network |
113
- | Artifacts / identity | Existing export metadata + retained import/export hashes for resume checks | Full workspace in checkpoints; secret-bearing identity blobs |
114
-
115
- ## Frozen finite limits and charging points
116
-
117
- **Rule:** Reuse Phase 4 / shipped coding-security and coding-agent defaults and hard caps. Task 2–5 **must not** raise hard caps or add unbounded sync. Charge before each sandbox FS/repo/exec operation against the same counters.
118
-
119
- ### Sandbox and workspace (reuse `sandbox-limits.ts`)
120
-
121
- | Resource | Default / hard cap | Charge/check point | Failure/cleanup owner |
122
- | --- | --- | --- | --- |
123
- | Startup / wall / idle | 30 s / 120 s; 20 min / 30 min; 5 min / 15 min | Existing create/exec | Task 4/Docker session |
124
- | CPU / memory / PIDs / FDs | 2 / 8; 2 GiB / 16 GiB; 256 / 1,024; 1,024 / 8,192 | Before `docker run` | existing |
125
- | Workspace / tmp / download tmpfs | 1 GiB / 8 GiB; 256 MiB / 2 GiB; 64 MiB / 512 MiB | Before create / write overflow | existing |
126
- | Commands / concurrent execs | 100 / 256; 1 / 8 | Before each exec **including FS-backend execFile** | Task 2 must share queue |
127
- | Command/FS output | 64 MiB / 1 GiB | Stream before retain | Task 2 + output accumulator |
128
- | Import/export entries/bytes / retained artifacts | 50,000 / 250,000; 256 MiB / 2 GiB; 16 / 64 | Before retain; two-pass hash verify | Task 4 |
129
- | Stop grace / cleanup | 5 s / 30 s; 30 s / 120 s cleanup | Terminal paths | existing |
130
-
131
- **Forbidden:** background host↔container watchers, periodic full-tree sync, unbounded `docker cp` retry loops, retaining more than `maxExport*` without export API.
132
-
133
- ### Repository / read / write / edit (reuse `packages/coding-agent/src/limits.ts`)
134
-
135
- | Resource | Default / hard cap | Owner for sandbox backends |
136
- | --- | --- | --- |
137
- | Repo depth / entries / files / results / concurrency | 32 / 128; 10k / 100k; 10k / 100k; 1k / 10k; 8 / 32 | Task 2 |
138
- | Search scan/file/matches/pattern/line/context/time | 64 MiB / 1 GiB; 8 MiB / 64 MiB; 1k / 10k; 512 / 4,096 B; 50 KiB / 1 MiB; 5 / 20; 30 s / 300 s | Task 2 |
139
- | Read text/image; write; edit file/input/edits | existing coding-agent ceilings | Task 2 |
140
- | Git paths/refs/message/output | existing git ceilings | Task 3 |
141
-
142
- ## Threat and authority matrix
143
-
144
- | Boundary | Trusted authority | Untrusted input | Mandatory control | Default / unsupported |
145
- | --- | --- | --- | --- | --- |
146
- | Workspace mode selection | Host sets `workspaceMode` explicitly | Model/tool args cannot change mode | Construction throws if missing; mixed wiring throws without hatch | Silent split-brain unsupported |
147
- | Sandbox containment claim | Host + composition when backends agree on disposable tree | Model claims, host cwd edits under sandbox advertising | `containmentClaim` only when mode=sandbox and backends bound; path containment + Docker policy | Host mode / escape hatch never claim containment |
148
- | Sandbox FS backends | Host-supplied `DisposableSandbox` or custom ops | Paths, symlink targets, archive/exec output | Workspace-root realpath/containment; byte/entry/time caps; share concurrent exec limits | Escape outside `/workspace` denied |
149
- | Mixed wiring escape hatch | Host sets `allowMixedWorkspaceWiring` | Accidental omitted ops | Explicit option + `composition.warnings` | Undocumented mixed wiring unsupported |
150
- | Import/export identity | Host artifact callback + hash verify | Tar headers/content | Existing type checks + two-pass hash; resume compares hashes | Advertise sandboxed coding on unbound host root unsupported |
151
- | Docker/image/secrets | Host digest/CLI/allow-list | Model env/commands | Phase 4 Docker controls unchanged | Pull/build/socket unsupported |
152
- | Git in sandbox | Host `commitIdentity` + `execFile` | Refs/pathspecs/hooks | Existing safe git config; same workspace root | Push/PR/credentials unsupported |
153
-
154
- ## Validation matrix for Task 0
155
-
156
- | Check | Frozen assertion |
157
- | --- | --- |
158
- | Traceability | Every Phase 5 roadmap criterion maps to exactly one primary owner among Tasks 1–7; 0.0.11+ items listed only under out-of-scope. |
159
- | Primitive reuse | No new core primitive. FS/repo helpers stay coding-security-local unless a second non-test consumer appears. |
160
- | Finite resources | Sandbox FS/repo paths reuse existing defaults/hard caps; concurrent exec shared; no sync loops. |
161
- | Security claims | Containment is Docker/host policy + bound backends, not regex; host mode and escape hatch are non-containing by contract. |
162
- | Mode API | `workspaceMode` required; modes `{host,sandbox}` only; escape hatch name `allowMixedWorkspaceWiring`; metadata on `SandboxCodingComposition`, not `ToolDefinition`. |
163
-
164
- ## Documentation and release ownership
165
-
166
- - Task 0 (this page): scope freeze, index link, docs.test evidence assertions.
167
- - Tasks 1–4: implementation; API docs deferred to Task 6 except in-code JSDoc.
168
- - Task 5: adversarial tests, `scripts/benchmark-0.0.10.mjs`, protected Docker extensions.
169
- - Task 6: `docs/coding-security.md`, `docs/coding-agent-tools.md`, `docs/migration.md`, `docs/host-security.md`, `docs/performance.md`, package READMEs/changelogs, index summary tweaks.
170
- - Task 7: version `0.0.10`, `sdk:ready`, pack/install/supply-chain, release dry-run — **done** (1,963 tests / 1,934 pass / 29 skip; 32/32 dry-run; no tag/publish).
171
-
172
- No public implementation API changes in Task 0. This page, `roadmap.md` Phase 5, and Plan 073 are the authoritative pre-implementation boundary; later tasks may tighten defaults but cannot raise hard caps, add sync loops, introduce a third mode, or claim host-mode containment without updating tests, docs, and this evidence.