@cairnkeep/cli 2.17.3 → 2.19.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 +41 -1
- package/CONTRIBUTING.md +1 -1
- package/docs/harness-compatibility.md +48 -0
- package/docs/learning/CURRICULUM-MAP.md +2 -1
- package/docs/learning/FEATURE-GUIDE.md +2 -1
- package/docs/learning/lessons/L00-why-cairnkeep.md +1 -1
- package/docs/learning/lessons/L01-safe-trial.md +1 -1
- package/docs/learning/lessons/L02-installation.md +1 -1
- 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 +1 -1
- package/docs/learning/lessons/L23-guided-setup.md +18 -7
- package/docs/learning/lessons/L24-okf-exchange.md +1 -1
- package/docs/learning/lessons/L25-playbooks.md +1 -1
- package/docs/operating.md +13 -6
- package/examples/eval/bundled-fake.json +1 -1
- package/mcp-memory-server/dist/artifact-schema.js +1 -1
- package/mcp-memory-server/dist/pi-bridge-child.js +109 -0
- package/mcp-memory-server/dist/pi-mcp-bridge.js +15 -3
- package/mcp-memory-server/dist/work-evidence-schema.js +1 -1
- package/mcp-memory-server/dist/work-evidence-store.js +1 -1
- package/mcp-memory-server/package.json +5 -3
- package/omp/extensions/cairnkeep-capture.ts +226 -0
- package/omp/extensions/cairnkeep-memory.ts +288 -0
- package/package.json +77 -76
- package/schemas/artifact.schema.json +1 -1
- package/schemas/cairnkeep-setup-policy.schema.json +3 -3
- package/schemas/cairnkeep-setup.schema.json +1 -1
- package/scripts/cairn-cli.mjs +2 -0
- package/scripts/completion.sh +8 -3
- package/scripts/harness-registry.mjs +15 -3
- package/scripts/lib/omp-capture-stage.mjs +103 -0
- package/scripts/setup.mjs +10 -5
- package/scripts/sync-omp-assets.sh +96 -0
- package/scripts/test-bootstrap-untracked.sh +1 -1
- package/scripts/test-cli-dispatch.sh +2 -0
- package/scripts/test-completion.sh +4 -2
- package/scripts/test-harness-registry.sh +28 -1
- package/scripts/test-setup-output.sh +20 -1
- package/scripts/test-setup-preflight.mjs +1 -1
- package/scripts/test-work-evidence-cli.sh +1 -1
- package/scripts/uninstall.sh +1 -0
- package/scripts/verify-omp-capture.mjs +370 -0
- package/scripts/verify-omp-mcp-bridge.mjs +333 -0
- package/templates/start-omp.sh.template +47 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,44 @@ All notable user-facing changes are documented here. This project follows
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [2.19.0] - 2026-09-28
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Include oh-my-pi (OMP) in guided setup with a project launcher and explicit,
|
|
13
|
+
opt-in machine sync instructions.
|
|
14
|
+
- Report every required machine sync command when multiple harnesses are
|
|
15
|
+
selected, while retaining the singular JSON field for compatibility.
|
|
16
|
+
- Support OMP in opt-in Git-linked work evidence and preserve its diff-artifact
|
|
17
|
+
provenance.
|
|
18
|
+
|
|
19
|
+
## [2.18.0] - 2026-09-28
|
|
20
|
+
|
|
21
|
+
### Added
|
|
22
|
+
|
|
23
|
+
- oh-my-pi (omp) integration: `omp/extensions/cairnkeep-memory.ts` registers
|
|
24
|
+
the cairn-memory MCP tools as native omp tools (collision-guarded), and
|
|
25
|
+
`omp/extensions/cairnkeep-capture.ts` stages durable-memory candidates at
|
|
26
|
+
session stop and surfaces them on the next session start, with a
|
|
27
|
+
`/cairn-staged` review command. The bridge runs as a node child process so
|
|
28
|
+
it also works under compiled Bun standalone binaries.
|
|
29
|
+
- `cairn sync-omp` command, bash/zsh/fish completion entries, and
|
|
30
|
+
`verify-omp-mcp-bridge.mjs` / `verify-omp-capture.mjs` verification gates.
|
|
31
|
+
- Smoke gates for the pi-mcp-bridge child environment: Bun node-shim PATH
|
|
32
|
+
stripping, `MCP_HTTP_PORT` isolation, and the node child bridge protocol.
|
|
33
|
+
|
|
34
|
+
### Fixed
|
|
35
|
+
|
|
36
|
+
- `pi-mcp-bridge` strips Bun `/tmp/bun-node-*` shim dirs from the stdio child
|
|
37
|
+
environment; grandchildren like `cairn memory-server` spawn a real node.
|
|
38
|
+
- Work-evidence smoke used fixed calendar dates that aged past the retention
|
|
39
|
+
window; timestamps are relative to the run.
|
|
40
|
+
|
|
41
|
+
### Documentation
|
|
42
|
+
|
|
43
|
+
- `docs/harness-compatibility.md`: oh-my-pi (omp) section.
|
|
44
|
+
- `docs/operating.md`: `CAIRN_PI_BRIDGE_COMMAND` / `CAIRN_PI_BRIDGE_ARGS`.
|
|
45
|
+
|
|
8
46
|
## [2.17.3] - 2026-09-03
|
|
9
47
|
|
|
10
48
|
### Security
|
|
@@ -534,7 +572,9 @@ stored memories.
|
|
|
534
572
|
- Preserve executable permissions and Bash 3.2 portability on macOS.
|
|
535
573
|
- Add backup-first uninstall and SQLite-safe memory export/import guidance.
|
|
536
574
|
|
|
537
|
-
[Unreleased]: https://github.com/cairnkeep/cairnkeep/compare/v2.
|
|
575
|
+
[Unreleased]: https://github.com/cairnkeep/cairnkeep/compare/v2.19.0...HEAD
|
|
576
|
+
[2.19.0]: https://github.com/cairnkeep/cairnkeep/compare/v2.18.0...v2.19.0
|
|
577
|
+
[2.18.0]: https://github.com/cairnkeep/cairnkeep/compare/v2.17.3...v2.18.0
|
|
538
578
|
[2.15.1]: https://github.com/cairnkeep/cairnkeep/compare/v2.15.0...v2.15.1
|
|
539
579
|
[2.15.0]: https://github.com/cairnkeep/cairnkeep/compare/v2.14.0...v2.15.0
|
|
540
580
|
[2.14.0]: https://github.com/cairnkeep/cairnkeep/compare/v2.13.1...v2.14.0
|
package/CONTRIBUTING.md
CHANGED
|
@@ -43,7 +43,7 @@ endpoints. They are not part of the default offline test suite.
|
|
|
43
43
|
Node-based CLI implementations.
|
|
44
44
|
- `bin/cairn` is the installed command entry point.
|
|
45
45
|
- `templates/` contains project scaffolding and managed instruction assets.
|
|
46
|
-
- `claude/`, `opencode/`, `pi/`, and `kimi/` contain harness-specific operating
|
|
46
|
+
- `claude/`, `opencode/`, `pi/`, `omp/`, and `kimi/` contain harness-specific operating
|
|
47
47
|
assets.
|
|
48
48
|
- `scripts/` contains sync, lifecycle, packaging, and contract checks.
|
|
49
49
|
- `docs/` contains the versioned user and operator references indexed from
|
|
@@ -19,6 +19,7 @@ Cairnkeep commands, hooks or native trajectory capture.
|
|
|
19
19
|
| Kimi Code | Memory MCP, `AGENTS.md`, launcher, opt-in graph and cairn-work Skills | Launcher tested; remote MCP tested with Kimi Code 0.30.0; Skills contract-tested |
|
|
20
20
|
| Qwen Code | Memory MCP, launcher, project `AGENTS.md` durable-context and playbook guidance | Launcher tested; stdio and remote MCP tested with Qwen Code 0.21.1 |
|
|
21
21
|
| Pi | Memory MCP through maintained local stdio extension, native opt-in trajectory extension, launcher, graph and cairn-work prompts | Pi 0.84.1 validated minimum; deterministic and real bridge/lifecycle tests |
|
|
22
|
+
| oh-my-pi (omp) | Memory MCP through maintained local stdio extension (Pi-successor API) | Smoke-tested against the local omp checkout with the deterministic bridge verification |
|
|
22
23
|
| Codex CLI | Project-scoped memory MCP, launcher, and project `AGENTS.md` durable-context and playbook guidance | Setup and launcher contract-tested on POSIX and simulated native Windows; project trust remains operator-controlled |
|
|
23
24
|
| Other MCP clients | Memory plus optional domain-knowledge and context-pack tools | Protocol-compatible; not automatically runtime-tested |
|
|
24
25
|
|
|
@@ -77,6 +78,53 @@ release, together with Node.js 22/24/26, Bash 3.2, and native Windows. The
|
|
|
77
78
|
executable paths were distinct; both reported 0.84.1 because that was also the
|
|
78
79
|
registry-current release.
|
|
79
80
|
|
|
81
|
+
## oh-my-pi (omp)
|
|
82
|
+
|
|
83
|
+
Select OMP in `cairn setup` to create the project launcher, then run
|
|
84
|
+
`cairn sync-omp --apply` explicitly to install
|
|
85
|
+
`extensions/cairnkeep-memory.ts` and `extensions/cairnkeep-capture.ts` under
|
|
86
|
+
the omp agent root (default
|
|
87
|
+
`~/.omp/agent`; `PI_CODING_AGENT_DIR` overrides it, matching omp's agent
|
|
88
|
+
directory resolution). Use `--check` for drift. Uninstall removes only that
|
|
89
|
+
owned path, backup-first.
|
|
90
|
+
|
|
91
|
+
The extension is the Pi memory extension ported to omp's successor extension
|
|
92
|
+
API: it supervises `cairn memory-server` as a local stdio child through the
|
|
93
|
+
same bridge, discovers the effective MCP catalog dynamically, and registers
|
|
94
|
+
each tool natively with omp under its bare MCP name. omp accepts the MCP input
|
|
95
|
+
schema as a plain JSON Schema document and normalizes results to its
|
|
96
|
+
`AgentToolResult` shape, preserving the trusted call metadata in `details`. A
|
|
97
|
+
`cairn-memory` entry in the omp MCP config coexists without collision:
|
|
98
|
+
config-served MCP tools are minted with an `mcp__` name prefix, so the two
|
|
99
|
+
surfaces never claim the same tool name. Server feature gates, capability
|
|
100
|
+
state, and least-authority profiles continue to decide which tools exist.
|
|
101
|
+
|
|
102
|
+
Startup, calls, results, stderr retention, cancellation, and shutdown are
|
|
103
|
+
bounded. The extension adds tools only: it does not run prompts, activate
|
|
104
|
+
context-pack skills, create an autonomous loop, or add a remote transport.
|
|
105
|
+
`bun scripts/verify-omp-mcp-bridge.mjs` renders, loads, and exercises the
|
|
106
|
+
installed extension against a supervised memory server, including catalog
|
|
107
|
+
parity, the result shape, cancellation, shutdown, orphan-freedom, and
|
|
108
|
+
tool-name collision refusal.
|
|
109
|
+
|
|
110
|
+
Sync also installs `extensions/cairnkeep-capture.ts`, the omp port of the
|
|
111
|
+
Claude SessionEnd/SessionStart `memory-capture` + `memory-wakeup` hook pair.
|
|
112
|
+
On the first `session_stop` of a main session (the event never fires for
|
|
113
|
+
task/subagent sessions), it converts the persisted branch to transcript text
|
|
114
|
+
(user/assistant text only, capped at 12000 characters keeping the most recent
|
|
115
|
+
turns) and pipes it to a detached staging child that runs the shared
|
|
116
|
+
extraction and writes candidates to `.planning/memory-staging/` — one file
|
|
117
|
+
per session, retention capped at 5 — so staging completes even if the agent
|
|
118
|
+
process exits first. Candidates are staged for review only: writes to AgentFS
|
|
119
|
+
stay agent-gated via the `memory_write` tool. On `session_start` of the main
|
|
120
|
+
session, staged candidates are surfaced through a UI notification and a
|
|
121
|
+
`deliverAs: "nextTurn"` context message injected at the next user turn; the
|
|
122
|
+
`/cairn-staged` command lists the staged files on demand. Both halves are
|
|
123
|
+
fail-open and skip ephemeral side-turn runtimes whose extension actions are
|
|
124
|
+
not initialized. `bun scripts/verify-omp-capture.mjs` exercises the guards,
|
|
125
|
+
transcript shaping, staging contract, retention cap, session de-dupe, wakeup
|
|
126
|
+
injection, and the skip paths.
|
|
127
|
+
|
|
80
128
|
## Kimi Code
|
|
81
129
|
|
|
82
130
|
Kimi Code reads three MCP files, in increasing precedence:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Curriculum Coverage Map
|
|
2
2
|
|
|
3
|
-
**Baseline:** Cairnkeep 2.
|
|
3
|
+
**Baseline:** Cairnkeep 2.19.0
|
|
4
4
|
**Last reviewed:** 2026-08-19
|
|
5
5
|
|
|
6
6
|
This map prevents the course from drifting behind the product. It assigns each
|
|
@@ -91,6 +91,7 @@ against `cairn help` so a new command cannot bypass a curriculum decision.
|
|
|
91
91
|
| `cairn sync` | L02 |
|
|
92
92
|
| `cairn sync-pi` | L13 and L23 |
|
|
93
93
|
| `cairn sync-kimi` | L02 |
|
|
94
|
+
| `cairn sync-omp` | L02 |
|
|
94
95
|
| `cairn doctor` | L03; advanced repair in L13-L14 |
|
|
95
96
|
| `cairn playbook` | L25 |
|
|
96
97
|
| `cairn trajectory` | L13 |
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cairnkeep feature guide
|
|
2
2
|
|
|
3
|
-
**Baseline:** Cairnkeep 2.
|
|
3
|
+
**Baseline:** Cairnkeep 2.19.0
|
|
4
4
|
|
|
5
5
|
This is the step-back map for choosing and operating Cairnkeep features. The
|
|
6
6
|
[course labs](https://github.com/cairnkeep/cairnkeep-course-labs) provide one
|
|
@@ -86,6 +86,7 @@ prerequisites for ordinary memory.
|
|
|
86
86
|
| Context packs | Manual local or commit-pinned Git install plus project enablement | Immutable objects and atomic pointers under `CAIRN_PACK_BASE_DIR`; no background sync | Validate, inspect digest, check/apply update, disable/remove | `course-10-trust-context` |
|
|
87
87
|
| OKF exchange | `cairn pack validate-okf`, `import-okf`, and preview-confirm `export-okf` | Local import/export by default; explicit file/shared-note allowlist; redacted output | Inspect diagnostics/provenance/output list; exact-digest apply; disable/remove imported pack | `course-10-trust-context` |
|
|
88
88
|
| Pi local stdio memory | Select Pi during setup, then explicitly run `cairn sync-pi --apply` | Local memory-server child; dynamic effective tool catalog; annotations retained in trusted details, not a native Pi field | `cairn sync-pi --check`, `cairn doctor`, cancel one call, then observe awaited shutdown with no orphan | `course-12-guided-setup` |
|
|
89
|
+
| OMP local stdio memory | Select OMP during setup, then explicitly run `cairn sync-omp --apply` | Local memory-server child; dynamic effective tool catalog; capture stages candidates for review | `cairn sync-omp --check`, `cairn doctor`, cancel one call, then verify session-stop staging and no orphan | `course-12-guided-setup` |
|
|
89
90
|
|
|
90
91
|
## Evidence, governance, and measurement
|
|
91
92
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
**Status:** Ready
|
|
4
4
|
**Track:** Quickstart and Operator
|
|
5
5
|
**Time:** 35 minutes
|
|
6
|
-
**Tested with:** Cairnkeep 2.
|
|
6
|
+
**Tested with:** Cairnkeep 2.19.0; Pi 0.84.1; Node.js 22, 24, and 26
|
|
7
7
|
|
|
8
8
|
## Outcome
|
|
9
9
|
|
|
@@ -13,13 +13,14 @@ Pi's local stdio memory bridge, and recover or uninstall every managed asset
|
|
|
13
13
|
without hidden machine changes.
|
|
14
14
|
|
|
15
15
|
The selected harnesses come from Cairnkeep's declarative registry. Codex is a
|
|
16
|
-
supported selection: it receives `.codex/config.toml` and a launcher
|
|
17
|
-
|
|
16
|
+
supported selection: it receives `.codex/config.toml` and a launcher. Pi and
|
|
17
|
+
OMP receive project launchers and each require a separate, explicit machine
|
|
18
|
+
sync; selecting both reports both sync commands.
|
|
18
19
|
|
|
19
20
|
## Prerequisites
|
|
20
21
|
|
|
21
22
|
- Node.js 22 or newer, npm, and Git for the main exercise.
|
|
22
|
-
- Pi 0.84.1 or newer.
|
|
23
|
+
- Pi 0.84.1 or newer; OMP is optional.
|
|
23
24
|
- A disposable parent directory containing no credentials, secrets, private
|
|
24
25
|
state, or identifying project data.
|
|
25
26
|
|
|
@@ -32,7 +33,7 @@ cairn setup /tmp/cairnkeep-guided-selector-lab
|
|
|
32
33
|
```
|
|
33
34
|
|
|
34
35
|
Choose Git with Up/Down and Enter, tick Pi with Space in the harness checklist,
|
|
35
|
-
keep local memory, then inspect the plan before confirming. Pressing Escape or
|
|
36
|
+
optionally tick OMP as well, keep local memory, then inspect the plan before confirming. Pressing Escape or
|
|
36
37
|
Ctrl-C cancels; redirected and limited terminals use the documented text-input
|
|
37
38
|
fallback. Remove that disposable selector lab before continuing if you applied
|
|
38
39
|
the plan.
|
|
@@ -63,6 +64,14 @@ cairn doctor
|
|
|
63
64
|
./.ai/start-pi.sh
|
|
64
65
|
```
|
|
65
66
|
|
|
67
|
+
If OMP was selected, run its separate sync and use the generated launcher:
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
cairn sync-omp --apply
|
|
71
|
+
cairn sync-omp --check
|
|
72
|
+
./.ai/start-omp.sh
|
|
73
|
+
```
|
|
74
|
+
|
|
66
75
|
In the disposable Pi session, list the registered Cairnkeep tools and make one
|
|
67
76
|
harmless read-only memory call. The extension starts `cairn memory-server` as a
|
|
68
77
|
local stdio child in this project; it does not select HTTP or a remote server.
|
|
@@ -107,9 +116,10 @@ cairn sync-pi --check
|
|
|
107
116
|
cairn doctor
|
|
108
117
|
```
|
|
109
118
|
|
|
110
|
-
Doctor reports project-state drift separately from missing or drifted
|
|
119
|
+
Doctor reports project-state drift separately from missing or drifted harness
|
|
111
120
|
machine assets. Setup repairs only recorded project assets; `cairn sync-pi
|
|
112
|
-
--apply`
|
|
121
|
+
--apply` and `cairn sync-omp --apply` repair only their respective package-owned
|
|
122
|
+
machine paths.
|
|
113
123
|
|
|
114
124
|
Preview backup-first removal before confirming it:
|
|
115
125
|
|
|
@@ -128,6 +138,7 @@ and context packs remain unless their separate purge flags are supplied.
|
|
|
128
138
|
| Setup refuses a missing target | The non-interactive command omitted an explicit choice or `--yes` | Run `cairn setup PATH` in a terminal, or supply the target, `--git`, `--harness`, `--memory`, and `--yes` together |
|
|
129
139
|
| Setup refuses `--git existing` | The target is not inside a Git work tree | Choose an existing repository, or explicitly authorize `--git init`; use `--git none` only when limited mode is intended |
|
|
130
140
|
| Doctor reports missing or drifted Pi assets | Project setup selected Pi but machine sync is incomplete | Run `cairn sync-pi --apply`, then `cairn sync-pi --check` and `cairn doctor` |
|
|
141
|
+
| OMP is missing an extension | Project setup selected OMP but its explicit machine sync was not applied | Run `cairn sync-omp --apply`, then `cairn sync-omp --check` and `cairn doctor` |
|
|
131
142
|
| A cancelled call ends the session | The Pi/bridge version does not satisfy the per-call cancellation contract | Preserve sanitized diagnostics, close the session, and do not claim release readiness |
|
|
132
143
|
| Pi exits but a child process remains | Shutdown did not complete or the tested extension drifted | Preserve process-state evidence, run the sync check, and treat the release gate as failed |
|
|
133
144
|
| A client expects native annotation hints | Pi's public tool API has no annotations field | Inspect trusted bridge metadata/result `details`; never claim native propagation |
|
package/docs/operating.md
CHANGED
|
@@ -75,7 +75,7 @@ cairn setup /path/to/project --git init --harness claude,pi --memory local --yes
|
|
|
75
75
|
```
|
|
76
76
|
|
|
77
77
|
The deterministic form accepts `--git init|existing|none`, a comma-separated
|
|
78
|
-
subset of `claude,opencode,pi,kimi,qwen,codex`, and `--memory local|none`. `--git
|
|
78
|
+
subset of `claude,opencode,pi,omp,kimi,qwen,codex`, and `--memory local|none`. `--git
|
|
79
79
|
existing` requires the target to be in an existing work tree. `--git init`
|
|
80
80
|
requires Git and is the only non-interactive authorization to initialize a
|
|
81
81
|
repository. `--git none` is an explicit limited mode: repository-aware features
|
|
@@ -95,16 +95,21 @@ selected harnesses, and digests/modes/template identifiers for setup-owned
|
|
|
95
95
|
assets. It contains no credentials, endpoints, or absolute paths.
|
|
96
96
|
|
|
97
97
|
Setup never installs or refreshes machine-level harness assets. Its
|
|
98
|
-
`machine_sync.automatic` field is always false, and the human output labels
|
|
99
|
-
reported command as not run automatically.
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
`machine_sync.automatic` field is always false, and the human output labels each
|
|
99
|
+
reported command as not run automatically. The JSON result's
|
|
100
|
+
`machine_sync.commands` lists every required command; the older singular
|
|
101
|
+
`machine_sync.command` field remains as the first command for compatibility.
|
|
102
|
+
For selections such as Codex and Qwen that need no machine sync,
|
|
103
|
+
`machine_sync.commands` is empty and the human output says that sync is not
|
|
104
|
+
required. Apply each reported command explicitly, check the corresponding
|
|
105
|
+
assets, then diagnose and launch:
|
|
103
106
|
|
|
104
107
|
```bash
|
|
105
108
|
cairn sync --apply # Claude Code operating assets
|
|
106
109
|
cairn sync-pi --apply # Pi extension and prompt
|
|
107
110
|
cairn sync-pi --check
|
|
111
|
+
cairn sync-omp --apply # OMP extensions
|
|
112
|
+
cairn sync-omp --check
|
|
108
113
|
cd /path/to/project && cairn doctor
|
|
109
114
|
./.ai/start-pi.sh
|
|
110
115
|
```
|
|
@@ -461,6 +466,8 @@ vendor or host.
|
|
|
461
466
|
| `CAIRN_LLM_API_KEY` | API key for the extraction / embeddings endpoint (unset → substring-only memory) |
|
|
462
467
|
| `CAIRN_LLM_API_URL` | Base URL of the OpenAI-compatible endpoint |
|
|
463
468
|
| `CAIRN_LLM_EXTRACTION_MODEL` | Chat model for `memory-capture` extraction |
|
|
469
|
+
| `CAIRN_PI_BRIDGE_COMMAND` | Memory-server command for the `pi-bridge-child` stdio host (default `cairn`) |
|
|
470
|
+
| `CAIRN_PI_BRIDGE_ARGS` | JSON argument array for the bridge child server command (default `["memory-server"]`) |
|
|
464
471
|
| `CAIRN_MEMORY_EMBEDDING_URL` | Embeddings endpoint (falls back to `CAIRN_LLM_API_URL`) |
|
|
465
472
|
| `CAIRN_MEMORY_EMBEDDING_MODEL` | Embedding model name (required for semantic search) |
|
|
466
473
|
| `CAIRN_MEMORY_EMBEDDING_TIMEOUT_MS` | Embedding request timeout before substring fallback (default `15000`) |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"identifier":"cairn-offline-fake-v1","package_version":"2.
|
|
1
|
+
{"identifier":"cairn-offline-fake-v1","package_version":"2.19.0","schema_version":1,"task_set_digest":"13e95379f35839593047ec34521a65a8fa3ab92bd3993bca9dc8bf5c4a9ff36f"}
|
|
@@ -32,7 +32,7 @@ export const artifactNodeRefSchema = z.object({
|
|
|
32
32
|
export const artifactProvenanceSchema = z.object({
|
|
33
33
|
producer: z.string().min(1).max(256).refine((value) => !/[\u0000-\u001f\u007f]/.test(value)),
|
|
34
34
|
source_event: z.string().min(1).max(256).optional(),
|
|
35
|
-
harness: z.enum(["claude-code", "opencode", "pi"]).optional(),
|
|
35
|
+
harness: z.enum(["claude-code", "opencode", "pi", "omp"]).optional(),
|
|
36
36
|
harness_version: z.string().min(1).max(128).optional(),
|
|
37
37
|
native_id: z.string().min(1).max(256).optional(),
|
|
38
38
|
}).strict();
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { childEnvironment, connectCairnPiBridge } from "./pi-mcp-bridge.js";
|
|
2
|
+
const STDERR_LIMIT_BYTES = 16 * 1024;
|
|
3
|
+
let stderrTail = "";
|
|
4
|
+
const stderrWrite = process.stderr.write.bind(process.stderr);
|
|
5
|
+
process.stderr.write = ((chunk, ...rest) => {
|
|
6
|
+
const text = typeof chunk === "string" ? chunk : String(chunk);
|
|
7
|
+
const next = stderrTail + text;
|
|
8
|
+
stderrTail = next.length <= STDERR_LIMIT_BYTES ? next : next.slice(next.length - STDERR_LIMIT_BYTES);
|
|
9
|
+
return stderrWrite(chunk, ...rest);
|
|
10
|
+
});
|
|
11
|
+
function send(message) {
|
|
12
|
+
process.stdout.write(`${JSON.stringify(message)}\n`);
|
|
13
|
+
}
|
|
14
|
+
function fatal(error) {
|
|
15
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
16
|
+
process.stderr.write(`${JSON.stringify({ type: "error", error: message })}\n`);
|
|
17
|
+
process.exit(1);
|
|
18
|
+
}
|
|
19
|
+
process.on("uncaughtException", fatal);
|
|
20
|
+
process.on("unhandledRejection", (reason) => fatal(reason));
|
|
21
|
+
async function main() {
|
|
22
|
+
const cwd = process.argv[2] ?? process.cwd();
|
|
23
|
+
const command = process.env.CAIRN_PI_BRIDGE_COMMAND ?? "cairn";
|
|
24
|
+
const args = JSON.parse(process.env.CAIRN_PI_BRIDGE_ARGS ?? '["memory-server"]');
|
|
25
|
+
const bridge = await connectCairnPiBridge({ cwd, command, args, env: childEnvironment(process.env) });
|
|
26
|
+
const controllers = new Map();
|
|
27
|
+
let stdinBuffer = "";
|
|
28
|
+
let closing = false;
|
|
29
|
+
const close = async () => {
|
|
30
|
+
if (closing)
|
|
31
|
+
return;
|
|
32
|
+
closing = true;
|
|
33
|
+
await bridge.close().catch(() => undefined);
|
|
34
|
+
process.exit(0);
|
|
35
|
+
};
|
|
36
|
+
process.on("SIGTERM", () => void close());
|
|
37
|
+
process.on("SIGINT", () => void close());
|
|
38
|
+
process.stdin.on("end", () => void close());
|
|
39
|
+
async function handle(request) {
|
|
40
|
+
try {
|
|
41
|
+
switch (request.type) {
|
|
42
|
+
case "list": {
|
|
43
|
+
send({ type: "result", id: request.id, ok: true, tools: await bridge.listAllTools() });
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
case "call": {
|
|
47
|
+
const controller = new AbortController();
|
|
48
|
+
controllers.set(request.id, controller);
|
|
49
|
+
try {
|
|
50
|
+
const result = await bridge.call(request.tool, request.args ?? {}, { signal: controller.signal });
|
|
51
|
+
send({ type: "result", id: request.id, ok: true, result });
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
send({
|
|
55
|
+
type: "result",
|
|
56
|
+
id: request.id,
|
|
57
|
+
ok: false,
|
|
58
|
+
error: error instanceof Error ? error.message : String(error),
|
|
59
|
+
stderr: stderrTail,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
controllers.delete(request.id);
|
|
64
|
+
}
|
|
65
|
+
break;
|
|
66
|
+
}
|
|
67
|
+
case "cancel": {
|
|
68
|
+
controllers.get(request.id)?.abort(new Error("cancelled"));
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case "close": {
|
|
72
|
+
await close();
|
|
73
|
+
break;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
const id = typeof request.id === "number" ? request.id : -1;
|
|
79
|
+
send({
|
|
80
|
+
type: "result",
|
|
81
|
+
id,
|
|
82
|
+
ok: false,
|
|
83
|
+
error: error instanceof Error ? error.message : String(error),
|
|
84
|
+
stderr: stderrTail,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
process.stdin.on("data", (chunk) => {
|
|
89
|
+
stdinBuffer += chunk.toString("utf8");
|
|
90
|
+
let newline = stdinBuffer.indexOf("\n");
|
|
91
|
+
while (newline >= 0) {
|
|
92
|
+
const line = stdinBuffer.slice(0, newline);
|
|
93
|
+
stdinBuffer = stdinBuffer.slice(newline + 1);
|
|
94
|
+
newline = stdinBuffer.indexOf("\n");
|
|
95
|
+
if (!line.trim())
|
|
96
|
+
continue;
|
|
97
|
+
let request;
|
|
98
|
+
try {
|
|
99
|
+
request = JSON.parse(line);
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
void handle(request);
|
|
105
|
+
}
|
|
106
|
+
});
|
|
107
|
+
send({ type: "ready" });
|
|
108
|
+
}
|
|
109
|
+
main().catch(fatal);
|
|
@@ -11,11 +11,23 @@ function positiveInteger(value, fallback, name) {
|
|
|
11
11
|
throw new Error(`${name} must be a positive integer.`);
|
|
12
12
|
return selected;
|
|
13
13
|
}
|
|
14
|
-
|
|
14
|
+
// Bun-hosted agents (pi, omp) prepend a /tmp/bun-node-* dir whose `node` is
|
|
15
|
+
// Bun itself; grandchildren like `cairn memory-server` spawn real node
|
|
16
|
+
// subprocesses, so those shim dirs must not shadow it.
|
|
17
|
+
const BUN_NODE_SHIM = /\/tmp\/bun-node-[^/:]+$/;
|
|
18
|
+
export function childEnvironment(source) {
|
|
15
19
|
const env = {};
|
|
16
20
|
for (const [name, value] of Object.entries(source)) {
|
|
17
|
-
if (value
|
|
18
|
-
|
|
21
|
+
if (value === undefined || name === "MCP_HTTP_PORT")
|
|
22
|
+
continue;
|
|
23
|
+
if (name === "PATH") {
|
|
24
|
+
env[name] = value
|
|
25
|
+
.split(":")
|
|
26
|
+
.filter((entry) => !BUN_NODE_SHIM.test(entry))
|
|
27
|
+
.join(":");
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
env[name] = value;
|
|
19
31
|
}
|
|
20
32
|
return env;
|
|
21
33
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { z } from "zod";
|
|
2
2
|
export const WORK_EVIDENCE_SCHEMA_VERSION = 1;
|
|
3
|
-
export const WORK_EVIDENCE_HARNESSES = ["claude", "opencode", "pi", "kimi", "qwen", "codex"];
|
|
3
|
+
export const WORK_EVIDENCE_HARNESSES = ["claude", "opencode", "pi", "omp", "kimi", "qwen", "codex"];
|
|
4
4
|
export const WORK_EVIDENCE_DEFAULT_RETENTION_DAYS = 30;
|
|
5
5
|
export const WORK_EVIDENCE_DEFAULT_STORE_MAX_BYTES = 64 * 1024 * 1024;
|
|
6
6
|
export const WORK_EVIDENCE_DEFAULT_MAX_TOUCHED_PATHS = 4096;
|
|
@@ -292,7 +292,7 @@ export async function finishWorkEvidence(projectRoot, evidenceId, exitStatus, op
|
|
|
292
292
|
provenance: {
|
|
293
293
|
producer: "cairn-work-evidence",
|
|
294
294
|
source_event: "launcher-exit",
|
|
295
|
-
harness: start.harness === "claude" ? "claude-code" : ["opencode", "pi"].includes(start.harness) ? start.harness : undefined,
|
|
295
|
+
harness: start.harness === "claude" ? "claude-code" : ["opencode", "pi", "omp"].includes(start.harness) ? start.harness : undefined,
|
|
296
296
|
},
|
|
297
297
|
content: { text: patchCapture.text },
|
|
298
298
|
}, { ...artifactLimits, artifactMaxBytes: Math.min(artifactLimits.artifactMaxBytes, limits.patchMaxBytes) });
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@cairnkeep/memory-server",
|
|
3
3
|
"version": "0.1.0",
|
|
4
4
|
"private": true,
|
|
5
|
-
"description": "Durable, harness-agnostic memory MCP server for coding agents
|
|
5
|
+
"description": "Durable, harness-agnostic memory MCP server for coding agents \u2014 the core of Cairnkeep.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"engines": {
|
|
@@ -61,10 +61,12 @@
|
|
|
61
61
|
"check:playbook": "node scripts/smoke-playbook.mjs",
|
|
62
62
|
"check:notes": "npm run build && npm run check:note-signatures && npm run check:note-distillation && npm run check:note-enrichment",
|
|
63
63
|
"test": "npm run test:smoke",
|
|
64
|
-
"test:smoke": "npm run build && npm run check:embeddings && npm run check:extract && npm run check:scope-guard && npm run check:http-guard && npm run check:remote-context && npm run check:explore-guard && npm run check:explore-cache && npm run check:explore-crossref && npm run check:route-guard && npm run check:reviewed-memory && npm run check:memory-proposals && npm run check:trajectory-roundtrip && npm run check:trajectory-redaction && npm run check:trajectory-retention && npm run check:note-signatures && npm run check:note-distillation && npm run check:note-enrichment && npm run check:node-compat && npm run check:typed-nodes && npm run check:memory-import && npm run check:note-mcp && npm run check:node-doctor && npm run check:artifact-store && npm run check:artifact-mcp && npm run check:compaction-capture && npm run check:capability-contract && npm run check:capability-logging && npm run check:capability-harness && npm run check:capability-mcp && npm run check:eval-schema && npm run check:eval-process && npm run check:eval-statistics && npm run check:skill-lifecycle && npm run check:graph-cli && npm run check:mcp-trust && npm run check:pi-mcp-bridge && npm run check:context-pack && npm run check:context-pack-retrieval && npm run check:context-pack-v216-compat && npm run check:context-usage && npm run check:domain-retrieval && npm run check:retrieval-benchmark && npm run check:work-evidence && npm run check:okf && npm run check:playbook",
|
|
64
|
+
"test:smoke": "npm run build && npm run check:embeddings && npm run check:extract && npm run check:scope-guard && npm run check:http-guard && npm run check:remote-context && npm run check:explore-guard && npm run check:explore-cache && npm run check:explore-crossref && npm run check:route-guard && npm run check:reviewed-memory && npm run check:memory-proposals && npm run check:trajectory-roundtrip && npm run check:trajectory-redaction && npm run check:trajectory-retention && npm run check:note-signatures && npm run check:note-distillation && npm run check:note-enrichment && npm run check:node-compat && npm run check:typed-nodes && npm run check:memory-import && npm run check:note-mcp && npm run check:node-doctor && npm run check:artifact-store && npm run check:artifact-mcp && npm run check:compaction-capture && npm run check:capability-contract && npm run check:capability-logging && npm run check:capability-harness && npm run check:capability-mcp && npm run check:eval-schema && npm run check:eval-process && npm run check:eval-statistics && npm run check:skill-lifecycle && npm run check:graph-cli && npm run check:mcp-trust && npm run check:pi-mcp-bridge && npm run check:pi-bridge-env && npm run check:pi-bridge-child && npm run check:context-pack && npm run check:context-pack-retrieval && npm run check:context-pack-v216-compat && npm run check:context-usage && npm run check:domain-retrieval && npm run check:retrieval-benchmark && npm run check:work-evidence && npm run check:okf && npm run check:playbook",
|
|
65
65
|
"test:search": "npm run build && npm run check:search",
|
|
66
66
|
"test:memory": "npm run build && npm run check:embeddings && npm run check:extract && npm run check:search",
|
|
67
|
-
"test:all": "npm run test:memory"
|
|
67
|
+
"test:all": "npm run test:memory",
|
|
68
|
+
"check:pi-bridge-env": "node scripts/smoke-pi-bridge-env.mjs",
|
|
69
|
+
"check:pi-bridge-child": "node scripts/smoke-pi-bridge-child.mjs"
|
|
68
70
|
},
|
|
69
71
|
"dependencies": {
|
|
70
72
|
"@modelcontextprotocol/sdk": "^1.30.0",
|