@arnilo/prism 0.0.1 → 0.0.3

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.
Files changed (121) hide show
  1. package/CHANGELOG.md +19 -2
  2. package/README.md +17 -7
  3. package/dist/agent-definitions.d.ts +12 -0
  4. package/dist/agent-definitions.js +131 -0
  5. package/dist/agent-loops.d.ts +14 -0
  6. package/dist/agent-loops.js +161 -0
  7. package/dist/agents.js +263 -76
  8. package/dist/cache-helpers.d.ts +28 -0
  9. package/dist/cache-helpers.js +73 -0
  10. package/dist/cli-runner.d.ts +38 -2
  11. package/dist/cli-runner.js +167 -5
  12. package/dist/compaction.js +2 -0
  13. package/dist/config.js +47 -12
  14. package/dist/contracts.d.ts +581 -6
  15. package/dist/contracts.js +41 -1
  16. package/dist/contribution-parsing.d.ts +19 -0
  17. package/dist/contribution-parsing.js +124 -0
  18. package/dist/contributions.d.ts +13 -3
  19. package/dist/contributions.js +96 -20
  20. package/dist/extensions.js +3 -0
  21. package/dist/index.d.ts +19 -9
  22. package/dist/index.js +10 -4
  23. package/dist/input.d.ts +7 -1
  24. package/dist/input.js +52 -11
  25. package/dist/instruction-injection.d.ts +28 -0
  26. package/dist/instruction-injection.js +55 -0
  27. package/dist/manifests.d.ts +1 -1
  28. package/dist/manifests.js +3 -3
  29. package/dist/models.d.ts +4 -1
  30. package/dist/models.js +5 -2
  31. package/dist/node/agent-definitions.d.ts +98 -0
  32. package/dist/node/agent-definitions.js +389 -0
  33. package/dist/node/contribution-discovery.d.ts +17 -0
  34. package/dist/node/contribution-discovery.js +163 -0
  35. package/dist/node/instruction-injectors.d.ts +32 -0
  36. package/dist/node/instruction-injectors.js +72 -0
  37. package/dist/node/session-store-jsonl.d.ts +1 -1
  38. package/dist/node/session-store-jsonl.js +42 -4
  39. package/dist/node/system-project-prompts.d.ts +30 -0
  40. package/dist/node/system-project-prompts.js +53 -0
  41. package/dist/provider-events.d.ts +3 -1
  42. package/dist/provider-events.js +34 -0
  43. package/dist/provider-request-policy.js +15 -1
  44. package/dist/providers/openai-compatible.js +1 -1
  45. package/dist/providers.d.ts +6 -2
  46. package/dist/providers.js +15 -1
  47. package/dist/redaction.d.ts +2 -1
  48. package/dist/redaction.js +3 -0
  49. package/dist/registry-options.d.ts +5 -0
  50. package/dist/registry-options.js +5 -0
  51. package/dist/rpc.d.ts +6 -2
  52. package/dist/rpc.js +71 -13
  53. package/dist/session-stores.d.ts +3 -1
  54. package/dist/session-stores.js +67 -6
  55. package/dist/skills.d.ts +4 -1
  56. package/dist/skills.js +3 -1
  57. package/dist/system-prompts.js +6 -2
  58. package/dist/testing/compaction-conformance.d.ts +17 -0
  59. package/dist/testing/compaction-conformance.js +61 -0
  60. package/dist/testing/extension-conformance.d.ts +26 -0
  61. package/dist/testing/extension-conformance.js +55 -0
  62. package/dist/testing/provider-conformance.d.ts +7 -0
  63. package/dist/testing/provider-conformance.js +18 -31
  64. package/dist/testing/session-store-conformance.d.ts +20 -0
  65. package/dist/testing/session-store-conformance.js +92 -0
  66. package/dist/testing/tool-conformance.d.ts +39 -0
  67. package/dist/testing/tool-conformance.js +79 -0
  68. package/dist/tools.d.ts +7 -2
  69. package/dist/tools.js +50 -13
  70. package/docs/agent-definitions.md +251 -0
  71. package/docs/agent-events.md +199 -0
  72. package/docs/agent-loops.md +217 -0
  73. package/docs/agent-session-runtime.md +20 -8
  74. package/docs/cli-rpc.md +39 -4
  75. package/docs/coding-agent-tools.md +208 -0
  76. package/docs/compaction-and-retry.md +2 -2
  77. package/docs/compaction-conformance.md +76 -0
  78. package/docs/compaction-llm.md +6 -3
  79. package/docs/compaction-observational-memory.md +4 -4
  80. package/docs/configuration-and-manifests.md +6 -1
  81. package/docs/context-and-skills.md +79 -6
  82. package/docs/contribution-discovery.md +149 -0
  83. package/docs/contribution-registries.md +9 -6
  84. package/docs/credentials-and-redaction.md +2 -0
  85. package/docs/customization.md +191 -0
  86. package/docs/database-persistence.md +407 -0
  87. package/docs/extension-authoring.md +193 -0
  88. package/docs/extension-conformance.md +80 -0
  89. package/docs/extensions.md +6 -0
  90. package/docs/host-security.md +141 -0
  91. package/docs/index.md +41 -19
  92. package/docs/input-and-prompt-assembly.md +19 -3
  93. package/docs/instruction-injection.md +183 -0
  94. package/docs/migration.md +201 -0
  95. package/docs/model-registry.md +122 -0
  96. package/docs/node-jsonl-session-store.md +5 -4
  97. package/docs/performance.md +127 -0
  98. package/docs/provider-caching.md +206 -0
  99. package/docs/provider-conformance.md +32 -5
  100. package/docs/provider-layer.md +51 -11
  101. package/docs/provider-packages.md +65 -5
  102. package/docs/provider-request-policies.md +113 -0
  103. package/docs/providers/kimi.md +22 -0
  104. package/docs/providers/neuralwatt.md +388 -0
  105. package/docs/providers/openai-compatible.md +1 -0
  106. package/docs/providers/openai.md +21 -0
  107. package/docs/providers/opencode-go.md +31 -3
  108. package/docs/providers/openrouter.md +29 -0
  109. package/docs/providers/zai.md +17 -0
  110. package/docs/public-contracts.md +87 -12
  111. package/docs/release-and-install.md +79 -27
  112. package/docs/runs-and-usage.md +236 -0
  113. package/docs/session-store-conformance.md +78 -0
  114. package/docs/session-stores-and-branching.md +10 -6
  115. package/docs/session-stores.md +126 -0
  116. package/docs/settings-auth-trust-security.md +18 -4
  117. package/docs/structured-output.md +247 -0
  118. package/docs/system-prompts.md +104 -2
  119. package/docs/tool-conformance.md +87 -0
  120. package/docs/tools.md +65 -8
  121. package/package.json +36 -2
@@ -83,12 +83,41 @@ await kernel.load([
83
83
  - Hosts choose base URL, attribution, credential source, and `fetch` impl.
84
84
  - Package contributes models and an `api_key` auth method.
85
85
 
86
+ ### Cache and session behavior
87
+
88
+ - `session_id` (request body) and the `X-Session-Id` header are derived from
89
+ `ProviderRequestOptions.cacheKey` (falling back to `sessionId`) and sanitized
90
+ + clamped to 256 characters via the shared `sanitizeCacheKey()` helper.
91
+ Session ids route requests and identify conversations; never credentials or
92
+ raw prompts.
93
+ - Anthropic-style `cache_control: { type: "ephemeral" }` markers are applied only
94
+ to the Prism `PromptCacheBreakpoint` locations the caller selects via
95
+ `ProviderRequestOptions.cache.breakpoints` (resolved with the shared
96
+ `applyCacheControl()` helper), and only on the last content block of each
97
+ selected message — not to every content block of every message. With no
98
+ breakpoints, no markers are emitted and the provider relies on implicit prefix
99
+ caching where available.
100
+ - Caching is enabled unless disabled (`cacheRetention: "none"` /
101
+ `cache.mode: "off"`) and the model opts in via `ModelConfig.cache.kind`
102
+ (`"cache_control"`) or the legacy `compat.openRouterCache: true` flag.
103
+ - `cacheRetention: "long"` (or `cache.retention: "long"`) emits
104
+ `cache_control: { type: "ephemeral", ttl: "1h" }` markers when the model allows
105
+ long retention (`ModelConfig.cache.longRetention !== false`); otherwise the
106
+ default 5-minute ephemeral window applies.
107
+ - Usage accounting is preserved: OpenRouter `prompt_tokens_details.cached_tokens`
108
+ maps to `Usage.cacheReadTokens` and `prompt_tokens_details.cache_write_tokens`
109
+ maps to `Usage.cacheWriteTokens`.
110
+
86
111
  ## Security and performance notes
87
112
 
88
113
  - No catalog fetch during setup; no automatic environment, file, keychain, or shell
89
114
  credential lookup.
90
115
  - API keys are resolved per request from caller-supplied values or resolvers and
91
116
  redacted from errors.
117
+ - Caller-supplied `ProviderRequest.options.headers` can add non-owned headers,
118
+ but OpenRouter-owned headers are applied last: `Authorization`,
119
+ `Content-Type`, `X-Session-Id`, `HTTP-Referer`, and `X-Title` cannot be
120
+ overridden by caller headers.
92
121
  - Attribution headers are sent only when `appUrl`/`appTitle` are supplied — no
93
122
  hidden app identity.
94
123
  - Live tests stay opt-in behind `PRISM_LIVE_PROVIDER_TESTS=1` plus fake-safe
@@ -88,12 +88,29 @@ await kernel.load([
88
88
  fallback).
89
89
  - Package contributes models via the extension `api` and an `api_key` auth method.
90
90
 
91
+ ### Cache behavior
92
+
93
+ - Z.AI GLM models use **implicit context caching**: the server caches prompt
94
+ prefixes automatically based on request content, with no explicit request-side
95
+ cache payload. Catalog models declare `cache: { kind: "implicit" }`.
96
+ - The provider sends no `cache_control`, `prompt_cache_key`, `prompt_cache_retention`,
97
+ or other explicit cache-control fields regardless of `ProviderRequestOptions.cache`
98
+ / `cacheKey` / `cacheRetention` settings — those options have no effect on the
99
+ Z.AI request body. Hosts relying on cache hits should keep their stable prompt
100
+ prefix byte-stable and stable inputs unchanged.
101
+ - Usage accounting is preserved: `prompt_tokens_details.cached_tokens` maps to
102
+ `Usage.cacheReadTokens` and `prompt_tokens_details.cache_write_tokens` maps to
103
+ `Usage.cacheWriteTokens` when the server reports them.
104
+
91
105
  ## Security and performance notes
92
106
 
93
107
  - No network calls during import, setup, build, or default tests.
94
108
  - No automatic environment, file, keychain, or shell credential lookup.
95
109
  - API keys are resolved per request from caller-supplied values or resolvers and
96
110
  redacted from errors.
111
+ - Caller-supplied `ProviderRequest.options.headers` can add non-owned headers,
112
+ but provider-owned headers (`content-type`, `authorization`) are applied last
113
+ and cannot be overridden by caller headers.
97
114
  - Live tests stay opt-in behind `PRISM_LIVE_PROVIDER_TESTS=1` plus fake-safe
98
115
  provider-specific env names; default tests are network-free.
99
116
 
@@ -7,14 +7,15 @@ The root `@arnilo/prism` export provides TypeScript contracts for host-owned age
7
7
  Current contract groups:
8
8
 
9
9
  - JSON/data: `JsonPrimitive`, `JsonValue`, `JsonObject`, `ErrorInfo`
10
- - Content/messages: `ContentBlock`, `TextContent`, `ImageContent`, `ThinkingContent`, `ToolCallContent`, `ToolResultContent`, `Message`
11
- - Providers/models/auth: `ModelConfig`, `ModelCapabilities`, `ModelLimits`, `ModelCost`, `Usage`, `CacheRetention`, `ProviderRequestOptions`, `ProviderRequest`, `ProviderEvent`, `AIProvider`, `ProviderPackage`, `ProviderPackageAPI`, `ProviderPackageDocs`, `AuthMethod`, `ApiKeyAuthMethod`, `OAuthAuthMethod`, `CustomAuthMethod`, `OAuthLoginCallbacks`, `OAuthCredentials`, `OAuthProvider`, `CredentialResolverSource`, `OAuthCredentialStore`, `ProviderRequestPolicy`, `ProviderRequestPolicyContext`, `ProviderRequestPolicyResult`, `SystemPromptContribution`, `SystemPromptMode`, `SystemPromptSource`, `SystemPromptConfig`
12
- - Agents/sessions: `AgentConfig`, `AgentDefinition`, `Agent`, `AgentSessionConfig`, `AgentSessionForkOptions`, `AgentSessionCloneOptions`, `AgentSession`, `RunOptions`, `AgentEvent`
10
+ - Content/messages: `ContentBlock`, `TextContent`, `ImageContent`, `ThinkingContent`, `ToolCallDeltaContent`, `ToolCallContent`, `ToolResultContent`, `Message`
11
+ - Providers/models/auth: `ModelConfig`, `ModelCapabilities`, `ModelLimits`, `ModelCost`, `ModelCacheCapabilities`, `PromptCacheKind`, `Usage`, `CacheRetention`, `PromptCacheMode`, `PromptCacheBreakpoint`, `PromptCacheHints`, `ProviderRequestOptions`, `ProviderRequest`, `ProviderEvent`, `AIProvider`, `ProviderPackage`, `ProviderPackageAPI`, `ProviderPackageDocs`, `AuthMethod`, `ApiKeyAuthMethod`, `OAuthAuthMethod`, `CustomAuthMethod`, `OAuthLoginCallbacks`, `OAuthCredentials`, `OAuthProvider`, `CredentialResolverSource`, `OAuthCredentialStore`, `ProviderRequestPolicy`, `ProviderRequestPolicyContext`, `ProviderRequestPolicyResult`, `SystemPromptContribution`, `SystemPromptMode`, `SystemPromptSource`, `SystemPromptConfig`
12
+ - Agents/sessions: `AgentConfig`, `AgentDefinition`, `Agent`, `AgentSessionConfig`, `AgentSessionForkOptions`, `AgentSessionCloneOptions`, `AgentSession`, `SubscribeOptions`, `SubscriberOverflowPolicy`, `RunOptions`, `AgentEvent`
13
13
  - Tools/commands: `ToolDefinition`, `ToolRegistry`, `ToolExecutionContext`, `ToolResult`, `CommandDefinition`, `CommandExecutionContext`, `CommandResult`
14
14
  - Input/prompt/context/skills: `InputBuilder`, `InputBuildContext`, `AgentInput`, `DefaultInputBuilder`, `DefaultInputBuildContext`, `InputAttachment`, `PromptInstruction`, `PromptBuilder`, `PromptBuildRequest`, `ContextBlock`, `ContextProvider`, `ContextResolutionContext`, `Skill`, `SkillRegistry`
15
15
  - Extensions/middleware: `ExtensionLifecycleEventName`, `ExtensionEvent`, `Extension`, `ExtensionAPI`, `MiddlewareHookName`, `Middleware`, `MiddlewareNext`, `MiddlewareRegistry`
16
16
  - Configuration/manifests: `ConfigProvider`, `ConfigLayer`, `ConfigLoadContext`, `PrismManifest`, `ManifestContributionDeclaration`, `ManifestResourceDeclaration`, `ManifestContributionKind`
17
- - Stores/resources/settings/credentials/compaction/retry: `SessionEntry`, `SessionStore`, `StoreFactory`, `Resource`, `ResourceLoader`, `ResourceLoadContext`, `SettingsProvider`, `CredentialRequest`, `Credential`, `CredentialResolver`, `CompactionStrategy`, `CompactionContext`, `CompactionResult`, `CompactionOptions`, `CompactionMiddlewarePayload`, `CompactionEntryData`, `DefaultCompactionStrategyOptions`, `RetryPolicy`, `RetryContext`, `RetryDecision`, `RetryOptions`, `RetryMiddlewarePayload`, `DefaultRetryPolicyOptions`
17
+ - Stores/resources/settings/credentials/compaction/retry/cache helpers: `SessionEntry`, `SessionStore`, `StoreFactory`, `Resource`, `ResourceLoader`, `ResourceLoadContext`, `SettingsProvider`, `CredentialRequest`, `Credential`, `CredentialResolver`, `CompactionStrategy`, `CompactionContext`, `CompactionResult`, `CompactionOptions`, `CompactionMiddlewarePayload`, `CompactionEntryData`, `DefaultCompactionStrategyOptions`, `RetryPolicy`, `RetryContext`, `RetryDecision`, `RetryOptions`, `RetryMiddlewarePayload`, `DefaultRetryPolicyOptions`, `CacheUsageReport`, `sanitizeCacheKey`, `mapCacheRetention`, `applyCacheControl`, `cacheHitRate`, `cacheSavings`, `cacheUsageReport`
18
+ - Production persistence (adapter-facing): `ProductionPersistenceStore`, `PersistencePage`, `PersistenceQuery`, `OwnershipScope`, `SessionRecord`, `SessionQuery`, `BranchRecord`, `BranchQuery`, `SessionEntryQuery`, `RunRecord`, `RunQuery`, `AgentEventRecord`, `AgentEventQuery`, `ToolCallRecord`, `ToolCallQuery`, `UsageRecord`, `UsageQuery`, `AgentDefinitionRecord`, `AgentDefinitionQuery`, `RetentionPolicy`, `RetentionPolicyQuery`, `MigrationRecord`, `MigrationQuery`
18
19
 
19
20
  ## When to use it
20
21
 
@@ -30,16 +31,41 @@ Public contracts are imported from the root package:
30
31
  import type {
31
32
  AgentConfig,
32
33
  AgentDefinition,
34
+ AgentDefinitionRecord,
35
+ AgentDefinitionQuery,
36
+ AgentEventQuery,
37
+ AgentEventRecord,
38
+ AgentLoopOptions,
39
+ AgentLoopStrategy,
33
40
  AIProvider,
41
+ ArtifactContext,
42
+ ArtifactParseResult,
43
+ ArtifactParser,
44
+ ArtifactRepairer,
45
+ ArtifactValidation,
46
+ ArtifactValidator,
34
47
  AuthMethod,
48
+ BranchQuery,
49
+ BranchRecord,
35
50
  CommandDefinition,
51
+ CacheUsageReport,
36
52
  CompactionStrategy,
37
53
  ConfigLayer,
38
54
  ConfigProvider,
39
55
  ContextProvider,
40
56
  CredentialResolver,
57
+ MigrationQuery,
58
+ MigrationRecord,
41
59
  OAuthProvider,
60
+ OwnershipScope,
61
+ PersistencePage,
62
+ PersistenceQuery,
63
+ ProductionPersistenceStore,
42
64
  ProviderRequestOptions,
65
+ ModelCacheCapabilities,
66
+ PromptCacheBreakpoint,
67
+ PromptCacheHints,
68
+ PromptCacheKind,
43
69
  DefaultInputBuildContext,
44
70
  Extension,
45
71
  InputBuilder,
@@ -53,29 +79,48 @@ import type {
53
79
  PromptTemplateOptions,
54
80
  ProviderPackage,
55
81
  ProviderRequestPolicy,
82
+ ProviderTurnResult,
56
83
  ResourceLoader,
84
+ RetentionPolicy,
85
+ RetentionPolicyQuery,
86
+ RunQuery,
87
+ RunRecord,
88
+ SessionEntryQuery,
89
+ SessionQuery,
90
+ SessionRecord,
91
+ SubscribeOptions,
92
+ SubscriberOverflowPolicy,
57
93
  SettingsProvider,
58
94
  Skill,
59
95
  StoreFactory,
60
96
  SystemPromptContribution,
61
97
  SystemPromptConfig,
98
+ ToolCallQuery,
99
+ ToolCallRecord,
62
100
  ToolDefinition,
101
+ UsageQuery,
102
+ UsageRecord,
63
103
  } from "@arnilo/prism";
104
+
105
+ import { applyCacheControl, cacheHitRate, cacheSavings, cacheUsageReport, mapCacheRetention, sanitizeCacheKey } from "@arnilo/prism";
64
106
  ```
65
107
 
66
108
  Important request shapes:
67
109
 
68
110
  | Contract | Purpose |
69
111
  | --- | --- |
70
- | `ModelConfig` | Provider/model id plus optional display name, capabilities, limits, cost/cache pricing, opaque compat JSON, parameters, and metadata. |
112
+ | `ModelConfig` | Provider/model id plus optional display name, capabilities, limits, cost/cache pricing, `cache` capability metadata, opaque compat JSON, parameters, and metadata. |
113
+ | `ModelCacheCapabilities` / `PromptCacheKind` | Generic model cache support metadata (`implicit`, `openai_key`, `cache_control`, `provider_specific`, `none`). See [Model registry](model-registry.md). |
114
+ | `PromptCacheHints` / `PromptCacheBreakpoint` | Structured provider cache intent and reusable prompt anchors. See [Provider caching](provider-caching.md). |
71
115
  | `ProviderPackage` | Inert provider package definition with docs metadata and explicit `setup(api)` registration. |
72
116
  | `ProviderRequest` | Normalized provider input: `model`, `messages`, optional `tools`, `context`, generic `options`, `metadata`, and `signal`. |
73
- | `ProviderRequestOptions` | Generic provider adapter hints: session/cache identifiers, cache retention, headers, timeout/retry hints, compat, and opaque `extra`. |
117
+ | `ProviderRequestOptions` | Generic provider adapter hints: session id, legacy `cacheKey`/`cacheRetention`, structured `cache?: PromptCacheHints`, headers, compat, and opaque `extra`; `timeoutMs`, `maxRetries`, and `maxRetryDelayMs` are deprecated inert hints in first-party providers. |
74
118
  | `ProviderRequestPolicy` | Ordered pre-provider hook that can patch the request and return exact secrets for provider-error redaction. |
75
119
  | `ToolRegistry` | Host active tool registry shape: `register()`, `get()`, `resolve()`, and `list()`. |
76
120
  | `ToolExecutionContext` | Host tool execution context: session/run ids, tool call id, optional abort signal, metadata, and progress callback. |
77
121
  | `ContextResolutionContext` | Context provider input: messages plus optional session/run ids, metadata, and signal. |
78
- | `DefaultInputBuildContext` | Optional default input assembly context: instructions, history, summaries, attachments, explicit resources, tool results, middleware, ids, metadata, and signal. |
122
+ | `InputAssemblyLayout` | Default input layout selector: `"legacy"` (default) or opt-in `"cache_aware"`. |
123
+ | `DefaultInputBuildContext` | Optional default input assembly context: input layout, instructions, history, summaries, attachments, explicit resources, tool results, middleware, ids, metadata, and signal. |
79
124
  | `ResolveContextOptions` | Ordered context resolution input: selected providers, messages, ids, metadata, signal, and optional middleware. |
80
125
  | `AssembleProviderInputOptions` | Provider input assembly input: model, input, optional builders, selected context providers/skills, active tools, metadata, and signal. |
81
126
  | `PromptTemplateOptions` | Missing-variable behavior for tiny `renderPromptTemplate()` substitutions. |
@@ -83,10 +128,33 @@ Important request shapes:
83
128
  | `CredentialRequest` | Credential lookup request: credential `name`, optional provider id, and metadata. |
84
129
  | `OAuthProvider` | Host/package OAuth callbacks for login, optional refresh, and conversion to a `Credential`. |
85
130
  | `AgentSessionConfig` | Session creation input: optional id, agent, store, leaf id, and metadata. |
86
- | `RunOptions` | Per-run overrides: optional abort signal, model, max tool rounds, provider options/request policies, system prompt layers, compaction, retry, and metadata. |
131
+ | `RunOptions` | Per-run overrides: optional abort signal, model, input layout, max tool rounds, provider options/request policies, system prompt layers, compaction, retry, metadata, skill selection, validate, redactor, and loop. |
132
+ | `SubscribeOptions` / `SubscriberOverflowPolicy` | Live `AgentEvent` subscriber queue limit and overflow policy: `maxQueuedEvents`, `overflow: "close" \| "drop_oldest" \| "drop_newest"`. |
133
+ | `AgentConfig.loop` / `RunOptions.loop` | Replaceable per-run control loop: `singleShotLoop` default, `generate-validate-revise` options, or a custom `AgentLoopStrategy`. `RunOptions.loop` wins. See [Agent loops](agent-loops.md). |
134
+ | `AgentLoopStrategy` | `{ name; run(ctx: LoopContext): Promise<Usage \| undefined> }` — orchestrates shared runtime primitives via `LoopContext`. |
135
+ | `LoopContext` | Loop-facing surface: run ids, signal, live `history`, `input`/`inputMessages`/`maxToolRounds`, and bound `assemble`/`generate`/`dispatchToolCall`/`appendMessage`/`emit` primitives. |
136
+ | `ProviderTurnResult` | The result of `LoopContext.generate()`: `content`, `calls`, optional `messageId`, `started`, `usage`. |
137
+ | `ArtifactValidation` | `{ ok; errors?: readonly { path?; message }[]; metadata? }` — host validator result. |
138
+ | `ArtifactContext` | `{ sessionId, runId, turn, signal, metadata }` — passed to artifact callbacks. |
139
+ | `ArtifactParser<T>` / `ArtifactValidator<T>` / `ArtifactRepairer<T>` | Host-supplied callbacks for `generate-validate-revise`; `T` is host-defined, Prism never instantiates it. |
87
140
  | `SystemPromptContribution` | Explicit caller-selected prompt layer with source, mode, text, and metadata. |
88
141
  | `ConfigLayer` | Named JSON config layer consumed by `mergeConfigLayers()`. |
89
142
  | `PrismManifest` | Data-only package manifest with config defaults, contribution declarations, and resource declarations. |
143
+ | `ProductionPersistenceStore` | Adapter-facing interface for durable, paginated, multi-tenant storage of sessions, branches, entries, runs, events, tool calls, usage, agent definitions, retention policies, and migrations. No SQL/ORM/host file storage/network dependency. |
144
+ | `PersistencePage<T>` | Cursor-paginated result page: `items`, optional `nextCursor`, optional `total`. |
145
+ | `PersistenceQuery` | Common pagination controls: `cursor?`, `limit?`, `order?: "asc" \| "desc"`. |
146
+ | `OwnershipScope` | Multi-tenant scope: `tenantId?`, `accountId?`, `userId?`. Included in records and queries. |
147
+ | `SessionRecord` / `SessionQuery` | Stored session and query filters (parent, agent definition, retention policy, timestamps, ownership). |
148
+ | `BranchRecord` / `BranchQuery` | Branch handle/leaf pointer and query filters (session, name, parent branch, leaf presence). |
149
+ | `SessionEntryQuery` | Paginated entry filters: `sessionId`, `runId`, `parentId`, `leafId`, `kind`, timestamp range, ownership. |
150
+ | `RunRecord` / `RunQuery` | Stored run and filters: session, branch, status, timestamps, ownership. |
151
+ | `AgentEventRecord` / `AgentEventQuery` | Event ledger row with `redacted` flag and filters by type, session, run, entry, timestamp, ownership. |
152
+ | `ToolCallRecord` / `ToolCallQuery` | Tool-call row with `redacted` flag and filters by name, status, session, run, entry, timestamps, ownership. |
153
+ | `UsageRecord` / `UsageQuery` | Usage row and filters: session, run, entry, recorded-at range, ownership. |
154
+ | `CacheUsageReport` | Numeric cache diagnostics from normalized `Usage`: read/write tokens, hit rate, estimated savings, and optional currency. |
155
+ | `AgentDefinitionRecord` / `AgentDefinitionQuery` | Versioned agent-definition snapshot and filters. Does not store credentials or provider instances. |
156
+ | `RetentionPolicy` / `RetentionPolicyQuery` | Retention policy and filters: age, entry count, byte limits, archive store, applied kinds. |
157
+ | `MigrationRecord` / `MigrationQuery` | Applied migration record and filters. |
90
158
 
91
159
  ## Outputs / response / events
92
160
 
@@ -95,7 +163,7 @@ Important output/event shapes:
95
163
  | Contract | Output |
96
164
  | --- | --- |
97
165
  | `ProviderEvent` | Provider stream events: message start, content delta, tool-call delta, final tool call, usage, done, or error. |
98
- | `AgentEvent` | Session/runtime events: agent/turn/message/tool/queue/compaction/retry/error events, including tool started/progress/finished/error/blocked. |
166
+ | `AgentEvent` | Session/runtime events: agent/turn/message/tool/queue/subscriber-overflow/compaction/retry/error events, including tool started/progress/finished/error/blocked. |
99
167
  | `ToolResult` | Host tool output with optional content, value, error, and metadata. |
100
168
  | `ContextBlock` | Context text or content blocks with optional title, priority, and metadata. |
101
169
  | `SessionEntry` | Branch-aware store entry for messages, events, summaries, metadata, model changes, labels, custom data, or compaction markers. |
@@ -134,6 +202,7 @@ import type {
134
202
  AIProvider,
135
203
  AssembleProviderInputOptions,
136
204
  CommandDefinition,
205
+ CacheUsageReport,
137
206
  CompactionStrategy,
138
207
  ConfigLayer,
139
208
  ConfigProvider,
@@ -338,9 +407,10 @@ void credentials;
338
407
  - Contracts are host-owned and package-friendly. External packages can implement `AIProvider`, `ToolDefinition`, `CommandDefinition`, `AgentDefinition`, `InputBuilder`, `PromptBuilder`, `Middleware`, `ContextProvider`, `Skill`, `Extension`, config providers, data-only manifests, compaction strategies, store factories, resource loaders, settings providers, and credential resolvers.
339
408
  - `ExtensionAPI` is implemented by the extension kernel. It exposes explicit registries, ordered middleware registration, ordered event subscription/emission, and registration methods for Phase 2 contribution categories.
340
409
  - `AgentConfig.provider` can hold a direct provider instance for simple host wiring. Hosts that need config-driven selection should use `ModelConfig.provider` with explicit `createProviderRegistry()` / `createModelRegistry()` objects; Prism does not create a hidden global provider registry.
341
- - `SettingsProvider` and `CredentialResolver` are explicit dependencies. Prism must not hide global settings or credentials behind these contracts, and `CredentialResolver` should be passed only to the edge that needs a credential.
410
+ - `SettingsProvider` and `CredentialResolver` are explicit dependencies. Prism must not hide global settings or credentials behind these contracts, and `CredentialResolver` should be passed only to the edge that needs a credential. `AgentConfig.settings` and `AgentConfig.credentials` are host-owned metadata; the session runtime does not call `settings.get()` or `credentials.resolve()`.
411
+ - `AgentConfig.extensions` is host-owned metadata; the session runtime does not load extensions or call `Extension.setup()`. Use `createExtensionKernel().load(...)` before creating an agent, then pass selected contributions into `AgentConfig`.
342
412
  - `PrismManifest` is data-only. It can describe contribution modules/resources and config defaults, but parsing it does not import modules, execute package code, or mutate registries.
343
- - Resource helper functions decode resources from a caller-provided `ResourceLoader`; Prism does not include filesystem, network, package, or URI router loaders.
413
+ - Resource helper functions decode resources from a caller-provided `ResourceLoader`; Prism does not include host file storage, network, package, or URI router loaders.
344
414
  - `createDefaultInputBuilder()` is a small default implementation of `InputBuilder`. It is replaceable and only loads explicit URI resources through a caller-provided `ResourceLoader`.
345
415
  - `resolveContextProviders()`, `createDefaultPromptBuilder()`, `assembleProviderInput()`, `createSkillRegistry()`, `resolveActiveSkills()`, and `renderPromptTemplate()` are replaceable Phase 5 helpers. They do not execute tools, evaluate template code, or grant tool permissions.
346
416
  - `createAgent()` and `createAgentSession()` implement the session runtime. They use explicit providers only; no hidden provider registry is created. Store-backed sessions use explicit `SessionStore` values and branch methods on `AgentSession`. `AgentSession.compact()` and `AgentConfig`/`RunOptions.compaction` provide manual and opt-in auto-compaction. `AgentConfig`/`RunOptions.retry` provide bounded provider-turn retry before observable output.
@@ -365,7 +435,12 @@ void credentials;
365
435
  - [Contribution registries](contribution-registries.md): explicit registries for contribution contracts.
366
436
  - [Tools](tools.md): active tool registry and exact allow/deny filtering built on `ToolDefinition`.
367
437
  - [Agent/session runtime](agent-session-runtime.md): `createAgent()` / `createAgentSession()` runtime, `AgentSession.compact()`, and auto-compaction config built on these contracts.
368
- - [Session stores and branching](session-stores-and-branching.md): branch-aware `SessionEntry` helpers and context rebuild.
438
+ - [Agent loops](agent-loops.md): `singleShotLoop` default, `generateValidateReviseLoop`, `resolveLoop`, and the `Artifact*`/`AgentLoop*`/`LoopContext` contracts.
439
+ - [Agent events](agent-events.md): the `AgentEvent` union including `artifact_*` variants and event ordering.
440
+ - [Structured output](structured-output.md): the `ArtifactParser<T>`/`ArtifactValidator<T>`/`ArtifactRepairer<T>` seam — the only typed-output path from a loop.
441
+ - [Session stores](session-stores.md): `SessionStore` contract, branch-aware `SessionEntry` helpers, context rebuild, and store responsibilities.
442
+ - [Database persistence](database-persistence.md): production persistence contracts, paginated query shapes, reference schema, indexes, retention, migrations, and NoSQL mapping.
443
+ - [Session stores and branching](session-stores-and-branching.md): detailed branch semantics and helper reference (compatibility page).
369
444
  - [Compaction and retry policies](compaction-and-retry.md): default compaction strategy, default retry policy, runtime compaction/retry options, middleware payloads, and compaction entry data.
370
445
  - [Provider layer](provider-layer.md): runtime registries, provider event helpers, and mock provider built on these contracts.
371
446
  - [Provider conformance](provider-conformance.md): testing subpath for network-free provider adapter checks.
@@ -2,23 +2,24 @@
2
2
 
3
3
  ## What it does
4
4
 
5
- Prism is published as one core package plus seven first-party workspace packages and three umbrella convenience packages. This page describes how they are packed, what each tarball contains, how to install them, the required `@arnilo/prism` peer dependency, the release workflow, and the offline test budget.
5
+ Prism is published as one core package plus nine first-party workspace packages and three umbrella convenience packages. This page describes how they are packed, what each tarball contains, how to install them, the required `@arnilo/prism` peer dependency, the release workflow, and the offline test budget.
6
6
 
7
7
  Core package:
8
8
 
9
9
  - `@arnilo/prism` — the runtime, contracts, registries, streaming events, CLI, and the `/docs` hub. `files`: `dist` (with `!dist/__tests__` and `!dist/**/*.map` negations), `docs`, `CHANGELOG.md`. `bin`: `prism` -> `./dist/cli.js`. `sideEffects`: `["dist/cli.js"]`.
10
10
 
11
- First-party workspace packages (each `peerDependencies: { "@arnilo/prism": "0.0.1" }`, non-optional; `sideEffects: false`):
11
+ First-party workspace packages (each `peerDependencies: { "@arnilo/prism": "0.0.3" }`, non-optional; `sideEffects: false`):
12
12
 
13
- - `@arnilo/prism-provider-openai`, `@arnilo/prism-provider-openrouter`, `@arnilo/prism-provider-kimi`, `@arnilo/prism-provider-zai`, `@arnilo/prism-provider-opencode-go` — provider adapters.
13
+ - `@arnilo/prism-provider-openai`, `@arnilo/prism-provider-openrouter`, `@arnilo/prism-provider-kimi`, `@arnilo/prism-provider-zai`, `@arnilo/prism-provider-opencode-go`, `@arnilo/prism-provider-neuralwatt` — provider adapters.
14
14
  - `@arnilo/prism-compaction-llm` — optional LLM-backed compaction strategy.
15
15
  - `@arnilo/prism-compaction-observational-memory` — optional source-backed observational memory.
16
+ - `@arnilo/prism-coding-agent` — optional host shell/filesystem coding tools (`shell`, `read`, `write`, `edit`). **Not included in `@arnilo/prism-all`** because these tools perform real host operations and must be opted into explicitly.
16
17
 
17
18
  Umbrella packages (pure manifests, no code, no `dist`; ship only `README.md`; use hard `dependencies` to transitively install their family):
18
19
 
19
- - `@arnilo/prism-providers` — depends on all 5 `@arnilo/prism-provider-*` packages.
20
+ - `@arnilo/prism-providers` — depends on all 6 `@arnilo/prism-provider-*` packages.
20
21
  - `@arnilo/prism-compaction` — depends on both `@arnilo/prism-compaction-*` packages.
21
- - `@arnilo/prism-all` — depends on `@arnilo/prism` + `@arnilo/prism-providers` + `@arnilo/prism-compaction` (the full kit in one install).
22
+ - `@arnilo/prism-all` — depends on `@arnilo/prism` + `@arnilo/prism-providers` + `@arnilo/prism-compaction` (the full runtime/provider/compaction kit in one install). Does **not** include `@arnilo/prism-coding-agent`; install that separately.
22
23
 
23
24
  Each code package's `files` array is `["dist", "!dist/__tests__", "!dist/**/*.map", "README.md", "CHANGELOG.md"]`; `README.md`, `LICENSE`, and `CHANGELOG.md` ship in every code-package tarball, the core tarball also ships the `docs/` directory, and umbrella tarballs ship only `README.md` + `package.json`.
24
25
 
@@ -35,24 +36,34 @@ Consumers install the core package for the runtime and add first-party packages
35
36
  | Install core only | `npm install @arnilo/prism` |
36
37
  | Install core + all providers | `npm install @arnilo/prism @arnilo/prism-providers` |
37
38
  | Install core + compaction | `npm install @arnilo/prism @arnilo/prism-compaction` |
39
+ | Install core + coding tools (opt-in) | `npm install @arnilo/prism @arnilo/prism-coding-agent` |
38
40
  | Install everything (core + providers + compaction) | `npm install @arnilo/prism-all` |
39
41
  | Install core + a single provider | `npm install @arnilo/prism @arnilo/prism-provider-openai` |
40
42
  | Build everything (core + workspaces) | `npm run build` |
41
43
  | Run the default (network-free) test suite | `npm test` |
42
44
  | Dry-run pack core + every package | `npm run pack:dry-run` |
43
45
  | Local mirror of the release verify gate | `npm run release:dry-run` |
46
+ | Full SDK readiness gate (typecheck + offline tests + pack) | `npm run sdk:ready` |
44
47
 
45
48
  Public core import specifiers (from the root `exports` map):
46
49
 
47
50
  | Specifier | Resolves to |
48
51
  | --- | --- |
49
- | `@arnilo/prism` | `dist/index.js` / `dist/index.d.ts` |
52
+ | `@arnilo/prism` | `dist/index.{js,d.ts}` |
50
53
  | `@arnilo/prism/providers/openai-compatible` | `dist/providers/openai-compatible.{js,d.ts}` |
51
54
  | `@arnilo/prism/testing/provider-conformance` | `dist/testing/provider-conformance.{js,d.ts}` |
55
+ | `@arnilo/prism/testing/session-store-conformance` | `dist/testing/session-store-conformance.{js,d.ts}` |
56
+ | `@arnilo/prism/testing/compaction-conformance` | `dist/testing/compaction-conformance.{js,d.ts}` |
57
+ | `@arnilo/prism/testing/tool-conformance` | `dist/testing/tool-conformance.{js,d.ts}` |
58
+ | `@arnilo/prism/testing/extension-conformance` | `dist/testing/extension-conformance.{js,d.ts}` |
52
59
  | `@arnilo/prism/node/config` | `dist/node/config.{js,d.ts}` |
53
60
  | `@arnilo/prism/node/settings` | `dist/node/settings.{js,d.ts}` |
54
61
  | `@arnilo/prism/node/trust` | `dist/node/trust.{js,d.ts}` |
55
62
  | `@arnilo/prism/node/session-store-jsonl` | `dist/node/session-store-jsonl.{js,d.ts}` |
63
+ | `@arnilo/prism/node/contribution-discovery` | `dist/node/contribution-discovery.{js,d.ts}` |
64
+ | `@arnilo/prism/node/instruction-injectors` | `dist/node/instruction-injectors.{js,d.ts}` |
65
+ | `@arnilo/prism/node/system-prompts` | `dist/node/system-project-prompts.{js,d.ts}` |
66
+ | `@arnilo/prism/node/agent-definitions` | `dist/node/agent-definitions.{js,d.ts}` |
56
67
 
57
68
  ## Outputs / response / events
58
69
 
@@ -62,7 +73,7 @@ A packed tarball contains only public compiled output and release files:
62
73
  - `README.md`, `LICENSE`, `CHANGELOG.md` in every package.
63
74
  - The core tarball additionally ships the full `docs/` directory (the docs hub).
64
75
  - `dist/cli.js` and the `bin` link in core.
65
- - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.1.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.1.tgz` / `arnilo-prism-compaction-<name>-0.0.1.tgz`; umbrella packages produce `arnilo-prism-providers-0.0.1.tgz` / `arnilo-prism-compaction-0.0.1.tgz` / `arnilo-prism-all-0.0.1.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).
76
+ - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.3.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.3.tgz` / `arnilo-prism-compaction-<name>-0.0.3.tgz` / `arnilo-prism-coding-agent-0.0.3.tgz`; umbrella packages produce `arnilo-prism-providers-0.0.3.tgz` / `arnilo-prism-compaction-0.0.3.tgz` / `arnilo-prism-all-0.0.3.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).
66
77
 
67
78
  Excluded from every tarball by `files` negation:
68
79
 
@@ -79,9 +90,9 @@ Excluded from every tarball by `files` negation:
79
90
  "name": "host-app",
80
91
  "type": "module",
81
92
  "dependencies": {
82
- "@arnilo/prism": "0.0.1",
83
- "@arnilo/prism-provider-openai": "0.0.1",
84
- "@arnilo/prism-compaction-observational-memory": "0.0.1"
93
+ "@arnilo/prism": "0.0.3",
94
+ "@arnilo/prism-provider-openai": "0.0.3",
95
+ "@arnilo/prism-compaction-observational-memory": "0.0.3"
85
96
  }
86
97
  }
87
98
  ```
@@ -91,48 +102,89 @@ Installing the provider/compaction packages without `@arnilo/prism` present prod
91
102
  ```text
92
103
  npm error code ERESOLVE
93
104
  npm error Could not resolve dependency:
94
- npm error peer @arnilo/prism@"0.0.1" from @arnilo/prism-provider-openai@0.0.1
105
+ npm error peer @arnilo/prism@"0.0.3" from @arnilo/prism-provider-openai@0.0.3
95
106
  ```
96
107
 
97
108
  ## Implementation example
98
109
 
99
110
  ```ts
100
- // Core runtime
101
- import { createAgent, createAgentSession } from "@arnilo/prism";
102
- // OpenAI-compatible provider subpath
111
+ import { createAgent, createAgentSession, type ModelConfig } from "@arnilo/prism";
103
112
  import { createOpenAICompatibleProvider } from "@arnilo/prism/providers/openai-compatible";
104
- // Node filesystem config loader
105
113
  import { loadConfigFile } from "@arnilo/prism/node/config";
106
114
 
107
- const agent = createAgent({ provider: createOpenAICompatibleProvider({ /* ... */ }) });
108
- const session = createAgentSession(agent, { /* session store, etc. */ });
115
+ const config = await loadConfigFile("./prism.config.json");
116
+ const model: ModelConfig = { provider: "openai-compatible", model: "gpt-4.1-mini" };
117
+ const provider = createOpenAICompatibleProvider({
118
+ id: "openai-compatible",
119
+ baseUrl: String(config.providers?.openai?.baseUrl ?? "https://api.openai.com/v1"),
120
+ apiKey: () => process.env.OPENAI_API_KEY,
121
+ });
122
+ const agent = createAgent({ model, provider });
123
+ const session = createAgentSession({ agent });
109
124
  ```
110
125
 
111
- Local release dry-run mirrors the GitHub Actions `verify` job (build + tests + packaging/install-smoke guards + pack dry-run):
126
+ Local release dry-run mirrors the GitHub Actions `verify` job and delegates to the SDK readiness gate:
112
127
 
113
128
  ```bash
114
129
  npm run release:dry-run
115
130
  ```
116
131
 
132
+ For SDK readiness, run the same one-command gate directly. It composes existing scripts only: examples/workspace typecheck, build, network-free core tests (docs/export/package/install smoke included), workspace tests, and pack dry-run.
133
+
134
+ ```bash
135
+ npm run sdk:ready
136
+ ```
137
+
138
+ Optional live smoke tests stay separate from SDK readiness because they require credentials and network access:
139
+
140
+ ```bash
141
+ PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
142
+ ```
143
+
117
144
  ## Extension and configuration notes
118
145
 
119
- - **Required `@arnilo/prism` peer.** Every first-party package declares `peerDependencies: { "@arnilo/prism": "0.0.1" }` with no `peerDependenciesMeta` (non-optional). The range stays pinned to `0.0.1` for the 0.x series and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
120
- - **Public access.** All 11 manifests (8 code packages + 3 umbrellas) declare `"publishConfig": { "access": "public" }` so a manual `npm publish` of a scoped `@arnilo/prism-*` package defaults to public rather than `restricted` (paid). The `release.yml` flags (`npm publish --access public` + `npm publish --workspaces --access public`) are belt-and-suspenders backups.
146
+ - **Required `@arnilo/prism` peer.** Every first-party package declares `peerDependencies: { "@arnilo/prism": "0.0.3" }` with no `peerDependenciesMeta` (non-optional). The range stays pinned to `0.0.3` for the 0.x series and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
147
+ - **Public access.** All 13 manifests (10 code packages + 3 umbrellas) declare `"publishConfig": { "access": "public" }` so a manual `npm publish` of a scoped `@arnilo/prism-*` package defaults to public rather than `restricted` (paid). The `release.yml` flags (`npm publish --access public` + `npm publish --workspaces --access public`) are belt-and-suspenders backups.
121
148
  - **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).
122
- - **Release workflow.** `.github/workflows/release.yml` has two jobs. `verify` runs on push (main/master, `v*` tags) and pull requests: `npm ci`, `npm test` (builds core + workspaces first, then runs the packaging and install-smoke guards), and `npm run pack:dry-run`. `publish` runs only on `refs/tags/v*` after `verify` succeeds: `npm run build`, then `npm publish --access public` for core (first, because packages require the `@arnilo/prism` peer on the registry) and `npm publish --workspaces --access public`. With no `NPM_TOKEN` secret it runs `--dry-run` instead of a real publish. `permissions.id-token: write` is set so `--provenance` can be added later without re-architecting permissions.
149
+ - **Release workflow.** `.github/workflows/release.yml` has three jobs. `verify` runs the full SDK readiness gate on Node 24: `npm ci`, then `npm run sdk:ready` (`npm run typecheck`, network-free `npm test`, and `npm run pack:dry-run`). `node20-compat` runs on Node 20: `npm ci`, `npm run build`, then imports every public root `exports` default target from `dist/`. This proves the published package basics under the declared `engines.node >=20` without running docs examples, which require Node >=22.6 native TypeScript stripping. `publish` runs only on `refs/tags/v*` after both `verify` and `node20-compat` succeed: `npm run build`, then `npm publish --access public` for core (first, because packages require the `@arnilo/prism` peer on the registry) and `npm publish --workspaces --access public`. With no `NPM_TOKEN` secret it runs `--dry-run` instead of a real publish. `permissions.id-token: write` is set so `--provenance` can be added later without re-architecting permissions. Local `npm run release:dry-run` delegates to the same `npm run sdk:ready` gate.
123
150
  - **Adding a package.** New workspace packages are picked up automatically by `npm run build --workspaces`, `npm test --workspaces`, `npm run pack:dry-run`, the packaging guard (`src/__tests__/packaging.test.ts`), and the install-smoke test (`src/__tests__/install-smoke.test.ts`) via the workspace glob; add the package to both tests' config arrays for explicit per-package assertions.
124
151
 
125
152
  ## Security and performance notes
126
153
 
127
154
  - **No secrets or fixtures in tarballs.** Tests, fixtures, `src/`, `plans/`, `.agents/`, `roadmap.md`, and `tsconfig` files are excluded. The `docs avoid real-looking secret examples` docs check and the packaging guard's deny list prevent secret-bearing fixtures from shipping.
128
- - **Live tests stay opt-in.** The default `npm test` is network-free by construction and never sets these vars. Three opt-in gate vars exist, each gating a different set of placeholder live smoke tests; none is set by default, in CI, or during release verification. Every gated live test is currently an empty placeholder awaiting provider-specific/worker checks in a later phase.
129
- - `PRISM_LIVE_PROVIDER_TESTS=1` — gates the five provider packages' `src/__tests__/live.test.ts` (`@arnilo/prism-provider-openai`, `provider-opencode-go`, `provider-openrouter`, `provider-zai`, `provider-kimi`).
130
- - `PRISM_LIVE_COMPACTION_TESTS=1` — gates `@arnilo/prism-compaction-llm`'s live summary-provider smoke test.
131
- - `PRISM_LIVE_OBSERVATIONAL_MEMORY_TESTS=1` — gates `@arnilo/prism-compaction-observational-memory`'s live worker/provider checks.
132
- - These guards use fake-safe names and carry no real credentials; the gated bodies intentionally do not read `OPENAI_API_KEY` or any provider key — they are placeholders. Itemize any provider-specific key env here only when a future phase adds a real live check that reads it.
155
+ - **Live tests stay opt-in.** The default `npm test` is network-free by construction and never sets these vars. Three opt-in gate vars exist, each gating a different set of live smoke tests; none is set by default, in CI, or during release verification. Provider live tests are real smoke tests (text generation, tool-call loop, abort, no-secret-leak) that also require a provider-specific API key; compaction live tests remain empty placeholders awaiting provider-specific checks.
156
+ - `PRISM_LIVE_PROVIDER_TESTS=1` — gates the six provider packages' `src/__tests__/live.test.ts` (`@arnilo/prism-provider-openai`, `provider-opencode-go`, `provider-openrouter`, `provider-zai`, `provider-kimi`, `provider-neuralwatt`). Each provider live test also requires its own API key env var and skips safely when it is missing:
157
+ - `OPENAI_API_KEY` for `@arnilo/prism-provider-openai`
158
+ - `OPENROUTER_API_KEY` for `@arnilo/prism-provider-openrouter`
159
+ - `KIMI_API_KEY` for `@arnilo/prism-provider-kimi`
160
+ - `ZAI_API_KEY` for `@arnilo/prism-provider-zai`
161
+ - `NEURALWATT_API_KEY` for `@arnilo/prism-provider-neuralwatt`
162
+ - `OPENCODE_API_KEY` for `@arnilo/prism-provider-opencode-go`
163
+ - `PRISM_LIVE_COMPACTION_TESTS=1` — gates `@arnilo/prism-compaction-llm`'s live summary-provider smoke test (placeholder).
164
+ - `PRISM_LIVE_OBSERVATIONAL_MEMORY_TESTS=1` — gates `@arnilo/prism-compaction-observational-memory`'s live worker/provider checks (placeholder).
165
+ - 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.
133
166
  - Enforced by `network-free-guard.test.ts` (default suite stays network-free) and by source-scanning meta-tests that assert each `live.test.ts` keeps its `skip:` guard.
134
167
  - **Install smoke is offline.** The install-smoke test packs core + every package into a temp dir and installs the tarballs with `--offline --no-audit --no-fund` into a fresh temp project; zero registry fetches happen because Prism has no runtime dependencies.
135
- - **Offline test budget.** The default `npm test` (no `PRISM_LIVE_PROVIDER_TESTS`) is pinned at **< 30s on Node 20** with a measured baseline of ~22s (build ~12.5s + tests ~9.5s, tests parallelized). The `npm test` CI step has `timeout-minutes: 3` as a hang backstop. If a future change pushes the CI median over 30s, raise it here and in `roadmap.md` Phase 17 with rationale rather than silently regressing.
168
+ - **Offline test budget.** The default `npm test` (no `PRISM_LIVE_PROVIDER_TESTS`) is pinned at **< 60s on Node 20** with a measured local baseline of ~45s (build ~18s + network-free tests/workspace tests/packaging smoke ~27s). The full CI `sdk:ready` gate runs on Node 24 because docs tests execute `examples/*.ts` via native TypeScript stripping. `npm run sdk:ready` also runs typecheck and pack dry-run, so it is allowed to exceed the `npm test` budget while remaining network-free. The CI `sdk:ready` step has `timeout-minutes: 5` as a hang backstop; the separate Node 20 compatibility step has `timeout-minutes: 3`. The budget was raised from 30s after the default suite grew to include every first-party package, offline install smoke, packaging guards, docs examples, and workspace tests; optimize before raising it again.
169
+
170
+ ## Release checklist
171
+
172
+ Every release gate maps to an exact enforcement test or command, so the checklist is executable rather than manual. Run `npm run sdk:ready` for the full local SDK readiness gate: `npm run typecheck`, network-free `npm test`, and `npm run pack:dry-run`. `npm run release:dry-run` is an alias for the same gate. The GitHub Actions `verify` job runs `npm ci` and `npm run sdk:ready` on Node 24; `node20-compat` runs `npm ci`, `npm run build`, and public export imports on Node 20.
173
+
174
+ | Gate | Enforcement |
175
+ | --- | --- |
176
+ | Docs coverage for persistence/runtime/migration surfaces | `docs.test.ts` enrolls every API page in `apiPages` (heading + index-link + bare-specifier + secret-scan checks); dedicated section assertions pin `database-persistence.md`, `runs-and-usage.md`, `session-stores-and-branching.md`, `migration.md`, `agent-definitions.md`, `performance.md`, and the Phase 41 `external_app_example_*` / `phase41_external_app_surfaces_*` gates. |
177
+ | Package exports/subpaths resolve to built output | `public-export-contract.test.ts` asserts every `exports`/`main`/`types`/`bin` target resolves to a built file under `dist/` with a sibling `.d.ts`, and no target escapes `dist/` (no `src/` or `examples/` leak). CI `node20-compat` also imports every public root `exports` default target on Node 20. |
178
+ | Public-API drift | `public-export-contract.test.ts` `phase39_public_protocol_exports_and_types_do_not_drift` pins the runtime protocol (`providerToolCallDelta`, `ToolCallDeltaContent`), the `/testing/provider-conformance` subpath shape, and the observational-memory runtime `.d.ts` surface. |
179
+ | Root SDK export surface freeze | `public-export-contract.test.ts` `root export surface is frozen` snapshots every value and type export of `src/index.ts` (107 value + 69 type) so any add/remove is a deliberate test update; `every frozen value export resolves at runtime` rebuilds `dist/index.js` and asserts each value export is present (catches build drift), and `every frozen type export appears in the built type declarations` asserts each type export is in `dist/index.d.ts`. |
180
+ | Examples compile and are listed | `npm run typecheck` runs `tsc -p examples --noEmit`; `docs.test.ts` `examples_files_exist_and_index_links_examples` and Phase 48 release gates check every example file exists and the cache-aware + NeuralWatt examples are listed in `examples/README.md`. |
181
+ | Examples run to completion with no secret leakage | `docs.test.ts` `examples_demos_run_to_completion_and_emit_no_secret` runs each demo (Node strips TypeScript types natively) with exit-0 and real-secret scans; `external_app_example_*` pins the DB-backed adapter reference exercising the `RunLedger`, branch-handle checkout, fork, and prior-run resume. |
182
+ | Tarball excludes built tests, source maps, and source | `packaging.test.ts` deny list rejects `dist/__tests__/`, `*.map`, `src/`, `plans/`, and internal files per package; confirms `README.md`/`LICENSE`/`CHANGELOG.md` ship, the core tarball ships `docs/` + `dist/cli.js`, every `exports` target is present as compiled output, and the Phase 48 NeuralWatt release gate pins `@arnilo/prism-provider-neuralwatt` `dist/index.js` + `dist/index.d.ts` plus umbrella membership. |
183
+ | NeuralWatt package/docs/examples release gate | `packaging.test.ts` pins `@arnilo/prism-provider-neuralwatt` package exports/type declarations and `@arnilo/prism-providers`/`@arnilo/prism-all` membership; `docs.test.ts` asserts `docs/index.md` links `providers/neuralwatt.md` and `provider-caching.md`, and that `examples/cache-aware-prompt-assembly.ts` plus `examples/neuralwatt-agent-run.ts` exist and are listed. |
184
+ | Network-free + offline test budget | `network-free-guard.test.ts` keeps the default suite network-free; budget pinned `< 60s` (measured baseline above). Install-smoke is offline (`--offline --no-audit --no-fund`, zero registry fetches). |
185
+ | Core security invariants reaffirmed | Runtime/docs tests hold the trust boundary: **no built-in app tools** (hosts register tools; the core ships only the mock provider and contract helpers), **no hidden provider/credential globals** (providers/credentials are host-owned `AgentConfig` fields, resolved via explicit `providerSource`/`CredentialResolver`), **no auto package discovery** (provider/tool/skill packages are opt-in and individually installed; contribution discovery is realpath-contained and emits inert envelopes the host registers), and **no secret persistence in core** (redaction applies before any `RunLedger`/`SessionStore` append; the ledger gate asserts each message event is written exactly once and redacted). |
186
+
187
+ A change that adds a public persistence/runtime surface, a new package, or a new example must extend the matching row's enforcement (add the page to `apiPages`, the package to the `packages` array, or the example to the demos list) so the checklist stays self-maintaining.
136
188
 
137
189
  ## Related APIs
138
190