@arnilo/prism 0.0.26 → 0.0.27

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
@@ -1,5 +1,20 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.27] - 2026-08-07
4
+
5
+ ### Added
6
+ - ACP coding-host interop (`@arnilo/prism-ag-ui/acp`, stable ACP v1 over `@agentclientprotocol/sdk@1.3.0`): capability advertisement is a pure function of host seams (`loadSession`/`sessionCapabilities.*`/`promptCapabilities.*`/`mcpCapabilities.*`; `close` always; UNSTABLE cells never advertised), session persistence (`session/load|resume|list|delete`, bounded registry), session modes and config options as host overlays (`set_mode`, `set_config_option`, `current_mode_update`, `config_option_update`), client fs/terminal adapters (`AcpClientFilesystem`/`AcpClientTerminals`), MCP servers only behind host `select`, rich prompt content (`projectAcpPrompt`: media + embedded resources under live policy), tool-call locations/diffs via projection allow-lists, `CodingLifecycleEvent` → ACP update mapping, four-outcome approvals with elicitation (`elicitation/create` when advertised), and `AcpError` codes `ERR_PRISM_ACP_INPUT/LIMIT/POLICY/CAPABILITY/MCP`. Frozen caps in `resolveAgUiLimits` (`caps.acp`/`caps.lifecycle` groups).
7
+ - Phase 10 evidence: network-free `scripts/phase10-conformance.test.mjs` (in `npm test`), operator-gated real-transport smoke (`scripts/acp-client-smoke.mjs` + fixture), `examples/acp-coding-host.ts`, `scripts/benchmark-0.0.27.mjs` + `scripts/benchmark-0.0.27.json` evidence, `scripts/budgets.json` `phase10` gate.
8
+ - Docs: new [docs/acp.md](docs/acp.md) ACP reference; migration `0.0.26 → 0.0.27`; `docs/ag-ui.md` ACP summary + link; ACP pointers across agent-events/coding-agent-tools/coding-security/mcp-tools/host-security; package README.
9
+
10
+ ### Changed
11
+ - `@arnilo/prism-ag-ui` depends on `@arnilo/prism-coding-agent` (workspace) for Phase 9 output-chunk caps and lifecycle types; publishable graph stays **48** manifests.
12
+ - SBOM license policy allows `Unlicense` (tweetnacl via `@nats-io/nkeys`); readiness SBOM evidence refreshed (227 packages / 12 licenses).
13
+ - `@arnilo/prism-ag-ui/renderer` now exports the DOM-free A2UI core values (`A2UiSurfaceState`, `reduceA2UiOps`, `readA2UiBatch`, `resolvePointer`, `A2UI_VERSION`) — Synapta FR, hosts can drive the surface state machine without mounting; `createA2UiRenderer` behavior and frozen A2UI caps unchanged.
14
+
15
+ ### Breaking (advertise/surface for ACP hosts only)
16
+ - `initialize` advertisement now reflects wired seams (previously minimal close-session); new session methods are registered only with their seams; `session/resume` of a live session rejects; `agentInfo.version` now comes from the package.json. Core, AG-UI, and coding-agent behavior unchanged. See [migration guide](docs/migration.md) `0.0.26 → 0.0.27`.
17
+
3
18
  ## [0.0.26] - 2026-08-06
4
19
 
5
20
  ### Added
package/dist/index.d.ts CHANGED
@@ -105,5 +105,5 @@ export type { ToolEffectErrorCode } from "./tool-effects.js";
105
105
  export type { ResolvedUseCaseModel, ResolveUseCaseModelInput, UseCaseModelBinding, } from "./use-case-model.js";
106
106
  export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
107
107
  export declare const name = "prism";
108
- export declare const version = "0.0.26";
108
+ export declare const version = "0.0.27";
109
109
  export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
package/dist/index.js CHANGED
@@ -57,6 +57,6 @@ export { createToolParameterValidator, createToolRegistry, dispatchToolCall, fil
57
57
  export { createMemoryToolEffectStore, ToolEffectError } from "./tool-effects.js";
58
58
  export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
59
59
  export const name = "prism";
60
- export const version = "0.0.26";
60
+ export const version = "0.0.27";
61
61
  export const description = "Agent harness for AI providers, agents, sessions, and tools.";
62
62
  //# sourceMappingURL=index.js.map
@@ -1,12 +1,12 @@
1
1
  # 0.1.0 / 1.0 Readiness Gates
2
2
 
3
- Status: **0.0.26** is the current release line (Phase 9 coding intelligence, managed processes, forge, and safe egress); **1.0** readiness remains operator-gated, not automatic.
3
+ Status: **0.0.27** is the current release line (Phase 10 ACP coding-host interop); **1.0** readiness remains operator-gated, not automatic.
4
4
 
5
5
  This page distills runnable readiness gates into one command-per-gate table. The
6
6
  **Last evidence** column records the 2026-07-26 **0.0.16** baseline snapshot
7
7
  (Phase 11, Node v24.18.0, Linux x86_64). Treat it as historical floor evidence,
8
8
  not the current release tag. Re-run each gate on the target release tree before
9
- cutting 0.0.26 / 1.0. The decision to cut 1.0 stays with the operator after
9
+ cutting 0.0.27 / 1.0. The decision to cut 1.0 stays with the operator after
10
10
  operator-gated legs run in a protected environment and Phase 12 demand evidence
11
11
  exists.
12
12
 
@@ -14,16 +14,16 @@ Evidence trail: [`docs/review-coverage-2026-07-26-phase-11.md`](./review-coverag
14
14
  (addenda 0–9), [`docs/release-and-install.md`](./release-and-install.md),
15
15
  [`docs/migration.md`](./migration.md), [`docs/performance.md`](./performance.md).
16
16
 
17
- ## Current line (0.0.26)
17
+ ## Current line (0.0.27)
18
18
 
19
19
  | Item | Status |
20
20
  |---|---|
21
- | Published graph | **48** publishable manifests at **0.0.26** (`docs/release-and-install.md`) |
22
- | Phase 9 coding intelligence / processes / forge / egress | Git-aware enumeration, LSP language intelligence, managed process sessions, GitHub forge with idempotent handoff, allow-list egress proxy with rebinding defense |
23
- | Docs tripwires | `node --test dist/__tests__/docs.test.js` — migration section `0.0.25 → 0.0.26 coding intelligence, processes, forge, and egress` |
24
- | Network-free Phase 9 evidence | `scripts/phase9-conformance.test.mjs`; `benchmark-0.0.26.json` under Task 0 ceilings |
21
+ | Published graph | **48** publishable manifests at **0.0.27** (`docs/release-and-install.md`) |
22
+ | Phase 10 ACP coding-host interop | Seam-based capability advertisement, session persistence, modes/config overlays, client fs/terminal adapters, MCP select gate, `CodingLifecycleEvent` → ACP updates, four-outcome approvals + elicitation, frozen caps |
23
+ | Docs tripwires | `node --test dist/__tests__/docs.test.js` — migration section `0.0.26 → 0.0.27 ACP coding-host interop`; `docs/acp.md` reference |
24
+ | Network-free Phase 10 evidence | `scripts/phase10-conformance.test.mjs`; `benchmark-0.0.27.json` under Task 0 p95 ceilings; freeze manifest matched by exports |
25
25
  | Protected database evidence (Phase 7) | `PRISM_TEST_POSTGRES_URL="$DATABASE_URL" npm run test:postgres`; `benchmark-0.0.24.json` under prior ceilings |
26
- | Readiness table below | **0.0.16 measured values** remain historical network-free baseline; 0.0.26 Phase 9 evidence is recorded separately |
26
+ | Readiness table below | **0.0.16 measured values** remain historical network-free baseline; 0.0.27 Phase 10 evidence is recorded separately |
27
27
 
28
28
  ## Gate table
29
29
 
@@ -36,7 +36,7 @@ Evidence trail: [`docs/review-coverage-2026-07-26-phase-11.md`](./review-coverag
36
36
  | Deterministic artifact budget | `node --test dist/__tests__/budget-gate.test.mjs` | root 579.2 kB / 2.1 MB / 270 files within +5% of baseline; startup 38 ms < 250 ms ceiling | CI (in `npm test`) |
37
37
  | Performance benchmark medians | `node scripts/benchmark-0.0.16.mjs` | 6 network-free scenarios within ±25%; 0 backpressure / 0 resource-limit signals | On-demand release evidence |
38
38
  | Secret scan | `node scripts/scan-secrets.mjs` | 3095 files / 0 findings | CI |
39
- | License / SBOM | `node scripts/verify-sbom.mjs` | 188 packages / 8 licenses, all allow-listed | CI |
39
+ | License / SBOM | `node scripts/verify-sbom.mjs` | 227 packages / 12 licenses, all allow-listed | CI |
40
40
  | Dependency audit | `npm audit --audit-level=high` | rc=0 (2 moderate, 0 high) at 0.0.16 | CI |
41
41
  | Whitespace hygiene | `git diff --check` | clean | CI |
42
42
  | Publish order + tarball validation | `node scripts/release.mjs publish --version <v> --dry-run --allow-dirty --allow-untagged` | 44/44 packages `dry-run`, deterministic dependency order, no failures | Operator (dry-run), CI |
@@ -114,7 +114,7 @@ protected environment, never faked.
114
114
  | Control | Command / source | 0.0.16 baseline |
115
115
  |---|---|---|
116
116
  | Secret scan | `node scripts/scan-secrets.mjs` | 3095 files / 0 findings |
117
- | License / SBOM | `node scripts/verify-sbom.mjs` | 188 packages / 8 licenses, allow-listed |
117
+ | License / SBOM | `node scripts/verify-sbom.mjs` | 227 packages / 12 licenses, allow-listed |
118
118
  | Dependency audit | `npm audit --audit-level=high` | 0 high (2 moderate) |
119
119
  | SAST | GitHub CodeQL workflow | CI-gated |
120
120
  | Sandbox / protocol / tenant threat suites | `npm test` (coding-security, MCP, policy, guardrail suites) | green at 0.0.16 |
package/docs/acp.md ADDED
@@ -0,0 +1,126 @@
1
+ # Agent Client Protocol (ACP) coding-host interop
2
+
3
+ ## What it does
4
+
5
+ `@arnilo/prism-ag-ui/acp` (stable ACP **v1**, `@agentclientprotocol/sdk@1.3.0` root exports only) exposes two adapters:
6
+
7
+ - `createPrismAcpAgent(options)` — serves ACP as an **agent**: an editor/AI client connects through the SDK transport and drives host-owned Prism sessions with `session/new`, `session/load`, `session/resume`, `session/prompt`, `session/set_mode`, `session/set_config_option`, `session/list`, `session/delete`, `session/close`, and `session/cancel`. The agent is a thin protocol adapter: every capability, decision, and byte cap is wired from host seams, and there is **no second policy engine** on the agent side.
8
+ - `createAcpEventMapper(options)` — maps a Prism `AgentEvent` stream (or `CoWorkEvent`) to ACP `SessionUpdate`s for hosts that stream through their own transport.
9
+
10
+ The adapter builds on the Phase 8/9 shared machinery: redacted event projection (`AgUiProjection`), the durable pending-decision batch model (`allow_once` / `allow_for_run` / `reject_once` / `reject_for_run`), `AgentRunLifecycle` resume, `CodingLifecycleEvent` emission, and the AG-UI/ACP package caps. It never ships experimental ACP v2 or UNSTABLE fields (`providers`, `nes`, `positionEncoding`, `sessionCapabilities.fork`, `mcpCapabilities.acp/auth`, `elicitation` is consumed client-side only and never advertised).
11
+
12
+ ## When to use it
13
+
14
+ Use `createPrismAcpAgent` when an editor/AI client already speaks ACP and you want it to reach host-owned Prism runs: text streaming, safe tool status, usage, four-outcome approvals, session persistence, modes, config options, and — when the client advertises them — editor-buffer filesystem (`fs/read_text_file`, `fs/write_text_file`) and terminal (`terminal/create` … `terminal/kill`) client methods, plus prompt media (`image`, `audio`, `embeddedContext`) and `elicitation` decisions.
15
+
16
+ Do **not** use it when the host needs a browser/TUI Web endpoint (use [AG-UI](ag-ui.md)), remote agent-to-agent tasks ([A2A](a2a.md)), or a full editor integration — ACP is a protocol adapter, not an editor, a TUI, or a credential provider.
17
+
18
+ ## Inputs / request
19
+
20
+ `createPrismAcpAgent(options: CreatePrismAcpAgentOptions)` — every field is host-supplied:
21
+
22
+ | Option | Shape | Effect |
23
+ |---|---|---|
24
+ | `authorize` | `(input) => AcpAuthorization \| Promise` | **Required.** Ownership/identity gate for every inbound call, scoped by `sessionId`; unknown sessions fail. |
25
+ | `sessionFactory` | `(input) => AcpSessionBinding \| Promise` | **Required.** Builds the Prism `AgentSession` for `session/new`. Input carries `authorization`, `cwd`, `additionalDirectories`, `mcpServers` (policy-checked), `signal`, optional pre-generated `sessionId`, and `coding` (built client fs/terminal adapters when the client advertised them). |
26
+ | `lifecycle` | `AgentRunLifecycle` | **Required.** `status`/`resume`/`resumeStream` for durable `session/load` and `session/resume`. |
27
+ | `sessions?` | `AcpSessionStoreSeams` | `load` (advertises `sessionCapabilities.loadSession`), `list` (list), `delete` (delete), `resume` (resume), `additionalDirectories` (policy narrowing of `additionalDirectories`). `close` is always advertised. |
28
+ | `mcp?` | `AcpMcpSeams` | `transports: ("http" \| "sse")[]` and `select({ servers, signal })` — **required** for any client-supplied MCP server; select must approve before the bridge connects. Advertises `mcpCapabilities.http`/`sse` per transport. |
29
+ | `modes?` | `{ modes: AcpSessionMode[], defaultModeId? }` | `AcpSessionMode { id, name, description?, apply? }`; `apply({ sessionId?, fromModeId?, modeId, signal })` is the host hook run on switch. Advertised in `SessionModeState` on new/load/resume; enables `session/set_mode`. |
30
+ | `configOptions?` | `{ options: AcpConfigOption[], onChange? }` | `boolean`/`select` options with `defaultValue`; enables `session/set_config_option` (requires the client to advertise `session.configOptions.boolean`). |
31
+ | `capabilities?` | `AcpCapabilitiesOptions` | `prompt.media`/`prompt.embedded` policy seams, re-checked **live at prompt time**; presence advertises `promptCapabilities.image`/`audio`/`embeddedContext`. |
32
+ | `coding?` | `AcpCodingSeams` | `filesystem(client, sessionId)` / `processes(client, sessionId)` factories building `AcpClientFilesystem` / `AcpClientTerminals` over client methods; `lifecycle?: CodingLifecycleEmitter` subscribes `CodingLifecycleEvent`s into ACP updates. |
33
+ | `name?` | `string` | `agentInfo.name` (default `"Prism"`). |
34
+
35
+ Client capabilities are read at `initialize` and gate **client-method use**, not advertisement: `fs.readTextFile`/`writeTextFile` gate the fs seam, `terminal` the processes seam, `session.configOptions.boolean` the config path, `elicitation` the elicitation route.
36
+
37
+ ## Outputs / response / events
38
+
39
+ `initialize` returns `{ protocolVersion, agentCapabilities, agentInfo }`; `agentInfo.version` comes from the package manifest. Advertised capability = a host seam is wired (pure function, no hand-maintained matrix): `loadSession`/`sessionCapabilities.*` iff the matching `sessions` seam exists (`close` always), `promptCapabilities.*` iff the matching `capabilities.prompt` seam exists, `mcpCapabilities.*` iff `mcp.select` + the transport are wired. Unadvertised agent methods fail naturally with JSON-RPC `-32601`; unadvertised client methods are never called.
40
+
41
+ In-stream `SessionUpdate`s:
42
+
43
+ | Prism event | ACP update |
44
+ |---|---|
45
+ | Assistant text | `agent_message_chunk` |
46
+ | Tool lifecycle | `tool_call` / `tool_call_update` (title/status/content) |
47
+ | Tool result, projected | `tool_call_update` with `locations` (≤ `acpLocationsPerUpdate`) and/or a `diff` block (≤ `acpDiffBytes`) — only from `AgUiProjection.toolLocations`/`toolDiff` allow-lists, at `finish()` |
48
+ | Provider usage / errors | `usage_update`, `error` |
49
+ | Durable suspension | `session/request_permission` with the four outcomes `allow_once` / `allow_for_run` / `reject_once` / `reject_for_run`; cancel, unknown options, and request failure deny. Sticky decisions expire at run end. |
50
+ | Elicitation suspension (all-elicitation batch + client advertised `elicitation`) | `elicitation/create` (form mode, bounded schema, redacted reason); `accept` → `allow_once` with the typed payload as `RunDecision.elicitation`, `decline`/`cancel` → `reject_once`. Otherwise falls back to the shared four-option permission path. |
51
+ | `file_changed` lifecycle | `tool_call_update` with `locations: [{ path }]` (needs a `toolCallId`; diff only from `fileDiff` allow-list, capped + redacted) |
52
+ | `worktree_changed` / process events | Projection-gated `agent_message_chunk` (deny-by-default: no `lifecycle` projection hook = no update) |
53
+ | `permission_denied` lifecycle | `tool_call_update` status `failed` (never raw args; synthesized id `prism:denied:<approvalId>` when no `toolCallId`) |
54
+ | `configuration_changed` lifecycle | `config_option_update` with the full current set, per streaming session |
55
+ | Session mode/config switch | `current_mode_update` / `config_option_update` |
56
+
57
+ Frozen caps (default / hard, from the Phase 10 freeze manifest): sessions 32/128, additional directories 8/32 (path 4 KiB/16 KiB), MCP servers 8/32 (config 16 KiB/256 KiB, header values 4 KiB/64 KiB), modes 16/64, config options 16/64, list page 20/100, diff bytes 64 KiB/1 MiB, locations per update 32/128, prompt media parts 16/64 and media bytes 64 KiB/1 MiB (shared AG-UI caps), terminal output chunks 51200 B/1 MiB (Phase 9 `process.outputChunkBytes`), stream events/bytes per AG-UI budgets. `session/load`/`session/resume` of a still-registered session rejects with `ERR_PRISM_ACP_INPUT` ("ACP session already exists"); model reconnect as resume of a pre-seeded stored session.
58
+
59
+ Errors surface as `AcpError` with codes `ERR_PRISM_ACP_INPUT` (malformed), `ERR_PRISM_ACP_LIMIT` (caps), `ERR_PRISM_ACP_POLICY` (host denied), `ERR_PRISM_ACP_CAPABILITY` (not advertised), `ERR_PRISM_ACP_MCP` (MCP bridging). Over the wire they become JSON-RPC `-32603` with the message in `data.details` (SDK behavior).
60
+
61
+ ## Request/response example
62
+
63
+ ```json
64
+ // initialize → agentCapabilities (all seams wired)
65
+ {
66
+ "protocolVersion": 1,
67
+ "agentCapabilities": {
68
+ "loadSession": {},
69
+ "sessionCapabilities": { "list": {}, "delete": {}, "additionalDirectories": {}, "resume": {}, "close": {} },
70
+ "promptCapabilities": { "image": true, "audio": true, "embeddedContext": true },
71
+ "mcpCapabilities": { "http": true, "sse": true }
72
+ },
73
+ "agentInfo": { "name": "Prism", "version": "0.0.27" }
74
+ }
75
+
76
+ // session/new response (modes + configOptions wired)
77
+ { "sessionId": "acp-9f1c…", "modes": { "currentModeId": "edit", "availableModes": [{ "id": "edit", "name": "Edit" }] },
78
+ "configOptions": [{ "type": "boolean", "id": "verbose", "name": "Verbose", "defaultValue": false, "currentValue": false }] }
79
+ ```
80
+
81
+ ## Implementation example
82
+
83
+ See [`examples/acp-coding-host.ts`](../examples/acp-coding-host.ts) (runs in the demo gate). The host owns all state and policy:
84
+
85
+ ```ts
86
+ import { createPrismAcpAgent } from "@arnilo/prism-ag-ui/acp";
87
+
88
+ const agent = createPrismAcpAgent({
89
+ authorize: ({ sessionId }) => (sessionId ? hostSessions.has(sessionId) : true)
90
+ ? { ownership: { userId: "host-user" } }
91
+ : false,
92
+ sessionFactory: (input) => ({ session: hostSessionFor(input) }), // Prism AgentSession
93
+ lifecycle: { status, resume, resumeStream }, // durable
94
+ sessions: { load, list, delete, resume, additionalDirectories }, // capability seams
95
+ mcp: { transports: ["http", "sse"], select: ({ servers }) => approve(servers) },
96
+ modes: { modes: [{ id: "edit", name: "Edit" }, { id: "review", name: "Review", apply: narrow }], defaultModeId: "edit" },
97
+ configOptions: { options: [{ type: "boolean", id: "verbose", name: "Verbose", defaultValue: false }] },
98
+ capabilities: { prompt: { media: async () => true, embedded: async () => false } },
99
+ coding: { lifecycle, filesystem: clientFsAdapter, processes: clientTerminalAdapter },
100
+ });
101
+ // serve over the host's ACP transport: agent.connect(stream)
102
+ ```
103
+
104
+ ## Extension and configuration notes
105
+
106
+ - **Seam = capability.** Wiring `sessions.load` advertises `loadSession`; removing it withdraws the method. There is no separate capability flag to keep in sync — the freeze manifest's advertise-when matrix is enforced by construction and asserted by `scripts/phase10-conformance.test.mjs`.
107
+ - **Client fs/terminal are adapters, not a second implementation.** `AcpClientFilesystem` / `AcpClientTerminals` wrap the client's `fs/*` and `terminal/*` methods behind the Phase 9 `ProcessSession`-flavored interfaces; the agent pre-generates the session id so terminal requests can carry it. Host repo operations remain default when the client fs is absent.
108
+ - **Modes and config options are a pure host overlay.** The agent stores only a thin per-session registry; `apply`/`onChange` hooks narrow the host's own behavior. Mode switches can narrow or host-authorized widen — never a parallel policy evaluator, never a client-enabled tool.
109
+ - **Lifecycle wiring.** Pass your `createCodingLifecycleEmitter()` as `coding.lifecycle`; `file_changed` etc. then flow to streaming sessions. `configuration_changed` broadcasts `config_option_update` (agent-message fallback if the SDK rejects the kind).
110
+ - **Stream budgets.** Every lifecycle update counts against the same per-run stream event/byte budget as prompt updates; overflowing closes the update, never the run.
111
+
112
+ ## Security and performance notes
113
+
114
+ - **Untrusted client input.** Client-supplied paths, `additionalDirectories`, MCP server configs, terminal env/args, and media are validated at the boundary: count/byte caps, ownership-scoped sessions, path policy via the `sessions.additionalDirectories` seam, MCP servers only through host `select` (never auto-connected), UNSTABLE `acp` transport always rejected.
115
+ - **Deny-closed by default.** Unknown mode ids, unadvertised methods, unprojected lifecycle events, oversize diffs/locations/media, thrown projection hooks, and failed elicitation all fail closed. Raw tool arguments/results are never sent unless a projection allow-list says otherwise.
116
+ - **No secrets.** Updates carry no raw file bodies, terminal output is capped by the Phase 9 chunk budget, and the shared redactor is applied before anything leaves the host. `permission_denied` never includes raw args.
117
+ - **Performance.** The adapter is O(1) per update with no unbounded buffering; p95 targets (fs round trip 250 ms, mode switch 250 ms, terminal chunk ack 1000 ms, prompt first update 2000 ms, prompt end 30 s) are recorded by `scripts/benchmark-0.0.27.mjs` and gated in `scripts/budgets.json` `phase10`.
118
+
119
+ ## Related APIs
120
+
121
+ - [AG-UI](ag-ui.md): sibling frontend protocol; shared projection/redaction/caps and the same pending-decision model. This page is the full ACP reference.
122
+ - [Coding agent tools](coding-agent-tools.md): the `CodingLifecycleEvent` source mapped here; `@arnilo/prism-coding-agent` `process.outputChunkBytes` caps terminal chunks.
123
+ - [Agent events](agent-events.md): the durable `AgentEventSource`/replay story behind `session/load` and `session/resume`.
124
+ - [Host security guide](host-security.md): fail-closed checklist rows for ACP boundaries (authorize, ownership, redaction, untrusted MCP).
125
+ - [Migration guide](migration.md): 0.0.26 → 0.0.27 advertise/surface changes for hosts that parsed the old `initialize`.
126
+ - [AG-UI adoption evaluation](ag-ui-adoption.md): the underlying input/event/capability matrix.
package/docs/ag-ui.md CHANGED
@@ -5,7 +5,7 @@
5
5
  `@arnilo/prism-ag-ui` is an optional, framework-free protocol adapter over Prism's existing redacted `AgentEvent`, session, durable-run, and persistence seams.
6
6
 
7
7
  - Root export maps Prism events to AG-UI `@ag-ui/core` **0.0.57** events and offers `createAgUiHandler()` (`Request` → SSE `Response`), compatible `createPersistenceAgUiReplay()` pages, distributed `createAgentEventSourceAgUiReplay()` follow, and explicit `createAgUiMcpAdapter()` / `createAgUiMcpAppHandler()` / `createAgUiA2AAdapter()` protocol handshakes.
8
- - `@arnilo/prism-ag-ui/acp` uses stable `@agentclientprotocol/sdk` **1.3.0** root exports for `createAcpEventMapper()` and `createPrismAcpAgent()`.
8
+ - `@arnilo/prism-ag-ui/acp` is the stable ACP **v1** sibling: `createAcpEventMapper()` and `createPrismAcpAgent()` over `@agentclientprotocol/sdk` **1.3.0** root exports. ACP is a protocol adapter — sessions, modes, MCP, fs/terminal, lifecycle mapping, and caps live on the host seams. See [ACP coding-host interop](acp.md) for the full reference; this page covers AG-UI only.
9
9
  - Core remains protocol-free. `resumeAgentRunStream()` / `AgentRunLifecycle.resumeStream()` are generic durable-resume streams shared by adapters.
10
10
 
11
11
  ## When to use it
@@ -50,7 +50,7 @@ A Prism durable `agent_suspended` returns `RUN_FINISHED` with core interrupt id
50
50
 
51
51
  `createPersistenceAgUiReplay()` remains a compatible page adapter. `createAgentEventSourceAgUiReplay()` resolves exact ownership/run once per open, then consumes the shared durable source through terminal or live follow; it never attaches replica-local `session.subscribe()`. Every record must already be redacted. Mapped events carry stable `prismEventId` and bounded opaque `prismCursor`; records with no standard mapping emit `CUSTOM prism.replay_cursor`, so clients can persist progress. Terminal replay never creates a session or reruns a provider/tool.
52
52
 
53
- ACP maps assistant text to `agent_message_chunk`, safe tool lifecycle to `tool_call`/`tool_call_update`, provider usage to `usage_update`, and durable suspension to `session/request_permission`. Only `allow_once` approves; reject, cancellation, unknown outcomes, and request failure deny. It advertises only close-session capability—no terminal, filesystem, MCP, editor state, location, diff, or raw input/output capability.
53
+ ACP maps assistant text to `agent_message_chunk`, safe tool lifecycle to `tool_call`/`tool_call_update` (locations/diffs only from projection allow-lists), provider usage to `usage_update`, and durable suspension to `session/request_permission` with the four shared outcomes — plus, per the client's advertised capabilities, editor-buffer fs, terminal, prompt media, modes/config options, lifecycle events, and elicitation. Advertisement is a pure function of the wired seams: no seam, no capability, no method. Only `allow_once` approves; reject, cancellation, unknown outcomes, and request failure deny. See [ACP coding-host interop](acp.md).
54
54
 
55
55
  Selected MCP tools use normal `TOOL_CALL_*` core dispatch. Linked Apps add safe `mcp-apps` activity; app-only tools stay model-hidden. The separate reauthorizing Apps proxy allow-lists initialize/ping/logging/tool/resource calls for one bridge; its sandbox helper returns CSP/iframe config and never executes HTML.
56
56
 
@@ -116,7 +116,7 @@ const handle = createAgUiHandler({
116
116
  const response = await handle(request); // adapt this Web Response in host framework
117
117
  ```
118
118
 
119
- See runnable network-free [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts). For ACP, construct `createPrismAcpAgent({ authorize, sessionFactory, lifecycle })` and connect the returned stable SDK agent through the host's ACP transport.
119
+ See runnable network-free [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts). For ACP, construct `createPrismAcpAgent({ authorize, sessionFactory, lifecycle, ...seams })` and connect the returned stable SDK agent through the host's ACP transport — see [`examples/acp-coding-host.ts`](../examples/acp-coding-host.ts) and [ACP coding-host interop](acp.md).
120
120
 
121
121
  ## Extension and configuration notes
122
122
 
@@ -202,7 +202,7 @@ const renderer = createA2UiRenderer({
202
202
  const surface = await renderer.surface("chat"); // detached DOM node, kept in sync
203
203
  ```
204
204
 
205
- The core is a DOM-free state machine (`reduceA2UiOps`): operations become a surface/component model (adjacency list with `id`/`component`/flat props, A2UI v0.9 JSON-Pointer data model, `deleteSurface`); a thin binding layer renders the model through catalog component renderers (framework-free `(props, ctx, dom) => node` functions). Snapshots replace a surface's model (streaming mode sends cumulative ops); RFC 6902 deltas append. The same frozen caps as the server painter are enforced client-side: 64/512 ops per message, 64 KiB/1 MiB per op, 16/64 surfaces per run, depth 32/64. Invalid or oversized ops drop closed with one bounded `prism.a2ui.error` event (host logging via `onError`); unknown catalog components render an explicit placeholder. The renderer never executes remote HTML: only `createElement`/`createTextNode`/`appendChild`, no HTML-string assignment, no dynamic code evaluation. Data bindings `{"path": "/pointer"}` resolve against the per-surface data model; `deleteSurface` detaches content. The main `@arnilo/prism-ag-ui` entry stays runtime-agnostic — DOM code lives only behind the `renderer` subpath (type-only re-exports). Hosts embedding it should follow the MCP Apps CSP/sandbox guidance (`docs/ag-ui-adoption.md`) for iframe/worker placement.
205
+ The core is a DOM-free state machine (`reduceA2UiOps`): operations become a surface/component model (adjacency list with `id`/`component`/flat props, A2UI v0.9 JSON-Pointer data model, `deleteSurface`); a thin binding layer renders the model through catalog component renderers (framework-free `(props, ctx, dom) => node` functions). The core is also exported as values from the subpath entry (`A2UiSurfaceState`, `reduceA2UiOps`, `readA2UiBatch`, `resolvePointer`, `A2UI_VERSION`, 0.0.27, Synapta FR) so framework hosts can drive the validated surface state machine and own the view layer; behavior and frozen caps are unchanged. Snapshots replace a surface's model (streaming mode sends cumulative ops); RFC 6902 deltas append. The same frozen caps as the server painter are enforced client-side: 64/512 ops per message, 64 KiB/1 MiB per op, 16/64 surfaces per run, depth 32/64. Invalid or oversized ops drop closed with one bounded `prism.a2ui.error` event (host logging via `onError`); unknown catalog components render an explicit placeholder. The renderer never executes remote HTML: only `createElement`/`createTextNode`/`appendChild`, no HTML-string assignment, no dynamic code evaluation. Data bindings `{"path": "/pointer"}` resolve against the per-surface data model; `deleteSurface` detaches content. The main `@arnilo/prism-ag-ui` entry stays runtime-agnostic — DOM code lives only behind the `renderer` subpath (the root entry re-exports renderer types only, no values). Hosts embedding it should follow the MCP Apps CSP/sandbox guidance (`docs/ag-ui-adoption.md`) for iframe/worker placement.
206
206
 
207
207
  ## Security and performance notes
208
208
 
@@ -218,6 +218,7 @@ Defaults / hard caps: request 64 KiB / 1 MiB; input 128 / 1024 messages, 32 / 25
218
218
  - [Web-standard server handler](server.md): generic Prism HTTP API, separate from AG-UI.
219
219
  - [A2A interoperability](a2a.md): remote agent-to-agent tasks, not frontend protocol mapping.
220
220
  - [AG-UI adoption evaluation](ag-ui-adoption.md): official 0.0.57 event/input matrix and shipped explicit MCP/MCP Apps/A2A handshakes.
221
+ - [ACP coding-host interop](acp.md): the full ACP reference — seam-based capability advertisement, session modes/config, MCP select, fs/terminal adapters, lifecycle mapping, elicitation, and caps.
221
222
  - [MCP bridge/server](mcp-tools.md): `mcpApps` negotiation, bounded resources, and remote tool trust.
222
223
  - [A2A interoperability](a2a.md): verified rich task client and remote task lifecycle.
223
224
  - [Host security guide](host-security.md): authorization, ownership, redaction, and credential boundaries.
@@ -242,4 +242,4 @@ for await (const event of session.stream("draft", { loop: { strategy: "generate-
242
242
  - [Observability](observability.md): `ProviderTurnMetadata`; optional adapter builds one parented GenAI span tree from metadata-only lifecycle events and ignores message/progress deltas.
243
243
  - [Tools](tools.md): `tool_execution_*` variants.
244
244
  - [Compaction and retry policies](compaction-and-retry.md): `compaction_*` and `retry_scheduled` variants.
245
- - [Frontend interoperability (AG-UI and ACP)](ag-ui.md): optional redacted mapping of this stream; durable replay is ledger-backed and at-least-once, never a live-subscriber substitute.
245
+ - [Frontend interoperability (AG-UI and ACP)](ag-ui.md): optional redacted mapping of this stream; durable replay is ledger-backed and at-least-once, never a live-subscriber substitute. [ACP coding-host interop](acp.md) additionally maps `CodingLifecycleEvent`s from `@arnilo/prism-coding-agent` (`file_changed`, `worktree_changed`, `permission_denied`, `configuration_changed`; process events reuse `CodingProcessEvent`) into ACP session updates — locations/diff blocks only through projection allow-lists, terminal chunks under `process.outputChunkBytes`.
@@ -560,4 +560,5 @@ Every configurable value is a positive safe integer (context may be zero); Prism
560
560
  - [Public contracts](public-contracts.md): `ToolDefinition`, `ToolResult`, `ToolExecutionContext`, `ContentBlock`, and `JsonObject` shapes.
561
561
  - [Host security guide](host-security.md): fail-closed checklist for permission policies, tool validation, and trust boundaries that must gate these tools.
562
562
  - [Tool conformance](tool-conformance.md): assertions for the tool-dispatch blocked-reason matrix these tools participate in.
563
+ - [ACP coding-host interop](acp.md): host editors drive these tools through stable ACP v1 — client fs/terminal adapters, `CodingLifecycleEvent` emission (`file_changed` etc. via the `onEvent` options), and permission/elicitation through the shared four-outcome decision model.
563
564
  - [LLM compaction package](compaction-llm.md): optional `createCodingCompactionStrategy()` retains bounded paths, patch intent, checks, plan/todo state, blockers, and next verification—not complete diffs or raw command output.
@@ -193,3 +193,4 @@ The egress proxy is a policy enforcer, not a firewall: it cannot stop a containe
193
193
  - [Forge integration](forge-integration.md): GitHub adapter whose mutations can be routed through the egress proxy
194
194
  - [Tool execution primitives](tool-execution-primitives.md)
195
195
  - [Security/auth/trust](settings-auth-trust-security.md)
196
+ - [ACP coding-host interop](acp.md): when an ACP client supplies fs/terminal methods and MCP servers, the same containment story applies at the protocol boundary — client paths/dirs pass host seams, MCP servers need host `select` approval (never auto-connect), updates are redacted and capped, and mode switches only narrow or host-authorized widen.
@@ -210,7 +210,7 @@ Every durable `AgentEventSource` page/subscribe and tool-effect claim rechecks e
210
210
  ## Related APIs
211
211
 
212
212
  - [Web-standard server handler](server.md): remote agent/workflow route, ownership, limits, abort, and deployment boundary.
213
- - [Frontend interoperability (AG-UI and ACP)](ag-ui.md): authorize every protocol selector/operation; full AG-UI input/output only through bounded host allow-lists; exact interrupt/version resume; redacted, ownership-scoped replay.
213
+ - [Frontend interoperability (AG-UI and ACP)](ag-ui.md): authorize every protocol selector/operation; full AG-UI input/output only through bounded host allow-lists; exact interrupt/version resume; redacted, ownership-scoped replay. [ACP coding-host interop](acp.md): untrusted client fs/terminal/paths/MCP configs are boundary-validated (caps + host seams); client MCP servers never auto-connect; mode switches only narrow or host-authorized widen; updates are redacted and never carry raw tool I/O.
214
214
  - [Supervisor delegation](supervisors.md): local child permission/memory/budget boundary.
215
215
  - [A2A interoperability](a2a.md): remote card/auth/origin/signature boundary.
216
216
  - [Settings, auth, trust, and security controls](settings-auth-trust-security.md): low-level helpers and boundary hardening table.
package/docs/index.md CHANGED
@@ -35,7 +35,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
35
35
  - [SQLite persistence](sqlite-persistence.md): optional `better-sqlite3` adapter with session/run storage, checkpoints/leases, feedback, FTS `searchSessions` (migration-v4), and transactionally verified/backfilled migration metadata.
36
36
  - [PostgreSQL persistence](postgres-persistence.md): optional pooled `pg` adapter with session/run/checkpoint/lease/feedback storage, FTS `searchSessions` (migration-v4), advisory-locked checksummed/full-shape migrations, and opt-in live conformance.
37
37
  - [Enterprise PostgreSQL state](enterprise-postgres-state.md): optional `@arnilo/prism-enterprise-postgres` composition for durable policy/evaluation/work-idempotency/model-router/`toolEffects` state, exact ownership, checksummed migrations, and explicit cleanup.
38
- - [Migration guide](migration.md): **0.0.26** coding intelligence, managed processes, forge, and safe egress; **0.0.25** durable custom loops and shared human-in-the-loop decisions; **0.0.24** distributed events and recoverable tool effects; **0.0.23** enterprise PostgreSQL state adapters (async router and work reconciliation); **0.0.22** third-party behavior integrations (Caveman, Ponytail); **0.0.21** coding-tool capability gaps (`outputMode`, glob, read-before-write, delete/move, aggregator 9/4); **0.0.20** progressive skill disclosure, empty registry default, `load_skill`, priority budget demotion, optional tool-result fold; **0.0.19** observational memory lifecycle; **0.0.15** OpenAI hosted tools/continuation/Realtime, exact AI SDK v4 matrix, RAG lifecycle/reranking/trust/status, and memory export/rebuild; **0.0.14** conversations, memory consent/lifecycle, artifact co-work review, AG-UI co-work events, scoped M365/GWS OAuth connectors, browser checkpoints, device contracts, and Alibaba/Ollama providers; plus prior release migrations.
38
+ - [Migration guide](migration.md): **0.0.27** ACP coding-host interop (capability advertise-when, session modes/config, MCP select, lifecycle events, elicitation); **0.0.26** coding intelligence, managed processes, forge, and safe egress; **0.0.25** durable custom loops and shared human-in-the-loop decisions; **0.0.24** distributed events and recoverable tool effects; **0.0.23** enterprise PostgreSQL state adapters (async router and work reconciliation); **0.0.22** third-party behavior integrations (Caveman, Ponytail); **0.0.21** coding-tool capability gaps (`outputMode`, glob, read-before-write, delete/move, aggregator 9/4); **0.0.20** progressive skill disclosure, empty registry default, `load_skill`, priority budget demotion, optional tool-result fold; **0.0.19** observational memory lifecycle; **0.0.15** OpenAI hosted tools/continuation/Realtime, exact AI SDK v4 matrix, RAG lifecycle/reranking/trust/status, and memory export/rebuild; **0.0.14** conversations, memory consent/lifecycle, artifact co-work review, AG-UI co-work events, scoped M365/GWS OAuth connectors, browser checkpoints, device contracts, and Alibaba/Ollama providers; plus prior release migrations.
39
39
  - [Node JSONL session store](node-jsonl-session-store.md): development-only JSONL file adapter for single-process Node hosts; no cross-process safety; `searchSessions` throws `SessionSearchUnsupportedError`.
40
40
  - [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.
41
41
 
@@ -98,6 +98,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
98
98
  - [Supervisor delegation](supervisors.md): optional explicit child allow-list, derived memory scopes, narrowing-only permissions, lifecycle hooks, nested delegation, cancellation, finite budgets, host-projected delegation telemetry, and separate A2A durable adapter boundary.
99
99
  - [A2A interoperability](a2a.md): A2A 1.0 JSON-RPC/HTTPS cards plus host-owned durable task get/list/cancel/subscribe, shared `AgentEventSource` task adapter, bounded rich parts/replay, principal-scoped push configs, exact-origin verified client, rich stream seam for explicit AG-UI fronting, and server-side `createAgUiA2AServer` exposure of a local AG-UI agent (0.0.26).
100
100
  - [Frontend interoperability (AG-UI and ACP)](ag-ui.md): optional `@arnilo/prism-ag-ui` full AG-UI 0.0.57 input/event/capability mapper, authorized Web handler/distributed source follow, opt-in A2UI painting middleware, explicit hardened MCP/MCP Apps/remote A2A adapters, a framework-free reference renderer subpath (`@arnilo/prism-ag-ui/renderer`, 0.0.26), and stable ACP sibling over shared redacted event and durable-approval seams; 0.0.14 adds reconnectable co-work events.
101
+ - [ACP coding-host interop](acp.md): stable ACP v1 `createPrismAcpAgent()`/`createAcpEventMapper()` over `@agentclientprotocol/sdk@1.3.0` — capability advertisement is a pure function of host seams (sessions load/list/delete/resume/dirs, close always, prompt media/embedded, MCP http/sse), client fs/terminal adapters, modes and config options as host overlays, `CodingLifecycleEvent` mapping, four-outcome approvals with elicitation, and frozen caps (0.0.27).
101
102
  - [AG-UI adoption evaluation](ag-ui-adoption.md): official 0.0.57 input/event/capability matrix and shipped hardened MCP/MCP Apps/A2A handshake boundaries.
102
103
 
103
104
  ## CLI/RPC
@@ -120,7 +121,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
120
121
  - [Compaction conformance](compaction-conformance.md): assert any `CompactionStrategy` returns a non-empty redacted summary and observes abort from `@arnilo/prism/testing/compaction-conformance`.
121
122
  - [Tool conformance](tool-conformance.md): assert the tool-dispatch blocked-reason matrix (unknown/denied/invalid/permission/validator) and success path from `@arnilo/prism/testing/tool-conformance`.
122
123
  - [Extension conformance](extension-conformance.md): assert an `Extension` setup runs, contributions stay inert, and setup errors are redacted or rethrown from `@arnilo/prism/testing/extension-conformance`.
123
- - `examples/`: compile-checked typed examples and runnable mock demos (SDK basics, provider registration, auth, tools, [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts), [`examples/ag-ui-a2ui.ts`](../examples/ag-ui-a2ui.ts), [`examples/ag-ui-mcp-apps.ts`](../examples/ag-ui-mcp-apps.ts), [`examples/enterprise-identity.ts`](../examples/enterprise-identity.ts), [`examples/enterprise-policy-audit.ts`](../examples/enterprise-policy-audit.ts), [`examples/enterprise-work-connectors.ts`](../examples/enterprise-work-connectors.ts), [`examples/enterprise-postgres-state.ts`](../examples/enterprise-postgres-state.ts), [`examples/conversation-durable-replay.ts`](../examples/conversation-durable-replay.ts), [`examples/artifact-review-delivery.ts`](../examples/artifact-review-delivery.ts), [`examples/server-deployment-seams.ts`](../examples/server-deployment-seams.ts), cache-aware prompt assembly, NeuralWatt agent run ([`examples/neuralwatt-agent-run.ts`](../examples/neuralwatt-agent-run.ts)), [`examples/coding-compaction.ts`](../examples/coding-compaction.ts), [`examples/caveman-ponytail.ts`](../examples/caveman-ponytail.ts), stores/branching, structured-output/artifact-loop, CLI, RPC, workflow orchestration).
124
+ - `examples/`: compile-checked typed examples and runnable mock demos (SDK basics, provider registration, auth, tools, [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts), [`examples/ag-ui-a2ui.ts`](../examples/ag-ui-a2ui.ts), [`examples/ag-ui-mcp-apps.ts`](../examples/ag-ui-mcp-apps.ts), [`examples/enterprise-identity.ts`](../examples/enterprise-identity.ts), [`examples/enterprise-policy-audit.ts`](../examples/enterprise-policy-audit.ts), [`examples/enterprise-work-connectors.ts`](../examples/enterprise-work-connectors.ts), [`examples/enterprise-postgres-state.ts`](../examples/enterprise-postgres-state.ts), [`examples/conversation-durable-replay.ts`](../examples/conversation-durable-replay.ts), [`examples/artifact-review-delivery.ts`](../examples/artifact-review-delivery.ts), [`examples/server-deployment-seams.ts`](../examples/server-deployment-seams.ts), cache-aware prompt assembly, NeuralWatt agent run ([`examples/neuralwatt-agent-run.ts`](../examples/neuralwatt-agent-run.ts)), [`examples/coding-compaction.ts`](../examples/coding-compaction.ts), [`examples/acp-coding-host.ts`](../examples/acp-coding-host.ts), [`examples/caveman-ponytail.ts`](../examples/caveman-ponytail.ts), stores/branching, structured-output/artifact-loop, CLI, RPC, workflow orchestration).
124
125
 
125
126
  ## Third-party integrations
126
127
  - [Caveman behavior integration](caveman.md): optional `@arnilo/prism-caveman` — upstream Caveman skills/commands, `caveman-mode` injector, session `caveman-level` persistence, progressive catalog + `load_skill`; requires host `upstreamPath` and session attach callbacks; inert until `kernel.load`.
package/docs/mcp-tools.md CHANGED
@@ -241,6 +241,7 @@ Official Exa/Firecrawl MCP servers may be tested only as explicit hardened proto
241
241
  - [Host security guide](host-security.md): permission, trust, validation checklist
242
242
  - [Web-standard server handler](server.md): agent/workflow HTTP routes and shared remote-boundary rules
243
243
  - Package README: [`@arnilo/prism-mcp`](../packages/mcp/README.md)
244
+ - [ACP coding-host interop](acp.md): ACP clients may attach MCP servers to sessions — bounded configs (8/32 servers, 16 KiB/256 KiB config, 4 KiB/64 KiB header values), http/sse only when advertised, stdio accepted behind the gate, UNSTABLE `acp` always rejected, and every server approved by host `mcp.select` before the bridge connects.
244
245
 
245
246
  ## Testing
246
247
 
package/docs/migration.md CHANGED
@@ -1,8 +1,23 @@
1
1
  # Migration guide
2
2
 
3
+ ## 0.0.26 → 0.0.27 ACP coding-host interop (intentional advertise/surface changes)
4
+
5
+ Release **0.0.27** (Phase 10) turns `@arnilo/prism-ag-ui/acp` from a text/tool/usage/approval glue layer into a full coding-host adapter over the Phase 8/9 primitives: host-seam capability advertisement, session persistence, modes and config options, client fs/terminal, MCP bridging behind a host gate, coding lifecycle events, and elicitation. ACP stays stable **v1** on `@agentclientprotocol/sdk@1.3.0`; UNSTABLE fields are never advertised or consumed. Publishable graph stays **48** manifests.
6
+
7
+ 1. **`initialize` advertisement is now a pure function of host seams — hosts that parsed the old response must re-check.** Previously the agent advertised only `sessionCapabilities.close` (plus `loadSession` when a lifecycle seam existed). Now: `loadSession` iff `sessions.load` is wired, `sessionCapabilities.list`/`delete`/`resume`/`additionalDirectories` iff the matching seam exists (`close` stays always-on), `promptCapabilities.image`/`audio`/`embeddedContext` iff the matching `capabilities.prompt` policy seam exists, and `mcpCapabilities.http`/`sse` iff `mcp.select` is wired with that transport. Removing a seam withdraws the method — there is no separate capability flag. Clients must treat every session method they call as capability-gated.
8
+ 2. **New session surface.** `session/load`, `session/resume`, `session/list`, `session/delete` register only with their seams; `session/new` input carries policy-checked `cwd`/`additionalDirectories`/`mcpServers`; `session/resume`/`session/load` responses carry `modes`/`configOptions` state when wired. Resuming a still-registered session rejects with `ERR_PRISM_ACP_INPUT` ("ACP session already exists") — reconnect after a replica change must resume a stored session, not a live one. `session/set_mode` and `session/set_config_option` are new when `modes`/`configOptions` are wired; `set_config_option` additionally requires the client to advertise `session.configOptions.boolean`.
9
+ 3. **Client fs/terminal are opt-in per client.** When the client advertises `fs.readTextFile`/`writeTextFile` (or `terminal`), `sessionFactory` input gains `coding.filesystem`/`coding.processes` adapters over the client's methods, keyed by a pre-generated session id. Hosts that do not use them keep prior behavior; clients that do not advertise them never see the methods called.
10
+ 4. **MCP servers require a host gate.** `mcpServers` on `session/new`/`load` are accepted only when `mcp.select` is wired and approves; the UNSTABLE `acp` transport is always rejected, stdio has no capability advertisement (accepted when the gate exists), and http/sse must match an advertised transport. Unapproved or unconfigured servers fail closed.
11
+ 5. **Lifecycle events map to updates.** With `coding.lifecycle` wired, `file_changed` → `tool_call_update` with `locations` (diff only from the `fileDiff` projection allow-list), `worktree_changed`/process events → projection-gated `agent_message_chunk`, `permission_denied` → `failed` status, `configuration_changed` → `config_option_update`. Nothing is emitted without a projection or a streaming session.
12
+ 6. **Elicitation, when the client advertises it.** All-elicitation suspensions surface as `elicitation/create` (form mode, bounded schema); otherwise they stay on the shared four-option permission path. Permission semantics are unchanged: `allow_once`/`allow_always`→`allow_for_run`/`reject_once`/`reject_always`→`reject_for_run`, cancel and unknown options deny.
13
+ 7. **Frozen caps.** Sessions 32/128, additional directories 8/32, MCP servers 8/32 (config 16 KiB/256 KiB), modes 16/64, config options 16/64, list page 20/100, diff 64 KiB/1 MiB, locations 32/128 per update, media parts 16/64 and 64 KiB/1 MiB, terminal chunks at Phase 9 `process.outputChunkBytes`. Exceeded caps fail closed with `ERR_PRISM_ACP_LIMIT`.
14
+ 8. **Errors.** `AcpError` codes `ERR_PRISM_ACP_INPUT` / `LIMIT` / `POLICY` / `CAPABILITY` / `MCP`; over the wire the SDK wraps them as JSON-RPC `-32603` with the message in `data.details` (the code string itself is transport-local). Unadvertised methods surface as `-32601 method not found`.
15
+
16
+ No core, coding-agent, or AG-UI behavior changed; hosts that never wire the new seams see the old minimal advertisement and all prior mappings. Conformance: `node --test scripts/phase10-conformance.test.mjs`; example: `node examples/acp-coding-host.ts`; docs: [ACP coding-host interop](acp.md).
17
+
3
18
  ## 0.0.25 → 0.0.26 coding intelligence, managed processes, forge, and safe egress (additive)
4
19
 
5
- Release **0.0.26** (Phase 9) adds four opt-in capability families to `@arnilo/prism-coding-agent` and `@arnilo/prism-coding-security`: Git-aware repository enumeration, host-selected LSP language intelligence, managed process sessions, a reference GitHub forge adapter with idempotent handoff, and an allow-list egress proxy with DNS-rebinding defense. All are **additive** — no existing export, event, or persisted shape changes; hosts that do not activate the new factories keep prior behavior. Publishable graph stays **47** manifests.
20
+ Release **0.0.26** (Phase 9) adds four opt-in capability families to `@arnilo/prism-coding-agent` and `@arnilo/prism-coding-security`: Git-aware repository enumeration, host-selected LSP language intelligence, managed process sessions, a reference GitHub forge adapter with idempotent handoff, and an allow-list egress proxy with DNS-rebinding defense. All are **additive** — no existing export, event, or persisted shape changes; hosts that do not activate the new factories keep prior behavior. Publishable graph stays **48** manifests.
6
21
 
7
22
  1. **Git-aware enumeration is opt-in.** `createLocalRepositoryOperations` keeps the native walker. `createGitAwareRepositoryOperations(cwd, options?)` runs a fixed `git ls-files --cached --others --exclude-standard -z` and falls back to native enumeration when the directory is not a Git work tree or git is unavailable. `includeIgnored` is host-only (never surfaced to tools). No change to `listLocal`/`searchLocal`/`globLocal` callers.
8
23
  2. **Language intelligence is host-activated.** `createLanguageIntelligence(options)` spawns the host-selected LSP server lazily (no spawn at construction) and speaks LSP 3.17 over bounded JSON-RPC. Unsupported languages fail closed with `ERR_PRISM_LSP_UNSUPPORTED`; out-of-workspace URIs fail with `ERR_PRISM_LSP_WORKSPACE`. Rename applies through `ExecutionPolicy` (kind `edit`, risk `high`) and atomic writes; hosts that never call it are unaffected.
@@ -26,7 +41,7 @@ Examples: `node examples/phase9-coding-intelligence.ts` (composed, network-free)
26
41
 
27
42
  ## 0.0.24 → 0.0.25 durable custom loops and human-in-the-loop (intentional pre-1.0 contract changes)
28
43
 
29
- Release **0.0.25** makes custom loops durable and replaces sequential binary approvals with one shared pending-decision model. Protocol adapters (AG-UI, ACP, MCP, coding `ask_user_decision`, server resume, supervisor nesting) map onto that model. Opt-in A2UI painting and standard AG-UI projectors ship in `@arnilo/prism-ag-ui`. Publishable graph stays **47** manifests.
44
+ Release **0.0.25** makes custom loops durable and replaces sequential binary approvals with one shared pending-decision model. Protocol adapters (AG-UI, ACP, MCP, coding `ask_user_decision`, server resume, supervisor nesting) map onto that model. Opt-in A2UI painting and standard AG-UI projectors ship in `@arnilo/prism-ag-ui`. Publishable graph stays **48** manifests.
30
45
 
31
46
  1. **Custom loops on durable runs need hooks.** Built-in `single-shot` / `generate-validate-revise` stay durable. A custom `AgentLoopStrategy` on `runState` must expose `snapshot` + `restore` (and usually `revision`) or the run fails closed with `AgentLoopStateError` / `ERR_PRISM_LOOP_NOT_DURABLE` before any provider call. Snapshots must be JSON-compatible and fit the run-state byte/depth caps (`ERR_PRISM_LOOP_SNAPSHOT`).
32
47
  2. **Fingerprint loop entry shape changed.** Durable fingerprints now store `{ name, revision }` instead of a bare loop name string. Persisted **0.0.24** runs fail closed on **0.0.25** resume (fingerprint mismatch / `ERR_PRISM_LOOP_REVISION`). Finish or abandon in-flight 0.0.24 durable runs before upgrading, or rebuild from a fresh suspension under 0.0.25.
@@ -4,7 +4,7 @@
4
4
 
5
5
  Prism is published as one core package, forty-one first-party capability packages, and six pure-manifest family/profile packages (**48** publishable manifests total). This page describes how they are packed, what each tarball contains, how to install them, the required `@arnilo/prism` peer dependency, the release workflow, and the offline test budget. The measurable 1.0 readiness gates (command-per-gate) live in [`0.1.0-readiness.md`](./0.1.0-readiness.md).
6
6
 
7
- Core `@arnilo/prism` ships runtime, CLI, templates, and docs. Every code package has a required `@arnilo/prism@0.0.26` peer; profiles are pure manifests. Installation activates no provider, listener, database, browser, credential, or tool capability.
7
+ Core `@arnilo/prism` ships runtime, CLI, templates, and docs. Every code package has a required `@arnilo/prism@0.0.27` peer; profiles are pure manifests. Installation activates no provider, listener, database, browser, credential, or tool capability.
8
8
 
9
9
  Current **48** publishable manifests:
10
10
 
@@ -45,9 +45,9 @@ Consumers install the core package for the runtime and add first-party packages
45
45
  | Run the default (network-free) test suite | `npm test` |
46
46
  | Dry-run pack core + every package | `npm run pack:dry-run` |
47
47
  | Local mirror of the release verify gate | `npm run release:dry-run` |
48
- | Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.26` |
49
- | Preview deterministic publish order | `npm run release:publish -- --version 0.0.26 --dry-run --allow-dirty --allow-untagged` |
50
- | Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.26 --resume --report release-artifacts/publish-report.json` |
48
+ | Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.27` |
49
+ | Preview deterministic publish order | `npm run release:publish -- --version 0.0.27 --dry-run --allow-dirty --allow-untagged` |
50
+ | Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.27 --resume --report release-artifacts/publish-report.json` |
51
51
  | Protected PostgreSQL enterprise suite | `PRISM_TEST_POSTGRES_URL="$DATABASE_URL" npm run test:postgres` |
52
52
  | Full SDK readiness gate (typecheck + offline tests + pack) | `npm run sdk:ready` |
53
53
 
@@ -87,7 +87,7 @@ A packed tarball contains only public compiled output and release files:
87
87
  - Code packages ship `README.md`, `LICENSE`, and `CHANGELOG.md`; family/profile packages ship `README.md` and `CHANGELOG.md`.
88
88
  - The core tarball additionally ships the full `docs/` directory (the docs hub) and `templates/init/` used by `prism init`.
89
89
  - `dist/cli.js` and the `bin` link in core.
90
- - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.26.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.26.tgz` / `arnilo-prism-compaction-<name>-0.0.26.tgz` / `arnilo-prism-coding-agent-0.0.26.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.26.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).
90
+ - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.27.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.27.tgz` / `arnilo-prism-compaction-<name>-0.0.27.tgz` / `arnilo-prism-coding-agent-0.0.27.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.27.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).
91
91
 
92
92
  Excluded from every tarball by `files` negation:
93
93
 
@@ -106,9 +106,9 @@ Excluded from every tarball by `files` negation:
106
106
  "name": "host-app",
107
107
  "type": "module",
108
108
  "dependencies": {
109
- "@arnilo/prism": "0.0.26",
110
- "@arnilo/prism-enterprise-postgres": "0.0.26",
111
- "@arnilo/prism-provider-openai": "0.0.26"
109
+ "@arnilo/prism": "0.0.27",
110
+ "@arnilo/prism-enterprise-postgres": "0.0.27",
111
+ "@arnilo/prism-provider-openai": "0.0.27"
112
112
  }
113
113
  }
114
114
  ```
@@ -151,11 +151,11 @@ For SDK readiness, run the same one-command gate directly. It composes existing
151
151
  npm run sdk:ready
152
152
  ```
153
153
 
154
- Release publication derives all **48** manifests from the workspace once, validates exact `0.0.26` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.26` 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` performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag, but does not publish.
154
+ Release publication derives all **48** manifests from the workspace once, validates exact `0.0.27` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.27` 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` performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag, but does not publish.
155
155
 
156
156
  ```bash
157
- npm run release:check -- --version 0.0.26
158
- npm run release:publish -- --version 0.0.26 --dry-run --allow-dirty --allow-untagged
157
+ npm run release:check -- --version 0.0.27
158
+ npm run release:publish -- --version 0.0.27 --dry-run --allow-dirty --allow-untagged
159
159
  ```
160
160
 
161
161
  `--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.
@@ -166,29 +166,29 @@ Optional live smoke tests stay separate from SDK readiness because they require
166
166
  PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
167
167
  ```
168
168
 
169
- ### GitHub Actions pipeline (0.0.26+)
169
+ ### GitHub Actions pipeline (0.0.27+)
170
170
 
171
- `.github/workflows/release.yml` is the single pipeline: **push to `main`** runs CI (`verify` = `npm run sdk:ready`, `node20-compat`, `postgres-integration`, `supply-chain`), **push of a `v*` tag** additionally runs `codeql-release` and the `publish` job (deterministic `release:publish` in dependency order with provenance attestation). `security.yml` adds CodeQL/dependency-review/SBOM on push and PR; `live-canaries.yml` and `sandbox-browser.yml` are scheduled. All actions are SHA-pinned (2026-08-06 fix: CodeQL pins were invalid 404 refs and `workflow_dispatch` was missing — re-verified every pin against its upstream repo). Prerequisites outside the repo: Actions enabled in repository settings, and the `NPM_TOKEN` secret (with `id-token: write` for provenance). To re-cut a tag after a fix commit, delete and recreate it (`git push origin :v0.0.26 && git push origin v0.0.26`) so the tag creation event fires.
171
+ `.github/workflows/release.yml` is the single pipeline: **push to `main`** runs CI (`verify` = `npm run sdk:ready`, `node20-compat`, `postgres-integration`, `supply-chain`), **push of a `v*` tag** additionally runs `codeql-release` and the `publish` job (deterministic `release:publish` in dependency order with provenance attestation). `security.yml` adds CodeQL/dependency-review/SBOM on push and PR; `live-canaries.yml` and `sandbox-browser.yml` are scheduled. All actions are SHA-pinned (2026-08-06 fix: CodeQL pins were invalid 404 refs and `workflow_dispatch` was missing — re-verified every pin against its upstream repo). Prerequisites outside the repo: Actions enabled in repository settings, and the `NPM_TOKEN` secret (with `id-token: write` for provenance). To re-cut a tag after a fix commit, delete and recreate it (`git push origin :v0.0.27 && git push origin v0.0.27`) so the tag creation event fires.
172
172
 
173
- ### 0.0.26 publish handoff
173
+ ### 0.0.27 publish handoff
174
174
 
175
- **Decision: GO after protected operator prerequisites below.** Release **0.0.26** (Phase 9, plan 009) ships Git-aware repository enumeration, host-selected LSP language intelligence, managed process sessions (sandbox-backed, ownership-scoped), a reference GitHub forge adapter with idempotent handoff, and an allow-list egress proxy with DNS-rebinding defense and Docker sandbox attestation. Publishable graph grows to **48** manifests (new `@arnilo/prism-session-store-nats`). See [migration](migration.md) `0.0.25 → 0.0.26`, [language intelligence](language-intelligence.md), [process sessions](process-sessions.md), [forge integration](forge-integration.md), and [coding security](coding-security.md).
175
+ **Decision: GO after protected operator prerequisites below.** Release **0.0.27** (Phase 10, plan 010) ships complete ACP coding-host interop in `@arnilo/prism-ag-ui/acp`: seam-based capability advertisement, session persistence, modes/config overlays, client fs/terminal adapters, MCP select gate, `CodingLifecycleEvent` → ACP update mapping, four-outcome approvals with elicitation, and frozen caps. Publishable graph stays **48** manifests. See [migration](migration.md) `0.0.26 → 0.0.27` and [ACP coding-host interop](acp.md).
176
176
 
177
177
  ```bash
178
178
  git diff --check
179
179
  npm ci
180
180
  npm run sdk:ready
181
- node --test scripts/phase9-conformance.test.mjs
182
- node scripts/benchmark-0.0.26.mjs > scripts/benchmark-0.0.26.json
181
+ node --test scripts/phase10-conformance.test.mjs
182
+ node scripts/benchmark-0.0.27.mjs > scripts/benchmark-0.0.27.json
183
183
  node --test scripts/budget-gate.test.mjs scripts/tooling-gate.test.mjs
184
184
  node scripts/scan-secrets.mjs && node scripts/verify-sbom.mjs
185
185
  npm audit --audit-level=moderate
186
- npm run release:gate -- --version 0.0.26 --allow-break --allow-dirty --allow-untagged
187
- npm run release:check -- --version 0.0.26 --allow-dirty --allow-untagged --report /tmp/prism-0.0.26-preflight.json
188
- npm run release:publish -- --version 0.0.26 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.26-dry-run.json
189
- git tag -s v0.0.26 -m "Prism 0.0.26"
190
- git verify-tag v0.0.26
191
- git push origin v0.0.26
186
+ npm run release:gate -- --version 0.0.27 --allow-break --allow-dirty --allow-untagged
187
+ npm run release:check -- --version 0.0.27 --allow-dirty --allow-untagged --report /tmp/prism-0.0.27-preflight.json
188
+ npm run release:publish -- --version 0.0.27 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.27-dry-run.json
189
+ git tag -s v0.0.27 -m "Prism 0.0.27"
190
+ git verify-tag v0.0.27
191
+ git push origin v0.0.27
192
192
  ```
193
193
 
194
194
  ### 0.0.24 publish handoff
@@ -288,7 +288,7 @@ Older 0.0.10–0.0.15 handoffs are summarized in [migration](migration.md); hist
288
288
 
289
289
  ## Extension and configuration notes
290
290
 
291
- - **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.26` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.26` for the current 0.x release 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.
291
+ - **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.27` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.27` for the current 0.x release 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.
292
292
  - **Public access.** All 48 manifests (42 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.
293
293
  - **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).
294
294
  - **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`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.0.26",
3
+ "version": "0.0.27",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -141,8 +141,8 @@
141
141
  "clean": "rm -rf dist packages/*/dist",
142
142
  "build": "npm run clean && npm run build:core && npm run build --workspaces --if-present",
143
143
  "typecheck": "npm run build && npm run typecheck --workspaces --if-present && tsc -p examples --noEmit",
144
- "test": "npm run build && node --test dist/__tests__/*.test.js && node --test scripts/release-gate.test.mjs scripts/tooling-gate.test.mjs scripts/budget-gate.test.mjs scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs && npm run test --workspaces --if-present",
145
- "test:coverage": "node --test --experimental-test-coverage --test-coverage-lines=60 --test-coverage-functions=70 --test-coverage-branches=75 --test-coverage-exclude='**/__tests__/**' --test-coverage-exclude='**/node_modules/**' --test-coverage-exclude='**/scripts/**' dist/__tests__/*.test.js",
144
+ "test": "npm run build && node --test dist/__tests__/*.test.js && node --test scripts/release-gate.test.mjs scripts/tooling-gate.test.mjs scripts/budget-gate.test.mjs scripts/phase8-conformance.test.mjs scripts/phase9-conformance.test.mjs scripts/phase10-conformance.test.mjs && npm run test --workspaces --if-present",
145
+ "test:coverage": "node --test --experimental-test-coverage --test-coverage-lines=60 --test-coverage-functions=70 --test-coverage-branches=75 --test-coverage-exclude='**/__tests__/**' --test-coverage-exclude='**/node_modules/**' --test-coverage-exclude='**/scripts/**' --test-coverage-exclude='**/packages/**' --test-coverage-exclude='**/examples/**' dist/__tests__/*.test.js",
146
146
  "lint": "biome lint .",
147
147
  "format": "biome format --write .",
148
148
  "format:check": "biome format .",