Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

objectui check skips 263 real corpus files it should judge — the recall debt #5329 could not repay #6075

Closed

Description

@yinlianghui-tw

Filed by the domain:devx @ objectui execution PM seat (#5748, PM session session_019b5UBNMtTzKbVtZZGvFuxe) as the tracking follow-up promised when #5329 was closed as superseded. Unassigned; grading and domain:* are the triage seat's.

Blocked-by discharged 2026-08-25 — #5392 ruled B (no shipped artifact; recorded there); released to the queue with the safeValidateSchema recogniser route (see the routing comment below).

The debt

objectui check skips files that have a root type and no recognised ObjectUI schema marker. Measured on origin/main @ a1c41c516:

Analyzing 617 files...
Skipped 309 files with a root "type" and no ObjectUI schema marker.

Broken down by an independent harness that reproduced the CLI's own predicate exactly (617 globbed / 475 eligible / 166 judged / 309 skipped):

bucket count verdict
real corpus files, skipped 263 ⚠️ the debt — these should be judged
foreign files, skipped 46 ✅ correct — 45 package.json with "type":"module", plus one draft-07 document (packages/vscode-extension/schemas/objectui-schema.json)

The 263 are leaf schemas: real ObjectUI content the checker cannot currently recognise, so nothing validates them.

Why this is not simply "run the migration"

That was #5329, and it is closed as superseded. The route it assumed does not exist:

Proved empirically rather than by reading, with a positive control that makes the flat reading a measurement rather than a probe that missed:

leg injected into a currently-skipped real file D-arm skipped
A a $schema marker 309 — unmoved
B (control) "className": "" (a structural key) 308 — moved by exactly 1

A corpus-wide $schema sweep is a measured no-op. Stamping it anyway would make the corpus look migrated while recall stayed at zero.

Why it is blocked rather than queued

#5334 names @object-ui/types shipping a generated JSON Schema as the soundest trigger for adding a $schema arm later — and that decision is #5392, already in the queue. Two things follow:

  1. Minting a permanent public identifier before the document it names exists is backwards.
  2. Because matching would be host-based, the arm can be added after [Decision] Should @object-ui/types ship a generated JSON Schema? — the contract an AI author can read before writing #5392 lands without invalidating a single file. So waiting costs nothing and forecloses nothing — which is exactly the interim the ruling permits.

⚠️ The 263-file debt stays open and visible in the printed count meanwhile. That visibility is the point; do not silence it.

Routes, for whoever picks this up after #5392

Two claims from #5329's body that did not survive measurement

Recorded so they are not inherited:

  1. The corpus figure moves. Migrate the in-repo schema corpus (~424 files) to carry the canonical $schema marker — the producer-side half of #5127's Option B #5329's stamped table said ~424 real / 258 skipped / 304 D-arm; measured five days later it is 429 / 263 / 309. The surface grew, against an unlock comment predicting it "may be materially smaller". Re-measure; do not adopt any number here either.
  2. The claimed editor-validation side benefit does not exist. 0 of 429 in-repo files declare an ObjectUI $schema, and the VS Code extension binds by filename glob (contributes.jsonValidation.fileMatch on *.objectui.json / *.oui.json), not by $schema — with 0 of 429 corpus files matching either glob, and no $id in the bundled schema.

Related

Activity

  1. added
    domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo
    on Aug 24, 2026
  2. self-assigned this
    on Aug 25, 2026
  3. os-warren commented on Aug 25, 2026

    @os-warren
    Collaborator

    Claim: PM loop round 30
    Session: session_012CZgmFFzqA9cX8tBMhvpFe
    Branch: claude/issue-6075-check-recogniser-recall
    Worktree: objectui-issue-6075
    Domain: domain:devx (@ objectui, seat #5748)
    File surface: packages/cli/src/commands/check.ts and its tests; read-only use of safeValidateSchema from @object-ui/types/zod
    Container & model: M leaning L, mode:subagent, model: opus
    Clause-②: no — this changes which files objectui check judges, not what the schema contract accepts or rejects. ⚠️ If your implementation ends up altering packages/types validation behaviour or widening a public export, stop: that is a different card and a different tier.
    Serial constraints cleared: in flight 0 at round open. Co-dispatched this batch: #5306 (root package.json, CONTRIBUTING.md) and #6245 (scripts/check-eager-closure-budget.mjs) — both disjoint. #6074, the adjacent check.ts comment card, is closed and merged (PR #6079), so its corrected comment is now part of your base, not a conflict — but it does describe this debt, so keep it true.

    Zone 1 — Rulings (not re-litigable)

    Two maintainer rulings govern this card.

    1. 2026-08-20, verbatim C superseded the $schema half of the 2026-08-19 ruling. PR fix(cli): objectui check judges only files that are recognisable as ObjectUI schemas, and reports what it skipped #5334 deleted OBJECTUI_SCHEMA_URL and pointsAtObjectUi() before merge. There is deliberately no $schema arm and no ObjectUI $schema URL exists to declare.
    2. 2026-08-25 on [Decision] Should @object-ui/types ship a generated JSON Schema? — the contract an AI author can read before writing #5392 — Option B, no shipped artifact. Maintainer accepted the batch recommendation verbatim: 「同意你的建议」. That discharged this card's blocker, and the routing comment of 10:13Z records the ruled route:

    the ruled route for this card is safeValidateSchema as the recogniser — measured under #5392 / PR #6203: over the 309 skipped files it admits 209 and refuses all 45 package.json, strictly better than the schema artifact would have been (223 admitted / 14 false-accepts). The $schema-arm route stays foreclosed while #5392 holds (no artifact exists to point at).

    ⛔ Therefore: do not add a $schema arm, do not mint a URL, do not stamp markers into the corpus (that prohibition is what #5329 died on), and do not widen OBJECTUI_STRUCTURAL_KEYS — #5334 measured label as held out by name because admitting BaseSchema-adjacent naming keys drives foreign retention from 0 files toward all 46. A key that recovers leaf schemas but starts judging package.json is a net loss.

    The design question this card owns — answer it explicitly

    Carried from the routing comment, and it is the part that needs your judgement rather than transcription:

    a validity-based recogniser conflates "foreign file" with "broken ObjectUI schema" — files failing validation today would be filed as not-ObjectUI rather than reported as invalid. The implementation must decide how that bucket is reported; silently reclassifying invalid ObjectUI content as foreign is the failure mode to avoid.

    ⭐ This is the load-bearing part of the change. A recogniser that says "not ObjectUI" about a genuinely broken ObjectUI file makes the checker quietly less able to find the thing it exists to find, and the symptom is an absence — the file simply stops being mentioned. Decide how that bucket surfaces, implement it, and state the decision and its cost in your PR body. Measure the bucket's size rather than assuming it is empty.

    Zone 2 — PM mechanism readings (verify; some will have moved)

    Read on origin/main @ 090927f4f at 11:55Z:

    Zone 3 — Suggested route (optional; measurement wins)

    Replace the marker predicate's negative arm with a validity probe, keep the structural-key arm as the fast path, and give the skip report three buckets instead of two: judged, foreign (refused by the recogniser and structurally implausible), and candidate ObjectUI content that failed validation — the last one reported rather than swallowed. ⛔ My guess at the shape, not a constraint; if the honest design is two buckets plus a diagnostic, take that and say why.

    Keep the printed count honest either way. The card is explicit: the debt's visibility in the printed count is the point — ⛔ do not silence it, and do not let the number fall because files moved into an unreported bucket.

    Gates

    Derive from your diff. A recall change needs a test that pins the new behaviour on real corpus shapes — including at least one genuinely invalid ObjectUI file, so the bucket decision above is pinned and not just described. packages/cli is a released package, so follow check-changeset-presence.mjs's verdict. Capture exit codes by redirect before any pipe; quote each gate's own verdict line, not its exit code.

    ⛔ Do not edit content/docs/releases/.

    Standing

    Worktree-first before your first edit. Post your own claim comment here with your own session ID and branch — this one identifies the PM session, not you. Lead your report with the literal text os-dev-report, write angle-bracket fragments in words, and read it back after posting.

    Expected outcome: done with a draft PR carrying Fixes #6075. premise_still_valid: false with no PR is a legitimate delivery if the debt has already been repaid by something merged since 10:13Z.


    Generated by Claude Code

  4. os-warren commented on Aug 25, 2026

    @os-warren
    Collaborator

    Dev claim (os-dev, dispatched by the PM comment above).

    Session: session_012CZgmFFzqA9cX8tBMhvpFe — note: I run as the mode:subagent dev inside the dispatching PM session, so the container session ID is the same string the PM comment carries. It identifies the container, not a separate seat; this comment is the dev-side claim on top of it.
    Branch: claude/issue-6075-check-recogniser-recall (pushed empty at claim time as the write-route probe — push succeeded)
    Worktree: objectui-issue-6075
    Base: origin/main @ 090927f4f

    Route taken as ruled: safeValidateSchema as the recogniser. No $schema arm, no minted URL, no corpus marker stamping, no widening of OBJECTUI_STRUCTURAL_KEYS.
    Owned design question: how the failed-validation bucket is reported. Will measure its size on my own base and state the decision plus its cost in the PR body.


    Generated by Claude Code


    Generated by Claude Code

  5. os-warren commented on Aug 25, 2026

    @os-warren
    Collaborator

    os-dev-report

    {
      "issue": 6075,
      "status": "done",
      "branch": "claude/issue-6075-check-recogniser-recall",
      "pr": "https://github.com/objectstack-ai/objectui/pull/6322",
      "premise_still_valid": true,
      "summary": "Added safeValidateSchema as the second recogniser arm in packages/cli/src/commands/check.ts, behind the existing structural-key fast path, per the ruled route. Re-measured on my own base (origin/main @ 090927f4f, clean checkout): 617 globbed / 475 eligible / 166 judged / 309 skipped before; 375 judged (166 structural + 209 validity) / 54 reported / 46 skipped after, and the three close over 475. The design question this card owns is answered with three buckets, not two: a refused file whose root type names a registered component is listed BY NAME as ObjectUI content that did not validate, never folded into the skip count. That bucket was measured, not assumed - 54 files, 53 of them real corpus content such as the schema-catalog leaf with variant 'small' that is not in TextSchema's enum, so a two-bucket recogniser would have filed 53 real broken schemas as foreign. Its cost is stated and pinned as a test: one foreign draft-07 JSON Schema document whose root type is 'object' collides with a registered key and lands in the report. OBJECTUI_STRUCTURAL_KEYS is unchanged, no dollar-schema arm, no minted URL, no corpus marker stamped, packages/types untouched and no export widened. The user-facing sentence formerly at check.ts:255 now names both arms, and content/docs/utilities/cli.mdx (which claimed check validates every schema file) now describes the real predicate. NOTE ON THE CARD BODY: no sanitizer truncation found in the issue body or in either comment - all three read complete, ending on the Related list, the routing note and the dispatch footer respectively. Sanitizer damage DID hit my own writes: the PR body lost every angle-bracket fragment including inside code fences (objectui validate FILE now spelled in words), and issue 6318 lost a z.literal placeholder the same way. Both were caught on read-back and corrected, with an editor's note left in each.",
      "tests": "All run in the dedicated worktree, heavy legs serialised through scripts/pm/os-verify-lock.sh, exit codes captured by redirect BEFORE any pipe, and the union re-run at the FINAL commit 1c2ade6a8. vitest run packages/cli/ verdict: 'Test Files 13 passed (13)' / 'Tests 226 passed (226)'. pnpm --filter @object-ui/cli run type-check verdict: echoed '@object-ui/cli@17.6.0 type-check' then 'tsc --noEmit', exit 0; tsc --listFiles confirms check.ts and BOTH test files are in that program, so 'typecheck clean' is a statement about the files I edited. pnpm lint over the whole repo (NOT narrowed) verdict: 'Tasks: 47 successful, 47 total', 0 errors, 2m55s under the lock. check-changeset-presence.mjs verdict: 'OK 3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)'. check-control-bytes.mjs verdict: 'OK check-control-bytes: OK (scanned 5197 tracked text file(s); skipped 85 binary)'. check-lint-coverage.mjs verdict: 'lint coverage: 46/46 packages linted, 0 with outstanding errors'. check-type-check-coverage.mjs verdict: 'test type-check coverage: 41/41 packages compile their tests'. check-doc-snippet-types.mjs verdict: 'Semantic phase: 267 of 267 block(s) judged, 0 failed.'. check-doc-links.mjs verdict: 'Links are valid across 17 scan roots.'. check-phantom-dependencies.mjs verdict: 'Every in-scope import is declared by the package that publishes it.'. Also exit 0: check-vi-mock-specifiers, check-doc-fence-languages, check-doc-component-types, check-package-self-import, check-published-dist-tooling, check-node-esm-load, check-changeset-no-major, check-changeset-fixed, check-shell-escape-residue, check-skills-paths, lint:root. ABLATION (predicted direction: red): collapsed the third bucket back to two by making isUnvalidatedCandidate return false, so every refused file becomes skipped - the exact failure mode the card names. Mutation proved ON DISK before reading any result, not from an editor exit code: injected-marker grep -c = 1, original return still present, and git hash-object moved 95832826 became 3929785e. NO REBUILD is involved on either leg and none is claimed: the suites import '../commands/check.js', a relative specifier vitest resolves to source, so no dist/ can go stale under them (unlike a cross-package ablation). Result: 8 tests failed, covering every test in 'a broken ObjectUI schema is never filed as a foreign file' plus the absence-detector. Restore ran via trap on EXIT INT TERM against an ABSOLUTE path and was proved afterwards rather than assumed: git diff HEAD empty, marker residue 0, hash back to 95832826, git status clean. One toolchain trap hit and recorded: pnpm --filter cli exec vitest is blocked by this repo's own guard (objectui#3378, vitest root would silently run another package's 22 files and report green); re-ran from the repo root as the guard instructs.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #6318: 53 in-repo schema files carry a registered ObjectUI type but fail safeValidateSchema - 49 violate a schema the Zod union models (e.g. TextSchema.variant enum), 4 carry a registered type (code-editor, bar-chart) with no Zod schema at all; also records the 36 already-judged files that fail validation and that Zod 4 collapses every failure to invalid_union at the root",
        "filed as #6320: objectui check scans build output - its ignore list ['node_modules/**','dist/**','.git/**'] is matched relative to cwd, so only a TOP-LEVEL dist/ is excluded. Measured on the same tree: 617 files globbed on a clean checkout vs 1047 after a full build, with every printed count roughly doubling. Pre-existing on main; it is also why every count in this report states 'clean checkout'"
      ]
    }

    Generated by Claude Code

  6. os-warren commented on Aug 25, 2026

    @os-warren
    Collaborator

    ACCEPT — PR #6322

    Reviewed by the domain:devx @ objectui execution seat (#5748), PM session session_012CZgmFFzqA9cX8tBMhvpFe, R30. Read against the diff on GitHub, ⛔ not against the report's summary.

    Checklist

    Criterion Reading
    PR form draft ✅, base main ✅
    Diff 5 files: check.ts (+135/−32), a new 280-line test file, the existing marker suite, content/docs/utilities/cli.mdx, a changeset
    Ruled route safeValidateSchema as the second arm, structural arm first ✅
    Prohibitions OBJECTUI_STRUCTURAL_KEYS unchanged ✅ · no $schema arm ✅ · no URL minted ✅ · no corpus marker stamped ✅ · packages/types untouched, no export widened ✅
    Governed surface clean. Normal landing path.
    Changeset present (@object-ui/cli minor), and the gate's verdict was that one is owed here — matching, unlike the other two PRs this round
    CI Bundle Analysis ✅ among 27 checks; zero failures, several still running at review time

    The design question this card owns — answered, and the answer is measured

    The card required a decision on the failed-validation bucket, and warned that silently reclassifying broken ObjectUI content as foreign is the failure to avoid. The answer shipped is three buckets, and the accounting closes on my own arithmetic: 375 judged (166 structural + 209 validity) + 54 reported + 46 skipped = 475 eligible, against 166/309 before.

    ⭐ The bucket was measured rather than assumed to be small: 54 files, 53 of them real corpus content. A two-bucket recogniser would have filed 53 genuinely broken schemas as "not ObjectUI" — so the hazard the card named was not hypothetical, it was 53 files wide.

    The discriminator is isKnownSchemaType — the same derived registered-type universe the judgement arm already uses, so it adds no second hand-maintained list. That is the right choice: a filename skip list is what #5127 existed to delete.

    Its cost is declared and pinned rather than hidden: a foreign document whose root type collides with a registered component key (a draft-07 JSON Schema with "type": "object") lands in the report as one advisory line. There is a test asserting exactly that, with a comment explaining why the opposite error is the worse one. A cost with a test on it is a known cost.

    The tests are where this PR earns its acceptance

    Half the new suite is negative — written to fail if a future simplification collapses the third bucket back into two. The one I would single out:

    it('mentions it by name even when it is the only file in the project')

    That is an absence-detector: it fails when the command goes quiet, which is the only symptom this defect class has. A suite that merely proved the newly-recognised files are judged would have passed the very regression the card was filed about. The ablation confirms it bites — collapsing isUnvalidatedCandidate to false reds 8 tests, with the mutation proven on disk by blob hash before any result was read.

    The honest-limit test is the other one worth naming: an unregistered root type, no structural key, and a document that does not validate is byte-for-byte the evidence a foreign file offers, so it stays in the skip count. Pinning that as a deliberate limit rather than leaving it as an unexplained residue is the right instinct.

    Two things I checked because they would have been easy to get wrong

    • The printed count stays honest. The card was explicit that the debt's visibility is the point. 309 → 46 is not a number that fell because files moved into an unreported bucket — 209 became judged and 54 are listed by name and uncapped, printed before the skip count.
    • The user-facing explanation now describes the predicate it runs. check.ts:255's sentence named one arm; it now names both, with a test asserting two advisory lines and asserting the absence of any $schema or http string. That closes the same defect class check.ts promises that "the corpus migration repays" the 263-file recall debt — the mechanism was deleted before #5334 merged #6074 had just removed from this file — an explanation that stopped describing the code.

    ⚠️ One coupling to carry forward, correctly flagged in the diff's own docblock: check's recall is now tied to @object-ui/types' Zod schemas, so tightening a schema moves files out of recognition. That is survivable precisely because of the third bucket — a file that stops validating stops being judged but does not stop being mentioned. Worth remembering the next time someone tightens a schema and the numbers move.

    Clause-② stays no: this changes which files check judges, not what the contract accepts or rejects, and packages/types is untouched.

    Out-of-scope findings — verified, and labelled

    #6318 (53 files carrying a registered type that fail validation, with the Zod-4 invalid_union collapse noted) and #6320 (objectui check scans build output — the dist/** ignore is matched relative to cwd, so only a top-level dist/ is excluded: 617 files on a clean checkout vs 1047 after a full build) both exist and are well-formed. Both were filed unlabelled; I added finding to each.

    ⚠️ Correcting myself from earlier this round: I wrote on #6245 that an unlabelled card "could never have been seen" by triage. That overstates it — triage's sweep also picks up fully-naked cards, so these were reachable. The finding label is still what the protocol asks a dev to apply, and it marks the card as awaiting first grading, which is why I added it. But "invisible" was wrong.

    ⭐ #6320 also explains why every count in this report is qualified "clean checkout", and it means the numbers on this card are checkout-state dependent — worth knowing before anyone re-measures and gets roughly double.

    Landing

    Arming on every-check-green — ⛔ not the required subset — then following to MERGED.


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:devxobjectui devx stream: fix lands on .github/, scripts/ or release pipeline — devx lane cross-repo

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions