@cairnkeep/cli 2.5.0 → 2.7.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 +24 -1
- package/README.md +33 -12
- package/bin/cairn +15 -3
- package/claude/commands/graphify.md +46 -55
- package/docs/building-an-overlay.md +2 -2
- package/docs/harness-compatibility.md +95 -9
- package/docs/learning/CURRICULUM-MAP.md +3 -1
- package/docs/learning/FEATURE-GUIDE.md +3 -2
- package/docs/learning/README.md +12 -12
- package/docs/learning/lessons/L00-why-cairnkeep.md +1 -5
- package/docs/learning/lessons/L01-safe-trial.md +3 -7
- package/docs/learning/lessons/L02-installation.md +15 -9
- package/docs/learning/lessons/L03-first-project.md +1 -5
- package/docs/learning/lessons/L04-memory-fundamentals.md +0 -6
- package/docs/learning/lessons/L05-daily-workflow.md +0 -5
- package/docs/learning/lessons/L06-repository-quality.md +0 -6
- package/docs/learning/lessons/L07-privacy-and-storage.md +0 -5
- package/docs/learning/lessons/L08-multiple-machines.md +0 -5
- package/docs/learning/lessons/L09-domain-knowledge.md +0 -5
- package/docs/learning/lessons/L10-context-exploration.md +0 -5
- package/docs/learning/lessons/L11-containers.md +0 -5
- package/docs/learning/lessons/L12-managed-overlays.md +0 -6
- package/docs/learning/lessons/L13-session-evidence.md +0 -6
- package/docs/learning/lessons/L14-typed-memory.md +0 -6
- package/docs/learning/lessons/L15-capability-governance.md +0 -6
- package/docs/learning/lessons/L16-evaluation.md +0 -7
- package/docs/learning/lessons/L17-agent-boundary.md +0 -6
- package/docs/learning/templates/lesson-template.md +0 -4
- package/docs/operating.md +111 -9
- package/docs/privacy-and-data-flow.md +1 -0
- package/examples/eval/bundled-fake.json +1 -1
- package/kimi/skills/graphify/SKILL.md +33 -0
- package/mcp-memory-server/dist/capability-registry.js +2 -2
- package/mcp-memory-server/dist/graph-cli.js +386 -0
- package/mcp-memory-server/package.json +2 -1
- package/opencode/command/graphify.md +48 -58
- package/package.json +4 -2
- package/pi/prompts/graphify.md +32 -0
- package/scripts/bootstrap.sh +4 -1
- package/scripts/completion.sh +17 -6
- package/scripts/smoke-bash32.sh +1 -0
- package/scripts/sync-kimi-assets.sh +77 -0
- package/scripts/sync-pi-assets.sh +52 -31
- package/scripts/test-bootstrap-untracked.sh +23 -1
- package/scripts/test-cli-dispatch.sh +4 -0
- package/scripts/test-completion.sh +5 -0
- package/scripts/test-graph-harness-adapters.sh +46 -0
- package/scripts/test-launcher-hooks.sh +33 -3
- package/scripts/test-learning-docs.sh +2 -9
- package/scripts/test-package-install.sh +9 -0
- package/scripts/test-trajectory-hooks.sh +5 -1
- package/scripts/test-uninstall.sh +12 -2
- package/scripts/uninstall.sh +12 -4
- package/templates/graph-policy.md.template +23 -4
- package/templates/start-qwen.sh.template +32 -0
- package/docs/learning/PRODUCTION-PLAN.md +0 -153
- package/docs/learning/instructor-guide.md +0 -66
- package/docs/learning/templates/video-script-template.md +0 -50
- package/docs/learning/video-scripts/L00-why-cairnkeep.md +0 -80
- package/docs/learning/video-scripts/L01-safe-trial.md +0 -78
- package/docs/learning/video-scripts/L02-installation.md +0 -97
- package/docs/learning/video-scripts/L03-first-project.md +0 -99
package/scripts/completion.sh
CHANGED
|
@@ -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 doctor trajectory artifact capabilities notes eval memory audit-timer uninstall completion version help"
|
|
14
|
+
commands="bootstrap memory-server sync sync-pi sync-kimi doctor trajectory artifact capabilities notes eval 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
|
|
@@ -20,6 +20,7 @@ _cairn_complete() {
|
|
|
20
20
|
bootstrap) COMPREPLY=( $(compgen -W "--untracked" -- "$current") ) ;;
|
|
21
21
|
sync) COMPREPLY=( $(compgen -W "--apply --live-root" -- "$current") ) ;;
|
|
22
22
|
sync-pi) COMPREPLY=( $(compgen -W "--apply --live-root" -- "$current") ) ;;
|
|
23
|
+
sync-kimi) COMPREPLY=( $(compgen -W "--apply --live-root" -- "$current") ) ;;
|
|
23
24
|
doctor) COMPREPLY=( $(compgen -W "--repair" -- "$current") ) ;;
|
|
24
25
|
trajectory) COMPREPLY=( $(compgen -W "list show prune --json --dry-run" -- "$current") ) ;;
|
|
25
26
|
artifact) COMPREPLY=( $(compgen -W "list show delete prune --kind --session --json --dry-run --include-protected" -- "$current") ) ;;
|
|
@@ -62,9 +63,10 @@ _cairn_complete() {
|
|
|
62
63
|
*) COMPREPLY=( $(compgen -W "validate run ablate report prune delete" -- "$current") ) ;;
|
|
63
64
|
esac
|
|
64
65
|
;;
|
|
66
|
+
graph) COMPREPLY=( $(compgen -W "build query status diff explain path --force" -- "$current") ) ;;
|
|
65
67
|
memory) COMPREPLY=( $(compgen -W "path export import" -- "$current") ) ;;
|
|
66
68
|
audit-timer) COMPREPLY=( $(compgen -W "--on-calendar --para-root --render-only" -- "$current") ) ;;
|
|
67
|
-
uninstall) COMPREPLY=( $(compgen -W "--dry-run --yes --purge-memory --live-root --pi-live-root" -- "$current") ) ;;
|
|
69
|
+
uninstall) COMPREPLY=( $(compgen -W "--dry-run --yes --purge-memory --live-root --pi-live-root --kimi-live-root" -- "$current") ) ;;
|
|
68
70
|
completion) COMPREPLY=( $(compgen -W "bash zsh fish" -- "$current") ) ;;
|
|
69
71
|
esac
|
|
70
72
|
}
|
|
@@ -80,13 +82,15 @@ _cairn() {
|
|
|
80
82
|
'bootstrap:scaffold a project'
|
|
81
83
|
'memory-server:run the memory MCP server'
|
|
82
84
|
'sync:install the Claude operating layer'
|
|
83
|
-
'sync-pi:install the Pi trajectory extension'
|
|
85
|
+
'sync-pi:install the Pi trajectory extension and graph prompt'
|
|
86
|
+
'sync-kimi:install the Kimi graph Skill'
|
|
84
87
|
'doctor:check runtime dependencies and endpoints'
|
|
85
88
|
'trajectory:inspect and prune local session trajectories'
|
|
86
89
|
'artifact:inspect, delete, and prune local artifacts'
|
|
87
90
|
'capabilities:inspect and manage project capability state'
|
|
88
91
|
'notes:distill and search local hindsight notes'
|
|
89
92
|
'eval:run and inspect default-off local evaluations'
|
|
93
|
+
'graph:inspect a published Graphify graph'
|
|
90
94
|
'memory:manage the durable memory store'
|
|
91
95
|
'audit-timer:install a memory and wiki audit timer'
|
|
92
96
|
'uninstall:remove installed Cairnkeep components safely'
|
|
@@ -102,6 +106,7 @@ _cairn() {
|
|
|
102
106
|
bootstrap) _arguments '--untracked[keep scaffold out of Git]' '*:project directory:_files -/' ;;
|
|
103
107
|
sync) _arguments '--apply[apply changes]' '--live-root[project Claude root]:directory:_files -/' ;;
|
|
104
108
|
sync-pi) _arguments '--apply[apply changes]' '--live-root[Pi agent root]:directory:_files -/' ;;
|
|
109
|
+
sync-kimi) _arguments '--apply[apply changes]' '--live-root[Kimi Code root]:directory:_files -/' ;;
|
|
105
110
|
doctor) _arguments '--repair[repair trajectory metadata and indexes]' ;;
|
|
106
111
|
trajectory) _values 'trajectory command' list show prune ;;
|
|
107
112
|
artifact)
|
|
@@ -134,9 +139,10 @@ _cairn() {
|
|
|
134
139
|
*) _values 'eval command' validate run ablate report prune delete ;;
|
|
135
140
|
esac
|
|
136
141
|
;;
|
|
142
|
+
graph) _values 'graph command' build query status diff explain path '--force[allow a smaller graph after code deletion]' ;;
|
|
137
143
|
memory) _values 'memory command' path export import ;;
|
|
138
144
|
audit-timer) _arguments '--on-calendar[systemd calendar]:calendar:' '--para-root[PARA root]:directory:_files -/' '--render-only[render directory]:directory:_files -/' ;;
|
|
139
|
-
uninstall) _arguments '--dry-run[show changes]' '--yes[skip confirmation]' '--purge-memory[delete memory]' '--live-root[project Claude root]:directory:_files -/' '--pi-live-root[Pi agent root]:directory:_files -/' '*:project directory:_files -/' ;;
|
|
145
|
+
uninstall) _arguments '--dry-run[show changes]' '--yes[skip confirmation]' '--purge-memory[delete memory]' '--live-root[project Claude root]:directory:_files -/' '--pi-live-root[Pi agent root]:directory:_files -/' '--kimi-live-root[Kimi Code root]:directory:_files -/' '*:project directory:_files -/' ;;
|
|
140
146
|
completion) _values 'shell' bash zsh fish ;;
|
|
141
147
|
*) _arguments '*:argument:_files' ;;
|
|
142
148
|
esac
|
|
@@ -147,13 +153,15 @@ EOF
|
|
|
147
153
|
fish)
|
|
148
154
|
cat <<'EOF'
|
|
149
155
|
complete -c cairn -f
|
|
150
|
-
for command in bootstrap memory-server sync sync-pi doctor trajectory artifact capabilities notes eval memory audit-timer uninstall completion version help
|
|
151
|
-
complete -c cairn -n "not __fish_seen_subcommand_from bootstrap memory-server sync sync-pi doctor trajectory artifact capabilities notes eval memory audit-timer uninstall completion version help" -a $command
|
|
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
|
|
152
158
|
end
|
|
153
159
|
complete -c cairn -n "__fish_seen_subcommand_from sync" -l apply
|
|
154
160
|
complete -c cairn -n "__fish_seen_subcommand_from sync" -l live-root -r
|
|
155
161
|
complete -c cairn -n "__fish_seen_subcommand_from sync-pi" -l apply
|
|
156
162
|
complete -c cairn -n "__fish_seen_subcommand_from sync-pi" -l live-root -r
|
|
163
|
+
complete -c cairn -n "__fish_seen_subcommand_from sync-kimi" -l apply
|
|
164
|
+
complete -c cairn -n "__fish_seen_subcommand_from sync-kimi" -l live-root -r
|
|
157
165
|
complete -c cairn -n "__fish_seen_subcommand_from bootstrap" -l untracked
|
|
158
166
|
complete -c cairn -n "__fish_seen_subcommand_from memory" -a "path export import"
|
|
159
167
|
complete -c cairn -n "__fish_seen_subcommand_from doctor" -l repair
|
|
@@ -183,8 +191,11 @@ complete -c cairn -n "__fish_seen_subcommand_from eval; and __fish_seen_subcomma
|
|
|
183
191
|
complete -c cairn -n "__fish_seen_subcommand_from eval; and __fish_seen_subcommand_from prune" -l older-than-days -r
|
|
184
192
|
complete -c cairn -n "__fish_seen_subcommand_from eval; and __fish_seen_subcommand_from prune delete" -l dry-run
|
|
185
193
|
complete -c cairn -n "__fish_seen_subcommand_from eval; and __fish_seen_subcommand_from validate run ablate report prune delete" -l json
|
|
194
|
+
complete -c cairn -n "__fish_seen_subcommand_from graph" -a "build query status diff explain path"
|
|
195
|
+
complete -c cairn -n "__fish_seen_subcommand_from graph; and __fish_seen_subcommand_from build" -l force
|
|
186
196
|
complete -c cairn -n "__fish_seen_subcommand_from completion" -a "bash zsh fish"
|
|
187
197
|
complete -c cairn -n "__fish_seen_subcommand_from uninstall" -l pi-live-root -r
|
|
198
|
+
complete -c cairn -n "__fish_seen_subcommand_from uninstall" -l kimi-live-root -r
|
|
188
199
|
EOF
|
|
189
200
|
;;
|
|
190
201
|
*)
|
package/scripts/smoke-bash32.sh
CHANGED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
usage() {
|
|
5
|
+
cat <<'EOF'
|
|
6
|
+
Usage: sync-kimi-assets.sh [--check|--apply] [--live-root PATH]
|
|
7
|
+
|
|
8
|
+
Compare or sync Cairnkeep's thin graph Skill against the live Kimi Code tree.
|
|
9
|
+
|
|
10
|
+
Options:
|
|
11
|
+
--check Verify managed live assets match the repo copies (default)
|
|
12
|
+
--apply Install managed assets, then verify
|
|
13
|
+
--live-root PATH Override the Kimi Code root (default: $KIMI_CODE_HOME or ~/.kimi-code)
|
|
14
|
+
-h, --help Show this help text
|
|
15
|
+
EOF
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
19
|
+
SOURCE_ROOT="$ROOT_DIR/kimi"
|
|
20
|
+
LIVE_ROOT="${KIMI_CODE_HOME:-$HOME/.kimi-code}"
|
|
21
|
+
MODE="check"
|
|
22
|
+
ASSETS=("skills/graphify/SKILL.md")
|
|
23
|
+
|
|
24
|
+
while [[ $# -gt 0 ]]; do
|
|
25
|
+
case "$1" in
|
|
26
|
+
--check) MODE="check"; shift ;;
|
|
27
|
+
--apply) MODE="apply"; shift ;;
|
|
28
|
+
--live-root) LIVE_ROOT="$2"; shift 2 ;;
|
|
29
|
+
-h|--help) usage; exit 0 ;;
|
|
30
|
+
*) echo "Unknown argument: $1" >&2; usage >&2; exit 2 ;;
|
|
31
|
+
esac
|
|
32
|
+
done
|
|
33
|
+
|
|
34
|
+
ensure_sources() {
|
|
35
|
+
local rel
|
|
36
|
+
for rel in "${ASSETS[@]}"; do
|
|
37
|
+
[[ -f "$SOURCE_ROOT/$rel" ]] || {
|
|
38
|
+
echo "Missing repo-managed source asset: $SOURCE_ROOT/$rel" >&2
|
|
39
|
+
return 2
|
|
40
|
+
}
|
|
41
|
+
done
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
check_assets() {
|
|
45
|
+
local rel
|
|
46
|
+
local failed=0
|
|
47
|
+
for rel in "${ASSETS[@]}"; do
|
|
48
|
+
if [[ ! -f "$LIVE_ROOT/$rel" ]]; then
|
|
49
|
+
echo "Missing live Kimi asset under $LIVE_ROOT: $rel" >&2
|
|
50
|
+
failed=1
|
|
51
|
+
elif ! cmp -s "$SOURCE_ROOT/$rel" "$LIVE_ROOT/$rel"; then
|
|
52
|
+
echo "Out-of-sync live Kimi asset under $LIVE_ROOT: $rel" >&2
|
|
53
|
+
failed=1
|
|
54
|
+
fi
|
|
55
|
+
done
|
|
56
|
+
return "$failed"
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
ensure_sources
|
|
60
|
+
|
|
61
|
+
if [[ "$MODE" == "apply" ]]; then
|
|
62
|
+
updated=0
|
|
63
|
+
unchanged=0
|
|
64
|
+
for rel in "${ASSETS[@]}"; do
|
|
65
|
+
mkdir -p "$(dirname "$LIVE_ROOT/$rel")"
|
|
66
|
+
if [[ -f "$LIVE_ROOT/$rel" ]] && cmp -s "$SOURCE_ROOT/$rel" "$LIVE_ROOT/$rel"; then
|
|
67
|
+
unchanged=$((unchanged + 1))
|
|
68
|
+
else
|
|
69
|
+
install -m 0644 "$SOURCE_ROOT/$rel" "$LIVE_ROOT/$rel"
|
|
70
|
+
updated=$((updated + 1))
|
|
71
|
+
fi
|
|
72
|
+
done
|
|
73
|
+
printf 'Applied %s Kimi asset(s); %s already matched.\n' "$updated" "$unchanged"
|
|
74
|
+
fi
|
|
75
|
+
|
|
76
|
+
check_assets
|
|
77
|
+
printf 'Kimi graph Skill is in sync under %s\n' "$LIVE_ROOT"
|
|
@@ -5,8 +5,8 @@ usage() {
|
|
|
5
5
|
cat <<'EOF'
|
|
6
6
|
Usage: sync-pi-assets.sh [--check|--apply] [--live-root PATH]
|
|
7
7
|
|
|
8
|
-
Compare or sync the repo-managed Pi extension assets against the
|
|
9
|
-
configuration tree.
|
|
8
|
+
Compare or sync the repo-managed Pi extension and prompt assets against the
|
|
9
|
+
live Pi agent configuration tree.
|
|
10
10
|
|
|
11
11
|
Options:
|
|
12
12
|
--check Verify managed live assets match the rendered repo copies (default)
|
|
@@ -20,7 +20,10 @@ ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
|
20
20
|
SOURCE_ROOT="$ROOT_DIR/pi"
|
|
21
21
|
LIVE_ROOT="${PI_CODING_AGENT_DIR:-$HOME/.pi/agent}"
|
|
22
22
|
MODE="check"
|
|
23
|
-
|
|
23
|
+
ASSETS=(
|
|
24
|
+
"extensions/cairnkeep-trajectory.ts"
|
|
25
|
+
"prompts/graphify.md"
|
|
26
|
+
)
|
|
24
27
|
|
|
25
28
|
while [[ $# -gt 0 ]]; do
|
|
26
29
|
case "$1" in
|
|
@@ -33,40 +36,58 @@ while [[ $# -gt 0 ]]; do
|
|
|
33
36
|
done
|
|
34
37
|
|
|
35
38
|
render_asset() {
|
|
36
|
-
|
|
39
|
+
local rel="$1"
|
|
40
|
+
if [[ "$rel" == "extensions/cairnkeep-trajectory.ts" ]]; then
|
|
41
|
+
sed "s|@@INFRA_ROOT@@|$ROOT_DIR|g" "$SOURCE_ROOT/$rel"
|
|
42
|
+
else
|
|
43
|
+
cat "$SOURCE_ROOT/$rel"
|
|
44
|
+
fi
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
ensure_sources() {
|
|
48
|
+
local rel
|
|
49
|
+
for rel in "${ASSETS[@]}"; do
|
|
50
|
+
[[ -f "$SOURCE_ROOT/$rel" ]] || {
|
|
51
|
+
echo "Missing repo-managed source asset: $SOURCE_ROOT/$rel" >&2
|
|
52
|
+
return 2
|
|
53
|
+
}
|
|
54
|
+
done
|
|
37
55
|
}
|
|
38
56
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
57
|
+
check_assets() {
|
|
58
|
+
local rel
|
|
59
|
+
local failed=0
|
|
60
|
+
for rel in "${ASSETS[@]}"; do
|
|
61
|
+
if [[ ! -f "$LIVE_ROOT/$rel" ]]; then
|
|
62
|
+
echo "Missing live Pi asset under $LIVE_ROOT: $rel" >&2
|
|
63
|
+
failed=1
|
|
64
|
+
elif ! cmp -s <(render_asset "$rel") "$LIVE_ROOT/$rel"; then
|
|
65
|
+
echo "Out-of-sync live Pi asset under $LIVE_ROOT: $rel" >&2
|
|
66
|
+
failed=1
|
|
67
|
+
fi
|
|
68
|
+
done
|
|
69
|
+
return "$failed"
|
|
52
70
|
}
|
|
53
71
|
|
|
72
|
+
ensure_sources
|
|
73
|
+
|
|
54
74
|
if [[ "$MODE" == "apply" ]]; then
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
75
|
+
updated=0
|
|
76
|
+
unchanged=0
|
|
77
|
+
for rel in "${ASSETS[@]}"; do
|
|
78
|
+
mkdir -p "$(dirname "$LIVE_ROOT/$rel")"
|
|
79
|
+
if [[ -f "$LIVE_ROOT/$rel" ]] && cmp -s <(render_asset "$rel") "$LIVE_ROOT/$rel"; then
|
|
80
|
+
unchanged=$((unchanged + 1))
|
|
81
|
+
continue
|
|
82
|
+
fi
|
|
63
83
|
rendered_tmp=$(mktemp)
|
|
64
|
-
render_asset > "$rendered_tmp"
|
|
65
|
-
install -m 0644 "$rendered_tmp" "$LIVE_ROOT/$
|
|
84
|
+
render_asset "$rel" > "$rendered_tmp"
|
|
85
|
+
install -m 0644 "$rendered_tmp" "$LIVE_ROOT/$rel"
|
|
66
86
|
rm -f "$rendered_tmp"
|
|
67
|
-
|
|
68
|
-
|
|
87
|
+
updated=$((updated + 1))
|
|
88
|
+
done
|
|
89
|
+
printf 'Applied %s Pi asset(s); %s already matched.\n' "$updated" "$unchanged"
|
|
69
90
|
fi
|
|
70
91
|
|
|
71
|
-
|
|
72
|
-
printf 'Pi extension
|
|
92
|
+
check_assets
|
|
93
|
+
printf 'Pi extension and graph prompt are in sync under %s\n' "$LIVE_ROOT"
|
|
@@ -54,7 +54,29 @@ git -C "$tmp/repo" init -q
|
|
|
54
54
|
"$ROOT/scripts/bootstrap.sh" --untracked "$tmp/repo" >/dev/null
|
|
55
55
|
[[ -f "$tmp/repo/.ai/start-claude.sh" ]] || fail "scaffold missing"
|
|
56
56
|
[[ -x "$tmp/repo/.ai/start-kimi.sh" ]] || fail "Kimi launcher missing"
|
|
57
|
+
[[ -x "$tmp/repo/.ai/start-qwen.sh" ]] || fail "Qwen launcher missing"
|
|
57
58
|
[[ -f "$tmp/repo/.planning/config.json" ]] || fail "planning layer missing"
|
|
59
|
+
graph_policy="$tmp/repo/.planning/graphs/policy.md"
|
|
60
|
+
grep -qF '`uv tool install graphifyy`' "$graph_policy" ||
|
|
61
|
+
fail "Graphify policy must install the CLI in an isolated uv tool environment"
|
|
62
|
+
if grep -qF '`uv pip install graphifyy && graphify install`' "$graph_policy"; then
|
|
63
|
+
fail "Graphify policy must not install Graphify-owned skills or hooks"
|
|
64
|
+
fi
|
|
65
|
+
if ! grep -qF 'Do not run' "$graph_policy" ||
|
|
66
|
+
! grep -qF '`graphify install`: Cairnkeep owns' "$graph_policy"; then
|
|
67
|
+
fail "Graphify policy must explain that Cairnkeep owns the harness wiring"
|
|
68
|
+
fi
|
|
69
|
+
grep -qF '`/graphify build`' "$graph_policy" ||
|
|
70
|
+
fail "Graphify policy must name Cairnkeep's installed build command"
|
|
71
|
+
grep -qF '`cairn sync-kimi' "$graph_policy" ||
|
|
72
|
+
fail "Graphify policy must identify the Kimi thin adapter"
|
|
73
|
+
grep -qF '`cairn sync-pi' "$graph_policy" ||
|
|
74
|
+
fail "Graphify policy must identify the Pi thin adapter"
|
|
75
|
+
grep -qF '`cairn graph build`' "$graph_policy" ||
|
|
76
|
+
fail "Graphify policy must provide the portable CLI equivalent"
|
|
77
|
+
if grep -qF '/gsd-graphify' "$graph_policy"; then
|
|
78
|
+
fail "Graphify policy must not name the GSD-internal command"
|
|
79
|
+
fi
|
|
58
80
|
[[ -f "$tmp/repo/.agentfs/.gitignore" ]] || fail "project-memory ignore guard missing"
|
|
59
81
|
[[ -z "$(git -C "$tmp/repo" status --porcelain)" ]] || fail "scaffold visible to git"
|
|
60
82
|
grep -qxF "/.ai/" "$tmp/repo/.git/info/exclude" || fail "missing /.ai/ exclude entry"
|
|
@@ -67,7 +89,7 @@ grep -qxF "/.agentfs/" "$tmp/repo/.git/info/exclude" || fail "missing /.agentfs/
|
|
|
67
89
|
printf '%s\n' '{"schema_version":1,"capabilities":{"wiki":false},"logging":{"callbacks":true}}' >"$tmp/repo/.ai/capabilities.json"
|
|
68
90
|
chmod 600 "$tmp/repo/.ai/capabilities.json"
|
|
69
91
|
printf '%s\n' '# operator-owned environment' >"$tmp/repo/.ai/env.example"
|
|
70
|
-
asset_paths='.ai/start-claude.sh .ai/start-opencode.sh .ai/start-pi.sh .ai/start-kimi.sh .ai/env.example .ai/trajectory-redaction.json .ai/capabilities.json .agentfs/.gitignore .planning/config.json .planning/wiki/index.md .planning/wiki/policy.md .planning/wiki/CONTRADICTIONS.md .planning/wiki/LOG.md .planning/alignment/policy.md .planning/alignment/gap-register.yaml .planning/graphs/policy.md .planning/graphs/.gitignore .planning/security/policy.md'
|
|
92
|
+
asset_paths='.ai/start-claude.sh .ai/start-opencode.sh .ai/start-pi.sh .ai/start-kimi.sh .ai/start-qwen.sh .ai/env.example .ai/trajectory-redaction.json .ai/capabilities.json .agentfs/.gitignore .planning/config.json .planning/wiki/index.md .planning/wiki/policy.md .planning/wiki/CONTRADICTIONS.md .planning/wiki/LOG.md .planning/alignment/policy.md .planning/alignment/gap-register.yaml .planning/graphs/policy.md .planning/graphs/.gitignore .planning/security/policy.md'
|
|
71
93
|
mkdir -p "$tmp/assets-before"
|
|
72
94
|
for path in $asset_paths; do
|
|
73
95
|
cp "$tmp/repo/$path" "$tmp/assets-before/${path//\//__}"
|
|
@@ -11,15 +11,19 @@ tmp=$(mktemp -d); trap 'rm -rf "$tmp"' EXIT
|
|
|
11
11
|
"$cairn" help | grep -q "cairn audit-timer" || fail "help missing audit-timer"
|
|
12
12
|
"$cairn" help | grep -q "cairn sync" || fail "help missing sync"
|
|
13
13
|
"$cairn" help | grep -q "cairn sync-pi" || fail "help missing sync-pi"
|
|
14
|
+
"$cairn" help | grep -q "cairn sync-kimi" || fail "help missing sync-kimi"
|
|
14
15
|
"$cairn" help | grep -q "cairn memory-server" || fail "help missing memory-server"
|
|
15
16
|
"$cairn" help | grep -q "cairn notes" || fail "help missing notes"
|
|
16
17
|
"$cairn" help | grep -q "cairn artifact <list|show|delete|prune>" || fail "help missing artifact"
|
|
17
18
|
"$cairn" help | grep -q "cairn capabilities <list|status|enable|disable|reset|logging>" || fail "help missing capabilities"
|
|
19
|
+
"$cairn" help | grep -q "cairn graph <build|query|status|diff|explain|path>" || fail "help missing graph"
|
|
18
20
|
"$cairn" sync --help >/dev/null 2>&1 || fail "cairn sync dispatch"
|
|
19
21
|
"$cairn" sync-pi --help >/dev/null 2>&1 || fail "cairn sync-pi dispatch"
|
|
22
|
+
"$cairn" sync-kimi --help >/dev/null 2>&1 || fail "cairn sync-kimi dispatch"
|
|
20
23
|
env -u CAIRN_NOTE_DISTILLATION "$cairn" notes --help >/dev/null 2>&1 || fail "cairn notes dispatch"
|
|
21
24
|
"$cairn" artifact --help | grep -q "cairn artifact list" || fail "cairn artifact dispatch"
|
|
22
25
|
"$cairn" capabilities --help >"$tmp/capabilities-help" 2>/dev/null || fail "cairn capabilities dispatch"
|
|
26
|
+
"$cairn" graph --help | grep -q "cairn graph explain <symbol>" || fail "cairn graph dispatch"
|
|
23
27
|
grep -qxF 'MCP capability changes require a memory-server restart. Operating capability' "$tmp/capabilities-help" || fail "capability help missing exact restart wording"
|
|
24
28
|
grep -qxF 'changes apply on the next invocation.' "$tmp/capabilities-help" || fail "capability help missing exact invocation wording"
|
|
25
29
|
if grep -Eq '^ cairn capabilities (guard|start|finish|doctor)' "$tmp/capabilities-help"; then
|
|
@@ -71,14 +71,19 @@ grep -q '#compdef cairn' "$tmp/zsh"
|
|
|
71
71
|
grep -q 'complete -c cairn' "$tmp/fish"
|
|
72
72
|
for shell in bash zsh; do
|
|
73
73
|
grep -q 'sync-pi' "$tmp/$shell"
|
|
74
|
+
grep -q 'sync-kimi' "$tmp/$shell"
|
|
74
75
|
grep -q -- '--live-root' "$tmp/$shell"
|
|
75
76
|
done
|
|
76
77
|
grep -q 'sync-pi' "$tmp/fish"
|
|
78
|
+
grep -q 'sync-kimi' "$tmp/fish"
|
|
79
|
+
grep -q 'not __fish_seen_subcommand_from .*sync-pi sync-kimi' "$tmp/fish"
|
|
77
80
|
grep -q -- '-l live-root' "$tmp/fish"
|
|
78
81
|
for shell in bash zsh fish; do
|
|
79
82
|
grep -q 'notes' "$tmp/$shell"
|
|
80
83
|
grep -q 'distill.*search-error.*promote.*doctor\|distill search-error promote doctor' "$tmp/$shell"
|
|
81
84
|
grep -q 'artifact' "$tmp/$shell"
|
|
85
|
+
grep -q 'graph' "$tmp/$shell"
|
|
86
|
+
grep -q 'build.*query.*status.*diff.*explain.*path\|build query status diff explain path' "$tmp/$shell"
|
|
82
87
|
grep -q 'list.*show.*delete.*prune' "$tmp/$shell"
|
|
83
88
|
grep -q -- '--json\|-l json' "$tmp/$shell"
|
|
84
89
|
grep -q -- '--dry-run\|-l dry-run' "$tmp/$shell"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Contract test: Pi and Kimi expose thin graph adapters owned by `cairn graph`.
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
ROOT=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
|
|
6
|
+
tmp=$(mktemp -d)
|
|
7
|
+
trap 'rm -rf "$tmp"' EXIT
|
|
8
|
+
fail() { echo "FAIL: $1" >&2; exit 1; }
|
|
9
|
+
|
|
10
|
+
PI_SOURCE="$ROOT/pi/prompts/graphify.md"
|
|
11
|
+
KIMI_SOURCE="$ROOT/kimi/skills/graphify/SKILL.md"
|
|
12
|
+
|
|
13
|
+
[[ -f "$PI_SOURCE" ]] || fail "Pi /graphify prompt source is missing"
|
|
14
|
+
[[ -f "$KIMI_SOURCE" ]] || fail "Kimi graphify skill source is missing"
|
|
15
|
+
|
|
16
|
+
for adapter in "$PI_SOURCE" "$KIMI_SOURCE"; do
|
|
17
|
+
grep -qF 'cairn graph' "$adapter" || fail "adapter does not delegate to cairn graph: $adapter"
|
|
18
|
+
if grep -Ei '(^|[^/[:alnum:]_-])graphify[[:space:]]+(build|update|query|status|diff|explain|path)' "$adapter" >/dev/null; then
|
|
19
|
+
fail "adapter invokes Graphify directly: $adapter"
|
|
20
|
+
fi
|
|
21
|
+
if grep -Ei '(^|[[:space:]`])(curl|git|node|npm|npx|python|python3)[[:space:]]' "$adapter" >/dev/null; then
|
|
22
|
+
fail "adapter introduces a second executable delegate: $adapter"
|
|
23
|
+
fi
|
|
24
|
+
done
|
|
25
|
+
|
|
26
|
+
grep -qF '$ARGUMENTS' "$PI_SOURCE" || fail "Pi prompt does not forward command arguments"
|
|
27
|
+
grep -qF 'name: graphify' "$KIMI_SOURCE" || fail "Kimi skill does not register as graphify"
|
|
28
|
+
grep -qF '$ARGUMENTS' "$KIMI_SOURCE" || fail "Kimi skill does not forward command arguments"
|
|
29
|
+
|
|
30
|
+
PI_LIVE="$tmp/pi"
|
|
31
|
+
"$ROOT/scripts/sync-pi-assets.sh" --apply --live-root "$PI_LIVE" >"$tmp/pi-first"
|
|
32
|
+
[[ -f "$PI_LIVE/extensions/cairnkeep-trajectory.ts" ]] || fail "Pi sync omitted trajectory extension"
|
|
33
|
+
cmp -s "$PI_SOURCE" "$PI_LIVE/prompts/graphify.md" || fail "Pi sync changed graphify prompt bytes"
|
|
34
|
+
"$ROOT/scripts/sync-pi-assets.sh" --apply --live-root "$PI_LIVE" >"$tmp/pi-second"
|
|
35
|
+
grep -qF 'Applied 0 Pi asset(s); 2 already matched.' "$tmp/pi-second" || fail "Pi sync is not idempotent"
|
|
36
|
+
|
|
37
|
+
KIMI_LIVE="$tmp/kimi"
|
|
38
|
+
"$ROOT/scripts/sync-kimi-assets.sh" --apply --live-root "$KIMI_LIVE" >"$tmp/kimi-first"
|
|
39
|
+
cmp -s "$KIMI_SOURCE" "$KIMI_LIVE/skills/graphify/SKILL.md" || fail "Kimi sync changed graphify skill bytes"
|
|
40
|
+
"$ROOT/scripts/sync-kimi-assets.sh" --apply --live-root "$KIMI_LIVE" >"$tmp/kimi-second"
|
|
41
|
+
grep -qF 'Applied 0 Kimi asset(s); 1 already matched.' "$tmp/kimi-second" || fail "Kimi sync is not idempotent"
|
|
42
|
+
|
|
43
|
+
"$ROOT/bin/cairn" help | grep -qF 'cairn sync-kimi' || fail "CLI help omits sync-kimi"
|
|
44
|
+
"$ROOT/bin/cairn" sync-kimi --help >/dev/null || fail "CLI does not dispatch sync-kimi"
|
|
45
|
+
|
|
46
|
+
echo "PASS: thin Pi and Kimi graph adapters delegate only to cairn graph"
|
|
@@ -425,14 +425,18 @@ pi_launcher="$repo/.ai/start-pi.sh"
|
|
|
425
425
|
[[ -x "$pi_launcher" ]] || fail "Pi launcher not scaffolded"
|
|
426
426
|
kimi_launcher="$repo/.ai/start-kimi.sh"
|
|
427
427
|
[[ -x "$kimi_launcher" ]] || fail "Kimi launcher not scaffolded"
|
|
428
|
+
qwen_launcher="$repo/.ai/start-qwen.sh"
|
|
429
|
+
[[ -x "$qwen_launcher" ]] || fail "Qwen launcher not scaffolded"
|
|
428
430
|
|
|
429
431
|
# OpenCode's run mode ends a turn after content-only output. Commands that need
|
|
430
432
|
# owner I/O must therefore make their first response action a tool call rather
|
|
431
433
|
# than requiring a standalone banner before the config gate.
|
|
432
434
|
! grep -qF '**Before ANY tool calls**, display this banner:' "$ROOT/opencode/command/graphify.md" \
|
|
433
435
|
|| fail "OpenCode graphify can stop after its pre-tool banner"
|
|
434
|
-
grep -qF '**First action:** invoke the Read tool' "$ROOT/opencode/command/graphify.md" \
|
|
435
|
-
|| fail "OpenCode graphify
|
|
436
|
+
! grep -qF '**First action:** invoke the Read tool' "$ROOT/opencode/command/graphify.md" \
|
|
437
|
+
|| fail "OpenCode graphify still duplicates the Cairnkeep-owned capability gate"
|
|
438
|
+
grep -qF '`cairn graph` operation enforces the typed `graph` capability' "$ROOT/opencode/command/graphify.md" \
|
|
439
|
+
|| fail "OpenCode graphify does not delegate its capability gate to the owner"
|
|
436
440
|
grep -qF '**Invoke the shell tool** with this exact command' "$ROOT/opencode/command/graphify.md" \
|
|
437
441
|
|| fail "OpenCode graphify does not require real shell delegation"
|
|
438
442
|
grep -qF '<argument>$ARGUMENTS</argument>' "$ROOT/opencode/command/graphify.md" \
|
|
@@ -471,12 +475,18 @@ cat > "$tmp/bin/kimi" <<'FAKE'
|
|
|
471
475
|
{ echo "args:$*"; echo "prelaunch:${PRELAUNCH_RAN:-0}"; echo "extra:${CAIRN_EXTRA_SETTINGS:-}"; } > "$KIMI_LOG"
|
|
472
476
|
exit "${FAKE_EXIT:-0}"
|
|
473
477
|
FAKE
|
|
474
|
-
|
|
478
|
+
cat > "$tmp/bin/qwen" <<'FAKE'
|
|
479
|
+
#!/usr/bin/env bash
|
|
480
|
+
{ echo "args:$*"; echo "prelaunch:${PRELAUNCH_RAN:-0}"; echo "extra:${CAIRN_EXTRA_SETTINGS:-}"; } > "$QWEN_LOG"
|
|
481
|
+
exit "${FAKE_EXIT:-0}"
|
|
482
|
+
FAKE
|
|
483
|
+
chmod +x "$tmp/bin/claude" "$tmp/bin/opencode" "$tmp/bin/kimi" "$tmp/bin/qwen"
|
|
475
484
|
ln -s "$ROOT/bin/cairn" "$tmp/bin/cairn"
|
|
476
485
|
export PATH="$tmp/bin:$PATH"
|
|
477
486
|
export CLAUDE_LOG="$tmp/claude.log"
|
|
478
487
|
export OPENCODE_LOG="$tmp/opencode.log"
|
|
479
488
|
export KIMI_LOG="$tmp/kimi.log"
|
|
489
|
+
export QWEN_LOG="$tmp/qwen.log"
|
|
480
490
|
|
|
481
491
|
# Claude sync has three exact installation states. Normal sync and an explicit
|
|
482
492
|
# overlay request with the master off must contain no capability hook bytes or
|
|
@@ -540,6 +550,10 @@ grep -qx "capability-registration:0" "$OPENCODE_LOG" || fail "OpenCode baseline
|
|
|
540
550
|
grep -qx "args:--foo bar" "$KIMI_LOG" || fail "Kimi baseline did not pass args through"
|
|
541
551
|
grep -qx "prelaunch:0" "$KIMI_LOG" || fail "Kimi prelaunch marker leaked without a hook"
|
|
542
552
|
|
|
553
|
+
"$qwen_launcher" --foo bar >/dev/null 2>&1 || fail "Qwen baseline launch failed"
|
|
554
|
+
grep -qx "args:--foo bar" "$QWEN_LOG" || fail "Qwen baseline did not pass args through"
|
|
555
|
+
grep -qx "prelaunch:0" "$QWEN_LOG" || fail "Qwen prelaunch marker leaked without a hook"
|
|
556
|
+
|
|
543
557
|
# Invalid/off master values stay on the legacy direct-exec path: one harness
|
|
544
558
|
# process, unchanged argv/config environment, and no isolated assets or store.
|
|
545
559
|
legacy_claude="$tmp/legacy-claude"
|
|
@@ -636,6 +650,12 @@ grep -qx "args:--plan" "$KIMI_LOG" || fail "Kimi pre-launch changed harness argv
|
|
|
636
650
|
grep -qx "prelaunch:1" "$KIMI_LOG" || fail "Kimi pre-launch env not visible to harness"
|
|
637
651
|
grep -qx "extra:$tmp/settings.json" "$KIMI_LOG" || fail "Kimi pre-launch environment was not preserved"
|
|
638
652
|
|
|
653
|
+
rm -f "$QWEN_LOG"
|
|
654
|
+
"$qwen_launcher" --approval-mode plan >/dev/null 2>&1 || fail "Qwen launch with pre-launch failed"
|
|
655
|
+
grep -qx "args:--approval-mode plan" "$QWEN_LOG" || fail "Qwen pre-launch changed harness argv"
|
|
656
|
+
grep -qx "prelaunch:1" "$QWEN_LOG" || fail "Qwen pre-launch env not visible to harness"
|
|
657
|
+
grep -qx "extra:$tmp/settings.json" "$QWEN_LOG" || fail "Qwen pre-launch environment was not preserved"
|
|
658
|
+
|
|
639
659
|
# 3. pre-launch.sh non-zero aborts the launch before the harness runs.
|
|
640
660
|
rm -f "$CLAUDE_LOG"
|
|
641
661
|
cat > "$repo/.ai/pre-launch.sh" <<'EOF'
|
|
@@ -647,6 +667,9 @@ if "$launcher" >/dev/null 2>&1; then fail "non-zero pre-launch should abort the
|
|
|
647
667
|
rm -f "$KIMI_LOG"
|
|
648
668
|
if "$kimi_launcher" >/dev/null 2>&1; then fail "non-zero pre-launch should abort Kimi"; fi
|
|
649
669
|
[[ ! -f "$KIMI_LOG" ]] || fail "Kimi ran despite pre-launch abort"
|
|
670
|
+
rm -f "$QWEN_LOG"
|
|
671
|
+
if "$qwen_launcher" >/dev/null 2>&1; then fail "non-zero pre-launch should abort Qwen"; fi
|
|
672
|
+
[[ ! -f "$QWEN_LOG" ]] || fail "Qwen ran despite pre-launch abort"
|
|
650
673
|
rm -f "$repo/.ai/pre-launch.sh"
|
|
651
674
|
|
|
652
675
|
# 4. post-exit.sh runs after the harness with $CAIRN_EXIT_STATUS.
|
|
@@ -666,6 +689,13 @@ status=$?
|
|
|
666
689
|
grep -qx "args:--auto" "$KIMI_LOG" || fail "Kimi launcher changed arguments"
|
|
667
690
|
grep -qx "post:8" "$tmp/post.log" || fail "Kimi launcher post-exit status missing"
|
|
668
691
|
|
|
692
|
+
rm -f "$tmp/post.log" "$QWEN_LOG"
|
|
693
|
+
FAKE_EXIT=10 "$qwen_launcher" --output-format json >/dev/null 2>&1 && fail "Qwen launcher should propagate harness exit code"
|
|
694
|
+
status=$?
|
|
695
|
+
[[ "$status" -eq 10 ]] || fail "expected exit 10 from Qwen launcher, got $status"
|
|
696
|
+
grep -qx "args:--output-format json" "$QWEN_LOG" || fail "Qwen launcher changed arguments"
|
|
697
|
+
grep -qx "post:10" "$tmp/post.log" || fail "Qwen launcher post-exit status missing"
|
|
698
|
+
|
|
669
699
|
# 5. Pi launcher preserves the same env/pre/post seams and passes arguments
|
|
670
700
|
# unchanged; Pi has no generic settings-file flag so CAIRN_EXTRA_SETTINGS is ignored.
|
|
671
701
|
rm -f "$repo/.ai/pre-launch.sh" "$repo/.ai/post-exit.sh"
|
|
@@ -6,11 +6,10 @@ cd "$ROOT"
|
|
|
6
6
|
|
|
7
7
|
version=$(node -p "require('./package.json').version")
|
|
8
8
|
landing=docs/learning/README.md
|
|
9
|
-
production=docs/learning/PRODUCTION-PLAN.md
|
|
10
9
|
coverage=docs/learning/CURRICULUM-MAP.md
|
|
11
10
|
feature_guide=docs/learning/FEATURE-GUIDE.md
|
|
12
11
|
|
|
13
|
-
[[ -f "$landing" && -f "$
|
|
12
|
+
[[ -f "$landing" && -f "$coverage" && -f "$feature_guide" ]]
|
|
14
13
|
grep -qF 'docs/learning/README.md' README.md
|
|
15
14
|
grep -qF "**Baseline:** Cairnkeep $version" "$coverage"
|
|
16
15
|
grep -qF "**Baseline:** Cairnkeep $version" "$feature_guide"
|
|
@@ -33,17 +32,11 @@ for number in $(seq -w 0 17); do
|
|
|
33
32
|
if grep -q '^\*\*Status:\*\* Ready' "$lesson"; then
|
|
34
33
|
ready=$((ready + 1))
|
|
35
34
|
grep -qF "Tested with:** Cairnkeep $version" "$lesson"
|
|
36
|
-
script=$(sed -n 's|.*(\.\./video-scripts/\([^)]*\)).*|docs/learning/video-scripts/\1|p' "$lesson")
|
|
37
|
-
[[ -n "$script" && -f "$script" ]] || {
|
|
38
|
-
echo "ready lesson has no presenter script: $lesson" >&2
|
|
39
|
-
exit 1
|
|
40
|
-
}
|
|
41
35
|
grep -q '^## Common failures$' "$lesson"
|
|
42
36
|
grep -q '^## Privacy and trust boundary$' "$lesson"
|
|
43
37
|
elif grep -q '^\*\*Status:\*\* Brief' "$lesson"; then
|
|
44
38
|
brief=$((brief + 1))
|
|
45
39
|
grep -q '^## Acceptance criteria$' "$lesson"
|
|
46
|
-
grep -q '^## Planned video$' "$lesson"
|
|
47
40
|
else
|
|
48
41
|
echo "lesson has an unsupported status: $lesson" >&2
|
|
49
42
|
exit 1
|
|
@@ -91,4 +84,4 @@ for (const file of markdownFiles("docs/learning")) {
|
|
|
91
84
|
}
|
|
92
85
|
NODE
|
|
93
86
|
|
|
94
|
-
echo "PASS: learning path structure, readiness,
|
|
87
|
+
echo "PASS: public learning path structure, readiness, links, and version alignment"
|
|
@@ -44,6 +44,7 @@ bootstrap_output=$(cairn bootstrap "$tmp/project")
|
|
|
44
44
|
[[ -x "$tmp/project/.ai/start-claude.sh" ]] || fail "bootstrap did not install an executable Claude launcher"
|
|
45
45
|
[[ -x "$tmp/project/.ai/start-pi.sh" ]] || fail "bootstrap did not install an executable Pi launcher"
|
|
46
46
|
[[ -x "$tmp/project/.ai/start-kimi.sh" ]] || fail "bootstrap did not install an executable Kimi launcher"
|
|
47
|
+
[[ -x "$tmp/project/.ai/start-qwen.sh" ]] || fail "bootstrap did not install an executable Qwen launcher"
|
|
47
48
|
[[ -f "$tmp/project/.planning/config.json" ]] || fail "bootstrap did not install the planning scaffold"
|
|
48
49
|
|
|
49
50
|
(cd "$tmp/project" && cairn doctor) >/dev/null || fail "installed package failed cairn doctor"
|
|
@@ -217,12 +218,20 @@ NODE
|
|
|
217
218
|
fail "npm tarball omitted the default AnythingLLM sync script"
|
|
218
219
|
[[ -f "$installed_root/pi/extensions/cairnkeep-trajectory.ts" ]] || \
|
|
219
220
|
fail "npm tarball omitted the Pi trajectory extension"
|
|
221
|
+
[[ -f "$installed_root/pi/prompts/graphify.md" ]] || \
|
|
222
|
+
fail "npm tarball omitted the Pi graph prompt"
|
|
223
|
+
[[ -f "$installed_root/kimi/skills/graphify/SKILL.md" ]] || \
|
|
224
|
+
fail "npm tarball omitted the Kimi graph Skill"
|
|
220
225
|
[[ -x "$installed_root/scripts/sync-pi-assets.sh" ]] || \
|
|
221
226
|
fail "npm tarball omitted the Pi sync command"
|
|
227
|
+
[[ -x "$installed_root/scripts/sync-kimi-assets.sh" ]] || \
|
|
228
|
+
fail "npm tarball omitted the Kimi sync command"
|
|
222
229
|
[[ -f "$installed_root/templates/start-pi.sh.template" ]] || \
|
|
223
230
|
fail "npm tarball omitted the Pi launcher template"
|
|
224
231
|
[[ -f "$installed_root/templates/start-kimi.sh.template" ]] || \
|
|
225
232
|
fail "npm tarball omitted the Kimi launcher template"
|
|
233
|
+
[[ -f "$installed_root/templates/start-qwen.sh.template" ]] || \
|
|
234
|
+
fail "npm tarball omitted the Qwen launcher template"
|
|
226
235
|
[[ -f "$installed_root/schemas/note.schema.json" ]] || \
|
|
227
236
|
fail "npm tarball omitted the note schema"
|
|
228
237
|
[[ -f "$installed_root/schemas/memory-node.schema.json" ]] || \
|
|
@@ -127,6 +127,8 @@ pi_live="$tmp/pi-live"
|
|
|
127
127
|
render "$ROOT/pi/extensions/cairnkeep-trajectory.ts" "$tmp/expected-pi-capture.ts"
|
|
128
128
|
cmp -s "$tmp/expected-pi-capture.ts" "$pi_live/extensions/cairnkeep-trajectory.ts" \
|
|
129
129
|
|| fail "installed Pi trajectory extension differs from rendered source"
|
|
130
|
+
cmp -s "$ROOT/pi/prompts/graphify.md" "$pi_live/prompts/graphify.md" \
|
|
131
|
+
|| fail "installed Pi graph prompt differs from source"
|
|
130
132
|
[[ $(find "$pi_live" -type f -name 'cairnkeep-trajectory.ts' | wc -l) -eq 1 ]] \
|
|
131
133
|
|| fail "Pi trajectory extension is duplicated"
|
|
132
134
|
|
|
@@ -136,7 +138,9 @@ cmp -s "$tmp/expected-pi-capture.ts" "$pi_live/extensions/cairnkeep-trajectory.t
|
|
|
136
138
|
|| fail "Claude memory-capture hook registration is missing or duplicated"
|
|
137
139
|
[[ $(grep -c 'plugins/memory-capture.ts' "$ROOT/scripts/sync-opencode-plugin-assets.sh") -eq 1 ]] \
|
|
138
140
|
|| fail "OpenCode memory-capture plugin asset is missing or duplicated"
|
|
139
|
-
[[ $(grep -c 'extensions/cairnkeep-trajectory.ts' "$ROOT/scripts/sync-pi-assets.sh") -eq 1 ]] \
|
|
141
|
+
[[ $(grep -c '^ "extensions/cairnkeep-trajectory.ts"' "$ROOT/scripts/sync-pi-assets.sh") -eq 1 ]] \
|
|
140
142
|
|| fail "Pi trajectory extension asset is missing or duplicated"
|
|
143
|
+
[[ $(grep -c '^ "prompts/graphify.md"' "$ROOT/scripts/sync-pi-assets.sh") -eq 1 ]] \
|
|
144
|
+
|| fail "Pi graph prompt asset is missing or duplicated"
|
|
141
145
|
|
|
142
146
|
echo "PASS: Claude/OpenCode/Pi trajectory hooks and flag-off regression"
|