@cairnkeep/cli 2.15.1 → 2.15.2
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 +18 -0
- package/README.md +8 -1
- package/docs/harness-compatibility.md +27 -5
- package/docs/learning/CURRICULUM-MAP.md +3 -3
- package/docs/learning/FEATURE-GUIDE.md +5 -2
- 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 +1 -1
- package/docs/learning/lessons/L24-okf-exchange.md +1 -1
- package/docs/learning/lessons/L25-playbooks.md +10 -1
- package/docs/learning/video-scripts/V25-playbooks.md +4 -2
- package/docs/operating.md +13 -2
- package/docs/quickstart.md +9 -4
- package/examples/eval/bundled-fake.json +1 -1
- package/mcp-memory-server/dist/playbook.js +60 -22
- package/package.json +1 -1
- package/scripts/test-package-install.sh +2 -0
- package/scripts/test-playbook-instructions.sh +5 -0
- package/scripts/test-windows-native.mjs +2 -0
- package/templates/playbook-agent-instructions.md.template +16 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,24 @@ All notable user-facing changes are documented here. This project follows
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [2.15.2] - 2026-08-18
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Add a generic, ownership-safe durable-context protocol to the managed project
|
|
13
|
+
`AGENTS.md` block. Compatible agents derive one short project-memory query
|
|
14
|
+
before broad exploration when prior decisions or conventions may matter,
|
|
15
|
+
verify referenced repository sources, fall back cleanly when retrieval is
|
|
16
|
+
unavailable, and never promote memory automatically.
|
|
17
|
+
- Extend setup, bootstrap, installed-package, native Windows, uninstall, and
|
|
18
|
+
documentation coverage for the managed retrieval guidance.
|
|
19
|
+
|
|
20
|
+
### Fixed
|
|
21
|
+
|
|
22
|
+
- Serialize same-process playbook configuration mutations before taking the
|
|
23
|
+
filesystem lock, avoiding Windows CI lock starvation under concurrent
|
|
24
|
+
profile and reset operations while preserving cross-process exclusion.
|
|
25
|
+
|
|
8
26
|
## [2.15.1] - 2026-08-17
|
|
9
27
|
|
|
10
28
|
### Fixed
|
package/README.md
CHANGED
|
@@ -51,6 +51,9 @@ launchers, including native Windows, without capturing prompts or replacing Git.
|
|
|
51
51
|
Version 2.15 adds bounded project playbooks that help agents select existing
|
|
52
52
|
recall, planning, verification, review, security, documentation, and learning
|
|
53
53
|
steps without becoming an agent runtime or granting approval.
|
|
54
|
+
Version 2.15.2 adds a generic durable-context protocol to the ownership-safe
|
|
55
|
+
managed project instructions so compatible agents can derive one project
|
|
56
|
+
memory query before broad exploration and verify its repository provenance.
|
|
54
57
|
|
|
55
58
|
## Compatibility
|
|
56
59
|
|
|
@@ -203,7 +206,11 @@ The exact command rendering depends on the client. Any MCP client can call
|
|
|
203
206
|
`memory_write` and `memory_search` directly.
|
|
204
207
|
|
|
205
208
|
Setup also installs a balanced `.ai/playbooks.json` policy and an ownership-safe
|
|
206
|
-
managed block in `AGENTS.md`.
|
|
209
|
+
managed block in `AGENTS.md`. The block directs compatible agents to make one
|
|
210
|
+
task-derived, project-scoped memory search for nontrivial work involving prior
|
|
211
|
+
decisions, conventions, constraints, or failures. Results are locators, not
|
|
212
|
+
authority; referenced repository sources must be verified, and memory is never
|
|
213
|
+
promoted automatically. Agents can evaluate the playbook at task boundaries:
|
|
207
214
|
|
|
208
215
|
```bash
|
|
209
216
|
cairn playbook check start --complexity standard --familiarity mixed
|
|
@@ -17,18 +17,20 @@ Cairnkeep commands, hooks or native trajectory capture.
|
|
|
17
17
|
| Claude Code | Memory MCP, commands (including `/cairn-work`), agents, hooks, launcher | Exercised by Cairnkeep tests |
|
|
18
18
|
| OpenCode | Memory MCP, commands (including `/cairn-work`), workflows, plugins, launcher | Exercised by Cairnkeep tests |
|
|
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
|
-
| Qwen Code | Memory MCP, launcher, project `AGENTS.md` playbook guidance | Launcher tested; stdio and remote MCP tested with Qwen Code 0.21.1 |
|
|
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
|
-
| Codex CLI | Project-scoped memory MCP, launcher, and project `AGENTS.md` playbook guidance | Setup and launcher contract-tested on POSIX and simulated native Windows; project trust remains operator-controlled |
|
|
22
|
+
| 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
23
|
| Other MCP clients | Memory plus optional domain-knowledge and context-pack tools | Protocol-compatible; not automatically runtime-tested |
|
|
24
24
|
|
|
25
25
|
Only Claude Code and OpenCode currently receive the complete operating layer.
|
|
26
26
|
Kimi receives narrow graph and playbook Skills, while Pi receives matching narrow prompts;
|
|
27
27
|
neither is equivalent to the full commands, agents, hooks, and plugins surface.
|
|
28
28
|
Qwen skills and hooks still require harness-specific adaptation and validation.
|
|
29
|
-
Codex receives a project-local MCP entry, launcher, and portable
|
|
30
|
-
instructions, but not Cairnkeep-specific commands, hooks, agents,
|
|
31
|
-
skill activation.
|
|
29
|
+
Codex receives a project-local MCP entry, launcher, and portable durable-context
|
|
30
|
+
and playbook instructions, but not Cairnkeep-specific commands, hooks, agents,
|
|
31
|
+
or automatic skill activation. Harness behavior remains probabilistic;
|
|
32
|
+
instruction presence must not be reported as a tool invocation without runtime
|
|
33
|
+
evidence.
|
|
32
34
|
|
|
33
35
|
Every MCP client receives complete tool annotations and may use a Cairnkeep
|
|
34
36
|
least-authority profile independent of harness assets. Context-pack tools are
|
|
@@ -240,6 +242,26 @@ The launcher loads `.ai/.env`, runs optional pre/post hooks, changes to the
|
|
|
240
242
|
project root, and passes all arguments to `codex`. It does not install native
|
|
241
243
|
Codex Skills or instructions and does not activate approved context-pack skills.
|
|
242
244
|
|
|
245
|
+
Codex uses MCP annotations when deciding whether a tool needs approval. In
|
|
246
|
+
non-interactive `codex exec`, an unapproved mutating call is cancelled rather
|
|
247
|
+
than silently executed. Cairnkeep intentionally does not autoapprove memory
|
|
248
|
+
writes during setup. An operator who has explicitly authorized a bounded,
|
|
249
|
+
unattended workflow may add narrow per-tool policy to the isolated Codex config:
|
|
250
|
+
|
|
251
|
+
```toml
|
|
252
|
+
[mcp_servers.cairn-memory.tools.memory_write]
|
|
253
|
+
approval_mode = "approve"
|
|
254
|
+
|
|
255
|
+
[mcp_servers.cairn-memory.tools.memory_supersede]
|
|
256
|
+
approval_mode = "approve"
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
Do not add this to shared or ordinary interactive configuration merely to avoid
|
|
260
|
+
prompts. Keep the allowlist limited to the authorized tools and continue to use
|
|
261
|
+
Cairn MCP profiles and project isolation. See the
|
|
262
|
+
[official Codex MCP configuration reference](https://developers.openai.com/codex/mcp)
|
|
263
|
+
for approval-mode semantics.
|
|
264
|
+
|
|
243
265
|
## Candidate memory clients
|
|
244
266
|
|
|
245
267
|
The following clients have documented MCP support and are reasonable adapter
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Curriculum Coverage Map
|
|
2
2
|
|
|
3
|
-
**Baseline:** Cairnkeep 2.15.
|
|
4
|
-
**Last reviewed:** 2026-08-
|
|
3
|
+
**Baseline:** Cairnkeep 2.15.2
|
|
4
|
+
**Last reviewed:** 2026-08-18
|
|
5
5
|
|
|
6
6
|
This map prevents the course from drifting behind the product. It assigns each
|
|
7
7
|
user-facing surface to a lesson and records whether the lesson is complete or
|
|
@@ -40,7 +40,7 @@ been rehearsed.
|
|
|
40
40
|
| Guided project setup, selected harness state, and Git-less limitations | L03 | L03 and L23 | Ready |
|
|
41
41
|
| Pi local stdio memory bridge, trusted annotation details, and explicit lifecycle | L23 | L23 | Ready; Pi 0.84.1 validated minimum |
|
|
42
42
|
| OKF 0.1/0.2 validation/import, provenance, links, regressions, and reviewed 0.2 export | L24 | L24 | Ready; local/offline by default |
|
|
43
|
-
| Bounded project playbooks,
|
|
43
|
+
| Bounded project playbooks, generic memory retrieval guidance, enforcement, and private receipts | L25 | L25 | Ready; balanced/local by default; invocation requires runtime evidence; actor identity unverified |
|
|
44
44
|
|
|
45
45
|
## Release Review
|
|
46
46
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Cairnkeep feature guide
|
|
2
2
|
|
|
3
|
-
**Baseline:** Cairnkeep 2.15.
|
|
3
|
+
**Baseline:** Cairnkeep 2.15.2
|
|
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
|
|
@@ -20,6 +20,9 @@ deterministic links, and reviewed OKF 0.2 export; see
|
|
|
20
20
|
[L24](lessons/L24-okf-exchange.md).
|
|
21
21
|
Version 2.15 adds local bounded playbooks and private outcome receipts; see
|
|
22
22
|
[L25](lessons/L25-playbooks.md).
|
|
23
|
+
Version 2.15.2 adds generic task-derived, project-scoped memory guidance to the
|
|
24
|
+
same ownership-safe managed instructions. Retrieval remains a locator and
|
|
25
|
+
actual tool invocation must be verified from runtime evidence.
|
|
23
26
|
|
|
24
27
|
## The three-layer model
|
|
25
28
|
|
|
@@ -65,7 +68,7 @@ prerequisites for ordinary memory.
|
|
|
65
68
|
| Repository quality | `/repo-review`, `/security-audit` | On-demand workflow; findings are hypotheses until reproduced | Require file/line evidence and regression tests | `course-03-quality` |
|
|
66
69
|
| Guided project setup | `cairn setup PATH --git init\|existing\|none --harness LIST --memory local\|none --yes` | Reconciles only selected project assets from one harness registry; private `.ai/cairnkeep.json`; machine sync is never automatic | Repeat deterministically, run doctor, or replay its recovery command; Git-less mode remains limited | `course-12-guided-setup` |
|
|
67
70
|
| Codex project memory | Select `--harness codex --memory local` | Writes `.codex/config.toml` plus POSIX/native Windows launchers; local stdio; user-wide configuration and trust remain untouched | Review the MCP table, accept Codex project trust, run doctor, and relaunch; uninstall is backup-first | `course-01-bootstrap` |
|
|
68
|
-
| Workflow playbooks | `cairn playbook check start|check|finish`; project `minimal`, `balanced`, or `strict` policy | Balanced by default; private `.ai/playbooks.json`; optional receipts in `.agentfs/playbooks/`; checks are offline and execute nothing |
|
|
71
|
+
| Workflow playbooks and durable-context guidance | `cairn playbook check start|check|finish`; project `minimal`, `balanced`, or `strict` policy; managed `AGENTS.md` retrieval protocol | Balanced by default; private `.ai/playbooks.json`; one task-derived project search when applicable; optional receipts in `.agentfs/playbooks/`; checks are offline and execute nothing | Verify the actual memory tool event and maintained source, inspect status/digests, enforce truthful `must` evidence, inspect receipts, reset overrides, remove only the managed `AGENTS.md` block | `course-13-playbooks` |
|
|
69
72
|
|
|
70
73
|
## Storage and optional topology
|
|
71
74
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# L25 - Bounded workflow playbooks
|
|
2
2
|
|
|
3
3
|
**Status:** Ready
|
|
4
|
-
**Tested with:** Cairnkeep 2.15.
|
|
4
|
+
**Tested with:** Cairnkeep 2.15.2 and Node.js 22 or newer
|
|
5
5
|
**Time:** 35 minutes
|
|
6
6
|
|
|
7
7
|
## Outcome
|
|
@@ -86,6 +86,13 @@ cairn playbook set balanced
|
|
|
86
86
|
|
|
87
87
|
## Privacy and trust boundary
|
|
88
88
|
|
|
89
|
+
The managed `AGENTS.md` block also gives compatible agents a bounded durable
|
|
90
|
+
context protocol: derive one short project query for a nontrivial task, treat
|
|
91
|
+
memory as a locator, and verify the maintained source. It does not contain a
|
|
92
|
+
task-specific query, force a tool call, or authorize an automatic memory write.
|
|
93
|
+
When evaluating the protocol, inspect the actual `memory_search` event rather
|
|
94
|
+
than assuming the instruction was followed.
|
|
95
|
+
|
|
89
96
|
Checks are offline and store nothing. Explicit receipts contain bounded
|
|
90
97
|
identifiers, digests, event/action/outcome/reason, and a timestamp, but no
|
|
91
98
|
prompt, file body, diff, command output, credential, or environment snapshot.
|
|
@@ -111,4 +118,6 @@ rm -rf "$lab"
|
|
|
111
118
|
evidence clears the relevant block.
|
|
112
119
|
- The receipt is private, project-bound, bounded, and visible to `doctor`.
|
|
113
120
|
- Removing managed instructions preserves all surrounding `AGENTS.md` content.
|
|
121
|
+
- The installed memory guidance contains no task-specific query and degrades to
|
|
122
|
+
ordinary inspection when `memory_search` is unavailable.
|
|
114
123
|
- No check executes an action, contacts a network service, or grants approval.
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
harness remains the agent runtime and every approval remains in force.
|
|
10
10
|
2. Run guided setup in a synthetic project. Show `.ai/playbooks.json` mode and
|
|
11
11
|
the delimited Cairnkeep block inside an `AGENTS.md` that already has user
|
|
12
|
-
content.
|
|
12
|
+
content. Point out the generic durable-context protocol: it derives a query
|
|
13
|
+
from the task, treats memory as a locator, and never writes automatically.
|
|
13
14
|
3. Compare `minimal`, `balanced`, and `strict` with `cairn playbook status`.
|
|
14
15
|
Customize one canonical action and show that an arbitrary command or unknown
|
|
15
16
|
field is rejected.
|
|
@@ -23,7 +24,8 @@
|
|
|
23
24
|
absent.
|
|
24
25
|
7. Show `/cairn-work` in Claude or OpenCode and the portable `AGENTS.md`
|
|
25
26
|
guidance for Codex/Qwen. State that adapters route to the same CLI and do not
|
|
26
|
-
automatically activate skills.
|
|
27
|
+
automatically activate skills. Show one real `memory_search` event so the
|
|
28
|
+
instruction is not mistaken for proof of invocation.
|
|
27
29
|
8. Remove the managed instruction block, prove user instructions remain, and
|
|
28
30
|
close on the design-only team boundary.
|
|
29
31
|
|
package/docs/operating.md
CHANGED
|
@@ -838,6 +838,15 @@ project's `AGENTS.md`. `--untracked` bootstrap leaves the shared `AGENTS.md`
|
|
|
838
838
|
untouched. The policy can select only eight canonical Cairnkeep actions; it
|
|
839
839
|
cannot contain commands, prompts, URLs, or extensions.
|
|
840
840
|
|
|
841
|
+
The same ownership-safe block contains a generic durable-context protocol. For
|
|
842
|
+
nontrivial work that may depend on existing decisions, conventions,
|
|
843
|
+
constraints, recurring failures, or prior work, compatible agents derive one
|
|
844
|
+
short task query and call `memory_search` with `scope: project` before broad
|
|
845
|
+
exploration. A result is only a locator: the maintained repository source must
|
|
846
|
+
still be read and verified. Missing tools and zero results fall back to normal
|
|
847
|
+
inspection, and the protocol never authorizes an automatic memory write,
|
|
848
|
+
supersede, or approval.
|
|
849
|
+
|
|
841
850
|
```bash
|
|
842
851
|
cairn playbook list
|
|
843
852
|
cairn playbook status --project .
|
|
@@ -881,8 +890,10 @@ cairn playbook instructions remove
|
|
|
881
890
|
|
|
882
891
|
Claude and OpenCode receive `/cairn-work`; Pi and Kimi receive corresponding
|
|
883
892
|
thin prompt/Skill adapters when their explicit machine sync runs. Codex and
|
|
884
|
-
Qwen follow the project `AGENTS.md` block.
|
|
885
|
-
|
|
893
|
+
Qwen follow the project `AGENTS.md` block. Instruction exposure does not prove
|
|
894
|
+
tool invocation, so evaluations and audits should verify the actual
|
|
895
|
+
`memory_search` event. These surfaces route to the same CLI and do not create a
|
|
896
|
+
Cairnkeep-owned agent loop.
|
|
886
897
|
|
|
887
898
|
## The workflow
|
|
888
899
|
|
package/docs/quickstart.md
CHANGED
|
@@ -70,8 +70,11 @@ result should survive the restart.
|
|
|
70
70
|
|
|
71
71
|
`cairn setup` creates only the selected harness assets plus the common `.ai`,
|
|
72
72
|
`.planning`, and `.agentfs` scaffold. It also reconciles Cairnkeep's delimited
|
|
73
|
-
|
|
74
|
-
file mode.
|
|
73
|
+
instruction block in `AGENTS.md` while preserving every surrounding user byte
|
|
74
|
+
and file mode. The block tells compatible agents when to make one
|
|
75
|
+
task-derived, project-scoped memory search, to verify maintained repository
|
|
76
|
+
sources, and never to promote memory automatically. It initializes Git only
|
|
77
|
+
with explicit
|
|
75
78
|
`--git init`, preserves unrelated files, does not overwrite modified files it
|
|
76
79
|
does not own, and records managed digests in private `.ai/cairnkeep.json`.
|
|
77
80
|
|
|
@@ -94,8 +97,10 @@ cairn playbook check finish --changed README.md --completed docs.update --enforc
|
|
|
94
97
|
|
|
95
98
|
`must` can produce a non-zero enforcement result; `should` is advisory with a
|
|
96
99
|
recorded reason when skipped; `may` is optional. A decision executes nothing
|
|
97
|
-
and grants no permission.
|
|
98
|
-
|
|
100
|
+
and grants no permission. The memory protocol also degrades to ordinary
|
|
101
|
+
repository inspection when the tool is unavailable or returns no relevant
|
|
102
|
+
result. `cairn playbook instructions remove` removes only the managed
|
|
103
|
+
`AGENTS.md` block, including that protocol.
|
|
99
104
|
|
|
100
105
|
For all harnesses, remote HTTP, storage, profiles, context packs, overlays, and
|
|
101
106
|
recovery details, continue with [Operating Cairnkeep](operating.md) or the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"identifier":"cairn-offline-fake-v1","package_version":"2.15.
|
|
1
|
+
{"identifier":"cairn-offline-fake-v1","package_version":"2.15.2","schema_version":1,"task_set_digest":"13e95379f35839593047ec34521a65a8fa3ab92bd3993bca9dc8bf5c4a9ff36f"}
|
|
@@ -8,6 +8,7 @@ const MAX_CONFIG_BYTES = 64 * 1024;
|
|
|
8
8
|
const LOCK_ATTEMPTS = 200;
|
|
9
9
|
const LOCK_WAIT_MS = 10;
|
|
10
10
|
const SESSION_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/;
|
|
11
|
+
const localLockTails = new Map();
|
|
11
12
|
export const PLAYBOOK_ACTIONS = Object.freeze([
|
|
12
13
|
{ id: "context.recall", title: "Recall durable context", command: "/recall <task topic>", description: "Read accepted project memory and derived knowledge before committing to an approach." },
|
|
13
14
|
{ id: "context.explore", title: "Explore focused code context", command: "/context-explore <question>", description: "Collect compact citations when the relevant code is unfamiliar or structurally complex." },
|
|
@@ -180,35 +181,72 @@ export async function resolvePlaybookStatus(options = {}) {
|
|
|
180
181
|
issues,
|
|
181
182
|
};
|
|
182
183
|
}
|
|
184
|
+
async function acquireLocalLock(lock) {
|
|
185
|
+
let state = localLockTails.get(lock);
|
|
186
|
+
if (!state) {
|
|
187
|
+
state = { tail: Promise.resolve(), users: 0 };
|
|
188
|
+
localLockTails.set(lock, state);
|
|
189
|
+
}
|
|
190
|
+
const predecessor = state.tail;
|
|
191
|
+
let releaseGate;
|
|
192
|
+
const gate = new Promise((resolveGate) => { releaseGate = resolveGate; });
|
|
193
|
+
state.tail = predecessor.then(() => gate);
|
|
194
|
+
state.users += 1;
|
|
195
|
+
await predecessor;
|
|
196
|
+
let released = false;
|
|
197
|
+
return () => {
|
|
198
|
+
if (released)
|
|
199
|
+
return;
|
|
200
|
+
released = true;
|
|
201
|
+
releaseGate();
|
|
202
|
+
state.users -= 1;
|
|
203
|
+
if (state.users === 0 && localLockTails.get(lock) === state)
|
|
204
|
+
localLockTails.delete(lock);
|
|
205
|
+
};
|
|
206
|
+
}
|
|
183
207
|
async function acquireLock(lock) {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return () => rm(lock, { recursive: true, force: true });
|
|
188
|
-
}
|
|
189
|
-
catch (error) {
|
|
190
|
-
const code = error.code;
|
|
191
|
-
if (code !== "EEXIST" && !(process.platform === "win32" && code === "EPERM"))
|
|
192
|
-
throw error;
|
|
208
|
+
const releaseLocal = await acquireLocalLock(lock);
|
|
209
|
+
try {
|
|
210
|
+
for (let attempt = 0; attempt < LOCK_ATTEMPTS; attempt += 1) {
|
|
193
211
|
try {
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
212
|
+
await mkdir(lock, { mode: 0o700 });
|
|
213
|
+
return async () => {
|
|
214
|
+
try {
|
|
215
|
+
await rm(lock, { recursive: true, force: true });
|
|
216
|
+
}
|
|
217
|
+
finally {
|
|
218
|
+
releaseLocal();
|
|
219
|
+
}
|
|
220
|
+
};
|
|
197
221
|
}
|
|
198
|
-
catch (
|
|
199
|
-
const
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
await
|
|
204
|
-
|
|
222
|
+
catch (error) {
|
|
223
|
+
const code = error.code;
|
|
224
|
+
if (code !== "EEXIST" && !(process.platform === "win32" && code === "EPERM"))
|
|
225
|
+
throw error;
|
|
226
|
+
try {
|
|
227
|
+
const info = await lstat(lock);
|
|
228
|
+
if (!info.isDirectory() || info.isSymbolicLink())
|
|
229
|
+
throw new Error("Playbook configuration lock is unsafe.");
|
|
230
|
+
}
|
|
231
|
+
catch (inspectionError) {
|
|
232
|
+
const inspectionCode = inspectionError.code;
|
|
233
|
+
if (inspectionCode === "ENOENT")
|
|
234
|
+
continue;
|
|
235
|
+
if (process.platform === "win32" && (inspectionCode === "EPERM" || inspectionCode === "EBUSY")) {
|
|
236
|
+
await delay(LOCK_WAIT_MS);
|
|
237
|
+
continue;
|
|
238
|
+
}
|
|
239
|
+
throw inspectionError;
|
|
205
240
|
}
|
|
206
|
-
|
|
241
|
+
await delay(LOCK_WAIT_MS);
|
|
207
242
|
}
|
|
208
|
-
await delay(LOCK_WAIT_MS);
|
|
209
243
|
}
|
|
244
|
+
throw new Error("Playbook configuration is locked; retry after the active update finishes.");
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
releaseLocal();
|
|
248
|
+
throw error;
|
|
210
249
|
}
|
|
211
|
-
throw new Error("Playbook configuration is locked; retry after the active update finishes.");
|
|
212
250
|
}
|
|
213
251
|
async function atomicConfigWrite(path, value) {
|
|
214
252
|
const bytes = Buffer.from(`${JSON.stringify(value, null, 2)}\n`, "utf8");
|
package/package.json
CHANGED
|
@@ -50,6 +50,8 @@ bootstrap_output=$(cairn bootstrap "$tmp/project")
|
|
|
50
50
|
[[ -f "$tmp/project/.planning/config.json" ]] || fail "bootstrap did not install the planning scaffold"
|
|
51
51
|
[[ -f "$tmp/project/.ai/playbooks.json" ]] || fail "bootstrap did not install the playbook policy"
|
|
52
52
|
grep -qF '<!-- cairnkeep:playbook:v1:start -->' "$tmp/project/AGENTS.md" || fail "bootstrap did not install playbook agent guidance"
|
|
53
|
+
grep -qF 'derive one short query from the task' "$tmp/project/AGENTS.md" || fail "bootstrap did not install generic memory retrieval guidance"
|
|
54
|
+
grep -qF 'Treat returned memory as a locator, not authority.' "$tmp/project/AGENTS.md" || fail "bootstrap did not install memory provenance guidance"
|
|
53
55
|
|
|
54
56
|
(cd "$tmp/project" && cairn doctor) >/dev/null || fail "installed package failed cairn doctor"
|
|
55
57
|
env -u CAIRN_NOTE_DISTILLATION cairn notes --help >/dev/null \
|
|
@@ -12,6 +12,10 @@ chmod 0640 "$project/AGENTS.md"
|
|
|
12
12
|
node "$ROOT/scripts/playbook-instructions.mjs" "$project" >/dev/null
|
|
13
13
|
grep -qF 'Keep this line.' "$project/AGENTS.md"
|
|
14
14
|
[[ $(grep -cF '<!-- cairnkeep:playbook:v1:start -->' "$project/AGENTS.md") -eq 1 ]]
|
|
15
|
+
grep -qF 'derive one short query from the task' "$project/AGENTS.md"
|
|
16
|
+
grep -qF 'search `scope: project` once' "$project/AGENTS.md"
|
|
17
|
+
grep -qF 'Treat returned memory as a locator, not authority.' "$project/AGENTS.md"
|
|
18
|
+
grep -qF 'Do not write, supersede, or approve durable memory' "$project/AGENTS.md"
|
|
15
19
|
[[ $(stat -c '%a' "$project/AGENTS.md") == 640 ]]
|
|
16
20
|
before=$(sha256sum "$project/AGENTS.md" | cut -d' ' -f1)
|
|
17
21
|
node "$ROOT/scripts/playbook-instructions.mjs" "$project" >/dev/null
|
|
@@ -22,6 +26,7 @@ after=$(sha256sum "$project/AGENTS.md" | cut -d' ' -f1)
|
|
|
22
26
|
node "$ROOT/scripts/playbook-instructions.mjs" "$project" --remove >/dev/null
|
|
23
27
|
grep -qF 'Keep this line.' "$project/AGENTS.md"
|
|
24
28
|
! grep -qF 'cairnkeep:playbook' "$project/AGENTS.md"
|
|
29
|
+
! grep -qF 'Cairnkeep Durable Context' "$project/AGENTS.md"
|
|
25
30
|
|
|
26
31
|
printf '%s\n%s\n%s\n' \
|
|
27
32
|
'<!-- cairnkeep:playbook:v1:start -->' \
|
|
@@ -40,6 +40,8 @@ try {
|
|
|
40
40
|
assert.match(launcherPowerShell(), /evidence run --harness/);
|
|
41
41
|
assert.match(launcherPowerShell(), /CAIRN_WORK_EVIDENCE/);
|
|
42
42
|
assert.match(readFileSync(join(project, "AGENTS.md"), "utf8"), /cairnkeep:playbook:v1:start/);
|
|
43
|
+
assert.match(readFileSync(join(project, "AGENTS.md"), "utf8"), /derive one short query from the task/);
|
|
44
|
+
assert.match(readFileSync(join(project, "AGENTS.md"), "utf8"), /Treat returned memory as a locator, not authority\./);
|
|
43
45
|
assert.match(readFileSync(join(project, "AGENTS.md"), "utf8"), /Keep this line\./);
|
|
44
46
|
|
|
45
47
|
const claudeRoot = join(sandbox, "Claude Config");
|
|
@@ -1,4 +1,20 @@
|
|
|
1
1
|
<!-- cairnkeep:playbook:v1:start -->
|
|
2
|
+
## Cairnkeep Durable Context
|
|
3
|
+
|
|
4
|
+
Before broad repository exploration on a nontrivial task that may depend on
|
|
5
|
+
existing project decisions, conventions, constraints, recurring failures, or
|
|
6
|
+
prior work:
|
|
7
|
+
|
|
8
|
+
- If `memory_search` is available, derive one short query from the task and
|
|
9
|
+
search `scope: project` once.
|
|
10
|
+
- Treat returned memory as a locator, not authority. Read and verify the
|
|
11
|
+
maintained repository sources it references before implementing a result.
|
|
12
|
+
- If the tool is unavailable or no relevant result exists, continue with
|
|
13
|
+
ordinary repository inspection. Do not repeat or broaden searches merely to
|
|
14
|
+
force a result.
|
|
15
|
+
- Do not write, supersede, or approve durable memory unless the user or an
|
|
16
|
+
applicable reviewed workflow explicitly requests capture.
|
|
17
|
+
|
|
2
18
|
## Cairnkeep Playbooks
|
|
3
19
|
|
|
4
20
|
Use Cairnkeep's bounded playbook policy to select workflow steps. It advises or
|