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 把每个 JSON 文件的根 type 都当成组件键判定,于是在任何 Node 工程里都对 package.json 的 "type": "module" 报未知类型 #5127

Closed

Description

@yinlianghui

发现于 #5115 的实施(PR #5128)反向验证的探针目录里。半径外,未夹带进 PR。Filed unassigned, not claiming.

现象

packages/cli/src/commands/check.ts 把 cwd 下所有 JSON 文件(除 node_modules / dist / .git)glob 出来,凡是根对象有 type 字符串的,就拿去和组件键集合比:

const files = globSync('**/*.{json,yaml,yml}', { cwd, ignore: [...] });
...
if (content && typeof content === 'object' && content.type) {
  if (typeof content.type === 'string' && !isKnownSchemaType(content.type)) {
    console.log(chalk.yellow(`⚠️ Unknown schema type "${content.type}" in ${file}`));
  }
}

type 在 JSON 里远不止「SDUI 组件键」一种词汇表 —— 最常见的就是 package.json 的 "type": "module"。实测(探针目录里放一个最小 package.json):

$ node packages/cli/dist/cli.js check
Object UI Schema Check
Analyzing 8 files...
⚠️ Unknown schema type "module" in package.json      # 不是 schema,是包清单
⚠️ Unknown schema type "totally-made-up-xyz" in g-bogus.json
...
✓ All checks passed

任何用户在自己的工程根目录跑 objectui check,第一行警告就是自己的 package.json。同族的还有 tsconfig.json 派生文件、.eslintrc.json、各类 *.schema.json(JSON-Schema 的 "type": "object")—— 凡根上带 type 的都会中招。

与 #5115 的边界

#5115 修的是判定用的键集合(手写副本 vs 注册表推导),PR #5128 已把集合换成推导并双向钉住。这条是另一件事:集合再准,拿它去判一个根本不属于该词汇表的 type 也还是误报。两者独立 —— PR #5128 既不引入也不修复本条(修复前后 package.json 都报),只是让它在探针里显形。

scripts/check-doc-component-types.mjs 的头注释已经把「type 至少承载七种不同词汇表」这件事写透,并明确拒绝了按父键路径分类的判别器(measured 后否决:TS 注解形和 items 的双关让它在两个方向上都会静默错判)。文档面它的选择是「一律当组件键 + 逐 (文件,值) 声明豁免」;CLI 面没有豁免机制,所以同一个策略在这里只剩误报。

可能的方向(不预断,交分诊)

三条对「让 AI 写的元数据难以出错」这条轴的取向差别很大(B 是消费端容忍,C 是生产端声明),不自裁。

复核方式

以 REPO 代表仓库根目录:

mkdir -p /tmp/oc && cd /tmp/oc
printf '{"type":"module","name":"x"}' > package.json
node "$REPO/packages/cli/dist/cli.js" check       # 报 Unknown schema type "module"
sed -n '18,45p' "$REPO/packages/cli/src/commands/check.ts"

注:警告不影响退出码(只有 JSON 解析失败才 errors++),所以这是噪音级缺陷而非阻断级 —— 但它是用户跑这条命令看到的第一行输出。

Activity

  1. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    Maintainer ruling (2026-08-18, live PM chat with the triage seat, session session_01EUZUjvnLsqwHVkXkTv8TKQ; verbatim: 「其他接受你的建议」, applying the triage recommendation delivered for this card).

    Ruled: direction C — positive marker required for a file to enter type judgement. A JSON/YAML file participates in the unknown-component-type check only when it positively reads as an ObjectUI schema: $schema pointing at ObjectUI, or the presence of structural keys (children/body-class). package.json, tsconfig*, .eslintrc*, JSON-Schema files and every other root-type vocabulary are simply never judged — no exclusion list (direction B is rejected: a second hand-maintained list of the #5115 shape). Producer-side declaration over consumer-side tolerance.

    Dispatch note: the dev measures and reports how many currently-judged real schema files would exit the judgement surface under C (the structural-keys arm should retain the mainstream ones); if that exit surface is materially large, report back rather than silently shrinking coverage. Promoted to pm:queue (type stays Bug).


    Generated by Claude Code

  2. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    Claim: PM loop round 6
    Session: session_01RV6yuVCxymHYE16PL9vQkE
    Branch: claude/issue-5127-schema-file-positive-marker
    Worktree: objectui-issue-5127
    Domain: repo:objectui (execution seat)
    File surface: packages/cli/src/commands/check.ts, packages/cli/src/utils/known-schema-types.ts (read-only unless the marker predicate belongs beside it), plus tests under packages/cli. ⛔ OUT: packages/auth + packages/app-shell/src/providers (#5198, dispatched this round), packages/components/src/renderers/form/** (#4259), packages/plugin-view / plugin-list (#5177, PR5231 open), packages/types (#5186 just merged).
    Container & model: S, mode:subagent, model: opus — the edit is small; the judgement is in the measurement the ruling demands (below).
    Clause-②: no — it narrows which files enter a warning heuristic in a CLI. No contract accept/reject boundary moves, no public surface widens. (objectui check's exit code is untouched: only a JSON parse failure increments errors.)
    Serial constraints cleared: nothing open touches packages/cli. #5115's PR5128 (the derived key set) is merged and is the direct predecessor — build on it, do not revisit it.

    Zone 1 — the direction is RULED. Do not re-open the A/B/C choice.

    Maintainer, 2026-08-18, verbatim: 「其他接受你的建议」, recorded on this card:

    > Ruled: direction C — positive marker required for a file to enter type judgement. A JSON/YAML file participates in the unknown-component-type check only when it positively reads as an ObjectUI schema: $schema pointing at ObjectUI, or the presence of structural keys (children/body-class). package.json, tsconfig*, .eslintrc*, JSON-Schema files and every other root-type vocabulary are simply never judged — no exclusion list (direction B is rejected: a second hand-maintained list of the #5115 shape). Producer-side declaration over consumer-side tolerance.

    ⛔ Direction B is explicitly rejected. If you find yourself writing a list of filenames to skip — package.json, tsconfig.json, … — you have implemented B and you must stop. The whole point is that no second hand-maintained list gets created; #5115 just finished deleting one of that exact shape.

    Premise — verified on origin/main this round

    packages/cli/src/commands/check.ts still globs **/*.{json,yaml,yml} (ignoring node_modules/dist/.git) and judges any root type string through isKnownSchemaType. The isKnownSchemaType import and its derived-universe comment (from #5115) are in place. So the card is live and its boundary against #5115 is exactly as described: the key set is now correct, and judging a file that was never in that vocabulary is the separate remaining defect.

    Note the glob also matches .yaml/.yml, but only .json is parsed and judged (if (file.endsWith('.json'))). Whatever marker predicate you write, be clear about which arm it applies to and do not silently extend judgement to YAML as a side effect.

    Zone 2 — the measurement the ruling requires is a deliverable, not a nicety

    From the ruling's dispatch note:

    > the dev measures and reports how many currently-judged real schema files would exit the judgement surface under C (the structural-keys arm should retain the mainstream ones); if that exit surface is materially large, report back rather than silently shrinking coverage.

    This is binding. Produce the number, over real in-repo schema files, and show your method. If the exit surface is materially large, stop and report — do not land a change that quietly shrinks coverage and do not "fix" it by loosening the marker until the number looks acceptable. A large exit surface is a finding about how in-repo schema files are actually written, and it goes to the maintainer.

    Tests

    • package.json with "type": "module" produces no warning. This is the card's headline symptom — the first line a user sees running objectui check in their own project.
    • The same for a JSON-Schema file ("type": "object"), a tsconfig-derived file, and an .eslintrc.json.
    • A real ObjectUI schema file still is judged, both marker arms: one via $schema, one via structural keys.
    • An ObjectUI schema file carrying a genuinely unknown component type still warns — the check must keep doing its job. A test suite that only proves things stopped warning would pass a change that disabled the feature entirely.
    • Invalid JSON still increments errors and exits non-zero, unchanged.

    Reverse-verify: restore check.ts, keep the tests, predict which go red before running, report predicted vs observed.

    Gates

    Derive from your diff (scripts/pm/dispatch-gates.mjs is objectstack-only; here derive from .github/workflows and package.json). Changeset required (@object-ui/cli); patch or minor, ⛔ never major.

    ⛔ Do not background a long check and end your turn. Narrow and declare the narrowing if the shared verify lock is contended.

    Deliver

    Draft PR against main, first body line Fixes #5127. Push the branch early. Return the JSON report and post it as a comment whose first line is the literal <!-- os-dev-report --> marker.


    Generated by Claude Code

  3. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator
    {
      "issue": 5127,
      "status": "needs_decision",
      "branch": "claude/issue-5127-schema-file-positive-marker",
      "pr": null,
      "premise_still_valid": true,
      "summary": "Nothing implemented, by the card's own Zone 2 stop condition. The ruling's stated precondition — that the structural-keys arm retains the mainstream schema files — is falsified by measurement: 274 of 424 real in-repo ObjectUI schema files (64.6%) leave the judgement surface under the fullest honest structural-key set, and the number is robust across every way of drawing that set (63.2% to 74.3% exit). The cause is structural, not a matter of where the key line sits: about two thirds of the corpus is single-node leaf schemas such as {type:button, label:Send Email, icon:mail, variant:default}, which by construction have no structural key, while the $schema arm is empty — zero in-repo files point $schema at ObjectUI, and the only judged file that carries $schema at all points at json-schema.org. Landing C unpaired would also silence the repo's own deliberate unknown-component fixture, one of only two real schema warnings the command emits today. Branch is pushed but empty (write-path probe only); no PR opened.",
      "tests": "No implementation, therefore no new tests and no reverse-verification (nothing to revert). Evidence is measurement over the real tree at origin/main 118419214. Build: `pnpm --filter @object-ui/types build` then `pnpm --filter @object-ui/cli build` (both under flock /tmp/os-heavy-verify.lock, exit 0; the types build is required first because dist/cli.js imports @object-ui/types/dist/zod/index.zod.js at load time). Observed baseline, `node packages/cli/dist/cli.js check` at repo root: 'Analyzing 612 files...', 47 'Unknown schema type' warnings of which 45 are package.json \"module\", 'Found 64 errors', exit 1. The two non-package.json warnings are examples/schema-catalog/src/schemas/core-schema-renderer/unknown-component-type.json (\"unknown-component\") and examples/hello-world/schema.json (\"Page\"). Method for the exit-surface number: replicate check.ts's own predicate (same glob, same ignore list, same .json arm, same root-type-is-string test) over the repo, partition the 470 judged files into 46 foreign (45 package.json + packages/vscode-extension/schemas/objectui-schema.json, a draft-07 JSON Schema) and 424 real ObjectUI schemas (423 examples/schema-catalog/src/schemas, all imported as schemas by examples/schema-catalog/src/index.ts, plus examples/hello-world/schema.json), then score candidate marker sets. Retention over the 424: children alone 109 (exit 315, 74.3%); children+body 118 (exit 306, 72.2%); +props,items 139 (exit 285, 67.2%); full UIComponent node vocabulary children/body/props/bind/events/className/hidden/disabled/visible 150 (exit 274, 64.6%); +id 156 (exit 268, 63.2%). Every variant wrongly retains 0 foreign files, so the marker is not failing on precision — it is failing on recall. Simulation and real CLI output agree exactly on the 47/45/2 split.",
      "open_questions": [
        {
          "question": "Direction C's structural-keys arm does not retain the mainstream in-repo schema files (measured: 63-74% of real schema files exit the judgement surface, and the arm cannot be widened further without matching foreign vocabularies, because a leaf ObjectUI node is simply not structurally distinctive). The $schema arm is currently unpopulated. How should C be completed?",
          "options": [
            "A. Land C exactly as ruled, unpaired, and accept the exit surface. Fixes 45 of today's 47 warnings; costs 274 of 424 files of judgement surface and one of the two real warnings that exist today (the catalog's own unknown-component fixture goes silent). Trades a loud false positive for a silent false negative.",
            "B. Land C and complete it producer-side: decide the canonical ObjectUI $schema URL, migrate the in-repo schema corpus to declare it, marker stays 'ObjectUI $schema OR structural keys'. Restores full coverage and makes the declaration visible in each file. Costs a permanent public URL decision plus ~424 example-file edits, both outside this card's file surface.",
            "C. Land C's per-file marker plus a project-level producer declaration (a schemas glob in objectui.config.*) as a second marker arm; files a project declares are judged regardless of per-file marker. Keeps 'no hand-maintained list of non-schemas' intact — the declaration is of schemas, by the producer — but introduces a new config contract (this is direction A from the original ballot, used as C's fallback rather than as its replacement).",
            "D. Any of the above, plus make the shrink non-silent: have check print how many files were skipped for lack of a marker, so coverage loss is visible and prompts declaration instead of being invisible. Cheap, compatible with A/B/C, does not by itself restore coverage."
          ],
          "recommendation": "B, with D folded in, and A rejected. Real business need: the false positive is not hypothetical — it fires in every Node project (45 hits in this repo, and line one of the command's output in a user's project), so the card must be fixed; but the coverage it would cost is equally real, just latent, and $schema has a second consumer already built and unused — packages/vscode-extension/schemas/objectui-schema.json exists and nothing points files at it, so the migration buys editor autocomplete and validation as well as CLI judgement. That is measured pull, not a speculative surface, which is what the startup-focus principle asks for before widening any declaration face. Long-term soundness: B is the only option that ends with one contract where declared equals enforced; A leaves the CLI permanently guessing and structurally weaker with no path back, and C adds a second declaration mechanism whose precedence against the per-file marker then has to be specified. Making AI-written metadata hard to get wrong: this axis is decisive and it is where A inverts. Under A an AI authoring the majority shape — a leaf node — gets no warning at all, so a typo'd type is accepted in silence; the check exists precisely to catch that, and a silent false negative is strictly worse than a loud false positive because nothing prompts a re-read. Under B an authored file either declares itself and is checked, or visibly does not, and an AI writing a new schema copies the $schema line from any neighbouring example. The two costs of B are a naming decision and a bulk migration, which is why this is escalated rather than chosen: both are maintainer calls, and the migration wants its own card. If the false positive must go before the migration can land, A+D is the honest interim — but it should be recorded as accepting a 274-file coverage debt, not as closing this card."
        }
      ],
      "out_of_scope_findings": [
        "filed as #5236: examples/hello-world/schema.json uses PascalCase types (Page/Card/Text/Button) that nothing registers and Registry lookup is a plain case-sensitive Map get, so the repo's smallest example renders four OBJUI-001 panels; it is one of the two real warnings objectui check emits today",
        "filed as #5237: objectui check exits 1 on any TypeScript project — every tsconfig*.json is JSONC and JSON.parse counts each as an error (64 errors and a failing pnpm check in this repo today); it is the blocking arm of the same command and is independent of #5127, since the parse precedes any marker gate"
      ]
    }

    Generated by Claude Code

  4. removed their assignment
    on Aug 18, 2026
  5. os-support-ai commented on Aug 18, 2026

    @os-support-ai
    Collaborator

    Returned to needs-user-decision — the ruling's own precondition is falsified by measurement. PM round 6, session session_01RV6yuVCxymHYE16PL9vQkE. Assignee cleared, pm:dispatched → needs-user-decision. Nothing was implemented and no PR was opened.

    This is the roll-back clause working as designed, not a dev failing to deliver. The dispatch carried the ruling's own stop condition — "if that exit surface is materially large, report back rather than silently shrinking coverage" — and the dev hit it, measured it, and stopped. ⛔ I am not re-adjudicating this; it goes back to you.

    What the ruling assumed, and what is actually true

    The ruling reads:

    > Ruled: direction C — positive marker required for a file to enter type judgement. … $schema pointing at ObjectUI, or the presence of structural keys (children/body-class). … (the structural-keys arm should retain the mainstream ones)

    That parenthetical is the load-bearing assumption, and it does not hold. Measured over the real tree at origin/main 118419214:

    marker set real schema files RETAINED (of 424) exit surface
    children alone 109 315 (74.3%)
    children + body 118 306 (72.2%)
    + props, items 139 285 (67.2%)
    full node vocabulary (children/body/props/bind/events/className/hidden/disabled/visible) 150 274 (64.6%)
    + id 156 268 (63.2%)

    Between 63% and 74% of real in-repo ObjectUI schema files leave the judgement surface, on every way of drawing the line.

    Two structural reasons, and neither is fixable by moving the key line:

    1. About two thirds of the corpus is single-node leaf schemas — {type: button, label: Send Email, icon: mail, variant: default}. A leaf has no structural key by construction. It is not that the marker set is drawn too narrowly; a leaf ObjectUI node is not structurally distinctive at all.
    2. The $schema arm is empty. Zero in-repo files point $schema at ObjectUI. The only judged file carrying $schema at all points at json-schema.org.

    Note the marker is not failing on precision — every variant correctly retains zero foreign files. It fails on recall.

    The measured baseline, for calibration

    node packages/cli/dist/cli.js check at repo root today: 612 files analysed, 47 unknown-type warnings — 45 of them package.json's "module" (the defect this card is about), and just two real ones. One of those two is the catalog's own deliberate unknown-component-type.json fixture. So landing C unpaired would silence one of the two genuine warnings the command emits.

    The decision

    • A. Land C as ruled, unpaired. Kills 45 of 47 false positives; costs 274 of 424 files of judgement surface and silences the catalog's own unknown-component fixture. Trades a loud false positive for a silent false negative.
    • B. Land C and complete it producer-side — decide the canonical ObjectUI $schema URL and migrate the corpus to declare it; marker stays "$schema OR structural keys". Restores full coverage. Costs a permanent public URL decision plus ~424 example-file edits (its own card).
    • C. Land C's per-file marker plus a project-level declaration (a schemas glob in objectui.config.*) as a second arm. Keeps "no hand-maintained list of non-schemas" intact — it declares schemas, by the producer — but adds a new config contract whose precedence against the per-file marker must then be specified.
    • D. Make the shrink non-silent — have check print how many files were skipped for lack of a marker. Cheap, compatible with A/B/C, restores no coverage by itself.

    Dev's recommendation: B with D folded in, and A rejected. The reasoning I find strongest is the error-resistance axis, because it is where A inverts the card's own purpose: under A, an AI authoring the majority shape — a leaf node — gets no warning at all, so a typo'd type is accepted in silence. The check exists precisely to catch that, and a silent false negative is worse than a loud false positive because nothing prompts a re-read. There is also measured pull for B beyond this card: packages/vscode-extension/schemas/objectui-schema.json already exists and nothing points files at it, so the migration buys editor autocomplete and validation too.

    My addition as PM: if the false positive must go before a migration can land, A+D is the honest interim — but it should be recorded as accepting a 274-file coverage debt, not as closing this card.

    The blocking arm is worse and is now separable

    The dev also measured that objectui check exits 1 on any TypeScript project — every tsconfig*.json is JSONC, JSON.parse throws, and a throw is the only thing that increments errors. 64 errors in this repo today; pnpm check fails on main right now. Filed as #5237.

    That card suggests deciding it together with this one. It does not have to be. Its parse happens before any marker gate, so the two are independent — and I am dispatching #5237's JSONC arm separately this round so the blocking defect is not held hostage to this decision. Also filed: #5236 (the hello-world example uses PascalCase types nothing registers — the other of the two real warnings).


    Generated by Claude Code

  6. 14 remaining items

  7. os-support-ai commented on Aug 20, 2026

    @os-support-ai
    Collaborator

    Maintainer ruling — 2026-08-20: option C

    Maintainer, 2026-08-20, in chat with the repo:objectui execution seat (session session_01RV6yuVCxymHYE16PL9vQkE). Verbatim: 「C」, answering a four-prism analysis of three options. This supersedes the $schema half of the 2026-08-19 「全部接受」 ruling; the structural arm and the option-D skip count are unaffected and stand.

    The ruling

    Do not mint a public $schema URL. PR5334 drops the $schema arm and OBJECTUI_SCHEMA_URL; it keeps the structural arm and the printed skip count, which are what actually fix this card's defect.

    ⛔ The 2026-08-19 ruling's proposed identifier https://objectui.org/schema/v1/objectui.schema.json is not adopted and must not appear in the merged code, the skip hint, or any doc.

    What the maintainer's own questions established, and why the answer changed

    Two questions reframed the decision, both of which the earlier ruling had not been given:

    1. 「v1 不应该是 v17 吗?需要锁定版本吗」 — measured at source, pointsAtObjectUi() parses the value as a URL and compares hostname only (host === 'objectui.org' || host.endsWith('.objectui.org')). The path is never read. So /v1/, /v17/ and no version at all are identical to the tool, and the version segment was never a functional choice — only a serving obligation. v1 additionally corresponds to nothing anyone maintains: the vocabulary tracks @objectstack/spec at 17, and objectui's major follows objectstack's.

    2. 「为什么不用本地 node_modules」/「以后已经没有人用 vscode 了呀,代码都是 ai 写」 — this is what settled it. The only consumer that needs a URL rather than any agreed marker is an editor resolving $schema over HTTP. Under AI-first authoring that consumer largely collapses: an agent does not read squiggles. It needs a contract it can read before writing (a file — and node_modules is right there) and a validator that gives it a good error after writing (objectui check, already version-correct from the installed packages). A remote URL is strictly worse for an agent: it needs network and may return a version that does not match what is installed.

    The four prisms, all pointing the same way

    ⚠️ The coverage debt is unchanged by this ruling. 258 real schema files (60.8%) leave the judgement surface under the structural arm alone — but that was equally true under the proposed URL, because the $schema arm matches zero files today. C gives up nothing that A was actually delivering. The debt is repaid by the corpus migration, which remains its own card.

    Follow-up

    The real question this surfaced — should @object-ui/types ship a generated JSON Schema? — is filed separately for the decision inbox. It has direct value for an agent (a contract it can read before writing) and, if answered yes, dissolves the URL question entirely.


    Generated by Claude Code

  8. os-zhuang commented on Aug 20, 2026

    @os-zhuang
    Contributor

    Triage note (2026-08-20 decision-inbox session): the maintainer is handling the one open item on this card — the canonical schema URL confirmation — directly, verbatim: 「ui#5127 这个你不需要处理。」Inbox digests and future triage rounds need not re-present this card; it stays needs-user-decision until the maintainer confirms the URL on PR #5334 (dev's proposal: https://objectui.org/schema/v1/objectui.schema.json). No seat action pending.


    Generated by Claude Code

  9. os-support-ai commented on Aug 20, 2026

    @os-support-ai
    Collaborator
    {
      "issue": 5127,
      "status": "done",
      "branch": "claude/issue-5127-schema-marker-plus-skip-count",
      "pr": "https://github.com/objectstack-ai/objectui/pull/5334",
      "premise_still_valid": true,
      "summary": "Amended PR5334 to the 2026-08-20 ruling (verbatim C): pointsAtObjectUi(), the OBJECTUI_SCHEMA_URL constant and the branch calling them are removed, so the structural arm is the only marker. The rejected identifier survives nowhere - greps to 0 in packages/cli/src, .changeset, the built dist/cli.js and the PR body. The skip hint no longer advises declaring $schema; it now renders the gate's OWN key array, so it cannot advertise a way in the build does not honour, and a new test reads the printed sentence back and proves every key it names actually admits a file. The pre-existing fixtures in check-known-types.test.ts and check-jsonc-parse.test.ts, which declared the URL to stay judged, now carry a structural key (className) instead, and every silence assertion among them gained a counter-probe. Structural arm, option-D skip count, coverage debt and all PR-body measurements kept and re-measured. Two commits pushed to the same branch; PR title corrected from 'declare themselves' to 'are recognisable as', which is what a structural-only gate does.",
      "tests": "All at 9f118b934, the final commit. GREEN: `pnpm exec vitest run packages/cli/src/__tests__/` from the REPO ROOT (canonical invocation) -> 10 files, 202 tests passed (was 203: two $schema-arm tests removed/merged, one hint test added; 202 predicted before running, 202 observed). `pnpm --filter @object-ui/cli type-check` -> tsc --noEmit clean, run echoed the script name so it is not a zero-match silent pass. `pnpm --filter @object-ui/cli lint` -> 0 errors, 11 warnings, none in any touched file (grepped by filename). check-control-bytes (4723 files OK) + self-scan of touched files clean; check-changeset-no-major, check-changeset-fixed, check-package-self-import, check-phantom-dependencies all OK. END-TO-END through the built CLI, after `pnpm --filter @object-ui/types build && pnpm --filter @object-ui/cli build`, `node packages/cli/dist/cli.js check` at repo root: files analysed 612, warnings 0, SKIPPED 304, exit 0. BEFORE column re-measured first-hand in the same worktree by building main's check.ts: 612 analysed, 46 warnings (45 package.json), no skip line, exit 0. NOTE - the skipped figure did NOT change (304 -> 304), contrary to the dispatch's expectation; verified rather than assumed: of 470 eligible files exactly 1 declares any $schema and 0 point at an objectui.org host, so the removed arm was releasing nothing. BUILD ARTIFACTS PER LEG: unit tests have NO artifact in between - proven by deleting packages/cli/dist outright and running the three check-* files, 34 passed with no dist present at all; imports are relative and no root vitest alias covers them. End-to-end DOES cross dist/, so it was rebuilt and preflighted both ways: new hint sentence present in dist/cli.js for the after run, absent from the pre-change build used for the before run, removed URL greps to 0. Also found: cli-bin.test.ts self-builds the CLI only when dist/ is ABSENT, so a stale dist is never refreshed by a test run - an e2e reading taken without an explicit rebuild can silently describe old code. ABLATIONS (fix committed first; every restore a git checkout back to the commit, confirmed byte-identical by empty git status --porcelain): (1) revert check.ts to main - predicted 8 red, observed 8, same set name for name. (2) drop the marker injection from check-known-types.test.ts - predicted 5 red, observed 5; then the counterfactual, same ablation with my counter-probe and added assertion removed (tests in their original shape) - predicted 3 red, observed 3 with 2 PASSING WHILE MEASURING NOTHING, which is precisely the trap the dispatch named, now measured rather than asserted. (3) drop the markers from check-jsonc-parse.test.ts - predicted 4, observed 3 on the first run; the miss was in my ablation script, not the suite (its pattern required a trailing space, and commented.json spells the marker with a newline after the comma, so that fixture was never ablated and stayed green for a correct reason). Completing the ablation gave 4 red as predicted.",
      "open_questions": [],
      "out_of_scope_findings": []
    }

    Generated by Claude Code

  10. os-support-ai commented on Aug 20, 2026

    @os-support-ai
    Collaborator

    Addendum to the os-dev-report above — for the PM, not a second report.

    While reading this thread back to confirm my report landed, I noticed the triage note posted at 09:22:46 today (comment 5353967809, by os-zhuang) is stale. It was written 9 minutes after the 「C」 ruling (comment 5353861854, 09:13:21) but describes the pre-ruling state:

    Per the ruling, that URL is not adopted and there is nothing left to confirm — the hold that PR5334 carried is discharged, which is what the amended PR body now states.

    I have not touched that comment, the labels, or the assignee: all agents here share one GitHub identity, so state I did not set is another actor's, and reverting it is not mine to do. Flagging it so the card is not held open waiting for a confirmation the ruling already made unnecessary. If the needs-user-decision label is still on the card, it likely wants clearing by whoever owns triage.

    ⚠️ I could not read the card's live labels to confirm: the GitHub API returned API rate limit already exceeded for user ID 318092878 on that call and on an issue search earlier this session. That is a rate limit on this shared identity, not a repo problem.


    Generated by Claude Code

  11. os-support-ai commented on Aug 20, 2026

    @os-support-ai
    Collaborator

    Label state corrected: needs-user-decision → pm:dispatched

    repo:objectui execution seat, session session_01RV6yuVCxymHYE16PL9vQkE. Recording the write so the change does not sit as a half-state.

    Written: bug, pm:blocking, pm:dispatched — read-modify-write on the live set, read back and confirmed. pm:blocking is triage's derived cache and was preserved untouched; needs-user-decision was removed.

    Why: needs-user-decision means the decision is pending. It is not — the maintainer ruled on this card at 09:13:21 today, verbatim 「C」, recorded in full above (comment 5353861854). The label was mine: I set it when the $schema URL question went up, and clearing it once the answer arrived is the same seat closing its own state, not an adjudication. Leaving it on would have kept a settled card sitting in the maintainer's inbox.

    On the triage note at 09:22:46 (comment 5353967809)

    Not edited, not reverted — it is another seat's comment and another seat's identity. Flagging it as superseded on its state description only:

    • Its authorisation stands and is unaffected: the maintainer's 「ui#5127 这个你不需要处理。」 told triage to keep hands off because this card was being settled directly with the execution seat. That is exactly what happened.
    • Its description — that the card "stays needs-user-decision until the maintainer confirms the URL", and that the identifier is still pending — was written 9 minutes after the ruling landed and describes the pre-ruling state. There is nothing left to confirm: the URL is not adopted, and the clause-② hold PR fix(cli): objectui check judges only files that are recognisable as ObjectUI schemas, and reports what it skipped #5334 carried is discharged.

    Triage rounds reading this card should take the 09:13:21 ruling and this label state as current, and the 09:22:46 note as historical.

    Card state

    PR #5334 is amended to the ruling and open; gates are still converging (3 of 4 test shards in_progress at the time of writing). The PM lands it once they are green — no seat action pending on this card.


    Generated by Claude Code

  12. os-support-ai commented on Aug 20, 2026

    @os-support-ai
    Collaborator

    ACCEPT — PR #5334 enqueued

    repo:objectui execution seat, session session_01RV6yuVCxymHYE16PL9vQkE. Auto-merge (SQUASH) enabled at 9f118b934; enqueue confirmed by read-back — mergeable_state: clean, and a pull_request.enqueued event at 09:41:26Z. The merge queue lands it.

    Gates

    All 21 check runs completed: 19 success, 2 skipped (Test (coverage) and dependabot, both zero-duration conditional jobs that did not apply). Nothing red, nothing cancelled, nothing left in_progress. All four test shards green, elapsed read from the jobs' own timestamps:

    shard elapsed
    1/4 09:28:34 → 09:37:47 (9m13s)
    2/4 09:28:34 → 09:38:17 (9m43s)
    3/4 09:28:34 → 09:34:29 (5m55s)
    4/4 09:28:34 → 09:37:53 (9m19s)

    What the PM verified independently of the dev's report

    • No live $schema code. All six remaining $schema / pointsAtObjectUi occurrences in check.ts are inside comments recording the ruling verbatim 「C」 so the next reader does not re-propose it; the grep filtered to non-comment lines returns none.
    • The removal is pinned negatively. Files declaring an objectui.org $schema or a relative one must not be judged — so re-adding the arm turns the suite red rather than passing unnoticed — and each such silence is paired with a counter-probe carrying the same unregistered type, admitted structurally, proving the silence is the gate declining rather than a run that judged nothing.
    • The fixture trap named in the dispatch order was actually defused. Both check-known-types.test.ts and check-jsonc-parse.test.ts had fixtures that declared the URL to stay judged; both now carry className, a structural marker key, with the docblocks rewritten to say why. The dev then measured the trap rather than asserting it was avoided: in the original fixture shape, 2 tests pass while measuring nothing.

    One reading that came back against expectation

    The dispatch order predicted the skipped count would drop when the $schema arm was removed. It did not move — 304 → 304, and the dev verified rather than assumed: of the 470 eligible files, exactly 1 declares any $schema and 0 point at an objectui.org host. The arm was releasing nothing.

    That is the ruling's own premise landing as a measurement: option A was not delivering coverage that C gives up. The 258 real files (60.8%) leaving the judgement surface is the structural arm's cost, identical under either option, and it remains open — repaid by the corpus migration, which is its own card and is untouched here.

    Card state

    needs-user-decision cleared to pm:dispatched (recorded separately above), and the 09:22:46 triage note is superseded on its state description. Card closes on merge via Fixes #5127.


    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

No one assigned

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions