@isaacriehm/cairn-core 0.14.1 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (88) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/gc/classify.js +0 -1
  3. package/dist/gc/classify.js.map +1 -1
  4. package/dist/gc/doc-gardening.d.ts +0 -14
  5. package/dist/gc/doc-gardening.js +0 -40
  6. package/dist/gc/doc-gardening.js.map +1 -1
  7. package/dist/gc/quality-update.js +7 -11
  8. package/dist/gc/quality-update.js.map +1 -1
  9. package/dist/gc/sweep.d.ts +0 -2
  10. package/dist/gc/sweep.js +1 -4
  11. package/dist/gc/sweep.js.map +1 -1
  12. package/dist/gc/walk-source.js +0 -1
  13. package/dist/gc/walk-source.js.map +1 -1
  14. package/dist/hooks/bypass-detection.d.ts +8 -0
  15. package/dist/hooks/bypass-detection.js +15 -1
  16. package/dist/hooks/bypass-detection.js.map +1 -1
  17. package/dist/hooks/runners/session-start.js +8 -21
  18. package/dist/hooks/runners/session-start.js.map +1 -1
  19. package/dist/index.d.ts +1 -0
  20. package/dist/index.js +1 -0
  21. package/dist/index.js.map +1 -1
  22. package/dist/init/curator/regex-prefilter.d.ts +1 -1
  23. package/dist/init/curator/regex-prefilter.js +2 -2
  24. package/dist/init/curator/regex-prefilter.js.map +1 -1
  25. package/dist/init/curator/walker.js +2 -2
  26. package/dist/init/curator/walker.js.map +1 -1
  27. package/dist/init/ingest-docs.js +0 -1
  28. package/dist/init/ingest-docs.js.map +1 -1
  29. package/dist/init/init.d.ts +1 -1
  30. package/dist/init/init.js +2 -2
  31. package/dist/init/init.js.map +1 -1
  32. package/dist/init/module-slicer.js +0 -1
  33. package/dist/init/module-slicer.js.map +1 -1
  34. package/dist/init/phases/5-preflight.js +0 -1
  35. package/dist/init/phases/5-preflight.js.map +1 -1
  36. package/dist/init/seed.d.ts +1 -1
  37. package/dist/init/seed.js +1 -2
  38. package/dist/init/seed.js.map +1 -1
  39. package/dist/init/source-comments/walker.js +0 -1
  40. package/dist/init/source-comments/walker.js.map +1 -1
  41. package/dist/init/topic-index/walk.js +0 -1
  42. package/dist/init/topic-index/walk.js.map +1 -1
  43. package/dist/init/walker.js +0 -1
  44. package/dist/init/walker.js.map +1 -1
  45. package/dist/join/index.js +21 -0
  46. package/dist/join/index.js.map +1 -1
  47. package/dist/mcp/index.d.ts +0 -2
  48. package/dist/mcp/index.js +0 -1
  49. package/dist/mcp/index.js.map +1 -1
  50. package/dist/mcp/path-allowlist.d.ts +1 -1
  51. package/dist/mcp/path-allowlist.js +1 -2
  52. package/dist/mcp/path-allowlist.js.map +1 -1
  53. package/dist/mcp/schemas.d.ts +0 -6
  54. package/dist/mcp/schemas.js +0 -7
  55. package/dist/mcp/schemas.js.map +1 -1
  56. package/dist/mcp/tools/index.js +0 -3
  57. package/dist/mcp/tools/index.js.map +1 -1
  58. package/dist/mcp/tools/retire-entity.d.ts +2 -2
  59. package/dist/mcp/tools/retire-entity.js +4 -4
  60. package/dist/mcp/tools/retire-entity.js.map +1 -1
  61. package/dist/session-start/index.d.ts +3 -3
  62. package/dist/session-start/index.js +3 -3
  63. package/dist/session-start/templates.js +1 -2
  64. package/dist/session-start/templates.js.map +1 -1
  65. package/dist/state/rebuild-derived.d.ts +45 -0
  66. package/dist/state/rebuild-derived.js +221 -0
  67. package/dist/state/rebuild-derived.js.map +1 -0
  68. package/package.json +2 -2
  69. package/dist/mcp/history/index.d.ts +0 -6
  70. package/dist/mcp/history/index.js +0 -5
  71. package/dist/mcp/history/index.js.map +0 -1
  72. package/dist/mcp/history/prompt.d.ts +0 -33
  73. package/dist/mcp/history/prompt.js +0 -99
  74. package/dist/mcp/history/prompt.js.map +0 -1
  75. package/dist/mcp/history/schema.d.ts +0 -58
  76. package/dist/mcp/history/schema.js +0 -41
  77. package/dist/mcp/history/schema.js.map +0 -1
  78. package/dist/mcp/history/summarizer.d.ts +0 -81
  79. package/dist/mcp/history/summarizer.js +0 -201
  80. package/dist/mcp/history/summarizer.js.map +0 -1
  81. package/dist/mcp/history/walker.d.ts +0 -57
  82. package/dist/mcp/history/walker.js +0 -156
  83. package/dist/mcp/history/walker.js.map +0 -1
  84. package/dist/mcp/tools/query-history.d.ts +0 -20
  85. package/dist/mcp/tools/query-history.js +0 -51
  86. package/dist/mcp/tools/query-history.js.map +0 -1
  87. package/templates/.archive/README.md +0 -67
  88. package/templates/.cairn/ground/manifest.yaml +0 -13
@@ -0,0 +1,45 @@
1
+ /**
2
+ * `rebuildDerived` — reconstruct the gitignored derived ground-state
3
+ * indexes from the committed source of truth (DEC/INV `.md` frontmatter
4
+ * + bodies + source tree).
5
+ *
6
+ * As of v0.15.0 the derived ground files are gitignored to kill multi-dev
7
+ * merge conflicts (every clone used to regenerate and commit divergent
8
+ * copies). They no longer ship in git, so every clone must be able to
9
+ * regenerate them locally. This routine is the single rebuild entry
10
+ * point, wired into:
11
+ * - `cairn join` — a fresh teammate clone has no derived files yet.
12
+ * - SessionStart — refresh on every session open (cheap).
13
+ *
14
+ * (CI needs no rebuild: sensors read the committed DEC/INV `.md` directly,
15
+ * not the derived indexes.)
16
+ *
17
+ * Haiku-free and deterministic from committed sources. Covers the
18
+ * load-bearing set:
19
+ * - decisions/invariants ledgers (context injection)
20
+ * - scope-index (cairn_in_scope)
21
+ * - manifest (inventory)
22
+ * - sot-bindings (lens + sensors + align resolve §DEC → path)
23
+ * - sot-cache (Layer A Jaccard pre-filter)
24
+ *
25
+ * `topic-index.yaml` + `anchor-map.yaml` are discovery-time artifacts
26
+ * (init builds them with a Haiku dedup walk). We don't re-run discovery,
27
+ * but we DO reconstruct them Haiku-free on a COLD clone: the accepted
28
+ * `sot_kind: path` DEC/INV already encode resolved topics, so we walk
29
+ * the source prose blocks (`walkProseBlocks`, deterministic) and
30
+ * content-hash-rematch each entity's `sot_content_hash` to its current
31
+ * location → `anchor-map[slug]` + `topic-index[slug].dec_id`. This only
32
+ * runs when the files are absent (fresh clone / post-untrack); when
33
+ * present they are left to the incremental sot-align hook (no repeat of
34
+ * the full walk on every SessionStart). `file-candidates-map` is a pure
35
+ * function of the resulting `topic-index`.
36
+ */
37
+ export interface RebuildDerivedResult {
38
+ decisions: number;
39
+ invariants: number;
40
+ bindings: number;
41
+ cacheEntries: number;
42
+ /** `sot_kind: path` entities relocated into topic-index/anchor-map on a cold rebuild. */
43
+ topicAnchorRebuilt: number;
44
+ }
45
+ export declare function rebuildDerived(repoRoot: string): RebuildDerivedResult;
@@ -0,0 +1,221 @@
1
+ /**
2
+ * `rebuildDerived` — reconstruct the gitignored derived ground-state
3
+ * indexes from the committed source of truth (DEC/INV `.md` frontmatter
4
+ * + bodies + source tree).
5
+ *
6
+ * As of v0.15.0 the derived ground files are gitignored to kill multi-dev
7
+ * merge conflicts (every clone used to regenerate and commit divergent
8
+ * copies). They no longer ship in git, so every clone must be able to
9
+ * regenerate them locally. This routine is the single rebuild entry
10
+ * point, wired into:
11
+ * - `cairn join` — a fresh teammate clone has no derived files yet.
12
+ * - SessionStart — refresh on every session open (cheap).
13
+ *
14
+ * (CI needs no rebuild: sensors read the committed DEC/INV `.md` directly,
15
+ * not the derived indexes.)
16
+ *
17
+ * Haiku-free and deterministic from committed sources. Covers the
18
+ * load-bearing set:
19
+ * - decisions/invariants ledgers (context injection)
20
+ * - scope-index (cairn_in_scope)
21
+ * - manifest (inventory)
22
+ * - sot-bindings (lens + sensors + align resolve §DEC → path)
23
+ * - sot-cache (Layer A Jaccard pre-filter)
24
+ *
25
+ * `topic-index.yaml` + `anchor-map.yaml` are discovery-time artifacts
26
+ * (init builds them with a Haiku dedup walk). We don't re-run discovery,
27
+ * but we DO reconstruct them Haiku-free on a COLD clone: the accepted
28
+ * `sot_kind: path` DEC/INV already encode resolved topics, so we walk
29
+ * the source prose blocks (`walkProseBlocks`, deterministic) and
30
+ * content-hash-rematch each entity's `sot_content_hash` to its current
31
+ * location → `anchor-map[slug]` + `topic-index[slug].dec_id`. This only
32
+ * runs when the files are absent (fresh clone / post-untrack); when
33
+ * present they are left to the incremental sot-align hook (no repeat of
34
+ * the full walk on every SessionStart). `file-candidates-map` is a pure
35
+ * function of the resulting `topic-index`.
36
+ */
37
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
38
+ import { join } from "node:path";
39
+ import { DecisionFrontmatter, InvariantFrontmatter, anchorMapPath, bindDec, bodyContentHash, decisionsDir, emptyAnchorMap, emptySotBindings, emptySotCache, emptyTopicIndex, invariantsDir, parseFrontmatter, readTopicIndex, rescanScopeIndex, setAnchor, setSotCacheEntry, setTopic, topicIndexPath, writeAnchorMap, writeDecisionsLedger, writeFileCandidatesMap, writeInvariantsLedger, writeManifest, writeSotBindings, writeSotCache, writeTopicIndex, } from "@isaacriehm/cairn-state";
40
+ import { walkProseBlocks } from "../init/topic-index/walk.js";
41
+ import { tokenize } from "../text/jaccard.js";
42
+ import { logger } from "../logger.js";
43
+ const log = logger("rebuild-derived");
44
+ /** Read every `.md` in a ground entity dir (skipping `_`-prefixed). */
45
+ function listEntityFiles(dir) {
46
+ if (!existsSync(dir))
47
+ return [];
48
+ try {
49
+ return readdirSync(dir)
50
+ .filter((n) => n.endsWith(".md") && !n.startsWith("_"))
51
+ .sort();
52
+ }
53
+ catch {
54
+ return [];
55
+ }
56
+ }
57
+ export function rebuildDerived(repoRoot) {
58
+ // 1. Deterministic ledgers + scope-index + manifest. These already had
59
+ // writers; SessionStart used to call the ledgers + scope rescan
60
+ // directly — now centralized here so join gets the same path.
61
+ writeDecisionsLedger({ repoRoot });
62
+ writeInvariantsLedger({ repoRoot });
63
+ rescanScopeIndex(repoRoot);
64
+ // 2. sot-bindings + sot-cache, reconstructed from committed DEC/INV
65
+ // frontmatter (sot_path) + bodies (tokens). The forward binding is
66
+ // one entity → its sot_path; sot-cache holds the tokenized body for
67
+ // the Layer A Jaccard pre-filter.
68
+ let bindings = emptySotBindings();
69
+ let cache = emptySotCache();
70
+ const pathEntities = [];
71
+ let decisions = 0;
72
+ let invariants = 0;
73
+ const decDir = decisionsDir(repoRoot);
74
+ for (const name of listEntityFiles(decDir)) {
75
+ const abs = join(decDir, name);
76
+ const parsed = parseFrontmatter(readFileSync(abs, "utf8"));
77
+ const fm = DecisionFrontmatter.safeParse(parsed.frontmatter);
78
+ if (!fm.success)
79
+ continue;
80
+ if (fm.data.status !== "accepted")
81
+ continue;
82
+ if (fm.data.superseded_by)
83
+ continue;
84
+ const entry = makeCacheEntry(fm.data.id, fm.data.sot_path, parsed.body, abs);
85
+ bindings = bindDec(bindings, fm.data.id, fm.data.sot_path);
86
+ cache = setSotCacheEntry(cache, fm.data.id, entry);
87
+ if (fm.data.sot_kind === "path") {
88
+ pathEntities.push({ id: fm.data.id, sotContentHash: fm.data.sot_content_hash });
89
+ }
90
+ decisions += 1;
91
+ }
92
+ const invDir = invariantsDir(repoRoot);
93
+ for (const name of listEntityFiles(invDir)) {
94
+ const abs = join(invDir, name);
95
+ const parsed = parseFrontmatter(readFileSync(abs, "utf8"));
96
+ const fm = InvariantFrontmatter.safeParse(parsed.frontmatter);
97
+ if (!fm.success)
98
+ continue;
99
+ if ((fm.data.status ?? "active") !== "active")
100
+ continue;
101
+ const entry = makeCacheEntry(fm.data.id, fm.data.sot_path, parsed.body, abs);
102
+ bindings = bindDec(bindings, fm.data.id, fm.data.sot_path);
103
+ cache = setSotCacheEntry(cache, fm.data.id, entry);
104
+ if (fm.data.sot_kind === "path") {
105
+ pathEntities.push({ id: fm.data.id, sotContentHash: fm.data.sot_content_hash });
106
+ }
107
+ invariants += 1;
108
+ }
109
+ writeSotBindings(repoRoot, bindings);
110
+ writeSotCache(repoRoot, cache);
111
+ // 3. Manifest (inventory over the freshly-written ground files).
112
+ writeManifest({ repoRoot });
113
+ // 4. Cold-start only: reconstruct topic-index + anchor-map for
114
+ // `sot_kind: path` entities by content-hash rematch. Skip when both
115
+ // files already exist — the sot-align hook maintains them warm, and
116
+ // a full prose walk on every SessionStart would be wasteful.
117
+ let topicAnchorRebuilt = 0;
118
+ const topicMissing = !existsSync(topicIndexPath(repoRoot));
119
+ const anchorMissing = !existsSync(anchorMapPath(repoRoot));
120
+ if ((topicMissing || anchorMissing) && pathEntities.length > 0) {
121
+ topicAnchorRebuilt = rebuildTopicAndAnchor(repoRoot, pathEntities);
122
+ }
123
+ // 5. file-candidates-map is a pure function of topic-index.
124
+ writeFileCandidatesMap(repoRoot, readTopicIndex(repoRoot));
125
+ const bindingCount = Object.keys(bindings.forward).length;
126
+ const cacheCount = Object.keys(cache.entries).length;
127
+ log.debug({
128
+ repoRoot,
129
+ decisions,
130
+ invariants,
131
+ bindings: bindingCount,
132
+ cache: cacheCount,
133
+ topicAnchorRebuilt,
134
+ }, "rebuilt derived ground state");
135
+ return {
136
+ decisions,
137
+ invariants,
138
+ bindings: bindingCount,
139
+ cacheEntries: cacheCount,
140
+ topicAnchorRebuilt,
141
+ };
142
+ }
143
+ /**
144
+ * Cold rebuild of `topic-index` + `anchor-map` for `sot_kind: path`
145
+ * entities. Walks the source prose blocks once, indexes them by content
146
+ * hash, and relocates each entity's `sot_content_hash` to its current
147
+ * block (slug, file, line range, anchor). Haiku-free — discovery already
148
+ * happened; this just re-resolves known topics. Entities whose SoT block
149
+ * isn't found (content drifted, or it lives in a source-comment the doc
150
+ * walker doesn't cover) are skipped and left to the incremental hook.
151
+ * Returns the number of entities relocated.
152
+ */
153
+ function rebuildTopicAndAnchor(repoRoot, entities) {
154
+ let blocksByHash;
155
+ try {
156
+ const blocks = walkProseBlocks(repoRoot);
157
+ blocksByHash = new Map();
158
+ for (const b of blocks) {
159
+ if (!blocksByHash.has(b.content_hash))
160
+ blocksByHash.set(b.content_hash, b);
161
+ }
162
+ }
163
+ catch {
164
+ return 0; // walk failed (non-repo / IO) — leave maps to the hook
165
+ }
166
+ let topic = emptyTopicIndex();
167
+ let anchors = emptyAnchorMap();
168
+ let relocated = 0;
169
+ const now = new Date().toISOString();
170
+ for (const e of entities) {
171
+ const b = blocksByHash.get(e.sotContentHash);
172
+ if (b === undefined)
173
+ continue;
174
+ const topicEntry = {
175
+ slug: b.slug,
176
+ dec_id: e.id,
177
+ sot_source: b.file,
178
+ candidates: [
179
+ {
180
+ file: b.file,
181
+ kind: b.kind,
182
+ line_range: b.line_range,
183
+ ...(b.anchor !== undefined ? { anchor: b.anchor } : {}),
184
+ },
185
+ ],
186
+ created_at: now,
187
+ content_hash: b.content_hash,
188
+ };
189
+ topic = setTopic(topic, b.slug, topicEntry);
190
+ const anchorEntry = {
191
+ file: b.file,
192
+ content_hash: b.content_hash,
193
+ line_range: b.line_range,
194
+ kind: b.kind,
195
+ ...(b.anchor !== undefined ? { current_anchor: b.anchor } : {}),
196
+ };
197
+ anchors = setAnchor(anchors, b.slug, anchorEntry);
198
+ relocated += 1;
199
+ }
200
+ writeTopicIndex(repoRoot, topic);
201
+ writeAnchorMap(repoRoot, anchors);
202
+ return relocated;
203
+ }
204
+ function makeCacheEntry(id, sotPath, body, abs) {
205
+ let mtimeMs = 0;
206
+ try {
207
+ mtimeMs = statSync(abs).mtimeMs;
208
+ }
209
+ catch {
210
+ /* best-effort — mtime is a local incremental-staleness hint only */
211
+ }
212
+ return {
213
+ dec_id: id,
214
+ sot_path: sotPath,
215
+ body_hash: bodyContentHash(body),
216
+ tokens: Array.from(tokenize(body, { codeAware: true })),
217
+ shingles: [],
218
+ mtime_ms: mtimeMs,
219
+ };
220
+ }
221
+ //# sourceMappingURL=rebuild-derived.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rebuild-derived.js","sourceRoot":"","sources":["../../src/state/rebuild-derived.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@isaacriehm/cairn-core",
3
- "version": "0.14.1",
3
+ "version": "0.15.0",
4
4
  "description": "Cairn core — state + context layer. Curated `.cairn/ground/` (decisions, §INV invariants, canonical-map, brand, quality-grades), MCP server, init wizard, hook runners, sensors, GC drift sweep.",
5
5
  "author": "Isaac Riehm",
6
6
  "license": "MIT",
@@ -39,7 +39,7 @@
39
39
  "simple-git": "^3.36.0",
40
40
  "yaml": "^2.8.4",
41
41
  "zod": "^4.4.3",
42
- "@isaacriehm/cairn-state": "0.14.1"
42
+ "@isaacriehm/cairn-state": "0.15.0"
43
43
  },
44
44
  "devDependencies": {
45
45
  "@types/cli-progress": "^3.11.6",
@@ -1,6 +0,0 @@
1
- export { walkArchive } from "./walker.js";
2
- export type { ArchiveFile, WalkArchiveOptions, WalkArchiveResult } from "./walker.js";
3
- export { HISTORY_SUMMARIZER_SYSTEM_PROMPT, buildHistorySummarizerUserPrompt, CAIRN_HISTORY_SUMMARIZE_PROMPT_ID, CAIRN_HISTORY_SUMMARIZE_VERSION, } from "./prompt.js";
4
- export { HISTORY_SUMMARIZER_OUTPUT_SCHEMA } from "./schema.js";
5
- export { runHistorySummarizer, runQueryHistory, } from "./summarizer.js";
6
- export type { QueryHistoryResponse, RunQueryHistoryArgs, SummarizedClaim, } from "./summarizer.js";
@@ -1,5 +0,0 @@
1
- export { walkArchive } from "./walker.js";
2
- export { HISTORY_SUMMARIZER_SYSTEM_PROMPT, buildHistorySummarizerUserPrompt, CAIRN_HISTORY_SUMMARIZE_PROMPT_ID, CAIRN_HISTORY_SUMMARIZE_VERSION, } from "./prompt.js";
3
- export { HISTORY_SUMMARIZER_OUTPUT_SCHEMA } from "./schema.js";
4
- export { runHistorySummarizer, runQueryHistory, } from "./summarizer.js";
5
- //# sourceMappingURL=index.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/mcp/history/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,OAAO,EACL,gCAAgC,EAChC,gCAAgC,EAChC,iCAAiC,EACjC,+BAA+B,GAChC,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,gCAAgC,EAAE,MAAM,aAAa,CAAC;AAC/D,OAAO,EACL,oBAAoB,EACpB,eAAe,GAChB,MAAM,iBAAiB,CAAC"}
@@ -1,33 +0,0 @@
1
- /**
2
- * Tier-1 (Haiku) summarizer prompts for cairn_query_history.
3
- *
4
- * Constraint: the LLM emits ONLY structured claims; raw historical
5
- * content never reaches the agent's context. Each claim cites a
6
- * concrete source_path + source_lines so the operator (and any future
7
- * audit) can verify the summary against the original.
8
- *
9
- * The prompt id + version are committed in source so a behavior change
10
- * here is a versioned change in the source tree, not a silent runtime
11
- * update.
12
- */
13
- import type { ArchiveFile } from "./walker.js";
14
- export declare const CAIRN_HISTORY_SUMMARIZE_PROMPT_ID = "cairn.history_summarize.v1";
15
- export declare const CAIRN_HISTORY_SUMMARIZE_VERSION = "v1";
16
- export declare const HISTORY_SUMMARIZER_SYSTEM_PROMPT = "You are the **history summarizer** for an agent cairn's two-zone read separation. The agent calling you cannot read .archive/ files directly \u2014 by design. You read those files on its behalf and emit a structured response with cited claims. Only your structured response reaches the agent's context.\n\nYour job: read N historical files and the operator's scope question. Produce per-claim records that capture what the historical files said, with full citation, dates, and supersedes-tags pointing at currently-canonical decisions when they exist.\n\n## Hard contract\n\nEvery claim you emit MUST include:\n\n- `claim` \u2014 one-sentence factual statement of what the historical content said. Past-tense. Imperative voice avoided. Example: \"The project considered using a JSONB expression index on commandPayload->>'userId' for dashboard queries.\" NOT \"The project should use a JSONB index\" \u2014 that is current-tense and reads as canon.\n- `as_of` \u2014 ISO date when the source content was authored / valid. Use the file's frontmatter `generated` or `verified-at`, the bucket date in the path (`.archive/2026-05-pre-cairn/`), or the most explicit date you can find in the body. If genuinely unknown, set the bucket date.\n- `source_path` \u2014 the repo-relative path EXACTLY as given in the file headers. Do not invent a path or a hash.\n- `source_lines` \u2014 line range like \"320-410\" or a single line \"47\". Required so the operator can audit your summary by opening the original file.\n- `superseded_by` \u2014 when an accepted decision in the supplied \"Currently-accepted decisions\" list directly relates to the historical claim, set the DEC-NNNN id. Otherwise set null. Do NOT invent decision ids.\n\n## When you should set `no_relevant_history: true`\n\nThe supplied files don't contain anything relevant to the operator's scope question. Better to short-circuit than to fabricate a summary. The cairn returns an empty claims array with a one-line caveat.\n\n## When you should set `summary_caveat`\n\nAnything important about the input that affects how the agent should treat your output:\n- \"Summary covers 8 files; 3 additional matches were truncated.\"\n- \"All claims are from a single bucket dated 2026-04-23; nothing more recent in scope.\"\n\n## What you must NOT do\n\n- Do NOT issue a recommendation. Your output is descriptive (what was said), not prescriptive (what to do).\n- Do NOT phrase claims as if they are current truth. Always past-tense + cited.\n- Do NOT invent paths, line ranges, decision ids, or dates. If you can't find a value, set what's required by schema and skip the claim.\n- Do NOT emit a free-form preamble before the JSON.\n- Do NOT emit fields not in the schema.\n\nOutput ONLY the JSON object.";
17
- interface BuildHistoryUserPromptArgs {
18
- /** Operator's free-text scope description. */
19
- scope: string;
20
- /** Repo-relative pathHint glob, when provided. */
21
- pathHint?: string;
22
- since?: string;
23
- until?: string;
24
- files: ArchiveFile[];
25
- /** Optional ledger of currently-accepted decisions for supersedes inference. */
26
- acceptedDecisions: {
27
- id: string;
28
- title: string;
29
- scope_globs?: string[];
30
- }[];
31
- }
32
- export declare function buildHistorySummarizerUserPrompt(args: BuildHistoryUserPromptArgs): string;
33
- export {};
@@ -1,99 +0,0 @@
1
- /**
2
- * Tier-1 (Haiku) summarizer prompts for cairn_query_history.
3
- *
4
- * Constraint: the LLM emits ONLY structured claims; raw historical
5
- * content never reaches the agent's context. Each claim cites a
6
- * concrete source_path + source_lines so the operator (and any future
7
- * audit) can verify the summary against the original.
8
- *
9
- * The prompt id + version are committed in source so a behavior change
10
- * here is a versioned change in the source tree, not a silent runtime
11
- * update.
12
- */
13
- export const CAIRN_HISTORY_SUMMARIZE_PROMPT_ID = "cairn.history_summarize.v1";
14
- export const CAIRN_HISTORY_SUMMARIZE_VERSION = "v1";
15
- export const HISTORY_SUMMARIZER_SYSTEM_PROMPT = `You are the **history summarizer** for an agent cairn's two-zone read separation. The agent calling you cannot read .archive/ files directly — by design. You read those files on its behalf and emit a structured response with cited claims. Only your structured response reaches the agent's context.
16
-
17
- Your job: read N historical files and the operator's scope question. Produce per-claim records that capture what the historical files said, with full citation, dates, and supersedes-tags pointing at currently-canonical decisions when they exist.
18
-
19
- ## Hard contract
20
-
21
- Every claim you emit MUST include:
22
-
23
- - \`claim\` — one-sentence factual statement of what the historical content said. Past-tense. Imperative voice avoided. Example: "The project considered using a JSONB expression index on commandPayload->>'userId' for dashboard queries." NOT "The project should use a JSONB index" — that is current-tense and reads as canon.
24
- - \`as_of\` — ISO date when the source content was authored / valid. Use the file's frontmatter \`generated\` or \`verified-at\`, the bucket date in the path (\`.archive/2026-05-pre-cairn/\`), or the most explicit date you can find in the body. If genuinely unknown, set the bucket date.
25
- - \`source_path\` — the repo-relative path EXACTLY as given in the file headers. Do not invent a path or a hash.
26
- - \`source_lines\` — line range like "320-410" or a single line "47". Required so the operator can audit your summary by opening the original file.
27
- - \`superseded_by\` — when an accepted decision in the supplied "Currently-accepted decisions" list directly relates to the historical claim, set the DEC-NNNN id. Otherwise set null. Do NOT invent decision ids.
28
-
29
- ## When you should set \`no_relevant_history: true\`
30
-
31
- The supplied files don't contain anything relevant to the operator's scope question. Better to short-circuit than to fabricate a summary. The cairn returns an empty claims array with a one-line caveat.
32
-
33
- ## When you should set \`summary_caveat\`
34
-
35
- Anything important about the input that affects how the agent should treat your output:
36
- - "Summary covers 8 files; 3 additional matches were truncated."
37
- - "All claims are from a single bucket dated 2026-04-23; nothing more recent in scope."
38
-
39
- ## What you must NOT do
40
-
41
- - Do NOT issue a recommendation. Your output is descriptive (what was said), not prescriptive (what to do).
42
- - Do NOT phrase claims as if they are current truth. Always past-tense + cited.
43
- - Do NOT invent paths, line ranges, decision ids, or dates. If you can't find a value, set what's required by schema and skip the claim.
44
- - Do NOT emit a free-form preamble before the JSON.
45
- - Do NOT emit fields not in the schema.
46
-
47
- Output ONLY the JSON object.`;
48
- const PER_FILE_HEADER_PREVIEW_LINES = 800;
49
- export function buildHistorySummarizerUserPrompt(args) {
50
- const sections = [];
51
- sections.push("## Operator scope question");
52
- sections.push(args.scope.trim());
53
- sections.push("");
54
- sections.push("## Filters applied to the .archive/ walk");
55
- sections.push(`path_hint: ${args.pathHint ?? "(none — full archive)"}`);
56
- sections.push(`since: ${args.since ?? "(none — beginning of time)"}`);
57
- sections.push(`until: ${args.until ?? "(none — present)"}`);
58
- sections.push(`matched_files: ${args.files.length}`);
59
- if (args.acceptedDecisions.length > 0) {
60
- sections.push("");
61
- sections.push("## Currently-accepted decisions (for supersedes inference)");
62
- sections.push("Each line: `<DEC-id> — <title> (scope: <globs>)`. If a historical claim directly contradicts or has been replaced by one of these, cite the id in `superseded_by`. Otherwise set null. Do NOT invent ids.");
63
- sections.push("");
64
- for (const d of args.acceptedDecisions.slice(0, 30)) {
65
- const scope = d.scope_globs && d.scope_globs.length > 0 ? d.scope_globs.join(", ") : "(no scope)";
66
- sections.push(`- **${d.id}** — ${d.title} (scope: ${scope})`);
67
- }
68
- if (args.acceptedDecisions.length > 30) {
69
- sections.push(`…(${args.acceptedDecisions.length - 30} additional accepted decisions omitted)`);
70
- }
71
- }
72
- sections.push("");
73
- sections.push("## Historical files (line-numbered)");
74
- if (args.files.length === 0) {
75
- sections.push("(none — return `no_relevant_history: true`)");
76
- }
77
- for (const f of args.files) {
78
- sections.push("");
79
- sections.push(`### ${f.relPath} (bucket: ${f.bucket}, archive_date: ${f.archiveDate}${f.truncated ? ", TRUNCATED" : ""})`);
80
- sections.push("```");
81
- sections.push(numberLines(f.content, PER_FILE_HEADER_PREVIEW_LINES));
82
- sections.push("```");
83
- }
84
- sections.push("");
85
- sections.push("## Your task");
86
- sections.push("Emit the JSON object per the schema. Cite source_path EXACTLY as the headers above show. Output ONLY the JSON object.");
87
- return sections.join("\n");
88
- }
89
- function numberLines(text, maxLines) {
90
- const lines = text.split(/\r?\n/);
91
- const truncated = lines.length > maxLines;
92
- const slice = truncated ? lines.slice(0, maxLines) : lines;
93
- const padWidth = String(slice.length).length;
94
- const out = slice.map((line, i) => `${String(i + 1).padStart(padWidth, " ")} ${line}`);
95
- if (truncated)
96
- out.push(`…[${lines.length - maxLines} more lines elided]`);
97
- return out.join("\n");
98
- }
99
- //# sourceMappingURL=prompt.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../src/mcp/history/prompt.ts"],"names":[],"mappings":"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"}
@@ -1,58 +0,0 @@
1
- /**
2
- * JSON Schema enforced by `claude --json-schema` for the history
3
- * summarizer Tier-1 call.
4
- *
5
- * Per MCP_SURFACE.md §"cairn_query_history": every claim MUST carry
6
- * source_path, source_lines, as_of, and a supersedes-tag (string DEC-id
7
- * or null). The cairn post-resolves currently_canonical_pointer from
8
- * the decisions ledger after the LLM returns — keeps the LLM's
9
- * responsibilities tight (cite + summarize) and makes the canonical
10
- * cross-reference mechanical.
11
- */
12
- export declare const HISTORY_SUMMARIZER_OUTPUT_SCHEMA: {
13
- readonly type: "object";
14
- readonly additionalProperties: false;
15
- readonly properties: {
16
- readonly claims: {
17
- readonly type: "array";
18
- readonly items: {
19
- readonly type: "object";
20
- readonly additionalProperties: false;
21
- readonly properties: {
22
- readonly claim: {
23
- readonly type: "string";
24
- readonly minLength: 1;
25
- };
26
- readonly as_of: {
27
- readonly type: "string";
28
- readonly minLength: 1;
29
- };
30
- readonly source_path: {
31
- readonly type: "string";
32
- readonly minLength: 1;
33
- };
34
- readonly source_lines: {
35
- readonly type: "string";
36
- readonly minLength: 1;
37
- };
38
- readonly superseded_by: {
39
- readonly anyOf: readonly [{
40
- readonly type: "string";
41
- readonly pattern: "^DEC-\\d{4,}$";
42
- }, {
43
- readonly type: "null";
44
- }];
45
- };
46
- };
47
- readonly required: readonly ["claim", "as_of", "source_path", "source_lines"];
48
- };
49
- };
50
- readonly summary_caveat: {
51
- readonly type: "string";
52
- };
53
- readonly no_relevant_history: {
54
- readonly type: "boolean";
55
- };
56
- };
57
- readonly required: readonly ["claims"];
58
- };
@@ -1,41 +0,0 @@
1
- /**
2
- * JSON Schema enforced by `claude --json-schema` for the history
3
- * summarizer Tier-1 call.
4
- *
5
- * Per MCP_SURFACE.md §"cairn_query_history": every claim MUST carry
6
- * source_path, source_lines, as_of, and a supersedes-tag (string DEC-id
7
- * or null). The cairn post-resolves currently_canonical_pointer from
8
- * the decisions ledger after the LLM returns — keeps the LLM's
9
- * responsibilities tight (cite + summarize) and makes the canonical
10
- * cross-reference mechanical.
11
- */
12
- export const HISTORY_SUMMARIZER_OUTPUT_SCHEMA = {
13
- type: "object",
14
- additionalProperties: false,
15
- properties: {
16
- claims: {
17
- type: "array",
18
- items: {
19
- type: "object",
20
- additionalProperties: false,
21
- properties: {
22
- claim: { type: "string", minLength: 1 },
23
- as_of: { type: "string", minLength: 1 },
24
- source_path: { type: "string", minLength: 1 },
25
- source_lines: { type: "string", minLength: 1 },
26
- superseded_by: {
27
- anyOf: [
28
- { type: "string", pattern: "^DEC-\\d{4,}$" },
29
- { type: "null" },
30
- ],
31
- },
32
- },
33
- required: ["claim", "as_of", "source_path", "source_lines"],
34
- },
35
- },
36
- summary_caveat: { type: "string" },
37
- no_relevant_history: { type: "boolean" },
38
- },
39
- required: ["claims"],
40
- };
41
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../../src/mcp/history/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,gCAAgC,GAAG;IAC9C,IAAI,EAAE,QAAQ;IACd,oBAAoB,EAAE,KAAK;IAC3B,UAAU,EAAE;QACV,MAAM,EAAE;YACN,IAAI,EAAE,OAAO;YACb,KAAK,EAAE;gBACL,IAAI,EAAE,QAAQ;gBACd,oBAAoB,EAAE,KAAK;gBAC3B,UAAU,EAAE;oBACV,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;oBACvC,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;oBACvC,WAAW,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;oBAC7C,YAAY,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,SAAS,EAAE,CAAC,EAAE;oBAC9C,aAAa,EAAE;wBACb,KAAK,EAAE;4BACL,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,eAAe,EAAE;4BAC5C,EAAE,IAAI,EAAE,MAAM,EAAE;yBACjB;qBACF;iBACF;gBACD,QAAQ,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,aAAa,EAAE,cAAc,CAAC;aAC5D;SACF;QACD,cAAc,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QAClC,mBAAmB,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE;KACzC;IACD,QAAQ,EAAE,CAAC,QAAQ,CAAC;CACZ,CAAC"}
@@ -1,81 +0,0 @@
1
- /**
2
- * Composes walker + Tier-1 summarizer + post-resolution of
3
- * currently_canonical_pointer for cairn_query_history.
4
- *
5
- * Flow:
6
- * 1. walkArchive(repoRoot, pathHint, since, until) → ArchiveFile[]
7
- * 2. Load currently-accepted decisions ledger.
8
- * 3. Build summarizer prompt with files + ledger.
9
- * 4. runClaude(tier=haiku, jsonSchema=HISTORY_SUMMARIZER_OUTPUT_SCHEMA).
10
- * 5. Validate output structurally.
11
- * 6. Post-resolve currently_canonical_pointer per claim by looking up
12
- * `superseded_by` against the on-disk decisions/ dir.
13
- * 7. Attach summarizer_model + summarizer_prompt_id metadata.
14
- *
15
- * Returns the structured QueryHistoryResponse the MCP tool emits.
16
- */
17
- import type { ClaudeTier } from "../../claude/index.js";
18
- import { type ArchiveFile } from "./walker.js";
19
- export interface SummarizedClaim {
20
- claim: string;
21
- as_of: string;
22
- source_path: string;
23
- source_lines: string;
24
- superseded_by: string | null;
25
- currently_canonical_pointer: string | null;
26
- warning: string;
27
- }
28
- export interface QueryHistoryResponse {
29
- historical_only: true;
30
- claims: SummarizedClaim[];
31
- summary_caveat: string;
32
- summarizer_model: string;
33
- summarizer_prompt_id: string;
34
- /** Structural metadata about the walk — useful for telemetry + tests. */
35
- walked_files: number;
36
- walked_buckets: string[];
37
- truncated_walk: boolean;
38
- }
39
- export interface RunQueryHistoryArgs {
40
- repoRoot: string;
41
- scope: string;
42
- pathHint?: string;
43
- since?: string;
44
- until?: string;
45
- /** Tier override; default haiku per workflow.md. */
46
- tier?: ClaudeTier;
47
- /** Per-call timeout. Default 120000 ms. */
48
- timeoutMs?: number;
49
- /** Smoke override — return canned summarizer output without burning quota. */
50
- summarizerOverride?: typeof runHistorySummarizer;
51
- }
52
- interface RunSummarizerInput {
53
- scope: string;
54
- pathHint?: string;
55
- since?: string;
56
- until?: string;
57
- files: ArchiveFile[];
58
- acceptedDecisions: {
59
- id: string;
60
- title: string;
61
- scope_globs?: string[];
62
- }[];
63
- tier: ClaudeTier;
64
- timeoutMs: number;
65
- }
66
- interface RunSummarizerResult {
67
- claims: {
68
- claim: string;
69
- as_of: string;
70
- source_path: string;
71
- source_lines: string;
72
- superseded_by: string | null;
73
- }[];
74
- summary_caveat: string;
75
- no_relevant_history: boolean;
76
- model: string;
77
- }
78
- export declare function runQueryHistory(args: RunQueryHistoryArgs): Promise<QueryHistoryResponse>;
79
- /** Default summarizer implementation — runs the real LLM. */
80
- export declare function runHistorySummarizer(input: RunSummarizerInput): Promise<RunSummarizerResult>;
81
- export {};