Repository navigation
[finding] gen:openapi and gen:schema disagree about OS_EAGER_SCHEMAS, so a published artifact's bytes depend on which generator ran — and it already made a measuring instrument lie #19101
Description
Activity
objectstack-fleet commented
on Sep 23, 2026 ContributorMore actionsTriage (seat
session_01Tw7jnJinGHvoGSi8aFkhPJ):pm:queue· p3 ·domain:spec·area:apiPath: 可对外的 API / 仪器为车队服务 | 缺项(无项断言生成器确定性)| P② | p3
Graded at 2026-09-23T01:33Z.It clears ruling batch #202 letter B on the published-surface limb: the artifact whose bytes depend on which generator ran is
json-schema/openapi.json, which the spec package both ships infilesand exposes as a named export. ⇒ a customer can import it.The asymmetry is real and measured on
origin/main: one generator script setsOS_EAGER_SCHEMASand the other does not — with a lit control confirming other scripts in the same directory do set it. ⇒ whetherlazySchema()bodies evaluate eagerly, and therefore whether a.describe()survives, depends on which command ran.⚠️ ⛔ NOT the same mechanism as #19098 / #19100, and this seat checked rather than folding it in: that generator imports the published-projection helper and its only mention of a bare call is a comment saying ⛔ not to make one. This card is an environment variable changing evaluation timing, ⛔ not a missing projection override. Route it alone.⚠️ NOT MEASURED: the byte divergence itself — reproducing it writes a generated artifact, so neither the reader nor this seat ran it. That reproduction is the round's first act.⚠️ p3 enters the queue but waits: NORTH-STAR rule 3 keeps a p3 behind the open product p0/p1s.Generated by Claude Code
- addedarea:apiThe API a customer can call, and integrations — REST, connectors, webhooks, jobsThe API a customer can call, and integrations — REST, connectors, webhooks, jobsand removed
on Sep 23, 2026 objectstack-fleet commented
on Sep 23, 2026 ContributorMore actionsClaim: seat 5 serial dispatch, one dev at a time
Session:session_01Sfe5YjBLwB9J3y8fvm2xq1
Branch:claude/issue-19101-openapi-eager-schemas
Domain:domain:spec
Seat:domain:spec#5(seat post #19357)
Maintainer instruction that releases this card (provenance): the maintainer, in this seat's session chat on 2026-09-23 (~23:4xZ). Verbatim reply: 「A」. It answers the seat's option A, 「本车道放开第 3 条,我立刻派 #17707,之后接着派 #19101、#17916」. That lifts NORTH-STAR 优先级 item 3 for this lane, the reason triage5787429974gave for this card to wait. #17707 is held for a premise question sent to the maintainer, so this card goes first.
File surface:packages/spec/package.json(thegen:openapiscript,:251),packages/spec/scripts/build-openapi.ts, thegen:openapientry inpackages/spec/scripts/check-generated.ts, and their tests and changeset. Stop and report on a breach.
Container & model:mode:subagent, default tier.dispatch-gates.mjs --tieron the three paths printed "Model tier — no path-derived mandate".
Clause-②: no. The accept set does not move. The change is which.describe()text a published artifact carries.
Thread-read: 5787429974
Serial constraints cleared: #19921 holdspackages/spec/package.json(hunk:293) andcheck-generated.ts(hunks:349,:377,:856), all away from:251and from thegen:openapientry at:422. No other open PR of the 34 touches this surface at 2026-09-23T23:49Z.
Generated by Claude Code
objectstack-fleet commented
on Sep 24, 2026 ContributorMore actionsos-dev-report
{
"issue": 19101,
"status": "needs_decision",
"branch": "claude/issue-19101-openapi-eager-schemas",
"pr": null,
"head_sha": "fdeeea0cc9 (branch pushed empty as the claim landing marker; zero commits on it)",
"session": "session_01Sfe5YjBLwB9J3y8fvm2xq1",
"premise_still_valid": true,
"summary": "Reproduced on origin/main fdeeea0: the asymmetry is real, but the generator's two outcomes are 'lazy document' vs 'crash', and the eager conversion adds exactly 2 description leaves. Neither candidate fix is clean inside the claimed surface: (a) as specified makes gen:openapi die at module load on a src import cycle (the same cycle crashes the PUBLISHED @objectstack/spec/api and /data entries under the documented rollback flag), and (b) lives in src/shared/lazy-schema.ts, where the same drop also costs 170 descriptions on the served /meta/types schemas and 445 on theos generateIDE schema. Per the dispatch's stop rule I made no code change and opened no PR; options with measured costs are in open_questions.",
"divergence": {
"generator_as_shipped": "env unset:tsx scripts/build-openapi.tsexit 0, Components: 9. OS_EAGER_SCHEMAS=1: exit 1 at module load, ReferenceError: Cannot access 'FilterConditionSchema' before initialization (src/data/field.zod.ts:1529 relatedListFilter, reached through the eager lazySchema at :1000). It writes nothing, and it leaves any earlier json-schema/openapi.json on disk as it was, so a naive run-then-copy compares the stale lazy file with itself and reads 'identical'.",
"cycle": "load chain measured with a Module._load hook: src/data/filter.zod.ts -> src/shared/strict-object.ts -> src/shared/suggestions.zod.ts (imports the FieldType value from data/field.zod) -> src/data/field.zod.ts, whose eager FieldSchema factory reads FilterConditionSchema while filter.zod is still in its import phase. First-import probes under the flag: src/api, src/data, src/api/contract.zod, src/data/filter.zod, scripts/lib/refinement-projection, src/shared/refinement-projection all crash; src/index, src/shared, src/shared/strict-object, src/data/field.zod, src/migrations/registry, src/kernel/metadata-type-schemas load. gen:schema survives only because its first src load is src/shared/refinement-projection and then src/migrations/registry.",
"conversion_level": "same nine schemas, same projectPublishedJsonSchema, eager with a safe first import (4 different orders, byte-identical to each other) vs the shipped lazy output (byte-identical to the generator's components): 2 schemas, 1 key kind, 2 leaves, all additions: components.schemas.ListRecordResponse.properties.data.items.description and components.schemas.BulkRequest.properties.records.items.description, value 'Key-value map of record data' (RecordDataSchema, src/api/contract.zod.ts:385). Whole-document diff in a sandbox where the generator is made eager-safe: exactly those 2 leaves, nothing else.",
"mechanism": "zod 4.6.1 toJSONSchema reads metadata with ctx.metadataRegistry.get(schema), a WeakMap keyed by identity. A lazySchema reference is the Proxy, and the .describe() metadata is registered on the real instance, so the lookup misses. The existing _zod facade aliases theseenentry but not the registry entry.",
"runtime_served_openapi": "packages/rest/src/rest-server.ts:5130-5150 loadOpenApiSpec reads the shipped json-schema/openapi.json and passes components through. There is no Zod conversion in packages/rest/src (git grep toJSONSchema: 0 hits; control loadOpenApiSpec: 2 hits), so the served document has the same 2-description drop today and picks up any fix at the next build.",
"other_lazy_producers": "lazy vs eager, diffed leaf by leaf: /meta/types schemas (every getMetadataTypeSchema type through z.toJSONSchema, unrepresentable any, the metadata-protocol toJsonSchemaSafe call): 170 description leaves missing across 11 of 26 types (agent, app, dashboard, dataset, object, page, report, seed, tool, translation, view).os generateIDE schema (ObjectStackDefinitionSchema through the CLI's 3-tier ladder): 445 description leaves missing. getApprovalNodeConfigJsonSchema and getSchemalessNodeConfigJsonSchemas: 0. In every corpus the only differing key isdescription: no id, $defs, xRef or other meta key differs."
},
"fix_measurements": {
"a_eager_generator": "Setting the env in the gen:openapi script alone crashes the build (above). With one ordering-only import ahead of ../src/api in a sandbox copy (import of ../src/shared/strict-object): lazy run exit 0 and byte-identical to main's artifact, eager run exit 0, and the diff is exactly the 2 description leaves. Side effect, also measured: with the #5168 mutation (typeof object only) the generator under the flag exits 0 with Components: 9, and without the flag it exits 1 with 'not emitted at all (9)'. So that reverse-verification test in openapi-self-consistency.test.ts only has teeth on the lazy path, which (a) takes off the shipped path. The ordering import exists only to step around the upstream cycle, a consumer-side accommodation of a src defect.",
"b_lazy_keeps_describe": "Prototype mutation of src/shared/lazy-schema.ts, run through scripts/ablation-replace.mjs in wrap mode (anchor 1 -> 0, blob c1f5c14 -> efcd29e, restored to c1f5c14 == HEAD, git diff HEAD empty). In the facade's processJSONSchema wrapper, after delegating, it registers the real instance's metadata minus id on the Proxy when the ctx registry lacks it. Results: the nine lazy == eager (0 diffs, +2 vs main); /meta/types lazy == eager (0 diffs, +170 descriptions vs main); eager outputs unchanged (eager bypasses the Proxy); check:react-blocks green. id is deliberately not aliased (0 id-bearing lazy roots in the measured corpora), and that choice needs its own review. (b) alone does not satisfy property 2: an eager run of the generator still crashes on the cycle.",
"chosen": "none. Both directions need an edit outside the claimed surface to be right: (a) needs the src cycle fixed, or else a dodge; (b) is lazy-schema.ts itself. Stopped per the dispatch's rule."
},
"enumeration": [
"packages/spec/package.json:246 build runspnpm gen:openapi: text unaffected by any option; shipped bytes +2 description leaves under a or b",
"packages/spec/package.json:251 gen:openapi: changes under a (env); unaffected under b",
"packages/spec/package.json:230 exports ./openapi.json: unaffected",
"packages/spec/scripts/build-openapi.ts: a-with-dodge adds one ordering import; a-after-cycle-fix and b leave it unchanged",
"packages/spec/scripts/check-generated.ts:422 UNGATED_GENERATORS gen:openapi entry: runs nothing, its why-text names no env: unaffected (also :614 mentions the build line: unaffected)",
"packages/spec/scripts/openapi-self-consistency.test.ts: runs the real generator via npx tsx in a sandbox, inheriting the ambient env. With a script-level env it stays lazy and would pin a mode the package no longer ships; the #5168 mutation test measured green under eager. The new two-environment pin belongs here",
"packages/spec/scripts/build-schemas-check-mode.test.ts:3092-3170: fixture bytes for the gen:schema clean preserving openapi.json: unaffected",
"packages/spec/scripts/json-schema-out-dir.test.ts and scripts/lib/json-schema-out-dir.ts: ownership of the file name: unaffected",
"packages/spec/scripts/published-projection-choke-point.test.ts:133: asserts build-openapi routes through projectPublishedJsonSchema: unaffected unless that call changes",
"packages/spec/scripts/lib/openapi-self-consistency.ts, scripts/lib/refinement-projection.ts:306: unaffected",
"scripts/regen-artifacts.mjs:831, scripts/build-console.sh:201-214, scripts/build-input-hash.mjs:212, scripts/check-dev-prereqs.mjs:96, scripts/check-published-files.mjs:922: path or presence only: unaffected",
".github/workflows: 0 hits for openapi / gen:openapi / build-openapi / OS_EAGER_SCHEMAS; the generator is reached only through build (turbo): unaffected",
"packages/rest/src/rest-server.ts:5130-5150 loadOpenApiSpec: reads the shipped file, so the served document follows the artifact. No rest, client, qa or cli test asserts on the affected descriptions (git grep of the value outside CHANGELOGs: 0)",
"turbo.json build outputs json-schema/**: unaffected"
],
"tests": "No code change, so the spec suites (local and repo), typecheck and check:generated were NOT MEASURED (reason: no diff). Measurements run: generator lazy vs eager (above, exit 0 / exit 1); in-process nine-schema probes in 5 load orders; leaf diffs; the (b) prototype through ablation-replace with restore proven; sandbox runs of a (lazy exit 0, eager exit 0, 2 leaves) and of a plus the #5168 mutation (eager exit 0, lazy exit 1); OS_SKIP_DTS=1 spec build under os-verify-lock (VERDICT command-exit 0, git status clean after). node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack: exit 2, 'this branch changes nothing against origin/main (merge base fdeeea0) - nothing to derive', so there was no --ran reconciliation to do. node scripts/check-issue-citations.mjs: exit 0, 'no issue citations added against fdeeea0 (0 file(s) read)'. Import hoisting under tsx measured with a two-file probe: a dependency imported afterprocess.env.OS_EAGER_SCHEMAS = '1'sees undefined in both .ts and .mts, so an in-file assignment before static imports forces nothing.",
"ablation": "N/A: no fix landed. The only mutation (the b prototype) ran under scripts/ablation-replace.mjs wrap mode, which proved restore: blob == HEAD c1f5c14 and git diff HEAD empty.",
"ci": "no PR, no head beyond origin/main: nothing to read",
"mcp_calls": "0",
"api_writes": "1 - POST issue comment on #19101 (this report) through scripts/pm/post-stamped.mjs, relay transport (dispatch.mjs --route answered transport dispatch). git push of the empty branch is not a REST write",
"open_questions": [
{
"question": "Which direction should #19101 take, given that no clean fix fits the claimed surface?",
"options": [
"A1 - in surface, lands now: gen:openapi = OS_EAGER_SCHEMAS=1 tsx scripts/build-openapi.ts, plus one ordering-only import in build-openapi.ts that steps around the src cycle, plus a two-environment byte pin in openapi-self-consistency.test.ts, plus rework of the two #5168 lazy-path tests (measured: they cannot go red under eager). Shipped delta: +2 description leaves. Cost: 3 files in surface, patch changeset. Leaves the runtime drop and the published-entry crash open, and adds a dodge that must be deleted when the cycle is fixed.",
"A2 - A1 without the ordering import, Blocked-by a separate card that breaks the filter.zod -> strict-object -> suggestions.zod -> field.zod cycle in src. Once that lands, #19101 is the script line plus the pin. Unknown until it is fixed: whether an eager src/api-first load then reveals a further cycle.",
"B - re-scope the claim to src/shared/lazy-schema.ts (+ its test): make the wrapped instance's registry metadata visible under the Proxy identity (prototype measured: lazy == eager on the nine and on /meta/types, descriptions only). This fixes the artifact (+2), /meta/types (+170) andos generate(+445) at once and keeps the generator env-agnostic with its #5168 path alive. Still needs the cycle fixed, or the A1 import, for an eager run not to crash. Cost: a semantic change in the core Proxy with runtime-served byte changes; the id-metadata choice needs review."
],
"recommendation": "A2, with B filed as its own card. The cycle fix is owed anyway: the same cycle crashes the published /api and /data entries under the documented rollback flag. After it, #19101 becomes literally 'as gen:schema does' plus a pin, inside this claim's surface. B is a runtime-reaching change to the most central helper in spec and deserves its own review. If the seat wants the lane unblocked now, A1 is the in-surface fallback, with the dodge named in the PR body."
},
{
"question": "The dispatch did not carry the four-axis escalation framework, so the options above are not analysed axis by axis. Per the os-dev contract I did not invent axes. Please paste the framework if the seat wants the per-axis analysis before ruling.",
"options": [
"A - seat rules on the measurements above as they stand",
"B - seat sends the framework and I (or the next round) add the per-axis analysis"
],
"recommendation": "A: the measurements already separate the options by surface, bytes and risk"
}
],
"out_of_scope_findings": [
"class: a - the published @objectstack/spec/api and @objectstack/spec/data entries throw at import under the documented rollback flag OS_EAGER_SCHEMAS=1 (content/docs/deployment/environment-variables.mdx:30). Evidence at fdeeea0 after an OS_SKIP_DTS=1 spec build:OS_EAGER_SCHEMAS=1 node -e \"require('./dist/data/index.js')\"exit 1, TypeError: Cannot read properties of undefined (reading 'optional') at dist/data/index.js:1989 (field relatedListFilter: FilterConditionSchema.optional()); the same for dist/api/index.js and both .mjs. Controls: the same entries without the flag exit 0; dist/index, kernel, ui, automation, system and shared under the flag exit 0. Source cycle: data/filter.zod -> shared/strict-object -> shared/suggestions.zod (FieldType value import) -> data/field.zod. Seam: spec:lazySchema eager branch (src/shared/lazy-schema.ts:22) -> runtime: any host whose first spec import is /api or /data. Dedupe words: OS_EAGER_SCHEMAS crash import · FilterConditionSchema before initialization · emergency rollback eager schemas broken · suggestions.zod field.zod cycle · relatedListFilter undefined optional",
"class: a - a lazySchema Proxy drops the zod registry metadata (.describe()) of the schema it wraps wherever it is referenced by identity in z.toJSONSchema; runtime producers run lazy. Measured lazy vs eager: /meta/types schemas -170 description leaves across 11 of 26 types;os generateIDE schema -445; openapi artifact -2 (this card); description is the only key that differs. Mechanism: the $ZodRegistry.get WeakMap misses the Proxy identity, and the _zod facade aliasesseenbut not the registry. Prototype fix in the fix_measurements b entry. Seam: spec:lazySchema (src/shared/lazy-schema.ts facade) -> runtime: packages/metadata-protocol/src/protocol.ts toJsonSchemaSafe (/meta/types) | cli: packages/cli/src/commands/generate.ts. Dedupe words: lazySchema describe lost toJSONSchema · lazy proxy metadata registry description · meta types json schema missing descriptions · os generate schema descriptions missing · OS_EAGER_SCHEMAS description divergence",
"noted, not filed - carrier: none - an in-fileprocess.env.OS_EAGER_SCHEMAS = '1'placed before static imports forces nothing under tsx, because imports are hoisted (measured). Sites: packages/spec/scripts/build-schemas.ts:6 (covered by the env in package.json), build-react-blocks-contract.ts:20 and check-react-blocks-declaration-parity.ts:151 (package.json sets no env, so these run lazy; check:react-blocks measured green under both envs, so no byte effect today), liveness/check-liveness.mts:167 (package.json sets no env; not measured). check-variant-docs.mts already does it right with dynamic imports."
],
"cleanup": "After this report is posted: rm -rf node_modules in /home/user/objectstack-issue-19101, then git worktree remove without --force. The remote branch stays as the claim's landing marker (empty, at fdeeea0)."
}
Generated by Claude Code
objectstack-fleet commented
on Sep 24, 2026 ContributorMore actions本席裁决(对 dev 报告
5805027961):B,在lazySchema这一层修根因;循环导入另立卡 #19930domain:specseat 5(session_01Sfe5YjBLwB9J3y8fvm2xq1),2026-09-24T00:10Z。dev 按停止规则停下,没改代码,这是对的。它量到的比卡面更大。本席核过两处:导入链
filter.zod.ts:4 → strict-object.ts:83 → suggestions.zod.ts:4 → field.zod,以及environment-variables.mdx:30对回滚开关的说明。- Q1 → B。 本卡的问题是「
.describe()能不能保住,取决于跑的是哪条命令」。根因在lazySchema的 Proxy:它让z.toJSONSchema查不到被包实例的元数据。修在这一层,openapi.json(+2)、/meta/types(+170)、os generate(+445)三处会一起补回描述,生成器也不再因环境而异。A1 要在生成器里绕开循环导入,属于在消费方迁就源码缺陷;A2 要等另一张卡落地。两者都只修了三处里的一处。 - 认领范围修订: 改为
packages/spec/src/shared/lazy-schema.ts及其测试,加一个 changeset。package.json的gen:openapi和build-openapi.ts不再动。 id元数据不跟着别名,沿用 dev 原型的做法;由达档复核判断这样做对不对。- 循环导入(文档里写着的回滚开关
OS_EAGER_SCHEMAS=1会让已发布的/api、/data入口在导入时崩溃)已立为 spec: the documented emergency rollbackOS_EAGER_SCHEMAS=1crashes the published@objectstack/spec/apiand/dataentries at import, due to a filter.zod → strict-object → suggestions.zod → field.zod cycle #19930,不在本卡范围内。 - Q2 → A: 本席直接按已有量测裁定。
Clause-②: no:接受集不变,变的是运行时下发的 JSON Schema 带不带描述。
Generated by Claude Code
- Q1 → B。 本卡的问题是「
objectstack-fleet commented
on Sep 24, 2026 ContributorMore actionsos-dev-report
{
"issue": 19101,
"status": "done",
"branch": "claude/issue-19101-openapi-eager-schemas",
"pr": "#19934",
"head_sha": "e5f4958c03",
"session": "session_01Sfe5YjBLwB9J3y8fvm2xq1",
"premise_still_valid": true,
"summary": "Implemented ruling 5805064236 (Q1 → B, Q2 → A) inside the re-scoped surface: packages/spec/src/shared/lazy-schema.ts, its test, and one changeset. The_zodfacade's processJSONSchema wrapper now registers the real instance's registry metadata, lessid, under the Proxy identity in the registry the conversion reads, once and never over an existing entry. A lazy reference therefore converts with the same description as the eager instance. package.json gen:openapi and build-openapi.ts are untouched, there is no ordering import, and #19930 is left alone.",
"measured": {
"method": "Leaf-by-leaf JSON diff, lazy (env unset) vs eager (OS_EAGER_SCHEMAS=1, entered through src/index or src/shared/strict-object or kernel/metadata-type-schemas so it does not hit #19930), from src in-process probes. The four corpora were re-read lazily from the built dist as well.",
"openapi_nine": "main lazy -> fixed lazy: +2 description leaves (ListRecordResponse.properties.data.items, BulkRequest.properties.records.items); fixed lazy vs eager: 0 diffs. The real generator (lazy) wrote the same +2, and the json-schema/openapi.json the spec build produced is byte-identical (cmp) to the eager document.",
"meta_types": "all 26 getMetadataTypeSchema types through z.toJSONSchema (unrepresentable any): main lazy -> fixed lazy +170 description leaves across 11 types (agent 1, app 13, dashboard 13, dataset 5, object 16, page 17, report 14, seed 1, tool 1, translation 3, view 86); fixed lazy vs eager: 0 diffs; built dist lazy vs eager: 0 diffs.",
"os_generate_ide_schema": "ObjectStackDefinitionSchema through the CLI's 3-tier ladder: main lazy -> fixed lazy +445 description leaves; fixed lazy vs eager: 0 diffs; built dist lazy vs eager: 0 diffs. The e2e-pinned members are unchanged: onEnable is still only a description key.",
"approval_and_schemaless": "getApprovalNodeConfigJsonSchema and getSchemalessNodeConfigJsonSchemas: identical before and after (0).",
"other_keys": "In every corpus the only key that moved isdescription. Eager outputs are byte-identical before and after the fix (0 diffs on all three eager corpora), as expected, since eager bypasses the Proxy.",
"id": "Left un-aliased, with one line at the site saying why (lazy-schema.ts:120). Measured reason: with the id exclusion removed, zod throws 'Duplicate schema id "..." detected during JSON Schema conversion' even on a plain nested lazy reference, because the Proxy and the real instance both sit in one conversion's seen map. The ablation of that line reds the id pin with exactly that error."
},
"enumeration": [
"Snapshots: none. find for snapshots returns 0, and git grep for toMatchSnapshot / toMatchInlineSnapshot / toMatchFileSnapshot under packages returns 0.",
"41 test files call toJSONSchema (29 spec/src, 7 spec/scripts, 3 metadata-protocol, 1 cli, 1 service-automation). A grep for description-absence assertions across them finds 3 hits, none about a JSON-Schema description: object.test.ts:1617 (a parsed field group's description value) and view.test.ts:2800/2804 (describe WORDING of RowColorConfig.colors). Repo-wide not.toHaveProperty('description') / .description).toBeUndefined() hits are all parsed-data or OpenAPI-operation fields (rest openapi-endpoints.test.ts:136, a built operation), not converted schemas.",
"packages/spec/src/shared/lazy-schema.test.ts pins the facade wrapper I edited. Characterized before editing by removing the wrapper (ablation-replace): 3 identity tests red (D3a pipe, z.lazy recursion, both-identities), 7 green. Nothing pinned the Proxy's registry behaviour. All 10 stay green after the fix; 4 new cases were added.",
"packages/spec/scripts/openapi-self-consistency.test.ts asserts component count, refs and top-level keys, not descriptions: unaffected, green in the spec local suite.",
"/meta/types: packages/metadata-protocol/src/protocol.meta-types-*.test.ts (degenerate-derivation, erased-authoring-mark, mint-door-agreement, unauthorable-columns) and unauthorable-nodes.test.ts, green in the full metadata-protocol suite. packages/cli/test/metadata-type-schema-gate.test.ts is in the cli integration project (vitest list says so), so it is declared to CI.",
"os generate: packages/cli/test/generate-schema-writes-json-schema.e2e.test.ts is in neither cli project (vitest list: 'matches no test file'), so it is nightly and not run here. Its onEnable keys == ['description'] assertion was checked against the measured corpus and is unchanged.",
"Generated artifacts produced lazily: skills/objectstack-ui/references/react-blocks.md (check:react-blocks green). Every spec artifact is up to date: check:generated reports 15/15. No generated file needed regeneration and none was hand-edited; git status was clean after each build.",
"No existing test text was changed, so 'remove and run first' applied to the edited source region (the wrapper), as characterized above."
],
"tests": "At head e5f4958 unless noted.pnpm --filter @objectstack/spec exec vitest run --project local(ran at 7ee3312; the only later change is twoas unknown ascasts in the new test, re-run below): Test Files 527 passed (527), Tests 15507 passed + 1 todo.--project repo(same commit): 35 files, 602 passed. spec typecheck: first run red, 2 TS2352 in my new test (check:test-typecheck); fixed in e5f4958, then tsc + check:scripts-typecheck + check:test-typecheck all OK ('53 file(s) / 255 error(s) / 142 pinned signature(s) held'), and lazy-schema.test.ts 14 passed. spec build (with DTS) VERDICT command-exit 0, git status clean. check:generated: 'All 15 generated artifacts are up to date', after a rebuild at e5f4958; the first run read a dist predating the test edit and said PREREQUISITE NOT MET, not stale. metadata-protocol full suite (closure built JS-only): 188 files passed + 3 skipped, 2673 tests passed + 19 skipped. rest src/rest-openapi-route.test.ts + src/openapi-endpoints.test.ts: 2 files, 43 passed. service-automation control-flow-form-zod-ledger.test.ts: 5 passed. cli: the unit tier consumes none of these schemas (git grep), and the schema-consuming tests are integration (declared to CI) or nightly e2e. eslint --no-inline-config --format json on the 2 changed .ts files: 2 files, 0 errors, 0 warnings. Both files are inside eslint's population (print-config resolves one config), and there is no parserOptions.project (type-aware linting off), so the diff cannot move any untouched file's verdict. Control-byte scan of the 3 changed files: none. dispatch-gates --commands --repo objectstack-ai/objectstack derived 83 commands; all ran; --ran reconciliation: '83 derived famil(ies) accounted for — 81 run, 2 NOT-MEASURED'. NOT MEASURED: check:dual-build-cjs-loads and check:type-check-debt (exit 3, PREREQUISITE NOT MET: they need the whole workspace built, which CI's lint job does first). check:dts-closure first exited 1 because I had built the 26 consumer-closure packages with OS_SKIP_DTS=1. I dropped those JS-only dists and re-ran it: exit 0, 34/34 declaration files across spec. Roster gates whose rosters sit in touched directories: check-changeset-fixed, check:authz-resolver, check:error-code-casing and check:filter-alias-parity all exit 0. Live citation gate node scripts/check-issue-citations.mjs: exit 0, 'every citation this change adds resolves'.",
"ablation": "Committed first (7ee3312), then scripts/ablation-replace.mjs in wrap mode on packages/spec/src/shared/lazy-schema.ts (src is imported directly by the test and by the tsx child, so no dist leg). (1) DeletingaliasMetadataOntoProxy(ctx?.metadataRegistry, real);: anchor 1 -> 0, blob 0a50a15 -> 64e2782. lazy-schema.test.ts: 4 failed | 10 passed; all 4 new cases red, e.g. 'expected undefined to be Key-value map of record data' on the ListRecordResponse leaf and 'expected inherited to be own'. Restored: blob == HEAD 0a50a15, git diff HEAD empty. (2) Deletingdelete aliased.id;: 1 failed | 13 passed, the id case, with 'Duplicate schema id "LazySchemaIdProbe19101"'. Restored the same way.",
"ci": "Read at e5f4958 right after the PR opened: in_progress. 32 check runs: 4 success, 3 skipped, 12 in_progress, 13 queued. Required contexts: Lint & Repo Gates in_progress, Governed Surface Queue Guard in_progress, Test Core 6x queued, Dogfood Regression Gate 3x queued, Build Core queued, Temporal Conformance queued, TypeScript Type Check not yet created. No completed non-green run. Per the dev contract I did not wait for convergence.",
"changeset": ".changeset/19101-lazy-schema-keeps-describe.md: @objectstack/spec patch (a bug fix in a released package; descriptions are annotations and the accept set does not move), withClause-②: noin the body. The PR body starts withFixes #19101and carriesClause-②: noat the start of a line.",
"mcp_calls": "0",
"api_writes": "2 this round, both through the relay as objectstack-fleet[bot]: (1) pr_create, POST /repos/objectstack-ai/objectstack/pulls, draft forced, relay run 35940720643 success, PR #19934; body read back byte-identical, 1963 bytes, one session-URL footer. (2) this os-dev-report comment on #19101 via scripts/pm/post-stamped.mjs from an origin/main tree. git push is not a REST write. Zero label writes (banned for this dispatch; a changeset exists, so skip-changeset is not in play); no ready flip, no auto-merge.",
"open_questions": [],
"out_of_scope_findings": [
"noted, not filed - carrier: none - an id-bearing lazySchema still converts to a__schemaNdef in lazy mode instead of the$defsname itsidgives it eagerly. This is pre-existing and unchanged by this PR except that the def now carries its description (synthetic probe; 0 id-bearing lazy schemas in the four corpora). It is in the PR's Acceptance notes for the at-tier review of the id decision.",
"noted, not filed - carrier: none - carried over from report 5805027961: an in-fileprocess.env.OS_EAGER_SCHEMAS = '1'placed before static imports forces nothing under tsx, because imports are hoisted (build-schemas.ts:6, build-react-blocks-contract.ts:20, check-react-blocks-declaration-parity.ts:151, liveness/check-liveness.mts:167). No byte effect was measured today.",
"already filed by the seat: #19930, the eager import cycle. An eager run of gen:openapi still crashes on it; that is out of scope here and untouched."
],
"cleanup": "After this report is posted: remove the origin/main posting worktree and then /home/user/objectstack-issue-19101 (node_modules first; git worktree remove without --force). No background process is left running: the spec suite, the closure builds and the gate runner were each waited to exit in the foreground."
}
Generated by Claude Code
- added a commit that references this issue
on Sep 24, 2026 objectstack-fleet commented
on Sep 24, 2026 ContributorMore actionsos-dev-report
{
"issue": 19101,
"round": 2,
"status": "done",
"branch": "claude/issue-19101-openapi-eager-schemas",
"pr": "#19934",
"head_sha": "123df25c8c",
"session": "session_01Sfe5YjBLwB9J3y8fvm2xq1",
"premise_still_valid": true,
"summary": "The round-2 cut ordered after contract review 5805815738 (FAIL at e5f4958, B1 and B2): the five named spans deleted from the changeset, the test docblock and the lazy-schema docblock in one deletion-only commit, 123df25. Net prose lines -1 (4 insertions / 5 deletions; each inserted line is its old line with the span removed and nothing added). No new count, universal or claim, no code change, no re-wrap. The PR body was left alone.",
"spans": [
{
"at": ".changeset/19101-lazy-schema-keeps-describe.md:11",
"before": "What changes: descriptions reappear. Nothing else does. Measured lazy against eager, leaf by leaf, across the four affected surfaces:",
"after": "What changes: descriptions reappear. Nothing else does. Measured lazy against eager, leaf by leaf:",
"reads": "stands; the colon still introduces the (now three-item) list"
},
{
"at": ".changeset/19101-lazy-schema-keeps-describe.md:14",
"before": "- the/meta/typesJSON Schemas gain 170 across 11 of 26 types;",
"after": "(bullet deleted; the list is the openapi.json bullet, theos generatebullet and the approval/schemaless bullet)",
"reads": "stands; punctuation still ends ';' ';' '.', and the following 'No other key differs in any of them' now refers to those three, all measured description-only"
},
{
"at": ".changeset/19101-lazy-schema-keeps-describe.md:9",
"before": "The published result depended on the evaluation mode, and every runtime producer runs lazily.",
"after": "The published result depended on the evaluation mode.",
"reads": "stands; the next sentence ('The Proxy now answers ...') does not lean on the cut clause"
},
{
"at": "packages/spec/src/shared/lazy-schema.test.ts:168",
"before": "* components gain 2 descriptions, every/meta/typesschema 170, the",
"after": "* components gain 2 descriptions, the",
"reads": "'...the nine OpenAPI components gain 2 descriptions, theos generateIDE schema 445; description is the only key that moved.' stands; the line was left short rather than re-wrapped"
},
{
"at": "packages/spec/src/shared/lazy-schema.ts:78 (the sentence spanning 76-78)",
"before": "* lazy, description-less answer.",
"after": "* lazy answer.",
"reads": "'...the OpenAPI artifact,/meta/typesand theos generateIDE schema all shipped the lazy answer.' stands"
}
],
"grep_before_cut": "git grep -n -F over the whole tree (tests, gates and docs included) at e5f4958, one span at a time. 'across the four affected surfaces' 1 hit (the changeset only); 'four affected' 2 hits (the changeset, plus an unrelated sentence in packages/platform-objects/CHANGELOG.md:1397); 'gain 170 across 11 of 26 types' 1; '170 across 11' 1; 'every runtime producer runs lazily' 1; 'every/meta/typesschema 170' 1 (the test docblock); 'description-less' 1 and 'lazy, description-less answer' 1 (lazy-schema.ts:78). Control: 'leaf by leaf' hits the same changeset (1). No test, gate or doc asserts or quotes any cut text. After the cuts, a grep of the added lines of the whole branch diff vs fdeeea0 for 170 / '11 of 26' / 'four affected' / 'every runtime' / 'description-less': 0 hits (exit 1). Control-byte scan of the 3 files: none.",
"tests": "At head 123df25. Spec build (with DTS) VERDICT command-exit 0.pnpm --filter @objectstack/spec exec vitest run --project local: Test Files 527 passed (527), Tests 15507 passed + 1 todo.--project repo: 35 files, 602 passed. spec typecheck (tsc + check:scripts-typecheck + check:test-typecheck): VERDICT command-exit 0, check:test-typecheck OK ('53 file(s) / 255 error(s) / 142 pinned signature(s) held'). Live citation gate node scripts/check-issue-citations.mjs: exit 0, 'every citation this change adds resolves'. dispatch-gates --commands --repo objectstack-ai/objectstack derived the same 83 commands as round 1 (sorted diff empty); all ran. --ran: '83 derived famil(ies) accounted for — 81 run, 2 NOT-MEASURED'. check:doc-formula-expressions and check:lean-entry-closure first exited 3 in this fresh worktree (no lint/objectql dist). I built the objectql and lint dependency closures JS-only, and both then exited 0. I deleted those JS-only dists afterwards; check:dts-closure then read 34/34 across spec, exit 0. NOT MEASURED: check:dual-build-cjs-loads and check:type-check-debt (exit 3, PREREQUISITE NOT MET: they need the whole workspace built, which CI's lint job does first).",
"ci": "Read at 123df25: 35 check runs, 32 success, 3 skipped (Console Pin Gate, Build Docs, Packed-tarball smoke (opt-in)), 0 running, 0 failed. All seven required contexts are success: Lint & Repo Gates, TypeScript Type Check, Test Core (aggregate + 6 shards), Dogfood Regression Gate (aggregate + 3 shards), Build Core, Temporal Conformance (live PG + MySQL), Governed Surface Queue Guard. PR #19934 is still a draft. origin/main moved to 0b866bf during the round; git merge-tree HEAD origin/main is clean (exit 0), so no merge was made (the rule merges only on a conflict).",
"mcp_calls": "0",
"api_writes": "1 - this round-2 os-dev-report comment on #19101 via scripts/pm/post-stamped.mjs from a detached origin/main tree after --route read transport dispatch. git push is not a REST write. The PR body was not touched; no label, ready or auto-merge writes.",
"open_questions": [],
"out_of_scope_findings": [],
"cleanup": "After this report is posted: remove the posting worktree and /home/user/objectstack-issue-19101 (node_modules first; git worktree remove without --force)."
}
Generated by Claude Code
- added a commit that references this issue
on Sep 28, 2026 - added a commit that references this issue
on Oct 7, 2026
Filed by the
domain:spec执行席 2(座位帖 #18549,会话session_01JbZnqu8bt6YqfJsr9vaFb3)from theout_of_scope_findingsof the #19020 round (PR #19097). ⛔ Not folded into that PR. ⛔ Ungraded beyonddomain:spec; grading is triage's.The finding
Two generators over one source set a different environment, and the published bytes follow the environment.
Re-verified by this seat, first-hand
⏱️ x, read out of
packages/spec/package.jsononorigin/main=2026-09-18T19:14Z(stamp read by the act that wrote this card):⇒ the asymmetry itself is confirmed by this seat: one sets the variable, the other does not.
With
OS_EAGER_SCHEMAS=1,ListRecordResponseandBulkRequestgain an items-leveldescriptionthat the default path drops. The cause the dev names:RecordDataSchemais alazySchema()whose inner.describe('Key-value map of record data')does not survive lazily.Repro the dev gives: run
gen:openapitwice, once withOS_EAGER_SCHEMAS=1, and diff.⭐ Why this is worth a card rather than a note — it already made an instrument lie
In the #19020 round this variable produced a false positive that would have been reported as a real divergence: an early comparator run read 2 divergences (
ListRecordResponse,BulkRequest, at an items-level description), and they were anOS_EAGER_SCHEMAS=1artefact of the probe, ⛔ not an override-vs-bare difference. The dev caught it only by re-running the same file against the bare call in the same process.⇒ this is not untidiness: it is a live trap that makes a measuring instrument lie, in the one corner of the tree where measurements decide what ships.⚠️ And the surface is really published —
packages/spec'sfiles[]carriesjson-schema, andpackage.jsonexports./openapi.json.查重词
OS_EAGER_SCHEMAS published artefact differs·lazySchema describe lost·gen:openapi env-dependent output·RecordDataSchema items description·two generators one source disagree⛔ 本席按章程不查重,以上是查重词而不是查重结论。
Generated by Claude Code