@isaacriehm/cairn-core 0.6.0 → 0.7.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 (81) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/attention/bulk-accept.js +56 -15
  3. package/dist/attention/bulk-accept.js.map +1 -1
  4. package/dist/attention/serve/api.js +7 -1
  5. package/dist/attention/serve/api.js.map +1 -1
  6. package/dist/ground/file-candidates-map.d.ts +23 -0
  7. package/dist/ground/file-candidates-map.js +76 -0
  8. package/dist/ground/file-candidates-map.js.map +1 -0
  9. package/dist/ground/index.d.ts +4 -2
  10. package/dist/ground/index.js +4 -2
  11. package/dist/ground/index.js.map +1 -1
  12. package/dist/ground/paths.d.ts +2 -0
  13. package/dist/ground/paths.js +6 -0
  14. package/dist/ground/paths.js.map +1 -1
  15. package/dist/ground/rejected.d.ts +42 -0
  16. package/dist/ground/rejected.js +100 -0
  17. package/dist/ground/rejected.js.map +1 -0
  18. package/dist/ground/schemas.d.ts +80 -0
  19. package/dist/ground/schemas.js +54 -0
  20. package/dist/ground/schemas.js.map +1 -1
  21. package/dist/hooks/post-tool-use/index.d.ts +1 -1
  22. package/dist/hooks/post-tool-use/index.js +1 -1
  23. package/dist/hooks/post-tool-use/index.js.map +1 -1
  24. package/dist/hooks/post-tool-use/ledger-cache.d.ts +13 -0
  25. package/dist/hooks/post-tool-use/ledger-cache.js +48 -0
  26. package/dist/hooks/post-tool-use/ledger-cache.js.map +1 -1
  27. package/dist/hooks/post-tool-use/legend-builder.d.ts +10 -1
  28. package/dist/hooks/post-tool-use/legend-builder.js +27 -2
  29. package/dist/hooks/post-tool-use/legend-builder.js.map +1 -1
  30. package/dist/hooks/post-tool-use/read-enricher.js +8 -2
  31. package/dist/hooks/post-tool-use/read-enricher.js.map +1 -1
  32. package/dist/init/index.d.ts +2 -2
  33. package/dist/init/index.js +1 -1
  34. package/dist/init/index.js.map +1 -1
  35. package/dist/init/ingest-docs.d.ts +82 -22
  36. package/dist/init/ingest-docs.js +632 -108
  37. package/dist/init/ingest-docs.js.map +1 -1
  38. package/dist/init/init.d.ts +10 -1
  39. package/dist/init/init.js +113 -251
  40. package/dist/init/init.js.map +1 -1
  41. package/dist/init/mapper-parallel.js +8 -0
  42. package/dist/init/mapper-parallel.js.map +1 -1
  43. package/dist/init/phases/6-docs-ingest.d.ts +9 -4
  44. package/dist/init/phases/6-docs-ingest.js +13 -10
  45. package/dist/init/phases/6-docs-ingest.js.map +1 -1
  46. package/dist/init/phases/parallel-678.js +10 -4
  47. package/dist/init/phases/parallel-678.js.map +1 -1
  48. package/dist/init/sot-emit.d.ts +22 -0
  49. package/dist/init/sot-emit.js +50 -4
  50. package/dist/init/sot-emit.js.map +1 -1
  51. package/dist/init/source-comments/ingest.js +107 -7
  52. package/dist/init/source-comments/ingest.js.map +1 -1
  53. package/dist/init/topic-index/index.d.ts +14 -0
  54. package/dist/init/topic-index/index.js +83 -4
  55. package/dist/init/topic-index/index.js.map +1 -1
  56. package/dist/init/topic-index/judge.js +14 -1
  57. package/dist/init/topic-index/judge.js.map +1 -1
  58. package/dist/init/topic-index/resolve.d.ts +19 -0
  59. package/dist/init/topic-index/resolve.js +100 -14
  60. package/dist/init/topic-index/resolve.js.map +1 -1
  61. package/dist/init/topic-index/walk.d.ts +32 -0
  62. package/dist/init/topic-index/walk.js +70 -4
  63. package/dist/init/topic-index/walk.js.map +1 -1
  64. package/dist/mcp/history/summarizer.js +5 -0
  65. package/dist/mcp/history/summarizer.js.map +1 -1
  66. package/dist/mcp/schemas.d.ts +48 -0
  67. package/dist/mcp/schemas.js +43 -0
  68. package/dist/mcp/schemas.js.map +1 -1
  69. package/dist/mcp/tools/index.js +8 -0
  70. package/dist/mcp/tools/index.js.map +1 -1
  71. package/dist/mcp/tools/propose-decision.d.ts +34 -0
  72. package/dist/mcp/tools/propose-decision.js +200 -0
  73. package/dist/mcp/tools/propose-decision.js.map +1 -0
  74. package/dist/mcp/tools/reject-candidate.d.ts +24 -0
  75. package/dist/mcp/tools/reject-candidate.js +71 -0
  76. package/dist/mcp/tools/reject-candidate.js.map +1 -0
  77. package/dist/mcp/tools/search-candidates.d.ts +20 -0
  78. package/dist/mcp/tools/search-candidates.js +93 -0
  79. package/dist/mcp/tools/search-candidates.js.map +1 -0
  80. package/package.json +1 -1
  81. package/templates/attention-ui/app.js +40 -3
@@ -1,18 +1,44 @@
1
1
  /**
2
- * Phase 6 — docs ingestion (v0.5.0 SoT model).
2
+ * Phase 6 — staged docs ingestion (PHASE_6_REDESIGN §4.1).
3
3
  *
4
- * Reads the topic-index built by phase 5b, filters to entries whose SoT
5
- * source lives under `docs/*`, and emits verbatim DEC files under
6
- * `.cairn/ground/decisions/`. Auto-promoted to `status: accepted`. No
7
- * draft inbox, no LLM paraphrase — the doc paragraph itself IS the
8
- * canonical body, recorded with `sot_kind: path` so the lens renders
9
- * the live source on every read.
4
+ * Replaces the v0.6 bulk-classifier path. Cuts wall from ~15 min
5
+ * ~75 s on gcb-platform-scale repos AND collapses the noisy ledger
6
+ * (7000 DECs) to a curated draft inbox (30-80 drafts).
10
7
  *
11
- * Per-entry Haiku call decides `kind` only (decision / domain-rule /
12
- * voice-guidelines / api-docs / other). The first two emit a DEC; the
13
- * rest are skipped at this layer (voice + canonical-topic flows are
14
- * handled by other tooling now — they were file-level concerns under
15
- * the v0.4.x model and have no clean paragraph-level analogue).
8
+ * Pipeline:
9
+ *
10
+ * Stage 3 (deterministic, 0 Haiku) marker scan
11
+ * Topic-index entries with `marker_kind` in {"decision","rule"} go
12
+ * straight to emit. The walker stamped them at parse time when it
13
+ * saw frontmatter `cairn.kind` or `<!-- cairn:decision -->` /
14
+ * `<!-- cairn:rule -->` within 3 lines of the heading.
15
+ *
16
+ * Stage 1 — file-purpose binary filter (batch=30, concurrency=5)
17
+ * Per file: filepath + frontmatter + first 800 chars + every
18
+ * H1/H2/H3 line (capped at 100). Locked rigid prompt: a file is
19
+ * authoritative ONLY if it's a canonical rulebook, formal ADR,
20
+ * or list of binding domain invariants. Plans / scratchpads /
21
+ * UAT logs / API docs are NOT authoritative even if they
22
+ * contain proposed or historical decisions.
23
+ *
24
+ * Stage 2 — section-level batch classifier (batch=30, concurrency=5)
25
+ * Same shape as the v0.6 classifier, but scoped to sections
26
+ * belonging to Stage-1-authoritative files AND not already
27
+ * handled by a marker. This is where Haiku still adds signal —
28
+ * the file passed the rigid filter; now decide WHICH sections
29
+ * of it are decisions vs context.
30
+ *
31
+ * Stage 4 — emit
32
+ * Stage 2 + Stage 3 outputs → `.cairn/ground/decisions/_inbox/<id>.draft.md`.
33
+ * `status: draft`, `capture_source: init-docs-ingest`,
34
+ * `decided_by: cairn-init`. Body is verbatim via
35
+ * `readSotBody` — no Haiku paraphrasing. Operator triages via
36
+ * the existing `cairn-attention` skill.
37
+ *
38
+ * Skipped entries (everything else) stay in the topic-index as
39
+ * unpromoted candidates. The PR 2 `cairn_search_candidates` /
40
+ * `cairn_propose_decision` MCP tools surface them to AI agents as
41
+ * the project lives.
16
42
  */
17
43
  import { type TopicIndexEntry } from "../ground/index.js";
18
44
  export interface DocCandidate {
@@ -32,33 +58,67 @@ export interface ClassifiedDoc {
32
58
  errorMessage?: string;
33
59
  }
34
60
  export interface IngestionResult {
35
- /** Verbatim DEC files written under `.cairn/ground/decisions/`. */
61
+ /** Verbatim DEC drafts written under `_inbox/`. */
36
62
  decsWritten: {
37
63
  id: string;
38
64
  path: string;
39
65
  sourceFile: string;
40
66
  slug: string;
41
67
  }[];
42
- /** Topic-index entries that were not emitted, with reasons. */
68
+ /** Topic-index entries skipped at Stage 4 (with reason). */
43
69
  skipped: {
44
70
  slug: string;
45
71
  reason: string;
46
72
  }[];
47
- /** Number of topic-index entries considered (sot_source under docs/). */
73
+ /** Total topic-index entries considered (pre-rejection-filter). */
48
74
  scannedEntries: number;
75
+ /** Stage 3 — entries emitted from operator markers (0 Haiku). */
76
+ markerEmits: number;
77
+ /** Stage 2 — entries emitted from authoritative-file section classifications. */
78
+ sectionEmits: number;
79
+ /**
80
+ * Stage 1 — files the binary filter accepted as authoritative
81
+ * (i.e. eligible to feed Stage 2).
82
+ */
83
+ authoritativeFiles: number;
84
+ /** Total distinct files Stage 1 evaluated. */
85
+ filesEvaluated: number;
86
+ /**
87
+ * Topic-index entries that remain unpromoted (`dec_id IS NULL`)
88
+ * after this run. Surface this in the cold-start summary as
89
+ * "K unpromoted candidates indexed".
90
+ */
91
+ unpromotedCandidates: number;
92
+ }
93
+ export interface ChunkProgressRow {
94
+ chunksDone: number;
95
+ totalChunks: number;
96
+ entriesDone: number;
97
+ totalEntries: number;
98
+ /** Which staged phase the chunk belongs to ("file-filter" or "section-classify"). */
99
+ stage: "file-filter" | "section-classify";
49
100
  }
50
101
  export interface RunDocsIngestionArgs {
51
102
  repoRoot: string;
52
- /** Smoke override — feed canned classifications keyed by slug. */
103
+ /**
104
+ * Smoke override — feed canned classifications keyed by entry. When
105
+ * set, Stages 1+2 are bypassed entirely; every non-marker candidate
106
+ * runs through this synchronously. Stage 3 still fires.
107
+ */
53
108
  mockClassify?: (entry: TopicIndexEntry, body: string) => DocClassification;
54
109
  /** Caller-supplied id collision Set (parallel pipeline). */
55
110
  existingDecIds?: Set<string>;
56
- /** Progress callback fired once per emitted entry. */
57
- onEntryProgress?: (row: {
58
- slug: string;
59
- emitted: boolean;
60
- total: number;
61
- }) => void;
111
+ /** Progress callback fired once per completed batch. */
112
+ onChunkProgress?: (row: ChunkProgressRow) => void;
62
113
  }
63
114
  export declare function discoverDocs(repoRoot: string): DocCandidate[];
115
+ export interface FileFilterVerdict {
116
+ is_authoritative: boolean;
117
+ reason: string;
118
+ }
64
119
  export declare function runDocsIngestion(args: RunDocsIngestionArgs): Promise<IngestionResult>;
120
+ export declare function runStage1FileFilter(args: {
121
+ repoRoot: string;
122
+ files: string[];
123
+ onChunkProgress?: (row: ChunkProgressRow) => void;
124
+ }): Promise<Map<string, FileFilterVerdict>>;