@sledorze/cairn 0.1.0 → 0.3.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 (117) hide show
  1. package/README.md +69 -18
  2. package/dist/cli.js +69378 -70958
  3. package/dist/cli.js.map +1 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +10 -10
  6. package/dist/config.js.map +1 -1
  7. package/dist/core/Config.d.ts +22 -22
  8. package/dist/core/Config.d.ts.map +1 -1
  9. package/dist/core/Config.js +33 -33
  10. package/dist/core/Config.js.map +1 -1
  11. package/dist/core/glob.bench.js +1 -1
  12. package/dist/core/glob.d.ts.map +1 -1
  13. package/dist/core/hashing.d.ts +3 -0
  14. package/dist/core/hashing.d.ts.map +1 -0
  15. package/dist/core/hashing.js +16 -0
  16. package/dist/core/hashing.js.map +1 -0
  17. package/dist/core/links/Anchors.d.ts +30 -0
  18. package/dist/core/links/Anchors.d.ts.map +1 -0
  19. package/dist/core/links/Anchors.js +119 -0
  20. package/dist/core/links/Anchors.js.map +1 -0
  21. package/dist/core/links/MarkdownLinks.bench.d.ts.map +1 -0
  22. package/dist/core/{MarkdownLinks.bench.js → links/MarkdownLinks.bench.js} +1 -1
  23. package/dist/core/links/MarkdownLinks.bench.js.map +1 -0
  24. package/dist/core/links/MarkdownLinks.d.ts +121 -0
  25. package/dist/core/links/MarkdownLinks.d.ts.map +1 -0
  26. package/dist/core/links/MarkdownLinks.js +228 -0
  27. package/dist/core/links/MarkdownLinks.js.map +1 -0
  28. package/dist/core/links/RefStore.d.ts +32 -0
  29. package/dist/core/links/RefStore.d.ts.map +1 -0
  30. package/dist/core/links/RefStore.js +60 -0
  31. package/dist/core/links/RefStore.js.map +1 -0
  32. package/dist/core/links/markdownFences.d.ts +10 -0
  33. package/dist/core/links/markdownFences.d.ts.map +1 -0
  34. package/dist/core/links/markdownFences.js +51 -0
  35. package/dist/core/links/markdownFences.js.map +1 -0
  36. package/dist/core/paths.d.ts +8 -0
  37. package/dist/core/paths.d.ts.map +1 -1
  38. package/dist/core/paths.js +13 -0
  39. package/dist/core/paths.js.map +1 -1
  40. package/dist/core/sidecar.d.ts +45 -0
  41. package/dist/core/sidecar.d.ts.map +1 -0
  42. package/dist/core/sidecar.js +83 -0
  43. package/dist/core/sidecar.js.map +1 -0
  44. package/dist/core/{DocSummaries.d.ts → summaries/DocSummaries.d.ts} +13 -3
  45. package/dist/core/summaries/DocSummaries.d.ts.map +1 -0
  46. package/dist/core/{DocSummaries.js → summaries/DocSummaries.js} +31 -11
  47. package/dist/core/summaries/DocSummaries.js.map +1 -0
  48. package/dist/core/summaries/StampStore.d.ts +19 -0
  49. package/dist/core/summaries/StampStore.d.ts.map +1 -0
  50. package/dist/core/summaries/StampStore.js +34 -0
  51. package/dist/core/summaries/StampStore.js.map +1 -0
  52. package/dist/core/summaries/SummaryTree.bench.d.ts.map +1 -0
  53. package/dist/core/{SummaryTree.bench.js → summaries/SummaryTree.bench.js} +24 -14
  54. package/dist/core/summaries/SummaryTree.bench.js.map +1 -0
  55. package/dist/core/{SummaryTree.d.ts → summaries/SummaryTree.d.ts} +10 -1
  56. package/dist/core/summaries/SummaryTree.d.ts.map +1 -0
  57. package/dist/core/{SummaryTree.js → summaries/SummaryTree.js} +35 -9
  58. package/dist/core/summaries/SummaryTree.js.map +1 -0
  59. package/dist/index.d.ts +5 -5
  60. package/dist/index.d.ts.map +1 -1
  61. package/dist/index.js +10 -10
  62. package/dist/index.js.map +1 -1
  63. package/dist/init/content.d.ts +2 -2
  64. package/dist/init/content.d.ts.map +1 -1
  65. package/dist/init/content.js +45 -15
  66. package/dist/init/content.js.map +1 -1
  67. package/dist/init/generate.d.ts +1 -1
  68. package/dist/init/generate.d.ts.map +1 -1
  69. package/dist/init/generate.js +1 -1
  70. package/dist/io/DocsFs.d.ts +2 -3
  71. package/dist/io/DocsFs.d.ts.map +1 -1
  72. package/dist/io/DocsFs.js +15 -5
  73. package/dist/io/DocsFs.js.map +1 -1
  74. package/dist/program/JsonReport.d.ts +2 -2
  75. package/dist/program/JsonReport.d.ts.map +1 -1
  76. package/dist/program/JsonReport.js +2 -2
  77. package/dist/program/JsonReport.js.map +1 -1
  78. package/dist/program/{CheckLinks.d.ts → links/CheckLinks.d.ts} +9 -4
  79. package/dist/program/links/CheckLinks.d.ts.map +1 -0
  80. package/dist/program/links/CheckLinks.js +243 -0
  81. package/dist/program/links/CheckLinks.js.map +1 -0
  82. package/dist/program/links/CheckRefs.d.ts +47 -0
  83. package/dist/program/links/CheckRefs.d.ts.map +1 -0
  84. package/dist/program/links/CheckRefs.js +151 -0
  85. package/dist/program/links/CheckRefs.js.map +1 -0
  86. package/dist/program/locale.d.ts.map +1 -1
  87. package/dist/program/summaries/CheckSummaries.bench.d.ts +2 -0
  88. package/dist/program/summaries/CheckSummaries.bench.d.ts.map +1 -0
  89. package/dist/program/summaries/CheckSummaries.bench.js +94 -0
  90. package/dist/program/summaries/CheckSummaries.bench.js.map +1 -0
  91. package/dist/program/summaries/CheckSummaries.d.ts +58 -0
  92. package/dist/program/summaries/CheckSummaries.d.ts.map +1 -0
  93. package/dist/program/summaries/CheckSummaries.js +302 -0
  94. package/dist/program/summaries/CheckSummaries.js.map +1 -0
  95. package/package.json +7 -8
  96. package/schema/cairn.schema.json +35 -38
  97. package/dist/core/DocSummaries.d.ts.map +0 -1
  98. package/dist/core/DocSummaries.js.map +0 -1
  99. package/dist/core/MarkdownLinks.bench.d.ts.map +0 -1
  100. package/dist/core/MarkdownLinks.bench.js.map +0 -1
  101. package/dist/core/MarkdownLinks.d.ts +0 -51
  102. package/dist/core/MarkdownLinks.d.ts.map +0 -1
  103. package/dist/core/MarkdownLinks.js +0 -115
  104. package/dist/core/MarkdownLinks.js.map +0 -1
  105. package/dist/core/SummaryTree.bench.d.ts.map +0 -1
  106. package/dist/core/SummaryTree.bench.js.map +0 -1
  107. package/dist/core/SummaryTree.d.ts.map +0 -1
  108. package/dist/core/SummaryTree.js.map +0 -1
  109. package/dist/program/CheckLinks.d.ts.map +0 -1
  110. package/dist/program/CheckLinks.js +0 -122
  111. package/dist/program/CheckLinks.js.map +0 -1
  112. package/dist/program/CheckSummaries.d.ts +0 -38
  113. package/dist/program/CheckSummaries.d.ts.map +0 -1
  114. package/dist/program/CheckSummaries.js +0 -198
  115. package/dist/program/CheckSummaries.js.map +0 -1
  116. /package/dist/core/{MarkdownLinks.bench.d.ts → links/MarkdownLinks.bench.d.ts} +0 -0
  117. /package/dist/core/{SummaryTree.bench.d.ts → summaries/SummaryTree.bench.d.ts} +0 -0
@@ -0,0 +1,45 @@
1
+ import { Schema } from 'effect';
2
+ /** The hidden directory name every metadata tree lives under, relative to `base`. */
3
+ export declare const META_DIR = ".cairn";
4
+ export interface MetaLayout {
5
+ /** The project root every node path and every sidecar is resolved under. */
6
+ readonly base: string;
7
+ /** `join(base, META_DIR)` — passed explicitly (not recomputed) so callers who
8
+ * already have it (e.g. after listing `.cairn/**`) don't rederive it. */
9
+ readonly metaRoot: string;
10
+ }
11
+ export declare const metaRootFor: (base: string) => string;
12
+ /** True for any path inside the hidden metadata tree — used to keep `.cairn/**`
13
+ * out of the set of markdown source files a plan considers. */
14
+ export declare const isSidecarPath: (candidate: string, metaRoot: string) => boolean;
15
+ /**
16
+ * `<base>/docs/a.summary.md` -> `<metaRoot>/docs/a.summary.md.json`, or, with
17
+ * a `namespace` (e.g. `'refs'`), `<metaRoot>/refs/docs/a.summary.md.json` —
18
+ * the mechanism that keeps two DIFFERENT sidecar kinds for the SAME doc path
19
+ * from colliding (a doc's own freshness stamp vs its reference hashes; see
20
+ * `links/RefStore.ts`'s header for the real collision this closes). Throws
21
+ * if `nodeAtPath` isn't under `base`: every real node path is (roots are
22
+ * always resolved under the project root before a plan ever runs), so this
23
+ * signals a caller bug, not a runtime data condition to recover from.
24
+ */
25
+ export declare const sidecarPathFor: (nodeAtPath: string, layout: MetaLayout, namespace?: string) => string;
26
+ /**
27
+ * The inverse of `sidecarPathFor` (namespace-free form): given a sidecar's
28
+ * own path (e.g. found by listing `.cairn/**`), recover the node path it
29
+ * mirrors. Returns `null` for a path that isn't a well-formed sidecar under
30
+ * `metaRoot` (not `.json`, or outside the tree) rather than throwing —
31
+ * unlike `sidecarPathFor`, this reads data that could plausibly be malformed
32
+ * (a stray non-JSON file dropped into `.cairn/` by hand), so `null` is the
33
+ * right "not a sidecar" signal, not a crash.
34
+ */
35
+ export declare const nodePathForSidecar: (sidecarPath: string, layout: MetaLayout) => string | null;
36
+ export interface SidecarCodec<A> {
37
+ /** Read a sidecar's record back, or `null` if missing/corrupt/malformed —
38
+ * NEVER throws (see module header). */
39
+ readonly parse: (content: string) => A | null;
40
+ /** The sidecar's on-disk JSON form. Trailing newline for a clean git diff. */
41
+ readonly serialize: (record: A) => string;
42
+ }
43
+ /** Build a lenient JSON codec for one sidecar record shape from its `Schema`. */
44
+ export declare const makeSidecarCodec: <S extends Parameters<typeof Schema.decodeUnknownResult>[0]>(schema: S) => SidecarCodec<S['Type']>;
45
+ //# sourceMappingURL=sidecar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidecar.d.ts","sourceRoot":"","sources":["../../src/core/sidecar.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAU,MAAM,EAAE,MAAM,QAAQ,CAAA;AAKvC,qFAAqF;AACrF,eAAO,MAAM,QAAQ,WAAW,CAAA;AAEhC,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB;6EACyE;IACzE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED,eAAO,MAAM,WAAW,SAAU,MAAM,KAAG,MAAmC,CAAA;AAE9E;+DAC+D;AAC/D,eAAO,MAAM,aAAa,cAAe,MAAM,YAAY,MAAM,KAAG,OACJ,CAAA;AAEhE;;;;;;;;;GASG;AACH,eAAO,MAAM,cAAc,eAAgB,MAAM,UAAU,UAAU,cAAc,MAAM,KAAG,MAO3F,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB,gBAAiB,MAAM,UAAU,UAAU,KAAG,MAAM,GAAG,IASrF,CAAA;AAED,MAAM,WAAW,YAAY,CAAC,CAAC;IAC7B;2CACuC;IACvC,QAAQ,CAAC,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,CAAC,GAAG,IAAI,CAAA;IAC7C,8EAA8E;IAC9E,QAAQ,CAAC,SAAS,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,MAAM,CAAA;CAC1C;AAED,iFAAiF;AACjF,eAAO,MAAM,gBAAgB,GAAI,CAAC,SAAS,UAAU,CAAC,OAAO,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC,UACjF,CAAC,KACR,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAexB,CAAA"}
@@ -0,0 +1,83 @@
1
+ // The shared low-level primitive under every hidden `.cairn/**` metadata
2
+ // sidecar: path mapping (a node's real path -> its sidecar's path, and back)
3
+ // and a lenient JSON codec factory. Used by BOTH `summaries/StampStore.ts`
4
+ // (doc-freshness records) and `links/RefStore.ts` (reference content-hash
5
+ // records) — genuinely shared mechanics, kept deliberately separate from
6
+ // either domain's own record shape (`StampRecord` vs `RefsRecord`), which
7
+ // stay domain-owned: forcing one schema to serve two different sidecar
8
+ // kinds would leave one half always meaningless for any given sidecar.
9
+ //
10
+ // Two invariants this module enforces:
11
+ // - every node path handed to `sidecarPathFor` must live under `base` (real
12
+ // usage: `base` is the project root, every root/node resolved under it) —
13
+ // violating this is a programming error, not a data error, so it throws;
14
+ // - a codec's `parse` decodes LENIENTLY: unknown keys are ignored rather
15
+ // than rejected (forward-compatible), and a corrupt/hand-edited/merge-
16
+ // conflicted sidecar reads as `null` — exactly equivalent to no record at
17
+ // all, never a crash.
18
+ import * as nodePath from 'node:path';
19
+ import { Result, Schema } from 'effect';
20
+ // POSIX path semantics so sidecar paths are identical on every OS.
21
+ const path = nodePath.posix;
22
+ /** The hidden directory name every metadata tree lives under, relative to `base`. */
23
+ export const META_DIR = '.cairn';
24
+ export const metaRootFor = (base) => path.join(base, META_DIR);
25
+ /** True for any path inside the hidden metadata tree — used to keep `.cairn/**`
26
+ * out of the set of markdown source files a plan considers. */
27
+ export const isSidecarPath = (candidate, metaRoot) => candidate === metaRoot || candidate.startsWith(`${metaRoot}/`);
28
+ /**
29
+ * `<base>/docs/a.summary.md` -> `<metaRoot>/docs/a.summary.md.json`, or, with
30
+ * a `namespace` (e.g. `'refs'`), `<metaRoot>/refs/docs/a.summary.md.json` —
31
+ * the mechanism that keeps two DIFFERENT sidecar kinds for the SAME doc path
32
+ * from colliding (a doc's own freshness stamp vs its reference hashes; see
33
+ * `links/RefStore.ts`'s header for the real collision this closes). Throws
34
+ * if `nodeAtPath` isn't under `base`: every real node path is (roots are
35
+ * always resolved under the project root before a plan ever runs), so this
36
+ * signals a caller bug, not a runtime data condition to recover from.
37
+ */
38
+ export const sidecarPathFor = (nodeAtPath, layout, namespace) => {
39
+ const rel = path.relative(layout.base, nodeAtPath);
40
+ if (rel.startsWith('..') || path.isAbsolute(rel)) {
41
+ throw new Error(`sidecarPathFor: "${nodeAtPath}" is not under base "${layout.base}"`);
42
+ }
43
+ const root = namespace === undefined ? layout.metaRoot : path.join(layout.metaRoot, namespace);
44
+ return `${path.join(root, rel)}.json`;
45
+ };
46
+ /**
47
+ * The inverse of `sidecarPathFor` (namespace-free form): given a sidecar's
48
+ * own path (e.g. found by listing `.cairn/**`), recover the node path it
49
+ * mirrors. Returns `null` for a path that isn't a well-formed sidecar under
50
+ * `metaRoot` (not `.json`, or outside the tree) rather than throwing —
51
+ * unlike `sidecarPathFor`, this reads data that could plausibly be malformed
52
+ * (a stray non-JSON file dropped into `.cairn/` by hand), so `null` is the
53
+ * right "not a sidecar" signal, not a crash.
54
+ */
55
+ export const nodePathForSidecar = (sidecarPath, layout) => {
56
+ if (!isSidecarPath(sidecarPath, layout.metaRoot) || !sidecarPath.endsWith('.json')) {
57
+ return null;
58
+ }
59
+ const rel = path.relative(layout.metaRoot, sidecarPath);
60
+ if (rel.startsWith('..')) {
61
+ return null;
62
+ }
63
+ return path.join(layout.base, rel.slice(0, -'.json'.length));
64
+ };
65
+ /** Build a lenient JSON codec for one sidecar record shape from its `Schema`. */
66
+ export const makeSidecarCodec = (schema) => {
67
+ const decode = Schema.decodeUnknownResult(schema);
68
+ return {
69
+ parse: (content) => {
70
+ let json;
71
+ try {
72
+ json = JSON.parse(content);
73
+ }
74
+ catch {
75
+ return null;
76
+ }
77
+ const decoded = decode(json);
78
+ return Result.isSuccess(decoded) ? decoded.success : null;
79
+ },
80
+ serialize: (record) => `${JSON.stringify(record, null, 2)}\n`,
81
+ };
82
+ };
83
+ //# sourceMappingURL=sidecar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sidecar.js","sourceRoot":"","sources":["../../src/core/sidecar.ts"],"names":[],"mappings":"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"}
@@ -29,14 +29,24 @@ export declare const isSummaryFile: (path: string, naming?: Naming) => boolean;
29
29
  export declare const summaryPathFor: (path: string, naming?: Naming) => string;
30
30
  /** A non-summary Markdown file longer than the threshold must have a summary. */
31
31
  export declare const needsSummary: ({ lineCount, naming, path, thresholdLines, }: NeedsSummaryArgs) => boolean;
32
- /** Deterministic content hash used to stamp and verify summaries. */
33
- export declare const hashContent: (content: string) => string;
34
32
  /** The HTML-comment stamp a summary must carry to declare which source it reflects. */
35
33
  export declare const sourceHashTag: (hash: string) => string;
36
34
  /** Read back the source hash recorded in a summary, or null if absent. */
37
35
  export declare const extractSourceHash: (summaryContent: string) => string | null;
38
- /** Return the summary content stamped with `hash` (replacing any existing stamp). */
36
+ /** Return the summary content stamped with `hash` (replacing any existing stamp).
37
+ * Retained only for the one-off `--migrate-stamps` path (`CheckSummaries.ts`),
38
+ * which needs to recognise the OLD in-content form while migrating a repo off
39
+ * it — the ongoing stamp mechanism now lives in a `.cairn/**` sidecar
40
+ * (`StampStore.ts`), never in a summary's own content. */
39
41
  export declare const withSourceHash: (summaryContent: string, hash: string) => string;
42
+ /**
43
+ * Remove a legacy in-content stamp (and the blank line `withSourceHash` used to
44
+ * insert after it), leaving pure authored prose. The one-time migration step:
45
+ * `--migrate-stamps` calls this on every summary that still carries the old
46
+ * comment, before writing the hash to its `.cairn/**` sidecar instead. A no-op
47
+ * (returns `summaryContent` unchanged) when no stamp is present.
48
+ */
49
+ export declare const stripSourceHash: (summaryContent: string) => string;
40
50
  /** Classify a summary: missing, stale (hash absent or mismatched) or ok. */
41
51
  export declare const classifySummary: ({ recordedHash, sourceHash, summaryExists }: ClassifyArgs) => SummaryStatus;
42
52
  //# sourceMappingURL=DocSummaries.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocSummaries.d.ts","sourceRoot":"","sources":["../../../src/core/summaries/DocSummaries.ts"],"names":[],"mappings":"AAyBA,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAAA;AAEtD,qDAAqD;AACrD,MAAM,WAAW,MAAM;IACrB,yDAAyD;IACzD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAA;CACnC;AAED,4DAA4D;AAC5D,eAAO,MAAM,cAAc,EAAE,MAG5B,CAAA;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAA;CAChC;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAA;CAChC;AAED,sEAAsE;AACtE,eAAO,MAAM,uBAAuB,KAAK,CAAA;AAIzC,uDAAuD;AACvD,eAAO,MAAM,UAAU,YAAa,MAAM,KAAG,MAM5C,CAAA;AAED,uDAAuD;AACvD,eAAO,MAAM,aAAa,SAAU,MAAM,WAAU,MAAM,KAAoB,OACrC,CAAA;AAEzC,wEAAwE;AACxE,eAAO,MAAM,cAAc,SAAU,MAAM,WAAU,MAAM,KAAoB,MAC9B,CAAA;AAEjD,iFAAiF;AACjF,eAAO,MAAM,YAAY,iDAKtB,gBAAgB,KAAG,OAQrB,CAAA;AAED,uFAAuF;AACvF,eAAO,MAAM,aAAa,SAAU,MAAM,KAAG,MAA2C,CAAA;AAExF,0EAA0E;AAC1E,eAAO,MAAM,iBAAiB,mBAAoB,MAAM,KAAG,MAAM,GAAG,IAAiD,CAAA;AAErH;;;;0DAI0D;AAC1D,eAAO,MAAM,cAAc,mBAAoB,MAAM,QAAQ,MAAM,KAAG,MAMrE,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,mBAAoB,MAAM,KAAG,MAKxD,CAAA;AAED,4EAA4E;AAC5E,eAAO,MAAM,eAAe,gDAAiD,YAAY,KAAG,aAQ3F,CAAA"}
@@ -6,13 +6,22 @@
6
6
  // Freshness is enforced by a content hash, NOT by filesystem mtime: git does not
7
7
  // preserve mtimes, so after a clone/checkout (e.g. in CI) every file shares the
8
8
  // same timestamp and a time-based check silently passes on stale summaries.
9
- // Each summary embeds `<!-- source-sha256: ... -->`; the checker recomputes the
10
- // source hash and flags any mismatch. Deterministic and clone-independent.
9
+ // The recorded hash lives in a hidden `.cairn/**` sidecar (StampStore.ts), never
10
+ // inside the summary's own content the checker recomputes the source hash and
11
+ // flags any mismatch against whatever the sidecar last recorded. Deterministic
12
+ // and clone-independent. `extractSourceHash`/`withSourceHash`/`HASH_RE` below
13
+ // recognise the OLD in-content `<!-- source-sha256: ... -->` form; they're kept
14
+ // only for `stripSourceHash` and the one-off `--migrate-stamps` path that moves
15
+ // an existing repo off it.
11
16
  //
12
17
  // Naming (directory-summary filename, file-summary suffix) is configurable; the
13
18
  // defaults below reproduce the original behaviour. Unit-tested in
14
- // DocSummaries.unit.test.ts; the Effect program is in ../program/CheckSummaries.ts.
15
- import { hash as hashHex } from 'node:crypto';
19
+ // DocSummaries.unit.test.ts; the Effect program is in ../../program/summaries/CheckSummaries.ts.
20
+ //
21
+ // `hashContent` itself lives in `../hashing.ts`, not here — it's genuinely
22
+ // shared (links/CheckRefs.ts hashes REFERENCED targets with the exact same
23
+ // function), not summary-specific; found via an import-graph audit that
24
+ // this file was the one summaries/ module a links/ program also depended on.
16
25
  /** Defaults matching the original hard-coded convention. */
17
26
  export const DEFAULT_NAMING = {
18
27
  dirSummary: '_SUMMARY.md',
@@ -43,17 +52,15 @@ export const needsSummary = ({ lineCount, naming = DEFAULT_NAMING, path, thresho
43
52
  }
44
53
  return lineCount > thresholdLines;
45
54
  };
46
- // One-shot `crypto.hash` (Node >=20.12) skips the streaming Hash object's
47
- // internal state entirely — faster than `createHash().update().digest()` for
48
- // the KB-sized markdown content this hashes, at the scale this runs at (once
49
- // per file/manifest per plan).
50
- /** Deterministic content hash used to stamp and verify summaries. */
51
- export const hashContent = (content) => hashHex('sha256', content, 'hex');
52
55
  /** The HTML-comment stamp a summary must carry to declare which source it reflects. */
53
56
  export const sourceHashTag = (hash) => `<!-- source-sha256: ${hash} -->`;
54
57
  /** Read back the source hash recorded in a summary, or null if absent. */
55
58
  export const extractSourceHash = (summaryContent) => HASH_RE.exec(summaryContent)?.[1] ?? null;
56
- /** Return the summary content stamped with `hash` (replacing any existing stamp). */
59
+ /** Return the summary content stamped with `hash` (replacing any existing stamp).
60
+ * Retained only for the one-off `--migrate-stamps` path (`CheckSummaries.ts`),
61
+ * which needs to recognise the OLD in-content form while migrating a repo off
62
+ * it — the ongoing stamp mechanism now lives in a `.cairn/**` sidecar
63
+ * (`StampStore.ts`), never in a summary's own content. */
57
64
  export const withSourceHash = (summaryContent, hash) => {
58
65
  const tag = sourceHashTag(hash);
59
66
  if (HASH_RE.test(summaryContent)) {
@@ -61,6 +68,19 @@ export const withSourceHash = (summaryContent, hash) => {
61
68
  }
62
69
  return `${tag}\n\n${summaryContent}`;
63
70
  };
71
+ /**
72
+ * Remove a legacy in-content stamp (and the blank line `withSourceHash` used to
73
+ * insert after it), leaving pure authored prose. The one-time migration step:
74
+ * `--migrate-stamps` calls this on every summary that still carries the old
75
+ * comment, before writing the hash to its `.cairn/**` sidecar instead. A no-op
76
+ * (returns `summaryContent` unchanged) when no stamp is present.
77
+ */
78
+ export const stripSourceHash = (summaryContent) => {
79
+ if (!HASH_RE.test(summaryContent)) {
80
+ return summaryContent;
81
+ }
82
+ return summaryContent.replace(HASH_RE, '').replace(/^\n+/, '');
83
+ };
64
84
  /** Classify a summary: missing, stale (hash absent or mismatched) or ok. */
65
85
  export const classifySummary = ({ recordedHash, sourceHash, summaryExists }) => {
66
86
  if (!summaryExists) {
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocSummaries.js","sourceRoot":"","sources":["../../../src/core/summaries/DocSummaries.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ export interface StampRecord {
2
+ readonly sha256: string;
3
+ readonly version: number;
4
+ }
5
+ /** Bumped only if the sidecar's own shape changes incompatibly (never for adding
6
+ * an optional field — the codec already tolerates unknown keys, forward-compatible
7
+ * with a future, richer sidecar). */
8
+ export declare const STAMP_VERSION = 1;
9
+ /** The sidecar's on-disk JSON form. Trailing newline for a clean git diff. */
10
+ export declare const serializeStamp: (record: StampRecord) => string;
11
+ /**
12
+ * Read a sidecar's `StampRecord` back, or `null` if it's missing/corrupt/
13
+ * malformed/hand-edited/merge-conflicted — this must NEVER throw. A stamp that
14
+ * can't be trusted is exactly equivalent to no stamp: the node it covers reads
15
+ * as stale, not as a crash (see AGENTS.md's note on treating an unparsable
16
+ * stamp the same as a missing one).
17
+ */
18
+ export declare const parseStamp: (content: string) => StampRecord | null;
19
+ //# sourceMappingURL=StampStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StampStore.d.ts","sourceRoot":"","sources":["../../../src/core/summaries/StampStore.ts"],"names":[],"mappings":"AAiBA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;qCAEqC;AACrC,eAAO,MAAM,aAAa,IAAI,CAAA;AAS9B,8EAA8E;AAC9E,eAAO,MAAM,cAAc,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,MAA6B,CAAA;AAEnF;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,WAAW,GAAG,IAAuB,CAAA"}
@@ -0,0 +1,34 @@
1
+ // The hidden, hierarchy-mirroring metadata tree that replaces the in-content
2
+ // `<!-- source-sha256: H -->` stamp (see AGENTS.md / issue #35). Every
3
+ // summarizable node keeps its authored prose stamp-free; instead, a sidecar
4
+ // JSON file under `<base>/.cairn/` mirrors the node's path 1:1 and carries the
5
+ // freshness hash. This module is pure (no IO): the `StampRecord` shape only.
6
+ // `../../program/summaries/CheckSummaries.ts` is the impure edge that reads/
7
+ // writes sidecars via `DocsFs`.
8
+ //
9
+ // Path mapping and the lenient-decode codec mechanics live in `../sidecar.ts`
10
+ // — genuinely shared with `../links/RefStore.ts` (both are `.cairn/**`
11
+ // sidecars), kept out of this file so it stays about ONE thing: what a
12
+ // summary-freshness record actually contains.
13
+ import { Schema } from 'effect';
14
+ import { makeSidecarCodec } from '../sidecar.js';
15
+ /** Bumped only if the sidecar's own shape changes incompatibly (never for adding
16
+ * an optional field — the codec already tolerates unknown keys, forward-compatible
17
+ * with a future, richer sidecar). */
18
+ export const STAMP_VERSION = 1;
19
+ const StampRecordSchema = Schema.Struct({
20
+ sha256: Schema.String,
21
+ version: Schema.Number,
22
+ });
23
+ const stampCodec = makeSidecarCodec(StampRecordSchema);
24
+ /** The sidecar's on-disk JSON form. Trailing newline for a clean git diff. */
25
+ export const serializeStamp = stampCodec.serialize;
26
+ /**
27
+ * Read a sidecar's `StampRecord` back, or `null` if it's missing/corrupt/
28
+ * malformed/hand-edited/merge-conflicted — this must NEVER throw. A stamp that
29
+ * can't be trusted is exactly equivalent to no stamp: the node it covers reads
30
+ * as stale, not as a crash (see AGENTS.md's note on treating an unparsable
31
+ * stamp the same as a missing one).
32
+ */
33
+ export const parseStamp = stampCodec.parse;
34
+ //# sourceMappingURL=StampStore.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StampStore.js","sourceRoot":"","sources":["../../../src/core/summaries/StampStore.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,uEAAuE;AACvE,4EAA4E;AAC5E,+EAA+E;AAC/E,6EAA6E;AAC7E,6EAA6E;AAC7E,gCAAgC;AAChC,EAAE;AACF,8EAA8E;AAC9E,uEAAuE;AACvE,uEAAuE;AACvE,8CAA8C;AAE9C,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAOhD;;qCAEqC;AACrC,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,CAAA;AAE9B,MAAM,iBAAiB,GAAG,MAAM,CAAC,MAAM,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC,MAAM;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM;CACvB,CAAC,CAAA;AAEF,MAAM,UAAU,GAAG,gBAAgB,CAAC,iBAAiB,CAAC,CAAA;AAEtD,8EAA8E;AAC9E,MAAM,CAAC,MAAM,cAAc,GAAoC,UAAU,CAAC,SAAS,CAAA;AAEnF;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,UAAU,GAA4C,UAAU,CAAC,KAAK,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SummaryTree.bench.d.ts","sourceRoot":"","sources":["../../../src/core/summaries/SummaryTree.bench.ts"],"names":[],"mappings":""}
@@ -1,13 +1,19 @@
1
1
  import * as nodePath from 'node:path';
2
2
  import { bench, describe } from 'vitest';
3
- import { hashContent, isSummaryFile, sourceHashTag, summaryPathFor } from "./DocSummaries.js";
4
- import { DIR_SUMMARY, isDirSummary, planSummaries } from "./SummaryTree.js";
3
+ import { hashContent } from '../hashing.js';
4
+ import { isSummaryFile, summaryPathFor } from './DocSummaries.js';
5
+ import { DIR_SUMMARY, isDirSummary, planSummaries } from './SummaryTree.js';
5
6
  const path = nodePath.posix;
6
7
  const bigContent = (seed) => Array.from({ length: 40 }, (_, i) => `${seed} body line ${i} with some representative prose content`).join('\n');
7
8
  const smallContent = (seed) => `${seed} short note`;
8
- /** A fully stamped, link-complete tree: `planSummaries` on it reports every node `ok`. */
9
- const buildFreshTree = ({ depth, dirsPerLevel, filesPerDir, root }) => {
9
+ /** A fully link-complete tree (no stamps embedded freshness lives in a
10
+ * separate `stamps` map now, see `StampStore.ts` / `SummaryTree.ts`'s
11
+ * `PlanArgs.stamps`), plus the stamps map a real `.cairn/**` sidecar store
12
+ * would hold for it. `planSummaries({files, stamps, ...})` on the pair reports
13
+ * every node `ok` — this is `buildFreshTree`'s "steady state" fixture. */
14
+ const buildFreshTree = ({ depth, dirsPerLevel, filesPerDir, root, }) => {
10
15
  const files = new Map();
16
+ const stamps = new Map();
11
17
  const visit = (dir, level) => {
12
18
  const docTargets = [];
13
19
  const inputs = [];
@@ -19,7 +25,9 @@ const buildFreshTree = ({ depth, dirsPerLevel, filesPerDir, root }) => {
19
25
  docTargets.push(docPath);
20
26
  if (big) {
21
27
  const sp = summaryPathFor(docPath);
22
- files.set(sp, `${sourceHashTag(hashContent(content))}\n\n# summary\n\nSee [source](./${path.basename(docPath)}).`);
28
+ const summaryContent = `# summary\n\nSee [source](./${path.basename(docPath)}).`;
29
+ files.set(sp, summaryContent);
30
+ stamps.set(sp, hashContent(content));
23
31
  inputs.push(sp);
24
32
  }
25
33
  else {
@@ -40,31 +48,33 @@ const buildFreshTree = ({ depth, dirsPerLevel, filesPerDir, root }) => {
40
48
  .toSorted()
41
49
  .join('\n');
42
50
  const links = [...docTargets, ...dirTargets].map((t) => `- [link](${path.relative(dir, t)})`).join('\n');
43
- files.set(`${dir}/${DIR_SUMMARY}`, `${sourceHashTag(hashContent(manifest))}\n\n${links}`);
51
+ files.set(`${dir}/${DIR_SUMMARY}`, links);
52
+ stamps.set(`${dir}/${DIR_SUMMARY}`, hashContent(manifest));
44
53
  };
45
54
  visit(root, 0);
46
- return files;
55
+ return { files, stamps };
47
56
  };
48
- /** Same source docs, no summaries anywhere yet — the "first run" worst case. */
57
+ /** Same source docs, no summaries anywhere yet — the "first run" worst case
58
+ * (no stamps either, matching an empty/not-yet-populated `.cairn/**`). */
49
59
  const sourceOnly = (files) => new Map([...files].filter(([p]) => !isSummaryFile(p) && !isDirSummary(p)));
50
60
  const SMALL = { depth: 1, dirsPerLevel: 9, filesPerDir: 10, root: '/repo/docs' };
51
61
  const LARGE = { depth: 4, dirsPerLevel: 3, filesPerDir: 16, root: '/repo/docs' };
52
62
  const smallFresh = buildFreshTree(SMALL);
53
- const smallRaw = sourceOnly(smallFresh);
63
+ const smallRaw = sourceOnly(smallFresh.files);
54
64
  const largeFresh = buildFreshTree(LARGE);
55
- const largeRaw = sourceOnly(largeFresh);
65
+ const largeRaw = sourceOnly(largeFresh.files);
56
66
  describe('planSummaries()', () => {
57
- bench('~100 files, flat/shallow, first run (no summaries)', () => {
67
+ bench('~100 files, flat/shallow, first run (no summaries, no stamps)', () => {
58
68
  planSummaries({ files: smallRaw, roots: [SMALL.root] });
59
69
  });
60
70
  bench('~100 files, flat/shallow, steady state (fully stamped)', () => {
61
- planSummaries({ files: smallFresh, roots: [SMALL.root] });
71
+ planSummaries({ files: smallFresh.files, roots: [SMALL.root], stamps: smallFresh.stamps });
62
72
  });
63
- bench('~2000 files, deep/nested, first run (no summaries)', () => {
73
+ bench('~2000 files, deep/nested, first run (no summaries, no stamps)', () => {
64
74
  planSummaries({ files: largeRaw, roots: [LARGE.root] });
65
75
  });
66
76
  bench('~2000 files, deep/nested, steady state (fully stamped)', () => {
67
- planSummaries({ files: largeFresh, roots: [LARGE.root] });
77
+ planSummaries({ files: largeFresh.files, roots: [LARGE.root], stamps: largeFresh.stamps });
68
78
  });
69
79
  });
70
80
  //# sourceMappingURL=SummaryTree.bench.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SummaryTree.bench.js","sourceRoot":"","sources":["../../../src/core/summaries/SummaryTree.bench.ts"],"names":[],"mappings":"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"}
@@ -16,11 +16,20 @@ export interface PlanArgs {
16
16
  readonly naming?: Naming;
17
17
  readonly requireDirSummaries?: boolean;
18
18
  readonly roots: readonly string[];
19
+ /** Node path -> recorded hash, loaded from `.cairn/**` sidecars. Optional and
20
+ * defaults to empty — an absent/not-yet-populated stamp store degrades every
21
+ * node to `stale`/`missing`, the correct first-run behaviour, never a crash. */
22
+ readonly stamps?: ReadonlyMap<string, string>;
19
23
  readonly thresholdLines?: number;
20
24
  }
21
25
  export interface SummaryPlan {
22
26
  readonly nodes: readonly PlanNode[];
23
27
  readonly orphans: readonly string[];
28
+ /** A `.cairn/**` sidecar whose node no longer exists — its source doc (and
29
+ * possibly its summary file too) was deleted, renamed, or dropped below the
30
+ * size threshold. See `findDeletedStamps` for why this is distinct from
31
+ * `orphans`. */
32
+ readonly orphanStamps: readonly string[];
24
33
  readonly todo: readonly PlanNode[];
25
34
  }
26
35
  /** True when `p` is a directory summary under the configured naming. */
@@ -41,5 +50,5 @@ export interface NodeHashArgs {
41
50
  */
42
51
  export declare const nodeExpectedHash: ({ files, inputs, kind, path: nodeAtPath }: NodeHashArgs) => string;
43
52
  /** Compute the full hierarchical summary plan from the current file contents. */
44
- export declare const planSummaries: ({ files, ignore, naming, requireDirSummaries, roots, thresholdLines, }: PlanArgs) => SummaryPlan;
53
+ export declare const planSummaries: ({ files, ignore, naming, requireDirSummaries, roots, stamps, thresholdLines, }: PlanArgs) => SummaryPlan;
45
54
  //# sourceMappingURL=SummaryTree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SummaryTree.d.ts","sourceRoot":"","sources":["../../../src/core/summaries/SummaryTree.ts"],"names":[],"mappings":"AA+BA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AAO9D,6CAA6C;AAC7C,eAAO,MAAM,WAAW,QAA4B,CAAA;AAEpD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IAC7B,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;IACpC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAC/B;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;IACtC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;IACjC;;oFAEgF;IAChF,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC7C,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,QAAQ,EAAE,CAAA;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC;;;oBAGgB;IAChB,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAA;IACxC,QAAQ,CAAC,IAAI,EAAE,SAAS,QAAQ,EAAE,CAAA;CACnC;AAMD,wEAAwE;AACxE,eAAO,MAAM,YAAY,MAAO,MAAM,WAAU,MAAM,KAAoB,OACV,CAAA;AA2BhE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3C,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAA;IAClC,QAAQ,CAAC,IAAI,EAAE,KAAK,GAAG,MAAM,CAAA;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACtB;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,gBAAgB,8CAA+C,YAAY,KAAG,MAU1F,CAAA;AAED,iFAAiF;AACjF,eAAO,MAAM,aAAa,mFAQvB,QAAQ,KAAG,WA2Hb,CAAA"}
@@ -6,10 +6,15 @@
6
6
  // direct docs (or their summary when the doc is big) AND the `_SUMMARY.md`
7
7
  // of its direct sub-directories.
8
8
  //
9
- // Freshness is content-hash based (clone/CI-proof, unlike mtime). Each summary
10
- // embeds `<!-- source-sha256: H -->`:
9
+ // Freshness is content-hash based (clone/CI-proof, unlike mtime). Each summary's
10
+ // hash H is recorded in a hidden sidecar under `.cairn/` (see StampStore.ts),
11
+ // never inside the summary's own content:
11
12
  // - file summary -> H = hash(source doc content)
12
13
  // - dir summary -> H = hash(manifest of its inputs' relative-path:content-hash)
14
+ // `planSummaries` never reads or writes a sidecar itself — it's handed the
15
+ // already-loaded `stamps` map (node path -> recorded hash) as a plain value, so
16
+ // this whole module stays pure and storage-agnostic; `program/CheckSummaries.ts`
17
+ // is the impure edge that loads `stamps` from `.cairn/**` via `DocsFs`.
13
18
  //
14
19
  // `planSummaries` returns every expected summary with its status and, crucially,
15
20
  // the bottom-up order in which to (re)generate them so a single pass converges:
@@ -19,14 +24,16 @@
19
24
  // Filenames (`naming`), the line threshold, ignored globs and whether directory
20
25
  // summaries are required are all configurable; defaults reproduce the original.
21
26
  import * as nodePath from 'node:path';
22
- import { countLines, DEFAULT_NAMING, extractSourceHash, hashContent, isSummaryFile, summaryPathFor, } from "./DocSummaries.js";
23
- import { matchesAny } from "./glob.js";
24
- import { extractLinks, isCheckableTarget, stripAnchor, stripCode } from "./MarkdownLinks.js";
27
+ import { extractLinks, isCheckableTarget, stripAnchor, stripCode } from '../links/MarkdownLinks.js';
28
+ import { matchesAny } from '../glob.js';
29
+ import { hashContent } from '../hashing.js';
30
+ import { countLines, DEFAULT_NAMING, isSummaryFile, summaryPathFor } from './DocSummaries.js';
25
31
  // POSIX path semantics so the plan is identical on every OS (inputs normalised
26
32
  // to `/` at the IO boundary).
27
33
  const path = nodePath.posix;
28
34
  /** Default per-directory digest filename. */
29
35
  export const DIR_SUMMARY = DEFAULT_NAMING.dirSummary;
36
+ const EMPTY_STAMPS = new Map();
30
37
  const DEFAULT_THRESHOLD_LINES = 30;
31
38
  /** True when `p` is a directory summary under the configured naming. */
32
39
  export const isDirSummary = (p, naming = DEFAULT_NAMING) => p === naming.dirSummary || p.endsWith(`/${naming.dirSummary}`);
@@ -73,9 +80,9 @@ export const nodeExpectedHash = ({ files, inputs, kind, path: nodeAtPath }) => {
73
80
  return hashContent(manifest);
74
81
  };
75
82
  /** Compute the full hierarchical summary plan from the current file contents. */
76
- export const planSummaries = ({ files, ignore = [], naming = DEFAULT_NAMING, requireDirSummaries = true, roots, thresholdLines = DEFAULT_THRESHOLD_LINES, }) => {
83
+ export const planSummaries = ({ files, ignore = [], naming = DEFAULT_NAMING, requireDirSummaries = true, roots, stamps = EMPTY_STAMPS, thresholdLines = DEFAULT_THRESHOLD_LINES, }) => {
77
84
  const allPaths = [...files.keys()];
78
- const recorded = (p) => (files.has(p) ? extractSourceHash(files.get(p) ?? '') : null);
85
+ const recorded = (p) => stamps.get(p) ?? null;
79
86
  const sourceDocs = allPaths.filter((p) => p.endsWith('.md') && !isSummaryFile(p, naming) && !isDirSummary(p, naming) && !matchesAny(p, ignore));
80
87
  // Computed once per doc up front (a Set lookup below) rather than via a
81
88
  // countLines() call at each of the two sites that ask "is this doc big" — the
@@ -103,7 +110,12 @@ export const planSummaries = ({ files, ignore = [], naming = DEFAULT_NAMING, req
103
110
  }
104
111
  if (!requireDirSummaries) {
105
112
  const orphans = findOrphans({ files, ignore, naming, nodes: fileNodes, requireDirSummaries });
106
- return { nodes: fileNodes, orphans, todo: fileNodes.filter((n) => n.status !== 'ok') };
113
+ const orphanStamps = findDeletedStamps({
114
+ expectedNodePaths: new Set(fileNodes.map((n) => n.path)),
115
+ ignore,
116
+ stampNodePaths: stamps.keys(),
117
+ });
118
+ return { nodes: fileNodes, orphanStamps, orphans, todo: fileNodes.filter((n) => n.status !== 'ok') };
107
119
  }
108
120
  // --- directories in scope ---
109
121
  const inScope = (d) => roots.some((r) => d === r || d.startsWith(`${r}/`));
@@ -177,8 +189,22 @@ export const planSummaries = ({ files, ignore = [], naming = DEFAULT_NAMING, req
177
189
  dirNodes.sort((a, b) => depth(b.path) - depth(a.path) || a.path.localeCompare(b.path));
178
190
  const nodes = [...fileNodes, ...dirNodes];
179
191
  const orphans = findOrphans({ files, ignore, naming, nodes, requireDirSummaries });
180
- return { nodes, orphans, todo: nodes.filter((n) => n.status !== 'ok') };
192
+ const orphanStamps = findDeletedStamps({
193
+ expectedNodePaths: new Set(nodes.map((n) => n.path)),
194
+ ignore,
195
+ stampNodePaths: stamps.keys(),
196
+ });
197
+ return { nodes, orphanStamps, orphans, todo: nodes.filter((n) => n.status !== 'ok') };
181
198
  };
199
+ /**
200
+ * A `.cairn/**` sidecar (see StampStore.ts) whose node no longer corresponds to
201
+ * any expected node. Unlike `findOrphans` (which only sees a leftover summary
202
+ * FILE still on disk), a sidecar is written exclusively by the tool and never
203
+ * touched by hand — so it remains as evidence even when the summary file
204
+ * itself was deleted alongside its source, catching a deletion `findOrphans`
205
+ * alone would miss entirely.
206
+ */
207
+ const findDeletedStamps = ({ expectedNodePaths, ignore, stampNodePaths }) => [...stampNodePaths].filter((p) => !expectedNodePaths.has(p) && !matchesAny(p, ignore)).toSorted();
182
208
  /**
183
209
  * A `.summary.md`/`_SUMMARY.md` on disk that no longer corresponds to any
184
210
  * expected node — its source doc was deleted, renamed, or (for file summaries)
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SummaryTree.js","sourceRoot":"","sources":["../../../src/core/summaries/SummaryTree.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,10 +1,10 @@
1
- export * from './core/DocSummaries.ts';
1
+ export * from './core/summaries/DocSummaries.ts';
2
2
  export * from './core/glob.ts';
3
- export * from './core/MarkdownLinks.ts';
4
- export * from './core/SummaryTree.ts';
3
+ export * from './core/links/MarkdownLinks.ts';
4
+ export * from './core/summaries/SummaryTree.ts';
5
5
  export * from './io/DocsFs.ts';
6
- export * from './program/CheckLinks.ts';
7
- export * from './program/CheckSummaries.ts';
6
+ export * from './program/links/CheckLinks.ts';
7
+ export * from './program/summaries/CheckSummaries.ts';
8
8
  export * from './program/locale.ts';
9
9
  export * from './config.ts';
10
10
  export type { AgentTarget, InitArgs, InitResult } from './init/generate.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,wBAAwB,CAAA;AACtC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,yBAAyB,CAAA;AACvC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,aAAa,CAAA;AAC3B,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,cAAc,kCAAkC,CAAA;AAChD,cAAc,gBAAgB,CAAA;AAC9B,cAAc,+BAA+B,CAAA;AAC7C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uCAAuC,CAAA;AACrD,cAAc,qBAAqB,CAAA;AACnC,cAAc,aAAa,CAAA;AAC3B,YAAY,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC3E,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA"}
package/dist/index.js CHANGED
@@ -1,13 +1,13 @@
1
1
  // Public API surface. The CLI (`cairn`) is the primary entrypoint, but the pure
2
2
  // planners and Effect programs are exported for programmatic use and testing.
3
- export * from "./core/DocSummaries.js";
4
- export * from "./core/glob.js";
5
- export * from "./core/MarkdownLinks.js";
6
- export * from "./core/SummaryTree.js";
7
- export * from "./io/DocsFs.js";
8
- export * from "./program/CheckLinks.js";
9
- export * from "./program/CheckSummaries.js";
10
- export * from "./program/locale.js";
11
- export * from "./config.js";
12
- export { runInit } from "./init/generate.js";
3
+ export * from './core/summaries/DocSummaries.js';
4
+ export * from './core/glob.js';
5
+ export * from './core/links/MarkdownLinks.js';
6
+ export * from './core/summaries/SummaryTree.js';
7
+ export * from './io/DocsFs.js';
8
+ export * from './program/links/CheckLinks.js';
9
+ export * from './program/summaries/CheckSummaries.js';
10
+ export * from './program/locale.js';
11
+ export * from './config.js';
12
+ export { runInit } from './init/generate.js';
13
13
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,8EAA8E;AAE9E,cAAc,wBAAwB,CAAA;AACtC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,yBAAyB,CAAA;AACvC,cAAc,uBAAuB,CAAA;AACrC,cAAc,gBAAgB,CAAA;AAC9B,cAAc,yBAAyB,CAAA;AACvC,cAAc,6BAA6B,CAAA;AAC3C,cAAc,qBAAqB,CAAA;AACnC,cAAc,aAAa,CAAA;AAE3B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,8EAA8E;AAE9E,cAAc,kCAAkC,CAAA;AAChD,cAAc,gBAAgB,CAAA;AAC9B,cAAc,+BAA+B,CAAA;AAC7C,cAAc,iCAAiC,CAAA;AAC/C,cAAc,gBAAgB,CAAA;AAC9B,cAAc,+BAA+B,CAAA;AAC7C,cAAc,uCAAuC,CAAA;AACrD,cAAc,qBAAqB,CAAA;AACnC,cAAc,aAAa,CAAA;AAE3B,OAAO,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAA"}