@cairnkeep/cli 2.3.1 → 2.4.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 +69 -0
- package/README.md +221 -6
- package/bin/cairn +43 -2
- package/claude/capability-contract/hooks/capability-command-finish.sh +81 -0
- package/claude/capability-contract/hooks/capability-command-start.sh +76 -0
- package/claude/hooks/compaction-capture.sh +34 -0
- package/claude/hooks/memory-capture.sh +47 -5
- package/claude/hooks/memory-wakeup.sh +55 -2
- package/docs/building-an-overlay.md +1 -1
- package/docs/design/meta-agent.md +439 -0
- package/docs/learning/lessons/L00-why-cairnkeep.md +1 -1
- package/docs/learning/lessons/L01-safe-trial.md +3 -3
- package/docs/learning/lessons/L02-installation.md +2 -2
- package/docs/learning/lessons/L03-first-project.md +1 -1
- package/docs/operating.md +531 -4
- package/docs/privacy-and-data-flow.md +417 -0
- package/docs/storage.md +252 -0
- package/examples/eval/README.md +42 -0
- package/examples/eval/adapter.json +12 -0
- package/examples/eval/bundled-fake.json +1 -0
- package/examples/eval/task-set.json +1 -0
- package/mcp-memory-server/dist/artifact-cli.js +184 -0
- package/mcp-memory-server/dist/artifact-schema.js +218 -0
- package/mcp-memory-server/dist/artifact-store.js +812 -0
- package/mcp-memory-server/dist/capability-adapter.js +286 -0
- package/mcp-memory-server/dist/capability-cli.js +361 -0
- package/mcp-memory-server/dist/capability-config.js +310 -0
- package/mcp-memory-server/dist/capability-harness.js +496 -0
- package/mcp-memory-server/dist/capability-registry.js +123 -0
- package/mcp-memory-server/dist/capability-schema.js +65 -0
- package/mcp-memory-server/dist/capability-store.js +431 -0
- package/mcp-memory-server/dist/compaction-normalize.js +267 -0
- package/mcp-memory-server/dist/eval-cli.js +523 -0
- package/mcp-memory-server/dist/eval-plan.js +346 -0
- package/mcp-memory-server/dist/eval-process.js +273 -0
- package/mcp-memory-server/dist/eval-report.js +609 -0
- package/mcp-memory-server/dist/eval-runner.js +827 -0
- package/mcp-memory-server/dist/eval-schema.js +368 -0
- package/mcp-memory-server/dist/eval-statistics.js +161 -0
- package/mcp-memory-server/dist/eval-workspace.js +313 -0
- package/mcp-memory-server/dist/failure-signature.js +141 -0
- package/mcp-memory-server/dist/index.js +600 -55
- package/mcp-memory-server/dist/node-cli.js +84 -0
- package/mcp-memory-server/dist/node-schema.js +170 -0
- package/mcp-memory-server/dist/node-store.js +455 -0
- package/mcp-memory-server/dist/note-cli.js +235 -0
- package/mcp-memory-server/dist/note-distiller.js +177 -0
- package/mcp-memory-server/dist/note-enrichment.js +93 -0
- package/mcp-memory-server/dist/note-schema.js +4 -0
- package/mcp-memory-server/dist/note-store.js +985 -0
- package/mcp-memory-server/dist/trajectory-cli.js +141 -0
- package/mcp-memory-server/dist/trajectory-normalize.js +448 -0
- package/mcp-memory-server/dist/trajectory-redaction.js +155 -0
- package/mcp-memory-server/dist/trajectory-schema.js +73 -0
- package/mcp-memory-server/dist/trajectory-store.js +339 -0
- package/mcp-memory-server/package.json +24 -2
- package/mcp-memory-server/scripts/fixtures/compaction-claude-code-2.1.219.json +9 -0
- package/mcp-memory-server/scripts/fixtures/compaction-claude-code-2.1.220.json +9 -0
- package/mcp-memory-server/scripts/fixtures/compaction-opencode-1.17.20-event.json +6 -0
- package/mcp-memory-server/scripts/fixtures/compaction-opencode-1.17.20-messages.json +119 -0
- package/mcp-memory-server/scripts/fixtures/compaction-unknown-version.json +17 -0
- package/opencode/capability-contract/plugins/capability-command.ts +319 -0
- package/opencode/command/graphify.md +25 -14
- package/opencode/plugins/memory-capture.ts +76 -10
- package/opencode/plugins/memory-wakeup.ts +58 -6
- package/package.json +8 -4
- package/pi/extensions/cairnkeep-trajectory.ts +55 -0
- package/schemas/artifact.schema.json +133 -0
- package/schemas/capability-callback.schema.json +68 -0
- package/schemas/capability-contract.schema.json +126 -0
- package/schemas/eval-adapter.schema.json +43 -0
- package/schemas/eval-protocol.schema.json +114 -0
- package/schemas/eval-report.schema.json +423 -0
- package/schemas/eval-task-set.schema.json +114 -0
- package/schemas/memory-node.schema.json +90 -0
- package/schemas/note.schema.json +112 -0
- package/schemas/trajectory-redaction.schema.json +25 -0
- package/schemas/trajectory.schema.json +82 -0
- package/scripts/bootstrap.sh +4 -0
- package/scripts/completion.sh +119 -5
- package/scripts/doctor.sh +284 -0
- package/scripts/fake-eval-adapter.mjs +120 -0
- package/scripts/fixtures/capability-harness-contracts.json +408 -0
- package/scripts/install-audit-timer.sh +3 -1
- package/scripts/lib/capability-opencode-plugin-harness.mjs +291 -0
- package/scripts/lib/trajectory-opencode-plugin-harness.mjs +25 -0
- package/scripts/lib/trajectory-pi-extension-harness.mjs +42 -0
- package/scripts/memory-wiki-audit.sh +49 -0
- package/scripts/smoke-bash32.sh +9 -0
- package/scripts/sync-claude-assets.sh +99 -6
- package/scripts/sync-opencode-graphify-assets.sh +24 -3
- package/scripts/sync-opencode-plugin-assets.sh +31 -5
- package/scripts/sync-opencode-security-assets.sh +24 -3
- package/scripts/sync-opencode-wiki-assets.sh +24 -3
- package/scripts/sync-pi-assets.sh +72 -0
- package/scripts/test-audit-timer.sh +98 -0
- package/scripts/test-bootstrap-untracked.sh +48 -0
- package/scripts/test-cli-dispatch.sh +41 -2
- package/scripts/test-compaction-hooks.sh +495 -0
- package/scripts/test-completion.sh +77 -0
- package/scripts/test-doctor.sh +348 -1
- package/scripts/test-eval-cli.sh +175 -0
- package/scripts/test-launcher-hooks.sh +602 -3
- package/scripts/test-notes-cli.sh +114 -0
- package/scripts/test-package-install.sh +251 -0
- package/scripts/test-phase16-node-lifecycle.sh +50 -0
- package/scripts/test-phase17-artifact-lifecycle.sh +370 -0
- package/scripts/test-phase18-capability-lifecycle.sh +504 -0
- package/scripts/test-phase18-harness-boundary.sh +1060 -0
- package/scripts/test-phase19-eval-lifecycle.sh +1015 -0
- package/scripts/test-trajectory-cli.sh +87 -0
- package/scripts/test-trajectory-hooks.sh +142 -0
- package/scripts/test-uninstall.sh +231 -5
- package/scripts/uninstall.sh +37 -5
- package/scripts/verify-dependency-security.mjs +121 -0
- package/scripts/verify-docs-parity.sh +527 -1
- package/scripts/verify-phase18-runtime-evidence.mjs +895 -0
- package/scripts/verify-phase19-runtime-evidence.mjs +947 -0
- package/templates/capabilities.json.template +7 -0
- package/templates/env.example.template +51 -0
- package/templates/memory-wiki-audit.service.template +1 -1
- package/templates/start-claude.sh.template +36 -0
- package/templates/start-opencode.sh.template +47 -5
- package/templates/start-pi.sh.template +30 -0
- package/templates/trajectory-redaction.json.template +4 -0
|
@@ -21,6 +21,9 @@ set -euo pipefail
|
|
|
21
21
|
usage() {
|
|
22
22
|
cat <<'EOF'
|
|
23
23
|
Usage: verify-docs-parity.sh
|
|
24
|
+
verify-docs-parity.sh --artifact-remote-path-only
|
|
25
|
+
verify-docs-parity.sh --expect-red-artifact-remote-path
|
|
26
|
+
verify-docs-parity.sh --self-test-native-capability-docs
|
|
24
27
|
verify-docs-parity.sh -h|--help
|
|
25
28
|
|
|
26
29
|
Checks that every CAIRN_*/MCP_HTTP_* env key read by the cairn-memory MCP
|
|
@@ -32,14 +35,235 @@ drift, or 0 if the docs are fully in sync with the shipped code.
|
|
|
32
35
|
EOF
|
|
33
36
|
}
|
|
34
37
|
|
|
38
|
+
EXPECTED_RED_EXIT=86
|
|
39
|
+
ARTIFACT_REMOTE_PATH_RED_MARKER='PHASE17_RED:ARTIFACT_REMOTE_PATH_DOC_DRIFT'
|
|
40
|
+
|
|
35
41
|
ENV_KEY_PATTERN='(CAIRN_[A-Z_]+|MCP_HTTP_[A-Z_]+)'
|
|
36
42
|
|
|
43
|
+
run_native_capability_docs_self_test() {
|
|
44
|
+
local fixture_root pristine_root
|
|
45
|
+
fixture_root=$(mktemp -d)
|
|
46
|
+
trap "rm -rf '$fixture_root'" EXIT HUP INT TERM
|
|
47
|
+
pristine_root="$fixture_root/pristine"
|
|
48
|
+
|
|
49
|
+
mkdir -p \
|
|
50
|
+
"$fixture_root/docs" \
|
|
51
|
+
"$fixture_root/mcp-memory-server/src" \
|
|
52
|
+
"$fixture_root/claude/capability-contract/hooks" \
|
|
53
|
+
"$fixture_root/opencode/capability-contract/plugins" \
|
|
54
|
+
"$fixture_root/scripts" \
|
|
55
|
+
"$pristine_root"
|
|
56
|
+
cp docs/operating.md docs/privacy-and-data-flow.md docs/storage.md "$fixture_root/docs/"
|
|
57
|
+
cp docs/operating.md docs/privacy-and-data-flow.md docs/storage.md "$pristine_root/"
|
|
58
|
+
cp mcp-memory-server/src/capability-harness.ts "$fixture_root/mcp-memory-server/src/"
|
|
59
|
+
cp mcp-memory-server/src/capability-store.ts "$fixture_root/mcp-memory-server/src/"
|
|
60
|
+
cp claude/capability-contract/hooks/capability-command-start.sh "$fixture_root/claude/capability-contract/hooks/"
|
|
61
|
+
cp claude/capability-contract/hooks/capability-command-finish.sh "$fixture_root/claude/capability-contract/hooks/"
|
|
62
|
+
cp opencode/capability-contract/plugins/capability-command.ts "$fixture_root/opencode/capability-contract/plugins/"
|
|
63
|
+
cp scripts/sync-claude-assets.sh scripts/sync-opencode-plugin-assets.sh "$fixture_root/scripts/"
|
|
64
|
+
|
|
65
|
+
check_native_capability_docs "$fixture_root"
|
|
66
|
+
|
|
67
|
+
expect_native_docs_drift() {
|
|
68
|
+
local label="$1" file="$2" before="$3" after="$4"
|
|
69
|
+
cp "$pristine_root/operating.md" "$fixture_root/docs/operating.md"
|
|
70
|
+
cp "$pristine_root/privacy-and-data-flow.md" "$fixture_root/docs/privacy-and-data-flow.md"
|
|
71
|
+
cp "$pristine_root/storage.md" "$fixture_root/docs/storage.md"
|
|
72
|
+
python3 - "$fixture_root/$file" "$before" "$after" <<'PY'
|
|
73
|
+
from pathlib import Path
|
|
74
|
+
import sys
|
|
75
|
+
|
|
76
|
+
path = Path(sys.argv[1])
|
|
77
|
+
before, after = sys.argv[2], sys.argv[3]
|
|
78
|
+
text = path.read_text(encoding="utf-8")
|
|
79
|
+
if before not in text:
|
|
80
|
+
raise SystemExit(f"self-test fixture text not found: {before}")
|
|
81
|
+
path.write_text(text.replace(before, after, 1), encoding="utf-8")
|
|
82
|
+
PY
|
|
83
|
+
if check_native_capability_docs "$fixture_root" >/dev/null 2>&1; then
|
|
84
|
+
echo "FATAL: native capability docs mutation was not rejected: $label" >&2
|
|
85
|
+
return 1
|
|
86
|
+
fi
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
expect_native_docs_drift "master-off state" docs/operating.md \
|
|
90
|
+
"create no capability measurement state" "create one capability measurement record"
|
|
91
|
+
expect_native_docs_drift "all-three-consents requirement" docs/privacy-and-data-flow.md \
|
|
92
|
+
"When all three consents are enabled" "When logging alone is enabled"
|
|
93
|
+
expect_native_docs_drift "disabled unmeasured block" docs/privacy-and-data-flow.md \
|
|
94
|
+
"the same fixed block remains in force and" "owner execution continues and"
|
|
95
|
+
expect_native_docs_drift "enabled unmeasured pass-through" docs/privacy-and-data-flow.md \
|
|
96
|
+
"measurement consent off leaves owner execution unchanged and writes no" \
|
|
97
|
+
"measurement consent off changes owner execution and writes one"
|
|
98
|
+
expect_native_docs_drift "StopFailure immediacy" docs/operating.md \
|
|
99
|
+
"error settlement is not deferred to" "error settlement is deferred to"
|
|
100
|
+
expect_native_docs_drift "immutable start binding" docs/operating.md \
|
|
101
|
+
"project identity and lease are immutable" "project identity and lease may be rebound"
|
|
102
|
+
expect_native_docs_drift "master-off installation" docs/operating.md \
|
|
103
|
+
"install and invoke no capability hook or plugin" "install and invoke a capability hook or plugin"
|
|
104
|
+
expect_native_docs_drift "evidence scope" docs/operating.md \
|
|
105
|
+
"They are not" "They are"
|
|
106
|
+
|
|
107
|
+
echo "[native-capability-docs-self-test] OK: focused drift cases are rejected"
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
native_file_text() {
|
|
111
|
+
awk '{$1=$1; printf "%s ", $0}' "$1"
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
native_section_text() {
|
|
115
|
+
local file="$1" start="$2" end="$3"
|
|
116
|
+
awk -v start="$start" -v end="$end" '
|
|
117
|
+
index($0, start) { active = 1 }
|
|
118
|
+
active && index($0, end) && !index($0, start) { exit }
|
|
119
|
+
active { $1=$1; printf "%s ", $0 }
|
|
120
|
+
' "$file"
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
require_native_term() {
|
|
124
|
+
local text="$1" term="$2" label="$3"
|
|
125
|
+
case "$text" in
|
|
126
|
+
*"$term"*) return 0 ;;
|
|
127
|
+
*) echo "FATAL: native capability parity term is missing: $label" >&2; return 1 ;;
|
|
128
|
+
esac
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
reject_native_term() {
|
|
132
|
+
local text="$1" term="$2" label="$3"
|
|
133
|
+
case "$text" in
|
|
134
|
+
*"$term"*) echo "FATAL: retired native capability wording remains: $label" >&2; return 1 ;;
|
|
135
|
+
*) return 0 ;;
|
|
136
|
+
esac
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
check_native_capability_docs() {
|
|
140
|
+
local root="${1:-.}" failed=0
|
|
141
|
+
local operating privacy storage harness store claude_start claude_finish opencode_plugin claude_sync opencode_sync
|
|
142
|
+
local operating_contract privacy_contract storage_contract file
|
|
143
|
+
|
|
144
|
+
operating="$root/docs/operating.md"
|
|
145
|
+
privacy="$root/docs/privacy-and-data-flow.md"
|
|
146
|
+
storage="$root/docs/storage.md"
|
|
147
|
+
harness="$root/mcp-memory-server/src/capability-harness.ts"
|
|
148
|
+
store="$root/mcp-memory-server/src/capability-store.ts"
|
|
149
|
+
claude_start="$root/claude/capability-contract/hooks/capability-command-start.sh"
|
|
150
|
+
claude_finish="$root/claude/capability-contract/hooks/capability-command-finish.sh"
|
|
151
|
+
opencode_plugin="$root/opencode/capability-contract/plugins/capability-command.ts"
|
|
152
|
+
claude_sync="$root/scripts/sync-claude-assets.sh"
|
|
153
|
+
opencode_sync="$root/scripts/sync-opencode-plugin-assets.sh"
|
|
154
|
+
|
|
155
|
+
for file in "$operating" "$privacy" "$storage" "$harness" "$store" \
|
|
156
|
+
"$claude_start" "$claude_finish" "$opencode_plugin" "$claude_sync" "$opencode_sync"; do
|
|
157
|
+
if [[ ! -f "$file" ]]; then
|
|
158
|
+
echo "FATAL: native capability parity input is missing: ${file#"$root"/}" >&2
|
|
159
|
+
failed=1
|
|
160
|
+
fi
|
|
161
|
+
done
|
|
162
|
+
[[ "$failed" -eq 0 ]] || return "$failed"
|
|
163
|
+
|
|
164
|
+
operating_contract=$(native_section_text "$operating" "### Managed capability contract" "### Typed memory nodes")
|
|
165
|
+
privacy_contract=$(native_section_text "$privacy" "## Capability callback flow" "## Hindsight note distillation")
|
|
166
|
+
storage_contract=$(native_section_text "$storage" "## Capability callback storage" "## Artifact storage")
|
|
167
|
+
|
|
168
|
+
while IFS='|' read -r term label; do
|
|
169
|
+
[[ -n "$term" ]] || continue
|
|
170
|
+
require_native_term "$operating_contract" "$term" "$label" || failed=1
|
|
171
|
+
done <<'EOF'
|
|
172
|
+
Master off is exact legacy behavior|master-off exact legacy behavior
|
|
173
|
+
install and invoke no capability hook or plugin|master-off native owner absence
|
|
174
|
+
no capability block|master-off block absence
|
|
175
|
+
create no capability measurement state|master-off measurement-state absence
|
|
176
|
+
`capability-overlay` mode|overlay-only installation
|
|
177
|
+
UserPromptExpansion|Claude pre-expansion admission
|
|
178
|
+
project identity and lease are immutable|immutable start-time project binding
|
|
179
|
+
StopFailure|Claude error terminal
|
|
180
|
+
error settlement is not deferred to|immediate StopFailure settlement
|
|
181
|
+
abandonment cleanup only for unfinished|unfinished-only cleanup
|
|
182
|
+
OpenCode 1.17.20|pinned OpenCode lifecycle
|
|
183
|
+
`session.error` settles error|OpenCode error settlement
|
|
184
|
+
all three consents are on|three-consent disabled final
|
|
185
|
+
either measurement consent is off, it blocks with no state|disabled unmeasured block
|
|
186
|
+
target enabled, either measurement consent being off preserves owner execution unchanged|enabled unmeasured pass-through
|
|
187
|
+
Deterministic native-boundary tests|deterministic evidence label
|
|
188
|
+
not exhaustive live real-owner evidence|non-exhaustive evidence label
|
|
189
|
+
complete live eight-by-seven matrix|mandatory live matrix
|
|
190
|
+
56 genuine owner executions|live matrix cell count
|
|
191
|
+
Any missing, failed, or unavailable cell keeps Phase 18 incomplete|blocking live acceptance
|
|
192
|
+
`wiki-ingest`, `wiki-query`, `wiki-lint`, `graphify`, and `security-audit`|five operating command surfaces
|
|
193
|
+
D-10, D-12, and D-16|preserved owner decisions
|
|
194
|
+
EOF
|
|
195
|
+
|
|
196
|
+
while IFS='|' read -r term label; do
|
|
197
|
+
[[ -n "$term" ]] || continue
|
|
198
|
+
require_native_term "$privacy_contract" "$term" "$label" || failed=1
|
|
199
|
+
done <<'EOF'
|
|
200
|
+
three-state privacy contract|three-state privacy declaration
|
|
201
|
+
installs or invokes no capability hook/plugin|master-off owner absence
|
|
202
|
+
creates no pending lease, callback final, or other capability measurement state|master-off state absence
|
|
203
|
+
target disabled, the fixed block always occurs before owner I/O|disabled pre-owner block
|
|
204
|
+
When all three consents are enabled|all-three-consents requirement
|
|
205
|
+
exactly one D-25/D-26 value-free `disabled` final|value-free disabled final
|
|
206
|
+
same fixed block remains in force and no pending or final state is written|disabled unmeasured no-state branch
|
|
207
|
+
target enabled, turning either measurement consent off leaves owner execution unchanged and writes no pending or final state|enabled unmeasured pass-through
|
|
208
|
+
EOF
|
|
209
|
+
|
|
210
|
+
while IFS='|' read -r term label; do
|
|
211
|
+
[[ -n "$term" ]] || continue
|
|
212
|
+
require_native_term "$storage_contract" "$term" "$label" || failed=1
|
|
213
|
+
done <<'EOF'
|
|
214
|
+
No capability state exists in exact legacy master-off operation|master-off storage absence
|
|
215
|
+
target-enabled invocation creates no lease or final when either measurement consent is off|enabled unmeasured storage absence
|
|
216
|
+
target-disabled invocation still blocks before owner I/O|disabled policy storage branch
|
|
217
|
+
Only all three consents may create the recoverable lease|all-three-consents lease issuance
|
|
218
|
+
exactly one value-free `disabled` final|disabled final storage shape
|
|
219
|
+
settlement is atomic and idempotent|atomic idempotent settlement
|
|
220
|
+
cleanup consume only unfinished leases as abandonment|unfinished-only abandonment
|
|
221
|
+
never replace a settled terminal|terminal immutability
|
|
222
|
+
EOF
|
|
223
|
+
|
|
224
|
+
for term in "prompt wrapper" "prompt owner" "command wrapper" "workflow wrapper"; do
|
|
225
|
+
reject_native_term "$operating_contract" "$term" "$term" || failed=1
|
|
226
|
+
reject_native_term "$privacy_contract" "$term" "$term" || failed=1
|
|
227
|
+
reject_native_term "$storage_contract" "$term" "$term" || failed=1
|
|
228
|
+
done
|
|
229
|
+
reject_native_term "$operating_contract" "They are exhaustive live real-owner evidence" \
|
|
230
|
+
"deterministic evidence presented as exhaustive" || failed=1
|
|
231
|
+
|
|
232
|
+
while IFS='|' read -r file term label; do
|
|
233
|
+
[[ -n "$file" ]] || continue
|
|
234
|
+
require_native_term "$(native_file_text "$file")" "$term" "$label" || failed=1
|
|
235
|
+
done <<EOF
|
|
236
|
+
$harness|if (!isCapabilityContractEnabled()) return ALLOW;|runtime master-off bypass
|
|
237
|
+
$harness|const measured = snapshot.logging.enabled && isTrajectoryCaptureEnabled();|runtime measurement consent
|
|
238
|
+
$harness|if (!measured) return BLOCK;|runtime disabled unmeasured block
|
|
239
|
+
$harness|if (!measured) return ALLOW;|runtime enabled unmeasured pass-through
|
|
240
|
+
$harness|canonicalProjectBinding|runtime project binding
|
|
241
|
+
$harness|settleLease|runtime recoverable settlement
|
|
242
|
+
$store|CAPABILITY_CALLBACK_PENDING_PREFIX|pending issuance namespace
|
|
243
|
+
$store|inImmediateTransaction|atomic callback transaction
|
|
244
|
+
$store|sameIssuance|issued handle matching
|
|
245
|
+
$claude_start|UserPromptExpansion|Claude start event
|
|
246
|
+
$claude_start|FIXED_BLOCK|Claude fixed disabled block
|
|
247
|
+
$claude_finish|StopFailure|Claude immediate error event
|
|
248
|
+
$claude_finish|SessionEnd|Claude abandonment event
|
|
249
|
+
$opencode_plugin|version: "1.17.20"|OpenCode version pin
|
|
250
|
+
$opencode_plugin|admissionHook: "command.execute.before"|OpenCode admission hook
|
|
251
|
+
$opencode_plugin|error_terminal: "session.error"|OpenCode error terminal
|
|
252
|
+
$opencode_plugin|abandonment_only: "session.deleted"|OpenCode abandonment event
|
|
253
|
+
$claude_sync|CAPABILITY_OVERLAY_ACTIVE|Claude overlay installation gate
|
|
254
|
+
$opencode_sync|CAPABILITY_OVERLAY|OpenCode overlay installation gate
|
|
255
|
+
EOF
|
|
256
|
+
|
|
257
|
+
[[ "$failed" -eq 0 ]] && echo "[native-capability-docs] OK: lifecycle, consent, storage, overlays, owners, and evidence scope match native runtime"
|
|
258
|
+
return "$failed"
|
|
259
|
+
}
|
|
260
|
+
|
|
37
261
|
# check_env_keys(): comm -23 of sorted code-keys vs sorted doc-keys --
|
|
38
262
|
# code-keys-not-in-docs only (one-directional, per D-10).
|
|
39
263
|
check_env_keys() {
|
|
40
264
|
local code_keys doc_keys missing
|
|
41
265
|
|
|
42
|
-
code_keys=$(grep -ohE "\\b${ENV_KEY_PATTERN}\\b" mcp-memory-server/src/*.ts | sort -u)
|
|
266
|
+
code_keys=$(grep -ohE "\\b${ENV_KEY_PATTERN}\\b" mcp-memory-server/src/*.ts | grep -v '^CAIRN_TEST_' | sort -u)
|
|
43
267
|
doc_keys=$(grep -ohE "\\b${ENV_KEY_PATTERN}\\b" docs/operating.md README.md | sort -u)
|
|
44
268
|
|
|
45
269
|
missing=$(comm -23 <(printf '%s\n' "$code_keys") <(printf '%s\n' "$doc_keys"))
|
|
@@ -83,7 +307,304 @@ check_commands() {
|
|
|
83
307
|
return 0
|
|
84
308
|
}
|
|
85
309
|
|
|
310
|
+
check_typed_contract() {
|
|
311
|
+
local failed=0 term files
|
|
312
|
+
while IFS='|' read -r term files; do
|
|
313
|
+
[[ -n "$term" ]] || continue
|
|
314
|
+
if ! grep -qF "$term" $files; then
|
|
315
|
+
echo "FATAL: typed-memory public term '$term' is missing from $files" >&2
|
|
316
|
+
failed=1
|
|
317
|
+
fi
|
|
318
|
+
done <<'EOF'
|
|
319
|
+
CAIRN_TYPED_MEMORY_NODES|README.md docs/operating.md
|
|
320
|
+
memory_import|README.md docs/operating.md docs/privacy-and-data-flow.md
|
|
321
|
+
address_space|README.md docs/operating.md docs/privacy-and-data-flow.md
|
|
322
|
+
node_types|README.md docs/operating.md
|
|
323
|
+
tags_all|README.md docs/operating.md
|
|
324
|
+
tags_any|README.md docs/operating.md
|
|
325
|
+
schemas/memory-node.schema.json|docs/storage.md
|
|
326
|
+
cairn_node_metadata_v1|docs/storage.md
|
|
327
|
+
cairn_node_import_replays_v1|docs/storage.md
|
|
328
|
+
prepared|docs/storage.md docs/privacy-and-data-flow.md
|
|
329
|
+
committing|docs/storage.md docs/privacy-and-data-flow.md
|
|
330
|
+
committed-before-cleanup|docs/storage.md docs/privacy-and-data-flow.md
|
|
331
|
+
EOF
|
|
332
|
+
[[ "$failed" -eq 0 ]] && echo "[typed-contract] OK: typed memory, import, and recovery terms are documented"
|
|
333
|
+
return "$failed"
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
check_artifact_contract() {
|
|
337
|
+
local failed=0 key value source_term
|
|
338
|
+
|
|
339
|
+
while IFS='|' read -r key value source_term; do
|
|
340
|
+
[[ -n "$key" ]] || continue
|
|
341
|
+
grep -qF "$key" mcp-memory-server/src/artifact-schema.ts || {
|
|
342
|
+
echo "FATAL: artifact env key '$key' is missing from source" >&2
|
|
343
|
+
failed=1
|
|
344
|
+
}
|
|
345
|
+
grep -qF "$source_term" mcp-memory-server/src/artifact-schema.ts || {
|
|
346
|
+
echo "FATAL: artifact default '$key=$value' is missing from source" >&2
|
|
347
|
+
failed=1
|
|
348
|
+
}
|
|
349
|
+
grep -qxF "# $key=$value" templates/env.example.template || {
|
|
350
|
+
echo "FATAL: artifact default '$key=$value' is missing from env.example" >&2
|
|
351
|
+
failed=1
|
|
352
|
+
}
|
|
353
|
+
grep -qF "$key" README.md docs/operating.md || {
|
|
354
|
+
echo "FATAL: artifact env key '$key' is missing from public configuration docs" >&2
|
|
355
|
+
failed=1
|
|
356
|
+
}
|
|
357
|
+
grep -qF "$value" README.md docs/operating.md || {
|
|
358
|
+
echo "FATAL: artifact default '$key=$value' is missing from public configuration docs" >&2
|
|
359
|
+
failed=1
|
|
360
|
+
}
|
|
361
|
+
done <<'EOF'
|
|
362
|
+
CAIRN_ARTIFACT_MAX_BYTES|1048576|ARTIFACT_DEFAULT_MAX_BYTES = 1024 * 1024
|
|
363
|
+
CAIRN_ARTIFACT_SESSION_MAX_BYTES|16777216|ARTIFACT_DEFAULT_SESSION_MAX_BYTES = 16 * 1024 * 1024
|
|
364
|
+
CAIRN_ARTIFACT_STORE_MAX_BYTES|268435456|ARTIFACT_DEFAULT_STORE_MAX_BYTES = 256 * 1024 * 1024
|
|
365
|
+
CAIRN_ARTIFACT_RETENTION_DAYS|30|ARTIFACT_DEFAULT_RETENTION_DAYS = 30
|
|
366
|
+
CAIRN_COMPACTION_MAX_REVISIONS|8|COMPACTION_DEFAULT_MAX_REVISIONS = 8
|
|
367
|
+
CAIRN_ARTIFACT_GENERATED_FILE_SNAPSHOT_MAX_BYTES|262144|GENERATED_FILE_MAX_SNAPSHOT_BYTES = 256 * 1024
|
|
368
|
+
EOF
|
|
369
|
+
|
|
370
|
+
for key in CAIRN_COMPACTION_CAPTURE CAIRN_ARTIFACT_STORE CAIRN_ARTIFACT_HTTP; do
|
|
371
|
+
grep -qF "$key" mcp-memory-server/src/artifact-schema.ts README.md docs/operating.md docs/privacy-and-data-flow.md || {
|
|
372
|
+
echo "FATAL: artifact feature flag '$key' is not source/docs complete" >&2
|
|
373
|
+
failed=1
|
|
374
|
+
}
|
|
375
|
+
done
|
|
376
|
+
|
|
377
|
+
for source_term in artifact_write artifact_read artifact_list artifact_delete; do
|
|
378
|
+
grep -qF "\"$source_term\"" mcp-memory-server/src/index.ts || failed=1
|
|
379
|
+
grep -qF "$source_term" README.md docs/operating.md docs/privacy-and-data-flow.md || failed=1
|
|
380
|
+
done
|
|
381
|
+
for source_term in 'list [--kind K] [--session REF] [--json]' 'show <artifact-id-or-prefix> [--json]' 'delete <artifact-id-or-prefix> [--dry-run] [--json]' 'prune [--dry-run] [--include-protected] [--json]'; do
|
|
382
|
+
grep -qF "$source_term" mcp-memory-server/src/artifact-cli.ts || failed=1
|
|
383
|
+
done
|
|
384
|
+
grep -qF '.agentfs/artifacts.db' docs/storage.md docs/privacy-and-data-flow.md || failed=1
|
|
385
|
+
grep -qF 'CAIRN_ARTIFACT_HTTP' mcp-memory-server/src/index.ts README.md docs/operating.md docs/privacy-and-data-flow.md || failed=1
|
|
386
|
+
grep -qE 'redact[^.]{0,180}(before|then)[^.]{0,180}(digest|index|write)' docs/privacy-and-data-flow.md || failed=1
|
|
387
|
+
grep -qE 'default uninstall retains|Default uninstall retains' docs/storage.md docs/privacy-and-data-flow.md || failed=1
|
|
388
|
+
grep -qF -- '--purge-memory PROJECT' docs/storage.md || failed=1
|
|
389
|
+
grep -qF 'revert.sh' docs/storage.md docs/privacy-and-data-flow.md || failed=1
|
|
390
|
+
|
|
391
|
+
for version in 2.1.219 2.1.220; do
|
|
392
|
+
grep -qF "version: \"$version\"" mcp-memory-server/src/compaction-normalize.ts || failed=1
|
|
393
|
+
grep -qF "$version" README.md docs/operating.md docs/privacy-and-data-flow.md || failed=1
|
|
394
|
+
done
|
|
395
|
+
grep -qF 'version: "1.17.20"' mcp-memory-server/src/compaction-normalize.ts || failed=1
|
|
396
|
+
grep -qF '1.17.20' README.md docs/operating.md docs/privacy-and-data-flow.md || failed=1
|
|
397
|
+
|
|
398
|
+
[[ "$failed" -eq 0 ]] && echo "[artifact-contract] OK: artifact flags/defaults/tools/paths/privacy/uninstall/version pins match source"
|
|
399
|
+
return "$failed"
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
check_artifact_remote_path_contract() {
|
|
403
|
+
local failed=0
|
|
404
|
+
local canonical_path='${CAIRN_AGENTFS_BASE_DIR}/<project-id>/.agentfs/artifacts.db'
|
|
405
|
+
|
|
406
|
+
grep -qF "$canonical_path" docs/storage.md || {
|
|
407
|
+
echo "FATAL: canonical remote artifact database path is missing from docs/storage.md" >&2
|
|
408
|
+
failed=1
|
|
409
|
+
}
|
|
410
|
+
grep -qF 'resolveRemoteArtifactProjectRoot' mcp-memory-server/src/artifact-store.ts || {
|
|
411
|
+
echo "FATAL: explicit remote artifact project-root helper is missing" >&2
|
|
412
|
+
failed=1
|
|
413
|
+
}
|
|
414
|
+
grep -qF 'resolveRemoteArtifactProjectRoot' mcp-memory-server/src/index.ts || {
|
|
415
|
+
echo "FATAL: explicit remote artifact project-root wiring is missing" >&2
|
|
416
|
+
failed=1
|
|
417
|
+
}
|
|
418
|
+
grep -qF 'getArtifactDbPath(resolveRemoteArtifactProjectRoot(baseDirectory, projectId))' mcp-memory-server/src/artifact-store.ts || {
|
|
419
|
+
echo "FATAL: remote artifact database resolver does not compose the canonical project-root helper" >&2
|
|
420
|
+
failed=1
|
|
421
|
+
}
|
|
422
|
+
grep -qF 'join("project-alpha", ".agentfs", "artifacts.db")' mcp-memory-server/scripts/smoke-artifact-mcp.mjs || {
|
|
423
|
+
echo "FATAL: HTTP smoke test does not assert the exact project-alpha artifact path" >&2
|
|
424
|
+
failed=1
|
|
425
|
+
}
|
|
426
|
+
grep -qF 'join("project-beta", ".agentfs", "artifacts.db")' mcp-memory-server/scripts/smoke-artifact-mcp.mjs || {
|
|
427
|
+
echo "FATAL: HTTP smoke test does not assert the exact project-beta artifact path" >&2
|
|
428
|
+
failed=1
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
[[ "$failed" -eq 0 ]] && echo "[artifact-remote-path] OK: source, HTTP behavior, and storage docs share the canonical path"
|
|
432
|
+
return "$failed"
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
check_capability_contract() {
|
|
436
|
+
local failed=0 file id env tool term source_file docs_files
|
|
437
|
+
|
|
438
|
+
for file in \
|
|
439
|
+
mcp-memory-server/src/capability-schema.ts \
|
|
440
|
+
mcp-memory-server/src/capability-registry.ts \
|
|
441
|
+
mcp-memory-server/src/capability-config.ts \
|
|
442
|
+
mcp-memory-server/src/capability-cli.ts \
|
|
443
|
+
mcp-memory-server/src/capability-store.ts \
|
|
444
|
+
mcp-memory-server/src/capability-adapter.ts \
|
|
445
|
+
schemas/capability-callback.schema.json \
|
|
446
|
+
docs/operating.md docs/storage.md docs/privacy-and-data-flow.md README.md; do
|
|
447
|
+
if [[ ! -f "$file" ]]; then
|
|
448
|
+
echo "FATAL: capability parity input is missing: $file" >&2
|
|
449
|
+
failed=1
|
|
450
|
+
fi
|
|
451
|
+
done
|
|
452
|
+
[[ "$failed" -eq 0 ]] || return "$failed"
|
|
453
|
+
|
|
454
|
+
while IFS='|' read -r id env; do
|
|
455
|
+
grep -qF "\"$id\"" mcp-memory-server/src/capability-schema.ts || {
|
|
456
|
+
echo "FATAL: canonical capability ID is missing from source: $id" >&2
|
|
457
|
+
failed=1
|
|
458
|
+
}
|
|
459
|
+
grep -qF "$id" README.md docs/operating.md || {
|
|
460
|
+
echo "FATAL: canonical capability ID is undocumented: $id" >&2
|
|
461
|
+
failed=1
|
|
462
|
+
}
|
|
463
|
+
grep -qF "$env" README.md docs/operating.md templates/env.example.template || {
|
|
464
|
+
echo "FATAL: capability environment key is not source/docs complete: $env" >&2
|
|
465
|
+
failed=1
|
|
466
|
+
}
|
|
467
|
+
done <<'EOF'
|
|
468
|
+
memory.write|CAIRN_CAPABILITY_MEMORY_WRITE
|
|
469
|
+
memory.search|CAIRN_CAPABILITY_MEMORY_SEARCH
|
|
470
|
+
notes.distill|CAIRN_CAPABILITY_NOTES_DISTILL
|
|
471
|
+
wiki|CAIRN_CAPABILITY_WIKI
|
|
472
|
+
graph|CAIRN_CAPABILITY_GRAPH
|
|
473
|
+
security.audit|CAIRN_CAPABILITY_SECURITY_AUDIT
|
|
474
|
+
route.check|CAIRN_CAPABILITY_ROUTE_CHECK
|
|
475
|
+
context.explore|CAIRN_CAPABILITY_CONTEXT_EXPLORE
|
|
476
|
+
EOF
|
|
477
|
+
|
|
478
|
+
for term in CAIRN_CAPABILITY_CONTRACT CAIRN_CAPABILITY_LOGGING; do
|
|
479
|
+
grep -qF "$term" mcp-memory-server/src/capability-config.ts README.md docs/operating.md templates/env.example.template || {
|
|
480
|
+
echo "FATAL: capability master/logging flag is not source/docs complete: $term" >&2
|
|
481
|
+
failed=1
|
|
482
|
+
}
|
|
483
|
+
done
|
|
484
|
+
|
|
485
|
+
while IFS='|' read -r id tool; do
|
|
486
|
+
grep -qF "\"$id\"" mcp-memory-server/src/index.ts || failed=1
|
|
487
|
+
grep -qF "\"$tool\"" mcp-memory-server/src/index.ts || failed=1
|
|
488
|
+
grep -qF "$tool" README.md docs/operating.md || {
|
|
489
|
+
echo "FATAL: omitted MCP tool is undocumented: $tool" >&2
|
|
490
|
+
failed=1
|
|
491
|
+
}
|
|
492
|
+
done <<'EOF'
|
|
493
|
+
memory.write|memory_write
|
|
494
|
+
memory.search|memory_search
|
|
495
|
+
route.check|route_check
|
|
496
|
+
context.explore|context_explore
|
|
497
|
+
EOF
|
|
498
|
+
|
|
499
|
+
while IFS='|' read -r term source_file doc_term docs_files; do
|
|
500
|
+
grep -qF "$term" "$source_file" || {
|
|
501
|
+
echo "FATAL: capability source term is missing: $term ($source_file)" >&2
|
|
502
|
+
failed=1
|
|
503
|
+
}
|
|
504
|
+
grep -qF "$doc_term" $docs_files || {
|
|
505
|
+
echo "FATAL: capability source fact is undocumented: $doc_term ($docs_files)" >&2
|
|
506
|
+
failed=1
|
|
507
|
+
}
|
|
508
|
+
done <<'EOF'
|
|
509
|
+
capability-callback/v1/record/|mcp-memory-server/src/capability-store.ts|capability-callback/v1|docs/storage.md docs/privacy-and-data-flow.md
|
|
510
|
+
capability-callback/v1/pending/|mcp-memory-server/src/capability-store.ts|capability-callback/v1/pending/|docs/storage.md docs/privacy-and-data-flow.md
|
|
511
|
+
.agentfs/trajectory.db|mcp-memory-server/src/capability-cli.ts|.agentfs/trajectory.db|docs/storage.md docs/privacy-and-data-flow.md
|
|
512
|
+
CAPABILITY_CALLBACK_RECORD_MAX_COUNT = 10_000|mcp-memory-server/src/capability-store.ts|10,000-record cap|docs/storage.md
|
|
513
|
+
getTrajectoryLimits|mcp-memory-server/src/capability-store.ts|CAIRN_TRAJECTORY_RETENTION_DAYS|docs/storage.md
|
|
514
|
+
transport !== "http"|mcp-memory-server/src/capability-adapter.ts|no remote/HTTP callback persistence|docs/privacy-and-data-flow.md
|
|
515
|
+
isTrajectoryCaptureEnabled|mcp-memory-server/src/capability-adapter.ts|CAIRN_TRAJECTORY_CAPTURE|docs/privacy-and-data-flow.md
|
|
516
|
+
configuration_digest|mcp-memory-server/src/capability-store.ts|configuration_digest|docs/operating.md docs/privacy-and-data-flow.md
|
|
517
|
+
correlation_id|mcp-memory-server/src/capability-store.ts|correlation_id|docs/privacy-and-data-flow.md
|
|
518
|
+
invocation_id|mcp-memory-server/src/capability-store.ts|invocation_id|docs/privacy-and-data-flow.md
|
|
519
|
+
duration_ms|mcp-memory-server/src/capability-store.ts|duration_ms|docs/privacy-and-data-flow.md
|
|
520
|
+
issueOperatingCapability|mcp-memory-server/src/capability-adapter.ts|durably issue|docs/privacy-and-data-flow.md
|
|
521
|
+
settleOperatingCapability|mcp-memory-server/src/capability-adapter.ts|consumed once|docs/storage.md docs/privacy-and-data-flow.md
|
|
522
|
+
isCapabilityContractEnabled()|mcp-memory-server/src/capability-adapter.ts|checked again at finish|docs/privacy-and-data-flow.md
|
|
523
|
+
const current = await resolveCapabilityStatus({ projectRoot });|mcp-memory-server/src/capability-adapter.ts|current three-consent authorization|docs/privacy-and-data-flow.md
|
|
524
|
+
current.logging.enabled|mcp-memory-server/src/capability-adapter.ts|managed logging|docs/privacy-and-data-flow.md
|
|
525
|
+
current.configuration_digest === handle.configuration_digest|mcp-memory-server/src/capability-adapter.ts|stale|docs/privacy-and-data-flow.md
|
|
526
|
+
EOF
|
|
527
|
+
|
|
528
|
+
local expected_final_fields source_final_fields public_final_fields
|
|
529
|
+
expected_final_fields=$(printf '%s\n' \
|
|
530
|
+
capability_id configuration_digest correlation_id duration_ms error_code \
|
|
531
|
+
finished_at harness invocation_id outcome schema_version source started_at \
|
|
532
|
+
state_source transport | sort)
|
|
533
|
+
source_final_fields=$(sed -n \
|
|
534
|
+
'/export const capabilityCallbackRecordSchema/,/}).superRefine/p' \
|
|
535
|
+
mcp-memory-server/src/capability-store.ts \
|
|
536
|
+
| sed -n 's/^ \([a-z_]*\):.*/\1/p' \
|
|
537
|
+
| sort)
|
|
538
|
+
public_final_fields=$(node -e '
|
|
539
|
+
const schema = require("./schemas/capability-callback.schema.json");
|
|
540
|
+
process.stdout.write(Object.keys(schema.properties).sort().join("\n"));
|
|
541
|
+
')
|
|
542
|
+
if [[ "$source_final_fields" != "$expected_final_fields" ]]; then
|
|
543
|
+
echo "FATAL: runtime final-record fields changed from the strict allow-list" >&2
|
|
544
|
+
failed=1
|
|
545
|
+
fi
|
|
546
|
+
if [[ "$public_final_fields" != "$expected_final_fields" ]]; then
|
|
547
|
+
echo "FATAL: public final-record fields changed from the strict allow-list" >&2
|
|
548
|
+
failed=1
|
|
549
|
+
fi
|
|
550
|
+
|
|
551
|
+
for term in \
|
|
552
|
+
'capabilities list' 'capabilities status' 'capabilities enable' \
|
|
553
|
+
'capabilities disable' 'capabilities reset' 'capabilities logging'; do
|
|
554
|
+
grep -qF "$term" mcp-memory-server/src/capability-cli.ts docs/operating.md || {
|
|
555
|
+
echo "FATAL: managed capability CLI operation is not source/docs complete: $term" >&2
|
|
556
|
+
failed=1
|
|
557
|
+
}
|
|
558
|
+
done
|
|
559
|
+
|
|
560
|
+
for term in \
|
|
561
|
+
'three consents' 'payload-free' 'no start record' 'fail-open' \
|
|
562
|
+
'no-payload, no-telemetry, no-network' \
|
|
563
|
+
'no telemetry' 'HTTP callbacks are never persisted' \
|
|
564
|
+
'Default uninstall retains' '--purge-memory PROJECT' 'revert.sh' \
|
|
565
|
+
'no database migration'; do
|
|
566
|
+
grep -qiF -- "$term" docs/storage.md docs/privacy-and-data-flow.md || {
|
|
567
|
+
echo "FATAL: capability privacy/storage term is missing: $term" >&2
|
|
568
|
+
failed=1
|
|
569
|
+
}
|
|
570
|
+
done
|
|
571
|
+
|
|
572
|
+
for term in 'wiki covers ingest, query, and lint' 'graph covers its command family' \
|
|
573
|
+
'audit covers its command and workflow family' 'five operating command surfaces' \
|
|
574
|
+
'Master off is exact'; do
|
|
575
|
+
grep -qiF "$term" docs/operating.md || {
|
|
576
|
+
echo "FATAL: capability operating-guard family is undocumented: $term" >&2
|
|
577
|
+
failed=1
|
|
578
|
+
}
|
|
579
|
+
done
|
|
580
|
+
|
|
581
|
+
[[ "$failed" -eq 0 ]] && echo "[capability-contract] OK: IDs, env, defaults, omissions, CLI, guards, storage, consent, and uninstall facts match source"
|
|
582
|
+
return "$failed"
|
|
583
|
+
}
|
|
584
|
+
|
|
86
585
|
main() {
|
|
586
|
+
local mode="${1:-}"
|
|
587
|
+
if [[ "$mode" == "--artifact-remote-path-only" ]]; then
|
|
588
|
+
[[ $# -eq 1 ]] || { usage >&2; exit 2; }
|
|
589
|
+
check_artifact_remote_path_contract
|
|
590
|
+
return
|
|
591
|
+
fi
|
|
592
|
+
if [[ "$mode" == "--expect-red-artifact-remote-path" ]]; then
|
|
593
|
+
[[ $# -eq 1 ]] || { usage >&2; exit 2; }
|
|
594
|
+
main
|
|
595
|
+
if check_artifact_remote_path_contract; then
|
|
596
|
+
echo "FATAL: artifact remote path documentation unexpectedly matches source" >&2
|
|
597
|
+
exit 1
|
|
598
|
+
fi
|
|
599
|
+
echo "$ARTIFACT_REMOTE_PATH_RED_MARKER"
|
|
600
|
+
exit "$EXPECTED_RED_EXIT"
|
|
601
|
+
fi
|
|
602
|
+
if [[ "$mode" == "--self-test-native-capability-docs" ]]; then
|
|
603
|
+
[[ $# -eq 1 ]] || { usage >&2; exit 2; }
|
|
604
|
+
run_native_capability_docs_self_test
|
|
605
|
+
return
|
|
606
|
+
fi
|
|
607
|
+
|
|
87
608
|
while [[ $# -gt 0 ]]; do
|
|
88
609
|
case "$1" in
|
|
89
610
|
-h|--help)
|
|
@@ -100,6 +621,11 @@ main() {
|
|
|
100
621
|
local failed=0
|
|
101
622
|
check_env_keys || failed=1
|
|
102
623
|
check_commands || failed=1
|
|
624
|
+
check_typed_contract || failed=1
|
|
625
|
+
check_artifact_contract || failed=1
|
|
626
|
+
check_artifact_remote_path_contract || failed=1
|
|
627
|
+
check_capability_contract || failed=1
|
|
628
|
+
check_native_capability_docs || failed=1
|
|
103
629
|
|
|
104
630
|
if [[ "$failed" -ne 0 ]]; then
|
|
105
631
|
echo "FATAL: docs-parity check found drift (see above) -- SC-02 not yet satisfied" >&2
|