@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,480 @@
1
+ /**
2
+ * T13360 — honest migration of legacy docs into the re-keyed store
3
+ * (spec `cleodocs-rearch-design` §5, D11165).
4
+ *
5
+ * Imports every legacy CleoDocs document (`docs_attachments` rows — the
6
+ * D11-collapse twin of the legacy `attachments` registry) into the T13354
7
+ * re-keyed conduit history family, inside the T13448 migration safety
8
+ * harness:
9
+ *
10
+ * backup → BEGIN IMMEDIATE → before-fingerprints → step → verify →
11
+ * COMMIT (only when every check passed) / ROLLBACK
12
+ *
13
+ * Honesty contract (the spec's words are the ACs):
14
+ *
15
+ * - **Every imported history row is labeled `origin: 'migrated'`** — no
16
+ * imported row poses as native (AC1).
17
+ * - **No fabricated authors, no invented version numbers** — authors come
18
+ * from the legacy docs audit log's real `actor`; when no provenance
19
+ * exists the row is system-attributed (`system:migration`), the AC's
20
+ * sanctioned "system attribution", never an invented human (AC2).
21
+ * Version ordinals are derived from the real audit-event order.
22
+ * - **Dangling-pointer docs are content-captured or marked dangling** —
23
+ * a doc whose recorded path is missing or ephemeral (worktree/tmp) gets
24
+ * its bytes recovered from the content-addressed blob store when
25
+ * possible (captured); otherwise it is recorded in
26
+ * `conduit_doc_migration_ledger` with `status: 'dangling'`, the legacy
27
+ * pointer and the reason — never silently imported (AC3).
28
+ * - **Idempotent** — every write carries a NATURAL uid (doc slug; (doc
29
+ * uid, content hash, event timestamp); ledger slug), so a re-run derives
30
+ * the same uids and `ON CONFLICT DO NOTHING` turns it into a verified
31
+ * no-op; docs already in the ledger are skipped. The second run's
32
+ * harness verification proves zero deltas and unchanged hashes (AC4).
33
+ *
34
+ * The migration is exposed as `cleo docs migrate` (dispatch op
35
+ * `docs.migrate`); it takes its own pre-step VACUUM INTO backup through the
36
+ * harness and needs no `--force` (it is additive — nothing is deleted).
37
+ *
38
+ * Cross-device identity (T13638): the audit log (`docs-audit.jsonl`) is a
39
+ * DEVICE-LOCAL file — it never syncs. Version identity therefore CANNOT
40
+ * derive from a row's position in it (`evt-<i>` was v1 and diverged across
41
+ * devices). Every imported version's natural uid is instead a pure function
42
+ * of the version's real facts — (doc uid, content hash, event timestamp) —
43
+ * so two devices migrating the same synced legacy doc derive IDENTICAL uids
44
+ * for the same content whatever their local audit logs hold, and two
45
+ * different contents can never collide on one uid. The doc uid, the ledger
46
+ * receipt, and the head projection were already device-independent.
47
+ *
48
+ * Existing installs: a store that already ran the t13360 import keeps its
49
+ * position-derived version uids — the ledger receipt makes the migration
50
+ * one-shot per doc, so the content-derived derivation applies to newly
51
+ * migrated rows only (accepted mixed state, per the task's (a) option; no
52
+ * re-key migration, since the spec does not mandate one).
53
+ *
54
+ * @module
55
+ * @task T13360
56
+ * @task T13633 — review round 2: leaf HLC constant, native-conflict count,
57
+ * cross-device caveat
58
+ * @task T13638 — version uids derived from (doc uid, content hash, event
59
+ * timestamp), never from the device-local audit position
60
+ * @epic T13340
61
+ * @saga T13339
62
+ */
63
+ import { createHash } from 'node:crypto';
64
+ import { existsSync, readFileSync } from 'node:fs';
65
+ import { tmpdir } from 'node:os';
66
+ import { isAbsolute, resolve, sep } from 'node:path';
67
+ import { getCleoWorktreesRoot } from '@cleocode/paths';
68
+ import { eq, isNotNull } from 'drizzle-orm';
69
+ import { getCleoDir } from '../paths.js';
70
+ import { blobContentExists, blobFilePath } from '../store/blob-keep.js';
71
+ import { findConduitDocMigration, importMigratedConduitDoc, importMigratedConduitVersion, recordConduitDocMigration, upsertConduitDocHead, } from '../store/conduit-doc-history.js';
72
+ import { runMigrationSteps, } from '../store/migration-safety.js';
73
+ import { conduitAttachments } from '../store/schema/cleo-project/conduit.js';
74
+ import { getDb } from '../store/sqlite.js';
75
+ import { encodeHlc, PRE_HLC_REPLICA } from '../store/sync/hlc.js';
76
+ import { docsAttachments } from '../store/tasks-schema.js';
77
+ import { readAuditLog } from './docs-audit.js';
78
+ /**
79
+ * The honest system attribution for migrated rows with no real author
80
+ * provenance (spec §5 "system attribution"). Never an invented human name.
81
+ */
82
+ export const MIGRATION_SYSTEM_AUTHOR = 'system:migration';
83
+ /** True when `absPath` is ephemeral — inside a CLEO/Claude worktree or tmp. */
84
+ function isEphemeralPath(absPath) {
85
+ const worktreesRoot = getCleoWorktreesRoot();
86
+ if (absPath === worktreesRoot || absPath.startsWith(`${worktreesRoot}${sep}`)) {
87
+ return 'worktree';
88
+ }
89
+ if (absPath.includes(`${sep}.claude${sep}worktrees${sep}`))
90
+ return 'worktree';
91
+ const tmp = tmpdir();
92
+ if (absPath.startsWith(`${tmp}${sep}`) || absPath.startsWith(`${sep}tmp${sep}`))
93
+ return 'tmp';
94
+ return null;
95
+ }
96
+ /** Read the content-addressed blob bytes for a sha/mime, or null. */
97
+ function readBlobBytes(cleoDir, sha256, mime) {
98
+ const primary = blobFilePath(cleoDir, sha256, mime);
99
+ try {
100
+ return readFileSync(primary);
101
+ }
102
+ catch {
103
+ return null;
104
+ }
105
+ }
106
+ /** Cheap whitespace token count — a measurement, never an invention. */
107
+ function countTokens(bytes) {
108
+ let count = 0;
109
+ let inWs = true;
110
+ for (let i = 0; i < bytes.length; i++) {
111
+ const c = bytes[i] ?? 0;
112
+ const ws = c === 32 || c === 9 || c === 10 || c === 13;
113
+ if (!ws && inWs)
114
+ count += 1;
115
+ inWs = ws;
116
+ }
117
+ return count;
118
+ }
119
+ function sha256Hex(bytes) {
120
+ return createHash('sha256').update(bytes).digest('hex');
121
+ }
122
+ function parsePayload(raw) {
123
+ try {
124
+ const parsed = JSON.parse(raw);
125
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
126
+ return parsed;
127
+ }
128
+ return null;
129
+ }
130
+ catch {
131
+ return null;
132
+ }
133
+ }
134
+ function formatFromMime(mime, slug) {
135
+ if (mime?.includes('markdown'))
136
+ return 'markdown';
137
+ if (slug.toLowerCase().endsWith('.md'))
138
+ return 'markdown';
139
+ return 'text';
140
+ }
141
+ /**
142
+ * Derive the import plan for every legacy doc — the SAME derivation runs in
143
+ * `planLegacyDocMigration` (to declare the harness's expected deltas) and
144
+ * inside the step (inside the transaction), so the deltas match by
145
+ * construction and any divergence fails verification and rolls back.
146
+ *
147
+ * Read-only: never writes; reads the store, the blob files and the audit
148
+ * log.
149
+ *
150
+ * @internal Exported for tests.
151
+ */
152
+ export async function deriveLegacyDocMigrationPlan(projectRoot) {
153
+ const cleoDir = getCleoDir(projectRoot);
154
+ const db = await getDb(projectRoot);
155
+ const rows = await db.select().from(docsAttachments).where(isNotNull(docsAttachments.slug)).all();
156
+ const audit = readAuditLog(projectRoot);
157
+ const docs = [];
158
+ let skipped = 0;
159
+ let nativeConflicts = 0;
160
+ for (const row of rows) {
161
+ const slug = row.slug;
162
+ // Idempotency: a doc already receipted (captured or dangling) is done.
163
+ if ((await findConduitDocMigration(projectRoot, slug)) !== null) {
164
+ skipped += 1;
165
+ continue;
166
+ }
167
+ // Never clobber a native conduit doc that happens to share the slug —
168
+ // counted explicitly so the operator can reconcile it (T13633).
169
+ const existing = await db
170
+ .select({ slug: conduitAttachments.slug })
171
+ .from(conduitAttachments)
172
+ .where(eq(conduitAttachments.slug, slug))
173
+ .get();
174
+ if (existing !== undefined && existing !== null) {
175
+ nativeConflicts += 1;
176
+ continue;
177
+ }
178
+ const payload = parsePayload(row.attachmentJson);
179
+ const mime = payload?.mime;
180
+ const fmt = formatFromMime(mime, slug);
181
+ // ── dangling classification (doctor parity: missing OR ephemeral path) ──
182
+ const pointerPath = payload !== null && typeof payload.path === 'string' && payload.path.length > 0
183
+ ? payload.path
184
+ : null;
185
+ let danglingReason = null;
186
+ if (payload === null) {
187
+ danglingReason = 'unparseable-payload';
188
+ }
189
+ else if (payload.kind !== 'blob' && payload.kind !== 'local-file') {
190
+ danglingReason = `no-local-content:${payload.kind}`;
191
+ }
192
+ else if (pointerPath !== null) {
193
+ const abs = isAbsolute(pointerPath) ? pointerPath : resolve(projectRoot, pointerPath);
194
+ const ephemeral = isEphemeralPath(abs);
195
+ if (!existsSync(abs)) {
196
+ danglingReason = 'path-missing';
197
+ }
198
+ else if (ephemeral !== null) {
199
+ danglingReason = `path-ephemeral:${ephemeral}`;
200
+ }
201
+ }
202
+ // ── content capture ──
203
+ let content = null;
204
+ let capturedReason = 'captured';
205
+ if (danglingReason === null) {
206
+ if (payload?.kind === 'local-file' && pointerPath !== null) {
207
+ const abs = isAbsolute(pointerPath) ? pointerPath : resolve(projectRoot, pointerPath);
208
+ try {
209
+ content = readFileSync(abs);
210
+ }
211
+ catch {
212
+ danglingReason = 'path-unreadable';
213
+ }
214
+ }
215
+ else {
216
+ content = readBlobBytes(cleoDir, row.sha256, mime ?? 'application/octet-stream');
217
+ if (content === null)
218
+ danglingReason = 'blob-bytes-missing';
219
+ }
220
+ if (content !== null && danglingReason !== null) {
221
+ // Dangling pointer, bytes recovered from the content-addressed store.
222
+ capturedReason = `recovered:${danglingReason}`;
223
+ danglingReason = null;
224
+ }
225
+ }
226
+ else if (danglingReason !== 'unparseable-payload' && payload?.kind !== undefined) {
227
+ // Dangling pointer — try to recover the bytes by sha from the blob store.
228
+ if (blobContentExists(cleoDir, row.sha256, mime ?? 'application/octet-stream')) {
229
+ content = readBlobBytes(cleoDir, row.sha256, mime ?? 'application/octet-stream');
230
+ if (content !== null) {
231
+ capturedReason = `recovered:${danglingReason}`;
232
+ danglingReason = null;
233
+ }
234
+ }
235
+ }
236
+ if (danglingReason !== null || content === null) {
237
+ docs.push({
238
+ slug,
239
+ status: 'dangling',
240
+ reason: danglingReason ?? 'blob-bytes-missing',
241
+ legacyPath: pointerPath,
242
+ legacySha256: row.sha256,
243
+ content: null,
244
+ format: fmt,
245
+ title: row.summary ?? null,
246
+ createdAt: row.createdAt,
247
+ versions: [],
248
+ fromAgentId: MIGRATION_SYSTEM_AUTHOR,
249
+ });
250
+ continue;
251
+ }
252
+ // ── history reconstruction from the real audit log ──
253
+ const events = audit.entries.filter((e) => e.slug === slug && (e.op === 'docs.add' || e.op === 'docs.update'));
254
+ const versions = [];
255
+ // T13638: two events with the SAME content at the SAME instant are one
256
+ // logical version — the content-derived natural uid cannot tell them
257
+ // apart, so a repeat would either no-op away honest history or parent a
258
+ // version to itself. The first occurrence is kept; each repeat is a
259
+ // collapsed duplicate write, counted into the survivor's summary.
260
+ const seenVersionKeys = new Map();
261
+ const collapsedDuplicates = new Map();
262
+ for (const event of events) {
263
+ if (event.sha256 === undefined)
264
+ continue;
265
+ const eventMime = mime ?? 'application/octet-stream';
266
+ if (!blobContentExists(cleoDir, event.sha256, eventMime))
267
+ continue; // bytes gone — honest omission
268
+ const bytes = readBlobBytes(cleoDir, event.sha256, eventMime);
269
+ if (bytes === null)
270
+ continue;
271
+ const versionKey = `${event.sha256}|${event.ts}`;
272
+ const prior = seenVersionKeys.get(versionKey);
273
+ if (prior !== undefined) {
274
+ collapsedDuplicates.set(versionKey, (collapsedDuplicates.get(versionKey) ?? 0) + 1);
275
+ continue;
276
+ }
277
+ seenVersionKeys.set(versionKey, versions.length);
278
+ versions.push({
279
+ authorAgentId: typeof event.actor === 'string' && event.actor.length > 0
280
+ ? event.actor
281
+ : MIGRATION_SYSTEM_AUTHOR,
282
+ contentHash: event.sha256,
283
+ sizeBytes: bytes.length,
284
+ tokens: countTokens(bytes),
285
+ createdAt: event.ts,
286
+ changeSummary: `migrated from the legacy docs store (audit ${event.op} @ ${event.ts})`,
287
+ });
288
+ }
289
+ for (const [versionKey, count] of collapsedDuplicates) {
290
+ const index = seenVersionKeys.get(versionKey);
291
+ if (index === undefined)
292
+ continue;
293
+ const survivor = versions[index];
294
+ if (survivor === undefined)
295
+ continue;
296
+ versions[index] = {
297
+ ...survivor,
298
+ changeSummary: `${survivor.changeSummary}; collapsed ${count} duplicate audit event(s) with identical content and timestamp`,
299
+ };
300
+ }
301
+ if (versions.length === 0) {
302
+ // No recoverable audit history — one content-capture version, honestly
303
+ // system-attributed. Never invented authors or ordinals.
304
+ versions.push({
305
+ authorAgentId: MIGRATION_SYSTEM_AUTHOR,
306
+ contentHash: row.sha256,
307
+ sizeBytes: content.length,
308
+ tokens: countTokens(content),
309
+ createdAt: row.createdAt,
310
+ changeSummary: 'migrated from the legacy docs store (content capture; no audit provenance)',
311
+ });
312
+ }
313
+ docs.push({
314
+ slug,
315
+ status: 'captured',
316
+ reason: capturedReason,
317
+ legacyPath: pointerPath,
318
+ legacySha256: row.sha256,
319
+ content,
320
+ format: fmt,
321
+ title: row.summary ?? null,
322
+ createdAt: row.createdAt,
323
+ versions,
324
+ fromAgentId: versions[versions.length - 1]?.authorAgentId ?? MIGRATION_SYSTEM_AUTHOR,
325
+ });
326
+ }
327
+ const expectedDelta = {
328
+ conduit_attachments: 0,
329
+ conduit_attachment_versions: 0,
330
+ conduit_doc_heads: 0,
331
+ conduit_doc_migration_ledger: 0,
332
+ };
333
+ for (const doc of docs) {
334
+ expectedDelta['conduit_doc_migration_ledger'] += 1;
335
+ if (doc.status === 'captured') {
336
+ expectedDelta['conduit_attachments'] += 1;
337
+ expectedDelta['conduit_attachment_versions'] += doc.versions.length;
338
+ expectedDelta['conduit_doc_heads'] += 1;
339
+ }
340
+ }
341
+ return { docs, skipped, nativeConflicts, expectedDelta };
342
+ }
343
+ /**
344
+ * Plan the migration: derive the work, declare the harness's expected deltas,
345
+ * and build the single harness step. Call immediately before
346
+ * {@link runLegacyDocMigration} — the plan and the step re-derive from the
347
+ * same state, and the harness fails verification (rolling back) if a
348
+ * concurrent write lands in between.
349
+ *
350
+ * @param projectRoot - Absolute path to the CLEO project root.
351
+ * @returns The plan (step + declared deltas + per-doc decisions).
352
+ * @task T13360
353
+ */
354
+ export async function planLegacyDocMigration(opts) {
355
+ const derived = await deriveLegacyDocMigrationPlan(opts.projectRoot);
356
+ const verify = {
357
+ expectedDelta: derived.expectedDelta,
358
+ };
359
+ const step = {
360
+ name: 'migrate-legacy-docs',
361
+ description: 'import legacy docs + history into the re-keyed conduit store (T13360, spec §5)',
362
+ verify,
363
+ run: async ({ db: _db, projectRoot, log }) => {
364
+ const plan = await deriveLegacyDocMigrationPlan(projectRoot);
365
+ for (const doc of plan.docs) {
366
+ if (doc.status === 'dangling') {
367
+ await recordConduitDocMigration(projectRoot, {
368
+ slug: doc.slug,
369
+ docUid: null,
370
+ status: 'dangling',
371
+ reason: doc.reason,
372
+ ...(doc.legacyPath !== null ? { legacyPath: doc.legacyPath } : {}),
373
+ legacySha256: doc.legacySha256,
374
+ versionsImported: 0,
375
+ });
376
+ log(`marked dangling: ${doc.slug} (${doc.reason})`);
377
+ continue;
378
+ }
379
+ const content = doc.content ?? Buffer.alloc(0);
380
+ const contentHash = sha256Hex(content);
381
+ const { uid: docUid } = await importMigratedConduitDoc(projectRoot, {
382
+ slug: doc.slug,
383
+ fromAgentId: doc.fromAgentId,
384
+ content,
385
+ contentHash,
386
+ format: doc.format,
387
+ ...(doc.title !== null ? { title: doc.title } : {}),
388
+ tokens: countTokens(content),
389
+ createdAt: doc.createdAt,
390
+ versionCount: doc.versions.length,
391
+ });
392
+ let parentUid = null;
393
+ let lastVersionUid = '';
394
+ let ordinal = 0;
395
+ for (const version of doc.versions) {
396
+ ordinal += 1;
397
+ const { uid } = await importMigratedConduitVersion(projectRoot, {
398
+ attachmentUid: docUid,
399
+ parentVersionUid: parentUid,
400
+ authorAgentId: version.authorAgentId,
401
+ storageKey: `sha256:${version.contentHash}`,
402
+ contentHash: version.contentHash,
403
+ sizeBytes: version.sizeBytes,
404
+ tokens: version.tokens,
405
+ versionNumber: ordinal,
406
+ createdAt: version.createdAt,
407
+ changeSummary: version.changeSummary,
408
+ slug: doc.slug,
409
+ });
410
+ parentUid = uid;
411
+ lastVersionUid = uid;
412
+ }
413
+ // Head projection: a deterministic HLC (pre-replica, phys = the last
414
+ // version's real timestamp) so a re-run's upsert is a stable no-op on
415
+ // every device — no spurious conflict records (AC4).
416
+ const lastVersion = doc.versions[doc.versions.length - 1];
417
+ if (lastVersion !== undefined && lastVersionUid.length > 0) {
418
+ await upsertConduitDocHead(projectRoot, {
419
+ attachmentUid: docUid,
420
+ headVersionUid: lastVersionUid,
421
+ headHlc: encodeHlc({
422
+ phys: Date.parse(lastVersion.createdAt),
423
+ ctr: ordinal,
424
+ replica: PRE_HLC_REPLICA,
425
+ }),
426
+ });
427
+ }
428
+ await recordConduitDocMigration(projectRoot, {
429
+ slug: doc.slug,
430
+ docUid,
431
+ status: 'captured',
432
+ reason: doc.reason,
433
+ ...(doc.legacyPath !== null ? { legacyPath: doc.legacyPath } : {}),
434
+ legacySha256: doc.legacySha256,
435
+ versionsImported: doc.versions.length,
436
+ });
437
+ log(`captured: ${doc.slug} (${doc.versions.length} version(s))`);
438
+ }
439
+ log(`legacy docs migration applied: ${plan.docs.filter((d) => d.status === 'captured').length} captured, ` +
440
+ `${plan.docs.filter((d) => d.status === 'dangling').length} dangling, ` +
441
+ `${plan.skipped} already migrated, ${plan.nativeConflicts} native-conflict skips`);
442
+ },
443
+ };
444
+ return {
445
+ step,
446
+ expectedDelta: derived.expectedDelta,
447
+ docs: derived.docs,
448
+ counts: {
449
+ toCapture: derived.docs.filter((d) => d.status === 'captured').length,
450
+ toMarkDangling: derived.docs.filter((d) => d.status === 'dangling').length,
451
+ toSkip: derived.skipped,
452
+ nativeConflicts: derived.nativeConflicts,
453
+ versions: derived.docs.reduce((n, d) => n + d.versions.length, 0),
454
+ },
455
+ };
456
+ }
457
+ /**
458
+ * Run the legacy docs migration inside the T13448 harness: pre-step VACUUM
459
+ * INTO backup → BEGIN IMMEDIATE → before-fingerprints → import → verify →
460
+ * COMMIT, or ROLLBACK on any failure (the failed step is never visible).
461
+ * Additive only — nothing is deleted, so no `force` is required.
462
+ *
463
+ * @param opts.projectRoot - Absolute path to the CLEO project root.
464
+ * @param opts.db - Live native handle on the project store (chokepoint-opened).
465
+ * @param opts.cwd - Invocation directory (the restore path's worktree guard).
466
+ * @param opts.onStepReport - Optional per-step report sink.
467
+ * @returns The harness report plus plan counts.
468
+ * @task T13360
469
+ */
470
+ export async function runLegacyDocMigration(opts) {
471
+ const plan = await planLegacyDocMigration({ projectRoot: opts.projectRoot });
472
+ const report = await runMigrationSteps([plan.step], {
473
+ db: opts.db,
474
+ projectRoot: opts.projectRoot,
475
+ cwd: opts.cwd,
476
+ onStepReport: opts.onStepReport,
477
+ });
478
+ return { report, counts: plan.counts };
479
+ }
480
+ //# sourceMappingURL=legacy-doc-migration.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"legacy-doc-migration.js","sourceRoot":"","sources":["../../src/docs/legacy-doc-migration.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Publications ledger store accessors (T13362) — the store-backed replacement
3
+ * for the deprecated `.cleo/docs-publications.json` sidecar.
4
+ *
5
+ * Every read/write of the docs publication ledger goes through this module on
6
+ * the `openDualScopeDb` chokepoint's drizzle handle ({@link getDb}) — gate 3
7
+ * (no raw opens) and gate 28 (no raw SQL writes to the syncing
8
+ * `docs_publications` table; the drizzle upsert compiles to the sanctioned
9
+ * `INSERT … ON CONFLICT … DO UPDATE` form).
10
+ *
11
+ * Semantics:
12
+ *
13
+ * - Identity is NATURAL over (owner_id, blob_name, published_path): both
14
+ * devices derive the same row uid for one triple, so a re-publish
15
+ * coalesces onto one row (gate 37 declaration in
16
+ * `row-identity-registry.ts`).
17
+ * - {@link upsertDocsPublication} refreshes `last_blob_sha` /
18
+ * `published_at` on conflict (latest-publish-wins); nothing is ever
19
+ * DELETEd here.
20
+ * - {@link readDocsPublications} carries a one-time, idempotent migration
21
+ * shim: when the store table is empty and the legacy
22
+ * `.cleo/docs-publications.json` still holds entries, they are seeded
23
+ * into the table on first access. The shim is marked for follow-up in
24
+ * T13362: once the JSON shim has shipped one release, drop the seed path.
25
+ *
26
+ * @module
27
+ * @task T13362
28
+ * @epic T13340
29
+ * @saga T13339
30
+ */
31
+ import type { DocsPublicationRecord } from './docs-ops.js';
32
+ /**
33
+ * Record (or refresh) one publication in the store ledger.
34
+ *
35
+ * Upserts on (ownerId, blobName, publishedPath). A conflicting row gets the
36
+ * fresh `lastBlobSha`/`publishedAt` so the ledger always reflects the latest
37
+ * known good publication; the row uid is the natural identity over the triple,
38
+ * so a concurrent publish on another device coalesces onto the same row.
39
+ *
40
+ * @param projectRoot - Absolute path to the CLEO project root.
41
+ * @param record - The publication facts; `publishedAt` is stamped here.
42
+ */
43
+ export declare function upsertDocsPublication(projectRoot: string, record: Omit<DocsPublicationRecord, 'publishedAt'>): Promise<void>;
44
+ /**
45
+ * Read every publication row from the store ledger.
46
+ *
47
+ * Legacy shim (T13362 follow-up: remove one release after ship): when the
48
+ * table is empty and `.cleo/docs-publications.json` still holds entries, the
49
+ * entries are seeded idempotently (natural-key insert, `ON CONFLICT DO
50
+ * NOTHING`) and a `.seeded` marker is written so the seed runs once. When the
51
+ * table already holds rows they are authoritative and the JSON is ignored.
52
+ *
53
+ * @param projectRoot - Absolute path to the CLEO project root.
54
+ * @returns All recorded publications (empty when none exist).
55
+ */
56
+ export declare function readDocsPublications(projectRoot: string): Promise<DocsPublicationRecord[]>;
57
+ /**
58
+ * Read the set of blob SHA-256 hashes named by any publication row.
59
+ *
60
+ * Used by the attachment janitor so a published blob is never declared
61
+ * unreferenced (and GC'd) while its publication lives.
62
+ *
63
+ * @param projectRoot - Absolute path to the CLEO project root.
64
+ * @returns Distinct `last_blob_sha` values across all publications.
65
+ */
66
+ export declare function readDocsPublicationSha256Set(projectRoot: string): Promise<Set<string>>;
67
+ //# sourceMappingURL=publications-store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publications-store.d.ts","sourceRoot":"","sources":["../../src/docs/publications-store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAOH,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAC;AAgF3D;;;;;;;;;;GAUG;AACH,wBAAsB,qBAAqB,CACzC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,IAAI,CAAC,qBAAqB,EAAE,aAAa,CAAC,GACjD,OAAO,CAAC,IAAI,CAAC,CAef;AAED;;;;;;;;;;;GAWG;AACH,wBAAsB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,qBAAqB,EAAE,CAAC,CA0ChG;AAED;;;;;;;;GAQG;AACH,wBAAsB,4BAA4B,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAO5F"}