@cleocode/core 2026.5.131 → 2026.5.133
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/db/index.d.ts +36 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +36 -0
- package/dist/db/index.js.map +1 -0
- package/dist/gc/daemon.d.ts +17 -8
- package/dist/gc/daemon.d.ts.map +1 -1
- package/dist/gc/daemon.js +24 -67
- package/dist/gc/daemon.js.map +1 -1
- package/dist/gc/gc-subsystem.d.ts +96 -0
- package/dist/gc/gc-subsystem.d.ts.map +1 -0
- package/dist/gc/gc-subsystem.js +186 -0
- package/dist/gc/gc-subsystem.js.map +1 -0
- package/dist/gc/index.d.ts +1 -0
- package/dist/gc/index.d.ts.map +1 -1
- package/dist/gc/index.js +1 -0
- package/dist/gc/index.js.map +1 -1
- package/dist/go/driver.d.ts +132 -0
- package/dist/go/driver.d.ts.map +1 -0
- package/dist/go/driver.js +191 -0
- package/dist/go/driver.js.map +1 -0
- package/dist/go/index.d.ts +13 -0
- package/dist/go/index.d.ts.map +1 -0
- package/dist/go/index.js +13 -0
- package/dist/go/index.js.map +1 -0
- package/dist/goal/advance-with-persist.d.ts +80 -0
- package/dist/goal/advance-with-persist.d.ts.map +1 -0
- package/dist/goal/advance-with-persist.js +105 -0
- package/dist/goal/advance-with-persist.js.map +1 -0
- package/dist/goal/arm.d.ts +61 -0
- package/dist/goal/arm.d.ts.map +1 -0
- package/dist/goal/arm.js +65 -0
- package/dist/goal/arm.js.map +1 -0
- package/dist/goal/index.d.ts +2 -0
- package/dist/goal/index.d.ts.map +1 -1
- package/dist/goal/index.js +2 -0
- package/dist/goal/index.js.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/orchestrate/lifecycle-ops.js +1 -1
- package/dist/orchestrate/lifecycle-ops.js.map +1 -1
- package/dist/orchestration/classify-readiness.d.ts +172 -0
- package/dist/orchestration/classify-readiness.d.ts.map +1 -0
- package/dist/orchestration/classify-readiness.js +346 -0
- package/dist/orchestration/classify-readiness.js.map +1 -0
- package/dist/orchestration/index.d.ts +2 -0
- package/dist/orchestration/index.d.ts.map +1 -1
- package/dist/orchestration/index.js +1 -0
- package/dist/orchestration/index.js.map +1 -1
- package/dist/output.d.ts +2 -0
- package/dist/output.d.ts.map +1 -1
- package/dist/output.js +59 -1
- package/dist/output.js.map +1 -1
- package/dist/release/pr-evidence.d.ts +4 -3
- package/dist/release/pr-evidence.d.ts.map +1 -1
- package/dist/release/pr-evidence.js +4 -3
- package/dist/release/pr-evidence.js.map +1 -1
- package/dist/sagas/index.d.ts +1 -0
- package/dist/sagas/index.d.ts.map +1 -1
- package/dist/sagas/index.js +1 -0
- package/dist/sagas/index.js.map +1 -1
- package/dist/sagas/next.d.ts +77 -0
- package/dist/sagas/next.d.ts.map +1 -0
- package/dist/sagas/next.js +159 -0
- package/dist/sagas/next.js.map +1 -0
- package/dist/sentient/daemon-entry.d.ts +6 -0
- package/dist/sentient/daemon-entry.d.ts.map +1 -1
- package/dist/sentient/daemon-entry.js +10 -1
- package/dist/sentient/daemon-entry.js.map +1 -1
- package/dist/sentient/daemon.d.ts +30 -0
- package/dist/sentient/daemon.d.ts.map +1 -1
- package/dist/sentient/daemon.js +12 -2
- package/dist/sentient/daemon.js.map +1 -1
- package/dist/sentient/index.d.ts +2 -0
- package/dist/sentient/index.d.ts.map +1 -1
- package/dist/sentient/index.js +5 -0
- package/dist/sentient/index.js.map +1 -1
- package/dist/sentient/propose-tick.d.ts +101 -0
- package/dist/sentient/propose-tick.d.ts.map +1 -1
- package/dist/sentient/propose-tick.js +284 -0
- package/dist/sentient/propose-tick.js.map +1 -1
- package/dist/sentient/tick.d.ts +23 -0
- package/dist/sentient/tick.d.ts.map +1 -1
- package/dist/sentient/tick.js +91 -21
- package/dist/sentient/tick.js.map +1 -1
- package/dist/store/dual-scope-db.d.ts +183 -0
- package/dist/store/dual-scope-db.d.ts.map +1 -0
- package/dist/store/dual-scope-db.js +315 -0
- package/dist/store/dual-scope-db.js.map +1 -0
- package/dist/store/open-cleo-db.d.ts +51 -4
- package/dist/store/open-cleo-db.d.ts.map +1 -1
- package/dist/store/open-cleo-db.js +56 -2
- package/dist/store/open-cleo-db.js.map +1 -1
- package/dist/store/schema/cleo-global/nexus.d.ts +1 -1
- package/dist/store/schema/cleo-global/signaldock.d.ts +1 -1
- package/dist/store/schema/cleo-shared/brain.d.ts +1 -1
- package/dist/tasks/add.d.ts.map +1 -1
- package/dist/tasks/add.js +16 -2
- package/dist/tasks/add.js.map +1 -1
- package/dist/tasks/evidence.d.ts +3 -2
- package/dist/tasks/evidence.d.ts.map +1 -1
- package/dist/tasks/evidence.js.map +1 -1
- package/dist/verification/verify-tools.d.ts +164 -0
- package/dist/verification/verify-tools.d.ts.map +1 -0
- package/dist/verification/verify-tools.js +236 -0
- package/dist/verification/verify-tools.js.map +1 -0
- package/package.json +16 -11
- package/templates/CLEO-INJECTION.md +3 -2
- package/templates/workflows/release-prepare.yml.tmpl +86 -7
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dual-scope SQLite DB open chokepoint for the SG-DB-SUBSTRATE-V2 consolidated schema.
|
|
3
|
+
*
|
|
4
|
+
* ## Overview (D1″ lifecycle split · T11246/E3 + T11247/E4)
|
|
5
|
+
*
|
|
6
|
+
* The owner-ratified D1″ decision (2026-05-30) collapses the CLEO SQLite fleet
|
|
7
|
+
* into exactly **two `cleo.db` files per machine view**:
|
|
8
|
+
*
|
|
9
|
+
* - **Project scope** — `<projectRoot>/.cleo/cleo.db`
|
|
10
|
+
* Contains every project-tier domain: `tasks_*` / `brain_*` (project-local
|
|
11
|
+
* memory) / `conduit_*` / `docs_*` / `telemetry_*` / lifecycle / provenance /
|
|
12
|
+
* chain / playbooks / agents (87 tables / 903 columns, T11360 count).
|
|
13
|
+
*
|
|
14
|
+
* - **Global scope** — `$XDG_DATA_HOME/cleo/cleo.db`
|
|
15
|
+
* Contains every cross-project domain: `nexus_*` / `skills_*` /
|
|
16
|
+
* `signaldock_*` / `brain_*` (global cross-project memory)
|
|
17
|
+
* (49 tables / 555 columns, T11361 count).
|
|
18
|
+
*
|
|
19
|
+
* ## Lifecycle
|
|
20
|
+
*
|
|
21
|
+
* `openDualScopeDb` is the **single chokepoint** for all opens of the
|
|
22
|
+
* consolidated schema. It:
|
|
23
|
+
* 1. Resolves the DB file path from scope + `cwd` (project) or `getCleoHome()`
|
|
24
|
+
* (global).
|
|
25
|
+
* 2. Opens a `node:sqlite` `DatabaseSync` handle.
|
|
26
|
+
* 3. Applies the canonical pragma set from `specs/sqlite-pragmas.json` via
|
|
27
|
+
* {@link applyPerfPragmas}.
|
|
28
|
+
* 4. Runs the drizzle-kit migrate step against the scope-appropriate
|
|
29
|
+
* migrations folder (`drizzle-cleo-project` or `drizzle-cleo-global`).
|
|
30
|
+
* 5. Returns a cached, typed `NodeSQLiteDatabase<TSchema>` handle.
|
|
31
|
+
* Subsequent calls for the same (scope, cwd) return the cached handle.
|
|
32
|
+
*
|
|
33
|
+
* ## Note on co-existence with legacy openCleoDb
|
|
34
|
+
*
|
|
35
|
+
* During the E3/E4 → E6 exodus transition, `openCleoDb` (the existing
|
|
36
|
+
* 8-role chokepoint) and `openDualScopeDb` (this module) co-exist. `openCleoDb`
|
|
37
|
+
* will be updated by E3 to delegate to this function for the consolidated
|
|
38
|
+
* schema. Until the E6 store rewrite, individual store modules still open their
|
|
39
|
+
* own legacy DBs via `openCleoDb`. The E6 milestone removes the legacy opens.
|
|
40
|
+
*
|
|
41
|
+
* @module
|
|
42
|
+
* @task T11512 (E4-T1)
|
|
43
|
+
* @task T11513 (E4-T2 — idempotent write helpers in this same file)
|
|
44
|
+
* @epic T11247 (E4)
|
|
45
|
+
* @saga T11242 (SG-DB-SUBSTRATE-V2)
|
|
46
|
+
* @adr ADR-068, ADR-069
|
|
47
|
+
* @see packages/core/src/store/schema/cleo-project/index.ts — project schema
|
|
48
|
+
* @see packages/core/src/store/schema/cleo-global/index.ts — global schema
|
|
49
|
+
* @see packages/core/migrations/drizzle-cleo-project — project migrations
|
|
50
|
+
* @see packages/core/migrations/drizzle-cleo-global — global migrations
|
|
51
|
+
*/
|
|
52
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
53
|
+
import { createRequire } from 'node:module';
|
|
54
|
+
import { dirname, join } from 'node:path';
|
|
55
|
+
import { getLogger } from '../logger.js';
|
|
56
|
+
import { getCleoHome, resolveCleoDir } from '../paths.js';
|
|
57
|
+
import { migrateWithRetry, reconcileJournal } from './migration-manager.js';
|
|
58
|
+
import { resolveCorePackageMigrationsFolder } from './resolve-migrations-folder.js';
|
|
59
|
+
import { applyPerfPragmas } from './sqlite-pragmas.js';
|
|
60
|
+
const _cache = new Map();
|
|
61
|
+
/**
|
|
62
|
+
* Build the singleton cache key for a given scope + resolved DB path.
|
|
63
|
+
* Uses `::` as a separator that cannot appear in POSIX paths.
|
|
64
|
+
*/
|
|
65
|
+
function cacheKey(scope, dbPath) {
|
|
66
|
+
return `${scope}::${dbPath}`;
|
|
67
|
+
}
|
|
68
|
+
// ── Path resolution ──────────────────────────────────────────────────────────
|
|
69
|
+
/**
|
|
70
|
+
* Resolve the absolute path to the dual-scope `cleo.db` for the given scope.
|
|
71
|
+
*
|
|
72
|
+
* - `project`: `resolveCleoDir(cwd)` + `'cleo.db'` (falls under `<root>/.cleo/`)
|
|
73
|
+
* - `global`: `getCleoHome()` + `'cleo.db'` (falls under XDG data home `/cleo/`)
|
|
74
|
+
*/
|
|
75
|
+
export function resolveDualScopeDbPath(scope, cwd) {
|
|
76
|
+
if (scope === 'project') {
|
|
77
|
+
return join(resolveCleoDir(cwd), 'cleo.db');
|
|
78
|
+
}
|
|
79
|
+
return join(getCleoHome(), 'cleo.db');
|
|
80
|
+
}
|
|
81
|
+
// ── Migration folder resolution ──────────────────────────────────────────────
|
|
82
|
+
/**
|
|
83
|
+
* Return the migrations folder name for the given scope.
|
|
84
|
+
* The folder lives under `@cleocode/core/migrations/<name>`.
|
|
85
|
+
*/
|
|
86
|
+
function migrationsSetName(scope) {
|
|
87
|
+
return scope === 'project' ? 'drizzle-cleo-project' : 'drizzle-cleo-global';
|
|
88
|
+
}
|
|
89
|
+
// ── Lazy drizzle loading ─────────────────────────────────────────────────────
|
|
90
|
+
// The drizzle-orm/node-sqlite driver statically imports `node:sqlite`, so we
|
|
91
|
+
// load it lazily (matching the pattern in sqlite.ts, T11280) to avoid pulling
|
|
92
|
+
// the native binding at module-load time and breaking lazy-init assertions.
|
|
93
|
+
const _require = createRequire(import.meta.url);
|
|
94
|
+
let _drizzle = null;
|
|
95
|
+
function getDrizzle() {
|
|
96
|
+
if (_drizzle === null) {
|
|
97
|
+
const mod = _require('drizzle-orm/node-sqlite');
|
|
98
|
+
_drizzle = mod.drizzle;
|
|
99
|
+
}
|
|
100
|
+
return _drizzle;
|
|
101
|
+
}
|
|
102
|
+
let _DatabaseSyncCtor = null;
|
|
103
|
+
function getDatabaseSyncCtor() {
|
|
104
|
+
if (_DatabaseSyncCtor === null) {
|
|
105
|
+
const mod = _require('node:sqlite');
|
|
106
|
+
_DatabaseSyncCtor = mod.DatabaseSync;
|
|
107
|
+
}
|
|
108
|
+
return _DatabaseSyncCtor;
|
|
109
|
+
}
|
|
110
|
+
// ── Schema loading ───────────────────────────────────────────────────────────
|
|
111
|
+
// Dynamic imports for schema barrels. Loaded once per scope and cached.
|
|
112
|
+
// We use dynamic import() to avoid loading both schemas at module-init time —
|
|
113
|
+
// only the requested scope's schema is loaded.
|
|
114
|
+
let _projectSchema = null;
|
|
115
|
+
let _globalSchema = null;
|
|
116
|
+
async function loadProjectSchema() {
|
|
117
|
+
if (_projectSchema === null) {
|
|
118
|
+
_projectSchema = await import('./schema/cleo-project/index.js');
|
|
119
|
+
}
|
|
120
|
+
return _projectSchema;
|
|
121
|
+
}
|
|
122
|
+
async function loadGlobalSchema() {
|
|
123
|
+
if (_globalSchema === null) {
|
|
124
|
+
_globalSchema = await import('./schema/cleo-global/index.js');
|
|
125
|
+
}
|
|
126
|
+
return _globalSchema;
|
|
127
|
+
}
|
|
128
|
+
// ── Existence table for migration reconciliation ──────────────────────────────
|
|
129
|
+
/**
|
|
130
|
+
* The "existence table" used by {@link reconcileJournal} to detect whether
|
|
131
|
+
* migrations have been run before.
|
|
132
|
+
*
|
|
133
|
+
* For the project scope the first domain is `tasks_tasks`; for global it
|
|
134
|
+
* is `nexus_project_registry`. These are the canonical first tables in each
|
|
135
|
+
* scope's migration.
|
|
136
|
+
*/
|
|
137
|
+
function existenceTable(scope) {
|
|
138
|
+
return scope === 'project' ? 'tasks_tasks' : 'nexus_project_registry';
|
|
139
|
+
}
|
|
140
|
+
export async function openDualScopeDb(scope, cwd) {
|
|
141
|
+
const dbPath = resolveDualScopeDbPath(scope, cwd);
|
|
142
|
+
const key = cacheKey(scope, dbPath);
|
|
143
|
+
// Return cached handle if available and not mid-init.
|
|
144
|
+
const existing = _cache.get(key);
|
|
145
|
+
if (existing) {
|
|
146
|
+
if (existing.initPromise) {
|
|
147
|
+
return existing.initPromise;
|
|
148
|
+
}
|
|
149
|
+
return existing.handle;
|
|
150
|
+
}
|
|
151
|
+
const log = getLogger('dual-scope-db');
|
|
152
|
+
// Create a placeholder entry so concurrent callers wait for the same init.
|
|
153
|
+
const initPromise = (async () => {
|
|
154
|
+
log.debug({ scope, dbPath }, 'opening dual-scope cleo.db');
|
|
155
|
+
// Ensure the directory exists before opening.
|
|
156
|
+
const dir = dirname(dbPath);
|
|
157
|
+
if (!existsSync(dir)) {
|
|
158
|
+
mkdirSync(dir, { recursive: true });
|
|
159
|
+
}
|
|
160
|
+
// Open the native SQLite handle.
|
|
161
|
+
const DatabaseSyncCtor = getDatabaseSyncCtor();
|
|
162
|
+
const nativeDb = new DatabaseSyncCtor(dbPath);
|
|
163
|
+
// Apply canonical pragma set (specs/sqlite-pragmas.json SSoT).
|
|
164
|
+
applyPerfPragmas(nativeDb);
|
|
165
|
+
// Load the schema barrel for this scope.
|
|
166
|
+
const schema = scope === 'project' ? await loadProjectSchema() : await loadGlobalSchema();
|
|
167
|
+
// Create the Drizzle ORM wrapper.
|
|
168
|
+
// Drizzle v1 RC3 node-sqlite API: pass { client, schema } as a single config object.
|
|
169
|
+
const drizzle = getDrizzle();
|
|
170
|
+
// biome-ignore lint/suspicious/noExplicitAny: schema type is scope-specific; typed via DualScopeDbHandle<TScope>
|
|
171
|
+
const db = drizzle({ client: nativeDb, schema });
|
|
172
|
+
// Resolve the migrations folder for this scope.
|
|
173
|
+
const migrationsFolder = resolveCorePackageMigrationsFolder(migrationsSetName(scope));
|
|
174
|
+
// Reconcile the migration journal (handles WAL/journal divergence across
|
|
175
|
+
// SQLite version upgrades — same pattern as sqlite.ts / memory-sqlite.ts).
|
|
176
|
+
reconcileJournal(nativeDb, migrationsFolder, existenceTable(scope), `dual-scope-db[${scope}]`);
|
|
177
|
+
// Run any pending migrations.
|
|
178
|
+
migrateWithRetry(db, migrationsFolder, nativeDb, existenceTable(scope), `dual-scope-db[${scope}]`);
|
|
179
|
+
log.debug({ scope, dbPath }, 'dual-scope cleo.db ready');
|
|
180
|
+
const handle = {
|
|
181
|
+
db,
|
|
182
|
+
scope,
|
|
183
|
+
dbPath,
|
|
184
|
+
close() {
|
|
185
|
+
_cache.delete(key);
|
|
186
|
+
try {
|
|
187
|
+
nativeDb.close();
|
|
188
|
+
}
|
|
189
|
+
catch {
|
|
190
|
+
// Idempotent — ignore double-close errors.
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
// Update the cache entry to mark init complete.
|
|
195
|
+
const entry = _cache.get(key);
|
|
196
|
+
if (entry) {
|
|
197
|
+
entry.initPromise = null;
|
|
198
|
+
entry.handle = handle;
|
|
199
|
+
}
|
|
200
|
+
return handle;
|
|
201
|
+
})();
|
|
202
|
+
// Store a placeholder with the in-flight promise so concurrent callers wait.
|
|
203
|
+
_cache.set(key, {
|
|
204
|
+
// biome-ignore lint/suspicious/noExplicitAny: placeholder until initPromise resolves
|
|
205
|
+
handle: null,
|
|
206
|
+
// biome-ignore lint/suspicious/noExplicitAny: nativeDb not available yet
|
|
207
|
+
nativeDb: null,
|
|
208
|
+
initPromise,
|
|
209
|
+
});
|
|
210
|
+
return initPromise;
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Reset all cached handles. Primarily for use in tests between test cases.
|
|
214
|
+
* Closes all open handles before evicting from the cache.
|
|
215
|
+
*
|
|
216
|
+
* @internal
|
|
217
|
+
*/
|
|
218
|
+
export function _resetDualScopeDbCache() {
|
|
219
|
+
for (const entry of _cache.values()) {
|
|
220
|
+
if (entry.handle) {
|
|
221
|
+
try {
|
|
222
|
+
entry.handle.close();
|
|
223
|
+
}
|
|
224
|
+
catch {
|
|
225
|
+
// ignore
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
_cache.clear();
|
|
230
|
+
// Also reset schema caches so tests can reload fresh schemas.
|
|
231
|
+
_projectSchema = null;
|
|
232
|
+
_globalSchema = null;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Attempt to insert `row` into `table`. If a row with the same value for
|
|
236
|
+
* `keyColumn` already exists (UNIQUE conflict), the insert is silently skipped.
|
|
237
|
+
*
|
|
238
|
+
* Wraps Drizzle v1's `.onConflictDoNothing()` to provide a type-safe,
|
|
239
|
+
* retry-safe idempotent insert for tables that carry an `idempotency_key`
|
|
240
|
+
* column or any other UNIQUE column.
|
|
241
|
+
*
|
|
242
|
+
* @param db - The Drizzle database handle (project or global scope).
|
|
243
|
+
* @param table - The Drizzle table reference from the consolidated schema.
|
|
244
|
+
* @param row - The row data to insert (all required columns).
|
|
245
|
+
* @param _keyColumn - The column name to conflict on (informational; the
|
|
246
|
+
* conflict resolution is applied table-wide via `.onConflictDoNothing()`).
|
|
247
|
+
* Pass the column name as a hint for documentation purposes.
|
|
248
|
+
* @returns The number of rows actually inserted (0 or 1).
|
|
249
|
+
*
|
|
250
|
+
* @example
|
|
251
|
+
* ```ts
|
|
252
|
+
* import { tasksTasksTable } from '@cleocode/core/store/schema/cleo-project';
|
|
253
|
+
* const inserted = await insertIdempotent(db, tasksTasksTable, newTask, 'idempotencyKey');
|
|
254
|
+
* ```
|
|
255
|
+
*
|
|
256
|
+
* @task T11513 (E4-T2)
|
|
257
|
+
* @epic T11247 (E4)
|
|
258
|
+
* @saga T11242
|
|
259
|
+
*/
|
|
260
|
+
export async function insertIdempotent(
|
|
261
|
+
// biome-ignore lint/suspicious/noExplicitAny: accepts both project and global schema handles
|
|
262
|
+
db, table, row,
|
|
263
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
264
|
+
_keyColumn) {
|
|
265
|
+
const result = await db.insert(table).values(row).onConflictDoNothing().returning();
|
|
266
|
+
return result.length;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Upsert `row` into `table`, updating all non-key columns when a row with
|
|
270
|
+
* the same `keyColumn` value already exists.
|
|
271
|
+
*
|
|
272
|
+
* Wraps Drizzle v1's `.onConflictDoUpdate()` for retry-safe upsert semantics.
|
|
273
|
+
*
|
|
274
|
+
* @param db - The Drizzle database handle.
|
|
275
|
+
* @param table - The Drizzle table reference.
|
|
276
|
+
* @param row - The row data to insert or update.
|
|
277
|
+
* @param keyColumn - The conflict-target column name (must be a UNIQUE or
|
|
278
|
+
* PRIMARY KEY column on the table).
|
|
279
|
+
* @param conflictTarget - The column reference used as the `.target` for
|
|
280
|
+
* `.onConflictDoUpdate()`. Pass the Drizzle column reference (e.g.
|
|
281
|
+
* `table.idempotencyKey`).
|
|
282
|
+
* @param set - The columns to update on conflict. If omitted, all columns
|
|
283
|
+
* in `row` are used as the update set.
|
|
284
|
+
* @returns The number of rows inserted or updated (always 1).
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ```ts
|
|
288
|
+
* await upsertIdempotent(db, tasksTasksTable, updatedTask, 'idempotencyKey',
|
|
289
|
+
* tasksTasksTable.idempotencyKey);
|
|
290
|
+
* ```
|
|
291
|
+
*
|
|
292
|
+
* @task T11513 (E4-T2)
|
|
293
|
+
* @epic T11247 (E4)
|
|
294
|
+
* @saga T11242
|
|
295
|
+
*/
|
|
296
|
+
export async function upsertIdempotent(
|
|
297
|
+
// biome-ignore lint/suspicious/noExplicitAny: accepts both project and global schema handles
|
|
298
|
+
db, table, row,
|
|
299
|
+
/** The conflict-target column name (informational hint for callers). */
|
|
300
|
+
_keyColumn,
|
|
301
|
+
// biome-ignore lint/suspicious/noExplicitAny: column reference type varies by table
|
|
302
|
+
conflictTarget, set) {
|
|
303
|
+
const updateSet = set ?? row;
|
|
304
|
+
const result = await db
|
|
305
|
+
.insert(table)
|
|
306
|
+
.values(row)
|
|
307
|
+
.onConflictDoUpdate({
|
|
308
|
+
target: conflictTarget,
|
|
309
|
+
// biome-ignore lint/suspicious/noExplicitAny: updateSet shape varies by table; type-safe at call sites
|
|
310
|
+
set: updateSet,
|
|
311
|
+
})
|
|
312
|
+
.returning();
|
|
313
|
+
return result.length;
|
|
314
|
+
}
|
|
315
|
+
//# sourceMappingURL=dual-scope-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dual-scope-db.js","sourceRoot":"","sources":["../../src/store/dual-scope-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,11 +21,24 @@
|
|
|
21
21
|
* ```typescript
|
|
22
22
|
* import { openCleoDb } from '@cleocode/core/store/open-cleo-db';
|
|
23
23
|
*
|
|
24
|
+
* // Dual-scope consolidated cleo.db (D1″ lifecycle — E3/E4 exodus):
|
|
25
|
+
* const projHandle = await openCleoDb('project', cwd);
|
|
26
|
+
* const globHandle = await openCleoDb('global');
|
|
27
|
+
*
|
|
28
|
+
* // Legacy 8-role API (deprecated — use 'project'|'global' for new code):
|
|
24
29
|
* const handle = await openCleoDb('tasks', cwd);
|
|
25
30
|
* // use handle.db (DatabaseSync) ...
|
|
26
31
|
* await handle.close();
|
|
27
32
|
* ```
|
|
28
33
|
*
|
|
34
|
+
* ## Dual-scope delegation (T11517 · E3)
|
|
35
|
+
*
|
|
36
|
+
* When called with `'project'` or `'global'` as the role, `openCleoDb` delegates
|
|
37
|
+
* directly to {@link openDualScopeDb} from `./dual-scope-db.ts`, returning a
|
|
38
|
+
* `CleoDbHandle`-shaped wrapper. This is the preferred API for all new code
|
|
39
|
+
* after the E3 exodus. The legacy 8-role CleoDbRole API is retained as a
|
|
40
|
+
* deprecated shim for one migration cycle (E6 removes it).
|
|
41
|
+
*
|
|
29
42
|
* ## Snapshot opener (read-only, no migrations)
|
|
30
43
|
*
|
|
31
44
|
* For short-lived read-only opens (backup verification, schema integrity
|
|
@@ -34,12 +47,25 @@
|
|
|
34
47
|
* migrations and singleton management, so the caller owns the handle's
|
|
35
48
|
* lifecycle directly.
|
|
36
49
|
*
|
|
37
|
-
* @task T9047, T9685
|
|
50
|
+
* @task T9047, T9685, T11517
|
|
38
51
|
* @adr ADR-068, ADR-069
|
|
39
52
|
*/
|
|
40
53
|
import type { DatabaseSync } from 'node:sqlite';
|
|
41
|
-
|
|
42
|
-
|
|
54
|
+
import type { DualScope } from './dual-scope-db.js';
|
|
55
|
+
/**
|
|
56
|
+
* Canonical roles for the CLEO SQLite databases (ADR-068).
|
|
57
|
+
*
|
|
58
|
+
* ### Preferred (dual-scope, D1″ — E3 exodus)
|
|
59
|
+
* - `'project'` — consolidated per-project `cleo.db` (delegates to {@link openDualScopeDb})
|
|
60
|
+
* - `'global'` — consolidated per-user `cleo.db` (delegates to {@link openDualScopeDb})
|
|
61
|
+
*
|
|
62
|
+
* ### Legacy 8-role API (deprecated — kept for one migration cycle until E6)
|
|
63
|
+
* The legacy roles below are retained as shims during the E3→E6 transition.
|
|
64
|
+
* New code MUST use `'project'` or `'global'` instead.
|
|
65
|
+
*
|
|
66
|
+
* @task T11517 (E3-T1 · SG-DB-SUBSTRATE-V2)
|
|
67
|
+
*/
|
|
68
|
+
export type CleoDbRole = DualScope | 'tasks' | 'brain' | 'sessions' | 'signaldock' | 'conduit' | 'nexus' | 'skills' | 'llmtxt';
|
|
43
69
|
/** Handle returned by {@link openCleoDb}. */
|
|
44
70
|
export interface CleoDbHandle {
|
|
45
71
|
db: unknown;
|
|
@@ -76,11 +102,32 @@ export type DBHandle = CleoDbHandle;
|
|
|
76
102
|
*/
|
|
77
103
|
export declare function validateProjectIdConsistency(role: CleoDbRole, db: unknown, cwd?: string): void;
|
|
78
104
|
/**
|
|
79
|
-
* Open (or create) a CLEO database by canonical role.
|
|
105
|
+
* Open (or create) a CLEO database by canonical role or dual-scope selector.
|
|
106
|
+
*
|
|
107
|
+
* ## Dual-scope delegation (preferred — T11517 · E3)
|
|
108
|
+
*
|
|
109
|
+
* When called with `'project'` or `'global'`, this function delegates to
|
|
110
|
+
* {@link openDualScopeDb} from `./dual-scope-db.ts`. The returned handle
|
|
111
|
+
* wraps the typed Drizzle client as `CleoDbHandle.db` for backward compat
|
|
112
|
+
* with legacy callers that treat `db` as an opaque `unknown`.
|
|
113
|
+
*
|
|
114
|
+
* ```ts
|
|
115
|
+
* // Preferred for new code after E3 exodus:
|
|
116
|
+
* const handle = await openCleoDb('project', cwd);
|
|
117
|
+
* const handle = await openCleoDb('global');
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* ## Legacy 8-role API (deprecated)
|
|
121
|
+
*
|
|
122
|
+
* The legacy role strings (`'tasks'`, `'brain'`, `'signaldock'`, …) remain
|
|
123
|
+
* functional as deprecated shims for existing callers. E6 will remove them.
|
|
80
124
|
*
|
|
81
125
|
* Single chokepoint for all DB opens. Applies pragma SSoT at open time.
|
|
82
126
|
* Enforces the worktree-isolation guard (T9806) on top of T9803's path-layer
|
|
83
127
|
* THROWS-on-orphan fix.
|
|
128
|
+
*
|
|
129
|
+
* @task T9047, T9685, T11517
|
|
130
|
+
* @adr ADR-068, ADR-069
|
|
84
131
|
*/
|
|
85
132
|
export declare function openCleoDb(role: CleoDbRole, cwd?: string): Promise<CleoDbHandle>;
|
|
86
133
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open-cleo-db.d.ts","sourceRoot":"","sources":["../../src/store/open-cleo-db.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"open-cleo-db.d.ts","sourceRoot":"","sources":["../../src/store/open-cleo-db.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmDG;AAGH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAMhD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAUpD;;;;;;;;;;;;GAYG;AACH,MAAM,MAAM,UAAU,GAElB,SAAS,GAET,OAAO,GACP,OAAO,GACP,UAAU,GACV,YAAY,GACZ,SAAS,GACT,OAAO,GACP,QAAQ,GACR,QAAQ,CAAC;AAYb,6CAA6C;AAC7C,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,IAAI,EAAE,UAAU,CAAC;IACjB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,4CAA4C;AAC5C,MAAM,MAAM,QAAQ,GAAG,YAAY,CAAC;AAqGpC;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,EAAE,OAAO,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAoD9F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,UAAU,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA4DtF;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAErE;AAMD,sDAAsD;AACtD,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,qCAAqC;IACrC,EAAE,EAAE,YAAY,CAAC;IACjB,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,KAAK,IAAI,IAAI,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,qBAA0B,GAClC,oBAAoB,CA8BtB"}
|
|
@@ -21,11 +21,24 @@
|
|
|
21
21
|
* ```typescript
|
|
22
22
|
* import { openCleoDb } from '@cleocode/core/store/open-cleo-db';
|
|
23
23
|
*
|
|
24
|
+
* // Dual-scope consolidated cleo.db (D1″ lifecycle — E3/E4 exodus):
|
|
25
|
+
* const projHandle = await openCleoDb('project', cwd);
|
|
26
|
+
* const globHandle = await openCleoDb('global');
|
|
27
|
+
*
|
|
28
|
+
* // Legacy 8-role API (deprecated — use 'project'|'global' for new code):
|
|
24
29
|
* const handle = await openCleoDb('tasks', cwd);
|
|
25
30
|
* // use handle.db (DatabaseSync) ...
|
|
26
31
|
* await handle.close();
|
|
27
32
|
* ```
|
|
28
33
|
*
|
|
34
|
+
* ## Dual-scope delegation (T11517 · E3)
|
|
35
|
+
*
|
|
36
|
+
* When called with `'project'` or `'global'` as the role, `openCleoDb` delegates
|
|
37
|
+
* directly to {@link openDualScopeDb} from `./dual-scope-db.ts`, returning a
|
|
38
|
+
* `CleoDbHandle`-shaped wrapper. This is the preferred API for all new code
|
|
39
|
+
* after the E3 exodus. The legacy 8-role CleoDbRole API is retained as a
|
|
40
|
+
* deprecated shim for one migration cycle (E6 removes it).
|
|
41
|
+
*
|
|
29
42
|
* ## Snapshot opener (read-only, no migrations)
|
|
30
43
|
*
|
|
31
44
|
* For short-lived read-only opens (backup verification, schema integrity
|
|
@@ -34,7 +47,7 @@
|
|
|
34
47
|
* migrations and singleton management, so the caller owns the handle's
|
|
35
48
|
* lifecycle directly.
|
|
36
49
|
*
|
|
37
|
-
* @task T9047, T9685
|
|
50
|
+
* @task T9047, T9685, T11517
|
|
38
51
|
* @adr ADR-068, ADR-069
|
|
39
52
|
*/
|
|
40
53
|
import { createRequire } from 'node:module';
|
|
@@ -43,6 +56,7 @@ import { CleoError } from '../errors.js';
|
|
|
43
56
|
import { resolveOrCwd } from '../paths.js';
|
|
44
57
|
import { getProjectInfoSync } from '../project-info.js';
|
|
45
58
|
import { getConduitNativeDb } from './conduit-sqlite.js';
|
|
59
|
+
import { openDualScopeDb } from './dual-scope-db.js';
|
|
46
60
|
import { getBrainDb } from './memory-sqlite.js';
|
|
47
61
|
import { getNexusDb } from './nexus-sqlite.js';
|
|
48
62
|
import { ensureGlobalSignaldockDb, getGlobalSignaldockNativeDb } from './signaldock-sqlite.js';
|
|
@@ -87,6 +101,7 @@ async function openSkillsDbHandle(_cwd) {
|
|
|
87
101
|
async function openBrainDbHandle(cwd) {
|
|
88
102
|
return getBrainDb(cwd);
|
|
89
103
|
}
|
|
104
|
+
/** Openers for the legacy 8-role API (deprecated shim — E6 removes these). */
|
|
90
105
|
const ROLE_OPENERS = {
|
|
91
106
|
tasks: getTasksDb,
|
|
92
107
|
// T10397: brain role MUST resolve to brain.db, NOT tasks.db. Prior to
|
|
@@ -203,13 +218,52 @@ export function validateProjectIdConsistency(role, db, cwd) {
|
|
|
203
218
|
}
|
|
204
219
|
}
|
|
205
220
|
/**
|
|
206
|
-
* Open (or create) a CLEO database by canonical role.
|
|
221
|
+
* Open (or create) a CLEO database by canonical role or dual-scope selector.
|
|
222
|
+
*
|
|
223
|
+
* ## Dual-scope delegation (preferred — T11517 · E3)
|
|
224
|
+
*
|
|
225
|
+
* When called with `'project'` or `'global'`, this function delegates to
|
|
226
|
+
* {@link openDualScopeDb} from `./dual-scope-db.ts`. The returned handle
|
|
227
|
+
* wraps the typed Drizzle client as `CleoDbHandle.db` for backward compat
|
|
228
|
+
* with legacy callers that treat `db` as an opaque `unknown`.
|
|
229
|
+
*
|
|
230
|
+
* ```ts
|
|
231
|
+
* // Preferred for new code after E3 exodus:
|
|
232
|
+
* const handle = await openCleoDb('project', cwd);
|
|
233
|
+
* const handle = await openCleoDb('global');
|
|
234
|
+
* ```
|
|
235
|
+
*
|
|
236
|
+
* ## Legacy 8-role API (deprecated)
|
|
237
|
+
*
|
|
238
|
+
* The legacy role strings (`'tasks'`, `'brain'`, `'signaldock'`, …) remain
|
|
239
|
+
* functional as deprecated shims for existing callers. E6 will remove them.
|
|
207
240
|
*
|
|
208
241
|
* Single chokepoint for all DB opens. Applies pragma SSoT at open time.
|
|
209
242
|
* Enforces the worktree-isolation guard (T9806) on top of T9803's path-layer
|
|
210
243
|
* THROWS-on-orphan fix.
|
|
244
|
+
*
|
|
245
|
+
* @task T9047, T9685, T11517
|
|
246
|
+
* @adr ADR-068, ADR-069
|
|
211
247
|
*/
|
|
212
248
|
export async function openCleoDb(role, cwd) {
|
|
249
|
+
// ── Dual-scope delegation (preferred API — E3 onwards) ──────────────────
|
|
250
|
+
if (role === 'project' || role === 'global') {
|
|
251
|
+
// Delegate to the E4 chokepoint which applies pragma SSoT, runs migrations,
|
|
252
|
+
// and manages the singleton cache. Explicit conditional narrows the overload.
|
|
253
|
+
const dualHandle = role === 'project'
|
|
254
|
+
? await openDualScopeDb('project', cwd)
|
|
255
|
+
: await openDualScopeDb('global', cwd);
|
|
256
|
+
return {
|
|
257
|
+
// The Drizzle handle is compatible with `unknown` — callers that need
|
|
258
|
+
// the native DatabaseSync should use `@cleocode/core/db` directly.
|
|
259
|
+
db: dualHandle.db,
|
|
260
|
+
role,
|
|
261
|
+
async close() {
|
|
262
|
+
dualHandle.close();
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
// ── Legacy 8-role API (deprecated shim — E6 removes) ───────────────────
|
|
213
267
|
if (role === 'llmtxt') {
|
|
214
268
|
throw new Error('CLEO DB role llmtxt is not yet implemented');
|
|
215
269
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"open-cleo-db.js","sourceRoot":"","sources":["../../src/store/open-cleo-db.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"open-cleo-db.js","sourceRoot":"","sources":["../../src/store/open-cleo-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -1919,7 +1919,7 @@ export declare const nexusSigils: import("drizzle-orm/sqlite-core").SQLiteTableW
|
|
|
1919
1919
|
name: string;
|
|
1920
1920
|
tableName: "nexus_sigils";
|
|
1921
1921
|
dataType: "string enum";
|
|
1922
|
-
data: "" | "orchestrator" | "validator" | "lead" | "worker" | "
|
|
1922
|
+
data: "" | "orchestrator" | "validator" | "lead" | "worker" | "subagent" | "specialist";
|
|
1923
1923
|
driverParam: string;
|
|
1924
1924
|
notNull: true;
|
|
1925
1925
|
hasDefault: true;
|
|
@@ -802,7 +802,7 @@ export declare const signaldockAgents: import("drizzle-orm/sqlite-core").SQLiteT
|
|
|
802
802
|
name: string;
|
|
803
803
|
tableName: "signaldock_agents";
|
|
804
804
|
dataType: "string enum";
|
|
805
|
-
data: "online" | "
|
|
805
|
+
data: "online" | "offline" | "busy" | "away";
|
|
806
806
|
driverParam: string;
|
|
807
807
|
notNull: true;
|
|
808
808
|
hasDefault: true;
|
|
@@ -4244,7 +4244,7 @@ export declare const brainBackfillRuns: import("drizzle-orm/sqlite-core").SQLite
|
|
|
4244
4244
|
name: string;
|
|
4245
4245
|
tableName: "brain_backfill_runs";
|
|
4246
4246
|
dataType: "string enum";
|
|
4247
|
-
data: "custom" | "
|
|
4247
|
+
data: "custom" | "observation-promotion" | "transcript-ingest" | "graph-backfill" | "noise-sweep-2440";
|
|
4248
4248
|
driverParam: string;
|
|
4249
4249
|
notNull: true;
|
|
4250
4250
|
hasDefault: false;
|
package/dist/tasks/add.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/tasks/add.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/tasks/add.ts"],"names":[],"mappings":"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"}
|
package/dist/tasks/add.js
CHANGED
|
@@ -694,12 +694,26 @@ export async function addTask(options, cwd, accessor) {
|
|
|
694
694
|
const ancestors = await dataAccessor.getAncestorChain(parentId);
|
|
695
695
|
const parentDepth = ancestors.length;
|
|
696
696
|
if (parentDepth + 1 >= policy.maxDepth) {
|
|
697
|
-
|
|
698
|
-
|
|
697
|
+
// T11491 — DHQ-044: produce a clear actionable message that names the
|
|
698
|
+
// parent epic the user SHOULD target instead. The ancestor chain is
|
|
699
|
+
// ordered [immediateParent, grandparent, …, root]. When the parent is a
|
|
700
|
+
// task (depth 2), ancestors[0] is the epic (depth 1) — tell the user
|
|
701
|
+
// to file under THAT epic instead.
|
|
702
|
+
const grandparentEpic = ancestors.length > 0 ? ancestors[ancestors.length - 1] : ancestors[0];
|
|
703
|
+
const epicSuggestion = grandparentEpic
|
|
704
|
+
? ` Use --parent ${grandparentEpic.id} (the parent epic) instead, or omit --parent to create a standalone task.`
|
|
705
|
+
: ' Omit --parent to create a standalone task, or reparent under a higher-level epic.';
|
|
706
|
+
throw new CleoError(ExitCode.DEPTH_EXCEEDED, `Cannot add a child to ${parentId}: the hierarchy depth cap (${policy.maxDepth}) would be exceeded. ` +
|
|
707
|
+
`Tasks at depth ${parentDepth} cannot have children.${epicSuggestion}`, {
|
|
708
|
+
fix: grandparentEpic
|
|
709
|
+
? `cleo add --parent ${grandparentEpic.id} --title "..." --acceptance "..."`
|
|
710
|
+
: 'Reparent this task under a higher-level epic',
|
|
699
711
|
details: {
|
|
700
712
|
field: 'parentId',
|
|
701
713
|
expected: `depth < ${policy.maxDepth}`,
|
|
702
714
|
actual: parentDepth + 1,
|
|
715
|
+
suggestedParentId: grandparentEpic?.id,
|
|
716
|
+
suggestedParentTitle: grandparentEpic?.title,
|
|
703
717
|
},
|
|
704
718
|
});
|
|
705
719
|
}
|