@arnilo/prism 0.5.5 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/README.md +10 -10
- package/dist/agent-approval.js +7 -6
- package/dist/agent-loops.js +51 -12
- package/dist/agent-session/session.d.ts +1 -0
- package/dist/agent-session/session.js +20 -2
- package/dist/agent-tool-dispatch.js +5 -4
- package/dist/cli-runner.d.ts +8 -1
- package/dist/cli-runner.js +97 -7
- package/dist/content.d.ts +3 -16
- package/dist/content.js +9 -99
- package/dist/context-budget.d.ts +12 -1
- package/dist/context-budget.js +42 -19
- package/dist/contracts-core/agent.d.ts +11 -0
- package/dist/contracts-core/agent.js +4 -1
- package/dist/extensions.d.ts +18 -1
- package/dist/extensions.js +10 -0
- package/dist/index.d.ts +6 -6
- package/dist/index.js +4 -4
- package/dist/input.d.ts +6 -0
- package/dist/input.js +12 -1
- package/dist/media-types.d.ts +34 -0
- package/dist/media-types.js +158 -0
- package/dist/pinned-fetch.d.ts +2 -2
- package/dist/pinned-fetch.js +11 -12
- package/dist/redaction.js +74 -1
- package/dist/session-stores.d.ts +11 -0
- package/dist/session-stores.js +23 -8
- package/docs/acp.md +1 -1
- package/docs/ag-ui.md +4 -2
- package/docs/agent-events.md +2 -0
- package/docs/agent-loops.md +1 -1
- package/docs/agent-session-runtime.md +3 -1
- package/docs/browser-automation.md +5 -2
- package/docs/cli-rpc.md +15 -1
- package/docs/contributing.md +37 -0
- package/docs/core.md +2 -0
- package/docs/document-reader.md +2 -0
- package/docs/documents.md +1 -1
- package/docs/extension-authoring.md +8 -9
- package/docs/extensions.md +13 -1
- package/docs/graft.md +29 -5
- package/docs/history/release-handoffs.md +33 -0
- package/docs/host-security.md +2 -2
- package/docs/index.md +33 -17
- package/docs/input-and-prompt-assembly.md +4 -4
- package/docs/language-intelligence.md +1 -1
- package/docs/migrate-to-0.5.md +7 -2
- package/docs/migrate-to-0.6.md +89 -0
- package/docs/migration.md +30 -0
- package/docs/model-registry.md +1 -1
- package/docs/multimodal-content.md +1 -1
- package/docs/obscura.md +3 -1
- package/docs/options-index.md +286 -0
- package/docs/peer-dependencies.md +94 -0
- package/docs/performance.md +34 -2
- package/docs/ponytail.md +2 -0
- package/docs/postgres-persistence.md +3 -1
- package/docs/provider-conformance.md +1 -1
- package/docs/provider-packages.md +21 -21
- package/docs/provider-primitives.md +2 -1
- package/docs/providers/ai-sdk.md +5 -2
- package/docs/public-contracts.md +2 -2
- package/docs/release-and-install.md +75 -55
- package/docs/server.md +1 -1
- package/docs/session-stores.md +3 -1
- package/docs/sqlite-persistence.md +2 -0
- package/docs/testing.md +38 -0
- package/docs/tools.md +1 -1
- package/docs/wiki.md +47 -3
- package/package.json +5 -5
|
@@ -96,12 +96,11 @@ The `contributed` set is what the extension registered. The `active` set is what
|
|
|
96
96
|
|
|
97
97
|
```ts
|
|
98
98
|
import {
|
|
99
|
+
activateKernel,
|
|
99
100
|
createAgent,
|
|
100
101
|
createExtensionKernel,
|
|
101
102
|
createMockProvider,
|
|
102
103
|
createContributionRegistries,
|
|
103
|
-
createSkillRegistry,
|
|
104
|
-
createToolRegistry,
|
|
105
104
|
providerDone,
|
|
106
105
|
type Extension,
|
|
107
106
|
} from "@arnilo/prism";
|
|
@@ -139,19 +138,18 @@ const registries = createContributionRegistries({ duplicate: "error" });
|
|
|
139
138
|
const kernel = createExtensionKernel({ registries, errorPolicy: "throw" });
|
|
140
139
|
await kernel.load([extension]);
|
|
141
140
|
|
|
142
|
-
// Host activation:
|
|
143
|
-
const
|
|
144
|
-
const skill = kernel.registries.skills.resolve("acme.brief");
|
|
141
|
+
// Host activation: copy the array slots; filter/narrow before createAgent() as needed.
|
|
142
|
+
const activated = activateKernel(kernel);
|
|
145
143
|
const provider = createMockProvider([providerDone()]);
|
|
146
144
|
|
|
147
145
|
const agent = createAgent({
|
|
148
146
|
model: { provider: "mock", model: "demo" },
|
|
149
147
|
provider,
|
|
150
|
-
tools:
|
|
151
|
-
skills:
|
|
152
|
-
context:
|
|
148
|
+
tools: activated.tools,
|
|
149
|
+
skills: activated.skills,
|
|
150
|
+
context: activated.context,
|
|
153
151
|
promptBuilder: kernel.registries.promptBuilders.resolve("acme.prompt"),
|
|
154
|
-
middleware:
|
|
152
|
+
middleware: activated.middleware,
|
|
155
153
|
});
|
|
156
154
|
|
|
157
155
|
await agent.createSession().run("Use the Acme extension.", { activeSkills: ["acme.brief"] });
|
|
@@ -166,6 +164,7 @@ await agent.createSession().run("Use the Acme extension.", { activeSkills: ["acm
|
|
|
166
164
|
- `registerSkill()` contributes instructions only. Referenced `toolNames` are checked against host-active tools when the skill is activated.
|
|
167
165
|
- `registerAuthMethod()` and `registerCredentialResolver()` must not contain resolved credential values. Use descriptors/resolvers; the host resolves secrets at the provider/request edge.
|
|
168
166
|
- Middleware from `api.use()` runs only when the host passes `kernel.middleware` into runtime configuration.
|
|
167
|
+
- `activateKernel(kernel)` copies the array slots (`tools`, `skills`, `instructionInjectors`, `context`, `commands`) plus `kernel.middleware` in one call; filter the returned arrays before `createAgent()` when the host wants narrower selection.
|
|
169
168
|
- Provider packages, provider request policies, system prompt contributions, instruction injectors, builders, strategies, commands, store factories, resource loaders, settings providers, and credential resolvers are all inert until host code selects or invokes them.
|
|
170
169
|
|
|
171
170
|
### Host driver hooks (opt-in)
|
package/docs/extensions.md
CHANGED
|
@@ -42,6 +42,7 @@ createExtensionEventBus(options?: { errorPolicy?: "event" | "throw"; secrets?: r
|
|
|
42
42
|
- `kernel.events.on(type, handler)` registers ordered event handlers and returns an unsubscribe function.
|
|
43
43
|
- `kernel.events.emit(event)` calls matching handlers in registration order.
|
|
44
44
|
- `kernel.middleware.run(hook, value)` runs matching middleware in registration order.
|
|
45
|
+
- `activateKernel(kernel)` copies the `createAgent()` array slots into one config: `{ tools, skills, instructionInjectors, context, commands, middleware }`. Contributions stay inert until the host passes them into runtime config; single-slot builders, `compaction`/`retry`, provider/model selection, and skill activation remain host-owned decisions.
|
|
45
46
|
- With default `errorPolicy: "event"`, setup/listener/middleware errors become `extension_error` events with redacted `ErrorInfo`.
|
|
46
47
|
- With `errorPolicy: "throw"`, setup/listener/middleware errors reject/throw.
|
|
47
48
|
|
|
@@ -57,7 +58,7 @@ createExtensionEventBus(options?: { errorPolicy?: "event" | "throw"; secrets?: r
|
|
|
57
58
|
## Implementation example
|
|
58
59
|
|
|
59
60
|
```ts
|
|
60
|
-
import { createAgent, createExtensionKernel, type Extension } from "@arnilo/prism";
|
|
61
|
+
import { activateKernel, createAgent, createExtensionKernel, type Extension } from "@arnilo/prism";
|
|
61
62
|
|
|
62
63
|
const extension: Extension = {
|
|
63
64
|
name: "demo-extension",
|
|
@@ -96,6 +97,17 @@ console.log(kernel.registries.skills.resolve("brief").name); // contributed only
|
|
|
96
97
|
console.log(kernel.registries.agents.resolve("demo").name); // contributed only; host must create/select before runtime use
|
|
97
98
|
console.log(kernel.registries.systemPromptContributions.resolve("demo-prompt").text); // contributed only; host must select before prompt use
|
|
98
99
|
await kernel.middleware.run("provider_request", { metadata: {} });
|
|
100
|
+
|
|
101
|
+
// Host activation: copy the array slots into createAgent() fields.
|
|
102
|
+
const activated = activateKernel(kernel);
|
|
103
|
+
const agent = createAgent({
|
|
104
|
+
model: { provider: "mock", model: "demo" },
|
|
105
|
+
tools: activated.tools,
|
|
106
|
+
skills: activated.skills,
|
|
107
|
+
instructionInjectors: activated.instructionInjectors,
|
|
108
|
+
context: activated.context,
|
|
109
|
+
middleware: activated.middleware,
|
|
110
|
+
});
|
|
99
111
|
```
|
|
100
112
|
|
|
101
113
|
## Extension and configuration notes
|
package/docs/graft.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# Graft context-graph integration
|
|
2
2
|
|
|
3
|
+
> **Optional peer install:** `@nanonets/graft` — see [Optional peer dependencies](peer-dependencies.md).
|
|
4
|
+
|
|
3
5
|
## What it does
|
|
4
6
|
|
|
5
7
|
`@arnilo/prism-memory/graft` is an optional subpath that wires [nanonets/graft](https://github.com/nanonets/graft) — a repository context-graph CLI (`graft/` directory, INDEX.md orientation, symbol-level wiring graph) — into Prism contribution contracts.
|
|
6
8
|
|
|
7
|
-
It registers six pull tools backed by the graft CLI (`--json`, argv-safe), a push-mode retrieval-pack context provider plus first-turn orientation injector carried on the `graft` skill, commands (`graft`, `graft-build`, `graft-check`, `graft-viz`), and an edit-watch middleware that computes blast radius after mutating tool calls. Import is inert; a missing graft CLI fails closed at `setup` with a bounded redacted error.
|
|
9
|
+
It registers six pull tools backed by the graft CLI (`--json`, argv-safe), a push-mode retrieval-pack context provider plus first-turn orientation injector carried on the `graft` skill, commands (`graft`, `graft-build`, `graft-build-deep`, `graft-check`, `graft-viz`, `graft-init`), and an edit-watch middleware that computes blast radius after mutating tool calls. Import is inert; a missing graft CLI fails closed at `setup` with a bounded redacted error.
|
|
8
10
|
|
|
9
11
|
## When to use it
|
|
10
12
|
|
|
@@ -14,7 +16,7 @@ Use it when a host wants agents to locate code by architecture, callers, and cou
|
|
|
14
16
|
- `"push"` — per-turn retrieval pack (pointers only) + first-turn orientation, injected automatically.
|
|
15
17
|
- `"both"` — everything.
|
|
16
18
|
|
|
17
|
-
Install optional peer `@nanonets/graft@^0.16.0` **or** pass `packageRoot`/`cliPath` explicitly. Pair with progressive disclosure: the `graft` skill body stays small; tool schemas carry the details. Graft complements indexed code search (`repository_search`): graph/semantic locators vs literal search — neither replaces the other.
|
|
19
|
+
Install optional peer `@nanonets/graft@^0.16.0 || ^0.18.0` **or** pass `packageRoot`/`cliPath` explicitly. Both floors are smoke-tested by the offline peer-contract suite (`resolveGraftCli` bin discovery + packaged manifest); the range lists exactly the two released lines Prism validates, and `0.17` is absent because upstream never published one. Pair with progressive disclosure: the `graft` skill body stays small; tool schemas carry the details. Graft complements indexed code search (`repository_search`): graph/semantic locators vs literal search — neither replaces the other.
|
|
18
20
|
|
|
19
21
|
Zero-code alternative (L0): hosts can skip this package entirely and let agents call `graft <command> --json` through their shell tool, optionally seeding context with graft's own generated instruction files. This package exists for native-tool ergonomics, budgeted subprocesses, session persistence, and push mode.
|
|
20
22
|
|
|
@@ -32,6 +34,9 @@ Zero-code alternative (L0): hosts can skip this package entirely and let agents
|
|
|
32
34
|
| `maxPromptChars` | `number` | no | Prompts longer than this never become ask argv (default 4096). |
|
|
33
35
|
| `allowUpstreamTelemetry` | `boolean` | no | Default false → children run with `DO_NOT_TRACK=1`. |
|
|
34
36
|
| `providerEnv` | `Record<string, string>` | no | Explicit graft provider settings (`GRAFT_API_KEY`, …). Never inherited from host env; only `GRAFT_*` keys reach the child. |
|
|
37
|
+
| `deepModel` | `{ provider: "openai" \| "anthropic" \| "litellm" \| "orcarouter", model: string, apiKey: string, baseUrl?: string }` | no | Model for `graft build --deep` (Graft's own LLM client — **Prism's `Provider` is not Graft's LLM**; they have different protocols). Merged over `providerEnv` as `GRAFT_PROVIDER`/`GRAFT_MODEL`/`GRAFT_API_KEY`/`GRAFT_BASE_URL`; wins on conflict. |
|
|
38
|
+
| `initAgents` / `initYes` / `initWireMcp` | `readonly string[]` / `boolean` / `boolean` | no | `graft init` configuration: agent ids for `--agents`, `--yes`, and whether to wire graft MCP servers (default off — Prism provides its own graft surfaces). `graft-init` refuses to spawn without `initAgents` or `initYes` (the child has no TTY). |
|
|
39
|
+
| `buildBudgetMs` / `deepBuildBudgetMs` / `buildMaxResultBytes` | `number` | no | Budgets for graph builds: structural `build`/`init` default 120000 ms, `--deep` default 600000 ms (the LLM pass over the graph), stdout cap 2 MiB. Ask/grep stay on `retrievalBudgetMs`. |
|
|
35
40
|
| `editToolNames` | `readonly string[]` | no | Tools triggering blast-radius lookup. Default `write`, `edit`, `move`. |
|
|
36
41
|
| `quietStartup`, `hideStatus` | `boolean` | no | Suppress startup status events / status reporting. |
|
|
37
42
|
| `appendEntry` | `(entry, opts?) => Promise<void>` | yes | Host session append (OM attach pattern). |
|
|
@@ -41,7 +46,20 @@ Pull tools (mode includes `pull`): `graft_ask`, `graft_grep`, `graft_callers`, `
|
|
|
41
46
|
|
|
42
47
|
Push surfaces (mode includes `push`): skill `graft` carrying context provider `graft-context` (per-turn pointers-only pack, gated: ≥12-char prompt, dedup by seen node ids, 32 KiB block ceiling) and instruction injector `graft-orient` (`first_turn`, byte-capped INDEX.md cut + staleness banner).
|
|
43
48
|
|
|
44
|
-
Registered commands: `graft` (`status` \| `build` \| `check` \| `viz` dispatch), plus `graft-build`, `graft-check`, `graft-viz` aliases.
|
|
49
|
+
Registered commands: `graft` (`status` \| `build` [deep:true] \| `check` \| `viz` \| `init` dispatch), plus `graft-build`, `graft-build-deep`, `graft-check`, `graft-viz`, `graft-init` aliases.
|
|
50
|
+
|
|
51
|
+
### Graph builds and init
|
|
52
|
+
|
|
53
|
+
- `/graft-build` — structural rebuild via `graft build` (tree-sitter pass, no API key, plain-text progress — no `JSON.parse` on this surface).
|
|
54
|
+
- `/graft-build-deep` — `graft build --deep --provider <> --model <> [--base-url <>]` using the host's `deepModel`. Without a configured model it errors before spawning. `GRAFT_API_KEY` rides in the child env, never on argv.
|
|
55
|
+
- `/graft-init` — `graft init --no-global` (never writes user-level state), default `--no-mcp --no-hooks --no-statusline` (opt in via `initWireMcp`), plus `--agents <id>` per `initAgents` and `--yes` when `initYes`. Requires one of the two; non-interactive by design.
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
# structural, no key
|
|
59
|
+
/graft-build
|
|
60
|
+
# deep — host-configured model
|
|
61
|
+
e.g. /graft-build-deep
|
|
62
|
+
```
|
|
45
63
|
|
|
46
64
|
## Outputs / response / events
|
|
47
65
|
|
|
@@ -49,7 +67,8 @@ Registered commands: `graft` (`status` \| `build` \| `check` \| `viz` dispatch),
|
|
|
49
67
|
| --- | --- |
|
|
50
68
|
| `createGraftExtension(options)` | Returns an inert `Extension` until `kernel.load([...])`; emits `graft:loaded` on setup. |
|
|
51
69
|
| `resolveGraftCli(options)` | Fail-closed CLI resolution (`explicit` → command+argv, `peer-bin` → node + manifest bin). |
|
|
52
|
-
| `runGraftJson(cli, argv, options)` / `childEnv(options)` / `childTimeoutMs` / `DEFAULT_MAX_RESULT_BYTES` |
|
|
70
|
+
| `runGraftJson(cli, argv, options)` / `runGraftExit(cli, argv, options)` / `childEnv(options)` / `childTimeoutMs` / `DEFAULT_MAX_RESULT_BYTES` | Budgeted runners for hosts building custom surfaces — JSON surfaces (`check`/`ask`) vs exit-code surfaces (`build`/`init`). |
|
|
71
|
+
| `deepProviderEnv(deepModel, providerEnv)` | `deepModel` merged over `providerEnv`, filtered to `GRAFT_*`. |
|
|
53
72
|
| `readBoundedFile` / `redactPaths` / `GraftResolveError` | Bounded-read and redaction helpers. |
|
|
54
73
|
|
|
55
74
|
Events: `graft:status` (check/build outcomes), `graft:dirty` (post-edit, repo-relative path + optional `staleCountEstimate`), `graft:loaded` (mode + cliKind metadata).
|
|
@@ -92,12 +111,15 @@ await kernel.load([
|
|
|
92
111
|
packageRoot: "./vendor/graft-checkout",
|
|
93
112
|
mode: "both",
|
|
94
113
|
quietStartup: true,
|
|
114
|
+
deepModel: { provider: "anthropic", model: "claude-sonnet-4-5", apiKey: process.env.ANTHROPIC_API_KEY! },
|
|
115
|
+
initAgents: ["codex"],
|
|
95
116
|
appendEntry: async (entry, options) => store.append(entry, options),
|
|
96
117
|
getEntries: async () => store.list("s1"),
|
|
97
118
|
}),
|
|
98
119
|
]);
|
|
99
120
|
// Pull: dispatch graft_ask/… tools. Push: runs assemble the skill-carried
|
|
100
121
|
// provider + graft-orient injector. Edits: middleware emits graft:dirty.
|
|
122
|
+
// /graft-build-deep runs graft's own LLM pass; /graft-init wires codex, --no-global.
|
|
101
123
|
```
|
|
102
124
|
|
|
103
125
|
## Extension and configuration notes
|
|
@@ -110,7 +132,9 @@ await kernel.load([
|
|
|
110
132
|
|
|
111
133
|
## Security and performance notes
|
|
112
134
|
|
|
113
|
-
- Telemetry default-off: children always get `DO_NOT_TRACK=1` unless `allowUpstreamTelemetry` is true; child env is fixed-base — host env vars are never inherited, and only explicit `GRAFT_*` keys from `providerEnv` pass through. Route secrets like `GRAFT_API_KEY` through the host's credential resolution when populating `providerEnv`.
|
|
135
|
+
- Telemetry default-off: children always get `DO_NOT_TRACK=1` unless `allowUpstreamTelemetry` is true; child env is fixed-base — host env vars are never inherited, and only explicit `GRAFT_*` keys from `providerEnv`/`deepModel` pass through. Route secrets like `GRAFT_API_KEY` through the host's credential resolution when populating `deepModel`/`providerEnv`. `deepModel`'s API key reaches the child via env only — never on argv (no `--api-key` flag exists in the surface), so it cannot leak through `ps` or logs.
|
|
136
|
+
- Build/init commands are budgeted separately from retrieval (`buildBudgetMs`, `deepBuildBudgetMs`, `buildMaxResultBytes`); deep builds fail closed without a configured model instead of spawning unconfigured.
|
|
137
|
+
- `graft-init` always passes `--no-global` — it never writes user-level agent state; MCP/hook/statusline wiring stays off unless the host opts in via `initWireMcp`.
|
|
114
138
|
- Upstream output is untrusted: stdout capped (`maxResultBytes`), prompts capped (`maxPromptChars`), injected packs bounded (32 KiB), orientation cut byte-capped (8 KiB); error paths are logged redacted (absolute paths/home dirs).
|
|
115
139
|
- Every CLI call is wall-clock-budgeted (`retrievalBudgetMs`, minus fixed overhead for the timeout math) and every failure degrades silently: pull tools return structured errors, the push pack contributes nothing, edit-watch passes the tool result through untouched.
|
|
116
140
|
- No background workers; state persists through two CAS appends per turn at most (freshness patch, seen-set/saved-tokens update).
|
|
@@ -2,6 +2,39 @@
|
|
|
2
2
|
|
|
3
3
|
Operator publish handoffs per release line, kept verbatim. Not read on the hot path.
|
|
4
4
|
|
|
5
|
+
### 0.6.0 publish handoff (plan 071 Task 16)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
**Decision: GO when the operator prerequisites below are recorded.** Release **0.6.0** is the first published cut after **0.5.6**: the 0.5.7 cut was never published and is **superseded** by this one (registry preflight `node scripts/release.mjs check --lockstep --version 0.6.0` reports all **10/10 packages available**, so there is no published 0.5.7 to replace or deprecate). The graph is **10 publishable manifests** at exact **0.6.0** with internal ranges `^0.6.0`: root `@arnilo/prism` plus 9 workspace packages (3 `prism-*` family packages, 6 capability packages, 19 provider adapter subpaths inside the providers family).
|
|
9
|
+
|
|
10
|
+
Host-visible delta (full detail in [migrate-to-0.6.md](../../docs/migrate-to-0.6.md)): the runtime floor moves to **Node `>=22`** (Node 20 is upstream EOL since 2026-04-30) and the never-published 0.5.7 content ships here — third-party floors (`pg ^8.23`, `playwright-core 1.63.0`, `@ai-sdk/provider 4.0.13`, `@agentclientprotocol/sdk` exact `1.4.0`, `@office-open/* 0.14.5`, `zod ^4.6.2`), the removed `@arnilo/prism-office` `playwright-core` peer, five additive host knobs, and the durable-tool-round / strict-provider tool-result fixes. No import path, store schema, event shape, or public signature was removed: the compat baselines were regenerated and reviewed as **+70 public names, zero removals** (32 declaration-site moves from the module splits).
|
|
11
|
+
|
|
12
|
+
Evidence recorded for the tree under publication: `scripts/release-evidence.json` — **42 surfaces, 11 pass, 31 protected with reasons, `blocked: false`** (`test:postgres durable conformance` is a real pass, count 91, env **name** only); `npm test` 5/5 stages (core count 3716, skip 33); combined coverage core 92.13% lines against the 60/70/75 gate with all nine workspace suites above their lines thresholds; `security:threat-suites` 83/83; `npm audit --audit-level=moderate` 0; SBOM regenerated (`npm sbom --sbom-format spdx > security-artifacts/sbom.spdx.json`, 172 packages, 10 licenses, `verify-sbom` clean); tracked-source secret scan 2166 files, 0 findings.
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# Operator prerequisites (each a named blocked gate — none may be skipped):
|
|
16
|
+
# 1. protected live-canary matrix green (live-canaries.yml, canary-report.json retained)
|
|
17
|
+
# 2. PostgreSQL protected suite green (test:postgres) and CodeQL SAST green on the release commit
|
|
18
|
+
# 3. npm OIDC trusted publishing identity authenticated (NPM_TOKEN with id-token, provenance)
|
|
19
|
+
# 4. branch protection: the compatibility leg is named node22-compat (renamed from node20-compat)
|
|
20
|
+
|
|
21
|
+
git diff --check
|
|
22
|
+
npm ci
|
|
23
|
+
# sdk:ready phases, as .github/workflows/release.yml runs them (env scoped to release:gate only):
|
|
24
|
+
npm run typecheck && npm run lint && npm run format:check
|
|
25
|
+
npm test && npm run test:coverage && npm run pack:dry-run
|
|
26
|
+
PRISM_TEST_POSTGRES_URL=... npm run release:gate
|
|
27
|
+
npm run security:threat-suites
|
|
28
|
+
|
|
29
|
+
# Sign the release on the clean tagged tree (operator GPG key):
|
|
30
|
+
git tag -s v0.6.0 -m "0.6.0"
|
|
31
|
+
node scripts/release.mjs publish --lockstep --version 0.6.0
|
|
32
|
+
|
|
33
|
+
# First-party package tags: push in batches of <=3 per push (tag-push storms; VENT 26-08-29).
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
Rollback pins the previous published line — `@arnilo/prism@0.5.6` and its siblings, exact pins per package. **Never pin 0.5.7: it does not exist on the registry.** Persisted shapes are unchanged across 0.5.6 → 0.6.0, so a pin rollback loses only the Node floor, the peer floors, and the new knobs.
|
|
37
|
+
|
|
5
38
|
### 0.3.2 independent workflow patch (plan 045)
|
|
6
39
|
|
|
7
40
|
|
package/docs/host-security.md
CHANGED
|
@@ -152,13 +152,13 @@ Wire those values where they matter: provider adapters receive the resolved cred
|
|
|
152
152
|
- `@arnilo/prism-core/runtime/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. The artifact review service (`createArtifactService`) requires authenticated identity + thread ownership on every attach/revise/compare/approve/reject/download, resolves concurrent reviewers via checkpoint CAS (no lost approvals), rejects local filesystem paths in `uri`/citations, redacts records before persist and on response, and serves downloads only through signed expiring links that are reauthorized against the token's ownership per request. When a blob store is wired (`bodies: ArtifactBodyStore`, 0.0.28), delivery links additionally resolve through `bodies.presign`; the reference `createS3ArtifactBodyStore` verifies ownership on every operation, verifies size/SHA-256/MIME on put and get (fail closed), refuses delete under legal hold (host `isHeld` callback), keeps credentials host-resolved, and never discloses bucket/path/key in errors, telemetry, or artifact records. 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. Outbound lifecycle webhooks (`createWebhookNotifier`, 0.3.2) share the same boundary posture: host-registered public HTTPS (or explicitly opted-in loopback HTTP) targets only, private/metadata literals rejected at registration, every attempt DNS-pinned and redirect-free through core `pinnedFetch`, redaction before HMAC signing, and the key held by the host only. Pass a known-secret `SecretRedactor`.
|
|
153
153
|
- Coding tools from `@arnilo/prism-coding-tools/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-tools/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** (every isolation capability false). Sandbox mode reports isolation only from validated adapter capability metadata: `composition.capabilities` carries the frozen `SandboxCapabilities` object (`workspaceCoherent`, `filesystemIsolated`, `networkIsolated`, `processIsolated`, `privilegeIsolated`, `egressRestricted`); the deprecated `containmentClaim` is a conservative projection and must never be used alone. Authorize security-sensitive actions from the individual capabilities the policy actually needs — e.g. require `filesystemIsolated` before hosting untrusted coding tasks, and `egressRestricted` before any network-capable run. Mixed wiring requires `allowMixedWorkspaceWiring` and still reports no isolation. 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.
|
|
154
154
|
- Allow-list egress (0.0.26, `@arnilo/prism-coding-tools/security`): `createEgressPolicy()` is deny-all with exact host/port/protocol rules and frozen `npm-registry`/`github` presets; `createAllowListEgressProxy()` is an HTTP forward proxy + CONNECT tunnel that pins DNS answers and verifies the connected address (rebinding defense), denies private/link-local/metadata ranges unless a rule opts in, re-validates every redirect hop against policy, and cuts oversized/slow transfers at frozen byte/time caps. TLS passes through without interception. Every allow/deny writes an audit record with no secrets. The proxy is inert until `start()`; `reloadPolicy()` is the only rule change path. `composeEgressSandboxNetwork(proxy.attestation(), name)` records validated attestation as `prism.egress.*` container labels — evidence, not enforcement: the host must restrict the Docker network so the proxy is the only reachable path, and `denyDirectEgress: true` is a claim the host makes true by topology. The proxy is not a firewall and cannot stop a container whose network reaches the internet directly.
|
|
155
|
-
- Optional `@arnilo/prism-web-tools/browser` requires a host-supplied Playwright Browser (`playwright-core@1.
|
|
155
|
+
- Optional `@arnilo/prism-web-tools/browser` requires a host-supplied Playwright Browser (`playwright-core@1.63.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()`.
|
|
156
156
|
- Browser verified-state checkpoints (0.0.14, `createBrowserCheckpointLedger()`) store URL + domain-state hash + host data refs only — never serialized browser internals (cookies/storage/contexts). After any resume/interruption the ledger fails closed (`assertVerifiedBeforeSideEffect`) until the host reloads + verifies, so side effects never replay on stale state.
|
|
157
157
|
- Device adapters (0.0.14, `resolveDevicePolicy`/`assertDeviceAdmit`) are deny-by-default: admission fails closed without explicit `enabled`, an explicit sandbox, approval (when required), an under-budget session count, and shared `RunLimits`. Stream chunks over the frozen cap are dropped with a marker; telemetry is redacted before emit/persist. No vendor voice/desktop package ships in 0.0.14 (demand-gated 0.1.x); device adapters cannot broaden consent/memory/network/file/browser/connector/tool permissions (gate 8).
|
|
158
158
|
- Optional `@arnilo/prism-memory/wiki` tools treat agent-supplied input as untrusted at the first-party `.wiki/` filesystem boundary. `wiki_read_page` enforces lexical containment (`path.relative` with separator-aware `..`/absolute checks) plus `fs.realpath` containment for the wiki root and every successfully read file, so sibling-prefix (`.wiki-evil`), `..`, absolute, alternate-separator, and symlink escapes are denied before content is returned; missing contained pages report `found: false` while denied paths throw an access-denied error (never mapped to not-found). `wiki_record_insight` rejects empty titles/content, caps titles at 200 characters and content at 65,536 bytes, and collapses control characters and newlines in titles to single-line display text before any page/frontmatter/index/log write, so titles cannot inject Markdown headings, index entries, or log entries; slugs are allow-listed to `[a-z0-9-_]` with a non-empty fallback. See [LLM Wiki](wiki.md).
|
|
159
159
|
- `@arnilo/prism-core/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.
|
|
160
160
|
- 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.
|
|
161
|
-
- Default remote-media loading resolves every DNS answer, rejects the hostname if any address is non-public, and pins one validated address through the request. Explicit `allowedHostnames` can trust private destinations. A host-supplied `fetch` owns DNS/rebinding/proxy/redirect safety; a custom `requestUrl` must connect to its supplied validated address.
|
|
161
|
+
- Default remote-media loading resolves every DNS answer, rejects the hostname if any address is non-public, and pins one validated address through the request. Explicit `allowedHostnames` can trust private destinations; `allowedCidrs` trusts IP ranges instead (checked after the hostname/denied-name lists, applied to literals and resolved answers, and bypassing only the private-IP block — metadata-style names and malformed ranges fail closed). A host-supplied `fetch` owns DNS/rebinding/proxy/redirect safety; a custom `requestUrl` must connect to its supplied validated address.
|
|
162
162
|
- Permission checks happen before tool validation and before `tool.execute()`. Middleware cannot grant permission by renaming a tool.
|
|
163
163
|
- Session stores and ledgers receive redacted values when a redactor is active, but durable storage remains host-owned. Enforce tenant/account/user ownership, retention, legal hold, and quotas via `ProductionPersistenceStore.lifecycle` (or host-equivalent DB controls). Hold always blocks delete.
|
|
164
164
|
- `@arnilo/prism-core/enterprise/postgres` request paths require exact tenant scope plus principal for work/router state, use bound SQL values, and retain no prompts, connector request bodies, raw provider results, tokens, or credentials. Configure TLS/credential rotation/connection limits with the host `pg` pool. Run checksum/catalog migration setup with a controlled migration principal; keep request-path SQL least-privilege (`USAGE`, `SELECT`, `INSERT`, `UPDATE`, `DELETE` on six state tables) and do not grant request workers `CREATE`, `ALTER`, `DROP`, `TRUNCATE`, `GRANT`, or `COPY PROGRAM`. Back up and restore-test the schema; run bounded owner-scoped `state.cleanup()` from an authorized host job. `unknown` connector outcomes require reconciliation and must never auto-replay.
|
package/docs/index.md
CHANGED
|
@@ -2,19 +2,31 @@
|
|
|
2
2
|
|
|
3
3
|
Prism is a TypeScript/Node.js agent harness. Hosts own providers, tools, credentials, storage, and behavior; Prism supplies contracts, registries, events, and replaceable runtime primitives.
|
|
4
4
|
|
|
5
|
-
## Current line (0.
|
|
6
|
-
|
|
5
|
+
## Current line (0.6.0)
|
|
6
|
+
|
|
7
|
+
- **Node 22 floor**: `engines.node` is `>=22` in all ten publishable packages, the `node20-compat` CI leg becomes `node22-compat`, and `@types/node` moves to `^22.20.0` (plan 071; Node 20 is upstream EOL since 2026-04-30).
|
|
8
|
+
- **Folded 0.5.7 content**: the 0.5.7 cut was never published — its durable-tool-round and strict-tool-result fixes, host knobs, peer/options truth, and dependency floors ship in 0.6.0 (migration guide below).
|
|
9
|
+
- **Release-truth gates**: one forward-claim version-literal gate (manifests, internal ranges, lockfile, version constant, index banner, workflow tags), a workflow-liveness gate (every script target and action reference resolves, actions SHA-pinned), and a load-tolerant startup budget ratio (plan 071).
|
|
10
|
+
- **Self-describing coverage failures**: a failing coverage child prints its redacted output tail and records `status`/`exitCode`/`tail` on its artifact row (plan 071).
|
|
11
|
+
- **Durable tool rounds**: concurrent tool dispatch persists successful sibling results — plus synthetic errors for failed and never-dispatched calls — before a round fails or aborts, so no `tool_use` is left unanswered (plan 070).
|
|
12
|
+
- **Strict-provider tool results**: a content-less `ToolResult` folds to the non-empty `(tool completed with no output)` payload instead of an empty one (plan 070).
|
|
13
|
+
- **Host-tunable knobs**: context-budget `tokenEstimator`, `snapshotCacheTtlMs`, memory-session search caps, `SsrfPolicy.allowedCidrs`, and browser `idleRunTtlMs` (plan 070).
|
|
14
|
+
- **Peer and options truth**: the optional peer-dependency matrix and the configuration options index (both linked below) cover every third-party peer and public option surface (plan 070).
|
|
15
|
+
- **Trusted extension activation**: `activateKernel(kernel)` returns ready-to-spread `AgentConfig` contributions; CLI loads allow-listed `--extension` packages (plan 069).
|
|
16
|
+
- **Wiki ingest**: `/wiki-ingest` + `ingestWikiSource` stage text/file/image/PDF (and URLs via a host `fetchUrl` hook) into `raw/ingest/` with an OKF filing brief (plan 069).
|
|
17
|
+
- **Graft graph commands**: `/graft-init`, `/graft-build`, `/graft-build-deep` (host-configured `deepModel`, key env-only) (plan 069).
|
|
7
18
|
- **Run limits**: HARD caps are request/response bytes only; policy axes accept `null` (plan 067).
|
|
8
19
|
- **Tool-result fold**: content-only `ToolResult`s fold into `tool_result.result` (0.5.3).
|
|
9
20
|
- **Stream token coalesce**: adjacent text/thinking deltas merge on persist (0.5.2).
|
|
10
21
|
- **Provider request construction**: kernel session/cache/thinking defaults; hosts overlay (0.5.1).
|
|
11
|
-
- **10 publishable packages** at current **0.
|
|
22
|
+
- **10 publishable packages** at current **0.6.0** lockstep — inventory below.
|
|
12
23
|
|
|
13
24
|
## Public contracts
|
|
14
25
|
|
|
15
26
|
- [Public contracts](public-contracts.md): canonical message, agent, tool, store, resource, credential, and event shapes.
|
|
16
27
|
- [Coding tools, sandboxing, and personas](coding-tools.md): `@arnilo/prism-coding-tools` family subpaths — agent, security, document-reader, openapi, computer-use-linux, dev, personas.
|
|
17
28
|
- [Core runtime, sessions, and governance](core.md): `@arnilo/prism-core` family subpaths — runtime, sessions, governance, credentials, enterprise, work, validation.
|
|
29
|
+
- [Configuration options index](options-index.md): every public `*Options`/`*Limits`/`*Config` surface mapped to the doc page that owns its fields.
|
|
18
30
|
|
|
19
31
|
## Identity and governance
|
|
20
32
|
|
|
@@ -53,7 +65,7 @@ Prism is a TypeScript/Node.js agent harness. Hosts own providers, tools, credent
|
|
|
53
65
|
- [SQLite persistence](sqlite-persistence.md): optional `better-sqlite3` adapter with FTS search and verified migrations.
|
|
54
66
|
- [PostgreSQL persistence](postgres-persistence.md): optional pooled `pg` adapter with advisory-locked migrations and live conformance.
|
|
55
67
|
- [Enterprise PostgreSQL state](enterprise-postgres-state.md): durable governance/router/ERP state, outbox/inbox messaging, approval records.
|
|
56
|
-
- [Migration guide](migration.md):
|
|
68
|
+
- [Migration guide](migration.md): the era index of migration cuts with replacement tables and rollback notes.
|
|
57
69
|
- [Node JSONL session store](node-jsonl-session-store.md): development-only JSONL adapter, single-process, no cross-process safety.
|
|
58
70
|
|
|
59
71
|
## Provider and model connection
|
|
@@ -85,7 +97,7 @@ Prism is a TypeScript/Node.js agent harness. Hosts own providers, tools, credent
|
|
|
85
97
|
- [Versioned prompt registry](prompt-registry.md): immutable content-hashed prompt assets with durable stores and bounded diff.
|
|
86
98
|
- [Instruction injection](instruction-injection.md): package injectors layer redacted instructions without granting capabilities.
|
|
87
99
|
- [Context and skills](context-and-skills.md): ordered context providers, progressive skill disclosure, fail-closed activation.
|
|
88
|
-
- [LLM Wiki](wiki.md): optional knowledge compiler emitting OKF bundles with on-device hybrid search.
|
|
100
|
+
- [LLM Wiki](wiki.md): optional knowledge compiler emitting OKF bundles, with `/wiki-ingest` raw staging (text, file, image, or URL via a host `fetchUrl` hook) and on-device hybrid search.
|
|
89
101
|
- [Retrieval-augmented generation](rag.md): bounded source lifecycle, hybrid retrieval, reranking, citations, inert injection.
|
|
90
102
|
|
|
91
103
|
## Tools
|
|
@@ -132,6 +144,7 @@ Prism is a TypeScript/Node.js agent harness. Hosts own providers, tools, credent
|
|
|
132
144
|
- [Configuration and manifests](configuration-and-manifests.md): layered JSON config merge with data-only manifest validation.
|
|
133
145
|
- [Node filesystem config loader](node-filesystem-config.md): explicitly read caller-named JSON config files in Node.
|
|
134
146
|
- [Resource loading](resource-loading.md): decode text/JSON/binary through caller-provided loaders; RAG bridge.
|
|
147
|
+
- [Optional peer dependencies](peer-dependencies.md): every third-party peer a package declares, the subpath it unlocks, its install line, pin rationale, and which peers touch the network.
|
|
135
148
|
|
|
136
149
|
## Server/API
|
|
137
150
|
|
|
@@ -150,7 +163,7 @@ Prism is a TypeScript/Node.js agent harness. Hosts own providers, tools, credent
|
|
|
150
163
|
## CLI/RPC
|
|
151
164
|
|
|
152
165
|
- [Dev inspector](dev-inspector.md): loopback-only local playground over a configured agent; `prism dev` composition.
|
|
153
|
-
- [CLI/RPC](cli-rpc.md): print/json modes, LF-delimited RPC, `prism init` scaffold, provider scaffolding.
|
|
166
|
+
- [CLI/RPC](cli-rpc.md): print/json modes, LF-delimited RPC, `prism init` scaffold, provider scaffolding, allow-listed `--extension` activation.
|
|
154
167
|
- [Workflows](workflows.md): typed bounded DAG orchestration with durable suspend/resume, schedules, sagas.
|
|
155
168
|
|
|
156
169
|
## Security and credentials
|
|
@@ -162,6 +175,8 @@ Prism is a TypeScript/Node.js agent harness. Hosts own providers, tools, credent
|
|
|
162
175
|
|
|
163
176
|
## Testing and examples
|
|
164
177
|
|
|
178
|
+
- [Test layout and isolation](testing.md): the five `npm test` stages, scratch-root rule, and the tracked-fixture isolation gate.
|
|
179
|
+
- [Contribution quality budgets](contributing.md): the non-null assertion allowance, export-surface ceilings, and the rule that keeps them shrinking.
|
|
165
180
|
- [Live and end-to-end testing](live-testing.md): opt-in live matrix with skip-not-fail contract and credential scoping table.
|
|
166
181
|
- Provider test doubles: `createMockProvider()` and provider event helpers are documented on the canonical Provider layer page above.
|
|
167
182
|
- [Provider conformance](provider-conformance.md): network-free adapter assertions from `@arnilo/prism/testing/provider-conformance`.
|
|
@@ -176,12 +191,13 @@ Prism is a TypeScript/Node.js agent harness. Hosts own providers, tools, credent
|
|
|
176
191
|
|
|
177
192
|
- [Caveman behavior integration](caveman.md): upstream Caveman skills with injector, persistence, and progressive catalog.
|
|
178
193
|
- [Ponytail behavior integration](ponytail.md): upstream Ponytail skills with injector and peer resolution; opt-in.
|
|
179
|
-
- [Graft context-graph integration](graft.md): graft CLI pull tools, retrieval-pack context provider, blast-radius middleware.
|
|
194
|
+
- [Graft context-graph integration](graft.md): graft CLI pull tools, retrieval-pack context provider, blast-radius middleware, and `/graft-init` / `/graft-build` / `/graft-build-deep` commands (host-configured `deepModel`).
|
|
180
195
|
- [Impeccable behavior integration](impeccable.md): upstream Impeccable skill behind `load_skill`; host supplies the compiled `SKILL.md`.
|
|
181
196
|
|
|
182
197
|
## Release and install
|
|
183
198
|
|
|
184
199
|
- [Release and install](release-and-install.md): install rules, package graph, and deterministic resumable publication.
|
|
200
|
+
- [Migrate 0.5 → 0.6](migrate-to-0.6.md): Node 22 floor, folded 0.5.7 host delta, third-party floors, and upgrade/rollback steps.
|
|
185
201
|
- [Migrate 0.5](migrate-to-0.5.md): 0.4 → 0.5 migration guide with per-release sections and rollback.
|
|
186
202
|
- [Documentation archive](history/README.md): frozen migration/history records — not read on the hot path.
|
|
187
203
|
- [Review coverage archive](_evidence/): per-phase evidence freezes — audit trail, excluded from tarballs.
|
|
@@ -195,14 +211,14 @@ The generated inventory below derives from [`scripts/package-truth.json`](../scr
|
|
|
195
211
|
|
|
196
212
|
| package | version | notes |
|
|
197
213
|
| --- | --- | --- |
|
|
198
|
-
| `@arnilo/prism` | 0.
|
|
199
|
-
| `@arnilo/prism-coding-tools` | 0.
|
|
200
|
-
| `@arnilo/prism-core` | 0.
|
|
201
|
-
| `@arnilo/prism-providers` | 0.
|
|
202
|
-
| `@arnilo/prism-acp-agent` | 0.
|
|
203
|
-
| `@arnilo/prism-ag-ui` | 0.
|
|
204
|
-
| `@arnilo/prism-mcp` | 0.
|
|
205
|
-
| `@arnilo/prism-memory` | 0.
|
|
206
|
-
| `@arnilo/prism-office` | 0.
|
|
207
|
-
| `@arnilo/prism-web-tools` | 0.
|
|
214
|
+
| `@arnilo/prism` | 0.6.0 | core — runtime, CLI/RPC, templates, docs |
|
|
215
|
+
| `@arnilo/prism-coding-tools` | 0.6.0 | family — /agent, /security, /document-reader, /openapi, /computer-use-linux, /dev, /caveman, /ponytail, /impeccable subpaths |
|
|
216
|
+
| `@arnilo/prism-core` | 0.6.0 | family — /runtime, /sessions, /governance, /credentials, /enterprise, /work, /validation subpaths |
|
|
217
|
+
| `@arnilo/prism-providers` | 0.6.0 | family — all provider adapters as `/<adapter>` subpaths |
|
|
218
|
+
| `@arnilo/prism-acp-agent` | 0.6.0 | capability — ACP adapter |
|
|
219
|
+
| `@arnilo/prism-ag-ui` | 0.6.0 | capability — AG-UI/A2A/A2UI adapter |
|
|
220
|
+
| `@arnilo/prism-mcp` | 0.6.0 | capability — MCP client/server/OAuth interop |
|
|
221
|
+
| `@arnilo/prism-memory` | 0.6.0 | capability — memory plus /rag, /compaction/*, /graft, /wiki subpaths |
|
|
222
|
+
| `@arnilo/prism-office` | 0.6.0 | capability — /documents, /sheets, /diagrams subpaths |
|
|
223
|
+
| `@arnilo/prism-web-tools` | 0.6.0 | capability — Brave/Exa/Firecrawl plus peer-gated /browser and /obscura subpaths |
|
|
208
224
|
<!-- generated:package-truth:inventory end -->
|
|
@@ -62,8 +62,8 @@ Useful exported types:
|
|
|
62
62
|
- `InputAttachment`: already-loaded text/content blocks (including `audio`, `file`, and `document`) or an explicit URI loaded through a caller-provided `ResourceLoader`.
|
|
63
63
|
- `PromptInstruction`: labeled system instruction text.
|
|
64
64
|
- `DefaultPromptBuilder`: the default `PromptBuilder`; cache-aware by default and legacy-preserving when `inputLayout: "legacy"` is passed in its request.
|
|
65
|
-
- `AssembleProviderInputOptions`: model, input, optional builders, context providers, selected skills, active tools, generic provider options, metadata, signal, and optional `contextBudget` (`maxInputTokens` / `maxInputBytes` / `reportOmissions`).
|
|
66
|
-
- `applyContextBudget` / `getContextBudgetReport` / `resolveContextBudget`: deterministic eviction + omission report helpers (estimate = UTF-16 code units ÷ 4).
|
|
65
|
+
- `AssembleProviderInputOptions`: model, input, optional builders, context providers, selected skills, active tools, generic provider options, metadata, signal, and optional `contextBudget` (`maxInputTokens` / `maxInputBytes` / `reportOmissions` / `tokenEstimator`).
|
|
66
|
+
- `applyContextBudget` / `getContextBudgetReport` / `resolveContextBudget`: deterministic eviction + omission report helpers (estimate = UTF-16 code units ÷ 4, or the host's `tokenEstimator`).
|
|
67
67
|
- `PromptTemplateOptions`: missing-variable behavior for `renderPromptTemplate()`.
|
|
68
68
|
|
|
69
69
|
## Outputs / response / events
|
|
@@ -88,10 +88,10 @@ In cache-aware mode, leading system instructions form the stable boundary before
|
|
|
88
88
|
- History is prepended before current input.
|
|
89
89
|
- Instructions and summaries are system messages; compacted branch summaries from `rebuildSessionContext()` use the same path.
|
|
90
90
|
- Text attachments and explicit text resources are user messages; inline `audio`/`file`/`document` blocks pass through unchanged on attachments with `content`.
|
|
91
|
-
- Tool results are tool messages containing `tool_result` content; the agent/session runtime uses this to feed dispatched tool results into the next provider turn, placing the assistant `tool_call` and the matching role `tool` `tool_result` before any final assistant content. Cache-aware layout keeps tool results before the current user suffix so it does not split tool transcripts.
|
|
91
|
+
- Tool results are tool messages containing `tool_result` content; the agent/session runtime uses this to feed dispatched tool results into the next provider turn, placing the assistant `tool_call` and the matching role `tool` `tool_result` before any final assistant content. Cache-aware layout keeps tool results before the current user suffix so it does not split tool transcripts. A result with no `value`, no `type:text` content, and no error carries the constant `EMPTY_TOOL_RESULT_TEXT` (`"(tool completed with no output)"`) as its `result`, so no provider route serializes an empty or absent tool payload.
|
|
92
92
|
- Middleware runs only when `middleware` is supplied in the context.
|
|
93
93
|
- `assembleProviderInput()` returns a `ProviderRequest` with the caller's model/tools/provider options/metadata/signal and composed messages/context. It stamps missing `sessionId`/`cacheKey` via `applyDefaultProviderRequestOptions` when `sessionId` is passed (agent sessions always pass `session.id`). It also calls `assertMessagesSupportModelCapabilities()` so unsupported `audio`/`file`/`document`/`image` blocks fail with `UnsupportedModalityError` when the model declares `capabilities.input`.
|
|
94
|
-
- Optional `contextBudget` (at least one of `maxInputTokens` / `maxInputBytes`) runs after default message groups are built and before final flatten. Eviction drops droppable sections first (toolResults → history → summaries → context → skills → attachments; layout-aware). Within `history`, oldest messages drop first. Protected instructions + current user `input` (+ tools catalog) fail closed with `ContextBudgetError` if they alone exceed the budget. When `reportOmissions: true`, attach `ProviderRequest.metadata[CONTEXT_BUDGET_REPORT_METADATA_KEY]` and read via `getContextBudgetReport(request)` (kinds/ids/sizes only — no secrets). Raw session store entries are never deleted.
|
|
94
|
+
- Optional `contextBudget` (at least one of `maxInputTokens` / `maxInputBytes`) runs after default message groups are built and before final flatten. `tokenEstimator` replaces the built-in ÷4 heuristic for **eviction accounting only** — it never reaches billing, provider usage, or the wire, byte caps (`maxInputBytes`) stay estimator-independent and are always enforced, and an estimator that returns a non-finite or negative count (or is not a function) fails the assembly closed with `TypeError` instead of making eviction decisions unsound. Eviction drops droppable sections first (toolResults → history → summaries → context → skills → attachments; layout-aware). Within `history`, oldest messages drop first. Protected instructions + current user `input` (+ tools catalog) fail closed with `ContextBudgetError` if they alone exceed the budget. When `reportOmissions: true`, attach `ProviderRequest.metadata[CONTEXT_BUDGET_REPORT_METADATA_KEY]` and read via `getContextBudgetReport(request)` (kinds/ids/sizes only — no secrets). Raw session store entries are never deleted.
|
|
95
95
|
- `renderPromptTemplate()` replaces top-level `{{name}}` variables with caller-supplied JSON-compatible values. Strings are inserted directly; numbers, booleans, `null`, arrays, and objects are stringified deterministically with sorted object keys. Missing variables throw by default or stay unchanged with `{ missing: "preserve" }`.
|
|
96
96
|
|
|
97
97
|
## Request/response example
|
|
@@ -167,7 +167,7 @@ try {
|
|
|
167
167
|
- Server `command`/`args` are host-config only — never taken from model tool arguments.
|
|
168
168
|
- File URIs must be `file:` and resolve inside `workspaceRoot`; escapes fail with `ERR_PRISM_LSP_WORKSPACE`.
|
|
169
169
|
- LSP payloads are untrusted: Content-Length framing is bounded; oversized/malformed frames fail closed; result lists and diagnostics are capped.
|
|
170
|
-
- Crash loop: unexpected exit increments a per-server restart counter; after the freeze budget (`LSP_RESTARTS_PER_SERVER` = 3) further starts fail with `ERR_PRISM_LSP_SERVER`.
|
|
170
|
+
- Crash loop: unexpected exit increments a per-server restart counter; after the freeze budget (`LSP_RESTARTS_PER_SERVER` = 3) further starts fail with `ERR_PRISM_LSP_SERVER`. A write that loses the server's pipe (the process died mid-write) is classified as that same `ERR_PRISM_LSP_SERVER` — a host never sees a raw `EPIPE`/`ECONNRESET`, and the loss still counts against the restart budget through the exit path.
|
|
171
171
|
- Defaults / hard caps (Phase 9 freeze): message 4 MiB / 32 MiB; diagnostics/file 200 / 1000; pending requests 32 / 128; results/query 500 / 5000; timeout 30 s / 120 s; servers/workspace 4 / 8.
|
|
172
172
|
|
|
173
173
|
## Related APIs
|
package/docs/migrate-to-0.5.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Migrate Prism 0.4 to 0.5
|
|
2
2
|
|
|
3
|
-
> **Status: 0.5.4** (run-limit HARD split from host policy
|
|
3
|
+
> **Status: 0.5.4 line** (run-limit HARD split from host policy). 0.5.0 covers plans 055–065. 0.5.1 adds kernel provider-request construction. 0.5.2 coalesces stream tokens. 0.5.3 folds content-only tool results. 0.5.4 splits run-limit HARD from host policy; 0.5.5 and 0.5.6 shipped as patches (per-frame byte limits, then trusted extension activation, wiki ingest, and graft commands). The planned 0.5.7 remediation was never published — it ships in 0.6.0, whose guide is [migrate-to-0.6.md](migrate-to-0.6.md).
|
|
4
4
|
|
|
5
5
|
## What changes
|
|
6
6
|
|
|
@@ -136,6 +136,10 @@ What to do:
|
|
|
136
136
|
- **Durable state:** runs with `maxWallTimeMs: null` persist checkpoints without `deadlineAt`; older checkpoints with a deadline still resume under it.
|
|
137
137
|
- **Documented ceiling:** vendors that omit usage charge zero to token counters; a configured `maxCost` stays the fail-closed envelope (missing/mixed-currency cost breaches immediately).
|
|
138
138
|
|
|
139
|
+
## 10. Later lines
|
|
140
|
+
|
|
141
|
+
The 0.5.x line ends here: the never-published 0.5.7 remediation and the 0.6.0 Node `>=22` floor are documented in [migrate-to-0.6.md](migrate-to-0.6.md), which also carries the folded 0.5.7 deltas (durable concurrent tool rounds, content-less tool results, host-tunable knobs, third-party peer floors, and the removed `@arnilo/prism-office` `playwright-core` peer).
|
|
142
|
+
|
|
139
143
|
## Upgrade steps
|
|
140
144
|
|
|
141
145
|
1. Bump every `@arnilo/*` dependency/peer to `^0.5.1` (0.5.0 hosts: `^0.5.0` still works until you want construction).
|
|
@@ -146,9 +150,10 @@ What to do:
|
|
|
146
150
|
6. If you set thinking levels: prefer `AgentConfig.thinkingLevel` / `RunOptions.thinkingLevel` (section 8); `applyThinkingLevelForModel` remains for custom generate sites (section 7).
|
|
147
151
|
7. Run your suite. No persisted-data migration exists or is needed.
|
|
148
152
|
8. After 0.5.1: drop host-only `createSessionCachePolicy` if it existed only for OpenCode Go / session headers (section 8).
|
|
153
|
+
9. Beyond 0.5: the never-published 0.5.7 content and the Node 22 floor ship in 0.6.0 — use [migrate-to-0.6.md](migrate-to-0.6.md).
|
|
149
154
|
|
|
150
155
|
## Rollback
|
|
151
156
|
|
|
152
|
-
Pin the previous version: `@arnilo/prism@0.4.x` (exact pins per package). Nothing persisted
|
|
157
|
+
Pin the previous version: `@arnilo/prism@0.4.x` (exact pins per package; the last published 0.5.x is 0.5.6). Nothing persisted
|
|
153
158
|
changes under 0.5, so a pin rollback is safe. The MCP module move (section 5) is the only
|
|
154
159
|
migration that touches host import code — keep a 0.4 pin if you need the monolithic SDK.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Migrate Prism 0.5 to 0.6
|
|
2
|
+
|
|
3
|
+
> **Status: 0.6.0** (Node `>=22`, the folded 0.5.7 content, self-describing coverage failures, release-truth gates). 0.6.0 is the first published release after 0.5.6 — the 0.5.7 cut was never published, so everything below is the single 0.5.6 → 0.6.0 delta.
|
|
4
|
+
|
|
5
|
+
## What changes
|
|
6
|
+
|
|
7
|
+
Prism 0.6 is a **lockstep cut**: all 10 publishable manifests move `0.5.6` → `0.6.0` and internal first-party ranges move `^0.5.6` → `^0.6.0`. Package names and import subpaths from 0.5 stay valid, no persisted shape changed, and no public signature was removed. The host-visible delta is:
|
|
8
|
+
|
|
9
|
+
1. the runtime floor: **Node `>=22`** (§1, breaking for a Node 20 host);
|
|
10
|
+
2. third-party version floors and one **removed peer** (§2, §3) — the install-visible part of the never-published 0.5.7;
|
|
11
|
+
3. additive tuning knobs for context assembly, session snapshots, memory-session search, SSRF policy, and browser run lifetime (§4);
|
|
12
|
+
4. behavior fixes that need no host action (§5) and release/CI gates that change no runtime contract (§6).
|
|
13
|
+
|
|
14
|
+
## 1. Runtime floor: Node `>=22` (breaking for Node 20 hosts)
|
|
15
|
+
|
|
16
|
+
Every publishable package declares `"engines": { "node": ">=22" }`, and a Node 20 host gets an `EBADENGINE` warning from npm (a hard failure under `engine-strict`) plus an unsupported runtime. Node 20 reached upstream end-of-life on 2026-04-30, so the 0.6 line moves to Node 22 (maintenance LTS to 2027-04-30) while Node 24 stays the CI default (active LTS to 2028-04-30).
|
|
17
|
+
|
|
18
|
+
What a 0.5.x host must check before upgrading:
|
|
19
|
+
|
|
20
|
+
- **Host and container images.** Move the host process to Node 22.6+ — the docs/test harness strips TypeScript natively from 22.6 — or to Node 24. `docs/release-and-install.md` carries the support matrix.
|
|
21
|
+
- **CI legs.** The release workflow's compatibility leg is renamed `node20-compat` → `node22-compat` and runs `node-version: "22"`; branch-protection required-check lists that name the old job id must be updated.
|
|
22
|
+
- **Development types.** `@types/node` (dev) moves `^20.19.0` → `^22.20.0` in the root and `@arnilo/prism-coding-tools`, tracking the declared floor. Hosts building Prism from source should not pin their own `@types/node` below 22 while the floor is `>=22`.
|
|
23
|
+
- **No code migration.** No import path, store schema, event shape, or public signature changed for this; the floor is the whole delta (`scripts/phase12-freeze-manifest.json` deviation `dev-006`).
|
|
24
|
+
|
|
25
|
+
## 2. Third-party floors (folded 0.5.7 content)
|
|
26
|
+
|
|
27
|
+
Ranges moved in the cut that never shipped; hosts that pin these themselves must move with them.
|
|
28
|
+
|
|
29
|
+
- `pg` **`^8.22.0` → `^8.23.0`** — driver dependency of `@arnilo/prism-core/sessions/postgres` and `@arnilo/prism-memory`, and core's optional peer. A host on 8.22 sees a peer warning until it upgrades.
|
|
30
|
+
- `playwright-core` optional exact peer **`1.61.0` → `1.63.0`** in `@arnilo/prism-web-tools` (`/browser`, `/obscura`). The exact pin is deliberate — browser control is version-sensitive, and the host still owns the browser binary/image.
|
|
31
|
+
- `@ai-sdk/provider` exact peer **`4.0.10` → `4.0.13`** in `@arnilo/prism-providers/ai-sdk`. The supported-version matrix gained a `4.0.13` row; `4.0.3`, `4.0.4`, and `4.0.10` stay listed. Unlisted versions still fail closed with `AiSdkProviderError { code: "unsupported_version" }`.
|
|
32
|
+
- `@nanonets/graft` optional peer **`^0.16.0` → `^0.16.0 || ^0.18.0`** in `@arnilo/prism-memory/graft` (upstream published no 0.17; both listed floors pass the offline peer-contract smoke).
|
|
33
|
+
- `@agentclientprotocol/sdk` exact pin **`1.3.0` → `1.4.0`** in `@arnilo/prism-ag-ui/acp` and `@arnilo/prism-acp-agent`. The wire protocol stays v1 (`PROTOCOL_VERSION === 1`); 1.4.0 stabilizes elicitation (the SDK's `unstable_*` helpers become `createElicitation`/`completeElicitation`, wire method names unchanged — Prism never called the unstable helpers) and adds `compaction` session-update kinds, which Prism does not advertise or map.
|
|
34
|
+
- `@office-open/*` **`0.13.1` → `0.14.5`** in `@arnilo/prism-office`. Upstream made `parseDocument`/`parsePresentation`/`parseWorkbook` async; Prism's adapters call the new synchronous `parse*Sync` variants, so no Prism signature changed — but the office package requires the 0.14.5 line.
|
|
35
|
+
- `zod` **`^4.4.3` → `^4.6.2`** in `@arnilo/prism-mcp` (AG-UI's `^3.25.0 || ^4.0.0` peer range is unchanged and still admits it).
|
|
36
|
+
- `@biomejs/biome` dev **`2.5.11` → `2.5.13`** (lint/format only; 0 findings on the repo).
|
|
37
|
+
|
|
38
|
+
## 3. `@arnilo/prism-office` is peer-free
|
|
39
|
+
|
|
40
|
+
The optional `playwright-core` peer is **removed**. No office subpath ever imported it at runtime — `/diagrams` drives a host-supplied iframe — so the only Browser consumer was a gated live draw.io test, now behind a devDependency. Hosts that added the install for office can drop it; office installs and imports without a browser.
|
|
41
|
+
|
|
42
|
+
## 4. Additive host knobs
|
|
43
|
+
|
|
44
|
+
All optional, all defaulting to the previous behavior:
|
|
45
|
+
|
|
46
|
+
- **Context assembly:** `AssembleProviderInputOptions.tokenEstimator?: (text: string) => number` replaces the built-in UTF-16/4 heuristic for eviction accounting. Hard byte caps stay estimator-independent.
|
|
47
|
+
- **Session snapshot cache:** `AgentSessionConfig.snapshotCacheTtlMs` — default `DEFAULT_SNAPSHOT_CACHE_TTL_MS` (1000), cap `HARD_MAX_SNAPSHOT_CACHE_TTL_MS` (30000), `0` disables the branch-rebuild cache.
|
|
48
|
+
- **Memory-session search:** `createMemorySessionStore(entries, { search: { maxLinearSessions, maxLinearEntries, maxLinearBytes } })`, validated against the same fail-closed bounds as the defaults.
|
|
49
|
+
- **SSRF policy:** `SsrfPolicy.allowedCidrs` takes IPv4/IPv6 CIDR entries for hosts that must reach a private range. Hostname denials (metadata endpoints), credential and redirect checks are unchanged, and an unparseable CIDR still fails closed.
|
|
50
|
+
- **Browser run lifetime:** `BrowserLimitOptions.idleRunTtlMs` (default `0` = never reap, cap `HARD_IDLE_RUN_TTL_MS` 30 min) closes a run with nothing queued after the TTL; any interaction resets the clock, and `manager.closeRun(runId)` stays the explicit close.
|
|
51
|
+
|
|
52
|
+
## 5. Behavior fixes (no host action)
|
|
53
|
+
|
|
54
|
+
- **Durable concurrent tool rounds.** With `toolConcurrency > 1`, a failed or aborted call used to throw before the round's results were appended, dropping the successful siblings — the next provider request then carried `tool_use` blocks with no `tool_result`. Successful results and synthetic errors (`tool_execution_failed` for the failing call, `tool_call_not_dispatched` for calls that never started) are now persisted before the round fails or aborts. Run-level control errors (`ERR_PRISM_AGENT_RUN_SUSPENDED`, `ERR_PRISM_DELEGATION_SUSPENDED`, `ERR_PRISM_LOOP_*`) intentionally skip synthetic results: durable recovery re-dispatches them.
|
|
55
|
+
- **Content-less tool results.** A `ToolResult` without `content`/`result` folds to `(tool completed with no output)` (`EMPTY_TOOL_RESULT_TEXT`) instead of an empty payload, so strict OpenAI-compatible providers accept the request.
|
|
56
|
+
- **Memory patch merge.** `packages/memory`'s `mergeJsonObjects` now delegates to core `mergeConfigLayers` (deep copy, strict JSON validation — `undefined`/`Date`/function values fail closed — with the `MemoryValidationError` taxonomy preserved) instead of aliasing the caller's objects.
|
|
57
|
+
- **`redactSecrets` cost.** A guarded single-pass alternation fast path handles large inputs (≥16 KiB, 2–32 non-overlapping needles) with byte-identical output (~13× faster on 1 MiB transcripts); the ordered loop stays the fallback.
|
|
58
|
+
- **Peer manifest resolution.** Upstream resolvers handle packages that do not export `./package.json` (e.g. `@dietrichgebert/ponytail`) by resolving the entry point and walking up to the manifest.
|
|
59
|
+
|
|
60
|
+
## 6. Test, coverage, and release-gate changes (no runtime contract)
|
|
61
|
+
|
|
62
|
+
- **`npm test` never short-circuits.** Every stage runs through `scripts/run-all-tests.mjs`, which prints one summary, so a failing stage cannot hide later failures.
|
|
63
|
+
- **Coverage truth.** Discovery finds nested `dist/**/__tests__` in all 9 workspace packages, `coverage-thresholds.json` may no longer name retired packages, and a failing coverage child is self-describing: the summary prints the child's redacted output tail and the artifact row records `status`/`exitCode`/`tail`.
|
|
64
|
+
- **Version-literal gate.** `scripts/version-literal-gate.test.mjs` asserts every release-claim surface (10 manifests, internal ranges, `package-lock.json`, the `src/index.ts` version constant, the `docs/index.md` current line, `release.yml` tag lists, `scripts/package-truth.json`) equals the root manifest version, so a half-finished cut fails the suite instead of shipping.
|
|
65
|
+
- **Workflow liveness.** `scripts/workflow-liveness.test.mjs` resolves every `-w`/`--workspace` target, named npm script, and `uses:` reference in `.github/workflows/*.yml` against the workspace inventory and requires full 40-hex SHA pins for actions.
|
|
66
|
+
- **Startup budget under load.** The root import budget asserts a machine-relative ratio (trimmed mean of imports ÷ process-start cost) and only applies the absolute 250 ms ceiling when the machine is off-load, so a busy CI runner no longer reports a false regression.
|
|
67
|
+
- **Internal ranges at the cut version exactly.** `release.mjs` lockstep mode requires every `@arnilo/*` range to be the cut version (exact `0.6.0` or caret `^0.6.0`); a range that merely *satisfies* it fails closed, because it lets two installs of one release line resolve different first-party minors.
|
|
68
|
+
- **Protected legs fail closed with one convention.** `scripts/blocked-gate.mjs` gives every environment-blocked gate the same shape and message, and `scripts/release-skip-manifest.mjs` records env var **names** only (never values) in the release evidence.
|
|
69
|
+
|
|
70
|
+
## Upgrade steps
|
|
71
|
+
|
|
72
|
+
1. Move the host process, containers, and CI legs to Node 22+ (§1) and bump `@types/node` to 22 if you build from source.
|
|
73
|
+
2. Bump every `@arnilo/*` dependency and peer to `^0.6.0` (0.5.x hosts: `^0.5.6` still resolves until you want the new knobs).
|
|
74
|
+
3. Move the third-party ranges your host pins itself (§2).
|
|
75
|
+
4. Remove `playwright-core` from an office install if you added it for `/diagrams` (§3).
|
|
76
|
+
5. Adopt the optional knobs where they matter (§4).
|
|
77
|
+
6. Build and run your suite. No persisted-data migration exists or is needed.
|
|
78
|
+
|
|
79
|
+
## Rollback
|
|
80
|
+
|
|
81
|
+
Pin the previous published line: `@arnilo/prism@0.5.6` (exact pins per package). Nothing persisted under 0.5 or 0.6 changes, so a pin rollback is safe; the Node floor, peer ranges, and host knobs listed here are the only deltas a 0.6 host would lose.
|
|
82
|
+
|
|
83
|
+
## Related APIs
|
|
84
|
+
|
|
85
|
+
- [Migration guide](migration.md): the era index of migration cuts with replacement tables and rollback notes.
|
|
86
|
+
- [Migrate Prism 0.4 to 0.5](migrate-to-0.5.md): the previous line's guide (plans 055–067).
|
|
87
|
+
- [Release and install](release-and-install.md): packed surfaces, install rules, support matrix, and the offline test budget.
|
|
88
|
+
- [Peer dependencies](peer-dependencies.md): every third-party peer declaration with range, optionality, subpath, and install line.
|
|
89
|
+
- [CHANGELOG](../CHANGELOG.md): the per-release record, including the folded 0.5.7 content.
|
package/docs/migration.md
CHANGED
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# Migration guide
|
|
2
2
|
|
|
3
|
+
## 0.5.6 → 0.6.0 (Node 22 floor; folds the never-published 0.5.7)
|
|
4
|
+
|
|
5
|
+
**Prism 0.6.0 requires Node `>=22`.** Every publishable package declares `"engines": { "node": ">=22" }`; a Node 20 host gets an `EBADENGINE` warning from npm (a hard failure under `engine-strict`) and an unsupported runtime. Node 20 reached upstream end-of-life on 2026-04-30, so the 0.6.0 line moves to Node 22 (maintenance LTS to 2027-04-30) while Node 24 stays the CI default (active LTS to 2028-04-30). The full 0.5.6 → 0.6.0 guide — third-party floors, the removed office peer, the additive host knobs, and upgrade/rollback steps — lives in [migrate-to-0.6.md](migrate-to-0.6.md).
|
|
6
|
+
|
|
7
|
+
What a 0.5.x host must check before upgrading:
|
|
8
|
+
|
|
9
|
+
- **Runtime.** Move the host process and any container image to Node 22.6+ (the docs/test harness strips TypeScript natively from 22.6; Node 22 LTS or later is the supported answer). `engines.node` is now `>=22`, so `npm install` fails closed on older runtimes with `engine-strict` enabled.
|
|
10
|
+
- **CI legs.** The release workflow's compatibility leg is renamed `node20-compat` → `node22-compat` and runs on `node-version: "22"`; branch-protection required-check lists that name the old job id must be updated.
|
|
11
|
+
- **Development types.** `@types/node` (dev) moves `^20.19.0` → `^22.20.0` in the root and `@arnilo/prism-coding-tools`, tracking the declared floor. Hosts building Prism from source should not pin their own `@types/node` below 22 while the floor is `>=22`.
|
|
12
|
+
- **No migration step for Prism itself.** No import path, store schema, event shape, or public signature changed for the floor; it is one of the two host-visible deltas in this cut (`scripts/phase12-freeze-manifest.json` deviation `dev-006`), the other being the third-party peer floors and the removed `@arnilo/prism-office` `playwright-core` peer listed in [migrate-to-0.6.md](migrate-to-0.6.md#3-arniloprim-office-is-peer-free).
|
|
13
|
+
|
|
14
|
+
### Folded 0.5.7 content (no import, store, or event-shape break)
|
|
15
|
+
|
|
16
|
+
The 0.5.7 cut was never published, so its content ships in 0.6.0. Third-party ranges moved; hosts that pin these themselves must move with them:
|
|
17
|
+
|
|
18
|
+
- `pg` **`^8.22.0` → `^8.23.0`** — driver dependency of `@arnilo/prism-core/sessions/postgres` and `@arnilo/prism-memory`, and its optional peer in core. Hosts on 8.22 see a peer warning until they upgrade.
|
|
19
|
+
- `playwright-core` optional exact peer **`1.61.0` → `1.63.0`** in `@arnilo/prism-web-tools` (the exact pin is deliberate — browser control is version-sensitive, and the host still owns the browser binary/image). `@arnilo/prism-office` **drops** its optional `playwright-core` peer: no office subpath ever imported it at runtime (the diagrams embed takes a host-supplied iframe), so it becomes a devDependency behind the gated live draw.io test. Hosts that installed it for office can remove it.
|
|
20
|
+
- `@ai-sdk/provider` exact peer **`4.0.10` → `4.0.13`** in `@arnilo/prism-providers/ai-sdk`. The supported-version matrix gained a `4.0.13` row; `4.0.3`, `4.0.4`, and `4.0.10` stay listed. Unlisted versions still fail closed with `AiSdkProviderError { code: "unsupported_version" }`.
|
|
21
|
+
- `@nanonets/graft` optional peer **`^0.16.0` → `^0.16.0 || ^0.18.0`** in `@arnilo/prism-memory/graft` (upstream published no 0.17; both listed floors pass the offline peer-contract smoke).
|
|
22
|
+
- `@agentclientprotocol/sdk` exact pin **`1.3.0` → `1.4.0`** in `@arnilo/prism-ag-ui/acp` and `@arnilo/prism-acp-agent`. Wire protocol stays v1 (`PROTOCOL_VERSION === 1`); 1.4.0 stabilizes elicitation (the SDK's `unstable_createElicitation`/`unstable_completeElicitation` helpers become `createElicitation`/`completeElicitation`, wire method names unchanged — Prism never called the unstable helpers) and adds `compaction` session-update kinds, which Prism does not advertise or map.
|
|
23
|
+
- `@office-open/*` **`0.13.1` → `0.14.5`** in `@arnilo/prism-office`. Upstream made `parseDocument`/`parsePresentation`/`parseWorkbook` async; Prism's synchronous document adapters now call the new `parse*Sync` variants, so no Prism signature changed — but the office package requires the 0.14.5 line.
|
|
24
|
+
- `zod` **`^4.4.3` → `^4.6.2`** in `@arnilo/prism-mcp` (AG-UI's `^3.25.0 || ^4.0.0` peer range is unchanged and still admits it).
|
|
25
|
+
- `@biomejs/biome` dev **`2.5.11` → `2.5.13`** (lint/format only; 0 findings on the repo).
|
|
26
|
+
|
|
27
|
+
Dev-tooling and release-gate changes in the same cut (no host action required):
|
|
28
|
+
|
|
29
|
+
- **`@types/node` dev `^26.1.1` → `^20.19.0` at the 0.5.7 cut, then `^22.20.0` here.** Development types track the declared runtime floor, so a Node-22+-only API fails the build instead of compiling clean against a newer type surface. `docs/release-and-install.md` records the policy: the types package tracks the floor, and raising the floor is a support-matrix change (freeze manifest + CI legs), not a dependency bump. The `^20.19.0` pin immediately caught four runnable examples using `import.meta.main` (Node ≥22.18/≥24.2) on a Node-20 floor — they now use the house `import.meta.url === \`file://${process.argv[1]}\`` guard, so they no longer silently no-op below Node 22.18.
|
|
30
|
+
- **Node 20 floor removed in 0.6.0.** The never-published 0.5.7 deliberately kept `engines.node >=20` because dropping a supported line is a host-breaking support-matrix change that does not belong in a patch release; the 0.6.0 minor is the right vehicle (Node 22 is maintenance LTS to 2027-04-30, Node 24 active LTS to 2028-04-30).
|
|
31
|
+
- **Internal first-party ranges are gated at the cut version exactly.** `release.mjs validateRelease` (lockstep mode, which `release.mjs gate --lockstep --version` and the publish path both use) requires every `@arnilo/*` range to be the cut version (exact `0.6.0` or caret `^0.6.0`). A range that merely *satisfies* it — `^0.5.5` alongside `^0.5.6`, which is what the pre-cut tree carried — now fails the gate closed, because it lets two installs of the same release line resolve different first-party minors.
|
|
32
|
+
|
|
3
33
|
## 0.5.3 → 0.5.4 (export-shape break in `@arnilo/prism`)
|
|
4
34
|
|
|
5
35
|
|