@cleocode/contracts 2026.5.107 → 2026.5.109
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/__tests__/db-inventory.test.d.ts +25 -0
- package/dist/__tests__/db-inventory.test.d.ts.map +1 -0
- package/dist/__tests__/db-inventory.test.js +148 -0
- package/dist/__tests__/db-inventory.test.js.map +1 -0
- package/dist/__tests__/task-type-narrowing.test.d.ts +14 -0
- package/dist/__tests__/task-type-narrowing.test.d.ts.map +1 -0
- package/dist/__tests__/task-type-narrowing.test.js +51 -0
- package/dist/__tests__/task-type-narrowing.test.js.map +1 -0
- package/dist/brain.d.ts +103 -0
- package/dist/brain.d.ts.map +1 -1
- package/dist/db-inventory.d.ts +193 -0
- package/dist/db-inventory.d.ts.map +1 -0
- package/dist/db-inventory.js +69 -0
- package/dist/db-inventory.js.map +1 -0
- package/dist/doctor.d.ts +152 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/operations/tasks.d.ts +4 -4
- package/dist/operations/tasks.d.ts.map +1 -1
- package/dist/task.d.ts +13 -2
- package/dist/task.d.ts.map +1 -1
- package/dist/task.js.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/db-inventory.test.ts +184 -0
- package/src/__tests__/task-type-narrowing.test.ts +56 -0
- package/src/brain.ts +114 -0
- package/src/db-inventory.ts +227 -0
- package/src/doctor.ts +162 -0
- package/src/index.ts +19 -0
- package/src/operations/tasks.ts +4 -4
- package/src/task.ts +13 -2
package/src/doctor.ts
CHANGED
|
@@ -286,6 +286,168 @@ export interface SagaAuditResult {
|
|
|
286
286
|
driftCount: number;
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
+
// ============================================================================
|
|
290
|
+
// DB-Substrate Survey (T10307 — Saga T10281 SG-BRAIN-DB-RESILIENCE / Epic T10282)
|
|
291
|
+
// ============================================================================
|
|
292
|
+
|
|
293
|
+
/**
|
|
294
|
+
* Per-database substrate-audit findings.
|
|
295
|
+
*
|
|
296
|
+
* Produced by `surveyProjectDbSubstrate` for every entry in the
|
|
297
|
+
* `DB_INVENTORY` SSoT. Fields that depend on the file existing on disk
|
|
298
|
+
* (`integrityOK`, `rowCounts`, `lastWriteMs`, `sizeBytes`) are `null` when
|
|
299
|
+
* the file is missing. `error` is non-null when integrity_check or the
|
|
300
|
+
* open / row-count round-trip threw — corrupt DBs surface here so the
|
|
301
|
+
* envelope's `summary.corrupt` counter increments.
|
|
302
|
+
*
|
|
303
|
+
* `suggestedFix` is a stable, machine-readable repair command (typically
|
|
304
|
+
* `cleo backup recover <role>` — the verb introduced by T10304). Always
|
|
305
|
+
* populated when `integrityOK === false` so the operator has a one-line
|
|
306
|
+
* remediation path.
|
|
307
|
+
*
|
|
308
|
+
* @task T10307
|
|
309
|
+
* @epic T10282
|
|
310
|
+
* @saga T10281
|
|
311
|
+
*/
|
|
312
|
+
export interface DbSubstrateEntry {
|
|
313
|
+
/** Absolute on-disk path the inventory template resolved to. */
|
|
314
|
+
filePath: string;
|
|
315
|
+
/** `true` iff the file currently exists on disk. */
|
|
316
|
+
exists: boolean;
|
|
317
|
+
/**
|
|
318
|
+
* Result of `PRAGMA integrity_check`. `true` when the pragma returned
|
|
319
|
+
* exactly one `'ok'` row; `false` when it returned anything else or
|
|
320
|
+
* the call threw; `null` when the file did not exist (no integrity
|
|
321
|
+
* check attempted).
|
|
322
|
+
*/
|
|
323
|
+
integrityOK: boolean | null;
|
|
324
|
+
/**
|
|
325
|
+
* Row counts for up to 3 representative tables (alphabetically first
|
|
326
|
+
* non-meta tables). `null` when the file is missing or the count
|
|
327
|
+
* round-trip threw.
|
|
328
|
+
*/
|
|
329
|
+
rowCounts: Readonly<Record<string, number>> | null;
|
|
330
|
+
/** `fs.statSync(filePath).mtimeMs`, or `null` when the file is missing. */
|
|
331
|
+
lastWriteMs: number | null;
|
|
332
|
+
/** `fs.statSync(filePath).size`, or `null` when the file is missing. */
|
|
333
|
+
sizeBytes: number | null;
|
|
334
|
+
/**
|
|
335
|
+
* Stable error string surfaced from a failed integrity_check or open.
|
|
336
|
+
* `null` when the survey succeeded (including when the file simply
|
|
337
|
+
* does not exist — that is `exists: false`, not an error).
|
|
338
|
+
*/
|
|
339
|
+
error: string | null;
|
|
340
|
+
/**
|
|
341
|
+
* Suggested repair command when `integrityOK === false`. `null`
|
|
342
|
+
* otherwise. Typically `cleo backup recover <role>` per T10304.
|
|
343
|
+
*/
|
|
344
|
+
suggestedFix: string | null;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
/**
|
|
348
|
+
* Warning kinds surfaced by `surveyDbSubstrate` via `envelope.meta.warnings`.
|
|
349
|
+
*
|
|
350
|
+
* @remarks
|
|
351
|
+
* Surfacing as warnings (not violations) means they do NOT drive a
|
|
352
|
+
* non-zero exit code on their own — operators should review and remediate,
|
|
353
|
+
* but the substrate is otherwise healthy.
|
|
354
|
+
*
|
|
355
|
+
* - `orphan-project-root` — a `.cleo/` directory found at a project-PARENT
|
|
356
|
+
* path (e.g. `/mnt/projects/.cleo/`). Regression class T9550.
|
|
357
|
+
* - `nested-nexus-duplicate` — `~/.local/share/cleo/nexus/{nexus,signaldock}.db`
|
|
358
|
+
* exists alongside the canonical flat `nexus.db` / `signaldock.db` files,
|
|
359
|
+
* indicating a structural duplicate from an older XDG-path resolution.
|
|
360
|
+
*
|
|
361
|
+
* @task T10307
|
|
362
|
+
*/
|
|
363
|
+
export type DbSubstrateWarningKind = 'orphan-project-root' | 'nested-nexus-duplicate';
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* One warning entry surfaced in the envelope's `meta.warnings` list.
|
|
367
|
+
*
|
|
368
|
+
* @task T10307
|
|
369
|
+
*/
|
|
370
|
+
export interface DbSubstrateWarning {
|
|
371
|
+
/** Machine-readable warning class. */
|
|
372
|
+
kind: DbSubstrateWarningKind;
|
|
373
|
+
/** Absolute path of the offending file or directory. */
|
|
374
|
+
path: string;
|
|
375
|
+
/**
|
|
376
|
+
* `fs.statSync(path).mtimeMs` for the offending file/directory.
|
|
377
|
+
* `null` when stat() threw (e.g. ephemeral race during scan).
|
|
378
|
+
*/
|
|
379
|
+
lastWriteMs: number | null;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
/**
|
|
383
|
+
* Survey result for one CLEO project (i.e. one `.cleo/` directory) plus
|
|
384
|
+
* the global tier of databases owned by it.
|
|
385
|
+
*
|
|
386
|
+
* @remarks
|
|
387
|
+
* `dbs` is keyed by the canonical role names from `DB_INVENTORY`. Every
|
|
388
|
+
* entry is populated regardless of whether the file exists — the caller
|
|
389
|
+
* can iterate every role and decide how to surface absent rows.
|
|
390
|
+
*
|
|
391
|
+
* @task T10307
|
|
392
|
+
*/
|
|
393
|
+
export interface DbSubstrateProjectSurvey {
|
|
394
|
+
/** Absolute path to the project root that was surveyed. */
|
|
395
|
+
projectRoot: string;
|
|
396
|
+
/**
|
|
397
|
+
* Stable identifier for the project — currently the `base64url(path)`
|
|
398
|
+
* truncated to 32 chars, matching the convention used by `cleo nexus`
|
|
399
|
+
* project resolution.
|
|
400
|
+
*/
|
|
401
|
+
projectId: string;
|
|
402
|
+
/** Per-role survey result, keyed by canonical role name. */
|
|
403
|
+
dbs: Readonly<Record<string, DbSubstrateEntry>>;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
/**
|
|
407
|
+
* Aggregate counters surfaced in `envelope.data.summary`.
|
|
408
|
+
*
|
|
409
|
+
* @task T10307
|
|
410
|
+
*/
|
|
411
|
+
export interface DbSubstrateSummary {
|
|
412
|
+
/** Total inventory entries surveyed across all projects + global tier. */
|
|
413
|
+
totalDbs: number;
|
|
414
|
+
/** Entries where `exists && integrityOK === true`. */
|
|
415
|
+
healthy: number;
|
|
416
|
+
/** Entries where `!exists`. */
|
|
417
|
+
missing: number;
|
|
418
|
+
/** Entries where `exists && integrityOK === false`. */
|
|
419
|
+
corrupt: number;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
/**
|
|
423
|
+
* Top-level result payload returned by `surveyDbSubstrate`.
|
|
424
|
+
*
|
|
425
|
+
* @remarks
|
|
426
|
+
* `scope === 'project'` means the survey covered exactly one project plus
|
|
427
|
+
* the global tier. `scope === 'fleet'` means the survey walked every
|
|
428
|
+
* `.cleo/` directory discoverable from a fleet-root search path.
|
|
429
|
+
*
|
|
430
|
+
* Carried as the `data` field of the LAFS envelope; the corresponding
|
|
431
|
+
* `meta` field carries `meta.warnings` per `DbSubstrateWarning` and the
|
|
432
|
+
* canonical `operation: 'doctor.db-substrate.run'` identifier.
|
|
433
|
+
*
|
|
434
|
+
* @task T10307
|
|
435
|
+
*/
|
|
436
|
+
export interface DbSubstrateAuditResult {
|
|
437
|
+
/** Survey scope. `'project'` = current project; `'fleet'` = many projects. */
|
|
438
|
+
scope: 'project' | 'fleet';
|
|
439
|
+
/** Per-project surveys. One entry for `scope='project'`; ≥1 for `scope='fleet'`. */
|
|
440
|
+
projects: DbSubstrateProjectSurvey[];
|
|
441
|
+
/** Aggregate counters across all surveyed entries. */
|
|
442
|
+
summary: DbSubstrateSummary;
|
|
443
|
+
/**
|
|
444
|
+
* Structural warnings the survey detected outside of any inventory
|
|
445
|
+
* entry — orphan project-root `.cleo/` directories, nested-nexus
|
|
446
|
+
* duplicates, etc. ALWAYS present (may be empty).
|
|
447
|
+
*/
|
|
448
|
+
warnings: DbSubstrateWarning[];
|
|
449
|
+
}
|
|
450
|
+
|
|
289
451
|
/**
|
|
290
452
|
* One line appended to `.cleo/audit/worktree-prune.jsonl` per prune
|
|
291
453
|
* operation. Extends the existing audit-log schema (timestamp +
|
package/src/index.ts
CHANGED
|
@@ -140,10 +140,13 @@ export type {
|
|
|
140
140
|
export { BOUNDARY_REGISTRY } from './boundary.js';
|
|
141
141
|
// === Brain/Memory Types ===
|
|
142
142
|
export type {
|
|
143
|
+
BackupRecoverBrainResult,
|
|
143
144
|
BrainCognitiveType,
|
|
144
145
|
BrainEntryRef,
|
|
145
146
|
BrainEntrySummary,
|
|
146
147
|
BrainMemoryTier,
|
|
148
|
+
BrainRecoveredRowCounts,
|
|
149
|
+
BrainRecoveryResult,
|
|
147
150
|
BrainSourceConfidence,
|
|
148
151
|
ContradictionDetail,
|
|
149
152
|
SupersededEntry,
|
|
@@ -271,6 +274,15 @@ export type {
|
|
|
271
274
|
TaskQueryFilters,
|
|
272
275
|
TransactionAccessor,
|
|
273
276
|
} from './data-accessor.js';
|
|
277
|
+
// === Database Inventory (Saga T10281 / Epic T10282 / Task T10305 — SG-BRAIN-DB-RESILIENCE) ===
|
|
278
|
+
export type {
|
|
279
|
+
DbConcurrency,
|
|
280
|
+
DbInventoryEntry,
|
|
281
|
+
DbPrivacy,
|
|
282
|
+
DbRole,
|
|
283
|
+
DbTier,
|
|
284
|
+
} from './db-inventory.js';
|
|
285
|
+
export { DB_INVENTORY } from './db-inventory.js';
|
|
274
286
|
// === Dependency Registry Contracts ===
|
|
275
287
|
export type {
|
|
276
288
|
DependencyCategory,
|
|
@@ -313,8 +325,15 @@ export {
|
|
|
313
325
|
} from './docs-taxonomy.js';
|
|
314
326
|
// === Doctor: Worktree-Orphan Audit + Prune Types (T9790, T9808, T9962) ===
|
|
315
327
|
// === Doctor: Saga Hierarchy Audit (T10119 — ADR-073 §1.2) ===
|
|
328
|
+
// === Doctor: DB-Substrate Survey (T10307 — Saga T10281 / Epic T10282) ===
|
|
316
329
|
export type {
|
|
317
330
|
ComprehensiveAuditResult,
|
|
331
|
+
DbSubstrateAuditResult,
|
|
332
|
+
DbSubstrateEntry,
|
|
333
|
+
DbSubstrateProjectSurvey,
|
|
334
|
+
DbSubstrateSummary,
|
|
335
|
+
DbSubstrateWarning,
|
|
336
|
+
DbSubstrateWarningKind,
|
|
318
337
|
OrphanEntry,
|
|
319
338
|
OrphanScanResult,
|
|
320
339
|
PruneAuditEntry,
|
package/src/operations/tasks.ts
CHANGED
|
@@ -24,7 +24,7 @@ import type { TaskAnalysisResult, TaskRef } from '../results.js';
|
|
|
24
24
|
* Common task types (API contract — matches CLI src/types/task.ts)
|
|
25
25
|
*/
|
|
26
26
|
import type { TaskStatus } from '../status-registry.js';
|
|
27
|
-
import type { TaskPriority } from '../task.js';
|
|
27
|
+
import type { TaskPriority, TaskType } from '../task.js';
|
|
28
28
|
import type { TaskRecord } from '../task-record.js';
|
|
29
29
|
import type { ExternalTask, ExternalTaskLink, ReconcileResult } from '../task-sync.js';
|
|
30
30
|
import type {
|
|
@@ -725,7 +725,7 @@ export interface TasksAddBatchParams {
|
|
|
725
725
|
depends?: string[];
|
|
726
726
|
priority?: string;
|
|
727
727
|
labels?: string[];
|
|
728
|
-
type?:
|
|
728
|
+
type?: TaskType; // SSoT-EXEMPT:kind≠type — 'type' is hierarchy(saga|epic|task|subtask), 'kind' is intent(work|bug|...) — separate axes T944 // ssot-exempt-ok: pre-existing exempt, narrowed string→TaskType (T10328)
|
|
729
729
|
acceptance?: string[];
|
|
730
730
|
phase?: string;
|
|
731
731
|
size?: string;
|
|
@@ -768,7 +768,7 @@ export interface TasksAddParams {
|
|
|
768
768
|
depends?: string[];
|
|
769
769
|
priority?: string;
|
|
770
770
|
labels?: string[];
|
|
771
|
-
type?:
|
|
771
|
+
type?: TaskType; // SSoT-EXEMPT:kind≠type — 'type' is hierarchy(saga|epic|task|subtask), 'kind' is intent(work|bug|...) — separate axes T944 // ssot-exempt-ok: pre-existing exempt, narrowed string→TaskType (T10328)
|
|
772
772
|
acceptance?: string[];
|
|
773
773
|
phase?: string;
|
|
774
774
|
size?: string;
|
|
@@ -824,7 +824,7 @@ export interface TasksUpdateQueryParams {
|
|
|
824
824
|
acceptance?: string[];
|
|
825
825
|
/** Canonical wire field for parent task ID. @see ADR-057 D2 */
|
|
826
826
|
parent?: string | null;
|
|
827
|
-
type?:
|
|
827
|
+
type?: TaskType; // SSoT-EXEMPT:kind≠type — 'type' is hierarchy(saga|epic|task|subtask), 'kind' is intent(work|bug|...) — separate axes T944 // ssot-exempt-ok: pre-existing exempt, narrowed string→TaskType (T10328)
|
|
828
828
|
size?: string;
|
|
829
829
|
files?: string[];
|
|
830
830
|
/** Add files incrementally (mirrors --add-labels pattern). @task T9242 */
|
package/src/task.ts
CHANGED
|
@@ -41,8 +41,19 @@ export type AcceptanceItem = string | AcceptanceGate;
|
|
|
41
41
|
/** Task priority levels. */
|
|
42
42
|
export type TaskPriority = 'critical' | 'high' | 'medium' | 'low';
|
|
43
43
|
|
|
44
|
-
/**
|
|
45
|
-
|
|
44
|
+
/**
|
|
45
|
+
* Task type in hierarchy.
|
|
46
|
+
*
|
|
47
|
+
* Per ADR-083 §2.5, `'saga'` is a first-class tier discriminator above
|
|
48
|
+
* Epic — a Saga groups N Epics across multiple releases. Hierarchy is now
|
|
49
|
+
* Saga (depth 0) → Epic (1) → Task (2) → Subtask (3), with `maxDepth=3`
|
|
50
|
+
* preserved under each Saga member.
|
|
51
|
+
*
|
|
52
|
+
* @adr ADR-083 §2.5
|
|
53
|
+
* @saga T10326
|
|
54
|
+
* @task T10328
|
|
55
|
+
*/
|
|
56
|
+
export type TaskType = 'saga' | 'epic' | 'task' | 'subtask';
|
|
46
57
|
|
|
47
58
|
/**
|
|
48
59
|
* Task kind axis — orthogonal to {@link TaskType}, describes the intent of work.
|