@cleocode/core 2026.6.3 → 2026.6.5
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/docs/export-document.js +626 -310
- package/dist/docs/export-document.js.map +3 -3
- package/dist/llm/catalog-cache.d.ts +3 -0
- package/dist/llm/catalog-cache.d.ts.map +1 -1
- package/dist/llm/catalog-cache.js.map +1 -1
- package/dist/llm/catalog-model-resolver.d.ts +89 -0
- package/dist/llm/catalog-model-resolver.d.ts.map +1 -0
- package/dist/llm/catalog-model-resolver.js +158 -0
- package/dist/llm/catalog-model-resolver.js.map +1 -0
- package/dist/llm/cli-ops.d.ts +14 -0
- package/dist/llm/cli-ops.d.ts.map +1 -1
- package/dist/llm/cli-ops.js +35 -0
- package/dist/llm/cli-ops.js.map +1 -1
- package/dist/llm/index.d.ts +3 -0
- package/dist/llm/index.d.ts.map +1 -1
- package/dist/llm/index.js +3 -0
- package/dist/llm/index.js.map +1 -1
- package/dist/llm/oauth/pkce.js +27 -5
- package/dist/llm/oauth/pkce.js.map +1 -1
- package/dist/llm/plugin-facade.js +613 -325
- package/dist/llm/plugin-facade.js.map +3 -3
- package/dist/llm/provider-registry/builtin/openai.d.ts +11 -2
- package/dist/llm/provider-registry/builtin/openai.d.ts.map +1 -1
- package/dist/llm/provider-registry/builtin/openai.js +15 -3
- package/dist/llm/provider-registry/builtin/openai.js.map +1 -1
- package/dist/llm/system-resolver.d.ts +94 -0
- package/dist/llm/system-resolver.d.ts.map +1 -0
- package/dist/llm/system-resolver.js +165 -0
- package/dist/llm/system-resolver.js.map +1 -0
- package/dist/memory/dialectic-evaluator.d.ts +13 -6
- package/dist/memory/dialectic-evaluator.d.ts.map +1 -1
- package/dist/memory/dialectic-evaluator.js +18 -7
- package/dist/memory/dialectic-evaluator.js.map +1 -1
- package/dist/memory/llm-backend-resolver.d.ts +23 -3
- package/dist/memory/llm-backend-resolver.d.ts.map +1 -1
- package/dist/memory/llm-backend-resolver.js +135 -0
- package/dist/memory/llm-backend-resolver.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts +20 -2
- package/dist/store/dual-scope-db.d.ts.map +1 -1
- package/dist/store/dual-scope-db.js +74 -7
- package/dist/store/dual-scope-db.js.map +1 -1
- package/dist/store/exodus/archive.d.ts +216 -0
- package/dist/store/exodus/archive.d.ts.map +1 -0
- package/dist/store/exodus/archive.js +314 -0
- package/dist/store/exodus/archive.js.map +1 -0
- package/dist/store/exodus/index.d.ts +1 -0
- package/dist/store/exodus/index.d.ts.map +1 -1
- package/dist/store/exodus/index.js +1 -0
- package/dist/store/exodus/index.js.map +1 -1
- package/dist/store/exodus/migrate.d.ts.map +1 -1
- package/dist/store/exodus/migrate.js +118 -24
- package/dist/store/exodus/migrate.js.map +1 -1
- package/dist/store/exodus/on-open.d.ts.map +1 -1
- package/dist/store/exodus/on-open.js +95 -34
- package/dist/store/exodus/on-open.js.map +1 -1
- package/dist/store/exodus/types.d.ts +10 -1
- package/dist/store/exodus/types.d.ts.map +1 -1
- package/dist/store/exodus/types.js.map +1 -1
- package/dist/store/exodus/verify-migration.d.ts.map +1 -1
- package/dist/store/exodus/verify-migration.js +12 -1
- package/dist/store/exodus/verify-migration.js.map +1 -1
- package/dist/store/sqlite.d.ts +16 -0
- package/dist/store/sqlite.d.ts.map +1 -1
- package/dist/store/sqlite.js +160 -39
- package/dist/store/sqlite.js.map +1 -1
- package/dist/validation/doctor/checks.d.ts +22 -0
- package/dist/validation/doctor/checks.d.ts.map +1 -1
- package/dist/validation/doctor/checks.js +67 -0
- package/dist/validation/doctor/checks.js.map +1 -1
- package/dist/validation/doctor/index.d.ts +1 -1
- package/dist/validation/doctor/index.d.ts.map +1 -1
- package/dist/validation/doctor/index.js +1 -1
- package/dist/validation/doctor/index.js.map +1 -1
- package/package.json +12 -12
|
@@ -6,13 +6,27 @@
|
|
|
6
6
|
* escalating to the cloud (Claude Sonnet). Cold-tier uses Claude Sonnet
|
|
7
7
|
* exclusively (owner-mandated, NOT Haiku).
|
|
8
8
|
*
|
|
9
|
+
* ## Unified resolver convergence (T11757)
|
|
10
|
+
*
|
|
11
|
+
* Before walking the legacy fallback chain, `resolveLlmBackend` FIRST consults
|
|
12
|
+
* the unified role/profile resolver (`resolveLLMForRole('extraction')` in
|
|
13
|
+
* `../llm/role-resolver.ts`). This honours a pinned `extraction`-role profile —
|
|
14
|
+
* e.g. an openai-compatible provider (`openai`/`ollama`, optionally with a
|
|
15
|
+
* `baseUrl` override) or `anthropic` — so the sentient loop uses the SAME
|
|
16
|
+
* provider/credential machinery as the rest of CLEO. When the unified resolver
|
|
17
|
+
* yields nothing usable (no pinned profile, no credential, or a client that
|
|
18
|
+
* cannot be constructed), the call falls through to the legacy warm/cold chain
|
|
19
|
+
* below — no behavioural regression for unconfigured installs.
|
|
20
|
+
*
|
|
9
21
|
* Fallback chain (warm):
|
|
22
|
+
* 0. Unified resolver (`extraction` role profile) — anthropic OR openai-compatible
|
|
10
23
|
* 1. Ollama daemon running at localhost:11434 (gemma4:e4b-it or fallback model)
|
|
11
24
|
* 2. @huggingface/transformers (already installed; ONNX pipeline, zero extra deps)
|
|
12
25
|
* 3. Claude Sonnet via Anthropic API (cold escalation)
|
|
13
26
|
* 4. null — no backend; caller must skip extraction
|
|
14
27
|
*
|
|
15
28
|
* Fallback chain (cold):
|
|
29
|
+
* 0. Unified resolver (`extraction` role profile)
|
|
16
30
|
* 1. Claude Sonnet via Anthropic API (ANTHROPIC_API_KEY required)
|
|
17
31
|
* 2. null — no API key; caller must skip extraction
|
|
18
32
|
*
|
|
@@ -22,6 +36,7 @@
|
|
|
22
36
|
* Spec reference: `docs/specs/memory-architecture-spec.md` §7
|
|
23
37
|
*
|
|
24
38
|
* @task T730
|
|
39
|
+
* @task T11757
|
|
25
40
|
* @epic T726
|
|
26
41
|
*/
|
|
27
42
|
/**
|
|
@@ -71,6 +86,15 @@ const TRANSFORMERS_FALLBACK_MODEL = 'onnx-community/Qwen2.5-0.5B-Instruct';
|
|
|
71
86
|
* ```
|
|
72
87
|
*/
|
|
73
88
|
export async function resolveLlmBackend(tier) {
|
|
89
|
+
// 0. Unified convergence (T11757): honour a pinned `extraction`-role profile
|
|
90
|
+
// from the unified role/profile resolver before any legacy chain. This is
|
|
91
|
+
// what makes the sentient loop use the SAME provider/credential machinery
|
|
92
|
+
// as every other LLM call-site (so a pinned codex/openai/ollama/anthropic
|
|
93
|
+
// profile is reachable). Returns null when nothing usable is configured —
|
|
94
|
+
// then we fall through to the legacy warm/cold chain below.
|
|
95
|
+
const unifiedBackend = await tryUnifiedResolver();
|
|
96
|
+
if (unifiedBackend)
|
|
97
|
+
return unifiedBackend;
|
|
74
98
|
if (tier === 'warm') {
|
|
75
99
|
// 1. Try Ollama (best local quality, GPU-accelerated if available)
|
|
76
100
|
const ollamaBackend = await tryOllama();
|
|
@@ -220,4 +244,115 @@ async function tryAnthropic(modelId) {
|
|
|
220
244
|
return null;
|
|
221
245
|
}
|
|
222
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Default OpenAI-compatible base URL for the local Ollama daemon (T11757).
|
|
249
|
+
*
|
|
250
|
+
* Ollama exposes an OpenAI-compatible surface under `/v1`. The provider-registry
|
|
251
|
+
* profile records the bare host (`http://localhost:11434`); the unified backend
|
|
252
|
+
* path appends `/v1` so `createOpenAICompatible` can speak the OpenAI wire shape.
|
|
253
|
+
*/
|
|
254
|
+
const OLLAMA_OPENAI_COMPAT_BASE_URL = 'http://localhost:11434/v1';
|
|
255
|
+
/**
|
|
256
|
+
* Resolve the OpenAI-compatible base URL for a provider resolved by the unified
|
|
257
|
+
* role/profile resolver.
|
|
258
|
+
*
|
|
259
|
+
* Looks up the provider-registry profile (which carries the canonical `baseUrl`)
|
|
260
|
+
* and normalises it for the OpenAI-compatible client. For `ollama` we guarantee
|
|
261
|
+
* the `/v1` shim suffix; other openai-family providers use their registered
|
|
262
|
+
* base URL verbatim (already a `/v1`-style endpoint) and fall back to the OpenAI
|
|
263
|
+
* default when no profile is registered.
|
|
264
|
+
*
|
|
265
|
+
* @param provider - The provider id resolved by the unified resolver.
|
|
266
|
+
* @returns A base URL suitable for `createOpenAICompatible`, or `undefined`
|
|
267
|
+
* when none can be determined (caller skips the openai-compatible path).
|
|
268
|
+
*/
|
|
269
|
+
async function resolveOpenAiCompatibleBaseUrl(provider) {
|
|
270
|
+
if (provider === 'ollama') {
|
|
271
|
+
return OLLAMA_OPENAI_COMPAT_BASE_URL;
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
const { getProviderProfile } = await import('../llm/provider-registry/index.js');
|
|
275
|
+
const profile = await getProviderProfile(provider);
|
|
276
|
+
if (profile?.baseUrl) {
|
|
277
|
+
return profile.baseUrl;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
catch {
|
|
281
|
+
// Registry lookup failed — fall through to the openai default below.
|
|
282
|
+
}
|
|
283
|
+
if (provider === 'openai') {
|
|
284
|
+
return 'https://api.openai.com/v1';
|
|
285
|
+
}
|
|
286
|
+
return undefined;
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Attempt to resolve an extraction backend via the unified role/profile resolver
|
|
290
|
+
* (`resolveLLMForRole('extraction')`) — the T11757 convergence point.
|
|
291
|
+
*
|
|
292
|
+
* This is consulted BEFORE the legacy warm/cold chain so a pinned `extraction`
|
|
293
|
+
* profile (or the unscoped default) drives the sentient loop with the same
|
|
294
|
+
* provider/credential machinery as every other CLEO LLM call-site:
|
|
295
|
+
*
|
|
296
|
+
* - `anthropic` provider → build via `createAnthropic` (returns `name: 'anthropic'`).
|
|
297
|
+
* - `openai` / `ollama` (openai-compatible) → build via `createOpenAICompatible`
|
|
298
|
+
* against the resolved base URL (returns `name: 'ollama'` for ollama, else
|
|
299
|
+
* `name: 'openai'`). An openai-family client whose key later 401s simply
|
|
300
|
+
* fails the downstream `generateObject` call and the caller degrades — it is
|
|
301
|
+
* NOT this resolver's job to validate the credential live.
|
|
302
|
+
*
|
|
303
|
+
* Returns `null` (so the caller falls through to the legacy chain) when:
|
|
304
|
+
* - the resolver throws or yields no usable provider, OR
|
|
305
|
+
* - no credential is reachable for the resolved provider, OR
|
|
306
|
+
* - the provider is not one we can wire here (e.g. a transport-only provider).
|
|
307
|
+
*
|
|
308
|
+
* NOTE: codex's ChatGPT-backend transport is intentionally NOT handled here
|
|
309
|
+
* (tracked separately as T11767). A codex/openai profile resolves through the
|
|
310
|
+
* openai-compatible path; if its client cannot authenticate it falls through to
|
|
311
|
+
* the warm chain rather than crashing.
|
|
312
|
+
*
|
|
313
|
+
* @task T11757
|
|
314
|
+
*/
|
|
315
|
+
async function tryUnifiedResolver() {
|
|
316
|
+
try {
|
|
317
|
+
const { resolveLLMForRole } = await import('../llm/role-resolver.js');
|
|
318
|
+
const resolved = await resolveLLMForRole('extraction');
|
|
319
|
+
// No credential reachable → let the legacy chain try local backends.
|
|
320
|
+
const apiKey = resolved.credential?.apiKey ?? null;
|
|
321
|
+
if (resolved.provider === 'anthropic') {
|
|
322
|
+
if (!apiKey)
|
|
323
|
+
return null;
|
|
324
|
+
const { createAnthropic } = await import('@ai-sdk/anthropic');
|
|
325
|
+
const anthropicProvider = createAnthropic({ apiKey });
|
|
326
|
+
return {
|
|
327
|
+
model: anthropicProvider(resolved.model),
|
|
328
|
+
name: 'anthropic',
|
|
329
|
+
modelId: resolved.model,
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
if (resolved.provider === 'openai' || resolved.provider === 'ollama') {
|
|
333
|
+
const baseURL = await resolveOpenAiCompatibleBaseUrl(resolved.provider);
|
|
334
|
+
if (!baseURL)
|
|
335
|
+
return null;
|
|
336
|
+
// Local Ollama needs no key; remote openai-compatible servers do. Use an
|
|
337
|
+
// empty placeholder when none is configured so the local path still works
|
|
338
|
+
// (mirrors tryOllama, which sends no Authorization for localhost).
|
|
339
|
+
const { createOpenAICompatible } = await import('@ai-sdk/openai-compatible');
|
|
340
|
+
const provider = createOpenAICompatible({
|
|
341
|
+
baseURL,
|
|
342
|
+
name: resolved.provider,
|
|
343
|
+
...(apiKey ? { apiKey } : {}),
|
|
344
|
+
});
|
|
345
|
+
return {
|
|
346
|
+
model: provider(resolved.model),
|
|
347
|
+
name: resolved.provider === 'ollama' ? 'ollama' : 'openai',
|
|
348
|
+
modelId: resolved.model,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
// Provider not wireable here (transport-only) — fall through to legacy chain.
|
|
352
|
+
return null;
|
|
353
|
+
}
|
|
354
|
+
catch {
|
|
355
|
+
return null;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
223
358
|
//# sourceMappingURL=llm-backend-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm-backend-resolver.js","sourceRoot":"","sources":["../../src/memory/llm-backend-resolver.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"llm-backend-resolver.js","sourceRoot":"","sources":["../../src/memory/llm-backend-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -83,6 +83,24 @@ export interface DualScopeDbHandle<TScope extends DualScope = DualScope> {
|
|
|
83
83
|
*/
|
|
84
84
|
close(): void;
|
|
85
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* Options for {@link openDualScopeDbAtPath}.
|
|
88
|
+
*
|
|
89
|
+
* @task T11782 (FIX D — dedicated migrate connection)
|
|
90
|
+
*/
|
|
91
|
+
export interface OpenDualScopeAtPathOptions {
|
|
92
|
+
/**
|
|
93
|
+
* When `true`, open a DEDICATED, NON-cached connection — a second SQLite
|
|
94
|
+
* handle to the same file, independent of the singleton `_cache`. Used by the
|
|
95
|
+
* exodus migrate engine so its copy + rollback transactions are isolated from
|
|
96
|
+
* the caller's cached handle (and any concurrent task INSERTs sharing it). The
|
|
97
|
+
* returned handle's `close()` closes only the native connection and never
|
|
98
|
+
* mutates the cache; the caller MUST close it to avoid a descriptor leak.
|
|
99
|
+
*
|
|
100
|
+
* @default false
|
|
101
|
+
*/
|
|
102
|
+
readonly dedicated?: boolean;
|
|
103
|
+
}
|
|
86
104
|
/**
|
|
87
105
|
* Resolve the absolute path to the dual-scope `cleo.db` for the given scope.
|
|
88
106
|
*
|
|
@@ -140,8 +158,8 @@ export declare function openDualScopeDb(scope: 'global', cwd?: string): Promise<
|
|
|
140
158
|
* @epic T11249 (E6)
|
|
141
159
|
* @saga T11242
|
|
142
160
|
*/
|
|
143
|
-
export declare function openDualScopeDbAtPath(scope: 'project', dbPath: string, exodusCwd?: string): Promise<DualScopeDbHandle<'project'>>;
|
|
144
|
-
export declare function openDualScopeDbAtPath(scope: 'global', dbPath: string, exodusCwd?: string): Promise<DualScopeDbHandle<'global'>>;
|
|
161
|
+
export declare function openDualScopeDbAtPath(scope: 'project', dbPath: string, exodusCwd?: string, options?: OpenDualScopeAtPathOptions): Promise<DualScopeDbHandle<'project'>>;
|
|
162
|
+
export declare function openDualScopeDbAtPath(scope: 'global', dbPath: string, exodusCwd?: string, options?: OpenDualScopeAtPathOptions): Promise<DualScopeDbHandle<'global'>>;
|
|
145
163
|
/**
|
|
146
164
|
* Reset cached dual-scope handles. Primarily for use in tests between test
|
|
147
165
|
* cases and by domain `closeDb()`/`resetDbState()` paths. Closes the targeted
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dual-scope-db.d.ts","sourceRoot":"","sources":["../../src/store/dual-scope-db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAKlE,OAAO,KAAK,KAAK,qBAAqB,MAAM,+BAA+B,CAAC;AAC5E,OAAO,KAAK,KAAK,sBAAsB,MAAM,gCAAgC,CAAC;AAK9E;;;;;GAKG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7C,4DAA4D;AAC5D,MAAM,MAAM,aAAa,GAAG,kBAAkB,CAAC,OAAO,sBAAsB,CAAC,CAAC;AAE9E,2DAA2D;AAC3D,MAAM,MAAM,YAAY,GAAG,kBAAkB,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAE5E;;;;;;GAMG;AACH,MAAM,WAAW,iBAAiB,CAAC,MAAM,SAAS,SAAS,GAAG,SAAS;IACrE,gFAAgF;IAChF,QAAQ,CAAC,EAAE,EAAE,MAAM,SAAS,SAAS,GAAG,aAAa,GAAG,YAAY,CAAC;IACrE,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,mDAAmD;IACnD,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB;;;OAGG;IACH,KAAK,IAAI,IAAI,CAAC;CACf;AAyBD;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAK7E;AAsFD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,SAAS,EAChB,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC,CAAC;AACzC,wBAAsB,eAAe,CACnC,KAAK,EAAE,QAAQ,EACf,GAAG,CAAC,EAAE,MAAM,GACX,OAAO,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"dual-scope-db.d.ts","sourceRoot":"","sources":["../../src/store/dual-scope-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -149,6 +149,58 @@ export async function openDualScopeDb(scope, cwd) {
|
|
|
149
149
|
? openDualScopeDbAtPath('project', dbPath, cwd)
|
|
150
150
|
: openDualScopeDbAtPath('global', dbPath, cwd);
|
|
151
151
|
}
|
|
152
|
+
/**
|
|
153
|
+
* Open a DEDICATED, NON-cached consolidated dual-scope `cleo.db` connection
|
|
154
|
+
* (T11782 · FIX D).
|
|
155
|
+
*
|
|
156
|
+
* This opens a fresh `DatabaseSync` to `dbPath`, applies the canonical pragmas,
|
|
157
|
+
* wraps it in Drizzle, reconciles + runs migrations, and returns a handle whose
|
|
158
|
+
* `close()` ONLY closes the native connection — it never reads or mutates the
|
|
159
|
+
* singleton `_cache`. WAL mode permits this second connection to coexist with
|
|
160
|
+
* the cached caller handle on the same file. The exodus migrate engine uses this
|
|
161
|
+
* so its bulk-copy + parity-abort rollback transactions are physically isolated
|
|
162
|
+
* from the caller's connection (and any concurrent task INSERTs sharing it).
|
|
163
|
+
*
|
|
164
|
+
* @param scope - The consolidated schema scope.
|
|
165
|
+
* @param dbPath - Absolute path to the consolidated `cleo.db` file.
|
|
166
|
+
* @param log - The module logger.
|
|
167
|
+
* @returns A typed {@link DualScopeDbHandle} backed by a dedicated connection.
|
|
168
|
+
*
|
|
169
|
+
* @task T11782 (FIX D — rollback connection isolation)
|
|
170
|
+
*/
|
|
171
|
+
async function openDedicatedDualScopeDb(scope, dbPath, log) {
|
|
172
|
+
log.debug({ scope, dbPath }, 'opening DEDICATED (non-cached) dual-scope cleo.db (T11782 FIX D)');
|
|
173
|
+
// Ensure the directory exists before opening.
|
|
174
|
+
const dir = dirname(dbPath);
|
|
175
|
+
if (!existsSync(dir)) {
|
|
176
|
+
mkdirSync(dir, { recursive: true });
|
|
177
|
+
}
|
|
178
|
+
const DatabaseSyncCtor = getDatabaseSyncCtor();
|
|
179
|
+
const nativeDb = new DatabaseSyncCtor(dbPath, { allowExtension: true });
|
|
180
|
+
applyPerfPragmas(nativeDb);
|
|
181
|
+
const schema = scope === 'project' ? await loadProjectSchema() : await loadGlobalSchema();
|
|
182
|
+
const drizzle = getDrizzle();
|
|
183
|
+
// biome-ignore lint/suspicious/noExplicitAny: schema type is scope-specific; typed via DualScopeDbHandle<TScope>
|
|
184
|
+
const db = drizzle({ client: nativeDb, schema });
|
|
185
|
+
const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
|
|
186
|
+
reconcileJournal(nativeDb, migrationsFolder, existenceTable(scope), `dual-scope-db[${scope}]`);
|
|
187
|
+
migrateWithRetry(db, migrationsFolder, nativeDb, existenceTable(scope), `dual-scope-db[${scope}]`);
|
|
188
|
+
log.debug({ scope, dbPath }, 'DEDICATED dual-scope cleo.db ready (T11782 FIX D)');
|
|
189
|
+
return {
|
|
190
|
+
db,
|
|
191
|
+
scope,
|
|
192
|
+
dbPath,
|
|
193
|
+
close() {
|
|
194
|
+
// Dedicated handles are never cached — close only the native connection.
|
|
195
|
+
try {
|
|
196
|
+
nativeDb.close();
|
|
197
|
+
}
|
|
198
|
+
catch {
|
|
199
|
+
// Idempotent — ignore double-close errors.
|
|
200
|
+
}
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
152
204
|
export async function openDualScopeDbAtPath(scope, dbPath,
|
|
153
205
|
/**
|
|
154
206
|
* Internal: the resolved `cwd` from the canonical {@link openDualScopeDb}
|
|
@@ -157,17 +209,32 @@ export async function openDualScopeDbAtPath(scope, dbPath,
|
|
|
157
209
|
* the public explicit-path callers (tests / legacy-path domains), which must
|
|
158
210
|
* never auto-migrate an isolated fixture DB.
|
|
159
211
|
*/
|
|
160
|
-
exodusCwd) {
|
|
212
|
+
exodusCwd, options) {
|
|
213
|
+
const dedicated = options?.dedicated === true;
|
|
161
214
|
const key = cacheKey(scope, dbPath);
|
|
162
|
-
//
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
215
|
+
// A DEDICATED open (T11782 · FIX D) bypasses the singleton cache entirely: it
|
|
216
|
+
// opens a SECOND SQLite connection to the same file (WAL allows concurrent
|
|
217
|
+
// connections) so the exodus migrate engine can copy + (on abort) truncate on
|
|
218
|
+
// an ISOLATED handle. The caller's cached handle — shared by concurrent task
|
|
219
|
+
// INSERTs — is a physically distinct connection, so the migration's rollback
|
|
220
|
+
// can only ever truncate its OWN connection's transaction, never the caller's
|
|
221
|
+
// concurrent writes. The returned handle's `close()` only closes the native
|
|
222
|
+
// connection; it never touches `_cache`. Callers MUST close it after use to
|
|
223
|
+
// avoid a file-descriptor leak.
|
|
224
|
+
if (!dedicated) {
|
|
225
|
+
// Return cached handle if available and not mid-init.
|
|
226
|
+
const existing = _cache.get(key);
|
|
227
|
+
if (existing) {
|
|
228
|
+
if (existing.initPromise) {
|
|
229
|
+
return existing.initPromise;
|
|
230
|
+
}
|
|
231
|
+
return existing.handle;
|
|
167
232
|
}
|
|
168
|
-
return existing.handle;
|
|
169
233
|
}
|
|
170
234
|
const log = getLogger('dual-scope-db');
|
|
235
|
+
if (dedicated) {
|
|
236
|
+
return openDedicatedDualScopeDb(scope, dbPath, log);
|
|
237
|
+
}
|
|
171
238
|
// Create a placeholder entry so concurrent callers wait for the same init.
|
|
172
239
|
const initPromise = (async () => {
|
|
173
240
|
log.debug({ scope, dbPath }, 'opening dual-scope cleo.db');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dual-scope-db.js","sourceRoot":"","sources":["../../src/store/dual-scope-db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,EAAE,kCAAkC,EAAE,MAAM,gCAAgC,CAAC;AAGpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"dual-scope-db.js","sourceRoot":"","sources":["../../src/store/dual-scope-db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkDG;AAEH,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAG1C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC5E,OAAO,EAAE,kCAAkC,EAAE,MAAM,gCAAgC,CAAC;AAGpF,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAqEvD,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwB,CAAC;AAE/C;;;GAGG;AACH,SAAS,QAAQ,CAAC,KAAgB,EAAE,MAAc;IAChD,OAAO,GAAG,KAAK,KAAK,MAAM,EAAE,CAAC;AAC/B,CAAC;AAED,gFAAgF;AAEhF;;;;;GAKG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAgB,EAAE,GAAY;IACnE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,OAAO,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC,CAAC;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC,WAAW,EAAE,EAAE,SAAS,CAAC,CAAC;AACxC,CAAC;AAED,gFAAgF;AAEhF;;;GAGG;AACH,SAAS,iBAAiB,CAAC,KAAgB;IACzC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,qBAAqB,CAAC;AAC9E,CAAC;AAED,gFAAgF;AAEhF,6EAA6E;AAC7E,8EAA8E;AAC9E,4EAA4E;AAC5E,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAIhD,IAAI,QAAQ,GAAqB,IAAI,CAAC;AAEtC,SAAS,UAAU;IACjB,IAAI,QAAQ,KAAK,IAAI,EAAE,CAAC;QACtB,MAAM,GAAG,GAAG,QAAQ,CAAC,yBAAyB,CAA2B,CAAC;QAC1E,QAAQ,GAAG,GAAG,CAAC,OAAO,CAAC;IACzB,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAQD,IAAI,iBAAiB,GAA4B,IAAI,CAAC;AAEtD,SAAS,mBAAmB;IAC1B,IAAI,iBAAiB,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,GAAG,GAAG,QAAQ,CAAC,aAAa,CAAuC,CAAC;QAC1E,iBAAiB,GAAG,GAAG,CAAC,YAAY,CAAC;IACvC,CAAC;IACD,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,gFAAgF;AAEhF,wEAAwE;AACxE,8EAA8E;AAC9E,+CAA+C;AAE/C,IAAI,cAAc,GAAyC,IAAI,CAAC;AAChE,IAAI,aAAa,GAAwC,IAAI,CAAC;AAE9D,KAAK,UAAU,iBAAiB;IAC9B,IAAI,cAAc,KAAK,IAAI,EAAE,CAAC;QAC5B,cAAc,GAAG,MAAM,MAAM,CAAC,gCAAgC,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC;AAED,KAAK,UAAU,gBAAgB;IAC7B,IAAI,aAAa,KAAK,IAAI,EAAE,CAAC;QAC3B,aAAa,GAAG,MAAM,MAAM,CAAC,+BAA+B,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,iFAAiF;AAEjF;;;;;;;GAOG;AACH,SAAS,cAAc,CAAC,KAAgB;IACtC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,wBAAwB,CAAC;AACxE,CAAC;AAiCD,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,KAAgB,EAAE,GAAY;IAClE,MAAM,MAAM,GAAG,sBAAsB,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAClD,gFAAgF;IAChF,4EAA4E;IAC5E,uEAAuE;IACvE,0EAA0E;IAC1E,2EAA2E;IAC3E,sDAAsD;IACtD,OAAO,KAAK,KAAK,SAAS;QACxB,CAAC,CAAC,qBAAqB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,CAAC;QAC/C,CAAC,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,KAAK,UAAU,wBAAwB,CACrC,KAAgB,EAChB,MAAc,EACd,GAAiC;IAEjC,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,kEAAkE,CAAC,CAAC;IAEjG,8CAA8C;IAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,MAAM,gBAAgB,GAAG,mBAAmB,EAAE,CAAC;IAC/C,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;IAExE,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAE3B,MAAM,MAAM,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC,CAAC,MAAM,gBAAgB,EAAE,CAAC;IAC1F,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,iHAAiH;IACjH,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAA4B,CAAC;IAE5E,MAAM,gBAAgB,GAAG,kCAAkC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;IACtF,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE,iBAAiB,KAAK,GAAG,CAAC,CAAC;IAC/F,gBAAgB,CACd,EAAE,EACF,gBAAgB,EAChB,QAAQ,EACR,cAAc,CAAC,KAAK,CAAC,EACrB,iBAAiB,KAAK,GAAG,CAC1B,CAAC;IAEF,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,mDAAmD,CAAC,CAAC;IAElF,OAAO;QACL,EAAE;QACF,KAAK;QACL,MAAM;QACN,KAAK;YACH,yEAAyE;YACzE,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,EAAE,CAAC;YACnB,CAAC;YAAC,MAAM,CAAC;gBACP,2CAA2C;YAC7C,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAyCD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,KAAgB,EAChB,MAAc;AACd;;;;;;GAMG;AACH,SAAkB,EAClB,OAAoC;IAEpC,MAAM,SAAS,GAAG,OAAO,EAAE,SAAS,KAAK,IAAI,CAAC;IAC9C,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IAEpC,8EAA8E;IAC9E,2EAA2E;IAC3E,8EAA8E;IAC9E,6EAA6E;IAC7E,6EAA6E;IAC7E,8EAA8E;IAC9E,4EAA4E;IAC5E,4EAA4E;IAC5E,gCAAgC;IAChC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,sDAAsD;QACtD,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,QAAQ,EAAE,CAAC;YACb,IAAI,QAAQ,CAAC,WAAW,EAAE,CAAC;gBACzB,OAAO,QAAQ,CAAC,WAAW,CAAC;YAC9B,CAAC;YACD,OAAO,QAAQ,CAAC,MAAM,CAAC;QACzB,CAAC;IACH,CAAC;IAED,MAAM,GAAG,GAAG,SAAS,CAAC,eAAe,CAAC,CAAC;IAEvC,IAAI,SAAS,EAAE,CAAC;QACd,OAAO,wBAAwB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,CAAC;IACtD,CAAC;IAED,2EAA2E;IAC3E,MAAM,WAAW,GAA+B,CAAC,KAAK,IAAgC,EAAE;QACtF,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,4BAA4B,CAAC,CAAC;QAE3D,8CAA8C;QAC9C,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;QAC5B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACrB,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACtC,CAAC;QAED,iCAAiC;QACjC,EAAE;QACF,uEAAuE;QACvE,uEAAuE;QACvE,4EAA4E;QAC5E,0EAA0E;QAC1E,4EAA4E;QAC5E,qEAAqE;QACrE,kEAAkE;QAClE,MAAM,gBAAgB,GAAG,mBAAmB,EAAE,CAAC;QAC/C,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,MAAM,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC;QAExE,+DAA+D;QAC/D,gBAAgB,CAAC,QAAQ,CAAC,CAAC;QAE3B,yCAAyC;QACzC,MAAM,MAAM,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,iBAAiB,EAAE,CAAC,CAAC,CAAC,MAAM,gBAAgB,EAAE,CAAC;QAE1F,kCAAkC;QAClC,qFAAqF;QACrF,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;QAC7B,iHAAiH;QACjH,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,CAA4B,CAAC;QAE5E,gDAAgD;QAChD,MAAM,gBAAgB,GAAG,kCAAkC,CAAC,iBAAiB,CAAC,KAAK,CAAC,CAAC,CAAC;QAEtF,yEAAyE;QACzE,2EAA2E;QAC3E,gBAAgB,CAAC,QAAQ,EAAE,gBAAgB,EAAE,cAAc,CAAC,KAAK,CAAC,EAAE,iBAAiB,KAAK,GAAG,CAAC,CAAC;QAE/F,8BAA8B;QAC9B,gBAAgB,CACd,EAAE,EACF,gBAAgB,EAChB,QAAQ,EACR,cAAc,CAAC,KAAK,CAAC,EACrB,iBAAiB,KAAK,GAAG,CAC1B,CAAC;QAEF,GAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,0BAA0B,CAAC,CAAC;QAEzD,MAAM,MAAM,GAAsB;YAChC,EAAE;YACF,KAAK;YACL,MAAM;YACN,KAAK;gBACH,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBACnB,IAAI,CAAC;oBACH,QAAQ,CAAC,KAAK,EAAE,CAAC;gBACnB,CAAC;gBAAC,MAAM,CAAC;oBACP,2CAA2C;gBAC7C,CAAC;YACH,CAAC;SACF,CAAC;QAEF,gDAAgD;QAChD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,KAAK,EAAE,CAAC;YACV,KAAK,CAAC,WAAW,GAAG,IAAI,CAAC;YACzB,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;QACxB,CAAC;QAED,2EAA2E;QAC3E,yEAAyE;QACzE,2EAA2E;QAC3E,8EAA8E;QAC9E,0EAA0E;QAC1E,8EAA8E;QAC9E,0EAA0E;QAC1E,EAAE;QACF,4EAA4E;QAC5E,yEAAyE;QACzE,8EAA8E;QAC9E,yEAAyE;QACzE,yEAAyE;QACzE,6EAA6E;QAC7E,kDAAkD;QAClD,EAAE;QACF,iEAAiE;QACjE,4EAA4E;QAC5E,uEAAuE;QACvE,IAAI,SAAS,KAAK,SAAS,IAAI,MAAM,KAAK,sBAAsB,CAAC,KAAK,EAAE,SAAS,CAAC,EAAE,CAAC;YACnF,IAAI,CAAC;gBACH,MAAM,EAAE,oBAAoB,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;gBACrE,MAAM,MAAM,GAAG,MAAM,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,CAAC,CAAC;gBAC9E,IAAI,MAAM,CAAC,OAAO,KAAK,UAAU,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;oBAClE,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;wBACjC,GAAG,CAAC,IAAI,CACN,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,EAChC,gFAAgF,CACjF,CAAC;oBACJ,CAAC;oBACD,yEAAyE;oBACzE,0EAA0E;oBAC1E,OAAO,KAAK,KAAK,SAAS;wBACxB,CAAC,CAAC,qBAAqB,CAAC,SAAS,EAAE,MAAM,CAAC;wBAC1C,CAAC,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;gBAC9C,CAAC;YACH,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,8DAA8D;gBAC9D,wEAAwE;gBACxE,8DAA8D;gBAC9D,GAAG,CAAC,IAAI,CACN,EAAE,GAAG,EAAE,KAAK,EAAE,EACd,wEAAwE,CACzE,CAAC;gBACF,OAAO,KAAK,KAAK,SAAS;oBACxB,CAAC,CAAC,qBAAqB,CAAC,SAAS,EAAE,MAAM,CAAC;oBAC1C,CAAC,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC9C,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,EAAE,CAAC;IAEL,6EAA6E;IAC7E,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE;QACd,qFAAqF;QACrF,MAAM,EAAE,IAAW;QACnB,yEAAyE;QACzE,QAAQ,EAAE,IAAW;QACrB,WAAW;KACZ,CAAC,CAAC;IAEH,OAAO,WAAW,CAAC;AACrB,CAAC;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAiB;IACtD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QAClC,4EAA4E;QAC5E,6EAA6E;QAC7E,2CAA2C;QAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,EAAE,KAAK,KAAK,KAAK;YAAE,SAAS;QACnE,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACvB,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS;YACX,CAAC;QACH,CAAC;QACD,wEAAwE;QACxE,6DAA6D;QAC7D,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACrB,CAAC;IACD,gFAAgF;IAChF,oEAAoE;IACpE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,cAAc,GAAG,IAAI,CAAC;QACtB,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;AACH,CAAC;AAOD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;AACpC,6FAA6F;AAC7F,EAA2B,EAC3B,KAAa,EACb,GAA6B;AAC7B,6DAA6D;AAC7D,UAAkB;IAElB,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,mBAAmB,EAAE,CAAC,SAAS,EAAE,CAAC;IACpF,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB;AACpC,6FAA6F;AAC7F,EAA2B,EAC3B,KAAa,EACb,GAA6B;AAC7B,wEAAwE;AACxE,UAAkB;AAClB,oFAAoF;AACpF,cAAmB,EACnB,GAAuC;IAEvC,MAAM,SAAS,GAAG,GAAG,IAAI,GAAG,CAAC;IAC7B,MAAM,MAAM,GAAG,MAAM,EAAE;SACpB,MAAM,CAAC,KAAK,CAAC;SACb,MAAM,CAAC,GAAG,CAAC;SACX,kBAAkB,CAAC;QAClB,MAAM,EAAE,cAAc;QACtB,uGAAuG;QACvG,GAAG,EAAE,SAAgB;KACtB,CAAC;SACD,SAAS,EAAE,CAAC;IACf,OAAO,MAAM,CAAC,MAAM,CAAC;AACvB,CAAC"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Exodus source-DB ARCHIVE + completion-marker subsystem (T11777).
|
|
3
|
+
*
|
|
4
|
+
* ## Why this exists (stranded-residue corruption trigger)
|
|
5
|
+
*
|
|
6
|
+
* The exodus engine migrates from SIX legacy source DBs (project: `tasks.db`,
|
|
7
|
+
* `brain.db`, `conduit.db`; global: `nexus.db`, `signaldock.db`, `skills.db`)
|
|
8
|
+
* but, historically, NEVER retired them — `on-open.ts` literally notes "the file
|
|
9
|
+
* is never unlinked." Every cutover therefore STRANDS the legacy files, and each
|
|
10
|
+
* stranded file re-arms the `tasks_tasks=0` auto-recover / exodus-on-open
|
|
11
|
+
* corruption trigger (DHQ-052 · T11662): on the next open the consolidated DB
|
|
12
|
+
* looks empty-with-legacy-present and the hook re-fires.
|
|
13
|
+
*
|
|
14
|
+
* This module closes the loop. After a migration's lossless validation passes
|
|
15
|
+
* (row-count parity + integrity — `verifyMigration` / `isDataContinuityOk`), the
|
|
16
|
+
* consumed source DBs are ARCHIVED (moved, never deleted) into a per-scope
|
|
17
|
+
* `_archive/` directory, and a committed COMPLETION MARKER records the cutover.
|
|
18
|
+
* The marker becomes the durable "this scope is already migrated" signal so a
|
|
19
|
+
* re-appearing or stranded legacy file can never re-trigger exodus-on-open.
|
|
20
|
+
*
|
|
21
|
+
* ## Archive destinations (per scope, via the paths SSoT)
|
|
22
|
+
*
|
|
23
|
+
* - project sources → `<cleoDir>/_archive/` (e.g. `.cleo/_archive/`)
|
|
24
|
+
* - global sources → `<cleoHome>/_archive/` (e.g. `~/.local/share/cleo/_archive/`)
|
|
25
|
+
*
|
|
26
|
+
* Both are resolved through `resolveCleoDir(cwd)` / `getCleoHome()` — never a
|
|
27
|
+
* hardcoded `~/.local/share` (Paths SSoT · Gate 2 · D009).
|
|
28
|
+
*
|
|
29
|
+
* ## Reversibility + idempotency invariants
|
|
30
|
+
*
|
|
31
|
+
* - **Reversible** — archiving is an atomic `rename` (fallback copy+unlink
|
|
32
|
+
* across filesystems). Nothing is ever deleted; an operator can move a DB
|
|
33
|
+
* back out of `_archive/` to roll the cutover back.
|
|
34
|
+
* - **Idempotent** — a source that is already absent (already archived, or a
|
|
35
|
+
* fresh install that never had it) is a silent no-op. Re-running over an
|
|
36
|
+
* already-archived fleet does nothing and never throws.
|
|
37
|
+
* - **Never blind-move** — only sources the caller asserts were actually
|
|
38
|
+
* consumed + validated by the migration are archived. A source whose
|
|
39
|
+
* migration did not run is left untouched.
|
|
40
|
+
* - **Emergency-archive reconciliation** — this box was emergency-archived
|
|
41
|
+
* (`.cleo/_archive-legacy-postcutover-*` already holds `tasks.db` +
|
|
42
|
+
* `conduit.db`). When the canonical destination already contains a file with
|
|
43
|
+
* the same name, the incoming file is parked under a timestamped sibling name
|
|
44
|
+
* rather than clobbering the prior archive.
|
|
45
|
+
*
|
|
46
|
+
* @module
|
|
47
|
+
* @task T11777 (exodus archives all 6 legacy DBs post-validation + completion marker)
|
|
48
|
+
* @epic T11249 (E6)
|
|
49
|
+
* @saga T11242 (SG-DB-SUBSTRATE-V2)
|
|
50
|
+
* @see packages/core/src/store/exodus/on-open.ts — wires this into the validated success path
|
|
51
|
+
* @see packages/core/src/store/exodus/plan.ts — buildSourceDescriptors (the 6 sources)
|
|
52
|
+
*/
|
|
53
|
+
import type { ExodusScope, LegacyDbDescriptor } from './types.js';
|
|
54
|
+
/**
|
|
55
|
+
* Absolute path to a scope's `_archive/` directory.
|
|
56
|
+
*
|
|
57
|
+
* @param scope - Target scope.
|
|
58
|
+
* @param cwd - Working directory used to resolve the project `.cleo/` dir.
|
|
59
|
+
* @returns Absolute path to `<scopeBase>/_archive/`.
|
|
60
|
+
*/
|
|
61
|
+
export declare function exodusArchiveDir(scope: ExodusScope, cwd?: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Absolute path to a scope's exodus completion marker file.
|
|
64
|
+
*
|
|
65
|
+
* @param scope - Target scope.
|
|
66
|
+
* @param cwd - Working directory used to resolve the project `.cleo/` dir.
|
|
67
|
+
* @returns Absolute path to `<scopeBase>/exodus-complete`.
|
|
68
|
+
*/
|
|
69
|
+
export declare function exodusMarkerPath(scope: ExodusScope, cwd?: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* Shape of the committed exodus completion marker (`exodus-complete`).
|
|
72
|
+
*
|
|
73
|
+
* Recorded once per scope after a validated cutover. Its presence — not the
|
|
74
|
+
* source-file `existsSync` — is the durable trigger-gate for exodus-on-open.
|
|
75
|
+
*/
|
|
76
|
+
export interface ExodusCompleteMarker {
|
|
77
|
+
/** Marker format version. */
|
|
78
|
+
readonly version: 1;
|
|
79
|
+
/** Scope this marker certifies as migrated. */
|
|
80
|
+
readonly scope: ExodusScope;
|
|
81
|
+
/** cleo package version that performed the cutover. */
|
|
82
|
+
readonly cleoVersion: string;
|
|
83
|
+
/** ISO-8601 timestamp of the cutover. */
|
|
84
|
+
readonly completedAt: string;
|
|
85
|
+
/** Logical names of the legacy sources that were archived (provenance). */
|
|
86
|
+
readonly archivedSources: readonly string[];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Return `true` if a scope's exodus completion marker exists on disk.
|
|
90
|
+
*
|
|
91
|
+
* Resolution-safe: when the project `.cleo/` dir cannot be resolved (e.g. `cwd`
|
|
92
|
+
* is not inside a CLEO project — `resolveCleoDir` throws), this returns `false`
|
|
93
|
+
* (no marker) rather than propagating, so the on-open trigger gate degrades to
|
|
94
|
+
* the source-file path safely instead of crashing the open.
|
|
95
|
+
*
|
|
96
|
+
* @param scope - Target scope.
|
|
97
|
+
* @param cwd - Working directory used to resolve the project `.cleo/` dir.
|
|
98
|
+
* @returns Whether `<scopeBase>/exodus-complete` exists.
|
|
99
|
+
*/
|
|
100
|
+
export declare function hasExodusCompleteMarker(scope: ExodusScope, cwd?: string): boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Write a scope's exodus completion marker atomically (write-then-rename).
|
|
103
|
+
*
|
|
104
|
+
* Idempotent: re-writing simply refreshes the marker (same path). The marker is
|
|
105
|
+
* the SSoT trigger-gate consulted by {@link maybeRunExodusOnOpen} — once present,
|
|
106
|
+
* a stranded/re-appearing legacy file cannot re-arm the auto-migration.
|
|
107
|
+
*
|
|
108
|
+
* @param scope - Scope being certified as migrated.
|
|
109
|
+
* @param archivedSources - Logical names of the sources archived for this scope.
|
|
110
|
+
* @param cwd - Working directory used to resolve the project dir.
|
|
111
|
+
* @returns The marker's absolute path.
|
|
112
|
+
*
|
|
113
|
+
* @task T11777
|
|
114
|
+
*/
|
|
115
|
+
export declare function writeExodusCompleteMarker(scope: ExodusScope, archivedSources: readonly string[], cwd?: string): string;
|
|
116
|
+
/**
|
|
117
|
+
* Outcome of archiving one source DB.
|
|
118
|
+
*/
|
|
119
|
+
export interface ArchivedSourceResult {
|
|
120
|
+
/** Logical source name (`LegacyDbDescriptor.name`). */
|
|
121
|
+
readonly name: string;
|
|
122
|
+
/** Original absolute source path. */
|
|
123
|
+
readonly sourcePath: string;
|
|
124
|
+
/** Destination path inside `_archive/`, or `null` when nothing was moved. */
|
|
125
|
+
readonly archivedTo: string | null;
|
|
126
|
+
/** `'archived'` — moved; `'absent'` — nothing to move (idempotent no-op). */
|
|
127
|
+
readonly action: 'archived' | 'absent';
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Archive ONE legacy source DB (and its `-wal` / `-shm` sidecars) into the
|
|
131
|
+
* scope's `_archive/` directory.
|
|
132
|
+
*
|
|
133
|
+
* Idempotent: if the main DB file is already absent, this is a no-op (the file
|
|
134
|
+
* was already archived, or never existed). Sidecars are archived best-effort and
|
|
135
|
+
* only when the main DB is present.
|
|
136
|
+
*
|
|
137
|
+
* @param source - The descriptor for the source DB to archive.
|
|
138
|
+
* @param cwd - Working directory used to resolve the project dir.
|
|
139
|
+
* @returns A {@link ArchivedSourceResult} describing what happened.
|
|
140
|
+
*
|
|
141
|
+
* @task T11777
|
|
142
|
+
*/
|
|
143
|
+
export declare function archiveSourceDb(source: LegacyDbDescriptor, cwd?: string): ArchivedSourceResult;
|
|
144
|
+
/**
|
|
145
|
+
* Result of {@link archiveMigratedSources}.
|
|
146
|
+
*/
|
|
147
|
+
export interface ArchiveMigratedSourcesResult {
|
|
148
|
+
/** Per-source archive outcomes. */
|
|
149
|
+
readonly sources: readonly ArchivedSourceResult[];
|
|
150
|
+
/** Scopes for which a completion marker was written. */
|
|
151
|
+
readonly markersWritten: readonly ExodusScope[];
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Archive every consumed legacy source DB AFTER a validated cutover and write a
|
|
155
|
+
* per-scope completion marker.
|
|
156
|
+
*
|
|
157
|
+
* **Never blind-moves**: only the descriptors passed in `consumed` are archived
|
|
158
|
+
* — the caller (the validated migrate/on-open success path) passes exactly the
|
|
159
|
+
* sources whose migration actually ran and passed parity. A completion marker is
|
|
160
|
+
* written for every scope represented in `consumed`, even if some of that scope's
|
|
161
|
+
* sources were already absent (already archived) — the marker certifies "this
|
|
162
|
+
* scope's cutover is done", which is true once parity passed.
|
|
163
|
+
*
|
|
164
|
+
* Idempotent + reversible (see module docs). Safe to call repeatedly.
|
|
165
|
+
*
|
|
166
|
+
* @param consumed - Source descriptors the migration consumed + validated.
|
|
167
|
+
* @param cwd - Working directory used to resolve the project dir.
|
|
168
|
+
* @returns A {@link ArchiveMigratedSourcesResult} with per-source + per-scope outcomes.
|
|
169
|
+
*
|
|
170
|
+
* @task T11777
|
|
171
|
+
*/
|
|
172
|
+
export declare function archiveMigratedSources(consumed: readonly LegacyDbDescriptor[], cwd?: string): ArchiveMigratedSourcesResult;
|
|
173
|
+
/**
|
|
174
|
+
* A legacy source DB that is still present on disk AFTER its scope's exodus
|
|
175
|
+
* completion marker was written — i.e. stranded residue that should have been
|
|
176
|
+
* archived.
|
|
177
|
+
*/
|
|
178
|
+
export interface StrandedResidueEntry {
|
|
179
|
+
/** Logical source name. */
|
|
180
|
+
readonly name: string;
|
|
181
|
+
/** Absolute path of the still-present legacy DB. */
|
|
182
|
+
readonly path: string;
|
|
183
|
+
/** Scope whose marker certifies the cutover. */
|
|
184
|
+
readonly scope: ExodusScope;
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Detect stranded legacy source DBs: any of the six sources still present on
|
|
188
|
+
* disk for a scope whose exodus completion marker exists.
|
|
189
|
+
*
|
|
190
|
+
* Returns an empty array when no marker exists for either scope (a pre-cutover
|
|
191
|
+
* install where legacy DBs are still the live source of truth — NOT residue) or
|
|
192
|
+
* when every source for a marked scope has been archived.
|
|
193
|
+
*
|
|
194
|
+
* @param sources - The full legacy source descriptor list (from `buildExodusPlan`).
|
|
195
|
+
* @param cwd - Working directory used to resolve the project dir + markers.
|
|
196
|
+
* @returns The stranded entries (empty when clean).
|
|
197
|
+
*
|
|
198
|
+
* @task T11777
|
|
199
|
+
*/
|
|
200
|
+
export declare function detectStrandedResidue(sources: readonly LegacyDbDescriptor[], cwd?: string): StrandedResidueEntry[];
|
|
201
|
+
/**
|
|
202
|
+
* Archive stranded residue detected by {@link detectStrandedResidue}.
|
|
203
|
+
*
|
|
204
|
+
* This is the `--fix` action for the `cleo doctor exodus-residue` check. It reuses
|
|
205
|
+
* {@link archiveSourceDb} so the on-open success path and the doctor fix share one
|
|
206
|
+
* archive routine. Reversible (move, never delete) and idempotent.
|
|
207
|
+
*
|
|
208
|
+
* @param stranded - The stranded entries to archive.
|
|
209
|
+
* @param sources - The full source descriptor list (to map name → descriptor).
|
|
210
|
+
* @param cwd - Working directory used to resolve the project dir.
|
|
211
|
+
* @returns Per-source archive outcomes.
|
|
212
|
+
*
|
|
213
|
+
* @task T11777
|
|
214
|
+
*/
|
|
215
|
+
export declare function archiveStrandedResidue(stranded: readonly StrandedResidueEntry[], sources: readonly LegacyDbDescriptor[], cwd?: string): ArchivedSourceResult[];
|
|
216
|
+
//# sourceMappingURL=archive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../../src/store/exodus/archive.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAcH,OAAO,KAAK,EAAE,WAAW,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AA6BlE;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACnC,6BAA6B;IAC7B,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;IACpB,+CAA+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,uDAAuD;IACvD,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,yCAAyC;IACzC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;CAC7C;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAMjF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,yBAAyB,CACvC,KAAK,EAAE,WAAW,EAClB,eAAe,EAAE,SAAS,MAAM,EAAE,EAClC,GAAG,CAAC,EAAE,MAAM,GACX,MAAM,CAkBR;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,uDAAuD;IACvD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qCAAqC;IACrC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,6EAA6E;IAC7E,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,6EAA6E;IAC7E,QAAQ,CAAC,MAAM,EAAE,UAAU,GAAG,QAAQ,CAAC;CACxC;AAiCD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,kBAAkB,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,oBAAoB,CAkC9F;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,mCAAmC;IACnC,QAAQ,CAAC,OAAO,EAAE,SAAS,oBAAoB,EAAE,CAAC;IAClD,wDAAwD;IACxD,QAAQ,CAAC,cAAc,EAAE,SAAS,WAAW,EAAE,CAAC;CACjD;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,SAAS,kBAAkB,EAAE,EACvC,GAAG,CAAC,EAAE,MAAM,GACX,4BAA4B,CAiB9B;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,2BAA2B;IAC3B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,oDAAoD;IACpD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gDAAgD;IAChD,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC7B;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,EAAE,SAAS,kBAAkB,EAAE,EACtC,GAAG,CAAC,EAAE,MAAM,GACX,oBAAoB,EAAE,CAexB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,SAAS,oBAAoB,EAAE,EACzC,OAAO,EAAE,SAAS,kBAAkB,EAAE,EACtC,GAAG,CAAC,EAAE,MAAM,GACX,oBAAoB,EAAE,CASxB"}
|