@arnilo/prism 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/docs/0.1.0-readiness.md +5 -5
- package/docs/caveman.md +129 -0
- package/docs/coding-agent-tools.md +123 -21
- package/docs/coding-security.md +3 -3
- package/docs/context-and-skills.md +11 -0
- package/docs/extensions.md +2 -0
- package/docs/index.md +9 -5
- package/docs/migration.md +49 -0
- package/docs/ponytail.md +127 -0
- package/docs/release-and-install.md +57 -15
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.0.22] - 2026-07-31
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- `@arnilo/prism-caveman` and `@arnilo/prism-ponytail`: optional third-party behavior integrations (Phase 5).
|
|
7
|
+
- Example `examples/caveman-ponytail.ts`.
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Publishable manifest count: **46** (was 44).
|
|
11
|
+
|
|
12
|
+
See [docs/migration.md](docs/migration.md) for the full 0.0.21 → 0.0.22 notes.
|
|
13
|
+
|
|
14
|
+
## [0.0.21] - 2026-07-31
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- `@arnilo/prism-coding-agent`: `repo_search` `outputMode`, bounded `glob`, optional `requireReadBeforeWrite`/`ReadPathSet`, bounded `delete`/`move`.
|
|
18
|
+
- Example `examples/coding-tools-capability-gaps.ts`.
|
|
19
|
+
|
|
20
|
+
### Changed
|
|
21
|
+
- Default coding aggregator: 9 tools (`createCodingTools`); read-only aggregator: 4 (includes `glob`).
|
|
22
|
+
- `@arnilo/prism-coding-security`: approval + sandbox wiring for `delete`/`move`.
|
|
23
|
+
|
|
24
|
+
### Breaking (minor, pre-1.0)
|
|
25
|
+
- Hosts asserting exact `createCodingTools().length === 6` or readonly length `3` must update (now 9 / 4).
|
|
26
|
+
- Custom sandbox `RepositoryOperations` must implement `glob`; full sandbox custom ops must supply `delete`/`move`.
|
|
27
|
+
|
|
28
|
+
See [docs/migration.md](docs/migration.md) for the full 0.0.20 → 0.0.21 notes.
|
|
29
|
+
|
|
30
|
+
|
|
3
31
|
## [0.0.20] - 2026-07-31
|
|
4
32
|
|
|
5
33
|
### Added
|
package/dist/index.d.ts
CHANGED
|
@@ -100,5 +100,5 @@ export { createToolParameterValidator, createToolRegistry, dispatchToolCall, fil
|
|
|
100
100
|
export type { ResolvedUseCaseModel, ResolveUseCaseModelInput, UseCaseModelBinding, } from "./use-case-model.js";
|
|
101
101
|
export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
|
|
102
102
|
export declare const name = "prism";
|
|
103
|
-
export declare const version = "0.0.
|
|
103
|
+
export declare const version = "0.0.22";
|
|
104
104
|
export declare const description = "Agent harness for AI providers, agents, sessions, and tools.";
|
package/dist/index.js
CHANGED
|
@@ -54,6 +54,6 @@ export { applyThinkingLevel, isThinkingLevel, normalizeThinkingLevel, THINKING_L
|
|
|
54
54
|
export { createToolParameterValidator, createToolRegistry, dispatchToolCall, filterTools } from "./tools.js";
|
|
55
55
|
export { resolveUseCaseModel, resolveUseCaseModelBinding, useCaseCredentialProviderId, } from "./use-case-model.js";
|
|
56
56
|
export const name = "prism";
|
|
57
|
-
export const version = "0.0.
|
|
57
|
+
export const version = "0.0.22";
|
|
58
58
|
export const description = "Agent harness for AI providers, agents, sessions, and tools.";
|
|
59
59
|
//# sourceMappingURL=index.js.map
|
package/docs/0.1.0-readiness.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# 0.1.0 / 1.0 Readiness Gates
|
|
2
2
|
|
|
3
|
-
Status: **0.0.
|
|
3
|
+
Status: **0.0.22** is the current release line (Phase 5 third-party behavior integrations); **1.0** readiness remains operator-gated, not automatic.
|
|
4
4
|
|
|
5
5
|
This page distills runnable readiness gates into one command-per-gate table. The
|
|
6
6
|
**Last evidence** column records the 2026-07-26 **0.0.16** baseline snapshot
|
|
@@ -14,13 +14,13 @@ Evidence trail: [`docs/review-coverage-2026-07-26-phase-11.md`](./review-coverag
|
|
|
14
14
|
(addenda 0–9), [`docs/release-and-install.md`](./release-and-install.md),
|
|
15
15
|
[`docs/migration.md`](./migration.md), [`docs/performance.md`](./performance.md).
|
|
16
16
|
|
|
17
|
-
## Current line (0.0.
|
|
17
|
+
## Current line (0.0.21)
|
|
18
18
|
|
|
19
19
|
| Item | Status |
|
|
20
20
|
|---|---|
|
|
21
|
-
| Published graph | **44** publishable manifests at **0.0.
|
|
22
|
-
| Phase
|
|
23
|
-
| Docs tripwires | `node --test dist/__tests__/docs.test.js` — migration section `0.0.
|
|
21
|
+
| Published graph | **44** publishable manifests at **0.0.21** (`docs/release-and-install.md`) |
|
|
22
|
+
| Phase 4 coding-tool gaps | `outputMode`, bounded `glob`, optional read-before-write, bounded `delete`/`move`, approval/sandbox wiring |
|
|
23
|
+
| Docs tripwires | `node --test dist/__tests__/docs.test.js` — migration section `0.0.20 → 0.0.21 coding-tool capability gaps` documents intentional breaks |
|
|
24
24
|
| Readiness table below | **0.0.16 measured values** — refresh evidence columns when 1.0 RC gates are recorded |
|
|
25
25
|
|
|
26
26
|
## Gate table
|
package/docs/caveman.md
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
# Caveman behavior integration
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`@arnilo/prism-caveman` is an optional package that wires [juliusbrussee/caveman](https://github.com/juliusbrussee/caveman) into Prism contribution contracts.
|
|
6
|
+
|
|
7
|
+
It registers upstream skills and commands, injects active level prompt slices via `InstructionInjector`, and persists level as session custom `caveman-level` entries. Import and extension `setup` without a resolvable upstream path fail closed with a bounded redacted error and register zero contributions.
|
|
8
|
+
|
|
9
|
+
Upstream prompt fragments, skill bodies, and rules load from the host-supplied upstream checkout — Prism does not reimplement or vendor Caveman content.
|
|
10
|
+
|
|
11
|
+
## When to use it
|
|
12
|
+
|
|
13
|
+
Use it when a host wants terse token-efficient communication modes (`lite`, `full`, `ultra`, wenyan variants, `micro`) with upstream Caveman skills (`caveman-commit`, `caveman-review`, `caveman-stats`, `caveman-compress`, `caveman-help`, `cavecrew`) in a Prism extension kernel.
|
|
14
|
+
|
|
15
|
+
Skip it when you do not have a local Caveman checkout (Caveman is not published on npm) or when you only need progressive skill catalog without mode injection.
|
|
16
|
+
|
|
17
|
+
Pair with Phase 3 progressive disclosure: register `createLoadSkillTool` and keep `skillsDisclosure: "progressive"` so full `SKILL.md` bodies stay catalog-only; mode slices come from the `caveman-mode` injector, not eager skill bodies.
|
|
18
|
+
|
|
19
|
+
## Inputs / request
|
|
20
|
+
|
|
21
|
+
`createCavemanExtension(options)`:
|
|
22
|
+
|
|
23
|
+
| Field | Type | Required | Purpose |
|
|
24
|
+
| --- | --- | --- | --- |
|
|
25
|
+
| `upstreamPath` | `string` | yes | Absolute path to a Caveman checkout containing `skills/`. |
|
|
26
|
+
| `defaultLevel` | `CavemanLevel` | no | Initial level when no session entry exists (default upstream: `full`). |
|
|
27
|
+
| `showStatus` | `boolean` | no | Emit `caveman:status` extension events on level changes. |
|
|
28
|
+
| `appendEntry` | `(entry, opts?) => Promise<void>` | yes | Host session append (OM `attach` pattern). |
|
|
29
|
+
| `getEntries` | `() => readonly SessionEntry[] \| Promise<...>` | yes | Current branch entries for level restore. |
|
|
30
|
+
| `configPath` | `string` | no | Bounded local config file for `defaultLevel` / `showStatus`. |
|
|
31
|
+
|
|
32
|
+
`CavemanLevel`: `off` \| `lite` \| `full` \| `ultra` \| `wenyan-lite` \| `wenyan` \| `wenyan-ultra` \| `micro`.
|
|
33
|
+
|
|
34
|
+
Session custom entry shape:
|
|
35
|
+
|
|
36
|
+
```json
|
|
37
|
+
{ "kind": "custom", "data": { "type": "caveman-level", "level": "full" } }
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Registered skills: `caveman`, `caveman-commit`, `caveman-review`, `caveman-stats`, `caveman-compress`, `caveman-help`, `cavecrew`.
|
|
41
|
+
|
|
42
|
+
Registered commands: `caveman`, `caveman-init`, `caveman-commit`, `caveman-review`, `caveman-stats`, `caveman-compress`.
|
|
43
|
+
|
|
44
|
+
## Outputs / response / events
|
|
45
|
+
|
|
46
|
+
| Export | Purpose |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `createCavemanExtension(options)` | Returns an inert `Extension` until `kernel.load([...])`. |
|
|
49
|
+
| `caveman-mode` injector | `InstructionInjector` — upstream filtered `skills/caveman/SKILL.md` slice when level ≠ `off`. |
|
|
50
|
+
| `caveman` command | Set level (`/caveman lite\|full\|ultra\|wenyan\|micro\|off`) or toggle `off`↔`full`. |
|
|
51
|
+
| Alias commands | Dispatch `{ skill, dispatch: "load_skill" }` metadata for companion skills. |
|
|
52
|
+
| `caveman:status` event | Optional metadata when `showStatus: true`. |
|
|
53
|
+
|
|
54
|
+
Deactivation phrases `stop caveman` and `normal mode` clear active injection without erasing session history.
|
|
55
|
+
|
|
56
|
+
## Request/response example
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{ "command": "caveman", "args": { "level": "ultra" }, "sessionId": "s1" }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{ "kind": "custom", "data": { "type": "caveman-level", "level": "ultra" } }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Implementation example
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { createCavemanExtension } from "@arnilo/prism-caveman";
|
|
70
|
+
import {
|
|
71
|
+
createExtensionKernel,
|
|
72
|
+
createLoadSkillTool,
|
|
73
|
+
createLoadedSkillSet,
|
|
74
|
+
createMemorySessionStore,
|
|
75
|
+
createSkillRegistry,
|
|
76
|
+
createSessionEntry,
|
|
77
|
+
} from "@arnilo/prism";
|
|
78
|
+
|
|
79
|
+
const store = createMemorySessionStore();
|
|
80
|
+
const callbacks = {
|
|
81
|
+
appendEntry: async (entry, options) => store.append(entry, options),
|
|
82
|
+
getEntries: async () => store.list("s1"),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
const kernel = createExtensionKernel({ errorPolicy: "throw" });
|
|
86
|
+
await kernel.load([
|
|
87
|
+
createCavemanExtension({
|
|
88
|
+
upstreamPath: "/path/to/juliusbrussee-caveman",
|
|
89
|
+
defaultLevel: "full",
|
|
90
|
+
...callbacks,
|
|
91
|
+
}),
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
const registry = createSkillRegistry(kernel.registries.skills.list());
|
|
95
|
+
const loaded = createLoadedSkillSet();
|
|
96
|
+
const loadSkill = createLoadSkillTool({ registry, loaded });
|
|
97
|
+
|
|
98
|
+
await kernel.registries.commands.get("caveman")!.execute({ level: "lite" }, { sessionId: "s1" });
|
|
99
|
+
// Select instructionInjectors: ["caveman-mode"] on runs that should receive level slices.
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
See `examples/caveman-ponytail.ts` for progressive catalog + `load_skill` wiring with fixture upstream trees (network-free).
|
|
103
|
+
|
|
104
|
+
## Extension and configuration notes
|
|
105
|
+
|
|
106
|
+
- Import alone registers nothing and starts no timers, watchers, or network I/O (`sideEffects: false`).
|
|
107
|
+
- `kernel.load` calls `setup`, which resolves upstream first; failure throws before any `register*`.
|
|
108
|
+
- Level restore scans `getEntries()` for the latest `data.type === "caveman-level"` — same OM attach pattern; core does not auto-emit `session_start`.
|
|
109
|
+
- Host must register `createLoadSkillTool` and pass `skillsDisclosure: "progressive"` for catalog-only skill bodies.
|
|
110
|
+
- `caveman-stats` dispatches skill metadata only; full stats need host session-log integration.
|
|
111
|
+
- `caveman-init` returns upstream guidance text; it does not write files in the host repo.
|
|
112
|
+
- No TUI status bar; optional `caveman:status` events for host UI.
|
|
113
|
+
|
|
114
|
+
## Security and performance notes
|
|
115
|
+
|
|
116
|
+
- Upstream `SKILL.md` and injected text are untrusted host-supplied content; reads are size-bounded (`MAX_SKILL_FILE_BYTES` 256 KiB, `MAX_INJECTED_INSTRUCTION_BYTES` 32 KiB).
|
|
117
|
+
- Config read/write is bounded (`MAX_CONFIG_FILE_BYTES` 16 KiB) at host-owned `configPath` only.
|
|
118
|
+
- Errors redact home directories and absolute paths.
|
|
119
|
+
- Setup is O(skills) directory scan; mode read/write is O(1) per change; injection is O(1) upstream lookup per turn.
|
|
120
|
+
- Session custom entries respect host session ownership and redaction policies.
|
|
121
|
+
|
|
122
|
+
## Related APIs
|
|
123
|
+
|
|
124
|
+
- [Ponytail behavior integration](ponytail.md): complementary lazy-minimalism mode package.
|
|
125
|
+
- [Extension kernel and event bus](extensions.md): `kernel.load` and contribution registration.
|
|
126
|
+
- [Context and skills](context-and-skills.md): progressive disclosure + `createLoadSkillTool`.
|
|
127
|
+
- [Instruction injection](instruction-injection.md): `caveman-mode` injector selection.
|
|
128
|
+
- [Observational memory compaction package](compaction-observational-memory.md): `appendEntry` / `getEntries` attach precedent.
|
|
129
|
+
- [Migration guide](migration.md): `0.0.21 → 0.0.22` install and opt-in notes.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
`@arnilo/prism-coding-agent` is an optional first-party package that provides host shell/filesystem/repository tools as Prism `ToolDefinition` objects. It ships
|
|
5
|
+
`@arnilo/prism-coding-agent` is an optional first-party package that provides host shell/filesystem/repository tools as Prism `ToolDefinition` objects. It ships nine default coding tools — `shell`, `read`, `write`, `edit`, `repo_list`, `repo_search`, `glob`, `delete`, `move` — plus opt-in structured Git/check set (`createGitTools`), opt-in `createAskUserDecisionTool({ ask })`, and bounded coding-plan/checkpoint helpers. The tools are **inert** until a host imports them and registers them into a `ToolRegistry`. Hosts may register any subset, omit aggregators entirely, or mix first-party tools with host-owned `ToolDefinition`s. Behavior for shell/read/write/edit is a behavioral port of the pi coding agent's tools, adapted to Prism's `ToolDefinition` / `ToolResult` contracts (no `@earendil-works/*` or `typebox` dependencies; only `diff` plus the Node standard library). List/search/glob/Git are native Prism tools with no picomatch/ripgrep/Git-library dependency (hand-rolled `*`/`?`/`**` glob matcher).
|
|
6
6
|
|
|
7
7
|
| Export | Purpose |
|
|
8
8
|
| --- | --- |
|
|
@@ -11,14 +11,18 @@
|
|
|
11
11
|
| `createWriteTool(cwd, options?)` | `write` tool: create or overwrite a file, creating parent directories. |
|
|
12
12
|
| `createEditTool(cwd, options?)` | `edit` tool: precise exact-then-fuzzy text replacement in an existing file. |
|
|
13
13
|
| `createRepoListTool(cwd, options?)` | `repo_list` tool: bounded deterministic repository listing. |
|
|
14
|
-
| `createRepoSearchTool(cwd, options?)` | `repo_search` tool: bounded literal text search. |
|
|
15
|
-
| `
|
|
16
|
-
| `
|
|
14
|
+
| `createRepoSearchTool(cwd, options?)` | `repo_search` tool: bounded literal text search (`outputMode`: content / files_with_matches / count). |
|
|
15
|
+
| `createGlobTool(cwd, options?)` | `glob` tool: bounded filename-pattern match (`*` / `?` / `**`; no brace expansion). |
|
|
16
|
+
| `createDeleteTool(cwd, options?)` | `delete` tool: high-risk delete of a file or empty directory (no recursive delete, no trash). |
|
|
17
|
+
| `createMoveTool(cwd, options?)` | `move` tool: high-risk rename/move within the workspace (`overwrite` default false). |
|
|
18
|
+
| `createReadPathSet()` | Session-scoped path set for optional `requireReadBeforeWrite` soft guard. |
|
|
19
|
+
| `createCodingTools(cwd, options?)` | Default nine tools (`shell`, `read`, `write`, `edit`, `repo_list`, `repo_search`, `glob`, `delete`, `move`). |
|
|
20
|
+
| `createReadOnlyTools(cwd, options?)` | Read-only subset: `read`, `repo_list`, `repo_search`, `glob`. |
|
|
17
21
|
| `createAllTools(cwd, options?)` | Identical to `createCodingTools` (Git tools remain opt-in via `createGitTools`). |
|
|
18
22
|
| `createGitTools(cwd, options?)` | Opt-in Git tools (`git_status`/`git_diff`/`git_branch`/`git_worktree`/`git_apply`/`git_commit`/`git_pr_handoff`) plus optional `coding_check`. |
|
|
19
23
|
| `createCodingCheckTool(cwd, options)` | Named host-declared checks; model selects only a name. |
|
|
20
24
|
| `createAskUserDecisionTool(options)` | Opt-in user decision tool (`ask_user_decision`); host supplies `ask` callback. Not in default aggregators. |
|
|
21
|
-
| `createLocalRepositoryOperations(limits?)` | Default streaming Node filesystem backend for list/search. |
|
|
25
|
+
| `createLocalRepositoryOperations(limits?)` | Default streaming Node filesystem backend for list/search/glob. |
|
|
22
26
|
| `createGitOperations(options)` | Typed Git operations backend (argument arrays, safe config, finite output). |
|
|
23
27
|
| `buildCodingCheckpointMetadata` / `validateCodingCheckpointMetadata` / `assertCodingResumeAllowed` | Bounded durable coding-task metadata for workflow `state.coding` (no second runtime). |
|
|
24
28
|
| `writeCodingPlanFile` / `readCodingPlanFile` / `createCodingPlanMarkdown` / `parseCodingPlanTodos` | Workspace plan/todo Markdown helpers with finite byte/todo caps and hash verification. |
|
|
@@ -66,13 +70,39 @@ const tools = createCodingTools(workspaceRoot, {
|
|
|
66
70
|
| `read` | `read` |
|
|
67
71
|
| `write` | `write` |
|
|
68
72
|
| `edit` | `edit` |
|
|
69
|
-
| `repo_list` / `repo_search` | _(native; no pi equivalent)_ |
|
|
73
|
+
| `repo_list` / `repo_search` / `glob` | _(native; no pi equivalent)_ |
|
|
74
|
+
| `delete` / `move` | _(native; no pi equivalent)_ |
|
|
75
|
+
|
|
76
|
+
### Tool selection guide
|
|
77
|
+
|
|
78
|
+
| Need | Prefer | Avoid |
|
|
79
|
+
| --- | --- | --- |
|
|
80
|
+
| Enumerate directories | `repo_list` | `shell` `find`/`ls` |
|
|
81
|
+
| Match filename patterns | `glob` | `shell` `find` |
|
|
82
|
+
| Find text in files | `repo_search` | `shell` `grep`/`rg` |
|
|
83
|
+
| Read one file (paged) | `read` | `shell` `cat` |
|
|
84
|
+
| Create / full overwrite | `write` | — |
|
|
85
|
+
| Targeted replace | `edit` | full `write` rewrite when a small edit works |
|
|
86
|
+
| Remove file / empty dir | `delete` | `shell` `rm` |
|
|
87
|
+
| Rename / relocate | `move` | `shell` `mv` |
|
|
88
|
+
| Arbitrary process | `shell` | dedicated tools above |
|
|
89
|
+
|
|
90
|
+
### Phase 4 non-goals (0.0.21)
|
|
91
|
+
|
|
92
|
+
These are **out of scope** for this package release (see roadmap Phase 9 / later):
|
|
93
|
+
|
|
94
|
+
- **No PDF / document reader** — text and supported images only via `read`.
|
|
95
|
+
- **No trash / recycle daemon** — `delete` / `move` are permanent; host undo is not automatic.
|
|
96
|
+
- **No PTY / interactive process control** — `shell` is one-shot exec with bounded capture.
|
|
97
|
+
- **No LSP / language-server tools** — use host-owned tools if needed.
|
|
98
|
+
- **No recursive directory delete** — `delete` refuses non-empty directories.
|
|
99
|
+
- **No brace-expansion globs** — `glob` supports only `*`, `?`, and `**`.
|
|
70
100
|
|
|
71
101
|
## Inputs / request
|
|
72
102
|
|
|
73
103
|
### `shell`
|
|
74
104
|
|
|
75
|
-
Run a shell command and return combined stdout+stderr.
|
|
105
|
+
Run a shell command and return combined stdout+stderr. Prefer dedicated coding tools (table above) when they fit.
|
|
76
106
|
|
|
77
107
|
**Inputs:**
|
|
78
108
|
|
|
@@ -141,7 +171,7 @@ const read = createReadTool(cwd, {
|
|
|
141
171
|
|
|
142
172
|
### `write`
|
|
143
173
|
|
|
144
|
-
Create or overwrite a file, creating parent directories as needed.
|
|
174
|
+
Create or **overwrite** a file (full replace), creating parent directories as needed. Prefer `edit` for targeted changes.
|
|
145
175
|
|
|
146
176
|
**Inputs:**
|
|
147
177
|
|
|
@@ -149,6 +179,7 @@ Create or overwrite a file, creating parent directories as needed.
|
|
|
149
179
|
| --- | --- | --- |
|
|
150
180
|
| `path` | `string` | Path to the file to write (relative or absolute). Required. |
|
|
151
181
|
| `content` | `string` | Content to write (empty string creates an empty file). Required. |
|
|
182
|
+
| `force` | `boolean` | Bypass optional read-before-write guard when the host enabled `requireReadBeforeWrite`. |
|
|
152
183
|
|
|
153
184
|
**Outputs:** a `TextContent` confirmation naming the **absolute path** with UTF-8 byte and line counts (e.g. `Successfully wrote 42 bytes (3 lines) to /abs/path.txt`). `maxInputBytes` defaults to 8 MiB (64 MiB hard cap); oversized UTF-8 input fails before policy evaluation, directory creation, or write. Write failures and abort are error results. Empty `content` is valid.
|
|
154
185
|
|
|
@@ -156,6 +187,19 @@ Default local `writeFile` uses same-directory temp + `rename` so a crash mid-wri
|
|
|
156
187
|
|
|
157
188
|
`write` result `metadata`: `{ bytes, lines, path }` (absolute path). Concurrent writes to the same path serialize through `withFileMutationQueue`; writes to different paths run in parallel.
|
|
158
189
|
|
|
190
|
+
### Optional read-before-write guard
|
|
191
|
+
|
|
192
|
+
Hosts may opt in to a session-scoped soft guard: share one `createReadPathSet()` across `read` / `write` / `edit` and set `requireReadBeforeWrite: true` on write/edit options. Successful `read` marks the path; unread existing-file writes/edits fail with a clear error unless `force: true`. Default is **off** (no behavior change for hosts that ignore it).
|
|
193
|
+
|
|
194
|
+
```ts
|
|
195
|
+
import { createReadPathSet, createReadTool, createWriteTool, createEditTool } from "@arnilo/prism-coding-agent";
|
|
196
|
+
|
|
197
|
+
const readPaths = createReadPathSet();
|
|
198
|
+
const read = createReadTool(cwd, { readPathSet: readPaths });
|
|
199
|
+
const write = createWriteTool(cwd, { requireReadBeforeWrite: true, readPathSet: readPaths });
|
|
200
|
+
const edit = createEditTool(cwd, { requireReadBeforeWrite: true, readPathSet: readPaths });
|
|
201
|
+
```
|
|
202
|
+
|
|
159
203
|
### `edit`
|
|
160
204
|
|
|
161
205
|
Precise text replacement in an existing file via exact-then-fuzzy matching.
|
|
@@ -166,8 +210,13 @@ Precise text replacement in an existing file via exact-then-fuzzy matching.
|
|
|
166
210
|
| --- | --- | --- |
|
|
167
211
|
| `path` | `string` | Path to the file to edit. Required. |
|
|
168
212
|
| `edits` | `Array<{ oldText: string, newText: string }>` | Targeted replacements, each matched against the **original** file (not incrementally). No overlapping/nested edits. Required, non-empty. |
|
|
213
|
+
| `force` | `boolean` | Bypass optional read-before-write guard when enabled. |
|
|
214
|
+
|
|
215
|
+
Each `edits[].oldText` must match a unique, non-overlapping region of the original file. Matching is exact first, then fuzzy (unicode normalization / whitespace collapse).
|
|
169
216
|
|
|
170
|
-
|
|
217
|
+
**Fuzzy silent-success tradeoff (loud):** when exact match fails, fuzzy may still apply a replacement **without warning the model**. That can edit the wrong region if `oldText` is slightly off (extra/missing whitespace, unicode lookalikes). Prefer exact `oldText` copied from a fresh `read`. Duplicate / non-unique matches already **fail closed** and leave the file unchanged — ambiguity is not silently resolved by picking the first hit.
|
|
218
|
+
|
|
219
|
+
A BOM is stripped before matching and re-prepended on write; original line endings are restored. Defaults reject targets over 8 MiB, aggregate old/new UTF-8 input over 2 MiB, or more than 100 edits (hard caps: 64 MiB, 16 MiB, and 1,000). Stat and bounded read checks run before matching or mutation. Default local `writeFile` uses same-directory temp + `rename` (crash-safe replace).
|
|
171
220
|
|
|
172
221
|
**Outputs:** a `TextContent` confirmation (`Successfully replaced N block(s) in {path}.`) plus `metadata`. Any failure — missing/unreadable file, no match, duplicate (non-unique) match, overlap, empty `oldText`, no-op edit, or abort — is an error result, and the file is left **unchanged** (the match runs before the write).
|
|
173
222
|
|
|
@@ -175,7 +224,7 @@ Each `edits[].oldText` must match a unique, non-overlapping region of the origin
|
|
|
175
224
|
|
|
176
225
|
### `repo_list`
|
|
177
226
|
|
|
178
|
-
List repository entries with deterministic relative paths. Uses Node `opendir`/`lstat` only — no glob dependency. Does not follow symlinks; rejects path escapes outside the workspace root. Hidden names and excluded basenames (default `.git`, `node_modules`, `dist`) are skipped unless `includeHidden` is set / host `exclude` is overridden.
|
|
227
|
+
List repository entries with deterministic relative paths. Uses Node `opendir`/`lstat` only — no glob dependency. Prefer `glob` when you already know a filename pattern. Prefer `repo_search` to find text inside files. Does not follow symlinks; rejects path escapes outside the workspace root. Hidden names and excluded basenames (default `.git`, `node_modules`, `dist`) are skipped unless `includeHidden` is set / host `exclude` is overridden.
|
|
179
228
|
|
|
180
229
|
**Inputs:**
|
|
181
230
|
|
|
@@ -202,10 +251,59 @@ Search text files under the workspace using literal substring match. Binary file
|
|
|
202
251
|
| `mode` | `"literal"` | Literal only (default). `regex` removed in 0.0.18. |
|
|
203
252
|
| `caseSensitive` | `boolean` | Default false. |
|
|
204
253
|
| `includeHidden` | `boolean` | Default false. |
|
|
205
|
-
| `context` | `number` | Context lines before/after each match (default 5, hard 20). |
|
|
254
|
+
| `context` | `number` | Context lines before/after each match (default 5, hard 20). Ignored for non-content `outputMode`. |
|
|
206
255
|
| `maxMatches` | `number` | Match cap (default 1,000, hard 10,000). |
|
|
256
|
+
| `outputMode` | `"content"` \| `"files_with_matches"` \| `"count"` | Result shape (default `content`). |
|
|
257
|
+
|
|
258
|
+
**Outputs:**
|
|
259
|
+
- `content` (default): ripgrep-like lines `path:line:column:text` with optional `path-` / `path+` context.
|
|
260
|
+
- `files_with_matches`: unique matching paths only.
|
|
261
|
+
- `count`: totals (`N matches in M files`) without line bodies.
|
|
262
|
+
|
|
263
|
+
Metadata includes `matches`, `truncated`, scan/skip counts; non-content modes also expose `fileCount`.
|
|
264
|
+
|
|
265
|
+
### `glob`
|
|
266
|
+
|
|
267
|
+
Find workspace files by filename pattern without shell `find`. Hand-rolled matcher: `*` (one path segment), `?` (one char), `**` (directories). Brace expansion (`{a,b}`) is **rejected**. Patterns match workspace-relative full paths (e.g. `src/util/a.ts`). Returns **files only** (directories traversed but not listed). Same exclude/hidden/depth/page/time caps as `repo_list`.
|
|
207
268
|
|
|
208
|
-
**
|
|
269
|
+
**Inputs:**
|
|
270
|
+
|
|
271
|
+
| Field | Type | Purpose |
|
|
272
|
+
| --- | --- | --- |
|
|
273
|
+
| `pattern` | `string` | Glob pattern (required). |
|
|
274
|
+
| `path` | `string` | Workspace-relative start directory (default root). |
|
|
275
|
+
| `includeHidden` | `boolean` | Default false. |
|
|
276
|
+
| `maxDepth` | `number` | Depth cap (default 32, hard 128). |
|
|
277
|
+
| `maxResults` | `number` | Page size (default 1,000, hard 10,000). |
|
|
278
|
+
| `offset` | `number` | Matches to skip (default 0). |
|
|
279
|
+
|
|
280
|
+
**Outputs:** one relative path per line plus metadata (`truncated`, `truncatedBy`, `nextOffset`, scan counts). Continue with `offset=nextOffset` when truncated.
|
|
281
|
+
|
|
282
|
+
### `delete`
|
|
283
|
+
|
|
284
|
+
High-risk: permanently delete a **single file or empty directory**. Non-empty directories fail closed (no recursive delete). Symlinks are unlinked as links (targets not followed for containment). **No trash daemon** — host undo is not automatic; gate with approval policy.
|
|
285
|
+
|
|
286
|
+
**Inputs:**
|
|
287
|
+
|
|
288
|
+
| Field | Type | Purpose |
|
|
289
|
+
| --- | --- | --- |
|
|
290
|
+
| `path` | `string` | File or empty directory to delete. Required. |
|
|
291
|
+
|
|
292
|
+
**Outputs:** confirmation with absolute path, or error (missing, non-empty dir, escape, abort).
|
|
293
|
+
|
|
294
|
+
### `move`
|
|
295
|
+
|
|
296
|
+
High-risk: rename or move a file within the workspace. Dual-path mutation queue (lexicographic lock order). `overwrite` defaults **false**; when true, replaces an existing destination **file** only. Does not create parent directories. **No trash** — host undo is not automatic.
|
|
297
|
+
|
|
298
|
+
**Inputs:**
|
|
299
|
+
|
|
300
|
+
| Field | Type | Purpose |
|
|
301
|
+
| --- | --- | --- |
|
|
302
|
+
| `from` | `string` | Source path. Required. |
|
|
303
|
+
| `to` | `string` | Destination path. Required. |
|
|
304
|
+
| `overwrite` | `boolean` | Replace existing destination file (default false). |
|
|
305
|
+
|
|
306
|
+
**Outputs:** confirmation with absolute from/to, or error (missing source, dest exists without overwrite, escape, abort).
|
|
209
307
|
|
|
210
308
|
### Structured Git tools (`createGitTools`)
|
|
211
309
|
|
|
@@ -351,10 +449,10 @@ Minimal drop-in for any Prism app:
|
|
|
351
449
|
import { createToolRegistry } from "@arnilo/prism";
|
|
352
450
|
import { createCodingTools, createReadOnlyTools } from "@arnilo/prism-coding-agent";
|
|
353
451
|
|
|
354
|
-
// Full coding set (shell + read + write + edit + repo_list + repo_search
|
|
452
|
+
// Full coding set (shell + read + write + edit + repo_list + repo_search + glob + delete + move):
|
|
355
453
|
const tools = createToolRegistry(createCodingTools(process.cwd()));
|
|
356
454
|
|
|
357
|
-
// Or a read-only set for inspection-only agents (read + repo_list + repo_search):
|
|
455
|
+
// Or a read-only set for inspection-only agents (read + repo_list + repo_search + glob):
|
|
358
456
|
const ro = createToolRegistry(createReadOnlyTools(process.cwd()));
|
|
359
457
|
```
|
|
360
458
|
|
|
@@ -381,23 +479,27 @@ const remoteWrite = createWriteTool("/repo", {
|
|
|
381
479
|
});
|
|
382
480
|
```
|
|
383
481
|
|
|
482
|
+
Packed capability demo: `examples/coding-tools-capability-gaps.ts` (search modes, glob, read-before-write, delete/move).
|
|
483
|
+
|
|
384
484
|
## Extension and configuration notes
|
|
385
485
|
|
|
386
486
|
- **Long coding sessions.** Use `createCodingCompactionStrategy()` from optional `@arnilo/prism-compaction-llm` when history needs a bounded coding handoff. It is selected explicitly through normal `session.compact()` / agent compaction configuration, preserves raw session entries, and prioritizes file paths, patch intent, checks, plan/todo state, blockers, and verification steps. It does not read files, retain full diffs, or create a second coding runtime.
|
|
387
|
-
- **Pluggable operation backends.** Every tool accepts an `operations` seam. Custom `ReadOperations` must implement bounded `readText` plus `statFile`; custom `EditOperations` must implement `statFile`; read/write methods receive caps/signals. `BashOperations` must stream through `onData` and honor `signal`/`timeout`. Custom `RepositoryOperations` must honor depth/entry/file/match/scan/time caps and abort. A hostile custom backend can still violate its host-owned contract, so isolate it separately.
|
|
388
|
-
- **Per-tool options.** `ShellToolOptions` adds `timeout` and `maxTotalOutputBytes`; `ReadToolOptions` adds `maxScanBytes`; `WriteToolOptions`
|
|
389
|
-
- **Aggregator options.** `ToolsOptions` (`{ executionPolicy?, shell?, read?, write?, edit?, list?, search?, repository? }`) threads each sub-object to the matching tool. `createCodingTools()`, `createAllTools()`, and `createReadOnlyTools()` apply the shared policy unless that tool has an explicit per-tool override.
|
|
390
|
-
- **Sandbox composition.** Prefer `@arnilo/prism-coding-security` `createSandboxCodingComposition(cwd, { workspaceMode, sandbox, ... })` (or tools-only wrappers). `workspaceMode` is required: `"sandbox"` keeps shell/read/write/edit/list/search on one disposable tree; `"host"` runs against host cwd and never claims containment. Mixed sandbox-shell + host-FS wiring throws unless `allowMixedWorkspaceWiring: true`. Same-tree Git: `createGitTools(composition.workspaceRoot, { execFile: sandbox.execFile, commitIdentity })`.
|
|
487
|
+
- **Pluggable operation backends.** Every tool accepts an `operations` seam. Custom `ReadOperations` must implement bounded `readText` plus `statFile`; custom `EditOperations` must implement `statFile`; read/write methods receive caps/signals. `BashOperations` must stream through `onData` and honor `signal`/`timeout`. Custom `RepositoryOperations` must honor depth/entry/file/match/scan/time caps and abort (including `glob`). Custom `DeleteOperations` / `MoveOperations` must honor containment and abort. A hostile custom backend can still violate its host-owned contract, so isolate it separately.
|
|
488
|
+
- **Per-tool options.** `ShellToolOptions` adds `timeout` and `maxTotalOutputBytes`; `ReadToolOptions` adds `maxScanBytes` and optional `readPathSet`; `WriteToolOptions` / `EditToolOptions` add input caps plus optional `requireReadBeforeWrite` / `readPathSet` / `force`; list/search/glob accept `repository` limits and shared aggregator `ToolsOptions.repository`.
|
|
489
|
+
- **Aggregator options.** `ToolsOptions` (`{ executionPolicy?, shell?, read?, write?, edit?, delete?, move?, list?, search?, glob?, repository? }`) threads each sub-object to the matching tool. `createCodingTools()`, `createAllTools()`, and `createReadOnlyTools()` apply the shared policy unless that tool has an explicit per-tool override. Full membership is nine tools; read-only is `read` + `repo_list` + `repo_search` + `glob`.
|
|
490
|
+
- **Sandbox composition.** Prefer `@arnilo/prism-coding-security` `createSandboxCodingComposition(cwd, { workspaceMode, sandbox, ... })` (or tools-only wrappers). `workspaceMode` is required: `"sandbox"` keeps shell/read/write/edit/list/search/glob/delete/move on one disposable tree; `"host"` runs against host cwd and never claims containment. Mixed sandbox-shell + host-FS wiring throws unless `allowMixedWorkspaceWiring: true`. Same-tree Git: `createGitTools(composition.workspaceRoot, { execFile: sandbox.execFile, commitIdentity })`.
|
|
391
491
|
- **`ToolsOptions`** and the per-tool option types are exported from the package barrel for host configuration.
|
|
392
492
|
- No auto-discovery or manifest registration: import and register explicitly. This package registers no extensions and owns no globals (the mutation queue is a process-wide per-path map — see `ponytail:` note in the source).
|
|
393
493
|
|
|
394
494
|
## Security and performance notes
|
|
395
495
|
|
|
396
|
-
- **Host shell/filesystem access.** These tools run real commands and read/write/list/search real files. They provide **no sandbox**. Gate them with Prism `PermissionPolicy` / `ToolValidator` / trust policies before registering them for any provider turn. Shared `executionPolicy` applies to both full and read-only aggregators before filesystem/process side effects. See [Host security guide](host-security.md) and [Security/auth/trust](settings-auth-trust-security.md).
|
|
496
|
+
- **Host shell/filesystem access.** These tools run real commands and read/write/list/search/glob/delete/move real files. They provide **no sandbox**. Gate them with Prism `PermissionPolicy` / `ToolValidator` / trust policies before registering them for any provider turn. Shared `executionPolicy` applies to both full and read-only aggregators before filesystem/process side effects. See [Host security guide](host-security.md) and [Security/auth/trust](settings-auth-trust-security.md).
|
|
497
|
+
- **High-risk mutations.** `delete` and `move` are permanent (no trash). Prefer host confirmation via `ExecutionPolicy` before allowing them. Do not instruct models to bypass policy/sandbox.
|
|
397
498
|
- **Non-zero exit is not an error.** A failing command is a normal `shell` result (exit code in metadata); only timeout/abort/spawn failures are error results. Do not assume `error == undefined` means the command succeeded.
|
|
398
|
-
- **Bounded I/O.** `read` streams one page and bounds scan bytes; image/edit reads use stat plus a shared cap-enforcing reader; write/edit inputs are measured before mutation. `repo_list`/`repo_search` stream walks and charge depth/entry/file/match/scan/time before retention. Structured Git tools use argument arrays with finite output/path/ref/message/patch caps, disable hooks/credential prompts/external diff by default, and never push or open PRs. `shell` retains only a rolling display tail and synchronously spills accepted raw chunks so stream backpressure cannot grow heap; wall time and total raw output remain finite.
|
|
399
|
-
- **Per-path serialization.** Concurrent mutations to the same file serialize; concurrent mutations to different files do not block each other. The queue is a process-wide map — across sessions in one process, same-path writes still serialize (upgrade path: scope per registry if throughput matters).
|
|
499
|
+
- **Bounded I/O.** `read` streams one page and bounds scan bytes; image/edit reads use stat plus a shared cap-enforcing reader; write/edit inputs are measured before mutation. `repo_list`/`repo_search`/`glob` stream walks and charge depth/entry/file/match/scan/time before retention. Structured Git tools use argument arrays with finite output/path/ref/message/patch caps, disable hooks/credential prompts/external diff by default, and never push or open PRs. `shell` retains only a rolling display tail and synchronously spills accepted raw chunks so stream backpressure cannot grow heap; wall time and total raw output remain finite.
|
|
500
|
+
- **Per-path serialization.** Concurrent mutations to the same file serialize; concurrent mutations to different files do not block each other. `move` locks both paths in lexicographic order. The queue is a process-wide map — across sessions in one process, same-path writes still serialize (upgrade path: scope per registry if throughput matters).
|
|
400
501
|
- **Bounded image reads.** `read` rejects images over `maxImageBytes` (default 10 MB) by `stat` before read when possible; MIME is detected from magic bytes only. Optional `transformImage` is host-owned — the base package has no image-processing dependency.
|
|
502
|
+
- **Fuzzy edit risk.** Silent fuzzy success can mis-apply edits; duplicate matches fail closed. See the `edit` section above.
|
|
401
503
|
|
|
402
504
|
### Resource-limit defaults and hard caps
|
|
403
505
|
|
package/docs/coding-security.md
CHANGED
|
@@ -26,14 +26,14 @@ import type { ExecutionAction, ExecutionPolicy, ExecutionDecision } from "@arnil
|
|
|
26
26
|
|
|
27
27
|
Use this package when coding tools need path scoping, human approval, command rules, or a pluggable sandbox backend. Wire the returned policy through `createCodingTools(cwd, { executionPolicy })` or per-tool `executionPolicy` options.
|
|
28
28
|
|
|
29
|
-
Use `createDockerSandbox()` when the host wants a production-reference containment boundary. Prism does **not** claim OS-level isolation unless the host constructs this adapter (or supplies an equivalent custom `DisposableSandbox`). Default policy denies shell/write/edit without an `approve` callback and rejects paths outside configured roots. Coding shell definitions are marked `exclusive: true`, matching the approval policy's shell decision, so a single-shot turn containing shell work runs sequentially even when `toolConcurrency > 1`. Non-shell turns retain configured parallelism.
|
|
29
|
+
Use `createDockerSandbox()` when the host wants a production-reference containment boundary. Prism does **not** claim OS-level isolation unless the host constructs this adapter (or supplies an equivalent custom `DisposableSandbox`). Default policy denies shell/write/edit/delete/move without an `approve` callback and rejects paths outside configured roots. Coding shell definitions are marked `exclusive: true`, matching the approval policy's shell decision, so a single-shot turn containing shell work runs sequentially even when `toolConcurrency > 1`. Non-shell turns retain configured parallelism.
|
|
30
30
|
|
|
31
31
|
## Inputs / request
|
|
32
32
|
|
|
33
33
|
| Option | Default | Purpose |
|
|
34
34
|
| --- | --- | --- |
|
|
35
35
|
| `roots` | required | Realpath-contained filesystem roots. |
|
|
36
|
-
| `readOnly` | `false` | Deny shell/write/edit
|
|
36
|
+
| `readOnly` | `false` | Deny non-`read` actions (including shell/write/edit/delete/move). |
|
|
37
37
|
| `commandRules` | `[]` | Ordered allow/deny/approval command classification. |
|
|
38
38
|
| `approve` | none | Host callback for actions not statically allowed; omission fails closed. |
|
|
39
39
|
| `approvalCacheScope` | `"none"` | Optional `run` or `session` decision cache scope. |
|
|
@@ -110,7 +110,7 @@ const sandbox = await createDockerSandbox({
|
|
|
110
110
|
limits: { cpus: 2, memoryBytes: 2 * 1024 ** 3, maxPids: 256, workspaceBytes: 1024 ** 3 },
|
|
111
111
|
});
|
|
112
112
|
|
|
113
|
-
// Sandbox mode: shell/read/write/edit/list/search share one disposable tree.
|
|
113
|
+
// Sandbox mode: shell/read/write/edit/list/search/glob/delete/move share one disposable tree.
|
|
114
114
|
const { tools, composition } = createSandboxCodingComposition("/srv/jobs/task-1/source", {
|
|
115
115
|
workspaceMode: "sandbox",
|
|
116
116
|
sandbox,
|
|
@@ -196,6 +196,17 @@ await agent.createSession().run("…", { activeSkills: ["ponytail"] });
|
|
|
196
196
|
// Turn 1: catalog only. After load_skill({ name: "ponytail" }), later turns include instructions.
|
|
197
197
|
```
|
|
198
198
|
|
|
199
|
+
### Third-party behavior packages (Caveman, Ponytail)
|
|
200
|
+
|
|
201
|
+
`@arnilo/prism-caveman` and `@arnilo/prism-ponytail` register upstream skills into the extension kernel skill registry. Hosts should:
|
|
202
|
+
|
|
203
|
+
1. `kernel.load([createCavemanExtension(...), createPonytailExtension(...)])` with session `appendEntry` / `getEntries` callbacks.
|
|
204
|
+
2. Build `createSkillRegistry(kernel.registries.skills.list())` and pass `activeSkills` / `resolveActiveSkills` names.
|
|
205
|
+
3. Keep `skillsDisclosure: "progressive"` and register `createLoadSkillTool` — full `SKILL.md` bodies stay catalog-only until `load_skill`.
|
|
206
|
+
4. Select `instructionInjectors: ["caveman-mode", "ponytail-mode"]` (or subset) for mode/level slices **without** forcing `skillsDisclosure: "eager"`.
|
|
207
|
+
|
|
208
|
+
Mode slices and skill bodies are independent: the injector can add `PONYTAIL MODE ACTIVE` while `ponytail-audit` remains catalog-only until loaded. See [Caveman](caveman.md), [Ponytail](ponytail.md), and `examples/caveman-ponytail.ts`.
|
|
209
|
+
|
|
199
210
|
Pure validation without the tool: `resolveSkillLoad({ registry, name, tools, loaded, activeSkillNames })`.
|
|
200
211
|
|
|
201
212
|
### Context budget priority and skill demotion
|
package/docs/extensions.md
CHANGED
|
@@ -140,6 +140,8 @@ await kernel.middleware.run("provider_request", { metadata: {} });
|
|
|
140
140
|
- [Compaction and retry policies](compaction-and-retry.md): compaction strategy/retry policy contributions and `compaction`/`retry` middleware runtime behavior.
|
|
141
141
|
- [LLM compaction package](compaction-llm.md): optional extension helper that registers a provider-backed compaction strategy.
|
|
142
142
|
- [Observational memory compaction package](compaction-observational-memory.md): optional extension helper that registers an inert fast memory compaction strategy.
|
|
143
|
+
- [Caveman behavior integration](caveman.md): optional `@arnilo/prism-caveman` upstream Caveman skills, commands, level injector, and session `caveman-level` persistence.
|
|
144
|
+
- [Ponytail behavior integration](ponytail.md): optional `@arnilo/prism-ponytail` upstream Ponytail skills, commands, mode injector, and session `ponytail-mode` persistence.
|
|
143
145
|
- [Public contracts](public-contracts.md): `Extension`, `ExtensionAPI`, and contribution contract types.
|
|
144
146
|
- [Credentials and redaction](credentials-and-redaction.md): secret-redaction behavior used for extension errors.
|
|
145
147
|
|
package/docs/index.md
CHANGED
|
@@ -34,7 +34,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
34
34
|
- [Database persistence](database-persistence.md): production persistence contracts, shared checksummed migration/full-shape catalog primitives (`@arnilo/prism/testing/persistence-schema`), conditional append, indexes, `readBranchPath`, reference relational schema, retention/legal-hold/quota lifecycle (`lifecycle`), and NoSQL mapping.
|
|
35
35
|
- [SQLite persistence](sqlite-persistence.md): optional `better-sqlite3` adapter with session/run storage, checkpoints/leases, feedback, FTS `searchSessions` (migration-v4), and transactionally verified/backfilled migration metadata.
|
|
36
36
|
- [PostgreSQL persistence](postgres-persistence.md): optional pooled `pg` adapter with session/run/checkpoint/lease/feedback storage, FTS `searchSessions` (migration-v4), advisory-locked checksummed/full-shape migrations, and opt-in live conformance.
|
|
37
|
-
- [Migration guide](migration.md): **0.0.20** progressive skill disclosure, empty registry default, `load_skill`, priority budget demotion, optional tool-result fold; **0.0.19** observational memory lifecycle; **0.0.15** OpenAI hosted tools/continuation/Realtime, exact AI SDK v4 matrix, RAG lifecycle/reranking/trust/status, and memory export/rebuild; **0.0.14** conversations, memory consent/lifecycle, artifact co-work review, AG-UI co-work events, scoped M365/GWS OAuth connectors, browser checkpoints, device contracts, and Alibaba/Ollama providers; plus prior release migrations.
|
|
37
|
+
- [Migration guide](migration.md): **0.0.22** third-party behavior integrations (Caveman, Ponytail); **0.0.21** coding-tool capability gaps (`outputMode`, glob, read-before-write, delete/move, aggregator 9/4); **0.0.20** progressive skill disclosure, empty registry default, `load_skill`, priority budget demotion, optional tool-result fold; **0.0.19** observational memory lifecycle; **0.0.15** OpenAI hosted tools/continuation/Realtime, exact AI SDK v4 matrix, RAG lifecycle/reranking/trust/status, and memory export/rebuild; **0.0.14** conversations, memory consent/lifecycle, artifact co-work review, AG-UI co-work events, scoped M365/GWS OAuth connectors, browser checkpoints, device contracts, and Alibaba/Ollama providers; plus prior release migrations.
|
|
38
38
|
- [Node JSONL session store](node-jsonl-session-store.md): development-only JSONL file adapter for single-process Node hosts; no cross-process safety; `searchSessions` throws `SessionSearchUnsupportedError`.
|
|
39
39
|
- [Persistence, credentials, and multimodality primitives](persistence-credentials-multimodality-primitives.md): Plan 056 inventory — session/run-ledger/persistence contracts, credential/OAuth seams, content/resource/model capabilities, package dependency matrix, conformance matrix, and threat model for production adapters.
|
|
40
40
|
|
|
@@ -71,7 +71,7 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
71
71
|
- [Work connectors](work-connectors.md): connector principles, capability gates, scoped OAuth establishment (0.0.14), and out-of-scope boundaries (Slack/Teams channels not shipped) for Microsoft 365 / Google Workspace.
|
|
72
72
|
- [Browser automation](browser-automation.md): optional `@arnilo/prism-browser` with host-supplied Playwright contexts, AI-mode snapshots/refs, ordered `browser_open`/`browser_snapshot`/`browser_act`/`browser_close`, egress/side-effect/upload/download/screenshot policy, finite page/action/snapshot/network/artifact caps, and 0.0.14 verified-state checkpoints with reload/verify-before-side-effect.
|
|
73
73
|
- [Device adapters](device-adapters.md): deny-by-default realtime voice / desktop-control contract + conformance (0.0.14); no vendor package — admission fails closed without explicit consent+sandbox+approval, stream bounds, shared `RunLimits`, redacted telemetry.
|
|
74
|
-
- [Coding agent tools](coding-agent-tools.md): optional `shell`, `read`, `write`, `edit`, `repo_list`, and `
|
|
74
|
+
- [Coding agent tools](coding-agent-tools.md): optional `shell`, `read`, `write`, `edit`, `repo_list`, `repo_search`, `glob`, `delete`, and `move` definitions plus opt-in `createGitTools()` / `coding_check`, opt-in `createAskUserDecisionTool` (single/multi/free-text + durable suspend glue), and `runCodingGoalVerify`; durable plan/todo Markdown helpers with workflow `state.coding` checkpoint metadata; streamed text pages, `repo_search` `outputMode`, bounded glob, optional read-before-write, finite Git/check/plan/ask caps, bounded image/edit reads and write/edit payloads, finite shell wall/total-output limits, secure host-owned spill cleanup, pluggable bounded operation contracts, per-path mutation serialization, and optional `ExecutionPolicy`. No PDF/trash/PTY/LSP in 0.0.21. Limits do not sandbox host access—gate with permission/trust policy and `@arnilo/prism-coding-security`.
|
|
75
75
|
- [Coding execution approval and sandboxing](coding-security.md): path/command approval, identity-scoped caching, shell-turn exclusivity, required `workspaceMode` (`host`/`sandbox`) with fail-closed mixed wiring, `createSandboxCodingComposition()` containment metadata, and the disposable Docker/OCI sandbox reference with bounded workspace import/export.
|
|
76
76
|
|
|
77
77
|
## Extensions/plugins
|
|
@@ -114,11 +114,15 @@ Prism is a TypeScript/Node.js agent harness. Host apps and extension packages ow
|
|
|
114
114
|
- [Compaction conformance](compaction-conformance.md): assert any `CompactionStrategy` returns a non-empty redacted summary and observes abort from `@arnilo/prism/testing/compaction-conformance`.
|
|
115
115
|
- [Tool conformance](tool-conformance.md): assert the tool-dispatch blocked-reason matrix (unknown/denied/invalid/permission/validator) and success path from `@arnilo/prism/testing/tool-conformance`.
|
|
116
116
|
- [Extension conformance](extension-conformance.md): assert an `Extension` setup runs, contributions stay inert, and setup errors are redacted or rethrown from `@arnilo/prism/testing/extension-conformance`.
|
|
117
|
-
- `examples/`: compile-checked typed examples and runnable mock demos (SDK basics, provider registration, auth, tools, [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts), [`examples/enterprise-identity.ts`](../examples/enterprise-identity.ts), [`examples/enterprise-policy-audit.ts`](../examples/enterprise-policy-audit.ts), [`examples/enterprise-work-connectors.ts`](../examples/enterprise-work-connectors.ts), [`examples/conversation-durable-replay.ts`](../examples/conversation-durable-replay.ts), [`examples/artifact-review-delivery.ts`](../examples/artifact-review-delivery.ts), [`examples/server-deployment-seams.ts`](../examples/server-deployment-seams.ts), cache-aware prompt assembly, NeuralWatt agent run ([`examples/neuralwatt-agent-run.ts`](../examples/neuralwatt-agent-run.ts)), [`examples/coding-compaction.ts`](../examples/coding-compaction.ts), stores/branching, structured-output/artifact-loop, CLI, RPC, workflow orchestration).
|
|
117
|
+
- `examples/`: compile-checked typed examples and runnable mock demos (SDK basics, provider registration, auth, tools, [`examples/ag-ui-server.ts`](../examples/ag-ui-server.ts), [`examples/enterprise-identity.ts`](../examples/enterprise-identity.ts), [`examples/enterprise-policy-audit.ts`](../examples/enterprise-policy-audit.ts), [`examples/enterprise-work-connectors.ts`](../examples/enterprise-work-connectors.ts), [`examples/conversation-durable-replay.ts`](../examples/conversation-durable-replay.ts), [`examples/artifact-review-delivery.ts`](../examples/artifact-review-delivery.ts), [`examples/server-deployment-seams.ts`](../examples/server-deployment-seams.ts), cache-aware prompt assembly, NeuralWatt agent run ([`examples/neuralwatt-agent-run.ts`](../examples/neuralwatt-agent-run.ts)), [`examples/coding-compaction.ts`](../examples/coding-compaction.ts), [`examples/caveman-ponytail.ts`](../examples/caveman-ponytail.ts), stores/branching, structured-output/artifact-loop, CLI, RPC, workflow orchestration).
|
|
118
|
+
|
|
119
|
+
## Third-party integrations
|
|
120
|
+
- [Caveman behavior integration](caveman.md): optional `@arnilo/prism-caveman` — upstream Caveman skills/commands, `caveman-mode` injector, session `caveman-level` persistence, progressive catalog + `load_skill`; requires host `upstreamPath` and session attach callbacks; inert until `kernel.load`.
|
|
121
|
+
- [Ponytail behavior integration](ponytail.md): optional `@arnilo/prism-ponytail` — upstream Ponytail skills/commands, `ponytail-mode` injector, session `ponytail-mode` persistence; resolves peer `@dietrichgebert/ponytail` or `upstreamPath`; opt-in (not in code/sdk profiles).
|
|
118
122
|
|
|
119
123
|
## Release and install
|
|
120
|
-
- [Release and install](release-and-install.md): current **0.0.
|
|
121
|
-
- [0.1.0 / 1.0 readiness gates](0.1.0-readiness.md): command-per-gate 1.0 readiness table — frozen API surface + compat gate, migration/docs tripwires, budget table, live-suite matrix, security matrix, current-line status (**0.0.
|
|
124
|
+
- [Release and install](release-and-install.md): current **0.0.22** 46-package graph (Phase 5 Caveman/Ponytail behavior integrations; plan 005), exact-peer/install/tarball rules, deterministic resumable publication and publish dry-run, pinned supply-chain gates, offline tests, the 0.0.15 provider/AI-SDK/RAG/memory protected live-canary matrix, and sandbox-browser Docker/Playwright gates.
|
|
125
|
+
- [0.1.0 / 1.0 readiness gates](0.1.0-readiness.md): command-per-gate 1.0 readiness table — frozen API surface + compat gate, migration/docs tripwires, budget table, live-suite matrix, security matrix, current-line status (**0.0.22** published target), signed-publication/live-canary prerequisites for 1.0, and Phase 12 demand-evidence entry criteria.
|
|
122
126
|
- [Review coverage (2026-07-26 Phase 11)](review-coverage-2026-07-26-phase-11.md): Plan 079 evidence freeze — baseline size/startup/benchmark budgets, hotspot domain extraction table, confirmed duplication survivors (redactor/cleanJson/row-codecs/checkpoints/exec-runner/approval/ownership), profile adoption recommendations, and tarball artifact-diet findings for 0.0.16.
|
|
123
127
|
- [Review coverage (2026-07-26 Phase 10)](review-coverage-2026-07-26-phase-10.md): Plan 078 evidence freeze — OpenAI hosted tools/continuation/realtime, AI SDK version matrix, remaining provider metadata parity, RAG replaceSource/loaders/parsers/reranker/provenance/ingestion-status, memory export/rebuild/conformance, and 0.0.15 (43 → 43 manifests; no new package) release gates.
|
|
124
128
|
- [Review coverage (2026-07-25 Phase 9)](review-coverage-2026-07-25-phase-9.md): Plan 077 evidence freeze — conversation service, memory consent/lifecycle, artifact co-work review, AG-UI co-work events, scoped M365/GWS OAuth, browser checkpoint composition, and deny-by-default device contracts for 0.0.14 (41 → 43 manifests; only the two provider packages are new).
|
package/docs/migration.md
CHANGED
|
@@ -1,5 +1,54 @@
|
|
|
1
1
|
# Migration guide
|
|
2
2
|
|
|
3
|
+
## 0.0.21 → 0.0.22 third-party behavior integrations (additive)
|
|
4
|
+
|
|
5
|
+
Release **0.0.22** adds two optional behavior packages; core `@arnilo/prism` runtime behavior is unchanged.
|
|
6
|
+
|
|
7
|
+
1. **New packages (opt-in).** `@arnilo/prism-caveman` and `@arnilo/prism-ponytail` wire upstream Caveman and Ponytail into Prism extension contracts. They are **not** included in `@arnilo/prism-code`, `@arnilo/prism-sdk`, or `@arnilo/prism-all` by default — install explicitly when needed.
|
|
8
|
+
2. **Inert until loaded.** Import registers nothing. Host calls `createExtensionKernel().load([createCavemanExtension(...)])` / `createPonytailExtension(...)`.
|
|
9
|
+
3. **Session attach required.** Both factories require host `appendEntry` and `getEntries` callbacks (same pattern as observational memory `attach`) for mode/level persistence (`caveman-level`, `ponytail-mode` custom entries).
|
|
10
|
+
4. **Progressive disclosure.** Keep `skillsDisclosure: "progressive"` and register `createLoadSkillTool`; mode/level slices come from `caveman-mode` / `ponytail-mode` instruction injectors, not eager full `SKILL.md` bodies.
|
|
11
|
+
5. **Upstream resolution.** Caveman requires `upstreamPath` to a [juliusbrussee/caveman](https://github.com/juliusbrussee/caveman) checkout (`skills/` marker). Ponytail resolves optional peer `@dietrichgebert/ponytail@^4.8.4` or `upstreamPath`. Missing upstream → `setup` throws; zero contributions registered.
|
|
12
|
+
6. **Publish graph.** Publishable manifest count is **46** (was 44).
|
|
13
|
+
|
|
14
|
+
Example: `node examples/caveman-ponytail.ts` (network-free fixture upstream trees).
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { createCavemanExtension } from "@arnilo/prism-caveman";
|
|
18
|
+
import { createPonytailExtension } from "@arnilo/prism-ponytail";
|
|
19
|
+
|
|
20
|
+
await kernel.load([
|
|
21
|
+
createCavemanExtension({ upstreamPath: "/path/to/caveman", appendEntry, getEntries }),
|
|
22
|
+
createPonytailExtension({ defaultMode: "full", appendEntry, getEntries }),
|
|
23
|
+
]);
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
No breaking changes for hosts that do not install the new packages.
|
|
27
|
+
|
|
28
|
+
## 0.0.20 → 0.0.21 coding-tool capability gaps (small intentional breaks)
|
|
29
|
+
|
|
30
|
+
Release **0.0.21** completes Phase 4 coding-tool capability gaps in `@arnilo/prism-coding-agent` / `@arnilo/prism-coding-security`:
|
|
31
|
+
|
|
32
|
+
1. **`repo_search` gains `outputMode`.** Optional `outputMode?: "content" | "files_with_matches" | "count"` (default `"content"`). Files-only and count modes omit match body text from model content; invalid values fail closed.
|
|
33
|
+
2. **Bounded `glob` tool.** `createGlobTool` / aggregator membership; `*` / `?` / `**` only (no brace expansion); reuses repository walk limits; files only.
|
|
34
|
+
3. **Optional read-before-write.** Host sets `requireReadBeforeWrite: true` with a shared `ReadPathSet` on read/write/edit; unread paths fail unless `force: true`. In-memory / session-scoped only — not checkpoint-persisted.
|
|
35
|
+
4. **Bounded `delete` and `move`.** File or empty directory delete (no recursive); move with `overwrite` default `false`; high-risk `ExecutionPolicy` kinds; host undo is not automatic.
|
|
36
|
+
5. **Aggregator membership.** `createCodingTools` → **9** tools (adds `glob`, `delete`, `move`); `createReadOnlyTools` → **4** (adds `glob`). Hosts asserting exact `.length` must update.
|
|
37
|
+
6. **Approval / sandbox.** `isMutatingKind` includes `delete` and `move` (not `glob`). Full sandbox custom ops must supply delete/move backends; `RepositoryOperations` requires `glob`.
|
|
38
|
+
|
|
39
|
+
Example: `node examples/coding-tools-capability-gaps.ts` (network-free).
|
|
40
|
+
|
|
41
|
+
```ts
|
|
42
|
+
const tools = createCodingTools(cwd); // length 9
|
|
43
|
+
const search = createRepoSearchTool(cwd);
|
|
44
|
+
await search.execute({ query: "TODO", outputMode: "files_with_matches" }, ctx);
|
|
45
|
+
|
|
46
|
+
const readPathSet = createReadPathSet();
|
|
47
|
+
const write = createWriteTool(cwd, { requireReadBeforeWrite: true, readPathSet });
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Fuzzy edit may still succeed silently on a normalized whitespace/unicode match — docs state that tradeoff; ambiguous multi-match already fails closed. No PDF/trash/PTY/LSP in 0.0.21.
|
|
51
|
+
|
|
3
52
|
## 0.0.19 → 0.0.20 skills and context progressive disclosure (small intentional breaks)
|
|
4
53
|
|
|
5
54
|
Release **0.0.20** completes Phase 3 progressive skill disclosure in core `@arnilo/prism`:
|
package/docs/ponytail.md
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# Ponytail behavior integration
|
|
2
|
+
|
|
3
|
+
## What it does
|
|
4
|
+
|
|
5
|
+
`@arnilo/prism-ponytail` is an optional package that wires [DietrichGebert/ponytail](https://github.com/DietrichGebert/ponytail) into Prism contribution contracts.
|
|
6
|
+
|
|
7
|
+
It registers upstream skills and commands, injects active mode instructions via upstream `getPonytailInstructions` / `filterSkillBodyForMode`, and persists mode as session custom `ponytail-mode` entries. Import is inert; missing upstream fails closed at `setup` with a bounded redacted error.
|
|
8
|
+
|
|
9
|
+
## When to use it
|
|
10
|
+
|
|
11
|
+
Use it when a host wants lazy-minimalism coding behavior (`lite`, `full`, `ultra`) with upstream Ponytail skills (`ponytail-audit`, `ponytail-debt`, `ponytail-gain`, `ponytail-help`, `ponytail-review`) in a Prism extension kernel.
|
|
12
|
+
|
|
13
|
+
Install optional peer `@dietrichgebert/ponytail@^4.8.4` **or** pass `upstreamPath` to a checkout with `skills/` and `hooks/`.
|
|
14
|
+
|
|
15
|
+
Pair with progressive disclosure: mode slices on the `ponytail-mode` injector; full skill bodies via `load_skill` only.
|
|
16
|
+
|
|
17
|
+
## Inputs / request
|
|
18
|
+
|
|
19
|
+
`createPonytailExtension(options)`:
|
|
20
|
+
|
|
21
|
+
| Field | Type | Required | Purpose |
|
|
22
|
+
| --- | --- | --- | --- |
|
|
23
|
+
| `upstreamPath` | `string` | no | Override path to Ponytail root; default resolves optional peer package. |
|
|
24
|
+
| `defaultMode` | `PonytailMode` | no | Initial mode when no session entry exists (default `full`). |
|
|
25
|
+
| `quietStartup` | `boolean` | no | Suppress startup status events. |
|
|
26
|
+
| `appendEntry` | `(entry, opts?) => Promise<void>` | yes | Host session append (OM `attach` pattern). |
|
|
27
|
+
| `getEntries` | `() => readonly SessionEntry[] \| Promise<...>` | yes | Current branch entries for mode restore. |
|
|
28
|
+
| `configPath` | `string` | no | Bounded local config for `defaultMode` / `quietStartup` / `hideStatus`. |
|
|
29
|
+
|
|
30
|
+
`PonytailMode`: `off` \| `lite` \| `full` \| `ultra`.
|
|
31
|
+
|
|
32
|
+
Session custom entry shape:
|
|
33
|
+
|
|
34
|
+
```json
|
|
35
|
+
{ "kind": "custom", "data": { "type": "ponytail-mode", "mode": "full" } }
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Registered skills: `ponytail`, `ponytail-audit`, `ponytail-debt`, `ponytail-gain`, `ponytail-help`, `ponytail-review`.
|
|
39
|
+
|
|
40
|
+
Registered commands: `ponytail`, `ponytail-review`, `ponytail-audit`, `ponytail-gain`, `ponytail-debt`, `ponytail-help`.
|
|
41
|
+
|
|
42
|
+
`ponytail` command actions: `lite|full|ultra|off`, `status`, `default <mode>`.
|
|
43
|
+
|
|
44
|
+
## Outputs / response / events
|
|
45
|
+
|
|
46
|
+
| Export | Purpose |
|
|
47
|
+
| --- | --- |
|
|
48
|
+
| `createPonytailExtension(options)` | Returns an inert `Extension` until `kernel.load([...])`. |
|
|
49
|
+
| `ponytail-mode` injector | `InstructionInjector` calling upstream `getPonytailInstructions(mode)`. |
|
|
50
|
+
| `ponytail` command | Set mode, report status, or persist default mode to config file. |
|
|
51
|
+
| Alias commands | Dispatch `{ skill, dispatch: "load_skill" }` for companion skills. |
|
|
52
|
+
| `ponytail:status` / `ponytail:loaded` events | Optional host metadata (no statusline shell scripts). |
|
|
53
|
+
|
|
54
|
+
Deactivation: exact phrases `stop ponytail` and `normal mode`.
|
|
55
|
+
|
|
56
|
+
## Request/response example
|
|
57
|
+
|
|
58
|
+
```json
|
|
59
|
+
{ "command": "ponytail", "args": { "mode": "lite" }, "sessionId": "s1" }
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
```json
|
|
63
|
+
{ "kind": "custom", "data": { "type": "ponytail-mode", "mode": "lite" } }
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Implementation example
|
|
67
|
+
|
|
68
|
+
```ts
|
|
69
|
+
import { createPonytailExtension } from "@arnilo/prism-ponytail";
|
|
70
|
+
import {
|
|
71
|
+
createExtensionKernel,
|
|
72
|
+
createLoadSkillTool,
|
|
73
|
+
createLoadedSkillSet,
|
|
74
|
+
createMemorySessionStore,
|
|
75
|
+
createSkillRegistry,
|
|
76
|
+
} from "@arnilo/prism";
|
|
77
|
+
|
|
78
|
+
const store = createMemorySessionStore();
|
|
79
|
+
const callbacks = {
|
|
80
|
+
appendEntry: async (entry, options) => store.append(entry, options),
|
|
81
|
+
getEntries: async () => store.list("s1"),
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
const kernel = createExtensionKernel({ errorPolicy: "throw" });
|
|
85
|
+
await kernel.load([
|
|
86
|
+
createPonytailExtension({
|
|
87
|
+
upstreamPath: undefined, // optional peer @dietrichgebert/ponytail
|
|
88
|
+
defaultMode: "full",
|
|
89
|
+
quietStartup: true,
|
|
90
|
+
...callbacks,
|
|
91
|
+
}),
|
|
92
|
+
]);
|
|
93
|
+
|
|
94
|
+
const registry = createSkillRegistry(kernel.registries.skills.list());
|
|
95
|
+
const loaded = createLoadedSkillSet();
|
|
96
|
+
const loadSkill = createLoadSkillTool({ registry, loaded });
|
|
97
|
+
|
|
98
|
+
await kernel.registries.commands.get("ponytail")!.execute({ mode: "lite" }, { sessionId: "s1" });
|
|
99
|
+
// Select instructionInjectors: ["ponytail-mode"] on runs that should receive mode slices.
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
See `examples/caveman-ponytail.ts` for combined Caveman + Ponytail progressive disclosure demo (network-free fixtures).
|
|
103
|
+
|
|
104
|
+
## Extension and configuration notes
|
|
105
|
+
|
|
106
|
+
- Import alone registers nothing (`sideEffects: false`); no timers, watchers, network, or shell scripts.
|
|
107
|
+
- Upstream hook modules load via `createRequire` from resolved root — instruction strings are not forked in Prism.
|
|
108
|
+
- Mode restore scans `getEntries()` for latest `data.type === "ponytail-mode"` (OM attach pattern).
|
|
109
|
+
- `ponytail-subagent` hook is not wired; nested-agent behavior is host responsibility.
|
|
110
|
+
- No TUI statusline scripts; use `ponytail status` command or extension events.
|
|
111
|
+
- Not included in `@arnilo/prism-code` or `@arnilo/prism-sdk` profiles — opt-in install only.
|
|
112
|
+
|
|
113
|
+
## Security and performance notes
|
|
114
|
+
|
|
115
|
+
- Upstream text is untrusted; reads bounded (`MAX_SKILL_FILE_BYTES` 256 KiB, `MAX_INJECTED_INSTRUCTION_BYTES` 32 KiB).
|
|
116
|
+
- Config writes only to host `configPath` with size cap (`MAX_CONFIG_FILE_BYTES` 16 KiB).
|
|
117
|
+
- Errors redact absolute paths and home directories.
|
|
118
|
+
- O(skills) setup scan; O(1) mode tracking per turn; no background workers.
|
|
119
|
+
|
|
120
|
+
## Related APIs
|
|
121
|
+
|
|
122
|
+
- [Caveman behavior integration](caveman.md): complementary terse-communication mode package.
|
|
123
|
+
- [Extension kernel and event bus](extensions.md): explicit `kernel.load`.
|
|
124
|
+
- [Context and skills](context-and-skills.md): progressive catalog + `load_skill`.
|
|
125
|
+
- [Instruction injection](instruction-injection.md): `ponytail-mode` injector.
|
|
126
|
+
- [Observational memory compaction package](compaction-observational-memory.md): session callback attach pattern.
|
|
127
|
+
- [Migration guide](migration.md): `0.0.21 → 0.0.22` notes.
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
## What it does
|
|
4
4
|
|
|
5
|
-
Prism is published as one core package, thirty-
|
|
5
|
+
Prism is published as one core package, thirty-nine first-party capability packages, and six pure-manifest family/profile packages (**46** publishable manifests total). 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).
|
|
6
6
|
|
|
7
7
|
Core package:
|
|
8
8
|
|
|
9
9
|
- `@arnilo/prism` — the runtime, contracts, registries, streaming events, CLI (including `prism init`), and the `/docs` hub. `files`: `dist` (with `!dist/__tests__` and `!dist/**/*.map` negations), `docs`, `templates`, `CHANGELOG.md`. `bin`: `prism` -> `dist/cli.js`. `sideEffects`: `["dist/cli.js"]`.
|
|
10
10
|
|
|
11
|
-
First-party workspace packages (each has non-optional `@arnilo/prism@0.0.
|
|
11
|
+
First-party workspace packages (each has non-optional `@arnilo/prism@0.0.22` peer and `sideEffects: false`; RAG also peers on memory, and server also peers on workflows):
|
|
12
12
|
|
|
13
13
|
- `@arnilo/prism-provider-anthropic`, `@arnilo/prism-provider-google`, `@arnilo/prism-provider-openai`, `@arnilo/prism-provider-openrouter`, `@arnilo/prism-provider-kimi`, `@arnilo/prism-provider-zai`, `@arnilo/prism-provider-opencode-go`, `@arnilo/prism-provider-neuralwatt` — provider adapters.
|
|
14
14
|
- `@arnilo/prism-provider-azure`, `@arnilo/prism-provider-bedrock`, `@arnilo/prism-provider-vertex` — optional enterprise-cloud adapters (Entra/IAM/ADC; separate from consumer Anthropic/Google).
|
|
@@ -33,10 +33,12 @@ First-party workspace packages (each has non-optional `@arnilo/prism@0.0.20` pee
|
|
|
33
33
|
- `@arnilo/prism-web-tools` — optional bounded host-selected Brave/Exa search and Firecrawl Markdown/schema extraction; native fetch, no vendor SDK/browser.
|
|
34
34
|
- `@arnilo/prism-browser` — optional host-supplied Playwright browser tools (`browser_open`/`browser_snapshot`/`browser_act`/`browser_close`); import launches nothing; `playwright-core@1.61.0` optional peer.
|
|
35
35
|
- `@arnilo/prism-ag-ui` — optional bounded AG-UI mapper/authorized Web handler/replay plus stable `./acp` sibling; root and ACP imports are inert.
|
|
36
|
+
- `@arnilo/prism-caveman` — optional upstream Caveman behavior integration (`upstreamPath` required; not in code/sdk/all profiles).
|
|
37
|
+
- `@arnilo/prism-ponytail` — optional upstream Ponytail behavior integration (peer `@dietrichgebert/ponytail` or `upstreamPath`; not in code/sdk/all profiles).
|
|
36
38
|
|
|
37
39
|
### 0.0.12 AG-UI package boundary
|
|
38
40
|
|
|
39
|
-
`@arnilo/prism-ag-ui` is a publishable optional code package with root AG-UI exports and stable `./acp` sibling, peer `@arnilo/prism@0.0.
|
|
41
|
+
`@arnilo/prism-ag-ui` is a publishable optional code package with root AG-UI exports and stable `./acp` sibling, peer `@arnilo/prism@0.0.22`, pinned `@ag-ui/core@0.0.57` / `@agentclientprotocol/sdk@1.3.0`, and no import-time network/listener/run. It is included by `@arnilo/prism-all` only—not `@arnilo/prism-code` or `@arnilo/prism-sdk`—so coding and SDK profiles stay free of UI protocol dependencies.
|
|
40
42
|
|
|
41
43
|
Family/profile packages (pure manifests, no code or `dist`; ship `README.md` and `CHANGELOG.md`; use exact hard `dependencies`):
|
|
42
44
|
|
|
@@ -78,9 +80,9 @@ Consumers install the core package for the runtime and add first-party packages
|
|
|
78
80
|
| Run the default (network-free) test suite | `npm test` |
|
|
79
81
|
| Dry-run pack core + every package | `npm run pack:dry-run` |
|
|
80
82
|
| Local mirror of the release verify gate | `npm run release:dry-run` |
|
|
81
|
-
| Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.
|
|
82
|
-
| Preview deterministic publish order | `npm run release:publish -- --version 0.0.
|
|
83
|
-
| Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.
|
|
83
|
+
| Validate clean tag/version/ranges and reject registry collisions | `npm run release:check -- --version 0.0.22` |
|
|
84
|
+
| Preview deterministic publish order | `npm run release:publish -- --version 0.0.22 --dry-run --allow-dirty --allow-untagged` |
|
|
85
|
+
| Resume interrupted tagged publication | `npm run release:publish -- --version 0.0.22 --resume --report release-artifacts/publish-report.json` |
|
|
84
86
|
| Full SDK readiness gate (typecheck + offline tests + pack) | `npm run sdk:ready` |
|
|
85
87
|
|
|
86
88
|
Public core import specifiers (from the root `exports` map):
|
|
@@ -117,7 +119,7 @@ A packed tarball contains only public compiled output and release files:
|
|
|
117
119
|
- Code packages ship `README.md`, `LICENSE`, and `CHANGELOG.md`; family/profile packages ship `README.md` and `CHANGELOG.md`.
|
|
118
120
|
- The core tarball additionally ships the full `docs/` directory (the docs hub) and `templates/init/` used by `prism init`.
|
|
119
121
|
- `dist/cli.js` and the `bin` link in core.
|
|
120
|
-
- **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.
|
|
122
|
+
- **Tarball filenames.** npm strips the `@scope/` prefix, so the core package `@arnilo/prism` produces a tarball named `arnilo-prism-0.0.22.tgz`; first-party packages produce `arnilo-prism-provider-<name>-0.0.22.tgz` / `arnilo-prism-compaction-<name>-0.0.22.tgz` / `arnilo-prism-coding-agent-0.0.22.tgz`; family/profile packages produce `arnilo-prism-{providers,compaction,base,code,sdk,all}-0.0.22.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).
|
|
121
123
|
|
|
122
124
|
Excluded from every tarball by `files` negation:
|
|
123
125
|
|
|
@@ -136,9 +138,9 @@ Excluded from every tarball by `files` negation:
|
|
|
136
138
|
"name": "host-app",
|
|
137
139
|
"type": "module",
|
|
138
140
|
"dependencies": {
|
|
139
|
-
"@arnilo/prism": "0.0.
|
|
140
|
-
"@arnilo/prism-provider-openai": "0.0.
|
|
141
|
-
"@arnilo/prism-compaction-observational-memory": "0.0.
|
|
141
|
+
"@arnilo/prism": "0.0.22",
|
|
142
|
+
"@arnilo/prism-provider-openai": "0.0.22",
|
|
143
|
+
"@arnilo/prism-compaction-observational-memory": "0.0.22"
|
|
142
144
|
}
|
|
143
145
|
}
|
|
144
146
|
```
|
|
@@ -181,11 +183,11 @@ For SDK readiness, run the same one-command gate directly. It composes existing
|
|
|
181
183
|
npm run sdk:ready
|
|
182
184
|
```
|
|
183
185
|
|
|
184
|
-
Release publication derives all **
|
|
186
|
+
Release publication derives all **46** manifests from the workspace once, validates exact `0.0.22` manifest/lockfile/internal ranges, then uses deterministic dependency order. `release:check` requires a clean commit tagged `v0.0.22` 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.
|
|
185
187
|
|
|
186
188
|
```bash
|
|
187
|
-
npm run release:check -- --version 0.0.
|
|
188
|
-
npm run release:publish -- --version 0.0.
|
|
189
|
+
npm run release:check -- --version 0.0.22
|
|
190
|
+
npm run release:publish -- --version 0.0.22 --dry-run --allow-dirty --allow-untagged
|
|
189
191
|
```
|
|
190
192
|
|
|
191
193
|
`--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.
|
|
@@ -196,6 +198,46 @@ Optional live smoke tests stay separate from SDK readiness because they require
|
|
|
196
198
|
PRISM_LIVE_PROVIDER_TESTS=1 npm run test --workspaces --if-present
|
|
197
199
|
```
|
|
198
200
|
|
|
201
|
+
### 0.0.22 publish handoff
|
|
202
|
+
|
|
203
|
+
**Decision: GO after protected operator prerequisites below.** Release **0.0.22** (Phase 5 third-party behavior integrations, plan 005) ships `@arnilo/prism-caveman` and `@arnilo/prism-ponytail` as opt-in behavior packages (upstream Caveman/Ponytail wiring, session mode persistence, progressive disclosure + injector split). Core `@arnilo/prism` runtime is unchanged. The publish graph is **46 manifests** (+2). No intentional pre-1.0 breaks for hosts that do not install the new packages — see [migration](migration.md) under `0.0.21 → 0.0.22 third-party behavior integrations`.
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
git diff --check
|
|
207
|
+
npm ci
|
|
208
|
+
npm run sdk:ready
|
|
209
|
+
node --test scripts/budget-gate.test.mjs
|
|
210
|
+
node scripts/scan-secrets.mjs && node scripts/verify-sbom.mjs
|
|
211
|
+
npm audit --audit-level=moderate
|
|
212
|
+
npm run release:gate
|
|
213
|
+
npm run release:check -- --version 0.0.22 --allow-dirty --allow-untagged --report /tmp/prism-0.0.22-preflight.json
|
|
214
|
+
npm run release:publish -- --version 0.0.22 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.22-dry-run.json
|
|
215
|
+
git tag -s v0.0.22 -m "Prism 0.0.22"
|
|
216
|
+
git verify-tag v0.0.22
|
|
217
|
+
git push origin v0.0.22
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
### 0.0.21 publish handoff
|
|
221
|
+
|
|
222
|
+
**Decision: GO after protected operator prerequisites below.** Release **0.0.21** (Phase 4 coding-tool capability gaps, plan 004) ships `repo_search` `outputMode`, bounded `glob`, optional session-scoped read-before-write, bounded `delete`/`move`, and coding-security approval/sandbox wiring. The exact graph stays **44 publishable manifests**; no package added or retired. Intentional pre-1.0 breaks are documented in [migration](migration.md) under `0.0.20 → 0.0.21 coding-tool capability gaps`.
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
git diff --check
|
|
226
|
+
npm ci
|
|
227
|
+
npm run sdk:ready
|
|
228
|
+
node --test scripts/budget-gate.test.mjs
|
|
229
|
+
node scripts/scan-secrets.mjs && node scripts/verify-sbom.mjs
|
|
230
|
+
npm audit --audit-level=moderate
|
|
231
|
+
npm run release:gate
|
|
232
|
+
npm run release:check -- --version 0.0.21 --allow-dirty --allow-untagged --report /tmp/prism-0.0.21-preflight.json
|
|
233
|
+
npm run release:publish -- --version 0.0.21 --dry-run --allow-dirty --allow-untagged --report /tmp/prism-0.0.21-dry-run.json
|
|
234
|
+
git tag -s v0.0.21 -m "Prism 0.0.21"
|
|
235
|
+
git verify-tag v0.0.21
|
|
236
|
+
git push origin v0.0.21
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
The dry-run checks every registry collision and executes npm's non-publishing tarball validation for each dependency-ordered manifest. The protected tag workflow alone publishes through `npm run release:publish -- --version "${GITHUB_REF_NAME#v}" --resume --report release-artifacts/publish-report.json`; re-run a failed job for the same tag. `npm audit signatures --json --include-attestations` and artifact checksums remain post-publish checks.
|
|
240
|
+
|
|
199
241
|
### 0.0.20 publish handoff
|
|
200
242
|
|
|
201
243
|
**Decision: GO after protected operator prerequisites below.** Release **0.0.20** (Phase 3 skills and context progressive disclosure, plan 003) ships progressive skill catalog assembly (`skillsDisclosure`), session `load_skill`, empty `SkillRegistry` default with `activateAllSkills` migration opt-in, priority-aware context budget demotion, and optional `toolResultFold`. The exact graph stays **44 publishable manifests**; no package added or retired. Intentional pre-1.0 breaks are documented in [migration](migration.md) under `0.0.19 → 0.0.20 skills and context progressive disclosure`.
|
|
@@ -835,8 +877,8 @@ npm publication is not transactional and published versions are immutable. Parti
|
|
|
835
877
|
|
|
836
878
|
## Extension and configuration notes
|
|
837
879
|
|
|
838
|
-
- **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.
|
|
839
|
-
- **Public access.** All
|
|
880
|
+
- **Required `@arnilo/prism` peer.** Every first-party code package declares a non-optional `@arnilo/prism@0.0.22` peer (`peerDependenciesMeta` must not mark `@arnilo/prism` optional; other peers such as `playwright-core` may be optional). The range stays pinned to `0.0.22` for the current 0.x release and will widen to `^1.0.0` at the 1.x stable release. Inside the workspace each package also declares `"@arnilo/prism": "file:../.."` in `devDependencies` so `npm install` resolves the peer locally; that devDependency is stripped from consumer installs and is not a runtime dependency.
|
|
881
|
+
- **Public access.** All 46 manifests (40 code packages + 6 family/profile packages) declare `"publishConfig": { "access": "public" }`; the publisher also passes `--access public` explicitly because scoped packages otherwise default to restricted on first publish.
|
|
840
882
|
- **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).
|
|
841
883
|
- **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`.
|
|
842
884
|
- **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.
|