@cairnkeep/cli 2.9.0 → 2.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -1
- package/README.md +54 -25
- package/bin/cairn +6 -165
- package/bin/cairn-container +8 -0
- package/docs/building-an-overlay.md +41 -4
- package/docs/containers.md +10 -0
- package/docs/harness-compatibility.md +30 -2
- package/docs/learning/CURRICULUM-MAP.md +9 -3
- package/docs/learning/FEATURE-GUIDE.md +9 -3
- package/docs/learning/README.md +2 -0
- package/docs/learning/lessons/L00-why-cairnkeep.md +1 -1
- package/docs/learning/lessons/L01-safe-trial.md +3 -3
- package/docs/learning/lessons/L02-installation.md +11 -2
- package/docs/learning/lessons/L03-first-project.md +1 -1
- package/docs/learning/lessons/L19-validated-skill-improvement.md +1 -1
- package/docs/learning/lessons/L20-mcp-tool-profiles.md +1 -1
- package/docs/learning/lessons/L21-context-packs.md +1 -1
- package/docs/learning/lessons/L22-native-windows.md +83 -0
- package/docs/learning/lessons/L23-guided-setup.md +138 -0
- package/docs/learning/tracks/operator.md +8 -3
- package/docs/learning/tracks/quickstart.md +7 -3
- package/docs/native-windows.md +122 -0
- package/docs/operating.md +119 -18
- package/docs/privacy-and-data-flow.md +34 -1
- package/docs/storage.md +14 -2
- package/examples/eval/bundled-fake.json +1 -1
- package/mcp-memory-server/dist/artifact-store-windows-worker.js +74 -0
- package/mcp-memory-server/dist/artifact-store.js +196 -55
- package/mcp-memory-server/dist/capability-cli.js +2 -1
- package/mcp-memory-server/dist/capability-config.js +4 -3
- package/mcp-memory-server/dist/capability-harness.js +34 -7
- package/mcp-memory-server/dist/context-pack.js +84 -25
- package/mcp-memory-server/dist/eval-cli.js +6 -5
- package/mcp-memory-server/dist/eval-plan.js +35 -13
- package/mcp-memory-server/dist/eval-process.js +11 -4
- package/mcp-memory-server/dist/eval-report.js +7 -5
- package/mcp-memory-server/dist/graph-cli.js +7 -1
- package/mcp-memory-server/dist/index.js +19 -20
- package/mcp-memory-server/dist/mcp-tool-profile.js +6 -4
- package/mcp-memory-server/dist/note-store.js +12 -3
- package/mcp-memory-server/dist/pi-mcp-bridge.js +185 -0
- package/mcp-memory-server/dist/platform-security.js +102 -0
- package/mcp-memory-server/dist/skill-store.js +27 -12
- package/mcp-memory-server/package.json +2 -1
- package/package.json +5 -4
- package/pi/extensions/cairnkeep-memory.ts +61 -0
- package/schemas/cairnkeep-setup-policy.schema.json +55 -0
- package/schemas/cairnkeep-setup.schema.json +36 -0
- package/scripts/cairn-cli.mjs +119 -0
- package/scripts/cairn-container-cli.mjs +121 -0
- package/scripts/cairn-hook.mjs +199 -0
- package/scripts/completion.sh +12 -3
- package/scripts/doctor.sh +57 -0
- package/scripts/fix-permissions.mjs +12 -0
- package/scripts/memory-wiki-audit.mjs +95 -0
- package/scripts/phase26-test-manifest.mjs +26 -0
- package/scripts/run-repository-tests.mjs +76 -0
- package/scripts/setup-core.mjs +310 -0
- package/scripts/setup-reconcile.mjs +331 -0
- package/scripts/setup.mjs +306 -0
- package/scripts/sync-pi-assets.sh +19 -4
- package/scripts/test-completion.sh +39 -0
- package/scripts/test-doctor.sh +66 -0
- package/scripts/test-learning-docs.sh +52 -3
- package/scripts/test-package-install.sh +64 -0
- package/scripts/test-phase17-artifact-lifecycle.sh +1 -1
- package/scripts/test-phase18-capability-lifecycle.sh +1 -1
- package/scripts/test-pi-lifecycle.mjs +190 -0
- package/scripts/test-setup-compatibility.mjs +186 -0
- package/scripts/test-setup-output.sh +131 -0
- package/scripts/test-setup-overlay.sh +113 -0
- package/scripts/test-setup-preflight.mjs +281 -0
- package/scripts/test-setup-reconcile.mjs +257 -0
- package/scripts/test-uninstall.sh +50 -0
- package/scripts/test-windows-native.mjs +136 -0
- package/scripts/uninstall.sh +69 -6
- package/scripts/verify-pi-mcp-bridge.mjs +588 -0
- package/scripts/windows-platform.mjs +725 -0
package/docs/operating.md
CHANGED
|
@@ -7,20 +7,23 @@ Cairnkeep has three moving parts:
|
|
|
7
7
|
|
|
8
8
|
1. **The memory server** (`cairn-memory`) — an MCP server your harness talks to.
|
|
9
9
|
2. **The project scaffold** — `.ai/` launchers and the `.planning/` knowledge
|
|
10
|
-
layer, written by `cairn
|
|
10
|
+
layer, written by `cairn setup` or the compatibility-oriented
|
|
11
|
+
`cairn bootstrap` primitive.
|
|
11
12
|
3. **The operating layer** — the commands, agents, and hooks that live in your
|
|
12
13
|
harness config and drive the workflow.
|
|
13
14
|
|
|
14
|
-
`cairn
|
|
15
|
-
|
|
15
|
+
`cairn setup` is the recommended project entry point. `cairn bootstrap`
|
|
16
|
+
retains its established deterministic behavior for existing automation. Steps
|
|
17
|
+
1 and 3 are one-time-per-machine installs; project setup reports the explicit
|
|
18
|
+
sync command but never runs it automatically. This guide covers all three.
|
|
16
19
|
|
|
17
20
|
## Prerequisites
|
|
18
21
|
|
|
19
22
|
- Node.js 22 or newer (for the memory server) and a supported harness. Claude
|
|
20
23
|
Code and OpenCode receive the full operating layer. Kimi Code receives the
|
|
21
24
|
memory MCP, launcher, and opt-in graph Skill; Qwen Code receives the memory
|
|
22
|
-
MCP and launcher. Pi receives
|
|
23
|
-
and launcher.
|
|
25
|
+
MCP and launcher. Pi receives a maintained local stdio MCP extension, native
|
|
26
|
+
trajectory adapter, graph prompt, and launcher after explicit machine sync.
|
|
24
27
|
- Optional: the `sqlite3` CLI for `cairn memory export`. Runtime memory and
|
|
25
28
|
`cairn memory import` do not require it.
|
|
26
29
|
- Optional: an OpenAI-compatible LLM endpoint for memory extraction and
|
|
@@ -29,6 +32,12 @@ installs. This guide covers all three in order.
|
|
|
29
32
|
- Optional: rootless Podman for the containerized memory server and isolated
|
|
30
33
|
workspace base described in [Containers](containers.md).
|
|
31
34
|
|
|
35
|
+
Native Windows x64 is supported directly from PowerShell or Command Prompt;
|
|
36
|
+
WSL and Git Bash are not required. The npm package installs a Node entry point,
|
|
37
|
+
and bootstrap emits `.cmd` plus PowerShell launchers. See
|
|
38
|
+
[Native Windows operation](native-windows.md) for the exact setup and recovery
|
|
39
|
+
contract. Windows ARM64 currently uses x64 emulation.
|
|
40
|
+
|
|
32
41
|
## Shell completion
|
|
33
42
|
|
|
34
43
|
Generate completion definitions directly from the CLI:
|
|
@@ -37,12 +46,65 @@ Generate completion definitions directly from the CLI:
|
|
|
37
46
|
cairn completion bash
|
|
38
47
|
cairn completion zsh
|
|
39
48
|
cairn completion fish
|
|
49
|
+
cairn completion powershell
|
|
40
50
|
```
|
|
41
51
|
|
|
42
52
|
Distributions can install these outputs into the platform's normal completion
|
|
43
53
|
directories. They can also be loaded for the current shell, for example with
|
|
44
54
|
`source <(cairn completion bash)`.
|
|
45
55
|
|
|
56
|
+
In PowerShell, load completion for the current session with:
|
|
57
|
+
|
|
58
|
+
```powershell
|
|
59
|
+
Invoke-Expression (& cairn completion powershell | Out-String)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Guided project setup
|
|
63
|
+
|
|
64
|
+
Interactive terminals may run `cairn setup` and answer the target, Git,
|
|
65
|
+
harness, memory, and confirmation questions. Automation must make every choice
|
|
66
|
+
explicit:
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
cairn setup /path/to/project --git init --harness claude,pi --memory local --yes
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The deterministic form accepts `--git init|existing|none`, a comma-separated
|
|
73
|
+
subset of `claude,opencode,pi,kimi,qwen`, and `--memory local|none`. `--git
|
|
74
|
+
existing` requires the target to be in an existing work tree. `--git init`
|
|
75
|
+
requires Git and is the only non-interactive authorization to initialize a
|
|
76
|
+
repository. `--git none` is an explicit limited mode: repository-aware features
|
|
77
|
+
remain unavailable, and both setup output and `cairn doctor` say so. A missing
|
|
78
|
+
or empty interactive target recommends initialization and asks before writing;
|
|
79
|
+
an existing non-Git tree is never initialized silently.
|
|
80
|
+
|
|
81
|
+
Setup first classifies the target and Git state without writing, then creates or
|
|
82
|
+
reconciles only the selected project launchers and common scaffold assets.
|
|
83
|
+
Identical managed files remain unchanged, changed managed files are updated,
|
|
84
|
+
and unrelated files are preserved. The result reports created, updated,
|
|
85
|
+
unchanged, and skipped counts; `cairn doctor`; an exact launcher per selected
|
|
86
|
+
harness; and the deterministic setup command to use for recovery. `--json`
|
|
87
|
+
returns the same schema-v1 result. The private mode-`0600`
|
|
88
|
+
`.ai/cairnkeep.json` record stores the package version, Git and memory modes,
|
|
89
|
+
selected harnesses, and digests/modes/template identifiers for setup-owned
|
|
90
|
+
assets. It contains no credentials, endpoints, or absolute paths.
|
|
91
|
+
|
|
92
|
+
Setup never installs or refreshes machine-level harness assets. Its
|
|
93
|
+
`machine_sync.automatic` field is always false, and the human output labels the
|
|
94
|
+
reported command as not run automatically. Apply the relevant machine command
|
|
95
|
+
explicitly, check it, then diagnose and launch:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
cairn sync --apply # Claude Code operating assets
|
|
99
|
+
cairn sync-pi --apply # Pi extension and prompt
|
|
100
|
+
cairn sync-pi --check
|
|
101
|
+
cd /path/to/project && cairn doctor
|
|
102
|
+
./.ai/start-pi.sh
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
`cairn bootstrap [--untracked] PATH` remains available for scripts that depend
|
|
106
|
+
on its original scaffold and Git-exclusion contract.
|
|
107
|
+
|
|
46
108
|
## Setup order (Claude Code)
|
|
47
109
|
|
|
48
110
|
The commands below install the default local topology: `cairn-memory` runs as a
|
|
@@ -206,8 +268,9 @@ cairn graph diff
|
|
|
206
268
|
```
|
|
207
269
|
|
|
208
270
|
The same direct CLI works with Qwen Code, Codex, and other shell-capable
|
|
209
|
-
clients.
|
|
210
|
-
the
|
|
271
|
+
clients. Pi sync separately installs Cairnkeep's maintained local stdio MCP
|
|
272
|
+
extension; the graph prompt remains a thin adapter and does not expand the rest
|
|
273
|
+
of Pi's operating surface.
|
|
211
274
|
|
|
212
275
|
All six modes delegate to `cairn graph`. Managed builds run Graphify's local
|
|
213
276
|
code-only `update` path with provider credentials removed from the subprocess
|
|
@@ -217,6 +280,9 @@ so Graphify cannot re-index its own generated HTML/report/JSON. Managed builds
|
|
|
217
280
|
do not perform Graphify's optional semantic document extraction. Prefer exact
|
|
218
281
|
function, class, or file names; broad natural-language graph queries are less
|
|
219
282
|
precise. Cairnkeep does not install or update Graphify automatically.
|
|
283
|
+
Set `CAIRN_GRAPHIFY_BINARY` to override the `graphify` command when Graphify is
|
|
284
|
+
installed at a specific path. Native executables run directly; `.js`, `.mjs`,
|
|
285
|
+
and `.cjs` helpers run through the active Node runtime on every platform.
|
|
220
286
|
|
|
221
287
|
Graphify also maintains an incremental `graphify-out/` work directory at the
|
|
222
288
|
repository root. It is separate from Cairnkeep's published
|
|
@@ -299,26 +365,52 @@ configuration, approval behavior, and overlay guidance.
|
|
|
299
365
|
|
|
300
366
|
## Setup order (Pi)
|
|
301
367
|
|
|
302
|
-
Pi
|
|
303
|
-
installs
|
|
368
|
+
Pi uses the same project scaffold and local memory store. Its explicit sync
|
|
369
|
+
installs the maintained memory extension, native trajectory extension, and thin
|
|
370
|
+
`/graphify` prompt into Pi's agent root:
|
|
304
371
|
|
|
305
372
|
```bash
|
|
306
373
|
npm install -g @cairnkeep/cli
|
|
307
374
|
cairn sync-pi --apply # default: ~/.pi/agent
|
|
308
|
-
cairn
|
|
375
|
+
cairn setup /path/to/project --git init --harness pi --memory local --yes
|
|
309
376
|
cp /path/to/project/.ai/env.example /path/to/project/.ai/.env
|
|
310
377
|
cd /path/to/project && cairn doctor && ./.ai/start-pi.sh
|
|
311
378
|
```
|
|
312
379
|
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
380
|
+
The memory extension starts `cairn memory-server` as a local stdio child from
|
|
381
|
+
the project root. It dynamically discovers the effective server catalog, so
|
|
382
|
+
feature gates, capability state, and the current MCP tool profile remain
|
|
383
|
+
authoritative. It does not contain a second hard-coded catalog. Startup is
|
|
384
|
+
bounded to 10 seconds, calls to 30 seconds, results to 4 MiB, and retained child
|
|
385
|
+
stderr to the newest 16 KiB. Cancellation is propagated, child or protocol
|
|
386
|
+
failure is surfaced, and session shutdown closes the child.
|
|
387
|
+
|
|
388
|
+
Tool names, descriptions, input and output schemas, content,
|
|
389
|
+
`structuredContent`, `_meta`, and failure behavior cross the bridge without
|
|
390
|
+
semantic rewriting. The exact MCP annotations are preserved in the trusted Pi
|
|
391
|
+
result `details`, together with the discovered tool metadata and original
|
|
392
|
+
content. Pi 0.84.1 has no native annotations field in its public tool API, so
|
|
393
|
+
Cairnkeep does not claim native model-facing annotation propagation or invent a
|
|
394
|
+
substitute field.
|
|
395
|
+
|
|
396
|
+
The bridge is tools-only: it does not run prompts, activate context-pack skills,
|
|
397
|
+
create an autonomous loop, add remote access, or bypass server-side tool
|
|
398
|
+
restrictions. Removing `MCP_HTTP_PORT` from the child environment deliberately
|
|
399
|
+
keeps this integration on local stdio.
|
|
316
400
|
|
|
317
401
|
Use `cairn sync-pi --check` to report drift without writing, or
|
|
318
402
|
`--live-root DIR` to target an isolated Pi agent root. The command owns exactly
|
|
319
|
-
`extensions/cairnkeep-
|
|
320
|
-
|
|
321
|
-
|
|
403
|
+
`extensions/cairnkeep-memory.ts`, `extensions/cairnkeep-trajectory.ts`, and
|
|
404
|
+
`prompts/graphify.md`; `cairn doctor` reports a selected Pi extension that is
|
|
405
|
+
missing or drifted and points to `cairn sync-pi --apply`. `cairn uninstall
|
|
406
|
+
--pi-live-root DIR` removes those files backup-first and leaves every other Pi
|
|
407
|
+
asset untouched.
|
|
408
|
+
|
|
409
|
+
Pi 0.84.1 is the validated minimum supported version for this extension. The
|
|
410
|
+
v2.11 release passed the complete setup and bridge matrix on separate Pi 0.84.1
|
|
411
|
+
minimum and registry-current installations, Node.js 22, 24, and 26, Bash 3.2,
|
|
412
|
+
and native Windows. The two Pi executable paths differed, while both reported
|
|
413
|
+
0.84.1 because that was also the registry-current release.
|
|
322
414
|
|
|
323
415
|
The extension listens for Pi's native `session_shutdown` event and reads only
|
|
324
416
|
the active branch from the read-only session manager. It returns before doing
|
|
@@ -381,6 +473,7 @@ vendor or host.
|
|
|
381
473
|
| `CAIRN_HARNESS_STATE_DIR` | Optional absolute local root for recoverable native capability leases (default `${XDG_STATE_HOME:-~/.local/state}/cairn/harness`) |
|
|
382
474
|
| `CAIRN_GIT_PROVIDER` | Git host for collaboration commands: `github`\|`gitlab`\|`codeberg`\|`forgejo`\|`none`. See [git-providers.md](git-providers.md) |
|
|
383
475
|
| `CAIRN_ROUTE_ENDPOINT` | Base URL of an already-running token-miser routing/tiering proxy (unset → the `route_check` tool is inert) |
|
|
476
|
+
| `CAIRN_GRAPHIFY_BINARY` | Optional Graphify command/path override; JavaScript helpers run through the active Node runtime (default `graphify` from `PATH`) |
|
|
384
477
|
| `CAIRN_EXPLORE_BINARY` | Absolute path to the `token_miser` binary used by `context_explore` (unset → the tool throws at call time) |
|
|
385
478
|
| `CAIRN_EXPLORE_REPO_ROOT` | Default repo root for `context_explore` when no per-call `repo_root` is given (unset + no param → the tool throws) |
|
|
386
479
|
| `CAIRN_EXPLORE_CACHE` | Caches `context_explore` results keyed on query + repo HEAD + dirty-state; default ON, set to `0` to disable |
|
|
@@ -809,6 +902,13 @@ rebuild only derived indexes/dedupe/pointers from valid authoritative records.
|
|
|
809
902
|
Unsupported schema, SQLite failure, invalid full records, or digest corruption
|
|
810
903
|
fails untouched with guidance to preserve the database before manual recovery.
|
|
811
904
|
|
|
905
|
+
When `.ai/cairnkeep.json` exists, doctor also validates its private state,
|
|
906
|
+
selected assets, digests, and modes. It reports `limited` for explicit
|
|
907
|
+
`--git none`, fails an incomplete or drifted setup with the recorded
|
|
908
|
+
deterministic `cairn setup` recovery command, and checks the Pi machine
|
|
909
|
+
extension when Pi was selected. `cairn sync-pi --apply` repairs that
|
|
910
|
+
machine-level drift; setup itself never performs the sync.
|
|
911
|
+
|
|
812
912
|
### Evaluation harness (opt-in)
|
|
813
913
|
|
|
814
914
|
`cairn eval` is a local, serial experiment coordinator. It is disabled unless
|
|
@@ -897,8 +997,9 @@ claims.
|
|
|
897
997
|
SIGINT or SIGTERM stops schedule admission, terminates the active adapter,
|
|
898
998
|
checkpoints a `cancelled` observation, waits for bounded cleanup, and retains
|
|
899
999
|
an inspectable partial report. On POSIX systems the runner targets the child
|
|
900
|
-
process group with TERM then bounded KILL escalation. Windows
|
|
901
|
-
|
|
1000
|
+
process group with TERM then bounded KILL escalation. Native Windows targets
|
|
1001
|
+
the adapter and its descendant tree with `taskkill.exe /T`, escalating to `/F`
|
|
1002
|
+
after the bounded grace period.
|
|
902
1003
|
|
|
903
1004
|
See [storage](storage.md#evaluation-report-and-note-snapshot-storage) for local
|
|
904
1005
|
retention/removal and [privacy](privacy-and-data-flow.md#evaluation-adapter-and-report-flow)
|
|
@@ -36,6 +36,8 @@ request unless the corresponding endpoint and credential are configured.
|
|
|
36
36
|
| Automatic compaction recovery | None | Structured categories are injected locally; raw summary and other bodies are excluded |
|
|
37
37
|
| Explicit artifact read/show | The redacted body only when HTTP is separately enabled and the operator/client explicitly reads it | Local terminal/stdio, or the explicitly registered authenticated server |
|
|
38
38
|
| Opt-in evaluation coordinator | Adapter-defined inference may leave the machine only according to the explicit operator-owned adapter and inherited environment | Local adapter subprocess; Cairnkeep supplies no provider, endpoint, credential, model, or network default |
|
|
39
|
+
| Guided project setup | None | Selected scaffold assets and private `.ai/cairnkeep.json` state in the target; machine sync is never automatic |
|
|
40
|
+
| Pi memory extension | None | Local `cairn memory-server` stdio child; no HTTP transport is inherited |
|
|
39
41
|
|
|
40
42
|
Model endpoints may be local or remote. Cairnkeep cannot determine a provider's
|
|
41
43
|
retention, training, or logging policy; verify it before sending confidential
|
|
@@ -91,6 +93,35 @@ and its generated `revert.sh` restores exact bytes, modes, and layout. Explicit
|
|
|
91
93
|
`cairn eval delete` and `prune` remove selected contained experiment trees with
|
|
92
94
|
no hidden tombstone.
|
|
93
95
|
|
|
96
|
+
## Guided setup and Pi bridge
|
|
97
|
+
|
|
98
|
+
Guided setup performs a read-only target and Git preflight before project
|
|
99
|
+
writes. Its schema-v1 `.ai/cairnkeep.json` record contains the package version,
|
|
100
|
+
Git and memory choices, selected harness names, and setup-owned asset paths,
|
|
101
|
+
digests, modes, and template identifiers. It does not contain credentials,
|
|
102
|
+
endpoints, absolute paths, prompts, or memory values. The file is mode `0600`
|
|
103
|
+
on POSIX and receives the private managed-file ACL on native Windows. Setup
|
|
104
|
+
never invokes machine sync, and it does not start a harness or server child.
|
|
105
|
+
|
|
106
|
+
When the explicitly installed Pi memory extension starts a session, it spawns
|
|
107
|
+
`cairn memory-server` as a child in the project directory over local stdio. The
|
|
108
|
+
bridge removes `MCP_HTTP_PORT` from the child environment, retains only the
|
|
109
|
+
newest 16 KiB of child stderr for bounded failure diagnostics, caps startup,
|
|
110
|
+
calls, catalogs, and results, and closes the child at shutdown. The child still
|
|
111
|
+
inherits the remaining operator environment needed by the normal local server,
|
|
112
|
+
so those environment values and the project directory are a child-process trust
|
|
113
|
+
boundary even though they are not persisted by the bridge.
|
|
114
|
+
|
|
115
|
+
Catalog and call replay is allow-listed to MCP tool metadata and result fields.
|
|
116
|
+
Names, schemas, annotations, content, `structuredContent`, `_meta`, and error
|
|
117
|
+
state are preserved without sanitizing away protocol meaning; Pi receives the
|
|
118
|
+
annotations in trusted result `details` because Pi 0.84.1 has no native
|
|
119
|
+
annotations field. The bridge does not log requests or results, create a second
|
|
120
|
+
catalog, activate prompts or skills, add remote access, or persist a transcript.
|
|
121
|
+
Sanitized test replay uses synthetic tool arguments, results, stderr, and
|
|
122
|
+
project paths only; release evidence must not include credentials, private
|
|
123
|
+
endpoints, memory values, or identifying local paths.
|
|
124
|
+
|
|
94
125
|
## Evaluation adapter and report flow
|
|
95
126
|
|
|
96
127
|
`CAIRN_EVAL` is unset/off by default. With it off, `cairn eval` returns a fixed
|
|
@@ -169,7 +200,9 @@ network-free, and permanently scoped as framework-only evidence.
|
|
|
169
200
|
SIGINT/SIGTERM stops new schedule admission, terminates the active adapter,
|
|
170
201
|
checkpoints cancellation, performs bounded cleanup, and retains a partial
|
|
171
202
|
report. POSIX process groups receive TERM followed by bounded KILL escalation.
|
|
172
|
-
|
|
203
|
+
Native Windows uses `taskkill.exe /T` for the exact child tree and `/F` for
|
|
204
|
+
bounded force escalation; it does not enumerate or terminate unrelated
|
|
205
|
+
processes.
|
|
173
206
|
|
|
174
207
|
Turns aggregate only under exact matching compatibility IDs. Missing token
|
|
175
208
|
components/totals, unknown verifier outcomes, incompatible turn semantics, and
|
package/docs/storage.md
CHANGED
|
@@ -31,6 +31,17 @@ For the local launchers, the server working directory is normally the project
|
|
|
31
31
|
root. Bootstrap installs `.agentfs/.gitignore` so private project memory is not
|
|
32
32
|
accidentally committed. SQLite may also create `-wal` and `-shm` sidecar files.
|
|
33
33
|
|
|
34
|
+
Private-file protection is platform-equivalent rather than mode-identical.
|
|
35
|
+
Linux and macOS use `0600` files and `0700` directories. Native Windows removes
|
|
36
|
+
inherited ACLs and grants access only to the current SID, Local System, and the
|
|
37
|
+
built-in Administrators group. `cairn doctor` fails closed when a managed MCP
|
|
38
|
+
profile or context-pack pointer has broader access. Context-pack objects also
|
|
39
|
+
receive a read-only attribute after their content digest is verified.
|
|
40
|
+
|
|
41
|
+
Where this document names a generated `revert.sh`, native Windows produces the
|
|
42
|
+
equivalent backup manifest and `revert.ps1`; it restores exact bytes and the
|
|
43
|
+
Windows ACL contract rather than emulating POSIX mode bits.
|
|
44
|
+
|
|
34
45
|
`CAIRN_LLM_API_URL` and `CAIRN_MEMORY_EMBEDDING_URL` select optional model
|
|
35
46
|
services used to process/search memory. They do not change where the SQLite
|
|
36
47
|
databases are stored. Git-provider and routing configuration do not change
|
|
@@ -502,8 +513,9 @@ bearer_token_env_var = "CAIRN_MEMORY_HTTP_TOKEN"
|
|
|
502
513
|
Context-pack objects are content-addressed, immutable directories. Installation
|
|
503
514
|
copies verified content through a temporary directory and atomically publishes
|
|
504
515
|
the digest; a failed or concurrent install never changes project enablement.
|
|
505
|
-
Project pointers are separate atomic
|
|
506
|
-
|
|
516
|
+
Project pointers are separate atomic private files (`0600` on POSIX, restricted
|
|
517
|
+
ACLs on Windows) keyed by canonical local project identity or a validated
|
|
518
|
+
remote project ID. Updates retain old objects
|
|
507
519
|
and switch only the named project after exact-digest confirmation.
|
|
508
520
|
|
|
509
521
|
`cairn doctor` verifies objects, pointers, and interrupted-install remnants.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"identifier":"cairn-offline-fake-v1","package_version":"2.
|
|
1
|
+
{"identifier":"cairn-offline-fake-v1","package_version":"2.11.0","schema_version":1,"task_set_digest":"13e95379f35839593047ec34521a65a8fa3ab92bd3993bca9dc8bf5c4a9ff36f"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { AgentFS } from "agentfs-sdk";
|
|
2
|
+
import { deleteArtifactForWindowsWorker, doctorArtifactStore, getArtifactDbPath, listArtifacts, pruneArtifactsForWindowsWorker, putArtifact, readArtifact, readLatestCompaction, recordUnsupportedCompactionAdapter, } from "./artifact-store.js";
|
|
3
|
+
async function readRequest() {
|
|
4
|
+
const chunks = [];
|
|
5
|
+
for await (const chunk of process.stdin)
|
|
6
|
+
chunks.push(Buffer.from(chunk));
|
|
7
|
+
const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8"));
|
|
8
|
+
if (!parsed || typeof parsed.operation !== "string" || typeof parsed.projectRoot !== "string") {
|
|
9
|
+
throw new Error("Invalid Windows artifact worker request.");
|
|
10
|
+
}
|
|
11
|
+
return parsed;
|
|
12
|
+
}
|
|
13
|
+
function resolvedOptions(options = {}) {
|
|
14
|
+
const { now, ...rest } = options;
|
|
15
|
+
return { ...rest, ...(now ? { now: new Date(now) } : {}) };
|
|
16
|
+
}
|
|
17
|
+
async function rawOperation(request) {
|
|
18
|
+
const agent = await AgentFS.open({ id: "artifacts", path: getArtifactDbPath(request.projectRoot) });
|
|
19
|
+
try {
|
|
20
|
+
if (request.action === "list")
|
|
21
|
+
return await agent.kv.list(request.prefix ?? "");
|
|
22
|
+
if (request.action === "get")
|
|
23
|
+
return await agent.kv.get(request.key ?? "");
|
|
24
|
+
if (request.action === "set") {
|
|
25
|
+
await agent.kv.set(request.key ?? "", request.value);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
if (request.action === "delete") {
|
|
29
|
+
await agent.kv.delete(request.key ?? "");
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
throw new Error("Unsupported raw Windows artifact operation.");
|
|
33
|
+
}
|
|
34
|
+
finally {
|
|
35
|
+
await agent.close();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async function dispatch(request) {
|
|
39
|
+
const limits = request.limits;
|
|
40
|
+
if (request.operation === "put" && limits) {
|
|
41
|
+
return { result: await putArtifact(request.projectRoot, request.candidate, limits, resolvedOptions(request.options)) };
|
|
42
|
+
}
|
|
43
|
+
if (request.operation === "read" && request.identifier) {
|
|
44
|
+
return { result: await readArtifact(request.identifier, request.projectRoot) };
|
|
45
|
+
}
|
|
46
|
+
if (request.operation === "list") {
|
|
47
|
+
return { result: await listArtifacts(request.projectRoot, request.filters) };
|
|
48
|
+
}
|
|
49
|
+
if (request.operation === "latest") {
|
|
50
|
+
return { result: await readLatestCompaction(request.projectRoot, request.sessionRef) };
|
|
51
|
+
}
|
|
52
|
+
if (request.operation === "delete" && request.identifier) {
|
|
53
|
+
return deleteArtifactForWindowsWorker(request.identifier, request.projectRoot, request.options);
|
|
54
|
+
}
|
|
55
|
+
if (request.operation === "prune" && limits) {
|
|
56
|
+
return pruneArtifactsForWindowsWorker(request.projectRoot, limits, resolvedOptions(request.options));
|
|
57
|
+
}
|
|
58
|
+
if (request.operation === "record-unsupported") {
|
|
59
|
+
await recordUnsupportedCompactionAdapter(request.projectRoot, request.diagnostic);
|
|
60
|
+
return { result: null };
|
|
61
|
+
}
|
|
62
|
+
if (request.operation === "doctor" && limits) {
|
|
63
|
+
return { result: await doctorArtifactStore(request.projectRoot, request.repair, limits) };
|
|
64
|
+
}
|
|
65
|
+
if (request.operation === "raw")
|
|
66
|
+
return { result: await rawOperation(request) };
|
|
67
|
+
throw new Error("Unsupported Windows artifact worker operation.");
|
|
68
|
+
}
|
|
69
|
+
dispatch(await readRequest())
|
|
70
|
+
.then((response) => process.stdout.write(JSON.stringify(response)))
|
|
71
|
+
.catch((error) => {
|
|
72
|
+
process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
|
|
73
|
+
process.exitCode = 1;
|
|
74
|
+
});
|