@arnilo/prism 0.6.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +79 -5
- package/README.md +12 -11
- package/dist/agent-approval.d.ts +4 -0
- package/dist/agent-approval.js +5 -1
- package/dist/agent-definitions.js +1 -0
- package/dist/agent-run-lifecycle.js +39 -4
- package/dist/agent-run-state.d.ts +18 -0
- package/dist/agent-run-state.js +39 -9
- package/dist/agent-session/helpers.js +6 -1
- package/dist/agent-session/session/assemble.js +159 -7
- package/dist/agent-session/session/persist.d.ts +16 -0
- package/dist/agent-session/session/persist.js +64 -4
- package/dist/agent-session/session/provider-round.d.ts +3 -3
- package/dist/agent-session/session/provider-round.js +12 -6
- package/dist/agent-session/session/tool-round.js +5 -1
- package/dist/agent-session/session/types.d.ts +22 -1
- package/dist/agent-session/session.d.ts +16 -0
- package/dist/agent-session/session.js +42 -3
- package/dist/artifacts.d.ts +39 -1
- package/dist/artifacts.js +73 -0
- package/dist/attention-compiler.d.ts +121 -0
- package/dist/attention-compiler.js +479 -0
- package/dist/checkpoints.js +7 -11
- package/dist/cli-init.js +20 -6
- package/dist/context-budget.d.ts +20 -1
- package/dist/context-budget.js +10 -1
- package/dist/contracts-core/agent.d.ts +7 -0
- package/dist/contracts-core/attention.d.ts +66 -0
- package/dist/contracts-core/attention.js +2 -0
- package/dist/contracts-core/compaction.d.ts +59 -0
- package/dist/contracts-core/compaction.js +77 -1
- package/dist/contracts-core/content.d.ts +5 -0
- package/dist/contracts-core/loop.d.ts +42 -0
- package/dist/contracts-core/provider.d.ts +4 -0
- package/dist/contracts-core/run-limits.d.ts +2 -0
- package/dist/contracts-core.d.ts +1 -0
- package/dist/contracts-core.js +1 -0
- package/dist/contracts-protocol.d.ts +44 -3
- package/dist/contracts-run-state.d.ts +32 -5
- package/dist/evidence-grounding.d.ts +29 -0
- package/dist/evidence-grounding.js +162 -0
- package/dist/host-composition.d.ts +91 -0
- package/dist/host-composition.js +279 -0
- package/dist/index.d.ts +13 -6
- package/dist/index.js +7 -4
- package/dist/input.d.ts +13 -1
- package/dist/input.js +40 -1
- package/dist/provider-events.d.ts +3 -1
- package/dist/provider-events.js +2 -2
- package/dist/providers/transport.d.ts +3 -1
- package/dist/providers/transport.js +36 -0
- package/dist/redaction.js +18 -2
- package/dist/run-bundle.d.ts +89 -0
- package/dist/run-bundle.js +149 -0
- package/dist/secure-agent.d.ts +2 -0
- package/dist/secure-agent.js +6 -1
- package/dist/testing/state-concurrency-conformance.js +5 -12
- package/dist/tool-result-fold.d.ts +12 -0
- package/dist/tool-result-fold.js +13 -6
- package/dist/tools.d.ts +10 -0
- package/dist/tools.js +41 -0
- package/docs/acp-agent.md +42 -11
- package/docs/acp.md +2 -1
- package/docs/ag-ui.md +10 -3
- package/docs/agent-definitions.md +9 -1
- package/docs/agent-events.md +4 -1
- package/docs/agent-loops.md +33 -0
- package/docs/agent-session-runtime.md +8 -7
- package/docs/attention-compiler.md +272 -0
- package/docs/cli-rpc.md +4 -2
- package/docs/coding-agent-tools.md +1 -1
- package/docs/coding-security.md +6 -3
- package/docs/coding-tools.md +0 -1
- package/docs/coding-workspaces.md +22 -0
- package/docs/compaction-and-retry.md +36 -4
- package/docs/compaction-observational-memory.md +63 -10
- package/docs/connected-apps.md +116 -0
- package/docs/context-and-skills.md +17 -2
- package/docs/conversations.md +1 -1
- package/docs/core.md +1 -1
- package/docs/dev-inspector.md +4 -0
- package/docs/device-adapters.md +1 -0
- package/docs/diagrams.md +6 -6
- package/docs/document-reader.md +18 -10
- package/docs/documents.md +40 -11
- package/docs/durable-runs.md +87 -0
- package/docs/enterprise-postgres-state.md +6 -2
- package/docs/evaluations.md +168 -4
- package/docs/execution-timeline.md +186 -0
- package/docs/guardrails.md +33 -0
- package/docs/history/0.7.0-primitive-review.md +254 -0
- package/docs/history/079-messaging-primitive-review.md +391 -0
- package/docs/history/080-messaging-followon-primitive-review.md +234 -0
- package/docs/history/081-connected-apps-primitive-review.md +74 -0
- package/docs/history/083-prism-work-primitive-review.md +84 -0
- package/docs/history/084-primitive-review.md +96 -0
- package/docs/history/085-honesty-and-cut-primitive-review.md +91 -0
- package/docs/history/README.md +5 -0
- package/docs/history/migration-0.0.md +2 -2
- package/docs/history/release-handoffs.md +75 -1
- package/docs/host-compositions.md +149 -0
- package/docs/host-security.md +2 -2
- package/docs/hosted-sandboxes.md +94 -0
- package/docs/index.md +82 -45
- package/docs/input-and-prompt-assembly.md +1 -0
- package/docs/knowledge-sync.md +84 -0
- package/docs/language-intelligence.md +1 -1
- package/docs/live-testing.md +8 -3
- package/docs/mcp-tools.md +3 -1
- package/docs/memory-fabric.md +416 -0
- package/docs/messaging-channel-operations.md +166 -0
- package/docs/messaging-channels.md +150 -0
- package/docs/migrate-to-0.5.md +1 -1
- package/docs/migrate-to-0.6.md +1 -0
- package/docs/migrate-to-0.7.md +345 -0
- package/docs/migrate-to-0.8.md +124 -0
- package/docs/migration.md +43 -1
- package/docs/model-registry.md +12 -2
- package/docs/model-routing.md +79 -4
- package/docs/multi-agent-patterns.md +20 -6
- package/docs/observability.md +52 -1
- package/docs/openapi-tools.md +1 -1
- package/docs/operations.md +14 -4
- package/docs/options-index.md +47 -3
- package/docs/peer-dependencies.md +12 -10
- package/docs/postgres-persistence.md +1 -1
- package/docs/process-sessions.md +3 -1
- package/docs/prompt-registry.md +1 -1
- package/docs/provider-caching.md +4 -2
- package/docs/provider-conformance.md +1 -1
- package/docs/provider-layer.md +2 -2
- package/docs/provider-packages.md +22 -22
- package/docs/providers/bedrock.md +71 -7
- package/docs/providers/neuralwatt.md +5 -1
- package/docs/providers/openai.md +1 -1
- package/docs/rag.md +24 -8
- package/docs/realtime-voice.md +87 -0
- package/docs/release-and-install.md +53 -45
- package/docs/run-bundle.md +92 -0
- package/docs/runs-and-usage.md +17 -2
- package/docs/server.md +7 -3
- package/docs/sheets.md +9 -9
- package/docs/signal-channel.md +112 -0
- package/docs/speech.md +7 -1
- package/docs/sqlite-persistence.md +1 -1
- package/docs/supervisors.md +33 -5
- package/docs/telegram-channel.md +157 -0
- package/docs/testing.md +2 -2
- package/docs/thinking-and-reasoning.md +3 -1
- package/docs/tools.md +6 -5
- package/docs/web-tools.md +2 -1
- package/docs/wiki.md +1 -1
- package/docs/work-artifacts-and-review.md +14 -4
- package/docs/work-connectors.md +12 -10
- package/docs/work-sandbox.md +115 -0
- package/docs/work-tools.md +50 -18
- package/docs/workflows.md +69 -1
- package/docs/working-and-semantic-memory.md +25 -14
- package/package.json +5 -3
- package/templates/README.md +2 -0
- package/templates/business-worker/README.md.tmpl +19 -0
- package/templates/business-worker/env.example.tmpl +1 -0
- package/templates/business-worker/gitignore.tmpl +11 -0
- package/templates/business-worker/manifest.json +12 -0
- package/templates/business-worker/package.json.tmpl +23 -0
- package/templates/business-worker/src/agent.ts.tmpl +92 -0
- package/templates/business-worker/src/index.ts.tmpl +13 -0
- package/templates/business-worker/src/tests/agent.test.ts.tmpl +77 -0
- package/templates/business-worker/tsconfig.json.tmpl +15 -0
- package/templates/personal-assistant/README.md.tmpl +18 -0
- package/templates/personal-assistant/env.example.tmpl +1 -0
- package/templates/personal-assistant/gitignore.tmpl +11 -0
- package/templates/personal-assistant/manifest.json +11 -0
- package/templates/personal-assistant/package.json.tmpl +23 -0
- package/templates/personal-assistant/src/agent.ts.tmpl +65 -0
- package/templates/personal-assistant/src/index.ts.tmpl +13 -0
- package/templates/personal-assistant/src/tests/agent.test.ts.tmpl +28 -0
- package/templates/personal-assistant/tsconfig.json.tmpl +15 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Connected apps and work-HTTP primitive review
|
|
2
|
+
|
|
3
|
+
Plan 081 Task 1 freezes the compatibility and security vocabulary for later tasks. This is evidence only: it adds no public symbol, network path, dependency, or runtime work.
|
|
4
|
+
|
|
5
|
+
## Sources reviewed
|
|
6
|
+
|
|
7
|
+
Current contracts: [MCP tools](../mcp-tools.md), [tool effects](../tool-effects.md), [work tools](../work-tools.md), [work connectors](../work-connectors.md), [host compositions](../host-compositions.md), [credential storage](../credential-storage.md), [credentials and redaction](../credentials-and-redaction.md), [host security](../host-security.md), [Obscura](../obscura.md), [computer-use-linux](../computer-use-linux.md), [messaging channels](../messaging-channels.md), and [ACP](../acp.md). The pinned MCP SDK v2 transport/OAuth API was checked against [MCP TypeScript SDK v2](https://ts.sdk.modelcontextprotocol.io/v2/).
|
|
8
|
+
|
|
9
|
+
## Existing primitives and compatibility freeze
|
|
10
|
+
|
|
11
|
+
| Existing contract | Evidence | Later use / compatibility rule |
|
|
12
|
+
| --- | --- | --- |
|
|
13
|
+
| MCP bridge connects only host-supplied `serverId` + transport, lists before returning, and exposes `refresh`/`close`. | `packages/mcp/src/bridge.ts:49-97`; `packages/mcp/src/types.ts:265-296,354-364` | Task 2 composes `connectMcpTools`; it does not fork transport, discovery, list caching, naming, limits, or bridge lifecycle. |
|
|
14
|
+
| Effect policy receives only host-configured `serverId` and `remoteName`; descriptions/annotations are deliberately unavailable. Omission resolves to `external_mutation` / `unsupported`. | `packages/mcp/src/types.ts:256-263`; `packages/mcp/src/bridge.ts:267-288` | `ConnectedAppSelect` controls admission; optional app/session effect policy can only narrow known remote names. Never infer effects from remote metadata. |
|
|
15
|
+
| Stdio is an explicit host `command`/`args`/`env`/`cwd` transport. Streamable HTTP requires exact origins and uses pinned, redirect-free, byte-bounded fetch; OAuth discovery uses the same boundary and strips bearer credentials from discovery GETs. | `packages/mcp/src/types.ts:34-59`; `packages/mcp/src/transport.ts:37-237`; `src/pinned-fetch.ts:50-82` | Task 2 accepts already host-built `McpTransportConfig`; no command construction, path search, credential resolution, or alternate HTTP client. HTTP adapters in Tasks 4–5 reuse `pinnedFetch`, not a weaker fetch path. |
|
|
16
|
+
| ACP requires an `mcp.select` seam before client MCP config is admitted, applies server/config/header caps, rejects unstable `acp`, and its launcher separately matches explicit stdio/origin allow entries. | `packages/ag-ui/src/acp/mcp-config.ts:17-54`; `packages/acp-agent/src/index.ts:78-125` | `ConnectedAppSelect` follows this fail-closed host-admission shape but remains MCP-package-local; Tasks 2–3 do not couple ACP to connected apps. |
|
|
17
|
+
| Work adapters are structural `Microsoft365Adapter` / `GoogleWorkspaceAdapter` contracts: identity, allowed ops, readiness, `runOp`, and common draft lifecycle. The CLI adapters are additive existing implementations. | `packages/prism-core/src/integrations/work/types.ts:304-365`; `packages/prism-core/src/integrations/work/google-workspace.ts:215-360`; `packages/prism-core/src/integrations/work/microsoft365.ts:281-434` | Tasks 4–5 add HTTP implementations only. Existing CLI factories and argv maps remain byte-compatible. |
|
|
18
|
+
| Work mutations are draft-then-approve, identity/revision/digest-bound, claim before external effect, and become unknown rather than replayed after ambiguous dispatch. Reads and mutations are classified centrally. | `packages/prism-core/src/integrations/work/drafts.ts:68-113`; `packages/prism-core/src/integrations/work/tools.ts:69-286,806-814` | HTTP adapters must feed these adapters/contracts; they must not own a second draft, approval, idempotency, or result-normalization system. |
|
|
19
|
+
| `WorkTokenProvider` returns a late-bound per-identity environment map or `undefined`; OAuth token resolution rejects account and tenant mismatches. | `packages/prism-core/src/integrations/work/types.ts:304-309`; `packages/prism-core/src/credentials/node/work-token.ts:24-68` | Tasks 4–5 require this provider at request edge. Tokens stay out of model arguments, URLs, argv, reports, and logs. |
|
|
20
|
+
| Composition inspection derives identifiers and readiness synchronously; it has no connector import or I/O. | `src/host-composition.ts:181-331`; `src/__tests__/host-composition.test.ts:299-320` | Task 3 reports only bounded app/server identifiers supplied by host. It never accepts transport, headers, `env`, tokens, bridge objects, or a live MCP check. |
|
|
21
|
+
| Obscura is a thin bridge wrapper with injected `connect` test seam and an explicit read-effect override; unclassified tools retain MCP mutation default. | `packages/web-tools/src/obscura/mcp.ts:63-72` | Task 6 copies this direct composition. Do not add a generic read/write wrapper until a third production caller exists. |
|
|
22
|
+
| computer-use-linux validates device admission before bridging, uses an allow-listed child environment, filters known tools, serializes mutations, and classifies unknown/mutating work conservatively. | `packages/prism-coding-tools/src/computer-use-linux/create.ts:56-123` | This is evidence that specialized MCP wrappers remain package-local policy layers, not a reason to generalize a connector framework. |
|
|
23
|
+
| Channels are authenticated inbound execution/delivery transports; work tools are high-trust typed draft/approval tools; MCP maps selected remote tools. | `packages/prism-channels/src/runtime.ts:1-80`; [messaging channels](../messaging-channels.md); [work connectors](../work-connectors.md#out-of-scope) | Tasks 2–7 preserve three planes: MCP tools != work tools != channels. Slack/Teams inbound adapters are out of scope; M365 `teams` capability is not a channel. |
|
|
24
|
+
|
|
25
|
+
### Frozen vocabulary
|
|
26
|
+
|
|
27
|
+
Later tasks use these exact names:
|
|
28
|
+
|
|
29
|
+
- `ConnectedAppBinding`, `ConnectedAppSession`, `createConnectedAppSession`
|
|
30
|
+
- `bind`, `unbind`, `list`, `tools`, `refresh`, `close`
|
|
31
|
+
- `ConnectedAppSelect`
|
|
32
|
+
- `createGoogleWorkspaceHttpAdapter`, `createMicrosoft365HttpAdapter`
|
|
33
|
+
|
|
34
|
+
`ConnectedAppSession` is the one new generic primitive. It belongs in `@arnilo/prism-mcp`; no twelfth package, catalog abstraction, generic remote proxy, or second OAuth stack is justified. Its transport admission is mandatory and deny-by-default. Its effect policy keeps the MCP default when it returns `undefined`.
|
|
35
|
+
|
|
36
|
+
## Later-task mapping
|
|
37
|
+
|
|
38
|
+
| Task | Frozen primitive or explicit boundary |
|
|
39
|
+
| --- | --- |
|
|
40
|
+
| 2 | `connectMcpTools`, `McpTransportConfig`, `McpToolEffectPolicy`, `assertValidServerId`, bounded MCP limits. New session only orchestrates host-approved bridges. |
|
|
41
|
+
| 3 | `inspectHostComposition` / `assertHostCompositionReadiness`; identifiers-only report with no MCP dependency or network. |
|
|
42
|
+
| 4 | `GoogleWorkspaceAdapter`, `WorkTokenProvider`, work drafts, idempotency, normalizers, `pinnedFetch`. Google REST implementation is additive. |
|
|
43
|
+
| 5 | `Microsoft365Adapter`, same shared work primitives, `pinnedFetch`. Graph implementation is additive. |
|
|
44
|
+
| 6 | `createObscuraMcpTools` direct `connect` + `effect` composition. Example only; no Slack dependency or work-tool provider. |
|
|
45
|
+
| 7 | Explicitly out of core: Open Connector remains a sibling sidecar recipe/mock. No dependency, vendoring, catalog discovery, or first-class `execute_action` tool. |
|
|
46
|
+
| 8 | Documentation/verification only. Refresh graph and verify budgets after implementation; no version bump here. |
|
|
47
|
+
|
|
48
|
+
## Threat model and required posture
|
|
49
|
+
|
|
50
|
+
| Threat | Current protection | Requirement for 081 |
|
|
51
|
+
| --- | --- | --- |
|
|
52
|
+
| MCP auto-discovery | Bridge requires explicit `serverId` and transport; docs prohibit auto-discovery. | No catalog URL, discovery scan, or implicit bind. `select` must approve every bind. |
|
|
53
|
+
| Remote effect annotations or descriptions | Policy input excludes them; missing policy is nonrecoverable mutation. | Host classifies exact server/name only. Unknown remote stays `external_mutation` / `unsupported`. |
|
|
54
|
+
| Stdio command injection / ambient secrets | Host supplies argv; specialized wrapper shows allow-listed child env. | Session receives a complete host-built transport only; model cannot choose command, args, cwd, or env. |
|
|
55
|
+
| HTTP SSRF, DNS rebinding, redirect, credential forwarding | Exact origins, DNS pinning, public-address checks, redirect rejection, byte caps, loopback-only plaintext exception. | Connected HTTP binds and work HTTP factories deny origins by default and retain `pinnedFetch`; model never supplies a request URL. |
|
|
56
|
+
| Cross-identity token reuse | Work OAuth token provider loads exact account and rejects mismatched tenant. | Bind identity must equal session identity; resolve tokens at connect/request edge per identity; do not retain secrets in inspection/listing. |
|
|
57
|
+
| `execute_action` exposed as harmless model action | Unclassified MCP tool is a nonrecoverable external mutation. | Open Connector example keeps it unclassified and allowlisted only after host `select`; no model-facing provider catalog. |
|
|
58
|
+
| In-process catalog sidecar compromise | Prism packages have explicit imports and no catalog dependency. | Sidecars run separately over an explicitly allowed loopback MCP transport; never vendor Open Connector, Klavis, or Nango. |
|
|
59
|
+
| Slack/Teams confused with inbound channels | Channel and work documentation distinguish channel adapters from M365 capability operations. | Slack example is an outbound MCP-tool wrap; no inbound Slack/Teams channel is introduced. |
|
|
60
|
+
|
|
61
|
+
## Current verification evidence
|
|
62
|
+
|
|
63
|
+
- MCP bridge default-effect coverage: `packages/mcp/src/__tests__/bridge.test.ts` exercises the bridge contract; the invariant is implemented at `packages/mcp/src/bridge.ts:267-288`.
|
|
64
|
+
- Zero-network composition probe: `src/__tests__/host-composition.test.ts:299-320` replaces `globalThis.fetch` and proves `inspectHostComposition` does not call it.
|
|
65
|
+
- Cross-account and wrong-tenant token probes: `packages/prism-core/src/credentials/node/__tests__/oauth.test.ts:369-391` expect `undefined` from `createOAuthWorkTokenProvider`.
|
|
66
|
+
- Work classification is centralized at `packages/prism-core/src/integrations/work/tools.ts:69-86,806-814`; coverage is in `packages/prism-core/src/integrations/work/__tests__/work-tools.test.ts`.
|
|
67
|
+
|
|
68
|
+
## Task 8 budget baseline
|
|
69
|
+
|
|
70
|
+
`scripts/budgets.json` has an explicit root packed-byte budget only. Task 8 must retain its 1,247,731-byte baseline with 5% tolerance (ceiling 1,310,118 bytes) and must not add a blanket package-size budget. Current `npm pack --dry-run --json` measurements are `@arnilo/prism-mcp` 46,060 bytes (32 files), `@arnilo/prism-core` 412,206 bytes (444 files), and `@arnilo/prism` 1,279,372 bytes (495 files). Public export counts exactly match their ceilings: `@arnilo/prism-mcp` 134, `@arnilo/prism-core` 1,474, and `@arnilo/prism` 1,347 (`scripts/budgets.json:3-67`; `scripts/budget-gates.mjs:151-163`). The two package-specific packed measurements are evidence, not a new ceiling.
|
|
71
|
+
|
|
72
|
+
## Review decision
|
|
73
|
+
|
|
74
|
+
Proceed with the thin MCP session and additive HTTP adapters. Reuse existing MCP transport/effect, work draft/idempotency/token, and host-inspection primitives. Keep catalogs, remote effect trust, command construction, generic Graph/Discovery calls, and Slack/Teams inbound channels out of scope.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Prism work, sandbox, and skills primitive review
|
|
2
|
+
|
|
3
|
+
Plan 083 Task 1 freezes compatibility and security vocabulary for later tasks. This is evidence only: no public symbol, dependency, runtime path, or generated skill body changes here.
|
|
4
|
+
|
|
5
|
+
## Sources reviewed
|
|
6
|
+
|
|
7
|
+
Current contracts: [work tools](../work-tools.md), [work connectors](../work-connectors.md), [documents](../documents.md), [sheets](../sheets.md), [diagrams](../diagrams.md), [document reader](../document-reader.md), [coding security](../coding-security.md), [context and skills](../context-and-skills.md), [core](../core.md), [coding tools](../coding-tools.md), [optional peer dependencies](../peer-dependencies.md), and [host compositions](../host-compositions.md). Package topology and prior HTTP-adapter decisions were checked in [plan 054](../../plans/054-Package-Consolidation-Proposal.md) and [plan 081](../../plans/081-Connected-Apps-Mcp-Host-And-Work-Http.md).
|
|
8
|
+
|
|
9
|
+
Vendor policy sources: [Agent Skills specification](https://agentskills.io/specification), the [Hermes MIT license](https://github.com/NousResearch/hermes-agent/blob/main/LICENSE), and the [Anthropic skills README](https://github.com/anthropics/skills). Hermes is MIT (copyright 2025 Nous Research). Anthropic calls its document skills source-available rather than open source; they are excluded from redistribution.
|
|
10
|
+
|
|
11
|
+
## Existing primitives and compatibility freeze
|
|
12
|
+
|
|
13
|
+
| Existing contract | Evidence | Later use / compatibility rule |
|
|
14
|
+
| --- | --- | --- |
|
|
15
|
+
| Work types define Microsoft 365 and Google Workspace operation/capability sets, bounded limits, identity-bound drafts, `IdempotencyStore`, token provider, structural adapters, and `WorkToolsOptions`. | `packages/prism-core/src/integrations/work/types.ts:3-365` | Move these interfaces unchanged in Task 2. New work package depends only on `@arnilo/prism` at runtime; the PostgreSQL adapter remains core-side and satisfies `IdempotencyStore` structurally. |
|
|
16
|
+
| `createWorkTools` joins configured adapters and centrally assigns observations versus `external_mutation` effects. | `packages/prism-core/src/integrations/work/tools.ts:806-814` | Tasks 2, 4, and 5 retain this single tool/draft/approval/idempotency path; no second work-tool framework. |
|
|
17
|
+
| HTTP adapters require a per-identity token provider, pin allowed origins, use fixed operation maps, and share the draft store. | `packages/prism-core/src/integrations/work/{microsoft365-http,google-workspace-http}.ts:27-191,33-179`; `http.ts:25-71` | Tasks 4-5 add fixed download/update paths only. Tokens stay in `Authorization`; model arguments never contain an arbitrary URL. |
|
|
18
|
+
| Drafts bind identity, revision, canonical payload digest, and approval; checkpoint-backed drafts retain the same lifecycle. | `packages/prism-core/src/integrations/work/drafts.ts:68-113,119-311,320-645`; `types.ts:111-201` | Tasks 4-5 extend existing draft payloads. Approval and ambiguous-outcome handling remain unchanged. |
|
|
19
|
+
| PostgreSQL idempotency atomically claims/finishes/fails/marks unknown records; enterprise composition exposes it as `workIdempotency`. | `packages/prism-core/src/enterprise/postgres/work-idempotency.ts:47-166`; `enterprise.ts:38-82`; `types.ts:153-165` | Task 2 retains the core export with type-only work coupling. Core must not runtime-import `prism-work` or `@office-open/*`. |
|
|
20
|
+
| Documents generate OOXML plus a SHA-256 hash, import only PK containers under caps and optional redaction, and validate every patched model. | `packages/office/src/documents/generate.ts:36-96`; `parse.ts:181-242`; `patch.ts:430-476`; `caps.ts:59-68` | Tasks 2-3 move and wrap these functions. No second document AST, ZIP parser, macro executor, filesystem path, or process runner. |
|
|
21
|
+
| `createDocumentReader` creates bounded PDF/DOCX literal extraction and returns `null` for unsupported bytes; coding `read` accepts its structural `DocumentReader` slot. | `packages/prism-coding-tools/src/document-reader/index.ts:168-202`; `packages/prism-coding-tools/src/agent/read.ts:199-252,472-677` | Task 2 moves implementation and optional peers to work while `DocumentReader` remains in coding tools. Task 3 adds XLSX/PPTX through the moved document parser without changing the slot. |
|
|
22
|
+
| Docker validates absolute executable/image/user/source, exact environment, network mode, limits, and returns one `DisposableSandbox`; sandbox compositions return shared tools plus containment metadata. | `packages/prism-coding-tools/src/security/docker-sandbox.ts:1038-1143`; `sandbox.ts:120-150`; `sandbox-coding-operations.ts:370-376` | Task 6 injects this interface into `createWorkComposition`; it does not fork Docker or claim isolation missing from sandbox capabilities. Default work network is `none`. |
|
|
23
|
+
| `parseSkillFile` validates frontmatter/name and preserves instructions; registry duplicate policy and active-tool checks remain host-owned. | `src/contribution-parsing.ts:87-111`; `src/skills.ts:12-45` | Task 7 parses four vendored files and overlays `toolNames` in TypeScript. No Prism-authored `SKILL.md` body, auto-activation, or permission grant. |
|
|
24
|
+
| Computer-use Linux loads a packaged skill synchronously, caps bytes, parses it with `parseSkillFile`, and verifies the expected name. | `packages/prism-coding-tools/src/computer-use-linux/skill.ts:10-21` | Task 7 reuses this small loader pattern: read, cap, parse, assert known name. Work scripts remain sandbox-only, unlike this host desktop bridge. |
|
|
25
|
+
|
|
26
|
+
### Frozen vocabulary
|
|
27
|
+
|
|
28
|
+
- Package: `@arnilo/prism-work`
|
|
29
|
+
- Subpaths: `/connectors`, `/connectors/microsoft365`, `/connectors/google-workspace`, `/connectors/drafts`, `/documents`, `/sheets`, `/diagrams`, `/document-reader`, `/tools`, `/sandbox`, `/skills`
|
|
30
|
+
- New names: `createOfficeTools`, `createWorkComposition`, `loadWorkSkills`, `WORK_SANDBOX_IMAGE`
|
|
31
|
+
- Injection seam: host supplies a `DisposableSandbox`; `prism-work` does not runtime-depend on `@arnilo/prism-coding-tools`.
|
|
32
|
+
|
|
33
|
+
The cut replaces `@arnilo/prism-office`; it does not add a twelfth publishable package or a compatibility shim. Existing hosts change imports on the next lockstep pre-1.0 cut.
|
|
34
|
+
|
|
35
|
+
## Later-task mapping
|
|
36
|
+
|
|
37
|
+
| Task | Frozen primitive or explicit boundary |
|
|
38
|
+
| --- | --- |
|
|
39
|
+
| 2 | Physical moves only: work types/tools/adapters/drafts, document libraries, and reader implementation. Preserve coding-tools `DocumentReader` interface and core PostgreSQL structural store; prohibit `prism-work` ↔ core/coding-tools runtime edges. |
|
|
40
|
+
| 3 | `generateDocument`, `importDocument`, `patchDocument`, `diffDocument`, preview functions, document caps, and structural reader slot. No duplicate AST or raw OOXML transcript output. |
|
|
41
|
+
| 4 | `createWorkHttpClient`, fixed adapter operation maps, work limits, draft store, approval, and idempotency. Explicitly out: model-supplied download URLs and generic Graph/Drive clients. |
|
|
42
|
+
| 5 | Existing `Microsoft365Op` / `GoogleWorkspaceOp`, capability gates, and draft lifecycle. Explicitly out: free-form `batchUpdate`, Planner/Teams tools, and a Graph Word/Excel session. |
|
|
43
|
+
| 6 | `DisposableSandbox`, `createDockerSandbox`, and `createSandboxCodingComposition`. Explicitly out: tokens/connectors in the sandbox, a second sandbox runtime, unrestricted egress, or an isolation claim without attested capabilities. |
|
|
44
|
+
| 7 | `parseSkillFile`, `createSkillRegistry`, and capped computer-use loader pattern. Explicitly out: Prism-written skill bodies, Anthropic document-skill redistribution, npm dependency on Hermes, and scripts executed on host. |
|
|
45
|
+
| 8 | Existing document model plus injected sandbox `execFile`. Explicitly out: in-process formula evaluation and default-test LibreOffice execution. |
|
|
46
|
+
| 9 | Existing XLSX/DOCX generate translation and document caps. Explicitly out: new model kinds, charts, pivots, comments, headers, and a general numbering engine. |
|
|
47
|
+
| 10 | Existing `isZipContainer` boundary and work sandbox. Explicitly out: an in-process OLE `.doc`/`.xls`/`.ppt` parser or macro execution. |
|
|
48
|
+
| 11 | Existing package/export truth and pack probes. Preserve 11 publishable names, import isolation, optional-peer failure, and history-only references to retired imports. |
|
|
49
|
+
|
|
50
|
+
## Threat model and required posture
|
|
51
|
+
|
|
52
|
+
| Threat | Current protection | Required follow-through |
|
|
53
|
+
| --- | --- | --- |
|
|
54
|
+
| Sandbox receives tenant tokens | Work HTTP resolves per-identity tokens only at request edge; Docker env is an exact allow-list and defaults to network none. | Task 6 rejects M365/Google token names, keeps connectors host-side, and reports `networkIsolated` only from injected capabilities. |
|
|
55
|
+
| LibreOffice macro/OLE execution | In-process document APIs never spawn a process; import reports unsupported macros/OLE as fidelity issues. | Task 6 uses headless LibreOffice with isolated profile, no macro-enable flags or socket, network none; Tasks 8/10 run it only inside that sandbox. |
|
|
56
|
+
| OOXML ZIP symlink/bomb escape | In-process parsing requires a PK container and document caps; Docker workspace import rejects unsafe archive entries. | Tasks 3 and 6 keep byte/element caps before parse and never extract model-supplied archives onto host. Add explicit regression coverage wherever sandbox filesystem import/export meets OOXML bytes. |
|
|
57
|
+
| Proprietary Anthropic skill vendoring | Anthropic labels document skills source-available, not open source. | Task 7 allows only the pinned Hermes MIT source, records `vendor-lock.json`/notice, byte-compares against Anthropic material, and fails without copying on provenance or license doubt. |
|
|
58
|
+
| Model-supplied Graph/Drive URL | Work HTTP client allowlists origins, pins fetch, bounds request/response, and resolves tokens late. | Tasks 4-5 expose item IDs and fixed builders only; schemas omit `url`, reject extra fields, and preserve origin tests. |
|
|
59
|
+
| Core runtime depends on office-open through prism-work | `PostgresEnterpriseState.workIdempotency` is structurally typed today; document imports are isolated in office. | Task 2 keeps core `workIdempotency` local, replaces value imports with local core errors/limits, and proves core ↛ prism-work at runtime. |
|
|
60
|
+
| Vendored skill scripts run outside sandbox | Existing skill loader reads text only; it does not execute scripts. | Tasks 6-7 bind scripts only to sandbox `execFile` with argv, require a work sandbox for registration, and never expose host shell/token env as a skill tool. |
|
|
61
|
+
|
|
62
|
+
## Task 11 baseline
|
|
63
|
+
|
|
64
|
+
Measured 2026-09-17 with `npm pack --dry-run --json` in each package. Export counts are `package.json` `exports` keys; pack values are evidence for Task 11, not new enforced budgets.
|
|
65
|
+
|
|
66
|
+
| Package | Packed bytes | Unpacked bytes | Files | Export keys |
|
|
67
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
68
|
+
| `@arnilo/prism-office` | 55,373 | 247,113 | 76 | 3 |
|
|
69
|
+
| `@arnilo/prism-core` | 418,550 | 2,062,441 | 450 | 23 |
|
|
70
|
+
| `@arnilo/prism-coding-tools` | 294,501 | 1,270,634 | 275 | 10 |
|
|
71
|
+
|
|
72
|
+
Current packaging remains 11 publishable packages and includes `@arnilo/prism-office`; Task 2 replaces that name with `@arnilo/prism-work` without changing the count. Task 11 compares the moved family against this pack/export snapshot before recording a justified ceiling change.
|
|
73
|
+
|
|
74
|
+
## Existing verification evidence
|
|
75
|
+
|
|
76
|
+
- Work tool construction and HTTP adapter coverage: `packages/prism-core/src/integrations/work/__tests__/{work-tools,microsoft365-http,google-workspace-http,drafts}.test.ts`; direct callers are enumerated by `graft callers createWorkTools`.
|
|
77
|
+
- PostgreSQL idempotency and enterprise composition: `packages/prism-core/src/enterprise/postgres/__tests__/{stores,work-idempotency,enterprise-conformance}.test.ts`; `createPostgresEnterpriseState` wires `workIdempotency` at `enterprise.ts:66`.
|
|
78
|
+
- Document reader cap and reader-slot coverage: `packages/prism-coding-tools/src/document-reader/__tests__/index.test.ts` and `packages/prism-coding-tools/src/__tests__/coding-tools-conformance.test.ts`.
|
|
79
|
+
- Sandbox, capability, Docker, and composition coverage: `packages/prism-coding-tools/src/security/__tests__/docker-sandbox.test.ts`, `sandbox-coding-operations.test.ts`, and related security suite.
|
|
80
|
+
- Packaging count/export truth: `src/__tests__/packaging.test.ts` and `scripts/package-truth.json`.
|
|
81
|
+
|
|
82
|
+
## Review decision
|
|
83
|
+
|
|
84
|
+
Proceed with one physical-move family, host-injected sandbox, and four pinned Hermes skills. Reuse work drafts/idempotency, document model/caps, coding-reader seam, Docker sandbox, and skill parser/registry. Keep secrets, generic provider URLs, macro/OLE execution, unpinned or proprietary skill content, host script execution, compatibility wrappers, and new package count out of scope.
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# Host long-run durability, steering, and honesty primitive review
|
|
2
|
+
|
|
3
|
+
Plan 084 Task 0 freezes the vocabulary, symbol inventory, threat posture, and packed baseline for Tasks 1–8. Evidence only: no public symbol, dependency, runtime path, or doc contract changes here.
|
|
4
|
+
|
|
5
|
+
Reviewed tree: `a7915d6c` with 304 dirty files (0.8.0 line in progress), root package version `0.7.0`. Every span below was verified against this revision, not from memory. Where the plan text drifted, [Plan corrections found during review](#plan-corrections-found-during-review) records the correction the implementation tasks must follow.
|
|
6
|
+
|
|
7
|
+
## Sources reviewed
|
|
8
|
+
|
|
9
|
+
Current contracts: [agent session runtime](../agent-session-runtime.md) (§Mid-run steer `90`, §Durable interruption `182`), [agent loops](../agent-loops.md), [AG-UI](../ag-ui.md), [host compositions](../host-compositions.md), [guardrails](../guardrails.md), [runs and usage](../runs-and-usage.md), [model registry](../model-registry.md), [provider layer](../provider-layer.md), [provider conformance](../provider-conformance.md), [execution timeline](../execution-timeline.md), [thinking and reasoning](../thinking-and-reasoning.md), [options index](../options-index.md).
|
|
10
|
+
|
|
11
|
+
Host evidence for the seven gaps: `~/Projects/synapta-core/docs/architecture/prism-070-and-agent-desk-review.md` §8, `plans/117-Prism070Adoption.md`, `docs/architecture/synapta-agent-mechanism.md` §9.2 (`Do` bounds and restart behavior), §9.8 (L0/L1/L2 autonomy law), Plan 111 T21 (`ERR_PRISM_AG_UI_INPUT` relay shim, `429 GoUsageLimitError` opacity), Plan 110 F9 (live `Do` run died at `maxTurns: 4`).
|
|
12
|
+
|
|
13
|
+
## Existing primitives and compatibility freeze
|
|
14
|
+
|
|
15
|
+
| Existing contract | Evidence | Later use / compatibility rule |
|
|
16
|
+
| --- | --- | --- |
|
|
17
|
+
| Durable resume validates revision, fingerprint, `expectedVersion`, ownership/fencing, and requires `status === "suspended"`. | `src/agent-run-lifecycle.ts:112` (`resumeAgentRun`), `:176-195` (`prepareAgentRunResume`; the hard gate is `state.status !== "suspended"` at `:191`); `src/agent-approval.ts:54` (`assertValidAgentRunResume`) | Task 1 adds a running-state resume path gated on a new explicit resume action. The suspension gate and CAS semantics stay; only a validated checkpoint-only path is added. |
|
|
18
|
+
| Resume vocabulary is approval-shaped: legacy `decision?: "approve" | "deny"` plus batched `RunDecision[]` whose outcome is `ApprovalOutcome = "allow_once" | "allow_for_run" | "reject_once" | "reject_for_run"`. | `src/contracts-run-state.ts:221-227` (`AgentRunResume`), `:26` (`ApprovalOutcome`), `:68-79` (`RunDecision`) | Task 1 must **not** add `"continue"` to `ApprovalOutcome` or to `AgUiInterruptResolution` (`packages/ag-ui/src/handler.ts:96`, `"approve" | "deny"`). It is a third resume action beside the legacy pair, resolved before decision work and never applied as a sticky/approval outcome. |
|
|
19
|
+
| Checkpoint persistence lives in one save path with redaction, `expectedVersion`, fencing, and byte caps; session-state payload carries loaded skills, activated tools, attention sticky frontier, and optional skill bodies. | `src/agent-run-state.ts:189` (`saveAgentRunState`); `src/agent-session/session/persist.ts:14-52` (`persistDurable`); `src/contracts-run-state.ts:177-196` (`AgentRunStateOptions`, `persistSessionState:192`, `includeSkillBodies:195`) | Task 1 reuses `saveAgentRunState` unchanged; `checkpointPolicy` only decides *when* it is called. No second checkpoint format, no new store interface. |
|
|
20
|
+
| Loop strategies call an optional steer seam at turn boundaries; the public session queue is bounded by count and bytes, and rejected steers emit a typed event. | `src/agent-loops.ts:34` (`singleShotLoop`), `:45,161` (drain points), `:395` (`resolveLoop`); `src/contracts-core/loop.ts:37-40` (`hasPendingSteers`/`applyPendingSteers`); `src/agent-session/session.ts:209` (`steer`); `src/contracts-run-state.ts:322,326` (caps); `src/contracts-protocol.ts:276` (`steer_rejected`) | Task 2 hooks the same boundary; steer already works and needs no new public surface. Steer caps and the `steer_rejected` event are frozen. |
|
|
21
|
+
| The agent fingerprint hashes id, revision, model, instructions, system prompt contributions, skills, tools, guardrails, and loop revision with SHA-256. | `src/agent-run-state.ts:118-156` (`agentFingerprint`) | Task 4's `RunBundleSnapshot` is the inspectable projection of these same inputs with the same digest algorithm — one truth, not two. |
|
|
22
|
+
| Run results and ledger records already carry a shared `ErrorInfo` (`name`, `message`, `code`, `retryAfterMs`, `cause`). | `src/contracts-core/content.ts:12-20` (`ErrorInfo`); `src/contracts-run-state.ts:285-307` (`AgentRunResult`, `error:302`, `limit:300`); `src/contracts-protocol.ts:519` (`RunRecord.error`); `src/contracts-protocol.ts:420` (`ToolResult.error`) | Task 6 adds `failureClass?` to `ErrorInfo` — it then flows to result, ledger, and tool results with no extra plumbing. No bespoke result-only field. |
|
|
23
|
+
| Provider HTTP errors are built once in the shared retry seam; 429 is already a retryable status with `Retry-After` and redacted bodies. | `src/providers/transport.ts:31` (`ProviderTransportError`); `packages/prism-providers/src/shared/retry-http.ts:12` (`RETRYABLE_STATUSES`), `:31` (`readRetryAfterMs`), `:39` (`parseErrorBody`), `:51` (`providerHttpError`) | Task 6 classifies at `providerHttpError`, from status plus redacted body only. No per-adapter copies, no header/body leakage, `unknown` as default. |
|
|
24
|
+
| Guardrail stages are a closed union with per-stage value typing; the runner and its concurrency cap are shared. | `src/contracts-core/run-limits.ts:63` (`GuardrailStage = "input" | "output" | "tool_input" | "tool_output"`), `:92` (`Guardrail`); `src/guardrails.ts:33,48,89` (`RunGuardrailsOptions`, `runGuardrails`, `assertGuardrailsAllowed`) | Task 5 needs **no** new stage — `"output"` already exists and the gap is the missing reusable factory, not a stage. `runGuardrails` stays unchanged. |
|
|
25
|
+
| Model capabilities are an advisory metadata bag that hosts read for pinning; provider catalogs stamp `thinkingFamily` derived from conformance runs, walked by a cross-catalog test and rendered into an evidence matrix. | `src/contracts-core/content.ts:123-143` (`ModelCapabilities`); stamps in `packages/prism-providers/src/*/models.ts` (e.g. `packages/prism-providers/src/anthropic/models.ts:131`); `packages/prism-providers/src/__tests__/thinking-conformance.test.ts`; `packages/prism-providers/scripts/generate-thinking-coverage.mjs`; `docs/_evidence/thinking-coverage-2026-09-05.md`; `docs/provider-conformance.md` | Task 7 clones this pattern for a second axis (`toolCallStrictness`). No runtime probes, no vendor marketing claims, absent field = unknown. |
|
|
26
|
+
| AG-UI input is fully schema-validated and byte-bounded, but the legacy no-projector path *rejects* client state/tools with `ERR_PRISM_AG_UI_INPUT`; interrupt resolution is deliberately `approve`/`deny` only. | `packages/ag-ui/src/input.ts:27` (`parseAgUiInput`), `:65` (`defaultAgUiInput` — throws when `tools.length !== 0 || !emptyState(state)`); `packages/ag-ui/src/handler.ts:64` (`AgUiInputOptions.project`), `:74` (`AgUiPreparedInput`), `:96` (`AgUiInterruptResolution`), `:160` (`createAgUiHandler`), `:237` (`resolveAgUiCapabilities`) | Task 3 makes server-authoritative mode a sanitize step on `ParsedAgUiInput` (state → `undefined`, tools → `[]`) applied before both the projector and the default path. Bounds and fail-closed parse stay untouched. |
|
|
27
|
+
| Composition inspection is zero-network and reports configuration posture without reading stores or emitting secrets. | `src/host-composition.ts:50` (`HostCompositionReport`), `:219` (`inspectHostComposition`), `:380` (`assertHostCompositionReadiness`) | Task 4's snapshot inherits the zero-network and redaction rules; it is a new pure function, not a change to composition inspection. |
|
|
28
|
+
| Execution timeline projects steps with kind, status, and a content policy; no stop-reason field exists yet, and no terminal event carries one. | `packages/prism-core/src/governance/observability/timeline-types.ts:19-35`; `timeline.ts`; terminal-ish events today: `turn_finished` (`src/contracts-protocol.ts:208`), `run_limit_exceeded` (`:272`), `queue_updated` (`:273`), `steer_rejected` (`:276`) | Task 2 adds `stopReason` additively to the result, the ledger `RunRecord`, and the timeline projection. No new event type; `run_limit_exceeded` is the vocabulary precedent. |
|
|
29
|
+
|
|
30
|
+
## Frozen vocabulary (new, additive only)
|
|
31
|
+
|
|
32
|
+
| Gap | New public surface | Explicitly out |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| G1 | `AgentRunStateOptions.checkpointPolicy?: "decision" \| "every-turn"` (default `"decision"`); a third resume action `"continue"` accepted only by `resumeAgentRun`/`resumeAgentRunStream`; `docs/durable-runs.md`; `examples/durable-investigation.ts` | `"continue"` in `ApprovalOutcome`/`AgUiInterruptResolution`/server routes; a second checkpoint format; any auto-replay of ambiguous tool effects |
|
|
35
|
+
| G2 | `RunOptions.turnPolicy?: { maxTurns?: number; stop?: (ctx: TurnBoundaryContext) => TurnStopDecision }`; `stopReason: "host_policy"` on result/ledger/timeline | New event type; tool-argument or prompt text in `TurnBoundaryContext`; any change to `resolveRunLimits` narrowing law |
|
|
36
|
+
| G3 | `CreateAgUiHandlerOptions.inputPolicy?: { clientState: "honor" \| "ignore" }` (default `"honor"`) | Client-named tool execution; relaxing `parseAgUiInput` bounds; `continue` exposure via AG-UI resume |
|
|
37
|
+
| G4 | `snapshotRunBundle({ agent, config?, run? })` → `RunBundleSnapshot` with `schemaVersion` + SHA-256 digest; `docs/run-bundle.md` | Network/store reads; secret or connection-string content; a second hashing vocabulary |
|
|
38
|
+
| G5 | `createClaimGroundingGuardrail(options)` in `src/evidence-grounding.ts` (stage `"output"`, already in the union); `docs/guardrails.md` section | New guardrail stage; LLM-judge grounding; `@arnilo/prism-memory` dependency; whole-transcript error payloads |
|
|
39
|
+
| G6 | `ProviderFailureClass`; `ErrorInfo.failureClass?` → result/ledger/tool errors; classifier in `providerHttpError` | Per-adapter error types; message-string parsing in hosts; body/header leakage; changed retry counts |
|
|
40
|
+
| G7 | `ModelCapabilities.toolCallStrictness?: "strict" \| "lenient" \| "legacy"`; catalog stamps; conformance walk; `docs/_evidence/toolcall-coverage-<date>.md` | Runtime probes; inferred upgrades; new dependency; a twelfth publishable package |
|
|
41
|
+
|
|
42
|
+
## Later-task mapping
|
|
43
|
+
|
|
44
|
+
| Task | Frozen primitive or explicit boundary |
|
|
45
|
+
| --- | --- |
|
|
46
|
+
| 1 (G1) | `saveAgentRunState` (`src/agent-run-state.ts:189`) called at the loop turn boundary when `checkpointPolicy === "every-turn"`; resume accepts a running-state checkpoint only via the new `"continue"` action; fingerprint/`expectedVersion`/ownership gates unchanged; ambiguity law (no auto-replay after unpersisted side effects) documented as the bounded window. |
|
|
47
|
+
| 2 (G2) | `turnPolicy.stop` evaluated at the same boundary; `stopReason` additive on `AgentRunResult` (`src/contracts-run-state.ts:285`), `RunRecord` (`src/contracts-protocol.ts:519`), timeline projection; `steer()` and its caps untouched. |
|
|
48
|
+
| 3 (G3) | Sanitize `ParsedAgUiInput` before projector/default path when `clientState === "ignore"`; parser bounds and `ERR_PRISM_AG_UI_INPUT`/`ERR_PRISM_AG_UI_LIMIT` semantics unchanged for malformed input. |
|
|
49
|
+
| 4 (G4) | New `src/run-bundle.ts` reuse of `agentFingerprint`'s field vocabulary (`src/agent-run-state.ts:118`) plus `ResolvedRunLimits` and provider/loop identities; `SecretRedactor` at the boundary; zero network. |
|
|
50
|
+
| 5 (G5) | Factory returning an ordinary `GuardrailDefinition` at the existing `"output"` stage; deterministic numeric attribution from run tool results; no memory-package dependency (citation shapes mirrored, not imported). |
|
|
51
|
+
| 6 (G6) | Single classifier beside `providerHttpError`; `failureClass` on `ErrorInfo`; adapters may stamp a provider `code` the classifier weighs; retry policy and budgets unchanged. |
|
|
52
|
+
| 7 (G7) | `toolCallStrictness` stamped only from conformance-observed behavior; cross-catalog walk cloned from `thinking-conformance.test.ts`; generator cloned from `generate-thinking-coverage.mjs`. |
|
|
53
|
+
| 8 | Additions-only compat diff, `docs/options-index.md` routes for the six new option surfaces, the two new `docs/index.md` entries, packed-size delta vs the baseline below. |
|
|
54
|
+
|
|
55
|
+
## Threat model and required posture
|
|
56
|
+
|
|
57
|
+
| Threat | Current protection | Required follow-through |
|
|
58
|
+
| --- | --- | --- |
|
|
59
|
+
| Forged resume `"continue"` from an untrusted caller | Resume is host-API only today; it already validates fingerprint, revision, ownership/fencing, and `expectedVersion` (`src/agent-run-lifecycle.ts:188-191`). | Task 1 keeps every gate, accepts running-state checkpoints only through the explicit action, and proves server/AG-UI surfaces still expose `approve`/`deny` only (`packages/ag-ui/src/handler.ts:96`). |
|
|
60
|
+
| Steer-queue flooding | Bounded queue (`DEFAULT_MAX_PENDING_STEERS = 8`, `DEFAULT_MAX_PENDING_STEER_BYTES = 64 KiB`, `src/contracts-run-state.ts:322,326`) with `steer_rejected` events. | Task 2 does not widen the queue or add a bypass; stop-then-steer tests assert the caps and event behavior survive. |
|
|
61
|
+
| AG-UI client-state trust | Client fields are parsed but carry no runtime authority; projection is host-owned (`packages/ag-ui/src/input.ts:27`, `packages/ag-ui/src/handler.ts:64`). | Task 3's `"ignore"` mode drops client state/tools before projection and keeps malformed/oversized envelopes failing closed. Client tool names still cannot reach the registry. |
|
|
62
|
+
| Bundle snapshot secret leakage | `SecretRedactor` already guards checkpoint payloads; composition inspection is zero-network (`src/host-composition.ts:219`). | Task 4 applies redaction to every string field, never reads stores/env, and adds a secret-shaped fixture test. |
|
|
63
|
+
| Guardrail bypass via missing evidence metadata | Guardrail runner fails closed (`src/guardrails.ts:48-89`). | Task 5 fails any numeric claim when no evidence set exists, never silently passes in flag mode (violation recorded), and bounds the reported span. |
|
|
64
|
+
| Error-classification leakage of provider headers/bodies | `providerHttpError` already redacts bodies; `ErrorInfo.message` is bounded (`src/contracts-core/content.ts:12`). | Task 6 classifies from status + redacted body, never copies headers, defaults to `unknown`, and secret-scans fixtures. |
|
|
65
|
+
| Crash-window double dispatch | The 0.6.0 contract persists tool results before treating a round as failed; resume never auto-replays an ambiguous side effect. | Task 1's `"every-turn"` policy narrows the ambiguity window to at most one provider turn of thinking and documents that residual window in `docs/durable-runs.md`; no auto-replay is added. |
|
|
66
|
+
|
|
67
|
+
## Plan corrections found during review
|
|
68
|
+
|
|
69
|
+
- `packages/prism-ag-ui` does not exist; the package directory is `packages/ag-ui` (name `@arnilo/prism-ag-ui`). Task 3 and Task 8 references use `packages/ag-ui`.
|
|
70
|
+
- `saveRunCheckpoint` does not exist; the single save path is `saveAgentRunState` (`src/agent-run-state.ts:189`), driven by `persistDurable` (`src/agent-session/session/persist.ts:14`).
|
|
71
|
+
- Resume of a crashed (never-suspended) run is today impossible by construction: `:191` requires `status === "suspended"`. Task 1 must add the running-state acceptance for the new action, and `assertValidAgentRunResume` (`src/agent-approval.ts:54`) must learn the action without touching `ApprovalOutcome`.
|
|
72
|
+
- G6 placement is `ErrorInfo.failureClass?` (`src/contracts-core/content.ts:12`), not a bespoke `AgentRunResult` field: `AgentRunResult.error`, `RunRecord.error`, and `ToolResult.error` already share `ErrorInfo`.
|
|
73
|
+
- G3 seam is sanitizing `ParsedAgUiInput` before both `project` and `defaultAgUiInput`; changing only `defaultAgUiInput` would leave projector-based handlers accepting unauthoritative client state.
|
|
74
|
+
- G5 needs no new stage: `"output"` exists in `GuardrailStage` (`src/contracts-core/run-limits.ts:63`).
|
|
75
|
+
- G7's conformance machinery is `packages/prism-providers/src/__tests__/thinking-conformance.test.ts` + `packages/prism-providers/scripts/generate-thinking-coverage.mjs` + `docs/_evidence/thinking-coverage-2026-09-05.md`; there is no `packages/prism/testing/provider-conformance`.
|
|
76
|
+
|
|
77
|
+
## Task 8 baseline
|
|
78
|
+
|
|
79
|
+
Measured 2026-09-17 with `npm pack --dry-run --json` at `a7915d6c` (304 dirty files, 0.8.0 line in progress), **after** this review doc landed, so Task 8 compares like-for-like. These are the plan-line reference points Task 8 reports deltas against; they are not new enforced budgets. Current `scripts/budgets.json` root baselines (plan 079 Task 1, 2026-09-15) are `1,247,731 / 4,137,527 / 489`; the root measurement below sits **+4.0% packed** against that baseline (tolerance 5%).
|
|
80
|
+
|
|
81
|
+
| Package | Packed bytes | Unpacked bytes | Files |
|
|
82
|
+
| --- | ---: | ---: | ---: |
|
|
83
|
+
| `@arnilo/prism` (root) | 1,297,619 | 4,285,038 | 499 |
|
|
84
|
+
| `@arnilo/prism-ag-ui` | 101,715 | 428,130 | 86 |
|
|
85
|
+
| `@arnilo/prism-core` | 385,689 | 1,876,362 | 422 |
|
|
86
|
+
|
|
87
|
+
Pack paths are `packages/ag-ui` and `packages/prism-core`; `@arnilo/prism` is the repo root. This review doc alone accounts for +5,948 packed / +18,060 unpacked / +1 file (`docs/history` is packed into the root tarball). Tasks 1, 4, and 7 add three more docs (`docs/durable-runs.md`, `docs/run-bundle.md`, the tool-call evidence matrix) plus this plan's source growth, so the root baseline will likely need a dated `$comment` rebaseline in Task 8 — the plan 079 Task 1 precedent — rather than being reported as over-tolerance after the fact.
|
|
88
|
+
|
|
89
|
+
## Existing verification evidence
|
|
90
|
+
|
|
91
|
+
- Durable run state, resume, and checkpoint primitives: `src/__tests__/agent-run-state.test.ts`, `durable-loops.test.ts`, `checkpoint-event-primitives.test.ts`.
|
|
92
|
+
- Steer, limits, guardrails, composition: `src/__tests__/run-limits.test.ts`, `guardrails.test.ts`, `host-composition.test.ts`.
|
|
93
|
+
- AG-UI input handling and interrupt resolution: `packages/ag-ui/src/__tests__/` (handler/input suites, A2UI and resume cases).
|
|
94
|
+
- Provider retry/error seam: `packages/prism-providers/src/__tests__/` transport and retry suites (`provider-transport`), plus per-provider HTTP adapter tests.
|
|
95
|
+
- Conformance walk precedent: `packages/prism-providers/src/__tests__/thinking-conformance.test.ts`.
|
|
96
|
+
- Budget/baseline gates: `scripts/budget-gates.mjs` (`measureRootPack`), `scripts/budget-gate.test.mjs`, `scripts/release.mjs gate --update-baseline`.
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# Honesty gates, runtime split, and 0.8.0 cut primitive review
|
|
2
|
+
|
|
3
|
+
Plan 085 Task 0 freezes evidence, compatibility, scope, and the 0.8.0 changelog inventory for Tasks 1–8. Evidence only: no runtime path, public symbol, dependency, or budget changed here.
|
|
4
|
+
|
|
5
|
+
Reviewed tree: `a7915d6c`, with the 0.8.0 working tree already dirty from plans 079–084. Root and all eleven publishable manifests still declare `0.7.0`; this is not release evidence.
|
|
6
|
+
|
|
7
|
+
## Sources reviewed
|
|
8
|
+
|
|
9
|
+
Current contracts: [testing](../testing.md), [release and install](../release-and-install.md), [observational memory](../compaction-observational-memory.md), [messaging channels](../messaging-channels.md), and [messaging channel operations](../messaging-channel-operations.md).
|
|
10
|
+
|
|
11
|
+
External contract: Node 24 [`--test-isolation=mode`](https://nodejs.org/docs/latest-v24.x/api/cli.html#--test-isolationmode) and [test execution model](https://nodejs.org/docs/latest-v24.x/api/test.html#test-runner-execution-model), verified 2026-09-17 through Context7 `/websites/nodejs_latest-v24_x_api`. `process` is the default (one child per file); `none` imports all files into the runner process and runs top-level tests serially. The nested wiki child must continue to remove `NODE_TEST_CONTEXT` and `NODE_TEST_WORKER_ID`.
|
|
12
|
+
|
|
13
|
+
Historical context: [079 review](079-messaging-primitive-review.md), [080 review](080-messaging-followon-primitive-review.md), [081 review](081-connected-apps-primitive-review.md), [083 review](083-prism-work-primitive-review.md), [084 review](084-primitive-review.md), [080 Task 10](../../plans/080-Messaging-Channel-Followons-And-0-8-0-Cut.md), and the [085 plan](../../plans/085-Honesty-Gates-Runtime-Split-And-0-8-0-Cut.md).
|
|
14
|
+
|
|
15
|
+
## Findings and frozen implementation boundary
|
|
16
|
+
|
|
17
|
+
| Review item | Evidence | Frozen boundary | Owning task |
|
|
18
|
+
| --- | --- | --- | --- |
|
|
19
|
+
| 1. Honest release, coverage, and wiki evidence | `scripts/release-skip-manifest.mjs:26-33` selects the newest `phase*-baseline.json`; `:152-180` turns its `testPostgres` count into a pass whenever `PRISM_TEST_POSTGRES_URL` is set. `scripts/coverage-summary.json:1-120` is captured `2026-09-16T21:26:54.219Z`, contains `@arnilo/prism-office`, and lacks live `@arnilo/prism-work` (`packages/prism-work/package.json:2`). `scripts/wiki-scratch-isolation.test.mjs:83-96` strips nested-runner environment but invokes default process isolation. | Postgres pass must require current-HEAD, this-run evidence; coverage keys must equal workspace manifests; use `node --test --test-isolation=none` for the nested wiki child, retaining fixture-hash pollution checks and environment scrubbing. No retry or sleep. | 1 |
|
|
20
|
+
| 2. OM worker contract | `packages/memory/src/compaction/observational-memory/worker-loop.ts:68-70` discards every non-tool event; `:91-92` returns when a provider turn made no tool calls. `:71-81` and `:84-88` identify worker failures by English message prefix before redacting other errors. `runMemoryWorkerLoop` has only the three worker callers listed in `workers/{dropper,observer,reflector}.ts`. | Tool-only is intentional: text/thinking/done-only turns are successful no-ops. Keep no text writer. Replace only the prefix-based internal error classification with a typed memory error in Task 2; provider/tool failures still redact. | 2 |
|
|
21
|
+
| 3. Channel lease release | `packages/prism-channels/src/runtime.ts:657-672` clears `route.lease` before awaiting the persistent release, then swallows an exception after incrementing `storageFailures`. The only callers are `scheduleRoute` (`:1295-1308`) and `stop` (`:1774-1797`). SQLite’s store release itself is ownership/token fenced (`packages/prism-core/src/sessions/sqlite/leases.ts:92-107`). | A failed store release is not success: retain the in-memory lease until persistent acknowledgement, then clear it. Do not roll back an already delivered reply or add a retry loop; idle/stop may retry and lease TTL remains the cross-process backstop. `telegram.ts:631-650` and `signal.ts:427-442` are receiver-specific best-effort paths, not a reason to weaken runtime fencing. | 3 |
|
|
22
|
+
| 4. Runtime decomposition | `createMessagingRuntime` is one 1,878-line closure, `packages/prism-channels/src/runtime.ts:141-2018`, with 80 nested helpers and state interfaces at `:81-139`. It owns authorization, binding/journal, leases, previews/media/replies, approval/resume, admission, drain/stop, and reconciliation. Its callers import only package `index` (examples, runtime/recovery/adapter tests, restart and soak fixtures). | Move private helpers into private sibling modules behind unchanged `createMessagingRuntime`; preserve authorize → lease → claim → provider order and package-index export. This target alone gets the ≤800-line rule—no repository-wide god-file campaign. | 4 |
|
|
23
|
+
| 5. Provider test/dead-binding cleanup | Exactly eleven source-regex tests read an adapter `index.ts` and assert an export at line 8: `anthropic`, `clinepass`, `deepseek`, `google`, `kimi`, `neuralwatt`, `openai`, `opencode-go`, `openrouter`, `xai`, and `zai` under `packages/prism-providers/src/*/__tests__/index.test.ts`. `alibaba/video.ts:23-51` declares `fetchUrl` but binds unused `_fetchUrl`; `openai/speech.ts:32-38` has zero-call `_bearerHeaders`; `alibaba/__tests__/embeddings.test.ts:14-18` only uses `_assignable` for a structural pin. | Delete the eleven vacuous tests, retain one real packaging assertion already owned by root packaging tests, make video’s declared `fetchUrl` work while retaining `pinnedFetch` default, delete speech helper, and use `satisfies` for the embedding shape. No provider test framework. | 5 |
|
|
24
|
+
| 6. Small dedupe only | `retryableAdmission` is equivalent in Telegram (`packages/prism-channels/src/telegram.ts:524-527`) and Signal (`signal.ts:164-170`); caller paths are Telegram poll/webhook and Signal notification enqueue. `pushM365Tools` (`packages/prism-work/src/connectors/tools.ts:435-723`) and `pushGwsTools` (`:725-1083`) are only called from `createWorkTools` (`:1085-1093`), which is 1,093 lines total. | One private admission predicate; one local tool-push helper, not a cross-provider schema DSL. Preserve `assertExternalAllowed` and `executeApprovedMutation` (`tools.ts:192-199,227-407`) on every mutation. Split work catalog files only if the local helper leaves a file over 800 lines. | 6 |
|
|
25
|
+
|
|
26
|
+
## Threat posture
|
|
27
|
+
|
|
28
|
+
| Threat | Current gap | Required posture |
|
|
29
|
+
| --- | --- | --- |
|
|
30
|
+
| A stale Postgres pass hides SQL/durable-store defects | The skip manifest accepts a historical baseline count once the environment variable exists; it does not bind that count to `HEAD`. | Task 1 records only redacted metadata and counts from the current commit. Missing/mismatched evidence is **blocked**, never inherited pass. NATS remains protected when infrastructure is absent. |
|
|
31
|
+
| Swallowed release makes a binding appear free locally | Runtime memory forgets a lease despite the persistent release throwing. A later local scheduling decision is no longer fenced by the held route state. | Task 3 keeps the route lease through a failed store call and proves a later idle/stop path retries it. Ownership/token checks and TTL remain fail-closed. |
|
|
32
|
+
| Later “keep text” change silently drops observations | Current worker ignores non-tools; adding text retention without an explicit writer would look like a successful observation while persisting nothing. | Task 2 documents text-only turns as no-op. A future text-observation feature must add a writer, bounded/redacted payload, ledger semantics, and tests in a separate plan. |
|
|
33
|
+
|
|
34
|
+
## Non-goals frozen out of 085
|
|
35
|
+
|
|
36
|
+
| Out of scope | Evidence / reason | Reconsider only when |
|
|
37
|
+
| --- | --- | --- |
|
|
38
|
+
| SQLite/Postgres persistence unification | Separate SQLite migration and Postgres store implementations have distinct transaction and driver contracts (`packages/prism-core/src/sessions/sqlite/migrations.ts:37-74`; `packages/memory/src/postgres.ts:93-246`). | A measured parity defect requires a shared contract, not merely similar code. |
|
|
39
|
+
| Provider framework | Twenty provider subpackages already have independent request/auth/conformance choices (`scripts/package-truth.json` `providers`). | A third implementation repeats an identical adapter seam after Task 5 cleanup. |
|
|
40
|
+
| Another memory API | Existing observational-memory extension/runtime and `createMemoryFabric` are established public surfaces (`packages/memory/src/compaction/observational-memory/extension.ts:13-24`; `fabric/create.ts:130-469`). | A host has a concrete missing use case neither current surface can express. |
|
|
41
|
+
| Byte-cap increases | Hard request/response limits are explicit process-safety boundaries (`src/run-limits.ts:9-22`; `src/__tests__/run-limits.test.ts:55-68`). | Measurement shows a valid bounded payload cannot fit and a corresponding hard-cap/security review approves it. |
|
|
42
|
+
| Embedder-backed tool search | Current tool search is bounded lexical scoring (`src/tool-search.ts:226-268`) and has a benchmark budget (`scripts/benchmark-tool-search.test.mjs`). | Tool count/relevance measurements fail the current indexed approach. |
|
|
43
|
+
| `asRecord` consolidation | Seven local variants have differing return/validation shapes, including channel and work HTTP code (`packages/prism-channels/src/telegram.ts:175-177`; `packages/prism-work/src/connectors/normalize.ts:3-5`). | A specific correctness defect reaches more than one implementation. |
|
|
44
|
+
| Semaphore consolidation | Existing copies serve different package-local roles (e.g. coding-tools `Semaphore`, `packages/prism-coding-tools/src/security/semaphore.ts:18-55`; core artifact transfer `createSemaphore`, `packages/prism-core/src/runtime/server/artifact-bodies.ts:188-203`). | Profiling or a shared fairness/cancellation bug proves a common contract. |
|
|
45
|
+
| `createGovernedProvider` work | It is a public governance seam with many direct tests (`packages/prism-core/src/governance/model-router/invocation.ts:87-429`). | A separately scoped governance bug or compatibility request exists. |
|
|
46
|
+
| Canonical model comparison | Model-change recording uses `JSON.stringify` in `src/agent-session/session/assemble.ts:223`; unrelated to this cut’s honesty/routing work. | Object key ordering produces a reproducible false model-change record. |
|
|
47
|
+
|
|
48
|
+
## 0.8.0 cut inventory
|
|
49
|
+
|
|
50
|
+
Task 7’s changelog and migration must name these working-tree surfaces. “Completed” below means all task checkboxes are checked; 083 and 084 still have stale `Status: planned` headers, which Task 7 must correct before cut evidence is produced.
|
|
51
|
+
|
|
52
|
+
| Plan | Changelog/migration surface |
|
|
53
|
+
| --- | --- |
|
|
54
|
+
| 079 | New `@arnilo/prism-channels`: transport-neutral runtime/journal, Telegram adapter, experimental Signal adapter, verified identity, durable approvals, restart/recovery and examples. |
|
|
55
|
+
| 080 Tasks 1–9 | Telegram group/topic ownership, draft streaming, bounded attachments/voice, opt-in notifications, ERP outbox composition, SIGTERM/soak, nested test glob, resume signal, and checkpoint scope fixes. |
|
|
56
|
+
| 081 | Identity-bound connected-app MCP session, host-selected allowlists, Google Workspace/Microsoft 365 HTTP adapters, Slack MCP wrap, and sidecar example. |
|
|
57
|
+
| 082 | Package-truth evidence generation and connected-app follow-up safety review. |
|
|
58
|
+
| 083 | `@arnilo/prism-office` replacement with `@arnilo/prism-work` subpaths, work sandbox/composition, file transfer, and vendored Hermes skills. This is the only planned breaking import-map change. |
|
|
59
|
+
| 084 | Durable turn checkpoints/continue, turn-stop policy, server-authoritative AG-UI input, run bundle, evidence grounding, typed provider failure classification, and tool-call reliability metadata. |
|
|
60
|
+
| 085 Tasks 1–6 | This-tree evidence gates, OM worker contract, fail-closed lease release, private runtime split, provider cleanup, and small channel/work dedupe. |
|
|
61
|
+
|
|
62
|
+
**080 Task 10 is superseded by 085 Tasks 7–8.** It remains unchecked in `plans/080-Messaging-Channel-Followons-And-0-8-0-Cut.md:427` until Task 7 marks it with that note; this review does not rewrite past completion evidence.
|
|
63
|
+
|
|
64
|
+
## Task 7 budget baseline
|
|
65
|
+
|
|
66
|
+
Measured 2026-09-17 using `npm pack --workspace <name> --dry-run --json`, against the reviewed dirty working tree. These measurements are Task 7 delta reference points, **not newly enforced budgets**.
|
|
67
|
+
|
|
68
|
+
No package-specific packed-size ceiling exists for the four target workspaces. `scripts/budgets.json:3-36` supplies only the root `@arnilo/prism` pack ceiling: 1,320,080 packed bytes, 4,356,107 unpacked bytes, and 505 files, each with 5% tolerance. The historical aggregate ceiling is explicitly obsolete (`scripts/budgets.json` `aggregate.$comment`). Keep that policy unchanged unless Task 7 adds a separately justified package-pack gate.
|
|
69
|
+
|
|
70
|
+
| Package | Packed bytes | Unpacked bytes | Files | Export ceiling |
|
|
71
|
+
| --- | ---: | ---: | ---: | ---: |
|
|
72
|
+
| `@arnilo/prism-channels` | 51,593 | 234,935 | 24 | 85 |
|
|
73
|
+
| `@arnilo/prism-memory` | 215,525 | 865,582 | 272 | 828 |
|
|
74
|
+
| `@arnilo/prism-work` | 176,039 | 765,717 | 176 | 392 |
|
|
75
|
+
| `@arnilo/prism-providers` | 157,932 | 759,339 | 234 | 528 |
|
|
76
|
+
|
|
77
|
+
Export ceilings come from `scripts/budgets.json:39` (memory), `:43` (work), `:55` (channels), and `:59` (providers); they remain unchanged through Tasks 1–6. Task 7 must record every deliberate budget rebaseline with a dated reason, rather than silently raising a tolerance.
|
|
78
|
+
|
|
79
|
+
## Verification evidence
|
|
80
|
+
|
|
81
|
+
- `node scripts/package-truth.mjs` confirmed 11 publishable manifests and all target manifests at `0.7.0`.
|
|
82
|
+
- Direct artifact probe confirmed the coverage-package mismatch above.
|
|
83
|
+
- Direct source probe found all 11 provider source-regex tests and all three unused binding sites.
|
|
84
|
+
- `npm pack --workspace <name> --dry-run --json` produced the four baseline rows above without creating tarballs.
|
|
85
|
+
- This task intentionally adds no runtime test. Subsequent tasks own the smallest failing checks for their behavior changes.
|
|
86
|
+
|
|
87
|
+
## Plan corrections found during review
|
|
88
|
+
|
|
89
|
+
- Task 7 must update both `plans/083-Prism-Work-Package-Sandbox-And-Skills.md` and `plans/084-Host-Long-Run-Durability-Steering-And-Honesty-Surfaces.md` headers from `Status: planned`; their task checkboxes are complete but their header prose is stale.
|
|
90
|
+
- The four target packages have export ceilings, but **not** independent packed-size ceilings. Task 7 reports measured package pack deltas against this table while retaining the existing root-pack gate.
|
|
91
|
+
- The objective says “table-driven work-tool registration,” but evidence supports only a shared local `pushTool` helper. Task 6 must not introduce a catalog DSL.
|
package/docs/history/README.md
CHANGED
|
@@ -9,3 +9,8 @@ page instead and note the archive where provenance matters.
|
|
|
9
9
|
- `migrate-to-0.4.md`: retired 0.3-era package reorganization guide (current line: [migrate-to-0.5.md](../migrate-to-0.5.md)).
|
|
10
10
|
- `0.1.0-readiness.md`: frozen 0.1.x readiness record.
|
|
11
11
|
- `persistence-credentials-multimodality-primitives.md`, `workflow-orchestration-primitives.md`, `workflow-tui-primitives.md`: plan-era primitive-review inventories.
|
|
12
|
+
- `079-messaging-primitive-review.md`, `080-messaging-followon-primitive-review.md`: messaging-channel primitive reviews (079 shipped runtime; 080 follow-ons + 0.8.0 cut).
|
|
13
|
+
- `081-connected-apps-primitive-review.md`: connected-apps / work-HTTP primitive review (081; page written in 081 Task 1).
|
|
14
|
+
- `083-prism-work-primitive-review.md`: work-family, sandbox, and vendored-skills primitive review (083; page written in 083 Task 1).
|
|
15
|
+
- `084-primitive-review.md`: host long-run durability, steering, and honesty primitive review (084; page written in 084 Task 0).
|
|
16
|
+
- `085-honesty-and-cut-primitive-review.md`: release/coverage/wiki honesty, OM worker and channel lease boundaries, private runtime split, dedupe scope, and 0.8.0 cut inventory (085; page written in Task 0).
|
|
@@ -513,7 +513,7 @@ OAuth client behavior is 2026-07-28 conformant: `finishAuth` now takes the full
|
|
|
513
513
|
|
|
514
514
|
### Monolithic SDK 1.x → modular SDK v2 migration table
|
|
515
515
|
|
|
516
|
-
| v1 (`@modelcontextprotocol/sdk` 1.30.0) | v2 / current
|
|
516
|
+
| v1 (`@modelcontextprotocol/sdk` 1.30.0) | v2 / current Prism MCP API | Notes |
|
|
517
517
|
| --- | --- | --- |
|
|
518
518
|
| `new Client(...)` from `sdk/client/index.js` | same name from `@modelcontextprotocol/client` | `ClientOptions` gains `versionNegotiation`, `listChanged`, `inputRequired`, `cachePartition`, `listMaxPages` |
|
|
519
519
|
| `InMemoryTransport` / `StdioClientTransport` / `StreamableHTTPClientTransport` | `InMemoryTransport`/`StreamableHTTPClientTransport` from `@modelcontextprotocol/client`; `StdioClientTransport` from `@modelcontextprotocol/client/stdio` | subpath moves only |
|
|
@@ -529,7 +529,7 @@ OAuth client behavior is 2026-07-28 conformant: `finishAuth` now takes the full
|
|
|
529
529
|
|
|
530
530
|
- **Now (default):** `createPrismMcpWebHandler(factory)` without `sessionIdGenerator` is stateless dual-era — modern 2026-07-28 serving plus the SDK stateless fallback for 2025 clients. No `Mcp-Session-Id`, no sticky routing, `Last-Event-ID` replay not enabled.
|
|
531
531
|
- **Now (opt-in):** configuring `sessionIdGenerator` keeps identity-bound legacy sessions (POST/GET/DELETE/SSE beside the strict modern handler) for hosts that still need them; the pairing requires exact `allowedOrigins` and host `resolveIdentity`.
|
|
532
|
-
- **Planned removal:** the legacy session leg is deprecated once
|
|
532
|
+
- **Planned removal:** the legacy session leg is deprecated once the package's clients and documented hosts are modern-era; removal lands as a breaking 0.x cut with a migration note here (the `sessionIdGenerator` option disappears and legacy traffic gets the SDK stateless fallback, which 2025 clients already work against). No date is committed in this release.
|
|
533
533
|
|
|
534
534
|
## 0.0.7 → 0.0.8 OpenTelemetry adapter
|
|
535
535
|
|
|
@@ -2,6 +2,80 @@
|
|
|
2
2
|
|
|
3
3
|
Operator publish handoffs per release line, kept verbatim. Not read on the hot path.
|
|
4
4
|
|
|
5
|
+
### 0.8.0 publish handoff (plan 085 Tasks 7–8)
|
|
6
|
+
|
|
7
|
+
**Decision: GO when the operator prerequisites below are recorded on the tagged commit.** Release **0.8.0** is the **seven-plan cut**: [079](../../plans/079-Prism-Messaging-Channels-Telegram-Signal.md) (messaging channels), [080](../../plans/080-Messaging-Channel-Followons-And-0-8-0-Cut.md) Tasks 1–9, [081](../../plans/081-Connected-Apps-Mcp-Host-And-Work-Http.md) (connected apps / work HTTP), [082](../../plans/082-Package-Evidence-Generation-And-Connected-App-Follow-Up-Review.md), [083](../../plans/083-Prism-Work-Package-Sandbox-And-Skills.md) (`@arnilo/prism-work` replacing `@arnilo/prism-office`), [084](../../plans/084-Host-Long-Run-Durability-Steering-And-Honesty-Surfaces.md) (durable runs), [085](../../plans/085-Honesty-Gates-Runtime-Split-And-0-8-0-Cut.md) Tasks 1–6 (honesty gates). **080 Task 10 is superseded here.** Plan 079 is **in** this cut.
|
|
8
|
+
|
|
9
|
+
The graph is **11 publishable manifests** at exact **0.8.0** with internal caret ranges `^0.8.0`: root `@arnilo/prism` plus 10 workspace packages (4 `prism-*` family packages, 6 capability packages, 19 provider adapter subpaths inside the providers family). The predecessor published release is **0.7.0**.
|
|
10
|
+
|
|
11
|
+
Host-visible delta (full detail in [migrate-to-0.8.md](../migrate-to-0.8.md)): one **import-map break** — `@arnilo/prism-office` and the work/document-reader subpaths move to `@arnilo/prism-work` with no shim; catch work-idempotency by `code`. Everything else is additive or a documented pin: `@arnilo/prism-channels`, connected-app MCP sessions, durable turn checkpoints / `continue`, turn-stop policy, run bundle, claim-grounding guardrail, OM workers stay tool-only, channel lease release is fail-closed, AG-UI `inputPolicy.clientState: "ignore"` is opt-in.
|
|
12
|
+
|
|
13
|
+
Evidence recorded for the tree under publication. `scripts/release-evidence.json` — **43 surfaces, 12 pass, 31 protected with reasons, `blocked: false`** (`test:postgres durable conformance` is a this-tree pass, count 544, `gitHead` matches `git rev-parse HEAD`). `npm test` 6/6 stages; `npm run typecheck` green for root, all workspaces, and `examples/`; coverage core 92.50 lines against the 60/70/75 gate with every non-protected workspace above its recorded lines threshold (artifact keys include `@arnilo/prism-work`, not `@arnilo/prism-office`); `npm run pack:dry-run` green for all eleven packages; `npm run release:check --lockstep --version 0.8.0` reports **11/11 packages available**; `npm run release:publish --dry-run --lockstep --version 0.8.0` produces all eleven packs deterministically; `npm run security:threat-suites` **83/83**; `npm audit --audit-level=moderate` **0**; secret scan **6895 files, 0 findings**; SBOM regenerated (173 packages) and `scripts/verify-sbom.mjs` clean against `security/license-policy.json`.
|
|
14
|
+
|
|
15
|
+
Protected legs actually run here (not just recorded): `PRISM_TEST_POSTGRES_URL=… npm run test:postgres` against `pgvector/pgvector:pg16` — 544 tests, 540 pass, 0 fail; `node scripts/drill-migration-rollback.mjs --url …` — Postgres apply → downgrade `009` → verify-compat → re-apply → checksum-fail-closed and the SQLite flow all pass, plus the `--self-test` URL-refusal check. The release workflow's `postgres-integration` job must be green on the release commit before publication. No registry write in this plan. Ledger: [0.8.0-cut.md](../_evidence/0.8.0-cut.md).
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Operator prerequisites (each a named blocked gate — none may be skipped):
|
|
19
|
+
# 1. protected live-canary matrix green (live-canaries.yml, canary-report.json retained)
|
|
20
|
+
# 2. PostgreSQL protected suite green (test:postgres) with this-tree scripts/postgres-evidence.json
|
|
21
|
+
# matching git rev-parse HEAD, and CodeQL SAST green on the release commit
|
|
22
|
+
# 3. npm OIDC trusted publishing identity authenticated (NPM_TOKEN with id-token, provenance)
|
|
23
|
+
# 4. branch protection: the compatibility leg is node22-compat
|
|
24
|
+
|
|
25
|
+
git diff --check
|
|
26
|
+
npm ci
|
|
27
|
+
# sdk:ready phases, as .github/workflows/release.yml runs them (env scoped to release:gate only):
|
|
28
|
+
npm run typecheck && npm run lint && npm run format:check
|
|
29
|
+
npm test && npm run test:coverage && npm run pack:dry-run
|
|
30
|
+
PRISM_TEST_POSTGRES_URL=... npm run test:postgres
|
|
31
|
+
PRISM_TEST_POSTGRES_URL=... npm run release:gate
|
|
32
|
+
npm run security:threat-suites
|
|
33
|
+
|
|
34
|
+
# Sign the release on the clean tagged tree (operator GPG key) — Task 8 / operator only:
|
|
35
|
+
# git tag -s v0.8.0 -m "0.8.0"
|
|
36
|
+
# node scripts/release.mjs publish --lockstep --version 0.8.0
|
|
37
|
+
|
|
38
|
+
# First-party package tags: push in batches of <=3 per push (tag-push storms; VENT 26-08-29).
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Rollback pins the previous published line — `@arnilo/prism@0.7.0` and its siblings, exact pins per package. Session/checkpoint schema is unchanged; channel journals and `@arnilo/prism-work` stores are new 0.8.0 surfaces a 0.7.0 host never opened.
|
|
42
|
+
|
|
43
|
+
### 0.7.0 publish handoff (plan 073 Tasks 28–29)
|
|
44
|
+
|
|
45
|
+
**Decision: GO when the operator prerequisites below are recorded.** Release **0.7.0** is the **six-plan cut** that closed the extended line: [072](../evaluations.md) (execution timeline, workflow graph, trajectory/outcome evals, cockpit aggregations, workflow OTel), [073](../index.md) (host completeness: traps A–C, R01–R06, R08, R10–R14, Tasks 15/30/31 and the cut itself), [074](../attention-compiler.md) (R17 attention compiler and the host-programmable compaction trigger), [075](../memory-fabric.md) (Memory Fabric subpath), [077](../compaction-observational-memory.md) (R16 work-scope memory index) and [078](../supervisors.md) (host-owned subagent spawn, bounded async spawn/wait/cancel, worktree isolation). **Plan 079 (Telegram/Signal channels) was moved to 0.8.0 on 2026-09-15** so the cut stopped waiting on unstarted work; no channel adapter ships in 0.7.0.
|
|
46
|
+
|
|
47
|
+
The graph is **10 publishable manifests** at exact **0.7.0** with internal caret ranges `^0.7.0`: root `@arnilo/prism` plus 9 workspace packages (3 `prism-*` family packages, 6 capability packages, 19 provider adapter subpaths inside the providers family). The predecessor published release is **0.6.0**.
|
|
48
|
+
|
|
49
|
+
Host-visible delta (full detail in [migrate-to-0.7.md](../migrate-to-0.7.md)): two **hard refusals** inside existing surfaces — `@arnilo/prism-acp-agent` matches `mcp.allow` by WHATWG origin plus path-segment subtree (lookalike hosts, sibling prefixes, credentials, and ambiguous encodings now fail closed) and no longer silently falls back to a mock provider; `router.providerSource(model)` throws `ERR_PRISM_MODEL_ROUTER_ASYNC_REQUIRED` / `_ASYNC_STATE` instead of bypassing budgets, rate limits, circuits, fallbacks, selection policies, or durable state. Everything else is additive: opt-in attention compiler, `@arnilo/prism-memory/fabric`, the observational-memory work-scope index, supervisor `spawn_agent`/`wait_agent`/`cancel_agent`, plus behavioral tightenings inside R01–R14 surfaces. **No export was removed**: the compat baselines were regenerated and reviewed as **+469 public declarations, zero removals**.
|
|
50
|
+
|
|
51
|
+
Evidence recorded for the tree under publication. `scripts/release-evidence.json` — **42 surfaces, 11 pass, 31 protected with reasons, `blocked: false`** (`test:postgres durable conformance` is a real pass; the only unavailable leg is the real-phase26 coding journey). `npm test` 5/5 stages; `npm run typecheck` green for root, all workspaces, and `examples/`; coverage core 92.43 lines against the 60/70/75 gate with every non-protected workspace above its recorded lines threshold (acp-agent recovered to 94.72 by exporting and testing its provider resolver); `npm run pack:dry-run` green for all ten packages; `npm run release:check --lockstep --version 0.7.0` reports **10/10 packages available**; `npm run release:publish --dry-run` produces all ten packs deterministically; `npm run security:threat-suites` **83/83**; `npm audit --audit-level=moderate` **0**; tracked+untracked secret scan **2328 files, 0 findings**; SBOM regenerated (172 packages) and `scripts/verify-sbom.mjs` clean against `security/license-policy.json`.
|
|
52
|
+
|
|
53
|
+
Protected legs actually run here (not just recorded): `PRISM_TEST_POSTGRES_URL=… npm run test:postgres` against `pgvector/pgvector:pg16` — core **72/72**, memory **457/457**, phase conformance **11/11**; `node scripts/drill-migration-rollback.mjs --url …` — Postgres apply → downgrade `009` → verify-compat → re-apply → checksum-fail-closed and the SQLite flow all pass, plus the `--self-test` URL-refusal check. That leg found and closed three real defects hermetic doubles could not see: a `42P08` parameter-type ambiguity on the first task-scoped budget insert, a swallowed serialization failure that issued SQL against an aborted transaction (`25P02`), and a retry policy too small for 16 concurrent serializable writers. The release workflow's `postgres-integration` job must be green on the release commit before publication.
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Operator prerequisites (each a named blocked gate — none may be skipped):
|
|
57
|
+
# 1. protected live-canary matrix green (live-canaries.yml, canary-report.json retained)
|
|
58
|
+
# 2. PostgreSQL protected suite green (test:postgres) and CodeQL SAST green on the release commit
|
|
59
|
+
# 3. npm OIDC trusted publishing identity authenticated (NPM_TOKEN with id-token, provenance)
|
|
60
|
+
# 4. branch protection: the compatibility leg is node22-compat
|
|
61
|
+
|
|
62
|
+
git diff --check
|
|
63
|
+
npm ci
|
|
64
|
+
# sdk:ready phases, as .github/workflows/release.yml runs them (env scoped to release:gate only):
|
|
65
|
+
npm run typecheck && npm run lint && npm run format:check
|
|
66
|
+
npm test && npm run test:coverage && npm run pack:dry-run
|
|
67
|
+
PRISM_TEST_POSTGRES_URL=... npm run release:gate
|
|
68
|
+
npm run security:threat-suites
|
|
69
|
+
|
|
70
|
+
# Sign the release on the clean tagged tree (operator GPG key):
|
|
71
|
+
git tag -s v0.7.0 -m "0.7.0"
|
|
72
|
+
node scripts/release.mjs publish --lockstep --version 0.7.0
|
|
73
|
+
|
|
74
|
+
# First-party package tags: push in batches of <=3 per push (tag-push storms; VENT 26-08-29).
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Rollback pins the previous published line — `@arnilo/prism@0.6.0` and its siblings, exact pins per package. Persisted shapes are additive across 0.6.0 → 0.7.0 (fabric notes, scope entries, and spawn handles write new records through existing stores; migrations `001`–`006` are forward-only), so a pin rollback is store-safe: a 0.6.0 host ignores entries it cannot read and regains the pre-0.7.0 ACP prefix matching and router facade bypass, which is why those two refusals should be re-checked before rolling back.
|
|
78
|
+
|
|
5
79
|
### 0.6.0 publish handoff (plan 071 Task 16)
|
|
6
80
|
|
|
7
81
|
|
|
@@ -271,7 +345,7 @@ node scripts/release.mjs publish --independent --baseline c600eaa18f65b56764ec2f
|
|
|
271
345
|
### 0.3.2 changed-package cut (plan 050 Task 12)
|
|
272
346
|
|
|
273
347
|
|
|
274
|
-
**Decision: GO when the operator prerequisites below are recorded.** The plan 050 cut covers the
|
|
348
|
+
**Decision: GO when the operator prerequisites below are recorded.** The plan 050 cut covers the integration-findings remediation and the OKF wiki adoption: baseline `edb4fcf` (the parent of the plan 050 implementation work); five packages publish in dependency order — root `@arnilo/prism` (FEATURE-1 agent-definition model override fallback, FEATURE-3 command driver hooks, FEATURE-2/6 docs+example, DOCS-1 contracts), `@arnilo/prism-coding-agent` (BUG-1 `allowCustom` default + optional `toolCallId`), `@arnilo/prism-supervisor` (BUG-2 child-factory `Agent` guard, FEATURE-4 opt-in child event passthrough), `@arnilo/prism-wiki` (OKF v0.2 bundle emission, 0.0.2 → 0.0.3), and `@arnilo/prism-acp-agent` (sqlite `:memory:` pass-through fix, 0.0.x-style patch 0.3.1 → 0.3.2). Every unchanged package stays byte-identical; docs-only packages (`@arnilo/prism-workflows`, `@arnilo/prism-compaction-observational-memory`) do not bump. Republished packages carry `^0.3.2` root peers; unchanged packages keep their window peers. Docs-only change on the root: none of the deltas are breaking (additive fields and fail-closed guards), compat additive-only, no migration.
|
|
275
349
|
|
|
276
350
|
```bash
|
|
277
351
|
node scripts/release.mjs changed --baseline edb4fcf # 5 packages
|