## [0.10.0] - 2026-09-21 (hook lifecycle completion, scoped agent memory)

> **Twelve publishable packages.** All 105–106 features ship behind their documented options and defaults: `@arnilo/prism-hooks` is the new twelfth package, and scoped memory is an opt-in subpath that does nothing until a host constructs it. Predecessor published line is **0.9.0**. Plans 097 (trajectory export) and 107 (behavior/graft removals) were not implemented for this line and are deferred rather than held unstarted against the cut. Registry/tag writes stay operator-authorized.

### Added
- **Scoped persistent memory (`@arnilo/prism-memory/scoped`).** New opt-in subpath: `createScopedMemoryPolicy({ memory, fabric, scopeRoot, policy })` is a policy and lifecycle layer over stores the host already configured (no fifth store). Create is inert and fails closed unless `scope.resourceId` equals the resolved `scopeRoot` and a `threadId` is set; the read path oversamples `fabric.recall`, applies an abstain floor (`activation.minSimilarity` 0.35) and activation budget (`topK` 3), ranks by `fabricScore × exp(−ageDays/tauDays) × (1 + ln(1 + uses))` (`tauDays` 30), and returns `{ hits: [], abstained: true }` rather than a weak hit. Writes go through a conservative post-run reviewer (`reviewSession`, strict JSON, garbage → zero writes), land as `candidate` records, and flip to `verified` after `promotion.reuseThreshold` (2) successful recalls — ledger status only, no fabric rewrite. `gcPass()` proposes archives onto `pending()` and never deletes (`legal_hold` skipped), `rememberFact` keeps a bounded working block (`maxChars` 2200, overflow throws `MemoryLimitError` with `consolidate first`), an injection scan plus an optional staged approval gate (`approval.default: "off"`) guard content, and a deterministic git audit mirror renders notes. State lives in one JSON ledger at `<scopeRoot>/.memory/state.json` (ids, counters, timestamps — never note content). Sizing: one reviewer call per run, one ledger read plus one write per recall, no model calls on the read path. See [docs/scoped-memory.md](docs/scoped-memory.md).
- **Scoped memory evaluation and health.** `runScopedMemoryEval` runs a win-rate A/B (with/without scoped memory) over a host-provided task set, `probePrecisionAt3` and `probeLocomoRecall` score the read path, `scopedMemoryHealth` reports counts plus conversion/activation/duplication rates, and `createScopedMemoryHealthCommand` exposes the same numbers as a command. See [docs/scoped-memory.md](docs/scoped-memory.md).
- **Stop hooks with bounded continuation.** `AgentConfig.stopHooks` / `RunOptions.stopHooks` run at the natural end of an agent loop with a `StopHookContext` (session and run ids, turn, redacted history, `stopHookActive`) and answer `{ action: "stop" }` or `{ action: "continue", reason }`; a continuation re-enters the loop with the reason queued as the next turn's steer — run-start input is never replayed — and `RunLimits.maxStopContinuations` (default 3, `0` disables, `null` uncaps) ends the run cleanly with the new `hook_limit` finish reason, which `checkpointPolicy: "every-turn"` leaves resumable. Extensions register hooks with `ExtensionAPI.registerStopHook()`. See [docs/hooks.md](docs/hooks.md).
- **Agent-event bridge and session lifecycle hooks.** `forwardAgentEvents(source, events, options?)` keeps the extension bus in step with a run (`agent_started` → `before_agent_start`, `turn_started` / `turn_finished` → `turn`, `tool_execution_started` → `tool_call`, `tool_execution_finished` → `tool_result`), delivering in event order with the original event as the read-only payload and never rethrowing into the run; core emits `session_start` once per session (durable resumes included) and `session_shutdown` on the new idempotent `AgentSession.close()`. See [docs/extensions.md](docs/extensions.md), [docs/middleware-hooks.md](docs/middleware-hooks.md).
- **Pre-compaction rewrite seam.** The `compaction_request` middleware hook runs after `compaction_started` and before the strategy, so a handler returns the `CompactionContext` the strategy actually compacts (entries and budget) and the following `compaction` hook plus `compaction_finished` event report that result. See [docs/middleware-hooks.md](docs/middleware-hooks.md).
- **`@arnilo/prism-hooks`, the hooks-file adapter.** New twelfth publishable package: `parseHooksConfig(text | object)` accepts the Claude flat and Codex `{ "hooks": { … } }` shapes, and `createHooksExtension(config, options)` compiles them onto public seams — `SessionStart` / `UserPromptSubmit` `additionalContext` through an instruction injector, `UserPromptSubmit` / `PreToolUse` / `PostToolUse` guardrails for denies, `tool_call` / `tool_result` middleware for `updatedInput` and post-tool context, and `Stop` onto stop hooks. Handlers are `command` (spawned shell-free, hash-pinned with `hookCommandHash()`) or `mcp_tool` (host-provided client, `${field.path}` templates), with seconds-based `timeout`, per-handler `additionalContextLimit` (default 2500 tokens, spilling to `<tempdir>/hook_outputs/`), and Codex's `continue: false` read as the stop signal. See [docs/hooks.md](docs/hooks.md).
- **Unified hook map.** [docs/hooks.md](docs/hooks.md) is the owning page for the hook model: the five families (transform, decide, inject, run-end control, observe), one row per Claude Code / Codex event mapped to its Prism surface or a documented non-goal with rationale (`PermissionRequest` stays host policy), the adapter reference, and migration steps from an existing `hooks.json` config.
- **Examples.** `examples/scoped-memory.ts` (scope guard → facts overflow → reviewer → abstain/hit recall → promotion → GC approval → mirror), `examples/hooks-json.ts` (a declarative `hooks.json` compiled onto guardrails, injectors, and stop hooks), and `examples/hooks-audit-command.mjs` (an audit-trail command handler).

### Changed
- **Lockstep `0.9.0` → `0.10.0`.** All twelve publishable manifests move together with `^0.10.0` internal ranges; the lockfile, the `src/index.ts` version constant, the docs index banner, the release-workflow tag lists, and the generated package-truth artifact agree (enforced by `scripts/version-literal-gate.test.mjs`).
- **Compat baselines regenerated at 0.10.0**: `+47` public names with **zero removals**, zero renames, and zero signature breaks (`@arnilo/prism` +6, `@arnilo/prism-memory` +41, `@arnilo/prism-hooks` new at 34). The only consumer-visible type addition is `AgentSession.close()`; see [docs/migration.md](docs/migration.md).
- **Budgets rebaselined with recorded reasons**: export ceilings `@arnilo/prism` 1456, `@arnilo/prism-memory` 934, `@arnilo/prism-hooks` 34, plus the non-null assertion ratchet; the root artifact diet is unchanged this cut.
- **Coverage thresholds gained the new package's row** (`@arnilo/prism-hooks` 84.7 / 78.67 / 90), so the coverage summary fails closed on a new package instead of passing silently.
- **Migration notes for 0.9.0 hosts**: [docs/migration.md](docs/migration.md) — the `AgentSession.close()` addition, `session_start` / `session_shutdown` now being emitted, the new `hook_limit` finish reason, the `maxStopContinuations` default, and the opt-in scoped-memory subpath.

### Security
- **Stop hooks and the hooks-file adapter fail closed.** `StopHook` entries are validated at run start (`name` plus `decide`), a malformed decision or a throwing handler is a non-blocking error that never silently allows a stop, `maxStopContinuations` (default 3) bounds continuation loops, and the adapter's `command` handlers spawn shell-free with tokenized argv and a `hookCommandHash()` trust pin. Codex's `continue: false` reads as the stop signal, not a continuation.
- **Scoped memory never widens access and never deletes.** Create fails closed on a scope mismatch, unknown policy fields are ignored and invalid values fail closed, recall abstains below the floor, GC only proposes, `legal_hold` is skipped, the ledger stores no note content, and the mirror is deterministic.

## [0.9.0] - 2026-09-20 (attention budget axes, turn traces, cache-stable disclosure, tool narrowing, guardrail packs, background agents, session search, deterministic turns, shared scopes)

> **Eleven publishable packages.** All 086–098 features ship behind their documented options, joined by the live-stream terminal fix (plan 100). Predecessor published line is **0.8.0**. Registry/tag writes stay operator-authorized.

### Added
- **Attention budget axes and durable folding.** `attentionCompiler.trigger` accepts `input_ratio` (the legacy axis), `run_input_ratio` (fires against `RunLimits.maxInputTokens` instead of the model window), `token_floor`, and a host predicate, alone or as an any-of array; `attentionCompiler.durable: true` writes the fold ledger and sticky frontier into the checkpoint so a resumed run keeps its stubs. See [docs/attention-compiler.md](docs/attention-compiler.md).
- **Turn traces and exhaustion attribution.** `provider_turn_finished` carries a closed `stopReason` taxonomy, a `budgets` snapshot, the effective tool menu (`tools.count` / `tools.idsHash`), and provider-reported cache counts with a per-turn `hitRate`; `agent_finished` carries `finishReason` / `stopDetail`, `AgentRunResult.stopReason` names host-policy and loop-ceiling stops, and the execution timeline adds `turns[i].stopReason` plus `timeline.exhaustion`. See [docs/agent-events.md](docs/agent-events.md), [docs/execution-timeline.md](docs/execution-timeline.md).
- **Cache-stable progressive disclosure and cache metrics.** Skill bodies, deferred tool schemas, and loaded references land at cache-stable positions (append-only tail or explicit invalidation); cache read/write tokens and per-turn hit rate are recorded on usage records and turn events. See [docs/provider-caching.md](docs/provider-caching.md), [docs/prefix-stability-conformance.md](docs/prefix-stability-conformance.md).
- **Per-turn tool narrowing.** `AgentConfig.toolNarrowing` / `RunOptions.toolNarrowing` returns the effective tool subset before each provider turn; out-of-grant names are dropped and reported on `tool_narrowing_clamped`. See [docs/tools.md](docs/tools.md).
- **Usage estimation and the context meter.** `estimateMessageTokens` / `MODEL_FAMILY_TOKENS` / `resolveModelFamily` produce labeled `TokenEstimate`s, `AgentConfig.usageEstimation: "fallback"` (default) charges one labeled estimate for usage-less providers, and `session.contextMeter()` exposes `{ inputTokens, source, inputCap?, runInputBudget?, usedRatio? }`. See [docs/runs-and-usage.md](docs/runs-and-usage.md).
- **Execution guardrail packs.** `guardrailPacks` compiles four built-in restrictive rule sets (`coding-standard`, `destructive-commands`, `validation-respect`, `secrets-hygiene`) onto existing tool stages, each with a trajectory scorer (`createGuardrailPackScorer`). See [docs/guardrails.md](docs/guardrails.md).
- **Background child agents and child-event passthrough.** `lifetime: "session"`, `report: "on-complete" | "milestones" | "stream"`, `milestone`, and `budgetShare` on `delegate` / `delegateAsync` / `spawn_agent`, with `child_milestone`, `child_failed`, and rate-coalesced child events. See [docs/supervisors.md](docs/supervisors.md), [docs/multi-agent-patterns.md](docs/multi-agent-patterns.md).
- **Checkpoint sidecar metadata and restore hooks.** A redacted ≤4 KB `checkpointMetadata` map rides every checkpoint record without charging `maxStateBytes`, and `restoreHooks` revert external layers before a resume claims the run. See [docs/durable-runs.md](docs/durable-runs.md).
- **Bounded workspace session search.** `SessionStore.searchSessions?(query)` over workspace/time/provider/label/kind/ownership filters with an indexed full-text path (SQLite FTS5, Postgres `tsvector`, migration 004) and a shared linear matcher for memory and JSONL stores. See [docs/session-stores.md](docs/session-stores.md).
- **Deterministic no-model turns.** The `beforeProviderTurn` middleware hook answers a turn from host data (`BeforeProviderTurnPayload` → `DeterministicTurnAnswer`) with no provider request, recorded as `deterministic` on the timeline and graded by `createDeterministicTurnScorer`. See [docs/middleware-hooks.md](docs/middleware-hooks.md).
- **Shared work scopes for observational memory.** `sharedScopes` at attach time plus owner-branch grants (`grant` / `revoke`) let granted sessions contribute to and read one scope, with deny-by-default rechecks, `onScopeAccess` auditing, and revocation at the next read. See [docs/compaction-observational-memory.md](docs/compaction-observational-memory.md).
- **Retrieval revocation and a zero-service default reranker.** `createDeletionPropagator` (+ `collectInvalidationIds` / `listInvalidatedIds`, `repointSource`, `retireWikiSources`, RAG/wiki handlers) propagates deletion and revocation through derived artifacts, `createAccessRecheck` rechecks governed sources per query, and `resolveReranker({ kind: "local" })` / `createLocalReranker()` run an in-process cross-encoder behind the `LocalRerankRuntime` seam with no declared inference dependency. See [docs/rag.md](docs/rag.md), [docs/embeddings.md](docs/embeddings.md).
- **Examples.** `examples/attention-budget-axes.ts`, `examples/tool-narrowing-planes.ts`, `examples/session-search.ts`.

### Changed
- **Lockstep `0.8.0` → `0.9.0`.** All eleven publishable manifests move together with `^0.9.0` internal ranges; the lockfile, the `src/index.ts` version constant, the docs index banner, the release-workflow tag lists, and the generated package-truth artifact agree (enforced by `scripts/version-literal-gate.test.mjs`).
- **A limit death no longer ends a stream early.** The terminal set is exactly `agent_finished` / `agent_denied` / `error`, decided by one exported `isTerminalAgentEventType` predicate shared by the memory, NATS, and Postgres sources, AG-UI replay, the A2A stream break, AG-UI `filterRun`, and conversation replay; `run_limit_exceeded` → `budget_exhausted` → `error` now reaches page, subscribe, and replay consumers in order. See [docs/migrate-to-0.9.md](docs/migrate-to-0.9.md).
- **Usage-less providers are charged a labeled estimate by default.** `AgentConfig.usageEstimation: "fallback"` records one `TokenEstimate` (`estimated: true` + `confidence`) at the existing usage seam; reported usage always wins, and `"off"` keeps the previous zero-for-no-usage behavior.
- **Compat baselines regenerated at 0.9.0**: `+119` public names with **zero removals** and zero renames (`@arnilo/prism` +49, `@arnilo/prism-memory` +60, `@arnilo/prism-core` +10). One type-level consumer change: the `recordUsage` callback of `generateProviderTurn` / `generateWithRetry` returns `Promise<Usage | undefined>` instead of `Promise<void>`.
- **Budgets rebaselined with recorded reasons**: root packed/unpacked/file count, per-package export ceilings, and the non-null assertion ratchet carry the measured 0.9.0 values and the plans that moved them.
- **Migration guide for 0.8.0 hosts**: [docs/migrate-to-0.9.md](docs/migrate-to-0.9.md) — four behavior changes inside existing surfaces, every new option with defaults and sizing lines, upgrade steps, and rollback — indexed from [docs/migration.md](docs/migration.md) and [docs/index.md](docs/index.md).

### Fixed
- **Streams ended one record early on a run-limit death.** In-memory, NATS, Postgres, and AG-UI replay consumers treated `run_limit_exceeded` as terminal, so a subscriber that stopped at the first breach record never saw the `budget_exhausted` attribution or the terminal `error` (`assertAgentEventSourceConforms` now asserts the delivery order against every source implementation).
- **Attention folding was inert when the run input cap sat below the model window.** The new `run_input_ratio` axis evaluates cumulative run spend plus the assembled request, so a 500k run cap under a 1M-window model folds instead of dying at the cap.
- **Unindexed session search could scan an unbounded store.** Memory and JSONL stores share `searchLinearSessions` with contract linear caps, overridable only within their hard bounds.

### Security
- **Guardrail packs fail closed on secrets and destructive commands.** `secrets-hygiene` scans tool arguments for credential shapes, `destructive-commands` matches shell commands, and `coding-standard` keeps edits inside `options.roots`; every pack is restrictive-only, so a pack can never widen a host policy. Cap: 8 packs, 64 rules per pack.
- **Shared-scope access is deny-by-default and audited.** Absent, unknown, revoked, unreachable, or not-opened-locally scope state denies the read, every decision reaches `onScopeAccess`, revocation lands on the next read, and the host `entries(sessionId)` callback stays inside one `OwnershipScope`.
- **Checkpoint metadata and restore hooks are redacted and bounded.** The sidecar map is redacted unconditionally (no public-key exemption) and capped at 4 KiB; a failing or timed-out restore hook aborts the restore rather than claiming the run.
- **Estimates can never masquerade as provider truth.** Every estimated token count carries `estimated: true` (and `confidence`), reported usage is never overwritten, and estimates never produce a price — a configured `maxCost` stays the fail-closed envelope.

## [0.8.0] - 2026-09-18 (messaging channels, connected apps, work family, durable runs, honesty gates)

> **Eleven publishable packages.** `@arnilo/prism-channels` is new; `@arnilo/prism-work` replaces `@arnilo/prism-office`. Predecessor published line is **0.7.0**. Registry/tag writes stay operator-authorized.

### Added
- **Messaging channels.** `@arnilo/prism-channels` ships the transport-neutral runtime (deny-by-default sender authorization, owned session binding, serialized turns, current-run replies, one-use durable approvals, bounded attachment refs), official Telegram (private DMs, opt-in granted groups/topics, private-chat drafts, bounded media, optional voice transcription/synthesis, opt-in notices to one already-bound pair), and experimental pinned signal-cli Signal. See [docs/messaging-channels.md](docs/messaging-channels.md), [docs/telegram-channel.md](docs/telegram-channel.md), [docs/signal-channel.md](docs/signal-channel.md), [docs/messaging-channel-operations.md](docs/messaging-channel-operations.md).
- **Connected apps and work HTTP.** Identity-bound MCP connected-app sessions admit host-selected transports and register prefixed tools. Google Workspace and Microsoft 365 HTTP adapters live under `@arnilo/prism-work/connectors`. Slack MCP wrap and Open Connector sidecar stay examples. See [docs/connected-apps.md](docs/connected-apps.md), [docs/work-connectors.md](docs/work-connectors.md).
- **Durable runs, turn-boundary stops, and run-bundle snapshots.** `AgentRunStateOptions.checkpointPolicy: "every-turn"` checkpoints a run at the provider-turn boundary so a crashed worker resumes with the host-only `decision: "continue"` action (never reachable from AG-UI or the server boundary, and rejected while any approval or ready tool call is pending). `RunOptions.turnPolicy` (`TurnPolicyOptions`) stops a run synchronously at a turn boundary and reports `stopReason: "host_policy"` with a redacted, bounded `stopDetail` on the result, the ledger row, the `agent_finished` event, and the execution timeline; a host-policy stop stays resumable. `snapshotRunBundle` returns a `RunBundleSnapshot` — a frozen, redacted digest projection of the effective run bundle with zero store or network reads. `createClaimGroundingGuardrail` (stage `"output"`) blocks or flags numeric claims that no tool result or host evidence supports. `ErrorInfo.failureClass` (`ProviderFailureClass`) types provider failures as `quota` / `rate_limited` / `auth` / `transient` / `permanent` / `unknown`; `ModelCapabilities.toolCallStrictness` adds advisory tool-call reliability. See [docs/durable-runs.md](docs/durable-runs.md), [docs/run-bundle.md](docs/run-bundle.md), [docs/guardrails.md](docs/guardrails.md).
- **Work sandbox and vendored skills.** `@arnilo/prism-work/sandbox` plus `createWorkComposition` run office/exec in an injected Docker sandbox; connectors stay on the host. The package ships `docx`, `xlsx`, `powerpoint`, `pdf` skills.

### Changed
- **Lockstep `0.7.0` → `0.8.0`.** All eleven publishable manifests move together with `^0.8.0` internal ranges; the lockfile, the `src/index.ts` version constant, the docs index banner, the release-workflow tag lists, and the generated package-truth artifact agree (enforced by `scripts/version-literal-gate.test.mjs`).
- **Work family rename.** `@arnilo/prism-office` is replaced by `@arnilo/prism-work` (connectors, documents, sheets, diagrams, document-reader, sandbox, skills, tools). No pre-1.0 shim. See [docs/migrate-to-0.8.md](docs/migrate-to-0.8.md).
- **AG-UI input authority is opt-in server-side.** `CreateAgUiHandlerOptions.inputPolicy.clientState: "ignore"` validates then discards client-supplied AG-UI state and tools before projection, and stops advertising client-provided tools; the default `"honor"` path is byte-identical to 0.7.0.
- **Observational-memory workers are tool-only.** Text/thinking/done-only turns are successful no-ops. Limit and unknown-tool failures throw `MemoryError` / `MemoryLimitError` rather than matching an English message prefix.
- **Channel lease release is fail-closed.** In-memory `route.lease` clears only after the store acknowledges; a failed release retries on idle/`stop`. TTL remains the cross-process backstop.
- **This-tree Postgres evidence.** `release:gate` reports `test:postgres` as pass only when `scripts/postgres-evidence.json` matches current `git rev-parse HEAD`. A stale phase baseline is blocked.
- **Compat baselines regenerated** at 0.8.0. Inherited 083 `@arnilo/prism-office` → `@arnilo/prism-work` removals (and `prism-core` / `prism-coding-tools` moves) are listed separately from 085 additions. This cut's own Tasks 1–6 add no public removals.
- **Migration guide for 0.7.0 hosts**: [docs/migrate-to-0.8.md](docs/migrate-to-0.8.md), indexed from [docs/migration.md](docs/migration.md) and [docs/index.md](docs/index.md).

### Fixed
- **Portable work-idempotency error codes survived the work-family move.** The enterprise PostgreSQL `IdempotencyStore` adapter keeps `ERR_PRISM_WORK_IDEMPOTENCY` / `ERR_PRISM_WORK_IDEMPOTENCY_CONFLICT`; only the error class changed (`EnterprisePostgresError`).
- **Stale ownership assertions in the protected PostgreSQL leg:** a foreign checkpoint scope is a miss plus a generic CAS conflict, and a foreign agent-run status read is indistinguishable from a missing run (`ERR_PRISM_AGENT_RUN_STATE`).
- **Wiki isolation nested-runner flake.** The wiki scratch gate spawns `node --test --test-isolation=none` (still strips `NODE_TEST_CONTEXT` / `NODE_TEST_WORKER_ID`) so worker IPC deserialization cannot fail the gate under `npm test` load.
- **Coverage artifact names.** Package keys in `scripts/coverage-summary.json` must equal live workspace manifests (`@arnilo/prism-work`, not `@arnilo/prism-office`).
- **Alibaba video `fetchUrl`.** Declared `fetchUrl` now downloads generated video bytes; unused OpenAI speech `_bearerHeaders` deleted.

### Security
- **Numeric claims must be grounded or they fail closed.** The claim-grounding guardrail blocks by default, bounds every reported span, caps evidence collection (4,096 figures, 16 levels, 128 KiB), and treats a missing evidence set as ungrounded rather than passing silently.
- **Crash recovery cannot bypass approval gates.** `"continue"` resumes only a running checkpoint with no pending decision or ready call, and keeps the recorded fingerprint, revision, ownership/fencing, and CAS-version gates.
- **Failed channel lease release is not success.** This process does not treat the binding as free until the store acknowledges; TTL is the other-process backstop.
- **Postgres release pass cannot be inherited.** Missing or stale this-tree evidence is blocked, never a pass from a previous commit's counts.

## [0.7.0] - 2026-09-15 (extended line: plans 072, 073, 074, 075, 077, 078)

> **Channels are not in this cut.** Plan 079 (Telegram/Signal adapters) was reassigned to **0.8.0** so the 0.7.0 cut stops waiting on it; nothing in this release mentions or ships a channel adapter.

### Added
- **Execution timeline (plan 072).** `@arnilo/prism-core/governance/observability` ships one frozen, JSON-serializable view-model for what a run did: `projectAgentTimeline` (live `AgentEvent[]`), `projectTraceTimeline` (persisted `EvaluationTrace`), `projectWorkflowTimeline` (workflow events plus optional checkpoint), incremental `createTimelineFolder` / `createWorkflowTimelineFolder` folders for SSE/cockpit updates, and `summarizeTimeline` / `summarizeSession` rollups (tool counts capped at 64, no double counting across runs). See [docs/execution-timeline.md](docs/execution-timeline.md).
- **Workflow graph view-model (plan 072).** `serializeWorkflowGraph`, `workflowGraphToMermaid`, `workflowGraphToDot`, `projectWorkflowGraphRun`, and `createWorkflowGraphRunFolder` render a workflow DAG and overlay live or checkpoint run state (`WorkflowGraphRunView`) without executing it.
- **Trajectory and outcome evals (plan 072).** Scorers (`defineScorer`, pairwise preferences, model-judge budgets), `runScenario`, `runExperiment`, `runWorkflowExperiment`, dataset items with expected trajectories, trials, manifests, comparisons, and thresholds — with `runComparison` / `datasetFromRuns` curation over recorded runs.
- **Eval primitives match their contracts (plan 073 Tasks 30–31).** Injection/timeline holes closed, deterministic `mulberry32` sampling, `collectWhileRunning`, and host-activity eval packs (coding, browser, memory, voice invariants) over the true primitives.
- **Attention compiler (plan 074, opt-in).** `createAttentionCompiler` / `resolveInputCap` / `compileAttention` / `createAttentionTruncationTrigger`: a per-turn gate that measures the assembled input against a host ratio of the model input cap and, only past the ratio, mutates a **history clone** oldest thinking blocks first, then fold-eligible tool results — keeping cache prefixes, the session store, and the observational-memory ledger untouched, and raising `AttentionBudgetError` rather than silently dropping context. Wired through `AgentConfig`, `AgentDefinition`, and `RunOptions` (run overlay narrows), plus `attention_compiled` telemetry and an `attention` timeline step; sticky frontier persists through `persistSessionState`. See [docs/attention-compiler.md](docs/attention-compiler.md).
- **Memory fabric subpath (plan 075, opt-in).** `@arnilo/prism-memory/fabric` adds typed notes (`fact`, `procedure`, `file`, `working`, `episode`) with links, validity windows, time/tool recall, conversation search, and opt-in consolidation/linker/evolution workers over the stores a host already configured. Inert until `fabric.attach(session)`; no new package, provider, database, or mandatory dependency. See [docs/memory-fabric.md](docs/memory-fabric.md).
- **Work-scope memory index (plan 077, opt-in).** `createWorkScopeController` appends `om.scope.*` entries to one observational-memory ledger; `foldWorkScopeMap`, `projectWorkMemory`, and `withWorkScope` project the outline to a host-selected working set (leaf `self+ancestors` by default), auto-bind new observations to the leaf, and skip the observation dropper while any host scope exists. Caps fail closed (256 scopes, depth 8, 4,096 binds, 512-char labels). See [docs/compaction-observational-memory.md](docs/compaction-observational-memory.md).
- **Host-owned subagent spawn (plan 078, opt-in).** `createSpawnAgentTool` turns the supervisor's host-owned child catalog into a non-exclusive `spawn_agent` whose closed schema exposes only allow-listed child ids, input, an optional thread id, and `mode: "sync" | "async"`; `createWaitAgentTool` / `createCancelAgentTool` join or abort async handles from `delegateAsync()`. Child identity narrows from the parent, results and errors are redacted, child slots are reserved atomically (after a before-hook narrows limits), and parent-run abort cancels running children. `createWorktreeChildFactory` gives each child its own linked git worktree and cleans it up on every terminal outcome (including a suspended child that later resumes), while `observeSupervisorLifecycle` bridges `delegation_*` events to redacted coding `subagent_started` / `subagent_stopped` lifecycle events. See [docs/supervisors.md](docs/supervisors.md).
- **Governed host completeness (plan 073).** Governed provider invocation with aggregate task/tenant accounting across every paid work kind (enterprise migration `006_aggregate_budgets`); durable business-action drafts with editable approvals; Docker process sessions and coherent workspace recovery; incremental Drive knowledge synchronization; snapshot/reconnect lifecycle with a hosted E2B sandbox; fair worker admission and operator routes; cross-layer memory lineage with correction and revocation; semantic artifact review with evidence-backed citations; import-fidelity reports with optional OCR; monotonic per-run tool narrowing with remote invalidation; native Bedrock `Converse`/`ConverseStream`; and governed realtime voice orchestration. New pages: [docs/execution-timeline.md](docs/execution-timeline.md), [docs/host-compositions.md](docs/host-compositions.md), [docs/hosted-sandboxes.md](docs/hosted-sandboxes.md), [docs/knowledge-sync.md](docs/knowledge-sync.md), [docs/realtime-voice.md](docs/realtime-voice.md), [docs/attention-compiler.md](docs/attention-compiler.md), [docs/memory-fabric.md](docs/memory-fabric.md).
- **Examples.** Runnable demos for the new surfaces: `examples/execution-timeline.ts`, `examples/behavior-evaluation.ts`, `examples/coding-browser-evaluation.ts`, `examples/attention-compiler.ts`, `examples/memory-fabric.ts`, `examples/work-scopes-coding-loop.ts`, `examples/spawn-agent-tool.ts`, `examples/governed-provider.ts`, `examples/docker-process-session.ts`, `examples/drive-rag-sync.ts`, `examples/hosted-sandbox.ts`, `examples/scanned-document-rag.ts`, and `examples/realtime-voice-host.ts`.

### Changed
- **Lockstep `0.6.0` → `0.7.0`.** All ten publishable manifests move together with `^0.7.0` internal ranges; the lockfile, the `src/index.ts` version constant, the docs index banner, the release-workflow tag lists, and the generated package-truth artifact agree (enforced by `scripts/version-literal-gate.test.mjs`).
- **Compat baselines regenerated** (`--update-baseline`): **469 added declarations, zero removals**. The additions are the new subpath APIs above plus members added to existing declaration groups; no export was renamed or dropped.
- **Release budgets rebaselined with recorded reasons**: root packed/unpacked/fileCount moved for the new dist modules, templates, and docs pages, and per-package export ceilings carry the 0.7.0 addition list. Startup and timing ceilings are unchanged.
- **Migration guide for 0.6.0 hosts**: [docs/migrate-to-0.7.md](docs/migrate-to-0.7.md) (per-item actions for the ACP/model-router refusals, every tightening, the opt-in activation steps, and rollback), indexed from [docs/migration.md](docs/migration.md) and [docs/index.md](docs/index.md).
- **Options index and peer matrix** cover the new surfaces: [docs/options-index.md](docs/options-index.md) routes `AttentionCompilerOptions`/`AttentionInputCapOptions`/`AttentionCompileOptions`/`AttentionTruncationTriggerOptions`, the fabric and work-scope option objects, and the supervisor/spawn/worktree/lifecycle options to their owning pages (gated by `scripts/live-doc-check.test.mjs`).

### Fixed
- **Task-scoped enterprise budgets failed on their first insert.** Migration `006_aggregate_budgets`' insert bound one JavaScript `Date` to both a `timestamptz` column and interval arithmetic, so PostgreSQL refused the statement with `42P08 inconsistent types deduced for parameter $8`; the parameter is now explicitly `::timestamptz` (found by the protected PostgreSQL leg, not by hermetic doubles).
- **A serialization failure inside the budget upsert was swallowed.** The read-then-insert path caught *every* error from the `SELECT … FOR UPDATE` probe and then issued SQL against an aborted transaction (`25P02`), which defeated the retry loop; only a genuinely missing row is recoverable by inserting now.
- **Serializable retry policy was too small for concurrent writers.** Budget/rate rewrites on one row now retry up to 12 times with full-jitter exponential backoff (capped at 250 ms), so a 16-client burst converges instead of exhausting three near-instant attempts with `ERR_PRISM_ENTERPRISE_POSTGRES_RETRYABLE`.
- **Integration tests were stale against migration 006** (expected five migrations) and `scripts/phase27-release.test.mjs` still asserted that no `006_` migration existed; both now check the append-only list including `006_aggregate_budgets`.

### Security
- **ACP MCP destination matching (Trap A).** `mcp.allow` entries now match by WHATWG origin plus path-segment subtree: origin lookalikes (`mcp.example.com.attacker.invalid`) and sibling path prefixes (`/mcp-other`) no longer match, and allow entries carrying userinfo, query, fragment, or ambiguous encoded path forms fail `ConfigError` at parse time.
- **Model-router facade fails closed (Trap B).** `router.providerSource(model)` throws `ERR_PRISM_MODEL_ROUTER_ASYNC_REQUIRED` / `ERR_PRISM_MODEL_ROUTER_ASYNC_STATE` instead of handing back a provider that bypasses budgets, rate limits, circuits, fallbacks, selection policies, or durable state; `isProviderSourceEligible` lets a host check first.
- **ACP launcher requires a real provider (Trap C/R05).** No silent `createMockProvider()` fallback; mock mode is an explicit opt-in.
- **Per-run tool narrowing is monotonic (R11)** and remote invalidation is honored; child agents cannot widen the tenant, account, user, or scopes of the parent identity (`narrowIdentity` + `assertIdentityPropagation`).

### Notes
- **Protected PostgreSQL leg now green on 0.7.0 code**: `PRISM_TEST_POSTGRES_URL=… npm run test:postgres` passes core (72), memory (457), and the phase conformance legs (11) against `pgvector/pgvector:pg16`, the same image the release workflow uses. The three fixes above are what that leg caught.
- **Node floor is unchanged** at `>=22` (Node 22/24 supported).

## [0.6.0] - 2026-09-12 (plans 070, 071)

> **0.5.7 was never published.** This release folds that cut's content (durable concurrent tool rounds, strict-provider tool results, host-tunable knobs, peer/options truth, the dependency refresh, and the module splits) together with the 0.6.0 changes below, so a host on 0.5.6 upgrades once. See [docs/migrate-to-0.6.md](docs/migrate-to-0.6.md).

### Fixed
- **Concurrent tool dispatch dropped sibling results.** With `toolConcurrency > 1` a failed or aborted call threw before the round's results were appended, so every successful sibling result was lost and the next provider request carried unanswered `tool_use` blocks. Results are now persisted before the round fails: successes as-is, the failing call as a real redacted `tool_execution_failed` error, and calls that never started as `tool_call_not_dispatched`. Run-level control errors (`ERR_PRISM_AGENT_RUN_SUSPENDED`, `ERR_PRISM_DELEGATION_SUSPENDED`, `ERR_PRISM_LOOP_*`) still skip synthetic results so durable recovery re-dispatches instead of double-appending.
- **Content-less tool results serialized as an empty payload.** A `ToolResult` with no `content`/`result` now folds to `EMPTY_TOOL_RESULT_TEXT` (`(tool completed with no output)`) through the shared `serializeToolResultJson` seam (OpenAI-compatible, Alibaba, DeepSeek, Kimi/Moonshot, NeuralWatt, OpenCode-Go), so strict providers stop rejecting zero-length tool payloads.
- **A failing coverage child hid its own error.** `npm run test:coverage` reported a crashed or failed workspace suite as a bare `no coverage data (suite failed)`, with the child's output discarded (the diagnostic gap that made a one-off `@arnilo/prism-memory` flake unreadable). The summary now prints the child's output tail under the failing row and records `status`/`exitCode`/`tail` on its artifact row — redacted through the public `createSecretRedactor` (repo root and home become placeholders, credential-shaped env values become `[REDACTED]`) and char-bounded (last 40 lines, 8 KiB) so one pathological line cannot bloat the artifact. Passing rows are byte-identical to before.
- **Memory patch merge aliased caller objects.** `packages/memory`'s `mergeJsonObjects` deep-merged in place; it now delegates to core `mergeConfigLayers` (deep copy, strict JSON validation — `undefined`/`Date`/function values fail closed — with the `MemoryValidationError` taxonomy preserved).
- **`redactSecrets` was O(n·m) in needles.** 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 remains the fallback for overlapping needle sets and small inputs.
- **Peer manifest resolution broke for packages that do not export `./package.json`** (e.g. `@dietrichgebert/ponytail`): upstream resolvers now resolve the package entry point and walk up to the manifest.

### Added
- **Host-tunable context assembly:** `AssembleProviderInputOptions.tokenEstimator?: (text: string) => number` replaces the built-in UTF-16/4 heuristic for eviction accounting (byte caps stay estimator-independent).
- **Host-tunable session snapshot cache:** `AgentSessionConfig.snapshotCacheTtlMs` — `DEFAULT_SNAPSHOT_CACHE_TTL_MS` (1000), `HARD_MAX_SNAPSHOT_CACHE_TTL_MS` (30000), `0` disables the branch-rebuild cache.
- **Host-tunable memory-session search caps:** `createMemorySessionStore(entries, { search: { maxLinearSessions, maxLinearEntries, maxLinearBytes } })`, validated against the same hard bounds as the defaults.
- **SSRF allow-list:** `SsrfPolicy.allowedCidrs` accepts IPv4 and IPv6 CIDR entries so a host can explicitly reach a private range; hostname denials (metadata endpoints), credential checks, and the fail-closed unparseable-CIDR behavior are unchanged.
- **Browser run lifetime:** `BrowserLimitOptions.idleRunTtlMs` (default `0`, `HARD_IDLE_RUN_TTL_MS` 30 min) reaps runs with nothing queued; any interaction resets the idle clock.
- **Host onboarding docs:** [`docs/peer-dependencies.md`](docs/peer-dependencies.md) (every third-party peer declaration with range, optionality, subpath, install line, and network footprint) and [`docs/options-index.md`](docs/options-index.md) (123 public option/limits/config surfaces routed to the page that documents them), both gated by `live-doc-check` against the manifests and the source.
- **Real-peer and ACP round-trip coverage:** contract smoke tests for the `@dietrichgebert/ponytail` and `@nanonets/graft` layouts, and stdio round-trip tests driving a spawned ACP agent with the real `@agentclientprotocol/sdk` client (spawn→close, mode negotiation, config options, refused/cancelled permissions).
- **Release-truth gates:** `scripts/version-literal-gate.test.mjs` asserts every release-claim surface (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, so a half-finished cut fails the suite instead of shipping; `scripts/workflow-liveness.test.mjs` resolves every workflow script/workspace/`uses:` reference and requires 40-hex SHA pins for actions; `scripts/wiki-scratch-isolation.test.mjs` proves the memory wiki suites leave tracked fixtures and the repository root untouched; `scripts/run-all-tests.mjs` runs every test stage without short-circuiting, and the startup import budget now asserts a machine-relative ratio (absolute 250 ms ceiling only off-load) so a busy machine no longer reports a false regression.

### Changed
- **Node floor raised to `>=22`** in all ten publishable packages (`@types/node` `^20.19.0` → `^22.20.0`; the `node20-compat` release leg becomes `node22-compat` on Node 22). Node 20 is upstream EOL since 2026-04-30; Node 24 stays the CI default. This is the host-breaking support-matrix change that the unreleased 0.5.7 deliberately deferred to a minor.
- **Dependency refresh:** `pg` 8.23, `playwright-core` 1.63.0, `zod` ^4.6.2, `@ai-sdk/provider` 4.0.13 (`@ai-sdk/openai` 4.0.65 with a new supported-version matrix entry), `@office-open/*` 0.14.5 (adapters use the `*Sync` parse variants), `@biomejs/biome` 2.5.13, `@agentclientprotocol/sdk` exact-pinned 1.4.0, and the `@arnilo/prism-memory` `@nanonets/graft` peer range widened to `^0.16.0 || ^0.18.0`.
- **Examples are Node-20-floor safe:** four runnable examples used `import.meta.main` (Node ≥22.18/≥24.2) on a Node-20 floor; they now use the house `import.meta.url` + `process.argv[1]` guard.
- **Release gate:** lockstep cuts now require every internal `@arnilo/*` range to be the cut version exactly (`0.6.0` or `^0.6.0`) instead of merely satisfying it, so one release line cannot resolve two first-party minors.
- **Test/coverage tooling:** the npm test chain runs every stage through `scripts/run-all-tests.mjs` (no short-circuit, one summary), coverage discovery finds nested `dist/**/__tests__` in all 9 workspace packages, `coverage-thresholds.json` may no longer name retired packages, and protected legs use one blocked-gate shape (`scripts/blocked-gate.mjs`) with env **names** only in the release evidence.
- **Internal structure, additive-only surface:** `runtime/server/artifacts.ts` split into four modules, `enterprise/postgres/model-router.ts` split into a directory (`util`/`circuit`/`capacity`/`reservations`/`expiry`/`state-store`), MCP OAuth discovery extracted to `oauth-metadata.ts`, one abort-aware `Semaphore` shared across `@arnilo/prism-coding-tools` (sandbox error types preserved), shared upstream persona primitives in `@arnilo/prism-coding-tools/src/upstream/`, shared provider HTTP retry primitives (`@arnilo/prism-providers/src/shared/retry-http.ts`), and the `content.ts` ↔ `pinned-fetch.ts` ESM cycle broken via the leaf module `src/media-types.ts`. Compat baselines were regenerated (`--update-baseline`): **69 added declarations, zero removals** — the five new host-tunable surfaces plus the helpers the moved modules now export from their new files.

### Removed
- **`@arnilo/prism-office` optional `playwright-core` peer** (test-only: `/diagrams` drives a host-supplied iframe). Hosts no longer install a browser for office; see [`docs/peer-dependencies.md`](docs/peer-dependencies.md).

### Notes
- **Lockstep `0.5.6` → `0.6.0` bump:** all 10 publishable manifests move to `0.6.0` with internal ranges `^0.6.0`; the predecessor published release is **0.5.6** (0.5.7 was never published and is superseded by this cut).
- **Retired-gate and test-truth fixes** landed in the same window (plans 070/071): frozen-era version markers derive from the root manifest, retired doc paths resolve through the frozen lineage, the packed-consumer enterprise journey no longer inherits a Postgres env var (the `pg` peer is not installed in a packed consumer), the `sandbox-browser` workflow references live packages again, the secret scan is operator-independent (tracked files only), the LSP restart-budget test awaits the exhaustion transition instead of racing a write, and the release workflow tag lists carry every published tag.

## [0.5.6] - 2026-09-09 (plan 069)

### Added
- **Trusted extension activation**: `activateKernel(kernel)` / `ActivatedKernelConfig` turn a loaded extension kernel into ready-to-spread `AgentConfig` contributions (tools, skills, context, middleware, commands, instruction injectors). No auto-picked single-slot builders/providers.
- **CLI `--extension`**: repeatable flag loads trusted extension packages — cwd-relative paths (realpath-contained) or `PRISM_EXTENSION_ALLOWLIST` specifiers — and merges their contributions into the run. Modules must export `createExtension()`, a default function, or a default `{name, setup}` object; `--config`/`--resource`/`--tool` stay rejected.
- **Wiki ingest**: `ingestWikiSource`, `/wiki-ingest` command, `wiki_ingest` tool, and `prism-wiki ingest` stage one external source (text, file, image, PDF; URL via a host `fetchUrl` hook with `assertSsrfAllowedUrl` first) into `raw/ingest/<utc>-<slug>/` as an immutable `source.*` + UTF-8 `extract.md`, then return a Karpathy/OKF filing brief (`metadata.trust: "untrusted_external"`). Compressed PDF/DOCX ride an optional host `extractDocument` hook. Caps: 32 MiB input / 2 MiB extract.
- **Ingest filing protocol**: `wiki-maintainer` skill + scaffolded `SCHEMA.md` gained the ten-step ingest procedure (catalog-first, integrate-don't-duplicate, OKF v0.2 frontmatter with `sources[].id` footnotes, index/log sync, raw layer read-only, one source per ingest).
- **Graft graph commands**: `/graft-init` (non-interactive `graft init --no-global`, host `initAgents`/`initYes`), `/graft-build-deep` (`build --deep` with host-configured `deepModel` — provider/model/base-url on argv, `GRAFT_API_KEY` env-only, never on argv, fails closed unconfigured) alongside the keyless `/graft-build`. New `runGraftExit` exit-code runner (build/init are plain text, not JSON) with separate `buildBudgetMs` (120s) / `deepBuildBudgetMs` (600s) / `buildMaxResultBytes` (2 MiB) budgets.

## [0.5.5] - 2026-09-08

### Fixed
- **Byte limits are per-frame, not cumulative.** `maxRequestBytes`/`maxResponseBytes` now compare each individual provider frame (request payload, streamed event) against the cap instead of a run-lifetime byte sum, so long autonomous coding runs (many megabyte-scale frames, each far under 64 MiB) no longer trip `Run limit exceeded: maxRequestBytes` after ~40 turns. HARD stays per-frame process safety — one giant frame still fails, 40 legal frames never do. Cumulative byte counters remain in snapshots/telemetry; token/turn/wall/cost axes stay cumulative.

## [0.5.4] - 2026-09-08 (plan 067)

### Changed
- **Run limits: process-safety HARD split from host policy.** `DEFAULT_RUN_LIMITS` stays the unconfigured fence (turns 16, attempts 24, tool rounds 8, calls 32, wall 120s, bytes 8 MiB, tokens 40k/10k/50k), but `HARD_RUN_LIMITS` shrinks to the two process-integrity axes (`maxRequestBytes`/`maxResponseBytes`, 64 MiB) so a bug cannot OOM the host through a giant provider frame — and hosts can legally raise or disable everything else. Policy axes accept `number | null`: omit for the default, set a positive safe integer, or set `null` to disable the axis (disabled wall still honors `RunOptions.signal`). Resolution stays narrowing-only with `null` as +Infinity (agent 16 + run `null` → 16); an omitted `maxProviderAttempts` lifts to at least a raised/disabled `maxTurns` so attempts cannot undercut turns. Byte axes reject `null` and >64 MiB. The former `$10k` `maxCost` ceiling is removed (any finite non-negative amount). Documented ceiling: vendors that omit usage charge zero to token counters; a configured `maxCost` remains fail-closed. Durable checkpoints omit `deadlineAt` on no-wall runs; older checkpoints with a deadline still resume. New `ResolvedRunLimits` type; `resolveRunLimits` returns it.

### Removed
- **`HARD_MAX_RUN_COST` export** (was a `$10k` validation ceiling; `maxCost` now accepts any finite non-negative amount plus one currency).

## [0.5.3] - 2026-09-08

### Fixed
- **Content-only tool results no longer serialize as JSON `"null"` on the provider wire.** First-party coding tools return output in `ToolResult.content` (`[{type:'text',text}]`), not `value`. Construction now folds that text onto `tool_result.result`; serializers join sibling `type:text` blocks when `result` is missing. Lockstep `0.5.2` → `0.5.3` with internal ranges `^0.5.2` → `^0.5.3`.

## [0.5.2] - 2026-09-08

### Fixed
- **Stream tokens no longer persist as one content block per SSE delta.** Adjacent `text`/`thinking` deltas merge on persist (`text += delta`); `message_delta` events stay per-token. Replay serializers join those parts with `""` instead of `"\n"`, so multi-turn tool loops stop poisoning the next request into one token per line. Lockstep `0.5.1` → `0.5.2` with internal ranges `^0.5.1` → `^0.5.2`.

## [0.5.1] - 2026-09-07 (plan 066)

### Changed
- **Prism constructs valid provider requests on every owned generate site (plan 066, additive):** new `applyDefaultProviderRequestOptions(request, { sessionId, thinkingLevel? })` fills missing `options.sessionId` (from the kernel session id) and `options.cacheKey` (from that id) with host values always winning; new `AgentConfig.thinkingLevel` / `RunOptions.thinkingLevel` session intent (run overrides agent) reaches the wire through the existing `applyThinkingLevelForModel` snap/merge; cache-control and explicit-breakpoint models now get default `{ system_prompt, last_stable_message }` breakpoints with `cacheRetention: "short"` unless the host sets `cache.mode: "off"`, `cacheRetention: "none"`, or explicit breakpoints — implicit/host-owned providers (Azure, Bedrock, Vertex, AI SDK) emit nothing new. Host request policies (`createSessionCachePolicy` and friends) remain overlays and are never required for request success.
- **Observational memory derives its own correlation id** (`om:{session.id}`, shared across observer/reflector/dropper) fully separate from the agent session (workers may use a different model); **LLM compaction reuses the agent session id** so summaries hit the same prompt cache.
- **OpenCode Go fails closed before fetch:** a raw `provider.generate()` without resolvable `sessionId`/`cacheKey` throws the new typed `ProviderRequirementError` (`ERR_PRISM_PROVIDER_REQUIREMENT`, redacted message naming requirement + provider id) instead of an opaque upstream HTTP 400.
- **Lockstep 0.5.1 bump:** all 10 publishable manifests `0.5.0` → `0.5.1` with internal ranges `^0.5.0` → `^0.5.1`. New exports: `applyDefaultProviderRequestOptions`, `ProviderRequirementError`, `ApplyDefaultProviderRequestOptionsContext`. Contract rewrite in `docs/provider-packages.md` and `docs/provider-request-policies.md`; additive 0.5.1 section in `docs/migrate-to-0.5.md`; each provider page documents its P1 session wire, mandatory flag, and P2 default cache behavior.

## [0.5.0] - 2026-09-06 (plans 055-065)

### Changed
- **Thinking/reasoning effort is now model-aware, declared, and snapped across all first-party providers (plan 065):** core gains `applyThinkingLevelForModel(base, level, model)` (family resolution + snap + merge in one call), `parseThinkingLevel` (known portable level → canonical; other non-empty string → opaque passthrough; empty/non-string → `undefined`, fail closed), `isSupportedThinkingLevel`, `thinkingLevelsForModel`, and `snapThinkingLevel` (nearest declared by ladder distance, ties break up, below-minimum snaps up; provider-documented tables remain wire authority). `ModelCapabilities` gains `thinkingLevels?: readonly string[]`; family inference is stamp-first via the new `compat.thinkingFamily` stamp set by every first-party catalog. Two new core compat families: `google` (`{ thinkingLevel }` → `generationConfig.thinkingConfig`) and `output_config_effort` (`{ output_config: { effort } }` → Anthropic Messages / DeepSeek anthropic-format). Per-provider: OpenAI catalogs declare per-family effort tables (gpt-5.1 `none/low/medium/high` default `none`; gpt-5.2 `none`–`xhigh` default `medium`) with Responses-side clamping; Google stamps per-model thinkingLevel sets (3.x) and budget ranges (2.5, `none` → range minimum); Anthropic emits generation-aware thinking (`adaptive` on 4.6+, legacy 4.5 budget default 10000) with per-model effort declarations; Azure/Vertex/Bedrock forward sanitized thinking compat through `buildBodyExtra` (previously silently dropped); Kimi K3, Z.AI GLM-5.2/5.3, and DeepSeek declare documented snap tables; xAI now sends `reasoning_effort` (grok-4.6 `low`–`xhigh`, grok-4.5 `low/medium/high`, grok-4.3 `none`–`high`) instead of dropping it; OpenRouter derives declared levels from the models API (`reasoning.supported_efforts`); Hyper snaps instead of dropping out-of-set efforts and derives levels from the live `effort_levels` list; ClinePass declares levels by inverting its slot maps; the shared Anthropic-Messages route gained `thinking`/`effort` hook slots (hyper/commandcode bind resolvers; opencode-go deleted its private serializer copy for the shared route); commandcode/opencode-go carry provenance-commented level tables; Alibaba/Qwen maps the `thinking_type` family onto `enable_thinking` with thinking-only models never disabled; Ollama/NeuralWatt declare + snap `reasoning_effort`. `@arnilo/prism-memory` workers (LLM compaction, observational memory) now use the single model-aware adapter. Conformance: a cross-catalog walk (`thinking-conformance.test.ts`) machine-checks all 133 reasoning-capable catalog models (declarations + legal wire fields + no verbatim leakage), generated evidence matrix `docs/_evidence/thinking-coverage-2026-09-05.md`, and env-gated live probes pin the riskiest wire changes (Anthropic `output_config.effort` + legacy-field outcome, Google `thinkingLevel`, xAI/Kimi/Z.AI `reasoning_effort`, GLM-5.3 `thinking.type: disabled` rejection gate, Azure `reasoning_effort`). Breaking wire moves + new exports in `docs/migrate-to-0.5.md`; contract rewrite in `docs/thinking-and-reasoning.md`; per-provider pages document declared levels, wire fields, and snapping.


### Changed
- **CLI real-provider support (plan 064 Task 5):** `prism --provider <id>` now runs real providers, not just the built-in mock — provider ids resolve through the init provider catalog (`templates/init/providers.json`, single source shared with `prism init` scaffolding via new `factoryModule`/`factoryExport` fields): the CLI dynamically imports the provider factory from the installed `@arnilo/prism-providers/*` package and reads the catalog's credential env var. `--mode print|json|rpc` all honor it; RPC's session factory became async-capable (`AgentSession | Promise<AgentSession>`) to support the dynamic import. Without `--provider` the CLI still fails with a usage error (unchanged contract). Covered by the new packed-install live journey `scripts/e2e-cli-live.test.mjs` (scaffold + `providers add` + print/json/rpc over the real wire + full-transcript secret scan; matrix entry `cli/journey`).
- **`@arnilo/prism-mcp` completes the MCP 2026-07-28 adoption (plan 063):** modular TypeScript SDK v2 (`@modelcontextprotocol/client` + `@modelcontextprotocol/server` 2.0.0 exact pins) replaces the monolithic `@modelcontextprotocol/sdk` 1.30.0; modern client negotiation (`legacy`/`auto`/`{pin}` with one bounded discovery probe), negotiated-era exposure, SDK-managed routing headers with `Mcp-Param-*` mirroring (SEP-2243), SDK subscriptions + explicit-cursor lists + `callTool({toolDefinition})`, SEP-2549 list-cache hints (private per principal by default), elicitation via SDK MRTR auto-fulfilment with `maxMrtrRounds` (roots/sampling callbacks `@deprecated` per SEP-2577), dual-era HTTP/stdio serving through `createMcpHandler`/`serveStdio` with host/origin gates in front, and 2026-07-28-conformant OAuth (issuer-keyed storage, CIMD preferred, RFC 9207 `iss` validation, explicit insufficient-scope policy). Tasks (`io.modelcontextprotocol/tasks`) intentionally not advertised; draft-era task vocabulary fails closed. Conformance: official suite (latest published spec version 2025-11-25 — no 2026-07-28 scenarios upstream yet) 20/20 expressible scenarios green against the dual-era serving fixture with the remaining 14 scenarios recorded as documented Prism boundaries in `scripts/mcp-conformance-2026-baseline.yaml`; two real defects found and fixed by the matrix (no-argument prompts rejected `undefined` args; tool inputSchema lost `$schema`/`$defs`/`$ref`/`additionalProperties` through the zod round-trip). Full migration table + legacy-session timeline in `docs/migration.md`; canonical API in `docs/mcp-tools.md`.


### Changed
- **pdf-parse 1.1 → 2.4 migration (plan 062, parser CVE class):** `@arnilo/prism-coding-tools` document-reader moves `pdf-parse` `^1.1.1` → `^2.4.5` (optional peer) and the two optional peers (`pdf-parse`, `mammoth`) become explicit devDependencies so the fixture suites actually run in this repo (previously they self-skipped via `PEERS_OK`). v2 replaced the v1 `pdf(buffer) → {numpages, text}` function with a `PDFParse` class: adapter now constructs `new PDFParse({ data, isEvalSupported: false })`, calls `getText({ pageJoiner: "" })`, and `destroy()`s in `finally`; page count reads `result.total` instead of `numpages`. `isEvalSupported: false` hard-disables pdf.js `eval` of PDF functions — the reader contract forbids embedded script execution (v1 did not disable it). Engine constraints for hosts: v2 parses in a worker thread (the `data` TypedArray is transferred, so the caller must not reuse the buffer — the adapter passes a fresh view per extract), requires Node ≥ 20.16 (repo already `engines.node >=20`), and ships CJS + ESM builds with a browser bundle; bundlers must resolve the `import`/`require` conditions of the new exports map. Golden deltas: extracted text for the committed fixtures is byte-identical to v1 modulo trailing `\n` (page-boundary markers suppressed via `pageJoiner: ""`); the 1000-page budget fixture parses in ~223ms (ceiling 2000ms, v1 baseline ~162ms — no regression). New fuzz smoke: a `%PDF-`-magic 256KiB garbage buffer rejects within the budget ceiling instead of hanging. Full coding-tools suite 646 pass / 0 fail; workspace typecheck green; root suite green.
- **better-sqlite3 12 → 13 migration (plan 062):** `@arnilo/prism-core` moves `better-sqlite3` `^12.11.1` → `^13.0.3` (optional peer) with `@types/better-sqlite3` `^7.6.13` → `^9.6.0`. Upstream 13 is an N-API rewrite (`node-addon-api`): no removed or changed APIs — only additions (`db.explain()`, `statement.toString()`) and a `SqliteError` cross-realm fix. Packaging change for hosts: 13 removes the deprecated `prebuild-install` and bundles prebuilt N-API binaries for supported platforms directly in the package (one binary across Node versions — no per-Node rebuild); unsupported platform/arch compiles from source during install as before (`npm rebuild better-sqlite3` after a toolchain change). No SQL construction or prepared-statement layout changed in the adapter (statements remain hoisted `db.prepare` consts); all sqlite session/enterprise/prompt suites green (34 pass / 1 env-gated skip), packed-tarball fresh-install native-load + round-trip smoke green, benchmark gate medians green.
- **Keyring 2 migration (plan 062, credential-storage boundary):** `@arnilo/prism-core` moves `@napi-rs/keyring` `^1.3.0` → `^2.0.0`. Upstream 2.0 changes error reporting, not success paths: reads (`getPassword`/`getSecret`) and deletes (`deleteCredential`) now reject on locked/inaccessible stores instead of silently resolving `undefined`/`false`; a missing credential still resolves `undefined`, and `false` from a delete now guarantees absence. The keychain adapter (`packages/prism-core/src/credentials/node/keychain-store.ts`) already routes every native call through `runKeychainOperation` → typed-error mapping (`CredentialStoreLockedError`/`CredentialStoreUnavailableError`/`CredentialStoreTimeoutError`), so host-visible behavior is unchanged in shape and strictly safer in semantics: a locked keychain now surfaces as a typed locked-store error instead of masquerading as an empty vault (which under 1.x could lead a `set()` to overwrite the real vault). Async signatures (`signal` parameters, binary `getSecret`, `AsyncEntry`) unchanged. Evidence: full credential-node suite 75/75 green; live Secret Service round-trip (`PRISM_TEST_KEYCHAIN=1`, credential + OAuth set/get/delete) green on Linux keyring 2.0.0; macOS/Windows legs are not exercisable in CI (all legs ubuntu) — the round-trip test ships gated per platform via `PRISM_TEST_KEYCHAIN=1`.

### Removed
- **Dead-export removal wave (plan 058 task 3, breaking):** all 27 unused public exports classified `deprecate`/`remove` in `docs/_evidence/dead-export-verification-2026-09-03.md` are deleted in one coordinated 0.5.0 cut (deprecated at 0.5.0-precursor in the same cycle). Per package — `@arnilo/prism`: `statusFromState`, `isInitProvider`, `isInitTemplate`, `parseContextFile`, `parseToolFile`, `defaultUserSettingsPath`, `resolveProviderMediaBlock`, `ProviderSecretLeakConformanceOptions`, `runToolEffectStoreConformance`; `@arnilo/prism-core`: `OidcIdentityVerifierResult`, `assertDiffLines`, `ResolvedPromptLimits`, `encodeMetadata`, `parseListOffsetCursor`, `nodeKindOf`; `@arnilo/prism-memory`: `DEFAULT_MAX_PROMPT_CHARS`, `GRAFT_RESOLVE_ERROR_CODE`, `LinterOptions`, `ResolvedGraftExtension`, `WikiCategory`; `@arnilo/prism-coding-tools`: `codingSha256Hex`, `DEFAULT_MAX_REVIEW_DELTA_ENTRIES`, `HARD_MAX_REVIEW_DELTA_ENTRIES`, `indexErrorCode`, `PONYTAIL_PEER_RANGE`, `CavemanSkillName`; `@arnilo/prism-providers`: `withOpenRouterCacheMarker`. All had zero in-repo references (test-only false positives were reclassified keep by the verification sweep; security guards are keep-classified and untouched). Compat baselines regenerated at the cut; intentional breaks recorded in `docs/migration.md`; removal table + replacements in `docs/migrate-to-0.5.md`. `scripts/unused-report.json` deadExports → 0 (the scan now counts test/example/script/template usage and suppresses keep-classified zero-ref exports). All manifests bump 0.4.x → 0.5.0 lockstep; internal ranges `^0.4.0` → `^0.5.0`. Security keeper surface (ownership/checkpoint guards, `secureCompare`, `zeroBuffer`, sandbox path-escape guard, RAG scope guard, MCP content-bounds guard, secret-leak conformance assert) unchanged.
- Removed `@arnilo/prism-antigravity-agent` workspace, package surface, active documentation, release wiring, and host-conformance branch. Delegated CLI execution belongs to hosts and composes through generic process, tool, MCP, supervisor, or A2A contracts.

### Changed
- Updated `@nanonets/graft` peer support to `^0.16.0`, AG-UI packages to `0.0.59`, `@ai-sdk/provider` to `4.0.10`, Office Open packages to `0.13.1`, Biome to `2.5.11`, and `fast-xml-parser` to `5.11.1`.
- Refreshed lockfile transitive dependencies; `npm audit` reports zero vulnerabilities.

### Deprecated
- **Type-level deprecation wave (plan 058, task 2):** 27 unused public exports now carry `@deprecated` JSDoc naming "no replacement" and the 0.5.0 removal plan; runtime behavior is unchanged (no warnings). Per package — `@arnilo/prism`: `statusFromState`, `isInitProvider`, `isInitTemplate`, `parseContextFile`, `parseToolFile`, `defaultUserSettingsPath`, `resolveProviderMediaBlock`, `ProviderSecretLeakConformanceOptions`, `runToolEffectStoreConformance`; `@arnilo/prism-core`: `OidcIdentityVerifierResult`, `assertDiffLines`, `encodeMetadata`, `parseListOffsetCursor`, `nodeKindOf`, `ResolvedPromptLimits` (marked for removal); `@arnilo/prism-memory`: `DEFAULT_MAX_PROMPT_CHARS`, `GRAFT_RESOLVE_ERROR_CODE`, `LinterOptions`, `ResolvedGraftExtension` (marked for removal), `WikiCategory` (marked for removal); `@arnilo/prism-coding-tools`: `codingSha256Hex`, `DEFAULT_MAX_REVIEW_DELTA_ENTRIES`, `HARD_MAX_REVIEW_DELTA_ENTRIES`, `indexErrorCode`, `PONYTAIL_PEER_RANGE`, `CavemanSkillName` (marked for removal); `@arnilo/prism-providers`: `withOpenRouterCacheMarker`. All are removed in the 0.5.0 cut above (plan 058 task 3, `docs/migrate-to-0.5.md`).

## [0.4.1] - 2026-09-02 (plan 055)

### Changed
- **Two new first-class provider adapters (plan 055):** `@arnilo/prism-providers` (0.4.0 → 0.4.1, Decision B changed-package cut) gains `./hyper` (Charm Hyper — dual-route `/v1/chat/completions` + `/v1/messages` adapter with cache_control on Anthropic-shaped models and Hypercredit cost telemetry) and `./commandcode` (Command Code Provider API — dual-route `/provider/v1/chat/completions` + `/provider/v1/messages` adapter with cache_control on Claude tiers and optional ZDR). Both keep zero network at setup, caller-gated model discovery, provider-owned header enforcement, secret redaction, and offline conformance suites; live probes are operator-gated behind `PRISM_LIVE_PROVIDER_TESTS=1` + provider key. Public symbols and trust boundaries unchanged except the two new subpaths; peer `@arnilo/prism@^0.4.0` unchanged; no root package change (docs only).

## [0.4.0] - 2026-09-01 (plan 054)

### Changed
- **Package consolidation (breaking import/package cut):** 11 active packages replace the 0.3.x graph. Families: `@arnilo/prism-core`, `@arnilo/prism-coding-tools`, `@arnilo/prism-web-tools`, `@arnilo/prism-memory`, `@arnilo/prism-providers` (17 adapter subpaths), `@arnilo/prism-office` (`/documents`, `/sheets`, `/diagrams`). Retired 54 published names stay installable at exact 0.3 pins; npm `legacy` dist-tag + `<0.4.0` deprecation warnings point at `docs/migrate-to-0.4.md`. Profile packages `prism-base`/`prism-code`/`prism-sdk`/`prism-all`/`prism-compaction` are gone — install the families. Peers and internal ranges are `^0.4.0`. No persisted-shape change; rollback = exact 0.3 pins.

## [0.3.3] - 2026-08-31 (plans 041-044, 051, 052, 053)

### Added
- **Documents engine (`@arnilo/prism-documents@0.3.0`, plan 051)**: Initial release of `@arnilo/prism-documents` with peer `@arnilo/prism@^0.3.0` (independent Decision B publication, omitted from `@arnilo/prism-all` and profile packages) — pure in-memory OpenXML generation, parsing, patching, and bounded preview rendering for Word (`.docx`), Excel (`.xlsx`), and PowerPoint (`.pptx`) artifacts; exact-pinned sub-packages `@office-open/{docx,xlsx,pptx}@0.12.3`; Draft-07 JSON Schema validation with on-demand slicing (`getDocumentModelSchema`) and transitive closures; typed AST patch engine with immutable undo/redo history (`createPatchHistory`); framework-neutral preview blocks and sanitize-by-construction HTML snippets; `SecretRedactor` boundary sanitization hook; dependency-free `DocumentsTelemetry` seam; and documented decimal fidelity ceiling (`{ type: "decimal", value: string }` representation with IEEE-754 round-trip limits in Excel cells).
- **Spreadsheet & CSV parsing engine (`@arnilo/prism-sheets@0.3.0`, plan 052)**: Initial release of `@arnilo/prism-sheets` with peer `@arnilo/prism@^0.3.0` (independent Decision B publication, omitted from `@arnilo/prism-all` and profile packages) — XLSX (`@office-open/xlsx@0.12.3` exact pin) and zero-dependency RFC 4180 CSV parsing with dialect sniffing (delimiter scoring across `,`, `;`, `\t`, `|`, quoted-region isolation, UTF-8 BOM stripping, UTF-16 rejection); decimal-safe typed schema inference (`inferAndTransformRows`, `normalizeDecimal`) with headline financial precision guarantees (monetary figures and currency patterns inferred as decimal strings `{ type: "decimal", value: string }` with zero floating-point coercion on decimal value paths; ambiguous numerics flagged `numeric-ambiguous`); bounded sampling window with full-parse validation; fail-closed caps (`DEFAULT_SHEETS_CAPS`: 100 MB file, 5M rows, 16k columns, 256 sheets, 500-row sample window, 20 max warnings); structured `InferenceWarning` and `SheetsDialectMismatchWarning` diagnostics; formula cell representation (`{ type: "formula", formula: string, value?: CellValue }`); dependency-free `SheetsTelemetry` seam.
- **Diagrams & draw.io embed client (`@arnilo/prism-diagrams@0.3.0`, plan 053)**: Initial release of `@arnilo/prism-diagrams` with peer `@arnilo/prism@^0.3.0` (independent Decision B publication, omitted from `@arnilo/prism-all` and profile packages) — origin-enforced iframe embed client (`createDrawioEmbed`) implementing diagrams.net `proto=json` protocol with dual inbound origin/source verification, strict outbound targetOrigin enforcement, and no public SaaS defaults (self-hosting as the documented deployment); typed lifecycle events (`init`, `load`, `save`, `autosave`, `exit`, `configure`, `export`, `error`); save-with-preview workflows generating SVG (`xmlsvg`) or PNG visual snapshots; XXE-safe mxGraph XML validation (`validateDrawioXml`) rejecting DOCTYPE/ENTITY declarations and billion-laughs payloads under strict element/attribute/byte caps; byte-stable deterministic XML canonicalization (`canonicalizeDrawioXml`) for content hashing; Visio binary (`.vsd`) and OpenXML (`.vsdx`) exclusion guard (`assertNotVisio`, P12); and dependency-free telemetry seam (`DiagramsTelemetry`, P15).
- **Progressive tool loading (plan 041)**: `search_tools({ query, k? })` — bounded inert name+description results (lexical disclosure, never wider than the eligible list, never zero via deterministic prefix), session-scoped activation persisted as names-only, dispatch re-checks allow/deny on every call (disclosure is not an authorization boundary). Benchmark: 86.4% provider-request tool-byte reduction at 128 tools / topK 16.
- **Prompt provenance (plan 042)**: `RunRecord.promptVersion` refs carried from `RunOptions` to durable run rows; session-store packages add the additive nullable `prompt_version` column + checked migrations (`@arnilo/prism-session-store-{codecs,sqlite,postgres}@0.3.1`); `PERSISTENCE_SCHEMA_VERSION` 8 → 9. `@arnilo/prism-prompts@0.0.1` initial cut ships the versioned immutable prompt store (independent host opt-in).
- **Docs**: `docs/documents.md` (documents, spreadsheets, and presentations hub guide), `docs/sheets.md` (spreadsheet and CSV parsing guide with decimal-safety invariant), `docs/diagrams.md` (diagramming and draw.io embed guide with origin-enforcement security), `docs/prompt-registry.md` (prompt registry contract), and composite memory recall scoring in `docs/working-and-semantic-memory.md`.
- **Package consolidation (plan 054, completed in 0.4.0)**: `@arnilo/prism-core` (Task 2) absorbs 16 runtime/session/governance/credentials/enterprise/work/validation packages behind explicit subpaths; `@arnilo/prism-coding-tools` (Task 3) absorbs nine coding/persona packages with the retained `prism-dev` bin; `@arnilo/prism-web-tools` (Task 4) absorbs `@arnilo/prism-browser` and `@arnilo/prism-obscura` as peer-gated `/browser` and `/obscura` subpaths; `@arnilo/prism-memory` (Task 5) absorbs `@arnilo/prism-rag`, both compaction strategies, `@arnilo/prism-graft`, and `@arnilo/prism-wiki` as `/rag`, `/compaction/{llm,observational-memory}`, `/graft`, and `/wiki` subpaths (deleting the `@arnilo/prism-compaction` profile; `prism-wiki` bin and skills ship from the memory tarball); `@arnilo/prism-providers` (Task 6) absorbs all 17 `@arnilo/prism-provider-*` packages as `/<adapter>` subpaths (deleting the standalone provider manifests, the 14-of-17 umbrella dependency set, and the Azure/Bedrock/Vertex all-only special case; the `/ai-sdk` adapter resolves its `@ai-sdk/provider` optional peer lazily at factory time) — public symbols and trust boundaries unchanged except import specifiers. A generated legacy-registry plan (`scripts/phase54-legacy-registry.mjs`) freezes each of the 54 retired names' final published version behind a `legacy` dist-tag and a `<0.4.0` install-time deprecation warning naming its exact 0.4 successor and migration-guide anchor; `--dry-run` verifies versions/anchors without mutating the registry and `--apply --confirm` is the idempotent, fail-closed cutover (Task 9). `@arnilo/prism-office` (Task 8) absorbs the unpublished documents/sheets/diagrams drafts as `/documents`, `/sheets`, `/diagrams` subpaths and deletes the `prism-base`/`prism-code`/`prism-sdk`/`prism-all` profile manifests; the 0.4 migration guide maps every retired name plus the office drafts.
- Package-level detail: `@arnilo/prism-memory@0.3.2` (composite recall scoring + importance at write), `@arnilo/prism-evals@0.3.1` (trace-to-dataset curation), `@arnilo/prism-documents@0.3.0` (initial cut), `@arnilo/prism-sheets@0.3.0` (initial cut), and `@arnilo/prism-diagrams@0.3.0` (initial cut).

## [0.3.2] - 2026-08-29 (plan 050)

### Added
- **OKF adoption (`@arnilo/prism-wiki`)**: wiki-init/refresh/lint emit and validate
  OKF v0.2 bundles (Karpathy prompt retained). See `docs/wiki.md`.
- **DOCS-1 (integration findings)**: three integrator contracts, in place on
  the pages that own them — resume-aware workflow nodes (`ctx.resume` or silent
  re-suspend) in `docs/workflows.md`; supervisor child factories return `Agent`
  not `AgentSession` (`SupervisorError: child "<id>" factory must return an
  Agent, got <type>`) plus durable-store nested approvals in `docs/supervisors.md`;
  task-boundary `session.compact()` fails closed during an active run in
  `docs/compaction-and-retry.md`. Each block links `examples/autonomous-coding-loop.ts`.
- **FEATURE-2 (integration findings)**: documented bounded iterate-until-done
  host-loop pattern in `docs/workflows.md` — one `runWorkflow` per iteration,
  iteration state in workflow inputs, explicit termination predicate and budgets,
  typed `BudgetExhaustedError` (fail-closed, never a hang), `replayWorkflow` per
  iteration run id. Seeded by `examples/autonomous-coding-loop.ts`. Plan 045 `loop`
  node remains the future in-graph primitive; this intake ships the docs+example
  minimum only.
- **FEATURE-6 (integration findings)**: composite `examples/autonomous-coding-loop.ts`
  conformance reference — goal → roadmap → per-task supervisor children (per-child
  models) → `runCodingGoalVerify`-style validation → observational-memory attach +
  task-boundary compact + recall → human gate with simulated restart → host-side
  bounded iterate-until-done with deterministic budget exhaustion. Mock providers
  only; no credentials or network.
- **FEATURE-3 (integration findings)**: host-opt-in command driver hooks.
  `CommandExecutionContext` gains an optional `drivers?: CommandDrivers`
  (`startRun` / `startWorkflow` / `steer` — typed minimal handles returning
  `AgentRunResult`-shaped results / workflow run id + status) so a contributed
  command can act through host-injected capabilities instead of being
  re-implemented host-side. The RPC session factory accepts `drivers` and
  forwards them at the single command-execution site; absent drivers leave
  the context shape unchanged (no key, no allocation). Drivers are
  host-injected capabilities, never package-supplied.
### Fixed
- **FEATURE-1 (integration findings)**: `resolveAgentDefinition` no longer
  throws `Agent "<name>" has no model` when the declarative definition omits
  `model` but `context.overrides.model` supplies one — the fallback is a
  single `??` at `buildBaseConfig`, the `create()` path is unchanged, and a
  definition with neither source still fails closed.

## [0.3.1] - 2026-08-29

> Root + 28 changed packages move to 0.3.1 in the plan 039 changed-package cut; `@arnilo/prism-rag` moves 0.3.1 → 0.3.2; `@arnilo/prism-obscura` publishes new at 0.3.0. Distinct from the 2026-08-26 rag/memory/otel 0.3.1 patch below (independent Decision B tags).

### Added
- `@arnilo/prism-obscura` (new workspace package, 0.3.0): optional Obscura headless-browser engine over a **host-installed** binary — fail-closed `spawnObscuraProcess` lifecycle (absolute shell-free command, Docker argv, bounded readiness, group close), `createObscuraMcpTools` bridging the complete advertised MCP surface (reads effect-free; mutations and unknown future tools exclusive/serialized; `obscura_` prefix; loopback-default HTTP), `connectObscuraCdp` managed/external CDP + Playwright `connectOverCDP` composition, and `createObscuraWebTools` (standard `web_search`/`web_fetch` through one replaceable HTML search profile plus native `obscura_fetch`/`obscura_scrape`; public-HTTP(S)-only URL validation, byte/count/timeout caps, `allowEval`-gated custom expressions, untrusted-content labeling). Deliberately omitted from `prism-all`/`prism-base`/`prism-sdk` umbrella profiles — installation does not supply the binary/image; consumers install it explicitly.
- Cross-host conformance (`scripts/obscura-host-conformance.test.mjs`, wired into `npm test`): the same Obscura `ToolDefinition[]` executes through core agent sessions, the Prism MCP server, the server handler, AG-UI, ACP, workflow nodes and supervisor children — no host branch; host authorization/selection deny before execution; abort kills owned children.
- New required peers: `@arnilo/prism-obscura` peers `@arnilo/prism` and `@arnilo/prism-web-tools` (reused citation/normalized shapes; `WebProvider` widened with `"obscura"`); `@arnilo/prism-obscura` also peers `@arnilo/prism-mcp`, `@arnilo/prism-browser`, and optional `playwright-core@1.61.0`.

## [0.3.1] - 2026-08-26

### Added
- **Release 0.3.1 (plan 034)** is the first Decision B independent patch: only `@arnilo/prism-rag`, `@arnilo/prism-memory`, and `@arnilo/prism-observability-opentelemetry` move `0.3.0 → 0.3.1`. Internal `^0.3.0` ranges stay valid; root and every other workspace package stay at their pre-plan versions. Production RAG engine (P1–P8):
  - **P1 transactional pgvector store** — `createPostgresVectorStore` (standalone) plus the existing `createPostgresMemoryStores().vectorStore` now implement `getBySource` + `transaction`. Additive DDL: `embedder_id` / `content_hash` / `generation`, `text_tsv` + GIN, HNSW when the embedding dimension is pinned, per-scope generation pointer table. Host names schema/table and owns the knowledge database.
  - **P2 hybrid retrieve** — `retrieveContext({ lexical: "fts" | "bm25" | "off" })` fuses vector + lexical legs with RRF (`fusion: "rrf"`, `rrfK` 60 / cap 1,000). Provenance `retrieval` is `vector` | `lexical` | `hybrid`. Stores advertise `lexicalModes`; unsupported `bm25` fails closed. `fuseReciprocalRank` / `tokenizeLexical` exported.
  - **P3 embedder identity** — `Embedder.id` is required and stamped as `embedderId`. Retrieve fails closed with `ERR_PRISM_RAG_EMBEDDER_MISMATCH` on id/dimension drift or legacy rows without an id (re-index path named). **TypeScript break for Embedder implementers** — add `readonly id: string`; see `docs/migration.md` `0.3.0 → 0.3.1`.
  - **P4 content-hash skip** — `replaceSource({ contentHash })` skips unchanged sources (`{ indexed: 0, skipped: true }`) and reuses embeddings when chunk text matches (`reuseEmbeddings`, `isValidContentHash`).
  - **P5 heading metadata** — `chunkMarkdown` stamps `metadata.heading` (parent-first ATX stack) unless the caller supplied one; parser metadata (`page`, `section`, …) copies onto chunks.
  - **P6 generation visibility** — `replaceSource` bumps a scope-level generation; retrieval filters to the current generation (legacy generation-less rows stay visible). `getCurrentGeneration` / `setCurrentGeneration` support rollback.
  - **P7 RAG telemetry** — dependency-free `RagTelemetry` seam; `createRagTelemetry()` in the OpenTelemetry package maps the `rag_request` / `rag_index` span tree. Span-name + `rag.*` allow-list drops raw chunk text.
  - **P8 TEI reranker** — `createTeiReranker({ baseUrl })` posts `{query, texts, raw_scores:false}` to host TEI `/rerank`, permutation-only, fail-closed parse, 65,536-byte ceiling, `pinnedFetch` default. SSRF/URL policy stays host-side.
  - **multi-scope retrieve** — `retrieveContext({ scopes: [org, user, session] })` embeds once, runs per-scope vector/lexical legs, fuses with one RRF, reranks once, and cuts `topK`. `scope` still valid; empty `scopes` returns zero hits with no embed/search/rerank (host “no allowed corpora” path). `HARD_RETRIEVE_SCOPE_CAP` is 8. Provenance carries `tenantId`/`resourceId`/`corpusId`. Telemetry: `rag.scope_count` + chunk tenant/corpus.
- Compat baselines regenerated (`--update-baseline`). Scanner sees additive exports only; the Embedder.id implementer break is documented, not a name-level removal. No `--allow-break`. Publication remains the operator handoff (`docs/release-and-install.md` `0.3.1 independent RAG engine patch` — package tags `@arnilo/prism-memory@0.3.1`, `@arnilo/prism-rag@0.3.1`, `@arnilo/prism-observability-opentelemetry@0.3.1`).

### Changed
- Store compatibility with 0.3.0: **compatible, additive**. New columns/indexes/tables are `IF NOT EXISTS`; 0.3.0 rows remain readable. Rollback = restore the 0.3.0 package versions (generation-less retrieve still works; heading/hash/telemetry/TEI simply disappear). No root/core persisted-shape change.

## [0.3.0] - 2026-08-20

### Added
- **Release 0.3.0 (plans 030, 031)** is the final lockstep cut and first independent-versioning line. The graph contains 57 publishable manifests; internal first-party ranges use `^0.3.0`, Decision B permits changed packages to patch/minor independently inside `<0.4.0`, and later publication uses `@arnilo/<package>@<version>` tags.
- Optional `@arnilo/prism-antigravity-agent` delegates autonomous coding sessions to the official Google Antigravity CLI (`agy`) with per-run loopback HTTP MCP capability exposure, AG-UI timeline projection, secret redaction, and `--conversation` continuation. Host owns the official binary and `agy login` authentication state.
- Optional `@arnilo/prism-computer-use-linux` wraps a host-owned Linux `computer-use-linux` MCP binary. DeviceAdapter admission is deny-by-default, setup tools are opt-in, mutating calls require approval/ExecutionPolicy, results are bounded and untrusted, input is serialized, and the package is omitted from umbrellas.
- Coding/ACP closeouts: `read.findText`, visible fuzzy edit outcomes and nearby miss context, ACP editor-buffer filesystem operations, spawnable per-session coding registries, and delete/move result locations.

### Changed
- Release automation keeps explicit `--lockstep --version 0.3.0` for the final cut, then defaults to changed-package validation/publication and package tags. No Changesets or new core runtime dependency.
- No persisted store migration. Live-service canaries and delegated Cursor adapter remain later demand-gated 0.3.x work.

## [0.2.9] - 2026-08-19

### Changed
- **Release 0.2.9 (plan 029)** is the provider-adoption and behavior-packages cut. **Additive-only.** New packages: `@arnilo/prism-provider-deepseek`, `@arnilo/prism-provider-xai` (API key + SuperGrok RFC 8628 device-code), `@arnilo/prism-provider-clinepass`, `@arnilo/prism-impeccable`. `pollDeviceCodeToken` accepts `bodyEncoding: "form"` and `extraDeviceParams`. Ponytail peer `^4.9.0` (empty `/ponytail` reports status). Caveman registers extra `SKILL.md`. Graph **55** publishable manifests at exact **0.2.9**. Store-compatible with 0.2.8; no migration. **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.9 publish handoff` — signed `v0.2.9` tag + npm OIDC).

## [0.2.8] - 2026-08-18

### Changed
- **Release 0.2.8 (plan 028)** is the ACP adoption-fixes cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.8: expected deltas are the version literal plus the plan 028 additive exports — `ToolKind`/`ToolDefinition.kind`, `AgentFinishReason`/`agent_finished.finishReason`, `AgUiProjectedImage`/`AgUiProjectedToolResult`/`createCodingToolProjection`, `AcpCommand`/`AcpCommandsSeam`, `ERR_PRISM_ACP_RUN`, `acpImageBytes`/`acpCommandsPerUpdate`, and the new `@arnilo/prism-acp-agent` package; zero removals; baselines regenerated with `--update-baseline`, no `--allow-break`). Client names are scrubbed from the tree and `scripts/check-client-neutrality.mjs` is wired into `npm run release:gate`. ACP bugs B1–B5: truthful `usage_update` via a host `contextWindow` seam (omit when unknown); run-level `error` rejects `session/prompt` with `ERR_PRISM_ACP_RUN` (no fake transcript chunks); only boolean config options are advertised/`set_config_option` (select fails `ERR_PRISM_ACP_CAPABILITY`); `tool_call.kind` prefers registry `ToolDefinition.kind`; permission docs match SDK wire kinds (`allow_always`/`reject_always`). Features F1–F10: thinking → `agent_thought_chunk`; bounded redacted transcript replay on `session/load`/`resume`; spawnable `@arnilo/prism-acp-agent` over stdio; `session/prompt` `StopReason` fidelity; UNSTABLE-gated `plan_update`/`plan_removed` from coding plan lifecycle; host-owned `session_info_update` titles; opt-in `createCodingToolProjection()` for first-party edit/write diffs+locations; projected `toolResult` images as ACP content/image blocks (`acpImageBytes`); host slash commands as `available_commands_update` (`acpCommandsPerUpdate`); Windows sandbox policy documented (native backend stays Linux-only, fail-closed). Release graph is **51** publishable manifests at exact **0.2.8** (root + 50 workspace; `+1` `@arnilo/prism-acp-agent`). Store compatibility with 0.2.7: **compatible, no migration**. Exit gate green (`sdk:ready`, `release:check` including the client-neutrality guard, audit 0 moderate, scan-secrets 0, SBOM regenerated). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.8 publish handoff` — signed `v0.2.8` tag + npm OIDC).

## [0.2.7] - 2026-08-17

### Changed
- **Release 0.2.7 (plan 027)** is the enterprise ERP production-readiness cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.7: expected deltas are the version literal plus the plan 027 additive exports — ERP outbox/inbox stores + bounded dispatcher, saga compensation/reconciliation engine, multi-party SoD approvals, signed hash-chained audit export with WORM/SIEM seams, field-level classification + fail-closed redaction, deterministic ERP invariant evals; zero removals; baselines regenerated with `--update-baseline`, no `--allow-break`; freeze manifest `scripts/phase27-freeze-manifest.json` records per-task evidence tokens, state machines, caps, the demand registry, measured HA/DR/classification/journey numbers, and the 0.3.0 blocker). Nine roadmap items with threat model ERP-T1–ERP-T10, ownership/tenant tests, no exactly-once claim, no implicit credential discovery, package budget, docs entries, and protected end-to-end evidence: (1) **transactional outbox/inbox** (`erp-messaging`, Task 1) — `ErpOutboxStore`/`ErpInboxStore` + bounded `ErpOutboxDispatcher` with claim-token CAS, `FOR UPDATE SKIP LOCKED`, `ON CONFLICT DO NOTHING` idempotent append, at-least-once delivery with explicit unknown-outcome, dead-letter/replay requiring verified tenant `AgentIdentity`; migrations 004 (`prism_erp_outbox`/`prism_erp_inbox`). (2) **saga compensation and reconciliation** (`saga`, Task 2) — `defineSaga`/`runSaga`/`resumeSaga` over existing CheckpointStore + LeaseStore with reverse-order compensation, unknown-outcome detection, manual resolution requiring verified identity + bounded reason + audit ref, stable tenant-scoped operation keys, redacted snapshots, `MAX_SAGA_STEPS=100`. (3) **multi-party SoD approvals** (`approvals`, Task 3) — `ApprovalStore` with role/quorum rules, requester/approver separation, any-party-veto rejection, delegated authority (max depth 8), expiry checked at every protected transition, atomic grant consumption in the host transaction, `policyRevision` pin denying on mismatch; migration 005 (`prism_erp_approvals`). (4) **tamper-evident audit export** (`audit-export`, Task 4) — `createAuditExporter` with WORM-then-SIEM ordering, hash-chained record envelopes (genesis 0x64 zeros), `verifyAuditBatch` independent verification, `AuditCursorStore` CAS, SIEM best-effort pending replay (8-entry cap), legal-hold flag preservation, RFC 8785 canonical JSON for digests. (5) **secret-manager adapters** (Task 5) — Vault/AWS/Azure/GCP stay **deferred** behind the demand gate (no named consumer; no adapter ships; `scripts/phase27-demand-gate.mjs` enforces zero ambient discovery). (6) **HA registries and recovery** (`ha-dr`, Task 6) — two-replica drill on real Postgres proves failover within lease TTL+5s (measured 4100 ms vs 9000 ms ceiling), idempotent outbox re-append on uncertain-commit replay, stale fence/revision write rejection, exactly-one lease owner, tenant isolation fail-closed. (7) **backup/restore/migration rollback evidence** (Task 7) — `pg_dump`/`pg_restore` custom-format backup (108,291 B / 122 ms / 382 ms restore), 0.2.6→0.2.7 migration forward+rollback rehearsed (5 migrations), PITR RPO 0 s / RTO 1 s (recovery 1163 ms); production rollback is roll-forward repair only (no down migrations). (8) **field-level classification and fail-closed redaction** (`field-policy`, Task 8) — `applyFieldPolicy`/`FieldPolicy`/`createProtectedFieldPolicy` at the redaction, audit-export, and OpenTelemetry seams; unknown-label deny-on-outbound fail-closed default, sparse-copy walker, measured overhead peak 99.8% of the redactor-walk baseline (cap 110%). (9) **ERP release journey** (`erp-evals`, Task 9) — `erpInvariantDataset` + `createErpInvariantScorers` (8 hard 0/1 gates consuming structured facts only) + `scripts/phase27-erp-journey.test.mjs` exercising identity/policy/budget/SoD-approval/outbox/saga-compensation/audit-export/legal-hold/classification/failover/restore end-to-end (4815 ms, all 8 invariants pass). Release graph stays **50** publishable manifests at exact **0.2.7**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.6: **compatible, additive** (two new ERP migrations 004/005 + outbox/inbox/approvals tables; rollback = stop 0.2.7 workers, restore the 0.2.6 manifests/tag — see `docs/migration.md` `0.2.6 → 0.2.7`). Exit gate green (core + script gates incl. `phase27-freeze` 9, `phase27-release` 12, `phase27-ha`/`phase27-dr`/`phase27-erp-journey` protected legs, coverage gate, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.7 — version literal + additive exports only, release-evidence manifest with zero blocked surfaces, evidence in `scripts/phase27-release-evidence.json`). **"ERP production ready" remains blocked until the 0.3.0 live-service matrix is recorded** — passing 0.2.7 gates unblocks the release cut, not the 0.3.0 live-service matrix. **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.7 publish handoff` — signed `v0.2.7` tag + npm OIDC).

## [0.2.6] - 2026-08-16

### Changed
- **Release 0.2.6 (plan 026)** is the fully-featured coding-agent-readiness cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.6: expected deltas are the version literal plus the Task 1-6 additive exports — PTY backend/handle types, the indexed-search seam, the workspace lifecycle, process/ACP recovery, the review manifest + diagnostics; zero removals; no `--allow-break`; freeze manifest `scripts/phase26-freeze-manifest.json` records per-task evidence tokens, state machines, caps, and the demand registry). Seven roadmap items with threat model T1-T8, ownership tests, no implicit activation, package budget, docs entry, and protected end-to-end evidence: (1) **host-selected PTY/interactive terminal backend** (`pty-backend`, plan 026 Task 1) — `createProcessSessions` gains an optional `ptyBackend` seam with explicit `capabilities.resize` (never duck-typed); `pty: true` without a backend fails byte-compatibly with `ERR_PRISM_PROCESS_PTY_UNSUPPORTED` before spawn; bounded terminal geometry/TERM/attach-timeout/resize-rate/metadata caps (`ERR_PRISM_PROCESS_PTY_LIMIT`), generic `ERR_PRISM_PROCESS_PTY_BACKEND` errors that never leak backend text, NUL rejected in PTY input as a policy error, terminal output stays untrusted with no parser/emulator, backend loss surfaces as `unknown` with `exitCode: null`. (2) **scalable indexed code-search seam** (`indexed-search`, Task 2) — `createIndexedRepositoryOperations` composes a host-owned incremental index backend (`update/remove/search/status/dispose`, `capabilities.semantic` explicit) with the bounded literal search as the unchanged default; `indexed_literal`/`semantic` modes fail closed on stale/failed/unsupported/untrusted indexes (`ERR_PRISM_INDEX_*`), no silent semantic-to-literal downgrade, results labeled `untrusted_index`, containment/score/snippet caps enforced, 100k-entry benchmark p95 <= 250 ms. (3) **ownership-scoped multi-repository and worktree lifecycle** (`workspace-lifecycle`, Task 3) — `createCodingWorkspaceLifecycle` over CheckpointStore CAS + LeaseStore fencing (`prism.coding-agent.workspace.v1` records, schemaVersion 1): deterministic `ws-` ids, locked worktrees with `prism-workspace:` reasons, credential-free remote fingerprints (sha256 of redacted URL + default branch, never the URL), idempotent create, verify revalidating repository/worktree identity, and a cleanup refusal matrix (dirty/locked/unowned/missing/mismatched/main) with `ERR_PRISM_WORKSPACE_*` codes; `GitOperations` gains worktree `lock`/`unlock` and `fingerprint()`. (4) **forge breadth demand-gated** (Task 4) — GitLab/Bitbucket adapters stay **deferred** in the demand registry (no named consumer/date/use case recorded), so no adapter source ships and the forge barrel contains no provider name; activation requires a recorded named consumer. (5) **durable ACP/live-task and managed-process recovery** (`durable-recovery`, Task 5) — `ProcessSessions` persists bounded intent/metadata before spawn in `prism.coding-agent.process.v1` records (never handles/env/tokens/raw output), serializes per-record transition CAS writes, and `recover()` is attach-if-attested reporting `attached|terminal|unknown` with no fabricated exit code and no PID probing; per-record leases (30 s/300 s) fence two replicas (split-brain conformance green on real Postgres); `PersistedAcpSession` gains an additive optional `activeRun` ref (0.2.5 records stay readable) and `createAcpRunRecovery` re-resolves status against `AgentRunLifecycle` (suspended keeps pending approval ids, unprovable in-flight -> unknown, never a restarted prompt) with durable ownership/version/fence-checked cancellation in `prism.coding-agent.cancel.v1` markers that never replays a pending/dispatched tool; `ERR_PRISM_RECOVERY_*` codes. (6) **bounded patch review and incremental diagnostics** (`review-diagnostics`, Task 6) — `createCodingPatchReviewManifest` builds a digest-bound manifest (patch sha256 + repository/worktree/base/head identity + changed paths/diffstat + checks + diagnostic summaries, never a raw patch body) composed over the server `ArtifactService`; `assertCodingPatchAccepted` derives `pending|accepted|rejected|superseded` bound to the exact artifact revision and digest, refuses stale acceptance, and never applies/commits/pushes/merges; `LanguageIntelligence` gains opt-in full-content `syncDocument` (monotonic versions) and `diagnosticDelta` (push/pull with resultId reuse, stale-version guards) plus `normalizeDiagnostics` with deterministic added/removed/unchanged deltas and host-supplied check parsers; LSP stays strictly opt-in (nothing spawns from tool factories or agent assembly). (7) **protected real coding journey** (`coding-journey`, Task 7) — `scripts/phase26-coding-journey.test.mjs` runs a packed consumer through real host services only (provider call, digest-pinned Docker sandbox, Postgres worktree lifecycle, provider-driven ACP edit with policy approval, named check + `diagnosticDelta`, patch review over the server artifact store, cross-replica process recovery, durable cancellation, real GitHub push/lookup-before-create PR/reconcile/cleanup, host Playwright inspection, host PTY adapter in the frozen profile) under the frozen wall/cleanup ceilings with run-suffix side effects and per-step idempotent cleanup; missing credentials/services or skipped substeps record `blocked`, never a passing skip; the retained `scripts/phase26-coding-journey-report.json` carries timings/states/ids only and gates release evidence (pass/blocked/protected). Release graph stays **50** publishable manifests at exact **0.2.6**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.5: **compatible, additive** (three new versioned record namespaces + the optional ACP `activeRun` field; rollback = stop 0.2.6 workers, mark active PTY/process/recovery records unknown, restore the 0.2.5 manifests/tag — see `docs/migration.md` `0.2.5 → 0.2.6`). Exit gate green (core + script gates incl. `phase26-freeze` 11, `phase26-index-benchmark`, coding-agent 348 + ag-ui 203 workspace suites, coverage gate, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.6 — version literal + additive exports only, protected Postgres recovery/workspace conformance 8/8, protected PTY leg 4/4, protected real coding journey per the retained report, release-evidence manifest with zero blocked surfaces, evidence in `scripts/phase26-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.6 publish handoff` — signed `v0.2.6` tag + npm OIDC).

## [0.2.5] - 2026-08-15

### Changed
- **Release 0.2.5 (plan 025)** is the maintainability-and-bounded-performance cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.5: expected deltas are the version literal plus 105 additive internal-helper exports — 84 Task 1 cross-family helpers across core/coding-agent/workflows/server/ag-ui and 21 `prism-session-store-codecs` helpers; zero removals; no `--allow-break`). Five roadmap items, no runtime contract change and no migration: (1) **god-module splits** (`god-module-split`, 0.1.4 precedent) — the six remaining implementation god-modules split along cohesive boundaries into internal family files behind preserved barrels: `src/contracts-core.ts` (1,719 L → 10 families, max 403 L), `src/agent-session.ts` (2,049 L → 4 modules; the 1,686-L `RuntimeAgentSession` class kept intact — a single TS class cannot span files without exporting private methods, recorded reason), `packages/workflows/src/run.ts` (1,227 L → 6 families, max 417 L), `packages/server/src/handler.ts` (1,005 L → 8 families, max 444 L), `packages/coding-agent/src/repository.ts` (974 L → 7 families, max 299 L), `packages/ag-ui/src/acp/agent.ts` (836 L → 8 families, max 386 L); no `exports`-map subpath added; `ponytail:` comments preserved; zero breaking compat deltas (`scripts/phase25-compat-diff.mjs`). (2) **persistence-mechanics dedup** (`session-store-codecs`) — 21 pure helpers (ownership scope/assertion, checkpoint stale/encode/decode, branch cursors, lifecycle quota/reason/page-limit, search metadata/clipping, deepFreeze/string-array/throwIfAborted, feedback row mapping) moved into the dependency-free codecs package (426 → 624 L, stdlib only); the postgres/sqlite adapters shrank 273 lines total; SQL dialect/DDL/query execution stay per-adapter; no persisted-shape change; cross-store conformance green before/after. (3) **quadratic accumulation removed** (`bounded-accumulation`) — the per-push `Buffer.concat` loops in `LspFrameReader` (language framing) and `summarizeTarStream` (tar parsing) became chunk-array readers (two-phase header parse, offset-advance drop, take/drop sliding window); caps + fail-closed overflow byte-identical; framing ~100–200× faster at 4,000 chunks (1,298.4 ms → 11.2 ms), tar linear at 8 MiB; CLI `collectOutput` audited and kept (already linear, plan 020); the 10-test near-limit probe `scripts/phase25-bounded-accumulation.test.mjs` is wired into the npm test gate segment and asserts linear copying by byte-count instrumentation. (4) **dead-code cleanup, internal-only** (`dead-code`) — the 62 `dead-exports.mjs` candidates triaged in `docs/_evidence/phase25-dead-exports-triage.md`: 2 internal removals (`PostgresPersistenceCloseOptions`, `SqlitePersistenceCloseOptions` — never re-exported from their adapter indexes), 37 test-used false positives, 20 dead-but-compat-tracked + 3 public type aliases deferred to the 0.3.0 breaking cut; the named-internal audit (`agent-session`/`cache-telemetry`/`skill-load`) recorded clean at 0.2.4; no public export removed. (5) **coverage close, behavior-backed** (`coverage`) — 76 focused regressions (approval 43, conversations 22, artifacts 6, tool-effect-store conformance 5; compaction via its 17 existing package suites); core coverage 90.53/84.20/90.54 → **91.43/84.80/91.60** lines/branches/functions (gate 60/70/75; all 39 non-protected packages above their evidence thresholds). Release graph stays **50** publishable manifests at exact **0.2.5**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.4: **compatible, no migration** (no persisted-shape change; rollback = restore the 0.2.4 manifests/tag — downgrade is store-safe and code-safe, the added exports simply disappear). Exit gate green (core + script gates incl. `phase24-truth` 12 + `phase25-bounded-accumulation` 10, coverage gate, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.5 — version literal + additive exports only, protected Postgres durable + cross-store conformance evidence per the release skip manifest, release-evidence manifest with zero blocked surfaces, evidence in `scripts/phase25-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.5 publish handoff` — signed `v0.2.5` tag + npm OIDC).

## [0.2.4] - 2026-08-14

### Changed
- **Release 0.2.4 (plan 024)** is the package-documentation-and-compatibility-truth cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.4: delta is the version literal only). Truth remediation, no runtime contract change: (1) **umbrella wording matches manifests** — `@arnilo/prism-providers` states 11 of 14 first-party provider adapters (Azure/Bedrock/Vertex are added separately by `@arnilo/prism-all`; its install list was corrected from 9 to the full 11 — alibaba and ollama were missing) and `@arnilo/prism-all` states 20 direct / 43 transitive packages with the complete omission set (document-reader, OpenAPI tools, NATS, Caveman, Ponytail); membership unchanged in 0.2.x (§0.3.0 owns expansion). (2) **manifest-derived package truth** — dependency-free `scripts/package-truth.mjs` → `scripts/package-truth.json` becomes the single source for counts (50/49/14/9/26), provider membership, umbrella closures, and profile closures; the count/tarball/current-line docs literals were regenerated from it; `scripts/phase24-truth.test.mjs` asserts generator reproducibility, committed-artifact equality, count/closure correctness, and fail-closed behavior on malformed manifests and unmatched workspace globs. (3) **peer-version policy Decision A** — exact `@arnilo/prism: <current>` pins remain through 0.2.x with the atomic-upgrade rule (all `@arnilo/prism-*` packages move at the same version; partial upgrades are unsupported and fail clearly with npm ERESOLVE); the range widens to `^1.0.0` at the 1.x stable release; documented in `docs/release-and-install.md` + `docs/migration.md`. (4) **current-line truth** — `docs/0.1.0-readiness.md` and `docs/index.md` current-line blocks refreshed to the 0.2.x line, with 0.1.7 recorded as the terminal 0.1.x baseline and the 0.1.1/0.1.0 tables demoted to historical record. Release graph stays **50** publishable manifests at exact **0.2.4**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.3: **compatible, no migration** (no persisted-shape change). Exit gate green (core + script gates incl. `phase24-truth` 12 tests, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.4 — version literal only, protected Postgres durable conformance evidence per the release skip manifest, release-evidence manifest with zero blocked surfaces, evidence in `scripts/phase24-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.4 publish handoff` — signed `v0.2.4` tag + npm OIDC).

## [0.2.3] - 2026-08-14

### Changed
- **Release 0.2.3 (plan 023)** is the build-coverage-and-release-evidence-integrity cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.3: delta is the version literal only — no export changes; baselines regenerated with `--update-baseline`, no `--allow-break`; freeze manifest `scripts/phase23-freeze-manifest.json` records per-task evidence tokens). Four tooling/evidence fixes, no runtime contract change: (1) **build serialization** (`build-serialization`, core tooling) — dependency-free `scripts/with-build-lock.mjs` holds one O_EXCL lockfile at `node_modules/.prism-build.lock` (pid + startedAt, read-back verified, stale-PID reclaim via `process.kill(pid, 0)`, 100 ms backoff to env-overridable `PRISM_BUILD_LOCK_TIMEOUT_MS` default 120 s, fail-closed exit 1) around every emit/test leaf (root `build:core`, both `node --test` segments, `test:coverage` leaves, coverage summary, all 43 workspace build/test/`test:postgres` scripts) so concurrent compilers and importers can never observe a partially emitted `dist/` — the 2026-08-12 review defect that 0.1.1's destructive-clean removal did not close; the lock is never held by orchestrator scripts, `PRISM_BUILD_LOCK_HELD=1` prevents accidental nesting, and the direct-`tsc` caveat is documented in `docs/release-and-install.md`. (2) **corrected workspace coverage denominators** (`coverage-denominators`, `scripts/coverage-summary.mjs`) — workspace coverage runs now pass package-local `--test-coverage-include=dist/**` so imported core `dist/` no longer pollutes package rows (`mcp` 45.47→90.25, `rag` 19.70→94.82, `memory` 20.37→72.00, `session-store-nats` 16.04→93.69, `enterprise-postgres` 21.93→43.26; `session-store-postgres` stays 22.89 as the protected durable-leg proof); the 60/70/75 core gate is unchanged; evidence-based per-package line thresholds in `scripts/coverage-thresholds.json` (freeze-run percentages minus 3 pp) with `protectedException` entries for the env-gated durable-leg packages (`session-store-postgres`, `enterprise-postgres`, `memory`, `session-store-nats`) shown separately; the machine-readable `scripts/coverage-summary.json` artifact records per-package lines/branches/functions/denominator files/threshold/pass-fail and the gate exits 1 on any non-protected below-threshold package. (3) **machine-auditable release skip manifest** (`skip-manifest`, `scripts/release-skip-manifest.mjs` → `scripts/release-evidence.json`) — every release surface (core `npm test`, each workspace suite, threat suites, `test:postgres` durable conformance, provider live legs, NATS real legs, the four live canaries) records `pass`/`skip`/`blocked`/`protected` with reason and required env names only (never secrets); the 33 protected/live skips are named; a required surface with absent evidence records `blocked` and `scripts/release.mjs` gate fails closed (`checkReleaseEvidence`) — missing credentials/services can never convert into a green release; the artifact is CI-retained and gitignored. (4) **stabilized quality gates** (`quality-gates`) — `biome.json` migrated to the 2.x canonical `linter.rules.preset: "recommended"` (deprecated key removed) and all 97 lint diagnostics resolved to zero (safe + reviewed `--unsafe` fixes across 108 files, 10 hand-removed dead `_`-renamed variables, 5 justified `biome-ignore` comments for shell-interpolation probes/verbatim fixtures/grep targets); the racy 150 ms MCP bridge timing assertion became a deterministic awaited-outcome barrier with a test-level timeout, and kept load-sensitive guards carry documented `ponytail:` ceilings; `npm run lint` writes machine-readable `scripts/lint-report.sarif` and `npm run sweep:unused` writes `scripts/unused-report.json`, both retained by the release workflow. New regression surface: `scripts/phase23-build-race.test.mjs` (8 lock/stress tests incl. synthetic partial-`dist` sensitivity, stale-lock reclaim, live-lock fail-closed), `scripts/phase23-coverage.test.mjs` (4 tests: include-filter + core-gate greps, thresholds JSON validation, real-artifact denominator proof, sabotaged fail-closed run), `scripts/phase23-skip-manifest.test.mjs` (6 tests: blocked-not-skip, protected-named with the frozen 33-skip floor, live-canary-not-pass, unexplained-skip-rejected, no-secret, wiring), `scripts/phase23-quality-gates.test.mjs` (5 tests: lint clean, preset config, timing quarantine, biome-ignore reasons, machine-readable reports), and `scripts/phase23-security.test.mjs` (3 tests: matrix item 4 concurrent emit+public-entry importer, matrix item 12 coverage denominator + protected rows, gate accounting — built public entrypoints, wired into `security:threat-suites`) plus the packed plain-JS `security23.mjs` consumer in install-smoke. Release graph stays **50** publishable manifests at exact **0.2.3**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.2: **compatible, no migration** (no persisted-shape change). Exit gate green (core + script gates incl. phase21-freeze done-phase + all phase23 suites, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.3, protected Postgres durable conformance evidence, release-evidence manifest with zero blocked surfaces, evidence in `scripts/phase23-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.3 publish handoff` — signed `v0.2.3` tag + npm OIDC).

## [0.2.2] - 2026-08-13

### Changed
- **Release 0.2.2 (plan 022)** is the concurrent-state-and-durability-integrity cut on the 0.2.x review-remediation line. API surface **additive-only** vs 0.2.1 (plain reviewed compat gate at 0.2.2: deltas are the version literal plus `ModelRouterStateStore.reserveBudget`/`commitBudget`/`releaseBudget`, `ModelRouterReservation`, `ModelRouterBudgets.reservationTtlMs`, `ModelRouterLimits.maxRateKeys`/`maxBudgetKeys`, `SessionRecord.version` with `appendSession` `expectedVersion`, `EventMultiplexerError` `ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER`, and the `@arnilo/prism/testing/state-concurrency-conformance` subpath; no removal; no `--allow-break`), four behavior tightenings documented in `docs/migration.md` `0.2.1 → 0.2.2`: (1) **atomic model-budget reservation** (`budget-reservation`, `@arnilo/prism-model-router` + `@arnilo/prism-enterprise-postgres`) — admission now runs `reserveBudget` (used + reserved + requested <= window max, `{reservationId, fencingToken, admitted, retryAfterMs?}`) and outcomes run `commitBudget` (actuals; a TTL-expired late commit charges the reserved amount with `unknownUsage: true`) or `releaseBudget`; reservations expire after `reservationTtlMs` (default 60 s, bounded to 31 days) so a crashed request never holds capacity forever; 0.2.1 `readBudget`/`addUsage` remain for cap-less requests and retrospective accounting, no longer admission authority; rate/budget key maps are capped (`maxRateKeys`/`maxBudgetKeys` 4,096 default / 65,536 hard; circuits unchanged) with LRU eviction that never drops a held-reservation row (capacity-exhausted fail-closed otherwise); durable store keeps reservations in a `reservations` JSONB column (enterprise migration 003, forward-only, checksummed). (2) **atomic conversation metadata** (`conversation-metadata-cas`, `@arnilo/prism-session-store-postgres` + `@arnilo/prism-session-store-sqlite`) — `SessionRecord.version` (fresh rows start at 1; migration 008 backfills legacy rows) and `appendSession` `expectedVersion` (`0` create-only, `N>0` exact-CAS update-only, omitted = 0.2.1 last-write-wins); stale writes throw `SessionMetadataConflictError` `metadata_conflict` carrying only `{id, expectedVersion, currentVersion}` (never metadata content), HTTP 409; concurrent create/branch/archive are single-statement with branch caps enforced inside the CAS write, archive wins over stale writers, retention-deleted rows are never resurrected. (3) **single-consumer EventMultiplexer** (`single-consumer`, core) — a second concurrent `subscribe()` throws `EventMultiplexerError` `ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER` instead of silently sharing one queue and losing events; slot frees on completion/return-at-yield/close; in-repo consumers (workflow bus, supervisor) already single-subscriber. (4) **restart-stable NATS durable identity + bounded non-durable active-run registries** (`nats-durable`, `@arnilo/prism-session-store-nats`; `active-runs`, `@arnilo/prism-workflows`) — the durable consumer name is exactly `prism_<hmac16 of tenantId|sessionId|runId>` (random suffix removed) so a crash-resumed subscribe continues from the last ack; clean stops delete the consumer (cursor resume), orphaned 0.2.1 `prism_<digest>_<random>` consumers are reclaimed by the existing cleanup; the workflow active-run registry sweeps aborted/leaked entries on register and fails closed at the 512 cap (`ERR_PRISM_WORKFLOW_RUN_REGISTRY_OVERFLOW`), documented non-durable. New regression surface: `scripts/phase22-security.test.mjs` (5 tests: 4 blockers + gate accounting, built public entrypoints, wired into `security:threat-suites`), the packed plain-JS `security22.mjs` consumer in install-smoke, the `@arnilo/prism/testing/state-concurrency-conformance` harness (7 probes — approval, cursor, checkpoint CAS, idempotency, router reservation, conversation metadata, unknown-outcome — memory leg in npm test, durable legs in `test:postgres`/NATS seam, zero timing-only sleeps), and the `scripts/phase22-conformance.test.mjs` gate in the `test:postgres` chain; phase-22 evidence in `scripts/phase22-baseline.json` + `scripts/phase22-freeze-manifest.json`. Release graph stays **50** publishable manifests at exact **0.2.2**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.1: **forward-only migrations** (`prism_sessions.version` migration 008, `prism_model_router_budgets.reservations` enterprise migration 003; 0.2.1 databases migrate in place, 0.2.1 binaries read 0.2.2 databases but ignore the new columns — see `docs/migration.md` rollback-risk). Exit gate green (core + script gates incl. phase21-freeze + phase22 conformance, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.2, protected OIDC/OPA + durable state-concurrency evidence, evidence in `scripts/phase22-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.2 publish handoff` — signed `v0.2.2` tag + npm OIDC).

## [0.2.1] - 2026-08-13

### Changed
- **Release 0.2.1 (plan 021)** is the provider-completion and outbound-trust-boundaries cut on the 0.2.x review-remediation line. API surface **additive-only** vs 0.2.0 (plain reviewed compat gate at 0.2.1: deltas are the version literal plus `@arnilo/prism-mcp` transport helpers re-exported from the lifted core primitives — same names/signatures, no removal; no `--allow-break`), five documented security-motivated behavior tightenings in `docs/migration.md` `0.2.0 → 0.2.1`: (1) **strict stream completion is the shared default** (`strict-completion`, core `createOpenAICompatibleProvider`) — `strictCompletion` defaults to `true` (explicit `false` stays the documented opt-out): a stream ending without `[DONE]` plus a choice-level `finish_reason` now fails with `ProviderTransportError` `incomplete_delta` instead of a successful `providerDone`, and done events carry usage only with completion evidence; applies to Azure, Bedrock, Vertex, OpenRouter, ZAI, NeuralWatt (Alibaba/Kimi/Ollama/OpenCode-go had already opted in). (2) **bounded success bodies** (`bounded-bodies`, core `@arnilo/prism/providers/transport`) — additive `readBoundedResponseJson` (65,536-byte UTF-8 ceiling, max JSON depth 32, max properties 4096, caller shape gate, abort, redacted errors, new `ProviderTransportError` code `response_body_shape`) replaces unbounded `response.json()` at all ten model-discovery sites plus NeuralWatt quota, Alibaba embeddings, OpenAI uploads, and both OAuth success paths. (3) **DNS-pinned OIDC/OPA/content fetch, redirects rejected** (`dns-pinning`, core `src/pinned-fetch.ts` + `@arnilo/prism-credentials-node`, `@arnilo/prism-policy`, `@arnilo/prism-mcp`) — `pinnedFetch`/`resolvePinnedAddress`/`requestPinned` lift the MCP pinning algorithm (one resolve, 1–32 bound, family check, loopback confinement, per-candidate `assertSsrfAllowedUrl`, pinned-lookup socket) into core; default JWKS, OPA decision, and content/media fetches route through it and **reject 3xx redirects outright** (`MediaContentError` code `redirect`); private/metadata/loopback answers fail closed `ssrf_denied`; MCP re-exports the lifted helpers with byte-identical behavior; egress `dns-pin.ts` deliberately NOT converged (0.3.x candidate). (4) **shared bounded OAuth device/token polling** (`oauth-consolidation`, core `src/oauth-device-code.ts`) — `pollDeviceCodeToken` serves both `@arnilo/prism-provider-openai` and `@arnilo/prism-credentials-node` device flows (RFC 8628 poll, `slow_down` +5 s, expiry deadline, cancellation, bounded reads, fail-closed token shape, `[REDACTED]` redaction); adapter fields stay plain options; behavior equivalent. (5) **edge fixes** (`edge-fixes`) — Azure/Vertex resolve rotating credentials **once per request** (inner provider re-created with the resolved token; never consumed twice); Bedrock SigV4 merges duplicate-case headers last-wins and sorts query params by encoded key then value (malformed duplicate-case signatures eliminated, single-case byte-identical); OpenAI upload cleanup retains file ids until their `DELETE` succeeds (no remote-file leak on failed cleanup); cache-telemetry `__overflow__` never carries cost (requests + token totals only). New regression surface: `scripts/phase21-security.test.mjs` (10 conformance tests over built public entrypoints covering all five items, wired into `security:threat-suites`) plus a packed plain-JS `security21.mjs` consumer in install-smoke; phase-21 freeze manifest `scripts/phase21-freeze-manifest.json` machine-checks each task's diff (preserved surface: egress dns-pin primitives, OAuth connector consumers, strictCompletion opt-in adapters, native streaming adapters). Release graph stays **50** publishable manifests (root + 49 workspace packages) at exact **0.2.1**; zero new runtime dependency names (core remains dependency-free). Store compatibility with 0.2.0: **compatible, no migration** (no persisted-shape change). Exit gate green (core + script gates incl. phase21-freeze done-phase, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.1, live OIDC JWKS protected evidence + live OPA fail-closed evidence, evidence in `scripts/phase21-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.1 publish handoff` — signed `v0.2.1` tag + npm OIDC).

## [0.2.0] - 2026-08-13

### Changed
- **Release 0.2.0 (plan 020)** is the first cut of the 0.2.x review-remediation line — fail-closed runtime and sandbox security, closing the three blockers from the 2026-08-12 comprehensive review. API surface **additive-only** vs 0.1.7 (plain compat gate at 0.2.0: 0 breaking deltas; no `--allow-break`), three documented security-motivated behavior tightenings in `docs/migration.md` `0.1.7 → 0.2.0`: (1) **durable-resume input validation** (`resume-validation`, core) — `assertValidAgentRunResume` runs once at the top of `prepareAgentRunResume` before any state claim/checkpoint write/tool execution, covering all four public resume entrypoints; unknown legacy decisions (`"sideways"`), malformed batches, oversized reasons/elicitation, and duplicate approval ids fail closed with stable `ERR_PRISM_DECISION_*` codes, version untouched, zero tool calls; the server parser stays defense in depth. (2) **work-tool environment isolation** (`work-tools-env`, `@arnilo/prism-work-tools`) — `createCliRunner` children no longer inherit ambient host env: fixed base allow-list (PATH/LANG/LC_ALL/TZ + Windows system keys), explicit validated `env`, forced HOME/telemetry controls, late-bound per-identity tokens, 64-name/64-KiB caps (`ERR_PRISM_WORK_ENV`), absolute `binary`/`configDir` required, linear output capture (single final `Buffer.concat`). (3) **explicit sandbox capabilities** (`sandbox-capabilities`, `@arnilo/prism-coding-security`) — `SandboxAdapter.capabilities` (`workspaceCoherent`/`filesystemIsolated`/`networkIsolated`/`processIsolated`/`privilegeIsolated`/`egressRestricted`); omission/malformed metadata resolves all isolation `false`; `SandboxCodingComposition.capabilities` resolved from real wiring + validated adapter metadata; `containmentClaim` retained as `@deprecated` conservative projection (`workspaceCoherent && filesystemIsolated && networkIsolated && processIsolated`); Docker reports only verified controls, native reports filesystem/process/privilege `false`; authorization reads individual capabilities (docs/coding-security.md capability table + docs/host-security.md). New regression surface: `scripts/phase20-security.test.mjs` (public built entrypoints, all three blockers + gate accounting, wired into `security:threat-suites`), packed plain-JS consumer regressions in install-smoke, and the sandbox-browser workflow now records Docker/native capability evidence with a fail-loud 0.2.0 blocker gate (never a passing skip). Release graph stays **50** publishable manifests (root + 49 workspace packages) at exact **0.2.0**; zero new runtime dependency names (dependency fingerprint unchanged). Store compatibility with 0.1.7: **compatible, no migration** (no persisted-shape change). Exit gate green (core + script gates incl. phase20-freeze done-phase, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain reviewed compat gate at 0.2.0, Docker daemon + native netns protected evidence, evidence in `scripts/phase20-baseline.json`). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.2.0 publish handoff` — signed `v0.2.0` tag + npm OIDC).

## [0.1.7] - 2026-08-12

### Changed
- **Release 0.1.7 (plan 019)** is the performance-and-DX patch on the frozen 0.1.x line — additive-only vs 0.1.6 (freeze manifest `scripts/phase19-freeze-manifest.json`; every task's diff stayed inside its allowed files, enforced by the phase19 freeze machine; the async `AgUiProjection` item is a verification closeout, not new code). (1) **Prompt-cache telemetry surface** (`cache-telemetry`): dependency-free `createCacheTelemetry()` aggregator in core — host-activated (nothing subscribes by import), consumes `Usage` + `ModelConfig` pairs from the usage `ProviderEvent` or run-ledger records, and reports per-provider/model request counts, aggregate hit rate via the existing `cacheHitRate` math, cache-read/write token totals, and estimated savings via `cacheSavings` when cost metadata exists; bounded cardinality (default cap 256 distinct provider/model keys, overflow collapses into the `CACHE_TELEMETRY_OVERFLOW_KEY` `__overflow__` bucket with an `overflowed` flag, ponytail ceiling named — host-configurable caps or LRU eviction only if a real deployment exceeds it); reports carry token counters/rates only — never prompt content, cache keys, or identity; `record()` is O(1) with validated finite non-negative inputs; no OTel metric emission (demand-gated follow-up). (2) **Model-router selection policies** (`router-selection`): additive `selection` hook on `CreateModelRouterOptions` — `ModelRouterSelectionPolicy` (`name`/`rank`/`observe`); default ordered behavior byte-identical (regression test); reference `createCostLatencySelection` ranks candidates by `ModelCost` (input/output/cacheRead with per-million normalization) then in-memory EMA latency fed from `recordOutcome`'s new optional `latencyMs` (`latencyWeight` 0–1, default 0.5; pure-cost order on cold start); the policy is a permutation-only reorder of already-allowed candidates so it cannot widen allow-list/residency/budget decisions, and any drop/add/duplicate misbehavior fails closed with `ERR_PRISM_MODEL_ROUTER_POLICY`; policy name rides the still-redacted diagnostics; durable latency stats are a demand-gated follow-up requiring a `ModelRouterStateStore` contract change. (3) **Async AgUiProjection closeout** (`async-hooks`): plan 009 Task 15 surface verified with evidence — hooks are typed `Awaitable<T>` (17 hooks), `getMessages` accepts `() => readonly AgUiMessage[] | Promise<...>` so `messagesFromSession` can call async host APIs like `session.entries()`, snapshots are awaited strictly in event order (never `Promise.all`), rejection fails closed per event with sibling hooks still projected, caps apply to awaited values; evidence in `scripts/phase19-baseline.json` `asyncHooks` (`verified: true`, `gapFound: false`). (4) **`prism providers add <name>` scaffold** (`provider-scaffold`): new CLI subcommand (stdlib-only, mirrors `prism init`) scaffolds an OpenAI-compatible provider package into `./<name>` — `package.json` (peer dep `@arnilo/prism`, `sideEffects: false`, publish metadata), `tsconfig.json`, `README.md`, `CHANGELOG.md`, `src/index.ts` (`defineProviderPackage` + `api_key` auth-method registration), `src/provider.ts` (built on `createOpenAICompatibleProvider`), `src/models.ts` (starter `ModelConfig` list), `src/cache.ts` (cache-hint mapping via the shared core helpers), `src/__tests__/provider.test.ts` (offline conformance: stream shape + usage, header ownership, tool-call delta reconstruction, serialized-content coverage, secret-leak redaction), and `docs/providers/<name>.md` stub; flags `--base-url` (http(s) validated), `--env-key` (shell-safe identifier), `--model`, `--force`; npm package-name validation, path-traversal and symlink-escape refusal (nothing can land outside the destination), usage errors exit 2 with nothing written, generated code contains placeholders only — never secrets; scaffold output is host-chosen and never auto-registered into repo workspaces or resolvers; a fixture test proves the generated package typechecks and passes its conformance test offline against the repo build. Release graph stays **50** publishable manifests (root + 49 workspace packages — 14 provider adapters, 9 `prism-*` family/profile, 26 capability incl. `@arnilo/prism-document-reader`) at exact **0.1.7**. Exit gate green (core tests + script gates incl. phase19-freeze done-phase, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain compat gate at 0.1.7 with 0 breaking deltas then version-literal baseline refresh — no `--allow-break` anywhere, evidence in `scripts/phase19-baseline.json`). Store compatibility with 0.1.6: **compatible, no migration** (additive-only; no persisted-shape change; `docs/migration.md` gains no entries). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.1.7 publish handoff` — signed `v0.1.7` tag + npm OIDC). **CI hardening after the exit gate** (same day): the release `verify` job now runs the sdk:ready legs phase-by-phase (explicit rc per leg so a silent failure still names the failing phase) and uploads `sdk-ready.log` as an artifact on failure; the examples demo test compiles the demos in place with the repo tsc before spawning them, so the spawned children are plain JS instead of loading the amaro type-stripping WASM module (whose large per-process virtual reservation fails with `WebAssembly.Instance(): Out of memory` on memory-constrained CI runners); emitted .js files are removed in a finally block.

## [0.1.6] - 2026-08-11

### Changed
- **Release 0.1.6 (plan 018)** is the coding-agent capability-closeouts patch on the frozen 0.1.x line — five demand-gated closeouts, all shipped, additive-only vs 0.1.5 (freeze manifest `scripts/phase18-freeze-manifest.json`; every closeout flipped to `demanded` by named demand evidence before its task landed, then the demand-gate registry validated demanded ⇒ implemented, deferred ⇒ untouched). (1) **Durable ACP session store** (`acp-session-store`): `@arnilo/prism-ag-ui` gains the host-owned `AcpSessionStore` seam on `CreatePrismAcpAgentOptions` — `save` (upsert on session/new, set_mode, set_config_option, never on cancel/prompt-end), `loadAll` (lazy, once per agent instance, after authorization, cross-tenant entries refused `ERR_PRISM_ACP_INPUT`), `evict` (on close/delete); the persisted entry shape `{sessionId, ownership, modeId, configValues, cwd, additionalDirectories, updatedAt}` deliberately excludes client/controller/budget/pending state; fail-closed restore drops corrupt/oversized entries, re-validates modes/config options, keeps the in-memory registry caps (32 default / 128 hard), and re-resolves the live session binding; absent seam = byte-identical 0.1.5 in-memory behavior; the whole persisted entry rides the optional `SecretRedactor` at the save boundary. (2) **Network-free native sandbox backend** (`native-sandbox`): `@arnilo/prism-coding-security` gains `createNativeSandbox` — spawn + POSIX rlimits + existing path containment, zero new dependencies; every command runs in a fresh network namespace via the OS `unshare` binary (plain or `--map-root-user` preflighted once at creation, fail-closed on macOS/Windows and where netns cannot be created), ulimit chains (`-v`/`-t`/`-n`) with `|| exit 126`, argv-only `exec` (never shell-interpolated), cwd containment via `assertPathInsideRoots`, process-group kill on timeout/abort, env allow-list (host env never inherited), output cap, `close({export})` tar parity, and a documented honest boundary (runs as the invoking OS user; egress denial + rlimits + cwd containment only). (3) **Bounded PDF/Office document reader** (`doc-reader`): new optional package `@arnilo/prism-document-reader` (the 50th publishable manifest) — `createDocumentReader({ maxBytes, maxPages, maxTextBytes, parsers })` behind optional peer parsers `pdf-parse`/`mammoth` (dynamic-import, fail-closed at creation with an install hint when absent), magic-byte format gating (never extension sniffing), null fall-through to the 0.1.5 text path, refuse-over-truncate for over-page PDFs, byte-safe text truncation, optional `SecretRedactor` at the adapter boundary, no embedded-content execution, no external resource fetch (egress tripwire test), extraction envelope recorded in `scripts/budgets.json`; `createReadTool` gains the additive `documentReader` slot with input/page/text caps re-checked in the read flow. (4) **Recursive delete + brace-expanding glob** (`delete-glob`): `delete` gains the per-call opt-in `recursive: true` (symlink children unlinked never followed, iterative post-order walk, per-call fan-out cap 10,000 default / 100,000 hard, partial deletion reported never silent, `maxEntries` bound); `glob` gains host-selected + per-call `braceExpansion` (`{a,b}` textual expansion, max 128 alternatives / 4096 expanded bytes, unbalanced/nested/empty braces and overflow fail closed, default matcher semantics unchanged). (5) **Checkpoint persistence for loaded-skill bodies** (`checkpoint-bodies`): durable runs may set `includeSkillBodies: true` on BOTH run and resume options (alongside `persistSessionState`) — the exact loaded-skill instructions ride the checkpoint (`{name, instructions}` pairs, ≤64 bodies / ≤256-char names / ≤262144-byte bodies / ≤1 MiB total, validated fail-closed on save and load, redacted at rest) so resume re-renders them registry-independently with no `load_skill` round-trip; names-only stays the default and 0.1.3/0.1.2 checkpoint shapes are byte-identical; `maxStateBytes` refuses oversize bodies with a recorded error, never truncates. Release graph **50** publishable manifests (root + 49 workspace packages — 14 provider adapters, 9 `prism-*` family/profile, 26 capability incl. `@arnilo/prism-document-reader`) at exact **0.1.6**. Exit gate green (core 1,433/1,433 + 190 script gates incl. phase18-freeze done-phase, `sdk:ready`, audit 0 moderate, pack dry-run 50/50 twice byte-identical, plain compat gate at 0.1.6 with 0 breaking deltas then version-literal baseline refresh, evidence in `scripts/phase18-baseline.json`). Store compatibility with 0.1.5: **compatible, no migration** (additive-only; no persisted-shape change). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.1.6 publish handoff` — signed `v0.1.6` tag + npm OIDC).

## [0.1.5] - 2026-08-11

### Changed
- **Release 0.1.5 (plan 017)** is the **documented breaking cut** on the frozen 0.1.x line — deprecated-option removal with the full removed-symbols list, replacements, before/after examples, dynamic-config refusal behavior, store compatibility, and rollback in the top `docs/migration.md` `0.1.4 → 0.1.5` section (three stale roadmap labels corrected there: `RunOptions.maxToolRounds` not `AgentConfig.maxToolRounds`, `autoResizeImages` removed with `transformImage` retained, `INIT_PROVIDERS` removed with `listInitProviders()` retained). (1) **Provider run-option aliases** (Task 1): `ProviderRequestOptions.timeoutMs`/`maxRetries`/`maxRetryDelayMs` (inert in first-party providers; host-side abort/retry is the replacement — `RunOptions.signal`, `AgentConfig.retry`/`RunOptions.retry`) and `RunOptions.maxToolRounds` (→ `limits.maxToolRounds`, defaults/caps unchanged) removed; untyped legacy run input is refused at the `runInternal` choke point before the agent starts; CLI `--max-tool-rounds` maps to the nested limit. (2) **Observational-memory compatibility surface** (Task 2): the 10 pre-0.0.19 flat settings keys and top-level `workerProvider`/`workerModel` aliases removed — settings resolution is nested-only with `assertNoRemovedFlatKeys` failing closed (settings-provider JSON or untyped overrides throw naming the key + nested replacement before any worker/provider call, compaction, or session append); `fallbackWorker`/`assertWorkerModelCompatibility`/`conflict()` deleted; workers resolve only from `observation`/`reflection`/`dropper` configs plus `sessionModel` fallback. (3) **Read alias + CLI constant** (Task 3): `ReadToolOptions.autoResizeImages` removed (`transformImage` is the only resize path; untyped callers fail closed at `createReadTool` before filesystem access) and `INIT_PROVIDERS` removed (`listInitProviders()` is the single provider-list API). Compat baselines regenerated after the reviewed `--allow-break` break report (root `arnilo__prism.txt` drops the `INIT_PROVIDERS` line; interface-member removals are verified by the phase-17 direct declaration scanner, not baseline text). Exit gate green (core tests + script gates incl. phase17-freeze 20/20, `sdk:ready`, audit 0, pack dry-run 49/49 twice byte-identical, evidence in `scripts/phase17-baseline.json`). Store compatibility with 0.1.4: **compatible, no migration** (removed options were inert aliases; rollback = restore the 0.1.4 manifests/tag). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.1.5 publish handoff` — signed `v0.1.5` tag + npm OIDC).

## [0.1.4] - 2026-08-10

### Changed
- **Release 0.1.4 (plan 016)** is the internal god-module split, compat-preserving on the frozen 0.1.x line. (1) **Contracts split** (Task 1): `src/contracts.ts` (2,549 lines) split by concern into `src/contracts-core.ts`, `src/contracts-run-state.ts`, and `src/contracts-protocol.ts` behind a pure `export *` barrel — the 295-name public surface is unchanged (0 added/0 removed/0 changed vs the 0.1.3 baseline, 702 = 702 at the entry). (2) **Agents split** (Task 2): `src/agents.ts` (2,576 lines) split into `src/agent-session.ts` (`RuntimeAgentSession` + factories + shared helpers), `src/agent-run-lifecycle.ts` (resume lifecycle), `src/agent-approval.ts`, `src/agent-tool-dispatch.ts`, with `agent-run-state.ts`/`agent-loops.ts`/`compaction.ts` reused — `agents.ts` is now a barrel of the four public functions; 14 internal cross-module helper exports joined the union `.d.ts` surface but are not consumer-importable (documented deviation #1, `scripts/phase16-freeze-manifest.json`). (3) **Tree-shake verification** (Task 3): measured in `scripts/phase16-baseline.json` — `dist/agents.js` 111,049 → 982 B, `dist/contracts.js` 9,420 → 418 B, `dist/contracts.d.ts` 98,825 → 1,029 B, dist module count 64 → 70 (static-import reachability reported, not gated). (4) **`@arnilo/prism-browser` CDP capabilities** (Tasks 4-5): additive Chrome DevTools Protocol surface riding playwright-core's existing transport — `browser_evaluate` (bounded `Runtime.evaluate`, policy-gated), `browser_observe` (console/network rings, bodies never captured), `block_urls`/`unblock_urls`/`throttle`/`emulate` act actions, and raw `{ css }`/`{ xpath }` targets; capability-gated via `BrowserCdpOptions.mode` with `ERR_PRISM_BROWSER_CDP_UNAVAILABLE`; documented additive deltas vs the 0.1.3 prism-browser baseline (41 added / 0 removed / 18 changed — 15 statement-text artifacts + 3 optional-member/signature-widening, deviation #2), root `@arnilo/prism` zero deltas. Zero new dependencies across the milestone; exit gate green (npm test core 1,425/1,425 + 151 script gates, `sdk:ready`, audit 0, pack dry-run 49/49 twice byte-identical, tree-shake + benchmark evidence in `scripts/phase16-baseline.json`). Store compatibility with 0.1.3: **compatible, no migration** (rollback = restore the 0.1.3 manifests/tag). **Publication remains the operator handoff** (`docs/release-and-install.md` `0.1.4 publish handoff` — signed `v0.1.4` tag + npm OIDC).

## [0.1.3] - 2026-08-10

### Changed
- **Release 0.1.3 (plan 015)** is the dead-code and deprecation hygiene patch on the frozen 0.1.x line, additive-only vs 0.1.2 (freeze manifest `scripts/phase15-freeze-manifest.json`). (1) **Benchmark-runner consolidation** (Task 1): one parameterized runner `scripts/benchmark.mjs --scenario <name>` replaces the per-version runners; the six live legs moved to `scripts/benchmark-scenarios/` as named scenarios (`phase6-postgres`, `phase7-postgres`, `phase8-loops-hitl`, `phase9-coding`, `phase10-acp`, `phase11-auth`) and the 0.1.0 envelope orchestrator composes them through the runner; **removed files**: `scripts/benchmark-0.0.{8,9,10,11,12,13,14,15,16}.mjs` and `scripts/benchmark-0.0.{9,10,11,12,13,14,15}.test.mjs` (orphaned, unreferenced by `npm test`); all `benchmark-*.json` evidence files kept byte-identical; the CI benchmark-schema leg now runs `scripts/benchmark.test.mjs`. (2) **Review-coverage archive** (Task 2): the 12 `docs/review-coverage-2026-07-*.md` per-phase evidence files moved to `docs/_evidence/` (tarball-excluded via the `files` field; index/migration/performance links updated; archived evidence is not part of the shipped docs surface). (3) **Non-blocking unused-code sweep** (Task 3): `npm run sweep:unused` runs tsc `--noUnusedLocals`/`--noUnusedParameters` over core + every workspace tsconfig plus a zero-dep dead-export scan (`scripts/dead-exports.mjs`), writes the combined report to `scripts/unused-sweep-report.txt`, and always exits 0; CI runs it as a `continue-on-error` step with a retained artifact; 43 internal unused diagnostics (22 test files + 13 source files) removed in-tree, public-but-unused exports are report-only (removal is the 0.1.5 breaking cut). (4) **Opt-in checkpoint persistence** (Task 4): durable runs may set `persistSessionState: true` on the run and resume options — the loaded-skill **name catalog** (≤64 names, ≤256 chars each, validated fail-closed on every save and load) rides the run-state checkpoint and is restored into the resumed session's `LoadedSkillSet`; skill **bodies are never persisted** and re-resolve from the live registry; flag off keeps the checkpoint shape byte-identical to 0.1.2. `@arnilo/prism-coding-agent` adds `createReadPathSetPersistence({ checkpoints, key, ownership })` for the read-before-write path set (≤1024 paths / ≤1024 chars each, CAS read-modify-write, cross-ownership restore fails closed). Store compatibility with 0.1.2: **compatible, no migration**; declaration surface additive-only vs the frozen 0.1.x contract.

## [0.1.2] - 2026-08-10

### Changed
- **Release 0.1.2 (plan 014)** is the Alibaba Cloud provider enrichment patch on the frozen 0.1.x line, additive-only vs 0.1.1 (freeze manifest `scripts/phase14-freeze-manifest.json`): (1) **embeddings** — `createAlibabaEmbedder` in `@arnilo/prism-provider-alibaba` over the OpenAI-compatible `POST {base}/embeddings` (text-embedding-v3/v4), a structural `Embedder` assignable to `@arnilo/prism-memory`'s without a dependency; inputs chunked at the DashScope cap (10/request), vectors in input order, dimensions 64–2048 (default 1024) + `encoding_format` passthrough, key resolved per call and redacted from errors; (2) **video input** — `file` blocks with `video/*` media types serialize to compatible-mode `video_url` content parts on Qwen-VL models, gated on the `file` input capability (`mapAlibabaModel` advertises `["text", "image", "file"]` for the qwen-vl family); (3) **documented deferrals** — document input (compatible path is the OpenAI Files API `file-extract` + `fileid://` reference, an upload/status lifecycle) and rerank (only workspace-dedicated `compatible-api/v1/reranks` exists, not on the public presets) are recorded in the verified decision table in [docs/providers/alibaba.md](docs/providers/alibaba.md) as demand-gated follow-ups; (4) **opt-in live probe** — `PRISM_LIVE_DASHSCOPE_KEY`-gated `test:live` script (skips when absent, never in CI). Store compatibility with 0.1.1: **compatible, no migration**; declaration surface additive-only vs the frozen 0.1.x contract.

## [0.1.1] - 2026-08-10

### Changed
- **Release 0.1.1 (plan 013)** is the post-release hardening patch on the frozen 0.1.x line, five scoped fixes and no new public packages/exports (freeze manifest `scripts/phase13-freeze-manifest.json`): (1) **build single-flight** — `npm run clean` removed from `npm run build` (standalone `npm run clean`; concurrent tsc is idempotent, the destructive `rm -rf` race is gone); (2) **deterministic MCP SSE relay test** — `relayStatelessBody` extracted as an internal export in `@arnilo/prism-mcp` with unit + E2E coverage (`packages/mcp/src/__tests__/sse-relay.test.ts`), closing the plan 011 relay compromise for the stateless path; (3) **combined coverage summary** — `scripts/coverage-summary.mjs` runs the core gate + 41 workspace suites and prints one labeled table (appended to `test:coverage`); (4) **canonical manifest-count narrative** — 49 publishable manifests = root + 48 workspace (14 provider + 9 `prism-*` + 25 capability), one statement in [docs/release-and-install.md](docs/release-and-install.md) with a tripwire; (5) **ACP modes/config ownership-scoped persistence guidance** — the agent never persists `modeId`/`configValues`; host stores MUST key by `sessions.ownership` (cross-tenant restore rejects `ERR_PRISM_ACP_INPUT`), asserted in `acp-modes-config.test.ts`. Store compatibility with 0.1.0: **compatible, no migration**; declaration surface additive-only vs the frozen 0.1.x contract (see [docs/migration.md](docs/migration.md) `0.1.0 → 0.1.1`).

## [0.1.0] - 2026-08-09

### Changed
- **Release 0.1.0 (Phase 12, plan 012)** is the release-candidate hardening cut of the 0.0.28 graph: no new packages, public exports, schema migrations, or runtime dependencies (frozen in `scripts/phase12-freeze-manifest.json`; deviations require a recorded plan 012 Task 0 entry). Store compatibility with 0.0.28: **compatible, no migration**; the `0.0.17 → 0.1.0` upgrade matrix in [docs/migration.md](docs/migration.md) documents every intermediate line (compatible / tested migration / tested refusal).
- **Compatibility matrix machine-checked** (plan 012 Task 1): [docs/release-and-install.md](docs/release-and-install.md) publishes the supported/measured matrix (Node 20+24, PostgreSQL 16, linux-x64, five protocol SDK pins, security-support boundary); release.yml CI legs match it, asserted by tripwires.
- **Upgrade/migration + release-integrity repair** (Task 2): per-release store-compatibility sections for 0.0.18–0.1.0; release-evidence matrix with tag presence + evidence pointers for every release (0.0.21 and 0.0.28 are the documented untagged lines); persistence schema contract reconciled to version 7 (7 checksummed migrations) across freeze manifest, docs, and tests; postgres upgrade-chain/refusal tests.
- **Packed-install e2e journeys** (Task 3): `scripts/e2e-enterprise-journey.test.mjs` + `scripts/e2e-coding-journey.test.mjs` install the exact packed manifest graph into fresh consumers (never workspace paths) and run the enterprise journey (OIDC → OPA ledger → durable events → batched approval → OpenAPI idempotent side effect → artifact signed delivery) and coding journey (ACP editor session → bounded coding tools → sandboxed process session → forge handoff) against public exports only.
- **Protected restart-recovery evidence** (Task 4): `scripts/phase12-restart-recovery.test.mjs` (in `npm run test:postgres`) proves multi-replica kill/resume with no event gap/duplicate, tool-effect unknown-outcome fail-closed replay, database-restart-during-streaming catch-up, and reconnect/contention p95 against frozen ceilings; missing `PRISM_TEST_POSTGRES_URL` is a named blocked gate.
- **Capacity envelopes frozen** (Task 5): `scripts/benchmark-0.1.0.mjs` composes the six phase benchmark scripts into one envelope report (`scripts/benchmark-0.1.0.json` — 24 network-free + 16 protected rows) gated on every `npm test` against the freeze-manifest ceilings; [docs/performance.md](docs/performance.md) publishes the full table with methodology and pass/fail thresholds. Budget baselines regenerated once via freeze deviation dev-001 (evidence scripts added ~35 kB to the root tarball; tolerance unchanged).
- **Security policy hardened** (Task 6): `npm audit --audit-level=moderate` enforced in `security.yml` and `release.yml` (0 vulnerabilities at every severity for the 0.1.0 tree, 317 locked deps); named threat-suites leg `npm run security:threat-suites` (Phase 8–11 conformance, 28/28); supply-chain negative fixtures (unexpected file types/credential material in tarballs, suppressed-provenance detection in dry-run args); live-canary blocked-gate semantics documented.
- **Docs freeze + version bump** (Task 7): `docs/0.1.0-readiness.md` current-line table at 0.1.0 with per-gate 0.1.0-tree evidence and the explicit remaining operator list for 1.0; `docs/public-contracts.md` publishes the frozen 0.1.x contract (declaration/exports surface, events, protocol payloads, migration checksums, additive-only patch promise); every public page, package README, and changelog verified consistent with 0.1.0 behavior (docs tripwires green); all 48 manifests + lockfile at exact 0.1.0 via scripted bump; publish dry-run verified deterministic (49/49 twice, byte-identical); signed-tag + npm OIDC publication documented as explicit operator steps with rollback notes ([docs/release-and-install.md](docs/release-and-install.md) `0.1.0 publish handoff`).

## [0.0.28] - 2026-08-08

### Added
- Phase 11 enterprise adapter seams (plan 011), all optional and fail-closed; hosts that wire none keep exact prior behavior.
- `@arnilo/prism-credentials-node/oidc`: `createOidcIdentityVerifier` — OIDC/JWKS identity verification over native WebCrypto (RS256/ES256), host-pinned SSRF-checked JWKS URL with bounded single-flight cache and exactly one refetch on unknown `kid`, bounded clock skew/claims, host revocation callback; fail-closed `IdentityError` reasons `ERR_PRISM_OIDC_*`.
- `@arnilo/prism-policy/opa`: `createOpaPolicyEvaluator` — OPA REST decision adapter for the durable Phase 6 policy ledger; default deny on timeout/transport failure (`onFailure`), bounded input/response/retries, redacted mapped reasons/evidence, optional bundle-revision pin (`requirePolicyVersion`); frozen codes `ERR_PRISM_OPA_*`.
- MCP OAuth (0.0.28) in `@arnilo/prism-mcp`: `createMcpOAuthTransport`/`createMcpOAuthFetch`/`createMcpClientAuth` reusing `@modelcontextprotocol/sdk` auth helpers — RFC 9728/8414 discovery with bounded SSRF-checked zero-redirect fetch, PKCE interactive flow, RFC 8707 resource-bound audience validation (confused-deputy defense), RFC 7009 revocation, host-owned `McpClientAuthState` persistence; server side gains `protectedResource` metadata route + `WWW-Authenticate` challenges. Frozen codes `ERR_PRISM_MCP_OAUTH_*`.
- New package `@arnilo/prism-openapi-tools`: `createOpenApiTools` compiles host-listed OpenAPI 3.1 `operationId`s at setup into bounded `ToolDefinition`s — pinned origin (drift fails closed), resolved/bounded schemas, mutation operations get `external_mutation` + `idempotency: required` (approval/idempotency via the core run loop), bounded body/response/retries/pagination, host credential resolver, untrusted redacted output. Frozen codes `ERR_PRISM_OPENAPI_*`.
- Artifact body contract + reference adapter: core `ArtifactBodyStore`/`ArtifactBodyRef`/`ArtifactBodyStoreError` (storage-free types, frozen `ERR_PRISM_ARTIFACT_BODY_*`), optional `size` on `ArtifactRevision`, `createArtifactService` `bodies` option with presigned `url` on delivery links (fail closed without recorded size); `@arnilo/prism-server/artifact-bodies` ships `createS3ArtifactBodyStore` — hand-rolled SigV4 over native fetch/WebCrypto, verified hash/size/mime on put/get, legal-hold-aware delete, bounded presign TTL, optional host KMS callback (`ERR_PRISM_S3_*`).
- Phase 11 evidence: network-free `scripts/phase11-conformance.test.mjs` (in `npm test`: composed OIDC → OPA ledger → MCP OAuth tool → OpenAPI side effect → artifact body + signed delivery; adapter-absent baseline; hostile origins and limit ladder; redaction sweep), `scripts/benchmark-0.0.28.mjs` + `scripts/benchmark-0.0.28.json` evidence, `scripts/budgets.json` `phase11` gate, `scripts/phase11-freeze-manifest.json` schema-gated by `scripts/phase11-freeze.test.mjs`.
- Docs: new [docs/openapi-tools.md](docs/openapi-tools.md); OIDC verifier section in [docs/agent-identity.md](docs/agent-identity.md); OPA section in [docs/policy-and-audit.md](docs/policy-and-audit.md); MCP OAuth section in [docs/mcp-tools.md](docs/mcp-tools.md); artifact body store section in [docs/work-artifacts-and-review.md](docs/work-artifacts-and-review.md); migration `0.0.27 → 0.0.28`; Phase 11 p95 evidence in [docs/performance.md](docs/performance.md); protected live-canary slot recorded as a blocked release gate in [docs/0.1.0-readiness.md](docs/0.1.0-readiness.md).

### Changed
- `createPrismMcpWebHandler` accepts `McpServer | (() => McpServer | Promise<McpServer>)`; stateless operation now requires a factory (a shared stateless transport threw on the second request). SSE (`text/event-stream`) responses are relayed instead of buffered, so streaming responses no longer stall the handler.
- Publishable graph stays **48** manifests (includes the new `@arnilo/prism-openapi-tools`); core remains dependency-free and every new seam is opt-in.
- Version bumped to exact `0.0.28` across the root, all workspace manifests, and the lockfile; compatibility baselines refreshed (additive surfaces only).

## [0.0.27] - 2026-08-07

### Added
- 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).
- 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.
- 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.

### Changed
- `@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.
- SBOM license policy allows `Unlicense` (tweetnacl via `@nats-io/nkeys`); readiness SBOM evidence refreshed (227 packages / 12 licenses).
- `@arnilo/prism-ag-ui/renderer` now exports the DOM-free A2UI core values (`A2UiSurfaceState`, `reduceA2UiOps`, `readA2UiBatch`, `resolvePointer`, `A2UI_VERSION`) — host FR, hosts can drive the surface state machine without mounting; `createA2UiRenderer` behavior and frozen A2UI caps unchanged.

### Breaking (advertise/surface for ACP hosts only)
- `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`.

## [0.0.26] - 2026-08-06

### Added
- Git-aware repository enumeration (`createGitAwareRepositoryOperations`): fixed `git ls-files` with native fallback, host-only `includeIgnored`, frozen ls-files output caps.
- Language intelligence (`createLanguageIntelligence`): host-selected LSP 3.17 client over bounded JSON-RPC — symbols/definitions/references/diagnostics/hover/rename; lazy spawn; policy-gated atomic rename; `ERR_PRISM_LSP_*` codes.
- Managed process sessions (`createProcessSessions`): start/output/input/wait/signal/kill/release, ownership + expiry sweep, optional sandbox `startProcess` backend with sandbox-loss → `unknown` reconciliation; `OutputAccumulator.readRaw` cursor paging.
- Reference GitHub forge adapter (`createGitHubForge`): issue context, authenticated push (`GIT_CONFIG_*` credential injection, never argv), PR create/update, review comments, checks/status, bounded `reconcileHandoff`; `ToolEffectStore` idempotency (retry never duplicates); host-injectable `fetch` option.
- Allow-list egress (`@arnilo/prism-coding-security`): deny-all `createEgressPolicy` with frozen presets, `createAllowListEgressProxy` (CONNECT tunnel, pinned-DNS rebinding defense, private/metadata IP denial, redirect re-validation, byte/time caps, audit records), `composeEgressSandboxNetwork` attestation labels.
- Network-free Phase 9 conformance + `benchmark-0.0.26.json` evidence; composed example `phase9-coding-intelligence.ts`.
- AG-UI reasoning encrypted-value helper (`createReasoningEncryptedValue`, FR-3) and MCP Apps UI-initiated mutation retry through `ToolEffectStore` (`reconcileAppEffect`, FR-4).
- Durable `AgentEventSource` root export in `@arnilo/prism-session-store-postgres` (FR-6) and new NATS JetStream sibling adapter `@arnilo/prism-session-store-nats` (FR-5): per-run subjects, per-subject replay, durable pull consumers with explicit acks (at-least-once), idempotent append, resumable cursors, ownership-scoped page/subscribe/cleanup.
- A2A server-side exposure (Task 13): `createAgUiA2AServer` in `@arnilo/prism-ag-ui` fronts a local AG-UI agent as an A2A 1.0 server over supervisor's `createA2AHandler` — remote clients run and stream the agent through the AG-UI input allow-list and event mapper, with a bounded live task registry and optional durable replay.
- Reference frontend renderer (Task 14): new `@arnilo/prism-ag-ui/renderer` subpath export — `createA2UiRenderer` consumes an AG-UI event stream and renders A2UI v0.9 surfaces into DOM from a host component catalog; DOM-free core with the server-side A2UI caps enforced client-side, fail-closed drops, explicit placeholders for unknown components, and no remote HTML execution.
- Async `AgUiProjection` hooks (Task 15): all hook returns are `Awaitable<T>`; the AG-UI and ACP mappers await hooks in event order with per-event fail-closed, so projectors can call `session.entries()` directly — `createMessagesFromSessionProjection` now accepts an async `getMessages` transcript source. Sync-only hosts keep exact prior behavior.

### Changed
- Publishable graph grows to **48** manifests at **0.0.26** (new `@arnilo/prism-session-store-nats`).

### Breaking (none)
- All Phase 9 additions are opt-in factories; no existing export, event, or persisted shape changed. See [migration guide](docs/migration.md) `0.0.25 → 0.0.26`.

## [0.0.25] - 2026-08-06

### Added
- Durable custom `AgentLoopStrategy` hooks: optional `revision` / `snapshot` / `restore`; `AgentLoopStateError` fail-closed codes; fingerprint includes loop `{name,revision}`.
- Shared pending-decision model: parallel approvals, batch CAS `decisions`, sticky allow/reject for run, modified arguments, elicitation; nested supervisor attribution.
- Protocol mappings: AG-UI/ACP/server batch resume, MCP elicitation helpers, coding `ask_user_decision` elicitation hook.
- Opt-in A2UI painting middleware + standard AG-UI projectors (`messages`/`state`/`activity`).
- Network-free Phase 8 conformance + `benchmark-0.0.25.json` evidence; examples `durable-loops-and-approvals.ts`, `ag-ui-a2ui.ts`.

### Changed
- Publishable graph remains **47** manifests at **0.0.25**.
- Fingerprint loop entry shape `string` → `{name,revision}` (0.0.24 persisted durable runs fail closed on resume).

### Breaking (minor, pre-1.0)
- Custom loops on durable runs need snapshot/restore hooks or `ERR_PRISM_LOOP_NOT_DURABLE`.
- Resume prefers `decisions: RunDecision[]`; legacy binary `decision` remains but is exclusive with the batch path.
- ACP permission offers four outcomes; `reject_once` is blocked-continue (cancelled stays terminal deny).

See [docs/migration.md](docs/migration.md) for the 0.0.24 → 0.0.25 guide.

## [0.0.24] - 2026-08-04

### Added
- Durable `AgentEventSource` with append/page/subscribe/resume and PostgreSQL LISTEN/NOTIFY wakeups (schema v6 streams + v7 retention index).
- Recoverable `ToolEffectStore` claim/CAS lifecycle; enterprise PostgreSQL `toolEffects`; coding/browser/work/MCP/supervisor effect classification.
- AG-UI 0.0.57 full input/event/interrupt compatibility plus MCP Apps and remote A2A adapters.
- Protected Phase 7 process conformance and `benchmark-0.0.24.json` evidence.
- Example `examples/distributed-events-and-tool-effects.ts`; docs `docs/tool-effects.md`.

### Changed
- Work mutations require core-derived idempotency keys; ambiguous outcomes stay `unknown` (not exactly-once).
- Publishable graph remains **47** manifests at **0.0.24**.

### Breaking (minor, pre-1.0)
- Hosts using approved work mutations must supply `effectStore` / core `idempotencyKey` (model keys ignored).
- Durable event reconnect uses `AgentEventSource` cursors / `Last-Event-ID`; sticky sessions are optional only.

See [docs/migration.md](docs/migration.md) for the 0.0.23 → 0.0.24 guide.

## [0.0.23] - 2026-08-03

### Added
- `@arnilo/prism-enterprise-postgres`: optional PostgreSQL composition for policy decisions, evaluation records, work-mutation idempotency, and model-router state.
- Checked enterprise PostgreSQL conformance/restart/contention, cleanup/index/storage performance evidence, and protected `PRISM_TEST_POSTGRES_URL` gate.

### Changed
- `@arnilo/prism-work-tools` idempotency uses claim/CAS lifecycle states; ambiguous connector outcomes are `unknown` and require reconciliation.
- `@arnilo/prism-model-router` accepts durable async state; `recordUsage`/`recordOutcome` are awaited and `providerSource` cannot bypass a supplied state store.
- Publishable graph: **47** manifests (was 46); `@arnilo/prism-all` includes enterprise PostgreSQL state.

### Breaking (minor, pre-1.0)
- Hosts implementing `IdempotencyStore` must migrate from `get`/`put` to `begin`/transition methods.
- Hosts using durable router state must await router methods with verified identity; synchronous `providerSource` is memory-state only.

See [docs/migration.md](docs/migration.md) for the 0.0.22 → 0.0.23 guide.

## [0.0.22] - 2026-07-31

### Added
- `@arnilo/prism-caveman` and `@arnilo/prism-ponytail`: optional third-party behavior integrations (Phase 5).
- Example `examples/caveman-ponytail.ts`.

### Changed
- Publishable manifest count: **46** (was 44).

See [docs/migration.md](docs/migration.md) for the full 0.0.21 → 0.0.22 notes.

## [0.0.21] - 2026-07-31

### Added
- `@arnilo/prism-coding-agent`: `repo_search` `outputMode`, bounded `glob`, optional `requireReadBeforeWrite`/`ReadPathSet`, bounded `delete`/`move`.
- Example `examples/coding-tools-capability-gaps.ts`.

### Changed
- Default coding aggregator: 9 tools (`createCodingTools`); read-only aggregator: 4 (includes `glob`).
- `@arnilo/prism-coding-security`: approval + sandbox wiring for `delete`/`move`.

### Breaking (minor, pre-1.0)
- Hosts asserting exact `createCodingTools().length === 6` or readonly length `3` must update (now 9 / 4).
- Custom sandbox `RepositoryOperations` must implement `glob`; full sandbox custom ops must supply `delete`/`move`.

See [docs/migration.md](docs/migration.md) for the full 0.0.20 → 0.0.21 notes.

## [0.0.20] - 2026-07-31

### Added
- Progressive skill disclosure: `skillsDisclosure` (`"progressive"` default, `"eager"` opt-in), session `LoadedSkillSet`, `createLoadSkillTool` / `resolveSkillLoad` (`load_skill`), catalog/body byte caps.
- Runtime `activateAllSkills` migration opt-in when `AgentConfig.skills` is a `SkillRegistry` without per-run activation.
- Context budget: `ContextBlock.priority` ordering; skill body demotion (`skill_body` omission) before full drop.
- Optional `toolResultFold` host-gated projection for aged large tool results (session store untouched).

### Changed
- Default runtime `SkillRegistry` activation is **empty** when neither `RunOptions.activeSkills` nor `RunOptions.skills` is set (was `SkillRegistry.list()`).
- Default skill prompt assembly is catalog-only (`name` + `description`); full `instructions` require eager mode or successful `load_skill`.

### Breaking (minor, pre-1.0)
- Hosts relying on implicit activate-all registry behavior must pass `activateAllSkills: true` or set `activeSkills` / `skills` explicitly.
- Hosts expecting full skill bodies every turn must set `skillsDisclosure: "eager"` or register and use `load_skill`.

See [docs/migration.md](docs/migration.md) for the full 0.0.19 → 0.0.20 notes.

## [0.0.19] - 2026-07-30

### Added
- `@arnilo/prism-compaction-observational-memory`: `createObservationalMemory()` + `attach()` lifecycle, four-layer provider context (recent exact messages, observation log, reflections, raw-source retrieval), `recallObservationalMemoryBranchPage()`, `wrapResumeRun` / `wrapResumeStream`, nested settings with legacy flat-key mapping.

### Changed
- Observational memory: separate observer/reflector/dropper workers, domain-neutral observer default, dual coverage/eligibility fixes, full-ledger reflection recall, hard fold/render byte caps, post-run `compactAfterTokens` compaction when attached.

See [docs/migration.md](docs/migration.md) for the full 0.0.18 → 0.0.19 observational memory notes.

## [0.0.18] - 2026-07-30

### Changed
- Default `inputLayout` is `cache_aware` (unset `AgentConfig` / `RunOptions` use cache-stable message order); set `inputLayout: "legacy"` to restore prior ordering.
- `applyContextBudget` evicts oldest history messages first under pressure (was newest-first).
- `@arnilo/prism-mcp` pins `@modelcontextprotocol/sdk` **1.30.0** (clears moderate `@hono/node-server` path-traversal advisory on the MCP HTTP stack).

### Breaking (minor, pre-1.0)
- `@arnilo/prism-coding-agent` `repo_search` is literal-only: `mode: "regex"` removed; `compileSearchPattern` drops the `mode` argument (ReDoS mitigation).
- Default local `write` / `edit` operations use same-directory temp + `rename` for crash-safe replacement.

See [docs/migration.md](docs/migration.md) for the full 0.0.17 → 0.0.18 notes.

## [0.0.17] - 2026-07-29

### Added
- Extension lifecycle: `ExtensionKernel.load()` returns `LoadedExtension[]` dispose handles; contribution/provider/model registries gain `unregister(...)`; a failed `setup` unwinds its partial registrations.
- `MemoryCredentialStoreOptions.allowProviderFallback` for strict provider-scoped credential resolution; `createMemoryCheckpointStore` `maxRecords`/`maxValueBytes` bounds; `ShellToolOptions.envAllowlist` (coding-agent); `ErrorInfo.retryAfterMs` plus `retryAfterMs`-aware `createDefaultRetryPolicy` with `jitter`/`random` options; guardrail `steer_rejected` event; `httpStatusError` provider transport helper wired into anthropic, google, kimi, openai, opencode-go, and the shared OpenAI-compatible transport.

### Changed
- Durable runs: run-state load now bounds against the 1 MiB hard cap (states saved with a raised `maxStateBytes` resume correctly); agent fingerprint also covers instructions, system-prompt contributions, and skills; resume-after-interrupt is explicit implicit-approval.
- Retry/backpressure: HTTP provider errors carry numeric codes and `Retry-After` hints; default retry policy applies ±25% jitter.
- `input_assembly` middleware runs unconditionally (both plain and context-budget paths, any `InputBuilder`); memory session store rejects cross-session `expectedParentId`; context-budget eviction is O(n) instead of O(n²).
- Guardrails: `interrupt` errors name the stage; `guardrail_failed` records carry the underlying error message in `metadata.error`; steer `block`/`tripwire` drops the message and emits `steer_rejected` instead of failing the run.
- Default prompt builder omits the `Available tools:` text for tool-capable models (`capabilities.tools === true`).
- Middleware registry throws on double `next()` and diagnoses conflicting `next(v)` + return; event multiplexer keeps sorted delivery while a consumer is parked; batched run-ledger dead counters removed.

### Breaking (minor, pre-1.0)
- CLI: `--config`, `--resource`, `--extension`, `--tool` are rejected (`<flag> is not supported in this build`); the dead `CliOptions.config/resources/extensions/tools` fields are removed.
- `ExtensionKernel.load()` resolves to `LoadedExtension[]` instead of `void`.

See [docs/migration.md](docs/migration.md) for the full 0.0.16 → 0.0.17 notes.

## [0.0.16] - 2026-07-26

### Added
- Phase 11 simplification/readiness: new public export `resolveRedactor` from `@arnilo/prism` (single survivor of four private copies across evals/memory/rag/workflows) and a new internal `@arnilo/prism-session-store-codecs` package (shared SQLite/Postgres row codecs, not enrolled in any profile family), bringing the exact graph to **44 publishable manifests**.
- Offline pre-publish release gates: `npm run release:gate` (API-surface `.d.ts` diff vs `scripts/compat-baseline/`, tarball deny-list, exact version ranges), wired into `npm run sdk:ready`.
- Performance budgets in `scripts/budgets.json`, enforced by `scripts/budget-gate.test.mjs` (in `npm test`) and `scripts/benchmark-0.0.16.mjs`.

### Changed
- Dropped historical `docs/review-coverage-*.md` from the root tarball (11 files, ~283 KB): packed size 659,478 → ≈575,680 bytes, 281 → 270 files.
- All six profiles (`prism-all`, `prism-base`, `prism-code`, `prism-compaction`, `prism-providers`, `prism-sdk`) retained on adoption evidence; zero retirements. No runtime behavior changes.

## [0.0.15] - 2026-07-26

### Added

- Phase 10 provider, memory, and RAG parity: OpenAI hosted-tool attribution, bounded Responses continuation and Realtime seam; exact AI SDK V4 mapping; bounded RAG source lifecycle, document adapters, reranking, citation provenance, content trust, and ingestion status; memory export/rebuild with production-store conformance.

### Changed

- Versioned all **43** publishable manifests, exact internal ranges, and lockfile entries to `0.0.15`; no package was added.
- Added network-free Phase 10 evidence: `scripts/benchmark-0.0.15.mjs`.

## [0.0.14] - 2026-07-26

### Added

- Phase 9 personal/work-agent surfaces: durable conversation service (`createConversationService`), durable artifact service with review/approval/authorized delivery (`createArtifactService`), memory consent + lifecycle (`setConsent`/`correct`/`forget`/`applyRetention`), AG-UI co-work events (`mapCoWork` + ACP parity), scoped M365/GWS OAuth connectors (`revokeOAuthCredential`, `createOAuthWorkTokenProvider`), a browser verified-state checkpoint ledger, and a deny-by-default device adapter contract (`resolveDevicePolicy`/`assertDeviceAdmit`).
- New optional provider packages `@arnilo/prism-provider-alibaba` (Model Studio / DashScope + Coding Plan) and `@arnilo/prism-provider-ollama` (cloud/local), both with dynamic model discovery; enrolled via `@arnilo/prism-providers`.

### Changed

- Versioned all **43** first-party manifests and exact internal ranges to `0.0.14` (41 → 43; only the two provider packages are new).
- Network-free Phase 9 evidence: `scripts/benchmark-0.0.14.mjs`.

## [0.0.13] - 2026-07-24

### Added

- Enterprise identity (`Principal` / `AgentIdentity`), optional `@arnilo/prism-policy`, `@arnilo/prism-model-router`, enterprise cloud providers (Azure/Bedrock/Vertex), server deployment seams, persistence schema v5 lifecycle hooks, and `@arnilo/prism-work-tools` (M365 + GWS).

### Changed

- Versioned all **41** first-party manifests and exact internal ranges to `0.0.13`; Phase 8 optional packages enroll in `@arnilo/prism-all` only.
- Network-free enterprise evidence: `scripts/benchmark-0.0.13.mjs`.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

All notable changes to this project will be documented in this file.

## [0.0.12] - 2026-07-22

### Added

- Optional `@arnilo/prism-ag-ui` package with bounded AG-UI mapper/authorized handler/replay and stable `./acp` sibling, built over shared durable resume streams.
- `createCodingCompactionStrategy()` preset for bounded coding-session handoff.

### Changed

- Versioned all 35 first-party manifests and exact internal ranges to `0.0.12`; `@arnilo/prism-all` includes AG-UI while `@arnilo/prism-code` and `@arnilo/prism-sdk` remain free of UI protocol dependencies.
- Added network-free interoperability/compaction evidence: `scripts/benchmark-0.0.12.mjs`.

## [0.0.11] - 2026-07-22

### Added

- Coding harness fundamentals for 0.0.11 (Plan 074): bounded `SessionIndex`/`searchSessions` (SQLite/Postgres FTS migration 004; memory linear|unsupported; JSONL unsupported), assembler `contextBudget` + omission reports, `@arnilo/prism-provider-anthropic` + `@arnilo/prism-provider-google`, mid-run `AgentSession.steer` / RPC steer, coding-agent `runCodingGoalVerify` and opt-in `ask_user_decision` (multi/free-text/durable suspend glue).
- Opt-in `structuredOutputTiming: "final-turn-only"` on `generate-validate-revise` (default `"every-turn"`): tool-eligible turns omit native schema so models can call tools; artifact/revision turns attach schema and withdraw tools.

### Changed

- Versioned all 34 first-party manifests and exact internal ranges to `0.0.11` (adds `@arnilo/prism-provider-anthropic` + `@arnilo/prism-provider-google` to the publishable graph and `@arnilo/prism-providers` umbrella).
- Network-free search/budget evidence: `scripts/benchmark-0.0.11.mjs`.

## [0.0.10] - 2026-07-21

### Changed

- Coding harness workspace modes (Phase 5): required `workspaceMode` on `@arnilo/prism-coding-security` composition; sandbox mode unifies shell/FS on one disposable tree; host mode never claims containment; fail-closed mixed wiring + `allowMixedWorkspaceWiring` escape hatch; import/export tree identity; `scripts/benchmark-0.0.10.mjs` evidence.
- Versioned all 32 first-party manifests and exact internal ranges from the post-ship `0.0.96` graph to `0.0.10` for the roadmap Phase 5 release line.

## [0.0.96] - 2026-07-21

### Changed

- Package graph and runtime version pins bumped from 0.0.9 to 0.0.96 for a clean publish tag after the mistaken `v0.0.95` tag and TypeScript 7 / workspace-order CI fixes.

## [0.0.9] - 2026-07-21

### Added

- Production coding and browser execution for Release 0.0.9: disposable Docker sandbox, bounded native repository list/search, structured Git/named checks/PR handoff, durable coding-plan/checkpoint composition, and optional `@arnilo/prism-browser` with egress/side-effect/upload/download/screenshot policy.
- Versioned all 32 first-party manifests and exact internal ranges to 0.0.9 (adds `@arnilo/prism-browser` to the publishable graph; browser stays out of `@arnilo/prism-code` and activates only through explicit install or `@arnilo/prism-all`).
- Added network-free coding/browser adversarial evaluation fixtures, `scripts/benchmark-0.0.9.mjs`, and protected Docker/Playwright gates via `.github/workflows/sandbox-browser.yml`.
- Office execution remains outside Prism packaging by product decision (host-selected skills/instructions only).
- `tryParseJsonObjectArguments` and `toolCallFromArgumentsText` for recoverable streamed tool-call argument parsing.

### Fixed

- Malformed streamed tool-call arguments (id+name present) become failed/`tool_execution_blocked` tool results (`invalid_arguments` / `invalid_json_arguments`) instead of terminal `ProviderTransportError`, so models can self-correct within existing turn budgets.
- Incomplete tool-call deltas (missing id/name) fail with typed `ProviderTransportError` / `ErrorInfo.code: "incomplete_delta"` instead of a bare `Error("Incomplete tool call delta...")`; openai-compatible streams no longer emit `done` alongside leftover incomplete deltas.
- Empty/whitespace-only call-free artifact candidates (including thinking-only output) are `parse_error` through the revision budget; `generate-validate-revise` session runs no longer resolve `succeeded` without `artifact_finished`.

## [0.0.8] - 2026-07-20

### Added

- Added OpenTelemetry GenAI agent/provider/tool hierarchy, context propagation, delegation/guardrail spans, bounded trace references, and evaluation linkage.
- Added bounded evaluation trace resolution, host model judges, deterministic pairwise reports, serialized artifacts, and CI threshold assertions.
- Added MCP resources/prompts/roots/sampling/elicitation plus principal-bound Streamable HTTP sessions on pinned SDK 1.29.0, and full A2A 1.0 durable task/rich-part/reconnect/push interoperability.
- Added immutable-revision CodeQL/dependency/SBOM/license/secret/attestation release gates, weekly dependency updates, and protected bounded provider/MCP/A2A/web live canaries.
- Added optional `@arnilo/prism-web-tools` with bounded host-selected Brave/Exa search, Firecrawl Markdown/schema extraction, stable citations, late credentials, and explicit untrusted-content results.
- Added optional `createBatchedRunLedger()` with bounded FIFO/backpressure, explicit durability/flush status, terminal acknowledgement, and documented buffered crash-loss semantics.
- Added one-leaf, one-second runtime session snapshot caching with mutation/checkout/resume invalidation and reproducible network-free 0.0.8 performance evidence.
- Versioned all 31 first-party manifests and exact internal ranges to 0.0.8; no tag or publication was created.

### Fixed

- `generateValidateReviseLoop` routes artifact parse failures through the revision budget (`metadata.reason: "parse_error"`, repairer receives `value: undefined`) instead of returning silently after one provider turn.
- `@arnilo/prism-provider-opencode-go` Anthropic route sends provider-owned `x-api-key` and `anthropic-version: 2023-06-01` headers alongside Bearer, fixing HTTP 401 on MiniMax/Qwen models; `structuredOutput: "json_schema"` is no longer inferred from OpenAI routing alone (verified models only), fixing HTTP 400 on `deepseek-v4-pro`; both stream parsers require protocol completion evidence and fail truncated streams with a terminal `error` instead of a false `done`.
- `@arnilo/prism-provider-kimi` aligns with official contracts: featured Coding `k3` defaults `reasoning_effort: "high"`, 256K-class context windows use the exact `262_144`, the featured Moonshot catalog adds `kimi-k2.7-code-highspeed`/`kimi-k2.6`/`kimi-k2.5`, routing keys (`route`, `preserve_thinking`) no longer leak into wire bodies, the Coding route sends provider-owned `x-api-key`/`anthropic-version` headers, and both stream parsers fail truncated streams instead of emitting `done`.

## [0.0.7] - 2026-07-19

### Added

- Typed `Guardrails` for input, provider output, tool input, and tool output. Guardrail decisions are bounded/redacted `guardrail_decision` events; provider output is buffered before exposure when output checks are configured.
- Workflow tool nodes and MCP server tool registrations now route optional tool guardrails through shared `dispatchToolCall()`.
- `RunLimits` adds validated, narrowing-only budgets for turns, provider attempts, tool rounds/calls, wall time, request/response bytes, token usage, and optional single-currency cost. Breaches emit one `run_limit_exceeded` event and return `AgentRunError.result.limit`.
- Opt-in durable built-in agent runs can suspend before a tool side effect and resume through versioned, bounded, redacted checkpoint state with CAS approval, ownership/fingerprint checks, and no automatic replay of an ambiguous dispatched tool.
- `createSecureAgent()` composes strict tool schemas/validation, trust and permission gates, redaction, finite limits, exact ownership, and durable pre-tool approval without changing low-level `createAgent()` defaults.
- `createAgentRunLifecycle()` adds explicit, ownership-scoped durable agent status/resume capability for selected server and MCP exposures; no lifecycle route/tool is enabled by default.

## [0.0.6] - 2026-07-19

### Added

- Caller-gated model discovery: `listOpenAIModels`, `listKimiModels`, `listZaiModels`, `listOpenRouterModels`, and `listOpenCodeGoModels`. Provider setup remains network-free; hosts explicitly fetch and register current models.
- Shared `ThinkingLevel` helpers and use-case model bindings. Background compaction and observational-memory jobs can use an explicit provider/model or a supplied session-model fallback.
- Opt-in sequential artifact-loop tools: `loop: { strategy: "generate-validate-revise", toolCalls: "bounded" }`. Tool rounds use existing authorization/redaction/ledger paths, share `maxToolRounds` across candidates, and fail with `artifact_failed` metadata `{ reason: "tool_round_limit" }` after exhaustion.
- Checksummed SQLite/PostgreSQL migration histories and catalog-shape verification, bounded JSON Schema compilation LRU, and public `assertFiniteVector` validation.

### Changed

- Provider packages now document and implement current cache, reasoning, streaming, and discovery behavior. OpenAI Responses replay/function-call/SSE argument handling is corrected; Kimi adds optional Moonshot support; Z.AI and OpenCode Go catalogs/routes were refreshed; OpenRouter discovery/reasoning and NeuralWatt thinking controls are hardened. AI SDK remains host-model-owned.
- Workflow definitions now require a non-empty `revision`; cancellation requires exact ownership and the current workflow definition. All workflow limits have finite hard caps.
- Coding tools now enforce bounded streamed reads, write/edit inputs, shell wall time, total output, and spill-file lifecycle. Custom coding operation interfaces now receive bounded read/stat/write/edit options and abort signals.
- Encrypted credential helpers `encryptBytes`, `decryptBytes`, and envelope rotation are asynchronous. Existing credential files must meet restrictive Unix permission requirements. Linux Secret Service/GNOME Keyring byte-array reads are accepted by the keychain store.
- MCP Streamable HTTP requires HTTPS and explicit `allowedOrigins`; loopback HTTP requires explicit opt-in. Discovery, schemas, results, and response bodies are bounded.
- Compaction and observational-memory workers now have finite turn/call/transcript/error budgets. A2A streaming uses strict incremental UTF-8 and LF/CRLF SSE parsing.
- Generated Prism, workflow, and evaluation IDs use cryptographic UUIDs; non-finite embedding vectors now fail before scoring or persistence.

### Security

- Fixed cross-owner workflow cancellation and duplicate active-run overwrite risks.
- Added fail-closed limits and validation at file, process, credential, MCP, migration, schema, vector, provider-worker, and A2A trust boundaries.

### Upgrade notes

- Finish or deliberately migrate pre-0.0.6 workflow runs/checkpoints before upgrading: their definition hashes lack the required revision.
- Update workflow definitions with `revision`, cancellation callers with `workflow` plus exact ownership, MCP HTTP configs with `allowedOrigins`, and custom coding/credential integrations for the changed interfaces above.

## [0.0.5] - 2026-07-16

- `@arnilo/prism-providers` now installs all seven first-party adapters including AI SDK interoperability; `@arnilo/prism-all` now installs every first-party package while activating none automatically.

- Added optional `@arnilo/prism-supervisor` with bounded explicit child delegation, derived memory scope IDs, narrowing-only permissions, A2A 1.0 cards/ES256 signatures, authorized JSON-RPC/SSE serving, and an exact-origin remote client.

- Added bounded immutable run/trace feedback with exact ownership, evaluation linkage, memory/SQLite/PostgreSQL stores, schema migration 003, and safe OpenTelemetry projection.

- Phase 11 extends workflows with explicit durable schedules/background execution, nested composition, bounded validated state, immutable-lineage replay, and optional command/Web bindings over existing checkpoint/lease primitives.

- Optional `@arnilo/prism-server` package with authorized bounded Web-standard direct/SSE agent and durable workflow routes; `@arnilo/prism-mcp` now supports explicit authorized Prism tool/command server exposure and bounded Web-standard Streamable HTTP handling.
- Optional `@arnilo/prism-rag` package: bounded deterministic text/Markdown chunking, Phase 7 vector indexing/retrieval, stable citations, metadata filters, redaction, and explicit ContextProvider injection.
- Workflows now support durable human `suspend()`/approve/deny, expected-version exact-once resume, validated/redacted resume payloads, and opt-in tool approval with execution-policy recheck.

### Added

- Optional `@arnilo/prism-memory` package: schema/template-backed working memory, semantic recall, package-owned `Embedder`/`VectorStore` contracts, in-memory adapters, context provider, opt-in processor, shared conformance, and PostgreSQL/pgvector production path.

## [0.0.4] - 2026-07-14

### Added

- Shared bounded provider transport, OpenAI serialization/media helpers, native structured-output contracts, provider/tool timing metadata, and audio/file/document content capability checks.
- Generic checkpoint, atomic lease, and bounded event-multiplexer contracts plus persistence/run-ledger conformance helpers.
- Optional packages for JSON Schema tool validation, MCP, coding approval/sandboxing, OpenTelemetry, encrypted/keychain credentials, SQLite/PostgreSQL persistence, and bounded workflow orchestration.
- Manifest-only `base`, `code`, and `sdk` profiles; `prism-all` now transitively installs every first-party package.
- Workflow, multimodal, persistence/resume, provider telemetry, cache, and external-adapter examples.

### Changed

- Single-shot loops support ordered bounded parallel tools; `ToolDefinition.exclusive` serializes dangerous turns without reducing later concurrency.
- Provider requests, SSE/error bodies, media, schemas, event queues, checkpoints, and workflow fan-out/output use documented finite limits.
- Session/ledger writes preserve order and redact before persistence; revision-loop transcript ordering and OAuth abort polling are hardened.
- All first-party providers use shared bounded transport helpers and expose current structured-output, multimodal, caching, reasoning, telemetry, and retry behavior where supported.

### Security

- Added fail-closed schema/prototype-pollution, SSRF/media, SQL/tenant, path/shell approval, MCP result, credential-envelope, OAuth, redaction, and stale-worker fencing coverage.
- Optional privileged capabilities remain inactive until hosts explicitly register transports/tools, configure roots/credentials/databases, and approve execution.

## [0.0.3] - 2026-07-08

### Added

- New first-party workspace package `@arnilo/prism-coding-agent` providing optional host coding tools (`shell`, `read`, `write`, `edit`) as Prism `ToolDefinition` objects. The package is opt-in and is **not** included in `@arnilo/prism-all` because the tools perform host shell/filesystem operations.
- `createCodingTools`, `createReadOnlyTools`, and `createAllTools` aggregator factories for importing/registering coding tools.
- Documentation: `docs/coding-agent-tools.md`, updated `docs/index.md` and `docs/tools.md`, and expanded `packages/coding-agent/README.md`.

### Changed

- Bumped all package versions from `0.0.2` to `0.0.3` (core, first-party workspace packages, and umbrella packages).
- Updated `@arnilo/prism` peer dependency range in every first-party workspace package to `0.0.3`.
- Updated umbrella package dependency pins to `0.0.3`.
- `docs/release-and-install.md` now documents nine first-party workspace packages, thirteen total manifests, and the explicit install command for `@arnilo/prism-coding-agent`.

## [0.0.2] - 2026-07-05

### Added

- Added `LICENSE` (MIT) and `CHANGELOG.md` to the published `prism` package.
- Added npm package metadata: `license`, `repository`, `bugs`, `homepage`,
  `keywords`, and `sideEffects`.

### Changed

- `files` whitelist now explicitly excludes `dist/__tests__/` and
  `dist/**/*.map` from published tarballs; source maps remain emitted locally
  for debugging but are no longer shipped.
- Core tarball now ships the `/docs` hub.
- Made `prism` a required peer dependency for all first-party workspace packages; it is no longer optional. The peer range remains `0.0.2` and will widen to `^1.0.0` at the 1.x stable release.
- Pinned the no-network `npm test` budget at < 60s on Node 20 (measured baseline ~45s) after the default suite grew to include every first-party package, offline install smoke, packaging guards, docs examples, and workspace tests.

## [0.0.1] - 2026-06-22

### Added

- Initial release of Prism: a framework for building agentic LLM applications
  with configurable providers, sessions, tools, context providers, compaction,
  extensions, and trust boundaries.
