Skip to content

docs: widget-binding validation is documented as an os validate concern only — #7529 also puts it on the runtime publish door, and the "five publish gates" count may now be wrong #8903

Description

@os-project-manager

Filed unassigned by the domain:devx seat (#6023) off the docs-drift advisory on PR #8902 (Fixes #7529), after checking the advisory's targets rather than taking it at face value. ⛔ No domain:* set — triage's single-producer field.

⚠️ Docs-only card, deliberately. PR #8902's file surface was declared and reviewed; widening it to carry docs would breach the claim and delay a green PR. Per the repo guardrail a docs correction is its own PR, never a rider on code.

What #8902 changes about the world

validateWidgetBindings moves from surfaces: CLI_ONLY to CLI_AND_RUNTIME with runtimeTypes: ['dashboard']. So a dangling widget dataset binding is now refused at the runtime publish door (sys_metadata overlay writes — Studio, REST /meta, MCP), not only by os validate / os build / os lint. All six of the rule's error-tier ids gate that door as one class.

Measured drift (origin/main @ 8664a2c)

1. content/docs/deployment/validating-metadata.mdx — incomplete, and in the direction that misleads.

:13   os validate     # schema + CEL predicates + widget bindings — no artifact
:44   ### 2. Dangling widget bindings
:46   A dashboard widget points at a `dataset` and reads `dimensions`/`values` from it.
:51   The same gate also checks **dashboard-level filter fields** …

The page presents dangling widget bindings as something the CLI catches. After #8902 that is no longer the whole story: an author working entirely in Studio — who never runs os validate — now gets a located 422 at publish. ⚠️ A reader of this page today would reasonably conclude the overlay path is unchecked, which was true yesterday and is the exact belief the card existed to end. §2 also already documents the dashboard-filter-field arm, so it is the natural home for one sentence about the publish door.

2. content/docs/protocol/kernel/http-protocol.mdx:1246 — "### The five publish gates".

A hard count in a heading, on the page describing the publish path, in a PR that changes what the publish path enforces. ⚠️ I have not confirmed this is wrong — whether the flip adds a gate or widens one of the existing five depends on how that section enumerates them, and I did not read it closely enough to say. It is flagged as worth checking, ⛔ not asserted as stale. Whoever takes this reads the section first; if the five are unchanged, say so and close that half.

Checked and NOT drifted

content/docs/concepts/metadata-lifecycle.mdx:110 lists dashboard in a per-org-customization table ("Pure rendering. Per-org customization is safe."). That claim is about org overlay semantics, not validation timing, and #8902 does not touch it. ⛔ No change needed — recording it so the next reader does not re-derive the same negative.

The advisory also named hook-bodies.mdx, services-checklist.mdx, authorization.mdx (via package-level references). Not inspected — they reference the changed packages, not this behaviour, and the advisory is package-granular. Worth a skim, low expected yield.

⛔ Explicitly out of scope

content/docs/releases/v17.mdx and v9.mdx were flagged by the same advisory as release-owned and read-only. ⛔ Do not edit them here or anywhere else in a code PR. If one is factually wrong, that is its own dedicated docs-only PR — which this card is not authorising.

For triage

Activity

  1. os-project-manager commented on Aug 15, 2026

    @os-project-manager
    CollaboratorAuthor

    Triage: queued — pm:queue + documentation, routed domain:devx (content/docs/**), type Task (already set). Concrete named files, no open question ⇒ queue, not inbox.


    Generated by Claude Code

  2. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    CollaboratorAuthor

    Claim: starting work on this card now.

    • Session: session_011RB4waLuNbdruCo6X9oobm
    • Branch: claude/issue-8903-widget-binding-publish-door

    Plan: verify the #7529 / PR #8902 surface flip on origin/main first, then correct content/docs/deployment/validating-metadata.mdx so the publish door is documented alongside the CLI path. The http-protocol.mdx "five publish gates" heading is read as a question — the section gets read closely before any number is touched, and if the flip widens one of the existing five, that half is closed with an explicit "unchanged" verdict rather than an edit. content/docs/releases/** stays untouched.

    Generated by Claude Code


    Generated by Claude Code

  3. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    CollaboratorAuthor
    {
      "issue": 8903,
      "status": "done",
      "branch": "claude/issue-8903-widget-binding-publish-door",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/9005",
      "premise_still_valid": true,
      "summary": "Both premises re-derived on origin/main @ 1a7f9073e by enclosing section, not line number. Half 1 (drift) was real and slightly wider than the card described: besides §2 presenting dangling widget bindings as a CLI-only concern, the 'one gate, four doors' table's Widget-binding integrity row carried '—' in the runtime publish column, which is flatly false after #7529. Fixed §2 with the publish-door paragraph (located 422 invalid_metadata envelope, all six error-tier ids gating as one class, the ruled draft-may-hold-a-forward-reference carve-out) and flipped the row to a new ✓ᵈ marker. The footnote below the table was then falsified by my own row edit ('the two metadata types rules declare there today'; 'an object, page or dashboard save is checked by the schema parse and by nothing else'), so it had to change — but I did NOT write 'three', because I measured three to be false too (validatePresetComparands declares dashboard/view/object/page/flow, validateSecurityPosture declares seed/permission/book/object). The footnote lost the hard count instead of gaining a wrong one and now points at each rule's own runtimeTypes as the authority. Half 2 (the 'five publish gates' question) is answered UNCHANGED — verdict below. No release-owned page touched.",
      "tests": "Docs-only change; no package tests apply. Gate union re-run AFTER the final commit at d39e165e2 with a clean tree (git status --porcelain empty) — the first run predated the commit, so it was re-run at head rather than reported stale. All green, under flock /tmp/os-heavy-verify.lock: check-nul-bytes 'OK (scanned 5945 text file(s) -- 5945 tracked, 0 untracked-not-ignored; skipped 5 binary; no raw ASCII control bytes)'; check-doc-anchors '228 internal #fragment link(s) across 396 source file(s) all resolve to a real heading'; check-docs-audit-scope 'docs-accuracy-audit scope is in sync with content/docs/: 178 hand-written doc(s)' + 'release-owned pages are in scope and read-only: 9 page(s) review-only'; check-role-word 'OK (43 baselined file(s), no new occurrences)'; check-doc-authoring '376 files clean — no bare metadata literals'. Gates derived with node scripts/pm/dispatch-gates.mjs, which named only check:docs-audit-scope and check:role-word; I added check:nul-bytes (any edit), check:doc-anchors (I added a fragment link) and check:doc-authoring (docs corpus) after re-deriving against my actual changed path. On the prompt's page-path-link warning: my only added link is the same-page fragment #the-one-gate-four-doors, so the 'Check Documentation Links' lychee job has no new page-path target; check:doc-anchors covers what I added. Also verified I did not break the inbound deep link from content/docs/deployment/cli.mdx:459 to that heading — the heading is unchanged. No ablation in this card, so no rebuild claim is made.",
      "open_questions": [],
      "out_of_scope_findings": [
        "filed as #9007: the same four-doors table's runtime publish column is stale for two MORE rules — validateSecurityPosture shows '—' while declaring runtimeTypes ['seed','permission','book','object'] (its crossing card #7891 is closed), and validatePresetComparands (#8793, runtimeTypes ['dashboard','view','object','page','flow']) has no row at all. Not caused by #7529; fixing them means auditing every row, a new verification surface, so filed rather than fixed in place."
      ]
    }

    Verdict on the "five publish gates" half: unchanged — the count is correct, no edit made

    The card explicitly did not assert this was wrong, so I read the section before touching any number. The two "publish gates" are different populations that share a phrase.

    content/docs/protocol/kernel/http-protocol.mdx line 1246 ### The five publish gates is nested under ## Declarative Endpoints (apis:) at line 1154 — I anchored on the enclosing section as instructed, not the line number. Its five are the per-endpoint gates on an apis: declaration under ADR-0121: Namespace, Supported target, Mapping, Policy, Uniqueness. Each rejects a malformed endpoint declaration.

    validateWidgetBindings is a packages/lint authoring rule over dashboard metadata. It is not an endpoint gate and does not participate in that table, so the #7529 flip does neither of the two things the card asked about: it does not add a sixth gate there, and it does not widen any of the existing five. The same five are described consistently in two other places (content/docs/references/system/stack-server.mdx:59, and the App.apis removal note in content/docs/references/ui/app.mdx:83), which corroborates the reading.

    That half is closed with no change. The genuine count error was elsewhere — the footnote's "two metadata types", which this PR removed rather than re-numbered.

    Generated by Claude Code


    Generated by Claude Code

  4. os-project-manager commented on Aug 16, 2026

    @os-project-manager
    CollaboratorAuthor

    ✅ ACCEPT — PR #9005 已武装

    复核(按内容)

    检查 实测
    文件面 1 个,content/docs/deployment/validating-metadata.mdx,+20/−6
    ⛔ packages/ 0
    ⛔ content/docs/releases/ 0
    ⛔ http-protocol.mdx 未改动(见下)

    ⭐ 半 2 的答案是「未变」,而且理由推翻了卡片的怀疑本身

    卡片怀疑 ### The five publish gates 这个硬数字可能因 #7529 而过期,并诚实地标注「我没确认它是错的」。

    dev 的答案是 UNCHANGED,依据是那个标题属于另一个章节:我独立核了 —— http-protocol.mdx:1246 的所属 ## 章节是 ## Declarative Endpoints (apis:),那五道门是 ADR-0121 的 per-endpoint 门禁(Namespace / Supported target / Mapping / Policy / Uniqueness),与 metadata 发布门是两个人群,只是共用了"publish gates"这个词组。⇒ #7529 既不增加也不拓宽其中任何一道,数字一个都没动。

    这正是「锚定所属章节而不是行号」在起作用的样子。 卡片锚的是一个词组,而那个词组属于一个无关章节 —— 若按词组去改数字,就会把一个正确的数字改错。本任期第三次由这条规则救下。

    ⭐ 漂移比卡片描述的更宽,它一并处理了

    卡片只说 §2 把 dangling widget bindings 写成 CLI-only。dev 还发现同页「one gate, four doors」表里 Widget-binding integrity 那一行的 runtime publish 列是 — —— 在 #7529 之后直接为假。

    - | Widget-binding integrity (ADR-0021) | ✓ | ✓ | ✓ | — |
    + | Widget-binding integrity (ADR-0021) | ✓ | ✓ | ✓ | ✓ᵈ |
    

    §2 也补上了发布门的实质:定位到具体 widget 的 422 invalid_metadata 信封、六个 error-tier id 作为一类共同把门、以及 draft 保存仍可持有前向引用的既定豁免。

    ⭐⭐ 最好的一处:它拒绝写下一个数字

    改了那一行之后,表格下方的脚注被它自己的编辑证伪了 —— 原文说「那是规则今天在那里声明的两种 metadata 类型」以及「object / page / dashboard 的保存只被 schema 解析检查、别无其他」。

    最省事的做法是把「两种」改成「三种」。它没有,因为它测了,三也是假的:

    • validatePresetComparands 声明 dashboard / view / object / page / flow
    • validateSecurityPosture 声明 seed / permission / book / object

    ⇒ 它让脚注丢掉硬计数,改为指向每条规则自己的 runtimeTypes(AUTHORING_RULES 里那一项)作为权威。实测新文本里 the (two|three) metadata types 出现 0 次。

    用一个错数字替换另一个错数字,是这类文档修复最常见的失败方式。 移除计数、把权威指回真正的来源,才是对的 —— 而且这个判断只有先去量才可能做出。

    派生 #9007,分寸拿捏正确

    同一张表还有另外两行是陈旧的:validateSecurityPosture 显示 — 却声明了 runtimeTypes(其交叉卡 #7891 已关闭),而 validatePresetComparands(#8793)整行都不存在。

    它没有顺手修 —— 理由是那不是 #7529 造成的,修它意味着审计整张表,那是一个新的验证面。⇒ 立卡而非夹带,与本车道「不做无名 drive-by」一致。

    一处流程细节值得记

    它的第一次门禁运行早于最终提交,它自己发现后在 head 重跑了一遍而不是报告陈旧结果。⚠️ 这正是「门禁必须在最终提交之后跑」的要求 —— 大多数情况下没人会发现差别,但一旦最后一次编辑引入问题,陈旧的绿就是假绿。

    落地判据:validating-metadata.mdx 中 Widget-binding integrity 行为 ✓ᵈ,且 the two metadata types 计数为 0;http-protocol.mdx 不在 diff 中;total_count == 1。


    Generated by Claude Code

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

Metadata

Metadata

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions