@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.
Files changed (125) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/README.md +221 -6
  3. package/bin/cairn +43 -2
  4. package/claude/capability-contract/hooks/capability-command-finish.sh +81 -0
  5. package/claude/capability-contract/hooks/capability-command-start.sh +76 -0
  6. package/claude/hooks/compaction-capture.sh +34 -0
  7. package/claude/hooks/memory-capture.sh +47 -5
  8. package/claude/hooks/memory-wakeup.sh +55 -2
  9. package/docs/building-an-overlay.md +1 -1
  10. package/docs/design/meta-agent.md +439 -0
  11. package/docs/learning/lessons/L00-why-cairnkeep.md +1 -1
  12. package/docs/learning/lessons/L01-safe-trial.md +3 -3
  13. package/docs/learning/lessons/L02-installation.md +2 -2
  14. package/docs/learning/lessons/L03-first-project.md +1 -1
  15. package/docs/operating.md +531 -4
  16. package/docs/privacy-and-data-flow.md +417 -0
  17. package/docs/storage.md +252 -0
  18. package/examples/eval/README.md +42 -0
  19. package/examples/eval/adapter.json +12 -0
  20. package/examples/eval/bundled-fake.json +1 -0
  21. package/examples/eval/task-set.json +1 -0
  22. package/mcp-memory-server/dist/artifact-cli.js +184 -0
  23. package/mcp-memory-server/dist/artifact-schema.js +218 -0
  24. package/mcp-memory-server/dist/artifact-store.js +812 -0
  25. package/mcp-memory-server/dist/capability-adapter.js +286 -0
  26. package/mcp-memory-server/dist/capability-cli.js +361 -0
  27. package/mcp-memory-server/dist/capability-config.js +310 -0
  28. package/mcp-memory-server/dist/capability-harness.js +496 -0
  29. package/mcp-memory-server/dist/capability-registry.js +123 -0
  30. package/mcp-memory-server/dist/capability-schema.js +65 -0
  31. package/mcp-memory-server/dist/capability-store.js +431 -0
  32. package/mcp-memory-server/dist/compaction-normalize.js +267 -0
  33. package/mcp-memory-server/dist/eval-cli.js +523 -0
  34. package/mcp-memory-server/dist/eval-plan.js +346 -0
  35. package/mcp-memory-server/dist/eval-process.js +273 -0
  36. package/mcp-memory-server/dist/eval-report.js +609 -0
  37. package/mcp-memory-server/dist/eval-runner.js +827 -0
  38. package/mcp-memory-server/dist/eval-schema.js +368 -0
  39. package/mcp-memory-server/dist/eval-statistics.js +161 -0
  40. package/mcp-memory-server/dist/eval-workspace.js +313 -0
  41. package/mcp-memory-server/dist/failure-signature.js +141 -0
  42. package/mcp-memory-server/dist/index.js +600 -55
  43. package/mcp-memory-server/dist/node-cli.js +84 -0
  44. package/mcp-memory-server/dist/node-schema.js +170 -0
  45. package/mcp-memory-server/dist/node-store.js +455 -0
  46. package/mcp-memory-server/dist/note-cli.js +235 -0
  47. package/mcp-memory-server/dist/note-distiller.js +177 -0
  48. package/mcp-memory-server/dist/note-enrichment.js +93 -0
  49. package/mcp-memory-server/dist/note-schema.js +4 -0
  50. package/mcp-memory-server/dist/note-store.js +985 -0
  51. package/mcp-memory-server/dist/trajectory-cli.js +141 -0
  52. package/mcp-memory-server/dist/trajectory-normalize.js +448 -0
  53. package/mcp-memory-server/dist/trajectory-redaction.js +155 -0
  54. package/mcp-memory-server/dist/trajectory-schema.js +73 -0
  55. package/mcp-memory-server/dist/trajectory-store.js +339 -0
  56. package/mcp-memory-server/package.json +24 -2
  57. package/mcp-memory-server/scripts/fixtures/compaction-claude-code-2.1.219.json +9 -0
  58. package/mcp-memory-server/scripts/fixtures/compaction-claude-code-2.1.220.json +9 -0
  59. package/mcp-memory-server/scripts/fixtures/compaction-opencode-1.17.20-event.json +6 -0
  60. package/mcp-memory-server/scripts/fixtures/compaction-opencode-1.17.20-messages.json +119 -0
  61. package/mcp-memory-server/scripts/fixtures/compaction-unknown-version.json +17 -0
  62. package/opencode/capability-contract/plugins/capability-command.ts +319 -0
  63. package/opencode/command/graphify.md +25 -14
  64. package/opencode/plugins/memory-capture.ts +76 -10
  65. package/opencode/plugins/memory-wakeup.ts +58 -6
  66. package/package.json +8 -4
  67. package/pi/extensions/cairnkeep-trajectory.ts +55 -0
  68. package/schemas/artifact.schema.json +133 -0
  69. package/schemas/capability-callback.schema.json +68 -0
  70. package/schemas/capability-contract.schema.json +126 -0
  71. package/schemas/eval-adapter.schema.json +43 -0
  72. package/schemas/eval-protocol.schema.json +114 -0
  73. package/schemas/eval-report.schema.json +423 -0
  74. package/schemas/eval-task-set.schema.json +114 -0
  75. package/schemas/memory-node.schema.json +90 -0
  76. package/schemas/note.schema.json +112 -0
  77. package/schemas/trajectory-redaction.schema.json +25 -0
  78. package/schemas/trajectory.schema.json +82 -0
  79. package/scripts/bootstrap.sh +4 -0
  80. package/scripts/completion.sh +119 -5
  81. package/scripts/doctor.sh +284 -0
  82. package/scripts/fake-eval-adapter.mjs +120 -0
  83. package/scripts/fixtures/capability-harness-contracts.json +408 -0
  84. package/scripts/install-audit-timer.sh +3 -1
  85. package/scripts/lib/capability-opencode-plugin-harness.mjs +291 -0
  86. package/scripts/lib/trajectory-opencode-plugin-harness.mjs +25 -0
  87. package/scripts/lib/trajectory-pi-extension-harness.mjs +42 -0
  88. package/scripts/memory-wiki-audit.sh +49 -0
  89. package/scripts/smoke-bash32.sh +9 -0
  90. package/scripts/sync-claude-assets.sh +99 -6
  91. package/scripts/sync-opencode-graphify-assets.sh +24 -3
  92. package/scripts/sync-opencode-plugin-assets.sh +31 -5
  93. package/scripts/sync-opencode-security-assets.sh +24 -3
  94. package/scripts/sync-opencode-wiki-assets.sh +24 -3
  95. package/scripts/sync-pi-assets.sh +72 -0
  96. package/scripts/test-audit-timer.sh +98 -0
  97. package/scripts/test-bootstrap-untracked.sh +48 -0
  98. package/scripts/test-cli-dispatch.sh +41 -2
  99. package/scripts/test-compaction-hooks.sh +495 -0
  100. package/scripts/test-completion.sh +77 -0
  101. package/scripts/test-doctor.sh +348 -1
  102. package/scripts/test-eval-cli.sh +175 -0
  103. package/scripts/test-launcher-hooks.sh +602 -3
  104. package/scripts/test-notes-cli.sh +114 -0
  105. package/scripts/test-package-install.sh +251 -0
  106. package/scripts/test-phase16-node-lifecycle.sh +50 -0
  107. package/scripts/test-phase17-artifact-lifecycle.sh +370 -0
  108. package/scripts/test-phase18-capability-lifecycle.sh +504 -0
  109. package/scripts/test-phase18-harness-boundary.sh +1060 -0
  110. package/scripts/test-phase19-eval-lifecycle.sh +1015 -0
  111. package/scripts/test-trajectory-cli.sh +87 -0
  112. package/scripts/test-trajectory-hooks.sh +142 -0
  113. package/scripts/test-uninstall.sh +231 -5
  114. package/scripts/uninstall.sh +37 -5
  115. package/scripts/verify-dependency-security.mjs +121 -0
  116. package/scripts/verify-docs-parity.sh +527 -1
  117. package/scripts/verify-phase18-runtime-evidence.mjs +895 -0
  118. package/scripts/verify-phase19-runtime-evidence.mjs +947 -0
  119. package/templates/capabilities.json.template +7 -0
  120. package/templates/env.example.template +51 -0
  121. package/templates/memory-wiki-audit.service.template +1 -1
  122. package/templates/start-claude.sh.template +36 -0
  123. package/templates/start-opencode.sh.template +47 -5
  124. package/templates/start-pi.sh.template +30 -0
  125. package/templates/trajectory-redaction.json.template +4 -0
@@ -14,15 +14,31 @@
14
14
  set -euo pipefail
15
15
 
16
16
  repo="$(pwd)"
17
- [ -f "$repo/.agentfs/project.db" ] || exit 0
17
+
18
+ trajectory_enabled=0
19
+ case "${CAIRN_TRAJECTORY_CAPTURE:-}" in
20
+ 1|true|TRUE|yes|YES|on|ON) trajectory_enabled=1 ;;
21
+ esac
22
+
23
+ # Preserve the original disabled path: outside a bootstrapped repository the
24
+ # hook exits before reading stdin or starting a process.
25
+ if [ "$trajectory_enabled" -eq 0 ]; then
26
+ [ -f "$repo/.agentfs/project.db" ] || exit 0
27
+ fi
18
28
 
19
29
  INFRA_ROOT="@@INFRA_ROOT@@"
20
30
  SERVER_ENTRY="$INFRA_ROOT/mcp-memory-server/dist/index.js"
31
+ TRAJECTORY_ENTRY="$INFRA_ROOT/mcp-memory-server/dist/trajectory-cli.js"
21
32
  TEXT_HELPER="$INFRA_ROOT/scripts/transcript-to-text.mjs"
22
- [ -f "$SERVER_ENTRY" ] || exit 0
23
- [ -z "${CAIRN_LLM_API_KEY:-}" ] && exit 0
24
- EXTRACT_MODEL="${CAIRN_LLM_EXTRACTION_MODEL:-}"
25
- [ -z "$EXTRACT_MODEL" ] && exit 0
33
+
34
+ # Keep every pre-existing no-model guard ahead of stdin parsing when trajectory
35
+ # capture is disabled.
36
+ if [ "$trajectory_enabled" -eq 0 ]; then
37
+ [ -f "$SERVER_ENTRY" ] || exit 0
38
+ [ -z "${CAIRN_LLM_API_KEY:-}" ] && exit 0
39
+ EXTRACT_MODEL="${CAIRN_LLM_EXTRACTION_MODEL:-}"
40
+ [ -z "$EXTRACT_MODEL" ] && exit 0
41
+ fi
26
42
 
27
43
  # Read hook JSON from stdin; pull transcript_path (fail-open if absent/malformed).
28
44
  input="$(cat)"
@@ -32,6 +48,32 @@ try:
32
48
  except Exception: print("")' 2>/dev/null || true)"
33
49
  [ -n "$transcript_path" ] && [ -f "$transcript_path" ] || exit 0
34
50
 
51
+ # Trajectory capture is local, model-free and independently bounded. The
52
+ # watchdog exists only on the opt-in path and cannot fail the SessionEnd hook.
53
+ if [ "$trajectory_enabled" -eq 1 ] && [ -f "$TRAJECTORY_ENTRY" ]; then
54
+ node "$TRAJECTORY_ENTRY" capture-claude "$transcript_path" "$repo" >/dev/null 2>&1 &
55
+ trajectory_pid=$!
56
+ (
57
+ sleep 3
58
+ kill -KILL "$trajectory_pid" >/dev/null 2>&1 || true
59
+ ) &
60
+ trajectory_watchdog_pid=$!
61
+ wait "$trajectory_pid" >/dev/null 2>&1 || true
62
+ kill "$trajectory_watchdog_pid" >/dev/null 2>&1 || true
63
+ wait "$trajectory_watchdog_pid" >/dev/null 2>&1 || true
64
+ fi
65
+
66
+ # Durable-memory extraction remains independently gated by the pre-existing
67
+ # project/model requirements. The disabled path passed these checks before
68
+ # stdin parsing above; the enabled path reaches them only after local capture.
69
+ if [ "$trajectory_enabled" -eq 1 ]; then
70
+ [ -f "$repo/.agentfs/project.db" ] || exit 0
71
+ [ -f "$SERVER_ENTRY" ] || exit 0
72
+ [ -z "${CAIRN_LLM_API_KEY:-}" ] && exit 0
73
+ EXTRACT_MODEL="${CAIRN_LLM_EXTRACTION_MODEL:-}"
74
+ [ -z "$EXTRACT_MODEL" ] && exit 0
75
+ fi
76
+
35
77
  # Convert transcript JSONL → readable text, then extract candidates.
36
78
  text="$(node "$TEXT_HELPER" "$transcript_path" 2>/dev/null || true)"
37
79
  [ -n "$text" ] || exit 0
@@ -6,7 +6,33 @@
6
6
  set -euo pipefail
7
7
 
8
8
  repo="$(pwd)"
9
- [ -f "$repo/.agentfs/project.db" ] || [ -f "$repo/.planning/wiki/index.md" ] || exit 0
9
+
10
+ compaction_enabled=0
11
+ case "${CAIRN_COMPACTION_CAPTURE:-}" in
12
+ 1|true|TRUE|yes|YES|on|ON) compaction_enabled=1 ;;
13
+ esac
14
+
15
+ if [ "$compaction_enabled" -eq 0 ]; then
16
+ [ -f "$repo/.agentfs/project.db" ] || [ -f "$repo/.planning/wiki/index.md" ] || exit 0
17
+ else
18
+ [ -f "$repo/.agentfs/project.db" ] || [ -f "$repo/.planning/wiki/index.md" ] \
19
+ || [ -f "$repo/.agentfs/artifacts.db" ] || exit 0
20
+ fi
21
+
22
+ session_ref=""
23
+ if [ "$compaction_enabled" -eq 1 ]; then
24
+ input="$(cat)"
25
+ session_id="$(printf '%s' "$input" | python3 -c 'import json,re,sys
26
+ try:
27
+ value=json.load(sys.stdin)
28
+ session_id=value.get("session_id", "")
29
+ source=value.get("source", "")
30
+ safe=lambda item: isinstance(item, str) and re.fullmatch(r"[A-Za-z0-9._:/-]{1,160}", item)
31
+ print(session_id if safe(session_id) and (source == "" or safe(source)) else "")
32
+ except Exception:
33
+ print("")' 2>/dev/null || true)"
34
+ [ -n "$session_id" ] && session_ref="claude-code:$session_id"
35
+ fi
10
36
 
11
37
  if [ -f "$repo/.agentfs/project.db" ]; then
12
38
  echo "## Project memory (AgentFS)"
@@ -24,7 +50,7 @@ fi
24
50
  # entries cannot both be correct and must be resolved before dependent work.
25
51
  contradictions="$repo/.planning/wiki/CONTRADICTIONS.md"
26
52
  if [ -f "$contradictions" ]; then
27
- open_hard="$(awk '/<!-- wiki:contradictions:open:start -->/{f=1;next} /<!-- wiki:contradictions:open:end -->/{f=0} f' "$contradictions" | grep -iE 'severity:[[:space:]]*hard')"
53
+ open_hard="$(awk '/<!-- wiki:contradictions:open:start -->/{f=1;next} /<!-- wiki:contradictions:open:end -->/{f=0} f' "$contradictions" | grep -iE 'severity:[[:space:]]*hard' || true)"
28
54
  if [ -n "$open_hard" ]; then
29
55
  echo
30
56
  echo "## Open HARD contradictions — resolve before dependent work"
@@ -43,3 +69,30 @@ if [ -d "$repo/.planning/memory-staging" ]; then
43
69
  echo "Run /memory-review to accept (→ AgentFS) or discard these before doing other work."
44
70
  fi
45
71
  fi
72
+
73
+ if [ "$compaction_enabled" -eq 1 ]; then
74
+ artifact_entry="@@INFRA_ROOT@@/mcp-memory-server/dist/artifact-cli.js"
75
+ if [ -f "$artifact_entry" ]; then
76
+ recovery_file="${TMPDIR:-/tmp}/cairn-compaction-recovery.$$"
77
+ if [ -n "$session_ref" ]; then
78
+ node "$artifact_entry" recover "$repo" --session-ref "$session_ref" >"$recovery_file" 2>/dev/null &
79
+ else
80
+ node "$artifact_entry" recover "$repo" >"$recovery_file" 2>/dev/null &
81
+ fi
82
+ recovery_pid=$!
83
+ (
84
+ sleep 3
85
+ kill -KILL "$recovery_pid" >/dev/null 2>&1 || true
86
+ ) &
87
+ recovery_watchdog_pid=$!
88
+ wait "$recovery_pid" >/dev/null 2>&1 || true
89
+ kill "$recovery_watchdog_pid" >/dev/null 2>&1 || true
90
+ wait "$recovery_watchdog_pid" >/dev/null 2>&1 || true
91
+ if [ -s "$recovery_file" ]; then
92
+ echo
93
+ grep -qF "## Compaction recovery" "$recovery_file" || echo "## Compaction recovery"
94
+ cat "$recovery_file"
95
+ fi
96
+ rm -f "$recovery_file"
97
+ fi
98
+ fi
@@ -33,7 +33,7 @@ by `cairn bootstrap`) run three optional hooks, each a no-op when absent:
33
33
  | Seam | When | Use it for |
34
34
  |---|---|---|
35
35
  | `.ai/pre-launch.sh` | sourced after `.env`, before launch | export a provider base URL / credentials, refresh a token, run a connectivity check, or **abort** the launch by returning non-zero |
36
- | `CAIRN_EXTRA_SETTINGS` | read just before launch | path to a settings file layered onto the harness (`--settings` for Claude Code, `--config` for OpenCode); process env still wins, so an inline value beats the file |
36
+ | `CAIRN_EXTRA_SETTINGS` | read just before launch | path to a settings file layered onto the harness (`--settings` for Claude Code, `OPENCODE_CONFIG` for OpenCode); process env still wins, so an inline value beats the file |
37
37
  | `.ai/post-exit.sh` | sourced after the harness exits | teardown; `CAIRN_EXIT_STATUS` holds the exit code |
38
38
 
39
39
  **Typical overlay launcher** — a corporate wrapper needs a non-default provider
@@ -0,0 +1,439 @@
1
+ # Meta-agent design contract
2
+
3
+ > **Design-only status.** Phase 20 ships this Markdown file only. It ships no
4
+ > executable schema, compiler, generator, controller, adapter change,
5
+ > configuration surface, command-line interface, or runtime default. Phase 18
6
+ > capability state and Phase 19 evaluation behavior described below are current
7
+ > facts. Every meta-agent control, artifact, state, and action described as a
8
+ > requirement is future work that requires separate approval.
9
+
10
+ ## Status and normative language
11
+
12
+ This document specifies a future, bounded build-test-improve configuration
13
+ loop. It does not accept input and is not an executable interface. In future
14
+ requirements, **MUST**, **MUST NOT**, **REQUIRED**, and **SHALL** are normative;
15
+ **SHOULD** and **MAY** describe constrained choices. Statements explicitly
16
+ labelled current describe accepted Phase 18 or Phase 19 behavior rather than
17
+ new behavior.
18
+
19
+ Every block labelled **Illustrative only** is fictional, secret-free, and
20
+ non-normative. Such a block is not a shipped schema and is not accepted CLI
21
+ input. It provides no default, compatibility promise, or implementation
22
+ authority.
23
+
24
+ ## Paper concept and Cairnkeep boundary
25
+
26
+ The paper's build-test-improve concept motivates a future bounded configuration
27
+ loop, but does not redefine Cairnkeep's ownership. Cairnkeep may eventually
28
+ compile an operator objective into a reviewable form, propose bounded candidate
29
+ artifacts, coordinate approved measurement, and prepare a reversible proposal.
30
+ It must not own a harness inference loop. Existing repository contracts remain
31
+ the authority over external design inspiration.
32
+
33
+ Natural-language objectives are untrusted proposal data. They never authorize
34
+ repository reads, writes, commands, network use, evaluation, or application.
35
+ Only a future compiler and deterministic validator may produce the strict,
36
+ versioned form that an operator can review, reject, or confirm. Confirmation of
37
+ that form grants no evaluation or apply authority.
38
+
39
+ ## Natural-language specification → strict form
40
+
41
+ The future form is the only reviewable control representation. Its validator
42
+ MUST reject unknown fields and MUST NOT infer, repair, or model-author any
43
+ safety-critical value. A natural-language objective remains attached as
44
+ untrusted provenance, not executable policy.
45
+
46
+ ### Required configuration fields and fail-closed rules
47
+
48
+ | Required field group | Required future content | Deterministic invalidation rule |
49
+ |---|---|---|
50
+ | Schema and specification identity | Supported schema version, unique specification ID, canonical form digest, and untrusted objective reference | Reject absent or duplicate identity, unknown fields, unsupported versions, or a digest that does not match canonical form bytes. |
51
+ | Repository scope and immutable revisions | One or more declared repository roots, each bound to an exact immutable revision | Reject an empty root set, unresolved or non-immutable revisions, duplicate aliases, or a root whose real path cannot be established. |
52
+ | Path policy | Canonical `allowed_paths` and `denied_paths`, with deny precedence and a declared symlink policy | Reject absolute or non-canonical entries, traversal, symlink escape, out-of-root resolution, overlap with ambiguous ownership, or any target denied after canonicalization. |
53
+ | Per-run execution limits | Finite positive elapsed-time and output-byte limits for every command and adapter run | Reject missing, zero, negative, non-finite, unsafe, or unbounded resources; do not assign compatibility defaults. |
54
+ | Search and campaign ceilings | Finite maximum candidates, iterations, total wall time, reported token budget, reported cost budget with currency, consecutive invalid candidates, and consecutive non-improving candidates | Reject every omitted or non-finite ceiling, incompatible cost units, or a bound that cannot be accounted from retained evidence. Exhaustion is terminal. |
55
+ | Safety policy | Explicit network, write, command, privacy, and hard-regression rules, including non-compensable gates | Reject omissions, ambiguous verbs, undeclared egress, ambient command authority, or a policy that lets metric gain compensate for a hard failure. |
56
+ | Capability baseline and candidate | All eight canonical IDs in canonical order, each with complete before/after enabled state and matching before/after configuration digests | Reject missing, extra, reordered, or duplicate IDs; partial deltas; unavailable status; or any state/digest mismatch. A Phase 18 digest is provenance, not approval. |
57
+ | Task-set separation | Separate committed exploration and held-out confirmation task-set references, each with immutable source revision and task-set digest | Reject reuse, overlap, mutable references, unresolved revisions, digest mismatch, or any path by which held-out results become generator feedback. |
58
+ | Evaluation identity and schedule | Operator-owned adapter/config IDs, exact adapter-config digest, repetitions, deterministic seeds and order, verifier identity, isolated workspace policy, and execution limits | Reject resolved secret or endpoint values, implicit ordering, incomplete schedules, mutable verifier inputs, or an adapter/config identity that changes after approval. |
59
+ | Selection policy | Primary metric, direction, minimum improvement rule, regression guards, minimum eligible pairs, interval/confidence rule, repeated-comparison policy, and sufficient evidence scope | Reject missing denominators, undefined direction, unusable interval rules, absent regression gates, or any policy able to reinterpret missing evidence as success. |
60
+ | Mutable surfaces | Exact allowed harness-owned prompt files and typed capability fields, with pre-image identities and digests | Reject a target outside repository/path policy, a non-harness-owned prompt file, free-form configuration, or a target not present in the approved candidate artifact. |
61
+ | Human authority | Explicit human approval policy for form confirmation, evaluation, apply, rollback, rejection, and cancellation | Reject combined or delegated gates, automatic application, ambiguous approvers, or a form that removes unconditional cancellation and rollback authority. |
62
+
63
+ The exact Phase 18 capability IDs, in canonical order, are:
64
+
65
+ 1. `memory.write`
66
+ 2. `memory.search`
67
+ 3. `notes.distill`
68
+ 4. `wiki`
69
+ 5. `graph`
70
+ 6. `security.audit`
71
+ 7. `route.check`
72
+ 8. `context.explore`
73
+
74
+ The current `resolveCapabilityStatus()` result supplies an effective ordered
75
+ snapshot and `configuration_digest`. Neither the status nor its digest is a
76
+ meta-agent candidate, signature, approval, or authorization.
77
+
78
+ ### Admission is fail closed
79
+
80
+ The future validator MUST reject every safety-critical omission, unknown field,
81
+ unsupported version, unresolved revision, non-finite resource, path traversal,
82
+ symlink escape, and out-of-root path. It MUST also reject stale or mismatched
83
+ digests and any value that would require an inferred default. Invalid input
84
+ cannot be made valid by prose interpretation, candidate output, prior runs, or
85
+ operator environment discovery.
86
+
87
+ Forms, proposals, and reports may carry only bounded, value-free identifiers
88
+ for operator-owned secret or adapter configuration. They MUST NOT contain
89
+ credentials, resolved secrets, endpoint values, provider defaults, complete
90
+ environment snapshots, or captured environment values. A reference says which
91
+ operator-owned configuration is expected; it never resolves or copies it.
92
+
93
+ ### Illustrative only — fictional strict form
94
+
95
+ The following is secret-free and non-normative. It is not a shipped schema and
96
+ is not accepted CLI input. Angle-bracketed values are fictional review labels,
97
+ not normative numeric defaults or accepted syntax.
98
+
99
+ ```text
100
+ specification: sample-improvement-study
101
+ schema: future-version
102
+ repositories:
103
+ - root_ref: repo-alpha
104
+ immutable_revision: revision-alpha
105
+ scope:
106
+ allowed_paths: [harness-owned/prompts]
107
+ denied_paths: [operator-settings]
108
+ limits:
109
+ maximum candidates: <operator-declared finite count>
110
+ iterations: <operator-declared finite count>
111
+ total_wall_time: <operator-declared finite duration>
112
+ reported_token_budget: <operator-declared finite amount>
113
+ evaluation:
114
+ exploration_task_set: committed-set-alpha
115
+ held_out_task_set: committed-set-beta
116
+ adapter_config_ref: operator-config-alpha
117
+ capabilities:
118
+ before_and_after: [memory.write, memory.search, notes.distill, wiki,
119
+ graph, security.audit, route.check, context.explore]
120
+ human approval policy:
121
+ form: separate
122
+ evaluation: separate
123
+ apply: separate
124
+ rollback: always available
125
+ cancellation: always available
126
+ ```
127
+
128
+ ## Bounded candidate artifact
129
+
130
+ A future candidate generator may emit only an immutable, canonically digested
131
+ artifact within the confirmed form's mutable surfaces. It may include bounded
132
+ prompt diffs and a complete typed capability before/after snapshot. It cannot
133
+ execute inference, commands, evaluation, or writes; grant itself new scope;
134
+ change any task, verifier, metric, threshold, resource bound, safety rule,
135
+ approval rule, stopping policy, or evidence history; or consult held-out
136
+ confirmation results. Generation and execution are separate authorities.
137
+
138
+ ## Ownership and authority
139
+
140
+ The operator retains every irreversible or cost-bearing authority. Cairnkeep's
141
+ future components may transform and validate bounded artifacts, but every
142
+ inference execution MUST cross the accepted Phase 19 coordinator into an
143
+ operator-configured external adapter. Candidate generation, comparison,
144
+ approval, application, confirmation policy, and rollback have no direct
145
+ inference edge.
146
+
147
+ ```text
148
+ untrusted objective
149
+ -> future form compiler/validator -> human form confirmation
150
+ -> future bounded candidate artifact -> human evaluation approval
151
+ -> Phase 19 immutable schedule
152
+ -> operator-configured external adapter -> inference execution
153
+ -> independent verifier -> canonical Phase 19 report
154
+ -> future comparison -> reviewable patch proposal -> human apply approval
155
+ -> future backup/digest/atomic applier -> held-out confirmation approval
156
+ -> Phase 19 immutable held-out schedule
157
+ -> operator-configured external adapter -> inference execution
158
+ -> independent verifier -> canonical Phase 19 report
159
+ -> accept | inconclusive | no_eligible_candidate | rollback
160
+ ```
161
+
162
+ There is no arrow from a Cairnkeep generator, selector, applier, or rollback
163
+ operation to inference. Phase 19 is the sole Cairnkeep execution and measurement
164
+ seam; the operator-configured external adapter remains the sole inference owner.
165
+
166
+ | Actor or component | May do | Must not do | Required authority |
167
+ |---|---|---|---|
168
+ | Operator | Confirm/reject form, approve/cancel evaluation, approve/reject application, accept confirmation, request rollback | Delegate mandatory gates to candidate output or ambient configuration | Separate, explicit decision at each gate |
169
+ | Future compiler/validator | Convert untrusted prose to a strict form; reject invalid fields | Execute prose, infer defaults, resolve secrets, or broaden scope | Form confirmation before admission |
170
+ | Future candidate generator | Produce bounded immutable artifacts within declared mutable surfaces | Execute inference/commands, mutate control policy, inspect held-out results, or write repositories | Confirmed form and remaining resource budget |
171
+ | Phase 18 capability contract | Resolve current ordered state and configuration digest | Select candidates, authorize changes, or represent arbitrary candidate overlays | Existing operator configuration |
172
+ | Phase 19 coordinator | Validate committed inputs, create isolated serial schedules, call the configured adapter, verify tasks, and persist canonical evidence | Own inference, generate candidates, choose a winner, apply a patch, or grant approval | Separate evaluation or confirmation approval |
173
+ | Operator-configured external adapter | Execute all inference under the approved bounded request and its operator-owned environment | Change tasks, verifier, policy, schedule, or repository state through this design | Operator configuration plus Phase 19 request |
174
+ | Future comparator | Apply the predeclared policy to canonical reports | Reclassify infrastructure errors, hide missingness, or relax thresholds after seeing results | Immutable form and validated reports |
175
+ | Future applier/rollback owner | Apply or exactly restore one approved proposal under digest guards | Infer intent, overwrite later edits, delete unrelated content, or invoke inference | Separate apply or rollback approval |
176
+
177
+ ## Candidate evaluation through Phase 19
178
+
179
+ Candidate generation first produces an immutable candidate artifact and stops.
180
+ Deterministic validation and explicit evaluation approval are required before
181
+ Phase 19. The approved evaluation freezes committed task sets, exact source
182
+ revision, independent verifier, finite limits, repetitions, seeds and order,
183
+ adapter/config identity, and fresh isolated workspaces. The adapter alone runs
184
+ inference. Comparison reads canonical JSON; it never parses arbitrary adapter
185
+ diagnostics or model output.
186
+
187
+ ### Current Phase 19 behavior versus missing future contract
188
+
189
+ | Concern | Current accepted Phase 18/19 behavior | Missing future contract; not shipped by Phase 20 |
190
+ |---|---|---|
191
+ | Capability identity | `expected_capability_digest` and `observed_capability_digest` bind the complete Phase 18 effective state. | Candidate-overlay identity and expected/observed candidate digests for arbitrary prompt/config candidates. |
192
+ | Adapter identity | `adapter_config_digest` binds the operator adapter configuration. | It is not a generated-candidate digest and grants no selection or apply authority. |
193
+ | Request surface | Phase 19 sends experiment/task identity, arm, repetition, pass, isolated paths, fixed input, limits, seed, expected capability digest, and output path. | Phase 19 has no arbitrary candidate overlay reference, injection contract, or expected candidate digest. |
194
+ | Result surface | Strict results may report bounded metrics, identities, references, and `observed_capability_digest`. | There is no observed candidate-overlay digest, and no candidate pass/approval field. |
195
+ | Ablation | `runCapabilityAblation()` compares an all-enabled baseline with exactly one disabled capability and requires four invocations per task/repetition: two passes in each of two arms. | It is not generic prompt search, arbitrary configuration injection, or a multi-capability candidate arm. |
196
+ | Scheduling | Deterministic, serial, immutable, paired schedules and fresh isolated workspaces are current. | Adaptive generation/selection and separate exploration/held-out campaign control are absent. |
197
+ | Report | Canonical reports preserve observations, aggregates, condition levels, eligible pairs, missingness, warnings, intervals, evidence scope, and provenance. | Reports do not choose winners, authorize application, or provide a proposal/rollback ledger. |
198
+
199
+ Exploration and held-out confirmation task sets MUST be separate, committed,
200
+ immutable, non-overlapping, and digest-bound. Exploration results may inform the
201
+ next bounded candidate within remaining limits. Held-out results MUST never
202
+ become generator feedback, even after rejection or rollback. A changed task,
203
+ verifier, metric, threshold, seed policy, bound, safety policy, or confirmation
204
+ set requires a new form and new approvals; it cannot be a candidate mutation.
205
+
206
+ The future comparator consumes Phase 19's exact terminal states: `completed`,
207
+ `verifier_failed`, `timeout`, `cancelled`, `adapter_error`, and
208
+ `invalid_result`; and pass states: `passed`, `failed`, and `unknown`. It also
209
+ consumes expected/observed capability digests, condition levels, eligible-pair
210
+ counts, missingness, warnings, intervals, and evidence scope. Infrastructure
211
+ states and unknown verification remain missing or ineligible evidence, never
212
+ candidate failures or passes. `offline-framework` evidence authorizes framework
213
+ mechanics only and cannot support product quality, efficiency, cost, latency,
214
+ significance, or causal claims.
215
+
216
+ ## Proposal bundle, application, and rollback
217
+
218
+ A future proposal bundle is one canonically identified, reviewable unit. Any
219
+ failed element invalidates the whole proposal; partial acceptance or partial
220
+ application is forbidden.
221
+
222
+ | Required proposal bundle element | Content | Whole-proposal invalidation |
223
+ |---|---|---|
224
+ | Canonical identity | Proposal version/ID/digest; confirmed form digest; immutable source revision; baseline and candidate artifact digests | Unknown version, non-canonical bytes, duplicate ID, unresolved revision, or any digest mismatch |
225
+ | Evidence-bound rationale | Primary metric rule, regression guards, eligible-pair counts, interval result, evidence scope, warnings, missingness, and bounded references to exact Phase 19 reports/digests | Unsupported claim, copied arbitrary diagnostics, missing report, stale digest, inadequate scope, or rationale exceeding evidence |
226
+ | Prompt change | A unified diff limited to operator-declared harness-owned prompt files, with contained canonical paths, modes, and pre/post digests | Non-declared target, symlink/out-of-root path, denied path, binary ambiguity, missing pre-image, or diff/digest mismatch |
227
+ | Typed capability change | All eight before/after rows in canonical order and their Phase 18 before/after configuration digests | Partial delta, unknown/reordered ID, unavailable status, or state/digest mismatch |
228
+ | Safety findings | Results for every non-compensable network, write, command, privacy, and hard-regression gate | Missing, unknown, failed, or waived hard gate |
229
+ | Apply preconditions | Exact revision, root/path identities, pre-image bytes/digests/modes, proposal digest, and separate apply-approval record | Stale, missing, mismatched, out-of-scope, or subsequently changed precondition |
230
+ | Rollback instructions | Backup references, original bytes/modes/digests, applied post-image digests, created-file ownership, and manual-resolution conditions | Incomplete backup, ambiguous ownership, unguarded removal, or restoration not exact |
231
+
232
+ ### Illustrative only — fictional proposal bundle
233
+
234
+ This fictional, secret-free, non-normative example is not a shipped schema and
235
+ is not accepted CLI input. It contains no credential, endpoint, provider
236
+ default, environment snapshot, or private identifier.
237
+
238
+ ```text
239
+ proposal: sample-proposal-alpha
240
+ form_digest: digest-form-alpha
241
+ source_revision: revision-alpha
242
+ candidate_digest: digest-candidate-alpha
243
+ evidence:
244
+ exploration_report_ref: report-alpha
245
+ report_digest: digest-report-alpha
246
+ prompt_change:
247
+ target: harness-owned/prompts/review.md
248
+ unified_diff_ref: reviewed-diff-alpha
249
+ pre_image_digest: digest-before-alpha
250
+ post_image_digest: digest-after-alpha
251
+ capability_delta:
252
+ snapshot: complete-eight-row-before-and-after
253
+ before_digest: digest-capabilities-before
254
+ after_digest: digest-capabilities-after
255
+ application: separate-human-approval-required
256
+ rollback: exact-backup-and-post-image-guard-required
257
+ ```
258
+
259
+ Application is default-off and needs approval distinct from form confirmation
260
+ and evaluation approval. Immediately before any write, a future applier MUST
261
+ revalidate the exact revision, real contained roots, canonical allow/deny
262
+ policy, path ownership, symlink status, pre-image bytes/modes/digests, proposal
263
+ digest, and complete capability snapshots. It MUST finish exact backups of
264
+ every pre-image before the first write, then apply the whole proposal atomically
265
+ or leave the repository unchanged. A local audit record contains only bounded,
266
+ value-free identities, paths, modes, digests, outcomes, and backup references.
267
+
268
+ Any stale, missing, mismatched, unsafe, or out-of-scope precondition invalidates
269
+ the entire proposal. No automatic rebase, fuzzy patch, best-effort subset, or
270
+ model-authored repair is allowed.
271
+
272
+ Rollback also requires explicit operator authority. Restoration may proceed
273
+ only when each current file still matches the applied post-image digest. A
274
+ proposal-created file may be removed only when it is proposal-owned and remains
275
+ byte-for-byte unchanged. Missing or later-edited files require manual
276
+ resolution. Rollback MUST NOT delete or overwrite unrelated content,
277
+ subsequently edited user files, user settings, retained evidence, or another
278
+ proposal's assets. Backup-first exact-revert and atomic write behavior in the
279
+ current project lifecycle are precedents, not a generic applier delivered here.
280
+
281
+ ## Bounded state machine and stopping policy
282
+
283
+ The future controller is a finite state machine. Every transition preserves the
284
+ confirmed form, immutable evidence history, and resource accounting. A
285
+ candidate cannot modify tasks, verifier, metrics, thresholds, bounds,
286
+ safety/approval/stopping policy, evidence scope rules, or prior evidence.
287
+
288
+ | State | Entry condition | Exit and outcome | Required evidence | Immutable while active |
289
+ |---|---|---|---|---|
290
+ | `specification` | Untrusted objective received | Reject/cancel, or submit strict form to `validation` | Objective reference only | No authority or inferred defaults |
291
+ | `validation` | Complete candidate form produced | Invalid → `rejection`; valid → human `approval`; cancel → `cancelled` | Canonical form, source/path/resource checks | Complete form and validation record |
292
+ | `candidate_proposal` | Confirmed form and remaining bounds | Invalid/non-improving ceiling → `exhausted`; valid artifact → `approval` | Candidate digest, scope checks, accounting | Control plane and evidence history |
293
+ | `approval` | A form, evaluation, patch, confirmation, or rollback action awaits a distinct decision | Approve to named next state; reject → `rejected`; cancel → `cancelled` | Exact object digest and authority type | Approval cannot cover another gate |
294
+ | `evaluation` | Explicit evaluation approval and validated Phase 19 plan | Complete → `comparison`; hard failure → `inconclusive` or `rejection`; cancel → `cancelled` | Canonical partial/final Phase 19 report | Schedule, task sets, source, adapter, verifier, seeds, limits |
295
+ | `comparison` | Canonical exploration report validated | Eligible → `patch_proposal`; insufficient evidence → `inconclusive` or `no_eligible_candidate`; budget remains → `candidate_proposal` | Terminal/pass states, digests, levels, pairs, missingness, warnings, intervals, scope | Selection and repeated-comparison policy |
296
+ | `patch_proposal` | Candidate passes exploration policy | Whole bundle valid → apply `approval`; invalid → `rejection` | Proposal identity, evidence, diff/delta, safety, preconditions, rollback | Proposal bytes and referenced evidence |
297
+ | `application` | Separate apply approval and immediate preflight passes | Atomic success → `confirmation`; preflight fail → `rejected`; ambiguous result → `manual_resolution` | Backups, pre/post digests, audit record | Approved proposal and backups |
298
+ | `confirmation` | Applied candidate and separately approved held-out schedule | Policy passes → `accepted`; inadequate evidence → `inconclusive`; regression/hard failure → `rollback` | One canonical held-out report, never generator feedback | Confirmation set and acceptance rules |
299
+ | `rollback` | Operator requests rollback or policy requires it | Exact restore → `rolled_back`; later edits/ambiguity → `manual_resolution`; cancel preserves state | Applied post-image checks and exact backups | No-clobber boundary and retained evidence |
300
+ | `rejection` | Invalid form/candidate/proposal, hard-gate failure, or explicit rejection | Terminal `rejected` | Value-free reason and retained evidence | All prior evidence |
301
+ | terminal | `accepted`, `inconclusive`, `no_eligible_candidate`, `rejected`, `cancelled`, `exhausted`, `rolled_back`, or `manual_resolution` reached | No automatic exit or restart | Final reason, resource totals, evidence/proposal references | Entire history |
302
+
303
+ ### Stopping policy and selection conditions
304
+
305
+ | Condition | Required action/outcome |
306
+ |---|---|
307
+ | All hard gates pass; no regression guard fails; candidate/capability digests match; minimum eligible pairs are met; a usable interval satisfies the predeclared metric/direction/improvement rule; evidence scope is sufficient | Candidate may proceed from exploration to patch proposal; it is not yet accepted. |
308
+ | Exactly one separately approved held-out confirmation passes the same hard gates and predeclared acceptance policy | Stop as `accepted`. Further search requires a new form. |
309
+ | No candidate has adequate eligible pairs or compatible observations | Stop as `no_eligible_candidate`; never choose from absence. |
310
+ | Evidence exists but interval, missingness, warnings, scope, or improvement rule cannot establish eligibility | Stop as `inconclusive`; never relax policy post hoc. |
311
+ | Any non-compensable hard gate or safety/privacy regression fails | Stop evaluation/application; `rejected` or approved `rollback`. Metric gain cannot compensate. |
312
+ | Maximum candidates, iterations, total wall time, reported token budget, or reported cost budget is reached | Stop as `exhausted` before next admission. Missing token/cost reporting is not zero. |
313
+ | Consecutive invalid or non-improving candidate bound is reached | Stop as `exhausted`. |
314
+ | Human rejects form, evaluation, proposal, application, confirmation, or rollback | Stop as `rejected`, preserving evidence and current repository state. |
315
+ | Cancellation requested at any state | Stop admission, bound active Phase 19 cleanup, preserve partial evidence, and terminate as `cancelled`. |
316
+ | Rollback cannot safely restore because post-images changed or ownership is ambiguous | Stop as `manual_resolution`; do not overwrite or delete. |
317
+
318
+ Only an accepted held-out confirmation produces `accepted`. Exploration alone
319
+ cannot do so. Selection remains at least as conservative as Phase 19's report
320
+ semantics: missing intervals, small samples, intervals crossing the declared
321
+ no-effect boundary, incompatible semantics, unknown verifier outcomes, and
322
+ infrastructure failures cannot name a winner.
323
+
324
+ ## Privacy and security invariants
325
+
326
+ These are requirements for any separately approved future implementation; Phase
327
+ 20 does not implement the controls. Hard privacy and safety failures are
328
+ terminal and non-compensable. Artifacts remain local, bounded, value-minimized,
329
+ and bound to immutable source and evidence. No proposal or report may persist
330
+ prompts beyond the reviewed unified diff, model output, arbitrary diagnostics,
331
+ resolved credentials, endpoint values, or complete environment state.
332
+
333
+ | Threat pattern | Required future control | Failure disposition |
334
+ |---|---|---|
335
+ | Untrusted specification escalates policy or authority | Strict allow-listed versioned form, unknown-field rejection, no inferred defaults, separate human gates | Reject form before generation or execution |
336
+ | Path, symlink, or secret escape | Canonical real-root containment, deny precedence, no-follow checks, immediate preflight, value-free secret/config references | Reject whole form/proposal; write nothing |
337
+ | Adapter or candidate digest spoofing | Independently reconstruct exact form, candidate, adapter, Phase 18 state, and future overlay digests at each boundary | Observation/proposal is invalid, not a task failure |
338
+ | Confirmation-set overfitting | Separate committed exploration and held-out task sets; no overlap; held-out results never return to generator | Reject campaign or stop confirmation |
339
+ | Safety regression masked by metric gain | Non-compensable network/write/command/privacy and regression guards before metric selection | Reject or roll back regardless of metric |
340
+ | Resource exhaustion | Finite per-run, candidate, iteration, wall-time, reported-token/cost, invalid, and non-improvement ceilings with pre-admission accounting | Cancel active bounded work and stop as `exhausted` or `cancelled` |
341
+ | Apply/rollback time-of-check/time-of-use race or partial write | Immediate revision/path/pre-image revalidation, exact backups first, atomic all-or-nothing apply, post-image-guarded rollback | Leave unchanged, roll back exactly, or require `manual_resolution` |
342
+ | Proposal, report, or audit leakage | Strict bounded fields, local permissions, value-free diagnostics/IDs, reviewed diff only, report references instead of copied runtime content | Reject sensitive artifact and retain no partial copy |
343
+ | Infrastructure error fabricated as task outcome | Preserve Phase 19 terminal/pass separation, explicit missingness and partial reports, unknown verifier outcomes | `inconclusive` or ineligible; never fabricate pass/fail/winner |
344
+
345
+ ## Prerequisites not delivered by Phases 14–19
346
+
347
+ Phases 14–19 already deliver structured local trajectories; asynchronous notes
348
+ and hindsight retrieval; typed memory nodes; compaction/artifact storage; the
349
+ eight capability IDs, toggles, digests, and value-free logs; committed strict
350
+ evaluation schemas; isolation and independent verification; two-pass and
351
+ one-off ablation execution; canonical reports, missingness, intervals,
352
+ cancellation; and `offline-framework` evidence. Those accepted substrates are
353
+ not backlog rows.
354
+
355
+ ### Future implementation backlog — not delivered by Phase 20
356
+
357
+ Each row is future work requiring separate approval. The list is exactly nine
358
+ items; Phase 20 delivers none of them.
359
+
360
+ | # | Exact absent capability | Accepted substrate it may reuse | Delivery status |
361
+ |---|---|---|---|
362
+ | 1 | Natural-language-to-form compiler and validator | Strict versioning, canonical digests, and path validation patterns | Future work requiring separate approval; not delivered by Phase 20 |
363
+ | 2 | Bounded candidate generator | Phase 18 typed capability identities and retained evidence | Future work requiring separate approval; not delivered by Phase 20 |
364
+ | 3 | Candidate-config injection contract for external adapters | Phase 19 adapter seam and Phase 18 capability digests; Phase 19 currently has no arbitrary overlay identity or observed candidate digest and supports only exactly-one-capability-off ablation | Future work requiring separate approval; not delivered by Phase 20 |
365
+ | 4 | Scoped proposal/artifact schema | Existing strict versioned local artifacts and canonical reports | Future work requiring separate approval; not delivered by Phase 20 |
366
+ | 5 | Backup-first patch applier and rollback ledger | Existing backup-first uninstall/revert and atomic single-file write precedents | Future work requiring separate approval; not delivered by Phase 20 |
367
+ | 6 | Exploration and held-out committed task sets | Current committed task-set schema, exact revisions, and verifier | Future work requiring separate approval; not delivered by Phase 20 |
368
+ | 7 | Selection policy accounting for uncertainty and repeated comparisons | Phase 19 condition levels, paired estimates, missingness, warnings, and intervals | Future work requiring separate approval; not delivered by Phase 20 |
369
+ | 8 | Sufficient live baseline evidence | Validator-checked evidence scope and exact-source runtime provenance; existing offline evidence is framework-only | Future work requiring separate approval; not delivered by Phase 20 |
370
+ | 9 | Dedicated privacy/security threat review | Current local privacy, bounded storage, secret exclusion, and public hygiene guards | Future work requiring separate approval; not delivered by Phase 20 |
371
+
372
+ ## Explicit exclusions
373
+
374
+ - No Cairnkeep orchestrator or unified orchestrator is designed or delivered.
375
+ - Cairnkeep does not own an inference loop; every inference execution remains
376
+ with an operator-configured external adapter reached through Phase 19.
377
+ - Architect-style in-loop compression is outside this design and Phase 20.
378
+ - Trace UI is outside this design and Phase 20.
379
+ - Eval UI is outside this design and Phase 20.
380
+ - Phase 20 implements no compiler, generator, selection controller, proposal
381
+ schema, patch applier, rollback ledger, candidate adapter-protocol change,
382
+ configuration schema, CLI surface, runtime default, or modification of Phase
383
+ 18 or Phase 19 contracts.
384
+ - Phase 20 adds no symbol, command, flag, package, dependency, test source,
385
+ executable interface, release, publication, or automatic product claim.
386
+
387
+ All excluded implementation work requires a new plan, threat review, approval,
388
+ tests, and evidence. Naming a future contract here does not reserve a public
389
+ interface or represent it as delivered.
390
+
391
+ ## Decision traceability
392
+
393
+ | ID | Document home | Normative trace |
394
+ |---|---|---|
395
+ | META-01 | Natural-language specification → strict form | Untrusted prose can become only a complete, versioned, fail-closed future form. |
396
+ | META-02 | Ownership; evaluation; proposal; state machine | Candidates are bounded, measured only through Phase 19/adapters, and separately approved for application. |
397
+ | META-03 | Prerequisites; explicit exclusions | Exactly nine prerequisites remain future work and prohibited ownership/UI/implementation is explicit. |
398
+ | D-01 | Natural-language specification → strict form | Natural language is untrusted proposal data, never executable control. |
399
+ | D-02 | Required configuration fields | Scope, revisions, paths, resources, safety, capabilities, tasks, evaluation, selection, mutation, and authority are required. |
400
+ | D-03 | Admission is fail closed | Omissions, unknowns, unsafe paths, unresolved revisions, non-finite resources, and inferred defaults invalidate. |
401
+ | D-04 | Admission; privacy invariants | Only value-free operator-owned references are allowed; secret/endpoint/environment values are forbidden. |
402
+ | D-05 | Status and normative language | The artifact is design-only; examples are non-normative; no schema or CLI ships. |
403
+ | D-06 | Ownership and authority | Phase 19 is the sole execution/measurement seam and the external adapter owns inference. |
404
+ | D-07 | Candidate evaluation | Source, tasks, verifier, adapter identity, schedule, limits, seeds, and digests are frozen and comparable. |
405
+ | D-08 | Candidate evaluation | Canonical terminal/pass states, condition levels, missingness, uncertainty, and evidence scope remain authoritative. |
406
+ | D-09 | Bounded candidate artifact; ownership | Candidate generation and adapter execution are separate authorities. |
407
+ | D-10 | Candidate evaluation | Exploration and held-out sets are separate; held-out results never become generator feedback. |
408
+ | D-11 | Candidate evaluation | `offline-framework` authorizes framework claims only. |
409
+ | D-12 | Proposal bundle | Canonical identity, rationale, reports, diffs/deltas, safety, preconditions, and rollback form one review unit. |
410
+ | D-13 | Proposal bundle | Unified prompt diffs are limited to operator-declared harness-owned files. |
411
+ | D-14 | Application and rollback | Apply is separately approved, immediately revalidated, backup-first, atomic, and locally audited. |
412
+ | D-15 | Proposal invalidation | Any stale, missing, mismatched, unsafe, or out-of-scope element invalidates the whole proposal. |
413
+ | D-16 | Application and rollback | Reject/apply/rollback are explicit and restoration cannot clobber unrelated or later-edited content. |
414
+ | D-17 | Bounded state machine | Every required state has entry, evidence, immutable fields, and an explicit exit/outcome. |
415
+ | D-18 | Selection and stopping | Hard gates are non-compensable and all resource/search ceilings are finite. |
416
+ | D-19 | Selection and stopping | Acceptance needs matching digests, no regression, adequate pairs, usable interval, sufficient scope, and held-out confirmation. |
417
+ | D-20 | Selection and stopping | Exhaustion, invalid/non-improving bounds, rejection, cancellation, hard failure, and confirmation all stop explicitly. |
418
+ | D-21 | Future backlog | Exactly nine missing prerequisites are enumerated once and separated from accepted Phase 14–19 substrate. |
419
+ | D-22 | Explicit exclusions | The backlog is not implementation and all ownership, compression, UI, runtime, schema, CLI, and adapter work remains excluded. |
420
+
421
+ ## References
422
+
423
+ - [Phase 18 capability schema](../../mcp-memory-server/src/capability-schema.ts)
424
+ and [configuration resolver](../../mcp-memory-server/src/capability-config.ts)
425
+ are the current capability contract of record.
426
+ - [Phase 19 evaluation schema](../../mcp-memory-server/src/eval-schema.ts),
427
+ [plan validator](../../mcp-memory-server/src/eval-plan.ts),
428
+ [runner](../../mcp-memory-server/src/eval-runner.ts), and
429
+ [report owner](../../mcp-memory-server/src/eval-report.ts) are the current
430
+ evaluation contract of record.
431
+ - Published current contracts are the
432
+ [task-set schema](../../schemas/eval-task-set.schema.json),
433
+ [adapter schema](../../schemas/eval-adapter.schema.json), and
434
+ [report schema](../../schemas/eval-report.schema.json).
435
+ - [Operating](../operating.md), [privacy and data flow](../privacy-and-data-flow.md),
436
+ and [storage](../storage.md) define the current operator, privacy, and local
437
+ lifecycle boundaries.
438
+ - The paper's §2.3.4 and §2.4 are design inspiration only. Repository source,
439
+ accepted Phase 18/19 behavior, and published schemas remain authoritative.
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Quickstart
5
5
  **Time:** 10 minutes
6
- **Tested with:** Cairnkeep 2.3.1
6
+ **Tested with:** Cairnkeep 2.4.0
7
7
 
8
8
  ## Outcome
9
9
 
@@ -3,7 +3,7 @@
3
3
  **Status:** Ready
4
4
  **Track:** Quickstart
5
5
  **Time:** 15 minutes
6
- **Tested with:** Cairnkeep 2.3.1
6
+ **Tested with:** Cairnkeep 2.4.0
7
7
 
8
8
  ## Outcome
9
9
 
@@ -26,7 +26,7 @@ ephemeral; the named course volume is persistent.
26
26
  1. Pull the public image:
27
27
 
28
28
  ```bash
29
- podman pull ghcr.io/cairnkeep/cairnkeep:2.3.1
29
+ podman pull ghcr.io/cairnkeep/cairnkeep:2.4.0
30
30
  ```
31
31
 
32
32
  2. Start the stdio server with a read-only root filesystem and no Linux
@@ -38,7 +38,7 @@ ephemeral; the named course volume is persistent.
38
38
  --read-only --cap-drop=all --security-opt=no-new-privileges \
39
39
  --tmpfs=/tmp:rw,noexec,nosuid,size=64m,mode=1777 \
40
40
  --volume cairnkeep-course-data:/data:Z,U \
41
- ghcr.io/cairnkeep/cairnkeep:2.3.1 stdio
41
+ ghcr.io/cairnkeep/cairnkeep:2.4.0 stdio
42
42
  ```
43
43
 
44
44
  3. The process waits quietly for MCP input. Press `Ctrl-C` after confirming it