@arnilo/prism 0.0.18 → 0.0.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.0.19] - 2026-07-30
4
+
5
+ ### Added
6
+ - `@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.
7
+
8
+ ### Changed
9
+ - 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.
10
+
11
+ See [docs/migration.md](docs/migration.md) for the full 0.0.18 → 0.0.19 observational memory notes.
12
+
3
13
  ## [0.0.18] - 2026-07-30
4
14
 
5
15
  ### Changed
package/dist/index.d.ts CHANGED
@@ -94,5 +94,5 @@ export { createToolParameterValidator, createToolRegistry, dispatchToolCall, fil
94
94
  export type { ResolvedUseCaseModel, ResolveUseCaseModelInput, UseCaseModelBinding, } from "./use-case-model.js";
95
95
  export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
96
96
  export declare const name = "prism";
97
- export declare const version = "0.0.18";
97
+ export declare const version = "0.0.19";
98
98
  export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
package/dist/index.js CHANGED
@@ -51,6 +51,6 @@ export { applyThinkingLevel, isThinkingLevel, normalizeThinkingLevel, THINKING_L
51
51
  export { createToolParameterValidator, createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
52
52
  export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
53
53
  export const name = "prism";
54
- export const version = "0.0.18";
54
+ export const version = "0.0.19";
55
55
  export const description = "Agent harness for AI providers, agents, sessions, and tools.";
56
56
  //# sourceMappingURL=index.js.map
@@ -1,12 +1,12 @@
1
1
  # 0.1.0 / 1.0 Readiness Gates
2
2
 
3
- Status: **0.0.18** is the current release line (Phase 1 restore integrity); **1.0** readiness remains operator-gated, not automatic.
3
+ Status: **0.0.19** is the current release line (Phase 2 observational memory lifecycle); **1.0** readiness remains operator-gated, not automatic.
4
4
 
5
5
  This page distills runnable readiness gates into one command-per-gate table. The
6
6
  **Last evidence** column records the 2026-07-26 **0.0.16** baseline snapshot
7
7
  (Phase 11, Node v24.18.0, Linux x86_64). Treat it as historical floor evidence,
8
8
  not the current release tag. Re-run each gate on the target release tree before
9
- cutting 0.0.18 / 1.0. The decision to cut 1.0 stays with the operator after
9
+ cutting 0.0.19 / 1.0. The decision to cut 1.0 stays with the operator after
10
10
  operator-gated legs run in a protected environment and Phase 12 demand evidence
11
11
  exists.
12
12
 
@@ -14,13 +14,13 @@ Evidence trail: [`docs/review-coverage-2026-07-26-phase-11.md`](./review-coverag
14
14
  (addenda 0–9), [`docs/release-and-install.md`](./release-and-install.md),
15
15
  [`docs/migration.md`](./migration.md), [`docs/performance.md`](./performance.md).
16
16
 
17
- ## Current line (0.0.18)
17
+ ## Current line (0.0.19)
18
18
 
19
19
  | Item | Status |
20
20
  |---|---|
21
- | Published graph | **44** publishable manifests at **0.0.18** (`docs/release-and-install.md`) |
22
- | Phase 1 integrity | `repo_search` literal-only, atomic write/edit, `cache_aware` default layout, oldest-first history eviction, MCP SDK 1.30.0, README/readiness alignment |
23
- | Docs tripwires | `node --test dist/__tests__/docs.test.js` — migration section `0.0.17 → 0.0.18` documents intentional breaks |
21
+ | Published graph | **44** publishable manifests at **0.0.19** (`docs/release-and-install.md`) |
22
+ | Phase 2 observational memory | `createObservationalMemory().attach()`, four-layer context, nested settings, recall paging, hard fold/render caps |
23
+ | Docs tripwires | `node --test dist/__tests__/docs.test.js` — migration section `0.0.18 → 0.0.19 observational memory lifecycle` documents intentional breaks |
24
24
  | Readiness table below | **0.0.16 measured values** — refresh evidence columns when 1.0 RC gates are recorded |
25
25
 
26
26
  ## Gate table
@@ -63,7 +63,9 @@ signatures can drift on a TypeScript bump without any real API change).
63
63
 
64
64
  `docs/migration.md` carries release migration sections tripwired by
65
65
  `docs.test.ts` (headings and key phrases). A missing or gutted section fails
66
- the suite. **0.0.18** adds intentional pre-1.0 breaks (`repo_search` literal-only,
66
+ the suite. **0.0.19** adds observational-memory lifecycle and nested settings in
67
+ `@arnilo/prism-compaction-observational-memory` — see `0.0.18 → 0.0.19 observational memory lifecycle`.
68
+ **0.0.18** adds intentional pre-1.0 breaks (`repo_search` literal-only,
67
69
  `cache_aware` default layout, oldest-first history eviction, atomic write/edit
68
70
  durability, MCP SDK bump) — see `0.0.17 → 0.0.18 restore integrity`.
69
71
 
@@ -133,7 +135,7 @@ Exact prerequisites that must be satisfied before cutting 1.0:
133
135
  checked-in baseline.
134
136
  7. **Phase 12 demand evidence** (below) recorded for any capability that 1.0
135
137
  is expected to anchor.
136
- 8. **0.0.18+ integrity gates green** on the release candidate (docs suite,
138
+ 8. **0.0.19+ lifecycle gates green** on the release candidate (docs suite,
137
139
  MCP SDK advisory cleared, coding-tool durability fixes, layout/eviction defaults).
138
140
 
139
141
  ## Phase 12 demand-evidence entry criteria
@@ -8,6 +8,21 @@ Current status: ledger/projection/render/recall utilities, explicit worker runti
8
8
 
9
9
  This package is distinct from `@arnilo/prism-memory` working/semantic memory: observational memory compresses and recalls source-backed observations/reflections; semantic memory retrieves embeddings; working memory stores the current structured profile/state. Hosts may compose both.
10
10
 
11
+ ## Four-layer provider context
12
+
13
+ Observational memory composes four independent layers for long sessions (Mastra-style):
14
+
15
+ | Layer | What it holds | How it is produced |
16
+ | --- | --- | --- |
17
+ | **Recent exact messages** | Last `context.recentMessages` user/assistant/tool entries in branch order (optional `recentMessageMaxTokens` trim, oldest first) | `buildObservationalMemoryContextBlocks()` → `recent-messages` ContextBlock; aligned with compaction `keepRecentEntries` |
18
+ | **Observation log** | Source-backed facts with 12-hex ids and `sourceEntryIds` | Observer worker on eligible unscanned `message` entries after `observation.messageTokens`; coverage advances even on empty passes |
19
+ | **Reflections** | Higher-level summaries over observation ids | Reflector worker on observations after last reflection coverage when `reflection.observationTokens` met |
20
+ | **Raw-source retrieval** | Exact branch messages behind a memory id or cursor page | `recallObservationalMemory()` / `recallObservationalMemoryBranchPage()` / `createRecallMemoryTool()` — exact-id or cursor paging only; no semantic search |
21
+
22
+ Activation is explicit: `createObservationalMemory().attach()` coordinates post-run observe/reflect/drop and `context.compactAfterTokens` compaction. Import and extension `setup` start nothing. Recall, commands, and utilities fail closed on invalid ids, wrong `sessionId`, ambiguous tool input, or oversized pages. Pass `secrets` for exact-value redaction in render/recall/worker paths. Branch isolation: hosts supply current-branch `appendEntry` and `getEntries`; mismatched store/session pairs fail closed after append.
23
+
24
+ See `examples/observational-memory-lifecycle.ts` for attach → turn → projection/recall/page without live credentials.
25
+
11
26
  ## When to use it
12
27
 
13
28
  Use it when a host wants to opt in to long-session memory that records observations/reflections as session custom entries, renders prepared memory during compaction, and supports exact-id recall.
@@ -20,7 +35,7 @@ Memory records use `SessionEntry.kind: "custom"` with `entry.data.type` markers:
20
35
 
21
36
  | Type | Payload |
22
37
  | --- | --- |
23
- | `om.observations.recorded` | `{ observations, coversUpToId? }` |
38
+ | `om.observations.recorded` | `{ observations, coversUpToId? }` — successful observer runs append coverage even when `observations` is empty. |
24
39
  | `om.reflections.recorded` | `{ reflections, coversUpToId? }` |
25
40
  | `om.observations.dropped` | `{ observationIds, coversUpToId? }` |
26
41
  | `om.folded` | Compaction `data.memory` folded details. |
@@ -38,6 +53,10 @@ Worker limits are finite positive safe integers:
38
53
  | `maxWorkerResultBytes` | 64 KiB | 1 MiB | Full tool result and replayed value/error payload |
39
54
  | `maxWorkerMessageBytes` | 1 MiB | 8 MiB | System/prompt plus assistant-call/tool-result transcript |
40
55
  | `maxWorkerErrorBytes` | 1 KiB | 8 KiB | Provider/tool/runtime error text after exact known-secret redaction |
56
+ | Rendered memory projection | — | 256 KiB | `renderObservationalMemory()` / context block text |
57
+ | Folded compaction payload | — | 512 KiB | `data.memory` JSON; strategy trims lowest-relevance observations before failing |
58
+ | Recent-message window | — | 512 KiB | `renderRecentMessageWindow()` hard cap |
59
+ | Recall page size | 20 | 100 | `retrieval.pageLimit` / recall tool `limit` |
41
60
 
42
61
  Direct `runObserver()` / `runReflector()` / `runDropper()` calls retain required `maxTurns` and accept the corresponding shorter worker fields (`maxToolCalls`, `maxResultBytes`, etc.). Named default/hard constants and `resolveMemoryWorkerLimits()` are exported.
43
62
 
@@ -48,20 +67,26 @@ Key exports:
48
67
  | Export | Purpose |
49
68
  | --- | --- |
50
69
  | `foldObservationalMemoryLedger()` | Fold custom memory entries into observations, reflections, drops, and coverage markers. |
70
+ | `isEligibleObservationSourceEntry()` / `eligibleObservationSources()` | Select user/assistant/tool `message` entries for observer input. |
71
+ | `unscannedEntries()` / `observationsUncoveredByReflection()` | Dual coverage helpers for observation scan and reflection windows. |
51
72
  | `buildObservationalMemoryProjection()` | Build active/full/folded projections from current branch entries. |
73
+ | `buildObservationalMemoryContextBlocks()` | Render observational-memory + recent-messages context blocks for provider input. |
74
+ | `selectRecentMessageEntries()` / `renderRecentMessageWindow()` | Bounded exact recent-message suffix; count via `keepRecentEntries`, optional token trim via `estimateEntryTokens`. |
52
75
  | `createFoldedMemoryDetails()` | Create JSON details for compaction `data.memory`. |
53
76
  | `renderObservationalMemory()` | Render reflections and observations into a prepared memory summary. |
54
77
  | `recallObservationalMemory()` | Recover source evidence for a known observation/reflection id from supplied current-branch entries. |
78
+ | `recallObservationalMemoryBranchPage()` | Page eligible user/assistant/tool messages around a cursor entry id (`forward`/`backward`, optional `detail: summary|full`). |
55
79
  | `createMemoryId()` / `isMemoryId()` | Create/check 12-character ids. |
56
80
  | `resolveObservationalMemorySettings()` | Merge `observational-memory` settings with defaults and overrides. |
57
- | `createObservationalMemoryRuntime()` | Explicitly run observer/reflector/dropper workers for a supplied session, owned append callback, and provider. |
81
+ | `createObservationalMemory()` / `attach()` | One activation wires post-run observe/reflect/drop and `compactAfterTokens` compaction; returns proxied session, runtime, context provider, and strategy. |
82
+ | `createObservationalMemoryRuntime()` | Low-level explicit flush for advanced hosts or tests. |
58
83
  | `createObservationalMemoryCompactionStrategy()` | Render existing folded memory as a standard Prism compaction summary with `data.memory`. |
59
84
  | `createObservationalMemoryExtension()` | Inert extension helper that registers the strategy contribution unless disabled. |
60
- | `createRecallMemoryTool()` | Optional exact-id `recall` tool factory backed by host-supplied current-branch entries. |
85
+ | `createRecallMemoryTool()` | Optional `recall` tool factory: exact id lookup or current-branch message paging via host-supplied entries. |
61
86
  | `createMemoryStatusCommand()` / `createMemoryViewCommand()` | Optional `om:status` and `om:view` command factories. |
62
87
  | `createObservationalMemoryCommands()` | Convenience factory returning status and view commands. |
63
88
 
64
- Pure utilities create no events, workers, tools, commands, credentials, or provider requests. `createObservationalMemoryRuntime()` runs workers only when the host explicitly constructs it and calls `flush()`. The compaction strategy is O(n) over supplied entries and makes no provider call. Tool and command factories are inert until a host registers/selects them.
89
+ Pure utilities create no events, workers, tools, commands, credentials, or provider requests. `createObservationalMemoryExtension()` and import alone start nothing. `createObservationalMemory().attach()` runs workers only after proxied `run`/`prompt`/`stream`/`compact` complete (or after `wrapResumeRun` / `wrapResumeStream`). `createObservationalMemoryRuntime().flush()` remains for manual/advanced use. Attached `contextProvider` renders two blocks each turn: `observational-memory` (active reflections/observations aligned to the recent-message boundary) and `recent-messages` (last `keepRecentEntries` message entries in branch order, optionally trimmed by `recentMessageMaxTokens` using `estimateEntryTokens`; oldest dropped first). Compaction uses the same `keepRecentEntries` setting. Observer input includes only eligible `message` entries (`user`, `assistant`, `tool`); memory/compaction/bookkeeping entries advance `coversUpToId` scan coverage without entering the observer prompt. Successful observer/reflector runs append coverage markers even when they record zero facts. Reflection uses only active observations recorded after the last `om.reflections.recorded` entry unless `flush({ fullReflectionRebuild: true })`. Attached `flush()` skips with `run_active` while a proxied run is in flight. The compaction strategy is O(n) over supplied entries and makes no provider call. Tool and command factories are inert until a host registers/selects them.
65
90
 
66
91
  ## Request/response example
67
92
 
@@ -74,6 +99,7 @@ Pure utilities create no events, workers, tools, commands, credentials, or provi
74
99
  ```ts
75
100
  import {
76
101
  buildObservationalMemoryProjection,
102
+ createObservationalMemory,
77
103
  createObservationalMemoryCompactionStrategy,
78
104
  createObservationalMemoryExtension,
79
105
  createObservationalMemoryCommands,
@@ -83,6 +109,18 @@ import {
83
109
  renderObservationalMemory,
84
110
  } from "@arnilo/prism-compaction-observational-memory";
85
111
 
112
+ const om = createObservationalMemory({
113
+ observation: { provider: observerProvider, model: observerModel, messageTokens: 10_000 },
114
+ reflection: { provider: reflectorProvider, model: reflectorModel, observationTokens: 20_000 },
115
+ context: { compactAfterTokens: 81_000, recentMessages: 8 },
116
+ retrieval: { pageLimit: 20 },
117
+ });
118
+ const attached = om.attach(session, {
119
+ appendEntry: (entry, options) => store.append(entry, options),
120
+ sessionModel: agent.config.model,
121
+ });
122
+ await attached.session.run("Continue from prior work");
123
+
86
124
  const entries = await session.entries();
87
125
  const projection = buildObservationalMemoryProjection(entries);
88
126
  const summary = renderObservationalMemory(projection.reflections, projection.observations);
@@ -111,13 +149,19 @@ await kernel.load([createObservationalMemoryExtension({ recallTool: { getEntries
111
149
 
112
150
  ## Extension and configuration notes
113
151
 
114
- Settings are read from the `observational-memory` key only when a host calls `resolveObservationalMemorySettings()` or `runtime.flush()`. Defaults are `observeAfterTokens: 10000`, `reflectAfterTokens: 20000`, `compactAfterTokens: 81000`, `observationsPoolMaxTokens: 20000`, `observationsPoolTargetTokens: 10000`, `agentMaxTurns: 16`, `passive: false`, and `debugLog: false`. `agentMaxTurns` now rejects non-integer/non-finite/out-of-range input (hard 64) instead of flooring/falling back. Runtime `maxWorkerTurns` takes precedence.
152
+ Settings resolve to nested `observation` / `reflection` / `dropper` / `context` / `retrieval` groups via `resolveObservationalMemorySettings()`. Defaults: `observation.messageTokens: 10000`, `reflection.observationTokens: 20000`, `context.compactAfterTokens: 81000`, `context.recentMessages: 8`, `context.observationsPoolMaxTokens: 20000`, `dropper.targetTokens: 10000` (from `context.observationsPoolTargetTokens`), `retrieval.pageLimit: 20`, `agentMaxTurns: 16`, `passive: false`, `debugLog: false`. Optional `context.recentMessageMaxTokens` trims the recent-message context window (oldest first) after the count limit.
153
+
154
+ Legacy flat keys still map for pre-1.0 hosts (`observeAfterTokens` → `observation.messageTokens`, `reflectAfterTokens` → `reflection.observationTokens`, `compactAfterTokens` → `context.compactAfterTokens`, `keepRecentEntries` → `context.recentMessages`, flat `workerModel` → all workers when nested models absent). Conflicting flat+nested values throw.
155
+
156
+ Observer/reflector/dropper may use separate providers, models, instructions, thinking levels, credentials, and `requireExplicitModel`. `dropper.policy: "lowest-relevance"` drops deterministically without a model call; default is `"model"`. Top-level `workerProvider` / `workerModel` remain as deprecated aliases.
157
+
158
+ Token counting uses `estimateEntryTokens()` / `estimateMessageTokens()`.
115
159
 
116
- The runtime requires host-supplied `session`, an `appendEntry` callback bound to that session's owning store/branch, and `workerProvider`. Model selection uses [use-case model selection](use-case-model-selection.md): pass optional `workerModel` (or settings `workerModel`) to override, and `sessionModel: agent.config.model` so workers fall back to the session model when no worker model is configured. `requireExplicitModel: true` restores the historical `missing_model` skip when no explicit worker model is set. It no longer accepts a separate `store` option because mismatched session/store pairs can append memory entries outside the active branch. After each memory append, the runtime checks the appended entry is visible at the session leaf and fails closed/restores the previous checkout if the callback points elsewhere. Optional credential resolution is explicit; missing requested credentials skip worker execution. Default credential requests use the **resolved** model's provider id.
160
+ The runtime requires host-supplied `session`, an `appendEntry` callback bound to that session's owning store/branch, and at least one worker provider (`observation.provider` or legacy `workerProvider`). Model selection uses [use-case model selection](use-case-model-selection.md): pass per-worker `model` (or settings `observation.model` / `reflection.model` / `dropper.model`) to override, and `sessionModel: agent.config.model` so workers fall back to the session model when no worker model is configured. `requireExplicitModel: true` restores the historical `missing_model` skip when no explicit worker model is set. It no longer accepts a separate `store` option because mismatched session/store pairs can append memory entries outside the active branch. After each memory append, the runtime checks the appended entry is visible at the session leaf and fails closed/restores the previous checkout if the callback points elsewhere. Optional credential resolution is explicit; missing requested credentials skip worker execution. Default credential requests use the **resolved** model's provider id.
117
161
 
118
- `createObservationalMemoryCompactionStrategy()` keeps recent message entries like the default compaction strategy, renders existing observations/reflections as the summary, and returns a standard Prism compaction entry. Its `data` includes `throughEntryId`, `keepEntryIds`, `strategy`, `trigger`, and `memory: { type: "om.folded", version: 1, fullFold, observations, reflections, droppedObservationIds }`. When active observations exceed `observationsPoolMaxTokens`, it performs a full fold into `data.memory`.
162
+ `createObservationalMemoryCompactionStrategy()` keeps recent message entries like the default compaction strategy, renders existing observations/reflections as the summary, and returns a standard Prism compaction entry. Its `data` includes `throughEntryId`, `keepEntryIds`, `strategy`, `trigger`, and `memory: { type: "om.folded", version: 1, fullFold, observations, reflections, droppedObservationIds }`. When active observations exceed `context.observationsPoolMaxTokens`, it performs a full fold and synchronously trims lowest-relevance observations until the folded payload fits hard byte/token caps (or throws a typed error).
119
163
 
120
- `createRecallMemoryTool()` requires `args.id` to match `^[a-f0-9]{12}$`; invalid ids fail before entry lookup. Recall returns text and structured details for observations/reflections, dropped observations, supporting observations, source entries, and missing source ids. It does not search by topic.
164
+ `createRecallMemoryTool()` accepts either `{ id }` for exact memory recall or `{ cursor, limit?, direction?, detail? }` for current-branch raw-message paging (default limit 20, hard cap 100). Reflection recall resolves supporting observations from the full ledger and reports `droppedSupportingObservationIds` / `missingSupportingObservationIds`; dropped supports still return available raw sources. Invalid ids, ambiguous requests, wrong `sessionId`, missing cursors, non-message cursors, and oversized pages fail closed. It does not search by topic.
121
165
 
122
166
  `createMemoryStatusCommand()` reports recorded/dropped/active/visible observations, recorded/visible reflections, pool token counts, and optional runtime in-flight/last-error state. `createMemoryViewCommand()` renders visible memory by default or full active recorded memory with `{ mode: "full" }`; other modes return `Usage: /om:view [full]`.
123
167
 
package/docs/index.md CHANGED
@@ -25,7 +25,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
25
25
  ## Compaction/session memory
26
26
  - [Compaction and retry policies](compaction-and-retry.md): summarize branch history and retry transient provider failures with host-replaceable policies.
27
27
  - [LLM compaction package](compaction-llm.md): optional provider-backed strategy with finite summary/reserve/error caps, bounded redacted streaming retention, mandatory finite post-policy `model.parameters.maxTokens`, and `createCodingCompactionStrategy()` for coding handoff focus.
28
- - [Observational memory compaction package](compaction-observational-memory.md): optional source-backed memory with owned append callback, finite turn/call/argument/result/transcript/error worker limits, redacted provider-valid transcripts, fast compaction, recall, and status/view commands; worker model falls back to host-supplied `sessionModel`.
28
+ - [Observational memory compaction package](compaction-observational-memory.md): optional source-backed memory with explicit `attach()` lifecycle — **Recent exact messages**, **Observation log**, **Reflections**, **Raw-source retrieval** (exact-id recall + cursor paging); dual coverage, nested settings with legacy map, branch-isolated `appendEntry`, secrets redaction, and inert import/extension.
29
29
  - [Working and semantic memory](working-and-semantic-memory.md): optional `@arnilo/prism-memory` working-memory store, semantic recall, finite Embedder/VectorStore contracts, PostgreSQL/pgvector path, consent lifecycle, identity-bound redacted export, and resumable bounded rebuild.
30
30
  - [Session stores](session-stores.md): `SessionStore` contract, `SessionAppendOptions`, `SessionAppendConflictError`, branch handles, `readBranchPath`, optional bounded `searchSessions` / `SessionIndex` (memory linear|unsupported), and dev-vs-production branch reads — start here for session persistence.
31
31
  - [Conversations](conversations.md): durable user-scoped conversation threads (create/list/continue/branch/archive/export/delete) on session + event-ledger seams, thread-bound reconnectable replay, frozen caps, and legal-hold-aware deletion.
@@ -117,8 +117,8 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
117
117
  - `examples/`: compile-checked typed examples and runnable mock demos (SDK basics, provider registration, auth, tools, [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts), [`examples/enterprise-identity.ts`](../examples/enterprise-identity.ts), [`examples/enterprise-policy-audit.ts`](../examples/enterprise-policy-audit.ts), [`examples/enterprise-work-connectors.ts`](../examples/enterprise-work-connectors.ts), [`examples/conversation-durable-replay.ts`](../examples/conversation-durable-replay.ts), [`examples/artifact-review-delivery.ts`](../examples/artifact-review-delivery.ts), [`examples/server-deployment-seams.ts`](../examples/server-deployment-seams.ts), cache-aware prompt assembly, NeuralWatt agent run ([`examples/neuralwatt-agent-run.ts`](../examples/neuralwatt-agent-run.ts)), [`examples/coding-compaction.ts`](../examples/coding-compaction.ts), stores/branching, structured-output/artifact-loop, CLI, RPC, workflow orchestration).
118
118
 
119
119
  ## Release and install
120
- - [Release and install](release-and-install.md): current **0.0.18** 44-package graph (Phase 1 restore integrity; plan 001), exact-peer/install/tarball rules, deterministic resumable publication and publish dry-run, pinned supply-chain gates, offline tests, the 0.0.15 provider/AI-SDK/RAG/memory protected live-canary matrix, and sandbox-browser Docker/Playwright gates.
121
- - [0.1.0 / 1.0 readiness gates](0.1.0-readiness.md): command-per-gate 1.0 readiness table — frozen API surface + compat gate, migration/docs tripwires, budget table, live-suite matrix, security matrix, current-line status (**0.0.18** published target), signed-publication/live-canary prerequisites for 1.0, and Phase 12 demand-evidence entry criteria.
120
+ - [Release and install](release-and-install.md): current **0.0.19** 44-package graph (Phase 2 observational memory lifecycle; plan 002), exact-peer/install/tarball rules, deterministic resumable publication and publish dry-run, pinned supply-chain gates, offline tests, the 0.0.15 provider/AI-SDK/RAG/memory protected live-canary matrix, and sandbox-browser Docker/Playwright gates.
121
+ - [0.1.0 / 1.0 readiness gates](0.1.0-readiness.md): command-per-gate 1.0 readiness table — frozen API surface + compat gate, migration/docs tripwires, budget table, live-suite matrix, security matrix, current-line status (**0.0.19** published target), signed-publication/live-canary prerequisites for 1.0, and Phase 12 demand-evidence entry criteria.
122
122
  - [Review coverage (2026-07-26 Phase 11)](review-coverage-2026-07-26-phase-11.md): Plan 079 evidence freeze — baseline size/startup/benchmark budgets, hotspot domain extraction table, confirmed duplication survivors (redactor/cleanJson/row-codecs/checkpoints/exec-runner/approval/ownership), profile adoption recommendations, and tarball artifact-diet findings for 0.0.16.
123
123
  - [Review coverage (2026-07-26 Phase 10)](review-coverage-2026-07-26-phase-10.md): Plan 078 evidence freeze — OpenAI hosted tools/continuation/realtime, AI SDK version matrix, remaining provider metadata parity, RAG replaceSource/loaders/parsers/reranker/provenance/ingestion-status, memory export/rebuild/conformance, and 0.0.15 (43 → 43 manifests; no new package) release gates.
124
124
  - [Review coverage (2026-07-25 Phase 9)](review-coverage-2026-07-25-phase-9.md): Plan 077 evidence freeze — conversation service, memory consent/lifecycle, artifact co-work review, AG-UI co-work events, scoped M365/GWS OAuth, browser checkpoint composition, and deny-by-default device contracts for 0.0.14 (41 → 43 manifests; only the two provider packages are new).
package/docs/migration.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Migration guide
2
2
 
3
+ ## 0.0.18 → 0.0.19 observational memory lifecycle (small intentional breaks)
4
+
5
+ Release **0.0.19** completes Phase 2 observational memory in `@arnilo/prism-compaction-observational-memory` only; core `@arnilo/prism` runtime behavior is unchanged.
6
+
7
+ 1. **Preferred host path: `createObservationalMemory().attach()`.** Post-run observe/reflect/drop and `compactAfterTokens` compaction run automatically after proxied `run`/`prompt`/`stream`/`compact` (and via `wrapResumeRun` / `wrapResumeStream`). Manual `createObservationalMemoryRuntime().flush()` remains on `attached.runtime` for advanced hosts.
8
+ 2. **Nested settings replace flat keys.** Use `observation` / `reflection` / `dropper` / `context` / `retrieval` groups from `resolveObservationalMemorySettings()`. Legacy flat keys still map (`observeAfterTokens` → `observation.messageTokens`, `reflectAfterTokens` → `reflection.observationTokens`, `compactAfterTokens` → `context.compactAfterTokens`, `keepRecentEntries` → `context.recentMessages`, flat `workerModel` → all workers when nested models absent). **Throw** if flat and nested values conflict.
9
+ 3. **Separate observer/reflector/dropper models.** Pass per-worker `provider` / `model` / `instruction` / `thinkingLevel` under `observation`, `reflection`, and `dropper`. `dropper.policy: "lowest-relevance"` drops without a model; default is `"model"`.
10
+ 4. **Reflection recall reads the full ledger.** Supporting observations dropped from the active pool still resolve in `recallObservationalMemory()` with `dropped` / `missingSourceEntryIds` status instead of being invisible.
11
+ 5. **Recall tool adds current-branch paging.** `createRecallMemoryTool()` accepts either `{ id }` or `{ cursor, limit?, direction?, detail? }` (default limit 20, hard cap 100). Both `id` and `cursor` together fail closed.
12
+ 6. **Coverage and eligibility fixes.** Observer input is eligible `user`/`assistant`/`tool` messages only; bookkeeping/compaction/custom OM entries advance scan coverage without entering the prompt. Empty observer passes still append `coversUpToId`. Compaction `fullFold` actively trims lowest-relevance observations to hard byte caps.
13
+
14
+ Example: `node examples/observational-memory-lifecycle.ts` (network-free). Live worker canary: `PRISM_LIVE_OBSERVATIONAL_MEMORY_TESTS=1` (Task 7 gate).
15
+
3
16
  ## 0.0.17 → 0.0.18 restore integrity (small intentional break)
4
17
 
5
18
  Release **0.0.18** removes model-facing regex from `repo_search`:
@@ -8,7 +8,7 @@ Core package:
8
8
 
9
9
  - `@arnilo/prism` — the runtime, contracts, registries, streaming events, CLI (including `prism init`), and the `/docs` hub. `files`: `dist` (with `!dist/__tests__` and `!dist/**/*.map` negations), `docs`, `templates`, `CHANGELOG.md`. `bin`: `prism` -> `dist/cli.js`. `sideEffects`: `["dist/cli.js"]`.
10
10
 
11
- First-party workspace packages (each has non-optional `@arnilo/prism@0.0.18` peer and `sideEffects: false`; RAG also peers on memory, and server also peers on workflows):
11
+ First-party workspace packages (each has non-optional `@arnilo/prism@0.0.19` peer and `sideEffects: false`; RAG also peers on memory, and server also peers on workflows):
12
12
 
13
13
  - `@arnilo/prism-provider-anthropic`, `@arnilo/prism-provider-google`, `@arnilo/prism-provider-openai`, `@arnilo/prism-provider-openrouter`, `@arnilo/prism-provider-kimi`, `@arnilo/prism-provider-zai`, `@arnilo/prism-provider-opencode-go`, `@arnilo/prism-provider-neuralwatt` — provider adapters.
14
14
  - `@arnilo/prism-provider-azure`, `@arnilo/prism-provider-bedrock`, `@arnilo/prism-provider-vertex` — optional enterprise-cloud adapters (Entra/IAM/ADC; separate from consumer Anthropic/Google).
@@ -36,7 +36,7 @@ First-party workspace packages (each has non-optional `@arnilo/prism@0.0.18` pee
36
36
 
37
37
  ### 0.0.12 AG-UI package boundary
38
38
 
39
- `@arnilo/prism-ag-ui` is a publishable optional code package with root AG-UI exports and stable `./acp` sibling, peer `@arnilo/prism@0.0.18`, pinned `@ag-ui/core@0.0.57` / `@agentclientprotocol/sdk@1.3.0`, and no import-time network/listener/run. It is included by `@arnilo/prism-all` only—not `@arnilo/prism-code` or `@arnilo/prism-sdk`—so coding and SDK profiles stay free of UI protocol dependencies.
39
+ `@arnilo/prism-ag-ui` is a publishable optional code package with root AG-UI exports and stable `./acp` sibling, peer `@arnilo/prism@0.0.19`, pinned `@ag-ui/core@0.0.57` / `@agentclientprotocol/sdk@1.3.0`, and no import-time network/listener/run. It is included by `@arnilo/prism-all` only—not `@arnilo/prism-code` or `@arnilo/prism-sdk`—so coding and SDK profiles stay free of UI protocol dependencies.
40
40
 
41
41
  Family/profile packages (pure manifests, no code or `dist`; ship `README.md` and `CHANGELOG.md`; use exact hard `dependencies`):
42
42
 
@@ -78,9 +78,9 @@ Consumers install the core package for the runtime and add first-party packages
78
78
  | Run the default (network-free) test suite | `npm test` |
79
79
  | Dry-run pack core + every package | `npm run pack:dry-run` |
80
80
  | Local mirror of the release verify gate | `npm run release:dry-run` |
81
- | Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.18` |
82
- | Preview deterministic publish order | `npm run release:publish -- --version 0.0.18 --dry-run --allow-dirty --allow-untagged` |
83
- | Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.18 --resume --report release-artifacts/publish-report.json` |
81
+ | Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.19` |
82
+ | Preview deterministic publish order | `npm run release:publish -- --version 0.0.19 --dry-run --allow-dirty --allow-untagged` |
83
+ | Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.19 --resume --report release-artifacts/publish-report.json` |
84
84
  | Full SDK readiness gate (typecheck + offline tests + pack) | `npm run sdk:ready` |
85
85
 
86
86
  Public core import specifiers (from the root `exports` map):
@@ -117,7 +117,7 @@ A packed tarball contains only public compiled output and release files:
117
117
  - Code packages ship `README.md`, `LICENSE`, and `CHANGELOG.md`; family/profile packages ship `README.md` and `CHANGELOG.md`.
118
118
  - The core tarball additionally ships the full `docs/` directory (the docs hub) and `templates/init/` used by `prism init`.
119
119
  - `dist/cli.js` and the `bin` link in core.
120
- - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.18.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.18.tgz` / `arnilo-prism-compaction-<name>-0.0.18.tgz` / `arnilo-prism-coding-agent-0.0.18.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.18.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
120
+ - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.19.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.19.tgz` / `arnilo-prism-compaction-<name>-0.0.19.tgz` / `arnilo-prism-coding-agent-0.0.19.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.19.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
121
121
 
122
122
  Excluded from every tarball by `files` negation:
123
123
 
@@ -136,9 +136,9 @@ Excluded from every tarball by `files` negation:
136
136
  "name": "host-app",
137
137
  "type": "module",
138
138
  "dependencies": {
139
- "@arnilo/prism": "0.0.18",
140
- "@arnilo/prism-provider-openai": "0.0.18",
141
- "@arnilo/prism-compaction-observational-memory": "0.0.18"
139
+ "@arnilo/prism": "0.0.19",
140
+ "@arnilo/prism-provider-openai": "0.0.19",
141
+ "@arnilo/prism-compaction-observational-memory": "0.0.19"
142
142
  }
143
143
  }
144
144
  ```
@@ -181,11 +181,11 @@ For SDK readiness, run the same one-command gate directly. It composes existing
181
181
  npm run sdk:ready
182
182
  ```
183
183
 
184
- Release publication derives all **44** manifests from the workspace once, validates exact `0.0.18` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.18` and rejects any existing registry version. `release:publish --resume` skips only registry versions whose internal dependency fingerprint matches the local manifest; conflicting versions fail closed. Each attempted package is written immediately to the JSON report, so a failed job can rerun safely. `--dry-run` performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag, but does not publish.
184
+ Release publication derives all **44** manifests from the workspace once, validates exact `0.0.19` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.19` and rejects any existing registry version. `release:publish --resume` skips only registry versions whose internal dependency fingerprint matches the local manifest; conflicting versions fail closed. Each attempted package is written immediately to the JSON report, so a failed job can rerun safely. `--dry-run` performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag, but does not publish.
185
185
 
186
186
  ```bash
187
- npm run release:check -- --version 0.0.18
188
- npm run release:publish -- --version 0.0.18 --dry-run --allow-dirty --allow-untagged
187
+ npm run release:check -- --version 0.0.19
188
+ npm run release:publish -- --version 0.0.19 --dry-run --allow-dirty --allow-untagged
189
189
  ```
190
190
 
191
191
  `--allow-dirty` and `--allow-untagged` exist only for local preview; real publication and CI never pass them. npm registry calls occur only in these release preflight/publication commands, never build/test/package discovery.
@@ -196,6 +196,27 @@ Optional live smoke tests stay separate from SDK readiness because they require
196
196
  PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
197
197
  ```
198
198
 
199
+ ### 0.0.19 publish handoff
200
+
201
+ **Decision: GO after protected operator prerequisites below.** Release **0.0.19** (Phase 2 observational memory lifecycle, plan 002) ships `@arnilo/prism-compaction-observational-memory` attach lifecycle, four-layer provider context, nested settings with legacy map, source-faithful recall/paging, and hard fold/render caps. Core `@arnilo/prism` runtime is unchanged. The exact graph stays **44 publishable manifests**; no package added or retired. Intentional pre-1.0 breaks are documented in [migration](migration.md) under `0.0.18 → 0.0.19 observational memory lifecycle`.
202
+
203
+ ```bash
204
+ git diff --check
205
+ npm ci
206
+ npm run sdk:ready
207
+ node --test scripts/budget-gate.test.mjs
208
+ node scripts/scan-secrets.mjs && node scripts/verify-sbom.mjs
209
+ npm audit --audit-level=moderate
210
+ npm run release:gate
211
+ npm run release:check -- --version 0.0.19 --allow-dirty --allow-untagged --report /tmp/prism-0.0.19-preflight.json
212
+ npm run release:publish -- --version 0.0.19 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.19-dry-run.json
213
+ git tag -s v0.0.19 -m "Prism 0.0.19"
214
+ git verify-tag v0.0.19
215
+ git push origin v0.0.19
216
+ ```
217
+
218
+ The dry-run checks every registry collision and executes npm's non-publishing tarball validation for each dependency-ordered manifest. The protected tag workflow alone publishes through `npm run release:publish -- --version "${GITHUB_REF_NAME#v}" --resume --report release-artifacts/publish-report.json`; re-run a failed job for the same tag. `npm audit signatures --json --include-attestations` and artifact checksums remain post-publish checks.
219
+
199
220
  ### 0.0.18 publish handoff
200
221
 
201
222
  **Decision: GO after protected operator prerequisites below.** Release **0.0.18** (Phase 1 restore integrity, plan 001) hardens coding tools and release trust without adding packages: `repo_search` is literal-only (ReDoS mitigation), default `write`/`edit` use temp+`rename`, `applyContextBudget` evicts oldest history first, default `inputLayout` is `cache_aware`, `@arnilo/prism-mcp` pins `@modelcontextprotocol/sdk` **1.30.0** (clears moderate `@hono/node-server` advisory), and README/readiness docs match the 14-adapter / optional-browser inventory. The exact graph stays **44 publishable manifests**; no package added or retired. Intentional pre-1.0 breaks are documented in [migration](migration.md) under `0.0.17 → 0.0.18 restore integrity`.
@@ -793,7 +814,7 @@ npm publication is not transactional and published versions are immutable. Parti
793
814
 
794
815
  ## Extension and configuration notes
795
816
 
796
- - **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.18` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.18` for the current 0.x release and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
817
+ - **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.19` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.19` for the current 0.x release and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
797
818
  - **Public access.** All 43 manifests (37 code packages + 6 family/profile packages) declare `"publishConfig": { "access": "public" }`; the publisher also passes `--access public` explicitly because scoped packages otherwise default to restricted on first publish.
798
819
  - **Map retention knob.** Source maps are emitted locally but stripped from tarballs by `!dist/**/*.map`. Removing that `files` negation ships maps in releases (larger tarballs, better consumer stack traces).
799
820
  - **Release workflow.** `.github/workflows/release.yml` has six jobs. `verify` runs network-free SDK readiness on Node 24; `node20-compat` builds/imports every public root `exports` default target on Node 20 for declared `engines.node >=20` (docs examples need Node >=22.6 native TypeScript stripping); `postgres-integration` uses `pgvector/pgvector:pg16`; `supply-chain` runs high-severity audit, SPDX/license policy, and tracked-source secret scanning; and tag-only `codeql-release` runs SAST. Tag-only `publish` needs all five gates, preserves clean exact-tag/version/topological publication, and alone receives `NPM_TOKEN`, `id-token: write`, and `attestations: write`. Before npm publish it packs all current tarballs, generates checksums plus SPDX, scans unpacked public artifacts, creates GitHub attestations for tarballs and SBOM, then retains artifacts for 30 days. Registry state remains the resumable journal. Local `npm run release:dry-run` remains network-free SDK readiness; local PostgreSQL coverage is `PRISM_TEST_POSTGRES_URL=... npm run test:postgres`.
@@ -815,7 +836,7 @@ npm publication is not transactional and published versions are immutable. Parti
815
836
  - `PRISM_TEST_DOCKER_SANDBOX=1` — gates `@arnilo/prism-coding-security` protected Docker matrix. Requires host-preloaded digest-pinned `PRISM_TEST_DOCKER_IMAGE` and absolute `PRISM_TEST_DOCKER_BIN` (optional `PRISM_TEST_DOCKER_USER`). Prism never pulls/builds the image during default tests. Missing prerequisites fail closed when the gate is enabled; disabled gate skips safely.
816
837
  - `PRISM_LIVE_CANARIES=1` — gates `scripts/live-canary.mjs`, used only by scheduled/manual `.github/workflows/live-canaries.yml` in protected `live-canaries` environment. It requires provider endpoint/key/model, MCP endpoint/token, A2A endpoint/token, and Brave token environment entries; performs four probes plus at most one MCP session DELETE; caps provider output at one token, each response at 64 KiB, each request at 15 seconds (30 seconds hard), and emits only aggregate kind/status/code/duration. Disabled gate skips before network; enabled but incomplete configuration fails closed.
817
838
  - `PRISM_LIVE_COMPACTION_TESTS=1` — gates `@arnilo/prism-compaction-llm`'s live summary-provider smoke test (placeholder).
818
- - `PRISM_LIVE_OBSERVATIONAL_MEMORY_TESTS=1` — gates `@arnilo/prism-compaction-observational-memory`'s live worker/provider checks (placeholder).
839
+ - `PRISM_LIVE_OBSERVATIONAL_MEMORY_TESTS=1` — gates `@arnilo/prism-compaction-observational-memory`'s live observer/reflector worker canary. Requires `OPENAI_API_KEY`; gate enabled without key fails closed.
819
840
  - `PRISM_TEST_POSTGRES_URL` — gates `@arnilo/prism-session-store-postgres` and `@arnilo/prism-memory` integration tests against a real database (memory path requires pgvector). Local: `PRISM_TEST_POSTGRES_URL=... npm run test:postgres`. CI: `postgres-integration` job with `pgvector/pgvector:pg16`.
820
841
  - `PRISM_TEST_KEYCHAIN=1` — gates `@arnilo/prism-credentials-node` system-keychain round-trips (requires a working OS keychain backend; skipped by default).
821
842
  - Provider live tests read the API key from the env only when both gates are set; the key is used as a bearer token and never logged. `assertNoSecretLeak` verifies the key value does not appear in any streamed event. The compaction placeholders still carry no real credentials.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.0.18",
3
+ "version": "0.0.19",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",