From 5ba57301a15cf44dcd18134279b7fbd24cc332ab Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 31 Aug 2026 23:11:53 +0000 Subject: [PATCH 1/3] wip: seed-loader import extensions --- .../src/seed-loader-composite-external-id.test.ts | 2 +- .../metadata-protocol/src/seed-loader-deferred-dropped.test.ts | 2 +- .../metadata-protocol/src/seed-loader-deferred-failure.test.ts | 2 +- .../src/seed-loader-engine-schema-fallback.test.ts | 2 +- .../src/seed-loader-multi-value-reference.test.ts | 2 +- packages/metadata-protocol/src/seed-loader-replay.test.ts | 2 +- packages/metadata-protocol/src/seed-loader-retry.test.ts | 2 +- .../src/seed-loader-state-machine-exempt.test.ts | 2 +- .../metadata-protocol/src/seed-loader-summary-stale.test.ts | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/packages/metadata-protocol/src/seed-loader-composite-external-id.test.ts b/packages/metadata-protocol/src/seed-loader-composite-external-id.test.ts index c4bece344d..26bea21141 100644 --- a/packages/metadata-protocol/src/seed-loader-composite-external-id.test.ts +++ b/packages/metadata-protocol/src/seed-loader-composite-external-id.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. import { describe, it, expect, vi } from 'vitest'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core'; diff --git a/packages/metadata-protocol/src/seed-loader-deferred-dropped.test.ts b/packages/metadata-protocol/src/seed-loader-deferred-dropped.test.ts index 5acf8f8bce..2a34032ecb 100644 --- a/packages/metadata-protocol/src/seed-loader-deferred-dropped.test.ts +++ b/packages/metadata-protocol/src/seed-loader-deferred-dropped.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. import { describe, it, expect, vi } from 'vitest'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core'; diff --git a/packages/metadata-protocol/src/seed-loader-deferred-failure.test.ts b/packages/metadata-protocol/src/seed-loader-deferred-failure.test.ts index 24406d1d43..82a0e2e1f4 100644 --- a/packages/metadata-protocol/src/seed-loader-deferred-failure.test.ts +++ b/packages/metadata-protocol/src/seed-loader-deferred-failure.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. import { describe, it, expect, vi } from 'vitest'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core'; diff --git a/packages/metadata-protocol/src/seed-loader-engine-schema-fallback.test.ts b/packages/metadata-protocol/src/seed-loader-engine-schema-fallback.test.ts index 616bf8111f..3f8452f512 100644 --- a/packages/metadata-protocol/src/seed-loader-engine-schema-fallback.test.ts +++ b/packages/metadata-protocol/src/seed-loader-engine-schema-fallback.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. import { describe, it, expect, vi } from 'vitest'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core'; diff --git a/packages/metadata-protocol/src/seed-loader-multi-value-reference.test.ts b/packages/metadata-protocol/src/seed-loader-multi-value-reference.test.ts index 41454d69f0..cba2f99332 100644 --- a/packages/metadata-protocol/src/seed-loader-multi-value-reference.test.ts +++ b/packages/metadata-protocol/src/seed-loader-multi-value-reference.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2026 ObjectStack. Licensed under the Apache-2.0 license. import { describe, it, expect, vi } from 'vitest'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core'; diff --git a/packages/metadata-protocol/src/seed-loader-replay.test.ts b/packages/metadata-protocol/src/seed-loader-replay.test.ts index b8e1f1746c..dcae11e8dc 100644 --- a/packages/metadata-protocol/src/seed-loader-replay.test.ts +++ b/packages/metadata-protocol/src/seed-loader-replay.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. import { describe, it, expect, vi } from 'vitest'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core'; diff --git a/packages/metadata-protocol/src/seed-loader-retry.test.ts b/packages/metadata-protocol/src/seed-loader-retry.test.ts index 6ddfeb473f..8a49d69199 100644 --- a/packages/metadata-protocol/src/seed-loader-retry.test.ts +++ b/packages/metadata-protocol/src/seed-loader-retry.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. import { describe, it, expect, vi } from 'vitest'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core'; diff --git a/packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts b/packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts index b1e2974d8f..a2b2dfa51b 100644 --- a/packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts +++ b/packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts @@ -1,7 +1,7 @@ // Copyright (c) 2025 ObjectStack. Licensed under the Apache-2.0 license. import { describe, it, expect, vi } from 'vitest'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate, type EngineFindOneQueryInput } from '@objectstack/metadata-core'; diff --git a/packages/metadata-protocol/src/seed-loader-summary-stale.test.ts b/packages/metadata-protocol/src/seed-loader-summary-stale.test.ts index 5e339bad6f..9a083bbd8b 100644 --- a/packages/metadata-protocol/src/seed-loader-summary-stale.test.ts +++ b/packages/metadata-protocol/src/seed-loader-summary-stale.test.ts @@ -2,7 +2,7 @@ import { describe, it, expect, vi } from 'vitest'; import { SeedLoadResultSchema, SeedLoaderResultSchema } from '@objectstack/spec/data'; -import { SeedLoaderService } from './seed-loader'; +import { SeedLoaderService } from './seed-loader.js'; import type { IDataEngine, IMetadataService } from '@objectstack/spec/contracts'; import { assertEngineDeleteDispatch, assertEngineUpdateDispatch, assertEngineFindOnePredicate } from '@objectstack/metadata-core'; From 07d76c7597a502791ff4469c4ccb96f138ae0090 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 31 Aug 2026 23:13:22 +0000 Subject: [PATCH 2/3] wip: seed row type + residual test repairs --- packages/metadata-protocol/src/mutation-listeners.test.ts | 7 ++++++- .../metadata-protocol/src/protocol.batch-atomic.test.ts | 5 ++++- .../src/protocol.stored-conversions.test.ts | 7 ++++++- .../src/protocol.stored-migration.test.ts | 7 ++++++- .../src/seed-loader-state-machine-exempt.test.ts | 2 +- .../src/sys-metadata-repository.history-counters.test.ts | 2 +- 6 files changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/metadata-protocol/src/mutation-listeners.test.ts b/packages/metadata-protocol/src/mutation-listeners.test.ts index 8bfbcb020b..3e6d3c1dac 100644 --- a/packages/metadata-protocol/src/mutation-listeners.test.ts +++ b/packages/metadata-protocol/src/mutation-listeners.test.ts @@ -20,7 +20,12 @@ function makeProtocol() { return new ObjectStackProtocolImplementation({} as any); } -const evt = (over: Partial = {}): MetadataMutationEvent => ({ +// `body` mirrors `runMutationProjector`'s own declared parameter +// (`MetadataMutationEvent & { body?: unknown }`) — the projector cases below +// pass one, and the bare `Partial` rejected it. +const evt = ( + over: Partial & { body?: unknown } = {}, +): MetadataMutationEvent & { body?: unknown } => ({ type: 'hook', name: 'rebind_probe_hook', state: 'active', diff --git a/packages/metadata-protocol/src/protocol.batch-atomic.test.ts b/packages/metadata-protocol/src/protocol.batch-atomic.test.ts index c0ade64b05..3f936ba10a 100644 --- a/packages/metadata-protocol/src/protocol.batch-atomic.test.ts +++ b/packages/metadata-protocol/src/protocol.batch-atomic.test.ts @@ -38,7 +38,10 @@ function makeTransactionalEngine(opts: { driverCanTransact?: boolean } = {}) { const rollbacks: unknown[] = []; const handle = { id: 'trx-1' }; - const insert = vi.fn(async (_object: string, data: any) => { + // Third parameter declared because the write path PASSES it and the + // assertions below read `call[2]`: a 2-arity mock made that a tuple + // with no element at index 2. + const insert = vi.fn(async (_object: string, data: any, _options?: any) => { if (data?.title === POISON) throw new Error('insert exploded'); return { id: `rec-${insert.mock.calls.length}`, ...data }; }); diff --git a/packages/metadata-protocol/src/protocol.stored-conversions.test.ts b/packages/metadata-protocol/src/protocol.stored-conversions.test.ts index 5b4638e6bf..b078e7094a 100644 --- a/packages/metadata-protocol/src/protocol.stored-conversions.test.ts +++ b/packages/metadata-protocol/src/protocol.stored-conversions.test.ts @@ -44,7 +44,12 @@ function matches(r: Row, where: Record): boolean { return true; } -function makeStubEngine(seedRows: Array & { type: string; name: string; metadata: unknown }>) { +// `metadata` is `Omit`-ed out of the `Partial` half, never merely +// intersected over it: `string & unknown` is `string`, so a plain +// intersection refuses every body written as an object literal. +function makeStubEngine( + seedRows: Array, 'metadata'> & { type: string; name: string; metadata: unknown }>, +) { let nextId = 0; const rows: Row[] = seedRows.map((r) => ({ id: `r_${++nextId}`, diff --git a/packages/metadata-protocol/src/protocol.stored-migration.test.ts b/packages/metadata-protocol/src/protocol.stored-migration.test.ts index 616ea5dbc6..8919ac3f1d 100644 --- a/packages/metadata-protocol/src/protocol.stored-migration.test.ts +++ b/packages/metadata-protocol/src/protocol.stored-migration.test.ts @@ -57,7 +57,12 @@ function matches(r: Record, where: Record): boolea * actually observable. */ function makeStubEngine( - seedRows: Array & { type: string; name: string; metadata: unknown }>, + // `metadata` is `Omit`-ed out of the `Partial` half, never merely + // intersected over it: on the row `metadata` is the STORED string, and + // `string & unknown` is `string`, so a plain intersection refuses every + // body written as an object literal — which is the seeding convenience + // this harness exists for, and what it already does at runtime below. + seedRows: Array, 'metadata'> & { type: string; name: string; metadata: unknown }>, ) { let nextId = 0; const tables = new Map[]>(); diff --git a/packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts b/packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts index a2b2dfa51b..1922eb4f82 100644 --- a/packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts +++ b/packages/metadata-protocol/src/seed-loader-state-machine-exempt.test.ts @@ -193,7 +193,7 @@ describe('seed loader — state_machine initialStates exemption (#3433)', () => // fallback), its options must carry the exemption flag — that is what the // engine reads to skip the state_machine rule. const writeCalls = [ - ...(engine.insertMany as any).mock.calls, + ...((engine as any).insertMany).mock.calls, ...(engine.insert as any).mock.calls, ].filter(([obj]) => obj === 'showcase_project'); expect(writeCalls.length).toBeGreaterThan(0); diff --git a/packages/metadata-protocol/src/sys-metadata-repository.history-counters.test.ts b/packages/metadata-protocol/src/sys-metadata-repository.history-counters.test.ts index 1e454fea99..4ed64b4840 100644 --- a/packages/metadata-protocol/src/sys-metadata-repository.history-counters.test.ts +++ b/packages/metadata-protocol/src/sys-metadata-repository.history-counters.test.ts @@ -334,7 +334,7 @@ describe('#4867 — history counters are never invented from a failed read', () expect(infoSpy).toHaveBeenCalledTimes(1); expect((infoSpy.mock.calls[0] as [string])[0]).toMatch(/readable again/i); // Numbering resumes after the surviving max — never from 1 again. - expect(engine.committed().at(-1)).toEqual({ + expect(engine.committed().slice(-1)[0]).toEqual({ name: 'case_grid', version: 3, event_seq: 4, From 926a38998c7f4bc03ce5308660e911badccb3342 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 31 Aug 2026 23:18:58 +0000 Subject: [PATCH 3/3] wip: manifest script + DEBT graduation --- packages/metadata-protocol/package.json | 1 + scripts/check-type-check-coverage.mjs | 26 +++++++++++-------------- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/packages/metadata-protocol/package.json b/packages/metadata-protocol/package.json index 60e3abe1f4..75a22c6aef 100644 --- a/packages/metadata-protocol/package.json +++ b/packages/metadata-protocol/package.json @@ -27,6 +27,7 @@ "build": "tsup && node ../../scripts/check-dts-emitted.mjs", "dev": "tsc --watch", "clean": "rm -rf dist", + "typecheck": "tsc --noEmit", "test": "vitest run", "test:watch": "vitest" }, diff --git a/scripts/check-type-check-coverage.mjs b/scripts/check-type-check-coverage.mjs index f4ca7d738b..84c4c6082a 100644 --- a/scripts/check-type-check-coverage.mjs +++ b/scripts/check-type-check-coverage.mjs @@ -677,15 +677,6 @@ const DEBT = { + 'metadata.test.ts (34) and register-notifies-watchers.test.ts (16) do still hold 50 of the 89, ' + 'but that is over HALF -- the "two thirds" claimed here was true at neither 92 nor 89.', }, - '@objectstack/metadata-protocol': { - errors: 63, - note: 'code-tier 40 (TS2322 x34, TS2532/TS2493 x2 each, TS2353, TS2339); config-tier 10 (TS2835 x9, ' - + 'TS2550); noise 13 (TS7006). Re-measured 63 at 5ab08428 -- the 2.25x drift that opened #5278, and ' - + 'the entry whose note was most misleading: it read "code-tier 9, the rest config-tier and noise", ' - + 'while code-tier alone is now 40. 27 of the TS2322 are in protocol.stored-migration.test.ts and 10 ' - + 'in seed-loader-multi-value-reference.test.ts, so this is concentrated debt in two files rather ' - + 'than a package-wide drizzle -- read it as two repairs, not as forty.', - }, '@objectstack/observability': { errors: 11, note: 'all code-tier (TS2554 wrong arity x10, TS2552).', @@ -1898,9 +1889,12 @@ function workspacePackages() { // "the workspace root itself: code-tier 4 ..." qualifies); // * a tier counted twice, or a further `code-tier 9`-shaped count ANYWHERE // later in the note, means the note is quoting its own history and the -// entry is skipped. metadata-protocol quotes the misleading note #5278 -// found ("code-tier 9, the rest config-tier and noise") and is skipped for -// exactly that reason -- correct entry, no verdict; +// entry is skipped. metadata-protocol's entry quoted the misleading note +// #5278 found ("code-tier 9, the rest config-tier and noise") and was +// skipped for exactly that reason -- correct entry, no verdict. That entry +// has since GRADUATED (the package declares `typecheck` and its 63 errors +// are repaired), so the rule's live example is the self-test case below +// rather than a ledger row you can still read here; // * per-code tallies (`TS2835 x72, TS7006 x49, ...`) are NOT summed. They are // partial by construction, and the worked example this rule was written // against says why: `@objectstack/rest`'s tally summed to 147 while saying @@ -4206,9 +4200,11 @@ function selfTest() { }, { // The false-positive guard, and the reason the rule abstains rather than - // reasons: metadata-protocol's real note quotes the misleading one #5278 - // found. Reading either count as the entry's own would red a correct - // entry, which is worse than the silence this check replaces. + // reasons: metadata-protocol's real note quoted the misleading one #5278 + // found (that entry has since graduated, which is why this synthetic case + // now carries the shape). Reading either count as the entry's own would + // red a correct entry, which is worse than the silence this check + // replaces. label: 'a note quoting its own history is SKIPPED, not guessed at', packages: [], root: { name: 'root', scripts: { typecheck: 'turbo run typecheck' } },