@sledorze/cairn 0.1.0 → 0.2.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 (57) hide show
  1. package/README.md +33 -18
  2. package/dist/cli.js +68527 -70592
  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 +21 -21
  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/DocSummaries.d.ts +13 -1
  12. package/dist/core/DocSummaries.d.ts.map +1 -1
  13. package/dist/core/DocSummaries.js +25 -3
  14. package/dist/core/DocSummaries.js.map +1 -1
  15. package/dist/core/MarkdownLinks.bench.js +1 -1
  16. package/dist/core/MarkdownLinks.d.ts.map +1 -1
  17. package/dist/core/StampStore.d.ts +47 -0
  18. package/dist/core/StampStore.d.ts.map +1 -0
  19. package/dist/core/StampStore.js +90 -0
  20. package/dist/core/StampStore.js.map +1 -0
  21. package/dist/core/SummaryTree.bench.js +23 -14
  22. package/dist/core/SummaryTree.bench.js.map +1 -1
  23. package/dist/core/SummaryTree.d.ts +10 -1
  24. package/dist/core/SummaryTree.d.ts.map +1 -1
  25. package/dist/core/SummaryTree.js +34 -9
  26. package/dist/core/SummaryTree.js.map +1 -1
  27. package/dist/core/glob.bench.js +1 -1
  28. package/dist/core/glob.d.ts.map +1 -1
  29. package/dist/core/paths.d.ts.map +1 -1
  30. package/dist/index.js +10 -10
  31. package/dist/init/content.d.ts +2 -2
  32. package/dist/init/content.d.ts.map +1 -1
  33. package/dist/init/content.js +45 -15
  34. package/dist/init/content.js.map +1 -1
  35. package/dist/init/generate.d.ts +1 -1
  36. package/dist/init/generate.d.ts.map +1 -1
  37. package/dist/init/generate.js +1 -1
  38. package/dist/io/DocsFs.d.ts +2 -3
  39. package/dist/io/DocsFs.d.ts.map +1 -1
  40. package/dist/io/DocsFs.js +15 -5
  41. package/dist/io/DocsFs.js.map +1 -1
  42. package/dist/program/CheckLinks.d.ts.map +1 -1
  43. package/dist/program/CheckLinks.js +4 -4
  44. package/dist/program/CheckLinks.js.map +1 -1
  45. package/dist/program/CheckSummaries.bench.d.ts +2 -0
  46. package/dist/program/CheckSummaries.bench.d.ts.map +1 -0
  47. package/dist/program/CheckSummaries.bench.js +92 -0
  48. package/dist/program/CheckSummaries.bench.js.map +1 -0
  49. package/dist/program/CheckSummaries.d.ts +25 -5
  50. package/dist/program/CheckSummaries.d.ts.map +1 -1
  51. package/dist/program/CheckSummaries.js +143 -40
  52. package/dist/program/CheckSummaries.js.map +1 -1
  53. package/dist/program/JsonReport.d.ts.map +1 -1
  54. package/dist/program/JsonReport.js +2 -2
  55. package/dist/program/locale.d.ts.map +1 -1
  56. package/package.json +6 -8
  57. package/schema/cairn.schema.json +35 -38
@@ -1,5 +1,4 @@
1
- import { FileSystem, Path } from '@effect/platform';
2
- import { Context, Effect, Layer } from 'effect';
1
+ import { Context, Effect, FileSystem, Layer, Path } from 'effect';
3
2
  export interface FileStat {
4
3
  readonly mtimeMs: number;
5
4
  readonly sizeBytes: number;
@@ -12,7 +11,7 @@ export interface DocsFsService {
12
11
  readonly stat: (abs: string) => Effect.Effect<FileStat>;
13
12
  readonly writeFile: (abs: string, content: string) => Effect.Effect<void>;
14
13
  }
15
- declare const DocsFs_base: Context.TagClass<DocsFs, "DocsFs", DocsFsService>;
14
+ declare const DocsFs_base: Context.ServiceClass<DocsFs, "DocsFs", DocsFsService>;
16
15
  export declare class DocsFs extends DocsFs_base {
17
16
  }
18
17
  /** Live implementation bound to the Node filesystem. */
@@ -1 +1 @@
1
- {"version":3,"file":"DocsFs.d.ts","sourceRoot":"","sources":["../../src/io/DocsFs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAU,MAAM,QAAQ,CAAA;AAIvD,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACzD,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACxD,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,CAAC,CAAA;IAClF,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACzD,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACvD,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CAC1E;;AAED,qBAAa,MAAO,SAAQ,WAA8C;CAAG;AAE7E,wDAAwD;AACxD,eAAO,MAAM,UAAU,+DA2DtB,CAAA;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CA2ClF,CAAA"}
1
+ {"version":3,"file":"DocsFs.d.ts","sourceRoot":"","sources":["../../src/io/DocsFs.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAU,IAAI,EAAE,MAAM,QAAQ,CAAA;AAIzE,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;CAC3B;AAED,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IACzD,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IACxD,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,KAAK,MAAM,CAAC,MAAM,CAAC,SAAS,MAAM,EAAE,CAAC,CAAA;IAClF,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IACzD,QAAQ,CAAC,IAAI,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IACvD,QAAQ,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;CAC1E;;AAED,qBAAa,MAAO,SAAQ,WAAkD;CAAG;AAEjF,wDAAwD;AACxD,eAAO,MAAM,UAAU,+DAwEtB,CAAA;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,UAAW,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAG,KAAK,CAAC,KAAK,CAAC,MAAM,CA2ClF,CAAA"}
package/dist/io/DocsFs.js CHANGED
@@ -1,10 +1,9 @@
1
1
  // Filesystem capability for the docs checkers, expressed as an Effect service
2
2
  // so programs stay testable. `DocsFsLive` binds it to the real Node platform
3
3
  // (via @effect/platform-node); `makeTestDocsFs` provides an in-memory layer.
4
- import { FileSystem, Path } from '@effect/platform';
5
- import { Context, Effect, Layer, Option } from 'effect';
6
- import { toPosix } from "../core/paths.js";
7
- export class DocsFs extends Context.Tag('DocsFs')() {
4
+ import { Context, Effect, FileSystem, Layer, Option, Path } from 'effect';
5
+ import { toPosix } from '../core/paths.js';
6
+ export class DocsFs extends Context.Service()('DocsFs') {
8
7
  }
9
8
  /** Live implementation bound to the Node filesystem. */
10
9
  export const DocsFsLive = Layer.effect(DocsFs, Effect.gen(function* () {
@@ -42,13 +41,24 @@ export const DocsFsLive = Layer.effect(DocsFs, Effect.gen(function* () {
42
41
  mtimeMs: Option.match(info.mtime, { onNone: () => 0, onSome: (d) => d.getTime() }),
43
42
  sizeBytes: Number(info.size),
44
43
  })), Effect.orDie);
44
+ // Every existing caller wrote into a directory that was already there (a doc's
45
+ // own directory, always present since the doc itself lives in it). That
46
+ // invariant broke the moment sidecar writes started targeting a brand-new
47
+ // `.cairn/**` tree (StampStore.ts / CheckSummaries.ts) — the FIRST sidecar
48
+ // under a given directory has no directory to write into yet. `recursive:
49
+ // true` makes this a no-op when the directory already exists, so it's safe
50
+ // to do unconditionally rather than only for `.cairn/**` paths.
51
+ const writeFile = (abs, content) => Effect.gen(function* () {
52
+ yield* fs.makeDirectory(path.dirname(abs), { recursive: true });
53
+ yield* fs.writeFileString(abs, content);
54
+ }).pipe(Effect.orDie);
45
55
  return {
46
56
  deleteFile: (abs) => fs.remove(abs).pipe(Effect.orDie),
47
57
  exists: (abs) => fs.exists(abs).pipe(Effect.orDie),
48
58
  listFiles,
49
59
  readFile: (abs) => fs.readFileString(abs).pipe(Effect.orDie),
50
60
  stat,
51
- writeFile: (abs, content) => fs.writeFileString(abs, content).pipe(Effect.orDie),
61
+ writeFile,
52
62
  };
53
63
  }));
54
64
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"DocsFs.js","sourceRoot":"","sources":["../../src/io/DocsFs.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DocsFs.js","sourceRoot":"","sources":["../../src/io/DocsFs.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"CheckLinks.d.ts","sourceRoot":"","sources":["../../src/program/CheckLinks.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAE1D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAMzC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAA;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AA+CD,kDAAkD;AAClD,eAAO,MAAM,YAAY,GAAI,QAAQ,eAAe,KAAG,MAA4C,CAAA;AAEnG,oEAAoE;AACpE,eAAO,MAAM,gBAAgB,GAAI,QAAQ,eAAe,EAAE,UAAS,iBAAsB,KAAG,MAAM,EA8BjG,CAAA;AAED,eAAO,MAAM,UAAU,GAAI,yBAIxB,cAAc,KAAG,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,KAAK,EAAE,MAAM,CA2C5D,CAAA"}
1
+ {"version":3,"file":"CheckLinks.d.ts","sourceRoot":"","sources":["../../src/program/CheckLinks.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAE1D,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAMzC,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,KAAK,EAAE,SAAS,UAAU,EAAE,CAAA;CACtC;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;IACtC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;IACnC,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAA;CAClC;AAED,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AA+CD,kDAAkD;AAClD,eAAO,MAAM,YAAY,WAAY,eAAe,KAAG,MAA4C,CAAA;AAEnG,oEAAoE;AACpE,eAAO,MAAM,gBAAgB,WAAY,eAAe,YAAW,iBAAiB,KAAQ,MAAM,EA8BjG,CAAA;AAED,eAAO,MAAM,UAAU,4BAIpB,cAAc,KAAG,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE,KAAK,EAAE,MAAM,CA2C5D,CAAA"}
@@ -3,10 +3,10 @@
3
3
  // ../core/MarkdownLinks.ts; filesystem access goes through the DocsFs service.
4
4
  import * as nodePath from 'node:path';
5
5
  import { Effect } from 'effect';
6
- import { matchesAny } from "../core/glob.js";
7
- import { buildBasenameIndex, checkContent, stripCode } from "../core/MarkdownLinks.js";
8
- import { DocsFs } from "../io/DocsFs.js";
9
- import { pick } from "./locale.js";
6
+ import { matchesAny } from '../core/glob.js';
7
+ import { buildBasenameIndex, checkContent, stripCode } from '../core/MarkdownLinks.js';
8
+ import { DocsFs } from '../io/DocsFs.js';
9
+ import { pick } from './locale.js';
10
10
  // POSIX path semantics (inputs are normalised to `/` at the IO boundary).
11
11
  const path = nodePath.posix;
12
12
  const withAncestors = (files) => {
@@ -1 +1 @@
1
- {"version":3,"file":"CheckLinks.js","sourceRoot":"","sources":["../../src/program/CheckLinks.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"CheckLinks.js","sourceRoot":"","sources":["../../src/program/CheckLinks.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,2EAA2E;AAC3E,+EAA+E;AAE/E,OAAO,KAAK,QAAQ,MAAM,WAAW,CAAA;AAErC,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AAE5C,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AACtF,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AAExC,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAElC,0EAA0E;AAC1E,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAA;AAuB3B,MAAM,aAAa,GAAG,CAAC,KAAwB,EAAe,EAAE;IAC9D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAS,KAAK,CAAC,CAAA;IAClC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;QAC5B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;YACZ,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;YAChC,IAAI,MAAM,KAAK,GAAG,EAAE,CAAC;gBACnB,MAAK;YACP,CAAC;YACD,GAAG,GAAG,MAAM,CAAA;QACd,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA;AAED,wCAAwC;AACxC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAAE,KAAa,EAAU,EAAE,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;AAEnH;;;;GAIG;AACH,MAAM,QAAQ,GAAG,CAAC,OAAe,EAAE,MAAc,EAAE,UAAkB,EAAyC,EAAE;IAC9G,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,CAAA;IACjC,IAAI,IAAI,GAAG,OAAO,CAAA;IAClB,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI;QACvB,CAAC,KAAK,MAAM,GAAG,EAAE,KAAK,UAAU,GAAG,CAAC;QACpC,CAAC,MAAM,MAAM,EAAE,EAAE,MAAM,UAAU,EAAE,CAAC;KAC5B,EAAE,CAAC;QACX,IAAI,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1C,SAAQ;QACV,CAAC;QACD,uEAAuE;QACvE,IAAI,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,CAAC;YACvE,SAAQ;QACV,CAAC;QACD,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChC,OAAO,GAAG,IAAI,CAAA;IAChB,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AACnC,CAAC,CAAA;AAED,kDAAkD;AAClD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,MAAuB,EAAU,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AAEnG,oEAAoE;AACpE,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,MAAuB,EAAE,OAAO,GAAsB,EAAE,EAAY,EAAE;IACrG,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,IAAI,CAAA;IACrC,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CACR,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,oBAAoB,MAAM,CAAC,KAAK,WAAW,EAAE,EAAE,EAAE,kBAAkB,MAAM,CAAC,KAAK,WAAW,EAAE,CAAC,CACjH,CAAA;IACH,CAAC;IACD,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC/B,KAAK,CAAC,IAAI,CACR,IAAI,CAAC,MAAM,EAAE;YACX,EAAE,EAAE,wBAAwB,MAAM,CAAC,OAAO,oBAAoB;YAC9D,EAAE,EAAE,wBAAwB,MAAM,CAAC,OAAO,0BAA0B;SACrE,CAAC,CACH,CAAA;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAA;IACnE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,KAAK,KAAK,gBAAgB,EAAE,EAAE,EAAE,KAAK,KAAK,oBAAoB,EAAE,CAAC,CAAC,CAAA;IAChG,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC,CAAA;QACvB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,GACR,IAAI,CAAC,UAAU,KAAK,SAAS;gBAC3B,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,kBAAkB,IAAI,CAAC,UAAU,EAAE,EAAE,EAAE,EAAE,mBAAmB,IAAI,CAAC,UAAU,EAAE,EAAE,CAAC;gBACrG,CAAC,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,qBAAqB,EAAE,EAAE,EAAE,wBAAwB,EAAE,CAAC,CAAA;YAC/E,KAAK,CAAC,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,MAAM,IAAI,IAAI,EAAE,CAAC,CAAA;QAC3D,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EACzB,GAAG,EACH,MAAM,GAAG,EAAE,EACX,KAAK,GACU,EAAiD,EAAE,CAClE,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,GAAG,GAAG,KAAK,CAAC,CAAC,MAAM,CAAA;IACzB,yEAAyE;IACzE,yEAAyE;IACzE,MAAM,QAAQ,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAA;IAC5C,MAAM,KAAK,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAA;IAC1C,MAAM,KAAK,GAAG,aAAa,CAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,SAAS,GAAG,CAAC,CAAS,EAAW,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;IACtD,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAA;IAE5F,MAAM,MAAM,GAAiB,EAAE,CAAA;IAC/B,IAAI,KAAK,GAAG,CAAC,CAAA;IAEb,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,OAAO,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QACvC,MAAM,KAAK,GAAG,YAAY,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAA;QACxE,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,SAAQ;QACV,CAAC;QAED,MAAM,SAAS,GAAiB,EAAE,CAAA;QAClC,IAAI,OAAO,GAAG,KAAK,CAAA;QACnB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,MAAM,GACV,GAAG,IAAI,IAAI,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;YACpG,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACpB,OAAO,GAAG,MAAM,CAAC,OAAO,CAAA;gBACxB,OAAO,GAAG,IAAI,CAAA;gBACd,KAAK,IAAI,CAAC,CAAA;YACZ,CAAC;iBAAM,CAAC;gBACN,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;YACtB,CAAC;QACH,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,KAAK,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QACrC,CAAC;QACD,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACzB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;QACzC,CAAC;IACH,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE,CAAA;AACnD,CAAC,CAAC,CAAA"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=CheckSummaries.bench.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckSummaries.bench.d.ts","sourceRoot":"","sources":["../../src/program/CheckSummaries.bench.ts"],"names":[],"mappings":""}
@@ -0,0 +1,92 @@
1
+ // Measures the actual new I/O cost the sidecar move introduces: `checkSummaries`
2
+ // now does an extra `dfs.listFiles([metaRoot])` + one `readFile` per sidecar
3
+ // (`readStamps`), on top of the markdown read `planSummaries()`'s own bench
4
+ // (`SummaryTree.bench.ts`) already covers. This is the realistic end-to-end path
5
+ // (`cairn check`), not just the pure planner, so it's the number that matters for
6
+ // "does the sidecar move keep things fast."
7
+ import { Effect } from 'effect';
8
+ import { bench, describe } from 'vitest';
9
+ import { hashContent, isSummaryFile, summaryPathFor } from '../core/DocSummaries.js';
10
+ import { DIR_SUMMARY, isDirSummary } from '../core/SummaryTree.js';
11
+ import { isSidecarPath, metaRootFor, serializeStamp, sidecarPathFor, STAMP_VERSION } from '../core/StampStore.js';
12
+ import { makeTestDocsFs } from '../io/DocsFs.js';
13
+ import { checkSummaries } from './CheckSummaries.js';
14
+ const bigContent = (seed) => Array.from({ length: 40 }, (_, i) => `${seed} body line ${i} with some representative prose content`).join('\n');
15
+ const smallContent = (seed) => `${seed} short note`;
16
+ const tf = (content) => ({ content, mtimeMs: 0 });
17
+ /** A fully link-complete, fully sidecar-stamped tree, as `makeTestDocsFs` fixture
18
+ * data — the "steady state" `cairn check` sees on a clean repo. */
19
+ const buildFreshFixture = (base, { depth, dirsPerLevel, filesPerDir, root }) => {
20
+ const files = {};
21
+ const layout = { base, metaRoot: metaRootFor(base) };
22
+ const visit = (dir, level) => {
23
+ const docTargets = [];
24
+ const inputs = [];
25
+ for (let f = 0; f < filesPerDir; f++) {
26
+ const docPath = `${dir}/doc-${f}.md`;
27
+ const big = f % 3 !== 0;
28
+ const content = big ? bigContent(docPath) : smallContent(docPath);
29
+ files[docPath] = tf(content);
30
+ docTargets.push(docPath);
31
+ if (big) {
32
+ const sp = summaryPathFor(docPath);
33
+ files[sp] = tf(`# summary\n\nSee [source](./${docPath.slice(dir.length + 1)}).`);
34
+ files[sidecarPathFor(sp, layout)] = tf(serializeStamp({ sha256: hashContent(content), version: STAMP_VERSION }));
35
+ inputs.push(sp);
36
+ }
37
+ else {
38
+ inputs.push(docPath);
39
+ }
40
+ }
41
+ const dirTargets = [];
42
+ if (level < depth) {
43
+ for (let d = 0; d < dirsPerLevel; d++) {
44
+ const sub = `${dir}/sub-${d}`;
45
+ visit(sub, level + 1);
46
+ dirTargets.push(sub);
47
+ inputs.push(`${sub}/${DIR_SUMMARY}`);
48
+ }
49
+ }
50
+ const manifest = inputs
51
+ .map((input) => `${input.slice(dir.length + 1)}:${hashContent(files[input]?.content ?? '')}`)
52
+ .toSorted()
53
+ .join('\n');
54
+ const links = [...docTargets, ...dirTargets].map((t) => `- [link](${t.slice(dir.length + 1)})`).join('\n');
55
+ const dsp = `${dir}/${DIR_SUMMARY}`;
56
+ files[dsp] = tf(links);
57
+ files[sidecarPathFor(dsp, layout)] = tf(serializeStamp({ sha256: hashContent(manifest), version: STAMP_VERSION }));
58
+ };
59
+ visit(root, 0);
60
+ return files;
61
+ };
62
+ /** Same source docs, no summaries and no `.cairn/**` sidecars anywhere yet —
63
+ * the "first run" worst case. */
64
+ const sourceOnly = (files, metaRoot) => Object.fromEntries(Object.entries(files).filter(([p]) => !isSummaryFile(p) && !isDirSummary(p) && !isSidecarPath(p, metaRoot)));
65
+ const BASE = '/repo';
66
+ const SMALL = { depth: 1, dirsPerLevel: 9, filesPerDir: 10, root: '/repo/docs' };
67
+ const LARGE = { depth: 4, dirsPerLevel: 3, filesPerDir: 16, root: '/repo/docs' };
68
+ const metaRoot = metaRootFor(BASE);
69
+ const smallFresh = buildFreshFixture(BASE, SMALL);
70
+ const smallRaw = sourceOnly(smallFresh, metaRoot);
71
+ const largeFresh = buildFreshFixture(BASE, LARGE);
72
+ const largeRaw = sourceOnly(largeFresh, metaRoot);
73
+ const run = (files, roots) => {
74
+ const program = checkSummaries({ base: BASE, roots, thresholdLines: 30 });
75
+ const layer = makeTestDocsFs(files);
76
+ return Effect.runPromise(program.pipe(Effect.provide(layer)));
77
+ };
78
+ describe('checkSummaries() (real end-to-end path, sidecar I/O included)', () => {
79
+ bench('~100 files, first run (no summaries, no .cairn/**)', async () => {
80
+ await run(smallRaw, [SMALL.root]);
81
+ });
82
+ bench('~100 files, steady state (fully stamped, sidecars read from .cairn/**)', async () => {
83
+ await run(smallFresh, [SMALL.root]);
84
+ });
85
+ bench('~2000 files, first run (no summaries, no .cairn/**)', async () => {
86
+ await run(largeRaw, [LARGE.root]);
87
+ });
88
+ bench('~2000 files, steady state (fully stamped, sidecars read from .cairn/**)', async () => {
89
+ await run(largeFresh, [LARGE.root]);
90
+ });
91
+ });
92
+ //# sourceMappingURL=CheckSummaries.bench.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"CheckSummaries.bench.js","sourceRoot":"","sources":["../../src/program/CheckSummaries.bench.ts"],"names":[],"mappings":"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"}
@@ -5,6 +5,9 @@ import { DocsFs } from '../io/DocsFs.ts';
5
5
  import type { Locale } from './locale.ts';
6
6
  export { DEFAULT_STAMP_COMMAND } from '../core/Config.ts';
7
7
  export interface CheckSummariesArgs {
8
+ /** Project root every root/node path and every `.cairn/**` sidecar is
9
+ * resolved under (see StampStore.ts's `MetaLayout`). Real usage: `process.cwd()`. */
10
+ readonly base: string;
8
11
  readonly ignore?: readonly string[];
9
12
  readonly naming?: Naming;
10
13
  readonly requireDirSummaries?: boolean;
@@ -16,22 +19,39 @@ export interface SummaryReportOptions {
16
19
  readonly stampCommand?: string;
17
20
  }
18
21
  export interface StampResult {
22
+ /** Legacy in-content `<!-- source-sha256 -->` stamps stripped along the way —
23
+ * an ordinary `--stamp` run (the one every existing `.cairnrc.json`'s
24
+ * `stampCommand` already points to) self-heals a repo upgrading off the old
25
+ * scheme with ZERO new command to discover; this count is only surfaced so
26
+ * that self-healing is visible, not silent-and-unverifiable. */
27
+ readonly migrated: number;
19
28
  readonly missing: readonly PlanNode[];
20
29
  readonly stamped: number;
21
30
  }
22
- /** 0 when nothing is missing/stale and no orphans remain, 1 otherwise. */
31
+ /** Alias kept for the explicit, nameable one-shot migration entry point
32
+ * (`--migrate-stamps`) — identical shape to `StampResult` now that stripping
33
+ * is unconditional in `stampFiles`, but naming it distinctly documents intent
34
+ * at the call site (`cli.ts`) and in reports. */
35
+ export type MigrateResult = StampResult;
36
+ /** 0 when nothing is missing/stale, no orphan summaries, and no deleted-source
37
+ * stamps remain, 1 otherwise. */
23
38
  export declare const summaryExitCode: (plan: SummaryPlan) => number;
24
39
  /** Report lines: methodology + the bottom-up update order, for a one-pass fix. */
25
40
  export declare const formatSummaryReport: (plan: SummaryPlan, options?: SummaryReportOptions) => string[];
26
41
  export declare const checkSummaries: (args: CheckSummariesArgs) => Effect.Effect<SummaryPlan, never, DocsFs>;
27
42
  /** `--explain`: why each todo node is not ok (see `explainPlan` for what this can and cannot show). */
28
43
  export declare const explainSummaries: (args: CheckSummariesArgs, options?: SummaryReportOptions) => Effect.Effect<string[], never, DocsFs>;
44
+ export declare const stampSummaries: (args: CheckSummariesArgs) => Effect.Effect<StampResult, never, DocsFs>;
29
45
  /**
30
- * Stamp every EXISTING summary with its current source/manifest hash, bottom-up.
31
- * Summaries whose content has not been authored yet are returned as `missing`.
46
+ * Explicit, nameable one-shot entry point (`--migrate-stamps`) for the SAME
47
+ * self-healing `stampFiles` already does unconditionally on every `--stamp`
48
+ * kept for anyone who wants to run/report the cleanup as its own step, not
49
+ * because plain `--stamp` needs it to be correct.
32
50
  */
33
- export declare const stampSummaries: (args: CheckSummariesArgs) => Effect.Effect<StampResult, never, DocsFs>;
34
- /** Delete every orphan summary (source doc gone) and report how many were removed. */
51
+ export declare const migrateStamps: (args: CheckSummariesArgs) => Effect.Effect<MigrateResult, never, DocsFs>;
52
+ /** Delete every orphan summary file (source doc gone) AND every orphan
53
+ * `.cairn/**` sidecar (deleted-source stamp — see `SummaryPlan.orphanStamps`),
54
+ * reporting the total count removed. */
35
55
  export declare const pruneOrphans: (args: CheckSummariesArgs) => Effect.Effect<number, never, DocsFs>;
36
56
  export { isSummaryFile } from '../core/DocSummaries.ts';
37
57
  export { isDirSummary } from '../core/SummaryTree.ts';
@@ -1 +1 @@
1
- {"version":3,"file":"CheckSummaries.d.ts","sourceRoot":"","sources":["../../src/program/CheckSummaries.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAY,QAAQ,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAE7E,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,MAAM,WAAW,kBAAkB;IACjC,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,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAyBD,0EAA0E;AAC1E,eAAO,MAAM,eAAe,GAAI,MAAM,WAAW,KAAG,MAAmE,CAAA;AAEvH,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,GAAI,MAAM,WAAW,EAAE,UAAS,oBAAyB,KAAG,MAAM,EA4EjG,CAAA;AAoDD,eAAO,MAAM,cAAc,GAAI,MAAM,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,CAI9F,CAAA;AAEJ,uGAAuG;AACvG,eAAO,MAAM,gBAAgB,GAC3B,MAAM,kBAAkB,EACxB,UAAS,oBAAyB,KACjC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAKpC,CAAA;AAEJ;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,MAAM,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,CA0B9F,CAAA;AAEJ,sFAAsF;AACtF,eAAO,MAAM,YAAY,GAAI,MAAM,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CASvF,CAAA;AAGJ,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA"}
1
+ {"version":3,"file":"CheckSummaries.d.ts","sourceRoot":"","sources":["../../src/program/CheckSummaries.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAA;AAErD,OAAO,KAAK,EAAY,QAAQ,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAW7E,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAA;AACxC,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAGzC,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,MAAM,WAAW,kBAAkB;IACjC;yFACqF;IACrF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,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,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAA;CACjC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B;;;;oEAIgE;IAChE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,OAAO,EAAE,SAAS,QAAQ,EAAE,CAAA;IACrC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAED;;;iDAGiD;AACjD,MAAM,MAAM,aAAa,GAAG,WAAW,CAAA;AA8DvC;iCACiC;AACjC,eAAO,MAAM,eAAe,SAAU,WAAW,KAAG,MACqC,CAAA;AAEzF,kFAAkF;AAClF,eAAO,MAAM,mBAAmB,SAAU,WAAW,YAAW,oBAAoB,KAAQ,MAAM,EAwFjG,CAAA;AAoDD,eAAO,MAAM,cAAc,SAAU,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,CAK9F,CAAA;AAEJ,uGAAuG;AACvG,eAAO,MAAM,gBAAgB,SACrB,kBAAkB,YACf,oBAAoB,KAC5B,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,MAAM,CAMpC,CAAA;AAwEJ,eAAO,MAAM,cAAc,SAAU,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,EAAE,MAAM,CAI9F,CAAA;AAEJ;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAAU,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,KAAK,EAAE,MAAM,CAI/F,CAAA;AAEJ;;wCAEwC;AACxC,eAAO,MAAM,YAAY,SAAU,kBAAkB,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,CAcvF,CAAA;AAGJ,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAA"}
@@ -1,23 +1,33 @@
1
1
  // Effect programs for the hierarchical summary system.
2
- // - `checkSummaries` -> the plan (what is missing/stale, bottom-up order).
3
- // - `stampSummaries` -> (re)writes the source-hash stamp of EXISTING summaries
4
- // bottom-up, so a parent's manifest sees its freshly-stamped children.
2
+ // - `checkSummaries` -> the plan (what is missing/stale, bottom-up order).
3
+ // - `stampSummaries` -> (re)writes the freshness stamp of EXISTING summaries,
4
+ // bottom-up, into their `.cairn/**` sidecar (never into the summary's own
5
+ // content — see StampStore.ts).
6
+ // - `migrateStamps` -> one-off: strips the legacy in-content stamp from
7
+ // every summary, then runs the sidecar stamp pass over the stripped tree.
5
8
  // Pure planning lives in ../core/SummaryTree.ts; freshness primitives in
6
- // ../core/DocSummaries.ts.
9
+ // ../core/DocSummaries.ts; sidecar path mapping + (de)serialisation in
10
+ // ../core/StampStore.ts.
7
11
  import { Effect } from 'effect';
8
- import { DEFAULT_STAMP_COMMAND } from "../core/Config.js";
9
- import { countLines, withSourceHash } from "../core/DocSummaries.js";
10
- import { nodeExpectedHash, planSummaries } from "../core/SummaryTree.js";
11
- import { DocsFs } from "../io/DocsFs.js";
12
- import { enOnly, pick } from "./locale.js";
13
- export { DEFAULT_STAMP_COMMAND } from "../core/Config.js";
14
- /** Assemble the pure planner's arguments from the program args + file map. */
15
- const toPlanArgs = (files, args) => ({
12
+ import { DEFAULT_STAMP_COMMAND } from '../core/Config.js';
13
+ import { countLines, isSummaryFile, stripSourceHash } from '../core/DocSummaries.js';
14
+ import { isDirSummary, nodeExpectedHash, planSummaries } from '../core/SummaryTree.js';
15
+ import { metaRootFor, nodePathForSidecar, parseStamp, serializeStamp, sidecarPathFor, STAMP_VERSION, } from '../core/StampStore.js';
16
+ import { DocsFs } from '../io/DocsFs.js';
17
+ import { enOnly, pick } from './locale.js';
18
+ export { DEFAULT_STAMP_COMMAND } from '../core/Config.js';
19
+ const EMPTY_STAMPS = new Map();
20
+ const layoutFor = (base) => ({ base, metaRoot: metaRootFor(base) });
21
+ /** Assemble the pure planner's arguments from the program args + file map.
22
+ * `stamps` defaults to empty — callers that don't need freshness status (the
23
+ * stamp-writing pass itself) can omit it entirely and skip loading it. */
24
+ const toPlanArgs = (files, args, stamps = EMPTY_STAMPS) => ({
16
25
  files,
17
26
  ...(args.ignore === undefined ? {} : { ignore: args.ignore }),
18
27
  ...(args.naming === undefined ? {} : { naming: args.naming }),
19
28
  ...(args.requireDirSummaries === undefined ? {} : { requireDirSummaries: args.requireDirSummaries }),
20
29
  roots: args.roots,
30
+ stamps,
21
31
  ...(args.thresholdLines === undefined ? {} : { thresholdLines: args.thresholdLines }),
22
32
  });
23
33
  const readMarkdown = (roots) => Effect.gen(function* () {
@@ -31,13 +41,39 @@ const readMarkdown = (roots) => Effect.gen(function* () {
31
41
  }
32
42
  return files;
33
43
  });
34
- /** 0 when nothing is missing/stale and no orphans remain, 1 otherwise. */
35
- export const summaryExitCode = (plan) => (plan.todo.length > 0 || plan.orphans.length > 0 ? 1 : 0);
44
+ /**
45
+ * Load every stamp recorded under `.cairn/**` into a `node path -> sha256` map.
46
+ * A sidecar that can't be mapped back to a node path, or whose content is
47
+ * corrupt/merge-conflicted/hand-edited (`parseStamp` returns `null`), is simply
48
+ * skipped — its node then reads as `stale`/`missing`, never a crash (see
49
+ * StampStore.ts's own contract). Absent `.cairn/` (first run) yields an empty
50
+ * map via `dfs.listFiles`, also without error.
51
+ */
52
+ const readStamps = (layout) => Effect.gen(function* () {
53
+ const dfs = yield* DocsFs;
54
+ const sidecarPaths = yield* dfs.listFiles([layout.metaRoot]);
55
+ const stamps = new Map();
56
+ for (const sidecarPath of sidecarPaths) {
57
+ const nodeAtPath = nodePathForSidecar(sidecarPath, layout);
58
+ if (nodeAtPath === null) {
59
+ continue;
60
+ }
61
+ const record = parseStamp(yield* dfs.readFile(sidecarPath));
62
+ if (record !== null) {
63
+ stamps.set(nodeAtPath, record.sha256);
64
+ }
65
+ }
66
+ return stamps;
67
+ });
68
+ /** 0 when nothing is missing/stale, no orphan summaries, and no deleted-source
69
+ * stamps remain, 1 otherwise. */
70
+ export const summaryExitCode = (plan) => plan.todo.length > 0 || plan.orphans.length > 0 || plan.orphanStamps.length > 0 ? 1 : 0;
36
71
  /** Report lines: methodology + the bottom-up update order, for a one-pass fix. */
37
72
  export const formatSummaryReport = (plan, options = {}) => {
38
73
  const locale = options.locale ?? 'en';
39
74
  const stampCommand = options.stampCommand ?? DEFAULT_STAMP_COMMAND;
40
- if (plan.todo.length === 0 && plan.orphans.length === 0) {
75
+ const totalOrphans = plan.orphans.length + plan.orphanStamps.length;
76
+ if (plan.todo.length === 0 && totalOrphans === 0) {
41
77
  return [
42
78
  pick(locale, {
43
79
  en: `✅ Hierarchical summaries OK (${plan.nodes.length} summary/ies checked).`,
@@ -49,13 +85,21 @@ export const formatSummaryReport = (plan, options = {}) => {
49
85
  en: ` ✗ orphan summary (source gone): ${p}`,
50
86
  fr: ` ✗ résumé orphelin (source disparue) : ${p}`,
51
87
  }));
88
+ // A `.cairn/**` sidecar with no corresponding node — its source (and possibly
89
+ // its summary file too) was deleted; the sidecar, never touched by hand, is
90
+ // what caught it (see StampStore.ts / SummaryTree.ts's `findDeletedStamps`).
91
+ const orphanStampLines = plan.orphanStamps.map((p) => pick(locale, {
92
+ en: ` ✗ deleted-source stamp (sidecar left behind): ${p}`,
93
+ fr: ` ✗ tampon d'une source supprimée (fichier annexe orphelin) : ${p}`,
94
+ }));
52
95
  if (plan.todo.length === 0) {
53
96
  return [
54
97
  pick(locale, {
55
- en: `❌ ${plan.orphans.length} orphan summary/ies (source doc deleted, renamed, or below threshold):`,
56
- fr: `❌ ${plan.orphans.length} résumé(s) orphelin(s) (source supprimée, renommée, ou sous le seuil) :`,
98
+ en: `❌ ${totalOrphans} orphan summary/ies or stamp(s) (source doc deleted, renamed, or below threshold):`,
99
+ fr: `❌ ${totalOrphans} résumé(s) ou tampon(s) orphelin(s) (source supprimée, renommée, ou sous le seuil) :`,
57
100
  }),
58
101
  ...orphanLines,
102
+ ...orphanStampLines,
59
103
  ];
60
104
  }
61
105
  const lines = pick(locale, {
@@ -95,11 +139,11 @@ export const formatSummaryReport = (plan, options = {}) => {
95
139
  }
96
140
  lines.push(` - [${tag}] ${node.path} : ${reason}`);
97
141
  }
98
- if (plan.orphans.length > 0) {
142
+ if (totalOrphans > 0) {
99
143
  lines.push('', pick(locale, {
100
- en: `${plan.orphans.length} orphan summary/ies (source doc deleted, renamed, or below threshold):`,
101
- fr: `${plan.orphans.length} résumé(s) orphelin(s) (source supprimée, renommée, ou sous le seuil) :`,
102
- }), ...orphanLines);
144
+ en: `${totalOrphans} orphan summary/ies or stamp(s) (source doc deleted, renamed, or below threshold):`,
145
+ fr: `${totalOrphans} résumé(s) ou tampon(s) orphelin(s) (source supprimée, renommée, ou sous le seuil) :`,
146
+ }), ...orphanLines, ...orphanStampLines);
103
147
  }
104
148
  return lines;
105
149
  };
@@ -145,21 +189,58 @@ const explainPlan = (plan, files, options) => {
145
189
  };
146
190
  export const checkSummaries = (args) => Effect.gen(function* () {
147
191
  const files = yield* readMarkdown(args.roots);
148
- return planSummaries(toPlanArgs(files, args));
192
+ const stamps = yield* readStamps(layoutFor(args.base));
193
+ return planSummaries(toPlanArgs(files, args, stamps));
149
194
  });
150
195
  /** `--explain`: why each todo node is not ok (see `explainPlan` for what this can and cannot show). */
151
196
  export const explainSummaries = (args, options = {}) => Effect.gen(function* () {
152
197
  const files = yield* readMarkdown(args.roots);
153
- const plan = planSummaries(toPlanArgs(files, args));
198
+ const stamps = yield* readStamps(layoutFor(args.base));
199
+ const plan = planSummaries(toPlanArgs(files, args, stamps));
154
200
  return explainPlan(plan, files, options);
155
201
  });
156
202
  /**
157
- * Stamp every EXISTING summary with its current source/manifest hash, bottom-up.
158
- * Summaries whose content has not been authored yet are returned as `missing`.
203
+ * Stamp every EXISTING summary with its current source/manifest hash, bottom-up,
204
+ * into its `.cairn/**` sidecar never into the summary's own content. Summaries
205
+ * whose content has not been authored yet are returned as `missing`.
206
+ *
207
+ * ALWAYS strips a legacy in-content `<!-- source-sha256 -->` stamp first, if one
208
+ * is still there, before computing any hash — not just when explicitly asked to
209
+ * migrate. This is the actual fix for the discoverability gap a one-off
210
+ * `--migrate-stamps` command alone would leave: an upgrading repo's EXISTING
211
+ * `stampCommand` (already `cairn check --summaries-only --stamp` in every
212
+ * `.cairnrc.json` this tool ever scaffolded) is what a user or CI already runs
213
+ * — making that command self-heal means there is no new command to discover,
214
+ * search for, or forget to run. `--migrate-stamps` (`migrateStamps`, below)
215
+ * still exists as an explicit, nameable entry point for anyone who wants to run
216
+ * the cleanup as its own reported step, but it is no longer load-bearing.
217
+ *
218
+ * Doesn't need to load `stamps` first: this loop writes every node's hash
219
+ * unconditionally (not just the stale ones), so `planSummaries`' ordering is all
220
+ * it needs from the planner — freshness status plays no role in stamping itself.
159
221
  */
160
- export const stampSummaries = (args) => Effect.gen(function* () {
222
+ const stampFiles = (files, args) => Effect.gen(function* () {
161
223
  const dfs = yield* DocsFs;
162
- const files = yield* readMarkdown(args.roots);
224
+ const layout = layoutFor(args.base);
225
+ // Only ever strips a SUMMARY file's own legacy stamp — never a plain source
226
+ // doc. A source doc's prose can legitimately contain the literal
227
+ // `<!-- source-sha256: <64hex> -->` text (e.g. a doc that documents cairn's
228
+ // OWN former stamp format, with a real-looking example) — that text is the
229
+ // user's content, not tool metadata, and `stampFiles` must never touch it.
230
+ // Restricting to `isSummaryFile`/`isDirSummary` is what keeps "the tool
231
+ // never writes into content" true for every file it doesn't own.
232
+ let migrated = 0;
233
+ for (const [p, content] of files) {
234
+ if (!isSummaryFile(p, args.naming) && !isDirSummary(p, args.naming)) {
235
+ continue;
236
+ }
237
+ const stripped = stripSourceHash(content);
238
+ if (stripped !== content) {
239
+ files.set(p, stripped);
240
+ yield* dfs.writeFile(p, stripped);
241
+ migrated += 1;
242
+ }
243
+ }
163
244
  const order = planSummaries(toPlanArgs(files, args)).nodes;
164
245
  const missing = [];
165
246
  let stamped = 0;
@@ -170,29 +251,51 @@ export const stampSummaries = (args) => Effect.gen(function* () {
170
251
  }
171
252
  // A node's `inputs` are structurally stable (only summary CONTENT changes
172
253
  // during stamping, never which paths feed a node) — so its hash can be
173
- // recomputed directly from `inputs` + their current content. Bottom-up
174
- // order guarantees any child this node depends on was already stamped
175
- // above, so `files` already reflects it. This avoids a full replan of the
176
- // whole tree per node (previously O(nodes) work repeated once per node).
254
+ // recomputed directly from `inputs` + their current content. Content no
255
+ // longer carries a stamp (that's the whole point of the sidecar), so —
256
+ // unlike the old in-content scheme a child's just-written sidecar never
257
+ // changes ITS OWN content, and therefore never perturbs a parent's
258
+ // manifest hash; bottom-up order is preserved for a single-pass write, but
259
+ // no longer required for correctness of the hash itself.
177
260
  const expectedHash = nodeExpectedHash({ files, inputs: node.inputs, kind: node.kind, path: node.path });
178
- const stampedContent = withSourceHash(files.get(node.path) ?? '', expectedHash);
179
- files.set(node.path, stampedContent);
180
- yield* dfs.writeFile(node.path, stampedContent);
261
+ const sidecarContent = serializeStamp({ sha256: expectedHash, version: STAMP_VERSION });
262
+ yield* dfs.writeFile(sidecarPathFor(node.path, layout), sidecarContent);
181
263
  stamped += 1;
182
264
  }
183
- return { missing, stamped };
265
+ return { migrated, missing, stamped };
266
+ });
267
+ export const stampSummaries = (args) => Effect.gen(function* () {
268
+ const files = yield* readMarkdown(args.roots);
269
+ return yield* stampFiles(files, args);
184
270
  });
185
- /** Delete every orphan summary (source doc gone) and report how many were removed. */
271
+ /**
272
+ * Explicit, nameable one-shot entry point (`--migrate-stamps`) for the SAME
273
+ * self-healing `stampFiles` already does unconditionally on every `--stamp` —
274
+ * kept for anyone who wants to run/report the cleanup as its own step, not
275
+ * because plain `--stamp` needs it to be correct.
276
+ */
277
+ export const migrateStamps = (args) => Effect.gen(function* () {
278
+ const files = yield* readMarkdown(args.roots);
279
+ return yield* stampFiles(files, args);
280
+ });
281
+ /** Delete every orphan summary file (source doc gone) AND every orphan
282
+ * `.cairn/**` sidecar (deleted-source stamp — see `SummaryPlan.orphanStamps`),
283
+ * reporting the total count removed. */
186
284
  export const pruneOrphans = (args) => Effect.gen(function* () {
187
285
  const dfs = yield* DocsFs;
286
+ const layout = layoutFor(args.base);
188
287
  const files = yield* readMarkdown(args.roots);
189
- const plan = planSummaries(toPlanArgs(files, args));
288
+ const stamps = yield* readStamps(layout);
289
+ const plan = planSummaries(toPlanArgs(files, args, stamps));
190
290
  for (const orphan of plan.orphans) {
191
291
  yield* dfs.deleteFile(orphan);
192
292
  }
193
- return plan.orphans.length;
293
+ for (const orphanStamp of plan.orphanStamps) {
294
+ yield* dfs.deleteFile(sidecarPathFor(orphanStamp, layout));
295
+ }
296
+ return plan.orphans.length + plan.orphanStamps.length;
194
297
  });
195
298
  // Re-exported so callers can recognise summary files without importing two modules.
196
- export { isSummaryFile } from "../core/DocSummaries.js";
197
- export { isDirSummary } from "../core/SummaryTree.js";
299
+ export { isSummaryFile } from '../core/DocSummaries.js';
300
+ export { isDirSummary } from '../core/SummaryTree.js';
198
301
  //# sourceMappingURL=CheckSummaries.js.map