@arnilo/prism 0.0.3 → 0.0.4
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 +22 -0
- package/README.md +32 -20
- package/dist/agent-loops.d.ts +8 -1
- package/dist/agent-loops.js +57 -11
- package/dist/agents.js +70 -17
- package/dist/checkpoints.d.ts +11 -0
- package/dist/checkpoints.js +144 -0
- package/dist/compaction.js +9 -1
- package/dist/content.d.ts +102 -0
- package/dist/content.js +410 -0
- package/dist/contracts.d.ts +142 -2
- package/dist/event-multiplexer.d.ts +23 -0
- package/dist/event-multiplexer.js +136 -0
- package/dist/execution-policy.d.ts +28 -0
- package/dist/execution-policy.js +24 -0
- package/dist/index.d.ts +17 -5
- package/dist/index.js +11 -4
- package/dist/input.js +11 -1
- package/dist/leases.d.ts +8 -0
- package/dist/leases.js +111 -0
- package/dist/node/agent-definitions.js +3 -5
- package/dist/node/config.d.ts +1 -0
- package/dist/node/config.js +5 -3
- package/dist/node/contribution-discovery.js +5 -8
- package/dist/node/session-store-jsonl.js +8 -5
- package/dist/node/settings.js +2 -2
- package/dist/node/trust.js +2 -4
- package/dist/observability.d.ts +3 -0
- package/dist/observability.js +18 -0
- package/dist/providers/media.d.ts +42 -0
- package/dist/providers/media.js +116 -0
- package/dist/providers/openai-compatible.js +18 -119
- package/dist/providers/openai-primitives.d.ts +9 -0
- package/dist/providers/openai-primitives.js +129 -0
- package/dist/providers/transport.d.ts +40 -0
- package/dist/providers/transport.js +221 -0
- package/dist/redaction.js +40 -13
- package/dist/resources.d.ts +5 -0
- package/dist/resources.js +4 -0
- package/dist/structured-output.d.ts +11 -0
- package/dist/structured-output.js +59 -0
- package/dist/testing/persistence-schema.d.ts +102 -0
- package/dist/testing/persistence-schema.js +457 -0
- package/dist/testing/provider-conformance.js +10 -1
- package/dist/testing/run-ledger-conformance.d.ts +33 -0
- package/dist/testing/run-ledger-conformance.js +172 -0
- package/dist/testing/session-store-conformance.d.ts +16 -0
- package/dist/testing/session-store-conformance.js +73 -0
- package/dist/tools.d.ts +17 -0
- package/dist/tools.js +29 -2
- package/docs/agent-events.md +13 -4
- package/docs/agent-loops.md +10 -4
- package/docs/agent-session-runtime.md +1 -0
- package/docs/cli-rpc.md +3 -0
- package/docs/coding-agent-tools.md +41 -7
- package/docs/coding-security.md +84 -0
- package/docs/credential-storage.md +177 -0
- package/docs/credentials-and-redaction.md +2 -1
- package/docs/database-persistence.md +44 -2
- package/docs/host-security.md +15 -1
- package/docs/index.md +28 -12
- package/docs/input-and-prompt-assembly.md +6 -5
- package/docs/mcp-tools.md +139 -0
- package/docs/middleware-hooks.md +2 -0
- package/docs/migration.md +21 -28
- package/docs/model-registry.md +5 -3
- package/docs/multimodal-content.md +148 -0
- package/docs/observability.md +163 -0
- package/docs/performance.md +40 -1
- package/docs/persistence-credentials-multimodality-primitives.md +303 -0
- package/docs/postgres-persistence.md +141 -0
- package/docs/provider-conformance.md +17 -0
- package/docs/provider-layer.md +1 -1
- package/docs/provider-primitives.md +281 -0
- package/docs/providers/kimi.md +1 -0
- package/docs/providers/neuralwatt.md +1 -0
- package/docs/providers/openai-compatible.md +2 -1
- package/docs/providers/openai.md +8 -1
- package/docs/providers/opencode-go.md +1 -0
- package/docs/providers/openrouter.md +1 -0
- package/docs/providers/zai.md +1 -0
- package/docs/public-contracts.md +9 -2
- package/docs/release-and-install.md +209 -25
- package/docs/resource-loading.md +14 -4
- package/docs/review-coverage-2026-07-14.md +260 -0
- package/docs/run-ledger-conformance.md +96 -0
- package/docs/runs-and-usage.md +2 -0
- package/docs/session-store-conformance.md +16 -0
- package/docs/session-stores-and-branching.md +1 -0
- package/docs/settings-auth-trust-security.md +2 -1
- package/docs/sqlite-persistence.md +122 -0
- package/docs/structured-output.md +9 -0
- package/docs/tool-conformance.md +1 -0
- package/docs/tool-execution-primitives.md +374 -0
- package/docs/tools.md +39 -1
- package/docs/workflow-orchestration-primitives.md +565 -0
- package/docs/workflow-tui-primitives.md +5 -0
- package/docs/workflows.md +219 -0
- package/package.json +33 -5
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Review coverage — 2026-07-14
|
|
2
|
+
|
|
3
|
+
Traceability matrix for the 2026-07-14 code review, `prism-bug-report.md`, and Plans 053-058. Status is updated as implementation lands for release 0.0.4.
|
|
4
|
+
|
|
5
|
+
## Final 0.0.4 status — complete for publish handoff
|
|
6
|
+
|
|
7
|
+
All frozen findings and capabilities are implemented, documented, and verified. Task 8's clean RC matrix passed; Task 9's live registry preflight reports all 24 `0.0.4` versions available. Decision is **GO** after protected release commit/tag and npm authentication prerequisites in `docs/release-and-install.md`. No package was published during plan execution. C-012 remains the sole approved out-of-scope capability.
|
|
8
|
+
|
|
9
|
+
## Frozen 0.0.4 release scope
|
|
10
|
+
|
|
11
|
+
Plans 053-057 contain no unchecked tasks. Frozen review scope contains R-001-R-012 and C-001-C-011. C-012 (interactive TUI) is the sole approved exclusion: Plan 057 replaced terminal UI with public workflow APIs and RPC commands. Any row marked `release blocker` must close before publication; it is not deferred.
|
|
12
|
+
|
|
13
|
+
| Surface | Owner | Implementation / evidence | Tests / release check | Docs | Compatibility owner | Security owner / responsibility | Status |
|
|
14
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
15
|
+
| Core correctness and storage hardening (R-001-R-007) | 053-1 through 053-6 | `src/agent-loops.ts`, `src/redaction.ts`, `src/agents.ts`, node stores/config | Plan 053 core suites; aggregate `sdk:ready` | `agent-loops.md`, `credentials-and-redaction.md`, `performance.md` | 058-1 | 058-2; host keeps production workloads off JSONL | verified |
|
|
16
|
+
| Provider transport, OAuth, structured output, telemetry (R-008-R-010, C-002/C-004/C-008) | 054-1 through 054-6 | `@arnilo/prism/providers/{transport,openai,media}`; provider packages; observability package | provider/conformance/OAuth/structured-output/observability suites | `provider-primitives.md`, `structured-output.md`, `observability.md` | 058-1 | 058-2; hosts own credentials, endpoints, exporter data policy | verified |
|
|
17
|
+
| Tool validation, MCP, parallel dispatch, coding policy/media bounds (C-001/C-003/C-006/C-007, R-011) | 055-1 through 055-6; 058-1/3 | core validator/concurrency/execution policy; validator/MCP/coding-security packages | Plan 055 342-test gate; 058 packed composition, hung MCP, and exclusive-turn/later-turn tests pass | `tool-execution-primitives.md`, `mcp-tools.md`, `coding-security.md`, `agent-loops.md` | 058-1 | 058-1/2/3; hosts trust transports and configure roots/approval | verified through 058-3 |
|
|
18
|
+
| Persistence, credentials, multimodality (C-005/C-010/C-011) | 056-1 through 056-7 | SQLite/PostgreSQL/credentials packages; content/provider media APIs | Plan 056 suites + PostgreSQL CI; 058 integration/performance audit | persistence, credential-storage, multimodal docs | 058-1 | 058-2; hosts own DB TLS, keychain availability, URL/path policy | verified through 058-2 |
|
|
19
|
+
| Workflow orchestration (C-009) | 057-0 through 057-7 | workflow package; checkpoint/event/lease core primitives; durable coordinators | 34 workflow tests, 1,000-node stress, Postgres lease/CAS CI | `workflows.md`, `workflow-orchestration-primitives.md` | 058-1 | 058-1/2; hosts own workflow definitions, tenant identity, approvals | verified |
|
|
20
|
+
| Release tag/version/provenance/resume (R-012) | 058-7/8/9 | Stdlib `scripts/release.mjs`; exact clean tag/version/lock/range validation; registry fingerprint preflight; topological resumable publisher | `release.test.ts`; clean tagged 24-package registry preflight, deterministic dry-run, and operator handoff guard | `release-and-install.md` | 058-7 | Existing `NPM_TOKEN` scoped to publish step; OIDC enabled; explicit public/provenance/latest args; retained artifacts/report | complete for handoff |
|
|
21
|
+
| Package/version graph: 24 publishable manifests | 058-5/7/8 | root + 23 workspace manifests; six family/profile metas; all manifests, internal dependencies/peers, lock entries, runtime metadata at 0.0.4 | exact graph + clean pack/install/import/bin + Node 20/24 checks | profile READMEs; `release-and-install.md` | 058-7 | 0-vulnerability audit, SBOM/license scan, checksums, tarball secret/deny scan | verified through 058-8 |
|
|
22
|
+
| Public API families: provider subpaths; structured output/telemetry; validation/concurrency/execution policy; multimodal content; persistence conformance; checkpoint/event/lease; optional package APIs and workflow RPC | 054-057; 058-6 | Root exports and eight new optional package entry points listed in Plans 054-057 | public-export, packaging, install, docs, and 0.0.3 compatibility fixtures | API pages linked exactly once from `docs/index.md`; all 24 changelogs finalized | 058-1/6 | 058-2; each API page records limits/trust boundaries | verified through 058-6 |
|
|
23
|
+
| Versioned formats/migrations: persistence/checkpoint/lease schema v1; credential envelope/vault v1 | 056/057 | migration contracts and adapter-owned migrations | reopen/migration/CAS/fencing/wrong-key/tamper suites | persistence and credential-storage docs | 058-1 | 058-2; migrations fail closed and values remain parameterized/encrypted | frozen |
|
|
24
|
+
|
|
25
|
+
### Performance and security release ownership
|
|
26
|
+
|
|
27
|
+
| Area | Frozen threshold / current evidence | Remaining release owner | Security test or host responsibility | Status |
|
|
28
|
+
| --- | --- | --- | --- | --- |
|
|
29
|
+
| Provider transport | 256 KiB event, 512 KiB buffer, 64 KiB error body; 16 MiB fixture at 380 MiB/s and +1.7 MiB heap | 058-2 regression comparison | Oversize/abort/header/redaction fixtures | recorded |
|
|
30
|
+
| Telemetry/events | realistic enabled overhead under 5%; measured within 1%; bounded subscriber/workflow buffers | 058-2/8 | Content off by default; exporters are host trust boundary | recorded |
|
|
31
|
+
| Media/MCP/workflows | 10 MB MCP result/image defaults; finite media totals/timeouts; workflow 1,000 nodes, concurrency 8, fan-out 64, event buffer 2,048 | 058-1/2/8 | SSRF/MIME/path/approval/tenant/fencing fixtures | recorded |
|
|
32
|
+
| Ledger/JSONL | 500 deltas: 1.19 ms with ledger, event append concurrency 1; 500 JSONL appends: 141.10 ms / 3,544 per second | closed 058-8 | Redaction canary; JSONL remains single-process development storage | verified 058-8 |
|
|
33
|
+
| Schema cache/parallel tools | warm validation 0.99 µs vs cold compile 2.50 ms; six 20 ms calls: 121.12 ms at concurrency 1 vs 60.92 ms at 2; exclusive turn clamps to 1 and later turn restores 2 | closed 058-8 | Invalid args never invoke handlers; coding shell definitions are exclusive | verified 058-8 |
|
|
34
|
+
| SQLite/PostgreSQL/KDF | SQLite 1,000 appends: 31.84 ms; scrypt/AES default: 48.09 ms; PostgreSQL fresh-container 15/15 integration pass | closed 058-8 | SQL isolation/injection, tamper/wrong-key/plaintext fixtures; DB TLS is host-owned | verified 058-8 |
|
|
35
|
+
| Dependency/artifact security | audit 0 vulnerabilities; clean graph; CycloneDX root + 173 components; 24 tarballs and 28 verified SHA-256 entries; 0 forbidden licenses/files/secret patterns | closed 058-8 | audit/license/provenance/secret/tarball scans | verified 058-8 |
|
|
36
|
+
|
|
37
|
+
### Plan 058 Task 1 integration and compatibility matrix — 2026-07-14
|
|
38
|
+
|
|
39
|
+
| Scenario | Public/packed boundary | Evidence | Result |
|
|
40
|
+
| --- | --- | --- | --- |
|
|
41
|
+
| 0.0.3 source compatibility + additive 0.0.4 structured-output/concurrency options | root public exports and TypeScript contracts | `src/__tests__/compatibility-0-0-3.test.ts`; root typecheck/runtime gate | pass |
|
|
42
|
+
| JSON Schema validator + `toolConcurrency: 3` + local and MCP-mapped tools + coding shell approval in one turn | fresh offline install of all 24 packed tarballs | generated consumer in `src/__tests__/install-smoke.test.ts`; ordered persisted results, exclusive-shell serialization, approval, invalid-arg block, read-only write denial; non-exclusive overlap covered by loop suite | pass |
|
|
43
|
+
| Hung MCP call | public `attachMcpToolBridge`, SDK linked in-memory transport | `packages/mcp/src/__tests__/bridge.test.ts`; 10 ms `callTimeoutMs`, attributable `mcp:hung:hang` error, returns under 150 ms | pass |
|
|
44
|
+
| Revision/redaction + native structured output and artifact fallback + provider telemetry | public core/provider APIs | root agent-loop, redaction, structured-output, observability, and provider conformance suites | pass |
|
|
45
|
+
| SQLite restart/resume + PostgreSQL checkpoint/lease resume | public persistence/workflow APIs | SQLite/workflow package suites and offline examples; Task 8 fresh `postgres:16` run passed all 15 live adapter tests | pass offline and live Postgres |
|
|
46
|
+
| Encrypted credentials + bounded multimodal provider mapping + workflow checkpoint/resume/cancel | public credentials/content/provider/workflow APIs | credential, content/provider-media, workflow package suites and nine offline workflow examples | pass |
|
|
47
|
+
| Secret containment | packed canary plus existing redaction/ledger/store/checkpoint/credential/provider fixtures | no canary in packed session store; aggregate threat suites green | pass |
|
|
48
|
+
| Node/package matrix | Node >=20 type/export contract plus Node 24 full gate | `npm run sdk:ready`: 1,475 tests, 1,450 pass, 25 explicit live skips, 0 failures; all 24 dry-run packs | pass |
|
|
49
|
+
| Live providers | six first-party provider smoke suites | `PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present`; skipped because no provider credentials were present | operator-gated, non-blocking offline |
|
|
50
|
+
|
|
51
|
+
### Plan 058 Task 2 release audit — 2026-07-14
|
|
52
|
+
|
|
53
|
+
| Audit | Evidence / decision | Result |
|
|
54
|
+
| --- | --- | --- |
|
|
55
|
+
| Dependencies | `npm audit --audit-level=high`; `npm ls --all`; lock integrity/provenance scan; `npm outdated --workspaces`; license and install-script inventories | 0 vulnerabilities; clean graph; `@types/node` patched to 22.20.1; runtime majors deferred with rationale in `release-and-install.md` |
|
|
56
|
+
| Maintainability | TODO/no-op scan, provider helper scan, hotspot/domain review, source-text-test scan, strict typecheck/export/package gates | no contradictory product TODO; shared bounded provider helpers used; no touched brittle source test; large core domains remain type-only/runtime-cohesive and are not churned for release |
|
|
57
|
+
| Performance | dated local benchmark matrix in `docs/performance.md`; existing SSE/telemetry/media/workflow stress evidence | all frozen thresholds pass; PostgreSQL wall-clock intentionally CI/environment-owned |
|
|
58
|
+
| Security | common-token/private-key scan plus SQL/SSRF/path/shell/schema/OAuth/credential/MCP/redaction suites; packed canary and deny-list guards | pass; host terminal ANSI/control rendering is explicitly host-owned because 0.0.4 ships RPC, not a TUI |
|
|
59
|
+
| Optional environments | packed imports/bin, failure fixtures, network-free guard, Node >=20 CI import job; PostgreSQL/provider/keychain gates retained | pass offline; credential/OS-backed gates remain explicit |
|
|
60
|
+
|
|
61
|
+
### Plan 058 Task 6 documentation release gate — 2026-07-14
|
|
62
|
+
|
|
63
|
+
| Surface | Evidence | Status |
|
|
64
|
+
| --- | --- | --- |
|
|
65
|
+
| API navigation and structure | 70 docs files; all non-template pages linked exactly once from `docs/index.md`; 59 API/provider pages enforce the wiki heading contract | pass |
|
|
66
|
+
| Imports/links/package graph | Local markdown links resolve; documented core subpaths and all 24 package names match manifests; packed export/import guards remain green | pass |
|
|
67
|
+
| Examples | All 39 TypeScript examples are listed and typechecked; runnable demos complete offline with secret-output scan | pass |
|
|
68
|
+
| READMEs/changelogs | Root + 23 workspace READMEs reviewed; every publishable package ships a finalized `0.0.4` changelog | pass |
|
|
69
|
+
| Compatibility/security/performance | Migration guide states additive 0.0.3 compatibility; API pages and release docs preserve finite limits, opt-in live gates, inactive-by-install behavior, and host trust/credential/transport/storage responsibilities | pass |
|
|
70
|
+
| Focused verification | `docs.test.ts`: 75 pass; `packaging.test.ts`: 124 pass; 0 failures | pass |
|
|
71
|
+
|
|
72
|
+
### Plan 058 Task 7 deterministic publication gate — 2026-07-15
|
|
73
|
+
|
|
74
|
+
| Surface | Evidence | Status |
|
|
75
|
+
| --- | --- | --- |
|
|
76
|
+
| Version graph | All 24 manifests, internal dependency/peer/dev ranges, lockfile workspace entries, root runtime version, and MCP client metadata are `0.0.4` | pass |
|
|
77
|
+
| Registry preflight | Live public-registry availability check reports all 24 `@arnilo/*@0.0.4` versions available; no publish performed | pass |
|
|
78
|
+
| Ordering/resume | One stdlib script derives graph once, emits stable topological order, skips only matching published manifests under `--resume`, and persists status after every package | pass |
|
|
79
|
+
| Publication security | Clean exact `v0.0.4` tag required; real publish cannot bypass checks; `--access public --provenance --tag latest`; OIDC `id-token: write` only in publish job; no long-lived token | pass |
|
|
80
|
+
| Dry run | Real npm CLI dry-run completed all 24 packages in graph order; report contains 24 `dry-run` statuses and 0 failures | pass |
|
|
81
|
+
| Automated regressions | Version/range mismatch, collision, matching/mismatched resume, interruption report, git state, publish args, and token canary tests | pass |
|
|
82
|
+
|
|
83
|
+
### Plan 058 Task 8 clean release-candidate gate — 2026-07-15
|
|
84
|
+
|
|
85
|
+
| Surface | Evidence | Status |
|
|
86
|
+
| --- | --- | --- |
|
|
87
|
+
| Clean build | Fresh 641-file committed snapshot; `npm ci` 1 s; `npm test` 28.209 s; `sdk:ready` 51.500 s; zero generated-file drift | pass |
|
|
88
|
+
| Test/runtime matrix | 1,475 tests: 1,450 pass, 25 explicit provider/keychain skips, 0 fail; Node 20.20.2 and Node 24.18.0 each import 20 root targets | pass |
|
|
89
|
+
| Optional database | Fresh `postgres:16`; all 15 PostgreSQL adapter integration tests pass, 0 skipped | pass |
|
|
90
|
+
| Exact packed consumer | 24 RC tarballs install offline; 24 packages, 37 imports, and `prism --help` pass | pass |
|
|
91
|
+
| Artifact inspection | 539,285 packed / 2,044,155 unpacked bytes; 24/24 reproducible shasums; no forbidden/unsafe files or metadata mismatch | pass |
|
|
92
|
+
| Supply chain | 0 audit vulnerabilities; clean dependency graph; CycloneDX 1.5 SBOM root + 173 components; no missing/prohibited license; 28 verified SHA-256 entries; 0 source/artifact token/private-key matches | pass |
|
|
93
|
+
| Publication boundary | Clean `v0.0.4` registry preflight and provenance-enabled npm dry-run pass 24/24; actual OIDC attestation awaits real publish by design | pass |
|
|
94
|
+
| Performance | `npm test` remains under 60 s; Task 2 ledger/JSONL/schema/parallel/SQLite/redaction/KDF/workflow benchmarks remain inside frozen ceilings | pass |
|
|
95
|
+
|
|
96
|
+
### Plan 058 Task 9 publish handoff — 2026-07-15
|
|
97
|
+
|
|
98
|
+
| Surface | Evidence | Status |
|
|
99
|
+
| --- | --- | --- |
|
|
100
|
+
| Registry state | Live preflight: 24/24 `0.0.4` versions available; 13 packages currently at `0.0.3`, 11 names unpublished | pass |
|
|
101
|
+
| Commit/tag dispatch | Protected signed commit/tag checklist; exact `v0.0.4` tag push dispatch; no local/manual publication | pass |
|
|
102
|
+
| Authentication | Existing GitHub `NPM_TOKEN` is scoped only to the publish step; OIDC/provenance remains enabled | operator prerequisite verified by owner |
|
|
103
|
+
| Order/resume | Exact 24-package topological order recorded; same-tag failed-job rerun skips only matching registry manifests | pass |
|
|
104
|
+
| Post-publish | Bounded metadata/integrity/checksum/import/bin/signature/provenance smoke documented | pass |
|
|
105
|
+
| Rollback | Immutable/non-transactional limitation, deprecation, dist-tag restoration/removal, and no-unpublish default documented | pass |
|
|
106
|
+
| Scope closure | Plans 053-057 follow-ups reconciled; no in-scope finding deferred; C-012 remains approved exclusion | complete |
|
|
107
|
+
|
|
108
|
+
## Core findings (Plan 053)
|
|
109
|
+
|
|
110
|
+
| ID | Priority | Finding | Plan task | Implementation | Tests | Docs | Status |
|
|
111
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
112
|
+
| R-001 | P0 | Revision request duplicated and corrupted by redaction | 053-1 | `src/agent-loops.ts`, `src/redaction.ts` | `src/__tests__/agent-loops.test.ts` (revision with redactor) | `docs/agent-loops.md`, `docs/credentials-and-redaction.md` | implemented |
|
|
113
|
+
| R-002 | P1 | Multi-round tool transcript chronologically invalid | 053-2 | `src/agent-loops.ts` | `src/__tests__/agent-loops.test.ts` (multi-round ordering) | `docs/agent-loops.md`, `docs/tools.md` | implemented |
|
|
114
|
+
| R-003 | P1 | Redactor leaks secrets in object/Map keys | 053-1 | `src/redaction.ts` | `src/__tests__/runtime-redaction.test.ts` | `docs/credentials-and-redaction.md` | implemented |
|
|
115
|
+
| R-004 | P1 | Event-ledger writes have no backpressure | 053-3 | `src/agents.ts` | `src/__tests__/run-ledger.test.ts` (serialized appends) | `docs/runs-and-usage.md`, `docs/performance.md` | implemented |
|
|
116
|
+
| R-005 | P2 | JSONL append silent on corrupt lines | 053-4 | `src/node/session-store-jsonl.ts` | `src/__tests__/node-session-store-jsonl.test.ts` | `docs/node-jsonl-session-store.md` | implemented |
|
|
117
|
+
| R-006 | P2 | Optional config ENOENT detected by message text | 053-5 | `src/node/config.ts`, `src/node/settings.ts` | `src/__tests__/node-config.test.ts` | `docs/node-filesystem-config.md` | implemented |
|
|
118
|
+
| R-007 | P2 | OpenAI-compatible malformed message `TypeError` | 053-1 | `src/providers/openai-compatible.ts` | `src/__tests__/openai-compatible.test.ts` | `docs/providers/openai-compatible.md` | implemented |
|
|
119
|
+
|
|
120
|
+
## Bug report fixes A–D
|
|
121
|
+
|
|
122
|
+
| Fix | Description | Covered by |
|
|
123
|
+
| --- | --- | --- |
|
|
124
|
+
| A+B | Repair input ownership / duplicate revision prompt | R-001 (`pendingHistory` + active-path redaction) |
|
|
125
|
+
| C | Diamond refs collapsed to `[Circular]` | R-001, R-003 |
|
|
126
|
+
| D | Provider assumes iterable `message.content` | R-007 |
|
|
127
|
+
|
|
128
|
+
## Provider findings (Plan 054)
|
|
129
|
+
|
|
130
|
+
| ID | Priority | Finding / capability | Plan task | Design / implementation | Tests | Docs | Status |
|
|
131
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
132
|
+
| R-008 | P1 | Unbounded SSE/error bodies | 054-1, 054-2 | `src/providers/transport.ts`; migrated in all first-party providers | `src/__tests__/provider-transport.test.ts` + provider package suites | `docs/provider-primitives.md` | implemented |
|
|
133
|
+
| R-009 | P1 | OpenAI device-code OAuth polling | 054-3 | `packages/provider-openai/src/oauth.ts` | `packages/provider-openai/src/__tests__/codex-oauth.test.ts` | `docs/providers/openai.md`, `docs/credentials-and-redaction.md` | implemented |
|
|
134
|
+
| R-010 | P2 | Duplicated provider protocol helpers | 054-1, 054-2 | `src/providers/transport.ts`, `src/providers/openai-primitives.ts`; local `sse.ts` removed | `src/__tests__/openai-primitives.test.ts` + provider package suites | `docs/provider-primitives.md` | implemented |
|
|
135
|
+
| C-002 | — | Native structured output | 054-4 | `StructuredOutputOptions`, `validateStructuredOutputOptions`, provider mappers | `src/__tests__/structured-output.test.ts`, `openai-compatible.test.ts` | `docs/structured-output.md` | implemented |
|
|
136
|
+
| C-004 | — | Shared resilient transport | 054-1, 054-2 | `readSseEvents`, `readBoundedResponseText` in all first-party providers | Fixture matrix + provider suites | `docs/provider-primitives.md` | implemented |
|
|
137
|
+
| C-008 | — | Provider/tool observability | 054-5 | `ProviderTurnMetadata`, `@arnilo/prism-observability-opentelemetry` | `src/__tests__/observability.test.ts` + package suite | `docs/observability.md` | implemented |
|
|
138
|
+
|
|
139
|
+
## Tool execution findings (Plan 055)
|
|
140
|
+
|
|
141
|
+
| ID | Priority | Finding / capability | Plan task | Design / implementation | Tests | Docs | Status |
|
|
142
|
+
| --- | --- | --- | --- | --- | --- | --- | --- |
|
|
143
|
+
| C-001 | — | Runtime JSON Schema tool validation | 055-1 | `src/tools.ts` (`ToolArgumentValidator`, `createToolParameterValidator`); `@arnilo/prism-tool-validator-json-schema` | `src/__tests__/tools.test.ts`, package suite | `docs/tools.md`, `docs/tool-execution-primitives.md` | implemented |
|
|
144
|
+
| C-003 | — | MCP client bridge | 055-3 | `@arnilo/prism-mcp`: `connectMcpTools`, stdio + Streamable HTTP, prefixed tools, bounded results | package suite (`packages/mcp`) | `docs/mcp-tools.md`, `docs/tool-execution-primitives.md` | implemented |
|
|
145
|
+
| C-006 | — | Approval/sandbox for coding tools | 055-4 | `src/execution-policy.ts`; `@arnilo/prism-coding-security`; coding-agent `executionPolicy` option | `src/__tests__/execution-policy.test.ts`, package suites | `docs/coding-security.md`, `docs/tool-execution-primitives.md` | implemented |
|
|
146
|
+
| C-007 | — | Parallel tool-call execution | 055-2 | `src/agent-loops.ts` (`dispatchToolCallsInOrder`, `resolveToolConcurrency`); `LoopContext.toolConcurrency` | `src/__tests__/agent-loops.test.ts` | `docs/agent-loops.md`, `docs/tools.md`, `docs/performance.md` | implemented |
|
|
147
|
+
| R-011 | P2 | Coding-agent image size / resize option | 055-5 | `maxImageBytes`, `transformImage`, `DEFAULT_MAX_IMAGE_BYTES`; deprecated `autoResizeImages` | `packages/coding-agent/src/__tests__/read.test.ts` | `docs/coding-agent-tools.md`, `docs/tool-execution-primitives.md` | implemented |
|
|
148
|
+
|
|
149
|
+
## Deferred to later plans (053–058)
|
|
150
|
+
|
|
151
|
+
| ID | Priority | Finding / capability | Owner plan | Status |
|
|
152
|
+
| --- | --- | --- | --- | --- |
|
|
153
|
+
| R-012 | P2 | Release workflow tag/version/resume | 058-7/9 | **implemented and verified** — deterministic graph, collision preflight, resumable publication, provenance, first-publication bootstrap, retained report, operator handoff |
|
|
154
|
+
| C-005 | — | Production database adapters | 056 | verified (sqlite offline + postgres CI live) |
|
|
155
|
+
| C-009 | — | Workflow orchestration | 057 | verified (distributed leases/coordinator + durable control + 9 examples + release gates) |
|
|
156
|
+
| C-010 | — | Audio/file/document multimodality | 056 | verified (core + provider mapping) |
|
|
157
|
+
| C-011 | — | Encrypted credential adapters | 056 | verified (`@arnilo/prism-credentials-node`) |
|
|
158
|
+
| C-012 | — | Interactive TUI | deferred | out of scope for 057 / 0.0.4 workflow completeness |
|
|
159
|
+
|
|
160
|
+
## Plan 056 — persistence, credentials, multimodality (Task 0)
|
|
161
|
+
|
|
162
|
+
| ID | Capability | Plan task | Design / implementation | Tests | Docs | Status |
|
|
163
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
164
|
+
| C-005 | Production database adapters | 056-0 / 056-1 / 056-2 / 056-3 / 056-7 | Task 0 matrix + Task 1 shared primitives + Task 2 `@arnilo/prism-session-store-sqlite` + Task 3 `@arnilo/prism-session-store-postgres` (`createPostgresPersistence`, advisory-lock migrations, pooled parameterized SQL, configurable schema); CI `postgres-integration` job | `packages/session-store-sqlite/src/__tests__/sqlite-persistence.test.ts`, `packages/session-store-postgres/src/__tests__/postgres-persistence.test.ts`, `postgres-integration.test.ts` (CI + `PRISM_TEST_POSTGRES_URL`), `persistence-schema.test.ts`, `conformance-helpers.test.ts` | `sqlite-persistence.md`, `postgres-persistence.md`, `database-persistence.md`, `session-store-conformance.md`, `run-ledger-conformance.md` | verified |
|
|
165
|
+
| C-010 | Audio/file/document multimodality | 056-0 / 056-5 / 056-6 / 056-7 | Core `audio`/`file`/`document` blocks + `resolveMediaContentBlock`; `@arnilo/prism/providers/media` wire helpers; OpenAI Responses maps `input_file`/`input_audio` with data-URL inline files, bounded upload cache + cleanup; Anthropic routes (OpenCode Go, Kimi) map PDF `document`/`file`; OpenRouter/NeuralWatt/Z.ai/OpenCode OpenAI route reject undeclared media | `src/__tests__/content.test.ts`, `src/__tests__/provider-media.test.ts`, `packages/provider-openai/src/__tests__/openai-media.test.ts`, provider package tests | `multimodal-content.md`, `provider-conformance.md`, `model-registry.md` | verified |
|
|
166
|
+
| C-011 | Encrypted credential adapters | 056-0 / 056-4 / 056-7 | `@arnilo/prism-credentials-node` — AES-256-GCM file envelope + scrypt + `@napi-rs/keyring@^1.3.0` keychain adapter; core stays storage-free | `packages/credentials-node/src/__tests__/credentials-node.test.ts` (opt-in keychain via `PRISM_TEST_KEYCHAIN=1`) | `credential-storage.md`, `credentials-and-redaction.md`, `settings-auth-trust-security.md` | verified |
|
|
167
|
+
|
|
168
|
+
## Verification evidence
|
|
169
|
+
|
|
170
|
+
### Plan 053 core gate
|
|
171
|
+
|
|
172
|
+
```bash
|
|
173
|
+
npm run typecheck
|
|
174
|
+
npm test
|
|
175
|
+
npm run build
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
All rows marked **implemented** in the core table pass their focused suites and aggregate core gates.
|
|
179
|
+
|
|
180
|
+
### Plan 054 provider gate — 2026-07-14
|
|
181
|
+
|
|
182
|
+
| Check | Result |
|
|
183
|
+
| --- | --- |
|
|
184
|
+
| `npm run sdk:ready` | pass; typecheck, 1,234 tests (1,209 pass, 25 opt-in live skips, 0 fail), workspace builds, export/install/package guards, and all dry-run packs |
|
|
185
|
+
| `npm audit --audit-level=high` | pass; 0 vulnerabilities |
|
|
186
|
+
| `npm ls --all --depth=0` | pass; clean workspace dependency tree |
|
|
187
|
+
| Duplicate-helper scan | pass; no provider-local `sse.ts`, `safeText`, `parseArgs`, or `toOpenAIMessage`; remaining Kimi/OpenCode Anthropic, OpenAI Responses, and NeuralWatt serializers are documented wire-format variants |
|
|
188
|
+
| Bounds/security fixtures | pass; SSE event/buffer/body/argument limits, abort, malformed schema, prototype-pollution keys, owned headers, and canonical secret-redaction tests |
|
|
189
|
+
| Benchmarks | 16 MiB SSE at 380 MiB/s with +1.7 MiB end heap delta; disabled telemetry within measurement noise; enabled realistic stream within 1%; details in `docs/performance.md` |
|
|
190
|
+
|
|
191
|
+
Plan 054 rows R-008 through R-010 and C-002/C-004/C-008 are verified **implemented**. Live provider tests remain explicit credential-gated smoke tests and account for the 25 aggregate skips.
|
|
192
|
+
|
|
193
|
+
### Plan 055 tool ecosystem / security gate — 2026-07-14
|
|
194
|
+
|
|
195
|
+
| Check | Result |
|
|
196
|
+
| --- | --- |
|
|
197
|
+
| `npm run sdk:ready` | pass; typecheck, 1,305 tests (1,280 pass, 25 opt-in live skips, 0 fail), workspace builds, export/install/package guards, and all dry-run packs |
|
|
198
|
+
| Focused 055 suites | pass; 342 focused tests across core tools/loops/execution-policy/export/install/packaging + tool-validator (12), mcp (11), coding-security (10), coding-agent read/shell/execution-policy |
|
|
199
|
+
| New package packs | pass; `@arnilo/prism-tool-validator-json-schema`, `@arnilo/prism-mcp`, `@arnilo/prism-coding-security` included in install-smoke + packaging + `pack:dry-run` |
|
|
200
|
+
| `npm audit --audit-level=high` | pass; 0 vulnerabilities |
|
|
201
|
+
| `npm ls --all --depth=0` | pass; clean workspace tree including Ajv 8 and MCP SDK 1.29 |
|
|
202
|
+
| Threat-model fixtures | pass; schema remote-ref/pollution/oversized args, parallel abort + ordered results, MCP name collision/list-changed/maxResultBytes, path/symlink/metacharacter/approval denial, image `maxImageBytes` stat-first reject |
|
|
203
|
+
| Secret scan (055 surfaces) | pass; no credential-like literals in new packages/core seams/docs |
|
|
204
|
+
|
|
205
|
+
Plan 055 rows C-001, C-003, C-006, C-007, and R-011 are verified **implemented**. Residual host responsibilities (MCP transport trust, `toolConcurrency` with dangerous shells, optional image transformers) are documented in `docs/tool-execution-primitives.md` and Plan 055 compromises.
|
|
206
|
+
|
|
207
|
+
### Plan 056 persistence / credentials / multimodality gate — 2026-07-14
|
|
208
|
+
|
|
209
|
+
| Check | Result |
|
|
210
|
+
| --- | --- |
|
|
211
|
+
| `npm run sdk:ready` | pass; typecheck, 1,396 tests (1,371 pass, 25 opt-in live skips, 0 fail), workspace builds, export/install/package guards, and all dry-run packs |
|
|
212
|
+
| Focused 056 suites | pass; persistence-schema + conformance helpers + content + provider-media (49), sqlite adapter (7), credentials-node (15), openai multimodal (3) + postgres offline identifiers/DDL |
|
|
213
|
+
| Live PostgreSQL matrix | pass; 9 integration tests via `PRISM_TEST_POSTGRES_URL` (session/run conformance, checkpoint CAS/fencing, atomic leases, migrations, pagination, tenant isolation, injection, advisory-lock race) |
|
|
214
|
+
| CI workflow | `.github/workflows/release.yml` adds `postgres-integration` job (`postgres:16` service + `npm run test:postgres`); publish waits on `verify`, `node20-compat`, and `postgres-integration` |
|
|
215
|
+
| New package packs | pass; `@arnilo/prism-session-store-sqlite`, `@arnilo/prism-session-store-postgres`, `@arnilo/prism-credentials-node` included in install-smoke + packaging + `pack:dry-run` |
|
|
216
|
+
| `npm audit --audit-level=high` | pass; 0 vulnerabilities |
|
|
217
|
+
| `npm ls --all --depth=0` | pass; clean tree including `better-sqlite3@12.11.1`, `pg@8.22.0`, `@napi-rs/keyring@1.3.0`; core remains dependency-free |
|
|
218
|
+
| Threat-model fixtures | pass; SQL injection/tenant isolation, encrypted-store wrong-key/tamper/plaintext scan/permissions/rotation, SSRF/MIME/bounds/unsupported modality, provider reject-undeclared media |
|
|
219
|
+
| Secret scan (056 surfaces) | pass; no credential-like literals in new packages/core media seams/docs |
|
|
220
|
+
|
|
221
|
+
Plan 056 rows C-005, C-010, and C-011 are verified. Residual host responsibilities (Postgres TLS/credential ownership, OS keychain availability, pre-resolving `resourceUri` before providers, provider upload retention) are documented in Plan 056 compromises and the persistence/credentials/multimodality docs.
|
|
222
|
+
|
|
223
|
+
## Plan 057 — workflow orchestration (Tasks 0–7)
|
|
224
|
+
|
|
225
|
+
| ID | Capability | Plan task | Design / implementation | Tests | Docs | Status |
|
|
226
|
+
| --- | --- | --- | --- | --- | --- | --- |
|
|
227
|
+
| C-009 | Workflow/graph orchestration | 057-0 through 057-7 | Tasks 0–6 shipped bounded DAG orchestration and generic persistence/event primitives; Task 7 added core `LeaseStore`, persistence-owned atomic leases, fenced checkpoint CAS, and package-local multi-process enqueue/claim/renew/takeover/cancel coordination. | 34 workflow tests including distributed claim/concurrency/cancel/takeover and 1,000-node stress + 6 focused core primitive tests + SQLite/PostgreSQL persistence coverage; `npm run sdk:ready`: 1,444 tests (1,419 pass, 25 opt-in live skips, 0 fail), strict typecheck, 9 examples, install smoke, packaging guard, all dry-run packs | `workflows.md`, `workflow-orchestration-primitives.md`, `cli-rpc.md`, persistence docs, `examples/README.md` | **verified** |
|
|
228
|
+
| C-012 | Interactive TUI | — | Removed from Plan 057; deferred indefinitely. Workflow host control uses public APIs + optional RPC/`CommandDefinition` bindings instead of a terminal UI. | n/a | `workflow-orchestration-primitives.md` (deferral note); stub at `workflow-tui-primitives.md` | deferred |
|
|
229
|
+
|
|
230
|
+
### Plan 057 workflow gate — 2026-07-14
|
|
231
|
+
|
|
232
|
+
| Check | Result |
|
|
233
|
+
| --- | --- |
|
|
234
|
+
| `npm run sdk:ready` | pass; strict typecheck, 1,444 tests (1,419 pass, 25 explicit live skips, 0 fail), workspace builds, fresh offline install smoke, packaging guard, and all dry-run packs |
|
|
235
|
+
| Workflow/core primitives | workflow 34/34 + focused core 6/6 pass, including distributed exclusive claim, concurrency bounds, heartbeat cancellation, expiry takeover/fencing, checkpoint/lease/event primitives, and a bounded 1,000-node DAG |
|
|
236
|
+
| Examples | 9/9 default executions pass offline and emit no credential-shaped secrets; PostgreSQL safely skips without `PRISM_TEST_POSTGRES_URL` |
|
|
237
|
+
| Live PostgreSQL | root/CI `test:postgres` covers session/run/query persistence, checkpoint CAS/fencing, and atomic leases when `PRISM_TEST_POSTGRES_URL` is present; default network-free gate keeps it opt-in |
|
|
238
|
+
| Scope | no TUI/readline dependency; C-012 remains explicitly deferred and does not block C-009 verification |
|
|
239
|
+
|
|
240
|
+
### Task 0 primitive review summary (2026-07-14)
|
|
241
|
+
|
|
242
|
+
| Area | Shipped seams reused | Gaps closed in Task 0 design | Task 1 core primitive |
|
|
243
|
+
| --- | --- | --- | --- |
|
|
244
|
+
| Orchestration | `AgentSession`, `AgentLoopStrategy`, `LoopContext`, abort, `maxToolRounds`/`toolConcurrency` | Package DAG scheduler over multiple sessions | **Skip** (package-only) |
|
|
245
|
+
| CLI/RPC | `runRpcServer`, branch handles, concurrent abort, JSON events, `CommandDefinition` | Optional `createWorkflowCommands()` for start/status/cancel/resume (replaces TUI control surface) | **Skip** |
|
|
246
|
+
| Events | `AgentEvent`, bounded `subscribe()`, `RunLedger`, redaction | Package `WorkflowEvent` facade over generic bounded fan-in | **Added Task 6:** `EventMultiplexer<T>` |
|
|
247
|
+
| Approval | `PermissionPolicy`, `ExecutionPolicy`, `createCodingApprovalPolicy` | Host `approve` callback + `workflowId`/`nodeId` metadata | **Skip** |
|
|
248
|
+
| Persistence | `SessionStore`, `ProductionPersistenceStore`, SQLite/Postgres, `RunLedger` | `WorkflowCheckpointAdapter` over generic persistence capability | **Added Task 6:** `CheckpointStore` |
|
|
249
|
+
|
|
250
|
+
### Task 1 confirmation (2026-07-14)
|
|
251
|
+
|
|
252
|
+
| Decision | Outcome |
|
|
253
|
+
| --- | --- |
|
|
254
|
+
| Core `CheckpointStore` | **Added in Task 6.** Optional `ProductionPersistenceStore.checkpoints`; memory/SQLite/PostgreSQL implementations; workflows adapt via `createWorkflowCheckpoints({ store })`. |
|
|
255
|
+
| Core event multiplexer | **Added in Task 6.** `WorkflowEventBus` delegates source fan-in, queue bounds, overflow, abort, and close to `createEventMultiplexer<T>()`. |
|
|
256
|
+
| Core `ApprovalHandler` / workflow types | **Not added.** Host policies + package-local types only. |
|
|
257
|
+
| Locked contracts | `WorkflowCheckpointAdapter` (+ value/list shapes), `WorkflowEvent`/`WorkflowEventBus`, `runWorkflow`/`resumeWorkflow`/`getWorkflowRun`/`listWorkflowRuns`, `createWorkflowCommands` — documented in `docs/workflow-orchestration-primitives.md`. |
|
|
258
|
+
| Core code changed | Task 1: none. Task 6 review: generic primitives added without workflow vocabulary. |
|
|
259
|
+
|
|
260
|
+
Tasks 2–4 shipped `@arnilo/prism-workflows`, durable control, and 8 examples. Task 6 removed workflow-owned SQL/queue duplication: core now owns generic checkpoint/event primitives and first-party persistence owns durable checkpoint tables.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Run ledger conformance
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
Run ledger conformance helpers are dependency-free assertions for `RunLedger` adapter tests. They exercise durable writes for runs, events, tool calls, and usage, per-run event ordering, optional tenant-scoped persistence, and restart survival without network or credentials.
|
|
6
|
+
|
|
7
|
+
Exported from `@arnilo/prism/testing/run-ledger-conformance`:
|
|
8
|
+
|
|
9
|
+
- `assertRunLedgerConforms(fixture, options?)`
|
|
10
|
+
- `runRunLedgerConformance(factory, options?)`
|
|
11
|
+
- `RunLedgerConformanceFixture`
|
|
12
|
+
- `RunLedgerConformanceOptions`
|
|
13
|
+
|
|
14
|
+
## When to use it
|
|
15
|
+
|
|
16
|
+
Use this helper when implementing a database-backed `RunLedger` (for example, alongside the reference pattern in `examples/external-app-db-backed.ts`). It asserts the write contract the runtime expects before you add dialect-specific SQL:
|
|
17
|
+
|
|
18
|
+
- `appendRun` / `appendEvent` / `appendToolCall` / `appendUsage` round-trip via optional `read*` callbacks
|
|
19
|
+
- per-run `AgentEventRecord` append order is preserved
|
|
20
|
+
- multiple `appendRun` rows for the same run id (running → terminal) are allowed
|
|
21
|
+
- `tenant_id` is stored on rows when `exerciseTenantIsolation: true`
|
|
22
|
+
- durable rows survive adapter reopen when `exerciseReopen: true` and the factory returns a reopened connection to the same backing store
|
|
23
|
+
|
|
24
|
+
Pair with `@arnilo/prism/testing/persistence-schema` for shared table/index/migration expectations and `@arnilo/prism/testing/session-store-conformance` for the `SessionStore` write path.
|
|
25
|
+
|
|
26
|
+
## Inputs / request
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
import { assertRunLedgerConforms } from "@arnilo/prism/testing/run-ledger-conformance";
|
|
30
|
+
import type { RunLedger } from "@arnilo/prism";
|
|
31
|
+
|
|
32
|
+
await assertRunLedgerConforms({
|
|
33
|
+
ledger: myLedger,
|
|
34
|
+
readRuns: () => queryRuns(),
|
|
35
|
+
readEvents: () => queryEvents(),
|
|
36
|
+
readToolCalls: () => queryToolCalls(),
|
|
37
|
+
readUsage: () => queryUsage(),
|
|
38
|
+
}, { exerciseTenantIsolation: true });
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Factory entry point for durable adapters:
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
import { runRunLedgerConformance } from "@arnilo/prism/testing/run-ledger-conformance";
|
|
45
|
+
|
|
46
|
+
await runRunLedgerConformance(() => createSqliteLedger(testDb), { exerciseReopen: true });
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Outputs / response / events
|
|
50
|
+
|
|
51
|
+
Returns `Promise<void>`; throws a plain `Error` on the first contract violation. No events, no runner.
|
|
52
|
+
|
|
53
|
+
## Request/response example
|
|
54
|
+
|
|
55
|
+
```ts
|
|
56
|
+
import { runRunLedgerConformance } from "@arnilo/prism/testing/run-ledger-conformance";
|
|
57
|
+
|
|
58
|
+
await runRunLedgerConformance(() => postgresLedgerFixture());
|
|
59
|
+
// throws if events are reordered, tool/usage rows are dropped, or reopen loses durable rows.
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Implementation example
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
import { assertRunLedgerConforms } from "@arnilo/prism/testing/run-ledger-conformance";
|
|
66
|
+
|
|
67
|
+
const runs: RunRecord[] = [];
|
|
68
|
+
const events: AgentEventRecord[] = [];
|
|
69
|
+
const ledger: RunLedger = {
|
|
70
|
+
appendRun: async (record) => { runs.push(record); },
|
|
71
|
+
appendEvent: async (record) => { events.push(record); },
|
|
72
|
+
appendToolCall: async () => undefined,
|
|
73
|
+
appendUsage: async () => undefined,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
await assertRunLedgerConforms({ ledger, readRuns: () => runs, readEvents: () => events });
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
## Extension and configuration notes
|
|
80
|
+
|
|
81
|
+
- `read*` callbacks are optional for smoke tests but required for ordering, tenant, and reopen probes.
|
|
82
|
+
- `RunLedger` is write-only from Prism's perspective; replay/query APIs live on `ProductionPersistenceStore` or host-owned reads.
|
|
83
|
+
- Redaction is not asserted here — the runtime calls `redactRunLedgerRecord()` before writes when a `SecretRedactor` is active.
|
|
84
|
+
|
|
85
|
+
## Security and performance notes
|
|
86
|
+
|
|
87
|
+
- No credentials, no network, no real secrets required.
|
|
88
|
+
- The helper performs a small fixed number of ledger writes; it is bounded and fast.
|
|
89
|
+
- Tenant isolation on reads is host-owned; the helper verifies `tenant_id` is stored and that scoped reads do not collide across tenants when you provide tenant-filtered `read*` callbacks.
|
|
90
|
+
|
|
91
|
+
## Related APIs
|
|
92
|
+
|
|
93
|
+
- [Runs and usage ledger](runs-and-usage.md)
|
|
94
|
+
- [Database persistence](database-persistence.md)
|
|
95
|
+
- [Session store conformance](session-store-conformance.md)
|
|
96
|
+
- [Persistence schema primitives](database-persistence.md#shared-schema-model-and-migration-contract)
|
package/docs/runs-and-usage.md
CHANGED
|
@@ -211,6 +211,7 @@ console.log(cacheUsageReport(usageRows.at(-1)?.usage));
|
|
|
211
211
|
- Adapters that need upsert semantics can use `RunRecord.id` (== `runId`) as the stable key.
|
|
212
212
|
- Use `cacheUsageReport(record.usage, model)` for cache diagnostics from normalized usage. It works when a provider reports `cacheReadTokens` without `cacheWriteTokens`; missing write tokens are reported as `0`, and unavailable hit rate/savings stay `undefined`.
|
|
213
213
|
- **Provider-specific telemetry is package-owned.** Core `Usage` carries token counts and `cost`/`currency`; it has no energy or detailed cost-breakdown fields. Providers that surface extra telemetry (e.g. `@arnilo/prism-provider-neuralwatt` exposes `neuralWattEventsWithTelemetry()`, `parseNeuralWattComment()`, and `mapNeuralWattTelemetry()` for `: energy`/`: cost` SSE comments and non-streaming top-level fields) keep that data in package-specific helpers/types. Telemetry never enters `RunLedger` usage rows unless the host explicitly copies it in; it carries usage/cost numbers only — never prompts, API keys, or headers. Account-level quota is likewise package-owned: `@arnilo/prism-provider-neuralwatt` exports an explicit `getNeuralWattQuota()` helper that the host calls on demand (never during generation); NeuralWatt rate-limits that endpoint to 1 request per second per customer, so the caller owns throttling.
|
|
214
|
+
- **Live timing metadata.** `provider_turn_*` events and `ToolExecutionMetadata` on terminal `tool_execution_*` events expose latency, retry `attempt`, and tool `durationMs` for subscribers and ledger replay — see [Observability](observability.md).
|
|
214
215
|
|
|
215
216
|
## Security and performance notes
|
|
216
217
|
|
|
@@ -233,4 +234,5 @@ console.log(cacheUsageReport(usageRows.at(-1)?.usage));
|
|
|
233
234
|
- [Session stores](session-stores.md): `SessionStore` contract for session entries and branches.
|
|
234
235
|
- [Credentials and redaction](credentials-and-redaction.md): `createSecretRedactor()` and redaction helpers.
|
|
235
236
|
- [Provider caching](provider-caching.md): cache hints and `cacheUsageReport()` diagnostics.
|
|
237
|
+
- [Observability](observability.md): `provider_turn_*` events, tool duration metadata, OpenTelemetry adapter.
|
|
236
238
|
- [Public contracts](public-contracts.md): full contract inventory.
|
|
@@ -7,7 +7,9 @@ Session store conformance helpers are dependency-free assertions for `SessionSto
|
|
|
7
7
|
Exported from `@arnilo/prism/testing/session-store-conformance`:
|
|
8
8
|
|
|
9
9
|
- `assertSessionStoreConforms(store, options?)`
|
|
10
|
+
- `runSessionStoreConformance(factory, options?)`
|
|
10
11
|
- `SessionStoreConformanceOptions`
|
|
12
|
+
- `SessionStoreConformanceFactory`
|
|
11
13
|
|
|
12
14
|
## When to use it
|
|
13
15
|
|
|
@@ -20,6 +22,9 @@ Use this helper when implementing a DB-backed `SessionStore` (for example, the r
|
|
|
20
22
|
- branching from any existing entry (existence validation, not tip-CAS)
|
|
21
23
|
- distinct linear appends sharing a run-level `idempotencyKey` are not collapsed
|
|
22
24
|
- optional `readBranchPath` returns the ancestor chain in root-to-leaf order (when `exerciseReadBranchPath: true`)
|
|
25
|
+
- session ids remain isolated (`assertSessionStoreConforms` always probes a secondary session)
|
|
26
|
+
- optional concurrent fork children of the same parent succeed when `exerciseConcurrentParentAppend: true`
|
|
27
|
+
- optional durable reopen/idempotency survival when `runSessionStoreConformance(..., { exerciseReopen: true })`
|
|
23
28
|
|
|
24
29
|
## Inputs / request
|
|
25
30
|
|
|
@@ -28,11 +33,21 @@ import { assertSessionStoreConforms } from "@arnilo/prism/testing/session-store-
|
|
|
28
33
|
import type { SessionStore } from "@arnilo/prism";
|
|
29
34
|
|
|
30
35
|
await assertSessionStoreConforms(myDbBackedStore, { exerciseReadBranchPath: true });
|
|
36
|
+
|
|
37
|
+
// Durable adapters: factory reopens the same backing store
|
|
38
|
+
await runSessionStoreConformance(() => createStore(testDatabase), {
|
|
39
|
+
exerciseReadBranchPath: true,
|
|
40
|
+
exerciseReopen: true,
|
|
41
|
+
exerciseConcurrentParentAppend: true,
|
|
42
|
+
});
|
|
31
43
|
```
|
|
32
44
|
|
|
33
45
|
`SessionStoreConformanceOptions`:
|
|
34
46
|
- `sessionId?: string` — stable session id for the run (default `"conformance"`)
|
|
47
|
+
- `otherSessionId?: string` — secondary session for isolation probes
|
|
35
48
|
- `exerciseReadBranchPath?: boolean` — also probe `readBranchPath` when implemented
|
|
49
|
+
- `exerciseConcurrentParentAppend?: boolean` — also probe concurrent fork appends
|
|
50
|
+
- `exerciseReopen?: boolean` — only on `runSessionStoreConformance`; reopen via the same factory
|
|
36
51
|
|
|
37
52
|
## Outputs / response / events
|
|
38
53
|
|
|
@@ -75,4 +90,5 @@ await assertSessionStoreConforms(createMemorySessionStore());
|
|
|
75
90
|
- [Session stores and branching](session-stores-and-branching.md)
|
|
76
91
|
- [Session stores](session-stores.md)
|
|
77
92
|
- [Database persistence](database-persistence.md)
|
|
93
|
+
- [Run ledger conformance](run-ledger-conformance.md)
|
|
78
94
|
- [Provider conformance](provider-conformance.md)
|
|
@@ -119,5 +119,6 @@ Use `createDefaultCompactionStrategy()` to create compaction entries that `rebui
|
|
|
119
119
|
- [Compaction and retry policies](compaction-and-retry.md): default strategy for creating compaction entries.
|
|
120
120
|
- [Input and prompt assembly](input-and-prompt-assembly.md): provider input assembly consumes rebuilt `messages` and `summaries`.
|
|
121
121
|
- [Credentials and redaction](credentials-and-redaction.md): security boundary for secrets that must not enter session entries.
|
|
122
|
+
- [Workflows](workflows.md): optional orchestration that reuses session `leafId` on resume rather than reloading full transcripts into the scheduler.
|
|
122
123
|
|
|
123
124
|
Session stores persist the entries they receive. Configure `AgentConfig.redactor` or `RunOptions.redactor` before a run when known secrets must be removed before entries reach durable stores.
|
|
@@ -57,7 +57,7 @@ void agent;
|
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
## Extension and configuration notes
|
|
60
|
-
Root imports stay filesystem-free. Node settings files are caller-named and read once; optional missing files are skipped. Trust storage, prompts, approval UI, OAuth token storage, environment-variable selection, and persistent credentials belong in the host or an extension package. Passing `settings` / `credentials` on `AgentConfig` does not wire hidden runtime reads; hosts pass concrete values or resolvers to the provider/request edge that needs them.
|
|
60
|
+
Root imports stay filesystem-free. Node settings files are caller-named and read once; optional missing files are skipped. Trust storage, prompts, approval UI, OAuth token storage, environment-variable selection, and persistent credentials belong in the host or an extension package. For Node.js hosts, [`@arnilo/prism-credentials-node`](credential-storage.md) provides encrypted-file and system-keychain backends. Passing `settings` / `credentials` on `AgentConfig` does not wire hidden runtime reads; hosts pass concrete values or resolvers to the provider/request edge that needs them.
|
|
61
61
|
|
|
62
62
|
## Security and performance notes
|
|
63
63
|
Prism does not sandbox host tools or extensions. Prism does not read environment variables, keychains, user config files, package manifests, resources, settings providers, credential resolvers, or project-local extensions unless the host explicitly wires those operations. Redaction is exact known-secret replacement only; it is not secret detection. Permission and trust checks are one operation per guarded call and add no workers, watchers, retries, network, or filesystem scans.
|
|
@@ -81,6 +81,7 @@ Boundary hardening summary:
|
|
|
81
81
|
- `createMemoryCredentialStore`, `createChainedCredentialResolver`, `createExplicitCredentialResolver`, `createEnvCredentialResolver`, `refreshOAuthCredential`, `resolveCredentialValue`
|
|
82
82
|
- `createStaticTrustPolicy`, `assertTrusted`, `isTrusted`, `TrustDeniedError`
|
|
83
83
|
- `createStaticPermissionPolicy`, `assertPermission`, `checkPermission`, `PermissionDeniedError`
|
|
84
|
+
- `ExecutionPolicy`, `assertExecutionAllowed`, `checkExecution`, `ExecutionDeniedError` (core); `@arnilo/prism-coding-security` for coding-tool approval adapters — see [Coding execution approval and sandboxing](coding-security.md)
|
|
84
85
|
- `createSecretRedactor`, `redactMessage`, `redactAgentEvent`, `redactSessionEntry`, `redactProviderRequest`
|
|
85
86
|
- `@arnilo/prism/node/settings`: `defaultUserSettingsPath`, `readSettingsFile`, `loadSettingsFiles`
|
|
86
87
|
- `@arnilo/prism/node/trust`: `createPathTrustPolicy`, `isPathInside`, `isPathInsideReal`
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# SQLite persistence
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
The optional `@arnilo/prism-session-store-sqlite` package ships a production-oriented SQLite adapter that implements:
|
|
6
|
+
|
|
7
|
+
- `SessionStore` — atomic `append` / `list` / `get` / `readBranchPath`
|
|
8
|
+
- `RunLedger` — durable run, event, tool-call, and usage rows
|
|
9
|
+
- `ProductionPersistenceStore` — cursor-paginated `query*` reads plus generic `checkpoints` and atomic `leases` capabilities
|
|
10
|
+
|
|
11
|
+
Factory:
|
|
12
|
+
|
|
13
|
+
- `createSqlitePersistence(options)`
|
|
14
|
+
- `SqlitePersistenceOptions`
|
|
15
|
+
- `SqlitePersistence.close()`
|
|
16
|
+
|
|
17
|
+
The adapter uses `better-sqlite3@^12.11.1`, enables WAL and foreign keys, applies versioned migrations from the shared Plan 056 schema model, and passes the full session-store and run-ledger conformance suites including process reopen.
|
|
18
|
+
|
|
19
|
+
## When to use it
|
|
20
|
+
|
|
21
|
+
Use this package when you want a small, file-backed persistence layer on Node without operating a database server:
|
|
22
|
+
|
|
23
|
+
- local CLI tools and desktop hosts
|
|
24
|
+
- single-writer or low-concurrency deployments
|
|
25
|
+
- integration tests that need durable reopen semantics
|
|
26
|
+
|
|
27
|
+
Do **not** use it as a substitute for PostgreSQL when you need heavy multi-writer concurrency, server-side pooling, or managed TLS. See [`@arnilo/prism-session-store-postgres`](postgres-persistence.md) for that path.
|
|
28
|
+
|
|
29
|
+
## Inputs / request
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { createSqlitePersistence } from "@arnilo/prism-session-store-sqlite";
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
| Field | Type | Purpose |
|
|
36
|
+
| --- | --- | --- |
|
|
37
|
+
| `filename` | `string` | SQLite database path. Use `:memory:` for ephemeral tests. |
|
|
38
|
+
| `wal` | `boolean` | Enable WAL journal mode. Defaults to `true`. |
|
|
39
|
+
| `busyTimeoutMs` | `number` | SQLite `busy_timeout` in milliseconds. Defaults to `5000`. |
|
|
40
|
+
| `fileMode` | `number` | Unix file mode for newly created database files. Defaults to `0o600`. |
|
|
41
|
+
| `database` | `Database` | Advanced: supply an existing `better-sqlite3` handle (caller owns lifecycle). |
|
|
42
|
+
|
|
43
|
+
## Outputs / response / events
|
|
44
|
+
|
|
45
|
+
`createSqlitePersistence()` returns one object implementing the three persistence contracts plus generic checkpoints and leases:
|
|
46
|
+
|
|
47
|
+
| Method group | Behavior |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| `SessionStore.append` | One transaction per append: parent existence check, idempotency dedup, duplicate-id rejection, entry insert. |
|
|
50
|
+
| `SessionStore.list` / `get` | Indexed reads by `session_id` and primary key. |
|
|
51
|
+
| `SessionStore.readBranchPath` | Recursive ancestor query from `leafId` (or latest leaf) in root→leaf order. |
|
|
52
|
+
| `RunLedger.append*` | Inserts run/event/tool/usage rows; events receive monotonic per-run `sequence` values. |
|
|
53
|
+
| `ProductionPersistenceStore.query*` | Parameterized cursor pagination on indexed columns. |
|
|
54
|
+
| `checkpoints` | Generic versioned `CheckpointStore` backed by `prism_checkpoints`; ownership, CAS/fencing checks, and bounded pagination. |
|
|
55
|
+
| `leases` | Atomic `LeaseStore` backed by `prism_leases`; database-clock expiry, opaque renew/release token, monotonic takeover fence. |
|
|
56
|
+
| `close()` | Closes the underlying database when the adapter opened it. |
|
|
57
|
+
|
|
58
|
+
Migrations run automatically on open and are idempotent across reopen.
|
|
59
|
+
|
|
60
|
+
## Request/response example
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"filename": "./prism.db",
|
|
65
|
+
"wal": true,
|
|
66
|
+
"busyTimeoutMs": 5000,
|
|
67
|
+
"fileMode": 384
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Implementation example
|
|
72
|
+
|
|
73
|
+
```ts
|
|
74
|
+
import { createAgentSession } from "@arnilo/prism";
|
|
75
|
+
import { createSqlitePersistence } from "@arnilo/prism-session-store-sqlite";
|
|
76
|
+
import { runSessionStoreConformance } from "@arnilo/prism/testing/session-store-conformance";
|
|
77
|
+
|
|
78
|
+
const persistence = createSqlitePersistence({ filename: "./prism.db" });
|
|
79
|
+
|
|
80
|
+
await runSessionStoreConformance(
|
|
81
|
+
() => createSqlitePersistence({ filename: "./prism.db" }),
|
|
82
|
+
{ exerciseReadBranchPath: true, exerciseReopen: true },
|
|
83
|
+
);
|
|
84
|
+
|
|
85
|
+
const session = createAgentSession({
|
|
86
|
+
sessionStore: persistence,
|
|
87
|
+
runLedger: persistence,
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
await session.run("hello");
|
|
91
|
+
persistence.close();
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
For resume/timeline flows, use `queryRuns`, `queryEvents`, `queryToolCalls`, and `queryUsage` the same way as the reference mock in [`examples/external-app-db-backed.ts`](../examples/external-app-db-backed.ts).
|
|
95
|
+
|
|
96
|
+
## Extension and configuration notes
|
|
97
|
+
|
|
98
|
+
- The package is optional and workspace-local; `@arnilo/prism` core has no SQLite dependency.
|
|
99
|
+
- Hosts choose the database path and own backup, retention enforcement, and filesystem permissions.
|
|
100
|
+
- `SessionAppendOptions` idempotency rows are durable in `prism_session_append_idempotency` and survive reopen.
|
|
101
|
+
- Schema version **1** (`001_init`) matches `@arnilo/prism/testing/persistence-schema` — PostgreSQL adapters share the same model with dialect-local DDL.
|
|
102
|
+
- Pass an existing `better-sqlite3` `Database` via `database` when your host already manages connections.
|
|
103
|
+
|
|
104
|
+
## Security and performance notes
|
|
105
|
+
|
|
106
|
+
- **Parameterized SQL only.** Session ids, idempotency keys, tenant ids, and JSON payloads are bound parameters.
|
|
107
|
+
- **File ownership.** Create database files on a host-controlled path with restrictive permissions (`0600` default on Unix via `fileMode`).
|
|
108
|
+
- **No path interpolation.** The adapter opens exactly the caller-supplied `filename`; it does not expand environment variables or discover paths.
|
|
109
|
+
- **Redaction upstream.** Event and tool-call payloads may contain secrets; redact before ledger writes. The adapter does not scan or rewrite row contents.
|
|
110
|
+
- **WAL + busy timeout.** WAL is enabled by default; busy timeout defaults to 5 seconds. This meets the Plan 056 local workload target but SQLite still serializes writers — prefer PostgreSQL for high write concurrency.
|
|
111
|
+
- **Indexed operations.** Append, parent validation, idempotency dedup, branch reads, and pagination use the indexes documented in [Database persistence](database-persistence.md); normal paths avoid whole-database scans.
|
|
112
|
+
- **Tenant isolation.** `tenant_id` / `account_id` / `user_id` columns on run and ownership tables participate in query filters; hosts must still scope writes correctly.
|
|
113
|
+
|
|
114
|
+
## Related APIs
|
|
115
|
+
|
|
116
|
+
- [Database persistence](database-persistence.md): shared schema model, conditional append pattern, indexes.
|
|
117
|
+
- [Session store conformance](session-store-conformance.md): `assertSessionStoreConforms` / `runSessionStoreConformance`.
|
|
118
|
+
- [Run ledger conformance](run-ledger-conformance.md): `assertRunLedgerConforms` / `runRunLedgerConformance`.
|
|
119
|
+
- [Persistence, credentials, and multimodality primitives](persistence-credentials-multimodality-primitives.md): package matrix and threat model.
|
|
120
|
+
- [Node JSONL session store](node-jsonl-session-store.md): dev-only single-process alternative.
|
|
121
|
+
- [Workflows](workflows.md): adapt `persistence.checkpoints` and pass `persistence.leases` to `createWorkflowCoordinator()` for durable multi-process workflow execution.
|
|
122
|
+
- [Migration guide](migration.md): moving from JSONL/in-memory to database-backed persistence.
|
|
@@ -10,6 +10,8 @@ An artifact loop generates provider text, parses it to `T`, validates `T` agains
|
|
|
10
10
|
|
|
11
11
|
Use `generateValidateReviseLoop` (with host `parser`/`validator`/`repairer`) when a run should produce an artifact that must satisfy a host-owned schema before it is considered complete: structured JSON output, a generated file passing lint, a typed response conforming to a Synapta-defined model. Wrap your existing schema/validation library behind the `Artifact*` callbacks.
|
|
12
12
|
|
|
13
|
+
When the model declares `capabilities.structuredOutput` and the host opts into native mode, pass `structuredOutput` on `RunOptions.providerOptions` or on the `generate-validate-revise` loop options so capable providers map the schema to their wire format (`response_format` / Responses `text.format`) and valid output can finish in one turn without repair revisions.
|
|
14
|
+
|
|
13
15
|
Do not use it to re-implement provider calls, retry, abort, store, or event emission — those stay runtime-owned and are exposed to the loop only through `LoopContext`. Do not use it for runs that need tool calls during revision turns — use `singleShotLoop` or a custom `AgentLoopStrategy` instead. Do not put Synapta domain types into Prism; map them to `ArtifactValidation` in your callbacks.
|
|
14
16
|
|
|
15
17
|
## Inputs / request
|
|
@@ -47,6 +49,11 @@ await session.run(input, {
|
|
|
47
49
|
parser, // optional; default treats assistant text as the value
|
|
48
50
|
repairer, // optional; default stringifies validation.errors[].message
|
|
49
51
|
maxRevisions: 3, // optional; default 3
|
|
52
|
+
structuredOutput: { name: "answer", schema, strict: true }, // optional native mode
|
|
53
|
+
structuredOutputMode: "native", // or "artifact-loop" to skip provider-native schema
|
|
54
|
+
},
|
|
55
|
+
providerOptions: {
|
|
56
|
+
structuredOutput: { name: "answer", schema, strict: true }, // direct native request
|
|
50
57
|
},
|
|
51
58
|
});
|
|
52
59
|
```
|
|
@@ -222,6 +229,8 @@ Key cross-seam points:
|
|
|
222
229
|
## Extension and configuration notes
|
|
223
230
|
|
|
224
231
|
- `generate-validate-revise` is selected via `AgentConfig.loop` / `RunOptions.loop` (`RunOptions.loop` wins). See [Agent loops](agent-loops.md). `resolveLoop()` maps the options form to the factory; an unknown `strategy` throws before the first turn; a custom `AgentLoopStrategy` instance bypasses the options form.
|
|
232
|
+
- Native structured output uses provider-neutral `StructuredOutputOptions` on `ProviderRequestOptions` / loop options. Capable OpenAI-family providers map to JSON-schema wire fields; unsupported models fail before fetch unless the host sets `structuredOutputMode: "artifact-loop"` and relies on parser/validator/repairer only.
|
|
233
|
+
- `validateStructuredOutputOptions()` enforces JSON-safe schemas, forbidden prototype-pollution keys, and a 64 KiB schema size cap.
|
|
225
234
|
- The default parser treats assistant text as the value (`{ ok: true, value: text }`); supply a host parser whenever `T` is not `string`.
|
|
226
235
|
- The default repairer builds a user message from `validation.errors[].message`; supply a host repairer for schema-specific guidance.
|
|
227
236
|
- `maxRevisions` (default 3) bounds revision turns; budget exhaustion ends the loop and emits `artifact_failed` (it does not throw).
|