Skip to content

Commit d08d72f

Browse files
committed
feat: Update CORTEX design plan and execution plan with status and next steps; enhance routing policy resolution and tests
1 parent 0250033 commit d08d72f

File tree

4 files changed

+176
-37
lines changed

4 files changed

+176
-37
lines changed

CORTEX-DESIGN-PLAN-TODO.md

Lines changed: 25 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,20 @@ Interpretation rule for this document:
2222
1. Architectural intent remains here.
2323
2. Execution order, command contract, and test matrix are governed by `PROJECT-EXECUTION-PLAN.md`.
2424

25+
### 0.1 Status Update (2026-03-11)
26+
27+
Completed since the prior snapshot:
28+
1. Model-profile source-of-truth layer exists (`core/ModelProfile.ts`, `core/ModelDefaults.ts`, `core/ModelProfileResolver.ts`).
29+
2. Routing policy dimensions are now derived from profile-owned embedding dimensions (`createRoutingPolicy`).
30+
3. Guard command exists for model-related hardcoded numeric literals (`npm run guard:model-derived`).
31+
4. Runtime numeric constants are centralized for backend/storage internals (`core/NumericConstants.ts`).
32+
5. Runtime helper resolves model metadata and derives routing policy in one call (`resolveRoutingPolicyForModel` in `Policy.ts`).
33+
34+
Next focus:
35+
1. Wire resolved model profiles into runtime ingest/query entry points.
36+
2. Build embedding provider resolver + runner modules and associated tests.
37+
3. Add browser/electron runtime test lanes to match merge-gate policy.
38+
2539
## 1. Design
2640

2741
### 1.1 Product contract
@@ -139,11 +153,10 @@ Graceful degradation:
139153

140154
### 1.9 Current gap analysis from repo snapshot
141155
Observed blockers in current PoC files:
142-
1. Interface mismatch: `VectorBackend.ts` method signatures differ from concrete backend implementations.
143-
2. `BackendKind` and `detectBackend` are referenced in code but only defined in sketch docs.
144-
3. No project scaffolding (`package.json`, `tsconfig`, test runner, lint config).
145-
4. Shader and backend files are present but not integrated into an executable runtime.
146-
5. No concrete OPFS or IndexedDB implementation files yet.
156+
1. Embedding runtime modules (provider resolver + runner) are still missing.
157+
2. Ingest/query orchestrators are not yet wired to resolved `ModelProfile` values.
158+
3. Browser/Electron runtime test lanes are not yet implemented in scripts/CI.
159+
4. Shader and backend files compile but are not yet integrated into a full vertical runtime path.
147160

148161
These are Phase 0 blockers and should be fixed before feature work.
149162

@@ -256,16 +269,16 @@ Priority legend:
256269
3. P2 = optimization, resilience, polish.
257270

258271
### P0 (do first)
259-
1. Create TypeScript project scaffolding (`package.json`, `tsconfig`, test runner).
260-
2. Define canonical shared types for all entities from sketch and errata.
261-
3. Resolve `VectorBackend` interface mismatch against all backend classes.
262-
4. Add `BackendKind` and `detectBackend` in real code module.
263-
5. Add missing imports/exports so backend factory compiles.
272+
1. ~~Create TypeScript project scaffolding (`package.json`, `tsconfig`, test runner).~~ ✅ Done
273+
2. ~~Define canonical shared types for all entities from sketch and errata.~~ ✅ Done
274+
3. ~~Resolve `VectorBackend` interface mismatch against all backend classes.~~ ✅ Done
275+
4. ~~Add `BackendKind` and `detectBackend` in real code module.~~ ✅ Done
276+
5. ~~Add missing imports/exports so backend factory compiles.~~ ✅ Done
264277
6. Decide and document naming convention: `Metroid` vs `Medoid`.
265278
7. Add minimal CI workflow for build and tests.
266-
8. Add lint/format rules for consistent style.
279+
8. ~~Add lint/format rules for consistent style.~~ ✅ Done
267280
9. Add deterministic floating-point tolerance helpers for backend parity tests.
268-
10. Add smoke test that instantiates each backend or cleanly falls back.
281+
10. ~~Add smoke test that instantiates each backend or cleanly falls back.~~ ✅ Done (`tests/BackendSmoke.test.ts`)
269282

270283
### P1 (v1 core)
271284
1. ~~Implement `OPFSVectorStore.appendVector` and `readVector`.~~ ✅ Done (Phase 1, 2026-03-11)

PROJECT-EXECUTION-PLAN.md

Lines changed: 53 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,48 @@
22

33
This file is the canonical carry-over plan for implementation sequencing, test gates, and next-session priority. Keep this file updated as work progresses.
44

5+
## Pass Status (2026-03-11)
6+
7+
Completed in this pass:
8+
1. Implemented `ModelProfile` source-of-truth layer:
9+
- `core/ModelProfile.ts`
10+
- `core/ModelDefaults.ts`
11+
- `core/ModelProfileResolver.ts`
12+
2. Added TDD coverage for model defaults/resolution and routing derivation:
13+
- `tests/model/ModelDefaults.test.ts`
14+
- `tests/model/ModelProfileResolver.test.ts`
15+
- `tests/model/RoutingPolicy.test.ts`
16+
3. Added `createRoutingPolicy(...)` derivation from profile-owned embedding dimensions.
17+
4. Added runtime numeric constants surface (`core/NumericConstants.ts`) and removed repeated byte/workgroup literals from backends and storage paths.
18+
5. Added `guard:model-derived` command and scanner (`scripts/guard-model-derived.mjs`) to block hardcoded model-related numeric literals outside approved sources.
19+
6. Validation gates passed in this workspace state:
20+
- `npm run test:unit`
21+
- `npm run guard:model-derived`
22+
- `npm run build`
23+
- `npm run lint`
24+
7. Added model-profile-to-policy bridge helper so runtime callers can resolve profile and derive routing in one step:
25+
- `resolveRoutingPolicyForModel(...)` in `Policy.ts`
26+
- integration tests in `tests/model/RoutingPolicy.test.ts`
27+
28+
Open items carried to next pass:
29+
1. Wire resolved `ModelProfile` into first concrete ingest/query orchestrator path (once those runtime modules are added).
30+
2. Add embedding provider resolver/runner modules and connect fallback policy to runtime execution.
31+
3. Add browser/electron runtime scripts and CI lanes for non-Node merge gating.
32+
533
## Next Session Highest Priority (P0)
634

7-
Run a full code pass across the repository before new feature coding.
35+
Integrate model-profile ownership into runtime flows and start the embedding vertical slice.
836

937
Instruction:
10-
1. Traverse all TypeScript source and tests.
11-
2. Remove hardcoded model-dependent assumptions.
12-
3. Classify every numeric constant as one of:
13-
- `model-derived`: must come from resolved model metadata.
14-
- `runtime-policy`: must come from explicit policy/config objects.
15-
4. Add or update tests first (Red), then implement (Green), then refactor.
38+
1. Use `ModelProfileResolver` at runtime boundaries before any policy derivation or embedding execution.
39+
2. Implement first embedding runner/provider resolver slice with fallback semantics.
40+
3. Keep strict TDD (Red -> Green -> Refactor).
41+
4. If a blocker appears, record it in this document under an error log entry and continue with the next actionable slice.
1642

1743
Definition of done for this pass:
18-
1. No model-dependent domain constants remain in feature code.
19-
2. A `ModelProfile` contract is the single source of truth for model-derived values.
20-
3. A guard command fails CI when disallowed hardcoded literals are introduced.
44+
1. Runtime path resolves model metadata through `ModelProfileResolver` before use.
45+
2. Embedding provider resolver tests and implementation are present.
46+
3. Any unresolved blocker is documented with file/symptom/next action.
2147

2248
## Non-Negotiable Rules
2349

@@ -30,11 +56,11 @@ Definition of done for this pass:
3056

3157
1. Lock contracts and TDD workflow.
3258
2. Lock command contract and CI lanes.
33-
3. Implement model-profile layer first:
59+
3. ~~Implement model-profile layer first:~~ ✅ Done (2026-03-11)
3460
- `core/ModelProfile.ts`
3561
- `core/ModelProfileResolver.ts`
3662
- `core/ModelDefaults.ts`
37-
4. Replace hardcoded model-dependent values with `ModelProfile` lookups.
63+
4. ~~Replace hardcoded model-dependent values with `ModelProfile` lookups.~~ ✅ Done for current code paths (2026-03-11)
3864
5. Implement embedding runner with fallback chain and telemetry:
3965
- `embeddings/EmbeddingRunner.ts`
4066
- `embeddings/ProviderResolver.ts`
@@ -63,24 +89,27 @@ Definition of done for this pass:
6389

6490
## Command Contract
6591

92+
Available now:
6693
1. `npm run test:unit`
6794
2. `npm run test:unit -- tests/model/ModelProfileResolver.test.ts`
6895
3. `npm run test:unit -- tests/model/ModelDefaults.test.ts`
69-
4. `npm run test:unit -- tests/embeddings/ProviderResolver.test.ts`
70-
5. `npm run test:unit -- tests/embeddings/OnnxEmbeddingRunner.test.ts`
71-
6. `npm run guard:model-derived`
72-
7. `npm run test:browser`
73-
8. `npm run test:electron`
74-
9. `npm run build && npm run lint`
75-
10. `npm run test:all`
76-
11. `npm run benchmark`
96+
4. `npm run guard:model-derived`
97+
5. `npm run build && npm run lint`
98+
99+
Planned commands to add in later passes:
100+
1. `npm run test:unit -- tests/embeddings/ProviderResolver.test.ts`
101+
2. `npm run test:unit -- tests/embeddings/OnnxEmbeddingRunner.test.ts`
102+
3. `npm run test:browser`
103+
4. `npm run test:electron`
104+
5. `npm run test:all`
105+
6. `npm run benchmark`
77106

78107
## Known Hardcoded Hotspots To Clean First
79108

80-
1. `core/types.ts` comments with sample token/dimension values.
81-
2. `Policy.ts` sample projection dimensions.
82-
3. `Cortex-sketch.md` and `Cortex-sketch-errata.md` illustrative constants (`2048`, `768`, `128`, `0.68`, `40`, etc.).
83-
4. Any ingest/query defaults currently assumed without model metadata backing.
109+
1. ~~`core/types.ts` comments with sample token/dimension values.~~ ✅ Updated to source-owned wording.
110+
2. ~~`Policy.ts` sample projection dimensions.~~ ✅ Replaced with derived policy implementation.
111+
3. ~~`Cortex-sketch.md` and `Cortex-sketch-errata.md` illustrative constants (`2048`, `768`, `128`, `0.68`, `40`, etc.).~~ ✅ Clarified as illustrative.
112+
4. Any ingest/query defaults currently assumed without model metadata backing. (Pending runtime module implementation)
84113

85114
## Scope Notes
86115

Policy.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import type { ModelProfile } from "./core/ModelProfile";
2+
import {
3+
ModelProfileResolver,
4+
type ModelProfileResolverOptions,
5+
type ResolveModelProfileInput,
6+
} from "./core/ModelProfileResolver";
27

38
export type QueryScope = "broad" | "normal" | "narrow" | "default";
49

@@ -16,6 +21,17 @@ export interface RoutingPolicy {
1621
narrow: ProjectionHead;
1722
}
1823

24+
export interface ResolvedRoutingPolicy {
25+
modelProfile: ModelProfile;
26+
routingPolicy: RoutingPolicy;
27+
}
28+
29+
export interface ResolveRoutingPolicyOptions {
30+
resolver?: ModelProfileResolver;
31+
resolverOptions?: ModelProfileResolverOptions;
32+
routingPolicyOverrides?: Partial<RoutingPolicyDerivation>;
33+
}
34+
1935
export interface RoutingPolicyDerivation {
2036
broadDimRatio: number;
2137
normalDimRatio: number;
@@ -112,3 +128,20 @@ export function createRoutingPolicy(
112128
},
113129
};
114130
}
131+
132+
export function resolveRoutingPolicyForModel(
133+
input: ResolveModelProfileInput,
134+
options: ResolveRoutingPolicyOptions = {},
135+
): ResolvedRoutingPolicy {
136+
const resolver =
137+
options.resolver ?? new ModelProfileResolver(options.resolverOptions);
138+
const modelProfile = resolver.resolve(input);
139+
140+
return {
141+
modelProfile,
142+
routingPolicy: createRoutingPolicy(
143+
modelProfile,
144+
options.routingPolicyOverrides,
145+
),
146+
};
147+
}

tests/model/RoutingPolicy.test.ts

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import { describe, expect, it } from "vitest";
22

3-
import { createRoutingPolicy } from "../../Policy";
3+
import {
4+
createRoutingPolicy,
5+
resolveRoutingPolicyForModel,
6+
} from "../../Policy";
7+
import { ModelProfileResolver } from "../../core/ModelProfileResolver";
48

59
describe("createRoutingPolicy", () => {
610
it("derives projection dimensions from embedding dimension", () => {
@@ -37,3 +41,63 @@ describe("createRoutingPolicy", () => {
3741
expect(policy.narrow.offset).toBe(24576);
3842
});
3943
});
44+
45+
describe("resolveRoutingPolicyForModel", () => {
46+
it("resolves from metadata and derives policy in one call", () => {
47+
const result = resolveRoutingPolicyForModel({
48+
modelId: "nomic-embed-text",
49+
metadata: {
50+
embeddingDimension: 768,
51+
contextWindowTokens: 8192,
52+
},
53+
});
54+
55+
expect(result.modelProfile.source).toBe("metadata");
56+
expect(result.modelProfile.embeddingDimension).toBe(768);
57+
expect(result.routingPolicy.broad.dimIn).toBe(768);
58+
expect(result.routingPolicy.normal.dimOut).toBe(192);
59+
});
60+
61+
it("resolves from registry when metadata is missing", () => {
62+
const result = resolveRoutingPolicyForModel(
63+
{ modelId: "all-MiniLM-L6-v2" },
64+
{
65+
resolverOptions: {
66+
registry: {
67+
"all-minilm-l6-v2": {
68+
embeddingDimension: 384,
69+
contextWindowTokens: 512,
70+
},
71+
},
72+
},
73+
},
74+
);
75+
76+
expect(result.modelProfile.source).toBe("registry");
77+
expect(result.routingPolicy.narrow.dimIn).toBe(384);
78+
});
79+
80+
it("supports injected resolver and routing overrides", () => {
81+
const resolver = new ModelProfileResolver({
82+
registry: {
83+
"my-model": {
84+
embeddingDimension: 1024,
85+
contextWindowTokens: 4096,
86+
},
87+
},
88+
});
89+
90+
const result = resolveRoutingPolicyForModel(
91+
{ modelId: "my-model" },
92+
{
93+
resolver,
94+
routingPolicyOverrides: {
95+
broadHashBits: 64,
96+
},
97+
},
98+
);
99+
100+
expect(result.modelProfile.embeddingDimension).toBe(1024);
101+
expect(result.routingPolicy.broad.bits).toBe(64);
102+
});
103+
});

0 commit comments

Comments
 (0)