@arnilo/prism 0.2.9 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (77) hide show
  1. package/CHANGELOG.md +39 -0
  2. package/README.md +12 -5
  3. package/dist/agent-loops.js +45 -8
  4. package/dist/agent-session/helpers.js +2 -2
  5. package/dist/cache-helpers.d.ts +11 -0
  6. package/dist/cache-helpers.js +29 -5
  7. package/dist/cli-provider-add.js +2 -1
  8. package/dist/context-budget.js +9 -6
  9. package/dist/contracts-core/agent.d.ts +2 -0
  10. package/dist/contracts-core/provider.d.ts +2 -0
  11. package/dist/contracts-protocol.d.ts +31 -1
  12. package/dist/delegated-agent-step.d.ts +20 -0
  13. package/dist/delegated-agent-step.js +99 -0
  14. package/dist/event-multiplexer.js +0 -4
  15. package/dist/index.d.ts +6 -2
  16. package/dist/index.js +5 -2
  17. package/dist/input.js +19 -11
  18. package/dist/node/session-store-jsonl.js +7 -3
  19. package/dist/providers/openai-compatible.js +2 -1
  20. package/dist/providers/openai-primitives.js +2 -1
  21. package/dist/providers/schema.d.ts +7 -0
  22. package/dist/providers/schema.js +25 -0
  23. package/dist/testing/provider-conformance.d.ts +10 -0
  24. package/dist/testing/provider-conformance.js +37 -0
  25. package/dist/trim-trailing-slashes.d.ts +8 -0
  26. package/dist/trim-trailing-slashes.js +14 -0
  27. package/docs/0.1.0-readiness.md +8 -8
  28. package/docs/acp.md +5 -3
  29. package/docs/ag-ui.md +6 -2
  30. package/docs/agent-events.md +8 -1
  31. package/docs/agent-loops.md +3 -0
  32. package/docs/agent-session-runtime.md +1 -0
  33. package/docs/antigravity-agent.md +207 -0
  34. package/docs/browser-automation.md +1 -0
  35. package/docs/coding-agent-tools.md +32 -4
  36. package/docs/computer-use-linux.md +122 -0
  37. package/docs/database-persistence.md +1 -1
  38. package/docs/device-adapters.md +4 -3
  39. package/docs/graft.md +125 -0
  40. package/docs/host-security.md +3 -1
  41. package/docs/index.md +21 -10
  42. package/docs/input-and-prompt-assembly.md +11 -6
  43. package/docs/instruction-injection.md +1 -1
  44. package/docs/mcp-tools.md +2 -1
  45. package/docs/migration.md +25 -2
  46. package/docs/node-jsonl-session-store.md +1 -1
  47. package/docs/obscura.md +175 -0
  48. package/docs/observability.md +21 -1
  49. package/docs/performance.md +58 -4
  50. package/docs/ponytail.md +1 -1
  51. package/docs/provider-caching.md +13 -11
  52. package/docs/provider-conformance.md +6 -0
  53. package/docs/provider-packages.md +1 -1
  54. package/docs/provider-primitives.md +15 -2
  55. package/docs/providers/ai-sdk.md +1 -1
  56. package/docs/providers/anthropic.md +1 -1
  57. package/docs/providers/azure.md +1 -0
  58. package/docs/providers/bedrock.md +1 -0
  59. package/docs/providers/kimi.md +2 -1
  60. package/docs/providers/openai.md +19 -7
  61. package/docs/providers/opencode-go.md +3 -1
  62. package/docs/providers/openrouter.md +4 -3
  63. package/docs/providers/vertex.md +1 -0
  64. package/docs/public-contracts.md +2 -1
  65. package/docs/rag.md +55 -8
  66. package/docs/release-and-install.md +105 -25
  67. package/docs/server.md +1 -0
  68. package/docs/supervisors.md +3 -2
  69. package/docs/system-prompts.md +1 -1
  70. package/docs/tools.md +1 -1
  71. package/docs/web-tools.md +2 -0
  72. package/docs/wiki.md +140 -0
  73. package/docs/workflows.md +4 -3
  74. package/docs/working-and-semantic-memory.md +20 -0
  75. package/package.json +14 -5
  76. package/docs/api-page-template.md +0 -32
  77. package/docs/release-0.2.7-evidence.md +0 -514
@@ -2,11 +2,11 @@
2
2
 
3
3
  ## What it does
4
4
 
5
- Prism is published as **55 publishable manifests**: the root `@arnilo/prism` core package plus **54 workspace packages** — 17 provider adapters, 10 `prism-*` family/profile packages, and 27 capability packages. (Generated by `node scripts/package-truth.mjs` → `scripts/package-truth.json` — the manifest-derived single source for counts, provider membership, umbrella closures, and profile closures.) The 0.2.9 plan 029 cut adds DeepSeek, xAI, ClinePass, and `@arnilo/prism-impeccable` on the 0.2.8 51-package graph. This page describes how they are packed, what each tarball contains, how to install them, the required `@arnilo/prism` peer dependency, the release workflow, and the offline test budget. The measurable 1.0 readiness gates (command-per-gate) live in [`0.1.0-readiness.md`](./0.1.0-readiness.md).
5
+ Prism's current **0.3.1** line has **60 publishable manifests**: the root `@arnilo/prism` core package plus **59 workspace packages** — 17 provider adapters, 10 `prism-*` family/profile packages, and 32 capability packages. (Generated by `node scripts/package-truth.mjs` → `scripts/package-truth.json` — the manifest-derived single source for counts, provider membership, umbrella closures, and profile closures.) The last lockstep cut was 0.3.0; Decision B now publishes changed packages independently inside `^0.3.0` — the plan 039 changed-package cut moved root `@arnilo/prism` and every plan-035+ changed package to **0.3.1** (obscura joined at its reviewed initial 0.3.0), and independent publication continues inside `^0.3.0` ranges (which satisfy 0.3.1). This page describes how they are packed, what each tarball contains, how to install them, the required `@arnilo/prism` peer range, the release workflow, and the offline test budget. The measurable 1.0 readiness gates (command-per-gate) live in [`0.1.0-readiness.md`](./0.1.0-readiness.md).
6
6
 
7
- Core `@arnilo/prism` ships runtime, CLI, templates, and docs. Every code package has a required `@arnilo/prism@0.2.9` peer; profiles are pure manifests. Installation activates no provider, listener, database, browser, credential, or tool capability.
7
+ Core `@arnilo/prism` ships runtime, CLI, templates, and docs. Every code package has a required `@arnilo/prism` peer inside the Decision B window — packages republishing in the plan 039 cut carry `^0.3.1`; unchanged packages keep their `^0.3.0` peer (both satisfy `@arnilo/prism@0.3.1`); profiles are pure manifests. The plan 039 republished set declares the required `@arnilo/prism@^0.3.1` peer; unchanged packages keep `^0.3.0`. Installation activates no provider, listener, database, browser, credential, or tool capability.
8
8
 
9
- Current **55** publishable manifests (root + 54 workspace packages):
9
+ Current **58** publishable manifests (root + 57 workspace packages):
10
10
 
11
11
  `@arnilo/prism`, `@arnilo/prism-ag-ui`, `@arnilo/prism-browser`, `@arnilo/prism-coding-agent`, `@arnilo/prism-coding-security`, `@arnilo/prism-compaction-llm`
12
12
  `@arnilo/prism-compaction-observational-memory`, `@arnilo/prism-credentials-node`, `@arnilo/prism-enterprise-postgres`, `@arnilo/prism-evals`, `@arnilo/prism-mcp`, `@arnilo/prism-memory`
@@ -15,7 +15,7 @@ Current **55** publishable manifests (root + 54 workspace packages):
15
15
  `@arnilo/prism-provider-alibaba`, `@arnilo/prism-provider-anthropic`, `@arnilo/prism-provider-azure`, `@arnilo/prism-provider-bedrock`, `@arnilo/prism-provider-google`, `@arnilo/prism-provider-kimi`
16
16
  `@arnilo/prism-provider-neuralwatt`, `@arnilo/prism-provider-ollama`, `@arnilo/prism-provider-openai`, `@arnilo/prism-provider-opencode-go`, `@arnilo/prism-provider-openrouter`, `@arnilo/prism-provider-vertex`
17
17
  `@arnilo/prism-provider-clinepass`, `@arnilo/prism-provider-deepseek`, `@arnilo/prism-provider-xai`, `@arnilo/prism-provider-zai`, `@arnilo/prism-rag`, `@arnilo/prism-server`, `@arnilo/prism-session-store-codecs`, `@arnilo/prism-session-store-nats`, `@arnilo/prism-session-store-postgres`, `@arnilo/prism-session-store-sqlite`
18
- `@arnilo/prism-openapi-tools`, `@arnilo/prism-supervisor`, `@arnilo/prism-tool-validator-json-schema`, `@arnilo/prism-web-tools`, `@arnilo/prism-work-tools`, `@arnilo/prism-workflows`, `@arnilo/prism-document-reader`
18
+ `@arnilo/prism-openapi-tools`, `@arnilo/prism-supervisor`, `@arnilo/prism-tool-validator-json-schema`, `@arnilo/prism-web-tools`, `@arnilo/prism-wiki`, `@arnilo/prism-work-tools`, `@arnilo/prism-workflows`, `@arnilo/prism-document-reader`, `@arnilo/prism-computer-use-linux`, `@arnilo/prism-antigravity-agent`, `@arnilo/prism-graft`, `@arnilo/prism-obscura`
19
19
 
20
20
  Core ships `dist`, docs, templates, and `CHANGELOG.md`; code packages ship compiled output, README, license, and changelog. Family/profile packages ship manifest, README, and changelog. `@arnilo/prism-providers` includes all fourteen `@arnilo/prism-provider-*` packages in its family (Azure/Bedrock/Vertex stay on `@arnilo/prism-all`).
21
21
 
@@ -41,21 +41,20 @@ Consumers install the core package for the runtime and add first-party packages
41
41
  | 0.0.12 AG-UI (after release) | `npm install @arnilo/prism@0.0.12 @arnilo/prism-ag-ui@0.0.12` |
42
42
  | Install bounded web research tools | `npm install @arnilo/prism @arnilo/prism-web-tools @arnilo/prism-tool-validator-json-schema` |
43
43
  | Install browser automation tools | `npm install @arnilo/prism @arnilo/prism-browser playwright-core@1.61.0` |
44
+ | Install Obscura browser-engine tools (host supplies the binary) | `npm install @arnilo/prism @arnilo/prism-obscura` |
44
45
  | Build everything (core + workspaces) | `npm run build` |
45
46
  | Delete all build output (explicit one-shot, see build notes) | `npm run clean` |
46
47
  | Run the default (network-free) test suite | `npm test` |
47
48
  | Dry-run pack core + every package | `npm run pack:dry-run` |
48
49
  | Local mirror of the release verify gate | `npm run release:dry-run` |
49
- | Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.1.0` |
50
- | Preview deterministic publish order | `npm run release:publish -- --version 0.1.0 --dry-run --allow-dirty --allow-untagged` |
51
- | Resume interrupted tagged publication | `npm run release:publish -- --version 0.1.0 --resume --report release-artifacts/publish-report.json` |
50
+ | Validate independent versions/ranges and reject registry collisions | `npm run release:check -- --allow-dirty --allow-untagged` |
51
+ | Preview deterministic changed-package publication | `npm run release:publish -- --dry-run --allow-dirty --allow-untagged` |
52
+ | Resume interrupted package-tag publication | `npm run release:publish -- --resume --report release-artifacts/publish-report.json` |
52
53
  | Protected PostgreSQL enterprise suite | `PRISM_TEST_POSTGRES_URL="$DATABASE_URL" npm run test:postgres` |
53
54
  | Full SDK readiness gate (typecheck + offline tests + pack) | `npm run sdk:ready` |
54
55
  | Non-blocking unused-code sweep (report to `scripts/unused-sweep-report.txt`, always exits 0) | `npm run sweep:unused` |
55
56
 
56
- > **Build notes (0.1.1+).** `npm run build` no longer runs `npm run clean` first: concurrent builds/tests (`npm test`, `npm run typecheck`) are now race-free because the only destructive step was the `rm -rf` clean, and concurrent `tsc` is write-only and idempotent on identical input (two processes emitting the same files end byte-identical regardless of interleaving).
57
- >
58
- > `ponytail:` concurrent `tsc` is idempotent on identical input, so no single-flight lock is needed; orphaned `dist/` files from deleted sources fail loudly on the next `node --test` (broken imports) and are filtered from tarballs by the `files` allowlists; run `npm run clean` after source deletions or branch switches; `tsc --build` (0.2.0 Module F) auto-cleans orphans.
57
+ > **Build notes (0.2.3+).** `npm run build` no longer runs `npm run clean` first. Emit-producing and dist-consuming leaves are serialized by `scripts/with-build-lock.mjs`, so concurrent builds/tests cannot expose partial `dist/`; run `npm run clean` after source deletions or branch switches for orphan cleanup. Direct `tsc` outside the wrapper remains an external-writer caveat.
59
58
 
60
59
  Run `npm run clean` explicitly after deleting source files or switching branches: a deleted `src/__tests__/*.test.ts` leaves an orphan `dist/__tests__/*.test.js` (tsc never auto-cleans). If the orphan's import chain still resolves it keeps running as a stale test — silent staleness, which is exactly what the explicit clean prevents — and if the chain is broken the next `node --test dist/__tests__/*.test.js` fails loudly (`ERR_MODULE_NOT_FOUND`), never silently swallowed. A fresh `npm run clean && npm run build` and the new `npm run build` from a clean state produce byte-identical `dist/` (tsc overwrites per-file outputs).
61
60
 
@@ -65,6 +64,7 @@ Run `npm run clean` explicitly after deleting source files or switching branches
65
64
  | `@arnilo/prism/providers/openai-compatible` | `dist/providers/openai-compatible.{js,d.ts}` |
66
65
  | `@arnilo/prism/providers/transport` | `dist/providers/transport.{js,d.ts}` |
67
66
  | `@arnilo/prism/providers/openai` | `dist/providers/openai-primitives.{js,d.ts}` |
67
+ | `@arnilo/prism/providers/schema` | `dist/providers/schema.{js,d.ts}` |
68
68
  | `@arnilo/prism/providers/media` | `dist/providers/media.{js,d.ts}` |
69
69
  | `@arnilo/prism/testing/provider-conformance` | `dist/testing/provider-conformance.{js,d.ts}` |
70
70
  | `@arnilo/prism/testing/agent-event-source-conformance` | `dist/testing/agent-event-source-conformance.{js,d.ts}` |
@@ -94,7 +94,7 @@ A packed tarball contains only public compiled output and release files:
94
94
  - Code packages ship `README.md`, `LICENSE`, and `CHANGELOG.md`; family/profile packages ship `README.md` and `CHANGELOG.md`.
95
95
  - The core tarball additionally ships the full `docs/` directory (the docs hub) and `templates/init/` used by `prism init`.
96
96
  - `dist/cli.js` and the `bin` link in core.
97
- - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.2.9.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.2.9.tgz` / `arnilo-prism-compaction-<name>-0.2.9.tgz` / `arnilo-prism-coding-agent-0.2.9.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.2.9.tgz`. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
97
+ - **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.3.1.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.3.1.tgz` / `arnilo-prism-compaction-<name>-0.3.1.tgz` / `arnilo-prism-coding-agent-0.3.1.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.3.1.tgz`; independent Decision B tags (e.g. `@arnilo/prism-obscura@0.3.0`, the 0.3.1 RAG engine patch) carry their own package version. Later independent package tags carry their own package version. The CLI bin name `prism` is unaffected by the package name (`npx prism` still works; npm allows the bin field to differ from the package name).
98
98
 
99
99
  Excluded from every tarball by `files` negation:
100
100
 
@@ -113,9 +113,9 @@ Excluded from every tarball by `files` negation:
113
113
  "name": "host-app",
114
114
  "type": "module",
115
115
  "dependencies": {
116
- "@arnilo/prism": "0.1.0",
117
- "@arnilo/prism-enterprise-postgres": "0.1.0",
118
- "@arnilo/prism-provider-openai": "0.1.0"
116
+ "@arnilo/prism": "^0.3.0",
117
+ "@arnilo/prism-enterprise-postgres": "^0.3.0",
118
+ "@arnilo/prism-provider-openai": "^0.3.0"
119
119
  }
120
120
  }
121
121
  ```
@@ -125,7 +125,7 @@ Installing the provider/compaction packages without `@arnilo/prism` present prod
125
125
  ```text
126
126
  npm error code ERESOLVE
127
127
  npm error Could not resolve dependency:
128
- npm error peer @arnilo/prism@"0.0.17" from @arnilo/prism-provider-openai@0.0.17
128
+ npm error peer @arnilo/prism@"^0.3.0" from @arnilo/prism-provider-openai@0.3.0
129
129
  ```
130
130
 
131
131
  ## Implementation example
@@ -158,11 +158,11 @@ For SDK readiness, run the same one-command gate directly. It composes existing
158
158
  npm run sdk:ready
159
159
  ```
160
160
 
161
- Release publication derives all **49** manifests from the workspace once, validates exact `0.1.0` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.1.0` and rejects any existing registry version. `release:publish --resume` skips only registry versions whose internal dependency fingerprint matches the local manifest; conflicting versions fail closed. Each attempted package is written immediately to the JSON report, so a failed job can rerun safely. `--dry-run` performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag, but does not publish.
161
+ Release publication derives the workspace graph from manifests. The final `v0.3.0` cut validates the 56-package lockstep graph; later `release:check` and `release:publish` default to independent changed-package validation/publication under package tags. Resume skips only registry versions whose internal dependency fingerprint matches the local manifest; conflicting versions fail closed. Each attempted package is written immediately to the JSON report, so a failed job can rerun safely. `--dry-run` performs registry availability checks and invokes `npm publish --dry-run` with explicit public access, provenance, and `latest` tag, but does not publish.
162
162
 
163
163
  ```bash
164
- npm run release:check -- --version 0.1.0
165
- npm run release:publish -- --version 0.1.0 --dry-run --allow-dirty --allow-untagged
164
+ npm run release:check -- --allow-dirty --allow-untagged
165
+ npm run release:publish -- --dry-run --allow-dirty --allow-untagged
166
166
  ```
167
167
 
168
168
  `--allow-dirty` and `--allow-untagged` exist only for local preview; real publication and CI never pass them. npm registry calls occur only in these release preflight/publication commands, never build/test/package discovery.
@@ -175,7 +175,7 @@ PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
175
175
 
176
176
  ### GitHub Actions pipeline (0.0.27+)
177
177
 
178
- `.github/workflows/release.yml` is the single pipeline: **push to `main`** runs CI (`verify` = `npm run sdk:ready`, `node20-compat`, `postgres-integration`, `supply-chain`), **push of a `v*` tag** additionally runs `codeql-release` and the `publish` job (deterministic `release:publish` in dependency order with provenance attestation). `security.yml` adds CodeQL/dependency-review/SBOM on push and PR; `live-canaries.yml` and `sandbox-browser.yml` are scheduled. All actions are SHA-pinned (2026-08-06 fix: CodeQL pins were invalid 404 refs and `workflow_dispatch` was missing — re-verified every pin against its upstream repo). Prerequisites outside the repo: Actions enabled in repository settings, and the `NPM_TOKEN` secret (with `id-token: write` for provenance). To re-cut a tag after a fix commit, delete and recreate it (`git push origin :v0.0.28 && git push origin v0.0.28`) so the tag creation event fires.
178
+ `.github/workflows/release.yml` is the single pipeline: **push to `main`** runs CI (`verify` = `npm run sdk:ready`, `node20-compat`, `postgres-integration`, `supply-chain`), **`v0.3.0` or `@arnilo/*@*` package tags** additionally run `codeql-release` and the `publish` job (deterministic `release:publish` in dependency order with provenance attestation). `security.yml` adds CodeQL/dependency-review/SBOM on push and PR; `live-canaries.yml` and `sandbox-browser.yml` are scheduled. All actions are SHA-pinned (2026-08-06 fix: CodeQL pins were invalid 404 refs and `workflow_dispatch` was missing — re-verified every pin against its upstream repo). Prerequisites outside the repo: Actions enabled in repository settings, and the `NPM_TOKEN` secret (with `id-token: write` for provenance). To re-cut a tag after a fix commit, delete and recreate it (`git push origin :v0.0.28 && git push origin v0.0.28`) so the tag creation event fires.
179
179
 
180
180
  ### 0.1.0 publish handoff (plan 012 Task 7)
181
181
 
@@ -348,6 +348,60 @@ npm run release:publish -- --version 0.2.6 --dry-run --allow-dirty --allow-untag
348
348
 
349
349
  Protected evidence (never a passing skip): the durable recovery/workspace conformance legs (real Postgres two-replica split-brain fence, cross-replica cancellation, terminal-before-recovery), the protected PTY leg (real PTY host adapter), the protected real coding journey (`scripts/phase26-coding-journey-report.json` — pass/blocked/protected, never a passing skip; runs in `.github/workflows/coding-journey.yml` with real provider/Docker/Playwright/GitHub/Postgres/PTY services), and the live canaries (provider OIDC/OPA, MCP, A2A, Brave — always `protected` rows in the manifest, never `pass`). The release skip manifest names every skip class with its required env; missing protected evidence records 0.2.6 as **blocked**, never a passing skip.
350
350
 
351
+ ### 0.3.0 lockstep cut and independent publication (plan 030 Task 9)
352
+
353
+ **Decision: GO when the operator prerequisites below are recorded.** Release **0.3.0** is the last lockstep cut: all **56** publishable manifests are `0.3.0`, and every internal `@arnilo/*` dependency, optional dependency, and peer dependency uses `^0.3.0`. This cut adds the optional host-owned `@arnilo/prism-computer-use-linux` wrapper, `read.findText`, loud edit fuzzy matches/miss context, and ACP editor-buffer wiring; the desktop package stays outside umbrella profiles. Peer policy is now **Decision B**: packages may move independently inside the 0.x caret window (`>=0.3.0 <0.4.0`).
354
+
355
+ After the signed `v0.3.0` cut, publication is package-tag driven: `@arnilo/<package>@<version>` publishes only changed packages at that version. The lockstep core artifact is `arnilo-prism-0.3.0.tgz`; later package artifacts carry their own name and version. A generic `v*` tag is not a publication trigger after this cut. The one emergency lockstep path remains explicit: `--lockstep --version 0.3.0`.
356
+
357
+ ```bash
358
+ # one manifest bump + one lockfile regeneration for the final cut
359
+ node scripts/release.mjs bump --from 0.2.9 --to 0.3.0 --ranges caret
360
+ node scripts/package-truth.mjs
361
+ node scripts/release.mjs check --lockstep --version 0.3.0 --allow-dirty --allow-untagged
362
+ # later checks default to independent mode
363
+ npm run release:check -- --allow-dirty --allow-untagged
364
+ ```
365
+
366
+ For a later coding-agent-only patch, bump its manifest with `bump --package @arnilo/prism-coding-agent --type patch`, regenerate the lockfile, commit, and push `@arnilo/prism-coding-agent@0.3.1`. The default independent check validates the mixed graph; the package tag publishes only that package in dependency order. Resume skips only a matching already-published manifest and refuses a same-version registry collision with different internal release fields.
367
+
368
+ **Rollback notes.** Before publication, restore the 0.2.9 manifests/tag. After publication, roll forward with an additive 0.3.x package patch; npm unpublish is not a rollback strategy.
369
+
370
+ ### 0.3.1 independent RAG engine patch (plan 034 Task 12)
371
+
372
+ **Decision: GO when the operator prerequisites below are recorded.** Release **0.3.1** is the first Decision B independent patch: only `@arnilo/prism-memory`, `@arnilo/prism-rag`, and `@arnilo/prism-observability-opentelemetry` move `0.3.0 → 0.3.1`. Internal `^0.3.0` ranges stay. Root current line remains **0.3.0**.
373
+
374
+ ```bash
375
+ node scripts/release.mjs bump --package @arnilo/prism-memory --type patch
376
+ node scripts/release.mjs bump --package @arnilo/prism-rag --type patch
377
+ node scripts/release.mjs bump --package @arnilo/prism-observability-opentelemetry --type patch
378
+ node scripts/release.mjs gate --update-baseline --skip-tarball # review Embedder.id; scanner is additive-only
379
+ node scripts/release.mjs check --allow-dirty --allow-untagged
380
+ # publish tags (operator handoff; not this task):
381
+ # git tag @arnilo/prism-memory@0.3.1 && git tag @arnilo/prism-rag@0.3.1
382
+ # git tag @arnilo/prism-observability-opentelemetry@0.3.1 && git push --tags
383
+ ```
384
+
385
+ **Compat.** Baselines regenerated with `--update-baseline`. Expected deltas are additive exports (`createPostgresVectorStore`, `createTeiReranker`, `createRagTelemetry`, multi-scope `scopes`, `HARD_RETRIEVE_SCOPE_CAP`, fusion/hash/generation helpers). `Embedder.id` is a TypeScript implementer break documented in `docs/migration.md` `0.3.0 → 0.3.1`; the name-level scanner does not see interface members, so `--allow-break` is not required. `RagProvenance` gained `tenantId`/`resourceId`/`corpusId` (additive interface members, invisible to scanner). **Store:** additive Postgres DDL; 0.3.0 rows remain readable. **Rollback:** restore the 0.3.0 package versions. Publication remains the operator handoff — this task does not publish.
386
+
387
+ ### 0.3.1 changed-package cut (plan 039 Task 8)
388
+
389
+ **Decision: GO when the operator prerequisites below are recorded.** The plan 039 cut is the first Decision B **root** patch: the baseline is the plan 035 completion parent `c600eaa`; 30 packages publish in dependency order — root `@arnilo/prism` plus 27 changed workspace packages move to **0.3.1** (`@arnilo/prism-rag` moves 0.3.1 → 0.3.2), and `@arnilo/prism-obscura` publishes new at its reviewed initial **0.3.0**. Every unchanged package stays byte-identical (peers keep the `^0.3.0` window; republished packages carry `^0.3.1` root peers — both satisfy the root). Additive-only compat (version literal + plan 036/037 additive exports + the obscura CDP/browser surface; baselines regenerated with `--update-baseline`, no `--allow-break`, no migration).
390
+
391
+ ```bash
392
+ node scripts/release.mjs changed --baseline c600eaa18f65b56764ec2fb408ec813536eff6f7 # 30 packages
393
+ # per-package: node scripts/release.mjs bump --package <name> --type patch (applied by plan 039 task 8)
394
+ node scripts/release.mjs gate --update-baseline --skip-tarball
395
+ node scripts/release.mjs check --independent --baseline c600eaa18f65b56764ec2fb408ec813536eff6f7
396
+ node scripts/release.mjs publish --independent --baseline c600eaa18f65b56764ec2fb408ec813536eff6f7 --dry-run
397
+ # publish tags (operator handoff; not this task): push the 30 annotated
398
+ # `<name>@<version>` package tags (e.g. @arnilo/prism@0.3.1,
399
+ # @arnilo/prism-obscura@0.3.0, @arnilo/prism-rag@0.3.2) — release.yml's publish
400
+ # job runs deterministic release:publish in dependency order with OIDC provenance.
401
+ ```
402
+
403
+ **Compat.** Baselines regenerated (`--update-baseline`): version literal, obscura `connectObscuraCdp`/`createObscuraWebTools` types, plan 036/037 additive exports. **Rollback:** restore the pre-cut manifests/tags. Publication remains the operator handoff — this task does not publish.
404
+
351
405
  ### 0.2.9 publish handoff (plan 029 Task 10)
352
406
 
353
407
  **Decision: GO when the operator prerequisites below are recorded.** Release **0.2.9** (plan 029) is the provider-adoption and behavior-packages cut on the 0.2.x review-remediation line. API surface **additive-only** (plain reviewed compat gate at 0.2.9: expected deltas are the version literal plus the new provider/OAuth/impeccable exports and the form-urlencoded `pollDeviceCodeToken` options; zero removals; baselines regenerated with `--update-baseline`, no `--allow-break`). Ships `@arnilo/prism-provider-deepseek`, `@arnilo/prism-provider-xai` (API key + SuperGrok RFC 8628), `@arnilo/prism-provider-clinepass`, and `@arnilo/prism-impeccable`. Ponytail peer `^4.9.0` (bare `/ponytail` reports status). Caveman registers extra `SKILL.md`. SuperGrok is host-invoked; Cline WorkOS, DeepSeek `/anthropic`, grok-cli file scan, harness/Cordis/Muse, Caveman 2 engine, and Impeccable live detector stay out. Release graph is **55** publishable manifests at exact **0.2.9** (root + 54 workspace). Store compatibility with 0.2.8: **compatible, no migration**.
@@ -859,10 +913,11 @@ Audit fixes, dependency updates, and security patches land only for the supporte
859
913
 
860
914
  ## Extension and configuration notes
861
915
 
862
- - **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional **exact** `@arnilo/prism@0.2.9` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). **Peer-version policy (plan 024, Decision A — exact pins):** the peer spec is the bare exact current version — no `~`/`^`/`>=` range, no `*` — for the whole 0.2.x line, and all `@arnilo/prism-*` packages move at the same version (the **atomic-upgrade rule**). A partial upgrade (e.g. `@arnilo/prism@0.2.8` installed with a package peering `@arnilo/prism@0.2.9`) is unsupported and fails clearly at install time with `ERESOLVE unable to resolve dependency tree` naming the conflicting peer — never a silent install of a pair that was never tested together. A third-party `@arnilo/prism-*` adapter declares the same exact peer on the documented current version; an unsupported mixture fails at install time, not at runtime. The range widens to `^1.0.0` at the 1.x stable release (the 1.0 readiness gates go operator-green on the 0.2.x line); rollback of a release moves the pins back atomically with the manifests/tag. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
863
- - **Public access.** All 55 manifests (root + 54 workspace packages: 48 code packages + 6 pure-manifest family/profile packages — the 10 `prism-*` family/profile set is the 6 pure-manifest profiles plus the 4 code packages `prism-caveman`, `prism-impeccable`, `prism-openapi-tools`, `prism-ponytail`) declare `"publishConfig": { "access": "public" }`; the publisher also passes `--access public` explicitly because scoped packages otherwise default to restricted on first publish.
916
+ - **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional **caret** `@arnilo/prism@^0.3.1` peer (plan 039 republished set; unchanged packages keep the prior `^0.3.0` window peer — both satisfy the root) (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). **Peer-version policy (plan 030, Decision B — independent packages):** internal ranges stay inside the 0.x `^0.3.0` window, so a package may patch independently while consumers remain on a compatible 0.3.x line. A package outside that window (for example `0.4.0`) is refused by the release gate until the next coordinated peer bump. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
917
+ - **Public access.** All 56 manifests (root + 55 workspace packages: 49 code packages + 6 pure-manifest family/profile packages — the 10 `prism-*` family/profile set is the 6 pure-manifest profiles plus the 4 code packages `prism-caveman`, `prism-impeccable`, `prism-openapi-tools`, `prism-ponytail`) declare `"publishConfig": { "access": "public" }`; the publisher also passes `--access public` explicitly because scoped packages otherwise default to restricted on first publish.
918
+ - **Shipped vs repository docs.** The npm tarball ships `docs/` pages linked from `docs/index.md` (public API, security, migration, providers, install). It excludes `docs/_evidence/` (per-phase evidence freezes, including `release-0.2.7-evidence.md`), `docs/release-*-evidence.md`, and `docs/api-page-template.md`. Those files remain in git for audit. `dist/__tests__` and `*.map` stay excluded.
864
919
  - **Map retention knob.** Source maps are emitted locally but stripped from tarballs by `!dist/**/*.map`. Removing that `files` negation ships maps in releases (larger tarballs, better consumer stack traces).
865
- - **Release workflow.** `.github/workflows/release.yml` has six jobs. `verify` runs network-free SDK readiness on Node 24; `node20-compat` builds/imports every public root `exports` default target on Node 20 for declared `engines.node >=20` (docs examples need Node >=22.6 native TypeScript stripping); `postgres-integration` uses `pgvector/pgvector:pg16`; `supply-chain` runs high-severity audit, SPDX/license policy, and tracked-source secret scanning; and tag-only `codeql-release` runs SAST. Tag-only `publish` needs all five gates, preserves clean exact-tag/version/topological publication, and alone receives `NPM_TOKEN`, `id-token: write`, and `attestations: write`. Before npm publish it packs all current tarballs, generates checksums plus SPDX, scans unpacked public artifacts, creates GitHub attestations for tarballs and SBOM, then retains artifacts for 30 days. Registry state remains the resumable journal. Local `npm run release:dry-run` remains network-free SDK readiness; local PostgreSQL coverage is `PRISM_TEST_POSTGRES_URL=... npm run test:postgres`.
920
+ - **Release workflow.** `.github/workflows/release.yml` has six jobs. `verify` runs network-free SDK readiness on Node 24; `node20-compat` builds/imports every public root `exports` default target on Node 20 for declared `engines.node >=20` (docs examples need Node >=22.6 native TypeScript stripping); `postgres-integration` uses `pgvector/pgvector:pg16`; `supply-chain` runs high-severity audit, SPDX/license policy, and tracked-source secret scanning; and tag-only `codeql-release` runs SAST. `publish` runs on `v0.3.0` for the one lockstep cut and on `@arnilo/*@*` package tags afterward; it needs all five gates, preserves clean tagged/version/topological publication, and alone receives `NPM_TOKEN`, `id-token: write`, and `attestations: write`. Before npm publish it packs all current tarballs, generates checksums plus SPDX, scans unpacked public artifacts, creates GitHub attestations for tarballs and SBOM, then retains artifacts for 30 days. Registry state remains the resumable journal. Local `npm run release:dry-run` remains network-free SDK readiness; local PostgreSQL coverage is `PRISM_TEST_POSTGRES_URL=... npm run test:postgres`.
866
921
  - **Adding a package.** New workspace packages are picked up automatically by `npm run build --workspaces`, `npm test --workspaces`, `npm run pack:dry-run`, the packaging guard (`src/__tests__/packaging.test.ts`), and the install-smoke test (`src/__tests__/install-smoke.test.ts`) via the workspace glob; add the package to both tests' config arrays for explicit per-package assertions.
867
922
 
868
923
  ## Security and performance notes
@@ -1034,7 +1089,7 @@ Every release gate maps to an exact enforcement test or command, so the checklis
1034
1089
  | Root SDK export surface freeze | `public-export-contract.test.ts` `root export surface is frozen` snapshots every value and type export of `src/index.ts` (107 value + 69 type) so any add/remove is a deliberate test update; `every frozen value export resolves at runtime` rebuilds `dist/index.js` and asserts each value export is present (catches build drift), and `every frozen type export appears in the built type declarations` asserts each type export is in `dist/index.d.ts`. |
1035
1090
  | Examples compile and are listed; runnable demos execute | `npm run typecheck` runs `tsc -p examples --noEmit`; `docs.test.ts` checks every `examples/*.ts` file is listed in `examples/README.md`, then runs demos offline and scans output for secrets. |
1036
1091
  | Examples run to completion with no secret leakage | `docs.test.ts` `examples_demos_run_to_completion_and_emit_no_secret` runs each demo (Node strips TypeScript types natively) with exit-0 and real-secret scans; `external_app_example_*` pins the DB-backed adapter reference exercising the `RunLedger`, branch-handle checkout, fork, and prior-run resume. |
1037
- | Tarball excludes built tests, source maps, and source | `packaging.test.ts` rejects `dist/__tests__/`, `*.map`, `src/`, `plans/`, and internal files; confirms every package ships README/changelog (and code packages ship LICENSE), core ships docs + CLI, and every export target exists. `prism-all` reaches 47 of the 54 workspace packages (21 direct + 26 transitive); the deliberate Caveman/Ponytail/Impeccable opt-outs and the other non-closure packages (document-reader, OpenAPI tools, NATS) are not in its install set. |
1092
+ | Tarball excludes built tests, source maps, and source | `packaging.test.ts` rejects `dist/__tests__/`, `*.map`, `src/`, `plans/`, and internal files; confirms every package ships README/changelog (and code packages ship LICENSE), core ships docs + CLI, and every export target exists. `prism-all` reaches 47 of the 59 workspace packages (21 direct + 26 transitive); the deliberate Caveman/Ponytail/Impeccable/computer-use-linux/antigravity-agent/Graft/Obscura opt-outs and the other non-closure packages (document-reader, OpenAPI tools, NATS, wiki) are not in its install set. |
1038
1093
  | NeuralWatt package/docs/examples release gate | `packaging.test.ts` pins `@arnilo/prism-provider-neuralwatt` package exports/type declarations and `@arnilo/prism-providers`/`@arnilo/prism-all` membership; `docs.test.ts` asserts `docs/index.md` links `providers/neuralwatt.md` and `provider-caching.md`, and that `examples/cache-aware-prompt-assembly.ts` plus `examples/neuralwatt-agent-run.ts` exist and are listed. |
1039
1094
  | Enterprise PostgreSQL package/docs/example gate | Packaging/install/public-contract tests include `@arnilo/prism-enterprise-postgres`; `docs.test.ts` pins its API page, four-store migration/ownership/unknown-outcome/async-router guidance, and `examples/enterprise-postgres-state.ts`; `npm run test:postgres` exercises migration, restart, contention, and cleanup with an explicit database URL. |
1040
1095
  | Version graph and resumable publication | `release.test.ts` covers exact package/lock/range validation, topological order, registry collisions, dry-run, interrupted reports/resume, clean tagged git state, provenance/public/tag arguments, and token-safe errors. `release:check` and `release:publish` derive the workspace graph without a manual package list. |
@@ -1046,11 +1101,36 @@ Every release gate maps to an exact enforcement test or command, so the checklis
1046
1101
 
1047
1102
  A change that adds a public persistence/runtime surface, a new package, or a new example must extend the matching row's enforcement (add the page to `apiPages`, the package to the `packages` array, or the example to the demos list) so the checklist stays self-maintaining.
1048
1103
 
1104
+ ## Independent package versioning (default after the 0.3.0 cut)
1105
+
1106
+ `scripts/release.mjs` now defaults `check`, `publish`, and `gate` to **independent** (Decision B). Each package bumps only when it changes, internal pins stay in `^0.3.0`, and publication targets only changed packages at their own `name@version`. The final lockstep path is explicit: `--lockstep --version 0.3.0`.
1107
+
1108
+ | Action | Command |
1109
+ | --- | --- |
1110
+ | List packages changed since a baseline tag | `node scripts/release.mjs changed [--baseline <tag>]` |
1111
+ | Bump one package (patch/minor/major) | `node scripts/release.mjs bump --package @arnilo/<name> --type patch` |
1112
+ | Validate current/mixed versions | `node scripts/release.mjs check --allow-dirty --allow-untagged` |
1113
+ | Validate the final lockstep cut | `node scripts/release.mjs check --lockstep --version 0.3.0 --allow-dirty --allow-untagged` |
1114
+ | Dry-run independent publish | `node scripts/release.mjs publish --dry-run --allow-dirty --allow-untagged` |
1115
+ | Resume interrupted package-tag publish | `node scripts/release.mjs publish --resume --report release-artifacts/publish-report.json` |
1116
+ | Convert the final cut to caret ranges | `node scripts/release.mjs bump --ranges caret --from 0.3.0 --to 0.3.0` |
1117
+
1118
+ **Independent validate rules** (`validateReleaseIndependent`):
1119
+
1120
+ - Every internal `@arnilo/*` range must satisfy the target package's actual version. On 0.x, `^` and `~` both mean `>=min <next-minor` (npm rule); exact pins must match. A `^0.3.0` pin does **not** satisfy `0.4.0`.
1121
+ - A changed package (git diff vs the baseline tag, or new at baseline) must have a version greater than the baseline; a changed package still at the baseline version fails with `bump required`.
1122
+ - An unchanged package must keep its version; an unchanged package with a bumped version fails with `was <baseline>`.
1123
+ - The lockfile per-package version must match each manifest version.
1124
+
1125
+ **Independent publish** walks topological order over changed packages only and publishes each at its own version, skipping any `name@version` already on the registry whose internal dependency fingerprint matches the local manifest (resume-safe); a same-version manifest with different release fields fails closed (`already exists on the registry`). Real publication requires a clean tree and the package tag `@arnilo/<name>@<version>` pointing at HEAD. A generic `v*` tag is not a publish trigger after `v0.3.0`.
1126
+
1127
+ No Changesets. No new runtime dependency. The 0.x caret window (`^0.3.0` = `>=0.3.0 <0.4.0`) is the independent band; the next coordinated peer bump is the 0.4.0 line.
1128
+
1049
1129
  ## Pre-publish compatibility gates (`release:gate`)
1050
1130
 
1051
- `npm run release:gate` (also run inside `npm run sdk:ready`) is the offline gate that must pass before `release:check`/`release:publish`. It runs three stages over the exact version graph (version defaults to the root manifest; no git or registry access):
1131
+ `npm run release:gate` (also run inside `npm run sdk:ready`) is the offline gate that must pass before `release:check`/`release:publish`. It runs three stages over the exact version graph; independent mode reads local git history for changed-package validation but never contacts the registry:
1052
1132
 
1053
- - **ranges**: reuses `validateRelease` — exact internal version ranges and lockfile entries.
1133
+ - **ranges**: reuses `validateReleaseIndependent` by default, or `validateRelease` for explicit `--lockstep --version 0.3.0`; both verify internal ranges and lockfile entries.
1054
1134
  - **compat**: diffs every package's packed `.d.ts` surface (exported names + normalized declaration signatures, `export *` resolved within the package) against `scripts/compat-baseline/<pkg>.txt`. Removed or changed exports fail unless `--allow-break` is passed **and** `docs/migration.md` mentions the target version. Manifest-only profiles (no `main`/`types`/`exports`) are skipped. Regenerate baselines after a deliberate reviewed change with `node scripts/release.mjs gate --update-baseline`.
1055
1135
  - **tarball**: `npm pack --dry-run --json` file lists must not match the deny list (`code-reviews/`, `bug-reports/`, `plans/`, `scripts/benchmark-*`, `docs/review-coverage-*`, `__tests__/`, `*.map`). Root `files` excludes `docs/review-coverage-*` historical reviews.
1056
1136
 
package/docs/server.md CHANGED
@@ -173,6 +173,7 @@ A2A routes are not added to `createPrismHandler()`. Install `@arnilo/prism-super
173
173
  - [MCP client and server exposure](mcp-tools.md): selected MCP capabilities and web-standard MCP transport.
174
174
  - [Host security guide](host-security.md): remote-boundary checklist.
175
175
  - [A2A interoperability](a2a.md): separately mounted A2A 1.0 handler/client.
176
+ - [Obscura browser engine](obscura.md): optional binary-backed generic tools for hosted agents.
176
177
  - [Conversations](conversations.md): durable user-scoped conversation service, replay, branches, export, deletion.
177
178
  - [Work artifacts and review](work-artifacts-and-review.md): durable artifact review service, revisions, approvals, authorized expiring delivery links.
178
179
  - [Frontend interoperability (AG-UI and ACP)](ag-ui.md): separately installed authorized AG-UI Web handler.
@@ -17,11 +17,11 @@ Use a supervisor when a host or agent must choose a child dynamically. Use `@arn
17
17
  | `delegate({ childId, input, threadId?, limits?, signal? })` | Invokes one allow-listed child. Input is text and byte-bounded. |
18
18
  | `hooks.before` | May reject, modify redacted input, or narrow limits/policy. |
19
19
  | `hooks.after` | Observes redacted terminal summary; failures cannot alter settled result. |
20
- | `limits` | Depth 4/16, active children 4/32, input 64 KiB/1 MiB, steps 8/64, tools 32/256, tokens 20k/1m, timeout 60s/30m, event queue 128/4096 default/hard. |
20
+ | `limits` | Depth 4/16, active children 4/32, input 64 KiB/1 MiB, steps 8/64, tools 32/256, tokens 20k/1m, timeout 60s/30m, event queue 128/4096 default/hard. Over-cap `delegate()` throws `SupervisorLimitError` before incrementing `activeChildren`. Hook rejection and timeout decrement the count exactly once (no leaked timers). |
21
21
 
22
22
  ## Outputs / response / events
23
23
 
24
- `delegate()` returns the child's `AgentRunResult` or throws its `AgentRunError`/a supervisor denial or limit error. `subscribe()` emits bounded `delegation_started`, `delegation_finished`, `delegation_rejected`, and `delegation_error` metadata events. Hosts may project those events through observability `handleDelegation()` using the parent Prism run ID; no OpenTelemetry dependency enters this package.
24
+ `delegate()` returns the child's `AgentRunResult` or throws its `AgentRunError`/a supervisor denial or limit error. `subscribe()` emits bounded `delegation_started`, `delegation_finished`, `delegation_rejected`, and `delegation_error` metadata events. Graceful close drains already-queued terminal events before the iterator completes (same core multiplexer contract). Hosts may project those events through observability `handleDelegation()` using the parent Prism run ID; no OpenTelemetry dependency enters this package.
25
25
 
26
26
  ## Request/response example
27
27
 
@@ -77,3 +77,4 @@ Supervisors propagate parent `identity` and `effectStore` to every child agent/r
77
77
  - [Workflows](workflows.md): preferred deterministic orchestration.
78
78
  - [Working and semantic memory](working-and-semantic-memory.md): child scope construction.
79
79
  - [Host security](host-security.md): permission and credential boundaries.
80
+ - [Obscura browser engine](obscura.md): optional binary-backed generic tools for child agents.
@@ -45,7 +45,7 @@ Known `source` order is deterministic: `user`, `package`, `app`, then `run`. Unk
45
45
 
46
46
  ## Outputs / response / events
47
47
 
48
- `composeSystemPrompt()` returns the composed prompt string or `undefined` when no prompt text remains. The agent/session runtime passes that string to `assembleProviderInput()` as `systemInstructions`; it does not emit a separate event or store prompt layers.
48
+ `composeSystemPrompt()` returns the composed prompt string or `undefined` when no prompt text remains. The agent/session runtime passes that string to `assembleProviderInput()` as `systemInstructions`; it does not emit a separate event or store prompt layers. With the default `cache_aware` layout, this composed system message is emitted before dynamic context, skills, history, tool results, and current input; set `inputLayout: "legacy"` to retain the prior whole-prompt order.
49
49
 
50
50
  ## Request/response example
51
51
 
package/docs/tools.md CHANGED
@@ -216,7 +216,7 @@ By default tools without `parameters` skip schema validation (`missingSchema: "a
216
216
 
217
217
  ### Parallel tool execution (single-shot loop)
218
218
 
219
- Opt in through `loop.toolConcurrency` on `AgentConfig` / `RunOptions` (single-shot strategy only). Default is `1` (sequential). Independent calls from one provider turn run concurrently up to the limit; transcript rows and `appendMessage` stay in original call order. Each call still uses `dispatchToolCall` (permission, validation, abort signal). See [Agent loops](agent-loops.md).
219
+ Opt in through `loop.toolConcurrency` on `AgentConfig` / `RunOptions` (single-shot strategy only). Default is `1` (sequential). Independent calls from one provider turn run concurrently up to the limit; transcript rows and `appendMessage` stay in original call order. Each call still uses `dispatchToolCall` (permission, validation, abort signal). If a worker throws or the run aborts, workers stop claiming new calls, already-claimed calls settle, buffered tool-result rows are not appended, and the first failure is rethrown. Already-claimed side effects are not rolled back; the shared abort signal is still passed to each dispatch. The round-level `chargeToolRound` approval gate runs before any worker starts. See [Agent loops](agent-loops.md).
220
220
 
221
221
  ```ts
222
222
  await session.run(input, {
package/docs/web-tools.md CHANGED
@@ -8,6 +8,8 @@
8
8
 
9
9
  Use when agent needs explicit public-web discovery or host-approved document retrieval/extraction. Keep search separate from fetch/extract so model cannot select provider, credential, API origin, extraction schema, or cost path.
10
10
 
11
+ **Obscura-backed alternative**: the optional [`@arnilo/prism-obscura`](obscura.md) package provides `web_search`/`web_fetch` behavior backed by a host-installed Obscura headless browser through its CLI (one replaceable HTML search profile instead of an API key), plus explicit native `obscura_fetch`/`obscura_scrape` batch tools. It reuses this package's normalized citation/untrusted shapes (`provider: "obscura"`) but does not require credentials; the API-backed Brave/Exa/Firecrawl adapters here remain the preferred path when an API key is available.
12
+
11
13
  ## Inputs / request
12
14
 
13
15
  | Tool | Model-visible input | Host-only construction input |
package/docs/wiki.md ADDED
@@ -0,0 +1,140 @@
1
+ # LLM Wiki (@arnilo/prism-wiki)
2
+
3
+ ## What it does
4
+
5
+ `@arnilo/prism-wiki` implements Andrej Karpathy's **LLM Wiki Pattern** for the Prism agent ecosystem. It acts as a knowledge compiler that transforms raw, immutable sources (source code, AST symbols, notes, markdown clips, transcripts, journal entries) into a persistent, compounding, cross-linked Markdown knowledge base (`.wiki/`).
6
+
7
+ It integrates Tobias Lütke's [`qmd`](https://github.com/tobi/qmd) on-device hybrid search engine (BM25, vector search, and LLM reranking) and hydrates search results with Context7-inspired hierarchical breadcrumbs (`# Category > ## Topic`) and live clickable source line anchors (`file:///path/to/file#Lxx-Lyy` format), enabling agents and humans to navigate code and notes directly without blind regex loops (`grep`/`rg`).
8
+
9
+ ## When to use it
10
+
11
+ - **Codebase Knowledge Compilation**: Ingesting modules, architecture patterns, and decision records (ADRs) with exact AST and line anchors that track code drift.
12
+ - **Personal Knowledge Management (PKM)**: Ingesting research papers, meeting notes, book summaries, and journal entries into an interlinked knowledge graph.
13
+ - **Context7-Style Navigation**: Allowing agents to query concepts and immediately jump to exact file and line locations without broad repository scans.
14
+ - **Compounding Q&A**: Persisting valuable answers, analyses, and architectural comparisons back into the wiki for future sessions.
15
+
16
+ ## Architecture
17
+
18
+ The Karpathy LLM Wiki pattern is structured into 3 distinct tiers:
19
+
20
+ 1. **Raw Sources (Immutable)**: Source code files, design docs, transcripts, journals, and Markdown notes. Raw sources are strictly read-only and never mutated.
21
+ 2. **Compiled Wiki (`.wiki/`)**: Persistent, cross-linked Markdown documents containing synthesized architecture models, entity descriptions, decision records, and line-anchored claims.
22
+ 3. **Schema & Protocols (`SCHEMA.md`)**: Operational guidelines governing entity categorization, link formatting (`[[wikilink]]`), citation rules (`file:///path#Lxx-Lyy`), catalog indexing (`index.md`), and chronological change logging (`log.md`).
23
+
24
+ ## Inputs / request
25
+
26
+ ### `createWikiExtension(options)`
27
+
28
+ | Field | Type | Required | Default | Description |
29
+ | :--- | :--- | :--- | :--- | :--- |
30
+ | `wikiRoot` | `string` | No | `".wiki"` | Path to the compiled wiki directory. |
31
+ | `rawRoots` | `readonly string[]` | No | `["."]` | Directories containing raw source files (code, notes, docs). |
32
+ | `profile` | `"codebase" \| "pkm" \| "hybrid" \| "auto"` | No | `"auto"` | Operating strategy for parsing and symbol indexing. |
33
+ | `qmdPath` | `string` | No | `"qmd"` | Path or executable name for the `qmd` CLI binary. |
34
+ | `workspaceRoot` | `string` | No | `process.cwd()` | Workspace root for resolving relative paths and `.agents/skills/`. |
35
+ | `autoDeploySkills` | `boolean` | No | `true` | Auto-deploys `wiki-maintainer` and `wiki-searcher` skills to `.agents/skills/` on init. |
36
+
37
+ ### Tools
38
+
39
+ - `wiki_search`: `{ query: string, mode?: "search" | "vsearch" | "query", maxResults?: number }`
40
+ - `wiki_read_page`: `{ pagePath: string }` — `pagePath` must resolve inside the wiki root (lexical + `fs.realpath` containment). Traversal (sibling-prefix, `..`, absolute paths) and symlinks pointing outside the wiki throw an access-denied error; a missing contained page returns `found: false`.
41
+ - `wiki_record_insight`: `{ title: string, content: string, category?: "decision" | "concept" | "entity" }` — title and content must be non-empty; titles are capped at 200 characters, content at 65,536 bytes, and control characters/newlines in titles are collapsed to spaces so titles cannot inject Markdown headings, index entries, or log entries.
42
+
43
+ ### Slash Commands
44
+
45
+ - `/wiki-init`: Scaffolds `.wiki/`, instantiates `SCHEMA.md`, `index.md`, and `log.md`, deploys skills, and adds the `qmd` collection.
46
+ - `/wiki-refresh`: Detects modified source files via SHA-256 Merkle diffing, compiles updates to affected entity pages, reconciles contradictions in `log.md`, and runs `qmd update`.
47
+ - `/wiki-lint`: Checks for broken `[[wikilinks]]`, dead line anchors, orphan pages, and unindexed symbols.
48
+
49
+ ### Standalone CLI Commands
50
+
51
+ ```bash
52
+ # Initialize wiki in project
53
+ npx prism-wiki init --profile codebase
54
+
55
+ # Refresh wiki after code edits
56
+ npx prism-wiki refresh
57
+
58
+ # Check wiki health and dead anchors
59
+ npx prism-wiki lint
60
+
61
+ # Search wiki from terminal
62
+ npx prism-wiki search "How does authentication work?" --mode query
63
+ ```
64
+
65
+ ## Outputs / response / events
66
+
67
+ - `wiki_search` returns a structured markdown payload containing section breadcrumbs, conceptual summaries, and clickable source line links (`file:///path#Lxx-Lyy`).
68
+ - Lifecycle commands return status objects (`{ status: "initialized" | "refreshed" | "clean", ok: boolean }`).
69
+
70
+ ## Request/response example
71
+
72
+ ### `wiki_search` Query:
73
+ ```json
74
+ {
75
+ "query": "How is authentication handled?",
76
+ "mode": "query",
77
+ "maxResults": 2
78
+ }
79
+ ```
80
+
81
+ ### Response Content:
82
+ ```markdown
83
+ ### Match 1: Authentication Architecture > Token Verification
84
+ - **Wiki Page:** [[entities/authentication.md]]
85
+ - **Category:** Core Module
86
+ - **Freshness:** Current (Source hash matches manifest)
87
+
88
+ **Synthesized Summary:**
89
+ The authentication layer uses asymmetric Ed25519 JWT verification in middleware, backed by a persistent token-revocation denylist stored in PostgreSQL.
90
+
91
+ **Code & Source Anchors (Clickable):**
92
+ - Token verification: `verifyToken()` (`file:///src/auth/jwt.ts#L45-L89`)
93
+ - Revocation check: `assertNotRevoked()` (`file:///src/auth/session-store.ts#L112-L138`)
94
+ - Architecture Decision: [[decisions/ADR-004-ed25519-migration.md]]
95
+ ```
96
+
97
+ ## Implementation example
98
+
99
+ ```ts
100
+ import { createExtensionKernel } from "@arnilo/prism";
101
+ import { createWikiExtension, initWiki, refreshWiki, lintWiki } from "@arnilo/prism-wiki";
102
+
103
+ const kernel = createExtensionKernel();
104
+
105
+ const wiki = createWikiExtension({
106
+ wikiRoot: ".wiki",
107
+ profile: "codebase",
108
+ });
109
+
110
+ await kernel.load([wiki]);
111
+ ```
112
+
113
+ ## Skills and Auto-Deployment
114
+
115
+ `@arnilo/prism-wiki` includes two specialized skills formatted according to `.agents/skills/skill-creator`:
116
+
117
+ 1. **`wiki-maintainer`**: Ingestion, compilation, line-anchor validation, and contradiction reconciliation rules.
118
+ 2. **`wiki-searcher`**: Context7 hierarchical breadcrumb query resolution, zero-grep instructions, and compounding insight recording.
119
+
120
+ When initialized (`wiki-init` or `createWikiExtension`), these skills are automatically deployed to the host workspace's `.agents/skills/` folder so any compatible agent can leverage them immediately.
121
+
122
+ ## Extension and configuration notes
123
+
124
+ - `@arnilo/prism-wiki` registers tools (`wiki_search`, `wiki_read_page`, `wiki_record_insight`), commands (`wiki-init`, `wiki-refresh`, `wiki-lint`), skills (`wiki-maintainer`, `wiki-searcher`), and instruction injectors (`wiki-guidance`) into Prism registries.
125
+ - It operates with zero core modifications and can be used with any `@arnilo/prism` agent.
126
+ - `qmd` is optional but recommended. When `@tobilu/qmd` is not installed, the search engine falls back to catalog matching against `index.md`.
127
+
128
+ ## Security and performance notes
129
+
130
+ - **Source Immutability**: Raw source files are read-only and never modified by wiki operations.
131
+ - **Subprocess Safety**: All `qmd` subprocess calls use argument arrays (`execFile`) to prevent shell injection.
132
+ - **Path Containment**: Wiki and raw source paths are confined to the workspace root; directory traversal (`../`) is rejected.
133
+ - **Bounded Token Consumption**: Incremental Merkle hashing ensures only modified files and 1-hop dependent wiki pages are processed during refresh passes.
134
+
135
+ ## Related APIs
136
+
137
+ - [`@arnilo/prism-rag`](rag.md): Bounded document chunking and vector context injection.
138
+ - [`@arnilo/prism-memory`](working-and-semantic-memory.md): Embedder and VectorStore primitives.
139
+ - [`@arnilo/prism-coding-agent`](coding-agent-tools.md): Code manipulation and reading tools.
140
+ - [`Contribution registries`](contribution-registries.md): Extension contribution model.
package/docs/workflows.md CHANGED
@@ -78,7 +78,7 @@ A function node returns `suspend({ reason, data?, resumeSchema? })` to persist `
78
78
 
79
79
  Coding-agent ask-user glue (opt-in, no Goal DB): `suspendAskUserDecision(request)` wraps `suspend` with durable question/options/`selectionMode`/`allowCustom` data + resume schema; resume with `createAskUserDecisionResumeValidator()` or `validateAskUserDecisionResume`. Goal→verify: `runCodingGoalVerify` / `createCodingGoalVerifyWorkflow` compose plan Markdown → named checks → approve suspend → bounded handoff over the same primitives (`examples/coding-goal-verify.ts`). When a workflow node wraps a durable agent run, that run's shared pending-decision batch (Task 2) is the approval authority — workflow `suspend`/`resume` stay workflow-scoped and do not mint a parallel decision store.
80
80
 
81
- Every node receives bounded `ctx.state`, `ctx.stateVersion`, and async `ctx.updateState(patch, { mode: "merge" | "replace" })`. Updates serialize, validate, redact, and snapshot before checkpoint save. `workflowNode({ workflow })` runs its child with the same ownership, agent/tool registries, execution policy, redactor, signal, checkpoints, and event bus; child state replaces parent state after success.
81
+ Every node receives bounded `ctx.state`, `ctx.stateVersion`, and async `ctx.updateState(patch, { mode: "merge" | "replace" })`. Updates serialize, validate, redact, and snapshot before checkpoint save. A rejected state or checkpoint write stays rejected (nothing committed) and recovers the per-run chain so a later valid write can run. `workflowNode({ workflow })` runs its child with the same ownership, agent/tool registries, execution policy, redactor, signal, checkpoints, and event bus; child state replaces parent state after success.
82
82
 
83
83
  `replayWorkflow(workflow, { sourceRunId, fromNodeId, runId? }, options)` requires a succeeded source/node, creates a new checkpoint, copies terminal evidence outside the selected node's downstream closure, restores selected-node pre-state, and records `{ sourceRunId, fromNodeId, rootRunId, depth }`. Source evidence is untouched. Copying any prior nested/tool approval is rejected; replay from that approval node or earlier so Phase 8 approval executes again.
84
84
 
@@ -304,7 +304,7 @@ runRpcServer({
304
304
 
305
305
  - Workflow semantics stay in this optional package; generic checkpoint persistence and bounded event fan-in live in core.
306
306
  - `ProductionPersistenceStore.checkpoints` and `.leases` are optional generic capabilities. First-party SQLite/PostgreSQL adapters own `prism_checkpoints` / `prism_leases`; workflows only adapt them. Sagas use the same `WorkflowCheckpointAdapter` and `LeaseStore`; they add no SQL table or scheduler.
307
- - `createWorkflowEventBus()` delegates queueing, source fan-in, overflow, abort, and close behavior to core `createEventMultiplexer()`, including its single-consumer contract: a second concurrent `subscribe()` is rejected with `EventMultiplexerError` (`ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER`) instead of silently splitting the stream.
307
+ - `createWorkflowEventBus()` delegates queueing, source fan-in, overflow, abort, and close behavior to core `createEventMultiplexer()`, including its single-consumer contract: a second concurrent `subscribe()` is rejected with `EventMultiplexerError` (`ERR_PRISM_EVENT_MULTIPLEXER_SINGLE_CONSUMER`) instead of silently splitting the stream. Graceful `close()` stops new emits/sources and drains already-queued events (in `(sequence, nodeId)` order) before the subscriber completes; overflow `close` still emits one `workflow_event_overflow` notice and terminates.
308
308
  - The in-process active-run registry (`registerActiveWorkflowRun` / `getActiveWorkflowRun` / `abortActiveWorkflowRun`) is **non-durable, in-process only — it does not survive restart**; durable active-run recovery is a later milestone. It is bounded: every register sweeps aborted/leaked entries (runs whose promise never settled) and the registry fails closed at `MAX_ACTIVE_WORKFLOW_RUNS` (512) rather than evicting a live run; `sweepActiveWorkflowRuns()` is available for hosts. Cross-tenant lookups stay ownership-isolated.
309
309
  - `createWorkflowCommands()` is optional; hosts can drive `workflow.start` / `enqueue` / `replay` / `status` / `list` / `cancel` / `resume`. The six `schedule.*` commands appear only when a scoped `schedules` service is supplied.
310
310
  - Hosts may bridge `WorkflowEvent` into OpenTelemetry or custom sinks; there is no built-in TUI.
@@ -314,7 +314,7 @@ runRpcServer({
314
314
  ## Security and performance notes
315
315
 
316
316
  - Definitions require a non-empty host-authored `revision` and fail closed on cycles, unknown edges, self-edges, invalid limits, and `maxNodes` overflow. Revision and every nested revision enter the deterministic definition hash; hosts must bump revision when function/tool behavior changes.
317
- - Fan-out length is bounded by `maxFanOut`; concurrency by `maxConcurrency`; every count/byte/runtime option has a finite hard cap.
317
+ - Fan-out length is bounded by `maxFanOut`. Independent `map` items run in a local worker pool capped by the resolved workflow `maxConcurrency` (and `options.concurrency`); output stays in input order. Abort or the first map failure stops further items. There is no extra global admission service.
318
318
  - Node outputs, shared state/history, schedule input/records, and checkpoints are byte/count/depth bounded. Checkpoint size remains the final aggregate ceiling.
319
319
  - Event buses use a bounded buffer (default 2048) with `close` / `drop_oldest` / `drop_newest` overflow.
320
320
  - Checkpoints redact suspension/resume payloads via `SecretRedactor` / `secrets` before save; resume rejects tenant, schema, definition-hash, and expected-version mismatch.
@@ -342,6 +342,7 @@ Use workflows for known, durable, replayable graphs. Use optional supervisor del
342
342
  - [Agent/session runtime](agent-session-runtime.md): `AgentSession.run()`/`stream()`, abort, subscribe
343
343
  - [Guardrails](guardrails.md): `RunWorkflowOptions.guardrails` routes tool nodes through core dispatch before policy and side effects.
344
344
  - [Supervisor delegation](supervisors.md): bounded dynamic child selection.
345
+ - [Obscura browser engine](obscura.md): optional binary-backed generic tools for `toolNode`/`agentNode` composition.
345
346
  - [A2A interoperability](a2a.md): hosts may adapt existing exact-owner workflow status/list/cancel/checkpoint/event surfaces to `A2ATaskLifecycle`; A2A package adds no workflow worker, queue, or schema.
346
347
  - [Agent events](agent-events.md): core `AgentEvent` wrapped by `agent_event`
347
348
  - [Session stores and branching](session-stores-and-branching.md): session `leafId` reuse on resume
@@ -155,6 +155,24 @@ const memory = createMemory({
155
155
  });
156
156
  ```
157
157
 
158
+ Standalone durable vector store for RAG:
159
+
160
+ ```ts
161
+ import { createPostgresVectorStore, createHashEmbedder } from "@arnilo/prism-memory";
162
+
163
+ const store = await createPostgresVectorStore({
164
+ connectionString: process.env.DATABASE_URL!,
165
+ schema: "prism_memory", // default
166
+ table: "semantic_memory", // default
167
+ dimension: 32, // optional; pins the embedding column width (HNSW + drift guard)
168
+ }); // PostgresVectorStoreOptions; dimension must match the embedder's dimensions
169
+ // store implements rag's VectorStore/TransactionalVectorStore contract: upsert,
170
+ // query, getBySource, transaction, lexicalQuery (fts, when available), and
171
+ // getCurrentGeneration/setCurrentGeneration. close() ends adapter-owned pools.
172
+ ```
173
+
174
+ `createPostgresVectorStore()` is the production counterpart to `createMemoryVectorStore()` used by `@arnilo/prism-rag`; `createPostgresMemoryStores()` reuses the same vector implementation internally.
175
+
158
176
  ## Extension and configuration notes
159
177
 
160
178
  - Hosts wire the context provider into `AgentConfig.context` or `resolveContextProviders()`.
@@ -162,6 +180,8 @@ const memory = createMemory({
162
180
  - `createHashEmbedder()` is for tests/demos only; production hosts supply a real `Embedder`.
163
181
  - Observational memory (`@arnilo/prism-compaction-observational-memory`) remains unchanged and composable.
164
182
  - Consent is enforced at the single `recall()` gate, so both direct recall and `createContextProvider()` injection honor it; `visible: false` (or a revoked grant) keeps an entry out of prompts, events, exports, and telemetry. `setConsent`/`correct` re-upsert in place (consent change does not re-embed); `forget`/`applyRetention` are real deletes, not tombstones. Retention uses indexed oldest-first pages plus a scoped count, deleting one default-500/hard-5000 batch without reading a corpus into memory. The PostgreSQL adapter persists consent in a `consent JSONB` column added by `buildMemoryDdl`.
183
+ - The PostgreSQL vector path owns its DDL in Prism (`buildMemoryDdl`/`buildVectorSearchDdl` exported): the `<table>_rag_scope_generations` per-scope generation pointer table, `text_tsv` tsvector column + GIN index for the lexical RAG leg, and an HNSW index when the embedding dimension is pinned. DDL runs against the host's **knowledge database** — the host names `schema`/`table` (defaults `prism_memory`/`semantic_memory`), owns backup/retention of that database, and can run migrations manually with `skipMigrations: true`. Identifiers are validated/quoted; values stay parameterized.
184
+ - `createPostgresVectorStore({ dimension })` pins the embedding column width before building indexes: pgvector can only build HNSW over `vector(N)` columns, and dimension mismatch fails closed instead of drifting.
165
185
  - `exportMemory()` requires an exact `{ tenantId, resourceId, threadId }` identity equal to its `createMemory()` scope. It excludes legacy consent-less, invisible, and revoked records even when normal recall allows legacy entries. It returns a stable sequence cursor page, redacted before response, with defaults/hard caps of 100/200 entries, 4/32 MiB, and 10/60 seconds. `rebuildIndex()` uses the same stable cursor shape to re-embed one 32/128-record page under a 10/60-second cap; save the cursor durably to resume. Both APIs require a store implementing bounded `listByThread()`; retention also requires `countByThread()`. PostgreSQL/pgvector and the in-memory reference adapter conform; SQLite persistence stores sessions, not semantic vectors.
166
186
  - Profile bundles do not include this package yet.
167
187