@cairnkeep/cli 2.7.0 → 2.8.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 (41) hide show
  1. package/CHANGELOG.md +22 -1
  2. package/README.md +23 -0
  3. package/bin/cairn +6 -0
  4. package/docs/design/meta-agent.md +39 -35
  5. package/docs/learning/CURRICULUM-MAP.md +9 -4
  6. package/docs/learning/FEATURE-GUIDE.md +6 -4
  7. package/docs/learning/README.md +4 -2
  8. package/docs/learning/lessons/L00-why-cairnkeep.md +1 -1
  9. package/docs/learning/lessons/L01-safe-trial.md +3 -3
  10. package/docs/learning/lessons/L02-installation.md +2 -2
  11. package/docs/learning/lessons/L03-first-project.md +1 -1
  12. package/docs/learning/lessons/L17-agent-boundary.md +12 -8
  13. package/docs/learning/lessons/L18-local-code-graph.md +97 -0
  14. package/docs/learning/lessons/L19-validated-skill-improvement.md +87 -0
  15. package/docs/learning/tracks/evidence-and-evaluation.md +5 -3
  16. package/docs/learning/tracks/practitioner.md +5 -4
  17. package/docs/operating.md +23 -0
  18. package/docs/privacy-and-data-flow.md +42 -1
  19. package/docs/skill-improvement.md +124 -0
  20. package/docs/storage.md +25 -0
  21. package/examples/eval/bundled-fake.json +1 -1
  22. package/mcp-memory-server/dist/eval-plan.js +22 -5
  23. package/mcp-memory-server/dist/eval-process.js +31 -0
  24. package/mcp-memory-server/dist/eval-runner.js +10 -4
  25. package/mcp-memory-server/dist/eval-schema.js +1 -1
  26. package/mcp-memory-server/dist/eval-workspace.js +50 -1
  27. package/mcp-memory-server/dist/skill-cli.js +236 -0
  28. package/mcp-memory-server/dist/skill-evaluation.js +244 -0
  29. package/mcp-memory-server/dist/skill-schema.js +164 -0
  30. package/mcp-memory-server/dist/skill-store.js +583 -0
  31. package/mcp-memory-server/package.json +2 -1
  32. package/package.json +1 -1
  33. package/schemas/eval-report.schema.json +1 -1
  34. package/schemas/skill-adapter.schema.json +39 -0
  35. package/schemas/skill-proposal-protocol.schema.json +97 -0
  36. package/scripts/completion.sh +41 -3
  37. package/scripts/test-completion.sh +11 -0
  38. package/scripts/test-learning-docs.sh +11 -2
  39. package/scripts/test-package-install.sh +18 -0
  40. package/scripts/test-skill-cli.sh +30 -0
  41. package/templates/graph-policy.md.template +3 -1
@@ -0,0 +1,97 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://raw.githubusercontent.com/cairnkeep/cairnkeep/main/schemas/skill-proposal-protocol.schema.json",
4
+ "title": "Cairnkeep skill proposal adapter protocol v1",
5
+ "oneOf": [{ "$ref": "#/$defs/request" }, { "$ref": "#/$defs/response" }],
6
+ "$defs": {
7
+ "identifier": { "type": "string", "minLength": 1, "maxLength": 128, "pattern": "^[a-z0-9][a-z0-9._-]*$" },
8
+ "digest": { "type": "string", "pattern": "^[a-f0-9]{64}$" },
9
+ "timestamp": { "type": "string", "format": "date-time" },
10
+ "relativePath": {
11
+ "type": "string",
12
+ "minLength": 1,
13
+ "maxLength": 1024,
14
+ "pattern": "^(?!/)(?!.*(?:^|/)(?:\\.|\\.\\.)(?:/|$))(?!.*\\\\)(?!.*//)(?!.*[\\u0000-\\u001f\\u007f])(?:.*\\/)?SKILL\\.md$"
15
+ },
16
+ "occurrence": {
17
+ "type": "object",
18
+ "additionalProperties": false,
19
+ "required": ["session_id", "session_digest", "ended_at", "outcome", "evidence"],
20
+ "properties": {
21
+ "session_id": { "type": "string", "minLength": 1, "maxLength": 256 },
22
+ "session_digest": { "$ref": "#/$defs/digest" },
23
+ "ended_at": { "$ref": "#/$defs/timestamp" },
24
+ "outcome": { "enum": ["failure", "resolution", "abandonment"] },
25
+ "tool_name": { "type": "string", "minLength": 1, "maxLength": 256 },
26
+ "evidence": { "type": "string", "maxLength": 4096 }
27
+ }
28
+ },
29
+ "candidate": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": ["schema_version", "id", "project_id", "status", "note_id", "source_digest", "title", "description", "failure_family", "failure_count", "resolution_count", "occurrences", "lessons", "caveats", "created_at", "reviewed_at"],
33
+ "properties": {
34
+ "schema_version": { "const": 1 },
35
+ "id": { "$ref": "#/$defs/identifier" },
36
+ "project_id": { "$ref": "#/$defs/identifier" },
37
+ "status": { "const": "approved" },
38
+ "note_id": { "$ref": "#/$defs/identifier" },
39
+ "source_digest": { "$ref": "#/$defs/digest" },
40
+ "title": { "type": "string", "minLength": 1, "maxLength": 512 },
41
+ "description": { "type": "string", "maxLength": 4096 },
42
+ "failure_family": { "$ref": "#/$defs/identifier" },
43
+ "failure_count": { "type": "integer", "minimum": 2, "maximum": 1024 },
44
+ "resolution_count": { "type": "integer", "minimum": 1, "maximum": 1024 },
45
+ "occurrences": { "type": "array", "minItems": 2, "maxItems": 64, "items": { "$ref": "#/$defs/occurrence" } },
46
+ "lessons": { "type": "array", "maxItems": 16, "items": { "type": "string", "minLength": 1, "maxLength": 1024 } },
47
+ "caveats": { "type": "array", "maxItems": 16, "items": { "type": "string", "minLength": 1, "maxLength": 1024 } },
48
+ "created_at": { "$ref": "#/$defs/timestamp" },
49
+ "reviewed_at": { "$ref": "#/$defs/timestamp" }
50
+ }
51
+ },
52
+ "edit": {
53
+ "type": "object",
54
+ "additionalProperties": false,
55
+ "required": ["operation", "anchor", "content", "rationale"],
56
+ "properties": {
57
+ "operation": { "enum": ["add", "replace", "delete"] },
58
+ "anchor": { "oneOf": [{ "type": "string", "minLength": 1, "maxLength": 16384 }, { "type": "null" }] },
59
+ "content": { "type": "string", "maxLength": 65536 },
60
+ "rationale": { "type": "string", "minLength": 1, "maxLength": 2048 }
61
+ }
62
+ },
63
+ "request": {
64
+ "type": "object",
65
+ "additionalProperties": false,
66
+ "required": ["schema_version", "operation", "candidate", "candidate_digest", "target", "edit_budget"],
67
+ "properties": {
68
+ "schema_version": { "const": 1 },
69
+ "operation": { "const": "propose" },
70
+ "candidate": { "$ref": "#/$defs/candidate" },
71
+ "candidate_digest": { "$ref": "#/$defs/digest" },
72
+ "target": {
73
+ "type": "object",
74
+ "additionalProperties": false,
75
+ "required": ["path", "baseline_digest", "content"],
76
+ "properties": {
77
+ "path": { "$ref": "#/$defs/relativePath" },
78
+ "baseline_digest": { "$ref": "#/$defs/digest" },
79
+ "content": { "type": "string", "maxLength": 262144 }
80
+ }
81
+ },
82
+ "edit_budget": { "type": "integer", "minimum": 1, "maximum": 16 }
83
+ }
84
+ },
85
+ "response": {
86
+ "type": "object",
87
+ "additionalProperties": false,
88
+ "required": ["schema_version", "status"],
89
+ "properties": {
90
+ "schema_version": { "const": 1 },
91
+ "status": { "enum": ["completed", "adapter_error"] },
92
+ "error_code": { "$ref": "#/$defs/identifier" },
93
+ "edits": { "type": "array", "maxItems": 16, "default": [], "items": { "$ref": "#/$defs/edit" } }
94
+ }
95
+ }
96
+ }
97
+ }
@@ -11,7 +11,7 @@ _cairn_complete() {
11
11
  COMPREPLY=()
12
12
  current=${COMP_WORDS[COMP_CWORD]}
13
13
  previous=${COMP_WORDS[COMP_CWORD-1]:-}
14
- commands="bootstrap memory-server sync sync-pi sync-kimi doctor trajectory artifact capabilities notes eval graph memory audit-timer uninstall completion version help"
14
+ commands="bootstrap memory-server sync sync-pi sync-kimi doctor trajectory artifact capabilities notes eval skill graph memory audit-timer uninstall completion version help"
15
15
  if (( COMP_CWORD == 1 )); then
16
16
  COMPREPLY=( $(compgen -W "$commands" -- "$current") )
17
17
  return
@@ -63,6 +63,7 @@ _cairn_complete() {
63
63
  *) COMPREPLY=( $(compgen -W "validate run ablate report prune delete" -- "$current") ) ;;
64
64
  esac
65
65
  ;;
66
+ skill) COMPREPLY=( $(compgen -W "harvest list show review propose evaluate apply rollback --project --minimum-occurrences --kind --id --candidate --approve --target --adapter --edit-budget --proposal --exploration-task-set --confirmation-task-set --output --repetitions --seed --minimum-improvement --evaluation --application --confirm --yes --json" -- "$current") ) ;;
66
67
  graph) COMPREPLY=( $(compgen -W "build query status diff explain path --force" -- "$current") ) ;;
67
68
  memory) COMPREPLY=( $(compgen -W "path export import" -- "$current") ) ;;
68
69
  audit-timer) COMPREPLY=( $(compgen -W "--on-calendar --para-root --render-only" -- "$current") ) ;;
@@ -90,6 +91,7 @@ _cairn() {
90
91
  'capabilities:inspect and manage project capability state'
91
92
  'notes:distill and search local hindsight notes'
92
93
  'eval:run and inspect default-off local evaluations'
94
+ 'skill:review and evaluate evidence-backed skill improvements'
93
95
  'graph:inspect a published Graphify graph'
94
96
  'memory:manage the durable memory store'
95
97
  'audit-timer:install a memory and wiki audit timer'
@@ -139,6 +141,19 @@ _cairn() {
139
141
  *) _values 'eval command' validate run ablate report prune delete ;;
140
142
  esac
141
143
  ;;
144
+ skill)
145
+ case $words[3] in
146
+ harvest) _arguments '--project[project root]:directory:_files -/' '--minimum-occurrences[minimum recurring failures]:count:' '--json[emit JSON]' ;;
147
+ list) _arguments '--project[project root]:directory:_files -/' '--kind[artifact kind]:kind:(candidate proposal evaluation application)' '--json[emit JSON]' ;;
148
+ show) _arguments '--project[project root]:directory:_files -/' '--kind[artifact kind]:kind:(candidate proposal evaluation application)' '--id[artifact ID]:artifact ID:' '--json[emit JSON]' ;;
149
+ review) _arguments '--project[project root]:directory:_files -/' '--candidate[candidate ID]:candidate ID:' '--approve[approve evidence]' '--json[emit JSON]' ;;
150
+ propose) _arguments '--project[project root]:directory:_files -/' '--candidate[candidate ID]:candidate ID:' '--target[existing SKILL.md]:file:_files' '--adapter[proposal adapter configuration]:file:_files' '--edit-budget[maximum edits]:count:' '--json[emit JSON]' ;;
151
+ evaluate) _arguments '--project[project root]:directory:_files -/' '--proposal[proposal ID]:proposal ID:' '--exploration-task-set[exploration task set]:file:_files' '--confirmation-task-set[confirmation task set]:file:_files' '--adapter[evaluation adapter configuration]:file:_files' '--output[report root]:directory:_files -/' '--repetitions[repetition count]:count:' '--seed[deterministic seed]:seed:' '--minimum-improvement[distinct improved tasks]:count:' '--yes[confirm execution]' '--json[emit JSON]' ;;
152
+ apply) _arguments '--project[project root]:directory:_files -/' '--proposal[proposal ID]:proposal ID:' '--evaluation[evaluation ID]:evaluation ID:' '--confirm[exact proposal digest]:digest:' '--json[emit JSON]' ;;
153
+ rollback) _arguments '--project[project root]:directory:_files -/' '--application[application ID]:application ID:' '--confirm[confirm rollback]' '--json[emit JSON]' ;;
154
+ *) _values 'skill command' harvest list show review propose evaluate apply rollback ;;
155
+ esac
156
+ ;;
142
157
  graph) _values 'graph command' build query status diff explain path '--force[allow a smaller graph after code deletion]' ;;
143
158
  memory) _values 'memory command' path export import ;;
144
159
  audit-timer) _arguments '--on-calendar[systemd calendar]:calendar:' '--para-root[PARA root]:directory:_files -/' '--render-only[render directory]:directory:_files -/' ;;
@@ -153,8 +168,8 @@ EOF
153
168
  fish)
154
169
  cat <<'EOF'
155
170
  complete -c cairn -f
156
- for command in bootstrap memory-server sync sync-pi sync-kimi doctor trajectory artifact capabilities notes eval graph memory audit-timer uninstall completion version help
157
- complete -c cairn -n "not __fish_seen_subcommand_from bootstrap memory-server sync sync-pi sync-kimi doctor trajectory artifact capabilities notes eval graph memory audit-timer uninstall completion version help" -a $command
171
+ for command in bootstrap memory-server sync sync-pi sync-kimi doctor trajectory artifact capabilities notes eval skill graph memory audit-timer uninstall completion version help
172
+ complete -c cairn -n "not __fish_seen_subcommand_from bootstrap memory-server sync sync-pi sync-kimi doctor trajectory artifact capabilities notes eval skill graph memory audit-timer uninstall completion version help" -a $command
158
173
  end
159
174
  complete -c cairn -n "__fish_seen_subcommand_from sync" -l apply
160
175
  complete -c cairn -n "__fish_seen_subcommand_from sync" -l live-root -r
@@ -191,6 +206,29 @@ complete -c cairn -n "__fish_seen_subcommand_from eval; and __fish_seen_subcomma
191
206
  complete -c cairn -n "__fish_seen_subcommand_from eval; and __fish_seen_subcommand_from prune" -l older-than-days -r
192
207
  complete -c cairn -n "__fish_seen_subcommand_from eval; and __fish_seen_subcommand_from prune delete" -l dry-run
193
208
  complete -c cairn -n "__fish_seen_subcommand_from eval; and __fish_seen_subcommand_from validate run ablate report prune delete" -l json
209
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and not __fish_seen_subcommand_from harvest list show review propose evaluate apply rollback" -a "harvest list show review propose evaluate apply rollback"
210
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from harvest list show review propose evaluate apply rollback" -l project -r
211
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from harvest list show review propose evaluate apply rollback" -l json
212
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from harvest" -l minimum-occurrences -r
213
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from list show" -l kind -r -a "candidate proposal evaluation application"
214
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from show" -l id -r
215
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from review propose" -l candidate -r
216
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from review" -l approve
217
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from propose" -l target -r
218
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from propose evaluate" -l adapter -r
219
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from propose" -l edit-budget -r
220
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from evaluate apply" -l proposal -r
221
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from evaluate" -l exploration-task-set -r
222
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from evaluate" -l confirmation-task-set -r
223
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from evaluate" -l output -r
224
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from evaluate" -l repetitions -r
225
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from evaluate" -l seed -r
226
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from evaluate" -l minimum-improvement -r
227
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from evaluate" -l yes
228
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from apply" -l evaluation -r
229
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from apply" -l confirm -r
230
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from rollback" -l application -r
231
+ complete -c cairn -n "__fish_seen_subcommand_from skill; and __fish_seen_subcommand_from rollback" -l confirm
194
232
  complete -c cairn -n "__fish_seen_subcommand_from graph" -a "build query status diff explain path"
195
233
  complete -c cairn -n "__fish_seen_subcommand_from graph; and __fish_seen_subcommand_from build" -l force
196
234
  complete -c cairn -n "__fish_seen_subcommand_from completion" -a "bash zsh fish"
@@ -14,6 +14,7 @@ done
14
14
  capability_ids='memory.write memory.search notes.distill wiki graph security.audit route.check context.explore'
15
15
  eval_commands='validate run ablate report prune delete'
16
16
  eval_flags='--task-set --adapter --output --repetitions --seed --json --yes --disable --experiment --older-than-days --dry-run'
17
+ skill_commands='harvest list show review propose evaluate apply rollback'
17
18
  for shell in bash zsh fish; do
18
19
  grep -q 'capabilities' "$tmp/$shell"
19
20
  grep -q 'list.*status.*enable.*disable.*reset.*logging\|list status enable disable reset logging' "$tmp/$shell"
@@ -37,6 +38,11 @@ for shell in bash zsh fish; do
37
38
  echo "completion exposed a private eval lifecycle operation for $shell" >&2
38
39
  exit 1
39
40
  fi
41
+ grep -q 'skill' "$tmp/$shell"
42
+ grep -q 'harvest.*list.*show.*review.*propose.*evaluate.*apply.*rollback\|harvest list show review propose evaluate apply rollback' "$tmp/$shell"
43
+ for skill_flag in --candidate --exploration-task-set --confirmation-task-set --evaluation --application --confirm; do
44
+ grep -q -- "$skill_flag\|-l ${skill_flag#--}" "$tmp/$shell"
45
+ done
40
46
  done
41
47
 
42
48
  "$ROOT/bin/cairn" help >"$tmp/root-help"
@@ -52,6 +58,11 @@ if grep -q 'doctor-diagnosis' "$tmp/eval-help"; then
52
58
  echo 'eval help exposed a private lifecycle operation' >&2
53
59
  exit 1
54
60
  fi
61
+ grep -qF 'cairn skill <harvest|list|show|review|propose|evaluate|apply|rollback>' "$tmp/root-help"
62
+ node "$ROOT/mcp-memory-server/dist/skill-cli.js" --help >"$tmp/skill-help"
63
+ for command in $skill_commands; do
64
+ grep -q "cairn skill $command" "$tmp/skill-help"
65
+ done
55
66
 
56
67
  node - "$ROOT/mcp-memory-server/src/capability-registry.ts" "$tmp/bash" "$tmp/zsh" "$tmp/fish" <<'NODE'
57
68
  const fs = require("fs");
@@ -21,7 +21,7 @@ done
21
21
 
22
22
  ready=0
23
23
  brief=0
24
- for number in $(seq -w 0 17); do
24
+ for number in $(seq -w 0 19); do
25
25
  matches=(docs/learning/lessons/L"$number"-*.md)
26
26
  [[ ${#matches[@]} -eq 1 && -f ${matches[0]} ]] || {
27
27
  echo "learning path must contain exactly one L$number lesson" >&2
@@ -43,7 +43,16 @@ for number in $(seq -w 0 17); do
43
43
  fi
44
44
  done
45
45
 
46
- [[ $ready -eq 4 && $brief -eq 14 ]] || {
46
+ graph_lesson=docs/learning/lessons/L18-local-code-graph.md
47
+ for mode in build query status diff explain path; do
48
+ grep -qF "cairn graph $mode" "$graph_lesson"
49
+ done
50
+ grep -qF 'Do not run `graphify install`' "$graph_lesson"
51
+ grep -qF '`cairn sync-kimi --apply`' "$graph_lesson"
52
+ grep -qF '`cairn sync-pi --apply`' "$graph_lesson"
53
+ grep -qF '`graphify-out/`' "$graph_lesson"
54
+
55
+ [[ $ready -eq 4 && $brief -eq 16 ]] || {
47
56
  echo "unexpected learning status totals: ready=$ready brief=$brief" >&2
48
57
  exit 1
49
58
  }
@@ -19,6 +19,7 @@ server_dev_dependencies_before=$(manifest_field "$ROOT/mcp-memory-server/package
19
19
  root_lock_before=$(sha256sum "$ROOT/package-lock.json" | cut -d' ' -f1)
20
20
  server_lock_before=$(sha256sum "$ROOT/mcp-memory-server/package-lock.json" | cut -d' ' -f1)
21
21
  node "$ROOT/mcp-memory-server/dist/eval-cli.js" --help >"$tmp/source-eval-help"
22
+ node "$ROOT/mcp-memory-server/dist/skill-cli.js" --help >"$tmp/source-skill-help"
22
23
  env -u CAIRN_EVAL "$ROOT/bin/cairn" eval validate \
23
24
  --task-set "$tmp/source-unread-task-set" \
24
25
  --adapter "$tmp/source-unread-adapter" \
@@ -52,6 +53,11 @@ env -u CAIRN_NOTE_DISTILLATION cairn notes --help >/dev/null \
52
53
  || fail "installed package omitted the notes command"
53
54
 
54
55
  installed_root="$tmp/prefix/lib/node_modules/@cairnkeep/cli"
56
+ cairn skill --help >"$tmp/installed-skill-help"
57
+ cmp -s "$tmp/source-skill-help" "$tmp/installed-skill-help" || \
58
+ fail "source and installed skill help differ"
59
+ cairn skill list --project "$tmp/project" --json >"$tmp/installed-skill-list.json" || \
60
+ fail "installed package skill list failed"
55
61
  cairn eval --help >"$tmp/installed-eval-help"
56
62
  cmp -s "$tmp/source-eval-help" "$tmp/installed-eval-help" || \
57
63
  fail "source and installed eval help differ"
@@ -80,6 +86,18 @@ do
80
86
  [[ -f "$installed_root/$required" ]] || fail "npm tarball omitted $required"
81
87
  done
82
88
 
89
+ for required in \
90
+ schemas/skill-adapter.schema.json \
91
+ schemas/skill-proposal-protocol.schema.json \
92
+ mcp-memory-server/dist/skill-schema.js \
93
+ mcp-memory-server/dist/skill-store.js \
94
+ mcp-memory-server/dist/skill-evaluation.js \
95
+ mcp-memory-server/dist/skill-cli.js \
96
+ docs/skill-improvement.md
97
+ do
98
+ [[ -f "$installed_root/$required" ]] || fail "npm tarball omitted $required"
99
+ done
100
+
83
101
  for required in \
84
102
  schemas/eval-task-set.schema.json \
85
103
  schemas/eval-adapter.schema.json \
@@ -0,0 +1,30 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
5
+ tmp=$(mktemp -d)
6
+ trap 'rm -rf "$tmp"' EXIT
7
+
8
+ node "$ROOT/mcp-memory-server/dist/skill-cli.js" --help >"$tmp/help"
9
+ for operation in harvest list show review propose evaluate apply rollback; do
10
+ grep -q "$operation" "$tmp/help" || { echo "FAIL: skill help omitted $operation" >&2; exit 1; }
11
+ done
12
+
13
+ mkdir -p "$tmp/project"
14
+ node "$ROOT/mcp-memory-server/dist/skill-cli.js" list --project "$tmp/project" --json >"$tmp/list.json"
15
+ node -e '
16
+ const value = require(process.argv[1]);
17
+ for (const key of ["candidates", "proposals", "evaluations", "applications"]) {
18
+ if (!Array.isArray(value[key]) || value[key].length !== 0) process.exit(1);
19
+ }
20
+ ' "$tmp/list.json"
21
+
22
+ if env -u CAIRN_EVAL node "$ROOT/mcp-memory-server/dist/skill-cli.js" evaluate \
23
+ --project "$tmp/project" --proposal missing --exploration-task-set missing \
24
+ --confirmation-task-set missing --adapter missing --yes >"$tmp/out" 2>"$tmp/err"; then
25
+ echo "FAIL: disabled skill evaluation succeeded" >&2
26
+ exit 1
27
+ fi
28
+ grep -q 'disabled' "$tmp/err" || { echo "FAIL: disabled skill evaluation did not fail closed" >&2; exit 1; }
29
+
30
+ echo "PASS: installed-style skill CLI discovery and default-off gate"
@@ -26,7 +26,9 @@ This repository uses `.planning/graphs/` as an optional, local, machine-facing d
26
26
 
27
27
  - Use the graph to compress dependency context for planning, exploration, and impact analysis.
28
28
  - Do not use graph outputs as a human-facing substitute for the repo wiki.
29
- - Do not commit graph build outputs by default; `.planning/graphs/.gitignore` keeps them local unless you intentionally override it.
29
+ - Do not commit graph build outputs by default. `.planning/graphs/.gitignore`
30
+ covers the published view; also ignore Graphify's root `graphify-out/` work
31
+ directory through repository policy or the clone-local Git exclude file.
30
32
 
31
33
  ## Maintenance
32
34