You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit 2bdb81f
Browse filesBrowse the repository at this point in the historyBrowse files
fix(spec): re-measure the ComponentPropsMap objectui read-point records at the live pin and make them assertable (#19743)
Part of #18459 (items N3 and N4). Item N1 was already repaired on `main`
before this round and item N2 landed as PR #19675; this PR carries the
two the previous seat deliberately left on the card. Whether the card
can be retired afterwards is triage's call, so ⛔ no closing keyword here
— the repo-wide remainder is measured at the bottom.
Clause-②: no
⚠️ **Fourth seat correction at 2026-09-22T23:07Z, after the at-tier
review `5785756910` at head `95987e2722` (**VERDICT: PASS**, blocking:
none).** Five passages were stale against this head and are fixed below;
round 4 is now recorded. ⛔ **Three of the five are the seat’s own, and
one of them is the same failure mode a third time:** an earlier revision
of this line said the `95 → 102` worklist figure was 「superseded by
**104**」 — while the passage further down still read **102**. ⭐ That is
**a partial correction inside the body**: a correction header that
updates a number the body itself does not. Both are superseded by the
**110** measured at this head. The seat’s two earlier slips of the same
shape are kept on the record below rather than tidied away.
⚠️ **Second seat correction at 2026-09-22T20:39Z, after the at-tier
review `5783719817`.** Three claims in this body were wrong or imprecise
and are fixed below rather than left standing: the retired-pin
reachability sentence (⛔ the seat’s own, and WRONG — see the acceptance
notes), the gate-invisible count’s semantic scope, and which anchor
count the `--verify-anchors` line was quoting.
⚠️ **Body corrected by the seat at 2026-09-22T18:44Z, at head
`60f75eeb27`.** Four anchors were wrong in the text above and are fixed
here: `ListView.tsx:3271`→`:3270` (the flatten resolving `titleField`
into `labelField`; `:3271` is `fields:`), `ObjectMap.tsx`
`:149-157`→`:150-157` (`:149` is a blank comment line),
`ObjectMap.tsx:159-161`→`:159-160` (the quoted sentence ends at `:160`),
and the gate-invisible-citation acceptance note is re-measured below.
All four were re-read by the seat against `git show
87af769e9a3e:<path>`, ⛔ not carried from the round report.
## What this is
`packages/spec/src` carries READ-POINT RECORDS: docblocks that say "this
key is LIVE, and here is the objectui `file:line` that reads it". Each
anchors itself to the objectui tree its numbers were counted in, and
`check:objectui-pin-citations` recognises two spellings for that anchor:
| spelling | what it claims | what the gate does |
|:--|:--|:--|
| ASSERTING — `` `.objectui-sha` = `<sha>` `` | this IS the pin we build
against | checked against the pin file on every run; a pin bump reds on
it |
| HISTORICAL — `` `.objectui-sha` pin `<sha>` `` | measured AT that pin,
a dated record | permitted, and re-checked by nothing, ever |
Eleven records in `ui/component.zod.ts` and `ui/component.test.ts` were
in the historical spelling naming the RETIRED pin `53ded82b`, although
every one of them is a live read-point record whose whole purpose is to
stay re-checkable. Each was re-READ against objectui at `87af769e9a3e`
and converted to the asserting spelling.
⛔ This is a RE-MEASUREMENT, not a spelling change: the asserting form
ASSERTS the anchors hold at the live pin, so nothing was converted that
was not opened and read in the pinned tree. Every anchor in this diff
was re-derived from `git show 87af769e9a3e:<path>`; ⛔ none was carried.
## Item N3 — the two anchors, as measured here
⛔ The card's own proposed corrections (`:1871`, `:500`) were themselves
taken at the retired pin. The previous seat's handover gave `:503` and
`:2181`. **Both re-measured here and both confirmed:**
| citation | card proposed | measured at `87af769e9a3e` |
|:--|:--|:--|
| `component.test.ts` gantt read set, `label` | `:1871` | **`:2181`** —
`?? resolveInlineI18nLabel(schema.label, displayLocale)`, the one
`schema.label` read outside comments in the file |
| `component.test.ts` config-block test, the gantt safeParse | `:500` |
**`:503`** — `const result = GanttConfigSchema.safeParse(config);`,
inside the `getGanttConfig` branch that opens at `:501` |
⚠️ Correcting only those two numbers would have left a record whose
header named one pin and whose numbers named two. So the whole describe
block was re-measured and its citation converted — which is also this
file's share of N4.
⭐ **The card’s retired-pin story IS verified now, and an earlier
sentence here was wrong.** This line used to say the story 「could NOT be
verified … `53ded82b` is unreachable … NOT MEASURED」. ⛔ Both halves are
false: `53ded82b` is a **readable commit** in the sibling checkout (`git
cat-file -t` → `commit`), and the at-tier review read the card’s own
numbers there — `ObjectGantt.tsx:1871` at `53ded82b` **IS** `??
resolveInlineI18nLabel(schema.label, displayLocale)` (that file’s only
non-comment `schema.label` read at that pin) and `:500` **IS**
`GanttConfigSchema.safeParse(config)`. ⇒ **the card’s `:1871` / `:500`
were correct RETIRED-pin readings**, and the handover’s `:2181` / `:503`
are the live-pin ones. ⚠️ The seat’s 2026-09-22T20:39Z correction fixed
the acceptance-notes version of this claim and **left this sentence
standing** — a partial correction, which is the defect this PR keeps
finding in others.
## Item N4 — what converted, and what the re-read found
⭐ **Round 3 (head `872e06ddf6`) — recorded here because the narrative
below stops at `60f75eeb27`.** Three comment-only edits: the blocking
`ObjectTimeline.tsx` anchor re-pointed `:518` → `:706-708` **with its
file spelled** (`:518` is the gate at the RETIRED pin and a comment line
at the live one — a carried reading on a line the conversion never
touched); the bare `ObjectView.tsx:1725` spelled `plugin-view/src/…`
(two such files exist at the pin and the gate refuses an ambiguous
suffix); and the `ElementDataSourceGate` count corrected with its method
(above). ⭐ The round also re-audited **every anchor in every converted
record end to end — the whole block, not the diff hunks** — 183
occurrences at `60f75eeb27`, 186 at `872e06ddf6`, **0 unresolvable and 0
content mismatches**, independently reproduced by the at-tier review.
⭐ **Round 4 (head `95987e2722`) — two false comparative claims this PR
had ADDED, both in published bytes, plus three fold-ins.** (a) The
changeset’s 「moved from 7 hits per control to 3」 — refuted by this PR’s
own `component.zod.ts:3974-3983`; re-measured at BOTH pins by three
methods (3/3/3/3 and tree 0 per shell; 7/5/11/5/0 whole-package) ⇒
**nothing moved**, and the paragraph now carries its method. (b)
`component.zod.ts:4104-4105`’s 「the one anchor in this record whose
NUMBER did not move」 — false: **exactly two** are identical at the same
number at both pins. ⭐ The round named both **existentially** rather
than minting a new whole-set superlative, because its enumeration
covered one record — the at-tier review ruled that restraint right.
Folded in: the four ambiguous bare suffixes now spell
`plugin-timeline/src/…` (they resolved to **2** and **21** files and
were therefore invisible to the gate’s worklist entirely), `:3957` now
names the LIVE pin as where it was measured, and the `0 hits` claim
carries its grep and its node-face scope. ⭐ And a **third** superlative
the round’s own sweep found on lines this PR added — 「the one number the
re-read did not reach, **because** it sat on a line the conversion never
touched」 — was measured false (**nine** anchors sat on untouched lines;
the untouched line does not discriminate) and replaced with the
discriminator that is. The sweep covered all **341** added prose lines
against a marker set, **70 hits, every one enumerated with a verdict**.
**Eleven of the thirty repo-wide historical `53ded82b` citations
converted, which is every one in the two files this claim holds.** Ten
in `ui/component.zod.ts` (`object-kanban` navigation, `object-calendar`
navigation, the `object-map` / `object-gantt` / `object-tree` /
`object-timeline` headers, the tree `objectName` gate-count control, the
timeline `data` door, and the two `ComponentPropsMap` row comments) and
one in `ui/component.test.ts`.
**Three anchors could not have been repaired by refreshing a number —
the read itself is gone or different:**
- `ObjectMap.tsx` — the array-shorthand head inside `getDataConfig` is
DELETED (objectui#8348). An authored `data` array now reaches that
renderer through the React props channel alone, never through the
record-source ladder. The record used to cite it at `:169-172`;
`:150-157` is now the note recording the deletion.
- `ObjectTree.tsx` — the `?? schema.titleField` rung in `getTreeConfig`
is DELETED (objectui#8841). ⭐ The flat-spelling prescription that names
`titleField` stays TRUE on its OTHER half: `ListView`'s flatten still
resolves `treeCfg.titleField` into `labelField` before emitting
(`ListView.tsx:3270`), and that is now what the record cites. Reading
only the renderer half would have produced a "this prescription is
stale" finding that is wrong.
- `object-kanban`'s navigation read no longer carries the `(schema as
any)` cast the record quoted, while its `object-calendar` twin still
does, ledgered there as the one objectui#8651 left standing.
**And one reading is a COUNT, not an anchor — and the count this line
used to carry was wrong.** It said the `plugin-tree` registry shell’s
`ElementDataSourceGate` control reading 「moved from 7 hits per control
to 3」. ⛔ **Nothing moved.** Re-measured at BOTH pins by one stated
method (occurrences of that identifier in each `src/index.tsx`): map /
gantt / grid / calendar **3 each** and tree **0** at `87af769e9` **and**
at `53ded82bf`; whole-package counts read 7 / 5 / 11 / 5 at both (the
lone 7 is plugin-map’s, almost certainly where the carried number came
from). The live reading the record rests on — tree **0** against **3
each**, four controls, the zero discriminating — is unchanged and
correct. ⭐ **A count is a reading only with its METHOD beside it**;
without one, re-stating the carried number is exactly what survives a
re-measure.
⭐ `renderer.tsx:1215`’s number is the same at both pins — **and so is
`plugin-timeline/src/index.tsx:333`’s**, an anchor of the same record.
⚠️ An earlier revision of this line called `:1215` 「the one anchor in
the entire set」 whose number did not move; tested across the whole set,
**exactly two** anchors have identical content at the same number at
both pins, so the superlative was false. ⛔ A superlative is a claim
about a whole SET and needs that set enumerated, exactly as a count
needs its method — which is the point this line was trying to make.
**Two further shapes the re-read surfaced, both repaired in place:**
- The `object-timeline` header was a MIXED record: its `limit` clause
had been re-read at the live pin one day earlier while every other
anchor beside it, in the same file, was still a `53ded82b` reading — and
the historical spelling is what let the two sit together with nothing to
tell them apart. Every anchor in it is now at one pin.
- Three records in these same blocks cited an objectui sha WITHOUT
naming `.objectui-sha` (`Measured at the objectui pin ...`), so they
were outside the gate's population entirely — neither asserting nor
historical, simply unseen, and stale. They are re-measured and spelled
so the gate can see them. See the acceptance notes: there are more of
these.
**Also made unambiguous:** `ObjectView.tsx:1725` is now spelled
`plugin-view/src/ObjectView.tsx:1725`. objectui carries a second
`ObjectView.tsx` in `app-shell`, and the gate REFUSES an ambiguous
suffix rather than resolving it, so the bare form could never have been
content-verified.
## What was deliberately NOT done
- ⛔ **No content assertions were added** (the `` `<path>:<line>` first
line `<the line>` `` form the gate can verify against the tree), and the
floor stays at **7** — ⭐ **which the at-tier review confirmed is the
correct, green state, not an omission.** `ASSERTED_ANCHOR_FLOOR` is a
const at `check-objectui-pin-citations.ts:815`, enforced as an EQUALITY
both ways at `:1271`, asserted against the tree again by `--self-test`
at `:1099-1105`, with the failure text at `:1317` demanding the edit
**in the same PR** — and `packages/spec/scripts/**` is a TOOLING landing
path under ruling #202 B, outside this claim's surface. ⇒ adding one
assertion here would red both the main run and the self-test. The gate
reports 7 verified. ⚠️ This diff DOES grow the `--verify-anchors`
worklist, which at head `95987e2722` reports **212** anchors carrying no
content assertion, because re-measuring spelled several read points as
proper backticked anchors that were previously prose and made one
previously-ambiguous anchor resolvable. ⚠️ **Which count that is,
named:** the gate's own `--verify-anchors` worklist reads **95 → 110**
for these two files at head `95987e2722` (82 `component.zod.ts` + 28
`component.test.ts`). ⚠️ Earlier revisions of this line read **102**,
then **104** in the header above while this passage still said 102 — ⭐
**a partial correction inside the body**, the very defect this PR keeps
catching elsewhere; both are superseded by the 110 measured here; the
「106 → 112」 figure quoted in an earlier revision of this line was a
`scanAnchors` count and is NOT the worklist figure — it is NOT MEASURED
against `scanAnchors` directly here, so it is withdrawn rather than
defended.
- ⛔ **Nineteen historical `53ded82b` citations remain repo-wide**, all
outside the two files this claim holds, and several in files under other
claims — `migrations/registry.ts` carries four and is held by four open
PRs, `ui/view.zod.ts` carries two and is held by two. They are listed in
the report so they can be carried as their own work.
- ⛔ The four remaining historical citations in these two files name
`190fbd01`, a different and older pin. They are dated records of past
measurements, which is what the historical spelling is FOR; they are not
the `53ded82b` class the card names and were left alone.
## Verification
Every heavy run went through `scripts/pm/os-verify-lock.sh`; verdicts
read from its `VERDICT command-exit` line, never a bare `$?`. Gate exit
codes were landed to a file BEFORE any pipe.
| run | exit |
|:--|:--|
| `pnpm --filter @objectstack/spec build` | 0 |
| `pnpm --filter @objectstack/spec test` — 515 files, 15043 passed, 1
todo | 0 |
| `pnpm --filter @objectstack/spec typecheck` | 0 |
| `pnpm --filter @objectstack/spec check:generated` — all 15 artifacts
up to date, nothing to regenerate | 0 |
| `pnpm --filter @objectstack/spec check:objectui-pin-citations` — 43
asserting match the pin, 37 historical recorded, 7 anchor assertions
verified | 0 |
| `check-objectui-pin-citations.ts --verify-anchors` (needs the sibling
checkout; run against it) | 0 |
| `pnpm lint` — `eslint . --no-inline-config`, whole repo, ⛔ NOT
narrowed | 0 |
| `pnpm exec turbo run build --concurrency=2` — 74/74 successful | 0 |
`scripts/pm/dispatch-gates.mjs` derives **83** families from the changed
paths. At head `872e06ddf6` the honest reconciliation is **79 run, 4 NOT
MEASURED** — `check:doc-formula-expressions`,
`check:dual-build-cjs-loads`, `check:lean-entry-closure` and
`check:type-check-debt` each exit **3** (`PREREQUISITE NOT MET`, an
unbuilt closure), and the round **killed a closure build at 420s rather
than hold the shared verify lock for a comment-only change**. ⛔ An
exit-3 run measured nothing and is ⛔ never written up as a pass. All
four run green in CI at this head: `check:dual-build-cjs-loads` and
`check:lean-entry-closure` in `Build Core`, `check:type-check-debt` in
`Type Check · debt ledger`, `check:doc-formula-expressions` in `Type
Check · consumer gates`. ⚠️ The 「83 run, 0 NOT-MEASURED, 0 UNRUN」
reading this line used to carry was taken at an earlier head.
⚠️ **The paragraph above supersedes this one.** An earlier revision said
all four exit-3 families 「were re-run to a real verdict after the full
workspace build and all four exit **0**」 — that was true at an earlier
head, where the round paid for a full build. At head `95987e2722` the
round deliberately did **not** hold the shared verify lock for a
comment-only change, so the four stay **NOT MEASURED** locally and are
covered by the named CI jobs above. ⛔ An exit-3 run measured nothing and
is ⛔ never written up as a pass. ⭐ Separately, two gates needed a
second, CORRECT run and then passed: `check:react-declaration-parity`
(exits 1 bare, 0 as CI spells it with `MANIFEST` + `--baseline` +
`--strict`) and `check:query-options-erasure` (killed by the round’s own
150 s per-command cut, exit **124**; it takes ~165 s and exits 0 without
that cut). ⚠️ The at-tier review ruled that distinction explicitly:
**NOT MEASURED is for a gate whose prerequisite was deliberately not
met, ⛔ not for one the harness interrupted and then let finish.**
`check:react-declaration-parity` exits **1** with no `MANIFEST`, which
is the script's documented behaviour rather than a finding. Run as CI
runs it — `MANIFEST="$PWD/sdui.manifest.json" ... --baseline
react-declaration-parity.baseline.json --strict` — it exits **0** with
no new declaration divergence against the accepted baseline.
⛔ No ablation was performed and none is owed: every changed line is a
comment, so there is no branch to ablate and no diagnostic to invert.
## Changeset — `patch` on `@objectstack/spec`, measured
`packages/spec` `files[]` carries `src/**/*.zod.ts`, so
`src/ui/component.zod.ts` ships VERBATIM. Measured against the real
packed tarball, not asserted: the text this diff adds appears **7**
times in `package/src/ui/component.zod.ts` inside the tarball (positive
control), a token present nowhere appears **0** times (negative
control), and the retired-pin spelling appears **0** times in the
shipped file. `src/ui/component.test.ts` is NOT in the tarball — the
pack carries **0** `src/**/*.test.ts` entries — so only one of the two
changed sources publishes.
⚠️ **A conflict worth naming rather than deciding quietly.** The os-dev
role file lists comments among the fast-path categories that "do not
publish", which would point at `skip-changeset`. The measurement above
says the opposite for THIS file: the comments are inside a source file
that ships verbatim, so the published bytes move. The dispatch order's
rule — a changeset is owed if published bytes change, measure it — is
the one followed here, and the fast-path line is reported rather than
silently overridden.
## Acceptance notes — reviewed, ⛔ nothing filed from this PR
- **Docs Drift Check (`5780983322`) — read, and no doc change is owed.
Measured, not asserted.** It lists
`content/docs/protocol/objectui/layout-dsl.mdx` via the
`ComponentPropsMap` symbol, and three release-owned
`content/docs/releases/v17/*` pages (read-only by AGENTS.md, ⛔ not
edited here). The seat measured the diff at head `60f75eeb27` and
re-measured it at `872e06ddf6` (387 changed lines) and again at
`95987e2722` (**414** changed lines across the two `.ts` files, **480**
with the changeset, **0 non-comment** either way) against its merge-base
`16d090ede0`: across both changed `packages/spec/src/ui/*.ts` files
there are **ZERO** non-comment changed lines — every added and removed
line is a `//`, `*`, `/*` or blank line. The two `ComponentPropsMap`
hunks move comment prose only; the rows (`object-map`, `object-gantt`,
`object-tree`, `object-timeline`), their schemas and the `as const` are
byte-identical to the base. ⇒ A diff that changes no behaviour cannot
have falsified a page that documents behaviour, so ⛔ no hand-written doc
is re-verified here and none is edited.
- ⭐ **The gate's population has a hole, and this diff sat in it.**
`check:objectui-pin-citations` builds its population from
`.objectui-sha` mentions only. A record spelled `Measured at the
objectui pin ...` names a sha that can rot and is invisible to every arm
of the gate — not historical, not asserting, not even the hard-failure
arm for an unrecognised spelling, because that arm only fires inside a
`.objectui-sha` window. ⚠️ **The remainder is not "outside these files"
— the seat re-measured it and the round undercounted twice.** Counted by
the seat at head `60f75eeb27` with the pattern `objectui pin ` +
backtick, excluding lines that also carry `.objectui-sha`: **15**
gate-invisible citations across `packages/spec/src`, and **7 of them are
inside the two files this claim holds** (`component.zod.ts` `:2703`,
`:2744`, `:3333`; `component.test.ts` `:2313`, `:2394`, `:3838`,
`:3904`). The round's own correction said five; it counted only the ones
naming the retired `53ded82b` and missed `component.test.ts:3838` and
`:3904`, which name the LIVE pin `87af769e9` and are gate-invisible all
the same — so a future pin bump will never red on them either. The
remaining 8 sit in five other files (`migrations/registry.ts` 2,
`ui/view.zod.ts` 2, `ui/page.test.ts` 1,
`calendar-config-allday-prescription-17054.test.ts` 1, and one each in
two `migrations/entries/semantic/18.*` files), naming `53ded82b`,
`a472b07` and `00d3f09c`. ⚠️ **Semantic correction (at-tier review
`5783719817`):** those numbers reproduce EXACTLY under the literal
pattern above, but the pattern **misses a sha wrapped to the next line
or held in parentheses** — three more inside the claimed files
(`component.zod.ts:2412` `00d3f09c`; `:3050-3051` and `:3313-3314`
`53ded82b`) and `view.zod.ts:1922-1923` `a472b07`. ⇒ the **semantic**
reading is **19 repo-wide / 10 in the two files**. ⭐ Writing the pattern
down is what made that refutable at all.
⚠️ NOT MEASURED: this **15** does not reconcile with the **17 / 9
remain** stated one round earlier, and the seat did not establish
whether the two counts used the same pattern. Take the pattern above as
the reading, ⛔ not the number on its own.
⛔ **What this remainder is NOT.** The round's report escalates
`component.zod.ts:2744` and `:3333` to a *falsified* claim, on the
ground that they assert `convertSortToQueryParams` still honours the
legacy string clause while at `87af769e9a3e` it refuses it out loud.
**The seat checked and does not carry that.** Both records anchor
themselves to `53ded82b` in their own first line and say "at THIS pin",
and both name objectui#8221's PR #8758 — merged 2026-09-09, *after* that
pin — as the change that drops the string arm. The live tree matches
exactly what the record predicted: `sort-query.ts:62-78` at
`87af769e9a3e` says a retired string is REFUSED OUT LOUD. ⇒ A dated
record measured at a retired pin is not falsified by a tree that pin
predates; measuring its anchors at the live pin and calling them stale
is the same category error in reverse. The defect here is the SPELLING,
which is what the card says.
⛔ **CORRECTION by the seat — the sentence that stood here was WRONG, and
it was written as the "sharper replacement" for a claim the seat had
just withdrawn.** It read: 「`53ded82b` is **unreachable from this
workspace** … a record anchored to it can never be re-verified by
anyone, in either direction.」 The at-tier reviewer (record `5783719817`)
refuted it and *used* the retired pin to verify the sort records above;
the seat re-measured and confirms the reviewer: `git cat-file -e
53ded82b^{commit}` exits 0, `git rev-parse` resolves it to
`53ded82bf7a494f54e344e19099dbf00854b8694`, and `git show
53ded82b:packages/core/src/utils/sort-query.ts` reads the string arm at
`:66-70`. The earlier reading was taken on a checkout **before the
session container was recycled**, where `cat-file -e` did fail — so it
measured that checkout's history depth, ⛔ not a property of the
repository.
⭐ What IS true, and it is much narrower: `git fetch origin 53ded82b`
answers `couldn't find remote ref` ⇒ **the remote does not serve it as a
bare sha**. Whether the object is present locally depends on the
checkout's depth at that moment ⇒ re-verifying such a record is **a
matter of luck**, ⛔ not "never, by anyone". ⚠️ A new statement does not
become true by virtue of replacing a false one — and a universal
quantifier ("anyone, in either direction") is the last thing that should
be written at that moment. Carrier for the class: card #19744.
- The objectui docblock at `plugin-map/src/ObjectMap.tsx:159-160` states
"MEASURED: `@objectstack/spec` 17.4.0 has NO
`ComponentPropsMap['object-map']` row". That row exists now. A comment
in another repository with no contract behind it, same class as the
`plugin-tree` one the previous round noted. ⛔ Not filed.
- `ObjectTree.tsx` passes `resolveRecordSourceConfig` the arm
`'undeclared'` while `object-map` and `object-gantt` pass `'view-data'`,
and the objectui comment beside it calls the tree "an unruled block" —
which it no longer is, since this repo now publishes its row. The
divergence is in the HARMLESS direction (the renderer is wider than the
door, so the door still refuses what it always refused) and it is
objectui-side. Recorded in the record itself; ⛔ not filed.
---
_Generated by [Claude
Code](https://claude.ai/code/session_01Sfe5YjBLwB9J3y8fvm2xq1)_
---------
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments