@isaacriehm/cairn-core 0.23.0 → 0.25.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 (53) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/context/index.d.ts +2 -0
  3. package/dist/context/index.js +1 -0
  4. package/dist/context/index.js.map +1 -1
  5. package/dist/context/task-summary.d.ts +18 -0
  6. package/dist/context/task-summary.js +94 -23
  7. package/dist/context/task-summary.js.map +1 -1
  8. package/dist/context/working-header.d.ts +29 -0
  9. package/dist/context/working-header.js +125 -0
  10. package/dist/context/working-header.js.map +1 -0
  11. package/dist/hooks/post-tool-use/post-write.js +16 -0
  12. package/dist/hooks/post-tool-use/post-write.js.map +1 -1
  13. package/dist/hooks/post-tool-use/read-enricher.js +96 -4
  14. package/dist/hooks/post-tool-use/read-enricher.js.map +1 -1
  15. package/dist/hooks/runners/annotate-surface.d.ts +41 -0
  16. package/dist/hooks/runners/annotate-surface.js +151 -0
  17. package/dist/hooks/runners/annotate-surface.js.map +1 -0
  18. package/dist/hooks/runners/stop.js +26 -0
  19. package/dist/hooks/runners/stop.js.map +1 -1
  20. package/dist/hooks/runners/user-prompt-submit.js +59 -9
  21. package/dist/hooks/runners/user-prompt-submit.js.map +1 -1
  22. package/dist/init/brand-setup.d.ts +16 -3
  23. package/dist/init/brand-setup.js +24 -17
  24. package/dist/init/brand-setup.js.map +1 -1
  25. package/dist/init/phases/6-brand.js +15 -11
  26. package/dist/init/phases/6-brand.js.map +1 -1
  27. package/dist/mcp/schemas.d.ts +27 -1
  28. package/dist/mcp/schemas.js +22 -0
  29. package/dist/mcp/schemas.js.map +1 -1
  30. package/dist/mcp/tools/component-annotate.d.ts +33 -0
  31. package/dist/mcp/tools/component-annotate.js +189 -0
  32. package/dist/mcp/tools/component-annotate.js.map +1 -0
  33. package/dist/mcp/tools/index.js +3 -1
  34. package/dist/mcp/tools/index.js.map +1 -1
  35. package/dist/mcp/tools/resume.js +10 -34
  36. package/dist/mcp/tools/resume.js.map +1 -1
  37. package/dist/session/index.d.ts +2 -0
  38. package/dist/session/index.js +2 -0
  39. package/dist/session/index.js.map +1 -1
  40. package/dist/session/seen.d.ts +37 -0
  41. package/dist/session/seen.js +110 -0
  42. package/dist/session/seen.js.map +1 -0
  43. package/dist/session/touched.d.ts +17 -0
  44. package/dist/session/touched.js +57 -0
  45. package/dist/session/touched.js.map +1 -0
  46. package/dist/session-start/build.js +19 -7
  47. package/dist/session-start/build.js.map +1 -1
  48. package/dist/status-line/format.js +17 -2
  49. package/dist/status-line/format.js.map +1 -1
  50. package/dist/tasks/spec-reader.d.ts +27 -0
  51. package/dist/tasks/spec-reader.js +60 -0
  52. package/dist/tasks/spec-reader.js.map +1 -0
  53. package/package.json +2 -2
@@ -9,3 +9,5 @@ export { buildSpecDelta } from "./spec-delta.js";
9
9
  export type { SpecDelta } from "./spec-delta.js";
10
10
  export { readActiveTaskSummary } from "./task-summary.js";
11
11
  export type { ActiveTaskSummary } from "./task-summary.js";
12
+ export { buildWorkingHeader } from "./working-header.js";
13
+ export type { WorkingHeader } from "./working-header.js";
@@ -7,4 +7,5 @@
7
7
  export { buildHandoffBlock } from "./handoff-builder.js";
8
8
  export { buildSpecDelta } from "./spec-delta.js";
9
9
  export { readActiveTaskSummary } from "./task-summary.js";
10
+ export { buildWorkingHeader } from "./working-header.js";
10
11
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/context/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC"}
@@ -16,3 +16,21 @@ export interface ActiveTaskSummary {
16
16
  taskModule: string;
17
17
  }
18
18
  export declare function readActiveTaskSummary(repoRoot: string): ActiveTaskSummary | null;
19
+ /**
20
+ * Summary for one specific active task id, or null when it is not
21
+ * in-flight. Used by the working-context header to render the task this
22
+ * session is actually on (resolved by session affinity) rather than the
23
+ * first/arbitrary active task.
24
+ */
25
+ export declare function readTaskSummaryById(repoRoot: string, taskId: string): ActiveTaskSummary | null;
26
+ /**
27
+ * Resolve which active task THIS session is on, for multi-task /
28
+ * multi-window correctness. Among in-flight tasks, prefer one this
29
+ * session created or last journaled (`created_by_session` /
30
+ * `last_journal_session` on status.yaml); fall back to the most-recently
31
+ * touched active task. Returns null when nothing is in flight.
32
+ *
33
+ * Without this, two Claude windows on one checkout would both surface
34
+ * whichever task was globally first/most-recent — wrong frame.
35
+ */
36
+ export declare function resolveSessionTaskId(repoRoot: string, sessionId: string | null): string | null;
@@ -8,7 +8,7 @@
8
8
  * unrecognized values collapse to `idle` so the surface stays quiet
9
9
  * when nothing is actually in flight.
10
10
  */
11
- import { existsSync, readFileSync, readdirSync } from "node:fs";
11
+ import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
12
12
  import { join } from "node:path";
13
13
  import { parse as parseYaml } from "yaml";
14
14
  import { cairnDir, parseFrontmatter } from "@isaacriehm/cairn-state";
@@ -52,8 +52,48 @@ export function readActiveTaskSummary(repoRoot) {
52
52
  for (const e of dirents) {
53
53
  if (!e.isDirectory())
54
54
  continue;
55
- const taskDir = join(activeDir, e.name);
56
- const statusPath = join(taskDir, "status.yaml");
55
+ const summary = summarizeActiveTask(join(activeDir, e.name), e.name);
56
+ if (summary !== null)
57
+ return summary;
58
+ }
59
+ return null;
60
+ }
61
+ /**
62
+ * Summary for one specific active task id, or null when it is not
63
+ * in-flight. Used by the working-context header to render the task this
64
+ * session is actually on (resolved by session affinity) rather than the
65
+ * first/arbitrary active task.
66
+ */
67
+ export function readTaskSummaryById(repoRoot, taskId) {
68
+ return summarizeActiveTask(cairnDir(repoRoot, "tasks", "active", taskId), taskId);
69
+ }
70
+ /**
71
+ * Resolve which active task THIS session is on, for multi-task /
72
+ * multi-window correctness. Among in-flight tasks, prefer one this
73
+ * session created or last journaled (`created_by_session` /
74
+ * `last_journal_session` on status.yaml); fall back to the most-recently
75
+ * touched active task. Returns null when nothing is in flight.
76
+ *
77
+ * Without this, two Claude windows on one checkout would both surface
78
+ * whichever task was globally first/most-recent — wrong frame.
79
+ */
80
+ export function resolveSessionTaskId(repoRoot, sessionId) {
81
+ const activeDir = cairnDir(repoRoot, "tasks", "active");
82
+ if (!existsSync(activeDir))
83
+ return null;
84
+ let dirents;
85
+ try {
86
+ dirents = readdirSync(activeDir, { withFileTypes: true, encoding: "utf8" });
87
+ }
88
+ catch {
89
+ return null;
90
+ }
91
+ const sid = sessionId !== null && sessionId.length > 0 ? sessionId : null;
92
+ const candidates = [];
93
+ for (const e of dirents) {
94
+ if (!e.isDirectory())
95
+ continue;
96
+ const statusPath = join(activeDir, e.name, "status.yaml");
57
97
  if (!existsSync(statusPath))
58
98
  continue;
59
99
  let parsed;
@@ -65,29 +105,60 @@ export function readActiveTaskSummary(repoRoot) {
65
105
  }
66
106
  if (typeof parsed !== "object" || parsed === null)
67
107
  continue;
68
- const phase = parsed.phase;
108
+ const o = parsed;
109
+ const phase = o["phase"];
69
110
  if (typeof phase !== "string" || !ACTIVE_PHASES.has(phase))
70
111
  continue;
71
- let title = e.name;
72
- const specPath = join(taskDir, "spec.tightened.md");
73
- if (existsSync(specPath)) {
74
- try {
75
- const specText = readFileSync(specPath, "utf8");
76
- const body = parseFrontmatter(specText).body;
77
- const m = body.match(/^#\s+(.+)$/m);
78
- if (m && m[1])
79
- title = m[1].trim();
80
- }
81
- catch {
82
- // fall through to taskId
83
- }
112
+ let mtimeMs = 0;
113
+ try {
114
+ mtimeMs = statSync(statusPath).mtimeMs;
84
115
  }
85
- return {
86
- taskId: e.name,
87
- taskState: mapPhase(phase),
88
- taskModule: title,
89
- };
116
+ catch {
117
+ // keep 0 — undated tasks sort last
118
+ }
119
+ const owned = sid !== null &&
120
+ (o["last_journal_session"] === sid || o["created_by_session"] === sid);
121
+ candidates.push({ taskId: e.name, mtimeMs, owned });
90
122
  }
91
- return null;
123
+ if (candidates.length === 0)
124
+ return null;
125
+ const byRecent = (a, b) => b.mtimeMs - a.mtimeMs;
126
+ const owned = candidates.filter((c) => c.owned).sort(byRecent);
127
+ if (owned.length > 0)
128
+ return owned[0].taskId;
129
+ return candidates.sort(byRecent)[0].taskId;
130
+ }
131
+ /** Read one active task dir into a summary, or null when not in-flight. */
132
+ function summarizeActiveTask(taskDir, taskId) {
133
+ const statusPath = join(taskDir, "status.yaml");
134
+ if (!existsSync(statusPath))
135
+ return null;
136
+ let parsed;
137
+ try {
138
+ parsed = parseYaml(readFileSync(statusPath, "utf8"));
139
+ }
140
+ catch {
141
+ return null;
142
+ }
143
+ if (typeof parsed !== "object" || parsed === null)
144
+ return null;
145
+ const phase = parsed.phase;
146
+ if (typeof phase !== "string" || !ACTIVE_PHASES.has(phase))
147
+ return null;
148
+ let title = taskId;
149
+ const specPath = join(taskDir, "spec.tightened.md");
150
+ if (existsSync(specPath)) {
151
+ try {
152
+ const specText = readFileSync(specPath, "utf8");
153
+ const body = parseFrontmatter(specText).body;
154
+ const m = body.match(/^#\s+(.+)$/m);
155
+ if (m && m[1])
156
+ title = m[1].trim();
157
+ }
158
+ catch {
159
+ // fall through to taskId
160
+ }
161
+ }
162
+ return { taskId, taskState: mapPhase(phase), taskModule: title };
92
163
  }
93
164
  //# sourceMappingURL=task-summary.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"task-summary.js","sourceRoot":"","sources":["../../src/context/task-summary.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"task-summary.js","sourceRoot":"","sources":["../../src/context/task-summary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Working-context header — the context engine's stage-1 surface.
3
+ *
4
+ * Per prompt (UserPromptSubmit), the server injects a compact "what am
5
+ * I working on" frame so the agent never has to call `cairn_in_scope` /
6
+ * `cairn_mission_get` to know its frame. This module builds that text +
7
+ * a fingerprint; the runner injects it only when the fingerprint
8
+ * changed (per-session dedup via session/seen.ts).
9
+ *
10
+ * The header is the PERSISTENT in-scope id INDEX (every prompt) — ids
11
+ * only, no bodies. The stage-2 read-enricher shows each DEC/INV/
12
+ * component BODY once per session. So the agent always knows WHAT is in
13
+ * scope (this header) even after a body scrolled off (D13).
14
+ *
15
+ * Pure-FS, zero LLM — safe to run on every prompt inside a hook.
16
+ *
17
+ * Spec: docs/CONTEXT_ENGINE.md (stage 1), CAIRN_REBUILD §6 / D11–D13.
18
+ */
19
+ export interface WorkingHeader {
20
+ text: string;
21
+ fingerprint: string;
22
+ }
23
+ /**
24
+ * Build the working-context header for the repo's current frame, or
25
+ * null when there is no active task AND no active mission (D11 — inject
26
+ * nothing extra). When a task is active but has no in-scope ids, the
27
+ * "In scope" line is omitted (active-task line only).
28
+ */
29
+ export declare function buildWorkingHeader(repoRoot: string, sessionId: string | null): WorkingHeader | null;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Working-context header — the context engine's stage-1 surface.
3
+ *
4
+ * Per prompt (UserPromptSubmit), the server injects a compact "what am
5
+ * I working on" frame so the agent never has to call `cairn_in_scope` /
6
+ * `cairn_mission_get` to know its frame. This module builds that text +
7
+ * a fingerprint; the runner injects it only when the fingerprint
8
+ * changed (per-session dedup via session/seen.ts).
9
+ *
10
+ * The header is the PERSISTENT in-scope id INDEX (every prompt) — ids
11
+ * only, no bodies. The stage-2 read-enricher shows each DEC/INV/
12
+ * component BODY once per session. So the agent always knows WHAT is in
13
+ * scope (this header) even after a body scrolled off (D13).
14
+ *
15
+ * Pure-FS, zero LLM — safe to run on every prompt inside a hook.
16
+ *
17
+ * Spec: docs/CONTEXT_ENGINE.md (stage 1), CAIRN_REBUILD §6 / D11–D13.
18
+ */
19
+ import { cairnDir, findActiveMission, readMissionState, readRoadmap, } from "@isaacriehm/cairn-state";
20
+ import { resolveSessionTaskId, readTaskSummaryById } from "./task-summary.js";
21
+ import { readTaskMissionAnchor } from "../missions/index.js";
22
+ import { readTaskSpec } from "../tasks/spec-reader.js";
23
+ import { fingerprintText } from "../session/seen.js";
24
+ const GOAL_MAX = 120;
25
+ const ID_LIST_CAP = 12;
26
+ /** Truncate at a word boundary, appending `…` when cut. */
27
+ function truncateAtWord(s, max) {
28
+ const flat = s.replace(/\s+/g, " ").trim();
29
+ if (flat.length <= max)
30
+ return flat;
31
+ const slice = flat.slice(0, max);
32
+ const lastSpace = slice.lastIndexOf(" ");
33
+ const cut = lastSpace > max * 0.6 ? slice.slice(0, lastSpace) : slice;
34
+ return `${cut.trimEnd()}…`;
35
+ }
36
+ /** Render up to `cap` ids, then `(+N more)`. Empty → "". */
37
+ function renderIdList(ids, cap) {
38
+ if (ids.length === 0)
39
+ return "";
40
+ const head = ids.slice(0, cap);
41
+ const extra = ids.length - head.length;
42
+ const base = head.join(", ");
43
+ return extra > 0 ? `${base} (+${extra} more)` : base;
44
+ }
45
+ /**
46
+ * Build the working-context header for the repo's current frame, or
47
+ * null when there is no active task AND no active mission (D11 — inject
48
+ * nothing extra). When a task is active but has no in-scope ids, the
49
+ * "In scope" line is omitted (active-task line only).
50
+ */
51
+ export function buildWorkingHeader(repoRoot, sessionId) {
52
+ // Resolve the task THIS session is on (affinity), not a global pick —
53
+ // correct when multiple tasks are active across windows.
54
+ const taskId = resolveSessionTaskId(repoRoot, sessionId);
55
+ const active = taskId !== null ? readTaskSummaryById(repoRoot, taskId) : null;
56
+ // Mission: prefer the resolved task's own anchor (the mission + phase
57
+ // this session is working) over a global scan — correct when several
58
+ // missions are active. Fall back to the single active mission only
59
+ // when there's no task to anchor on.
60
+ const anchor = active !== null ? readTaskMissionAnchor(repoRoot, active.taskId) : null;
61
+ const missionId = anchor?.mission_id ?? findActiveMission(repoRoot);
62
+ const preferredPhaseId = anchor?.phase_id ?? null;
63
+ if (active === null && missionId === null)
64
+ return null;
65
+ const lines = ["## Cairn — working context"];
66
+ let hasInScope = false;
67
+ if (active !== null) {
68
+ const spec = readTaskSpec(cairnDir(repoRoot, "tasks", "active", active.taskId));
69
+ const goal = spec !== null && spec.goal.length > 0 ? spec.goal : "";
70
+ const parts = [`Active: ${active.taskId} (${active.taskState})`];
71
+ if (goal.length > 0)
72
+ parts.push(`— ${truncateAtWord(goal, GOAL_MAX)}`);
73
+ if (active.taskModule.length > 0 && active.taskModule !== active.taskId) {
74
+ parts.push(`· module ${active.taskModule}`);
75
+ }
76
+ lines.push(parts.join(" "));
77
+ const decs = spec?.inScopeDecisions ?? [];
78
+ const invs = spec?.inScopeInvariants ?? [];
79
+ if (decs.length > 0 || invs.length > 0) {
80
+ hasInScope = true;
81
+ const segs = [];
82
+ if (decs.length > 0)
83
+ segs.push(renderIdList(decs, ID_LIST_CAP));
84
+ if (invs.length > 0)
85
+ segs.push(renderIdList(invs, ID_LIST_CAP));
86
+ lines.push(`In scope: ${segs.join(" · ")}`);
87
+ }
88
+ }
89
+ if (missionId !== null) {
90
+ const missionLine = renderMissionLine(repoRoot, missionId, preferredPhaseId);
91
+ if (missionLine !== null)
92
+ lines.push(missionLine);
93
+ }
94
+ if (hasInScope) {
95
+ lines.push("Bodies on demand: cairn_decision_get / cairn_invariant_get.");
96
+ }
97
+ const text = lines.join("\n");
98
+ return { text, fingerprint: fingerprintText(text) };
99
+ }
100
+ /**
101
+ * `Mission: <title> — phase <i>/<n> "<phase title>"`. Degrades to a
102
+ * title-only line when the cursor phase can't be located, and to null
103
+ * when the mission state/roadmap is unreadable (D-graceful: never throw).
104
+ */
105
+ function renderMissionLine(repoRoot, missionId, preferredPhaseId) {
106
+ const roadmap = readRoadmap(repoRoot, missionId);
107
+ const state = readMissionState(repoRoot, missionId);
108
+ if (roadmap === null)
109
+ return null;
110
+ const title = roadmap.frontmatter.title;
111
+ const phases = roadmap.frontmatter.phases;
112
+ // The task anchor's phase wins (the phase THIS session is working);
113
+ // fall back to the mission cursor when there's no task anchor.
114
+ const activePhase = preferredPhaseId ?? state?.cursor.active_phase ?? null;
115
+ if (activePhase !== null) {
116
+ const idx = phases.findIndex((p) => p.id === activePhase);
117
+ if (idx >= 0) {
118
+ const phase = phases[idx];
119
+ const phaseTitle = phase !== undefined ? phase.title : activePhase;
120
+ return `Mission: ${title} — phase ${idx + 1}/${phases.length} "${phaseTitle}"`;
121
+ }
122
+ }
123
+ return `Mission: ${title}`;
124
+ }
125
+ //# sourceMappingURL=working-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"working-header.js","sourceRoot":"","sources":["../../src/context/working-header.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EACL,QAAQ,EACR,iBAAiB,EACjB,gBAAgB,EAChB,WAAW,GACZ,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC9E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAOrD,MAAM,QAAQ,GAAG,GAAG,CAAC;AACrB,MAAM,WAAW,GAAG,EAAE,CAAC;AAEvB,2DAA2D;AAC3D,SAAS,cAAc,CAAC,CAAS,EAAE,GAAW;IAC5C,MAAM,IAAI,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,IAAI,CAAC,MAAM,IAAI,GAAG;QAAE,OAAO,IAAI,CAAC;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACjC,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,SAAS,GAAG,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACtE,OAAO,GAAG,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC;AAC7B,CAAC;AAED,4DAA4D;AAC5D,SAAS,YAAY,CAAC,GAAa,EAAE,GAAW;IAC9C,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAChC,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC;IACvC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC7B,OAAO,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAgB,EAChB,SAAwB;IAExB,sEAAsE;IACtE,yDAAyD;IACzD,MAAM,MAAM,GAAG,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAE9E,sEAAsE;IACtE,qEAAqE;IACrE,mEAAmE;IACnE,qCAAqC;IACrC,MAAM,MAAM,GACV,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1E,MAAM,SAAS,GAAG,MAAM,EAAE,UAAU,IAAI,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACpE,MAAM,gBAAgB,GAAG,MAAM,EAAE,QAAQ,IAAI,IAAI,CAAC;IAElD,IAAI,MAAM,KAAK,IAAI,IAAI,SAAS,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEvD,MAAM,KAAK,GAAa,CAAC,4BAA4B,CAAC,CAAC;IAEvD,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,MAAM,IAAI,GAAG,YAAY,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;QAChF,MAAM,IAAI,GAAG,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,MAAM,KAAK,GAAa,CAAC,WAAW,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,SAAS,GAAG,CAAC,CAAC;QAC3E,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,cAAc,CAAC,IAAI,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvE,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC;YACxE,KAAK,CAAC,IAAI,CAAC,YAAY,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAE5B,MAAM,IAAI,GAAG,IAAI,EAAE,gBAAgB,IAAI,EAAE,CAAC;QAC1C,MAAM,IAAI,GAAG,IAAI,EAAE,iBAAiB,IAAI,EAAE,CAAC;QAC3C,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvC,UAAU,GAAG,IAAI,CAAC;YAClB,MAAM,IAAI,GAAa,EAAE,CAAC;YAC1B,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;YAChE,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;gBAAE,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC;YAChE,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC9C,CAAC;IACH,CAAC;IAED,IAAI,SAAS,KAAK,IAAI,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,gBAAgB,CAAC,CAAC;QAC7E,IAAI,WAAW,KAAK,IAAI;YAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,UAAU,EAAE,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,6DAA6D,CAAC,CAAC;IAC5E,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9B,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,eAAe,CAAC,IAAI,CAAC,EAAE,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,SAAS,iBAAiB,CACxB,QAAgB,EAChB,SAAiB,EACjB,gBAA+B;IAE/B,MAAM,OAAO,GAAG,WAAW,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACpD,IAAI,OAAO,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAElC,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,KAAK,CAAC;IACxC,MAAM,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,MAAM,CAAC;IAC1C,oEAAoE;IACpE,+DAA+D;IAC/D,MAAM,WAAW,GAAG,gBAAgB,IAAI,KAAK,EAAE,MAAM,CAAC,YAAY,IAAI,IAAI,CAAC;IAE3E,IAAI,WAAW,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,WAAW,CAAC,CAAC;QAC1D,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;YACb,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;YAC1B,MAAM,UAAU,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,WAAW,CAAC;YACnE,OAAO,YAAY,KAAK,YAAY,GAAG,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,GAAG,CAAC;QACjF,CAAC;IACH,CAAC;IACD,OAAO,YAAY,KAAK,EAAE,CAAC;AAC7B,CAAC"}
@@ -8,6 +8,7 @@
8
8
  import { z } from "zod";
9
9
  import { relative, resolve } from "node:path";
10
10
  import { resolveRepoRoot } from "../../session-start/index.js";
11
+ import { appendTouched } from "../../session/index.js";
11
12
  import { readHookStdin } from "../runners/payload.js";
12
13
  import { executeSotAlign } from "./sot-align.js";
13
14
  import { executeWriteGuardian } from "./write-guardian.js";
@@ -93,6 +94,21 @@ export async function runPostWriteHook() {
93
94
  // gitignore / glob / scope-index lookups all expect a repo-relative
94
95
  // path, so normalize here before handing it over.
95
96
  const relPath = relative(repoRoot, resolve(cwd, filePath));
97
+ // Stage-3 (D6): record the touched path so the Stop capture-gate can
98
+ // later filter to component-dir files missing a @cairn header. Best-
99
+ // effort, before the guard block — PostToolUse fires after the write
100
+ // landed, so the file is on disk regardless of the guard hint.
101
+ const sessionId = typeof payload.session_id === "string" && payload.session_id.length > 0
102
+ ? payload.session_id
103
+ : null;
104
+ if (sessionId !== null) {
105
+ try {
106
+ appendTouched(repoRoot, sessionId, relPath);
107
+ }
108
+ catch {
109
+ // best-effort — never affect the write
110
+ }
111
+ }
96
112
  const guard = executeWriteGuardian({
97
113
  repoRoot,
98
114
  relPath,
@@ -1 +1 @@
1
- {"version":3,"file":"post-write.js","sourceRoot":"","sources":["../../../src/hooks/post-tool-use/post-write.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"post-write.js","sourceRoot":"","sources":["../../../src/hooks/post-tool-use/post-write.ts"],"names":[],"mappings":"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"}
@@ -14,11 +14,12 @@
14
14
  */
15
15
  import { resolve, relative } from "node:path";
16
16
  import { z } from "zod";
17
- import { getDecisionsLedger, getInvariantsLedger, getScopeIndexEntry, } from "@isaacriehm/cairn-state";
17
+ import { componentsInScope, getDecisionsLedger, getInvariantsLedger, getScopeIndexEntry, hasComponentConfig, loadComponentsConfig, } from "@isaacriehm/cairn-state";
18
18
  import { readHookStdin, emitShapeB, appendTelemetry, } from "../runners/payload.js";
19
19
  import { resolveRepoRoot } from "../../session-start/index.js";
20
20
  import { scanCitations } from "./citation-scanner.js";
21
21
  import { buildLegend } from "./legend-builder.js";
22
+ import { filterUnshownIds, hasShownId, markShownIds } from "../../session/index.js";
22
23
  import { logger } from "../../logger.js";
23
24
  const MAX_CONTENT_BYTES = 512_000;
24
25
  const BINARY_SAMPLE_BYTES = 1024;
@@ -86,21 +87,88 @@ export async function runReadEnricher() {
86
87
  emitShapeB("", "PostToolUse");
87
88
  return;
88
89
  }
90
+ const sessionId = typeof payload.session_id === "string" && payload.session_id.length > 0
91
+ ? payload.session_id
92
+ : null;
89
93
  const citations = scanCitations(content);
90
94
  const scopeEntry = getScopeIndexEntry(repoRoot, relPath);
91
95
  const decisionsLedger = getDecisionsLedger(repoRoot);
92
96
  const invariantsLedger = getInvariantsLedger(repoRoot);
93
- const legend = buildLegend(citations, invariantsLedger, decisionsLedger, scopeEntry);
97
+ // Stage-2 dedup (D13): the stage-1 working header carries the
98
+ // persistent in-scope id INDEX, so the enricher renders each cited
99
+ // DEC/INV BODY at most once per session. Re-reads of the same file
100
+ // no longer re-inject the (bulky) title lines.
101
+ const citedIds = [
102
+ ...citations.decisions.map((d) => d.id),
103
+ ...citations.invariants.map((i) => i.id),
104
+ ];
105
+ const freshIds = sessionId !== null
106
+ ? new Set(filterUnshownIds(repoRoot, sessionId, citedIds))
107
+ : new Set(citedIds);
108
+ const freshCitations = {
109
+ decisions: citations.decisions.filter((d) => freshIds.has(d.id)),
110
+ invariants: citations.invariants.filter((i) => freshIds.has(i.id)),
111
+ };
112
+ // The stage-1 working header is the persistent in-scope id index, so
113
+ // the enricher's file-scope box ("Decisions/Invariants in scope")
114
+ // renders at most once per file per session. Without this, every
115
+ // re-read of a scoped file re-injects the box — the over-injection
116
+ // the engine exists to avoid (D13).
117
+ const scopeKey = `scope:${relPath}`;
118
+ const showScope = scopeEntry !== null &&
119
+ (sessionId === null || !hasShownId(repoRoot, sessionId, scopeKey));
120
+ const legend = buildLegend(freshCitations, invariantsLedger, decisionsLedger, showScope ? scopeEntry : null);
121
+ // Stage-2 component slice (D17): when the agent reads a file under a
122
+ // component dir, attach the entitled inventory (name · category ·
123
+ // purpose · [S]) once per component per session — replacing the
124
+ // agent's need to classify "UI work" and call components_in_scope.
125
+ let componentSlice = "";
126
+ const shownComponentKeys = [];
127
+ try {
128
+ const config = loadComponentsConfig(repoRoot);
129
+ if (hasComponentConfig(config) && fileInComponentDir(config, relPath)) {
130
+ const scope = componentsInScope(repoRoot, [relPath]);
131
+ const keys = scope.components.map((c) => `comp:${c.name}`);
132
+ const freshCompKeys = sessionId !== null
133
+ ? new Set(filterUnshownIds(repoRoot, sessionId, keys))
134
+ : new Set(keys);
135
+ const freshComponents = scope.components.filter((c) => freshCompKeys.has(`comp:${c.name}`));
136
+ if (freshComponents.length > 0) {
137
+ componentSlice = renderComponentSlice(freshComponents);
138
+ for (const c of freshComponents)
139
+ shownComponentKeys.push(`comp:${c.name}`);
140
+ }
141
+ }
142
+ }
143
+ catch {
144
+ // component config is optional — never block the read on it
145
+ }
146
+ // Mark shown AFTER building so a crash before this point leaves the
147
+ // ids un-shown (they surface on the next read instead of vanishing).
148
+ if (sessionId !== null) {
149
+ const toMark = [
150
+ ...freshIds,
151
+ ...shownComponentKeys,
152
+ ...(showScope ? [scopeKey] : []),
153
+ ];
154
+ if (toMark.length > 0)
155
+ markShownIds(repoRoot, sessionId, toMark);
156
+ }
157
+ const combined = [legend ?? "", componentSlice]
158
+ .filter((s) => s.length > 0)
159
+ .join("\n\n");
94
160
  outcome = {
95
161
  ok: true,
96
162
  path: relPath,
97
163
  citations: {
98
164
  invariants: citations.invariants.length,
99
165
  decisions: citations.decisions.length,
166
+ fresh: freshCitations.invariants.length + freshCitations.decisions.length,
100
167
  },
101
- legend_chars: legend?.length ?? 0,
168
+ components_shown: shownComponentKeys.length,
169
+ legend_chars: combined.length,
102
170
  };
103
- emitShapeB(legend ?? "", "PostToolUse");
171
+ emitShapeB(combined, "PostToolUse");
104
172
  }
105
173
  catch (err) {
106
174
  const message = err instanceof Error ? err.message : String(err);
@@ -164,4 +232,28 @@ function isBinary(content) {
164
232
  }
165
233
  return nullCount / sampleLen > BINARY_THRESHOLD;
166
234
  }
235
+ /** True when `relPath` sits inside any workspace's component dir. */
236
+ function fileInComponentDir(config, relPath) {
237
+ const p = relPath.replace(/\\/g, "/");
238
+ for (const ws of config.workspaces) {
239
+ for (const dir of ws.componentDirs) {
240
+ if (p === dir || p.startsWith(`${dir}/`))
241
+ return true;
242
+ }
243
+ }
244
+ return false;
245
+ }
246
+ /** Render the deduped component slice (D17): name · category · purpose · [S]. */
247
+ function renderComponentSlice(components) {
248
+ const lines = [
249
+ "## Cairn — components in scope (USE > EXTEND > CREATE)",
250
+ ];
251
+ for (const c of components) {
252
+ const flag = c.singleton ? " [S]" : "";
253
+ const purpose = c.purpose.length > 0 ? ` · ${c.purpose}` : "";
254
+ lines.push(`- ${c.name} · ${c.category}${purpose}${flag}`);
255
+ }
256
+ lines.push("`[S]` = singleton: extend in place, never fork or rebuild.");
257
+ return lines.join("\n");
258
+ }
167
259
  //# sourceMappingURL=read-enricher.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"read-enricher.js","sourceRoot":"","sources":["../../../src/hooks/post-tool-use/read-enricher.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"read-enricher.js","sourceRoot":"","sources":["../../../src/hooks/post-tool-use/read-enricher.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Component-annotate capture-gate surface (context engine, stage 3).
3
+ *
4
+ * Mirrors phase-ready-surface: the Stop hook detects components the
5
+ * session touched that still lack a `@cairn` header, pre-derives their
6
+ * mechanical fields (export symbol, allowed categories), and stashes a
7
+ * fully-specified ask to `.cairn/sessions/<id>/annotate-pending.json`.
8
+ * The next UserPromptSubmit injects it as `additionalContext` — inject-
9
+ * only, no Stop block. The pre-commit component check is the hard
10
+ * backstop; this is the deferred nudge.
11
+ *
12
+ * The agent supplies only judgment (category, purpose, aliases); the
13
+ * server holds the grammar + validation in `cairn_component_annotate`.
14
+ *
15
+ * Spec: docs/CONTEXT_ENGINE.md (stage 3), CAIRN_REBUILD §8 / D5–D9.
16
+ */
17
+ export interface AnnotateAsk {
18
+ /** Repo-relative POSIX path of the component file missing a header. */
19
+ file: string;
20
+ /** Best-effort detected export symbol, or null when undetectable. */
21
+ export_name: string | null;
22
+ /** The owning workspace's allowed `@category` taxonomy. */
23
+ categories: string[];
24
+ }
25
+ /**
26
+ * Collect the component-dir files this session touched that still lack a
27
+ * `@cairn` header, skipping any already surfaced (`annotate:<file>` in
28
+ * seen.shownIds — the once-per-component debounce, D5). Pure read; the
29
+ * caller marks shown after stashing. Returns [] for non-component repos.
30
+ */
31
+ export declare function collectAnnotateAsks(repoRoot: string, sessionId: string): AnnotateAsk[];
32
+ /** Persist the asks for the next UPS to inject. Latest set wins. */
33
+ export declare function writeAnnotatePending(repoRoot: string, sessionId: string, asks: AnnotateAsk[]): void;
34
+ /** Read + delete the pending file (show-once). Null when absent/malformed. */
35
+ export declare function readAndConsumeAnnotatePending(repoRoot: string, sessionId: string): AnnotateAsk[] | null;
36
+ /**
37
+ * Render the fully-specified annotate ask. The agent supplies only
38
+ * judgment; the `cairn_component_annotate` call template carries the
39
+ * mechanical fields the server already derived.
40
+ */
41
+ export declare function renderAnnotateHint(asks: AnnotateAsk[]): string;