@arnilo/prism 0.5.4 → 0.5.6

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 (41) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +10 -10
  3. package/dist/cli-runner.d.ts +8 -1
  4. package/dist/cli-runner.js +97 -7
  5. package/dist/extensions.d.ts +18 -1
  6. package/dist/extensions.js +10 -0
  7. package/dist/index.d.ts +3 -3
  8. package/dist/index.js +2 -2
  9. package/dist/run-limits.js +7 -2
  10. package/docs/cli-rpc.md +15 -1
  11. package/docs/credential-storage.md +1 -1
  12. package/docs/extension-authoring.md +8 -9
  13. package/docs/extensions.md +13 -1
  14. package/docs/graft.md +27 -5
  15. package/docs/{0.1.0-readiness.md → history/0.1.0-readiness.md} +6 -6
  16. package/docs/history/README.md +11 -0
  17. package/docs/{migrate-to-0.4.md → history/migrate-to-0.4.md} +4 -4
  18. package/docs/history/migration-0.0.md +738 -0
  19. package/docs/history/migration-0.1.md +151 -0
  20. package/docs/history/migration-0.2.md +173 -0
  21. package/docs/history/migration-0.3.md +39 -0
  22. package/docs/history/migration-0.4.md +6 -0
  23. package/docs/{persistence-credentials-multimodality-primitives.md → history/persistence-credentials-multimodality-primitives.md} +13 -13
  24. package/docs/history/release-handoffs.md +848 -0
  25. package/docs/{workflow-orchestration-primitives.md → history/workflow-orchestration-primitives.md} +11 -11
  26. package/docs/host-security.md +1 -1
  27. package/docs/index.md +160 -143
  28. package/docs/migrate-to-0.5.md +1 -1
  29. package/docs/migration.md +15 -1042
  30. package/docs/multimodal-content.md +1 -1
  31. package/docs/performance.md +1 -1
  32. package/docs/postgres-persistence.md +1 -1
  33. package/docs/provider-packages.md +20 -20
  34. package/docs/release-and-install.md +57 -842
  35. package/docs/runs-and-usage.md +2 -2
  36. package/docs/session-stores-and-branching.md +1 -122
  37. package/docs/sqlite-persistence.md +1 -1
  38. package/docs/wiki.md +46 -2
  39. package/docs/workflows.md +1 -1
  40. package/package.json +1 -1
  41. /package/docs/{workflow-tui-primitives.md → history/workflow-tui-primitives.md} +0 -0
@@ -59,9 +59,9 @@ await session.run("Summarize", {
59
59
  });
60
60
  ```
61
61
 
62
- Defaults are the unconfigured fence (OWASP LLM10): turns 16, provider attempts 24, tool rounds 8, tool calls 32, wall time 120 seconds, request and response bytes 8 MiB each, input tokens 40,000, output tokens 10,000, total tokens 50,000. Hard process ceilings exist only for request/response bytes (64 MiB each), so a bug cannot OOM the host through a giant provider frame; those two axes reject `null`. Every other axis is host policy (0.5.4): omit a key for the default, set a positive safe integer sized to the workload, or set `null` to disable the axis — overnight sessions raise turns/wall/tokens, and a disabled wall still honors `RunOptions.signal`. Resolution stays narrowing-only: `RunOptions.limits` may lower `AgentConfig.limits`, `null` acts as +Infinity (agent 16 + run `null` → 16), and a raised/disabled `maxTurns` lifts an omitted `maxProviderAttempts` (default 24) to at least `maxTurns` so attempts cannot undercut turns; explicitly set attempts values are lifted only when both are finite. Cumulative token counters are billed usage across the whole run, not the context window (`contextBudget` governs window compaction). For production, prefer an explicit `maxCost`: cost needs a finite non-negative amount plus one currency, and when cost is limited, absent, non-finite, or mixed-currency provider cost fails closed. Vendors that omit usage charge zero to the token counters (local/Ollama report none), so a configured `maxCost` is the fail-closed envelope for usage-less vendors.
62
+ Defaults are the unconfigured fence (OWASP LLM10): turns 16, provider attempts 24, tool rounds 8, tool calls 32, wall time 120 seconds, request and response bytes 8 MiB each, input tokens 40,000, output tokens 10,000, total tokens 50,000. Hard process ceilings exist only for request/response bytes (64 MiB each), so a bug cannot OOM the host through a giant provider frame; those two axes reject `null` and are charged **per frame** (request payload, provider event), not as a run-lifetime sum — a 2 MiB prompt sent forty times is 2 MiB frames, not an 80 MiB parse. Snapshots still report the cumulative `requestBytes`/`responseBytes` counters for telemetry. Every other axis is host policy (0.5.4): omit a key for the default, set a positive safe integer sized to the workload, or set `null` to disable the axis — overnight sessions raise turns/wall/tokens, and a disabled wall still honors `RunOptions.signal`. Resolution stays narrowing-only: `RunOptions.limits` may lower `AgentConfig.limits`, `null` acts as +Infinity (agent 16 + run `null` → 16), and a raised/disabled `maxTurns` lifts an omitted `maxProviderAttempts` (default 24) to at least `maxTurns` so attempts cannot undercut turns; explicitly set attempts values are lifted only when both are finite. Cumulative token counters are billed usage across the whole run, not the context window (`contextBudget` governs window compaction). For production, prefer an explicit `maxCost`: cost needs a finite non-negative amount plus one currency, and when cost is limited, absent, non-finite, or mixed-currency provider cost fails closed. Vendors that omit usage charge zero to the token counters (local/Ollama report none), so a configured `maxCost` is the fail-closed envelope for usage-less vendors.
63
63
 
64
- Prism charges turns before assembly, provider attempts and request bytes before generation, response bytes per provider event, tool rounds before a batch, tool calls before dispatch, and usage before another turn. A breach stops new work, aborts active work through the run signal, emits exactly one redacted `run_limit_exceeded` event/ledger row, and throws `AgentRunError` with `result.limit` (`limit`, `maximum`, `observed`, optional `currency`). Provider-reported token/cost totals arrive after generation, so that completed provider turn can be the unavoidable overshoot boundary.
64
+ Prism charges turns before assembly, provider attempts before generation, request bytes per request payload, response bytes per provider event (each frame must fit the byte cap on its own), tool rounds before a batch, tool calls before dispatch, and usage before another turn. A breach stops new work, aborts active work through the run signal, emits exactly one redacted `run_limit_exceeded` event/ledger row, and throws `AgentRunError` with `result.limit` (`limit`, `maximum`, `observed`, optional `currency`). Provider-reported token/cost totals arrive after generation, so that completed provider turn can be the unavoidable overshoot boundary.
65
65
 
66
66
  `createRunLimitTracker()` and `resolveRunLimits()` are public for adapters that need the same validation and accounting semantics. Workflow agent nodes forward `RunWorkflowOptions.limits`; supervisor delegation narrows its step/tool/token/timeout budget into core limits; MCP tool calls use a per-call tracker.
67
67
 
@@ -1,124 +1,3 @@
1
1
  # Session stores and branching
2
2
 
3
- > Compatibility page: the canonical session-store overview now lives at [Session stores](session-stores.md). This page retains the detailed branch-helper reference and is kept to avoid breaking existing links.
4
-
5
- ## What it does
6
-
7
- Session store helpers define branch-aware session entries and pure utilities for creating entries, listing branch leaves, reading a leaf path, and rebuilding provider context from a selected leaf. For atomic append options, `SessionAppendConflictError`, branch handles, and production `readBranchPath` guidance, start with [Session stores](session-stores.md#atomic-append-and-branch-handles).
8
-
9
- Public helpers:
10
-
11
- - `createSessionEntry(options)`
12
- - `createMemorySessionStore(initialEntries?)`
13
- - `getSessionBranchEntries(entries, options)` and `getSessionBranchEntries(reader, query)`
14
- - `listSessionBranches(entries)`
15
- - `rebuildSessionContext(entries, options)` and `rebuildSessionContext(reader, query)`
16
-
17
- ## When to use it
18
-
19
- Use these helpers when a host, runtime session, or store adapter needs durable, branch-aware session data without coupling stores to providers, tools, credentials, or files.
20
-
21
- Do not use them as a database layer, migration system, lock service, compaction strategy, retry policy, CLI/RPC protocol, or hidden global store registry.
22
-
23
- ## Inputs / request
24
-
25
- `SessionEntry` has stable branch fields plus typed payloads:
26
-
27
- | Field | Purpose |
28
- | --- | --- |
29
- | `id` | Unique entry id. |
30
- | `parentId` | Previous entry on the branch, if any. |
31
- | `sessionId` | Session that owns the entry. |
32
- | `timestamp` | ISO timestamp chosen by the caller/helper. |
33
- | `kind` | `message`, `event`, `summary`, `metadata`, `model_change`, `label`, `custom`, or `compaction`. |
34
- | `runId` | Optional run id. |
35
- | `message`, `event`, `model`, `previousModel`, `label`, `summary`, `data`, `metadata` | Optional payload fields for the entry kind. |
36
-
37
- `rebuildSessionContext()` and `getSessionBranchEntries()` accept an optional `leafId`. If omitted, the last entry is used as the leaf. The async reader overloads accept `SessionBranchRead { sessionId, leafId?, cursor?, limit? }` and call a `BranchReader` / `readBranchPath` implementation so database adapters can return one ancestor chain without `list(sessionId)`. `createMemorySessionStore()` accepts optional initial entries.
38
-
39
- ## Outputs / response / events
40
-
41
- | Helper | Output |
42
- | --- | --- |
43
- | `createSessionEntry()` | A `SessionEntry` with generated `id` and `timestamp` when omitted. |
44
- | `getSessionBranchEntries()` | Ordered entries from root to selected leaf (deep copies). |
45
- | `listSessionBranches()` | Leaf ids and their root-to-leaf entry paths (deep copies). |
46
- | `rebuildSessionContext()` | `{ leafId, entries, messages, summaries }` for provider input rebuild; with a compaction entry, raw `entries` stay intact while `messages` becomes recent context and `summaries` includes the compaction summary. All arrays and objects are deep copies. |
47
- | `createMemorySessionStore()` | Async `SessionStore` with `append()`, `list(sessionId)`, and `get(id)`. `list()` and `get()` return deep copies. |
48
-
49
- Helpers throw on duplicate entry ids, unknown leaves, or missing parents. They do not mutate input arrays.
50
-
51
- For `kind: "compaction"`, `data` may contain `throughEntryId`, `keepEntryIds`, `strategy`, and `trigger`. The latest valid compaction entry on a branch is used as the provider-context boundary; raw history remains in `entries`.
52
-
53
- ## Request/response example
54
-
55
- ```json
56
- {
57
- "leafId": "entry_2",
58
- "messages": [{ "role": "user", "content": [{ "type": "text", "text": "Hi" }] }]
59
- }
60
- ```
61
-
62
- ## Implementation example
63
-
64
- ```ts
65
- import { createMemorySessionStore, createSessionEntry, rebuildSessionContext } from "@arnilo/prism";
66
-
67
- const first = createSessionEntry({
68
- id: "entry_1",
69
- sessionId: "s1",
70
- kind: "message",
71
- message: { role: "user", content: [{ type: "text", text: "Hi" }] },
72
- });
73
- const label = createSessionEntry({
74
- id: "entry_2",
75
- parentId: first.id,
76
- sessionId: "s1",
77
- kind: "label",
78
- label: "investigation",
79
- });
80
-
81
- const store = createMemorySessionStore([first]);
82
- await store.append(label);
83
-
84
- const context = rebuildSessionContext(await store.list("s1"), { leafId: label.id });
85
- ```
86
-
87
- ## Extension and configuration notes
88
-
89
- Stores and extensions can use these data helpers directly. Store adapters only need append/list/get behavior; branch queries are derived in memory from listed entries unless the store implements `readBranchPath`. See [Session stores](session-stores.md) for `SessionAppendOptions`, `SessionAppendConflictError`, and `(sessionId, leafId)` branch-handle guidance.
90
-
91
- `createMemorySessionStore()` is the built-in in-memory implementation. It preserves append order per session, isolates session ids, returns entries by id in O(1), rejects duplicate entry ids, and returns deep copies from `list()` and `get()`. It is process memory only; hosts that need durability should pass another `SessionStore`.
92
-
93
- `getSessionBranchEntries()` and `rebuildSessionContext()` also return deep copies of entries and messages, so callers cannot mutate the input arrays or the memory store by editing returned objects.
94
-
95
- `AgentSession` uses `AgentSessionConfig.store` before `AgentConfig.store`, otherwise a private memory store. It appends user, assistant, tool-result, and model-change entries, resumes from `leafId`, rebuilds provider history from the selected branch, checks out old leaves, forks by selecting a leaf in the same session, and clones the selected branch to a new session id.
96
-
97
- Node hosts that need simple file durability can import `createJsonlSessionStore()` from the explicit `@arnilo/prism/node/session-store-jsonl` subpath.
98
-
99
- Use `createDefaultCompactionStrategy()` to create compaction entries that `rebuildSessionContext()` understands. Compaction adds summaries; it does not delete or rewrite raw store entries.
100
-
101
- `createSessionEntry()` accepts injectable `createId` and `now` functions for deterministic tests or host id policy. Prism does not create a global store or id service.
102
-
103
- ## Security and performance notes
104
-
105
- - Helpers are pure data functions: no provider calls, tool calls, settings reads, credential resolution, filesystem access, network access, timers, or dependencies.
106
- - Store only host-approved session entries. Do not put provider credentials, credential resolvers, provider objects, full provider requests, or secrets in entries.
107
- - Branch rebuild is linear over listed entries for development stores. Production stores should implement `readBranchPath` and return one branch ancestor chain so large sessions are not fully loaded.
108
- - Compaction-aware rebuild keeps raw branch entries in `entries`; only provider-context `messages`/`summaries` are reduced.
109
- - Memory store lookup by id is O(1); list is O(n) for that session.
110
- - Duplicate ids and missing parents fail clearly instead of guessing a branch.
111
-
112
- ## Related APIs
113
-
114
- - [Migration guide](migration.md): moving branch-handle reads from the dev `list(sessionId)` path to a database-backed `readBranchPath`.
115
- - [Session stores](session-stores.md): canonical overview for `SessionAppendOptions`, `SessionAppendConflictError`, branch handles, and dev-vs-production branch reads.
116
- - [Public contracts](public-contracts.md): `SessionEntry`, `SessionStore`, `StoreFactory`, and session contracts.
117
- - [Agent/session runtime](agent-session-runtime.md): runtime sessions use these branch helpers for store-backed history, checkout, fork, and clone.
118
- - [Node JSONL session store](node-jsonl-session-store.md): optional Node filesystem store for caller-named JSONL files.
119
- - [Compaction and retry policies](compaction-and-retry.md): default strategy for creating compaction entries.
120
- - [Input and prompt assembly](input-and-prompt-assembly.md): provider input assembly consumes rebuilt `messages` and `summaries`.
121
- - [Credentials and redaction](credentials-and-redaction.md): security boundary for secrets that must not enter session entries.
122
- - [Workflows](workflows.md): optional orchestration that reuses session `leafId` on resume rather than reloading full transcripts into the scheduler.
123
-
124
- Session stores persist the entries they receive. Configure `AgentConfig.redactor` or `RunOptions.redactor` before a run when known secrets must be removed before entries reach durable stores.
3
+ > Compatibility stub: the canonical session-store overview — `SessionStore`, atomic append, `SessionAppendConflictError`, branch handles, and `readBranchPath` — lives at [Session stores](session-stores.md).
@@ -126,7 +126,7 @@ SQLite applies migrations **006**/**007** for per-run event sequence compatibili
126
126
  - [Database persistence](database-persistence.md): shared schema model, conditional append pattern, indexes.
127
127
  - [Session store conformance](session-store-conformance.md): `assertSessionStoreConforms` / `runSessionStoreConformance`.
128
128
  - [Run ledger conformance](run-ledger-conformance.md): `assertRunLedgerConforms` / `runRunLedgerConformance`.
129
- - [Persistence, credentials, and multimodality primitives](persistence-credentials-multimodality-primitives.md): package matrix and threat model.
129
+ - [Persistence, credentials, and multimodality primitives](history/persistence-credentials-multimodality-primitives.md): package matrix and threat model.
130
130
  - [Node JSONL session store](node-jsonl-session-store.md): dev-only single-process alternative.
131
131
  - [Workflows](workflows.md): adapt `persistence.checkpoints` and pass `persistence.leases` to `createWorkflowCoordinator()` and `createWorkflowSchedules()` for durable background execution and schedules.
132
132
  - [Migration guide](migration.md): moving from JSONL/in-memory to database-backed persistence.
package/docs/wiki.md CHANGED
@@ -17,7 +17,7 @@ It integrates Tobias Lütke's [`qmd`](https://github.com/tobi/qmd) on-device hyb
17
17
 
18
18
  The Karpathy LLM Wiki pattern is structured into 3 distinct tiers:
19
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.
20
+ 1. **Raw Sources (Immutable)**: Source code files, design docs, transcripts, journals, and Markdown notes. Raw sources are strictly read-only and never mutated. New external material arrives through the ingest staging area (`raw/ingest/<utc>-<slug>/`): an immutable `source.*` original plus a UTF-8 `extract.md` the maintainer skill files into the wiki.
21
21
  2. **Compiled Wiki (`.wiki/`)**: Persistent, cross-linked Markdown documents containing synthesized architecture models, entity descriptions, decision records, and line-anchored claims.
22
22
  3. **Schema & Protocols (`SCHEMA.md`)**: Operational guidelines governing OKF v0.2 emission, entity categorization, citation rules (`file:///path#Lxx-Lyy`), catalog indexing (`index.md`), and chronological change logging (`log.md`).
23
23
 
@@ -39,12 +39,14 @@ The Karpathy LLM Wiki pattern is structured into 3 distinct tiers:
39
39
  - `wiki_search`: `{ query: string, mode?: "search" | "vsearch" | "query", maxResults?: number }`
40
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
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
+ - `wiki_ingest`: `{ text?: string, path?: string, url?: string, title?: string }` — stages one raw source and returns a filing brief for the `wiki-maintainer` skill (see `/wiki-ingest` below). Exactly one of `text`/`path`/`url` must be provided; `url` requires a host `fetchUrl` hook.
42
43
 
43
44
  ### Slash Commands
44
45
 
45
46
  - `/wiki-init`: Scaffolds `.wiki/`, instantiates `SCHEMA.md`, `index.md`, and `log.md`, deploys skills, and adds the `qmd` collection.
46
47
  - `/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
48
  - `/wiki-lint`: Checks OKF frontmatter (`type`, ISO `generated.at`), leftover `[[wikilinks]]`, unresolved relative markdown links, dead line anchors, and orphan pages.
49
+ - `/wiki-ingest`: `{ text?, path?, url?, title? }` — stages one external source into `raw/ingest/<utc>-<slug>/` (`source.*` original + `extract.md`), then returns a brief (staged paths, extract preview, source URL when applicable, Karpathy filing checklist). When the host injects `drivers`, the command calls `drivers.startRun(brief, { activeSkills: ["wiki-maintainer"] })` so the maintainer skill files the source into the wiki; without drivers it stages only and reports `runStarted: false`. Results are labeled `metadata.trust: "untrusted_external"`.
48
50
 
49
51
  ### Standalone CLI Commands
50
52
 
@@ -60,12 +62,49 @@ npx prism-wiki lint
60
62
 
61
63
  # Search wiki from terminal
62
64
  npx prism-wiki search "How does authentication work?" --mode query
65
+
66
+ # Stage an external source for the wiki
67
+ npx prism-wiki ingest --path notes/paper.pdf --title "Paper"
68
+
69
+ # `--url` is a usage error in the standalone CLI:
70
+ # the wiki package never fetches — URL ingest needs a host fetchUrl hook
71
+ npx prism-wiki ingest --url https://example.com/rfc.pdf # → exit 1
63
72
  ```
64
73
 
65
74
  ## Outputs / response / events
66
75
 
67
76
  - `wiki_search` returns a structured markdown payload containing section breadcrumbs, conceptual summaries, and clickable source line links (`file:///path#Lxx-Lyy`).
68
77
  - Lifecycle commands return status objects (`{ status: "initialized" | "refreshed" | "clean", ok: boolean }`).
78
+ - `wiki_ingest` / `/wiki-ingest` return the staged paths, the (capped) extract preview, and a filing brief; `value.runStarted` reports whether a driver run was started.
79
+
80
+ ### `ingestWikiSource(input, options)`
81
+
82
+ The staging primitive behind `/wiki-ingest`, `wiki_ingest`, and the CLI. Accepts `{ text?, path?, bytes?, url?, filename?, title? }` (precedence `path` > `bytes` > `url` > `text`) and returns `{ id, rawDir, sourcePath, extractPath, mediaType?, extract, truncated, url? }` (`url` present only for URL-staged sources).
83
+
84
+ | Input | Parse behavior |
85
+ | :--- | :--- |
86
+ | Text-like files and `text` | Decoded as UTF-8 (RAG text/markdown/html parsers) |
87
+ | Uncompressed PDF | Parsed by the RAG PDF parser (bounded pages/bytes) |
88
+ | Compressed PDF / DOCX | Throws a named error unless the host supplies `options.extractDocument` (e.g. wire `createDocumentReader()` from `@arnilo/prism-coding-tools/document-reader`) |
89
+ | `url` | `assertSsrfAllowedUrl` runs first (private/link-local hosts rejected before any fetch); then the host `fetchUrl` hook supplies the bytes/text — missing or empty hook output fails closed. Staged filename comes from the hook, the URL extension (`doc.pdf`), or `source.md` |
90
+ | Images | Staged as-is; stub extract points at the staged `source.*` — no OCR; view the file |
91
+ | Unknown binary | Fails closed unless `extractDocument` claims it |
92
+
93
+ Caps: 32 MiB per staged input, 2 MiB per extract. `path` must resolve inside the workspace root (realpath containment). `log.md` gains an `**Ingested**` entry only when the wiki root exists.
94
+
95
+ Wiring a `fetchUrl` hook (the wiki package ships no HTTP client — hosts bring their own, e.g. Obscura):
96
+
97
+ ```ts
98
+ import { runObscuraCli, validateObscuraWebUrl } from "@arnilo/prism-web-tools/obscura";
99
+
100
+ const wiki = createWikiExtension({
101
+ fetchUrl: async ({ url }) => {
102
+ validateObscuraWebUrl(url); // host-side SSRF gate of its own
103
+ const run = await runObscuraCli({ command: "obscura", args: ["fetch", url, "--dump", "markdown"] });
104
+ return { text: run.stdout, filename: "source.md" };
105
+ },
106
+ });
107
+ ```
69
108
 
70
109
  ## Request/response example
71
110
 
@@ -135,12 +174,17 @@ Emitted `.wiki/` trees are [OKF v0.2](https://github.com/GoogleCloudPlatform/ope
135
174
 
136
175
  ## Extension and configuration notes
137
176
 
138
- - The wiki subpath 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.
177
+ - The wiki subpath registers tools (`wiki_search`, `wiki_read_page`, `wiki_record_insight`, `wiki_ingest`), commands (`wiki-init`, `wiki-refresh`, `wiki-lint`, `wiki-ingest`), skills (`wiki-maintainer`, `wiki-searcher`), and instruction injectors (`wiki-guidance`) into Prism registries.
139
178
  - It operates with zero core modifications and can be used with any `@arnilo/prism` agent.
140
179
  - `qmd` is optional but recommended. When `@tobilu/qmd` is not installed, the search engine falls back to catalog matching against `index.md`.
141
180
 
181
+ ## Ingest filing rules (Karpathy/OKF)
182
+
183
+ After staging, the `wiki-maintainer` skill files the source: read `.wiki/SCHEMA.md` and `index.md` first, read the staged `extract.md` (and view `source.*` for images/PDFs), integrate claims into existing entity/concept/decision pages — create pages only for genuinely new concepts — then emit OKF v0.2 frontmatter (`type` required; `sources[].resource` pointing at the staged `source.*` — for URL-staged sources the original URL is also legitimate; `generated.by: prism-wiki/ingest`), add per-claim footnotes keyed to `sources[].id` for source-specific claims, update `index.md`, and prepend an `**Ingested**` entry to `log.md`. Never copy raw bodies into wiki pages; one source per ingest; contradictions update the existing page and are logged. The same rules ship in every scaffolded `SCHEMA.md` (`## Ingest Protocol`).
184
+
142
185
  ## Security and performance notes
143
186
 
187
+ - **Ingest boundaries**: the wiki package never fetches — `url` inputs require a host `fetchUrl` hook, and `assertSsrfAllowedUrl` rejects private/link-local hosts before the hook runs; the standalone CLI rejects `--url` with a usage error. `path` inputs are contained inside the workspace root via realpath; extracts are untrusted data (`trust: "untrusted_external"`), never instructions; the raw layer stays read-only for the LLM; images get a stub extract (no OCR).
144
188
  - **Source Immutability**: Raw source files are read-only and never modified by wiki operations.
145
189
  - **Subprocess Safety**: All `qmd` subprocess calls use argument arrays (`execFile`) to prevent shell injection.
146
190
  - **Path Containment**: Wiki and raw source paths are confined to the workspace root; directory traversal (`../`) is rejected.
package/docs/workflows.md CHANGED
@@ -432,7 +432,7 @@ Use workflows for known, durable, replayable graphs. Use optional supervisor del
432
432
  ## Related APIs
433
433
 
434
434
  - Examples: `examples/workflow-research-and-review.ts`, `examples/workflow-parallel-research.ts`, `examples/workflow-tool-approval.ts`, `examples/workflow-multimodal-document.ts`, `examples/workflow-sqlite-resume.ts`, `examples/workflow-postgres-resume.ts`, `examples/workflow-event-sink.ts`, `examples/workflow-rpc-cancel.ts`, `examples/workflow-distributed-coordinator.ts`, `examples/autonomous-coding-loop.ts` (host-loop iterate-until-done) — offline runnable demos; PostgreSQL safely skips unless `PRISM_TEST_POSTGRES_URL` is set.
435
- - [Workflow orchestration primitives](workflow-orchestration-primitives.md): Task 0–1 inventory and locked adapter contracts
435
+ - [Workflow orchestration primitives](history/workflow-orchestration-primitives.md): Task 0–1 inventory and locked adapter contracts
436
436
  - [Agent/session runtime](agent-session-runtime.md): `AgentSession.run()`/`stream()`, abort, subscribe
437
437
  - [Guardrails](guardrails.md): `RunWorkflowOptions.guardrails` routes tool nodes through core dispatch before policy and side effects.
438
438
  - [Supervisor delegation](supervisors.md): bounded dynamic child selection.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arnilo/prism",
3
- "version": "0.5.4",
3
+ "version": "0.5.6",
4
4
  "description": "Agent harness for AI providers, agents, sessions, and tools.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",