@cleocode/contracts 2026.5.130 → 2026.5.132
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__/atomic-tools-contract.test.d.ts +14 -0
- package/dist/__tests__/atomic-tools-contract.test.d.ts.map +1 -0
- package/dist/__tests__/atomic-tools-contract.test.js +55 -0
- package/dist/__tests__/atomic-tools-contract.test.js.map +1 -0
- package/dist/__tests__/gateway-contract.test.d.ts +18 -0
- package/dist/__tests__/gateway-contract.test.d.ts.map +1 -0
- package/dist/__tests__/gateway-contract.test.js +187 -0
- package/dist/__tests__/gateway-contract.test.js.map +1 -0
- package/dist/__tests__/mvi.test.d.ts +17 -0
- package/dist/__tests__/mvi.test.d.ts.map +1 -0
- package/dist/__tests__/mvi.test.js +147 -0
- package/dist/__tests__/mvi.test.js.map +1 -0
- package/dist/__tests__/operation-def.test.js +1 -1
- package/dist/__tests__/operation-def.test.js.map +1 -1
- package/dist/boundary.d.ts +26 -0
- package/dist/boundary.d.ts.map +1 -1
- package/dist/boundary.js +44 -6
- package/dist/boundary.js.map +1 -1
- package/dist/branch-lock.d.ts +35 -1
- package/dist/branch-lock.d.ts.map +1 -1
- package/dist/branch-lock.js +23 -2
- package/dist/branch-lock.js.map +1 -1
- package/dist/daemon/__tests__/health-roundtrip.test.d.ts +13 -0
- package/dist/daemon/__tests__/health-roundtrip.test.d.ts.map +1 -0
- package/dist/daemon/__tests__/health-roundtrip.test.js +69 -0
- package/dist/daemon/__tests__/health-roundtrip.test.js.map +1 -0
- package/dist/daemon/health.d.ts +108 -0
- package/dist/daemon/health.d.ts.map +1 -0
- package/dist/daemon/health.js +95 -0
- package/dist/daemon/health.js.map +1 -0
- package/dist/daemon/index.d.ts +24 -0
- package/dist/daemon/index.d.ts.map +1 -0
- package/dist/daemon/index.js +22 -0
- package/dist/daemon/index.js.map +1 -0
- package/dist/daemon/subsystem.d.ts +121 -0
- package/dist/daemon/subsystem.d.ts.map +1 -0
- package/dist/daemon/subsystem.js +28 -0
- package/dist/daemon/subsystem.js.map +1 -0
- package/dist/daemon-ipc/__tests__/daemon-ipc-freeze.test.d.ts +15 -0
- package/dist/daemon-ipc/__tests__/daemon-ipc-freeze.test.d.ts.map +1 -0
- package/dist/daemon-ipc/__tests__/daemon-ipc-freeze.test.js +40 -0
- package/dist/daemon-ipc/__tests__/daemon-ipc-freeze.test.js.map +1 -0
- package/dist/daemon-ipc/index.d.ts +44 -0
- package/dist/daemon-ipc/index.d.ts.map +1 -0
- package/dist/daemon-ipc/index.js +43 -0
- package/dist/daemon-ipc/index.js.map +1 -0
- package/dist/db-inventory.json +8 -8
- package/dist/dispatch/identity.d.ts +1 -1
- package/dist/dispatch/identity.d.ts.map +1 -1
- package/dist/dispatch/identity.js +3 -0
- package/dist/dispatch/identity.js.map +1 -1
- package/dist/dispatch/operation-def.d.ts +16 -0
- package/dist/dispatch/operation-def.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.d.ts.map +1 -1
- package/dist/dispatch/operations-registry.js +133 -0
- package/dist/dispatch/operations-registry.js.map +1 -1
- package/dist/exit-codes.d.ts +1 -1
- package/dist/exit-codes.js +1 -1
- package/dist/gateway/rpc/__tests__/freeze.test.d.ts +20 -0
- package/dist/gateway/rpc/__tests__/freeze.test.d.ts.map +1 -0
- package/dist/gateway/rpc/__tests__/freeze.test.js +122 -0
- package/dist/gateway/rpc/__tests__/freeze.test.js.map +1 -0
- package/dist/gateway/rpc/index.d.ts +23 -0
- package/dist/gateway/rpc/index.d.ts.map +1 -0
- package/dist/gateway/rpc/index.js +22 -0
- package/dist/gateway/rpc/index.js.map +1 -0
- package/dist/gateway/rpc/messages.d.ts +263 -0
- package/dist/gateway/rpc/messages.d.ts.map +1 -0
- package/dist/gateway/rpc/messages.js +152 -0
- package/dist/gateway/rpc/messages.js.map +1 -0
- package/dist/gateway/rpc/version.d.ts +39 -0
- package/dist/gateway/rpc/version.d.ts.map +1 -0
- package/dist/gateway/rpc/version.js +39 -0
- package/dist/gateway/rpc/version.js.map +1 -0
- package/dist/gateway.d.ts +239 -0
- package/dist/gateway.d.ts.map +1 -0
- package/dist/gateway.js +171 -0
- package/dist/gateway.js.map +1 -0
- package/dist/goal.d.ts +314 -0
- package/dist/goal.d.ts.map +1 -0
- package/dist/goal.js +118 -0
- package/dist/goal.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -1
- package/dist/mvi.d.ts +209 -0
- package/dist/mvi.d.ts.map +1 -0
- package/dist/mvi.js +99 -0
- package/dist/mvi.js.map +1 -0
- package/dist/operations/attention.d.ts +114 -0
- package/dist/operations/attention.d.ts.map +1 -0
- package/dist/operations/attention.js +22 -0
- package/dist/operations/attention.js.map +1 -0
- package/dist/operations/focus.d.ts +25 -0
- package/dist/operations/focus.d.ts.map +1 -1
- package/dist/operations/index.d.ts +1 -0
- package/dist/operations/index.d.ts.map +1 -1
- package/dist/operations/index.js +1 -0
- package/dist/operations/index.js.map +1 -1
- package/dist/operations/session.d.ts +11 -0
- package/dist/operations/session.d.ts.map +1 -1
- package/dist/release/evidence-atoms.d.ts +3 -2
- package/dist/release/evidence-atoms.d.ts.map +1 -1
- package/dist/release/evidence-atoms.js +3 -2
- package/dist/release/evidence-atoms.js.map +1 -1
- package/dist/sdk-tool.d.ts +1 -1
- package/dist/sdk-tool.js +1 -1
- package/dist/supervisor-ipc/__tests__/freeze.test.d.ts +15 -0
- package/dist/supervisor-ipc/__tests__/freeze.test.d.ts.map +1 -0
- package/dist/supervisor-ipc/__tests__/freeze.test.js +159 -0
- package/dist/supervisor-ipc/__tests__/freeze.test.js.map +1 -0
- package/dist/supervisor-ipc/index.d.ts +15 -0
- package/dist/supervisor-ipc/index.d.ts.map +1 -0
- package/dist/supervisor-ipc/index.js +14 -0
- package/dist/supervisor-ipc/index.js.map +1 -0
- package/dist/supervisor-ipc/messages.d.ts +457 -0
- package/dist/supervisor-ipc/messages.d.ts.map +1 -0
- package/dist/supervisor-ipc/messages.js +312 -0
- package/dist/supervisor-ipc/messages.js.map +1 -0
- package/dist/supervisor-ipc/version.d.ts +29 -0
- package/dist/supervisor-ipc/version.d.ts.map +1 -0
- package/dist/supervisor-ipc/version.js +29 -0
- package/dist/supervisor-ipc/version.js.map +1 -0
- package/dist/task.d.ts +5 -5
- package/dist/tools/__tests__/composite.test.d.ts +14 -0
- package/dist/tools/__tests__/composite.test.d.ts.map +1 -0
- package/dist/tools/__tests__/composite.test.js +75 -0
- package/dist/tools/__tests__/composite.test.js.map +1 -0
- package/dist/tools/atomic.d.ts +195 -0
- package/dist/tools/atomic.d.ts.map +1 -0
- package/dist/tools/atomic.js +82 -0
- package/dist/tools/atomic.js.map +1 -0
- package/dist/tools/composite.d.ts +128 -0
- package/dist/tools/composite.d.ts.map +1 -0
- package/dist/tools/composite.js +88 -0
- package/dist/tools/composite.js.map +1 -0
- package/package.json +34 -2
- package/src/__tests__/__snapshots__/operations-registry.test.ts.snap +1 -1
- package/src/__tests__/atomic-tools-contract.test.ts +67 -0
- package/src/__tests__/gateway-contract.test.ts +219 -0
- package/src/__tests__/mvi.test.ts +175 -0
- package/src/__tests__/operation-def.test.ts +2 -1
- package/src/boundary.ts +76 -6
- package/src/branch-lock.ts +49 -2
- package/src/daemon/__tests__/health-roundtrip.test.ts +84 -0
- package/src/daemon/health.ts +121 -0
- package/src/daemon/index.ts +35 -0
- package/src/daemon/subsystem.ts +126 -0
- package/src/daemon-ipc/__tests__/daemon-ipc-freeze.test.ts +53 -0
- package/src/daemon-ipc/index.ts +90 -0
- package/src/db-inventory.json +8 -8
- package/src/dispatch/identity.ts +3 -0
- package/src/dispatch/operation-def.ts +16 -0
- package/src/dispatch/operations-registry.ts +140 -0
- package/src/exit-codes.ts +1 -1
- package/src/gateway/rpc/__tests__/freeze.test.ts +139 -0
- package/src/gateway/rpc/index.ts +43 -0
- package/src/gateway/rpc/messages.ts +187 -0
- package/src/gateway/rpc/version.ts +40 -0
- package/src/gateway.ts +252 -0
- package/src/goal.ts +348 -0
- package/src/index.ts +109 -0
- package/src/mvi.ts +236 -0
- package/src/operations/attention.ts +117 -0
- package/src/operations/focus.ts +26 -0
- package/src/operations/index.ts +1 -0
- package/src/operations/session.ts +11 -0
- package/src/release/evidence-atoms.ts +3 -2
- package/src/sdk-tool.ts +1 -1
- package/src/supervisor-ipc/__tests__/freeze.test.ts +180 -0
- package/src/supervisor-ipc/index.ts +62 -0
- package/src/supervisor-ipc/messages.ts +396 -0
- package/src/supervisor-ipc/version.ts +30 -0
- package/src/task.ts +5 -5
- package/src/tools/__tests__/composite.test.ts +88 -0
- package/src/tools/atomic.ts +274 -0
- package/src/tools/composite.ts +173 -0
package/src/branch-lock.ts
CHANGED
|
@@ -309,13 +309,23 @@ export type BranchLockErrorCode =
|
|
|
309
309
|
* Exported as a frozen const tuple so git-shim, harness adapters, and test
|
|
310
310
|
* utilities can reference the authoritative key list without duplication.
|
|
311
311
|
*
|
|
312
|
+
* `CLEO_SESSION_ID` + `CLEO_AGENT_ID` were added in T11343 (Epic T11284,
|
|
313
|
+
* SG-COGNITIVE-SUBSTRATE) so every spawned agent carries its OWN session and
|
|
314
|
+
* agent identity into the isolation shell. Before this, spawn injected only
|
|
315
|
+
* worktree-binding keys and every short-lived `cleo` call inside the worktree
|
|
316
|
+
* collapsed onto "whoever touched the DB last" via `getActiveSession()` —
|
|
317
|
+
* the root cause of multi-agent session-bleed AND memory scope-leakage.
|
|
318
|
+
*
|
|
312
319
|
* @task T1759
|
|
320
|
+
* @task T11343
|
|
313
321
|
*/
|
|
314
322
|
export const ISOLATION_ENV_KEYS = [
|
|
315
323
|
'CLEO_WORKTREE_ROOT',
|
|
316
324
|
'CLEO_AGENT_ROLE',
|
|
317
325
|
'CLEO_WORKTREE_BRANCH',
|
|
318
326
|
'CLEO_PROJECT_HASH',
|
|
327
|
+
'CLEO_SESSION_ID',
|
|
328
|
+
'CLEO_AGENT_ID',
|
|
319
329
|
] as const satisfies readonly string[];
|
|
320
330
|
|
|
321
331
|
/** Union of all isolation env key strings. */
|
|
@@ -402,6 +412,32 @@ export interface IsolationOptions {
|
|
|
402
412
|
role: 'worker' | 'orchestrator';
|
|
403
413
|
/** Project hash scoping this worktree under the XDG root (sha256(projectRoot)[:16]). */
|
|
404
414
|
projectHash: string;
|
|
415
|
+
/**
|
|
416
|
+
* Per-agent CLEO session id to bind to the isolation shell (T11343).
|
|
417
|
+
*
|
|
418
|
+
* Injected as `CLEO_SESSION_ID` so every short-lived `cleo` call inside the
|
|
419
|
+
* worktree resolves THIS agent's session via `resolveSessionIdFromEnv()`
|
|
420
|
+
* rather than collapsing onto the orchestrator's most-recent active row.
|
|
421
|
+
* When omitted, `CLEO_SESSION_ID` is set to the empty string and downstream
|
|
422
|
+
* resolution falls back to the legacy `getActiveSession()` path (backward
|
|
423
|
+
* compatible — no behaviour change for callers that do not yet allocate a
|
|
424
|
+
* per-agent session).
|
|
425
|
+
*
|
|
426
|
+
* @defaultValue '' (empty — falls back to active-session resolution)
|
|
427
|
+
* @task T11343
|
|
428
|
+
*/
|
|
429
|
+
sessionId?: string;
|
|
430
|
+
/**
|
|
431
|
+
* Per-agent identity handle to bind to the isolation shell (T11343).
|
|
432
|
+
*
|
|
433
|
+
* Injected as `CLEO_AGENT_ID` so audit rows, conduit messages, and memory
|
|
434
|
+
* observations are attributed to the spawned agent rather than to the
|
|
435
|
+
* orchestrator. When omitted, `CLEO_AGENT_ID` is set to the empty string.
|
|
436
|
+
*
|
|
437
|
+
* @defaultValue '' (empty — no per-agent attribution)
|
|
438
|
+
* @task T11343
|
|
439
|
+
*/
|
|
440
|
+
agentId?: string;
|
|
405
441
|
}
|
|
406
442
|
|
|
407
443
|
/**
|
|
@@ -468,17 +504,23 @@ export interface IsolationResult {
|
|
|
468
504
|
* @task T1759
|
|
469
505
|
*/
|
|
470
506
|
export function provisionIsolatedShell(options: IsolationOptions): IsolationResult {
|
|
471
|
-
const { worktreePath, branch, role, projectHash } = options;
|
|
507
|
+
const { worktreePath, branch, role, projectHash, sessionId, agentId } = options;
|
|
472
508
|
|
|
473
509
|
// --- cwd -----------------------------------------------------------------
|
|
474
510
|
const cwd = worktreePath;
|
|
475
511
|
|
|
476
512
|
// --- env -----------------------------------------------------------------
|
|
513
|
+
// T11343: CLEO_SESSION_ID + CLEO_AGENT_ID bind the spawned agent's own
|
|
514
|
+
// identity into the shell. Empty-string default keeps backward compatibility
|
|
515
|
+
// — `resolveSessionIdFromEnv()` treats '' as absent and falls back to the
|
|
516
|
+
// legacy active-session resolution path.
|
|
477
517
|
const env: Record<(typeof ISOLATION_ENV_KEYS)[number], string> = {
|
|
478
518
|
CLEO_WORKTREE_ROOT: worktreePath,
|
|
479
519
|
CLEO_AGENT_ROLE: role,
|
|
480
520
|
CLEO_WORKTREE_BRANCH: branch,
|
|
481
521
|
CLEO_PROJECT_HASH: projectHash,
|
|
522
|
+
CLEO_SESSION_ID: sessionId ?? '',
|
|
523
|
+
CLEO_AGENT_ID: agentId ?? '',
|
|
482
524
|
};
|
|
483
525
|
|
|
484
526
|
// --- preamble ------------------------------------------------------------
|
|
@@ -487,7 +529,12 @@ export function provisionIsolatedShell(options: IsolationOptions): IsolationResu
|
|
|
487
529
|
// - The worktree directory having been pruned before the agent starts.
|
|
488
530
|
// - A future change where cwd is silently coerced to something else.
|
|
489
531
|
// - Symlink traversal producing a path that doesn't share the prefix.
|
|
490
|
-
|
|
532
|
+
// T11343: skip empty values so an unallocated CLEO_SESSION_ID / CLEO_AGENT_ID
|
|
533
|
+
// does not emit a clobbering `export KEY=""` that would clear an inherited
|
|
534
|
+
// value. Worktree-binding keys are always non-empty so they always export.
|
|
535
|
+
const exportBlock = ISOLATION_ENV_KEYS.filter((k) => env[k] !== '')
|
|
536
|
+
.map((k) => `export ${k}="${env[k]}"`)
|
|
537
|
+
.join('\n');
|
|
491
538
|
|
|
492
539
|
const preamble = [
|
|
493
540
|
'## Worktree Isolation (REQUIRED — do not skip)',
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Round-trip guard for the daemon health contracts (T11366 AC5).
|
|
3
|
+
*
|
|
4
|
+
* Proves a {@link HealthStatus} aggregate projects onto the FROZEN
|
|
5
|
+
* `supervisor-ipc` {@link MonitorResponseSchema} shape **without a lossy cast**:
|
|
6
|
+
* `toMonitorChildren` yields rows that validate against the supervisor's own
|
|
7
|
+
* `MonitorResponse.children` schema, and a `monitor` response carrying them
|
|
8
|
+
* round-trips through `MonitorResponseSchema.parse`.
|
|
9
|
+
*
|
|
10
|
+
* @task T11366
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import { describe, expect, it } from 'vitest';
|
|
14
|
+
import {
|
|
15
|
+
type HealthStatus,
|
|
16
|
+
MonitorResponseSchema,
|
|
17
|
+
type SubsystemHealth,
|
|
18
|
+
SubsystemHealthSchema,
|
|
19
|
+
summarizeHealth,
|
|
20
|
+
toMonitorChildren,
|
|
21
|
+
} from '../../index.js';
|
|
22
|
+
|
|
23
|
+
describe('daemon HealthStatus ↔ supervisor-ipc MonitorResponse (T11366)', () => {
|
|
24
|
+
const rows: SubsystemHealth[] = [
|
|
25
|
+
{ child_id: 'studio', pid: 4242, state: 'running', restart_count: 0 },
|
|
26
|
+
{
|
|
27
|
+
child_id: 'gc-cron',
|
|
28
|
+
pid: 0,
|
|
29
|
+
state: 'stopped',
|
|
30
|
+
restart_count: 2,
|
|
31
|
+
detail: 'awaiting next scheduled run',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
35
|
+
it('summarizeHealth computes allHealthy from row states', () => {
|
|
36
|
+
expect(summarizeHealth(rows).allHealthy).toBe(false);
|
|
37
|
+
expect(
|
|
38
|
+
summarizeHealth([{ child_id: 'studio', pid: 1, state: 'running', restart_count: 0 }])
|
|
39
|
+
.allHealthy,
|
|
40
|
+
).toBe(true);
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
it('toMonitorChildren projects onto MonitorResponse.children without lossy casts', () => {
|
|
44
|
+
const health: HealthStatus = summarizeHealth(rows);
|
|
45
|
+
const children = toMonitorChildren(health);
|
|
46
|
+
|
|
47
|
+
// Each projected row must validate against the FROZEN supervisor schema.
|
|
48
|
+
const monitor = {
|
|
49
|
+
kind: 'monitor' as const,
|
|
50
|
+
children,
|
|
51
|
+
};
|
|
52
|
+
const parsed = MonitorResponseSchema.safeParse(monitor);
|
|
53
|
+
expect(parsed.success).toBe(true);
|
|
54
|
+
if (parsed.success) {
|
|
55
|
+
expect(parsed.data.children).toHaveLength(2);
|
|
56
|
+
// The daemon-only `detail` field is stripped on projection.
|
|
57
|
+
expect(parsed.data.children[1]).not.toHaveProperty('detail');
|
|
58
|
+
expect(parsed.data.children[0]?.child_id).toBe('studio');
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
it('a SubsystemHealth row is a structural superset of a supervisor ChildStatus', () => {
|
|
63
|
+
// Validating with the daemon schema accepts the supervisor fields verbatim.
|
|
64
|
+
const row = SubsystemHealthSchema.parse({
|
|
65
|
+
child_id: 'web',
|
|
66
|
+
pid: 9000,
|
|
67
|
+
state: 'running',
|
|
68
|
+
restart_count: 0,
|
|
69
|
+
});
|
|
70
|
+
expect(row.child_id).toBe('web');
|
|
71
|
+
// detail is optional and absent here.
|
|
72
|
+
expect(row.detail).toBeUndefined();
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('rejects a health row with a state outside the frozen ChildState enum', () => {
|
|
76
|
+
const bad = SubsystemHealthSchema.safeParse({
|
|
77
|
+
child_id: 'x',
|
|
78
|
+
pid: 0,
|
|
79
|
+
state: 'paused',
|
|
80
|
+
restart_count: 0,
|
|
81
|
+
});
|
|
82
|
+
expect(bad.success).toBe(false);
|
|
83
|
+
});
|
|
84
|
+
});
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon health contracts — the aggregate shape a subsystem's `healthProbe`
|
|
3
|
+
* produces and the Rust supervisor consumes.
|
|
4
|
+
*
|
|
5
|
+
* These types **compose** the FROZEN `supervisor-ipc` v1.0 contract
|
|
6
|
+
* ({@link ChildState}, {@link ChildStatus}, {@link MonitorResponse}) rather than
|
|
7
|
+
* redeclaring it: a single subsystem health row maps onto a supervised
|
|
8
|
+
* {@link ChildStatus}, and a {@link HealthStatus} aggregate projects losslessly
|
|
9
|
+
* onto the {@link MonitorResponse} shape the supervisor already aggregates. This
|
|
10
|
+
* keeps the daemon submodule's probe output on the same wire vocabulary the
|
|
11
|
+
* supervisor monitors with — no parallel health taxonomy.
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
* @module @cleocode/contracts/daemon
|
|
15
|
+
*
|
|
16
|
+
* @epic T11253 R2 — `@cleocode/runtime/daemon` submodule
|
|
17
|
+
* @task T11366 — daemon lifecycle + subsystem contracts
|
|
18
|
+
* @saga T11243 SG-RUNTIME-UNIFICATION
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
import { z } from 'zod';
|
|
22
|
+
import {
|
|
23
|
+
type ChildState,
|
|
24
|
+
ChildStateSchema,
|
|
25
|
+
type ChildStatus,
|
|
26
|
+
ChildStatusSchema,
|
|
27
|
+
} from '../supervisor-ipc/messages.js';
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* The liveness state of a single subsystem.
|
|
31
|
+
*
|
|
32
|
+
* This is the FROZEN `supervisor-ipc` {@link ChildState} (`running` |
|
|
33
|
+
* `restarting` | `stopped`) re-exported under a daemon-facing name so subsystem
|
|
34
|
+
* authors do not reach across into the IPC module. A subsystem maps onto a
|
|
35
|
+
* supervised child, so the two states are deliberately identical.
|
|
36
|
+
*/
|
|
37
|
+
export type SubsystemState = ChildState;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Zod schema for {@link SubsystemState}. Aliases the FROZEN
|
|
41
|
+
* {@link ChildStateSchema} — additive only; never edit the underlying enum.
|
|
42
|
+
*/
|
|
43
|
+
export const SubsystemStateSchema = ChildStateSchema;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A single subsystem's health row.
|
|
47
|
+
*
|
|
48
|
+
* Structurally a superset of the supervisor's {@link ChildStatus}: it carries
|
|
49
|
+
* the same `child_id`/`pid`/`state`/`restart_count` fields (so it projects onto
|
|
50
|
+
* a {@link ChildStatus} without a lossy cast) plus an optional human-readable
|
|
51
|
+
* `detail` for diagnostics that never crosses the IPC wire.
|
|
52
|
+
*
|
|
53
|
+
* The `child_id` is the subsystem's logical name, matching the id the
|
|
54
|
+
* supervisor tracks the corresponding child under.
|
|
55
|
+
*/
|
|
56
|
+
export const SubsystemHealthSchema = ChildStatusSchema.extend({
|
|
57
|
+
/**
|
|
58
|
+
* Optional human-readable detail (e.g. last error message, queue depth).
|
|
59
|
+
* Diagnostic only — not part of the supervisor wire contract.
|
|
60
|
+
*/
|
|
61
|
+
detail: z.string().optional(),
|
|
62
|
+
}).strict();
|
|
63
|
+
|
|
64
|
+
/** A single subsystem's health row (inferred from {@link SubsystemHealthSchema}). */
|
|
65
|
+
export type SubsystemHealth = z.infer<typeof SubsystemHealthSchema>;
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The aggregate health snapshot across every registered subsystem.
|
|
69
|
+
*
|
|
70
|
+
* Projects losslessly onto the supervisor's `monitor` snapshot: each
|
|
71
|
+
* {@link SubsystemHealth} row's supervisor-visible fields ARE a
|
|
72
|
+
* {@link ChildStatus}, so {@link toMonitorChildren} can hand the supervisor a
|
|
73
|
+
* `MonitorResponse.children` array with zero casts.
|
|
74
|
+
*/
|
|
75
|
+
export const HealthStatusSchema = z
|
|
76
|
+
.object({
|
|
77
|
+
/** One health row per registered subsystem. */
|
|
78
|
+
subsystems: z.array(SubsystemHealthSchema),
|
|
79
|
+
/**
|
|
80
|
+
* `true` iff every subsystem is in the `running` state. A convenience roll-up
|
|
81
|
+
* derived from {@link HealthStatusSchema.shape.subsystems}; recomputed by
|
|
82
|
+
* {@link summarizeHealth} so producers cannot desync it.
|
|
83
|
+
*/
|
|
84
|
+
allHealthy: z.boolean(),
|
|
85
|
+
})
|
|
86
|
+
.strict();
|
|
87
|
+
|
|
88
|
+
/** The aggregate daemon health snapshot (inferred from {@link HealthStatusSchema}). */
|
|
89
|
+
export type HealthStatus = z.infer<typeof HealthStatusSchema>;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Project a {@link HealthStatus} onto the FROZEN supervisor `monitor` row array
|
|
93
|
+
* (`MonitorResponse['children']`) without a lossy cast.
|
|
94
|
+
*
|
|
95
|
+
* Each {@link SubsystemHealth} already carries the four supervisor-visible
|
|
96
|
+
* fields of a {@link ChildStatus}; this strips the daemon-only `detail` so the
|
|
97
|
+
* result is byte-compatible with what `cleo-supervisor` aggregates.
|
|
98
|
+
*
|
|
99
|
+
* @param health - The aggregate daemon health snapshot.
|
|
100
|
+
* @returns An array of {@link ChildStatus} rows for a `MonitorResponse`.
|
|
101
|
+
*/
|
|
102
|
+
export function toMonitorChildren(health: HealthStatus): ChildStatus[] {
|
|
103
|
+
return health.subsystems.map((row): ChildStatus => {
|
|
104
|
+
const { detail: _detail, ...childStatus } = row;
|
|
105
|
+
return childStatus;
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* Build the aggregate {@link HealthStatus} from per-subsystem rows, computing
|
|
111
|
+
* the `allHealthy` roll-up so it can never desync from the row states.
|
|
112
|
+
*
|
|
113
|
+
* @param subsystems - One {@link SubsystemHealth} row per registered subsystem.
|
|
114
|
+
* @returns The aggregate health snapshot.
|
|
115
|
+
*/
|
|
116
|
+
export function summarizeHealth(subsystems: SubsystemHealth[]): HealthStatus {
|
|
117
|
+
return {
|
|
118
|
+
subsystems,
|
|
119
|
+
allHealthy: subsystems.every((row) => row.state === 'running'),
|
|
120
|
+
};
|
|
121
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@cleocode/contracts/daemon` — daemon lifecycle + subsystem type contracts.
|
|
3
|
+
*
|
|
4
|
+
* The shared, IO-free type vocabulary for the `@cleocode/runtime/daemon`
|
|
5
|
+
* submodule (R2, T11253): the {@link Subsystem} descriptor, the typed
|
|
6
|
+
* {@link DaemonLifecycleHooks}, and the {@link HealthStatus} aggregate that
|
|
7
|
+
* composes the FROZEN `supervisor-ipc` v1.0 contract.
|
|
8
|
+
*
|
|
9
|
+
* The implementation (`defineSubsystem`, registry, NDJSON client) lives in
|
|
10
|
+
* `@cleocode/runtime/daemon` and consumes these types — never redeclares them
|
|
11
|
+
* (Contracts Fan-Out gate, T10074).
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
* @module @cleocode/contracts/daemon
|
|
15
|
+
*
|
|
16
|
+
* @epic T11253 R2 — `@cleocode/runtime/daemon` submodule
|
|
17
|
+
* @task T11366 — daemon lifecycle + subsystem contracts
|
|
18
|
+
* @saga T11243 SG-RUNTIME-UNIFICATION
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
export type { HealthStatus, SubsystemHealth, SubsystemState } from './health.js';
|
|
22
|
+
export {
|
|
23
|
+
HealthStatusSchema,
|
|
24
|
+
SubsystemHealthSchema,
|
|
25
|
+
SubsystemStateSchema,
|
|
26
|
+
summarizeHealth,
|
|
27
|
+
toMonitorChildren,
|
|
28
|
+
} from './health.js';
|
|
29
|
+
export type {
|
|
30
|
+
DaemonLifecycleHooks,
|
|
31
|
+
Subsystem,
|
|
32
|
+
SubsystemDefinition,
|
|
33
|
+
SubsystemLifecyclePhase,
|
|
34
|
+
} from './subsystem.js';
|
|
35
|
+
export { SUBSYSTEM_LIFECYCLE_PHASES } from './subsystem.js';
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Daemon subsystem + lifecycle-hook contracts.
|
|
3
|
+
*
|
|
4
|
+
* A **subsystem** is one supervised unit of long-running work inside a CLEO
|
|
5
|
+
* daemon process — Studio supervision, the GC cron, the web server, the
|
|
6
|
+
* docs-viewer, the runtime poller. Each declares a uniform lifecycle
|
|
7
|
+
* (`start → healthProbe → shutdown`) so the `@cleocode/runtime/daemon`
|
|
8
|
+
* registry can drive them identically and the Rust `cleo-supervisor` can
|
|
9
|
+
* aggregate their health over the FROZEN `supervisor-ipc` v1.0 contract.
|
|
10
|
+
*
|
|
11
|
+
* These are **pure type contracts** (no runtime/IO). The implementation —
|
|
12
|
+
* `defineSubsystem()`, the registry, the NDJSON client — lives in
|
|
13
|
+
* `@cleocode/runtime/daemon` (R2 child T11367) and imports these types rather
|
|
14
|
+
* than redeclaring them (Contracts Fan-Out gate, T10074).
|
|
15
|
+
*
|
|
16
|
+
* @packageDocumentation
|
|
17
|
+
* @module @cleocode/contracts/daemon
|
|
18
|
+
*
|
|
19
|
+
* @epic T11253 R2 — `@cleocode/runtime/daemon` submodule
|
|
20
|
+
* @task T11366 — daemon lifecycle + subsystem contracts
|
|
21
|
+
* @saga T11243 SG-RUNTIME-UNIFICATION
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
import type { SubsystemHealth } from './health.js';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Lifecycle hooks fired by the subsystem registry around a subsystem's
|
|
28
|
+
* `start`/`shutdown` transitions.
|
|
29
|
+
*
|
|
30
|
+
* All hooks are optional and may be async. They are observational — a hook
|
|
31
|
+
* MUST NOT mutate registry state. `onError` is the single failure sink: a
|
|
32
|
+
* throwing `start` or `shutdown`, or a rejected `healthProbe`, surfaces here.
|
|
33
|
+
*
|
|
34
|
+
* Hooks fire in a defined order relative to the underlying transition:
|
|
35
|
+
* - `onStart` — after the subsystem's `start()` resolves.
|
|
36
|
+
* - `onShutdown` — after the subsystem's `shutdown()` resolves.
|
|
37
|
+
* - `onError` — when any lifecycle step throws/rejects (start, probe, or
|
|
38
|
+
* shutdown), with the offending `error` and the `phase` it occurred in.
|
|
39
|
+
*/
|
|
40
|
+
export interface DaemonLifecycleHooks {
|
|
41
|
+
/**
|
|
42
|
+
* Fired after the subsystem has successfully started.
|
|
43
|
+
*
|
|
44
|
+
* @param name - The logical subsystem name.
|
|
45
|
+
*/
|
|
46
|
+
onStart?: (name: string) => void | Promise<void>;
|
|
47
|
+
/**
|
|
48
|
+
* Fired after the subsystem has successfully shut down.
|
|
49
|
+
*
|
|
50
|
+
* @param name - The logical subsystem name.
|
|
51
|
+
*/
|
|
52
|
+
onShutdown?: (name: string) => void | Promise<void>;
|
|
53
|
+
/**
|
|
54
|
+
* Fired when a lifecycle step throws or rejects. The single failure sink.
|
|
55
|
+
*
|
|
56
|
+
* @param name - The logical subsystem name.
|
|
57
|
+
* @param error - The thrown value, normalized to an `Error`.
|
|
58
|
+
* @param phase - Which lifecycle step failed.
|
|
59
|
+
*/
|
|
60
|
+
onError?: (name: string, error: Error, phase: SubsystemLifecyclePhase) => void | Promise<void>;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The lifecycle phase a subsystem transition is in, used to tag
|
|
65
|
+
* {@link DaemonLifecycleHooks.onError} and registry diagnostics.
|
|
66
|
+
*/
|
|
67
|
+
export type SubsystemLifecyclePhase = 'start' | 'healthProbe' | 'shutdown';
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The frozen, ordered set of lifecycle phases. Pinned by the daemon test suite
|
|
71
|
+
* so a phase cannot be silently added or removed.
|
|
72
|
+
*/
|
|
73
|
+
export const SUBSYSTEM_LIFECYCLE_PHASES = ['start', 'healthProbe', 'shutdown'] as const;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* A subsystem descriptor — the declarative unit `defineSubsystem()` produces
|
|
77
|
+
* and the registry drives.
|
|
78
|
+
*
|
|
79
|
+
* The three lifecycle methods are intentionally minimal and uniform so that
|
|
80
|
+
* every long-running concern (supervised child process, cron job, HTTP server)
|
|
81
|
+
* can be expressed identically:
|
|
82
|
+
*
|
|
83
|
+
* - `start` — bring the subsystem up. May be async. Idempotent callers
|
|
84
|
+
* should guard re-entry.
|
|
85
|
+
* - `healthProbe` — report current liveness as a {@link SubsystemHealth} row.
|
|
86
|
+
* Maps onto a supervised `ChildStatus` the Rust supervisor aggregates.
|
|
87
|
+
* - `shutdown` — bring the subsystem down gracefully. May be async.
|
|
88
|
+
*
|
|
89
|
+
* @typeParam TContext - Optional opaque context the registry threads through
|
|
90
|
+
* `start`/`shutdown` (e.g. a resolved config or handle). Defaults to `void`.
|
|
91
|
+
*/
|
|
92
|
+
export interface Subsystem<TContext = void> {
|
|
93
|
+
/** Logical, stable subsystem name (matches the supervised `child_id`). */
|
|
94
|
+
readonly name: string;
|
|
95
|
+
/**
|
|
96
|
+
* Bring the subsystem up. The resolved value is threaded back into
|
|
97
|
+
* `shutdown` as its context argument.
|
|
98
|
+
*
|
|
99
|
+
* @returns The subsystem context (or `void`).
|
|
100
|
+
*/
|
|
101
|
+
start: () => TContext | Promise<TContext>;
|
|
102
|
+
/**
|
|
103
|
+
* Report the subsystem's current health as a single
|
|
104
|
+
* {@link SubsystemHealth} row.
|
|
105
|
+
*
|
|
106
|
+
* @returns The current health row.
|
|
107
|
+
*/
|
|
108
|
+
healthProbe: () => SubsystemHealth | Promise<SubsystemHealth>;
|
|
109
|
+
/**
|
|
110
|
+
* Bring the subsystem down gracefully.
|
|
111
|
+
*
|
|
112
|
+
* @param context - The value returned by `start`.
|
|
113
|
+
*/
|
|
114
|
+
shutdown: (context: TContext) => void | Promise<void>;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* The descriptor passed to `defineSubsystem()` — the same surface as
|
|
119
|
+
* {@link Subsystem} (a 1:1 mapping; `defineSubsystem` validates + freezes it).
|
|
120
|
+
*
|
|
121
|
+
* Exposed as a distinct name so call-sites can annotate the literal they pass
|
|
122
|
+
* without importing the post-construction {@link Subsystem} type.
|
|
123
|
+
*
|
|
124
|
+
* @typeParam TContext - See {@link Subsystem}.
|
|
125
|
+
*/
|
|
126
|
+
export type SubsystemDefinition<TContext = void> = Subsystem<TContext>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Freeze + AC8-alias guard for the `@cleocode/contracts/daemon-ipc` surface
|
|
3
|
+
* (T11369 — R2 gates R4-R7).
|
|
4
|
+
*
|
|
5
|
+
* Proves the AC8-named `daemon-ipc` barrel:
|
|
6
|
+
* 1. resolves and re-exports the FROZEN supervisor-ipc v1.0 schemas + version,
|
|
7
|
+
* 2. is byte-identical to the `supervisor-ipc` surface (one contract, two
|
|
8
|
+
* names — no duplicate drift surface),
|
|
9
|
+
* 3. pins `DAEMON_IPC_PROTOCOL_VERSION === SUPERVISOR_IPC_PROTOCOL_VERSION ===
|
|
10
|
+
* '1.0.0'` and the complete frozen message-kind tuple.
|
|
11
|
+
*
|
|
12
|
+
* @task T11369
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { describe, expect, it } from 'vitest';
|
|
16
|
+
import {
|
|
17
|
+
SUPERVISOR_IPC_MESSAGE_KINDS,
|
|
18
|
+
SUPERVISOR_IPC_PROTOCOL_VERSION,
|
|
19
|
+
SupervisorIpcEnvelopeSchema as SupervisorEnvelopeFromRoot,
|
|
20
|
+
} from '../../supervisor-ipc/index.js';
|
|
21
|
+
import {
|
|
22
|
+
DAEMON_IPC_PROTOCOL_VERSION,
|
|
23
|
+
SUPERVISOR_IPC_MESSAGE_KINDS as MESSAGE_KINDS_VIA_DAEMON_IPC,
|
|
24
|
+
SupervisorIpcEnvelopeSchema as SupervisorEnvelopeFromDaemonIpc,
|
|
25
|
+
SUPERVISOR_IPC_PROTOCOL_VERSION as VERSION_VIA_DAEMON_IPC,
|
|
26
|
+
} from '../index.js';
|
|
27
|
+
|
|
28
|
+
describe('@cleocode/contracts/daemon-ipc AC8 alias surface (T11369)', () => {
|
|
29
|
+
it('re-exports the SAME frozen schema binding as supervisor-ipc', () => {
|
|
30
|
+
// Referential identity proves it is a re-export, not a duplicate schema.
|
|
31
|
+
expect(SupervisorEnvelopeFromDaemonIpc).toBe(SupervisorEnvelopeFromRoot);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
it('pins the frozen protocol version through both names', () => {
|
|
35
|
+
expect(VERSION_VIA_DAEMON_IPC).toBe('1.0.0');
|
|
36
|
+
expect(DAEMON_IPC_PROTOCOL_VERSION).toBe('1.0.0');
|
|
37
|
+
expect(DAEMON_IPC_PROTOCOL_VERSION).toBe(SUPERVISOR_IPC_PROTOCOL_VERSION);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
it('exposes the identical frozen message-kind set through the daemon-ipc name', () => {
|
|
41
|
+
expect([...MESSAGE_KINDS_VIA_DAEMON_IPC]).toEqual([...SUPERVISOR_IPC_MESSAGE_KINDS]);
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('validates a real Rust wire envelope through the daemon-ipc schema', () => {
|
|
45
|
+
const wire = {
|
|
46
|
+
protocol_version: '1.0.0',
|
|
47
|
+
id: 'abc',
|
|
48
|
+
direction: 'request',
|
|
49
|
+
request: { kind: 'health' },
|
|
50
|
+
};
|
|
51
|
+
expect(SupervisorEnvelopeFromDaemonIpc.safeParse(wire).success).toBe(true);
|
|
52
|
+
});
|
|
53
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@cleocode/contracts/daemon-ipc` — the FROZEN v1.0 daemon-IPC surface
|
|
3
|
+
* R4-R7 adapt against (T11253 AC8).
|
|
4
|
+
*
|
|
5
|
+
* ## AC8 reconciliation (T11369)
|
|
6
|
+
*
|
|
7
|
+
* Epic T11253 AC8 specifies the frozen surface is published under the name
|
|
8
|
+
* `@cleocode/contracts/daemon-ipc/`. R1 (T11339) had already shipped the
|
|
9
|
+
* byte-for-byte Rust mirror under `@cleocode/contracts/supervisor-ipc/`. Rather
|
|
10
|
+
* than DUPLICATE the contract (which would create two drift surfaces), this
|
|
11
|
+
* module is a **thin re-export barrel**: `supervisor-ipc` IS the frozen v1.0
|
|
12
|
+
* contract, and `daemon-ipc` is the AC8-named alias the R2 epic promised.
|
|
13
|
+
*
|
|
14
|
+
* Both import sites resolve to the same FROZEN schemas + version constant:
|
|
15
|
+
*
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { SupervisorIpcEnvelopeSchema } from '@cleocode/contracts/daemon-ipc';
|
|
18
|
+
* import { SupervisorIpcEnvelopeSchema } from '@cleocode/contracts/supervisor-ipc';
|
|
19
|
+
* // identical binding — one frozen contract, two names.
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* R4-R7 are **pure adapters** against this frozen surface (see the
|
|
23
|
+
* contract-evolution policy doc, slug `daemon-ipc-contract-evolution-policy`).
|
|
24
|
+
* Breaking changes require a NEW versioned directory + a version-negotiation
|
|
25
|
+
* shim + an R2 amendment task — never an in-place edit to the v1.0 schemas.
|
|
26
|
+
*
|
|
27
|
+
* @packageDocumentation
|
|
28
|
+
* @module @cleocode/contracts/daemon-ipc
|
|
29
|
+
*
|
|
30
|
+
* @epic T11253 R2 — `@cleocode/runtime/daemon` submodule
|
|
31
|
+
* @task T11369 — freeze + publish v1.0 daemon-IPC contract surface (AC8 + AC9)
|
|
32
|
+
* @saga T11243 SG-RUNTIME-UNIFICATION
|
|
33
|
+
*/
|
|
34
|
+
|
|
35
|
+
export type {
|
|
36
|
+
ChildState,
|
|
37
|
+
ChildStatus,
|
|
38
|
+
EnvPair,
|
|
39
|
+
ErrorResponse,
|
|
40
|
+
HealthRequest,
|
|
41
|
+
HealthResponse,
|
|
42
|
+
LifecycleEventKind,
|
|
43
|
+
LifecycleEventResponse,
|
|
44
|
+
MonitorRequest,
|
|
45
|
+
MonitorResponse,
|
|
46
|
+
RestartedResponse,
|
|
47
|
+
RestartRequest,
|
|
48
|
+
SpawnedResponse,
|
|
49
|
+
SpawnRequest,
|
|
50
|
+
SupervisorIpcEnvelope,
|
|
51
|
+
SupervisorIpcRequest,
|
|
52
|
+
SupervisorIpcRequestEnvelope,
|
|
53
|
+
SupervisorIpcResponse,
|
|
54
|
+
SupervisorIpcResponseEnvelope,
|
|
55
|
+
} from '../supervisor-ipc/index.js';
|
|
56
|
+
export {
|
|
57
|
+
ChildStateSchema,
|
|
58
|
+
ChildStatusSchema,
|
|
59
|
+
EnvPairSchema,
|
|
60
|
+
ErrorResponseSchema,
|
|
61
|
+
HealthRequestSchema,
|
|
62
|
+
HealthResponseSchema,
|
|
63
|
+
LifecycleEventKindSchema,
|
|
64
|
+
LifecycleEventResponseSchema,
|
|
65
|
+
MonitorRequestSchema,
|
|
66
|
+
MonitorResponseSchema,
|
|
67
|
+
RestartedResponseSchema,
|
|
68
|
+
RestartRequestSchema,
|
|
69
|
+
SpawnedResponseSchema,
|
|
70
|
+
SpawnRequestSchema,
|
|
71
|
+
SUPERVISOR_IPC_CHANNEL_BASENAME,
|
|
72
|
+
SUPERVISOR_IPC_MESSAGE_KINDS,
|
|
73
|
+
SUPERVISOR_IPC_PROTOCOL_VERSION,
|
|
74
|
+
SUPERVISOR_IPC_REQUEST_KINDS,
|
|
75
|
+
SUPERVISOR_IPC_RESPONSE_KINDS,
|
|
76
|
+
SupervisorIpcEnvelopeSchema,
|
|
77
|
+
SupervisorIpcRequestEnvelopeSchema,
|
|
78
|
+
SupervisorIpcRequestSchema,
|
|
79
|
+
SupervisorIpcResponseEnvelopeSchema,
|
|
80
|
+
SupervisorIpcResponseSchema,
|
|
81
|
+
} from '../supervisor-ipc/index.js';
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* The AC8-canonical name for the frozen daemon-IPC protocol version.
|
|
85
|
+
*
|
|
86
|
+
* Alias of `SUPERVISOR_IPC_PROTOCOL_VERSION` — re-exported so the freeze/drift
|
|
87
|
+
* test (T11369) can pin the value through the `daemon-ipc` surface name AC8
|
|
88
|
+
* specifies. Both constants are the SAME frozen `'1.0.0'`.
|
|
89
|
+
*/
|
|
90
|
+
export { SUPERVISOR_IPC_PROTOCOL_VERSION as DAEMON_IPC_PROTOCOL_VERSION } from '../supervisor-ipc/version.js';
|
package/src/db-inventory.json
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"role": "brain",
|
|
23
23
|
"tier": "project",
|
|
24
24
|
"filePathTemplate": "<projectRoot>/.cleo/brain.db",
|
|
25
|
-
"drizzleSchemaPath": "packages/core/src/store/memory-schema.ts",
|
|
25
|
+
"drizzleSchemaPath": "packages/core/src/store/schema/memory-schema.ts",
|
|
26
26
|
"migrationsDir": "packages/core/migrations/drizzle-brain/",
|
|
27
27
|
"ownerPackage": "@cleocode/brain",
|
|
28
28
|
"openedVia": "openCleoDb('brain', cwd)",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
"role": "conduit",
|
|
36
36
|
"tier": "project",
|
|
37
37
|
"filePathTemplate": "<projectRoot>/.cleo/conduit.db",
|
|
38
|
-
"drizzleSchemaPath": "packages/core/src/store/conduit-schema.ts",
|
|
38
|
+
"drizzleSchemaPath": "packages/core/src/store/schema/conduit-schema.ts",
|
|
39
39
|
"migrationsDir": "packages/core/migrations/drizzle-conduit/",
|
|
40
40
|
"ownerPackage": "@cleocode/core",
|
|
41
41
|
"openedVia": "openCleoDb('conduit', cwd)",
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
"role": "nexus",
|
|
75
75
|
"tier": "global",
|
|
76
76
|
"filePathTemplate": "$XDG_DATA_HOME/cleo/nexus.db",
|
|
77
|
-
"drizzleSchemaPath": "packages/core/src/store/nexus-schema.ts",
|
|
77
|
+
"drizzleSchemaPath": "packages/core/src/store/schema/nexus-schema.ts",
|
|
78
78
|
"migrationsDir": "packages/core/migrations/drizzle-nexus/",
|
|
79
79
|
"ownerPackage": "@cleocode/core",
|
|
80
80
|
"openedVia": "openCleoDb('nexus')",
|
|
@@ -87,7 +87,7 @@
|
|
|
87
87
|
"role": "signaldock-project",
|
|
88
88
|
"tier": "project",
|
|
89
89
|
"filePathTemplate": "<projectRoot>/.cleo/signaldock.db",
|
|
90
|
-
"drizzleSchemaPath": "packages/core/src/store/signaldock-schema.ts",
|
|
90
|
+
"drizzleSchemaPath": "packages/core/src/store/schema/signaldock-schema.ts",
|
|
91
91
|
"migrationsDir": "packages/core/migrations/drizzle-signaldock/",
|
|
92
92
|
"ownerPackage": "@cleocode/core",
|
|
93
93
|
"openedVia": "HISTORICAL — project-tier signaldock.db was migrated into conduit.db post-T310/ADR-037. No live opener; charter row retained for migration provenance and legacy backup detection.",
|
|
@@ -100,7 +100,7 @@
|
|
|
100
100
|
"role": "signaldock-global",
|
|
101
101
|
"tier": "global",
|
|
102
102
|
"filePathTemplate": "$XDG_DATA_HOME/cleo/signaldock.db",
|
|
103
|
-
"drizzleSchemaPath": "packages/core/src/store/signaldock-schema.ts",
|
|
103
|
+
"drizzleSchemaPath": "packages/core/src/store/schema/signaldock-schema.ts",
|
|
104
104
|
"migrationsDir": "packages/core/migrations/drizzle-signaldock/",
|
|
105
105
|
"ownerPackage": "@cleocode/core",
|
|
106
106
|
"openedVia": "openCleoDb('signaldock')",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"role": "telemetry",
|
|
114
114
|
"tier": "global",
|
|
115
115
|
"filePathTemplate": "$XDG_DATA_HOME/cleo/telemetry.db",
|
|
116
|
-
"drizzleSchemaPath": "packages/core/src/
|
|
116
|
+
"drizzleSchemaPath": "packages/core/src/store/schema/telemetry-schema.ts",
|
|
117
117
|
"migrationsDir": "packages/core/migrations/drizzle-telemetry/",
|
|
118
118
|
"ownerPackage": "@cleocode/core",
|
|
119
119
|
"openedVia": "@cleocode/core telemetry/sqlite.ts — lazy open on first event when opted-in; not yet registered as openCleoDb role",
|
|
@@ -126,7 +126,7 @@
|
|
|
126
126
|
"role": "skills",
|
|
127
127
|
"tier": "global",
|
|
128
128
|
"filePathTemplate": "$XDG_DATA_HOME/cleo/skills.db",
|
|
129
|
-
"drizzleSchemaPath": "packages/core/src/store/skills-schema.ts",
|
|
129
|
+
"drizzleSchemaPath": "packages/core/src/store/schema/skills-schema.ts",
|
|
130
130
|
"migrationsDir": "packages/core/migrations/drizzle-skills/",
|
|
131
131
|
"ownerPackage": "@cleocode/core",
|
|
132
132
|
"openedVia": "openCleoDb('skills')",
|
|
@@ -139,7 +139,7 @@
|
|
|
139
139
|
"role": "global-brain",
|
|
140
140
|
"tier": "global",
|
|
141
141
|
"filePathTemplate": "$XDG_DATA_HOME/cleo/brain.db",
|
|
142
|
-
"drizzleSchemaPath": "packages/core/src/store/memory-schema.ts",
|
|
142
|
+
"drizzleSchemaPath": "packages/core/src/store/schema/memory-schema.ts",
|
|
143
143
|
"migrationsDir": "packages/core/migrations/drizzle-brain/",
|
|
144
144
|
"ownerPackage": "@cleocode/brain",
|
|
145
145
|
"openedVia": "UNREGISTERED — file exists on disk (audit §1.2 row 3) but no live opener. Provenance unclear; likely orphan from a getCleoHome()-vs-project-resolution path bug. Tracked for cleanup decision under T10282/T10307.",
|