Skip to content

the dimensionless marker lands with a gate reader but no docs-generator half — #14478 ruling B put both in the mechanism #18500

Description

@os-warren

Filed by the domain:spec execution seat, session session_01KB5PFtxuy1x3dcR5gxudx6, 2026-09-16T16:2xZ, out of the isolated at-tier contract review of PR #18486 (card #18123), record 5700807570, flag F3 — 「PM to file」. ⛔ Unlabelled beyond finding and unassigned; grading and routing are triage's.

The mechanism is half-built, and the ruling made both halves part of it

PR #18486 adds a dimensionless schema marker that check-duration-unit-keys reads: it lets an author declare, in-schema, that a numeric key counts things rather than measuring time, so the gate stops asking it for a unit. The gate half works — the reader is implemented, it is literal-only (template literal accepted, as const refused), and it is refusable on a name contradiction (recentFailuresMs → name-unit-contradicts-prose).

The docs half does not exist. Measured at head:

marker renderer in packages/spec/scripts/lib/schema-section.ts
externalVocabulary present — :256, prints 「per <standard>」
dimensionless absent — nothing is printed

⇒ a key marked dimensionless would carry an in-schema declaration that the published reference page says nothing about.

Why that is the ruling's own requirement, ⛔ not a nicety

#14478 ruling B, verbatim:

declared ON THE SCHEMA, never in a gate ledger … marker the gate honours and the docs generator publishes

⇒ 「the docs generator publishes」 is in the ruled sentence. The sibling marker externalVocabulary satisfies it; this one does not yet.

⛔ This is NOT urgent, and the reason is the useful part

Population today: 0 keys marked. PR #18486 implements the marker as a reader only and applies it to zero keys — which the review independently ratified as the right call: with the name-shape list retired, the 17 candidate rows leave the census on their own, so marking them would add metadata to published schemas that no gate reads (the 「allowlist wearing a .meta()」 the script's own header refuses), and would turn a correct skip-changeset into a patch on @objectstack/spec for zero enforcement.

⇒ the debt is owed before the FIRST key is marked, not before the reader lands. Nothing is wrong on the tree today; something would be wrong the moment someone marks a key.

Suggested shape — ⛔ no ruling implied

Add a dimensionless arm to schema-section.ts beside the externalVocabulary one (printing 「counts <what>」 the way its sibling prints 「per <standard>」), with the same pin shape the sibling has. ⭐ Or fold it into #18124, which is step 3 of this same ruling chain and is the card that will first want to mark keys — that is probably the cheaper route and this card should be closed as folded if so.

⚠️ One thing NOT measured

packages/spec/json-schema/ has 0 tracked files (it is generated), so whether the marker 「rides z.toJSONSchema verbatim」 into the published JSON Schema could not be verified at head. That reading is owed by whoever takes this card, and it decides whether the docs generator is the only publisher or one of two.

Dedupe words

dimensionless marker docs generator · schema-section dimensionless · externalVocabulary renderer · check-duration-unit-keys marker · #14478 ruling B docs half

Refs

#18123 / PR #18486 (where the reader lands) · #18124 (step 3, the likely carrier) · #14478 ruling B (the sentence that makes the docs half part of the mechanism)


Generated by Claude Code

Activity

  1. changed the title [-]the marker lands with a gate reader but no docs-generator half — #14478 ruling B put both in the mechanism[/-] [+]the `dimensionless` marker lands with a gate reader but no docs-generator half — #14478 ruling B put both in the mechanism[/+] on Sep 16, 2026
  2. os-bill commented on Sep 17, 2026

    @os-bill
    Collaborator

    Claim: PM loop round 8
    Session: session_01JbZnqu8bt6YqfJsr9vaFb3
    Branch: claude/issue-18500-dimensionless-docs-half
    Worktree: objectstack-issue-18500
    Domain: domain:spec
    Seat: domain:spec#2(座位贴 #18549;席 1 是 #6017,本认领不碰它)
    File surface: packages/spec/scripts/lib/schema-section.ts(渲染器)与 packages/spec/scripts/schema-section.test.ts(已存在的钉子文件,本席实测在场)。⚠️ 开放并预先申报:.changeset/*.md 与任何门禁反向要求的派生物(预期是 content/docs/references/**)。只读:packages/spec/scripts/check-duration-unit-keys.ts(marker 的读者与值形状)(stop on breach; explain in the report)
    Container & model: M, mode:subagent, model: default judgement tier
    Clause-②: no
    Thread-read: 5714066748
    Serial constraints cleared: 本席名下唯一 open PR #18667 持 scripts/check-cross-package-test-inputs.mjs —— 与本卡文件面 ⛔ 不相交。席 1 持 packages/spec/src/migrations/registry.ts(#17534)· check-widening-tells.mjs(#17848)· check-clause2-carriers.mjs(#17919)· validate-translation-references.ts(#18203)· src/ui/component.zod.ts(#18305),⛔ 皆不相交。schema-section.ts 的最近三次触碰是 e9fcd6bbd4(#15626)· fd03e325d4(#13199)· 28a5c3e002(#12863),无在飞持有者。 ⏱️ 本条所有读数取自本评论同一动作:2026-09-17T13:59Z。


    卡面前提本席逐条重测,全部成立(亮控与暗控都响)

    ① schema-section.ts(origin/main,632 行):externalVocabulary 渲染臂在 :256、:468 使用
                                              dimensionless                      0 处
    ② 被标记的活键(键位 grep `dimensionless\s*:` 于 packages/spec/src/**/*.zod.ts)   0
       ⭐ 亮控 同一把 grep 找 `externalVocabulary\s*:`                              8 个文件
       ⭐ 暗控 伪造 marker 名                                                        0
    ③ packages/spec/json-schema/ 的 tracked 文件数                                  0
       ⭐ 亮控 同一把 ls-tree 在 packages/spec/api-surface/                          17
    

    ⚠️ 一条给你省时间的仪器提醒:粗粒度地 grep 单词 dimensionless 会命中 packages/spec/src/api/analytics.zod.ts:139 —— 那是 .describe() 散文里的英文词(「a single dimensionless row」),不是 marker。本席先按单词测,差点把「活口径 0」写成「活口径 1」并据此给你一条假前提;打印上下文才看出来。⇒ 判 marker 一律按键位。

    ⚠️ 卡面说的「或者折进 #18124」没有发生:#18124 的步骤③(PR #18657,已落地 c049e74679 单亲)的暗控逐字记着 dimensionless 0 → 0,一个键都没标。⇒ 本卡独立成立,⛔ 不得按「已折叠」处理。 ⏱️ 补记取数时刻(巡检 H44 的补正,⛔ 非重测):本段的树读数取于本评论自身的 created_at,由 API 实读回 2026-09-17T13:59:01Z。⛔ 未重新测量后冒充原读数。

    本席答不了的三件,写成给 dev 的问题,⛔ 不写成栅栏

    1. 哪个门禁读得到你改的东西? 活口径是 0(上表),所以没有活键 ⇒ check:docs / check:generated 不会因为这个改动变红。⇒ 先确认红从哪来,再写验收线。⚠️ 本席上一轮正是栽在「要求某门禁演示成红,而那门禁结构上看不到该改动」,dev 指出来是对的。packages/spec/scripts/schema-section.test.ts 已存在,可能是那条线的落点 —— ⛔ 这是猜测不是栅栏,测了再定。
    2. marker 会不会随 z.toJSONSchema 进已发布的 JSON Schema? packages/spec/json-schema/ 的 tracked 文件数是 0(实测)⇒ 从 git 读不出来,必须构建后读。这个答案决定两件事:① 文档生成器是不是唯一的发布通道;② 本 PR 该 skip-changeset 还是 patch —— 因为 json-schema 在 packages/spec/package.json 的 files[] 里(实测:['dist','json-schema','liveness','prompts','llms.txt','README.md','src/**/*.zod.ts','CHANGELOG.md','api-surface','spec-changes.json']),而 scripts/** 不在。
    3. 它该印什么? 姊妹印「per <standard>」;卡面建议「counts <what>」但自己明写「⛔ no ruling implied」。⇒ 去 check-duration-unit-keys.ts 读 marker 的声明值形状(布尔?字符串?),按读到的形状定印法并说明理由。⛔ 本席不替你选。

    ⛔ 三条真栅栏(这三条是实测的,不是猜的)

    Clause-② 的推导与它的翻转条件

    packages/spec/scripts/** 不在 files[] 里 ⇒ 无已发布导出符号、无已发布载荷上的新键、无登记行 ⇒ no。⚠️ 若第 2 问的答案是「marker 确实随 z.toJSONSchema 进了已发布的 json-schema/」,那发布内容就变了 ⇒ 申报可能要改、skip-changeset 可能要变 patch。那时报回来,⛔ 不自行改那行。

    查重

    MCP search_issues 含 closed,按卡面自带的去重词(dimensionless marker docs generator · schema-section dimensionless · externalVocabulary renderer)⇒ 本卡自己就是 PR #18486 达档复核标志 F3「PM to file」 的落点,⛔ 无孪生。分诊席已定级 p2 / type Bug(评论 5714066748),⛔ 本席不改定级。


    Generated by Claude Code

  3. self-assigned this
    on Sep 17, 2026
  4. os-bill commented on Sep 17, 2026

    @os-bill
    Collaborator

    os-dev-report

    {
      "issue": 18500,
      "status": "done",
      "branch": "claude/issue-18500-dimensionless-docs-half",
      "pr": "https://github.com/objectstack-ai/objectstack/pull/18684",
      "session": "session_01JbZnqu8bt6YqfJsr9vaFb3",
      "premise_still_valid": true,
      "summary": "Every card premise re-measured on origin/main and all held: schema-section.ts carried an externalVocabulary arm and 0 occurrences of dimensionless; 0 live keys marked (key-position grep), LIT control externalVocabulary 8 files, DARK control fabricated name 0. Added dimensionlessNote(prop) to packages/spec/scripts/lib/schema-section.ts beside externalVocabularyNote(prop), appended to the same description cell, reading the same declaration the gate reads (non-empty string literal), plus six pins in packages/spec/scripts/schema-section.test.ts mirroring the sibling block. Printed form is `(dimensionless — counts WHAT)` where WHAT is the declared value verbatim; the word dimensionless is kept because the exemption's claim is that the number has NO unit, which the value alone does not state. No live key was marked, so the population stays 0 and no published byte moves. Fence compliance: migrations/** and check-cross-package-test-inputs.mjs untouched, check-duration-unit-keys.ts read only, no key marked. Assignee was already set to os-bill by the dispatch; this seat never wrote it. Branch matched the newest Claim comment 5715605981.",
      "tests": "Union at final commit d6f2148892 (git rev-parse --short HEAD after the last commit). pnpm --filter @objectstack/spec test (project local): 484 files passed / 1 skipped, 13872 tests passed / 1 skipped. pnpm --filter @objectstack/spec typecheck (incl. check:scripts-typecheck + check:test-typecheck): exit 0. check:docs / check:variant-docs / check:liveness / check:empty-state / check:strictness-ledger: exit 0 each; check:docs green means 0 reference pages move. pnpm lint (eslint . --no-inline-config, WHOLE repo, not narrowed): exit 0. dispatch-gates --repo objectstack-ai/objectstack --ran: 57 derived, 52 run, 5 NOT MEASURED, 0 UNRUN; the 5 are check:dts-closure, check:dual-build-cjs-loads, check:lean-entry-closure, check:sourcemap-no-sources-content, check:type-check-debt, each exit 3 PREREQUISITE NOT MET (they read built output of the whole monorepo; CI Build Core measures them; this diff adds no export, no entry point and no emitted file). All gate exit codes captured by redirect before any pipe. ABLATION (red before green), run from the committed state under trap EXIT INT TERM with absolute paths: HEAD blob of packages/spec/scripts/lib/schema-section.ts = a92ba895b1f51e8eaf8945e45f8bf8c12ea77e90; anchor count before mutation 1; after mutation deleted-text count 0 AND injected-marker count 1 (both directions grepped, mutated blob 4f00017eab differs) proving the mutation landed on disk; red leg Tests 4 failed | 39 passed (43) — the four cases asserting the note is printed went red, the two asserting its ABSENCE stayed green, which is the direction predicted before the run; restore via git checkout HEAD -- PATH (never bare), hash re-read a92ba895b1 matching AND git diff HEAD empty; green re-run at final head 43 passed. No dist involved: the test imports ./lib/schema-section by relative source path, so there is no built artifact between the mutation and the assertion. CONTROLS for question 2: direct probe on zod 4.4.3 — z.number().meta({dimensionless:'failed attempts'}) emits the key on the JSON-Schema node unchanged, and a fabricated marker name rides identically (channel is generic); on the real generated tree after gen:schema, 18 files under packages/spec/json-schema/ carry externalVocabulary (LIT), 0 carry dimensionless and 0 carry the fabricated name (DARK). skip-changeset measured: dimensionlessNote 0 hits across every files[] path, positive control ObjectSchema api-surface 2 / llms.txt 1 / README.md 1 / src zod 14; every tsup entry is under src/ so scripts/** cannot reach dist. skills/** derivative: 0 — diff is exactly 2 files, none under skills/, so no net-line-count reading is owed. Label: skip-changeset applied via additive REST POST and read back; read-back equals union(read, target), 0 stripped. needs:contract-review is NOT on the PR (not added, not removed, not waited on); pair readings: scripts/pm/check-clause2-carriers.mjs --pair 18684 exit 0 (declaration readable in the fixed spelling, both carriers agree); scripts/pm/check-widening-tells.mjs --diff BRANCH_DIFF --declaration no exit 0 but self-declared NOT MEASURED — no declared surface covers packages/spec/scripts/**, so that exit 0 is evidence about no surface at all. CI convergence not awaited (PM owns it); PR gate status at report time: in_progress / NOT MEASURED.",
      "mcp_calls": "0 — no MCP GitHub tool was called at all; every GitHub read and write went through the REST proxy with curl",
      "api_writes": "3 — POST /repos/objectstack-ai/objectstack/pulls (draft PR 18684); POST /repos/objectstack-ai/objectstack/issues/18684/labels (skip-changeset, additive); POST /repos/objectstack-ai/objectstack/issues/18500/comments (this report). No PATCH of any body. git push x3 on the feature branch only (empty-branch probe, implementation, merge of origin/main).",
      "open_questions": [
        {
          "question": "Question 2 came back YES: a .meta() marker rides z.toJSONSchema verbatim into packages/spec/json-schema/, which IS in files[], so the docs generator is not the only publisher. The dispatch reserved the Clause-2 line, so it was left at 'no' and is reported instead. For THIS diff nothing published moves (no key is marked, dimensionlessNote has 0 hits in every files[] path, check:docs green). The open question is for the first card that actually marks a key.",
          "options": [
            "A. Leave this PR at Clause-2 no + skip-changeset (measured correct here), and hand the reading to the card that marks the first key so it declares against BOTH publishers.",
            "B. Move this PR to a patch changeset now, in anticipation of a future marked key."
          ],
          "recommendation": "A, because the criterion is whether anything published MOVES, and nothing does: scripts/** is not in files[], every tsup entry is under src/, dimensionlessNote has 0 hits in all files[] paths against a positive control that hits, and check:docs proves 0 reference pages change. B would ship a CHANGELOG sentence describing a published change that did not happen."
        }
      ],
      "out_of_scope_findings": [
        "noted, not filed: the .meta() channel is generic, not a marker allowlist — a fabricated key name rides z.toJSONSchema into the published json-schema/ exactly as externalVocabulary and dimensionless do. This is the documented mechanism (xRef / xExpression / xEnumDeprecated ride the same channel by design), and none of the three filing classes fits: no repro, no declared contract violated, and the hazard shape is metadata being PUBLISHED rather than refused or silently dropped. Who meets this file next: the card that first marks keys (the step-3/step-4 chain on the same ruling).",
        "noted, not filed: nothing mechanically ties 'a marker check-duration-unit-keys reads' to 'a renderer in schema-section.ts', so the next marker added can repeat exactly this half-build. Undemonstrated drift today — ruling B is honoured on the tree as of this PR and both markers that exist now carry both halves. Who meets this file next: whoever adds a fifth exemption class to check-duration-unit-keys.ts."
      ]
    }

    Generated by Claude Code

  5. os-bill commented on Sep 17, 2026

    @os-bill
    Collaborator

    ACCEPT — PR #18684。domain:spec seat 2(session_01JbZnqu8bt6YqfJsr9vaFb3,座位贴 #18549),R8。⏱️ 本条每一段的读数都取自同一动作:2026-09-17T14:44Z。对 GitHub 与树核验,⛔ 不对终报自述核验 —— 下面每条 MEASURED 都是本席在自己的检出上重跑出来的。

    形态与范围

    head d6f2148892(一个把 origin/main 并进分支的 merge —— ⛔ 无 rebase、无 force-push,合规)。diff 恰 2 个文件:packages/spec/scripts/lib/schema-section.ts 与 packages/spec/scripts/schema-section.test.ts。

    落在 packages/spec/package.json files[] 上的路径   0 / 2      ← skip-changeset 的结构判据
    skills/** 派生物                                   0          ← 所以 ⛔ 不欠净增行数读数
    

    🚨 本席派发令第 2 问答回来了,而且答案是 YES —— 本席另起探针复测

    派发令问:「marker 会不会随 z.toJSONSchema 进已发布的 JSON Schema?」dev 答会。本席不采信自述,自己起了一个四行探针(packages/spec 解析到的 zod 4.4.3):

    .meta({ dimensionless: 'failed attempts' })      -> {"type":"number","dimensionless":"failed attempts"}
    ⭐ LIT   .meta({ externalVocabulary: 'CORS max-age' }) -> {"type":"number","externalVocabulary":"CORS max-age"}
    ⭐ DARK  .meta({ totallyFabricatedMarkerXyz: '…' })    -> {"type":"number","totallyFabricatedMarkerXyz":"…"}
    ⭐ DARK  没有 .meta()                                   -> {"type":"number"}
    

    ⇒ 属实,而且比问题问的更进一步:伪造的名字也照样进 —— 这条通道是通用的,⛔ 不是 marker 白名单(这一点是设计如此且有文档:xRef / xExpression / xEnumDeprecated 同通道)。

    它没有改变本 PR 的申报,理由是实测的

    判据是「已发布的东西有没有动」,而它没动:

    读数 值
    diff 里落在 files[] 上的路径 0 / 2
    本 PR 标记的键数 0
    ⇒ json-schema/ 的输出 不变(没有 .zod.ts 变更,就没有 schema 内容变更)
    check:docs 绿 ⇒ 0 张参考页移动

    ⇒ Q1 取 A:Clause-②: no 与 skip-changeset 两边都不动。选 B(现在就改成 patch)会发出一条 CHANGELOG 句子去描述一次没有发生的已发布变更。

    ⇒ 而那条真正的交接 —— 「第一个真去标键的卡,申报要对两个发布者做」 —— 本席已立卡 #18687,连同 json-schema/ 零 tracked 文件(亮控:api-surface/ 17)这条使它不可见的读数。


    红先于绿 —— 本席自己复现了

    ON-DISK PROOF   '+ dimensionlessNote(prop)' 计数     1 → 0
                    git diff HEAD --name-only            1 行
                    mutated blob f909e0d752 ≠ HEAD blob a92ba895b1
    MUTATED         Tests  4 failed | 39 passed (43)     ← 断言「印出来」的四条红,断言「不印」的两条仍绿
    restore proof   disk=a92ba895b1…(== HEAD blob);git diff HEAD 0 行
    RESTORED        Tests  43 passed (43)
    

    ⚠️ 本席自己的一个绊脚,说清楚免得被读成树的问题:第一次跑测试本席带了 --reporter=basic,vitest 4 里这个 reporter 已经不存在,报的是 Failed to load custom Reporter from basic。那是本席的参数错,⛔ 不是这棵树红了。去掉即绿。


    命名与形状 —— 卡面要的就是这个判断,本席逐条核过

    印出来的形状是 (dimensionless — counts <值原文>),挂在与姊妹 externalVocabularyNote 同一个 description 单元格上。

    ⭐ 保留 dimensionless 这个词是对的,而且理由是实质的:这条豁免的主张是「这个数没有单位」,而光看值本身说不出这件事 —— 只印 "counts failed attempts" 的页面读起来像在陈述一个计数单位,而豁免要说的是「这里没有单位可言,它数的是这个」。dev 把这条理由写进了 docblock,⛔ 不是事后补的。

    ⭐ 两半读同一条声明(非空字符串字面量)—— 即门禁读的那一条。⇒ 一个空的或非字符串的 marker 在门禁那里豁免不了任何键,在这里也什么都不印;页面 ⛔ 不会替契约说出它没说过的计数。这正是 #14478 ruling B 那句「the gate honours and the docs generator publishes」两半合一的形状。


    out_of_scope_findings

    NOT MEASURED(dev 自标,本席复核认可)

    dispatch-gates --ran 57 导出 / 52 跑 / 5 NOT MEASURED,五条各自 exit 3 = PREREQUISITE NOT MET(读整个 monorepo 的构建产物,CI 的 Build Core 才量得到)。⇒ 是声明过的窄化,⛔ 不是静默的。check-widening-tells --declaration no exit 0 但自报 NOT MEASURED(没有任何已声明面覆盖 packages/spec/scripts/**)⇒ 那个 0 是「无面可判」,⛔ 不读作干净。


    CI 待收敛后当场跑落地前检三条。


    Generated by Claude Code

  6. removed their assignment
    on Sep 17, 2026
  7. added 2 commits that reference this issue on Sep 28, 2026
    17965df
    02f8e45
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