Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/objectql/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,9 @@
"scripts": {
"build": "tsup && node ../../scripts/check-dts-emitted.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json"
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck",
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/objectql --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/objectql --project tsconfig.test.json"
},
"dependencies": {
"@objectstack/core": "workspace:*",
Expand All@@ -35,6 +37,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"tsx": "^4.23.12",
"typescript": "^6.0.3",
"vitest": "^4.1.10"
},
Expand Down
163 changes: 163 additions & 0 deletions packages/objectql/test-typecheck-debt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
{
"_comment": "Per-file tsc error debt of the @objectstack/objectql TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/objectql gen:test-typecheck-debt",
"_note": "SEEDED at 2a181174a6 by the PR that first put this layer in front of tsc (#13676), workspace closure built first. All 242 errors across 44 files are PRE-EXISTING: that PR edits no test file, and every one of these would have been reported on origin/main had this program ever existed. ⛔ Not one `any` and not one `@ts-expect-error` was added anywhere to open the gate — bulk-suppressing this residue is the exact shape the card was filed to prevent, and it would turn a real gate into a phantom one. The residue is NOT annotation debt to sweep: 14 of the 17 in src/datasource-mapping.test.ts and the bulk of the TS2345 population are one story — a driver double that does not satisfy IDataDriver — and src/engine.test.ts alone carries 102 of the 242, so read the classes before touching anything (`tsc --noEmit --pretty false -p tsconfig.test.json`). ⚠️ src/engine-filter-array-lowering.test.ts is DELIBERATELY ABSENT and must stay absent: it is the #13357 point-3 negative pin proving a refused filter shape cannot reach the reference matcher, it reports zero errors, and an unledgered file is red on its first error. ⚠️ But its zero is a weak guarantee today and must not be read as 'that pin is type-checked': the file holds `const driver: any` and `interface SeenRead { ast: any }` at the very seam the proof reads, so a drifted IDataDriver signature would not redden it. Repairing that is tracked separately and is not a licence to loosen tsconfig.test.json.",
"entries": {
"src/build-probes.test.ts": {
"TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1
},
"src/datasource-mapping.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type 'IDataDriver'.": 14,
"TS6133: 'obj' is declared but its value is never read.": 3
},
"src/engine-audit-anchor-write.test.ts": {
"TS2532: Object is possibly 'undefined'.": 1
},
"src/engine-autonumber-default-format.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 3
},
"src/engine-autonumber-defer.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 4
},
"src/engine-autonumber-resync.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-outage.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-scan.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 5
},
"src/engine-autonumber-seed-suffix.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-cascade-delete.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-data-events.test.ts": {
"TS6133: 'warn' is declared but its value is never read.": 1
},
"src/engine-delete-prior-read-scope.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 3,
"TS6196: 'ObjectSchema' is declared but never used.": 1
},
"src/engine-lifecycle-datasource.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-update-prior-read-scope.test.ts": {
"TS2345: Argument of type 'unknown' is not assignable to parameter of type '…'.": 1
},
"src/engine.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 75,
"TS2339: Property 'registerKind' does not exist on type 'typeof SchemaRegistry'.": 1,
"TS2339: Property 'registerObject' does not exist on type 'typeof SchemaRegistry'.": 3,
"TS2353: Object literal may only specify known properties, and 'filter' does not exist in type '…'.": 1,
"TS7006: Parameter 'name' implicitly has an 'any' type.": 22
},
"src/function-registry-effect.test.ts": {
"TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1
},
"src/hook-binder.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-bulk-previous.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 3,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 3
},
"src/hook-condition-fail-loud.test.ts": {
"TS2339: Property 'catch' does not exist on type '…'.": 2,
"TS2339: Property 'then' does not exist on type '…'.": 5,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 5
},
"src/hook-condition-merged-record.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-previous-scope.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS6133: 'reads' is declared but its value is never read.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/in-memory-aggregation.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/layered-overlay-integration.test.ts": {
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1,
"TS2353: Object literal may only specify known properties, and 'org' does not exist in type 'InMemoryRepositoryOptions'.": 1
},
"src/metadata-service-roundtrip-conformance.test.ts": {
"TS2322: Type 'WritableFixtureLoader' is not assignable to type 'MetadataLoader'.": 1,
"TS2416: Property 'save' in type 'WritableFixtureLoader' is not assignable to the same property in base type 'MetadataLoader'.": 1
},
"src/plugin-authored-hooks.test.ts": {
"TS6133: 'obj' is declared but its value is never read.": 1
},
"src/plugin.integration.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 11,
"TS6133: 'ObjectSchema' is declared but its value is never read.": 1
},
"src/protocol-boot-hydration-scoped.test.ts": {
"TS2322: Type '…' is not assignable to type 'string'.": 3
},
"src/protocol-boot-object-package-binding.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 3
},
"src/protocol-discovery.test.ts": {
"TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ data: string; metadata: string; discovery?: string | undefined; ui?: string | undefined; auth?: string | undefined; automation?: string | undefined; storage?: string | undefined; analytics?: string | undefined; ... 8 more ...; mcp?: string | undefined; }'.": 1
},
"src/protocol-lock-enforcement.test.ts": {
"TS6133: 'beforeEach' is declared but its value is never read.": 1
},
"src/protocol-package-lifecycle.test.ts": {
"TS2339: Property 'mock' does not exist on type 'never'.": 3,
"TS2339: Property 'mockResolvedValue' does not exist on type 'never'.": 2,
"TS7006: Parameter 'c' implicitly has an 'any' type.": 3
},
"src/protocol-publish-rollback.test.ts": {
"TS6133: 'rows' is declared but its value is never read.": 1
},
"src/protocol-recorded-by-null.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-registry-shadow.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-save-meta-repo-path-real-engine.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/protocol-save-meta-repo-path.test.ts": {
"TS18048: 'row.checksum' is possibly 'undefined'.": 1
},
"src/protocol-writepath-object-ownership.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 2
},
"src/query-expression-conformance.test.ts": {
"TS2322: Type '…' is not assignable to type 'QueryInput'.": 2
},
"src/registry-invalidate.test.ts": {
"TS2459: Module '\"@objectstack/spec\"' declares 'ServiceObject' locally, but it is not exported.": 1
},
"src/registry.test.ts": {
"TS18048: 'out.enable' is possibly 'undefined'.": 7,
"TS2339: Property 'indexed' does not exist on type '…'.": 3
},
"src/sys-metadata-repository-list-drafts.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/sys-metadata-repository.test.ts": {
"TS2322: Type '\"theme\"' is not assignable to type '…'.": 2,
"TS2322: Type '\"trigger\"' is not assignable to type '…'.": 1,
"TS2322: Type '\"webhook\"' is not assignable to type '…'.": 1,
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1
},
"src/validation/record-validator.test.ts": {
"TS2367: This comparison appears to be unintentional because the types 'number' and 'boolean' have no overlap.": 1
},
"src/validation/rule-fail-closed.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1,
"TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'ConditionalFieldDef'.": 2
}
}
}
103 changes: 103 additions & 0 deletions packages/objectql/tsconfig.test.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
// The TEST-layer type-check program (#13676), adopting the mechanism #5286 set
// for `packages/spec` and #5449 generalised. `tsconfig.json` above stays as it
// is: it is the BUILD config, and its `**/*.test.ts` exclusion has a reason —
// ci.yml gates that no test file reaches the published artifact. This sibling
// puts the excluded layer back in front of tsc, and `package.json`'s
// `typecheck` script NAMES it (via `check:test-typecheck --project`), because a
// config no script invokes is exactly the phantom this whole change is about.
//
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE. Measured
// at 2a181174a6 with the workspace closure built first: `tsc --listFiles`
// against the build config puts 536 files in the program and **0** of the
// package's 251 `*.test.ts` files among them, while 50 `src/**` non-test files
// ARE there — so the zero is the `exclude` line, not a probe that sees nothing.
// The directional control is `packages/drivers/driver-memory`, whose tsconfig
// carries no test exclusion: the same probe puts **38 of its 38** test files in
// the program. `pnpm --filter @objectstack/objectql typecheck` exiting 0 was a
// true sentence carrying no information about any test file in this package.
//
// ⭐ WHY THIS PACKAGE, AND WHY NOW. `src/engine-filter-array-lowering.test.ts`
// is the negative pin required by maintainer ruling #13357 execution point 3
// (landed in #13673): it proves a refused filter shape CANNOT REACH the
// reference matcher. A pin whose whole job is a security-relevant
// unreachability guarantee was type-checked by nothing at all.
//
// What differs from the build config, and what deliberately does NOT:
// - module semantics ONLY, plus `lib`. The tests are written and executed as
// ESM by vitest (esbuild/vite), while `objectql` has no `"type": "module"`,
// so the build config's NodeNext compiles them as CJS. Measured cost of
// that mismatch here: 9 of 251 raw diagnostics — TS2550 x8 (all eight the
// same `Array.prototype.at` message, against a `lib` older than es2022) and
// TS1470 x1 (`import.meta` in a CJS program). Those 9 are about the CHECK,
// never about the code. Notably SMALL next to the sibling packages
// (`rest` paid 137, `spec` 108): this layer's relative imports already
// carry their `.js` extensions, so there is no TS2835 pile here and hence
// none of the TS7006 cascade an unresolved import drags behind it.
// Matching vitest is fidelity, not laxity. No `DOM` in `lib`, unlike
// `packages/client`: nothing in this layer touches a browser global.
// - `rootDir` widens to the PACKAGE, from the build config's `src`. Under
// `noEmit` that setting carries no output meaning; all it does is constrain
// which files may enter the program. Measured: inherited as `src` it
// reports a TS6059 for `src/dry-run-hash-compat.test.ts` importing
// `scripts/dry-run-hash-compat.ts` — the SAME diagnostic #10779 retired
// from the TEST_DEBT ledger as "measuring the tape measure", i.e. the
// generated re-measure project billing this package for its own `rootDir`.
// Re-introducing it here would re-import a defect this repo already fixed.
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`
// are inherited from the root config, and `types: ["node"]` restates
// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does
// not compile, that is the finding. ⛔ Not one `any` and not one
// `@ts-expect-error` was added to any test file to open this gate — that
// shape is what turns a real gate into a phantom one.
//
// `include` deliberately stops at `src`, matching the build config's root and
// covering all 251 test files (239 in `src`, plus `src/integrity`,
// `src/lifecycle`, `src/validation`). `scripts/` is the sibling
// `tsconfig.scripts.json` (#10756) and stays a separate program: it carries no
// ledger entries at all, so plain `tsc` is a stricter gate for it than this
// file's shrink-only debt list.
//
// MEASURED at 2a181174a6, workspace closure built first (an error count taken
// against an unbuilt closure is not a reading — unresolved-import cascades
// inflate it): this program reports **242 errors across 44 files**, from a raw
// 251 under the inherited NodeNext semantics. By code: TS2339 x115,
// TS7006 x36, TS2345 x34, TS2749 x14, TS2322 x14, TS6133 x9, TS18048 x8,
// TS2353 x4, plus 8 singletons (TS7053, TS6196, TS2532, TS2493, TS2459,
// TS2416, TS2367, TS2352). `src/engine.test.ts` alone carries 102 of the 242;
// the next five are `datasource-mapping` x17, `plugin.integration` x12,
// `hook-condition-fail-loud` x12, `registry` x10, `protocol-package-lifecycle`
// x8. Every one of the 242 is PRE-EXISTING: this change edits no test file, and
// each would have been reported on `origin/main` had this program always
// existed. They are ledgered per file in `test-typecheck-debt.json` beside this
// config, EXACT and shrink-only — a file that gains an error is red, one that
// loses one is red until re-recorded, one that reaches zero is red until its
// entry is deleted, and a file NOT listed there may have no errors at all.
//
// ⚠️ THE NEGATIVE PIN CARRIES NO LEDGER ENTRY, and that is load-bearing:
// `src/engine-filter-array-lowering.test.ts` reports ZERO errors under this
// program, so any error it ever gains is red on arrival. ⚠️ Read that zero
// correctly — it is NOT evidence the pin is well typed. The file holds 20 `:
// any` annotations, and the two that matter are at its witness seam: the
// recording driver is `const driver: any` and the recorded AST is `interface
// SeenRead { ast: any }`, so `lastWhere()` — the expression the whole
// unreachability proof reads — is typed by nothing, and a drifted
// `IDataDriver` signature would not redden this file. Its own header rejects
// "a bare `as any`" in favour of `as unknown as EngineQueryOptions`
// (`asFilterArrayQuery`, used 14 times), yet 31 call sites use the bare form
// anyway. Putting the file in a program is the precondition for fixing that,
// not the fix; the repair is tracked separately (see the PR that added this
// file) and ⛔ must not be smuggled in by loosening anything here.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": ".",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/objectql/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,9 @@
"scripts": {
"build": "tsup && node ../../scripts/check-dts-emitted.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json"
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck",
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/objectql --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/objectql --project tsconfig.test.json"
},
"dependencies": {
"@objectstack/core": "workspace:*",
Expand All@@ -35,6 +37,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"tsx": "^4.23.12",
"typescript": "^6.0.3",
"vitest": "^4.1.10"
},
Expand Down
163 changes: 163 additions & 0 deletions packages/objectql/test-typecheck-debt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
{
"_comment": "Per-file tsc error debt of the @objectstack/objectql TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/objectql gen:test-typecheck-debt",
"_note": "SEEDED at 2a181174a6 by the PR that first put this layer in front of tsc (#13676), workspace closure built first. All 242 errors across 44 files are PRE-EXISTING: that PR edits no test file, and every one of these would have been reported on origin/main had this program ever existed. ⛔ Not one `any` and not one `@ts-expect-error` was added anywhere to open the gate — bulk-suppressing this residue is the exact shape the card was filed to prevent, and it would turn a real gate into a phantom one. The residue is NOT annotation debt to sweep: 14 of the 17 in src/datasource-mapping.test.ts and the bulk of the TS2345 population are one story — a driver double that does not satisfy IDataDriver — and src/engine.test.ts alone carries 102 of the 242, so read the classes before touching anything (`tsc --noEmit --pretty false -p tsconfig.test.json`). ⚠️ src/engine-filter-array-lowering.test.ts is DELIBERATELY ABSENT and must stay absent: it is the #13357 point-3 negative pin proving a refused filter shape cannot reach the reference matcher, it reports zero errors, and an unledgered file is red on its first error. ⚠️ But its zero is a weak guarantee today and must not be read as 'that pin is type-checked': the file holds `const driver: any` and `interface SeenRead { ast: any }` at the very seam the proof reads, so a drifted IDataDriver signature would not redden it. Repairing that is tracked separately and is not a licence to loosen tsconfig.test.json.",
"entries": {
"src/build-probes.test.ts": {
"TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1
},
"src/datasource-mapping.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type 'IDataDriver'.": 14,
"TS6133: 'obj' is declared but its value is never read.": 3
},
"src/engine-audit-anchor-write.test.ts": {
"TS2532: Object is possibly 'undefined'.": 1
},
"src/engine-autonumber-default-format.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 3
},
"src/engine-autonumber-defer.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 4
},
"src/engine-autonumber-resync.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-outage.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-scan.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 5
},
"src/engine-autonumber-seed-suffix.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-cascade-delete.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-data-events.test.ts": {
"TS6133: 'warn' is declared but its value is never read.": 1
},
"src/engine-delete-prior-read-scope.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 3,
"TS6196: 'ObjectSchema' is declared but never used.": 1
},
"src/engine-lifecycle-datasource.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-update-prior-read-scope.test.ts": {
"TS2345: Argument of type 'unknown' is not assignable to parameter of type '…'.": 1
},
"src/engine.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 75,
"TS2339: Property 'registerKind' does not exist on type 'typeof SchemaRegistry'.": 1,
"TS2339: Property 'registerObject' does not exist on type 'typeof SchemaRegistry'.": 3,
"TS2353: Object literal may only specify known properties, and 'filter' does not exist in type '…'.": 1,
"TS7006: Parameter 'name' implicitly has an 'any' type.": 22
},
"src/function-registry-effect.test.ts": {
"TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1
},
"src/hook-binder.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-bulk-previous.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 3,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 3
},
"src/hook-condition-fail-loud.test.ts": {
"TS2339: Property 'catch' does not exist on type '…'.": 2,
"TS2339: Property 'then' does not exist on type '…'.": 5,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 5
},
"src/hook-condition-merged-record.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-previous-scope.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS6133: 'reads' is declared but its value is never read.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/in-memory-aggregation.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/layered-overlay-integration.test.ts": {
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1,
"TS2353: Object literal may only specify known properties, and 'org' does not exist in type 'InMemoryRepositoryOptions'.": 1
},
"src/metadata-service-roundtrip-conformance.test.ts": {
"TS2322: Type 'WritableFixtureLoader' is not assignable to type 'MetadataLoader'.": 1,
"TS2416: Property 'save' in type 'WritableFixtureLoader' is not assignable to the same property in base type 'MetadataLoader'.": 1
},
"src/plugin-authored-hooks.test.ts": {
"TS6133: 'obj' is declared but its value is never read.": 1
},
"src/plugin.integration.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 11,
"TS6133: 'ObjectSchema' is declared but its value is never read.": 1
},
"src/protocol-boot-hydration-scoped.test.ts": {
"TS2322: Type '…' is not assignable to type 'string'.": 3
},
"src/protocol-boot-object-package-binding.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 3
},
"src/protocol-discovery.test.ts": {
"TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ data: string; metadata: string; discovery?: string | undefined; ui?: string | undefined; auth?: string | undefined; automation?: string | undefined; storage?: string | undefined; analytics?: string | undefined; ... 8 more ...; mcp?: string | undefined; }'.": 1
},
"src/protocol-lock-enforcement.test.ts": {
"TS6133: 'beforeEach' is declared but its value is never read.": 1
},
"src/protocol-package-lifecycle.test.ts": {
"TS2339: Property 'mock' does not exist on type 'never'.": 3,
"TS2339: Property 'mockResolvedValue' does not exist on type 'never'.": 2,
"TS7006: Parameter 'c' implicitly has an 'any' type.": 3
},
"src/protocol-publish-rollback.test.ts": {
"TS6133: 'rows' is declared but its value is never read.": 1
},
"src/protocol-recorded-by-null.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-registry-shadow.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-save-meta-repo-path-real-engine.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/protocol-save-meta-repo-path.test.ts": {
"TS18048: 'row.checksum' is possibly 'undefined'.": 1
},
"src/protocol-writepath-object-ownership.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 2
},
"src/query-expression-conformance.test.ts": {
"TS2322: Type '…' is not assignable to type 'QueryInput'.": 2
},
"src/registry-invalidate.test.ts": {
"TS2459: Module '\"@objectstack/spec\"' declares 'ServiceObject' locally, but it is not exported.": 1
},
"src/registry.test.ts": {
"TS18048: 'out.enable' is possibly 'undefined'.": 7,
"TS2339: Property 'indexed' does not exist on type '…'.": 3
},
"src/sys-metadata-repository-list-drafts.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/sys-metadata-repository.test.ts": {
"TS2322: Type '\"theme\"' is not assignable to type '…'.": 2,
"TS2322: Type '\"trigger\"' is not assignable to type '…'.": 1,
"TS2322: Type '\"webhook\"' is not assignable to type '…'.": 1,
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1
},
"src/validation/record-validator.test.ts": {
"TS2367: This comparison appears to be unintentional because the types 'number' and 'boolean' have no overlap.": 1
},
"src/validation/rule-fail-closed.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1,
"TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'ConditionalFieldDef'.": 2
}
}
}
103 changes: 103 additions & 0 deletions packages/objectql/tsconfig.test.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
// The TEST-layer type-check program (#13676), adopting the mechanism #5286 set
// for `packages/spec` and #5449 generalised. `tsconfig.json` above stays as it
// is: it is the BUILD config, and its `**/*.test.ts` exclusion has a reason —
// ci.yml gates that no test file reaches the published artifact. This sibling
// puts the excluded layer back in front of tsc, and `package.json`'s
// `typecheck` script NAMES it (via `check:test-typecheck --project`), because a
// config no script invokes is exactly the phantom this whole change is about.
//
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE. Measured
// at 2a181174a6 with the workspace closure built first: `tsc --listFiles`
// against the build config puts 536 files in the program and **0** of the
// package's 251 `*.test.ts` files among them, while 50 `src/**` non-test files
// ARE there — so the zero is the `exclude` line, not a probe that sees nothing.
// The directional control is `packages/drivers/driver-memory`, whose tsconfig
// carries no test exclusion: the same probe puts **38 of its 38** test files in
// the program. `pnpm --filter @objectstack/objectql typecheck` exiting 0 was a
// true sentence carrying no information about any test file in this package.
//
// ⭐ WHY THIS PACKAGE, AND WHY NOW. `src/engine-filter-array-lowering.test.ts`
// is the negative pin required by maintainer ruling #13357 execution point 3
// (landed in #13673): it proves a refused filter shape CANNOT REACH the
// reference matcher. A pin whose whole job is a security-relevant
// unreachability guarantee was type-checked by nothing at all.
//
// What differs from the build config, and what deliberately does NOT:
// - module semantics ONLY, plus `lib`. The tests are written and executed as
// ESM by vitest (esbuild/vite), while `objectql` has no `"type": "module"`,
// so the build config's NodeNext compiles them as CJS. Measured cost of
// that mismatch here: 9 of 251 raw diagnostics — TS2550 x8 (all eight the
// same `Array.prototype.at` message, against a `lib` older than es2022) and
// TS1470 x1 (`import.meta` in a CJS program). Those 9 are about the CHECK,
// never about the code. Notably SMALL next to the sibling packages
// (`rest` paid 137, `spec` 108): this layer's relative imports already
// carry their `.js` extensions, so there is no TS2835 pile here and hence
// none of the TS7006 cascade an unresolved import drags behind it.
// Matching vitest is fidelity, not laxity. No `DOM` in `lib`, unlike
// `packages/client`: nothing in this layer touches a browser global.
// - `rootDir` widens to the PACKAGE, from the build config's `src`. Under
// `noEmit` that setting carries no output meaning; all it does is constrain
// which files may enter the program. Measured: inherited as `src` it
// reports a TS6059 for `src/dry-run-hash-compat.test.ts` importing
// `scripts/dry-run-hash-compat.ts` — the SAME diagnostic #10779 retired
// from the TEST_DEBT ledger as "measuring the tape measure", i.e. the
// generated re-measure project billing this package for its own `rootDir`.
// Re-introducing it here would re-import a defect this repo already fixed.
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`
// are inherited from the root config, and `types: ["node"]` restates
// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does
// not compile, that is the finding. ⛔ Not one `any` and not one
// `@ts-expect-error` was added to any test file to open this gate — that
// shape is what turns a real gate into a phantom one.
//
// `include` deliberately stops at `src`, matching the build config's root and
// covering all 251 test files (239 in `src`, plus `src/integrity`,
// `src/lifecycle`, `src/validation`). `scripts/` is the sibling
// `tsconfig.scripts.json` (#10756) and stays a separate program: it carries no
// ledger entries at all, so plain `tsc` is a stricter gate for it than this
// file's shrink-only debt list.
//
// MEASURED at 2a181174a6, workspace closure built first (an error count taken
// against an unbuilt closure is not a reading — unresolved-import cascades
// inflate it): this program reports **242 errors across 44 files**, from a raw
// 251 under the inherited NodeNext semantics. By code: TS2339 x115,
// TS7006 x36, TS2345 x34, TS2749 x14, TS2322 x14, TS6133 x9, TS18048 x8,
// TS2353 x4, plus 8 singletons (TS7053, TS6196, TS2532, TS2493, TS2459,
// TS2416, TS2367, TS2352). `src/engine.test.ts` alone carries 102 of the 242;
// the next five are `datasource-mapping` x17, `plugin.integration` x12,
// `hook-condition-fail-loud` x12, `registry` x10, `protocol-package-lifecycle`
// x8. Every one of the 242 is PRE-EXISTING: this change edits no test file, and
// each would have been reported on `origin/main` had this program always
// existed. They are ledgered per file in `test-typecheck-debt.json` beside this
// config, EXACT and shrink-only — a file that gains an error is red, one that
// loses one is red until re-recorded, one that reaches zero is red until its
// entry is deleted, and a file NOT listed there may have no errors at all.
//
// ⚠️ THE NEGATIVE PIN CARRIES NO LEDGER ENTRY, and that is load-bearing:
// `src/engine-filter-array-lowering.test.ts` reports ZERO errors under this
// program, so any error it ever gains is red on arrival. ⚠️ Read that zero
// correctly — it is NOT evidence the pin is well typed. The file holds 20 `:
// any` annotations, and the two that matter are at its witness seam: the
// recording driver is `const driver: any` and the recorded AST is `interface
// SeenRead { ast: any }`, so `lastWhere()` — the expression the whole
// unreachability proof reads — is typed by nothing, and a drifted
// `IDataDriver` signature would not redden this file. Its own header rejects
// "a bare `as any`" in favour of `as unknown as EngineQueryOptions`
// (`asFilterArrayQuery`, used 14 times), yet 31 call sites use the bare form
// anyway. Putting the file in a program is the precondition for fixing that,
// not the fix; the repair is tracked separately (see the PR that added this
// file) and ⛔ must not be smuggled in by loosening anything here.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": ".",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/objectql/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,9 @@
"scripts": {
"build": "tsup && node ../../scripts/check-dts-emitted.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json"
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck",
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/objectql --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/objectql --project tsconfig.test.json"
},
"dependencies": {
"@objectstack/core": "workspace:*",
Expand All@@ -35,6 +37,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"tsx": "^4.23.12",
"typescript": "^6.0.3",
"vitest": "^4.1.10"
},
Expand Down
163 changes: 163 additions & 0 deletions packages/objectql/test-typecheck-debt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
{
"_comment": "Per-file tsc error debt of the @objectstack/objectql TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/objectql gen:test-typecheck-debt",
"_note": "SEEDED at 2a181174a6 by the PR that first put this layer in front of tsc (#13676), workspace closure built first. All 242 errors across 44 files are PRE-EXISTING: that PR edits no test file, and every one of these would have been reported on origin/main had this program ever existed. ⛔ Not one `any` and not one `@ts-expect-error` was added anywhere to open the gate — bulk-suppressing this residue is the exact shape the card was filed to prevent, and it would turn a real gate into a phantom one. The residue is NOT annotation debt to sweep: 14 of the 17 in src/datasource-mapping.test.ts and the bulk of the TS2345 population are one story — a driver double that does not satisfy IDataDriver — and src/engine.test.ts alone carries 102 of the 242, so read the classes before touching anything (`tsc --noEmit --pretty false -p tsconfig.test.json`). ⚠️ src/engine-filter-array-lowering.test.ts is DELIBERATELY ABSENT and must stay absent: it is the #13357 point-3 negative pin proving a refused filter shape cannot reach the reference matcher, it reports zero errors, and an unledgered file is red on its first error. ⚠️ But its zero is a weak guarantee today and must not be read as 'that pin is type-checked': the file holds `const driver: any` and `interface SeenRead { ast: any }` at the very seam the proof reads, so a drifted IDataDriver signature would not redden it. Repairing that is tracked separately and is not a licence to loosen tsconfig.test.json.",
"entries": {
"src/build-probes.test.ts": {
"TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1
},
"src/datasource-mapping.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type 'IDataDriver'.": 14,
"TS6133: 'obj' is declared but its value is never read.": 3
},
"src/engine-audit-anchor-write.test.ts": {
"TS2532: Object is possibly 'undefined'.": 1
},
"src/engine-autonumber-default-format.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 3
},
"src/engine-autonumber-defer.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 4
},
"src/engine-autonumber-resync.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-outage.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-scan.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 5
},
"src/engine-autonumber-seed-suffix.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-cascade-delete.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-data-events.test.ts": {
"TS6133: 'warn' is declared but its value is never read.": 1
},
"src/engine-delete-prior-read-scope.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 3,
"TS6196: 'ObjectSchema' is declared but never used.": 1
},
"src/engine-lifecycle-datasource.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-update-prior-read-scope.test.ts": {
"TS2345: Argument of type 'unknown' is not assignable to parameter of type '…'.": 1
},
"src/engine.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 75,
"TS2339: Property 'registerKind' does not exist on type 'typeof SchemaRegistry'.": 1,
"TS2339: Property 'registerObject' does not exist on type 'typeof SchemaRegistry'.": 3,
"TS2353: Object literal may only specify known properties, and 'filter' does not exist in type '…'.": 1,
"TS7006: Parameter 'name' implicitly has an 'any' type.": 22
},
"src/function-registry-effect.test.ts": {
"TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1
},
"src/hook-binder.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-bulk-previous.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 3,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 3
},
"src/hook-condition-fail-loud.test.ts": {
"TS2339: Property 'catch' does not exist on type '…'.": 2,
"TS2339: Property 'then' does not exist on type '…'.": 5,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 5
},
"src/hook-condition-merged-record.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-previous-scope.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS6133: 'reads' is declared but its value is never read.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/in-memory-aggregation.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/layered-overlay-integration.test.ts": {
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1,
"TS2353: Object literal may only specify known properties, and 'org' does not exist in type 'InMemoryRepositoryOptions'.": 1
},
"src/metadata-service-roundtrip-conformance.test.ts": {
"TS2322: Type 'WritableFixtureLoader' is not assignable to type 'MetadataLoader'.": 1,
"TS2416: Property 'save' in type 'WritableFixtureLoader' is not assignable to the same property in base type 'MetadataLoader'.": 1
},
"src/plugin-authored-hooks.test.ts": {
"TS6133: 'obj' is declared but its value is never read.": 1
},
"src/plugin.integration.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 11,
"TS6133: 'ObjectSchema' is declared but its value is never read.": 1
},
"src/protocol-boot-hydration-scoped.test.ts": {
"TS2322: Type '…' is not assignable to type 'string'.": 3
},
"src/protocol-boot-object-package-binding.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 3
},
"src/protocol-discovery.test.ts": {
"TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ data: string; metadata: string; discovery?: string | undefined; ui?: string | undefined; auth?: string | undefined; automation?: string | undefined; storage?: string | undefined; analytics?: string | undefined; ... 8 more ...; mcp?: string | undefined; }'.": 1
},
"src/protocol-lock-enforcement.test.ts": {
"TS6133: 'beforeEach' is declared but its value is never read.": 1
},
"src/protocol-package-lifecycle.test.ts": {
"TS2339: Property 'mock' does not exist on type 'never'.": 3,
"TS2339: Property 'mockResolvedValue' does not exist on type 'never'.": 2,
"TS7006: Parameter 'c' implicitly has an 'any' type.": 3
},
"src/protocol-publish-rollback.test.ts": {
"TS6133: 'rows' is declared but its value is never read.": 1
},
"src/protocol-recorded-by-null.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-registry-shadow.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-save-meta-repo-path-real-engine.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/protocol-save-meta-repo-path.test.ts": {
"TS18048: 'row.checksum' is possibly 'undefined'.": 1
},
"src/protocol-writepath-object-ownership.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 2
},
"src/query-expression-conformance.test.ts": {
"TS2322: Type '…' is not assignable to type 'QueryInput'.": 2
},
"src/registry-invalidate.test.ts": {
"TS2459: Module '\"@objectstack/spec\"' declares 'ServiceObject' locally, but it is not exported.": 1
},
"src/registry.test.ts": {
"TS18048: 'out.enable' is possibly 'undefined'.": 7,
"TS2339: Property 'indexed' does not exist on type '…'.": 3
},
"src/sys-metadata-repository-list-drafts.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/sys-metadata-repository.test.ts": {
"TS2322: Type '\"theme\"' is not assignable to type '…'.": 2,
"TS2322: Type '\"trigger\"' is not assignable to type '…'.": 1,
"TS2322: Type '\"webhook\"' is not assignable to type '…'.": 1,
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1
},
"src/validation/record-validator.test.ts": {
"TS2367: This comparison appears to be unintentional because the types 'number' and 'boolean' have no overlap.": 1
},
"src/validation/rule-fail-closed.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1,
"TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'ConditionalFieldDef'.": 2
}
}
}
103 changes: 103 additions & 0 deletions packages/objectql/tsconfig.test.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
// The TEST-layer type-check program (#13676), adopting the mechanism #5286 set
// for `packages/spec` and #5449 generalised. `tsconfig.json` above stays as it
// is: it is the BUILD config, and its `**/*.test.ts` exclusion has a reason —
// ci.yml gates that no test file reaches the published artifact. This sibling
// puts the excluded layer back in front of tsc, and `package.json`'s
// `typecheck` script NAMES it (via `check:test-typecheck --project`), because a
// config no script invokes is exactly the phantom this whole change is about.
//
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE. Measured
// at 2a181174a6 with the workspace closure built first: `tsc --listFiles`
// against the build config puts 536 files in the program and **0** of the
// package's 251 `*.test.ts` files among them, while 50 `src/**` non-test files
// ARE there — so the zero is the `exclude` line, not a probe that sees nothing.
// The directional control is `packages/drivers/driver-memory`, whose tsconfig
// carries no test exclusion: the same probe puts **38 of its 38** test files in
// the program. `pnpm --filter @objectstack/objectql typecheck` exiting 0 was a
// true sentence carrying no information about any test file in this package.
//
// ⭐ WHY THIS PACKAGE, AND WHY NOW. `src/engine-filter-array-lowering.test.ts`
// is the negative pin required by maintainer ruling #13357 execution point 3
// (landed in #13673): it proves a refused filter shape CANNOT REACH the
// reference matcher. A pin whose whole job is a security-relevant
// unreachability guarantee was type-checked by nothing at all.
//
// What differs from the build config, and what deliberately does NOT:
// - module semantics ONLY, plus `lib`. The tests are written and executed as
// ESM by vitest (esbuild/vite), while `objectql` has no `"type": "module"`,
// so the build config's NodeNext compiles them as CJS. Measured cost of
// that mismatch here: 9 of 251 raw diagnostics — TS2550 x8 (all eight the
// same `Array.prototype.at` message, against a `lib` older than es2022) and
// TS1470 x1 (`import.meta` in a CJS program). Those 9 are about the CHECK,
// never about the code. Notably SMALL next to the sibling packages
// (`rest` paid 137, `spec` 108): this layer's relative imports already
// carry their `.js` extensions, so there is no TS2835 pile here and hence
// none of the TS7006 cascade an unresolved import drags behind it.
// Matching vitest is fidelity, not laxity. No `DOM` in `lib`, unlike
// `packages/client`: nothing in this layer touches a browser global.
// - `rootDir` widens to the PACKAGE, from the build config's `src`. Under
// `noEmit` that setting carries no output meaning; all it does is constrain
// which files may enter the program. Measured: inherited as `src` it
// reports a TS6059 for `src/dry-run-hash-compat.test.ts` importing
// `scripts/dry-run-hash-compat.ts` — the SAME diagnostic #10779 retired
// from the TEST_DEBT ledger as "measuring the tape measure", i.e. the
// generated re-measure project billing this package for its own `rootDir`.
// Re-introducing it here would re-import a defect this repo already fixed.
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`
// are inherited from the root config, and `types: ["node"]` restates
// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does
// not compile, that is the finding. ⛔ Not one `any` and not one
// `@ts-expect-error` was added to any test file to open this gate — that
// shape is what turns a real gate into a phantom one.
//
// `include` deliberately stops at `src`, matching the build config's root and
// covering all 251 test files (239 in `src`, plus `src/integrity`,
// `src/lifecycle`, `src/validation`). `scripts/` is the sibling
// `tsconfig.scripts.json` (#10756) and stays a separate program: it carries no
// ledger entries at all, so plain `tsc` is a stricter gate for it than this
// file's shrink-only debt list.
//
// MEASURED at 2a181174a6, workspace closure built first (an error count taken
// against an unbuilt closure is not a reading — unresolved-import cascades
// inflate it): this program reports **242 errors across 44 files**, from a raw
// 251 under the inherited NodeNext semantics. By code: TS2339 x115,
// TS7006 x36, TS2345 x34, TS2749 x14, TS2322 x14, TS6133 x9, TS18048 x8,
// TS2353 x4, plus 8 singletons (TS7053, TS6196, TS2532, TS2493, TS2459,
// TS2416, TS2367, TS2352). `src/engine.test.ts` alone carries 102 of the 242;
// the next five are `datasource-mapping` x17, `plugin.integration` x12,
// `hook-condition-fail-loud` x12, `registry` x10, `protocol-package-lifecycle`
// x8. Every one of the 242 is PRE-EXISTING: this change edits no test file, and
// each would have been reported on `origin/main` had this program always
// existed. They are ledgered per file in `test-typecheck-debt.json` beside this
// config, EXACT and shrink-only — a file that gains an error is red, one that
// loses one is red until re-recorded, one that reaches zero is red until its
// entry is deleted, and a file NOT listed there may have no errors at all.
//
// ⚠️ THE NEGATIVE PIN CARRIES NO LEDGER ENTRY, and that is load-bearing:
// `src/engine-filter-array-lowering.test.ts` reports ZERO errors under this
// program, so any error it ever gains is red on arrival. ⚠️ Read that zero
// correctly — it is NOT evidence the pin is well typed. The file holds 20 `:
// any` annotations, and the two that matter are at its witness seam: the
// recording driver is `const driver: any` and the recorded AST is `interface
// SeenRead { ast: any }`, so `lastWhere()` — the expression the whole
// unreachability proof reads — is typed by nothing, and a drifted
// `IDataDriver` signature would not redden this file. Its own header rejects
// "a bare `as any`" in favour of `as unknown as EngineQueryOptions`
// (`asFilterArrayQuery`, used 14 times), yet 31 call sites use the bare form
// anyway. Putting the file in a program is the precondition for fixing that,
// not the fix; the repair is tracked separately (see the PR that added this
// file) and ⛔ must not be smuggled in by loosening anything here.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": ".",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/objectql/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,9 @@
"scripts": {
"build": "tsup && node ../../scripts/check-dts-emitted.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json"
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck",
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/objectql --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/objectql --project tsconfig.test.json"
},
"dependencies": {
"@objectstack/core": "workspace:*",
Expand All@@ -35,6 +37,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"tsx": "^4.23.12",
"typescript": "^6.0.3",
"vitest": "^4.1.10"
},
Expand Down
163 changes: 163 additions & 0 deletions packages/objectql/test-typecheck-debt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
{
"_comment": "Per-file tsc error debt of the @objectstack/objectql TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/objectql gen:test-typecheck-debt",
"_note": "SEEDED at 2a181174a6 by the PR that first put this layer in front of tsc (#13676), workspace closure built first. All 242 errors across 44 files are PRE-EXISTING: that PR edits no test file, and every one of these would have been reported on origin/main had this program ever existed. ⛔ Not one `any` and not one `@ts-expect-error` was added anywhere to open the gate — bulk-suppressing this residue is the exact shape the card was filed to prevent, and it would turn a real gate into a phantom one. The residue is NOT annotation debt to sweep: 14 of the 17 in src/datasource-mapping.test.ts and the bulk of the TS2345 population are one story — a driver double that does not satisfy IDataDriver — and src/engine.test.ts alone carries 102 of the 242, so read the classes before touching anything (`tsc --noEmit --pretty false -p tsconfig.test.json`). ⚠️ src/engine-filter-array-lowering.test.ts is DELIBERATELY ABSENT and must stay absent: it is the #13357 point-3 negative pin proving a refused filter shape cannot reach the reference matcher, it reports zero errors, and an unledgered file is red on its first error. ⚠️ But its zero is a weak guarantee today and must not be read as 'that pin is type-checked': the file holds `const driver: any` and `interface SeenRead { ast: any }` at the very seam the proof reads, so a drifted IDataDriver signature would not redden it. Repairing that is tracked separately and is not a licence to loosen tsconfig.test.json.",
"entries": {
"src/build-probes.test.ts": {
"TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1
},
"src/datasource-mapping.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type 'IDataDriver'.": 14,
"TS6133: 'obj' is declared but its value is never read.": 3
},
"src/engine-audit-anchor-write.test.ts": {
"TS2532: Object is possibly 'undefined'.": 1
},
"src/engine-autonumber-default-format.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 3
},
"src/engine-autonumber-defer.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 4
},
"src/engine-autonumber-resync.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-outage.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-scan.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 5
},
"src/engine-autonumber-seed-suffix.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-cascade-delete.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-data-events.test.ts": {
"TS6133: 'warn' is declared but its value is never read.": 1
},
"src/engine-delete-prior-read-scope.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 3,
"TS6196: 'ObjectSchema' is declared but never used.": 1
},
"src/engine-lifecycle-datasource.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-update-prior-read-scope.test.ts": {
"TS2345: Argument of type 'unknown' is not assignable to parameter of type '…'.": 1
},
"src/engine.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 75,
"TS2339: Property 'registerKind' does not exist on type 'typeof SchemaRegistry'.": 1,
"TS2339: Property 'registerObject' does not exist on type 'typeof SchemaRegistry'.": 3,
"TS2353: Object literal may only specify known properties, and 'filter' does not exist in type '…'.": 1,
"TS7006: Parameter 'name' implicitly has an 'any' type.": 22
},
"src/function-registry-effect.test.ts": {
"TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1
},
"src/hook-binder.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-bulk-previous.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 3,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 3
},
"src/hook-condition-fail-loud.test.ts": {
"TS2339: Property 'catch' does not exist on type '…'.": 2,
"TS2339: Property 'then' does not exist on type '…'.": 5,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 5
},
"src/hook-condition-merged-record.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-previous-scope.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS6133: 'reads' is declared but its value is never read.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/in-memory-aggregation.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/layered-overlay-integration.test.ts": {
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1,
"TS2353: Object literal may only specify known properties, and 'org' does not exist in type 'InMemoryRepositoryOptions'.": 1
},
"src/metadata-service-roundtrip-conformance.test.ts": {
"TS2322: Type 'WritableFixtureLoader' is not assignable to type 'MetadataLoader'.": 1,
"TS2416: Property 'save' in type 'WritableFixtureLoader' is not assignable to the same property in base type 'MetadataLoader'.": 1
},
"src/plugin-authored-hooks.test.ts": {
"TS6133: 'obj' is declared but its value is never read.": 1
},
"src/plugin.integration.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 11,
"TS6133: 'ObjectSchema' is declared but its value is never read.": 1
},
"src/protocol-boot-hydration-scoped.test.ts": {
"TS2322: Type '…' is not assignable to type 'string'.": 3
},
"src/protocol-boot-object-package-binding.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 3
},
"src/protocol-discovery.test.ts": {
"TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ data: string; metadata: string; discovery?: string | undefined; ui?: string | undefined; auth?: string | undefined; automation?: string | undefined; storage?: string | undefined; analytics?: string | undefined; ... 8 more ...; mcp?: string | undefined; }'.": 1
},
"src/protocol-lock-enforcement.test.ts": {
"TS6133: 'beforeEach' is declared but its value is never read.": 1
},
"src/protocol-package-lifecycle.test.ts": {
"TS2339: Property 'mock' does not exist on type 'never'.": 3,
"TS2339: Property 'mockResolvedValue' does not exist on type 'never'.": 2,
"TS7006: Parameter 'c' implicitly has an 'any' type.": 3
},
"src/protocol-publish-rollback.test.ts": {
"TS6133: 'rows' is declared but its value is never read.": 1
},
"src/protocol-recorded-by-null.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-registry-shadow.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-save-meta-repo-path-real-engine.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/protocol-save-meta-repo-path.test.ts": {
"TS18048: 'row.checksum' is possibly 'undefined'.": 1
},
"src/protocol-writepath-object-ownership.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 2
},
"src/query-expression-conformance.test.ts": {
"TS2322: Type '…' is not assignable to type 'QueryInput'.": 2
},
"src/registry-invalidate.test.ts": {
"TS2459: Module '\"@objectstack/spec\"' declares 'ServiceObject' locally, but it is not exported.": 1
},
"src/registry.test.ts": {
"TS18048: 'out.enable' is possibly 'undefined'.": 7,
"TS2339: Property 'indexed' does not exist on type '…'.": 3
},
"src/sys-metadata-repository-list-drafts.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/sys-metadata-repository.test.ts": {
"TS2322: Type '\"theme\"' is not assignable to type '…'.": 2,
"TS2322: Type '\"trigger\"' is not assignable to type '…'.": 1,
"TS2322: Type '\"webhook\"' is not assignable to type '…'.": 1,
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1
},
"src/validation/record-validator.test.ts": {
"TS2367: This comparison appears to be unintentional because the types 'number' and 'boolean' have no overlap.": 1
},
"src/validation/rule-fail-closed.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1,
"TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'ConditionalFieldDef'.": 2
}
}
}
103 changes: 103 additions & 0 deletions packages/objectql/tsconfig.test.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
// The TEST-layer type-check program (#13676), adopting the mechanism #5286 set
// for `packages/spec` and #5449 generalised. `tsconfig.json` above stays as it
// is: it is the BUILD config, and its `**/*.test.ts` exclusion has a reason —
// ci.yml gates that no test file reaches the published artifact. This sibling
// puts the excluded layer back in front of tsc, and `package.json`'s
// `typecheck` script NAMES it (via `check:test-typecheck --project`), because a
// config no script invokes is exactly the phantom this whole change is about.
//
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE. Measured
// at 2a181174a6 with the workspace closure built first: `tsc --listFiles`
// against the build config puts 536 files in the program and **0** of the
// package's 251 `*.test.ts` files among them, while 50 `src/**` non-test files
// ARE there — so the zero is the `exclude` line, not a probe that sees nothing.
// The directional control is `packages/drivers/driver-memory`, whose tsconfig
// carries no test exclusion: the same probe puts **38 of its 38** test files in
// the program. `pnpm --filter @objectstack/objectql typecheck` exiting 0 was a
// true sentence carrying no information about any test file in this package.
//
// ⭐ WHY THIS PACKAGE, AND WHY NOW. `src/engine-filter-array-lowering.test.ts`
// is the negative pin required by maintainer ruling #13357 execution point 3
// (landed in #13673): it proves a refused filter shape CANNOT REACH the
// reference matcher. A pin whose whole job is a security-relevant
// unreachability guarantee was type-checked by nothing at all.
//
// What differs from the build config, and what deliberately does NOT:
// - module semantics ONLY, plus `lib`. The tests are written and executed as
// ESM by vitest (esbuild/vite), while `objectql` has no `"type": "module"`,
// so the build config's NodeNext compiles them as CJS. Measured cost of
// that mismatch here: 9 of 251 raw diagnostics — TS2550 x8 (all eight the
// same `Array.prototype.at` message, against a `lib` older than es2022) and
// TS1470 x1 (`import.meta` in a CJS program). Those 9 are about the CHECK,
// never about the code. Notably SMALL next to the sibling packages
// (`rest` paid 137, `spec` 108): this layer's relative imports already
// carry their `.js` extensions, so there is no TS2835 pile here and hence
// none of the TS7006 cascade an unresolved import drags behind it.
// Matching vitest is fidelity, not laxity. No `DOM` in `lib`, unlike
// `packages/client`: nothing in this layer touches a browser global.
// - `rootDir` widens to the PACKAGE, from the build config's `src`. Under
// `noEmit` that setting carries no output meaning; all it does is constrain
// which files may enter the program. Measured: inherited as `src` it
// reports a TS6059 for `src/dry-run-hash-compat.test.ts` importing
// `scripts/dry-run-hash-compat.ts` — the SAME diagnostic #10779 retired
// from the TEST_DEBT ledger as "measuring the tape measure", i.e. the
// generated re-measure project billing this package for its own `rootDir`.
// Re-introducing it here would re-import a defect this repo already fixed.
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`
// are inherited from the root config, and `types: ["node"]` restates
// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does
// not compile, that is the finding. ⛔ Not one `any` and not one
// `@ts-expect-error` was added to any test file to open this gate — that
// shape is what turns a real gate into a phantom one.
//
// `include` deliberately stops at `src`, matching the build config's root and
// covering all 251 test files (239 in `src`, plus `src/integrity`,
// `src/lifecycle`, `src/validation`). `scripts/` is the sibling
// `tsconfig.scripts.json` (#10756) and stays a separate program: it carries no
// ledger entries at all, so plain `tsc` is a stricter gate for it than this
// file's shrink-only debt list.
//
// MEASURED at 2a181174a6, workspace closure built first (an error count taken
// against an unbuilt closure is not a reading — unresolved-import cascades
// inflate it): this program reports **242 errors across 44 files**, from a raw
// 251 under the inherited NodeNext semantics. By code: TS2339 x115,
// TS7006 x36, TS2345 x34, TS2749 x14, TS2322 x14, TS6133 x9, TS18048 x8,
// TS2353 x4, plus 8 singletons (TS7053, TS6196, TS2532, TS2493, TS2459,
// TS2416, TS2367, TS2352). `src/engine.test.ts` alone carries 102 of the 242;
// the next five are `datasource-mapping` x17, `plugin.integration` x12,
// `hook-condition-fail-loud` x12, `registry` x10, `protocol-package-lifecycle`
// x8. Every one of the 242 is PRE-EXISTING: this change edits no test file, and
// each would have been reported on `origin/main` had this program always
// existed. They are ledgered per file in `test-typecheck-debt.json` beside this
// config, EXACT and shrink-only — a file that gains an error is red, one that
// loses one is red until re-recorded, one that reaches zero is red until its
// entry is deleted, and a file NOT listed there may have no errors at all.
//
// ⚠️ THE NEGATIVE PIN CARRIES NO LEDGER ENTRY, and that is load-bearing:
// `src/engine-filter-array-lowering.test.ts` reports ZERO errors under this
// program, so any error it ever gains is red on arrival. ⚠️ Read that zero
// correctly — it is NOT evidence the pin is well typed. The file holds 20 `:
// any` annotations, and the two that matter are at its witness seam: the
// recording driver is `const driver: any` and the recorded AST is `interface
// SeenRead { ast: any }`, so `lastWhere()` — the expression the whole
// unreachability proof reads — is typed by nothing, and a drifted
// `IDataDriver` signature would not redden this file. Its own header rejects
// "a bare `as any`" in favour of `as unknown as EngineQueryOptions`
// (`asFilterArrayQuery`, used 14 times), yet 31 call sites use the bare form
// anyway. Putting the file in a program is the precondition for fixing that,
// not the fix; the repair is tracked separately (see the PR that added this
// file) and ⛔ must not be smuggled in by loosening anything here.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": ".",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/objectql/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,9 @@
"scripts": {
"build": "tsup && node ../../scripts/check-dts-emitted.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json"
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck",
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/objectql --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/objectql --project tsconfig.test.json"
},
"dependencies": {
"@objectstack/core": "workspace:*",
Expand All@@ -35,6 +37,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"tsx": "^4.23.12",
"typescript": "^6.0.3",
"vitest": "^4.1.10"
},
Expand Down
163 changes: 163 additions & 0 deletions packages/objectql/test-typecheck-debt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
{
"_comment": "Per-file tsc error debt of the @objectstack/objectql TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/objectql gen:test-typecheck-debt",
"_note": "SEEDED at 2a181174a6 by the PR that first put this layer in front of tsc (#13676), workspace closure built first. All 242 errors across 44 files are PRE-EXISTING: that PR edits no test file, and every one of these would have been reported on origin/main had this program ever existed. ⛔ Not one `any` and not one `@ts-expect-error` was added anywhere to open the gate — bulk-suppressing this residue is the exact shape the card was filed to prevent, and it would turn a real gate into a phantom one. The residue is NOT annotation debt to sweep: 14 of the 17 in src/datasource-mapping.test.ts and the bulk of the TS2345 population are one story — a driver double that does not satisfy IDataDriver — and src/engine.test.ts alone carries 102 of the 242, so read the classes before touching anything (`tsc --noEmit --pretty false -p tsconfig.test.json`). ⚠️ src/engine-filter-array-lowering.test.ts is DELIBERATELY ABSENT and must stay absent: it is the #13357 point-3 negative pin proving a refused filter shape cannot reach the reference matcher, it reports zero errors, and an unledgered file is red on its first error. ⚠️ But its zero is a weak guarantee today and must not be read as 'that pin is type-checked': the file holds `const driver: any` and `interface SeenRead { ast: any }` at the very seam the proof reads, so a drifted IDataDriver signature would not redden it. Repairing that is tracked separately and is not a licence to loosen tsconfig.test.json.",
"entries": {
"src/build-probes.test.ts": {
"TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1
},
"src/datasource-mapping.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type 'IDataDriver'.": 14,
"TS6133: 'obj' is declared but its value is never read.": 3
},
"src/engine-audit-anchor-write.test.ts": {
"TS2532: Object is possibly 'undefined'.": 1
},
"src/engine-autonumber-default-format.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 3
},
"src/engine-autonumber-defer.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 4
},
"src/engine-autonumber-resync.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-outage.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-scan.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 5
},
"src/engine-autonumber-seed-suffix.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-cascade-delete.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-data-events.test.ts": {
"TS6133: 'warn' is declared but its value is never read.": 1
},
"src/engine-delete-prior-read-scope.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 3,
"TS6196: 'ObjectSchema' is declared but never used.": 1
},
"src/engine-lifecycle-datasource.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-update-prior-read-scope.test.ts": {
"TS2345: Argument of type 'unknown' is not assignable to parameter of type '…'.": 1
},
"src/engine.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 75,
"TS2339: Property 'registerKind' does not exist on type 'typeof SchemaRegistry'.": 1,
"TS2339: Property 'registerObject' does not exist on type 'typeof SchemaRegistry'.": 3,
"TS2353: Object literal may only specify known properties, and 'filter' does not exist in type '…'.": 1,
"TS7006: Parameter 'name' implicitly has an 'any' type.": 22
},
"src/function-registry-effect.test.ts": {
"TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1
},
"src/hook-binder.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-bulk-previous.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 3,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 3
},
"src/hook-condition-fail-loud.test.ts": {
"TS2339: Property 'catch' does not exist on type '…'.": 2,
"TS2339: Property 'then' does not exist on type '…'.": 5,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 5
},
"src/hook-condition-merged-record.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-previous-scope.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS6133: 'reads' is declared but its value is never read.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/in-memory-aggregation.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/layered-overlay-integration.test.ts": {
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1,
"TS2353: Object literal may only specify known properties, and 'org' does not exist in type 'InMemoryRepositoryOptions'.": 1
},
"src/metadata-service-roundtrip-conformance.test.ts": {
"TS2322: Type 'WritableFixtureLoader' is not assignable to type 'MetadataLoader'.": 1,
"TS2416: Property 'save' in type 'WritableFixtureLoader' is not assignable to the same property in base type 'MetadataLoader'.": 1
},
"src/plugin-authored-hooks.test.ts": {
"TS6133: 'obj' is declared but its value is never read.": 1
},
"src/plugin.integration.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 11,
"TS6133: 'ObjectSchema' is declared but its value is never read.": 1
},
"src/protocol-boot-hydration-scoped.test.ts": {
"TS2322: Type '…' is not assignable to type 'string'.": 3
},
"src/protocol-boot-object-package-binding.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 3
},
"src/protocol-discovery.test.ts": {
"TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ data: string; metadata: string; discovery?: string | undefined; ui?: string | undefined; auth?: string | undefined; automation?: string | undefined; storage?: string | undefined; analytics?: string | undefined; ... 8 more ...; mcp?: string | undefined; }'.": 1
},
"src/protocol-lock-enforcement.test.ts": {
"TS6133: 'beforeEach' is declared but its value is never read.": 1
},
"src/protocol-package-lifecycle.test.ts": {
"TS2339: Property 'mock' does not exist on type 'never'.": 3,
"TS2339: Property 'mockResolvedValue' does not exist on type 'never'.": 2,
"TS7006: Parameter 'c' implicitly has an 'any' type.": 3
},
"src/protocol-publish-rollback.test.ts": {
"TS6133: 'rows' is declared but its value is never read.": 1
},
"src/protocol-recorded-by-null.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-registry-shadow.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-save-meta-repo-path-real-engine.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/protocol-save-meta-repo-path.test.ts": {
"TS18048: 'row.checksum' is possibly 'undefined'.": 1
},
"src/protocol-writepath-object-ownership.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 2
},
"src/query-expression-conformance.test.ts": {
"TS2322: Type '…' is not assignable to type 'QueryInput'.": 2
},
"src/registry-invalidate.test.ts": {
"TS2459: Module '\"@objectstack/spec\"' declares 'ServiceObject' locally, but it is not exported.": 1
},
"src/registry.test.ts": {
"TS18048: 'out.enable' is possibly 'undefined'.": 7,
"TS2339: Property 'indexed' does not exist on type '…'.": 3
},
"src/sys-metadata-repository-list-drafts.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/sys-metadata-repository.test.ts": {
"TS2322: Type '\"theme\"' is not assignable to type '…'.": 2,
"TS2322: Type '\"trigger\"' is not assignable to type '…'.": 1,
"TS2322: Type '\"webhook\"' is not assignable to type '…'.": 1,
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1
},
"src/validation/record-validator.test.ts": {
"TS2367: This comparison appears to be unintentional because the types 'number' and 'boolean' have no overlap.": 1
},
"src/validation/rule-fail-closed.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1,
"TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'ConditionalFieldDef'.": 2
}
}
}
103 changes: 103 additions & 0 deletions packages/objectql/tsconfig.test.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
// The TEST-layer type-check program (#13676), adopting the mechanism #5286 set
// for `packages/spec` and #5449 generalised. `tsconfig.json` above stays as it
// is: it is the BUILD config, and its `**/*.test.ts` exclusion has a reason —
// ci.yml gates that no test file reaches the published artifact. This sibling
// puts the excluded layer back in front of tsc, and `package.json`'s
// `typecheck` script NAMES it (via `check:test-typecheck --project`), because a
// config no script invokes is exactly the phantom this whole change is about.
//
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE. Measured
// at 2a181174a6 with the workspace closure built first: `tsc --listFiles`
// against the build config puts 536 files in the program and **0** of the
// package's 251 `*.test.ts` files among them, while 50 `src/**` non-test files
// ARE there — so the zero is the `exclude` line, not a probe that sees nothing.
// The directional control is `packages/drivers/driver-memory`, whose tsconfig
// carries no test exclusion: the same probe puts **38 of its 38** test files in
// the program. `pnpm --filter @objectstack/objectql typecheck` exiting 0 was a
// true sentence carrying no information about any test file in this package.
//
// ⭐ WHY THIS PACKAGE, AND WHY NOW. `src/engine-filter-array-lowering.test.ts`
// is the negative pin required by maintainer ruling #13357 execution point 3
// (landed in #13673): it proves a refused filter shape CANNOT REACH the
// reference matcher. A pin whose whole job is a security-relevant
// unreachability guarantee was type-checked by nothing at all.
//
// What differs from the build config, and what deliberately does NOT:
// - module semantics ONLY, plus `lib`. The tests are written and executed as
// ESM by vitest (esbuild/vite), while `objectql` has no `"type": "module"`,
// so the build config's NodeNext compiles them as CJS. Measured cost of
// that mismatch here: 9 of 251 raw diagnostics — TS2550 x8 (all eight the
// same `Array.prototype.at` message, against a `lib` older than es2022) and
// TS1470 x1 (`import.meta` in a CJS program). Those 9 are about the CHECK,
// never about the code. Notably SMALL next to the sibling packages
// (`rest` paid 137, `spec` 108): this layer's relative imports already
// carry their `.js` extensions, so there is no TS2835 pile here and hence
// none of the TS7006 cascade an unresolved import drags behind it.
// Matching vitest is fidelity, not laxity. No `DOM` in `lib`, unlike
// `packages/client`: nothing in this layer touches a browser global.
// - `rootDir` widens to the PACKAGE, from the build config's `src`. Under
// `noEmit` that setting carries no output meaning; all it does is constrain
// which files may enter the program. Measured: inherited as `src` it
// reports a TS6059 for `src/dry-run-hash-compat.test.ts` importing
// `scripts/dry-run-hash-compat.ts` — the SAME diagnostic #10779 retired
// from the TEST_DEBT ledger as "measuring the tape measure", i.e. the
// generated re-measure project billing this package for its own `rootDir`.
// Re-introducing it here would re-import a defect this repo already fixed.
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`
// are inherited from the root config, and `types: ["node"]` restates
// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does
// not compile, that is the finding. ⛔ Not one `any` and not one
// `@ts-expect-error` was added to any test file to open this gate — that
// shape is what turns a real gate into a phantom one.
//
// `include` deliberately stops at `src`, matching the build config's root and
// covering all 251 test files (239 in `src`, plus `src/integrity`,
// `src/lifecycle`, `src/validation`). `scripts/` is the sibling
// `tsconfig.scripts.json` (#10756) and stays a separate program: it carries no
// ledger entries at all, so plain `tsc` is a stricter gate for it than this
// file's shrink-only debt list.
//
// MEASURED at 2a181174a6, workspace closure built first (an error count taken
// against an unbuilt closure is not a reading — unresolved-import cascades
// inflate it): this program reports **242 errors across 44 files**, from a raw
// 251 under the inherited NodeNext semantics. By code: TS2339 x115,
// TS7006 x36, TS2345 x34, TS2749 x14, TS2322 x14, TS6133 x9, TS18048 x8,
// TS2353 x4, plus 8 singletons (TS7053, TS6196, TS2532, TS2493, TS2459,
// TS2416, TS2367, TS2352). `src/engine.test.ts` alone carries 102 of the 242;
// the next five are `datasource-mapping` x17, `plugin.integration` x12,
// `hook-condition-fail-loud` x12, `registry` x10, `protocol-package-lifecycle`
// x8. Every one of the 242 is PRE-EXISTING: this change edits no test file, and
// each would have been reported on `origin/main` had this program always
// existed. They are ledgered per file in `test-typecheck-debt.json` beside this
// config, EXACT and shrink-only — a file that gains an error is red, one that
// loses one is red until re-recorded, one that reaches zero is red until its
// entry is deleted, and a file NOT listed there may have no errors at all.
//
// ⚠️ THE NEGATIVE PIN CARRIES NO LEDGER ENTRY, and that is load-bearing:
// `src/engine-filter-array-lowering.test.ts` reports ZERO errors under this
// program, so any error it ever gains is red on arrival. ⚠️ Read that zero
// correctly — it is NOT evidence the pin is well typed. The file holds 20 `:
// any` annotations, and the two that matter are at its witness seam: the
// recording driver is `const driver: any` and the recorded AST is `interface
// SeenRead { ast: any }`, so `lastWhere()` — the expression the whole
// unreachability proof reads — is typed by nothing, and a drifted
// `IDataDriver` signature would not redden this file. Its own header rejects
// "a bare `as any`" in favour of `as unknown as EngineQueryOptions`
// (`asFilterArrayQuery`, used 14 times), yet 31 call sites use the bare form
// anyway. Putting the file in a program is the precondition for fixing that,
// not the fix; the repair is tracked separately (see the PR that added this
// file) and ⛔ must not be smuggled in by loosening anything here.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": ".",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/objectql/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,9 @@
"scripts": {
"build": "tsup && node ../../scripts/check-dts-emitted.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json"
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck",
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/objectql --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/objectql --project tsconfig.test.json"
},
"dependencies": {
"@objectstack/core": "workspace:*",
Expand All@@ -35,6 +37,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"tsx": "^4.23.12",
"typescript": "^6.0.3",
"vitest": "^4.1.10"
},
Expand Down
163 changes: 163 additions & 0 deletions packages/objectql/test-typecheck-debt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
{
"_comment": "Per-file tsc error debt of the @objectstack/objectql TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/objectql gen:test-typecheck-debt",
"_note": "SEEDED at 2a181174a6 by the PR that first put this layer in front of tsc (#13676), workspace closure built first. All 242 errors across 44 files are PRE-EXISTING: that PR edits no test file, and every one of these would have been reported on origin/main had this program ever existed. ⛔ Not one `any` and not one `@ts-expect-error` was added anywhere to open the gate — bulk-suppressing this residue is the exact shape the card was filed to prevent, and it would turn a real gate into a phantom one. The residue is NOT annotation debt to sweep: 14 of the 17 in src/datasource-mapping.test.ts and the bulk of the TS2345 population are one story — a driver double that does not satisfy IDataDriver — and src/engine.test.ts alone carries 102 of the 242, so read the classes before touching anything (`tsc --noEmit --pretty false -p tsconfig.test.json`). ⚠️ src/engine-filter-array-lowering.test.ts is DELIBERATELY ABSENT and must stay absent: it is the #13357 point-3 negative pin proving a refused filter shape cannot reach the reference matcher, it reports zero errors, and an unledgered file is red on its first error. ⚠️ But its zero is a weak guarantee today and must not be read as 'that pin is type-checked': the file holds `const driver: any` and `interface SeenRead { ast: any }` at the very seam the proof reads, so a drifted IDataDriver signature would not redden it. Repairing that is tracked separately and is not a licence to loosen tsconfig.test.json.",
"entries": {
"src/build-probes.test.ts": {
"TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1
},
"src/datasource-mapping.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type 'IDataDriver'.": 14,
"TS6133: 'obj' is declared but its value is never read.": 3
},
"src/engine-audit-anchor-write.test.ts": {
"TS2532: Object is possibly 'undefined'.": 1
},
"src/engine-autonumber-default-format.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 3
},
"src/engine-autonumber-defer.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 4
},
"src/engine-autonumber-resync.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-outage.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-scan.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 5
},
"src/engine-autonumber-seed-suffix.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-cascade-delete.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-data-events.test.ts": {
"TS6133: 'warn' is declared but its value is never read.": 1
},
"src/engine-delete-prior-read-scope.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 3,
"TS6196: 'ObjectSchema' is declared but never used.": 1
},
"src/engine-lifecycle-datasource.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-update-prior-read-scope.test.ts": {
"TS2345: Argument of type 'unknown' is not assignable to parameter of type '…'.": 1
},
"src/engine.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 75,
"TS2339: Property 'registerKind' does not exist on type 'typeof SchemaRegistry'.": 1,
"TS2339: Property 'registerObject' does not exist on type 'typeof SchemaRegistry'.": 3,
"TS2353: Object literal may only specify known properties, and 'filter' does not exist in type '…'.": 1,
"TS7006: Parameter 'name' implicitly has an 'any' type.": 22
},
"src/function-registry-effect.test.ts": {
"TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1
},
"src/hook-binder.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-bulk-previous.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 3,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 3
},
"src/hook-condition-fail-loud.test.ts": {
"TS2339: Property 'catch' does not exist on type '…'.": 2,
"TS2339: Property 'then' does not exist on type '…'.": 5,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 5
},
"src/hook-condition-merged-record.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-previous-scope.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS6133: 'reads' is declared but its value is never read.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/in-memory-aggregation.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/layered-overlay-integration.test.ts": {
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1,
"TS2353: Object literal may only specify known properties, and 'org' does not exist in type 'InMemoryRepositoryOptions'.": 1
},
"src/metadata-service-roundtrip-conformance.test.ts": {
"TS2322: Type 'WritableFixtureLoader' is not assignable to type 'MetadataLoader'.": 1,
"TS2416: Property 'save' in type 'WritableFixtureLoader' is not assignable to the same property in base type 'MetadataLoader'.": 1
},
"src/plugin-authored-hooks.test.ts": {
"TS6133: 'obj' is declared but its value is never read.": 1
},
"src/plugin.integration.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 11,
"TS6133: 'ObjectSchema' is declared but its value is never read.": 1
},
"src/protocol-boot-hydration-scoped.test.ts": {
"TS2322: Type '…' is not assignable to type 'string'.": 3
},
"src/protocol-boot-object-package-binding.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 3
},
"src/protocol-discovery.test.ts": {
"TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ data: string; metadata: string; discovery?: string | undefined; ui?: string | undefined; auth?: string | undefined; automation?: string | undefined; storage?: string | undefined; analytics?: string | undefined; ... 8 more ...; mcp?: string | undefined; }'.": 1
},
"src/protocol-lock-enforcement.test.ts": {
"TS6133: 'beforeEach' is declared but its value is never read.": 1
},
"src/protocol-package-lifecycle.test.ts": {
"TS2339: Property 'mock' does not exist on type 'never'.": 3,
"TS2339: Property 'mockResolvedValue' does not exist on type 'never'.": 2,
"TS7006: Parameter 'c' implicitly has an 'any' type.": 3
},
"src/protocol-publish-rollback.test.ts": {
"TS6133: 'rows' is declared but its value is never read.": 1
},
"src/protocol-recorded-by-null.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-registry-shadow.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-save-meta-repo-path-real-engine.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/protocol-save-meta-repo-path.test.ts": {
"TS18048: 'row.checksum' is possibly 'undefined'.": 1
},
"src/protocol-writepath-object-ownership.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 2
},
"src/query-expression-conformance.test.ts": {
"TS2322: Type '…' is not assignable to type 'QueryInput'.": 2
},
"src/registry-invalidate.test.ts": {
"TS2459: Module '\"@objectstack/spec\"' declares 'ServiceObject' locally, but it is not exported.": 1
},
"src/registry.test.ts": {
"TS18048: 'out.enable' is possibly 'undefined'.": 7,
"TS2339: Property 'indexed' does not exist on type '…'.": 3
},
"src/sys-metadata-repository-list-drafts.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/sys-metadata-repository.test.ts": {
"TS2322: Type '\"theme\"' is not assignable to type '…'.": 2,
"TS2322: Type '\"trigger\"' is not assignable to type '…'.": 1,
"TS2322: Type '\"webhook\"' is not assignable to type '…'.": 1,
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1
},
"src/validation/record-validator.test.ts": {
"TS2367: This comparison appears to be unintentional because the types 'number' and 'boolean' have no overlap.": 1
},
"src/validation/rule-fail-closed.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1,
"TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'ConditionalFieldDef'.": 2
}
}
}
103 changes: 103 additions & 0 deletions packages/objectql/tsconfig.test.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
// The TEST-layer type-check program (#13676), adopting the mechanism #5286 set
// for `packages/spec` and #5449 generalised. `tsconfig.json` above stays as it
// is: it is the BUILD config, and its `**/*.test.ts` exclusion has a reason —
// ci.yml gates that no test file reaches the published artifact. This sibling
// puts the excluded layer back in front of tsc, and `package.json`'s
// `typecheck` script NAMES it (via `check:test-typecheck --project`), because a
// config no script invokes is exactly the phantom this whole change is about.
//
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE. Measured
// at 2a181174a6 with the workspace closure built first: `tsc --listFiles`
// against the build config puts 536 files in the program and **0** of the
// package's 251 `*.test.ts` files among them, while 50 `src/**` non-test files
// ARE there — so the zero is the `exclude` line, not a probe that sees nothing.
// The directional control is `packages/drivers/driver-memory`, whose tsconfig
// carries no test exclusion: the same probe puts **38 of its 38** test files in
// the program. `pnpm --filter @objectstack/objectql typecheck` exiting 0 was a
// true sentence carrying no information about any test file in this package.
//
// ⭐ WHY THIS PACKAGE, AND WHY NOW. `src/engine-filter-array-lowering.test.ts`
// is the negative pin required by maintainer ruling #13357 execution point 3
// (landed in #13673): it proves a refused filter shape CANNOT REACH the
// reference matcher. A pin whose whole job is a security-relevant
// unreachability guarantee was type-checked by nothing at all.
//
// What differs from the build config, and what deliberately does NOT:
// - module semantics ONLY, plus `lib`. The tests are written and executed as
// ESM by vitest (esbuild/vite), while `objectql` has no `"type": "module"`,
// so the build config's NodeNext compiles them as CJS. Measured cost of
// that mismatch here: 9 of 251 raw diagnostics — TS2550 x8 (all eight the
// same `Array.prototype.at` message, against a `lib` older than es2022) and
// TS1470 x1 (`import.meta` in a CJS program). Those 9 are about the CHECK,
// never about the code. Notably SMALL next to the sibling packages
// (`rest` paid 137, `spec` 108): this layer's relative imports already
// carry their `.js` extensions, so there is no TS2835 pile here and hence
// none of the TS7006 cascade an unresolved import drags behind it.
// Matching vitest is fidelity, not laxity. No `DOM` in `lib`, unlike
// `packages/client`: nothing in this layer touches a browser global.
// - `rootDir` widens to the PACKAGE, from the build config's `src`. Under
// `noEmit` that setting carries no output meaning; all it does is constrain
// which files may enter the program. Measured: inherited as `src` it
// reports a TS6059 for `src/dry-run-hash-compat.test.ts` importing
// `scripts/dry-run-hash-compat.ts` — the SAME diagnostic #10779 retired
// from the TEST_DEBT ledger as "measuring the tape measure", i.e. the
// generated re-measure project billing this package for its own `rootDir`.
// Re-introducing it here would re-import a defect this repo already fixed.
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`
// are inherited from the root config, and `types: ["node"]` restates
// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does
// not compile, that is the finding. ⛔ Not one `any` and not one
// `@ts-expect-error` was added to any test file to open this gate — that
// shape is what turns a real gate into a phantom one.
//
// `include` deliberately stops at `src`, matching the build config's root and
// covering all 251 test files (239 in `src`, plus `src/integrity`,
// `src/lifecycle`, `src/validation`). `scripts/` is the sibling
// `tsconfig.scripts.json` (#10756) and stays a separate program: it carries no
// ledger entries at all, so plain `tsc` is a stricter gate for it than this
// file's shrink-only debt list.
//
// MEASURED at 2a181174a6, workspace closure built first (an error count taken
// against an unbuilt closure is not a reading — unresolved-import cascades
// inflate it): this program reports **242 errors across 44 files**, from a raw
// 251 under the inherited NodeNext semantics. By code: TS2339 x115,
// TS7006 x36, TS2345 x34, TS2749 x14, TS2322 x14, TS6133 x9, TS18048 x8,
// TS2353 x4, plus 8 singletons (TS7053, TS6196, TS2532, TS2493, TS2459,
// TS2416, TS2367, TS2352). `src/engine.test.ts` alone carries 102 of the 242;
// the next five are `datasource-mapping` x17, `plugin.integration` x12,
// `hook-condition-fail-loud` x12, `registry` x10, `protocol-package-lifecycle`
// x8. Every one of the 242 is PRE-EXISTING: this change edits no test file, and
// each would have been reported on `origin/main` had this program always
// existed. They are ledgered per file in `test-typecheck-debt.json` beside this
// config, EXACT and shrink-only — a file that gains an error is red, one that
// loses one is red until re-recorded, one that reaches zero is red until its
// entry is deleted, and a file NOT listed there may have no errors at all.
//
// ⚠️ THE NEGATIVE PIN CARRIES NO LEDGER ENTRY, and that is load-bearing:
// `src/engine-filter-array-lowering.test.ts` reports ZERO errors under this
// program, so any error it ever gains is red on arrival. ⚠️ Read that zero
// correctly — it is NOT evidence the pin is well typed. The file holds 20 `:
// any` annotations, and the two that matter are at its witness seam: the
// recording driver is `const driver: any` and the recorded AST is `interface
// SeenRead { ast: any }`, so `lastWhere()` — the expression the whole
// unreachability proof reads — is typed by nothing, and a drifted
// `IDataDriver` signature would not redden this file. Its own header rejects
// "a bare `as any`" in favour of `as unknown as EngineQueryOptions`
// (`asFilterArrayQuery`, used 14 times), yet 31 call sites use the bare form
// anyway. Putting the file in a program is the precondition for fixing that,
// not the fix; the repair is tracked separately (see the PR that added this
// file) and ⛔ must not be smuggled in by loosening anything here.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": ".",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/objectql/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,9 @@
"scripts": {
"build": "tsup && node ../../scripts/check-dts-emitted.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json"
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck",
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/objectql --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/objectql --project tsconfig.test.json"
},
"dependencies": {
"@objectstack/core": "workspace:*",
Expand All@@ -35,6 +37,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"tsx": "^4.23.12",
"typescript": "^6.0.3",
"vitest": "^4.1.10"
},
Expand Down
163 changes: 163 additions & 0 deletions packages/objectql/test-typecheck-debt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
{
"_comment": "Per-file tsc error debt of the @objectstack/objectql TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/objectql gen:test-typecheck-debt",
"_note": "SEEDED at 2a181174a6 by the PR that first put this layer in front of tsc (#13676), workspace closure built first. All 242 errors across 44 files are PRE-EXISTING: that PR edits no test file, and every one of these would have been reported on origin/main had this program ever existed. ⛔ Not one `any` and not one `@ts-expect-error` was added anywhere to open the gate — bulk-suppressing this residue is the exact shape the card was filed to prevent, and it would turn a real gate into a phantom one. The residue is NOT annotation debt to sweep: 14 of the 17 in src/datasource-mapping.test.ts and the bulk of the TS2345 population are one story — a driver double that does not satisfy IDataDriver — and src/engine.test.ts alone carries 102 of the 242, so read the classes before touching anything (`tsc --noEmit --pretty false -p tsconfig.test.json`). ⚠️ src/engine-filter-array-lowering.test.ts is DELIBERATELY ABSENT and must stay absent: it is the #13357 point-3 negative pin proving a refused filter shape cannot reach the reference matcher, it reports zero errors, and an unledgered file is red on its first error. ⚠️ But its zero is a weak guarantee today and must not be read as 'that pin is type-checked': the file holds `const driver: any` and `interface SeenRead { ast: any }` at the very seam the proof reads, so a drifted IDataDriver signature would not redden it. Repairing that is tracked separately and is not a licence to loosen tsconfig.test.json.",
"entries": {
"src/build-probes.test.ts": {
"TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1
},
"src/datasource-mapping.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type 'IDataDriver'.": 14,
"TS6133: 'obj' is declared but its value is never read.": 3
},
"src/engine-audit-anchor-write.test.ts": {
"TS2532: Object is possibly 'undefined'.": 1
},
"src/engine-autonumber-default-format.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 3
},
"src/engine-autonumber-defer.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 4
},
"src/engine-autonumber-resync.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-outage.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-scan.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 5
},
"src/engine-autonumber-seed-suffix.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-cascade-delete.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-data-events.test.ts": {
"TS6133: 'warn' is declared but its value is never read.": 1
},
"src/engine-delete-prior-read-scope.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 3,
"TS6196: 'ObjectSchema' is declared but never used.": 1
},
"src/engine-lifecycle-datasource.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-update-prior-read-scope.test.ts": {
"TS2345: Argument of type 'unknown' is not assignable to parameter of type '…'.": 1
},
"src/engine.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 75,
"TS2339: Property 'registerKind' does not exist on type 'typeof SchemaRegistry'.": 1,
"TS2339: Property 'registerObject' does not exist on type 'typeof SchemaRegistry'.": 3,
"TS2353: Object literal may only specify known properties, and 'filter' does not exist in type '…'.": 1,
"TS7006: Parameter 'name' implicitly has an 'any' type.": 22
},
"src/function-registry-effect.test.ts": {
"TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1
},
"src/hook-binder.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-bulk-previous.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 3,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 3
},
"src/hook-condition-fail-loud.test.ts": {
"TS2339: Property 'catch' does not exist on type '…'.": 2,
"TS2339: Property 'then' does not exist on type '…'.": 5,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 5
},
"src/hook-condition-merged-record.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-previous-scope.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS6133: 'reads' is declared but its value is never read.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/in-memory-aggregation.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/layered-overlay-integration.test.ts": {
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1,
"TS2353: Object literal may only specify known properties, and 'org' does not exist in type 'InMemoryRepositoryOptions'.": 1
},
"src/metadata-service-roundtrip-conformance.test.ts": {
"TS2322: Type 'WritableFixtureLoader' is not assignable to type 'MetadataLoader'.": 1,
"TS2416: Property 'save' in type 'WritableFixtureLoader' is not assignable to the same property in base type 'MetadataLoader'.": 1
},
"src/plugin-authored-hooks.test.ts": {
"TS6133: 'obj' is declared but its value is never read.": 1
},
"src/plugin.integration.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 11,
"TS6133: 'ObjectSchema' is declared but its value is never read.": 1
},
"src/protocol-boot-hydration-scoped.test.ts": {
"TS2322: Type '…' is not assignable to type 'string'.": 3
},
"src/protocol-boot-object-package-binding.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 3
},
"src/protocol-discovery.test.ts": {
"TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ data: string; metadata: string; discovery?: string | undefined; ui?: string | undefined; auth?: string | undefined; automation?: string | undefined; storage?: string | undefined; analytics?: string | undefined; ... 8 more ...; mcp?: string | undefined; }'.": 1
},
"src/protocol-lock-enforcement.test.ts": {
"TS6133: 'beforeEach' is declared but its value is never read.": 1
},
"src/protocol-package-lifecycle.test.ts": {
"TS2339: Property 'mock' does not exist on type 'never'.": 3,
"TS2339: Property 'mockResolvedValue' does not exist on type 'never'.": 2,
"TS7006: Parameter 'c' implicitly has an 'any' type.": 3
},
"src/protocol-publish-rollback.test.ts": {
"TS6133: 'rows' is declared but its value is never read.": 1
},
"src/protocol-recorded-by-null.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-registry-shadow.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-save-meta-repo-path-real-engine.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/protocol-save-meta-repo-path.test.ts": {
"TS18048: 'row.checksum' is possibly 'undefined'.": 1
},
"src/protocol-writepath-object-ownership.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 2
},
"src/query-expression-conformance.test.ts": {
"TS2322: Type '…' is not assignable to type 'QueryInput'.": 2
},
"src/registry-invalidate.test.ts": {
"TS2459: Module '\"@objectstack/spec\"' declares 'ServiceObject' locally, but it is not exported.": 1
},
"src/registry.test.ts": {
"TS18048: 'out.enable' is possibly 'undefined'.": 7,
"TS2339: Property 'indexed' does not exist on type '…'.": 3
},
"src/sys-metadata-repository-list-drafts.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/sys-metadata-repository.test.ts": {
"TS2322: Type '\"theme\"' is not assignable to type '…'.": 2,
"TS2322: Type '\"trigger\"' is not assignable to type '…'.": 1,
"TS2322: Type '\"webhook\"' is not assignable to type '…'.": 1,
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1
},
"src/validation/record-validator.test.ts": {
"TS2367: This comparison appears to be unintentional because the types 'number' and 'boolean' have no overlap.": 1
},
"src/validation/rule-fail-closed.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1,
"TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'ConditionalFieldDef'.": 2
}
}
}
103 changes: 103 additions & 0 deletions packages/objectql/tsconfig.test.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
// The TEST-layer type-check program (#13676), adopting the mechanism #5286 set
// for `packages/spec` and #5449 generalised. `tsconfig.json` above stays as it
// is: it is the BUILD config, and its `**/*.test.ts` exclusion has a reason —
// ci.yml gates that no test file reaches the published artifact. This sibling
// puts the excluded layer back in front of tsc, and `package.json`'s
// `typecheck` script NAMES it (via `check:test-typecheck --project`), because a
// config no script invokes is exactly the phantom this whole change is about.
//
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE. Measured
// at 2a181174a6 with the workspace closure built first: `tsc --listFiles`
// against the build config puts 536 files in the program and **0** of the
// package's 251 `*.test.ts` files among them, while 50 `src/**` non-test files
// ARE there — so the zero is the `exclude` line, not a probe that sees nothing.
// The directional control is `packages/drivers/driver-memory`, whose tsconfig
// carries no test exclusion: the same probe puts **38 of its 38** test files in
// the program. `pnpm --filter @objectstack/objectql typecheck` exiting 0 was a
// true sentence carrying no information about any test file in this package.
//
// ⭐ WHY THIS PACKAGE, AND WHY NOW. `src/engine-filter-array-lowering.test.ts`
// is the negative pin required by maintainer ruling #13357 execution point 3
// (landed in #13673): it proves a refused filter shape CANNOT REACH the
// reference matcher. A pin whose whole job is a security-relevant
// unreachability guarantee was type-checked by nothing at all.
//
// What differs from the build config, and what deliberately does NOT:
// - module semantics ONLY, plus `lib`. The tests are written and executed as
// ESM by vitest (esbuild/vite), while `objectql` has no `"type": "module"`,
// so the build config's NodeNext compiles them as CJS. Measured cost of
// that mismatch here: 9 of 251 raw diagnostics — TS2550 x8 (all eight the
// same `Array.prototype.at` message, against a `lib` older than es2022) and
// TS1470 x1 (`import.meta` in a CJS program). Those 9 are about the CHECK,
// never about the code. Notably SMALL next to the sibling packages
// (`rest` paid 137, `spec` 108): this layer's relative imports already
// carry their `.js` extensions, so there is no TS2835 pile here and hence
// none of the TS7006 cascade an unresolved import drags behind it.
// Matching vitest is fidelity, not laxity. No `DOM` in `lib`, unlike
// `packages/client`: nothing in this layer touches a browser global.
// - `rootDir` widens to the PACKAGE, from the build config's `src`. Under
// `noEmit` that setting carries no output meaning; all it does is constrain
// which files may enter the program. Measured: inherited as `src` it
// reports a TS6059 for `src/dry-run-hash-compat.test.ts` importing
// `scripts/dry-run-hash-compat.ts` — the SAME diagnostic #10779 retired
// from the TEST_DEBT ledger as "measuring the tape measure", i.e. the
// generated re-measure project billing this package for its own `rootDir`.
// Re-introducing it here would re-import a defect this repo already fixed.
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`
// are inherited from the root config, and `types: ["node"]` restates
// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does
// not compile, that is the finding. ⛔ Not one `any` and not one
// `@ts-expect-error` was added to any test file to open this gate — that
// shape is what turns a real gate into a phantom one.
//
// `include` deliberately stops at `src`, matching the build config's root and
// covering all 251 test files (239 in `src`, plus `src/integrity`,
// `src/lifecycle`, `src/validation`). `scripts/` is the sibling
// `tsconfig.scripts.json` (#10756) and stays a separate program: it carries no
// ledger entries at all, so plain `tsc` is a stricter gate for it than this
// file's shrink-only debt list.
//
// MEASURED at 2a181174a6, workspace closure built first (an error count taken
// against an unbuilt closure is not a reading — unresolved-import cascades
// inflate it): this program reports **242 errors across 44 files**, from a raw
// 251 under the inherited NodeNext semantics. By code: TS2339 x115,
// TS7006 x36, TS2345 x34, TS2749 x14, TS2322 x14, TS6133 x9, TS18048 x8,
// TS2353 x4, plus 8 singletons (TS7053, TS6196, TS2532, TS2493, TS2459,
// TS2416, TS2367, TS2352). `src/engine.test.ts` alone carries 102 of the 242;
// the next five are `datasource-mapping` x17, `plugin.integration` x12,
// `hook-condition-fail-loud` x12, `registry` x10, `protocol-package-lifecycle`
// x8. Every one of the 242 is PRE-EXISTING: this change edits no test file, and
// each would have been reported on `origin/main` had this program always
// existed. They are ledgered per file in `test-typecheck-debt.json` beside this
// config, EXACT and shrink-only — a file that gains an error is red, one that
// loses one is red until re-recorded, one that reaches zero is red until its
// entry is deleted, and a file NOT listed there may have no errors at all.
//
// ⚠️ THE NEGATIVE PIN CARRIES NO LEDGER ENTRY, and that is load-bearing:
// `src/engine-filter-array-lowering.test.ts` reports ZERO errors under this
// program, so any error it ever gains is red on arrival. ⚠️ Read that zero
// correctly — it is NOT evidence the pin is well typed. The file holds 20 `:
// any` annotations, and the two that matter are at its witness seam: the
// recording driver is `const driver: any` and the recorded AST is `interface
// SeenRead { ast: any }`, so `lastWhere()` — the expression the whole
// unreachability proof reads — is typed by nothing, and a drifted
// `IDataDriver` signature would not redden this file. Its own header rejects
// "a bare `as any`" in favour of `as unknown as EngineQueryOptions`
// (`asFilterArrayQuery`, used 14 times), yet 31 call sites use the bare form
// anyway. Putting the file in a program is the precondition for fixing that,
// not the fix; the repair is tracked separately (see the PR that added this
// file) and ⛔ must not be smuggled in by loosening anything here.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": ".",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion packages/objectql/package.json
Original file line numberDiff line numberDiff line change
Expand Up@@ -20,7 +20,9 @@
"scripts": {
"build": "tsup && node ../../scripts/check-dts-emitted.mjs",
"test": "vitest run",
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json"
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.scripts.json && pnpm check:test-typecheck",
"check:test-typecheck": "tsx ../../scripts/check-test-typecheck.mts --self-test && tsx ../../scripts/check-test-typecheck.mts --package packages/objectql --project tsconfig.test.json",
"gen:test-typecheck-debt": "tsx ../../scripts/check-test-typecheck.mts --update --package packages/objectql --project tsconfig.test.json"
},
"dependencies": {
"@objectstack/core": "workspace:*",
Expand All@@ -35,6 +37,7 @@
"zod": "^4.4.3"
},
"devDependencies": {
"tsx": "^4.23.12",
"typescript": "^6.0.3",
"vitest": "^4.1.10"
},
Expand Down
163 changes: 163 additions & 0 deletions packages/objectql/test-typecheck-debt.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
{
"_comment": "Per-file tsc error debt of the @objectstack/objectql TEST layer (#5286). `tsconfig.test.json` compiles `src/**/*.test.ts` — which `tsconfig.json` excludes and therefore no gate ever read — and every file below still carries errors from before that gate existed. THIS FIELD IS GENERATED: every regeneration rewrites it from scripts/check-test-typecheck.mts, and the EXACT ratchet below requires a regeneration on every repair — so an edit made here is gone by the next one. Anything true of THIS package goes in the sibling `_note` field, which is authored, is preserved verbatim, and is never written by the generator (#12624). This comment states NO cause for the errors, deliberately: the classes differ per package and per file, they move as the debt is paid down, and a cause written here is rewritten verbatim into every ledger by every regeneration — so it outlives its own repair and cannot be corrected in the file where it is read. Measure instead, before repairing anything: `tsc --noEmit --pretty false -p tsconfig.test.json` in the package prints the real classes with their TS codes. Each entry maps a file to its per-SIGNATURE error counts, never to a bare total (#13470): a signature is the TS code plus the diagnostic message with structural type blobs collapsed, and it carries NO line or column — so the pin survives edits that move code around, and only stops matching when the error itself becomes a different error. EXACT ratchet, judged by re-running tsc: a file that gains errors is red, a file that loses them is red until its number is re-recorded, a file that reaches zero is red until its entry is deleted, a signature that ARRIVES or VANISHES is red even when the file total is unchanged, and a file NOT listed here may have no errors at all. Regenerate with: pnpm --filter @objectstack/objectql gen:test-typecheck-debt",
"_note": "SEEDED at 2a181174a6 by the PR that first put this layer in front of tsc (#13676), workspace closure built first. All 242 errors across 44 files are PRE-EXISTING: that PR edits no test file, and every one of these would have been reported on origin/main had this program ever existed. ⛔ Not one `any` and not one `@ts-expect-error` was added anywhere to open the gate — bulk-suppressing this residue is the exact shape the card was filed to prevent, and it would turn a real gate into a phantom one. The residue is NOT annotation debt to sweep: 14 of the 17 in src/datasource-mapping.test.ts and the bulk of the TS2345 population are one story — a driver double that does not satisfy IDataDriver — and src/engine.test.ts alone carries 102 of the 242, so read the classes before touching anything (`tsc --noEmit --pretty false -p tsconfig.test.json`). ⚠️ src/engine-filter-array-lowering.test.ts is DELIBERATELY ABSENT and must stay absent: it is the #13357 point-3 negative pin proving a refused filter shape cannot reach the reference matcher, it reports zero errors, and an unledgered file is red on its first error. ⚠️ But its zero is a weak guarantee today and must not be read as 'that pin is type-checked': the file holds `const driver: any` and `interface SeenRead { ast: any }` at the very seam the proof reads, so a drifted IDataDriver signature would not redden it. Repairing that is tracked separately and is not a licence to loosen tsconfig.test.json.",
"entries": {
"src/build-probes.test.ts": {
"TS2493: Tuple type '…' of length '0' has no element at index '1'.": 1
},
"src/datasource-mapping.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type 'IDataDriver'.": 14,
"TS6133: 'obj' is declared but its value is never read.": 3
},
"src/engine-audit-anchor-write.test.ts": {
"TS2532: Object is possibly 'undefined'.": 1
},
"src/engine-autonumber-default-format.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 3
},
"src/engine-autonumber-defer.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 4
},
"src/engine-autonumber-resync.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-outage.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-autonumber-seed-scan.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 5
},
"src/engine-autonumber-seed-suffix.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 1
},
"src/engine-cascade-delete.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-data-events.test.ts": {
"TS6133: 'warn' is declared but its value is never read.": 1
},
"src/engine-delete-prior-read-scope.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 3,
"TS6196: 'ObjectSchema' is declared but never used.": 1
},
"src/engine-lifecycle-datasource.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/engine-update-prior-read-scope.test.ts": {
"TS2345: Argument of type 'unknown' is not assignable to parameter of type '…'.": 1
},
"src/engine.test.ts": {
"TS2339: Property 'getObject' does not exist on type 'typeof SchemaRegistry'.": 75,
"TS2339: Property 'registerKind' does not exist on type 'typeof SchemaRegistry'.": 1,
"TS2339: Property 'registerObject' does not exist on type 'typeof SchemaRegistry'.": 3,
"TS2353: Object literal may only specify known properties, and 'filter' does not exist in type '…'.": 1,
"TS7006: Parameter 'name' implicitly has an 'any' type.": 22
},
"src/function-registry-effect.test.ts": {
"TS2352: Conversion of type '…' to type '…' may be a mistake because neither type sufficiently overlaps with the other. If this was intentional, convert the expression to 'unknown' first.": 1
},
"src/hook-binder.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-bulk-previous.test.ts": {
"TS2339: Property 'then' does not exist on type '…'.": 3,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 3
},
"src/hook-condition-fail-loud.test.ts": {
"TS2339: Property 'catch' does not exist on type '…'.": 2,
"TS2339: Property 'then' does not exist on type '…'.": 5,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 5
},
"src/hook-condition-merged-record.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/hook-condition-previous-scope.test.ts": {
"TS2322: Type '…' is not assignable to type '…'.": 1,
"TS2339: Property 'then' does not exist on type '…'.": 1,
"TS6133: 'reads' is declared but its value is never read.": 1,
"TS7006: Parameter 'e' implicitly has an 'any' type.": 1
},
"src/in-memory-aggregation.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/layered-overlay-integration.test.ts": {
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1,
"TS2353: Object literal may only specify known properties, and 'org' does not exist in type 'InMemoryRepositoryOptions'.": 1
},
"src/metadata-service-roundtrip-conformance.test.ts": {
"TS2322: Type 'WritableFixtureLoader' is not assignable to type 'MetadataLoader'.": 1,
"TS2416: Property 'save' in type 'WritableFixtureLoader' is not assignable to the same property in base type 'MetadataLoader'.": 1
},
"src/plugin-authored-hooks.test.ts": {
"TS6133: 'obj' is declared but its value is never read.": 1
},
"src/plugin.integration.test.ts": {
"TS2749: 'ObjectSchema' refers to a value, but is being used as a type here. Did you mean 'typeof ObjectSchema'?": 11,
"TS6133: 'ObjectSchema' is declared but its value is never read.": 1
},
"src/protocol-boot-hydration-scoped.test.ts": {
"TS2322: Type '…' is not assignable to type 'string'.": 3
},
"src/protocol-boot-object-package-binding.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 3
},
"src/protocol-discovery.test.ts": {
"TS7053: Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{ data: string; metadata: string; discovery?: string | undefined; ui?: string | undefined; auth?: string | undefined; automation?: string | undefined; storage?: string | undefined; analytics?: string | undefined; ... 8 more ...; mcp?: string | undefined; }'.": 1
},
"src/protocol-lock-enforcement.test.ts": {
"TS6133: 'beforeEach' is declared but its value is never read.": 1
},
"src/protocol-package-lifecycle.test.ts": {
"TS2339: Property 'mock' does not exist on type 'never'.": 3,
"TS2339: Property 'mockResolvedValue' does not exist on type 'never'.": 2,
"TS7006: Parameter 'c' implicitly has an 'any' type.": 3
},
"src/protocol-publish-rollback.test.ts": {
"TS6133: 'rows' is declared but its value is never read.": 1
},
"src/protocol-recorded-by-null.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-registry-shadow.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 2
},
"src/protocol-save-meta-repo-path-real-engine.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 3
},
"src/protocol-save-meta-repo-path.test.ts": {
"TS18048: 'row.checksum' is possibly 'undefined'.": 1
},
"src/protocol-writepath-object-ownership.test.ts": {
"TS2345: Argument of type 'Row' is not assignable to parameter of type '…'.": 2
},
"src/query-expression-conformance.test.ts": {
"TS2322: Type '…' is not assignable to type 'QueryInput'.": 2
},
"src/registry-invalidate.test.ts": {
"TS2459: Module '\"@objectstack/spec\"' declares 'ServiceObject' locally, but it is not exported.": 1
},
"src/registry.test.ts": {
"TS18048: 'out.enable' is possibly 'undefined'.": 7,
"TS2339: Property 'indexed' does not exist on type '…'.": 3
},
"src/sys-metadata-repository-list-drafts.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1
},
"src/sys-metadata-repository.test.ts": {
"TS2322: Type '\"theme\"' is not assignable to type '…'.": 2,
"TS2322: Type '\"trigger\"' is not assignable to type '…'.": 1,
"TS2322: Type '\"webhook\"' is not assignable to type '…'.": 1,
"TS2322: Type '…' is not assignable to type 'SysMetadataEngine'.": 1
},
"src/validation/record-validator.test.ts": {
"TS2367: This comparison appears to be unintentional because the types 'number' and 'boolean' have no overlap.": 1
},
"src/validation/rule-fail-closed.test.ts": {
"TS2345: Argument of type '…' is not assignable to parameter of type '…'.": 1,
"TS2353: Object literal may only specify known properties, and 'name' does not exist in type 'ConditionalFieldDef'.": 2
}
}
}
103 changes: 103 additions & 0 deletions packages/objectql/tsconfig.test.json
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
// The TEST-layer type-check program (#13676), adopting the mechanism #5286 set
// for `packages/spec` and #5449 generalised. `tsconfig.json` above stays as it
// is: it is the BUILD config, and its `**/*.test.ts` exclusion has a reason —
// ci.yml gates that no test file reaches the published artifact. This sibling
// puts the excluded layer back in front of tsc, and `package.json`'s
// `typecheck` script NAMES it (via `check:test-typecheck --project`), because a
// config no script invokes is exactly the phantom this whole change is about.
//
// BEFORE THIS FILE, NO tsc PROGRAM COMPILED A SINGLE TEST FILE HERE. Measured
// at 2a181174a6 with the workspace closure built first: `tsc --listFiles`
// against the build config puts 536 files in the program and **0** of the
// package's 251 `*.test.ts` files among them, while 50 `src/**` non-test files
// ARE there — so the zero is the `exclude` line, not a probe that sees nothing.
// The directional control is `packages/drivers/driver-memory`, whose tsconfig
// carries no test exclusion: the same probe puts **38 of its 38** test files in
// the program. `pnpm --filter @objectstack/objectql typecheck` exiting 0 was a
// true sentence carrying no information about any test file in this package.
//
// ⭐ WHY THIS PACKAGE, AND WHY NOW. `src/engine-filter-array-lowering.test.ts`
// is the negative pin required by maintainer ruling #13357 execution point 3
// (landed in #13673): it proves a refused filter shape CANNOT REACH the
// reference matcher. A pin whose whole job is a security-relevant
// unreachability guarantee was type-checked by nothing at all.
//
// What differs from the build config, and what deliberately does NOT:
// - module semantics ONLY, plus `lib`. The tests are written and executed as
// ESM by vitest (esbuild/vite), while `objectql` has no `"type": "module"`,
// so the build config's NodeNext compiles them as CJS. Measured cost of
// that mismatch here: 9 of 251 raw diagnostics — TS2550 x8 (all eight the
// same `Array.prototype.at` message, against a `lib` older than es2022) and
// TS1470 x1 (`import.meta` in a CJS program). Those 9 are about the CHECK,
// never about the code. Notably SMALL next to the sibling packages
// (`rest` paid 137, `spec` 108): this layer's relative imports already
// carry their `.js` extensions, so there is no TS2835 pile here and hence
// none of the TS7006 cascade an unresolved import drags behind it.
// Matching vitest is fidelity, not laxity. No `DOM` in `lib`, unlike
// `packages/client`: nothing in this layer touches a browser global.
// - `rootDir` widens to the PACKAGE, from the build config's `src`. Under
// `noEmit` that setting carries no output meaning; all it does is constrain
// which files may enter the program. Measured: inherited as `src` it
// reports a TS6059 for `src/dry-run-hash-compat.test.ts` importing
// `scripts/dry-run-hash-compat.ts` — the SAME diagnostic #10779 retired
// from the TEST_DEBT ledger as "measuring the tape measure", i.e. the
// generated re-measure project billing this package for its own `rootDir`.
// Re-introducing it here would re-import a defect this repo already fixed.
// - ⛔ STRICTNESS IS UNTOUCHED. `strict`, `noUnusedLocals`,
// `noUnusedParameters`, `noImplicitReturns`, `noFallthroughCasesInSwitch`
// are inherited from the root config, and `types: ["node"]` restates
// `tsconfig.json`'s. Nothing here may loosen a type rule; if a test does
// not compile, that is the finding. ⛔ Not one `any` and not one
// `@ts-expect-error` was added to any test file to open this gate — that
// shape is what turns a real gate into a phantom one.
//
// `include` deliberately stops at `src`, matching the build config's root and
// covering all 251 test files (239 in `src`, plus `src/integrity`,
// `src/lifecycle`, `src/validation`). `scripts/` is the sibling
// `tsconfig.scripts.json` (#10756) and stays a separate program: it carries no
// ledger entries at all, so plain `tsc` is a stricter gate for it than this
// file's shrink-only debt list.
//
// MEASURED at 2a181174a6, workspace closure built first (an error count taken
// against an unbuilt closure is not a reading — unresolved-import cascades
// inflate it): this program reports **242 errors across 44 files**, from a raw
// 251 under the inherited NodeNext semantics. By code: TS2339 x115,
// TS7006 x36, TS2345 x34, TS2749 x14, TS2322 x14, TS6133 x9, TS18048 x8,
// TS2353 x4, plus 8 singletons (TS7053, TS6196, TS2532, TS2493, TS2459,
// TS2416, TS2367, TS2352). `src/engine.test.ts` alone carries 102 of the 242;
// the next five are `datasource-mapping` x17, `plugin.integration` x12,
// `hook-condition-fail-loud` x12, `registry` x10, `protocol-package-lifecycle`
// x8. Every one of the 242 is PRE-EXISTING: this change edits no test file, and
// each would have been reported on `origin/main` had this program always
// existed. They are ledgered per file in `test-typecheck-debt.json` beside this
// config, EXACT and shrink-only — a file that gains an error is red, one that
// loses one is red until re-recorded, one that reaches zero is red until its
// entry is deleted, and a file NOT listed there may have no errors at all.
//
// ⚠️ THE NEGATIVE PIN CARRIES NO LEDGER ENTRY, and that is load-bearing:
// `src/engine-filter-array-lowering.test.ts` reports ZERO errors under this
// program, so any error it ever gains is red on arrival. ⚠️ Read that zero
// correctly — it is NOT evidence the pin is well typed. The file holds 20 `:
// any` annotations, and the two that matter are at its witness seam: the
// recording driver is `const driver: any` and the recorded AST is `interface
// SeenRead { ast: any }`, so `lastWhere()` — the expression the whole
// unreachability proof reads — is typed by nothing, and a drifted
// `IDataDriver` signature would not redden this file. Its own header rejects
// "a bare `as any`" in favour of `as unknown as EngineQueryOptions`
// (`asFilterArrayQuery`, used 14 times), yet 31 call sites use the bare form
// anyway. Putting the file in a program is the precondition for fixing that,
// not the fix; the repair is tracked separately (see the PR that added this
// file) and ⛔ must not be smuggled in by loosening anything here.
{
"extends": "./tsconfig.json",
"compilerOptions": {
"noEmit": true,
"rootDir": ".",
"module": "esnext",
"moduleResolution": "bundler",
"lib": ["ES2022"],
"types": ["node"]
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist"]
}
3 changes: 3 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading