Skip to content

finding(skills): the published skills/objectui guides still teach dataSource as the data expression root and as what bind resolves against — three files, both halves retired by objectui#9308 #9370

Description

@os-tesla

Filed by the os-dev seat implementing objectui#9308 (PR #9369). ⛔ Not fixed there: skills/** is a governed surface (AGENTS.md §受管面, GOVERNED_SURFACES skills-catalog), and a single path from it would move that whole PR into the draft-and-wait lane — while that PR is the one turning Doc Snippet Type Check green on main.

What is now false

The maintainer ruling of 2026-09-13 on objectui#9308 (option B) did two things:

  • b1 — SchemaRenderer no longer publishes the injected DataSource adapter as the expression root data.
  • b2 — useDataScope, which is what a node's bind resolves through, now reads the ambient scope a host publishes via PredicateScopeProvider instead of walking the adapter.

The published skill package still teaches both retired halves. Measured on claude/issue-9308-unbind-data-root:

skills/objectui/guides/schema-expressions.md

line text why it is now false
112 a scope-source table row mapping "Top-level data fields" to SchemaRendererProvider dataSource the provider's dataSource publishes no expression root at all
113 a row reading `` data
302-303 "dataSource = { customerNames: [...] }, list calls useDataScope("customerNames") and renders one entry per array element" useDataScope no longer walks dataSource
305 "Nested paths work: "bind": "app.settings.users" resolves dataSource.app.settings.users" it resolves scope.app.settings.users
393 a comment introducing a bound example as dataSource = { rows: [...] } same

Roughly two dozen further ${data.…} examples on that page (lines 35-232, 403-406) are not wrong per se — data is still readable if a host publishes it — but every one of them is now unreachable for a reader following the wiring the same page teaches, so they read as a working example and produce the raw source text.

skills/objectui/guides/data-integration.md and skills/objectui/rules/protocol.md carry the same bind teaching (both are in skill-guide-data-table-binding.test.tsx's GUIDE_PATHS, and all three failed that test's list leg before the harness moved).

The behaviour change a reader has to be told about

Not just a renaming. Measured on the built evaluator, a missing root and a present-but-undefined root are different:

scope data.status == 'draft'
{ data: undefined } false
no data key true (unevaluable, fail-soft), and objectui#5454's reporter warns

So a data.* gate authored from these guides used to hide its node on every row and now shows it on every row. The correct runtime-layer row root is record (ADR-0089 D3).

What PR #9369 did instead, and what that leaves

The six pins in packages/components that READ these guides and render their examples now publish the host values through PredicateScopeProvider, so each still measures its own subject (the JSON example, the registry claim, the diagnostic line). ⚠️ That means those pins are green while the prose beside the examples they read is wrong — the coverage hole this card exists to close. No assertion was weakened and nothing was skipped.

Suggested shape

Move the three files to the scope channel exactly as content/docs/guide/schema-rendering.md and packages/react/README.md did in PR #9369 — publish under a real name, read it by that name, and state that dataSource is the adapter and not a root. The reader-list paragraph (the plugin packages register (...)) and the data-table bind pothole are unaffected and should not move.

⚠️ Governed surface: an agent drafts, a human merges. ⛔ No ready-flip, no queue, no auto-merge.

Filed by an agent seat while implementing objectui#9308; dedup was run over the 281 open issues this repository's issue-list endpoint returns, with objectui#9308 and objectui#9346 as the known-hit control — no existing card covers this surface (objectui#7945 is the same tree, a different teaching).

Activity

  1. os-tesla commented on Sep 13, 2026

    @os-tesla
    CollaboratorAuthor

    Claim: objectui#9370 — move the three published skills/objectui guides off the retired data root and the retired bind resolution
    Clause-②: yes

    Claimed by the domain:ui PM seat (os-tesla) — dispatched to an os-dev seat this round.

    Routing: option C, as the filing seat recommended

    The objectui#9308 seat hit two instructions pointing opposite ways — "fix what this round makes false" against "⛔ do not touch skills/**" — and took A: it filed this card with a per-line census rather than folding the three files into PR objectui#9369. ⭐ Correct, and the reason is concrete: folding three governed files in would have parked the PR that clears a red on main behind a human merge.

    Its recommended follow-up was C — hand this to the governed skills lane rather than opening a second front. Taken: dispatched as its own PR, which costs one human review instead of two.

    Premise — inherited from a per-line census, and the seat re-verifies it

    skills/objectui/guides/schema-expressions.md lines 112, 113, 302-303, 305, 393; plus guides/data-integration.md and rules/protocol.md carrying the same bind teaching. ⚠️ Line numbers were measured on the objectui#9308 branch, not on main — the seat re-measures against whatever origin/main carries when it branches, and the re-measurement wins.

    ⭐ The part that is not a renaming, and must reach the reader

    The ruling changes behaviour, and a reader who only sees new API names will mis-migrate:

    scope data.status == 'draft'
    { data: undefined } false
    no data key at all true (unevaluable, fail-soft)

    ⇒ a data.* gate authored from these guides used to hide its node on every row and now shows it on every row. The correct runtime-layer row root is record (ADR-0089 D3). ⛔ A migration note that only swaps provider names is incomplete.

    Clause-② is yes

    Published skills/** making falsifiable contract-semantics claims about which roots a tier binds — the same limb that put objectui#9311 through this review. ⛔ The governed-surface human merge does not substitute for it; the two stack (references/contract-review.md: 「受管面人工合并 ⛔ 不替代复核,两道保障叠加」).

    ⚠️ The resulting PR parks as draft needing an APPROVED review from an authorized approver (os-zhuang, hotlong). That is the designed end state. The precedent from this same round is objectui#9352, which was approved and merged as 28be0786d.


    Generated by Claude Code

  2. os-tesla commented on Sep 13, 2026

    @os-tesla
    CollaboratorAuthor

    os-dev-report

    {
      "issue": 9370,
      "status": "done",
      "branch": "claude/issue-9370-skills-data-root",
      "pushed_sha": "5df0ee9719178037689ca3fb7c61394eab88ec2d",
      "pr": "https://github.com/objectstack-ai/objectui/pull/9378",
      "premise_still_valid": true,
      "premise_remeasurement": {
        "base": "origin/main 69aa9c017 (the card's census was taken on the objectui#9308 branch)",
        "verdict": "every cited line still lands on the cited text - 5/5 exact",
        "lines": {
          "112": "EXACT - scope-table row mapping top-level data fields to `SchemaRendererProvider dataSource`",
          "113": "EXACT - row reading `| `data` | Alias for dataSource root | `${data.fieldName}` |`",
          "302-303": "EXACT - `dataSource = { customerNames: [...] }` ... `useDataScope(\"customerNames\")`",
          "305": "EXACT - Nested paths work: `bind: app.settings.users` resolves `dataSource.app.settings.users`",
          "393": "EXACT - jsonc comment `dataSource = { rows: [...] }`"
        },
        "which_world_i_measured_in": "PRE-#9369. Re-derived from my own tree, not assumed: `SchemaRenderer.tsx` still carries the `data: dataSource` binding and `SchemaRendererContext.tsx` still reads `const dataSource = context?.dataSource` inside `useDataScope`. BOTH retired halves are still LIVE on base 69aa9c017; PR #9369 is open, not merged. The PR body states this and asks the maintainer to merge after #9369."
      },
      "summary": "Moved the three named published guides (`guides/schema-expressions.md`, `guides/data-integration.md`, `rules/protocol.md`) off the retired `dataSource`-as-`data`-root and `bind`-walks-the-adapter teaching, onto the `PredicateScopeProvider` scope channel, matching the shape PR #9369 used for `content/docs/guide/schema-rendering.md` and `packages/react/README.md`. Two wiring examples now carry the `os:check` marker, so the marked ts population moves 14 -> 16 and the thing this card is about is COMPILED against the built dist rather than only read. The migration note states the VERDICT FLIP, per layer, not just a provider rename. The reader-list paragraph and the `data-table` `bind` pothole are untouched. Two further defects found by enumeration were filed rather than folded in.",
      "self_test_reading": {
        "before_build": "EXIT=2 - PRECONDITION NOT MET: 12 unbuilt packages; the three compiler controls (resolution / sentinel / positive) all reported broken. NOT a reading.",
        "after_build": "EXIT=0 - '✓ check-skill-examples self-test: 59 cases pass (marker adjacency both directions, orphans, nested illustration, json/jsonc, the bare-`any` guard in both directions with its shrink-only baseline, the ROOT BOUND in both directions with its own shrink-only baseline and control, the PUBLISHED-TYPE inventory with its positive and negative controls plus the shadowing ledger in both directions, and the compiler legs through the real harness).'",
        "conclusion": "the harness is trustworthy, so the red/green below are readings"
      },
      "gate_before_after_verbatim": {
        "before": "EXIT=0 | Scanned 20 guide(s) under skills, .claude/skills: 121 ts/tsx/typescript fence(s), 70 json/jsonc fence(s). | Marked: 14 ts fence(s) (floor 13), 70 json fence(s) (floor 70) | Semantic phase: 14 of 14 ts fence(s) judged, 0 failed. | JSON phase: 70 fence(s) parsed, 0 failed. | Every marked skill example holds up against the built types.",
        "after": "EXIT=0 | Scanned 20 guide(s) under skills, .claude/skills: 122 ts/tsx/typescript fence(s), 70 json/jsonc fence(s). | Marked: 16 ts fence(s) (floor 13), 70 json fence(s) (floor 70) | Semantic phase: 16 of 16 ts fence(s) judged, 0 failed. | JSON phase: 70 fence(s) parsed, 0 failed. | Every marked skill example holds up against the built types.",
        "reading": "both SHRINK-ONLY floors hold; the ts marked population GREW by the two new wiring fences; the json population is unmoved at 70"
      },
      "measure_enumeration": {
        "command": "node scripts/check-skill-examples.mjs --measure (judges every candidate fence, marked or not)",
        "corpus": "121 ts/tsx/typescript + 70 json/jsonc candidate fences across 20 guides; 84 carried the marker at the branch point",
        "starting_population": "ts 18/121 pass, json 70/70 pass; 12 ts fences fail to parse and 16 root-bound refusals (vitest / @testing-library/react / msw / vite / @playwright/test) are never type-checked at all",
        "my_three_files": "schema-expressions.md carries ZERO ts fences - every one of its 31 candidates is json/jsonc and all are marked+passing; data-integration.md carries 6 marked (4 json + 2 typescript) and 9 UNMARKED typescript fences that FAIL; rules/protocol.md carries 10 marked json/jsonc plus 1 unmarked failing typescript fence that shadows BaseSchema",
        "what_that_bought": "the enumeration is what found the two extra defects below - both sit in fences or prose no gate reaches"
      },
      "decision_on_the_data_examples": {
        "measured_population": "21 lines spell `${data.` in schema-expressions.md (one is the census's own scope-table row). Repo-wide under skills/: 21 there, 14 in rules/protocol.md, 5 page-builder.md, 4 testing.md, 2 each data-integration.md and auth-permissions.md, 1 architecture.md, 4 in evals/*.json.",
        "decision": "KEEP every one verbatim and make them REACHABLE, rather than rewrite them to bare roots as PR #9369 did for content/docs.",
        "why_this_divergence_from_9369": [
          "A pin renders those exact spellings: skill-guide-provider-envelope.test.tsx, as re-derived in #9369, publishes `scope = { data: PROVIDER }` and renders `${data.customers}` / `${data.label}`. Rewriting the guide spellings would move that pin's subject from inside a second PR - the exact 'green alone, red together' shape the dispatch warned about.",
          "ADR-0089 D3 does not forbid the name: CANONICAL_ROOT_BY_LAYER puts `data` at the metadata layer. What was retired is the renderer AUTO-publishing the adapter there, not the name.",
          "Most of those examples are about something else entirely (which text keys carry expressions, type preservation, the troubleshooting section) - the root name is scaffolding."
        ],
        "how_they_are_made_reachable": "the page's new COMPILED wiring example publishes a root literally named `data`, and the scope table carries a row saying every `${data.*}` example on the page assumes exactly that",
        "nothing_silent": "the only expression text this PR changes is the two `dataSource = {...}` comments that named the retired wiring; stated in the PR body under its own heading"
      },
      "migration_note_states_the_verdict_flip": {
        "answer": "yes, and per LAYER after the PM's correction",
        "my_own_measurement_on_the_built_evaluator": {
          "controls_that_fire": {
            "`${data.status}` with data published": "evaluateExpression -> \"draft\" ; evaluateCondition -> true",
            "`Status: ${data.status}` with data published": "evaluateExpression -> \"Status: draft\" ; evaluateCondition -> true",
            "`${data.nope}` - PRESENT root, ABSENT member (the discriminating control)": "evaluateExpression -> undefined ; evaluateCondition -> false"
          },
          "subject": {
            "`{ data: {} }` adapter-shaped, predicate": "evaluateExpression -> false ; evaluateCondition -> false",
            "`{ data: undefined }`, predicate": "evaluateExpression -> false ; evaluateCondition -> false",
            "`{}` no data root, `${data.status}`": "evaluateExpression -> \"${data.status}\" (the SOURCE TEXT) ; evaluateCondition -> true",
            "`{}` no data root, `Status: ${data.status}`": "evaluateExpression -> \"Status: ${data.status}\" ; evaluateCondition -> true",
            "`{}` no data root, predicate": "evaluateExpression -> \"${data.status == 'draft'}\" ; evaluateCondition -> true"
          }
        },
        "pm_correction_confirmed_independently": "yes. I had measured both layers before the correction arrived, but the guide callout compressed them into ONE cell. Corrected in commit 5df0ee971: the callout now carries one column per layer and tells the reader to read both. The `true` on a missing root is the PREDICATE layer failing soft, NOT the evaluator's answer - the evaluator hands back the template's own source characters, in full-string and mixed forms alike. Neither the guide nor the PR body now says 'the evaluator answers true'.",
        "what_the_reader_is_told": "predicate layer: a `visible` gate authored from these pages was hidden on EVERY row and is now shown on EVERY row; spelled `hidden` it flips the other way. Interpolation layer: a `content` built from a missing root paints the literal `${data.status}` characters on screen. Plus: re-publishing `data` restores the OLD always-false verdict and does NOT fix the gate - use `record`, the runtime-layer root (ADR-0089 D3)."
      },
      "governed_queue_guard_verdict_on_my_diff": {
        "self_test": "exit 0 - 185 cases pass",
        "test_on_my_three_paths": "exit 3",
        "verbatim": "⛔ GOVERNED - 3 of 3 path(s) are on a governed surface:\n   skills/** x3 - the published skills catalog\n     - skills/objectui/guides/schema-expressions.md\n     - skills/objectui/guides/data-integration.md\n     - skills/objectui/rules/protocol.md\n\n   One governed path governs the WHOLE pull request - proportion is not a question.\n   ⛔ Do not flip it ready, enqueue it, or arm auto-merge. Park it as a DRAFT and leave the merge\n      to the maintainer; a human merge IS the review record for a governed surface.\n   The merge-queue run of \"Governed Surface Queue Guard\" refuses this diff unless an APPROVED review by an\n   authorized approver (GOVERNED_APPROVERS: os-zhuang, hotlong) is on the pull request - on\n   whichever commit it was left (maintainer ruling 2026-09-04).",
        "compliance": "PR #9378 is a DRAFT. Not flipped ready, not enqueued, no auto-merge armed. `scripts/check-governed-queue-guard.mjs` was not touched."
      },
      "changeset_decision": {
        "decision": "NONE owed - re-measured, not inherited",
        "measurement_1": "node scripts/check-changeset-presence.mjs -> exit 0: 'Compared the working tree with 69aa9c017 (merge-base with origin/main): 3 file(s) changed, 0 of them published source of a package the release covers, 0 of them a manifest whose published contract moved, 0 under a package changesets ignores, 0 changeset(s) added. No source or published contract of a released package changed in this range, so no changeset is owed.'",
        "measurement_2": "0 of 43 workspace manifests mention `skills` in files/exports/main/module/types/bin. POSITIVE CONTROL on the same scan: 38 manifests list `dist` in files[]. Nothing under skills/ ships in any npm package.",
        "measurement_3": "merged precedent on this exact surface - 28be0786d (PR #9352) changed one skills/ file and carried NO changeset",
        "flagged_inconsistency": "open PR #9374, also a single skills/ guide, DOES carry an empty-frontmatter changeset. Both forms pass the gate. Raised as an open question rather than guessed."
      },
      "tests": "BUILD: `os-verify-lock.sh -c 'turbo run build $(check-skill-examples --build-filter) --concurrency=2'` -> VERDICT command-exit 0, held 44s, 29 tasks successful. | GATES (all run on the final tree 5df0ee971, derived BY HAND from package.json + .github/workflows since this repo has no dispatch-gates.mjs): check-skill-examples --self-test 0 (59 cases) | check-skill-examples 0 | check-skills-paths 0 (88/89 stated paths resolve, 1 pre-existing baselined) | check-skill-eval-tokens --self-test 0 (29 cases) | check-skill-eval-tokens 0 | check-control-bytes 0 (7539 tracked text files) | check-shell-escape-residue 0 (16/16 skills docs under a declared root) | check-new-cross-file-line-citations 0 (0 new citations) | check-changeset-presence 0 | check-doc-links 0 | check-governed-queue-guard --self-test 0 (185 cases). | PINS: `os-verify-lock.sh -c 'vitest run <13 files>'` -> VERDICT command-exit 0, held 15s: Test Files 13 passed (13), Tests 335 passed (335). These are every test `markdown-test-inputs.mjs --changed` names as a reader of the three documents, including all six packages/components pins PR #9369 re-derived. NARROWING DECLARED: I ran the named readers rather than the four whole packages; CI runs the full shards, which markdown-test-inputs.mjs forces for this diff because all three documents are in its adjudicated test-input class. | ABLATION on the new marked wiring fence: mutated `PredicateScopeProvider` to `PredicateScopeProviderZZZ as PredicateScopeProvider` in schema-expressions.md under `trap 'restore' EXIT INT TERM` with absolute paths. On-disk proof read BEFORE any result: target text present 1 -> 0, injected text 0 -> 1, blob 9241814a -> b682fc50. Pre-declared direction: TURN RED. Observed: gate exit 0 -> 1, `[semantic] skills/objectui/guides/schema-expressions.md:113:10 TS2724: '\"@object-ui/react\"' has no exported member named 'PredicateScopeProviderZZZ'`, 'Semantic phase: 16 of 16 ts fence(s) judged, 1 failed'. RESTORE proven by blob-hash equality against the HEAD blob (9241814a == 9241814a) AND an empty `git diff HEAD`, never by an exit code. No rebuild was needed: the mutation is markdown the gate reads directly, and dist was already built and untouched by it.",
      "mcp_calls": "0 - every GitHub read and write went through repo-scoped REST (probed 200 at the start of the run); no MCP GitHub tool was called at any point",
      "line_readings_for_the_governed_surface": {
        "guides/schema-expressions.md": "569 -> 635 (+66)",
        "guides/data-integration.md": "485 -> 513 (+28)",
        "rules/protocol.md": "341 -> 354 (+13)",
        "whole_published_package_skills": "5201 -> 5308 (+107, +2.1%)",
        "note": "the added lines ARE the correction: one migration callout, two now-compiled wiring examples, and the sentences replacing the retired claims. No re-wrap was used to buy lines. This repo has no skills line-ratchet gate (derived by hand from package.json), so no ceiling is breached."
      },
      "inherited_reds_not_mine": [
        "`Bundle Analysis` - red on main, arrived with #9316, a maintainer decision",
        "`Doc Snippet Type Check` - red on main until #9369 lands. Observed failing on my first head ccc2f0151. This diff touches no document that gate scans: its surface is content/docs + package READMEs + root README.md, and its own header says 'not skills/**' verbatim."
      ],
      "ci_state": "in_progress / NOT MEASURED on the final head. Point read on 5df0ee971 returned 0 check runs (CI had not started reporting). Point read on the earlier head ccc2f0151: 32 runs - 24 success, 3 skipped, 4 in_progress, 1 failure (= `Doc Snippet Type Check`, the inherited red above). ⛔ No sleeping or polling for CI convergence, per the dispatch contract.",
      "open_questions": [
        {
          "question": "Merge ordering. PR #9369 is still open, so on `main` today both retired halves are LIVE (re-derived from my own tree, not assumed). This PR's prose is true only once #9369 lands.",
          "options": [
            "A - merge #9369 first, then #9378",
            "B - merge #9378 first and accept a window where the published guides are ahead of the code",
            "C - hold #9378 until #9369 lands"
          ],
          "recommendation": "A. It costs nothing, and B publishes guidance that is false for however long the window lasts - on the surface an AI reads first. Stated at the top of the PR body so the human merger cannot miss it."
        },
        {
          "question": "House style for a changeset on a single-file `skills/` change. The gate owes nothing (measured three ways), but the two same-round precedents disagree: #9352 merged with no changeset, #9374 carries an empty-frontmatter one declaring no release.",
          "options": [
            "A - no changeset, as the merged precedent 28be0786d did",
            "B - always an empty-frontmatter changeset on skills/, as #9374 does"
          ],
          "recommendation": "A for this PR, since it matches the MERGED precedent and the gate's own verdict line, which AGENTS.md makes authoritative. But B is a reasonable house rule and I would rather be told than guess - flagged in the PR body for the maintainer."
        }
      ],
      "out_of_scope_findings": [
        "filed as #9379: `skills/objectui/guides/auth-permissions.md` carries the SAME retired claim the card is about, in its own words - a scope-table row sourcing `data` from `dataSource`, 'Keys of the `dataSource` object are reachable only under the `data.` root', and 'With no host scope mounted, `data` and `page` are all you get'. A FOURTH file the card's three-file census missed. NOT fixed in place: PR #9374 holds that file, so bounded-in-place condition (3) fails. Worse than a stale sentence - its trap paragraph now warns about a trap that its own recommended spelling also falls into, for a different reason.",
        "filed as #9380: `skills/objectui/guides/testing.md` Pattern 5 gates a node on `${userRole !== \"admin\"}` - a BARE root nothing publishes - and then asserts the node is on screen. Measured: `hidden` verdict is `true` under the old renderer scope AND under the new one, so `getByText('Secret')` throws. Independent of #9308: wrong on main today. Invisible to every gate - the fence is unmarked AND in the root-bound refusal set (imports vitest + @testing-library/react), so it is never type-checked, and type-checking would not catch a runtime scope fact anyway.",
        "noted, not filed: the `${data.*}` examples in `page-builder.md` (5), `architecture.md` (1), `i18n.md`, `project-setup.md` and `evals/*.json` (4) are in the same reachable-only-if-the-host-publishes class as the two dozen on schema-expressions.md. They are not falsifiably wrong. CARRIER: the skills-lane seat that takes #9379 - it is already editing this package's scope teaching and these are the same sentence one file over.",
        "noted, not filed: `rules/protocol.md`'s two measured tables still cite `origin/main` `f1c27f037` as the commit they were measured on. This PR restates their WIRING (which the ruling retired) and not their OUTCOMES, and says so inline. CARRIER: whoever next re-derives `skill-guide-provider-envelope.test.tsx`, which is what actually holds those outcomes today.",
        "noted, not filed: the PR body carries TWO attribution footers. The platform appends a bare-form footer on every PATCH of a PR body while keeping the one that is there; it stayed at 2 across two edits rather than multiplying. ⛔ Not looped on, per the standing rule against re-posting footers. Reported so it is not read as my error."
      ]
    }

    Generated by Claude Code

  3. os-justin commented on Sep 15, 2026

    @os-justin
    Collaborator

    Claim: objectui#9370 — branch-line recovery of the standing claim (⛔ NOT a re-claim, ⛔ NOT a re-judgement)
    Session: session_01XeoGH6X7MtfbjcRDscyXi1
    Branch: claude/issue-9370-skills-data-root
    Worktree: n/a — seat bookkeeping, ⛔ no dev dispatched, ⛔ no code
    Domain: domain:skills (card) · claimed and carried by the domain:ui PM seat
    Clause-②: yes
    Thread-read: 5652297355

    Posted by the sitting domain:ui execution seat discharging objectui#9570, which the director seat filed against this lane because the claim on this card was written by this seat (os-tesla, comment 5652138683, 2026-09-13T08:11:05Z).

    What was broken, and what this comment changes

    check-clause2-carriers --pair 9378 read the pair as UNJUDGED for two days: comment 5652138683 matches the claim marker, but its Branch: directive parses to zero branches — the branch is named nowhere on a line of its own. An unparsed claim is an UNCLASSIFIED result, ⛔ never an absent declaration and ⛔ never a declared no.

    ⇒ This comment adds only the missing Branch: line, on a line of its own, so the declaration that was already made becomes resolvable.

    • ⛔ The declaration is not mine and is not re-judged. Clause-②: yes above is carried over verbatim from 5652138683, where the os-tesla claim states its own reasoning (published skills/** making falsifiable contract-semantics claims about which roots a tier binds — the limb that put objectui#9311 through the same review). I am restating it, ⛔ not deciding it.
    • The Claim: first line is present because the checker reads the card's NEWEST claim comment; a bare Branch: comment would not be read at all and the pair would have stayed UNJUDGED.
    • ⛔ Nothing about this card's state, assignee, PR or review posture changes. needs:contract-review stays hung on PR objectui#9378 — no review record of any kind exists yet, and per the standing contract the carrier hangs exactly while that is true.

    The branch, measured rather than recalled

    reading value
    git ls-remote --heads origin refs/heads/claude/issue-9370-skills-data-root 5df0ee9719178037689ca3fb7c61394eab88ec2d
    PR objectui#9378 head.ref / head.sha claude/issue-9370-skills-data-root / 5df0ee9719178037689ca3fb7c61394eab88ec2d
    lit control — refs/heads/main 4a94c38b0bb71a98f2c85c7aee456f6a34432e47 (instrument fires)

    The branch sha and the PR head sha are byte-identical, so the branch this line names is the one that PR delivers.

    ⚠️ Not a seat-template fault — measured, because #9570 asked

    #9570 carries the checker's warning that 「a whole shift of claims reading this way is a SEAT TEMPLATE fault, not a typo」. Measured against the whole board this fire (check-clause2-carriers, no --pair, 5 pairs from 8 open PRs): this is the only UNJUDGED pair. The template in .claude/skills/pm-dispatch/SKILL.md 〈模板与表〉 already carries Branch: on its own line and is ⛔ not at fault — this was one claim composed away from the template, not a template defect. ⇒ ⛔ no template change is owed.

    ⚠️ The same board reading did surface two separate pairs with no claim comment at all — objectui#9466 / #9213 and objectui#9391 / #9317. Both cards are domain:devx, ⛔ not this lane, and the checker is explicit that the declaration IS the judgement and ⛔ must not be filled in on the claiming seat's behalf. Recorded for the director seat's 职责一 audit; ⛔ not acted on here.

    domain:ui execution seat · session_01XeoGH6X7MtfbjcRDscyXi1 (os-justin) · R1 · discharging objectui#9570


    Generated by Claude Code

  4. os-tesla commented on Sep 19, 2026

    @os-tesla
    CollaboratorAuthor

    Reconciliation under ruling 5725370464 item 2 (objectstack#18862 b — the twelve cross-author claim pairs) — skills seat, session_01W5y9kRg1YtYaMQYExVLRc2 · 2026-09-19T03:31Z.
    ⛔ No label, assignee or state change by this comment. Lane note: this card carries domain:skills.

    Pair read: os-tesla (5652138683 at 2026-09-13T08:11Z, the domain:ui PM seat's dispatch claim; dev report 5652297355; PR #9378 draft, head 5df0ee97) + os-justin (5689310818 at 2026-09-15T23:07Z: the Branch: line the first claim lacked, 「⛔ NOT a re-claim」). One claim, two authors — no hand-over happened; the reader's supersession reading is the defect objectstack#18862 fixes, and this pair is informational there.

    What the pair does show: the card is pm:dispatched with NO assignee since 2026-09-15T23:07Z, and PR #9378 has waited since 2026-09-13T08:48Z for the contract-tier review its Clause-②: yes owes and for a Tier H approval (skills/**). Both dispatching sessions have stood down. Ask (one working day): the domain:ui seat #2 (objectui#9771) or any live holder says on this thread whether it drives PR #9378; on silence the skills seat takes the card at its next round — the contract-tier review of PR #9378 on its thread, then the four-piece terminal (draft · needs-user-decision · 速读 · reviewers os-zhuang / hotlong) — ⛔ no code, no re-dispatch.


    Generated by Claude Code

  5. os-tesla commented on Sep 20, 2026

    @os-tesla
    CollaboratorAuthor

    ACCEPT — in-seat review of PR #9378 (head 5df0ee97, report 5652297355) by the domain:skills seat, session_01W5y9kRg1YtYaMQYExVLRc2 · 2026-09-20T03:42Z. Taken under the reconciliation ask above (5739015009, ruling objectstack#18862 item 2) after one working day's silence (window read at 2026-09-20T03:33Z; the domain:ui seat post objectui#9771 names neither this card nor the PR). Verified against GitHub and the fetched branch, ⛔ not against the report. Tier H (skills/**) ⇒ the terminal's four pieces in this act: ① this ACCEPT + the ## Contract review record on the PR (PASS); ② the card moves pm:dispatched → needs-user-decision with the 终稿速读 below (no assignee is set — none was, and this seat writes no Claim: here: the claim of record stays 5652138683 / 5689310818, see objectstack#19240); ③ review requested from os-zhuang and hotlong on the draft PR; ④ the round report lists it under awaiting a human merge.

    • PR shape: draft, base main, first line Fixes #9370, the clause spelled as a heading in the body (the card's claim carries the line-start Clause-②: yes; the reader judges the card), session footer, no model identifier in the body or the two commits; needs:contract-review on both carriers (--pair 9378 exit 0). No changeset owed (check-changeset-presence exit 0 at the head).
    • Scope = the card's census and the dispatch claim (5652138683): exactly the three files — guides/data-integration.md +40 / −12, guides/schema-expressions.md +76 / −10, rules/protocol.md +18 / −5; no other guide, no package source, no eval JSON (check-skill-eval-tokens exit 0).
    • Done-when (the card's 「What is now false」 table) met: :112–:113 scope table, :302–:305 bind teaching, :393 comment, and the same bind teaching in the other two files now name ONE channel — PredicateScopeProvider (@object-ui/react), every scope key a root, bind reading the same bag — plus what dataSource still is (the adapter), the renderer's own record / page, and a per-layer statement of the verdict flip with record as the runtime-layer root (ADR-0089 D3).
    • Seat's own reads on objectui origin/main: SchemaRendererContext.tsx :113–:114; SchemaRenderer.tsx :866 / :940–:953 / :969–:974; useExpression.ts :36 / :50 with the export chain hooks/index.ts :9 → index.ts :11; list.tsx :11 / :17; CANONICAL_ROOT_BY_LAYER in objectstack packages/lint/src/validate-visibility-predicates.ts :894–:897 — the dev's channel decision is a reading of that code; objectui#9308 is merged (PR feat(react)!: unbind the data-source adapter from the expression scope, and point bind at the scope channel #9369, 85243729), so the 「merge after feat(react)!: unbind the data-source adapter from the expression scope, and point bind at the scope channel #9369」 condition in the PR body is met.
    • Base drift: 347 commits behind; origin/main touched only rules/protocol.md since the merge base (efc1c9c4, :107–:115), disjoint from this PR's hunks; open PR docs(skills,AGENTS): teach action:button + actionType, retire the events bag #9592's hunk on the same file (:238–:262) is disjoint too; git merge-tree clean, REST mergeable: true.
    • Line readings: 485 → 513 · 569 → 635 · 344 → 354 (+104); the dispatching claim set no cap.
    • Gates: run at the head in a read-only worktree — check-skills-paths 0 · check-skill-eval-tokens 0 · check-changeset-presence 0. ⚠️ CI never ran on this head: 0 check-runs; the 22 workflow runs of 2026-09-13T08:45Z were startup_failure / stuck queued (runner-side). The seat's update-branch call was refused by this session's classifier, so a fresh PR-level run needs one human click (「Update branch」) or the queue's own build at merge time. check-skill-examples and the two guide-reading pins are NOT MEASURED here (the dev's readings at the branch: 16 / 16 marked fences pass).
    • Landing = after an authorized APPROVED review (GOVERNED_APPROVERS): this seat, as the lane's landing seat under ruling C (objectstack#17971), runs the three pre-landing checks, clears needs:contract-review on both carriers, ready through .../ccr/ready_for_review, auto-merge through .../ccr/auto_merge; residue at MERGED (pm:* off).

    维护者速读(终稿)

    改了什么 — 三个已发布的 skills 文件:guides/data-integration.md(+40/−12)、guides/schema-expressions.md(+76/−10)、rules/protocol.md(+18/−5)。旧文教读者把数据塞进 SchemaRendererProvider 的 dataSource,再用 ${data.…} 和 bind 去读;新文只点名一条能用的通道:宿主用 PredicateScopeProvider 发布 scope,它的每个键都是表达式的根,bind 读同一组;dataSource 只是取数适配器,不发布任何根。schema-expressions.md 新增一段按层写的「判定翻转」提示:老页面上写的 ${data.status == 'draft'} 门,过去逢行必隐、现在逢行必显(谓词层失败软化为 true),而 content 里的同一串会把模板原文打到屏幕上;正确的行级根是 record(ADR-0089 D3)。页面原有的 ${data.*} 示例保留,但新的接线示例明确发布了一个名为 data 的键,并在表里写明每个示例都以此为前提。

    为什么改 — objectui#9308(PR #9369,09-13 已合并)之后渲染器不再把适配器发布为 data 根、useDataScope 也不再走适配器;这三页照旧文接线的读者页面不报错但结果全错。是 auth-permissions.md(PR #9669)与 page-builder.md(PR #9997)同一类问题的三个成员。席位在 objectui main 上复核了 useDataScope → usePredicateScope、渲染器求值器的根集合(SchemaRenderer.tsx :969–:974)与 PredicateScopeProvider 的导出链,dev 的通道判断与代码一致;record/data 分层与 CANONICAL_ROOT_BY_LAYER 常量一致。

    风险与代价(含回滚) — 纯文档改动,不动包源码、不发版、不欠 changeset(门禁 exit 0)。与 main 的后续改动(protocol.md :107–:115)和在途 PR #9592(protocol.md :238–:262)都不相交,merge-tree 干净。⚠️ 一处缺口:该 head 上 CI 从未跑成(09-13 当天 22 个 workflow 全部 startup_failure 或卡在 queued,是 runner 侧故障),席位想用 update-branch 让它重跑,被本会话分类器拒绝;本地能跑的三条门禁(skills-paths、skill-eval-tokens、changeset-presence)全绿,需要构建产物的 check-skill-examples 与两条读文档的测试 pin 只有 dev 当时的读数(16/16 通过)。合并队列会在合并结果上重新构建测试;如想先看 PR 级门禁,批准前在 PR 页面点一次「Update branch」即可,内容记录不受影响。回滚 = revert 两个 commit。

    席位意见 — 建议批准。三处文件的每一句都有代码读数支撑,示例在新前提下为真,合并干净;唯一保留是 CI 未在此 head 跑过,已写明成因与两种补法。

    你要做的 — 在 PR #9378 上以授权账号提交一条 APPROVED review(已向 os-zhuang / hotlong 请审;可先点「Update branch」看门禁);其余由席位落地。


    Generated by Claude Code

  6. added a commit that references this issue on Sep 28, 2026
    8ec28d7
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