refactor(showcase): drop the unreachable rowsOf normalizer from the nightly health sweep - #14841
Merged
Merged
Conversation
… health sweep
`sweepProjectHealth` wrapped both of its `ql.find(...)` reads in a local
`rowsOf()` that accepted either an array or a `{ records }` envelope. The
`{ records }` limb cannot fire: `IObjectQLEngine.find` is declared
`Promise<any[]>`, ObjectQL's implementation returns arrays on both of its
return paths, and `IDataDriver.find` — the value those paths thread through
— is itself declared `Promise<Record<string, unknown>[]>`.
This is the repo's only shipped `defineJob`, so it is the copy-source for
scheduled work. A defensive shape that cannot fire teaches a false contract
to whoever copies it. Both reads now read as the contract actually is.
No behaviour change: the normalizer was an identity on every value the
engine can produce.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AUF1NoViznQK32gqpK8wS8
This was referenced Sep 3, 2026
os-sales
marked this pull request as ready for review
September 3, 2026 05:17
os-sales
enabled auto-merge
September 3, 2026 05:17
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #14460
Deletes the local
rowsOf()normalizer fromsweepProjectHealthand reads the twoql.find(...)results as the arrays they are. Nothing else.This is the repo's only shipped
defineJob, so it is the copy-source for scheduled work.A defensive shape that cannot fire teaches a false contract to whoever copies it.
The
{ records }limb is unreachable — measured on the tree, not assumedrowsOf()accepted either an array or an object carrying arecordsarray. The secondlimb cannot fire for this handler. Four independent legs, all at
e275b7b8:Declared engine contract —
packages/spec/src/contracts/data-engine.ts:251:find(objectName, query?, options?)resolves toany[], an array.The implementation behind it —
packages/objectql/src/engine.ts:9075,async find(object, query?, options?), also resolving toany[]. Its body has exactlytwo
returnstatements:return hookContext.resultandreturn opCtx.result as any[].Both carry the value of
driver.find(...); every post-processing step between them isguarded by
Array.isArray(result)and reassigns only arrays.The driver contract those two returns thread through —
packages/spec/src/contracts/data-driver.ts:155declaresfindas resolving to anarray of row objects. So the value the engine returns originates as an array by
contract, not by convention.
The one seam that could substitute a different value is unused. The
return hookContext.resultpath returns whatever anafterFindhook left behind. Thewhole repo registers exactly one
afterFindhook outside tests —packages/plugins/plugin-audit/src/read-audit.ts:600(auditRead) — and that modulecontains no assignment to
.resultat all; it only reads it. The showcase app itselfdeclares no
afterFindhook:examples/app-showcase/src/data/hooks/index.tsdeclaresonly
beforeInsert,beforeUpdateandafterUpdate.And
ctx.qlin this handler is that engine, not some other handle:packages/runtime/src/job-handler-context.tstypesJobHandlerContext.qlasIObjectQLEngine;packages/runtime/src/app-plugin.ts:1029builds the job context withthe
qlresolved atapp-plugin.ts:520viactx.getService('objectql'); and theproduction registration of that service name is
packages/objectql/src/plugin.ts:400,ctx.registerService('objectql', this.ql), wherethis.qlisnew ObjectQL(...)— the class whosefindis leg 2.One more datum worth recording: the
recordsenvelope does exist in this repo, on adifferent function with a different declared return —
packages/metadata/src/loaders/database-loader.ts,queryHistory(), a metadata-historypagination shape. Nothing on
ql.find's path produces it.The two call sites, before and after
Before (the two
rowsOf(...)wrappers):After:
The explicit annotation is deliberate: the declared return is
any[], and lettinganypropagate would have silently weakened every downstream member read in this file
(
project.budget,task.progress,p.id). The annotation keeps the exact static typethe code already had while deleting the runtime branch. No behaviour changes — the
normalizer was an identity on every value the engine can produce.
The delete leaves no dangling reference:
rowsOfnow occurs 0 times in the file (3before),
records0 times, and the file's only import (JobHandlerContext) is stillused. Diff is 1 file, +12 / -23.
Tests
Suite covering this job:
examples/app-showcase/test/inert-wirings.test.ts.Measured both ways from the committed state, restoring the parent version of the file on
disk for the "before" leg and confirming each leg by blob hash before reading anything:
rowsOfdeleted)rowsOfcount 0Tests 36 passed (36)cd757ba8==HEAD~1blob,rowsOfcount 3Tests 36 passed (36)006c547c==HEADblob,git diff HEADemptyNo rebuild leg was needed for either measurement:
@objectstack/example-showcaseexportsTypeScript source (
main: ./objectstack.config.ts) and the suite imports the handler byrelative source path, so no
dist/sits between the edit and the assertion.Both legs pass identically, which is the expected direction here rather than a red: the
suite's fake engine returns arrays on every path, so it never exercised the deleted limb.
That is corroboration that the limb was dead, and it means no coverage was lost.
Whole package, after:
Test Files 27 passed (27),Tests 375 passed (375).pnpm --filter @objectstack/example-showcase run typecheck(tsc --noEmit) clean —and verified to actually cover the edit:
tsc --listFileslistssweep-project-health.tsamong the 1589 files in the program.Gates
Derived from the real change set with
node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack(1 path vs merge base
2d40f914), then run ate275b7b8with exit codes captured byredirect, never across a pipe.
15 of 17 green, including
check:react-page-adapter-contract, which reports21 app-showcase page module(s) + 1 content/docs react-page sample(s) ... no find() result is tested for array-ness.Two exited 3, which each gate's own verdict text declares is not a result:
check-test-completeness—Nothing was measured: this gate exited before parsing a single summary line.check:dual-build-cjs-loads—PREREQUISITE NOT MET — this gate reads built output, and some package has no dist/.Its self-test half passed (93 cases). Recorded as NOTMEASURED, not as a pass and not as a red; CI runs it after a full build.
Also run:
pnpm check:nul-bytesgreen (8070 files, no raw control bytes), and therepo-wide
pnpm lint(eslint . --no-inline-config) — exit 0, no findings. That is thefull scan, not a narrowed one.
Changeset
None,
skip-changeset.@objectstack/example-showcaseis"private": true, so this diffpublishes nothing from any released package — AGENTS.md's stated criterion for the label.
The direct precedent is
253da34c4, the examples-only commit that created this veryhandler, which carried no changeset either.
Out of scope, deliberately
Per the triage ruling, this card is the instance and not the class:
scripts/check-react-page-adapter-contract.mjsand its population are untouched. A secondinstance of the same dead-normalizer shape exists at
packages/cli/src/commands/secret/orphans.ts(its own localrowsOf, oversecretDriver.find(...)); it is reported back to the dispatching PM rather than fixedhere — different package, different lane.
🤖 Generated with Claude Code
https://claude.ai/code/session_01AUF1NoViznQK32gqpK8wS8