diff --git a/package.json b/package.json index 4d0c5c0..0adb9fc 100644 --- a/package.json +++ b/package.json @@ -14,8 +14,8 @@ }, "scripts": { "build": "node scripts/build.mjs", - "typecheck": "node scripts/build.mjs --check", - "test": "npm run build && node dist/tests/run-tests.js", + "typecheck": "tsc --noEmit", + "test": "npm run typecheck && npm run build && node dist/tests/run-tests.js", "start": "npm run build && node dist/src/cli.js", "codex": "npm run build && node dist/src/cli.js codex --json", "clean": "rm -rf dist", @@ -60,5 +60,9 @@ "external-brain", "session-memory", "developer-tools" - ] + ], + "devDependencies": { + "@types/node": "^22.19.19", + "typescript": "^6.0.3" + } } diff --git a/src/cli.ts b/src/cli.ts index 2f29ddd..b98ecc0 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -14,6 +14,13 @@ import { runBenchmarkCli } from './benchmark/index.js'; import { runScanCli } from './scan/index.js'; import { exportClaudeMd, exportAgentsMd } from './export/index.js'; +type HistoryRecord = { + readonly valid_from?: string | null; + readonly valid_until?: string | null; + readonly status: string; + readonly updated_at: string; +}; + export function runCli(argv: string[], io: CliIo): number { let parsed; try { @@ -510,8 +517,7 @@ export function runCli(argv: string[], io: CliIo): number { const store = createTruthKernelStorage(storePath, { autoMigrate: true }); try { // Try entity history first, then decision history - let history: readonly { valid_from?: string | null; valid_until?: string | null; status: string; updated_at: string; [key: string]: unknown }[] = - store.listEntityHistory(parsed.entityId); + let history: readonly HistoryRecord[] = store.listEntityHistory(parsed.entityId); let historyType = 'entity'; if (history.length === 0) { diff --git a/src/contracts/types.ts b/src/contracts/types.ts index 0754cb8..4a0a2d4 100644 --- a/src/contracts/types.ts +++ b/src/contracts/types.ts @@ -27,6 +27,8 @@ export type SourceKind = | 'transcript' | 'note' | 'pointer' + | 'probe' + | 'local_adapter' | 'observation' | 'daily' | 'person' @@ -72,6 +74,8 @@ const SOURCE_KIND_SET = new Set([ 'transcript', 'note', 'pointer', + 'probe', + 'local_adapter', 'observation', 'daily', 'person', diff --git a/src/facade/facade.ts b/src/facade/facade.ts index 3af5362..e4d7461 100644 --- a/src/facade/facade.ts +++ b/src/facade/facade.ts @@ -219,13 +219,13 @@ export function createFacade(options: FacadeOptions = {}): ManagedFacadeApi { }, sourceStatus(): LocalSourceStatusResult { return buildSourceStatusResult({ - sourceAdaptersEnabled: options.sourceAdaptersEnabled, + ...(options.sourceAdaptersEnabled ? { sourceAdaptersEnabled: options.sourceAdaptersEnabled } : {}), jcpLiveReader, }); }, health(): WaypathHealthResult { return healthCheck(store, { - sourceAdaptersEnabled: options.sourceAdaptersEnabled, + ...(options.sourceAdaptersEnabled ? { sourceAdaptersEnabled: options.sourceAdaptersEnabled } : {}), jcpLiveReader, }); }, @@ -478,7 +478,7 @@ function withEvidenceAppendix( store, { ...(recallWeights ? { weights: recallWeights } : {}), - jcpLiveReader, + ...(jcpLiveReader ? { jcpLiveReader } : {}), }, ); diff --git a/src/jarvis_fusion/archive-provider.ts b/src/jarvis_fusion/archive-provider.ts index e0a916c..25f0d06 100644 --- a/src/jarvis_fusion/archive-provider.ts +++ b/src/jarvis_fusion/archive-provider.ts @@ -466,7 +466,9 @@ export function buildLocalArchiveBundle( const extraCandidates = [...jcpRanked.candidates, ...mempalaceCandidates]; const extraRankedLists: RankedList[] = [ ...jcpRanked.rankedLists, - ...(mempalaceCandidates.length > 0 ? [{ dimension: 'keyword', results: mempalaceCandidates }] : []), + ...(mempalaceCandidates.length > 0 + ? [{ dimension: 'keyword' as const, results: mempalaceCandidates }] + : []), ]; const searchResults = store diff --git a/src/jarvis_fusion/bootstrap-import.ts b/src/jarvis_fusion/bootstrap-import.ts index c508550..0a5af40 100644 --- a/src/jarvis_fusion/bootstrap-import.ts +++ b/src/jarvis_fusion/bootstrap-import.ts @@ -1,4 +1,4 @@ -import type { ImportResult } from '../contracts/index.js'; +import type { ImportResult, ImportRun } from '../contracts/index.js'; import { createDemoSourceReader } from './source-readers-demo.js'; import { createJarvisBrainDbSourceReader, @@ -224,14 +224,14 @@ export function runBootstrapImport(store: SqliteTruthKernelStorage, manifest: Bo } export function toImportResult(result: BootstrapImportResult, storePath: string): ImportResult { - const run = { + const run: ImportRun = { manifest_id: result.manifest_id, mode: result.import_mode, imported_at: result.imported_at, reader_names: result.readers, source_anchors: result.readers.map((reader) => ({ source_system: reader, - source_kind: 'import_reader', + source_kind: 'import_reader' as const, source_ref: `${result.manifest_id}#${reader}`, })), }; diff --git a/src/jarvis_fusion/truth-kernel/storage.ts b/src/jarvis_fusion/truth-kernel/storage.ts index 5c01ecb..d4f8cd9 100644 --- a/src/jarvis_fusion/truth-kernel/storage.ts +++ b/src/jarvis_fusion/truth-kernel/storage.ts @@ -6,6 +6,7 @@ import type { SourceSystem, GraphContext, GraphRelationshipSummary, + ProvenanceRecord, SqliteQueryResult, TruthDecisionRecord, TruthEntityRecord, @@ -576,13 +577,13 @@ export class SqliteTruthKernelStorage implements TruthKernelStore { return row ? mapRelationship(row) : undefined; } - getProvenance(provenanceId: string) { + getProvenance(provenanceId: string): ProvenanceRecord | undefined { const row = this.get>(`SELECT * FROM provenance_records WHERE provenance_id = :provenance_id LIMIT 1`, { provenance_id: provenanceId }); if (!row) return undefined; return { provenance_id: String(row.provenance_id), - source_system: String(row.source_system), - source_kind: String(row.source_kind), + source_system: String(row.source_system) as SourceSystem, + source_kind: String(row.source_kind) as SourceKind, source_ref: String(row.source_ref), observed_at: row.observed_at === null ? null : String(row.observed_at), imported_at: row.imported_at === null ? null : String(row.imported_at), diff --git a/src/shared/config/runtime-config.ts b/src/shared/config/runtime-config.ts index 807d832..8a317aa 100644 --- a/src/shared/config/runtime-config.ts +++ b/src/shared/config/runtime-config.ts @@ -202,8 +202,8 @@ function decodeRuntimeConfig(raw: TomlObject): RuntimeConfig { function applyEnvOverrides(base: RuntimeConfig, env: EnvMap): RuntimeConfig { const sourceAdapterOverrides = { ...(base.sourceAdapters?.enabled ?? {}) }; - const sourceSystemWeights = { ...(base.retrieval?.weights?.sourceSystems ?? {}) }; - const sourceKindWeights = { ...(base.retrieval?.weights?.sourceKinds ?? {}) }; + const sourceSystemWeights: Record = { ...(base.retrieval?.weights?.sourceSystems ?? {}) }; + const sourceKindWeights: Record = { ...(base.retrieval?.weights?.sourceKinds ?? {}) }; let allowMissingLocalReaders = base.import?.allowMissingLocalReaders; let reviewQueueLimit = base.reviewQueue?.limit; diff --git a/src/shared/globals.d.ts b/src/shared/globals.d.ts deleted file mode 100644 index e1b9865..0000000 --- a/src/shared/globals.d.ts +++ /dev/null @@ -1,43 +0,0 @@ -declare const process: { - argv: string[]; - exitCode?: number; - env: Record; - cwd(): string; - stdout: { - write(chunk: string): void; - }; - stderr: { - write(chunk: string): void; - }; -}; - -declare const console: { - log(...args: unknown[]): void; - error(...args: unknown[]): void; -}; - -declare module 'node:fs' { - export interface Dirent { - name: string; - isDirectory(): boolean; - isFile(): boolean; - } - export function existsSync(path: string): boolean; - export function mkdirSync(path: string, options?: { recursive?: boolean }): void; - export function mkdtempSync(prefix: string): string; - export function readdirSync(path: string): string[]; - export function readdirSync(path: string, options: { withFileTypes: true }): Dirent[]; - export function readFileSync(path: string, encoding: string): string; - export function writeFileSync(path: string, data: string): void; -} - -declare module 'node:os' { - export function homedir(): string; - export function tmpdir(): string; -} - -declare module 'node:path' { - export function dirname(path: string): string; - export function join(...paths: string[]): string; - export function resolve(...paths: string[]): string; -} diff --git a/tests/node-shim.d.ts b/tests/node-shim.d.ts deleted file mode 100644 index 7ab5f22..0000000 --- a/tests/node-shim.d.ts +++ /dev/null @@ -1,42 +0,0 @@ -interface ImportMeta { - url: string; -} - -declare const process: { - cwd(): string; -}; - -declare module 'node:assert/strict' { - type Matcher = RegExp | string; - interface AssertionAPI { - equal(actual: unknown, expected: unknown, message?: string): void; - match(actual: string, matcher: Matcher, message?: string): void; - } - - const assert: AssertionAPI; - export default assert; -} - -declare module 'node:fs' { - export function mkdtempSync(prefix: string): string; - export function writeFileSync(path: string, data: string): void; -} - -declare module 'node:os' { - export function tmpdir(): string; -} - -declare module 'node:path' { - export function dirname(path: string): string; - export function resolve(...paths: string[]): string; -} - -declare module 'node:test' { - type TestFn = () => void | Promise; - function test(name: string, fn: TestFn): void; - export default test; -} - -declare module 'node:url' { - export function fileURLToPath(url: string | URL): string; -} diff --git a/tests/unit/promotion-engine.test.ts b/tests/unit/promotion-engine.test.ts index fbc07c4..7af56c0 100644 --- a/tests/unit/promotion-engine.test.ts +++ b/tests/unit/promotion-engine.test.ts @@ -131,7 +131,7 @@ export function testSubmitWithEvidenceBundleLinkage(): void { evidence_bundle_id: 'bundle:test-evidence', claim_type: 'observation', source: { - source_system: 'test-system', + source_system: 'demo-source', source_kind: 'observation', source_ref: 'test-ref', }, diff --git a/tests/unit/search-pipeline.test.ts b/tests/unit/search-pipeline.test.ts index abfdb87..4db4290 100644 --- a/tests/unit/search-pipeline.test.ts +++ b/tests/unit/search-pipeline.test.ts @@ -47,8 +47,8 @@ export function testRrfFusionMergesLists(): void { } export function testRrfScoreIsRankBased(): void { - const c1: SearchCandidate = { id: '1', title: 'First', content: '', source_type: 'entity', source_system: 's', source_kind: 'k', confidence: null, graph_depth: null, graph_weight: null, metadata: {} }; - const c2: SearchCandidate = { id: '2', title: 'Second', content: '', source_type: 'entity', source_system: 's', source_kind: 'k', confidence: null, graph_depth: null, graph_weight: null, metadata: {} }; + const c1: SearchCandidate = { id: '1', title: 'First', content: '', source_type: 'entity', source_system: 'truth-kernel', source_kind: 'entity', confidence: null, graph_depth: null, graph_weight: null, metadata: {} }; + const c2: SearchCandidate = { id: '2', title: 'Second', content: '', source_type: 'entity', source_system: 'truth-kernel', source_kind: 'entity', confidence: null, graph_depth: null, graph_weight: null, metadata: {} }; const results = rrfFusion([ { dimension: 'keyword', results: [c1, c2] }, @@ -62,7 +62,7 @@ export function testRrfScoreIsRankBased(): void { // --- Dedup Tests --- export function testDedupById(): void { - const candidate: SearchCandidate = { id: 'dup', title: 'Same', content: 'Same content', source_type: 'entity', source_system: 's', source_kind: 'k', confidence: null, graph_depth: null, graph_weight: null, metadata: {} }; + const candidate: SearchCandidate = { id: 'dup', title: 'Same', content: 'Same content', source_type: 'entity', source_system: 'truth-kernel', source_kind: 'entity', confidence: null, graph_depth: null, graph_weight: null, metadata: {} }; const r1: ScoredResult = { candidate, score: 0.5, breakdown: { keyword: 0.5, graph: 0, provenance: 0, lexical: 0, rrf_fused: 0.5 } }; const r2: ScoredResult = { candidate, score: 0.8, breakdown: { keyword: 0.8, graph: 0, provenance: 0, lexical: 0, rrf_fused: 0.8 } }; @@ -75,7 +75,7 @@ export function testDedupTypeDiversity(): void { const results: ScoredResult[] = []; for (let i = 0; i < 10; i++) { results.push({ - candidate: { id: `e${i}`, title: `Entity ${i}`, content: `Unique content ${i} with different words`, source_type: 'entity', source_system: 's', source_kind: 'k', confidence: null, graph_depth: null, graph_weight: null, metadata: {} }, + candidate: { id: `e${i}`, title: `Entity ${i}`, content: `Unique content ${i} with different words`, source_type: 'entity', source_system: 'truth-kernel', source_kind: 'entity', confidence: null, graph_depth: null, graph_weight: null, metadata: {} }, score: 1 - i * 0.01, breakdown: { keyword: 0, graph: 0, provenance: 0, lexical: 0, rrf_fused: 0 }, }); diff --git a/tsconfig.json b/tsconfig.json index 64360ca..ec5961c 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,8 +1,8 @@ { "compilerOptions": { "target": "ES2022", - "module": "Node16", - "moduleResolution": "Node16", + "module": "ESNext", + "moduleResolution": "Bundler", "rootDir": ".", "outDir": "dist", "strict": true, @@ -14,7 +14,9 @@ "skipLibCheck": true, "declaration": true, "resolveJsonModule": false, - "types": [], + "types": [ + "node" + ], "ignoreDeprecations": "6.0" }, "include": [