@cairnkeep/cli 2.13.1 → 2.15.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.
Files changed (70) hide show
  1. package/CHANGELOG.md +45 -1
  2. package/README.md +29 -6
  3. package/claude/commands/cairn-work.md +19 -0
  4. package/docs/context-packs.md +13 -3
  5. package/docs/design/team-mode.md +145 -0
  6. package/docs/harness-compatibility.md +12 -11
  7. package/docs/learning/CURRICULUM-MAP.md +8 -4
  8. package/docs/learning/FEATURE-GUIDE.md +13 -5
  9. package/docs/learning/README.md +3 -1
  10. package/docs/learning/lessons/L00-why-cairnkeep.md +1 -1
  11. package/docs/learning/lessons/L01-safe-trial.md +3 -3
  12. package/docs/learning/lessons/L02-installation.md +2 -2
  13. package/docs/learning/lessons/L03-first-project.md +1 -1
  14. package/docs/learning/lessons/L19-validated-skill-improvement.md +1 -1
  15. package/docs/learning/lessons/L20-mcp-tool-profiles.md +1 -1
  16. package/docs/learning/lessons/L21-context-packs.md +5 -1
  17. package/docs/learning/lessons/L22-native-windows.md +2 -2
  18. package/docs/learning/lessons/L23-guided-setup.md +2 -2
  19. package/docs/learning/lessons/L24-okf-exchange.md +111 -0
  20. package/docs/learning/lessons/L25-playbooks.md +114 -0
  21. package/docs/learning/tracks/operator.md +8 -2
  22. package/docs/learning/tracks/practitioner.md +5 -3
  23. package/docs/learning/video-scripts/V24-okf-exchange.md +31 -0
  24. package/docs/learning/video-scripts/V25-playbooks.md +38 -0
  25. package/docs/native-windows.md +12 -0
  26. package/docs/open-knowledge-format.md +100 -0
  27. package/docs/operating.md +68 -0
  28. package/docs/privacy-and-data-flow.md +25 -0
  29. package/docs/quickstart.md +17 -1
  30. package/docs/storage.md +28 -0
  31. package/examples/eval/bundled-fake.json +1 -1
  32. package/kimi/skills/cairn-work/SKILL.md +13 -0
  33. package/mcp-memory-server/dist/context-pack-cli.js +54 -1
  34. package/mcp-memory-server/dist/context-pack.js +243 -47
  35. package/mcp-memory-server/dist/index.js +13 -1
  36. package/mcp-memory-server/dist/mcp-tool-catalog.js +1 -0
  37. package/mcp-memory-server/dist/note-store.js +44 -2
  38. package/mcp-memory-server/dist/okf.js +432 -0
  39. package/mcp-memory-server/dist/playbook-cli.js +321 -0
  40. package/mcp-memory-server/dist/playbook-receipt.js +245 -0
  41. package/mcp-memory-server/dist/playbook-schema.js +56 -0
  42. package/mcp-memory-server/dist/playbook.js +383 -0
  43. package/mcp-memory-server/package.json +4 -1
  44. package/opencode/command/cairn-work.md +13 -0
  45. package/package.json +2 -1
  46. package/pi/prompts/cairn-work.md +12 -0
  47. package/schemas/context-pack.schema.json +9 -0
  48. package/schemas/playbook.schema.json +29 -0
  49. package/scripts/bootstrap.sh +17 -0
  50. package/scripts/cairn-cli.mjs +2 -0
  51. package/scripts/completion.sh +26 -6
  52. package/scripts/doctor.sh +14 -1
  53. package/scripts/playbook-instructions.mjs +108 -0
  54. package/scripts/setup-core.mjs +1 -0
  55. package/scripts/setup.mjs +8 -0
  56. package/scripts/sync-kimi-assets.sh +3 -3
  57. package/scripts/sync-opencode-memory-assets.sh +2 -1
  58. package/scripts/sync-pi-assets.sh +2 -1
  59. package/scripts/test-cli-dispatch.sh +2 -0
  60. package/scripts/test-completion.sh +11 -2
  61. package/scripts/test-graph-harness-adapters.sh +9 -3
  62. package/scripts/test-harness-registry.sh +11 -0
  63. package/scripts/test-learning-docs.sh +23 -2
  64. package/scripts/test-package-install.sh +26 -0
  65. package/scripts/test-playbook-instructions.sh +60 -0
  66. package/scripts/test-windows-native.mjs +7 -0
  67. package/scripts/uninstall.sh +16 -1
  68. package/scripts/windows-platform.mjs +24 -3
  69. package/templates/playbook-agent-instructions.md.template +14 -0
  70. package/templates/playbooks.json.template +5 -0
@@ -21,11 +21,13 @@ import { spawnSync } from "node:child_process";
21
21
  import { basename, dirname, isAbsolute, join, resolve, sep } from "node:path";
22
22
  import { homedir, tmpdir } from "node:os";
23
23
  import { HARNESS_IDS, harnessProjectAssets } from "./harness-registry.mjs";
24
+ import { reconcilePlaybookInstructions, removePlaybookInstructions } from "./playbook-instructions.mjs";
24
25
 
25
26
  const BOOTSTRAP_FILES = [
26
27
  ["env.example.template", ".ai/env.example"],
27
28
  ["trajectory-redaction.json.template", ".ai/trajectory-redaction.json"],
28
29
  ["capabilities.json.template", ".ai/capabilities.json"],
30
+ ["playbooks.json.template", ".ai/playbooks.json"],
29
31
  ["agentfs-gitignore.template", ".agentfs/.gitignore"],
30
32
  ["planning-config.json.template", ".planning/config.json"],
31
33
  ["project-brief.md.template", ".planning/PROJECT-BRIEF.md"],
@@ -257,9 +259,11 @@ export function bootstrapWindows(root, args) {
257
259
  prefix = git(["rev-parse", "--show-prefix"], target).replaceAll("\\", "/");
258
260
  }
259
261
 
262
+ if (!options.has("--untracked")) reconcilePlaybookInstructions(target, { check: true });
263
+
260
264
  const templates = join(root, "templates");
261
265
  for (const [source, destination] of BOOTSTRAP_FILES) {
262
- installFile(join(templates, source), join(target, ...destination.split("/")), destination.endsWith("capabilities.json") ? 0o600 : 0o644);
266
+ installFile(join(templates, source), join(target, ...destination.split("/")), /(?:capabilities|playbooks)\.json$/.test(destination) ? 0o600 : 0o644);
263
267
  }
264
268
  for (const harness of HARNESSES) {
265
269
  const asset = harnessProjectAssets(harness, "local")[0];
@@ -271,6 +275,9 @@ export function bootstrapWindows(root, args) {
271
275
  if (!existsSync(modulePath)) atomicWrite(modulePath, launcherModule(), 0o755);
272
276
  const powershellPath = join(target, ".ai", "start-harness.ps1");
273
277
  if (!existsSync(powershellPath)) atomicWrite(powershellPath, launcherPowerShell(), 0o600);
278
+ if (!options.has("--untracked")) {
279
+ reconcilePlaybookInstructions(target);
280
+ }
274
281
 
275
282
  if (excludeFile) {
276
283
  mkdirSync(dirname(excludeFile), { recursive: true });
@@ -456,6 +463,7 @@ async function doctorWindows(root, args) {
456
463
  ["typed memory", "node-cli.js", ["doctor", "--project-root", process.cwd(), ...(repair ? ["--repair"] : [])]],
457
464
  ["capability", "capability-cli.js", ["doctor", "--json"]],
458
465
  ["context pack", "context-pack-cli.js", ["doctor", "--json"]],
466
+ ["playbook", "playbook-cli.js", ["doctor", "--json"]],
459
467
  ]) {
460
468
  const entry = join(root, "mcp-memory-server", "dist", file);
461
469
  if (!existsSync(entry)) { line("FAIL", `${label} diagnostics are unavailable`); continue; }
@@ -627,9 +635,11 @@ function uninstallWindows(root, args) {
627
635
  join(piLive, "extensions", "cairnkeep-memory.ts"),
628
636
  join(piLive, "extensions", "cairnkeep-trajectory.ts"),
629
637
  join(piLive, "prompts", "graphify.md"),
638
+ join(piLive, "prompts", "cairn-work.md"),
630
639
  );
631
640
  const kimiLive = resolve(expandHome(options.get("--kimi-live-root") || process.env.KIMI_CODE_HOME || join(homedir(), ".kimi-code")));
632
641
  targets.push(join(kimiLive, "skills", "graphify", "SKILL.md"));
642
+ targets.push(join(kimiLive, "skills", "cairn-work", "SKILL.md"));
633
643
  for (const project of projects) {
634
644
  const base = resolve(project);
635
645
  for (const [, rel] of BOOTSTRAP_FILES) targets.push(join(base, ...rel.split("/")));
@@ -677,6 +687,16 @@ function uninstallWindows(root, args) {
677
687
  console.log(`updated: ${settingsPath}`);
678
688
  }
679
689
  }
690
+ for (const project of projects) {
691
+ const agents = join(resolve(project), "AGENTS.md");
692
+ if (!existsSync(agents)) continue;
693
+ const info = lstatSync(agents);
694
+ if (!info.isFile() || info.isSymbolicLink()) continue;
695
+ if (!readFileSync(agents, "utf8").includes("<!-- cairnkeep:playbook:v1:start -->")) continue;
696
+ backupTarget(agents);
697
+ removePlaybookInstructions(resolve(project));
698
+ console.log(`removed Cairnkeep playbook block: ${agents}`);
699
+ }
680
700
  for (const target of existing) {
681
701
  backupTarget(target);
682
702
  rmSync(target, { recursive: true, force: true });
@@ -708,9 +728,10 @@ export function powershellCompletion() {
708
728
  const harnesses = HARNESS_IDS.map((id) => `'${id}'`).join(",");
709
729
  return `Register-ArgumentCompleter -Native -CommandName cairn -ScriptBlock {
710
730
  param($wordToComplete, $commandAst, $cursorPosition)
711
- $commands = 'bootstrap','setup','memory-server','sync','sync-pi','sync-kimi','doctor','trajectory','artifact','evidence','capabilities','mcp-tools','pack','notes','eval','skill','graph','memory','audit-timer','uninstall','completion','version','help'
731
+ $commands = 'bootstrap','setup','memory-server','sync','sync-pi','sync-kimi','doctor','trajectory','artifact','evidence','playbook','capabilities','mcp-tools','pack','notes','eval','skill','graph','memory','audit-timer','uninstall','completion','version','help'
712
732
  $setup = '--git','--harness','--memory','--policy','--yes','--json','init','existing','none',${harnesses},'local'
713
- $candidates = if ($commandAst.ToString() -match '^\\s*cairn\\s+setup(?:\\s|$)') { $setup } else { $commands }
733
+ $playbook = 'list','status','init','set','enable','disable','reset','check','record','receipts','instructions','doctor','minimal','balanced','strict','must','should','may','off','start','finish','install','remove','context.recall','context.explore','work.plan','verify.tests','review.repository','review.security','docs.update','learning.capture','--project','--json','--enforce','--complexity','--familiarity','--risk','--public-change','--changed','--change-type','--completed','--skipped','--failed','--actor','--actor-kind','--session','--policy','--decision','--event','--action','--outcome','--reason'
734
+ $candidates = if ($commandAst.ToString() -match '^\\s*cairn\\s+setup(?:\\s|$)') { $setup } elseif ($commandAst.ToString() -match '^\\s*cairn\\s+playbook(?:\\s|$)') { $playbook } else { $commands }
714
735
  $candidates | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object {
715
736
  [System.Management.Automation.CompletionResult]::new($_, $_, 'ParameterValue', $_)
716
737
  }
@@ -0,0 +1,14 @@
1
+ <!-- cairnkeep:playbook:v1:start -->
2
+ ## Cairnkeep Playbooks
3
+
4
+ Use Cairnkeep's bounded playbook policy to select workflow steps. It advises or
5
+ enforces existing capabilities; it does not execute a workflow for you.
6
+
7
+ - At task start, run `cairn playbook check start --session SESSION --complexity LEVEL --familiarity LEVEL` and follow every applicable `must` action. Apply `should` actions unless there is a concrete reason to skip them; use judgment for `may` actions.
8
+ - Re-run `cairn playbook check check` when scope, familiarity, complexity, or risk changes materially.
9
+ - Before claiming completion, run `cairn playbook check finish --session SESSION --changed PATH... --risk LEVEL --public-change --completed ACTION... --skipped ACTION=REASON... --enforce` with accurate signals and evidence.
10
+ - A non-zero enforcement result means applicable `must` evidence is missing. Perform the action and check again; do not relabel a skipped or failed action as completed.
11
+ - Record material outcomes with `cairn playbook record`, using the exact policy and decision digests returned by the check. Actor identity is an unverified local assertion in this release.
12
+ - Existing approval and capability boundaries still apply. A playbook cannot enable a disabled capability, grant approval, write durable memory automatically, run arbitrary commands, or authorize destructive work.
13
+ - If the CLI or an applicable capability is unavailable, state that limitation and follow the policy intent manually; never invent a receipt or successful result.
14
+ <!-- cairnkeep:playbook:v1:end -->
@@ -0,0 +1,5 @@
1
+ {
2
+ "schema_version": 1,
3
+ "profile": "balanced",
4
+ "overrides": {}
5
+ }