@isaacriehm/cairn-core 0.4.3 → 0.5.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 (162) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/align-undo/index.d.ts +6 -0
  3. package/dist/align-undo/index.js +6 -0
  4. package/dist/align-undo/index.js.map +1 -0
  5. package/dist/align-undo/log.d.ts +53 -0
  6. package/dist/align-undo/log.js +99 -0
  7. package/dist/align-undo/log.js.map +1 -0
  8. package/dist/align-undo/undo.d.ts +66 -0
  9. package/dist/align-undo/undo.js +187 -0
  10. package/dist/align-undo/undo.js.map +1 -0
  11. package/dist/attention/dedup.js +1 -47
  12. package/dist/attention/dedup.js.map +1 -1
  13. package/dist/drain/drain.d.ts +77 -0
  14. package/dist/drain/drain.js +464 -0
  15. package/dist/drain/drain.js.map +1 -0
  16. package/dist/drain/index.d.ts +5 -0
  17. package/dist/drain/index.js +5 -0
  18. package/dist/drain/index.js.map +1 -0
  19. package/dist/fix-align/index.d.ts +5 -0
  20. package/dist/fix-align/index.js +5 -0
  21. package/dist/fix-align/index.js.map +1 -0
  22. package/dist/fix-align/run.d.ts +99 -0
  23. package/dist/fix-align/run.js +258 -0
  24. package/dist/fix-align/run.js.map +1 -0
  25. package/dist/ground/alignment-pending.d.ts +28 -0
  26. package/dist/ground/alignment-pending.js +83 -0
  27. package/dist/ground/alignment-pending.js.map +1 -0
  28. package/dist/ground/anchor-map.d.ts +14 -0
  29. package/dist/ground/anchor-map.js +57 -0
  30. package/dist/ground/anchor-map.js.map +1 -0
  31. package/dist/ground/index.d.ts +9 -2
  32. package/dist/ground/index.js +8 -2
  33. package/dist/ground/index.js.map +1 -1
  34. package/dist/ground/paths.d.ts +21 -0
  35. package/dist/ground/paths.js +43 -0
  36. package/dist/ground/paths.js.map +1 -1
  37. package/dist/ground/schemas.d.ts +201 -0
  38. package/dist/ground/schemas.js +126 -1
  39. package/dist/ground/schemas.js.map +1 -1
  40. package/dist/ground/slug.d.ts +60 -0
  41. package/dist/ground/slug.js +103 -0
  42. package/dist/ground/slug.js.map +1 -0
  43. package/dist/ground/sot-bindings.d.ts +14 -0
  44. package/dist/ground/sot-bindings.js +80 -0
  45. package/dist/ground/sot-bindings.js.map +1 -0
  46. package/dist/ground/sot-cache.d.ts +18 -0
  47. package/dist/ground/sot-cache.js +63 -0
  48. package/dist/ground/sot-cache.js.map +1 -0
  49. package/dist/ground/topic-index.d.ts +20 -0
  50. package/dist/ground/topic-index.js +60 -0
  51. package/dist/ground/topic-index.js.map +1 -0
  52. package/dist/hooks/post-tool-use/index.d.ts +2 -0
  53. package/dist/hooks/post-tool-use/index.js +1 -0
  54. package/dist/hooks/post-tool-use/index.js.map +1 -1
  55. package/dist/hooks/post-tool-use/sot-align.d.ts +166 -0
  56. package/dist/hooks/post-tool-use/sot-align.js +1311 -0
  57. package/dist/hooks/post-tool-use/sot-align.js.map +1 -0
  58. package/dist/hooks/pre-commit/index.d.ts +8 -0
  59. package/dist/hooks/pre-commit/index.js +8 -0
  60. package/dist/hooks/pre-commit/index.js.map +1 -0
  61. package/dist/hooks/pre-commit/sot-align-precommit.d.ts +60 -0
  62. package/dist/hooks/pre-commit/sot-align-precommit.js +221 -0
  63. package/dist/hooks/pre-commit/sot-align-precommit.js.map +1 -0
  64. package/dist/hooks/runners/session-start.js +41 -0
  65. package/dist/hooks/runners/session-start.js.map +1 -1
  66. package/dist/hooks/sot-align-common.d.ts +39 -0
  67. package/dist/hooks/sot-align-common.js +152 -0
  68. package/dist/hooks/sot-align-common.js.map +1 -0
  69. package/dist/index.d.ts +5 -0
  70. package/dist/index.js +5 -0
  71. package/dist/index.js.map +1 -1
  72. package/dist/init/index.d.ts +4 -2
  73. package/dist/init/index.js +2 -1
  74. package/dist/init/index.js.map +1 -1
  75. package/dist/init/ingest-docs.d.ts +30 -47
  76. package/dist/init/ingest-docs.js +113 -410
  77. package/dist/init/ingest-docs.js.map +1 -1
  78. package/dist/init/init.d.ts +8 -0
  79. package/dist/init/init.js +58 -29
  80. package/dist/init/init.js.map +1 -1
  81. package/dist/init/phases/5-brand.js +1 -1
  82. package/dist/init/phases/5-brand.js.map +1 -1
  83. package/dist/init/phases/5b-topic-index.d.ts +30 -0
  84. package/dist/init/phases/5b-topic-index.js +62 -0
  85. package/dist/init/phases/5b-topic-index.js.map +1 -0
  86. package/dist/init/phases/6-docs-ingest.d.ts +4 -5
  87. package/dist/init/phases/6-docs-ingest.js +5 -6
  88. package/dist/init/phases/6-docs-ingest.js.map +1 -1
  89. package/dist/init/phases/index.d.ts +2 -0
  90. package/dist/init/phases/index.js +1 -0
  91. package/dist/init/phases/index.js.map +1 -1
  92. package/dist/init/phases/parallel-678.d.ts +14 -17
  93. package/dist/init/phases/parallel-678.js +77 -98
  94. package/dist/init/phases/parallel-678.js.map +1 -1
  95. package/dist/init/phases/source-comments-output-io.d.ts +16 -10
  96. package/dist/init/phases/source-comments-output-io.js +7 -10
  97. package/dist/init/phases/source-comments-output-io.js.map +1 -1
  98. package/dist/init/phases/types.d.ts +1 -1
  99. package/dist/init/phases/types.js +1 -0
  100. package/dist/init/phases/types.js.map +1 -1
  101. package/dist/init/rules-merge/discover.d.ts +8 -3
  102. package/dist/init/rules-merge/discover.js +7 -3
  103. package/dist/init/rules-merge/discover.js.map +1 -1
  104. package/dist/init/rules-merge/ingest.d.ts +81 -28
  105. package/dist/init/rules-merge/ingest.js +456 -162
  106. package/dist/init/rules-merge/ingest.js.map +1 -1
  107. package/dist/init/sot-emit.d.ts +84 -0
  108. package/dist/init/sot-emit.js +218 -0
  109. package/dist/init/sot-emit.js.map +1 -0
  110. package/dist/init/source-comments/classify.d.ts +12 -10
  111. package/dist/init/source-comments/classify.js +13 -25
  112. package/dist/init/source-comments/classify.js.map +1 -1
  113. package/dist/init/source-comments/index.d.ts +1 -1
  114. package/dist/init/source-comments/index.js +1 -1
  115. package/dist/init/source-comments/index.js.map +1 -1
  116. package/dist/init/source-comments/ingest.d.ts +91 -67
  117. package/dist/init/source-comments/ingest.js +392 -361
  118. package/dist/init/source-comments/ingest.js.map +1 -1
  119. package/dist/init/topic-index/index.d.ts +36 -0
  120. package/dist/init/topic-index/index.js +46 -0
  121. package/dist/init/topic-index/index.js.map +1 -0
  122. package/dist/init/topic-index/judge.d.ts +20 -0
  123. package/dist/init/topic-index/judge.js +65 -0
  124. package/dist/init/topic-index/judge.js.map +1 -0
  125. package/dist/init/topic-index/resolve.d.ts +50 -0
  126. package/dist/init/topic-index/resolve.js +196 -0
  127. package/dist/init/topic-index/resolve.js.map +1 -0
  128. package/dist/init/topic-index/walk.d.ts +43 -0
  129. package/dist/init/topic-index/walk.js +293 -0
  130. package/dist/init/topic-index/walk.js.map +1 -0
  131. package/dist/mcp/schemas.d.ts +45 -8
  132. package/dist/mcp/schemas.js +43 -7
  133. package/dist/mcp/schemas.js.map +1 -1
  134. package/dist/mcp/tools/align-drain.d.ts +7 -0
  135. package/dist/mcp/tools/align-drain.js +26 -0
  136. package/dist/mcp/tools/align-drain.js.map +1 -0
  137. package/dist/mcp/tools/index.js +3 -0
  138. package/dist/mcp/tools/index.js.map +1 -1
  139. package/dist/mcp/tools/init-phases.js +4 -1
  140. package/dist/mcp/tools/init-phases.js.map +1 -1
  141. package/dist/mcp/tools/resolve-attention.d.ts +2 -2
  142. package/dist/mcp/tools/resolve-attention.js +828 -5
  143. package/dist/mcp/tools/resolve-attention.js.map +1 -1
  144. package/dist/status-line/event-queue.d.ts +40 -0
  145. package/dist/status-line/event-queue.js +195 -0
  146. package/dist/status-line/event-queue.js.map +1 -0
  147. package/dist/status-line/format.d.ts +1 -1
  148. package/dist/status-line/format.js +49 -6
  149. package/dist/status-line/format.js.map +1 -1
  150. package/dist/status-line/index.d.ts +41 -0
  151. package/dist/status-line/index.js +14 -0
  152. package/dist/status-line/index.js.map +1 -1
  153. package/dist/status-line/reader.js +23 -18
  154. package/dist/status-line/reader.js.map +1 -1
  155. package/dist/status-line/writer.d.ts +1 -1
  156. package/dist/status-line/writer.js +5 -0
  157. package/dist/status-line/writer.js.map +1 -1
  158. package/dist/text/jaccard.d.ts +19 -0
  159. package/dist/text/jaccard.js +68 -0
  160. package/dist/text/jaccard.js.map +1 -0
  161. package/package.json +1 -1
  162. package/templates/.cairn/git-hooks/pre-commit +16 -3
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Layer A undo log + `cairn attention undo` runner. Plan §11.7.
3
+ */
4
+ export { AlignUndoEntry, alignUndoLogPath, appendAlignUndoEntry, pruneAlignUndoLog, readAlignUndoLog, } from "./log.js";
5
+ export { runAttentionUndo } from "./undo.js";
6
+ export type { UndoArgs, UndoEntryOutcome, UndoResult } from "./undo.js";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Layer A undo log + `cairn attention undo` runner. Plan §11.7.
3
+ */
4
+ export { AlignUndoEntry, alignUndoLogPath, appendAlignUndoEntry, pruneAlignUndoLog, readAlignUndoLog, } from "./log.js";
5
+ export { runAttentionUndo } from "./undo.js";
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/align-undo/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Layer A audit log for `cairn attention undo` (plan §11.7).
3
+ *
4
+ * Every Layer A auto-resolution (Tier 1 cite, Tier 2 same cite, Tier 3
5
+ * fresh DEC creation, augments-DEC/INV emission) appends one line to
6
+ * `.cairn/state/align-undo-log.jsonl`. The CLI command
7
+ * `cairn attention undo [--since <duration>]` reads recent entries and
8
+ * reverses them.
9
+ *
10
+ * The deviation from plan §11.7's literal "reads invalidation events
11
+ * from `.cairn/events/`" — invalidation events are designed for
12
+ * cross-session broadcast (kind, refs, source), not for carrying the
13
+ * (file, offset, original_raw) metadata that undo needs. Keeping the
14
+ * undo log separate avoids polluting the broadcast surface and lets
15
+ * the GC retention policy stay independent.
16
+ *
17
+ * Truncation policy: `cairn attention undo` rewrites the log keeping
18
+ * only entries OUTSIDE the undo window so re-running `undo` against
19
+ * the same window is idempotent.
20
+ */
21
+ import { z } from "zod";
22
+ export declare const AlignUndoEntry: z.ZodObject<{
23
+ ts: z.ZodString;
24
+ session_id: z.ZodOptional<z.ZodNullable<z.ZodString>>;
25
+ kind: z.ZodEnum<{
26
+ "tier1-cite": "tier1-cite";
27
+ "tier2-cite": "tier2-cite";
28
+ "tier3-creation": "tier3-creation";
29
+ augments: "augments";
30
+ }>;
31
+ file: z.ZodString;
32
+ start_offset: z.ZodNumber;
33
+ end_offset: z.ZodNumber;
34
+ original_raw: z.ZodString;
35
+ replacement: z.ZodString;
36
+ primary_id: z.ZodString;
37
+ primary_kind: z.ZodOptional<z.ZodEnum<{
38
+ DEC: "DEC";
39
+ INV: "INV";
40
+ }>>;
41
+ augments_existing_id: z.ZodOptional<z.ZodString>;
42
+ }, z.core.$strip>;
43
+ export type AlignUndoEntry = z.infer<typeof AlignUndoEntry>;
44
+ export declare function alignUndoLogPath(repoRoot: string): string;
45
+ export declare function appendAlignUndoEntry(repoRoot: string, entry: AlignUndoEntry): void;
46
+ export declare function readAlignUndoLog(repoRoot: string): AlignUndoEntry[];
47
+ /**
48
+ * Rewrite the undo log keeping only the entries NOT in `undone`.
49
+ * Idempotency: running `cairn attention undo --since <window>` twice
50
+ * on the same window does nothing the second time because the entries
51
+ * inside the window have already been removed.
52
+ */
53
+ export declare function pruneAlignUndoLog(repoRoot: string, remaining: AlignUndoEntry[]): void;
@@ -0,0 +1,99 @@
1
+ /**
2
+ * Layer A audit log for `cairn attention undo` (plan §11.7).
3
+ *
4
+ * Every Layer A auto-resolution (Tier 1 cite, Tier 2 same cite, Tier 3
5
+ * fresh DEC creation, augments-DEC/INV emission) appends one line to
6
+ * `.cairn/state/align-undo-log.jsonl`. The CLI command
7
+ * `cairn attention undo [--since <duration>]` reads recent entries and
8
+ * reverses them.
9
+ *
10
+ * The deviation from plan §11.7's literal "reads invalidation events
11
+ * from `.cairn/events/`" — invalidation events are designed for
12
+ * cross-session broadcast (kind, refs, source), not for carrying the
13
+ * (file, offset, original_raw) metadata that undo needs. Keeping the
14
+ * undo log separate avoids polluting the broadcast surface and lets
15
+ * the GC retention policy stay independent.
16
+ *
17
+ * Truncation policy: `cairn attention undo` rewrites the log keeping
18
+ * only entries OUTSIDE the undo window so re-running `undo` against
19
+ * the same window is idempotent.
20
+ */
21
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
22
+ import { dirname, join } from "node:path";
23
+ import { z } from "zod";
24
+ import { logger } from "../logger.js";
25
+ const log = logger("align-undo.log");
26
+ export const AlignUndoEntry = z.object({
27
+ ts: z.string(),
28
+ session_id: z.string().nullable().optional(),
29
+ kind: z.enum(["tier1-cite", "tier2-cite", "tier3-creation", "augments"]),
30
+ file: z.string(),
31
+ start_offset: z.number(),
32
+ end_offset: z.number(),
33
+ /** Original prose block raw (incl. comment delimiters) before strip-replace. */
34
+ original_raw: z.string(),
35
+ /** Replacement that was inserted (e.g. `// §DEC-1234567`). */
36
+ replacement: z.string(),
37
+ /** DEC/INV id cited (tier1/tier2 cite) or freshly emitted (tier3 / augments). */
38
+ primary_id: z.string(),
39
+ /** For tier3-creation: was the freshly-emitted entity a DEC or INV? */
40
+ primary_kind: z.enum(["DEC", "INV"]).optional(),
41
+ /** For augments: the existing entity id that was augmented (its cite stays). */
42
+ augments_existing_id: z.string().optional(),
43
+ });
44
+ export function alignUndoLogPath(repoRoot) {
45
+ return join(repoRoot, ".cairn", "state", "align-undo-log.jsonl");
46
+ }
47
+ export function appendAlignUndoEntry(repoRoot, entry) {
48
+ const validated = AlignUndoEntry.parse(entry);
49
+ const path = alignUndoLogPath(repoRoot);
50
+ try {
51
+ mkdirSync(dirname(path), { recursive: true });
52
+ appendFileSync(path, `${JSON.stringify(validated)}\n`, "utf8");
53
+ }
54
+ catch (err) {
55
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, "align-undo log append failed");
56
+ }
57
+ }
58
+ export function readAlignUndoLog(repoRoot) {
59
+ const path = alignUndoLogPath(repoRoot);
60
+ if (!existsSync(path))
61
+ return [];
62
+ const text = readFileSync(path, "utf8");
63
+ if (text.trim().length === 0)
64
+ return [];
65
+ const out = [];
66
+ for (const line of text.split("\n")) {
67
+ const trimmed = line.trim();
68
+ if (trimmed.length === 0)
69
+ continue;
70
+ try {
71
+ out.push(AlignUndoEntry.parse(JSON.parse(trimmed)));
72
+ }
73
+ catch (err) {
74
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, "skipping malformed align-undo entry");
75
+ }
76
+ }
77
+ return out;
78
+ }
79
+ /**
80
+ * Rewrite the undo log keeping only the entries NOT in `undone`.
81
+ * Idempotency: running `cairn attention undo --since <window>` twice
82
+ * on the same window does nothing the second time because the entries
83
+ * inside the window have already been removed.
84
+ */
85
+ export function pruneAlignUndoLog(repoRoot, remaining) {
86
+ const path = alignUndoLogPath(repoRoot);
87
+ try {
88
+ mkdirSync(dirname(path), { recursive: true });
89
+ if (remaining.length === 0) {
90
+ writeFileSync(path, "", "utf8");
91
+ return;
92
+ }
93
+ writeFileSync(path, `${remaining.map((e) => JSON.stringify(e)).join("\n")}\n`, "utf8");
94
+ }
95
+ catch (err) {
96
+ log.warn({ err: err instanceof Error ? err.message : String(err) }, "align-undo log prune failed");
97
+ }
98
+ }
99
+ //# sourceMappingURL=log.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/align-undo/log.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * `cairn attention undo` runner (plan §11.7).
3
+ *
4
+ * Reverses Layer A auto-resolutions logged at
5
+ * `.cairn/state/align-undo-log.jsonl`. The CLI passes `--since
6
+ * <duration>` (default 1h); only entries within the window are
7
+ * undone, the rest stay in the log.
8
+ *
9
+ * Currently reverses:
10
+ *
11
+ * - `tier1-cite` / `tier2-cite` — find the cite line in the current
12
+ * source, swap it back for the original prose block. Idempotent
13
+ * when the source has been hand-edited away from the cite already.
14
+ *
15
+ * Out of scope for v0.5.0 (deferred to v0.6 — these need targeted
16
+ * ledger surgery + sotBindings/sotCache rollback):
17
+ *
18
+ * - `tier3-creation` — would need to delete the DEC/INV file, drop
19
+ * its sotBindings / sotCache / topic-index entries, refresh the
20
+ * ledger, and restore the source. Reported in the undo summary
21
+ * so the operator can hand-resolve.
22
+ *
23
+ * - `augments` — would need to delete the sibling DEC/INV and
24
+ * remove its cite from the double-cite while keeping the
25
+ * existing-id cite in place.
26
+ *
27
+ * Idempotent: the runner truncates undone entries from the log so a
28
+ * second invocation against the same window is a no-op.
29
+ */
30
+ import { type AlignUndoEntry } from "./log.js";
31
+ export interface UndoArgs {
32
+ repoRoot: string;
33
+ /**
34
+ * Wall-clock window. Entries with `ts` newer than `now - sinceMs`
35
+ * are undone. Default 1h.
36
+ */
37
+ sinceMs?: number;
38
+ /** Dry-run: classify entries but do not modify source / log. */
39
+ dryRun?: boolean;
40
+ }
41
+ export interface UndoEntryOutcome {
42
+ entry: AlignUndoEntry;
43
+ /**
44
+ * - `reverted` — source was rewritten back to the original prose.
45
+ * - `already-reverted`— the cite token is no longer in source (operator beat us).
46
+ * - `not-supported` — kind requires manual surgery (tier3-creation, augments).
47
+ * - `source-missing` — source file no longer exists.
48
+ * - `error` — write failed (logged + reported).
49
+ */
50
+ status: "reverted" | "already-reverted" | "not-supported" | "source-missing" | "error";
51
+ detail?: string;
52
+ }
53
+ export interface UndoResult {
54
+ /** Total entries inside the undo window. */
55
+ windowEntries: number;
56
+ /** Entries left in the log because they were outside the window. */
57
+ outsideWindow: number;
58
+ /** Per-entry outcomes for everything inside the window. */
59
+ outcomes: UndoEntryOutcome[];
60
+ reverted: number;
61
+ alreadyReverted: number;
62
+ notSupported: number;
63
+ sourceMissing: number;
64
+ errors: number;
65
+ }
66
+ export declare function runAttentionUndo(args: UndoArgs): Promise<UndoResult>;
@@ -0,0 +1,187 @@
1
+ /**
2
+ * `cairn attention undo` runner (plan §11.7).
3
+ *
4
+ * Reverses Layer A auto-resolutions logged at
5
+ * `.cairn/state/align-undo-log.jsonl`. The CLI passes `--since
6
+ * <duration>` (default 1h); only entries within the window are
7
+ * undone, the rest stay in the log.
8
+ *
9
+ * Currently reverses:
10
+ *
11
+ * - `tier1-cite` / `tier2-cite` — find the cite line in the current
12
+ * source, swap it back for the original prose block. Idempotent
13
+ * when the source has been hand-edited away from the cite already.
14
+ *
15
+ * Out of scope for v0.5.0 (deferred to v0.6 — these need targeted
16
+ * ledger surgery + sotBindings/sotCache rollback):
17
+ *
18
+ * - `tier3-creation` — would need to delete the DEC/INV file, drop
19
+ * its sotBindings / sotCache / topic-index entries, refresh the
20
+ * ledger, and restore the source. Reported in the undo summary
21
+ * so the operator can hand-resolve.
22
+ *
23
+ * - `augments` — would need to delete the sibling DEC/INV and
24
+ * remove its cite from the double-cite while keeping the
25
+ * existing-id cite in place.
26
+ *
27
+ * Idempotent: the runner truncates undone entries from the log so a
28
+ * second invocation against the same window is a no-op.
29
+ */
30
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
31
+ import { join } from "node:path";
32
+ import { logger } from "../logger.js";
33
+ import { pruneAlignUndoLog, readAlignUndoLog, } from "./log.js";
34
+ const log = logger("align-undo.runner");
35
+ const DEFAULT_SINCE_MS = 60 * 60 * 1_000;
36
+ /* -------------------------------------------------------------------------- */
37
+ /* Run */
38
+ /* -------------------------------------------------------------------------- */
39
+ export async function runAttentionUndo(args) {
40
+ const { repoRoot } = args;
41
+ const sinceMs = args.sinceMs ?? DEFAULT_SINCE_MS;
42
+ const dryRun = args.dryRun === true;
43
+ const cutoff = Date.now() - sinceMs;
44
+ const all = readAlignUndoLog(repoRoot);
45
+ const inside = [];
46
+ const outside = [];
47
+ for (const e of all) {
48
+ const tsMs = Date.parse(e.ts);
49
+ if (Number.isFinite(tsMs) && tsMs >= cutoff) {
50
+ inside.push(e);
51
+ }
52
+ else {
53
+ outside.push(e);
54
+ }
55
+ }
56
+ const outcomes = [];
57
+ // Process newest first — undoing in reverse order matches typical
58
+ // operator intent ("undo my last 5 minutes of cites").
59
+ inside.sort((a, b) => Date.parse(b.ts) - Date.parse(a.ts));
60
+ for (const entry of inside) {
61
+ outcomes.push(reverseEntry(repoRoot, entry, dryRun));
62
+ }
63
+ const result = {
64
+ windowEntries: inside.length,
65
+ outsideWindow: outside.length,
66
+ outcomes,
67
+ reverted: outcomes.filter((o) => o.status === "reverted").length,
68
+ alreadyReverted: outcomes.filter((o) => o.status === "already-reverted").length,
69
+ notSupported: outcomes.filter((o) => o.status === "not-supported").length,
70
+ sourceMissing: outcomes.filter((o) => o.status === "source-missing").length,
71
+ errors: outcomes.filter((o) => o.status === "error").length,
72
+ };
73
+ if (!dryRun) {
74
+ // Keep entries that we couldn't undo (not-supported / errors) so
75
+ // the operator can re-attempt or hand-resolve. Entries we
76
+ // reverted (or that were already reverted) are removed.
77
+ const keep = [
78
+ ...outside,
79
+ ...outcomes
80
+ .filter((o) => o.status === "not-supported" || o.status === "error")
81
+ .map((o) => o.entry),
82
+ ];
83
+ pruneAlignUndoLog(repoRoot, keep);
84
+ }
85
+ return result;
86
+ }
87
+ /* -------------------------------------------------------------------------- */
88
+ /* Per-entry reversal */
89
+ /* -------------------------------------------------------------------------- */
90
+ function reverseEntry(repoRoot, entry, dryRun) {
91
+ if (entry.kind === "tier3-creation" || entry.kind === "augments") {
92
+ return {
93
+ entry,
94
+ status: "not-supported",
95
+ detail: entry.kind === "tier3-creation"
96
+ ? "fresh DEC/INV creation undo deferred to v0.6 — manually delete the entity file and restore the source block"
97
+ : "augments-sibling undo deferred to v0.6 — manually delete the sibling and trim the double-cite",
98
+ };
99
+ }
100
+ const abs = join(repoRoot, entry.file);
101
+ if (!existsSync(abs)) {
102
+ return { entry, status: "source-missing", detail: `${entry.file} no longer exists` };
103
+ }
104
+ let source;
105
+ try {
106
+ source = readFileSync(abs, "utf8");
107
+ }
108
+ catch (err) {
109
+ return {
110
+ entry,
111
+ status: "error",
112
+ detail: `cannot read ${entry.file}: ${err instanceof Error ? err.message : String(err)}`,
113
+ };
114
+ }
115
+ // Locate the cite line in the current source. The exact byte offsets
116
+ // recorded at log-time are stale (the strip-replace re-flowed the
117
+ // file), so we search for the literal replacement string instead.
118
+ const replacement = entry.replacement.trimEnd();
119
+ const idx = source.indexOf(replacement);
120
+ if (idx === -1) {
121
+ // Already hand-edited away — operator removed the cite themselves.
122
+ return {
123
+ entry,
124
+ status: "already-reverted",
125
+ detail: `cite "${replacement.trim()}" not found in ${entry.file}`,
126
+ };
127
+ }
128
+ // Swap the replacement (matched + any trailing whitespace until newline) for the original raw.
129
+ // Replacement is typically a one-liner like "// §DEC-aaaaaaa"; we
130
+ // want to preserve indentation if the original raw had any.
131
+ const lineStart = source.lastIndexOf("\n", idx) + 1;
132
+ const lineEnd = source.indexOf("\n", idx + replacement.length);
133
+ const cutEnd = lineEnd === -1 ? source.length : lineEnd;
134
+ const before = source.slice(0, lineStart);
135
+ const after = source.slice(cutEnd);
136
+ // Match the indentation that strip-replace prepended on the cite —
137
+ // leading whitespace from `lineStart` up to the `idx`.
138
+ const indent = source.slice(lineStart, idx);
139
+ const reflowedOriginal = reapplyIndent(entry.original_raw, indent);
140
+ const next = `${before}${reflowedOriginal}${after}`;
141
+ if (!dryRun) {
142
+ try {
143
+ writeFileSync(abs, next, "utf8");
144
+ }
145
+ catch (err) {
146
+ log.warn({ file: entry.file, err: err instanceof Error ? err.message : String(err) }, "align-undo write failed");
147
+ return {
148
+ entry,
149
+ status: "error",
150
+ detail: `cannot write ${entry.file}: ${err instanceof Error ? err.message : String(err)}`,
151
+ };
152
+ }
153
+ }
154
+ return { entry, status: "reverted", detail: `${entry.file}` };
155
+ }
156
+ /**
157
+ * Re-apply the leading indent that the cite line carried so the
158
+ * restored original block lines up at the right column. Most blocks'
159
+ * raw already includes the full indentation — we only prepend `indent`
160
+ * to lines that start without it, which handles JSDoc / line-comment
161
+ * blocks captured at column 0.
162
+ */
163
+ function reapplyIndent(raw, indent) {
164
+ if (indent.length === 0)
165
+ return raw;
166
+ const lines = raw.split("\n");
167
+ const out = [];
168
+ let isFirst = true;
169
+ for (const line of lines) {
170
+ if (isFirst) {
171
+ out.push(line);
172
+ isFirst = false;
173
+ continue;
174
+ }
175
+ if (line.length === 0) {
176
+ out.push(line);
177
+ continue;
178
+ }
179
+ if (line.startsWith(indent) || /^\s/.test(line)) {
180
+ out.push(line);
181
+ continue;
182
+ }
183
+ out.push(`${indent}${line}`);
184
+ }
185
+ return out.join("\n");
186
+ }
187
+ //# sourceMappingURL=undo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"undo.js","sourceRoot":"","sources":["../../src/align-undo/undo.ts"],"names":[],"mappings":"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"}
@@ -20,55 +20,9 @@
20
20
  import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
21
21
  import { join } from "node:path";
22
22
  import { decisionsDir } from "../ground/paths.js";
23
- /* -------------------------------------------------------------------------- */
24
- /* Tokenization */
25
- /* -------------------------------------------------------------------------- */
26
- /**
27
- * Stopwords. Hard-coded English set plus a handful of cairn-domain
28
- * terms that appear in nearly every draft and would otherwise dominate
29
- * Jaccard scores ("rationale", "decision").
30
- */
31
- const STOPWORDS = new Set([
32
- "the", "a", "an", "and", "or", "of", "in", "on", "to", "for", "with",
33
- "by", "from", "is", "are", "was", "were", "be", "been", "being", "has",
34
- "have", "had", "do", "does", "did", "this", "that", "these", "those",
35
- "it", "its", "as", "at", "but", "if", "than", "so", "use", "used",
36
- "using", "via", "out", "off", "up", "our", "their", "one", "two",
37
- "when", "where", "what", "how", "why", "who", "which", "can", "should",
38
- "must", "will", "shall", "may", "not", "no", "any", "all", "some",
39
- "few", "more", "most", "only", "also",
40
- ]);
23
+ import { jaccard, tokenize } from "../text/jaccard.js";
41
24
  /** Default char window of body to fold into the token bag. */
42
25
  const BODY_CHAR_WINDOW = 500;
43
- function stem(w) {
44
- if (w.length <= 4)
45
- return w;
46
- if (w.endsWith("ing"))
47
- return w.slice(0, -3);
48
- if (w.endsWith("ed"))
49
- return w.slice(0, -2);
50
- if (w.endsWith("s") && !w.endsWith("ss"))
51
- return w.slice(0, -1);
52
- return w;
53
- }
54
- function tokenize(text) {
55
- return new Set(text
56
- .toLowerCase()
57
- .replace(/[^a-z0-9\s]/g, " ")
58
- .split(/\s+/)
59
- .map(stem)
60
- .filter((w) => w.length >= 3 && !STOPWORDS.has(w)));
61
- }
62
- function jaccard(a, b) {
63
- if (a.size === 0 && b.size === 0)
64
- return 0;
65
- let inter = 0;
66
- for (const x of a)
67
- if (b.has(x))
68
- inter += 1;
69
- const union = a.size + b.size - inter;
70
- return union === 0 ? 0 : inter / union;
71
- }
72
26
  function parseMinimalFrontmatter(raw) {
73
27
  const m = raw.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);
74
28
  if (m === null || m[1] === undefined || m[2] === undefined) {
@@ -1 +1 @@
1
- {"version":3,"file":"dedup.js","sourceRoot":"","sources":["../../src/attention/dedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,gFAAgF;AAChF,gFAAgF;AAChF,gFAAgF;AAEhF;;;;GAIG;AACH,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC;IACxB,KAAK,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM;IACpE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK;IACtE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO;IACpE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM;IACjE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK;IAChE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,QAAQ;IACtE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM;IACjE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CACtC,CAAC,CAAC;AAEH,8DAA8D;AAC9D,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B,SAAS,IAAI,CAAC,CAAS;IACrB,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC7C,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5C,IAAI,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAChE,OAAO,CAAC,CAAC;AACX,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,GAAG,CACZ,IAAI;SACD,WAAW,EAAE;SACb,OAAO,CAAC,cAAc,EAAE,GAAG,CAAC;SAC5B,KAAK,CAAC,KAAK,CAAC;SACZ,GAAG,CAAC,IAAI,CAAC;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CACrD,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,CAAc,EAAE,CAAc;IAC7C,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,CAAC,CAAC;IAC3C,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,KAAK,IAAI,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAG,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC;IACtC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC;AACzC,CAAC;AAcD,SAAS,uBAAuB,CAAC,GAAW;IAI1C,MAAM,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,oCAAoC,CAAC,CAAC;IAC1D,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC3D,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;IAC/B,CAAC;IACD,MAAM,EAAE,GAAuB,EAAE,CAAC;IAClC,KAAK,MAAM,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QAC9C,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,KAAK,SAAS;YAAE,SAAS;QACxE,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QACrD,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,OAAO,IAAI,GAAG,KAAK,YAAY,IAAI,GAAG,KAAK,gBAAgB,IAAI,GAAG,KAAK,oBAAoB,EAAE,CAAC;YACxH,EAAE,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC;QAChB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5B,CAAC;AAsDD,4DAA4D;AAC5D,MAAM,CAAC,MAAM,0BAA0B,GAAG,GAAG,CAAC;AAC9C,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAC;AAE3C;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAIrC;IACC,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,uBAAuB,CAAC;IACtE,MAAM,iBAAiB,GAAG,IAAI,CAAC,iBAAiB,IAAI,0BAA0B,CAAC;IAC/E,MAAM,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,QAAQ,CAAC,CAAC;IAC1D,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;QACvB,OAAO;YACL,aAAa,EAAE,CAAC;YAChB,QAAQ,EAAE,EAAE;YACZ,gBAAgB,EAAE,CAAC;YACnB,SAAS,EAAE,CAAC;YACZ,cAAc;YACd,iBAAiB;SAClB,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAClE,CAAC,CAAC,QAAQ,CAAC,WAAW,CAAC,CACxB,CAAC;IACF,MAAM,IAAI,GAAkB,EAAE,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QAC3B,IAAI,GAAW,CAAC;QAChB,IAAI,OAAe,CAAC;QACpB,IAAI,CAAC;YACH,GAAG,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;YAChC,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC;QAClC,CAAC;QAAC,MAAM,CAAC;YACP,SAAS;QACX,CAAC;QACD,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;QAClD,MAAM,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC,EAAE,CAAC;QAC3D,IAAI,CAAC,IAAI,CAAC;YACR,EAAE;YACF,IAAI,EAAE,kCAAkC,CAAC,EAAE;YAC3C,KAAK;YACL,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,EAAE;YAC/B,MAAM,EAAE,EAAE,CAAC,cAAc,IAAI,EAAE;YAC/B,UAAU,EAAE,EAAE,CAAC,kBAAkB,IAAI,IAAI;YACzC,MAAM,EAAE,QAAQ,CAAC,IAAI,CAAC;YACtB,OAAO;SACR,CAAC,CAAC;IACL,CAAC;IACD,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;IACtB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACZ,OAAO;YACL,aAAa,EAAE,CAAC;YAChB,QAAQ,EAAE,EAAE;YACZ,gBAAgB,EAAE,CAAC;YACnB,SAAS,EAAE,CAAC;YACZ,cAAc;YACd,iBAAiB;SAClB,CAAC;IACJ,CAAC;IAED,wEAAwE;IACxE,6DAA6D;IAC7D,MAAM,MAAM,GAAa,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC;IAChE,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE;QACjC,IAAI,GAAG,GAAG,CAAC,CAAC;QACZ,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,IAAI,GAAG,CAAC;YAChD,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC;QAC3B,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CAAC,CAAS,EAAE,CAAS,EAAQ,EAAE;QAC3C,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,EAAE,KAAK,EAAE;YAAE,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,CAAC;IACjC,CAAC,CAAC;IACF,MAAM,QAAQ,GAA4C,EAAE,CAAC;IAC7D,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,IAAI,EAAE,KAAK,SAAS;YAAE,SAAS;QAC/B,KAAK,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/B,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;YACnB,IAAI,EAAE,KAAK,SAAS;gBAAE,SAAS;YAC/B,MAAM,GAAG,GAAG,OAAO,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;YAC1C,IAAI,GAAG,IAAI,cAAc,EAAE,CAAC;gBAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC;gBACnC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,MAAM,UAAU,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC/C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,IAAI,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;QAC/B,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;YACzB,MAAM,GAAG,EAAE,CAAC;YACZ,UAAU,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjB,CAAC;IAED,MAAM,QAAQ,GAAuB,EAAE,CAAC;IACxC,IAAI,gBAAgB,GAAG,CAAC,CAAC;IACzB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,IAAI,IAAI,UAAU,CAAC,MAAM,EAAE,EAAE,CAAC;QACvC,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC;YAAE,SAAS;QAC9B,kEAAkE;QAClE,uDAAuD;QACvD,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,IAAI,KAAK,GAAG,CAAC,CAAC;QACd,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC;QAC1B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;YACzB,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACjC,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC;gBACf,KAAK,IAAI,CAAC,CAAC;YACb,CAAC;QACH,CAAC;QACD,MAAM,GAAG,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC;QAC5C,MAAM,IAAI,GACR,GAAG,IAAI,iBAAiB,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,CAAC;QACtD,qEAAqE;QACrE,mEAAmE;QACnE,mEAAmE;QACnE,uDAAuD;QACvD,MAAM,OAAO,GAAG,IAAI;aACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;aACnB,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;YACpB,IAAI,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO;gBAAE,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;YAC1D,OAAO,CAAC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QACH,QAAQ,CAAC,IAAI,CAAC;YACZ,IAAI;YACJ,iBAAiB,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YACzC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC;SAC1D,CAAC,CAAC;QACH,gBAAgB,IAAI,IAAI,CAAC,MAAM,CAAC;QAChC,SAAS,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC;IAC/B,CAAC;IACD,qEAAqE;IACrE,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACrB,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;YAAE,OAAO,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7D,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM;YAAE,OAAO,CAAC,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;QAClF,OAAO,CAAC,CAAC,iBAAiB,GAAG,CAAC,CAAC,iBAAiB,CAAC;IACnD,CAAC,CAAC,CAAC;IAEH,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,QAAQ;QACR,gBAAgB;QAChB,SAAS;QACT,cAAc;QACd,iBAAiB;KAClB,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"dedup.js","sourceRoot":"","sources":["../../src/attention/dedup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * Layer C — SessionStart drain (plan §4.3).
3
+ *
4
+ * Reads the rich deferred logs written by Layer A
5
+ * (`.cairn/staleness/layer-a-deferred.jsonl`) and Layer B
6
+ * (`.cairn/staleness/pre-commit-deferred.jsonl`), re-checks each entry
7
+ * against the current source location, and applies one of three
8
+ * verdicts to each surviving entry:
9
+ *
10
+ * - `same` → strip-replace the prose block with `// §DEC-<id>`
11
+ * cite. Pure deterministic for Layer B `tier1`
12
+ * entries (the pre-commit hook already passed the
13
+ * Tier 1 floors); Haiku-judged for everything else.
14
+ * - `different` → drop the entry, no source change.
15
+ * - `ambiguous` → write to `.cairn/ground/alignment-pending/` so
16
+ * the cairn-attention skill surfaces a side-by-side
17
+ * review next session.
18
+ *
19
+ * Drain truncates both deferred logs after running. The lightweight
20
+ * drift events in `.cairn/staleness/log.jsonl` are an audit trail and
21
+ * stay.
22
+ *
23
+ * Cost: capped at `max_haiku_calls` (default 30 per plan §4.3 budget).
24
+ * Excess entries stay in the deferred logs for the next drain. Each
25
+ * Haiku call is verdict-cached at
26
+ * `.cairn/cache/haiku/drain-judge/<blockHash>-<decId>.json` keyed on
27
+ * `(block_content_hash, dec_body_hash)`, so re-running the same block
28
+ * against the same DEC body short-circuits without burning a call.
29
+ *
30
+ * Haiku unavailable fallback: drain attempts the deterministic re-check
31
+ * pass only (Layer B tier1 entries get applied; everything else stays
32
+ * deferred). `setHaikuAvailable(false)` raises the statusline banner.
33
+ */
34
+ export type DrainJudgeVerdict = "same" | "different" | "ambiguous";
35
+ export interface DrainArgs {
36
+ repoRoot: string;
37
+ /** When provided, drain pushes drain-progress / drain-done blips to this session's queue. */
38
+ sessionId?: string | null;
39
+ /** Hard cap on Haiku judge calls. Default 30 (plan §4.3). */
40
+ maxHaikuCalls?: number;
41
+ /** Dry run — classify but do not strip-replace, write alignment-pending, or truncate logs. */
42
+ dryRun?: boolean;
43
+ /**
44
+ * Inject the dedup judge — bypasses the live Haiku call. Used by
45
+ * smoke fixtures and the `cairn align drain --mock` debug path.
46
+ */
47
+ mockJudge?: (args: {
48
+ blockBody: string;
49
+ candidate: {
50
+ id: string;
51
+ body: string;
52
+ };
53
+ }) => Promise<DrainJudgeVerdict>;
54
+ /** Override Haiku availability detection (smoke fixtures). */
55
+ haikuAvailable?: boolean;
56
+ }
57
+ export interface DrainResult {
58
+ /** Total entries read from both deferred logs. */
59
+ totalEntries: number;
60
+ /** Entries whose source block could not be relocated (gone / edited / cited). */
61
+ droppedMissing: number;
62
+ /** Entries auto-cited via deterministic re-check (Layer B tier1). */
63
+ citedDeterministic: number;
64
+ /** Entries auto-cited via Haiku `same` verdict. */
65
+ citedHaiku: number;
66
+ /** Entries dropped via Haiku `different` verdict. */
67
+ droppedDifferent: number;
68
+ /** Entries written to alignment-pending via Haiku `ambiguous` verdict. */
69
+ pending: number;
70
+ /** Entries left in the deferred logs because the Haiku cap was hit or Haiku is offline. */
71
+ deferred: number;
72
+ /** Total Haiku calls actually issued (cache hits do not count). */
73
+ haikuCalls: number;
74
+ /** True when the drain ran without Haiku (fallback path). */
75
+ haikuFallback: boolean;
76
+ }
77
+ export declare function runDrain(args: DrainArgs): Promise<DrainResult>;