Skip to content

skills/objectstack-ui/rules/navigation.md still prescribes span over colSpan on the basis #17328 measured false, and calls colSpan deprecated when nothing in packages/spec deprecates it #18496

Description

@os-warren

Filed by the domain:spec execution seat, session session_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T15:5xZ, out of the #17670 round (PR #18492). ⛔ Unlabelled beyond finding and unassigned; grading and routing are triage's. ⛔ Filed rather than fixed: the primary carrier is skills/** — a governed surface, human-merge only — so the domain:spec lane did not and will not touch it.

Why this one matters more than the carriers already fixed

#17328 measured two claims about FormField.colSpan / span: 'full' false. PR #18492 removes them from packages/spec and the generated reference page. The line below is the only place left in the tree that still states them — and it is the carrier most likely to be acted on, because it is prescriptive, it is shipped to customer projects, and the spelling it prescribes is the one the measurement puts on the worse side.

Carrier 1 — skills/objectstack-ui/rules/navigation.md:139 (governed)

Both falsified sentences, verbatim:

Use the relative span: full to make a field take the whole row

Do not use the absolute colSpan — it only lines up at one width and is deprecated.

⚠️ "deprecated" is false on its own terms, independently of #17328. Measured in packages/spec today: no .deprecated(), no retiredKey, no ADR-0087 conversion entry and no UNKNOWN_KEY_GUIDANCE row for colSpan; and #17328's own changeset states "Authored metadata is untouched: FormField.colSpan is unchanged and still valid."

Measured after PR #18492, over the tree excluding content/docs/releases/ and **/CHANGELOG.md (where historical entries correctly keep the old wording):

probe result
git grep -F 'only lines up at' exactly this one line
git grep -F 'at any column count' 0
lit control git grep -c -F colSpan, same exclusion set lit across 20+ files

Carrier 2 — examples/app-showcase/src/ui/views/task.view.ts:363-366

Same claim plus one now stale on its own terms:

'full' = whole row at any / derived column count — the primary primitive; absolute colSpan / is legacy and lint-discouraged

⚠️ The lint rule it names was withdrawn by #17328 and is gone from the tree.

⭐ Why the card that produced this one missed it: the phrase breaks across a comment line, so a line-oriented grep reads 0. grep -z finds it. ⇒ any successor sweeping for these sentences must use grep -z or it will report a false all-clear.

⛔ Scope note, so this is not over-read

Carrier 2 is recorded as a boundary, ⛔ not an expansion of the finding classes: copying the example does not fail (so ⛔ not class (a)), no declared contract is violated (⛔ not (b)), and a warning steering an author toward metadata the runtime does honour but which makes the result worse is explicitly outside class (c). It travels with carrier 1 because they are one routing round, ⛔ not because it is independently fileable.

Carrier 1 is where the decision sits: skills/** is governed, so ⛔ no code lane may land it. It needs the rules-layer owner.

Dedupe words

only lines up at · span: full · colSpan · objectstack-ui/rules/navigation · lint-discouraged

Refs

#17328 (the measurement) · #17670 / PR #18492 (the packages/spec carriers) · content/docs/protocol/objectui/layout-dsl.mdx:846 (a FormField listing that omits span entirely — incompleteness, ⛔ not an error, and ⛔ not part of this card)


Generated by Claude Code

Activity

  1. os-justin commented on Sep 17, 2026

    @os-justin
    Collaborator

    Claim: PM loop round 1
    Session: session_01Gqi43smmqjJ5sUrhfoPeKu
    Branch: claude/issue-18496-navigation-span-colspan
    Worktree: objectstack-issue-18496
    Domain: domain:skills
    Seat: domain:skills#1
    File surface: skills/objectstack-ui/rules/navigation.md :136–:139 (the 「Field width」 bullet: the two claims #17328 measured false — 「Use the relative span: 'full' …」 as the prescribed spelling and 「Do not use the absolute colSpan — it only lines up at one width and is deprecated」 — rewritten to what packages/spec actually declares and the measurement actually found; ⛔ nothing deprecates colSpan in packages/spec; scripts/check-skills-token-ratchet.mjs row :472 2273 — the token ratchet is held or paid by deletion in the same file, ⛔ never raised without a maintainer ruling quoted; ⛔ carrier 2 — examples/app-showcase/src/ui/views/task.view.ts:363-366 — is a boundary the card records, NOT this PR's surface); published skills/** ⇒ governed rules layer ⇒ draft, four-piece, the maintainer's approval lands it (stop on breach; explain in the report)
    Container & model: S(发布技能一条规则改正,受管面), mode:subagent, model: claude-fable-5-1 — node scripts/pm/dispatch-gates.mjs --tier --repo objectstack-ai/objectstack skills/objectstack-ui/rules/navigation.md at 2026-09-17T13:31Z on the fast-forwarded tree (14d254411): 「Model tier — MANDATORY: claude-fable-5-1 (derived from the file surface, not recalled)」
    Clause-②: no
    Thread-read: 5714065901
    Serial constraints cleared: 20 open PRs' file lists read at 2026-09-17T13:31Z — none touches skills/objectstack-ui/** or the token ratchet; os-verify-lock.sh --status at 2026-09-17T13:31Z: free; shared checkout fast-forwarded to origin/main 14d254411 before this dispatch. Slot freed by #18454's delivery (PR #18666, in-seat review done, four-piece pending CI). Total order at 2026-09-17T13:31Z: fourth p2 Bug by card age; #18506 follows, then the p2 Tasks (the platform-readings cluster), then p3.
    Ruling-ref: 5714065901


    Generated by Claude Code

  2. os-justin commented on Sep 17, 2026

    @os-justin
    Collaborator

    os-dev-report

    {
      "issue": 18496,
      "status": "done",
      "branch": "claude/issue-18496-navigation-span-colspan",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/18674",
      "head": "7155de6ac528f2612d7d7ff0c23268b24333678c",
      "base": "30be2ac0bb21d5262fc0447740b374b842c46048 (origin/main at worktree creation; the dispatch read 14d254411 — one commit older, no skills/** or ratchet change between them)",
      "files": [
        "skills/objectstack-ui/rules/navigation.md (+8/-8; the Field width bullet :136-:141 rewritten; two same-section restatements deleted to pay the ratchet: Overlay width :142-:143 parenthetical, Column count :146-:147 closing clause)"
      ],
      "session": "session_01Gqi43smmqjJ5sUrhfoPeKu",
      "premise_still_valid": true,
      "summary": "Premise re-verified on origin/main 30be2ac0b: navigation.md :136-:139 still read 'Use the relative span: full ... Do not use the absolute colSpan — it only lines up at one width and is deprecated'; packages/spec/src/ui/view.zod.ts declares colSpan (:2664, clamped to the form grid's column count, grid-aligned at every width) and span (:2676, 'full' resolves to the form grid's full column count; at the .objectui-sha pin 53ded82bf7 only the widest tier's class is emitted, one cell of two at the 720px modal) with no preference between them, and nothing in packages/spec deprecates colSpan (.deprecated( 0 files; retiredKey( naming colSpan 0; UNKNOWN_KEY_GUIDANCE 7 files / RETIRED_KEY_GUIDANCE 8 files carry 0 colSpan lines; ADR-0087 registries conversions/* and migrations/* 0, positive control namespace/tableName/sourceView hits registry.ts x3 apply.ts x2 types.ts x2 stored.ts x1). The bullet now reads: omit it by default (auto); both keys are valid; colSpan (1-4) is clamped to the current column count, grid-aligned at every width; span: 'full' resolves to the form grid's full column count, but the shipped renderer emits it at the widest tier only (a 3-column form: one cell of two in a modal). No preference is prescribed because the spec prescribes none (PR #18492: the preference is removed, not reversed) and the renderer fix objectui#9253 / bd09957380 is ahead of the pin (two-leg: is-ancestor exit 1, control leg PIN~5 exit 0, reverse exit 0, 0 tags contain it; .objectui-sha unchanged since 3a9ad22ec), after which 'full' is the row at every multi-column tier; the word deprecated is gone. Carrier 2 (examples/app-showcase task.view.ts:363-366) untouched as the card's boundary. Draft PR #18674, Fixes #18496, Clause-②: no at creation, skip-changeset by measurement (0 of 83 manifests ship a skills path in files[]; control 70 ship dist), skills/** governed: check-governed-merges --test exit 3 GOVERNED; left for the maintainer's word. Reversal deviation, declared: the dispatch's file surface named :136-:139 only; the ratchet (ceiling 2273, headroom 0) could not hold a truthful two-key bullet inside 319 bytes, so 93 bytes of restated reason clauses in the same section were deleted (permitted by the dispatch's 'deletion or compression inside the same file'), each named in the PR body with the sentence it duplicated.",
      "measurements": {
        "bullet_before": "- **Field width.** Use the relative **`span: 'full'`** to make a field take the whole row; otherwise **omit it** (`auto` sizes by widget type × current columns — textarea / rich-text / file take the row automatically). Do **not** use the absolute `colSpan` — it only lines up at one width and is deprecated.",
        "bullet_after": "- **Field width.** **Omit it** (`auto` sizes by widget type × current columns — textarea / rich-text / file take the row). Both keys are valid: `colSpan` (1–4) is clamped to the current column count, grid-aligned at every width; `span: 'full'` resolves to the form grid's full column count, but the shipped renderer emits it at the widest tier only (a 3-column form: one cell of two in a modal).",
        "spec_readings": "packages/spec/src/ui/view.zod.ts@30be2ac0b :2664 colSpan describe (clamp, grid-aligned at every surface width, colSpan:4 in a 3-column grid renders as 3, colSpan:1 emits no class); :2665-:2675 span TSDoc (objectui#9253 / bd09957380 ahead of the pin; 're-read this block at the pin bump'); :2676 span describe ('full' = form grid's full column count; at pin 53ded82bf7 widest tier only, one cell of two at 720px); :3539-:3540 drawerWidth @deprecated + '[DEPRECATED → size buckets]' (the neighbouring Overlay bullet's claim, kept, is true). .changeset/17670-colspan-span-measured-behaviour.md: 'The preference between the two keys is removed, not reversed'; 'Both keys are unchanged, both still parse'. Generated page content/docs/references/ui/view.mdx:201-:202 matches.",
        "measurement_readings": "#17328 geometry table (hotcrm 427c98535d, @objectstack/* 17.4.0, Chromium, 3-column section): colSpan:2 → 358/586/1006 px at 390/720/1700 (2 of 2 at the modal, 2 of 3 on the page), overflow 0; span:'full' → 358/285/1517 (285 at 720 = pixel-identical to authoring nothing, one cell of two); colSpan:4 ≡ span:'full' (@2xl:col-span-3); colSpan:1 emits no class. Pin state on 30be2ac0b: .objectui-sha 53ded82bf7a494f54e344e19099dbf00854b8694; objectui clone not shallow; merge-base --is-ancestor bd09957380 PIN exit 1, control PIN~5 (83c77dc30, 2026-09-05) exit 0, reverse exit 0, git tag --contains bd09957380 = 0.",
        "ratchet": "scripts/check-skills-token-ratchet.mjs:472 row 2273 unchanged; before 9092 bytes = 2273 tokens (headroom 0); after 9091 bytes = 2273 (headroom 0); gate line '✓ check-skills-token-ratchet: skills/objectstack-ui/rules/navigation.md is 2273 tokens (ceiling 2273; headroom 0).'; bullet 319 → 411 bytes (+92), deletions -61 -32, net -1 byte; 162 → 162 lines; section widest line 84.",
        "sweep": "git grep -z -l -F over the tree excluding content/docs/releases/ and **/CHANGELOG.md, files, 30be2ac0b → 7155de6ac: 'only lines up at' 2 (navigation.md + .changeset/17670-… quoting the removed wording) → 1 (changeset only); 'at any column count' 1 (changeset) → 1; 'lint-discouraged' 1 (task.view.ts, carrier 2) → 1; 'is deprecated' 40 → 39 files, in navigation.md 1 → 0; files carrying both colSpan and 'is deprecated' 3 → 2 (view.zod.ts, view.mdx — 0 same-line hits); lit control colSpan 35 → 35; dark control zzz-no-such-token 0 → 0."
      },
      "tests": "No package touched: no ① closure build, no ② package test owed. dispatch-gates.mjs --commands --repo objectstack-ai/objectstack at 7155de6ac (1 path vs merge base 30be2ac0b): 22 derived, all run redirect-then-$?, all exit 0, --ran reconcile exit 0 '22 derived, 22 run, 0 NOT-MEASURED, 0 UNRUN': check-ci-filter-parity 0; check-closing-keyword-parity 0 (+--self-test 0); check-comment-mask-corpus 0; check-doc-route-spelling --advisory 0 (+--self-test 0); check-skills-token-ratchet 0 (+--self-test 0, '65 cases pass'); check:agent-test-spelling 0; check:corpus-claim-drift 0; check:cross-package-test-inputs 0; check:doc-authoring 0 ('44 published skill files clean — no internal issue-id references'); check:driver-memory-census 0; check:nul-bytes 0; check:pm-governed-merges 0; check:refd-timer-probe 0; check:role-word 0; check:skill-compatibility 0; check:skill-frame-sync 0; check:skill-identifier-liveness 0; check:watch-hint-literal 0; pnpm --filter @objectstack/lint run check:doc-formula-expressions 0 after building @objectstack/lint... under os-verify-lock.sh (VERDICT command-exit 0, held 186s, waited 0s). check-governed-merges --test navigation.md exit 3 GOVERNED (recorded as such). check-clause2-carriers --pair 18674 exit 0 (both carriers agree). grep -naP control-character scan of the file: no match. Label: POST /issues/18674/labels skip-changeset 200, readback = union, nothing stripped. PR body read back: identical to the sent body minus the trailing newline; session-URL footer stored once, no bare footer appended. No ablation: prose-only change with no test asserting it; the ratchet gate was read on both trees instead. Not measured locally: the 51 artifact-roster, 11 wide-population and 2 workflow-valued families, CI's own.",
      "mcp_calls": "0 — no MCP GitHub tool called; every read and write went through the REST proxy with GITHUB_TOKEN or local git.",
      "api_writes": "5 — git push x2 (empty-branch probe, then 7155de6ac); POST /repos/objectstack-ai/objectstack/pulls x1 (PR 18674, draft); POST /repos/objectstack-ai/objectstack/issues/18674/labels x1 (skip-changeset); POST /repos/objectstack-ai/objectstack/issues/18496/comments x1 (this report).",
      "open_questions": [],
      "out_of_scope_findings": [
        "noted, not filed (承接者: the card's own routing round): carrier 2 examples/app-showcase/src/ui/views/task.view.ts:363-366 still says 'full' = whole row at any / derived column count and colSpan is legacy and lint-discouraged (rule withdrawn by #17328); #18496 records it as a boundary, left as found.",
        "noted, not filed (承接者: the pin-bump PR that absorbs objectui bd09957380; dedupe words spanLadderFor, objectui#9253, span-full-tier-ladder): the new bullet's 'the shipped renderer emits it at the widest tier only' is pin-anchored like the spec describe, but no gate watches skills/** for pin-state prose (check-objectui-pin-citations.ts scans packages/spec/src only); that PR must re-read navigation.md:139-:141 with view.zod.ts:2665-:2676.",
        "noted, not filed (承接者: whoever next edits that interface block; PR #18492 note 4 says the same): content/docs/protocol/objectui/layout-dsl.mdx:850 FormField listing has colSpan and no span — incompleteness, not an error.",
        "noted, not filed (承接者: 无): .changeset/17670-colspan-span-measured-behaviour.md quotes 'only lines up at' and 'at any column count' as the removed wording; a historical record consumed into CHANGELOG.md at release, which the sweep's exclusion set already expects."
      ]
    }

    Generated by Claude Code

  3. os-justin commented on Sep 17, 2026

    @os-justin
    Collaborator

    ACCEPT — in-seat contract-tier review of PR #18674 (head 7155de6ac, report 5715524799) by the skills seat, 2026-09-17T14:12Z. Verified against GitHub and a scratch worktree at the head, ⛔ not against the report:

    • Scope = the claim (5715188923), with one declared widening inside the same section: one file, +8 / −8 — skills/objectstack-ui/rules/navigation.md, the 「Field width」 bullet :136–:141 rewritten; to hold the token ratchet (2273 / 2273, headroom 0 — the bullet grew 319 → 411 B) two restatements in the same section were deleted: the Overlay-width parenthetical 「(they can't be chosen without knowing the client viewport)」 and the Column-count closing clause 「the columns adapt themselves」 — each a restatement of the sentence before it, named in the PR body. 162 lines before and after. ⛔ Carrier 2 (examples/app-showcase … task.view.ts:363-366) untouched, as the card's boundary.
    • The bullet now says what the spec and the measurement say: 「Omit it (auto …). Both keys are valid: colSpan (1–4) is clamped to the current column count, grid-aligned at every width; span: 'full' resolves to the form grid's full column count, but the shipped renderer emits it at the widest tier only (a 3-column form: one cell of two in a modal).」 Seat's own reading of packages/spec/src/ui/view.zod.ts on main: :2664 colSpan 「Absolute column span (1-4). The renderer clamps it to the form grid's current column count, so the cell starts at a real column boundary at every surface width…」; :2676 span 「'auto' (default — omit it) … 'full' …」 — no preference between the keys and nothing deprecating colSpan (the dev's census: .deprecated( 0, retiredKey( 0, guidance rows 0, ADR-0087 registries 0, with lit controls). The preference is REMOVED, not reversed — matching PR docs(spec,ui): colSpan and span state their measured behaviour — the two claims #17328 falsified are gone #18492's changeset 「the preference between the two keys is removed, not reversed」. The 「widest tier only」 clause is pin-anchored like the spec's own describe (objectui#9253 / bd09957380 is ahead of the .objectui-sha pin 53ded82bf7, measured two-leg) — the dev notes the pin-bump PR must re-read this bullet; so does this record.
    • Sweep, the card's own discipline (git grep -z, releases + CHANGELOG excluded): 「only lines up at」 navigation.md 1 → 0 (the changeset quoting the removed wording is the only remaining carrier); 「is deprecated」 in navigation.md 1 → 0 (the Overlay bullet's 「are deprecated」 for width / drawerWidth stays and is TRUE per view.zod.ts :3539 @deprecated); lit control colSpan 35 → 35 files. Seat's grep on the head: no 「only lines up at」 / 「lint-discouraged」 / 「is deprecated」 line left in the file.
    • Gates: re-run here on the head — check-skills-token-ratchet 0 (2273 / 2273), --pair 18674 → 0 (Clause-②: no, both carriers agree, no widening tell), check-governed-merges --test exit 3 = GOVERNED (skills/** ×1). The report's 22 derived families all exit 0 (one prerequisite build through the lock), --ran reconciled 0 NOT-MEASURED; skip-changeset by measurement (0 of 83 manifests ship a skills/ path). CI on 7155de6ac: 24 success / 11 skipped on 7155de6ac (check-expected-skips --pr 18674 exit 0, every skip rostered), 0 failures — every check run read completed and none failure before this act.
    • Tier: MANDATORY claude-fable-5-1 from the file surface — the dev ran at that tier (claim 5715188923).
    • Deviations: the two same-section deletions, declared and accepted (the dispatch allowed 「deletion or compression inside the same file」). Dev's open questions: none. Out-of-scope notes recorded, nothing to file (carrier 2 stays the card's boundary; the pin-bump re-read; the layout-dsl.mdx listing incompleteness already noted by PR docs(spec,ui): colSpan and span state their measured behaviour — the two claims #17328 falsified are gone #18492).

    Rules layer (published skills/**) ⇒ the four-piece is hung on PR #18674 in the same act: 维护者速读(终稿) on the PR, needs-user-decision, review requested from os-zhuang and hotlong. An authorized APPROVED lands it by ruling C; a human merge is equally the record. The token ratchet row stays 2273 — no raise asked.


    Generated by Claude Code

  4. os-justin commented on Sep 18, 2026

    @os-justin
    Collaborator

    LANDED — PR #18674 (#18496, governed published skill: skills/objectstack-ui/rules/navigation.md 「Field width」 rewritten to what packages/spec and #17328 say — both keys valid, colSpan clamped and grid-aligned at every width, span: 'full' at the widest tier only under the current pin; 「deprecated」 gone; two same-section restatements deleted to hold the token ratchet 2273 / 2273) merged through the queue at 2026-09-18T01:44:29Z (merged_at), squash 62b114f8b8a2d22d8f4a2a6569150ad476493651 (single parent 5a8c94b7f27abc8902ce858287cee2ac97f0f096, an ancestor of origin/main). Governed surface (published skills/**): the seat's ACCEPT 5715809477 here, ## 维护者速读(终稿) 5715809871 on the PR, needs-user-decision + reviewers at 2026-09-17T14:12Z; os-zhuang APPROVED at 2026-09-18T01:12:48Z (review 5243110314 on the ACCEPT head 7155de6ac5), marked ready and enqueued by hand at 2026-09-18T01:12:52Z; the seat stripped needs-user-decision at 2026-09-18T01:14:58Z per ruling C (--pair 18674 0, CI 40 / 15 skipped rostered, harness CURRENT at 88aa326deb). The card auto-closed completed at 2026-09-18T01:44:30Z on the PR's Fixes; pm:dispatched is stripped in the same act. Landing criterion per the seat's publication register: MERGED through the queue, read from merged_at.


    Generated by Claude Code

  5. added a commit that references this issue on Sep 28, 2026
    62b114f
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

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions