@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.
- package/dist/build-provenance.json +2 -2
- package/dist/cloud/nexus-auth.d.ts.map +1 -1
- package/dist/cloud/nexus-auth.js +11 -2
- package/dist/cloud/nexus-auth.js.map +1 -1
- package/dist/cloud/nexus-cloud-status.d.ts.map +1 -1
- package/dist/cloud/nexus-cloud-status.js +18 -5
- package/dist/cloud/nexus-cloud-status.js.map +1 -1
- package/dist/cloud/nexus-credentials.d.ts +3 -2
- package/dist/cloud/nexus-credentials.d.ts.map +1 -1
- package/dist/cloud/nexus-credentials.js +58 -14
- package/dist/cloud/nexus-credentials.js.map +1 -1
- package/dist/cloud/nexus-logout.d.ts.map +1 -1
- package/dist/cloud/nexus-logout.js +12 -2
- package/dist/cloud/nexus-logout.js.map +1 -1
- package/dist/cloud/nexus-vault-state.d.ts.map +1 -1
- package/dist/cloud/nexus-vault-state.js +6 -26
- package/dist/cloud/nexus-vault-state.js.map +1 -1
- package/dist/config/registry.d.ts +21 -0
- package/dist/config/registry.d.ts.map +1 -1
- package/dist/config/registry.js +41 -0
- package/dist/config/registry.js.map +1 -1
- package/dist/dispatch/mvi-projection.d.ts.map +1 -1
- package/dist/dispatch/mvi-projection.js +2 -0
- package/dist/dispatch/mvi-projection.js.map +1 -1
- package/dist/docs/docs-ops.d.ts +15 -14
- package/dist/docs/docs-ops.d.ts.map +1 -1
- package/dist/docs/docs-ops.js +32 -96
- package/dist/docs/docs-ops.js.map +1 -1
- package/dist/docs/docs-read-model.d.ts +19 -10
- package/dist/docs/docs-read-model.d.ts.map +1 -1
- package/dist/docs/docs-read-model.js +31 -47
- package/dist/docs/docs-read-model.js.map +1 -1
- package/dist/docs/docs-update.d.ts +51 -1
- package/dist/docs/docs-update.d.ts.map +1 -1
- package/dist/docs/docs-update.js +235 -13
- package/dist/docs/docs-update.js.map +1 -1
- package/dist/docs/doctor.d.ts +26 -4
- package/dist/docs/doctor.d.ts.map +1 -1
- package/dist/docs/doctor.js +260 -102
- package/dist/docs/doctor.js.map +1 -1
- package/dist/docs/fetch-result.d.ts +30 -10
- package/dist/docs/fetch-result.d.ts.map +1 -1
- package/dist/docs/fetch-result.js +100 -15
- package/dist/docs/fetch-result.js.map +1 -1
- package/dist/docs/index.d.ts +1 -0
- package/dist/docs/index.d.ts.map +1 -1
- package/dist/docs/index.js +1 -0
- package/dist/docs/index.js.map +1 -1
- package/dist/docs/legacy-doc-migration.d.ts +182 -0
- package/dist/docs/legacy-doc-migration.d.ts.map +1 -0
- package/dist/docs/legacy-doc-migration.js +480 -0
- package/dist/docs/legacy-doc-migration.js.map +1 -0
- package/dist/docs/publications-store.d.ts +67 -0
- package/dist/docs/publications-store.d.ts.map +1 -0
- package/dist/docs/publications-store.js +193 -0
- package/dist/docs/publications-store.js.map +1 -0
- package/dist/docs/publish-pr.d.ts.map +1 -1
- package/dist/docs/publish-pr.js +31 -18
- package/dist/docs/publish-pr.js.map +1 -1
- package/dist/docs/section-leases.d.ts +233 -0
- package/dist/docs/section-leases.d.ts.map +1 -0
- package/dist/docs/section-leases.js +344 -0
- package/dist/docs/section-leases.js.map +1 -0
- package/dist/docs/section-merge.d.ts +159 -0
- package/dist/docs/section-merge.d.ts.map +1 -0
- package/dist/docs/section-merge.js +215 -0
- package/dist/docs/section-merge.js.map +1 -0
- package/dist/docs/section-write-path.d.ts +191 -0
- package/dist/docs/section-write-path.d.ts.map +1 -0
- package/dist/docs/section-write-path.js +423 -0
- package/dist/docs/section-write-path.js.map +1 -0
- package/dist/docs/stats.d.ts +56 -0
- package/dist/docs/stats.d.ts.map +1 -0
- package/dist/docs/stats.js +119 -0
- package/dist/docs/stats.js.map +1 -0
- package/dist/gc/cleanup.d.ts +1 -1
- package/dist/gc/cleanup.d.ts.map +1 -1
- package/dist/gc/cleanup.js +10 -1
- package/dist/gc/cleanup.js.map +1 -1
- package/dist/gc/janitor.js +1 -1
- package/dist/gc/janitor.js.map +1 -1
- package/dist/internal.d.ts +1 -1
- package/dist/internal.d.ts.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.d.ts +34 -0
- package/dist/memory/pipeline-manifest-sqlite.d.ts.map +1 -1
- package/dist/memory/pipeline-manifest-sqlite.js +114 -0
- package/dist/memory/pipeline-manifest-sqlite.js.map +1 -1
- package/dist/nexus/analyze-orchestrator.d.ts +5 -1
- package/dist/nexus/analyze-orchestrator.d.ts.map +1 -1
- package/dist/nexus/analyze-orchestrator.js +25 -13
- package/dist/nexus/analyze-orchestrator.js.map +1 -1
- package/dist/nexus/assessment-store.d.ts +8 -4
- package/dist/nexus/assessment-store.d.ts.map +1 -1
- package/dist/nexus/assessment-store.js +18 -27
- package/dist/nexus/assessment-store.js.map +1 -1
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +6 -0
- package/dist/orchestration/index.js.map +1 -1
- package/dist/orchestration/lean-change.d.ts +104 -5
- package/dist/orchestration/lean-change.d.ts.map +1 -1
- package/dist/orchestration/lean-change.js +162 -6
- package/dist/orchestration/lean-change.js.map +1 -1
- package/dist/orchestration/spawn-prompt.d.ts +6 -1
- package/dist/orchestration/spawn-prompt.d.ts.map +1 -1
- package/dist/orchestration/spawn-prompt.js +3 -1
- package/dist/orchestration/spawn-prompt.js.map +1 -1
- package/dist/orchestration/spawn.d.ts.map +1 -1
- package/dist/orchestration/spawn.js +6 -0
- package/dist/orchestration/spawn.js.map +1 -1
- package/dist/release/open.d.ts.map +1 -1
- package/dist/release/open.js +6 -2
- package/dist/release/open.js.map +1 -1
- package/dist/release/plan.d.ts.map +1 -1
- package/dist/release/plan.js +33 -2
- package/dist/release/plan.js.map +1 -1
- package/dist/resources/admission-ledger.d.ts +5 -0
- package/dist/resources/admission-ledger.d.ts.map +1 -1
- package/dist/resources/admission-ledger.js +1 -1
- package/dist/resources/admission-ledger.js.map +1 -1
- package/dist/resources/run-admission.d.ts.map +1 -1
- package/dist/resources/run-admission.js +4 -1
- package/dist/resources/run-admission.js.map +1 -1
- package/dist/resources/run-governed.d.ts +29 -4
- package/dist/resources/run-governed.d.ts.map +1 -1
- package/dist/resources/run-governed.js +113 -73
- package/dist/resources/run-governed.js.map +1 -1
- package/dist/sentient/worktree-dispatch.d.ts +12 -1
- package/dist/sentient/worktree-dispatch.d.ts.map +1 -1
- package/dist/sentient/worktree-dispatch.js +19 -0
- package/dist/sentient/worktree-dispatch.js.map +1 -1
- package/dist/spawn/branch-lock.d.ts +11 -1
- package/dist/spawn/branch-lock.d.ts.map +1 -1
- package/dist/spawn/branch-lock.js +54 -4
- package/dist/spawn/branch-lock.js.map +1 -1
- package/dist/sticky/archive.d.ts +1 -0
- package/dist/sticky/archive.d.ts.map +1 -1
- package/dist/sticky/archive.js +13 -0
- package/dist/sticky/archive.js.map +1 -1
- package/dist/sticky/engine-ops.d.ts.map +1 -1
- package/dist/sticky/engine-ops.js +7 -0
- package/dist/sticky/engine-ops.js.map +1 -1
- package/dist/store/attachment-repair.d.ts +10 -4
- package/dist/store/attachment-repair.d.ts.map +1 -1
- package/dist/store/attachment-repair.js +52 -25
- package/dist/store/attachment-repair.js.map +1 -1
- package/dist/store/attachment-store.d.ts.map +1 -1
- package/dist/store/attachment-store.js +27 -18
- package/dist/store/attachment-store.js.map +1 -1
- package/dist/store/blob-keep.d.ts +83 -0
- package/dist/store/blob-keep.d.ts.map +1 -1
- package/dist/store/blob-keep.js +139 -0
- package/dist/store/blob-keep.js.map +1 -1
- package/dist/store/blob-ops.d.ts +24 -0
- package/dist/store/blob-ops.d.ts.map +1 -1
- package/dist/store/blob-ops.js +47 -0
- package/dist/store/blob-ops.js.map +1 -1
- package/dist/store/conduit-doc-history.d.ts +209 -0
- package/dist/store/conduit-doc-history.d.ts.map +1 -1
- package/dist/store/conduit-doc-history.js +315 -3
- package/dist/store/conduit-doc-history.js.map +1 -1
- package/dist/store/decision-adr-links.d.ts +11 -0
- package/dist/store/decision-adr-links.d.ts.map +1 -1
- package/dist/store/decision-adr-links.js +20 -1
- package/dist/store/decision-adr-links.js.map +1 -1
- package/dist/store/display-id-alias.d.ts +8 -2
- package/dist/store/display-id-alias.d.ts.map +1 -1
- package/dist/store/display-id-alias.js +8 -3
- package/dist/store/display-id-alias.js.map +1 -1
- package/dist/store/lock.d.ts +18 -0
- package/dist/store/lock.d.ts.map +1 -1
- package/dist/store/lock.js +41 -0
- package/dist/store/lock.js.map +1 -1
- package/dist/store/row-identity-registry.d.ts.map +1 -1
- package/dist/store/row-identity-registry.js +17 -0
- package/dist/store/row-identity-registry.js.map +1 -1
- package/dist/store/schema/cleo-project/conduit.d.ts +16 -0
- package/dist/store/schema/cleo-project/conduit.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/conduit.js +8 -0
- package/dist/store/schema/cleo-project/conduit.js.map +1 -1
- package/dist/store/schema/cleo-project/docs.d.ts +294 -0
- package/dist/store/schema/cleo-project/docs.d.ts.map +1 -1
- package/dist/store/schema/cleo-project/docs.js +82 -0
- package/dist/store/schema/cleo-project/docs.js.map +1 -1
- package/dist/store/sync/hlc.d.ts +9 -0
- package/dist/store/sync/hlc.d.ts.map +1 -1
- package/dist/store/sync/hlc.js +9 -0
- package/dist/store/sync/hlc.js.map +1 -1
- package/dist/store/sync/merge/engine.d.ts.map +1 -1
- package/dist/store/sync/merge/engine.js +4 -2
- package/dist/store/sync/merge/engine.js.map +1 -1
- package/dist/store/sync/merge/rules.d.ts +12 -1
- package/dist/store/sync/merge/rules.d.ts.map +1 -1
- package/dist/store/sync/merge/rules.js +76 -1
- package/dist/store/sync/merge/rules.js.map +1 -1
- package/dist/store/sync/replica-registry.d.ts +6 -2
- package/dist/store/sync/replica-registry.d.ts.map +1 -1
- package/dist/store/sync/replica-registry.js +21 -9
- package/dist/store/sync/replica-registry.js.map +1 -1
- package/dist/store/sync/timestamp-canon.d.ts.map +1 -1
- package/dist/store/sync/timestamp-canon.js +6 -0
- package/dist/store/sync/timestamp-canon.js.map +1 -1
- package/dist/store/table-classification.d.ts +58 -0
- package/dist/store/table-classification.d.ts.map +1 -1
- package/dist/store/table-classification.js +72 -0
- package/dist/store/table-classification.js.map +1 -1
- package/dist/store/twin-collapse.d.ts.map +1 -1
- package/dist/store/twin-collapse.js +4 -1
- package/dist/store/twin-collapse.js.map +1 -1
- package/dist/store/vault-manifest.d.ts +10 -1
- package/dist/store/vault-manifest.d.ts.map +1 -1
- package/dist/store/vault-manifest.js +59 -1
- package/dist/store/vault-manifest.js.map +1 -1
- package/dist/tasks/affected-scope.d.ts +11 -0
- package/dist/tasks/affected-scope.d.ts.map +1 -1
- package/dist/tasks/affected-scope.js +30 -11
- package/dist/tasks/affected-scope.js.map +1 -1
- package/dist/tasks/cancel-ops.d.ts.map +1 -1
- package/dist/tasks/cancel-ops.js +7 -2
- package/dist/tasks/cancel-ops.js.map +1 -1
- package/dist/tasks/change-set.d.ts +22 -0
- package/dist/tasks/change-set.d.ts.map +1 -1
- package/dist/tasks/change-set.js +119 -2
- package/dist/tasks/change-set.js.map +1 -1
- package/dist/tasks/complete.d.ts.map +1 -1
- package/dist/tasks/complete.js +7 -0
- package/dist/tasks/complete.js.map +1 -1
- package/dist/tasks/done-plan.d.ts +5 -0
- package/dist/tasks/done-plan.d.ts.map +1 -1
- package/dist/tasks/done-plan.js +54 -19
- package/dist/tasks/done-plan.js.map +1 -1
- package/dist/tasks/engine-wrap.d.ts +4 -0
- package/dist/tasks/engine-wrap.d.ts.map +1 -1
- package/dist/tasks/engine-wrap.js +20 -4
- package/dist/tasks/engine-wrap.js.map +1 -1
- package/dist/tasks/evidence-paths.d.ts +11 -0
- package/dist/tasks/evidence-paths.d.ts.map +1 -1
- package/dist/tasks/evidence-paths.js +12 -0
- package/dist/tasks/evidence-paths.js.map +1 -1
- package/dist/tools/fs.d.ts +7 -3
- package/dist/tools/fs.d.ts.map +1 -1
- package/dist/tools/fs.js +23 -8
- package/dist/tools/fs.js.map +1 -1
- package/dist/worktree/list.d.ts.map +1 -1
- package/dist/worktree/list.js +9 -0
- package/dist/worktree/list.js.map +1 -1
- package/dist/worktree/prune.d.ts.map +1 -1
- package/dist/worktree/prune.js +52 -1
- package/dist/worktree/prune.js.map +1 -1
- package/migrations/drizzle-cleo-project/20261013000000_t13360-migrated-doc-import/migration.sql +61 -0
- package/migrations/drizzle-cleo-project/20261014000000_t13362-docs-publications-ledger/migration.sql +45 -0
- package/package.json +13 -13
- package/templates/CLEO-INJECTION.md +1 -1
- 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"}
|