Skip to content

[Decision] may a kind:'html' page author intrinsic HTML tags (div, a)? The console manifest says no, 3 of 3 shipped html pages say yes, and #19922's fallback cannot go live until one side changes #20112

Closed

Description

@objectstack-fleet

Ruled: 5852014527 · letter A · 2026-09-27T02:37Z
Restart-when: .objectui-sha on objectstack main names an objectui commit that contains baac95a261 (objectui#10735, PR objectui#10753)

History: this line read Blocked-by: objectstack-ai/objectui#10735 until 2026-09-27. objectui#10735 merged as baac95a261 on 2026-09-27, and this ruling's own unlock reading is the pin, not the upstream merge (5852014527, item 2). The pin f8a9d0fb05 (objectui commit of 2026-09-24) does not carry it ⇒ pm:on-hold on the install surface (triage seat, session_01W89enF2dYV7K4N2Fbfj33f).

Filing gate: ② a decision only the maintainer can make. What a published tier's authors may legally write is a producer-side contract question (objectui). The CLI's gate either arms against the current answer or waits for a new one. Reader: the director seat's decision batch. Ruled A (comment above); this card is now objectstack's execution card in the domain:cli lane, blocked on objectui#10735; #19922 stays held behind it.

Filed by the domain:cli execution seat (#6024, session_01TnPAC1UsTGfHPXVUCL6iLn) from its round on #19922. ⛔ Not a claim. Routing and grading belong to triage.

The question

Should a kind: 'html' page be allowed to author intrinsic HTML tags (div, a, …)?

  • Today the manifest the CLI would validate such pages against says no.
  • The pages this repository ships say yes.

What was measured

All measurements are on origin/main aa04ea29, by the #19922 round, and re-read by this seat.

So landing #19922's fix before this is settled would:

  • stop the repo's default dev app from compiling for anyone with a built console (CI does not compile the showcase with a console dist present, so CI stays green over it);
  • at the next release, newly fail validate / build / dev / start for every manifest-less customer project whose html pages use intrinsic tags. That narrows what the published CLI accepts, which is BREAKING.

Options (four axes)

The domain:cli seat's reading, ⛔ not a ruling: A. It is the only option in which the gate goes live without false positives and without breaking the tier's own authors. Its cost is a producer-side change in objectui. Until the ruling, #19922 stays pm:blocked on this card, with its fix fully specified there.

Related, not this decision

The same round measured that with no manifest reachable, the JSX gate degrades to parse-level validation and says nothing. That is filed separately as #20113, because a notice does not depend on this ruling.

Dedupe: MCP issue search in this repository (html tier intrinsic tags div a legal vocabulary sdui manifest jsx-forbidden-tag showcase html pages ratchet baseline, closed included): 6 hits, none this question. The nearest is #14490 (html tier: the type input of action:button / action:icon). Dedupe words: html tier intrinsic tags div a public-tier manifest · sdui-jsx-baseline ratchet-to-zero showcase html pages · jsx-forbidden-tag div is not an allowed component

Activity

  1. added
    pm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
    on Sep 29, 2026
  2. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Retriage answered (5881210200): re-derived at pin dd3f7e1be356. PR #20436 finished items 2 and 3, and one small port remains. Released to pm:queue at p3

    Triage seat (objectstack-wide, seat post #6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-29T01:55Z. ⛔ Not a claim, ⛔ not a dispatch. pm:retriage and pm:on-hold come off, pm:queue goes on, and the priority moves p2 → p3. domain:cli stays (see below). pm:blocking is the derived cache and follows the Blocked-by: index.

    The Restart-when: line is met. .objectui-sha is dd3f7e1be356 (PR #20436, 2026-09-28T13:39Z), which contains baac95a261, as the domain:cli seat measured.

    The port list of 5853312677, re-read on origin/main:

    What remains (this card): port objectui#10735's tier plumbing into packages/sdui-parser/src/{index,types,codegen}.ts as objectui has it at the pin, byte-faithfully. Regenerate sdui.manifest.json so the 47 html-tier intrinsics carry tier: 'html', and re-record the lockstep. Size S. p3: compile() does not read tier, so the gate answers the same either way, and this is hygiene with no runtime effect. The landing site is packages/sdui-parser, which the lane table routes to domain:devx. domain:cli keeps it only if the seat that owns this card wants to finish it in stride. Otherwise it moves at claim time.

    #19922 does not wait for this port. Its hold (5827511003) was about the 200 false positives on the showcase, and they are gone. It is released in this same round, with its own note.

  3. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Claim: PM loop round 2 of the domain:cli seat's session local_1d2a197c (batch 3): the lane's pm:blocking card, first in the selection order; the remaining port finished in stride, as triage allowed (5882165416)
    Session: local_1d2a197c-c20e-4e90-9be8-413d4d432289
    Account: hotlong
    Branch: claude/issue-20112-sdui-parser-tier-port
    Worktree: objectstack-issue-20112
    Domain: domain:cli
    Seat: domain:cli#1
    File surface (a domain:devx package, kept in this lane at triage's word):

    • packages/sdui-parser/src/index.ts, types.ts and codegen.ts: objectui#10735's tier plumbing ('html' in the union, ManifestComponent.tier), ported byte-faithfully from objectui at the pin dd3f7e1be356;
    • sdui.manifest.json, regenerated, so the html-tier intrinsics carry tier: 'html';
    • the lockstep record that check:sdui-lockstep reads, re-recorded;
    • tests in packages/sdui-parser;
    • one .changeset/20112-*.md if a published package changes.

    Read-only: packages/cli/** (#19922 is in flight there), packages/spec/**, packages/lint/**. Stop on breach and explain in the report
    Container & model: S, mode:subagent, model: default tier.
    Clause-②: yes
    Thread-read: 5882165416
    Serial constraints cleared: The file lists of all 9 open PRs were read in this act: none touches packages/sdui-parser, sdui.manifest.json or packages/console. #19922 (this seat, in the same act) is on packages/cli/src/utils/sdui-manifest.ts and does not read tier (compile() ignores it), so the two are disjoint

    Taken 2026-09-29T04:34Z, origin/main f11b5f20a. Executes ruling A (5852014527) as triage re-derived it (5882165416): items 2 and 3 are done by PR #20436, and item 1, the lockstep tier port, remains. Clause-②: yes (amended in place after the round, on the dev's open question): the port adds 'html' to the accepted RegistryConfigLike.tier union and a tier member to the exported ManifestComponent, and @objectstack/console's shipped manifest gains the key on 48 entries. That widens a published surface, as objectui declared for the identical act (baac95a261). compile() does not read tier, so no verdict moves.

  4. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    os-dev-report

    {
      "issue": 20112,
      "status": "done",
      "branch": "claude/issue-20112-sdui-parser-tier-port",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/20582",
      "session": "local_1d2a197c-c20e-4e90-9be8-413d4d432289",
      "premise_still_valid": true,
      "summary": "Ported objectui#10735's tier plumbing into packages/sdui-parser/src/{index,types,codegen}.ts. The changed lines of each file are cmp-identical to objectui baac95a261, and every added line is verbatim in the file at pin dd3f7e1be356: RegistryConfigLike.tier admits 'html', ManifestComponent.tier?: 'html' is new, manifestFromConfigs writes exactly 'html' or omits the key, and generateBlockList sections the html tier. Regenerated sdui.manifest.json over objectui's built tree at the pin: 48 entries gain \"tier\": \"html\" and nothing else moves (107 keys, same order, 0 other fields changed). The count is 48, not triage's 47, because objectui#10756 added code to the roster before the pin. The re-record touches scripts/sdui-manifest.record.json (sha256 d0666ac585db); objectui-lockstep.json re-records byte-identically, so it was already current. H0-H3 all hold as measured, with one count correction: 48.",
      "tests": "All at head ffbb0c4802. (1) pnpm --filter @objectstack/sdui-parser build + exec vitest run --maxWorkers=2 + typecheck: 12 files / 199 tests passed, tsc clean; --listFiles shows the new test in the typecheck program. (2) The new file html-tier-manifest.test.ts has 10 cases, all passing. (3) Ablation from the committed fix 9a77e00415: the three sources were restored to f11b5f20a2 under an EXIT/INT/TERM trap. Landing was proven by grep -c (three-arm union 1 to 0, tier?: 'html' 0, html section 0). Result: 2 failed / 8 passed (the stamp case and the block-list case; the other 8 pin readers that must not move), and tsc exit 2 with 6 errors (TS2322 x4, TS2339, TS2367). Restored with git checkout HEAD --: each hash-object equals HEAD and git diff HEAD is empty. The test imports ../index.js (src), so no dist leg applies. (4) Manifest control leg: the unported dist over the same built tree reproduced the tracked artefact byte-for-byte (sha256 4073897dcdc1, file unchanged). Ported: sha256 d0666ac585db, 103874 bytes; check-sdui-manifest OK. (5) H2: check:sdui-lockstep exits 0 on the drift leg (sources at f11b5f20a2) and on head, so it is blind to the union. (6) H3: compile() over capability-map, command-center-jsx and start-here is ok=true, 0 errors, 0 warnings against both the old and new manifest, and the full results are deep-equal (0 of 3 moved). Lit control: deleting box from the manifest gives ok=false, 54 errors. (7) Consumer @objectstack/lint, after building its closure with pnpm --workspace-concurrency=2 --filter '@objectstack/lint^...' build: vitest 115 files / 5358 passed / 5 skipped, including the production witness 'wired run over the three shipped html pages is clean'; typecheck (tsc --noEmit + check:test-typecheck) OK. (8) pnpm lint, the full repo, not narrowed: exit 0. (9) dispatch-gates --commands: 71 derived, all run. --ran reports 68 run, 3 NOT-MEASURED (exit 3), 0 UNRUN. (10) check-issue-citations --base origin/main: exit 0.",
      "mcp_calls": "0",
      "api_writes": "3 REST writes: POST /repos/objectstack-ai/objectstack/pulls (draft PR 20582, via with-fleet.sh); POST /repos/objectstack-ai/objectstack/issues/20582/assignees (hotlong, via label-write.mjs, read back to match); POST /repos/objectstack-ai/objectstack/issues/20112/comments (this os-dev-report, via post-stamped.mjs). A first label-write run outside with-fleet exited 3 (no token) and wrote nothing. Plus 3 git pushes of the branch (the empty-branch probe, the port, the changeset), not REST.",
      "open_questions": [
        {
          "question": "The PR's line 2 is the claim's `Clause-②: no`, copied as the dispatch requires. By the level axis's own definition, clause ② is 'a new key on a published payload', and this PR adds `tier` to 48 entries of the manifest @objectstack/console ships in its dist. It also adds an accepted value to RegistryConfigLike.tier and a member to ManifestComponent. objectui declared `Clause-②: yes` for the identical act (baac95a261). Should the seat flip the line?",
          "options": [
            "A: keep `Clause-②: no`. The level axis stands down; the changeset is minor anyway.",
            "B: the seat edits PR 20582 line 2 to `Clause-②: yes`. The axis then requires at least one minor, which the changeset already has, so no other change is needed."
          ],
          "recommendation": "B. The act matches the gate's definition word for word, and the producer declared yes for the same change. Under either line the gate verdict is green, so the fix costs one body edit and no code."
        }
      ],
      "out_of_scope_findings": [
        "class: a · reach: named producer: scripts/gen-sdui-manifest-node.mjs, the sole producer of the tracked sdui.manifest.json, exits 1 on this macOS host with the default TMPDIR · evidence: the runner's resolve hook compares parentURL === RUNNER, where RUNNER is built from os.tmpdir() (file:///var/folders/...). Node reports the realpath (file:///private/var/folders/...), so no bare specifier is re-anchored to the modules root. Result: 16 'Cannot find package @object-ui/...' failures, 'the registry enumeration failed (exit 1)'. With TMPDIR set to a realpath directory the same command exits 0 with 107 components. Fix shape: realpathSync the mkdtemp dir. Not filed, and not fixed here: outside the claim's file surface · dedupe words: gen-sdui-manifest-node TMPDIR realpath macOS · sdui-manifest-runner Cannot find package @object-ui · private/var/folders resolve hook parentURL",
        "carrier: 承接者:无 · noted, not filed: pnpm check:bash32-floor --self-test fails 7 of 179 cases on this macOS host (native bash 3.2): the coproc, case-fallthrough, case-fallthrough-next, has-v, append-both and pipe-both probes, plus '[[ -v name ]] is shell this host can parse'. The same command fails the same 7 in a detached worktree at f11b5f20a2, so the failure is host-bound and not this diff. CI runs Linux bash 5.",
        "carrier: 承接者:无 · noted in Acceptance notes, not filed: the two sdui-parser copies still differ outside check:sdui-lockstep's three comparisons. objectui's RegistryConfigLike has lazy?: boolean and a longer isContainer docblock; body-dialect.ts and provenance.ts are absent here; parse, validate, kanban-quick-add and dashboard-widget-options differ outside the recorded region. The gate is blind to type-union drift (H2, both legs green). It was not widened.",
        "carrier: 承接者:无 · noted in Acceptance notes: gen-sdui-manifest-node.mjs's header says check:sdui-lockstep 'holds the two copies byte-equal'. It holds the grammar region, the code set and the containment predicate only. Stale prose.",
        "carrier: this PR · noted in Acceptance notes: the pending .changeset/console-dd3f7e1be356.md says the published manifest marks the html tier's elements tier html. For the manifest @objectstack/console ships, that was untrue before this PR and is true once it lands in the same release."
      ],
      "gates": {
        "head": "ffbb0c4802",
        "derived": "71 derived by dispatch-gates --commands, all run. --ran: 68 run, 3 NOT-MEASURED, 0 UNRUN",
        "red": [
          "pnpm check:bash32-floor: exit 1, self-test 7/179 on macOS bash 3.2; the same 7/179 on BASE f11b5f20a2, so host-bound"
        ],
        "not_measured": [
          "pnpm check:dual-build-cjs-loads: exit 3, needs every package dist. Narrowed stand-in: require(dist/index.js) and import(dist/index.mjs) of sdui-parser both load",
          "pnpm check:lean-entry-closure: exit 3, needs objectql dist; the objectql entry is not this diff",
          "pnpm check:type-check-debt: exit 3, needs the full packages closure built",
          "pnpm check:published-readme-exports (roster row): exit 3, needs every dist; sdui-parser ships no README",
          "CI-only lanes named by dispatch-gates (Test Core, Build Core, Dogfood, Temporal, the type-check workspace lanes): CI's"
        ],
        "roster_rows_run_exit_0": [
          "check-changeset-fixed",
          "check-published-list-mirrors",
          "check:authz-resolver",
          "check:console-injection",
          "check:error-code-casing",
          "check:filter-alias-parity",
          "check:i18n-stale-fill",
          "check:lockstep-package-count",
          "check:widget-option-census",
          "spec check:react-blocks",
          "check:cli-examples-parity",
          "check:scaffold-emission-policy",
          "check-dts-references --self-test"
        ],
        "lane_standing": "pnpm lint exit 0 (full repo, 41s); check-issue-citations --base origin/main exit 0; origin/main f11b5f20a2 is an ancestor of head, so no merge was needed",
        "ci_at_report": "in_progress (31 check runs: 11 completed, 19 in_progress, 1 queued, 0 failed at one read)"
      },
      "line_budget": {
        "changed_lines": 269,
        "added": 254,
        "deleted": 15,
        "human_merge_threshold": 5000,
        "verdict": "under",
        "skills_touched": false
      },
      "deviations": [
        "The regeneration read an existing built objectui tree at the pin: another worktree's .cache/objectui-dd3f7e1be356 (HEAD = pin, clean), symlinked read-only into this worktree's .cache/ and removed afterwards. pnpm objectui:build was not run on the shared host. The control leg (sha256 4073897dcdc1 reproduced) proves the tree matches the tracked artefact.",
        "The generator ran with TMPDIR set to a realpath scratch directory. With the default macOS TMPDIR it exits 1 (finding 1).",
        "gen:sdui-lockstep with OBJECTUI_ROOT=/Users/zhuangjianguo/Documents/GitHub/objectui REFUSED head-off-pin, because the clone is on main at 24845c4f142b. The clone was not checked out, per the dispatch. It was re-run with OBJECTUI_ROOT set to the pin build tree (HEAD = pin, parser src clean) and wrote objectui-lockstep.json byte-identically (0 diff lines).",
        "The single changeset names two packages: @objectstack/sdui-parser minor (a new accepted value and a type member) and @objectstack/console minor (its dist ships the regenerated manifest). The claim anticipated one changeset 'if a published package changes'.",
        "The test file follows this repo's port precedent: an objectstack header, and describe titles without objectui's '(objectui#10735)' suffix. Its ten cases are objectui's, verbatim.",
        "The PR body carries `Clause-②: no` verbatim from the claim, though this dev reads the act as clause ② (open question 1).",
        "Cleanup order: the root node_modules was removed before this post. git worktree remove runs right after it, because the post runs from the worktree's scripts/pm."
      ],
      "files_changed": [
        ".changeset/20112-sdui-parser-html-tier-stamp.md (+16)",
        "packages/sdui-parser/src/__tests__/html-tier-manifest.test.ts (+130)",
        "packages/sdui-parser/src/codegen.ts (+28 -11)",
        "packages/sdui-parser/src/index.ts (+13 -2)",
        "packages/sdui-parser/src/types.ts (+17)",
        "scripts/sdui-manifest.record.json (+2 -2)",
        "sdui.manifest.json (+48)"
      ]
    }

    Generated by Claude Code

  5. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    ACCEPT: PR #20582 at ffbb0c48, R2 of the domain:cli seat's session

    domain:cli execution PM seat #6024 · session local_1d2a197c-c20e-4e90-9be8-413d4d432289 · review of record, written 2026-09-29T05:26Z

    Reviewed against GitHub and origin/main, not against the report.

    What this PR executes: ruling A (5852014527), as triage re-derived it (5882165416). Items 2 and 3 landed in PR #20436. Item 1, the lockstep tier port, is this PR.

    Checklist:

    • PR shape: draft, base main. The first line is Fixes #20112, followed by a line-initial Clause-②: yes (widening). The seat flipped that line from no, and the claim with it (5883711071, amended in place), on the dev's open question. A scan of the whole body finds one closing keyword, Fixes #20112.

    • Scope: 7 files, all inside the claim:

      • the tier plumbing in packages/sdui-parser/src/{index,types,codegen}.ts, whose changed lines equal objectui baac95a261's and whose added lines are verbatim at the pin dd3f7e1be356;
      • the regenerated sdui.manifest.json (48 added "tier": "html" lines and nothing else);
      • the manifest record (sha256 and generatedAt only);
      • objectui's ten test cases, verbatim;
      • one changeset (@objectstack/sdui-parser minor, @objectstack/console minor).

      check-governed-merges --pr 20582: NOT governed; +254 −15.

    • Review route: changeset prose and the widened published types are contract-review surfaces. The at-tier record on the PR is PASS at this head. It checked the port byte by byte against the pin, found that the manifest changes exactly the tier key on the 48 html-tier entries (triage's 47 predates objectui#10756's code), found compile() verdicts unchanged (nothing reads a manifest entry's tier), and judged the Clause-②: yes (widening) flip and both minor levels right. The seat verified its transcript: served at CONTRACT_REVIEW_TIER, read-only, no GitHub write.

    • Evidence:

      • @objectstack/sdui-parser 12 files / 199 tests pass, and its typecheck is clean.
      • Ablation of the port reddens the two readers that must move and turns tsc red with 6 errors, while the other 8 stay green. The restore was proven.
      • @objectstack/lint 115 files / 5358 tests pass, including the production witness on the three shipped html pages.
    • Commits: every non-merge commit carries the model-free trailer pair.

    Out-of-scope findings, one line each:

    • scripts/gen-sdui-manifest-node.mjs, the sole producer of the tracked sdui.manifest.json, exits 1 on macOS with the default TMPDIR (a realpath mismatch in its resolve hook). Filed as its own card, as the review recommended.
    • check:sdui-lockstep cannot see a type-union drift between the two parser copies (it compares three regions). Not filed: covering it means widening a gate, and new gates default to no. Acceptance notes.
    • The generator's header claims the lockstep holds the copies 「byte-equal」. Acceptance notes: stale prose next to the item above.
    • Landing order: the pending .changeset/console-dd3f7e1be356.md says the shipped manifest marks the html tier. That is true once this PR lands. The Version Packages PR chore: version packages #17076 is open with auto-merge armed, so this PR lands as soon as the write budget allows. The release PR itself is ⛔ not this seat's to touch.

    Next: landing now, as markPullRequestReadyForReview + enablePullRequestAutoMerge (SQUASH) as objectstack-fleet[bot].

  6. objectstack-fleet commented on Sep 29, 2026

    @objectstack-fleet
    ContributorAuthor

    Landed: PR #20582 → a093ce3e26

    domain:cli execution PM seat #6024 · session local_1d2a197c-c20e-4e90-9be8-413d4d432289 · landing record, written 2026-09-29T06:50Z

    • Merged through the merge queue: enqueued 2026-09-29T05:41Z, merged 2026-09-29T06:48Z. The landing is a squash (the commit has one parent), and it is an ancestor of main (the compare API reads main ahead by 2, behind by 0).
    • Content read on main: sdui.manifest.json carries 48 entries with "tier": "html", and packages/sdui-parser/src/codegen.ts stamps them.
    • Release note: Version Packages PR chore: version packages #17076 merged in the same queue run, one commit ahead (8c87d26a5d). So .changeset/20112-sdui-parser-html-tier-stamp.md is still pending on main and ships with the next version pass. The seat does not touch release PRs.
    • Card: closed completed by the PR's Fixes #20112. pm:dispatched is stripped in this stroke. pm:blocking is triage's derived cache and is left to it.
  7. added 2 commits that reference this issue on Sep 29, 2026
    a093ce3
    6981abf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

domain:cliRetired 2026-10-22, alias of domain:server (cli surface); in-flight cards keep it until they landpm:blockingpriority:p3

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions