@cleocode/contracts 2026.5.96 → 2026.5.98
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__/enums.test.d.ts +14 -0
- package/dist/__tests__/enums.test.d.ts.map +1 -0
- package/dist/__tests__/enums.test.js +75 -0
- package/dist/__tests__/enums.test.js.map +1 -0
- package/dist/__tests__/jobs.test.d.ts +11 -0
- package/dist/__tests__/jobs.test.d.ts.map +1 -0
- package/dist/__tests__/jobs.test.js +48 -0
- package/dist/__tests__/jobs.test.js.map +1 -0
- package/dist/__tests__/memory-wire-shapes.test.d.ts +19 -0
- package/dist/__tests__/memory-wire-shapes.test.d.ts.map +1 -0
- package/dist/__tests__/memory-wire-shapes.test.js +119 -0
- package/dist/__tests__/memory-wire-shapes.test.js.map +1 -0
- package/dist/__tests__/operation-def.test.d.ts +20 -0
- package/dist/__tests__/operation-def.test.d.ts.map +1 -0
- package/dist/__tests__/operation-def.test.js +111 -0
- package/dist/__tests__/operation-def.test.js.map +1 -0
- package/dist/__tests__/provenance.test.d.ts +18 -0
- package/dist/__tests__/provenance.test.d.ts.map +1 -0
- package/dist/__tests__/provenance.test.js +142 -0
- package/dist/__tests__/provenance.test.js.map +1 -0
- package/dist/__tests__/scaffold-diagnostics.test.d.ts +19 -0
- package/dist/__tests__/scaffold-diagnostics.test.d.ts.map +1 -0
- package/dist/__tests__/scaffold-diagnostics.test.js +70 -0
- package/dist/__tests__/scaffold-diagnostics.test.js.map +1 -0
- package/dist/dispatch/identity.d.ts +72 -0
- package/dist/dispatch/identity.d.ts.map +1 -0
- package/dist/dispatch/identity.js +72 -0
- package/dist/dispatch/identity.js.map +1 -0
- package/dist/dispatch/operation-def.d.ts +92 -0
- package/dist/dispatch/operation-def.d.ts.map +1 -0
- package/dist/dispatch/operation-def.js +31 -0
- package/dist/dispatch/operation-def.js.map +1 -0
- package/dist/doctor.d.ts +43 -0
- package/dist/doctor.d.ts.map +1 -1
- package/dist/enums.d.ts +123 -0
- package/dist/enums.d.ts.map +1 -0
- package/dist/enums.js +139 -0
- package/dist/enums.js.map +1 -0
- package/dist/index.d.ts +15 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/jobs.d.ts +39 -0
- package/dist/jobs.d.ts.map +1 -0
- package/dist/jobs.js +19 -0
- package/dist/jobs.js.map +1 -0
- package/dist/memory/budgeted.d.ts +67 -0
- package/dist/memory/budgeted.d.ts.map +1 -0
- package/dist/memory/budgeted.js +17 -0
- package/dist/memory/budgeted.js.map +1 -0
- package/dist/memory/fetch.d.ts +58 -0
- package/dist/memory/fetch.d.ts.map +1 -0
- package/dist/memory/fetch.js +19 -0
- package/dist/memory/fetch.js.map +1 -0
- package/dist/memory/observe.d.ts +158 -0
- package/dist/memory/observe.d.ts.map +1 -0
- package/dist/memory/observe.js +46 -0
- package/dist/memory/observe.js.map +1 -0
- package/dist/memory/search.d.ts +137 -0
- package/dist/memory/search.d.ts.map +1 -0
- package/dist/memory/search.js +22 -0
- package/dist/memory/search.js.map +1 -0
- package/dist/memory/timeline.d.ts +89 -0
- package/dist/memory/timeline.d.ts.map +1 -0
- package/dist/memory/timeline.js +22 -0
- package/dist/memory/timeline.js.map +1 -0
- package/dist/operations/focus.d.ts +199 -0
- package/dist/operations/focus.d.ts.map +1 -0
- package/dist/operations/focus.js +15 -0
- package/dist/operations/focus.js.map +1 -0
- 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 +65 -0
- package/dist/operations/session.d.ts.map +1 -1
- package/dist/operations/tasks.d.ts +38 -0
- package/dist/operations/tasks.d.ts.map +1 -1
- package/dist/provenance.d.ts +257 -0
- package/dist/provenance.d.ts.map +1 -0
- package/dist/provenance.js +42 -0
- package/dist/provenance.js.map +1 -0
- package/dist/release/plan.d.ts +7 -7
- package/dist/scaffold-diagnostics.d.ts +110 -0
- package/dist/scaffold-diagnostics.d.ts.map +1 -0
- package/dist/scaffold-diagnostics.js +28 -0
- package/dist/scaffold-diagnostics.js.map +1 -0
- package/dist/session.d.ts +37 -0
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js.map +1 -1
- package/dist/tasks/archive.d.ts +3 -3
- package/package.json +42 -2
- package/src/__tests__/enums.test.ts +114 -0
- package/src/__tests__/jobs.test.ts +76 -0
- package/src/__tests__/memory-wire-shapes.test.ts +371 -0
- package/src/__tests__/operation-def.test.ts +185 -0
- package/src/__tests__/provenance.test.ts +259 -0
- package/src/__tests__/scaffold-diagnostics.test.ts +137 -0
- package/src/dispatch/identity.ts +109 -0
- package/src/dispatch/operation-def.ts +102 -0
- package/src/doctor.ts +44 -0
- package/src/enums.ts +144 -0
- package/src/index.ts +79 -1
- package/src/jobs.ts +45 -0
- package/src/memory/budgeted.ts +75 -0
- package/src/memory/fetch.ts +66 -0
- package/src/memory/observe.ts +176 -0
- package/src/memory/search.ts +145 -0
- package/src/memory/timeline.ts +100 -0
- package/src/operations/focus.ts +226 -0
- package/src/operations/index.ts +1 -0
- package/src/operations/session.ts +67 -0
- package/src/operations/tasks.ts +40 -0
- package/src/provenance.ts +335 -0
- package/src/scaffold-diagnostics.ts +119 -0
- package/src/session.ts +37 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cleocode/contracts",
|
|
3
|
-
"version": "2026.5.
|
|
3
|
+
"version": "2026.5.98",
|
|
4
4
|
"description": "Domain types, interfaces, and contracts for the CLEO ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -10,6 +10,30 @@
|
|
|
10
10
|
"types": "./dist/index.d.ts",
|
|
11
11
|
"import": "./dist/index.js"
|
|
12
12
|
},
|
|
13
|
+
"./provenance": {
|
|
14
|
+
"types": "./dist/provenance.d.ts",
|
|
15
|
+
"import": "./dist/provenance.js"
|
|
16
|
+
},
|
|
17
|
+
"./provenance.js": {
|
|
18
|
+
"types": "./dist/provenance.d.ts",
|
|
19
|
+
"import": "./dist/provenance.js"
|
|
20
|
+
},
|
|
21
|
+
"./jobs": {
|
|
22
|
+
"types": "./dist/jobs.d.ts",
|
|
23
|
+
"import": "./dist/jobs.js"
|
|
24
|
+
},
|
|
25
|
+
"./jobs.js": {
|
|
26
|
+
"types": "./dist/jobs.d.ts",
|
|
27
|
+
"import": "./dist/jobs.js"
|
|
28
|
+
},
|
|
29
|
+
"./enums": {
|
|
30
|
+
"types": "./dist/enums.d.ts",
|
|
31
|
+
"import": "./dist/enums.js"
|
|
32
|
+
},
|
|
33
|
+
"./enums.js": {
|
|
34
|
+
"types": "./dist/enums.d.ts",
|
|
35
|
+
"import": "./dist/enums.js"
|
|
36
|
+
},
|
|
13
37
|
"./nexus-contract-ops": {
|
|
14
38
|
"types": "./dist/nexus-contract-ops.d.ts",
|
|
15
39
|
"import": "./dist/nexus-contract-ops.js"
|
|
@@ -50,6 +74,14 @@
|
|
|
50
74
|
"types": "./dist/nexus-tasks-bridge-ops.d.ts",
|
|
51
75
|
"import": "./dist/nexus-tasks-bridge-ops.js"
|
|
52
76
|
},
|
|
77
|
+
"./dispatch/*": {
|
|
78
|
+
"types": "./dist/dispatch/*.d.ts",
|
|
79
|
+
"import": "./dist/dispatch/*.js"
|
|
80
|
+
},
|
|
81
|
+
"./dispatch/*.js": {
|
|
82
|
+
"types": "./dist/dispatch/*.d.ts",
|
|
83
|
+
"import": "./dist/dispatch/*.js"
|
|
84
|
+
},
|
|
53
85
|
"./operations/*": {
|
|
54
86
|
"types": "./dist/operations/*.d.ts",
|
|
55
87
|
"import": "./dist/operations/*.js"
|
|
@@ -73,6 +105,14 @@
|
|
|
73
105
|
"./memory/*.js": {
|
|
74
106
|
"types": "./dist/memory/*.d.ts",
|
|
75
107
|
"import": "./dist/memory/*.js"
|
|
108
|
+
},
|
|
109
|
+
"./*": {
|
|
110
|
+
"types": "./dist/*.d.ts",
|
|
111
|
+
"import": "./dist/*.js"
|
|
112
|
+
},
|
|
113
|
+
"./*.js": {
|
|
114
|
+
"types": "./dist/*.d.ts",
|
|
115
|
+
"import": "./dist/*.js"
|
|
76
116
|
}
|
|
77
117
|
},
|
|
78
118
|
"engines": {
|
|
@@ -98,7 +138,7 @@
|
|
|
98
138
|
"dependencies": {
|
|
99
139
|
"zod": "^4.3.6",
|
|
100
140
|
"zod-to-json-schema": "^3.25.2",
|
|
101
|
-
"@cleocode/lafs": "2026.5.
|
|
141
|
+
"@cleocode/lafs": "2026.5.98"
|
|
102
142
|
},
|
|
103
143
|
"scripts": {
|
|
104
144
|
"build": "tsc -b --force && node scripts/emit-schemas.mjs",
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural-equivalence + value-set tests for the task-axis enum
|
|
3
|
+
* constants promoted in Phase 0c (T9955).
|
|
4
|
+
*
|
|
5
|
+
* These tests pin the runtime value sets of the 6 `as const` arrays
|
|
6
|
+
* (`TASK_KINDS`, `TASK_SCOPES`, `TASK_SEVERITIES`, `TASK_SIZES`,
|
|
7
|
+
* `ARCHIVE_REASONS`, `TASK_RELATION_TYPES`) so that:
|
|
8
|
+
* - The Drizzle row-type narrowing in `tasks-schema.ts` stays byte-identical.
|
|
9
|
+
* - The DB CHECK constraints they back keep their canonical value list.
|
|
10
|
+
*
|
|
11
|
+
* @since SG-ARCH-SOLID Saga T9831 · E-CONTRACTS-FOUNDATION T9832 · T9955 (Phase 0c)
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { describe, expect, it } from 'vitest';
|
|
15
|
+
import {
|
|
16
|
+
ARCHIVE_REASONS,
|
|
17
|
+
TASK_KINDS,
|
|
18
|
+
TASK_RELATION_TYPES,
|
|
19
|
+
TASK_SCOPES,
|
|
20
|
+
TASK_SEVERITIES,
|
|
21
|
+
TASK_SIZES,
|
|
22
|
+
} from '../enums.js';
|
|
23
|
+
|
|
24
|
+
// ─── Compile-time readonly-tuple guarantees ─────────────────────────
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Compile-time assertion that `T` is a readonly tuple (not a mutable
|
|
28
|
+
* `string[]`). Drizzle's `text({ enum })` narrowing depends on the
|
|
29
|
+
* literal tuple shape, so accidental widening MUST fail at build time.
|
|
30
|
+
*/
|
|
31
|
+
type _AssertReadonlyTuple<T extends readonly string[]> = T;
|
|
32
|
+
|
|
33
|
+
type _PinTaskKinds = _AssertReadonlyTuple<typeof TASK_KINDS>;
|
|
34
|
+
type _PinTaskScopes = _AssertReadonlyTuple<typeof TASK_SCOPES>;
|
|
35
|
+
type _PinTaskSeverities = _AssertReadonlyTuple<typeof TASK_SEVERITIES>;
|
|
36
|
+
type _PinTaskSizes = _AssertReadonlyTuple<typeof TASK_SIZES>;
|
|
37
|
+
type _PinArchiveReasons = _AssertReadonlyTuple<typeof ARCHIVE_REASONS>;
|
|
38
|
+
type _PinTaskRelationTypes = _AssertReadonlyTuple<typeof TASK_RELATION_TYPES>;
|
|
39
|
+
|
|
40
|
+
// ─── Runtime value-set assertions ───────────────────────────────────
|
|
41
|
+
|
|
42
|
+
describe('task-axis enum constants', () => {
|
|
43
|
+
it('TASK_KINDS holds the 6 canonical task kinds', () => {
|
|
44
|
+
expect(TASK_KINDS).toEqual(['work', 'research', 'experiment', 'bug', 'spike', 'release']);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('TASK_SCOPES holds project / feature / unit (in canonical order)', () => {
|
|
48
|
+
expect(TASK_SCOPES).toEqual(['project', 'feature', 'unit']);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('TASK_SEVERITIES holds P0 through P3 in increasing severity order', () => {
|
|
52
|
+
expect(TASK_SEVERITIES).toEqual(['P0', 'P1', 'P2', 'P3']);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
it('TASK_SIZES holds small / medium / large (CLEO avoids time estimates)', () => {
|
|
56
|
+
expect(TASK_SIZES).toEqual(['small', 'medium', 'large']);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it('ARCHIVE_REASONS holds exactly the 6 truth-grade closure reasons', () => {
|
|
60
|
+
expect(ARCHIVE_REASONS).toEqual([
|
|
61
|
+
'verified',
|
|
62
|
+
'reconciled',
|
|
63
|
+
'superseded',
|
|
64
|
+
'shadowed',
|
|
65
|
+
'cancelled',
|
|
66
|
+
'completed-unverified',
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('TASK_RELATION_TYPES includes "groups" (ADR-073 Saga membership)', () => {
|
|
71
|
+
expect(TASK_RELATION_TYPES).toContain('groups');
|
|
72
|
+
expect(TASK_RELATION_TYPES).toEqual([
|
|
73
|
+
'related',
|
|
74
|
+
'blocks',
|
|
75
|
+
'duplicates',
|
|
76
|
+
'absorbs',
|
|
77
|
+
'fixes',
|
|
78
|
+
'extends',
|
|
79
|
+
'supersedes',
|
|
80
|
+
'groups',
|
|
81
|
+
]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('All enum arrays are non-empty readonly tuples', () => {
|
|
85
|
+
expect(TASK_KINDS.length).toBeGreaterThan(0);
|
|
86
|
+
expect(TASK_SCOPES.length).toBeGreaterThan(0);
|
|
87
|
+
expect(TASK_SEVERITIES.length).toBeGreaterThan(0);
|
|
88
|
+
expect(TASK_SIZES.length).toBeGreaterThan(0);
|
|
89
|
+
expect(ARCHIVE_REASONS.length).toBeGreaterThan(0);
|
|
90
|
+
expect(TASK_RELATION_TYPES.length).toBeGreaterThan(0);
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// The six `_Pin…` aliases above will fail compilation if any const
|
|
94
|
+
// array is accidentally widened to `string[]`. The reference below
|
|
95
|
+
// prevents unused-locals diagnostics from removing them.
|
|
96
|
+
it('compile-time readonly-tuple pins are wired (no-op at runtime)', () => {
|
|
97
|
+
const pinned: [
|
|
98
|
+
_PinTaskKinds,
|
|
99
|
+
_PinTaskScopes,
|
|
100
|
+
_PinTaskSeverities,
|
|
101
|
+
_PinTaskSizes,
|
|
102
|
+
_PinArchiveReasons,
|
|
103
|
+
_PinTaskRelationTypes,
|
|
104
|
+
] = [
|
|
105
|
+
TASK_KINDS,
|
|
106
|
+
TASK_SCOPES,
|
|
107
|
+
TASK_SEVERITIES,
|
|
108
|
+
TASK_SIZES,
|
|
109
|
+
ARCHIVE_REASONS,
|
|
110
|
+
TASK_RELATION_TYPES,
|
|
111
|
+
];
|
|
112
|
+
expect(pinned).toHaveLength(6);
|
|
113
|
+
});
|
|
114
|
+
});
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural-equivalence tests for the background-job contracts.
|
|
3
|
+
*
|
|
4
|
+
* Pins the literal shape of {@link BackgroundJobStatus} promoted in
|
|
5
|
+
* Phase 0c (T9955) so accidental narrowing or widening triggers a
|
|
6
|
+
* compile-time failure during `tsc -b` in the CI gate.
|
|
7
|
+
*
|
|
8
|
+
* @since SG-ARCH-SOLID Saga T9831 · E-CONTRACTS-FOUNDATION T9832 · T9955 (Phase 0c)
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { describe, expect, it } from 'vitest';
|
|
12
|
+
import type { BackgroundJobStatus } from '../jobs.js';
|
|
13
|
+
|
|
14
|
+
// ─── Compile-time structural-equality helpers ───────────────────────
|
|
15
|
+
|
|
16
|
+
/** Resolve to `1` IFF `A` and `B` are mutually assignable; `2` otherwise. */
|
|
17
|
+
type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? 1 : 2;
|
|
18
|
+
|
|
19
|
+
/** Compile-time assert that `T` resolves to `1`. */
|
|
20
|
+
type AssertEquals1<T extends 1> = T;
|
|
21
|
+
|
|
22
|
+
// ─── BackgroundJobStatus shape pin ──────────────────────────────────
|
|
23
|
+
|
|
24
|
+
type _BackgroundJobStatusShape =
|
|
25
|
+
| 'pending'
|
|
26
|
+
| 'running'
|
|
27
|
+
| 'complete'
|
|
28
|
+
| 'failed'
|
|
29
|
+
| 'cancelled'
|
|
30
|
+
| 'orphaned';
|
|
31
|
+
|
|
32
|
+
type _AssertBackgroundJobStatusPinned = AssertEquals1<
|
|
33
|
+
Equals<BackgroundJobStatus, _BackgroundJobStatusShape>
|
|
34
|
+
>;
|
|
35
|
+
|
|
36
|
+
// ─── Runtime constructibility smoke ─────────────────────────────────
|
|
37
|
+
|
|
38
|
+
describe('jobs contracts', () => {
|
|
39
|
+
it('BackgroundJobStatus enumerates the 6 documented lifecycle states', () => {
|
|
40
|
+
const all: BackgroundJobStatus[] = [
|
|
41
|
+
'pending',
|
|
42
|
+
'running',
|
|
43
|
+
'complete',
|
|
44
|
+
'failed',
|
|
45
|
+
'cancelled',
|
|
46
|
+
'orphaned',
|
|
47
|
+
];
|
|
48
|
+
expect(all).toHaveLength(6);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('BackgroundJobStatus distinguishes terminal from in-flight states', () => {
|
|
52
|
+
const terminal: BackgroundJobStatus[] = ['complete', 'failed', 'cancelled', 'orphaned'];
|
|
53
|
+
const inFlight: BackgroundJobStatus[] = ['pending', 'running'];
|
|
54
|
+
expect(terminal).toHaveLength(4);
|
|
55
|
+
expect(inFlight).toHaveLength(2);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('Every BackgroundJobStatus is a non-empty string literal', () => {
|
|
59
|
+
const statuses: BackgroundJobStatus[] = [
|
|
60
|
+
'pending',
|
|
61
|
+
'running',
|
|
62
|
+
'complete',
|
|
63
|
+
'failed',
|
|
64
|
+
'cancelled',
|
|
65
|
+
'orphaned',
|
|
66
|
+
];
|
|
67
|
+
for (const s of statuses) {
|
|
68
|
+
expect(s.length).toBeGreaterThan(0);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('compile-time pin is wired (no-op at runtime)', () => {
|
|
73
|
+
const pinned: _AssertBackgroundJobStatusPinned = 1;
|
|
74
|
+
expect(pinned).toBe(1);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structural-equivalence tests for the BRAIN memory wire-shape contracts.
|
|
3
|
+
*
|
|
4
|
+
* These tests pin the field shapes of the 15 types promoted from
|
|
5
|
+
* `packages/core/src/memory/brain-retrieval.ts` in Phase 0e of
|
|
6
|
+
* SG-ARCH-SOLID (E-CONTRACTS-FOUNDATION). Accidental narrowing or
|
|
7
|
+
* widening triggers a compile-time failure during `tsc -b` in the CI gate.
|
|
8
|
+
*
|
|
9
|
+
* The compile-time assertions use the conditional-equality trick
|
|
10
|
+
* (`Equals<A, B>`) so any structural drift produces a TS2322 or TS2344
|
|
11
|
+
* at build time. The runtime `expect` smoke verifies that constructible
|
|
12
|
+
* literals satisfy each interface — these are pure type contracts with
|
|
13
|
+
* no runtime, so this is a thin satisfies check rather than a behavior
|
|
14
|
+
* test.
|
|
15
|
+
*
|
|
16
|
+
* @since SG-ARCH-SOLID Saga T9831 · E-CONTRACTS-FOUNDATION T9832 · T9956 (Phase 0e)
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
import { describe, expect, it } from 'vitest';
|
|
20
|
+
import type { BrainSourceConfidence } from '../brain.js';
|
|
21
|
+
import type { BrainObservationType } from '../facade.js';
|
|
22
|
+
import type {
|
|
23
|
+
BudgetedEntry,
|
|
24
|
+
BudgetedResult,
|
|
25
|
+
BudgetedRetrievalOptions,
|
|
26
|
+
} from '../memory/budgeted.js';
|
|
27
|
+
import type {
|
|
28
|
+
FetchBrainEntriesParams,
|
|
29
|
+
FetchBrainEntriesResult,
|
|
30
|
+
FetchedBrainEntry,
|
|
31
|
+
} from '../memory/fetch.js';
|
|
32
|
+
import {
|
|
33
|
+
BRAIN_OBSERVATION_SOURCE_TYPES,
|
|
34
|
+
type BrainObservationSourceType,
|
|
35
|
+
type ObserveBrainParams,
|
|
36
|
+
type ObserveBrainResult,
|
|
37
|
+
} from '../memory/observe.js';
|
|
38
|
+
import type {
|
|
39
|
+
BrainCompactHit,
|
|
40
|
+
SearchBrainCompactParams,
|
|
41
|
+
SearchBrainCompactResult,
|
|
42
|
+
} from '../memory/search.js';
|
|
43
|
+
import type {
|
|
44
|
+
BrainAnchor,
|
|
45
|
+
TimelineBrainParams,
|
|
46
|
+
TimelineBrainResult,
|
|
47
|
+
TimelineNeighbor,
|
|
48
|
+
} from '../memory/timeline.js';
|
|
49
|
+
|
|
50
|
+
// ─── Compile-time structural-equality helpers ───────────────────────
|
|
51
|
+
|
|
52
|
+
/** Resolve to `1` IFF `A` and `B` are mutually assignable; `2` otherwise. */
|
|
53
|
+
type Equals<A, B> = (<T>() => T extends A ? 1 : 2) extends <T>() => T extends B ? 1 : 2 ? 1 : 2;
|
|
54
|
+
|
|
55
|
+
/** Compile-time assert that `T` resolves to `1`. */
|
|
56
|
+
type AssertEquals1<T extends 1> = T;
|
|
57
|
+
|
|
58
|
+
// ─── Search: BrainCompactHit shape pin ──────────────────────────────
|
|
59
|
+
|
|
60
|
+
type _BrainCompactHitShape = {
|
|
61
|
+
id: string;
|
|
62
|
+
type: 'decision' | 'pattern' | 'learning' | 'observation';
|
|
63
|
+
title: string;
|
|
64
|
+
date: string;
|
|
65
|
+
relevance?: number;
|
|
66
|
+
rrfScore?: number;
|
|
67
|
+
bm25Score?: number;
|
|
68
|
+
_next?: Record<string, string>;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
type _AssertBrainCompactHitPinned = AssertEquals1<Equals<BrainCompactHit, _BrainCompactHitShape>>;
|
|
72
|
+
|
|
73
|
+
// ─── Search: SearchBrainCompactParams shape pin ─────────────────────
|
|
74
|
+
|
|
75
|
+
type _SearchBrainCompactParamsShape = {
|
|
76
|
+
query: string;
|
|
77
|
+
limit?: number;
|
|
78
|
+
tables?: Array<'decisions' | 'patterns' | 'learnings' | 'observations'>;
|
|
79
|
+
dateStart?: string;
|
|
80
|
+
dateEnd?: string;
|
|
81
|
+
agent?: string;
|
|
82
|
+
useRRF?: boolean;
|
|
83
|
+
peerId?: string;
|
|
84
|
+
includeGlobal?: boolean;
|
|
85
|
+
mode?: 'recency' | 'lexical' | 'hybrid';
|
|
86
|
+
since?: string;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
type _AssertSearchParamsPinned = AssertEquals1<
|
|
90
|
+
Equals<SearchBrainCompactParams, _SearchBrainCompactParamsShape>
|
|
91
|
+
>;
|
|
92
|
+
|
|
93
|
+
// ─── Search: SearchBrainCompactResult shape pin ─────────────────────
|
|
94
|
+
|
|
95
|
+
type _SearchBrainCompactResultShape = {
|
|
96
|
+
results: BrainCompactHit[];
|
|
97
|
+
total: number;
|
|
98
|
+
tokensEstimated: number;
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
type _AssertSearchResultPinned = AssertEquals1<
|
|
102
|
+
Equals<SearchBrainCompactResult, _SearchBrainCompactResultShape>
|
|
103
|
+
>;
|
|
104
|
+
|
|
105
|
+
// ─── Timeline: BrainAnchor shape pin ────────────────────────────────
|
|
106
|
+
|
|
107
|
+
type _BrainAnchorShape = {
|
|
108
|
+
id: string;
|
|
109
|
+
type: string;
|
|
110
|
+
data: unknown;
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
type _AssertBrainAnchorPinned = AssertEquals1<Equals<BrainAnchor, _BrainAnchorShape>>;
|
|
114
|
+
|
|
115
|
+
// ─── Timeline: TimelineBrainParams shape pin ────────────────────────
|
|
116
|
+
|
|
117
|
+
type _TimelineBrainParamsShape = {
|
|
118
|
+
anchor: string;
|
|
119
|
+
depthBefore?: number;
|
|
120
|
+
depthAfter?: number;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
type _AssertTimelineParamsPinned = AssertEquals1<
|
|
124
|
+
Equals<TimelineBrainParams, _TimelineBrainParamsShape>
|
|
125
|
+
>;
|
|
126
|
+
|
|
127
|
+
// ─── Timeline: TimelineNeighbor shape pin ───────────────────────────
|
|
128
|
+
|
|
129
|
+
type _TimelineNeighborShape = {
|
|
130
|
+
id: string;
|
|
131
|
+
type: string;
|
|
132
|
+
date: string;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
type _AssertTimelineNeighborPinned = AssertEquals1<
|
|
136
|
+
Equals<TimelineNeighbor, _TimelineNeighborShape>
|
|
137
|
+
>;
|
|
138
|
+
|
|
139
|
+
// ─── Timeline: TimelineBrainResult shape pin ────────────────────────
|
|
140
|
+
|
|
141
|
+
type _TimelineBrainResultShape = {
|
|
142
|
+
anchor: BrainAnchor | null;
|
|
143
|
+
before: TimelineNeighbor[];
|
|
144
|
+
after: TimelineNeighbor[];
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
type _AssertTimelineResultPinned = AssertEquals1<
|
|
148
|
+
Equals<TimelineBrainResult, _TimelineBrainResultShape>
|
|
149
|
+
>;
|
|
150
|
+
|
|
151
|
+
// ─── Fetch: FetchBrainEntriesParams shape pin ───────────────────────
|
|
152
|
+
|
|
153
|
+
type _FetchBrainEntriesParamsShape = {
|
|
154
|
+
ids: string[];
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
type _AssertFetchParamsPinned = AssertEquals1<
|
|
158
|
+
Equals<FetchBrainEntriesParams, _FetchBrainEntriesParamsShape>
|
|
159
|
+
>;
|
|
160
|
+
|
|
161
|
+
// ─── Fetch: FetchedBrainEntry shape pin ─────────────────────────────
|
|
162
|
+
|
|
163
|
+
type _FetchedBrainEntryShape = {
|
|
164
|
+
id: string;
|
|
165
|
+
type: string;
|
|
166
|
+
data: unknown;
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
type _AssertFetchedEntryPinned = AssertEquals1<Equals<FetchedBrainEntry, _FetchedBrainEntryShape>>;
|
|
170
|
+
|
|
171
|
+
// ─── Fetch: FetchBrainEntriesResult shape pin ───────────────────────
|
|
172
|
+
|
|
173
|
+
type _FetchBrainEntriesResultShape = {
|
|
174
|
+
results: FetchedBrainEntry[];
|
|
175
|
+
notFound: string[];
|
|
176
|
+
tokensEstimated: number;
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
type _AssertFetchResultPinned = AssertEquals1<
|
|
180
|
+
Equals<FetchBrainEntriesResult, _FetchBrainEntriesResultShape>
|
|
181
|
+
>;
|
|
182
|
+
|
|
183
|
+
// ─── Observe: BrainObservationSourceType shape pin ──────────────────
|
|
184
|
+
|
|
185
|
+
type _BrainObservationSourceTypeShape = 'agent' | 'session-debrief' | 'claude-mem' | 'manual';
|
|
186
|
+
|
|
187
|
+
type _AssertObservationSourceTypePinned = AssertEquals1<
|
|
188
|
+
Equals<BrainObservationSourceType, _BrainObservationSourceTypeShape>
|
|
189
|
+
>;
|
|
190
|
+
|
|
191
|
+
// ─── Observe: ObserveBrainParams shape pin ──────────────────────────
|
|
192
|
+
|
|
193
|
+
type _ObserveBrainParamsShape = {
|
|
194
|
+
text: string;
|
|
195
|
+
title?: string;
|
|
196
|
+
type?: BrainObservationType;
|
|
197
|
+
project?: string;
|
|
198
|
+
sourceSessionId?: string;
|
|
199
|
+
sourceType?: BrainObservationSourceType;
|
|
200
|
+
agent?: string;
|
|
201
|
+
sourceConfidence?: BrainSourceConfidence;
|
|
202
|
+
crossRef?: string[];
|
|
203
|
+
attachmentRefs?: string[];
|
|
204
|
+
origin?: string | null;
|
|
205
|
+
provenanceChain?: string[] | null;
|
|
206
|
+
_skipGate?: boolean;
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
type _AssertObserveParamsPinned = AssertEquals1<
|
|
210
|
+
Equals<ObserveBrainParams, _ObserveBrainParamsShape>
|
|
211
|
+
>;
|
|
212
|
+
|
|
213
|
+
// ─── Observe: ObserveBrainResult shape pin ──────────────────────────
|
|
214
|
+
|
|
215
|
+
type _ObserveBrainResultShape = {
|
|
216
|
+
id: string;
|
|
217
|
+
type: string;
|
|
218
|
+
createdAt: string;
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
type _AssertObserveResultPinned = AssertEquals1<
|
|
222
|
+
Equals<ObserveBrainResult, _ObserveBrainResultShape>
|
|
223
|
+
>;
|
|
224
|
+
|
|
225
|
+
// ─── Budgeted: BudgetedRetrievalOptions shape pin ───────────────────
|
|
226
|
+
|
|
227
|
+
type _BudgetedRetrievalOptionsShape = {
|
|
228
|
+
types?: Array<'semantic' | 'episodic' | 'procedural'>;
|
|
229
|
+
tiers?: Array<'short' | 'medium' | 'long'>;
|
|
230
|
+
verified?: boolean;
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
type _AssertBudgetedOptionsPinned = AssertEquals1<
|
|
234
|
+
Equals<BudgetedRetrievalOptions, _BudgetedRetrievalOptionsShape>
|
|
235
|
+
>;
|
|
236
|
+
|
|
237
|
+
// ─── Budgeted: BudgetedEntry shape pin ──────────────────────────────
|
|
238
|
+
|
|
239
|
+
type _BudgetedEntryShape = {
|
|
240
|
+
id: string;
|
|
241
|
+
type: string;
|
|
242
|
+
title: string;
|
|
243
|
+
text: string;
|
|
244
|
+
score: number;
|
|
245
|
+
tokensEstimated: number;
|
|
246
|
+
memoryTier?: string;
|
|
247
|
+
memoryType?: string;
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
type _AssertBudgetedEntryPinned = AssertEquals1<Equals<BudgetedEntry, _BudgetedEntryShape>>;
|
|
251
|
+
|
|
252
|
+
// ─── Budgeted: BudgetedResult shape pin ─────────────────────────────
|
|
253
|
+
|
|
254
|
+
type _BudgetedResultShape = {
|
|
255
|
+
entries: BudgetedEntry[];
|
|
256
|
+
tokensUsed: number;
|
|
257
|
+
tokensRemaining: number;
|
|
258
|
+
excluded: number;
|
|
259
|
+
};
|
|
260
|
+
|
|
261
|
+
type _AssertBudgetedResultPinned = AssertEquals1<Equals<BudgetedResult, _BudgetedResultShape>>;
|
|
262
|
+
|
|
263
|
+
// ─── Runtime constructibility smoke ─────────────────────────────────
|
|
264
|
+
|
|
265
|
+
describe('memory wire-shape contracts (T9956)', () => {
|
|
266
|
+
it('BrainCompactHit is constructible with the canonical shape', () => {
|
|
267
|
+
const hit: BrainCompactHit = {
|
|
268
|
+
id: 'O-abc123',
|
|
269
|
+
type: 'observation',
|
|
270
|
+
title: 'sample',
|
|
271
|
+
date: '2026-05-21T00:00:00Z',
|
|
272
|
+
};
|
|
273
|
+
expect(hit.id).toBe('O-abc123');
|
|
274
|
+
expect(hit.type).toBe('observation');
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
it('SearchBrainCompactResult composes BrainCompactHit and token accounting', () => {
|
|
278
|
+
const result: SearchBrainCompactResult = {
|
|
279
|
+
results: [{ id: 'O-1', type: 'observation', title: 't', date: '2026-05-21' }],
|
|
280
|
+
total: 1,
|
|
281
|
+
tokensEstimated: 50,
|
|
282
|
+
};
|
|
283
|
+
expect(result.results).toHaveLength(1);
|
|
284
|
+
expect(result.tokensEstimated).toBe(50);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
it('BrainAnchor and TimelineBrainResult compose correctly', () => {
|
|
288
|
+
const anchor: BrainAnchor = { id: 'O-anchor', type: 'observation', data: { x: 1 } };
|
|
289
|
+
const result: TimelineBrainResult = {
|
|
290
|
+
anchor,
|
|
291
|
+
before: [{ id: 'O-prev', type: 'observation', date: '2026-05-20' }],
|
|
292
|
+
after: [{ id: 'O-next', type: 'observation', date: '2026-05-22' }],
|
|
293
|
+
};
|
|
294
|
+
expect(result.anchor?.id).toBe('O-anchor');
|
|
295
|
+
expect(result.before).toHaveLength(1);
|
|
296
|
+
expect(result.after).toHaveLength(1);
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
it('TimelineBrainResult accepts null anchor for unresolved IDs', () => {
|
|
300
|
+
const result: TimelineBrainResult = { anchor: null, before: [], after: [] };
|
|
301
|
+
expect(result.anchor).toBeNull();
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
it('FetchBrainEntriesResult tracks notFound IDs alongside resolved entries', () => {
|
|
305
|
+
const result: FetchBrainEntriesResult = {
|
|
306
|
+
results: [{ id: 'O-1', type: 'observation', data: null }],
|
|
307
|
+
notFound: ['O-missing'],
|
|
308
|
+
tokensEstimated: 100,
|
|
309
|
+
};
|
|
310
|
+
expect(result.results).toHaveLength(1);
|
|
311
|
+
expect(result.notFound).toContain('O-missing');
|
|
312
|
+
});
|
|
313
|
+
|
|
314
|
+
it('BRAIN_OBSERVATION_SOURCE_TYPES is the runtime tuple backing BrainObservationSourceType', () => {
|
|
315
|
+
expect(BRAIN_OBSERVATION_SOURCE_TYPES).toEqual([
|
|
316
|
+
'agent',
|
|
317
|
+
'session-debrief',
|
|
318
|
+
'claude-mem',
|
|
319
|
+
'manual',
|
|
320
|
+
]);
|
|
321
|
+
// The derived type must include every const member.
|
|
322
|
+
const sample: BrainObservationSourceType[] = [...BRAIN_OBSERVATION_SOURCE_TYPES];
|
|
323
|
+
expect(sample).toHaveLength(4);
|
|
324
|
+
});
|
|
325
|
+
|
|
326
|
+
it('ObserveBrainParams accepts the minimal required shape (text only)', () => {
|
|
327
|
+
const params: ObserveBrainParams = { text: 'hello world' };
|
|
328
|
+
expect(params.text).toBe('hello world');
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
it('ObserveBrainResult mirrors the persisted row identity tuple', () => {
|
|
332
|
+
const result: ObserveBrainResult = {
|
|
333
|
+
id: 'O-new',
|
|
334
|
+
type: 'observation',
|
|
335
|
+
createdAt: '2026-05-21T12:00:00Z',
|
|
336
|
+
};
|
|
337
|
+
expect(result.id).toBe('O-new');
|
|
338
|
+
expect(result.type).toBe('observation');
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
it('BudgetedRetrievalOptions composes all three optional filter axes', () => {
|
|
342
|
+
const opts: BudgetedRetrievalOptions = {
|
|
343
|
+
types: ['semantic', 'procedural'],
|
|
344
|
+
tiers: ['medium', 'long'],
|
|
345
|
+
verified: true,
|
|
346
|
+
};
|
|
347
|
+
expect(opts.types).toHaveLength(2);
|
|
348
|
+
expect(opts.tiers).toHaveLength(2);
|
|
349
|
+
expect(opts.verified).toBe(true);
|
|
350
|
+
});
|
|
351
|
+
|
|
352
|
+
it('BudgetedResult tracks token usage, remaining budget, and exclusion count', () => {
|
|
353
|
+
const result: BudgetedResult = {
|
|
354
|
+
entries: [
|
|
355
|
+
{
|
|
356
|
+
id: 'L-1',
|
|
357
|
+
type: 'learning',
|
|
358
|
+
title: 'insight',
|
|
359
|
+
text: 'body',
|
|
360
|
+
score: 0.42,
|
|
361
|
+
tokensEstimated: 32,
|
|
362
|
+
},
|
|
363
|
+
],
|
|
364
|
+
tokensUsed: 32,
|
|
365
|
+
tokensRemaining: 468,
|
|
366
|
+
excluded: 0,
|
|
367
|
+
};
|
|
368
|
+
expect(result.entries).toHaveLength(1);
|
|
369
|
+
expect(result.tokensUsed + result.tokensRemaining).toBe(500);
|
|
370
|
+
});
|
|
371
|
+
});
|