@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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/align-undo/index.d.ts +6 -0
- package/dist/align-undo/index.js +6 -0
- package/dist/align-undo/index.js.map +1 -0
- package/dist/align-undo/log.d.ts +53 -0
- package/dist/align-undo/log.js +99 -0
- package/dist/align-undo/log.js.map +1 -0
- package/dist/align-undo/undo.d.ts +66 -0
- package/dist/align-undo/undo.js +187 -0
- package/dist/align-undo/undo.js.map +1 -0
- package/dist/attention/dedup.js +1 -47
- package/dist/attention/dedup.js.map +1 -1
- package/dist/drain/drain.d.ts +77 -0
- package/dist/drain/drain.js +464 -0
- package/dist/drain/drain.js.map +1 -0
- package/dist/drain/index.d.ts +5 -0
- package/dist/drain/index.js +5 -0
- package/dist/drain/index.js.map +1 -0
- package/dist/fix-align/index.d.ts +5 -0
- package/dist/fix-align/index.js +5 -0
- package/dist/fix-align/index.js.map +1 -0
- package/dist/fix-align/run.d.ts +99 -0
- package/dist/fix-align/run.js +258 -0
- package/dist/fix-align/run.js.map +1 -0
- package/dist/ground/alignment-pending.d.ts +28 -0
- package/dist/ground/alignment-pending.js +83 -0
- package/dist/ground/alignment-pending.js.map +1 -0
- package/dist/ground/anchor-map.d.ts +14 -0
- package/dist/ground/anchor-map.js +57 -0
- package/dist/ground/anchor-map.js.map +1 -0
- package/dist/ground/index.d.ts +9 -2
- package/dist/ground/index.js +8 -2
- package/dist/ground/index.js.map +1 -1
- package/dist/ground/paths.d.ts +21 -0
- package/dist/ground/paths.js +43 -0
- package/dist/ground/paths.js.map +1 -1
- package/dist/ground/schemas.d.ts +201 -0
- package/dist/ground/schemas.js +126 -1
- package/dist/ground/schemas.js.map +1 -1
- package/dist/ground/slug.d.ts +60 -0
- package/dist/ground/slug.js +103 -0
- package/dist/ground/slug.js.map +1 -0
- package/dist/ground/sot-bindings.d.ts +14 -0
- package/dist/ground/sot-bindings.js +80 -0
- package/dist/ground/sot-bindings.js.map +1 -0
- package/dist/ground/sot-cache.d.ts +18 -0
- package/dist/ground/sot-cache.js +63 -0
- package/dist/ground/sot-cache.js.map +1 -0
- package/dist/ground/topic-index.d.ts +20 -0
- package/dist/ground/topic-index.js +60 -0
- package/dist/ground/topic-index.js.map +1 -0
- package/dist/hooks/post-tool-use/index.d.ts +2 -0
- package/dist/hooks/post-tool-use/index.js +1 -0
- package/dist/hooks/post-tool-use/index.js.map +1 -1
- package/dist/hooks/post-tool-use/sot-align.d.ts +166 -0
- package/dist/hooks/post-tool-use/sot-align.js +1311 -0
- package/dist/hooks/post-tool-use/sot-align.js.map +1 -0
- package/dist/hooks/pre-commit/index.d.ts +8 -0
- package/dist/hooks/pre-commit/index.js +8 -0
- package/dist/hooks/pre-commit/index.js.map +1 -0
- package/dist/hooks/pre-commit/sot-align-precommit.d.ts +60 -0
- package/dist/hooks/pre-commit/sot-align-precommit.js +221 -0
- package/dist/hooks/pre-commit/sot-align-precommit.js.map +1 -0
- package/dist/hooks/runners/session-start.js +41 -0
- package/dist/hooks/runners/session-start.js.map +1 -1
- package/dist/hooks/sot-align-common.d.ts +39 -0
- package/dist/hooks/sot-align-common.js +152 -0
- package/dist/hooks/sot-align-common.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -1
- package/dist/init/index.d.ts +4 -2
- package/dist/init/index.js +2 -1
- package/dist/init/index.js.map +1 -1
- package/dist/init/ingest-docs.d.ts +30 -47
- package/dist/init/ingest-docs.js +113 -410
- package/dist/init/ingest-docs.js.map +1 -1
- package/dist/init/init.d.ts +8 -0
- package/dist/init/init.js +58 -29
- package/dist/init/init.js.map +1 -1
- package/dist/init/phases/5-brand.js +1 -1
- package/dist/init/phases/5-brand.js.map +1 -1
- package/dist/init/phases/5b-topic-index.d.ts +30 -0
- package/dist/init/phases/5b-topic-index.js +62 -0
- package/dist/init/phases/5b-topic-index.js.map +1 -0
- package/dist/init/phases/6-docs-ingest.d.ts +4 -5
- package/dist/init/phases/6-docs-ingest.js +5 -6
- package/dist/init/phases/6-docs-ingest.js.map +1 -1
- package/dist/init/phases/index.d.ts +2 -0
- package/dist/init/phases/index.js +1 -0
- package/dist/init/phases/index.js.map +1 -1
- package/dist/init/phases/parallel-678.d.ts +14 -17
- package/dist/init/phases/parallel-678.js +77 -98
- package/dist/init/phases/parallel-678.js.map +1 -1
- package/dist/init/phases/source-comments-output-io.d.ts +16 -10
- package/dist/init/phases/source-comments-output-io.js +7 -10
- package/dist/init/phases/source-comments-output-io.js.map +1 -1
- package/dist/init/phases/types.d.ts +1 -1
- package/dist/init/phases/types.js +1 -0
- package/dist/init/phases/types.js.map +1 -1
- package/dist/init/rules-merge/discover.d.ts +8 -3
- package/dist/init/rules-merge/discover.js +7 -3
- package/dist/init/rules-merge/discover.js.map +1 -1
- package/dist/init/rules-merge/ingest.d.ts +81 -28
- package/dist/init/rules-merge/ingest.js +456 -162
- package/dist/init/rules-merge/ingest.js.map +1 -1
- package/dist/init/sot-emit.d.ts +84 -0
- package/dist/init/sot-emit.js +218 -0
- package/dist/init/sot-emit.js.map +1 -0
- package/dist/init/source-comments/classify.d.ts +12 -10
- package/dist/init/source-comments/classify.js +13 -25
- package/dist/init/source-comments/classify.js.map +1 -1
- package/dist/init/source-comments/index.d.ts +1 -1
- package/dist/init/source-comments/index.js +1 -1
- package/dist/init/source-comments/index.js.map +1 -1
- package/dist/init/source-comments/ingest.d.ts +91 -67
- package/dist/init/source-comments/ingest.js +392 -361
- package/dist/init/source-comments/ingest.js.map +1 -1
- package/dist/init/topic-index/index.d.ts +36 -0
- package/dist/init/topic-index/index.js +46 -0
- package/dist/init/topic-index/index.js.map +1 -0
- package/dist/init/topic-index/judge.d.ts +20 -0
- package/dist/init/topic-index/judge.js +65 -0
- package/dist/init/topic-index/judge.js.map +1 -0
- package/dist/init/topic-index/resolve.d.ts +50 -0
- package/dist/init/topic-index/resolve.js +196 -0
- package/dist/init/topic-index/resolve.js.map +1 -0
- package/dist/init/topic-index/walk.d.ts +43 -0
- package/dist/init/topic-index/walk.js +293 -0
- package/dist/init/topic-index/walk.js.map +1 -0
- package/dist/mcp/schemas.d.ts +45 -8
- package/dist/mcp/schemas.js +43 -7
- package/dist/mcp/schemas.js.map +1 -1
- package/dist/mcp/tools/align-drain.d.ts +7 -0
- package/dist/mcp/tools/align-drain.js +26 -0
- package/dist/mcp/tools/align-drain.js.map +1 -0
- package/dist/mcp/tools/index.js +3 -0
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/init-phases.js +4 -1
- package/dist/mcp/tools/init-phases.js.map +1 -1
- package/dist/mcp/tools/resolve-attention.d.ts +2 -2
- package/dist/mcp/tools/resolve-attention.js +828 -5
- package/dist/mcp/tools/resolve-attention.js.map +1 -1
- package/dist/status-line/event-queue.d.ts +40 -0
- package/dist/status-line/event-queue.js +195 -0
- package/dist/status-line/event-queue.js.map +1 -0
- package/dist/status-line/format.d.ts +1 -1
- package/dist/status-line/format.js +49 -6
- package/dist/status-line/format.js.map +1 -1
- package/dist/status-line/index.d.ts +41 -0
- package/dist/status-line/index.js +14 -0
- package/dist/status-line/index.js.map +1 -1
- package/dist/status-line/reader.js +23 -18
- package/dist/status-line/reader.js.map +1 -1
- package/dist/status-line/writer.d.ts +1 -1
- package/dist/status-line/writer.js +5 -0
- package/dist/status-line/writer.js.map +1 -1
- package/dist/text/jaccard.d.ts +19 -0
- package/dist/text/jaccard.js +68 -0
- package/dist/text/jaccard.js.map +1 -0
- package/package.json +1 -1
- package/templates/.cairn/git-hooks/pre-commit +16 -3
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4
|
+
import { logger } from "../logger.js";
|
|
5
|
+
import { sotBindingsPath } from "./paths.js";
|
|
6
|
+
import { SotBindings } from "./schemas.js";
|
|
7
|
+
const log = logger("ground.sot-bindings");
|
|
8
|
+
/**
|
|
9
|
+
* Sot-bindings is the lookup table that lens + sensors + the alignment
|
|
10
|
+
* hook all consult to resolve a §DEC-<hash> token to its canonical
|
|
11
|
+
* source. The forward index is one DEC → one path. The reverse index is
|
|
12
|
+
* one path → many DECs (supersedes chains share their sot_path).
|
|
13
|
+
*/
|
|
14
|
+
export function emptySotBindings() {
|
|
15
|
+
return {
|
|
16
|
+
version: 1,
|
|
17
|
+
generated: new Date().toISOString(),
|
|
18
|
+
forward: {},
|
|
19
|
+
reverse: {},
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
export function readSotBindings(repoRoot) {
|
|
23
|
+
const path = sotBindingsPath(repoRoot);
|
|
24
|
+
if (!existsSync(path))
|
|
25
|
+
return emptySotBindings();
|
|
26
|
+
try {
|
|
27
|
+
const raw = readFileSync(path, "utf8");
|
|
28
|
+
const parsed = SotBindings.safeParse(parseYaml(raw));
|
|
29
|
+
if (!parsed.success) {
|
|
30
|
+
log.warn({ path, error: parsed.error.message }, "sot-bindings invalid; treating as empty");
|
|
31
|
+
return emptySotBindings();
|
|
32
|
+
}
|
|
33
|
+
return parsed.data;
|
|
34
|
+
}
|
|
35
|
+
catch (err) {
|
|
36
|
+
log.warn({ path, err }, "sot-bindings read failed; treating as empty");
|
|
37
|
+
return emptySotBindings();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export function writeSotBindings(repoRoot, bindings) {
|
|
41
|
+
const path = sotBindingsPath(repoRoot);
|
|
42
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
43
|
+
const next = { ...bindings, generated: new Date().toISOString() };
|
|
44
|
+
writeFileSync(path, stringifyYaml(next), "utf8");
|
|
45
|
+
log.debug({ path, decs: Object.keys(next.forward).length }, "wrote sot-bindings");
|
|
46
|
+
return path;
|
|
47
|
+
}
|
|
48
|
+
export function bindDec(bindings, decId, sotPath) {
|
|
49
|
+
const forward = { ...bindings.forward, [decId]: sotPath };
|
|
50
|
+
const reverse = { ...bindings.reverse };
|
|
51
|
+
const existing = reverse[sotPath] ?? [];
|
|
52
|
+
if (!existing.includes(decId)) {
|
|
53
|
+
reverse[sotPath] = [...existing, decId];
|
|
54
|
+
}
|
|
55
|
+
return { ...bindings, forward, reverse };
|
|
56
|
+
}
|
|
57
|
+
export function unbindDec(bindings, decId) {
|
|
58
|
+
const sotPath = bindings.forward[decId];
|
|
59
|
+
if (sotPath === undefined)
|
|
60
|
+
return bindings;
|
|
61
|
+
const forward = { ...bindings.forward };
|
|
62
|
+
delete forward[decId];
|
|
63
|
+
const reverse = { ...bindings.reverse };
|
|
64
|
+
const list = reverse[sotPath] ?? [];
|
|
65
|
+
const filtered = list.filter((id) => id !== decId);
|
|
66
|
+
if (filtered.length === 0) {
|
|
67
|
+
delete reverse[sotPath];
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
reverse[sotPath] = filtered;
|
|
71
|
+
}
|
|
72
|
+
return { ...bindings, forward, reverse };
|
|
73
|
+
}
|
|
74
|
+
export function decsForPath(bindings, sotPath) {
|
|
75
|
+
return bindings.reverse[sotPath] ?? [];
|
|
76
|
+
}
|
|
77
|
+
export function pathForDec(bindings, decId) {
|
|
78
|
+
return bindings.forward[decId] ?? null;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=sot-bindings.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sot-bindings.js","sourceRoot":"","sources":["../../src/ground/sot-bindings.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { SotCache, type SotCacheEntry } from "./schemas.js";
|
|
2
|
+
/**
|
|
3
|
+
* Sot-cache holds pre-tokenized DEC body content for the Layer A Jaccard
|
|
4
|
+
* pre-filter. Rebuilt at SessionStart, incremental on PostToolUse Write
|
|
5
|
+
* events that touch a DEC body or sot-path file. Mtime-keyed so a stale
|
|
6
|
+
* entry is detected without re-tokenizing every body on every Write.
|
|
7
|
+
*/
|
|
8
|
+
export declare function emptySotCache(): SotCache;
|
|
9
|
+
export declare function readSotCache(repoRoot: string): SotCache;
|
|
10
|
+
export declare function writeSotCache(repoRoot: string, cache: SotCache): string;
|
|
11
|
+
export declare function setEntry(cache: SotCache, decId: string, entry: SotCacheEntry): SotCache;
|
|
12
|
+
export declare function getEntry(cache: SotCache, decId: string): SotCacheEntry | null;
|
|
13
|
+
export declare function deleteEntry(cache: SotCache, decId: string): SotCache;
|
|
14
|
+
/**
|
|
15
|
+
* Iterate all entries. Layer A's pre-filter pass calls this on each
|
|
16
|
+
* Write to compute Jaccard against every cached DEC body.
|
|
17
|
+
*/
|
|
18
|
+
export declare function entries(cache: SotCache): SotCacheEntry[];
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4
|
+
import { logger } from "../logger.js";
|
|
5
|
+
import { sotCachePath } from "./paths.js";
|
|
6
|
+
import { SotCache } from "./schemas.js";
|
|
7
|
+
const log = logger("ground.sot-cache");
|
|
8
|
+
/**
|
|
9
|
+
* Sot-cache holds pre-tokenized DEC body content for the Layer A Jaccard
|
|
10
|
+
* pre-filter. Rebuilt at SessionStart, incremental on PostToolUse Write
|
|
11
|
+
* events that touch a DEC body or sot-path file. Mtime-keyed so a stale
|
|
12
|
+
* entry is detected without re-tokenizing every body on every Write.
|
|
13
|
+
*/
|
|
14
|
+
export function emptySotCache() {
|
|
15
|
+
return { version: 1, generated: new Date().toISOString(), entries: {} };
|
|
16
|
+
}
|
|
17
|
+
export function readSotCache(repoRoot) {
|
|
18
|
+
const path = sotCachePath(repoRoot);
|
|
19
|
+
if (!existsSync(path))
|
|
20
|
+
return emptySotCache();
|
|
21
|
+
try {
|
|
22
|
+
const raw = readFileSync(path, "utf8");
|
|
23
|
+
const parsed = SotCache.safeParse(parseYaml(raw));
|
|
24
|
+
if (!parsed.success) {
|
|
25
|
+
log.warn({ path, error: parsed.error.message }, "sot-cache invalid; treating as empty");
|
|
26
|
+
return emptySotCache();
|
|
27
|
+
}
|
|
28
|
+
return parsed.data;
|
|
29
|
+
}
|
|
30
|
+
catch (err) {
|
|
31
|
+
log.warn({ path, err }, "sot-cache read failed; treating as empty");
|
|
32
|
+
return emptySotCache();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
export function writeSotCache(repoRoot, cache) {
|
|
36
|
+
const path = sotCachePath(repoRoot);
|
|
37
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
38
|
+
const next = { ...cache, generated: new Date().toISOString() };
|
|
39
|
+
writeFileSync(path, stringifyYaml(next), "utf8");
|
|
40
|
+
log.debug({ path, entries: Object.keys(next.entries).length }, "wrote sot-cache");
|
|
41
|
+
return path;
|
|
42
|
+
}
|
|
43
|
+
export function setEntry(cache, decId, entry) {
|
|
44
|
+
return { ...cache, entries: { ...cache.entries, [decId]: entry } };
|
|
45
|
+
}
|
|
46
|
+
export function getEntry(cache, decId) {
|
|
47
|
+
return cache.entries[decId] ?? null;
|
|
48
|
+
}
|
|
49
|
+
export function deleteEntry(cache, decId) {
|
|
50
|
+
if (cache.entries[decId] === undefined)
|
|
51
|
+
return cache;
|
|
52
|
+
const entries = { ...cache.entries };
|
|
53
|
+
delete entries[decId];
|
|
54
|
+
return { ...cache, entries };
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Iterate all entries. Layer A's pre-filter pass calls this on each
|
|
58
|
+
* Write to compute Jaccard against every cached DEC body.
|
|
59
|
+
*/
|
|
60
|
+
export function entries(cache) {
|
|
61
|
+
return Object.values(cache.entries);
|
|
62
|
+
}
|
|
63
|
+
//# sourceMappingURL=sot-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sot-cache.js","sourceRoot":"","sources":["../../src/ground/sot-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { TopicIndex, type TopicIndexEntry } from "./schemas.js";
|
|
2
|
+
/**
|
|
3
|
+
* Topic-index is the ground-state file that maps content-fingerprint
|
|
4
|
+
* slugs to the DECs they belong to. Phase 5b builds it before any
|
|
5
|
+
* extractor runs so phases 6 / 7b / 7c can dedup-by-topic instead of
|
|
6
|
+
* emitting one DEC per source. Layer A's PostToolUse hook reads it on
|
|
7
|
+
* every Write to know whether a freshly typed prose block is the first
|
|
8
|
+
* sighting of its content or a repeat of an existing topic.
|
|
9
|
+
*/
|
|
10
|
+
export declare function emptyTopicIndex(): TopicIndex;
|
|
11
|
+
export declare function readTopicIndex(repoRoot: string): TopicIndex;
|
|
12
|
+
export declare function writeTopicIndex(repoRoot: string, index: TopicIndex): string;
|
|
13
|
+
/**
|
|
14
|
+
* Insert or replace a topic entry. Returns the updated index.
|
|
15
|
+
*/
|
|
16
|
+
export declare function setTopic(index: TopicIndex, slug: string, entry: TopicIndexEntry): TopicIndex;
|
|
17
|
+
/**
|
|
18
|
+
* Look up a topic by slug. Returns null if absent.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getTopic(index: TopicIndex, slug: string): TopicIndexEntry | null;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname } from "node:path";
|
|
3
|
+
import { parse as parseYaml, stringify as stringifyYaml } from "yaml";
|
|
4
|
+
import { logger } from "../logger.js";
|
|
5
|
+
import { topicIndexPath } from "./paths.js";
|
|
6
|
+
import { TopicIndex } from "./schemas.js";
|
|
7
|
+
const log = logger("ground.topic-index");
|
|
8
|
+
/**
|
|
9
|
+
* Topic-index is the ground-state file that maps content-fingerprint
|
|
10
|
+
* slugs to the DECs they belong to. Phase 5b builds it before any
|
|
11
|
+
* extractor runs so phases 6 / 7b / 7c can dedup-by-topic instead of
|
|
12
|
+
* emitting one DEC per source. Layer A's PostToolUse hook reads it on
|
|
13
|
+
* every Write to know whether a freshly typed prose block is the first
|
|
14
|
+
* sighting of its content or a repeat of an existing topic.
|
|
15
|
+
*/
|
|
16
|
+
export function emptyTopicIndex() {
|
|
17
|
+
return { version: 1, generated: new Date().toISOString(), topics: {} };
|
|
18
|
+
}
|
|
19
|
+
export function readTopicIndex(repoRoot) {
|
|
20
|
+
const path = topicIndexPath(repoRoot);
|
|
21
|
+
if (!existsSync(path))
|
|
22
|
+
return emptyTopicIndex();
|
|
23
|
+
try {
|
|
24
|
+
const raw = readFileSync(path, "utf8");
|
|
25
|
+
const parsed = TopicIndex.safeParse(parseYaml(raw));
|
|
26
|
+
if (!parsed.success) {
|
|
27
|
+
log.warn({ path, error: parsed.error.message }, "topic-index invalid; treating as empty");
|
|
28
|
+
return emptyTopicIndex();
|
|
29
|
+
}
|
|
30
|
+
return parsed.data;
|
|
31
|
+
}
|
|
32
|
+
catch (err) {
|
|
33
|
+
log.warn({ path, err }, "topic-index read failed; treating as empty");
|
|
34
|
+
return emptyTopicIndex();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
export function writeTopicIndex(repoRoot, index) {
|
|
38
|
+
const path = topicIndexPath(repoRoot);
|
|
39
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
40
|
+
const next = { ...index, generated: new Date().toISOString() };
|
|
41
|
+
writeFileSync(path, stringifyYaml(next), "utf8");
|
|
42
|
+
log.debug({ path, topics: Object.keys(next.topics).length }, "wrote topic-index");
|
|
43
|
+
return path;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Insert or replace a topic entry. Returns the updated index.
|
|
47
|
+
*/
|
|
48
|
+
export function setTopic(index, slug, entry) {
|
|
49
|
+
return {
|
|
50
|
+
...index,
|
|
51
|
+
topics: { ...index.topics, [slug]: entry },
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Look up a topic by slug. Returns null if absent.
|
|
56
|
+
*/
|
|
57
|
+
export function getTopic(index, slug) {
|
|
58
|
+
return index.topics[slug] ?? null;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=topic-index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"topic-index.js","sourceRoot":"","sources":["../../src/ground/topic-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,SAAS,IAAI,aAAa,EAAE,MAAM,MAAM,CAAC;AACtE,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAwB,MAAM,cAAc,CAAC;AAEhE,MAAM,GAAG,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAEzC;;;;;;;GAOG;AAEH,MAAM,UAAU,eAAe;IAC7B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACtC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,eAAe,EAAE,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACvC,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;YACpB,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,wCAAwC,CAAC,CAAC;YAC1F,OAAO,eAAe,EAAE,CAAC;QAC3B,CAAC;QACD,OAAO,MAAM,CAAC,IAAI,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,GAAG,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,4CAA4C,CAAC,CAAC;QACtE,OAAO,eAAe,EAAE,CAAC;IAC3B,CAAC;AACH,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAgB,EAAE,KAAiB;IACjE,MAAM,IAAI,GAAG,cAAc,CAAC,QAAQ,CAAC,CAAC;IACtC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAe,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;IAC3E,aAAa,CAAC,IAAI,EAAE,aAAa,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,CAAC;IACjD,GAAG,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,mBAAmB,CAAC,CAAC;IAClF,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAiB,EAAE,IAAY,EAAE,KAAsB;IAC9E,OAAO;QACL,GAAG,KAAK;QACR,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE;KAC3C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAiB,EAAE,IAAY;IACtD,OAAO,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AACpC,CAAC"}
|
|
@@ -17,3 +17,5 @@ export { scanForCopyLeakage } from "./copy-scanner.js";
|
|
|
17
17
|
export type { CopyIssue } from "./copy-scanner.js";
|
|
18
18
|
export { readCopySafetyConfig } from "./allowlist-reader.js";
|
|
19
19
|
export type { CopySafetyConfig } from "./allowlist-reader.js";
|
|
20
|
+
export { alignFile, runSotAlign } from "./sot-align.js";
|
|
21
|
+
export type { AlignFileArgs, AlignFileResult, CreationVerdict, DedupVerdict, } from "./sot-align.js";
|
|
@@ -12,4 +12,5 @@ export { buildLegend } from "./legend-builder.js";
|
|
|
12
12
|
export { runWriteGuardian } from "./write-guardian.js";
|
|
13
13
|
export { scanForCopyLeakage } from "./copy-scanner.js";
|
|
14
14
|
export { readCopySafetyConfig } from "./allowlist-reader.js";
|
|
15
|
+
export { alignFile, runSotAlign } from "./sot-align.js";
|
|
15
16
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hooks/post-tool-use/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,GACX,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/hooks/post-tool-use/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EACL,mBAAmB,EACnB,kBAAkB,EAClB,UAAU,GACX,MAAM,mBAAmB,CAAC;AAM3B,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAElD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Layer A — live SoT alignment hook (plan §4.1).
|
|
3
|
+
*
|
|
4
|
+
* `cairn hook sot-align` runs as a PostToolUse hook on Claude Code's
|
|
5
|
+
* Write/Edit. For every prose block in the just-written file the
|
|
6
|
+
* pipeline picks one of:
|
|
7
|
+
*
|
|
8
|
+
* - **Tier 1 (deterministic, no Haiku)** — block is a verbatim/
|
|
9
|
+
* near-verbatim duplicate of an existing accepted DEC/INV body
|
|
10
|
+
* (Jaccard ≥ 0.85, 3-shingle ≥ 60%, length ratio 0.5-2.0).
|
|
11
|
+
* Auto-replace with `// §DEC-<hash>` (or `# §DEC-<hash>` per
|
|
12
|
+
* language). Statusline blip `⬡ aligned`.
|
|
13
|
+
*
|
|
14
|
+
* - **Tier 2 — Haiku dedup judge, two-pass.**
|
|
15
|
+
* Pass 1 (cheap, snippet + candidate body) → `same | different |
|
|
16
|
+
* ambiguous`. `same` → cite. `different` → next candidate.
|
|
17
|
+
* `ambiguous` → escalate to Pass 2.
|
|
18
|
+
* Pass 2 (full bodies + ±200-char source context + step-by-step
|
|
19
|
+
* prompt) → `same | different | augments | ambiguous`. `same`
|
|
20
|
+
* cite; `different` next; `augments` triggers two-stage delta:
|
|
21
|
+
* - Stage 1 — Haiku extracts the delta prose ("NO_DELTA" → same).
|
|
22
|
+
* - Stage 2 — Haiku classifies the delta `constraint | rationale`.
|
|
23
|
+
* constraint → fresh INV linked via `derived_from`; rationale
|
|
24
|
+
* → fresh DEC linked via `related`. The augmented source
|
|
25
|
+
* gains a `// §INV-<new>` / `// §DEC-<new>` cite *alongside*
|
|
26
|
+
* the existing one (existing token preserved).
|
|
27
|
+
* `ambiguous` (still!) → write to `.cairn/ground/alignment-
|
|
28
|
+
* pending/<id>.md` and surface via cairn-attention.
|
|
29
|
+
*
|
|
30
|
+
* - **Tier 3 — Haiku creation judge, two-pass.**
|
|
31
|
+
* Pass 1 → `decision | constraint | descriptive | ambiguous`.
|
|
32
|
+
* `descriptive` no-op (false-positive DEC creation pollutes
|
|
33
|
+
* ground state worse than missed capture). `ambiguous` →
|
|
34
|
+
* escalate to Pass 2 (full prose + ±200-char context + step-by-
|
|
35
|
+
* step prompt). Pass-2-still-ambiguous → alignment-pending.
|
|
36
|
+
*
|
|
37
|
+
* Hard rules:
|
|
38
|
+
* - The hook never blocks the Write. Failures degrade to no-op +
|
|
39
|
+
* log; the operator's edit always succeeds.
|
|
40
|
+
* - Per-Write call caps: max HAIKU_PASS1_CAP Pass-1 calls + max
|
|
41
|
+
* HAIKU_PASS2_CAP Pass-2 calls per Write. Excess defers to
|
|
42
|
+
* `.cairn/staleness/layer-a-deferred.jsonl` for Layer C drain.
|
|
43
|
+
* - Verdict cache at `.cairn/cache/haiku/<scope>/<blockHash>-<key>.json`
|
|
44
|
+
* so re-running the same prose hits cache instead of Haiku.
|
|
45
|
+
* - Source files outside Claude's repo (cwd) are skipped. Markdown
|
|
46
|
+
* (`.md`/`.mdx`) skipped entirely — operator-curated narrative is
|
|
47
|
+
* handled by phase 5b's topic-index + the doc-drift sensor.
|
|
48
|
+
*/
|
|
49
|
+
export interface AlignFileArgs {
|
|
50
|
+
repoRoot: string;
|
|
51
|
+
/** Repo-relative POSIX path written by Claude Code. */
|
|
52
|
+
filePath: string;
|
|
53
|
+
/** Claude Code session id (for statusline blips). */
|
|
54
|
+
sessionId: string | null;
|
|
55
|
+
/**
|
|
56
|
+
* Mock dedup judge — Pass 1. Default uses Haiku via runClaude.
|
|
57
|
+
*/
|
|
58
|
+
mockDedupJudgePass1?: (args: {
|
|
59
|
+
blockBody: string;
|
|
60
|
+
candidate: {
|
|
61
|
+
id: string;
|
|
62
|
+
body: string;
|
|
63
|
+
};
|
|
64
|
+
}) => Promise<DedupVerdictPass1>;
|
|
65
|
+
/**
|
|
66
|
+
* Mock dedup judge — Pass 2 (CoT escalation). Default uses Haiku.
|
|
67
|
+
*/
|
|
68
|
+
mockDedupJudgePass2?: (args: {
|
|
69
|
+
blockBody: string;
|
|
70
|
+
blockContext: string;
|
|
71
|
+
candidate: {
|
|
72
|
+
id: string;
|
|
73
|
+
body: string;
|
|
74
|
+
};
|
|
75
|
+
}) => Promise<DedupVerdictPass2>;
|
|
76
|
+
/**
|
|
77
|
+
* Mock delta extractor (Stage 1) — extract the prose delta when
|
|
78
|
+
* Pass 2 returns `augments`. Default uses Haiku.
|
|
79
|
+
*/
|
|
80
|
+
mockDeltaExtract?: (args: {
|
|
81
|
+
blockBody: string;
|
|
82
|
+
candidateBody: string;
|
|
83
|
+
}) => Promise<string>;
|
|
84
|
+
/**
|
|
85
|
+
* Mock delta classifier (Stage 2) — `constraint | rationale`.
|
|
86
|
+
* Default uses Haiku.
|
|
87
|
+
*/
|
|
88
|
+
mockDeltaClassify?: (args: {
|
|
89
|
+
delta: string;
|
|
90
|
+
}) => Promise<DeltaKind>;
|
|
91
|
+
/**
|
|
92
|
+
* Mock creation judge — Pass 1. Default uses Haiku via runClaude.
|
|
93
|
+
*/
|
|
94
|
+
mockCreationJudgePass1?: (args: {
|
|
95
|
+
blockBody: string;
|
|
96
|
+
file: string;
|
|
97
|
+
line: number;
|
|
98
|
+
}) => Promise<CreationVerdict>;
|
|
99
|
+
/**
|
|
100
|
+
* Mock creation judge — Pass 2 (CoT escalation). Default uses Haiku.
|
|
101
|
+
*/
|
|
102
|
+
mockCreationJudgePass2?: (args: {
|
|
103
|
+
blockBody: string;
|
|
104
|
+
blockContext: string;
|
|
105
|
+
file: string;
|
|
106
|
+
line: number;
|
|
107
|
+
}) => Promise<CreationVerdict>;
|
|
108
|
+
/**
|
|
109
|
+
* Override the per-call Pass-1 Haiku cap. Default 5 — appropriate
|
|
110
|
+
* for live PostToolUse Writes where the cost has to stay tight.
|
|
111
|
+
* Layer D (`cairn fix align`) sets this much higher (e.g. 200) so a
|
|
112
|
+
* single-file sweep can fully judge every block.
|
|
113
|
+
*/
|
|
114
|
+
pass1Cap?: number;
|
|
115
|
+
/** Override the per-call Pass-2 Haiku cap. Default 2. */
|
|
116
|
+
pass2Cap?: number;
|
|
117
|
+
/**
|
|
118
|
+
* When true, suppress the Tier 3 creation pipeline entirely — Tier 1
|
|
119
|
+
* + Tier 2 dedup still run. Layer D's `--no-creation` flag sets this
|
|
120
|
+
* so a sweep only consolidates duplicates without proposing fresh
|
|
121
|
+
* DECs from prose that doesn't match anything in the ledger yet.
|
|
122
|
+
*/
|
|
123
|
+
skipCreation?: boolean;
|
|
124
|
+
}
|
|
125
|
+
type DedupVerdictPass1 = "same" | "different" | "ambiguous";
|
|
126
|
+
type DedupVerdictPass2 = "same" | "different" | "augments" | "ambiguous";
|
|
127
|
+
type DeltaKind = "constraint" | "rationale";
|
|
128
|
+
export type CreationVerdict = "decision" | "constraint" | "descriptive" | "ambiguous";
|
|
129
|
+
/** Back-compat alias preserved for external callers. */
|
|
130
|
+
export type DedupVerdict = DedupVerdictPass1;
|
|
131
|
+
export interface AlignFileResult {
|
|
132
|
+
/** Number of prose blocks discovered in the written file. */
|
|
133
|
+
blocksConsidered: number;
|
|
134
|
+
/** Tier 1 deterministic auto-cites. */
|
|
135
|
+
tier1Aligned: number;
|
|
136
|
+
/** Tier 2 Haiku-confirmed cites. */
|
|
137
|
+
tier2Aligned: number;
|
|
138
|
+
/** Tier 3 fresh DECs emitted. */
|
|
139
|
+
decsCreated: number;
|
|
140
|
+
/** Tier 3 fresh INVs emitted. */
|
|
141
|
+
invsCreated: number;
|
|
142
|
+
/** Augments-DEC siblings (Pass 2 delta = rationale). */
|
|
143
|
+
augmentsDecs: number;
|
|
144
|
+
/** Augments-INV siblings (Pass 2 delta = constraint). */
|
|
145
|
+
augmentsInvs: number;
|
|
146
|
+
/** Blocks queued in `.cairn/ground/alignment-pending/`. */
|
|
147
|
+
pending: number;
|
|
148
|
+
/** Blocks deferred to staleness (cap exceeded). */
|
|
149
|
+
deferredToStaleness: number;
|
|
150
|
+
/** Blocks classified as descriptive (no-op). */
|
|
151
|
+
descriptive: number;
|
|
152
|
+
/** Blocks skipped for any reason — already-cited, length floor, etc. */
|
|
153
|
+
skipped: number;
|
|
154
|
+
/** Pass-1 Haiku calls made. */
|
|
155
|
+
haikuPass1Calls: number;
|
|
156
|
+
/** Pass-2 Haiku calls made. */
|
|
157
|
+
haikuPass2Calls: number;
|
|
158
|
+
/** Total Haiku calls (Pass 1 + Pass 2 + augments stages). Back-compat. */
|
|
159
|
+
haikuCalls: number;
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Run the Layer A pipeline against one repo-relative file.
|
|
163
|
+
*/
|
|
164
|
+
export declare function alignFile(args: AlignFileArgs): Promise<AlignFileResult>;
|
|
165
|
+
export declare function runSotAlign(): Promise<void>;
|
|
166
|
+
export {};
|