@cleocode/core 2026.10.12 → 2026.10.13-rc.ci.682

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 (255) hide show
  1. package/dist/build-provenance.json +2 -2
  2. package/dist/cloud/nexus-auth.d.ts.map +1 -1
  3. package/dist/cloud/nexus-auth.js +11 -2
  4. package/dist/cloud/nexus-auth.js.map +1 -1
  5. package/dist/cloud/nexus-cloud-status.d.ts.map +1 -1
  6. package/dist/cloud/nexus-cloud-status.js +18 -5
  7. package/dist/cloud/nexus-cloud-status.js.map +1 -1
  8. package/dist/cloud/nexus-credentials.d.ts +3 -2
  9. package/dist/cloud/nexus-credentials.d.ts.map +1 -1
  10. package/dist/cloud/nexus-credentials.js +58 -14
  11. package/dist/cloud/nexus-credentials.js.map +1 -1
  12. package/dist/cloud/nexus-logout.d.ts.map +1 -1
  13. package/dist/cloud/nexus-logout.js +12 -2
  14. package/dist/cloud/nexus-logout.js.map +1 -1
  15. package/dist/cloud/nexus-vault-state.d.ts.map +1 -1
  16. package/dist/cloud/nexus-vault-state.js +6 -26
  17. package/dist/cloud/nexus-vault-state.js.map +1 -1
  18. package/dist/config/registry.d.ts +21 -0
  19. package/dist/config/registry.d.ts.map +1 -1
  20. package/dist/config/registry.js +41 -0
  21. package/dist/config/registry.js.map +1 -1
  22. package/dist/dispatch/mvi-projection.d.ts.map +1 -1
  23. package/dist/dispatch/mvi-projection.js +2 -0
  24. package/dist/dispatch/mvi-projection.js.map +1 -1
  25. package/dist/docs/docs-ops.d.ts +15 -14
  26. package/dist/docs/docs-ops.d.ts.map +1 -1
  27. package/dist/docs/docs-ops.js +32 -96
  28. package/dist/docs/docs-ops.js.map +1 -1
  29. package/dist/docs/docs-read-model.d.ts +19 -10
  30. package/dist/docs/docs-read-model.d.ts.map +1 -1
  31. package/dist/docs/docs-read-model.js +31 -47
  32. package/dist/docs/docs-read-model.js.map +1 -1
  33. package/dist/docs/docs-update.d.ts +51 -1
  34. package/dist/docs/docs-update.d.ts.map +1 -1
  35. package/dist/docs/docs-update.js +235 -13
  36. package/dist/docs/docs-update.js.map +1 -1
  37. package/dist/docs/doctor.d.ts +26 -4
  38. package/dist/docs/doctor.d.ts.map +1 -1
  39. package/dist/docs/doctor.js +260 -102
  40. package/dist/docs/doctor.js.map +1 -1
  41. package/dist/docs/fetch-result.d.ts +30 -10
  42. package/dist/docs/fetch-result.d.ts.map +1 -1
  43. package/dist/docs/fetch-result.js +100 -15
  44. package/dist/docs/fetch-result.js.map +1 -1
  45. package/dist/docs/index.d.ts +1 -0
  46. package/dist/docs/index.d.ts.map +1 -1
  47. package/dist/docs/index.js +1 -0
  48. package/dist/docs/index.js.map +1 -1
  49. package/dist/docs/legacy-doc-migration.d.ts +182 -0
  50. package/dist/docs/legacy-doc-migration.d.ts.map +1 -0
  51. package/dist/docs/legacy-doc-migration.js +480 -0
  52. package/dist/docs/legacy-doc-migration.js.map +1 -0
  53. package/dist/docs/publications-store.d.ts +67 -0
  54. package/dist/docs/publications-store.d.ts.map +1 -0
  55. package/dist/docs/publications-store.js +193 -0
  56. package/dist/docs/publications-store.js.map +1 -0
  57. package/dist/docs/publish-pr.d.ts.map +1 -1
  58. package/dist/docs/publish-pr.js +31 -18
  59. package/dist/docs/publish-pr.js.map +1 -1
  60. package/dist/docs/section-leases.d.ts +233 -0
  61. package/dist/docs/section-leases.d.ts.map +1 -0
  62. package/dist/docs/section-leases.js +344 -0
  63. package/dist/docs/section-leases.js.map +1 -0
  64. package/dist/docs/section-merge.d.ts +159 -0
  65. package/dist/docs/section-merge.d.ts.map +1 -0
  66. package/dist/docs/section-merge.js +215 -0
  67. package/dist/docs/section-merge.js.map +1 -0
  68. package/dist/docs/section-write-path.d.ts +191 -0
  69. package/dist/docs/section-write-path.d.ts.map +1 -0
  70. package/dist/docs/section-write-path.js +423 -0
  71. package/dist/docs/section-write-path.js.map +1 -0
  72. package/dist/docs/stats.d.ts +56 -0
  73. package/dist/docs/stats.d.ts.map +1 -0
  74. package/dist/docs/stats.js +119 -0
  75. package/dist/docs/stats.js.map +1 -0
  76. package/dist/gc/cleanup.d.ts +1 -1
  77. package/dist/gc/cleanup.d.ts.map +1 -1
  78. package/dist/gc/cleanup.js +10 -1
  79. package/dist/gc/cleanup.js.map +1 -1
  80. package/dist/gc/janitor.js +1 -1
  81. package/dist/gc/janitor.js.map +1 -1
  82. package/dist/internal.d.ts +1 -1
  83. package/dist/internal.d.ts.map +1 -1
  84. package/dist/internal.js +1 -1
  85. package/dist/internal.js.map +1 -1
  86. package/dist/memory/pipeline-manifest-sqlite.d.ts +34 -0
  87. package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
  88. package/dist/memory/pipeline-manifest-sqlite.js +114 -0
  89. package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
  90. package/dist/nexus/analyze-orchestrator.d.ts +5 -1
  91. package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
  92. package/dist/nexus/analyze-orchestrator.js +25 -13
  93. package/dist/nexus/analyze-orchestrator.js.map +1 -1
  94. package/dist/nexus/assessment-store.d.ts +8 -4
  95. package/dist/nexus/assessment-store.d.ts.map +1 -1
  96. package/dist/nexus/assessment-store.js +18 -27
  97. package/dist/nexus/assessment-store.js.map +1 -1
  98. package/dist/orchestration/index.d.ts.map +1 -1
  99. package/dist/orchestration/index.js +6 -0
  100. package/dist/orchestration/index.js.map +1 -1
  101. package/dist/orchestration/lean-change.d.ts +104 -5
  102. package/dist/orchestration/lean-change.d.ts.map +1 -1
  103. package/dist/orchestration/lean-change.js +162 -6
  104. package/dist/orchestration/lean-change.js.map +1 -1
  105. package/dist/orchestration/spawn-prompt.d.ts +6 -1
  106. package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
  107. package/dist/orchestration/spawn-prompt.js +3 -1
  108. package/dist/orchestration/spawn-prompt.js.map +1 -1
  109. package/dist/orchestration/spawn.d.ts.map +1 -1
  110. package/dist/orchestration/spawn.js +6 -0
  111. package/dist/orchestration/spawn.js.map +1 -1
  112. package/dist/release/open.d.ts.map +1 -1
  113. package/dist/release/open.js +6 -2
  114. package/dist/release/open.js.map +1 -1
  115. package/dist/release/plan.d.ts.map +1 -1
  116. package/dist/release/plan.js +33 -2
  117. package/dist/release/plan.js.map +1 -1
  118. package/dist/resources/admission-ledger.d.ts +5 -0
  119. package/dist/resources/admission-ledger.d.ts.map +1 -1
  120. package/dist/resources/admission-ledger.js +1 -1
  121. package/dist/resources/admission-ledger.js.map +1 -1
  122. package/dist/resources/run-admission.d.ts.map +1 -1
  123. package/dist/resources/run-admission.js +4 -1
  124. package/dist/resources/run-admission.js.map +1 -1
  125. package/dist/resources/run-governed.d.ts +29 -4
  126. package/dist/resources/run-governed.d.ts.map +1 -1
  127. package/dist/resources/run-governed.js +113 -73
  128. package/dist/resources/run-governed.js.map +1 -1
  129. package/dist/sentient/worktree-dispatch.d.ts +12 -1
  130. package/dist/sentient/worktree-dispatch.d.ts.map +1 -1
  131. package/dist/sentient/worktree-dispatch.js +19 -0
  132. package/dist/sentient/worktree-dispatch.js.map +1 -1
  133. package/dist/spawn/branch-lock.d.ts +11 -1
  134. package/dist/spawn/branch-lock.d.ts.map +1 -1
  135. package/dist/spawn/branch-lock.js +54 -4
  136. package/dist/spawn/branch-lock.js.map +1 -1
  137. package/dist/sticky/archive.d.ts +1 -0
  138. package/dist/sticky/archive.d.ts.map +1 -1
  139. package/dist/sticky/archive.js +13 -0
  140. package/dist/sticky/archive.js.map +1 -1
  141. package/dist/sticky/engine-ops.d.ts.map +1 -1
  142. package/dist/sticky/engine-ops.js +7 -0
  143. package/dist/sticky/engine-ops.js.map +1 -1
  144. package/dist/store/attachment-repair.d.ts +10 -4
  145. package/dist/store/attachment-repair.d.ts.map +1 -1
  146. package/dist/store/attachment-repair.js +52 -25
  147. package/dist/store/attachment-repair.js.map +1 -1
  148. package/dist/store/attachment-store.d.ts.map +1 -1
  149. package/dist/store/attachment-store.js +27 -18
  150. package/dist/store/attachment-store.js.map +1 -1
  151. package/dist/store/blob-keep.d.ts +83 -0
  152. package/dist/store/blob-keep.d.ts.map +1 -1
  153. package/dist/store/blob-keep.js +139 -0
  154. package/dist/store/blob-keep.js.map +1 -1
  155. package/dist/store/blob-ops.d.ts +24 -0
  156. package/dist/store/blob-ops.d.ts.map +1 -1
  157. package/dist/store/blob-ops.js +47 -0
  158. package/dist/store/blob-ops.js.map +1 -1
  159. package/dist/store/conduit-doc-history.d.ts +209 -0
  160. package/dist/store/conduit-doc-history.d.ts.map +1 -1
  161. package/dist/store/conduit-doc-history.js +315 -3
  162. package/dist/store/conduit-doc-history.js.map +1 -1
  163. package/dist/store/decision-adr-links.d.ts +11 -0
  164. package/dist/store/decision-adr-links.d.ts.map +1 -1
  165. package/dist/store/decision-adr-links.js +20 -1
  166. package/dist/store/decision-adr-links.js.map +1 -1
  167. package/dist/store/display-id-alias.d.ts +8 -2
  168. package/dist/store/display-id-alias.d.ts.map +1 -1
  169. package/dist/store/display-id-alias.js +8 -3
  170. package/dist/store/display-id-alias.js.map +1 -1
  171. package/dist/store/lock.d.ts +18 -0
  172. package/dist/store/lock.d.ts.map +1 -1
  173. package/dist/store/lock.js +41 -0
  174. package/dist/store/lock.js.map +1 -1
  175. package/dist/store/row-identity-registry.d.ts.map +1 -1
  176. package/dist/store/row-identity-registry.js +17 -0
  177. package/dist/store/row-identity-registry.js.map +1 -1
  178. package/dist/store/schema/cleo-project/conduit.d.ts +16 -0
  179. package/dist/store/schema/cleo-project/conduit.d.ts.map +1 -1
  180. package/dist/store/schema/cleo-project/conduit.js +8 -0
  181. package/dist/store/schema/cleo-project/conduit.js.map +1 -1
  182. package/dist/store/schema/cleo-project/docs.d.ts +294 -0
  183. package/dist/store/schema/cleo-project/docs.d.ts.map +1 -1
  184. package/dist/store/schema/cleo-project/docs.js +82 -0
  185. package/dist/store/schema/cleo-project/docs.js.map +1 -1
  186. package/dist/store/sync/hlc.d.ts +9 -0
  187. package/dist/store/sync/hlc.d.ts.map +1 -1
  188. package/dist/store/sync/hlc.js +9 -0
  189. package/dist/store/sync/hlc.js.map +1 -1
  190. package/dist/store/sync/merge/engine.d.ts.map +1 -1
  191. package/dist/store/sync/merge/engine.js +4 -2
  192. package/dist/store/sync/merge/engine.js.map +1 -1
  193. package/dist/store/sync/merge/rules.d.ts +12 -1
  194. package/dist/store/sync/merge/rules.d.ts.map +1 -1
  195. package/dist/store/sync/merge/rules.js +76 -1
  196. package/dist/store/sync/merge/rules.js.map +1 -1
  197. package/dist/store/sync/replica-registry.d.ts +6 -2
  198. package/dist/store/sync/replica-registry.d.ts.map +1 -1
  199. package/dist/store/sync/replica-registry.js +21 -9
  200. package/dist/store/sync/replica-registry.js.map +1 -1
  201. package/dist/store/sync/timestamp-canon.d.ts.map +1 -1
  202. package/dist/store/sync/timestamp-canon.js +6 -0
  203. package/dist/store/sync/timestamp-canon.js.map +1 -1
  204. package/dist/store/table-classification.d.ts +58 -0
  205. package/dist/store/table-classification.d.ts.map +1 -1
  206. package/dist/store/table-classification.js +72 -0
  207. package/dist/store/table-classification.js.map +1 -1
  208. package/dist/store/twin-collapse.d.ts.map +1 -1
  209. package/dist/store/twin-collapse.js +4 -1
  210. package/dist/store/twin-collapse.js.map +1 -1
  211. package/dist/store/vault-manifest.d.ts +10 -1
  212. package/dist/store/vault-manifest.d.ts.map +1 -1
  213. package/dist/store/vault-manifest.js +59 -1
  214. package/dist/store/vault-manifest.js.map +1 -1
  215. package/dist/tasks/affected-scope.d.ts +11 -0
  216. package/dist/tasks/affected-scope.d.ts.map +1 -1
  217. package/dist/tasks/affected-scope.js +30 -11
  218. package/dist/tasks/affected-scope.js.map +1 -1
  219. package/dist/tasks/cancel-ops.d.ts.map +1 -1
  220. package/dist/tasks/cancel-ops.js +7 -2
  221. package/dist/tasks/cancel-ops.js.map +1 -1
  222. package/dist/tasks/change-set.d.ts +22 -0
  223. package/dist/tasks/change-set.d.ts.map +1 -1
  224. package/dist/tasks/change-set.js +119 -2
  225. package/dist/tasks/change-set.js.map +1 -1
  226. package/dist/tasks/complete.d.ts.map +1 -1
  227. package/dist/tasks/complete.js +7 -0
  228. package/dist/tasks/complete.js.map +1 -1
  229. package/dist/tasks/done-plan.d.ts +5 -0
  230. package/dist/tasks/done-plan.d.ts.map +1 -1
  231. package/dist/tasks/done-plan.js +54 -19
  232. package/dist/tasks/done-plan.js.map +1 -1
  233. package/dist/tasks/engine-wrap.d.ts +4 -0
  234. package/dist/tasks/engine-wrap.d.ts.map +1 -1
  235. package/dist/tasks/engine-wrap.js +20 -4
  236. package/dist/tasks/engine-wrap.js.map +1 -1
  237. package/dist/tasks/evidence-paths.d.ts +11 -0
  238. package/dist/tasks/evidence-paths.d.ts.map +1 -1
  239. package/dist/tasks/evidence-paths.js +12 -0
  240. package/dist/tasks/evidence-paths.js.map +1 -1
  241. package/dist/tools/fs.d.ts +7 -3
  242. package/dist/tools/fs.d.ts.map +1 -1
  243. package/dist/tools/fs.js +23 -8
  244. package/dist/tools/fs.js.map +1 -1
  245. package/dist/worktree/list.d.ts.map +1 -1
  246. package/dist/worktree/list.js +9 -0
  247. package/dist/worktree/list.js.map +1 -1
  248. package/dist/worktree/prune.d.ts.map +1 -1
  249. package/dist/worktree/prune.js +52 -1
  250. package/dist/worktree/prune.js.map +1 -1
  251. package/migrations/drizzle-cleo-project/20261013000000_t13360-migrated-doc-import/migration.sql +61 -0
  252. package/migrations/drizzle-cleo-project/20261014000000_t13362-docs-publications-ledger/migration.sql +45 -0
  253. package/package.json +13 -13
  254. package/templates/CLEO-INJECTION.md +1 -1
  255. package/templates/CLEO-REFERENCE.md +2 -2
@@ -0,0 +1,423 @@
1
+ /**
2
+ * Docs update write path through the section CRDT merge layer (T13355 ·
3
+ * spec `cleodocs-rearch-design` §2 option b · D11165).
4
+ *
5
+ * Every `cleo docs update` carrying new inline text is projected through
6
+ * this module after the legacy whole-row write lands (`docs-update.ts`):
7
+ *
8
+ * 1. Resolve the doc's immutable uid, adopting a legacy doc into the
9
+ * conduit family on first sight ({@link ensureConduitDoc}).
10
+ * 2. Split the new text into sections and resolve the previous head's
11
+ * section texts from its version blob — the single-writer vs.
12
+ * concurrent discriminator (T13589).
13
+ * 3. Apply each section's edit to its local Loro state
14
+ * (`section-merge.ts`): while the stored state equals the head's text
15
+ * the input projects EXACTLY (re-seed; replaces and deletions apply
16
+ * verbatim — the primitives can only append, so re-seeding is the
17
+ * honest encoding); a concurrent edit that is a pure append composes
18
+ * onto the stored state so both survive (T13585); a concurrent
19
+ * NON-append edit is never fabricated into a merge — it is landed as
20
+ * its own version row and recorded as a head conflict (T13595).
21
+ * 4. Read the MERGED text back out of the merged Loro states — never out
22
+ * of the input — and write its content-addressed blob so the version
23
+ * row's `storage_key` resolves.
24
+ * 5. Append the merged text as a DAG version row
25
+ * (`appendConduitAttachmentVersion`, parent = the previous head's
26
+ * version) — history is append-only.
27
+ * 6. Project the merged text into the current-version row via
28
+ * {@link upsertConduitDocHead}: the max-HLC head wins and a losing
29
+ * concurrent head is recorded as a conflict, never silently shadowed
30
+ * (typed rule `docs.head.max-hlc`).
31
+ * 7. Rebase the local section states onto the landed version and rebuild
32
+ * the derived contributors rollup.
33
+ *
34
+ * Steps 1–7 run inside ONE `BEGIN IMMEDIATE` transaction
35
+ * ({@link withConduitDocWriteTransaction}, T13583): a failure after the
36
+ * version append rolls everything back, so the next update cannot fork
37
+ * onto a half-landed projection. The body uses only sync-driver accessors
38
+ * and sync `node:fs` calls, so no real I/O yield can admit another writer
39
+ * on the connection mid-transaction (the documented constraint).
40
+ *
41
+ * Loro owns LOCAL-ONLY section state; the syncing rows are owned by the
42
+ * Stage C journal merge engine — one merge authority per table (§2).
43
+ *
44
+ * @module
45
+ * @task T13355
46
+ * @epic T13340
47
+ * @saga T13339
48
+ */
49
+ import { createHash, randomUUID } from 'node:crypto';
50
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
51
+ import { dirname, join } from 'node:path';
52
+ import { getCleoDirAbsolute } from '../paths.js';
53
+ import { appendConduitAttachmentVersion, ensureConduitDoc, getConduitAttachmentVersion, getConduitDocHead, readSectionCrdtState, rebaseSectionCrdtStates, rebuildConduitAttachmentContributors, resolveConduitDocUid, upsertConduitDocHead, withConduitDocWriteTransaction, writeSectionCrdtState, } from '../store/conduit-doc-history.js';
54
+ import { resolveBoundSession } from '../store/session-store.js';
55
+ import { compareHlc, encodeHlc, genesisHlc, parseHlc, tick } from '../store/sync/hlc.js';
56
+ import { listSectionLeases, SectionLeaseManager, } from './section-leases.js';
57
+ import { applySectionTextEdit, joinSections, sectionId, sectionStateText, splitDocIntoSections, } from './section-merge.js';
58
+ /**
59
+ * TTL granted by the write path's lease acquisitions (seconds). Inside
60
+ * llmtxt's 1–300 s range; long enough to cover an edit burst, short enough
61
+ * that a dead session's lease dies quickly (AC4: lease state never outlives
62
+ * its session without renew).
63
+ */
64
+ export const SECTION_LEASE_TTL_SECONDS = 60;
65
+ /**
66
+ * This device's docs-writer HLC state. Module-level (not the journal's
67
+ * persisted `_sync_clock`): the docs projection's HLC orders the
68
+ * current-version row only, is seeded from the stored head on open, and a
69
+ * reset across processes is safe because the head comparison is (phys, ctr,
70
+ * replica) — a fresher wall clock always wins.
71
+ */
72
+ let writerReplica = null;
73
+ let lastIssued = null;
74
+ /** The local writer's replica id (one random UUID per process). */
75
+ function localWriterReplica() {
76
+ writerReplica ??= randomUUID();
77
+ return writerReplica;
78
+ }
79
+ /**
80
+ * Mint the next local head HLC, strictly above the stored head when one
81
+ * exists (so a local write always advances the max-HLC projection).
82
+ *
83
+ * @param headHlc - The stored head's HLC, or `null` when no projection yet.
84
+ * @param wallMs - The physical candidate (defaults to `Date.now()`).
85
+ * @returns The encoded HLC.
86
+ */
87
+ function mintHeadHlc(headHlc, wallMs = Date.now()) {
88
+ let base = lastIssued ?? genesisHlc(localWriterReplica());
89
+ if (headHlc !== null) {
90
+ try {
91
+ const head = parseHlc(headHlc);
92
+ if (compareHlc(head, base) > 0)
93
+ base = { ...head, replica: localWriterReplica() };
94
+ }
95
+ catch {
96
+ // A stored head this process cannot parse is ignored: the mint below
97
+ // still lands at the wall clock, ahead of any plausible stored head.
98
+ }
99
+ }
100
+ lastIssued = tick(base, wallMs);
101
+ return encodeHlc(lastIssued);
102
+ }
103
+ /**
104
+ * Rough token count for the version row (whitespace split; display only).
105
+ *
106
+ * @param text - The text to count.
107
+ * @returns The token count.
108
+ */
109
+ function countTokens(text) {
110
+ return text.split(/\s+/).filter((w) => w.length > 0).length;
111
+ }
112
+ /**
113
+ * Resolve the on-disk path of a version row's content-addressed blob.
114
+ *
115
+ * @param projectRoot - Absolute path to the CLEO project root.
116
+ * @param storageKey - The version's `storage_key` (`<2>/<rest>.md`).
117
+ * @returns The absolute blob path.
118
+ */
119
+ function versionBlobPath(projectRoot, storageKey) {
120
+ return join(getCleoDirAbsolute(projectRoot), 'attachments', 'sha256', storageKey);
121
+ }
122
+ /**
123
+ * Read the previous head version's merged text and split it into sections.
124
+ *
125
+ * This is the single-writer vs. concurrent discriminator (T13589): a
126
+ * section whose stored state text equals the head's section text holds no
127
+ * unlanded concurrent edit. Sync `node:fs` only — the caller runs inside
128
+ * the write transaction, which must not yield to real I/O.
129
+ *
130
+ * @param projectRoot - Absolute path to the CLEO project root.
131
+ * @param head - The current head row.
132
+ * @returns The head's sections in document order, or `null` when the head's
133
+ * version or its blob is not resolvable locally (callers then take the
134
+ * single-writer path — see {@link applySectionTextEdit}).
135
+ */
136
+ async function readHeadSectionTexts(projectRoot, head) {
137
+ const version = await getConduitAttachmentVersion(projectRoot, head.headVersionUid);
138
+ if (!version?.storageKey)
139
+ return null;
140
+ try {
141
+ const text = readFileSync(versionBlobPath(projectRoot, version.storageKey), 'utf-8');
142
+ return splitDocIntoSections(text);
143
+ }
144
+ catch {
145
+ return null;
146
+ }
147
+ }
148
+ /**
149
+ * Write the merged text's content-addressed blob so the version row's
150
+ * `storage_key` resolves. Sync `node:fs` only (transaction constraint, see
151
+ * {@link withConduitDocWriteTransaction}); content-addressed, so an existing
152
+ * file is reused and an orphan from a rolled-back transaction is harmless.
153
+ *
154
+ * @param projectRoot - Absolute path to the CLEO project root.
155
+ * @param storageKey - The version's `storage_key`.
156
+ * @param text - The merged text the key addresses.
157
+ */
158
+ function writeMergedBlob(projectRoot, storageKey, text) {
159
+ const path = versionBlobPath(projectRoot, storageKey);
160
+ if (existsSync(path))
161
+ return;
162
+ mkdirSync(dirname(path), { recursive: true });
163
+ writeFileSync(path, text, 'utf-8');
164
+ }
165
+ /**
166
+ * Project one docs update through the section CRDT merge layer.
167
+ *
168
+ * The whole projection — adopt, section-state writes, version append, head
169
+ * upsert, rebase, contributors rebuild — is one transaction
170
+ * ({@link withConduitDocWriteTransaction}); the merged text is read back
171
+ * from the merged Loro states, so concurrent same-base section edits both
172
+ * survive into the version row and the head projection.
173
+ *
174
+ * Lease coordination (T13356, ADVISORY): before the transaction, the
175
+ * projection resolves the caller's session (input, else the bound session,
176
+ * gate 16) and acquires/renews a lease for every section the edit touches.
177
+ * A section leased by another live session yields a {@link SectionLeaseNotice}
178
+ * — the 409 equivalent as data. The edit PROCEEDS regardless: "409 is a
179
+ * social signal, not a hard lock" (llmtxt T285); the CRDT layer guarantees
180
+ * nothing is lost when coordination fails. Leases acquired for a projection
181
+ * that then rolls back are released, so a failed edit leaves no stale claim.
182
+ *
183
+ * @param projectRoot - Absolute path to the CLEO project root.
184
+ * @param input - The update facts.
185
+ * @returns The merge outcome.
186
+ */
187
+ export async function projectDocUpdateThroughSections(projectRoot, input) {
188
+ const existingUid = await resolveConduitDocUid(projectRoot, input.slug);
189
+ const contentBuffer = Buffer.from(input.content, 'utf-8');
190
+ // T13356 — advisory lease coordination, before the transaction. Unbound
191
+ // callers (no input session, no bound session) edit uncoordinated: leases
192
+ // are per-session state and there is nothing to acquire under.
193
+ const boundSessionId = input.sessionId ?? (await resolveBoundSession(projectRoot))?.session.id ?? null;
194
+ const leaseNotices = [];
195
+ const acquiredThisRun = [];
196
+ if (boundSessionId !== null) {
197
+ const leaseManager = new SectionLeaseManager(projectRoot, {
198
+ sessionId: boundSessionId,
199
+ holder: input.authorAgentId,
200
+ });
201
+ const docUidForLeases = existingUid ?? input.slug;
202
+ for (const [index, text] of splitDocIntoSections(input.content).entries()) {
203
+ const id = sectionId(index);
204
+ const stored = existingUid !== null ? await readSectionCrdtState(projectRoot, docUidForLeases, id) : null;
205
+ // Only sections the edit actually touches are coordinated: unchanged
206
+ // sections carry no edit, so claiming them would only block others.
207
+ const touches = stored === null || sectionStateText(stored.snapshot) !== text;
208
+ if (!touches)
209
+ continue;
210
+ const acquired = await leaseManager.acquire(input.slug, id, SECTION_LEASE_TTL_SECONDS, input.changeSummary ?? 'section edit');
211
+ if (acquired.ok) {
212
+ acquiredThisRun.push(id);
213
+ continue;
214
+ }
215
+ if (acquired.conflict.sessionId === boundSessionId) {
216
+ // Our own lease: continued edits renew it (T13356 AC2).
217
+ const renewed = await leaseManager.renew(input.slug, id, SECTION_LEASE_TTL_SECONDS);
218
+ if (!renewed.ok) {
219
+ // Expired between the probes: re-acquire (takeover of our own
220
+ // stale lease). A foreign live lease here is reported below.
221
+ const retry = await leaseManager.acquire(input.slug, id, SECTION_LEASE_TTL_SECONDS, input.changeSummary ?? 'section edit');
222
+ if (retry.ok) {
223
+ acquiredThisRun.push(id);
224
+ continue;
225
+ }
226
+ leaseNotices.push(noticeOf(id, retry.conflict));
227
+ }
228
+ continue;
229
+ }
230
+ leaseNotices.push(noticeOf(id, acquired.conflict));
231
+ }
232
+ }
233
+ try {
234
+ return await withConduitDocWriteTransaction(projectRoot, async () => {
235
+ const { uid: docUid, adopted } = existingUid !== null
236
+ ? { uid: existingUid, adopted: false }
237
+ : await ensureConduitDoc(projectRoot, {
238
+ slug: input.slug,
239
+ authorAgentId: input.authorAgentId,
240
+ content: contentBuffer,
241
+ });
242
+ // Resolve the previous head's section texts FIRST — the default
243
+ // single-writer vs. concurrent discriminator for every section below
244
+ // (T13589). A caller-declared base (T13674) REPLACES it: the incoming
245
+ // edit is then judged against the base it was authored from, so a
246
+ // stale base composes (append) or conflicts (non-append) instead of
247
+ // re-seeding over a concurrent writer's landed edit.
248
+ const previousHead = await getConduitDocHead(projectRoot, docUid);
249
+ const headSections = previousHead !== null ? await readHeadSectionTexts(projectRoot, previousHead) : null;
250
+ const referenceSections = input.baseSections !== undefined && input.baseSections !== null
251
+ ? input.baseSections
252
+ : headSections;
253
+ // Apply each section's edit onto its stored Loro state and read the
254
+ // MERGED text back out of the state — never out of the input (T13585).
255
+ const sections = splitDocIntoSections(input.content);
256
+ const mergedSections = [];
257
+ const sectionsModified = [];
258
+ const conflictedSections = [];
259
+ for (const [index, text] of sections.entries()) {
260
+ const id = sectionId(index);
261
+ const stored = await readSectionCrdtState(projectRoot, docUid, id);
262
+ const { snapshot, changed, conflicted } = applySectionTextEdit(stored?.snapshot ?? null, text, referenceSections?.[index] ?? null);
263
+ if (changed || stored === null) {
264
+ await writeSectionCrdtState(projectRoot, {
265
+ attachmentUid: docUid,
266
+ sectionId: id,
267
+ snapshot,
268
+ baseVersionUid: stored?.baseVersionUid ?? null,
269
+ });
270
+ }
271
+ if (changed)
272
+ sectionsModified.push(id);
273
+ if (conflicted)
274
+ conflictedSections.push(id);
275
+ mergedSections.push(sectionStateText(snapshot));
276
+ }
277
+ const mergedText = joinSections(mergedSections);
278
+ // Append the DAG version row (parent = the previous head's version).
279
+ const contentHash = createHash('sha256').update(mergedText, 'utf-8').digest('hex');
280
+ const size = Buffer.byteLength(mergedText, 'utf-8');
281
+ const storageKey = `${contentHash.slice(0, 2)}/${contentHash.slice(2)}.md`;
282
+ // Write the blob BEFORE the insert so a committed row never references
283
+ // missing bytes; a rollback only leaves a harmless content-addressed
284
+ // orphan (reused by a later identical projection).
285
+ writeMergedBlob(projectRoot, storageKey, mergedText);
286
+ const parentVersionUid = input.parentVersionUid !== undefined
287
+ ? input.parentVersionUid
288
+ : (previousHead?.headVersionUid ?? null);
289
+ const version = await appendConduitAttachmentVersion(projectRoot, {
290
+ attachmentUid: docUid,
291
+ parentVersionUid,
292
+ authorAgentId: input.authorAgentId,
293
+ storageKey,
294
+ contentHash,
295
+ originalSize: size,
296
+ compressedSize: size,
297
+ tokens: countTokens(mergedText),
298
+ changeType: 'patch',
299
+ ...(input.changeSummary !== undefined ? { changeSummary: input.changeSummary } : {}),
300
+ sectionsModified,
301
+ tokensAdded: countTokens(input.content),
302
+ });
303
+ // Project into the current-version row under the max-HLC rule. The
304
+ // version row survives even when a concurrent head wins, so nothing
305
+ // written above is lost.
306
+ const headHlc = input.hlc ?? mintHeadHlc(previousHead?.headHlc ?? null);
307
+ const head = await upsertConduitDocHead(projectRoot, {
308
+ attachmentUid: docUid,
309
+ headVersionUid: version.uid ?? '',
310
+ headHlc,
311
+ });
312
+ // T13595: a non-append concurrent section edit cannot be merged without
313
+ // fabricating text (the primitives are append-only), so land the incoming
314
+ // edit as its OWN version row — append-only history already preserves
315
+ // both — keep the stored projection as the head, and record the conflict
316
+ // on the head, mirroring the docs.head.max-hlc semantics. The conflict
317
+ // upsert uses the previous head's HLC, which is strictly below the
318
+ // projection HLC in the local-mint path, so the incoming version always
319
+ // loses honestly. (With an explicit `hlc` at or below the previous
320
+ // head's, the projection itself loses first and the incoming version
321
+ // records a second conflict — both stay visible, nothing is invented.)
322
+ const conflicts = [];
323
+ if (conflictedSections.length > 0) {
324
+ const incomingHash = createHash('sha256').update(input.content, 'utf-8').digest('hex');
325
+ const incomingKey = `${incomingHash.slice(0, 2)}/${incomingHash.slice(2)}.md`;
326
+ writeMergedBlob(projectRoot, incomingKey, input.content);
327
+ const incoming = await appendConduitAttachmentVersion(projectRoot, {
328
+ attachmentUid: docUid,
329
+ parentVersionUid,
330
+ authorAgentId: input.authorAgentId,
331
+ storageKey: incomingKey,
332
+ contentHash: incomingHash,
333
+ originalSize: Buffer.byteLength(input.content, 'utf-8'),
334
+ compressedSize: Buffer.byteLength(input.content, 'utf-8'),
335
+ tokens: countTokens(input.content),
336
+ changeType: 'patch',
337
+ changeSummary: `concurrent non-append edit on ${conflictedSections.join(', ')} — conflict recorded, not merged`,
338
+ sectionsModified: conflictedSections,
339
+ tokensAdded: countTokens(input.content),
340
+ });
341
+ if (previousHead !== null && incoming.uid) {
342
+ await upsertConduitDocHead(projectRoot, {
343
+ attachmentUid: docUid,
344
+ headVersionUid: incoming.uid,
345
+ headHlc: previousHead.headHlc,
346
+ });
347
+ for (const sectionId of conflictedSections) {
348
+ conflicts.push({
349
+ sectionId,
350
+ incomingVersionUid: incoming.uid,
351
+ projectionVersionUid: version.uid ?? '',
352
+ });
353
+ }
354
+ }
355
+ }
356
+ // A landed version rebases the local section states; the derived
357
+ // contributors rollup is rebuilt from the versions table.
358
+ if (version.uid) {
359
+ await rebaseSectionCrdtStates(projectRoot, docUid, version.uid);
360
+ }
361
+ await rebuildConduitAttachmentContributors(projectRoot, docUid);
362
+ return {
363
+ docUid,
364
+ adopted,
365
+ mergedText,
366
+ sectionsModified,
367
+ version,
368
+ head,
369
+ previousHeadVersionUid: previousHead?.headVersionUid ?? null,
370
+ conflicts,
371
+ leaseNotices,
372
+ };
373
+ });
374
+ }
375
+ catch (err) {
376
+ // The projection rolled back: release the leases acquired for it, so a
377
+ // failed edit leaves no stale claim. (Renewed pre-existing leases stay —
378
+ // the session still holds them.)
379
+ if (boundSessionId !== null && acquiredThisRun.length > 0) {
380
+ const leaseManager = new SectionLeaseManager(projectRoot, {
381
+ sessionId: boundSessionId,
382
+ holder: input.authorAgentId,
383
+ });
384
+ for (const section of acquiredThisRun) {
385
+ await leaseManager.release(input.slug, section);
386
+ }
387
+ }
388
+ throw err;
389
+ }
390
+ }
391
+ /** Conflict view of a lease for a {@link SectionLeaseNotice}. */
392
+ function noticeOf(sectionIdValue, conflict) {
393
+ return {
394
+ sectionId: sectionIdValue,
395
+ holder: conflict.holder,
396
+ sessionId: conflict.sessionId,
397
+ expiresAt: conflict.expiresAt,
398
+ };
399
+ }
400
+ /**
401
+ * Release every section lease this session holds for a doc — the "release
402
+ * on completion" path of T13356 AC2: a session calls this when it finishes
403
+ * editing the doc, so the sections are free for the next editor before the
404
+ * TTL would have expired them.
405
+ *
406
+ * @param projectRoot - Absolute path to the CLEO project root.
407
+ * @param slug - The doc's live slug (leases are keyed by it).
408
+ * @param sessionId - The finishing session (only its own leases are released).
409
+ * @returns The section ids released.
410
+ */
411
+ export async function releaseSectionLeases(projectRoot, slug, sessionId) {
412
+ const leaseManager = new SectionLeaseManager(projectRoot, { sessionId });
413
+ const released = [];
414
+ for (const lease of await listSectionLeases(projectRoot, slug)) {
415
+ if (lease.sessionId !== sessionId)
416
+ continue;
417
+ if (await leaseManager.release(lease.slug, lease.sectionId)) {
418
+ released.push(lease.sectionId);
419
+ }
420
+ }
421
+ return released;
422
+ }
423
+ //# sourceMappingURL=section-write-path.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"section-write-path.js","sourceRoot":"","sources":["../../src/docs/section-write-path.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * `docs.stats` — per-project CleoDocs adoption metrics (T13363, spec §7/§9).
3
+ *
4
+ * Emitted so the CleoDocs re-architecture is judged by behaviour, not by
5
+ * file counts in the store:
6
+ *
7
+ * - **add:update ratio** — `docs.add` vs `docs.update` entries in the docs
8
+ * audit log (`.cleo/audit/docs-audit.jsonl`, via {@link readAuditLog}).
9
+ * The pilot's starting point is ~10:1.
10
+ * - **loose-markdown count** — `*.md` files TRACKED BY GIT outside the
11
+ * CleoDocs store (`git ls-files '*.md'` minus the store). Using the index
12
+ * makes the scan gitignore-aware by construction: dependency trees,
13
+ * VCS internals, `.cleo/council-runs`, and nested git worktrees never
14
+ * appear because real projects ignore them. The Council baseline counts
15
+ * (~751 axiom-app + 1,265 admin-operations) were of tracked/counted
16
+ * loose files, so this is the comparable shape. UNTracked loose `.md`
17
+ * files are intentionally out of scope — they are invisible to the
18
+ * adoption signal. Outside a git work tree the metric is 0 (there is no
19
+ * tracked-files notion to measure).
20
+ * - **wikilinks edges** — row count of the `docs_wikilinks` graph table
21
+ * (T11826), through the chokepoint drizzle handle.
22
+ * - **decisions linked** — live `decision_adr_links` rows (status
23
+ * `linked`, T13359). The legacy ledger `adrPath` field has no read
24
+ * accessor, so only the link table contributes.
25
+ *
26
+ * Read-only: never writes to the store, the filesystem, or the audit log.
27
+ *
28
+ * @module
29
+ * @task T13363
30
+ * @task T13629 — loose-markdown scan is git ls-files-based (gitignore-aware)
31
+ * @epic T13340
32
+ * @saga T13339
33
+ */
34
+ import type { DocsStatsResult, LooseMarkdownMetrics } from '@cleocode/contracts/operations/docs.js';
35
+ /**
36
+ * Count loose `*.md` files — git-tracked markdown outside the CleoDocs
37
+ * store. `git ls-files '*.md'` from the project root returns the tracked
38
+ * markdown paths (gitignore-aware); the store and dependency trees are then
39
+ * filtered defensively. Untracked files are intentionally NOT counted.
40
+ *
41
+ * @param projectRoot - Absolute project root (must be a git work tree).
42
+ * @returns The count plus what was scanned and excluded; `count` is 0 with
43
+ * empty `scannedDirs` when the root is not a git work tree.
44
+ */
45
+ export declare function countLooseMarkdown(projectRoot: string): LooseMarkdownMetrics;
46
+ /**
47
+ * Compute the per-project adoption metrics for `docs.stats` (T13363).
48
+ *
49
+ * @param opts.projectRoot - Absolute path to the CLEO project root.
50
+ * @returns The metrics envelope (read-only; nothing is written).
51
+ * @task T13363
52
+ */
53
+ export declare function computeDocsStats(opts: {
54
+ projectRoot: string;
55
+ }): Promise<DocsStatsResult>;
56
+ //# sourceMappingURL=stats.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.d.ts","sourceRoot":"","sources":["../../src/docs/stats.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AAGH,OAAO,KAAK,EAEV,eAAe,EACf,oBAAoB,EACrB,MAAM,wCAAwC,CAAC;AAgBhD;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,oBAAoB,CAkB5E;AAED;;;;;;GAMG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE;IAAE,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,eAAe,CAAC,CAsC9F"}
@@ -0,0 +1,119 @@
1
+ /**
2
+ * `docs.stats` — per-project CleoDocs adoption metrics (T13363, spec §7/§9).
3
+ *
4
+ * Emitted so the CleoDocs re-architecture is judged by behaviour, not by
5
+ * file counts in the store:
6
+ *
7
+ * - **add:update ratio** — `docs.add` vs `docs.update` entries in the docs
8
+ * audit log (`.cleo/audit/docs-audit.jsonl`, via {@link readAuditLog}).
9
+ * The pilot's starting point is ~10:1.
10
+ * - **loose-markdown count** — `*.md` files TRACKED BY GIT outside the
11
+ * CleoDocs store (`git ls-files '*.md'` minus the store). Using the index
12
+ * makes the scan gitignore-aware by construction: dependency trees,
13
+ * VCS internals, `.cleo/council-runs`, and nested git worktrees never
14
+ * appear because real projects ignore them. The Council baseline counts
15
+ * (~751 axiom-app + 1,265 admin-operations) were of tracked/counted
16
+ * loose files, so this is the comparable shape. UNTracked loose `.md`
17
+ * files are intentionally out of scope — they are invisible to the
18
+ * adoption signal. Outside a git work tree the metric is 0 (there is no
19
+ * tracked-files notion to measure).
20
+ * - **wikilinks edges** — row count of the `docs_wikilinks` graph table
21
+ * (T11826), through the chokepoint drizzle handle.
22
+ * - **decisions linked** — live `decision_adr_links` rows (status
23
+ * `linked`, T13359). The legacy ledger `adrPath` field has no read
24
+ * accessor, so only the link table contributes.
25
+ *
26
+ * Read-only: never writes to the store, the filesystem, or the audit log.
27
+ *
28
+ * @module
29
+ * @task T13363
30
+ * @task T13629 — loose-markdown scan is git ls-files-based (gitignore-aware)
31
+ * @epic T13340
32
+ * @saga T13339
33
+ */
34
+ import { spawnSync } from 'node:child_process';
35
+ import { count } from 'drizzle-orm';
36
+ import { countLinkedDecisionAdrs } from '../store/decision-adr-links.js';
37
+ import { docsWikilinks } from '../store/schema/attachments.js';
38
+ import { getDb } from '../store/sqlite.js';
39
+ import { readAuditLog } from './docs-audit.js';
40
+ /**
41
+ * Directory names excluded from the loose-markdown count. The gitignore-aware
42
+ * `git ls-files` scan already keeps these out of the index in real projects;
43
+ * the filter below is defense-in-depth for a project that force-adds one.
44
+ * `.cleo` covers the CleoDocs storage surfaces (attachments, blobs) and
45
+ * `.cleo/council-runs` (the Council workload store).
46
+ */
47
+ const EXCLUDED_DIR_NAMES = ['node_modules', '.git', '.cleo'];
48
+ /**
49
+ * Count loose `*.md` files — git-tracked markdown outside the CleoDocs
50
+ * store. `git ls-files '*.md'` from the project root returns the tracked
51
+ * markdown paths (gitignore-aware); the store and dependency trees are then
52
+ * filtered defensively. Untracked files are intentionally NOT counted.
53
+ *
54
+ * @param projectRoot - Absolute project root (must be a git work tree).
55
+ * @returns The count plus what was scanned and excluded; `count` is 0 with
56
+ * empty `scannedDirs` when the root is not a git work tree.
57
+ */
58
+ export function countLooseMarkdown(projectRoot) {
59
+ const excludedDirs = [...EXCLUDED_DIR_NAMES];
60
+ const result = spawnSync('git', ['ls-files', '--', '*.md'], {
61
+ cwd: projectRoot,
62
+ encoding: 'utf8',
63
+ });
64
+ if (result.status !== 0) {
65
+ // Not a git work tree (or git unavailable): the metric counts tracked
66
+ // loose markdown only, so there is nothing to measure.
67
+ return { count: 0, scannedDirs: [], excludedDirs };
68
+ }
69
+ const tracked = result.stdout.split('\n').filter((line) => line.length > 0);
70
+ const counted = tracked.filter((p) => !p.startsWith('.cleo/') && !p.startsWith('node_modules/'));
71
+ const scanned = new Set();
72
+ for (const path of counted) {
73
+ scanned.add(path.includes('/') ? path.slice(0, path.indexOf('/')) : '(root)');
74
+ }
75
+ return { count: counted.length, scannedDirs: [...scanned].sort(), excludedDirs };
76
+ }
77
+ /**
78
+ * Compute the per-project adoption metrics for `docs.stats` (T13363).
79
+ *
80
+ * @param opts.projectRoot - Absolute path to the CLEO project root.
81
+ * @returns The metrics envelope (read-only; nothing is written).
82
+ * @task T13363
83
+ */
84
+ export async function computeDocsStats(opts) {
85
+ const { projectRoot } = opts;
86
+ // Add vs update activity — the audit log is the canonical mutation record.
87
+ const audit = readAuditLog(projectRoot);
88
+ let adds = 0;
89
+ let updates = 0;
90
+ for (const entry of audit.entries) {
91
+ if (entry.op === 'docs.add')
92
+ adds += 1;
93
+ else if (entry.op === 'docs.update')
94
+ updates += 1;
95
+ }
96
+ const addUpdate = {
97
+ adds,
98
+ updates,
99
+ ratio: updates > 0 ? adds / updates : null,
100
+ };
101
+ const looseMarkdown = countLooseMarkdown(projectRoot);
102
+ // Graph edge count, through the chokepoint drizzle handle (reads only).
103
+ const db = await getDb(projectRoot);
104
+ const edgeRows = await db.select({ n: count() }).from(docsWikilinks).all();
105
+ const wikilinksEdges = edgeRows[0]?.n ?? 0;
106
+ const decisionsLinked = await countLinkedDecisionAdrs(projectRoot);
107
+ const ratioText = addUpdate.ratio === null ? 'n/a' : addUpdate.ratio.toFixed(2);
108
+ return {
109
+ addUpdate,
110
+ looseMarkdown,
111
+ wikilinksEdges,
112
+ decisionsLinked,
113
+ generatedAt: new Date().toISOString(),
114
+ summary: `adds ${adds} / updates ${updates} (ratio ${ratioText}); ` +
115
+ `${looseMarkdown.count} loose markdown files; ` +
116
+ `${wikilinksEdges} wikilinks edges; ${decisionsLinked} decisions linked`,
117
+ };
118
+ }
119
+ //# sourceMappingURL=stats.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stats.js","sourceRoot":"","sources":["../../src/docs/stats.ts"],"names":[],"mappings":"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"}
@@ -160,7 +160,7 @@ export interface OrphanEntry {
160
160
  * @task T9043
161
161
  * @task T11996
162
162
  */
163
- export declare function pruneOrphanWorktrees(options: PruneOrphanWorktreesOptions): CleanupResult;
163
+ export declare function pruneOrphanWorktrees(options: PruneOrphanWorktreesOptions): Promise<CleanupResult>;
164
164
  /**
165
165
  * Prune orphaned CLEO-generated temp directories.
166
166
  *
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/gc/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAoBH;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAqCtC,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,QAAqB,CAAC;AAM1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,kCAAkC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoND;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,2BAA2B,GAAG,aAAa,CAwKxF;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,0BAA+B,GAAG,aAAa,CAsE3F;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,GAAE,MAAgC,EAC1C,OAAO,GAAE,MAAiB,GACzB,WAAW,EAAE,CA4Bf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,WAAW,CAAC,EAAE,MAAM,GACnB,WAAW,EAAE,CAkDf"}
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"","sources":["../../src/gc/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAoBH;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,SAAS,MAAM,EAqCtC,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,uBAAuB,QAAqB,CAAC;AAM1D;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,iFAAiF;IACjF,WAAW,EAAE,MAAM,CAAC;IACpB,oFAAoF;IACpF,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,MAAM,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAChD,kCAAkC;IAClC,MAAM,EAAE,OAAO,CAAC;IAChB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;OAGG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;IAC3B;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAC;CAClB;AAoND;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,2BAA2B,GACnC,OAAO,CAAC,aAAa,CAAC,CAkLxB;AAMD;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,0BAA+B,GAAG,aAAa,CAsE3F;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,GAAE,MAAgC,EAC1C,OAAO,GAAE,MAAiB,GACzB,WAAW,EAAE,CA4Bf;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,mBAAmB,CACjC,aAAa,EAAE,MAAM,EACrB,aAAa,EAAE,GAAG,CAAC,MAAM,CAAC,EAC1B,WAAW,CAAC,EAAE,MAAM,GACnB,WAAW,EAAE,CAkDf"}