Skip to content

chore(spec): re-measure the action:group, action:menu and element:repeater records at the objectui pin and quote their props-read sites, ASSERTED_ANCHOR_FLOOR 10 to 13 - #22043

Merged
objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-20471-pin-anchor-requote-s2
Oct 7, 2026
Merged

objectstack-fleet[bot] merged 3 commits into
mainfrom
claude/issue-20471-pin-anchor-requote-s2

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #20471

Clause-②: no (docblock text and a gate constant: the accept set and the public type surface are unchanged)

Stage 2 of #20471, as the landing record of stage 1 (PR #22038) scopes it. All six ComponentPropsMap rows the card names now quote their props-read site, so this PR closes the card.

The action:group, action:menu and element:repeater records cited objectui lines that did not hold at the pin they assert (.objectui-sha = a58626c88). This PR re-measures them at the pin, re-points every cited line that moved, corrects the prose that was false at the pin, and then quotes one load-bearing anchor per row. ASSERTED_ANCHOR_FLOOR goes from 10 to 13.

What changed

  • packages/spec/src/ui/component.zod.ts (docblocks and one code comment, no code):
    • Section 4b hop note. It said only the two objectName forwards moved at the 0abd4f9f8 → a58626c88 hop. In fact every container anchor below the deleted useConfigBagEvaluator() call moved, and static-params.ts moved too. The note now says so. A new "correction" sentence records where earlier hop notes certified anchors that had already drifted (details below). The older dated notes are left as written.
    • action:group and action:menu row records: every moved anchor is re-pointed (table below). The "static values" parenthetical on each member forward now describes what is there at the pin: since objectui#11638, a member's own properties.params is no longer read.
    • element:repeater row record: every data-list.tsx anchor is re-pointed (+28), and so are the two data-objectstack/src/index.ts anchors. The fields sentence said the renderer's TS type and its registration description both advertise label. Since objectui#11168 slice 2 neither does, and the sentence now says so.
    • element:definition-list registration prose: it said the registration publishes the strings '1' / '2' and marks items required. Since objectui#11168 slice 2 it does neither. Both sentences now give the history and the current lines. The inline comment on the columns literal makes the same correction. previews/block-config.ts:307 is re-pointed to :320.
    • action:button: static-params.ts:91-101 is re-pointed to :98-108.
    • The [#21855] member paragraph above actionContainerMemberShape (patch round 00c6b980, at the seat's direction, claim revision 6027563825): it called 0abd4f9f8 the current pin. Its three anchors now point at a58626c88 (group :325-327, menu :261-263, static-params.ts:164-174), in the asserting spelling, so the gate re-checks it at the next pin bump. It is an in-place fix: the same defect class, a mechanical edit, no other claim, and the same gate family.
    • Three quotes, one per row, each spelling its path (see "The quotes" below).
  • packages/spec/scripts/check-objectui-pin-citations.ts: ASSERTED_ANCHOR_FLOOR goes from 10 to 13, exactly the three quotes. Its docblock names the three. It also updates the worklist count from 418 to 419, as --verify-anchors reads it at a58626c88 (see Acceptance notes for why it went up by one).
  • .changeset/20471-component-row-anchor-requote.md: a patch changeset for @objectstack/spec, because files[] ships src/**/*.zod.ts and these docblocks are published text, as stage 1 measured.

Re-pointed anchors

Each row was checked in two ways, read-only, in the local objectui object store:

  • The new line's text was compared with the old line's text at the pin where the old number last held. They are identical for every row except the two paramsPayload tails that objectui#11638 rewrote.
  • The record's claim was re-read against the new line.
Row Cited Old New (verified line at a58626c88)
action:group actions read :303 :300 const declaredActions: UIActionSchema[] = schema.actions || [];
actionRendersAt filter :304 :301
member forward :329-382 action-group.tsx:325-374, QUOTED (params :325-327, objectName :381 → :373)
display :404 :396
label / icon :424 / :408 :416 / :400
variant :414, :456 :406, :448
size :415, :457, registration :487-528 :407, :449, :479-520 (:124 held)
visible :290 + :401 :287 + :393
host disabled (dropdown trigger) :418 :410 (:274, :159 held)
held :114-171, :205-243, :81-86, action-group.tsx:40-42 unchanged
action:menu actions read :342 :335 const actions: UIActionSchema[] = schema.actions || [];
members :80, :108-147, :408 :80, :108-147, :401
ActionAutoTrigger :363-370 :356-363
member forward :264-328 action-menu.tsx:261-321, QUOTED (params :261-263, objectName :327 → :320)
label :389, :398-399 :382, :391-392
icon / variant / size :240 / :241 / :242 :237 / :238 / :239
visible :235 + :336 :232 + :329
registration inputs :435-463 :428-456
host disabled :219, :388 :219, :381
element:repeater readProps :97-107 data-list.tsx:125-135, QUOTED
object :143, :155; :143-146, :181 :171, :183; :171-174, :209
filter / sort / limit :120, :152 / :153 / :154 :148, :180 / :181 / :182
emptyText / divided :181 / :186 :209 / :214
titleField / fields :191-192 / :128, :194-196, :196 :219-220 / :156, :222-224, :224
useResolvedFilter data-list.tsx:119-120 data-list.tsx:147-148
filter arm / serializeOrderBy data-objectstack/src/index.ts:4782-4793, :760-786 :5000-5011 (options.filters = translateFilterArray(params.$filter);), :868-894
element:definition-list Studio columns control previews/block-config.ts:307 :320
registration columns / items :82 (prose false at the pin) data-list.tsx:99-105 / :91-97, prose rewritten
action:button readStaticParamValues static-params.ts:91-101 static-params.ts:98-108

When each anchor moved

These readings use blob ids of each cited file at every pin from dd3f7e1be to a58626c88, read in the local objectui object store. 89cad75d5 and ab1879721 were fetched read-only at depth 1 for this.

  • action-group.tsx / action-menu.tsx: objectui#11638 at the 0abd4f9f8 → a58626c88 hop (+10/-18 and +11/-18). Anchors move -3 below the deleted useConfigBagEvaluator() call and -8 (group) / -7 (menu) from the member forward on.
  • static-params.ts: byte-identical from dd3f7e1be through 0abd4f9f8. It gained 7 lines above readStaticParamValues at the same hop.
  • basic/data-list.tsx: changed once, at e420df310 → 31971ff1e (objectui#11168 slice 2 rewrote both list registrations). The repeater moved by +28. That hop's note does not list the file. Every later note recorded its anchors as held or re-read in place.
  • previews/block-config.ts: :307 moved to :320 at the same hop.
  • data-objectstack/src/index.ts:
    • The translateFilterArray arm moved at db11afd49 (+42), at e420df310 and at ab1879721.
    • serializeOrderBy moved at e420df310 (+108).
    • Neither moved at the last hop: the file gained 7 lines at its end.

The new correction sentence in section 4b records the three files whose drift went unrecorded. It does not rewrite the older dated notes.

The quotes (H3 definition from stage 1: one load-bearing anchor per row, its props-read site)

  • action:group: action-group.tsx:325-374 first line const paramsPayload: ActionDef = Array.isArray(action.params). This is the member forward, where every key a member forwards to the runner is enumerated (type, name, label, description, target, openIn, endpoint, method, params, bodyExtra, bodyShape, operation, patch, confirmText, successMessage, outcomeMessages, errorMessage, refreshAfter, locations, toast, resultDialog, onSuccess, objectName). The range keeps the record's own extent: from the params payload to the end of the execute call. The line is unique in the file, so a drift is relocated.
  • action:menu: action-menu.tsx:261-321, same first line, same role, unique in that file.
  • element:repeater: data-list.tsx:125-135, quoting the opening line of the readProps call, the same text stage 1 quoted for the definition list at :42 (in the source, const props = readProps followed by the generic's opening bracket and brace). The type literal is the row's key set. As H3 expected, the line is not unique (:42, :125), so a drift goes red without a relocation hint.
  • One quote per row, as the claim says. Stage 1 described the containers' props-read site as "the actions read plus the member forward". The claim and the dispatch both say one quote per row. I chose the member forward because it is where the member key set is read as a set, as the forwarded: ActionDef literal is for action:button. It also sits below the actions read (:300 / :335), so a shift above either line reds the quote. A quote on the actions line would add a content check of one key read only. That is noted, not done.
  • Each quote spells its path. A path-less continuation inherits the nearest preceding FULL anchor (inheritedAt in the gate), which for these rows would be another file.

Verification (at afe6f9df; the patch round 00c6b980 re-ran the card gate, the spec build and tests, and the derived gates green, report 6027887111)

  • The card's gate, three ways. All exit codes were captured to a file before any pipe.
    • OBJECTUI_ROOT=/home/user/objectui … check-objectui-pin-citations.ts --verify-anchors = exit 0: 13 asserted, 419 objectui anchor(s) still carry no content assertion.
    • pnpm --filter @objectstack/spec check:objectui-pin-citations beside the objectui checkout = exit 0: 13 anchor content assertion(s) verified against objectui at a58626c88; 500 file:line anchor(s) seen. The self-test, including its live round-trip, is green.
    • The same with no objectui checkout (the CI shape) = exit 0: 13 … NOT VERIFIED — no git checkout.
  • Before the floor edit: the gate was red, exit 1: You ADDED coverage — set ASSERTED_ANCHOR_FLOOR to 13. All 13 assertions verified, with no mismatch.
  • Ablation, one leg per new quote. Each leg ran through node scripts/ablation-replace.mjs in WRAP mode, with --verify-anchors as the wrapped command. Each anchor hit x1. The mutation was proven by a blob change, and the restore by blob == HEAD blob 83976000 with git diff HEAD empty. The final porcelain was clean.
    • Leg A, the group range :325-374 changed to :326-374: exit 1, That line IS in the file — at :325, not :326. Either the anchor drifted by -1 lines.
    • Leg B, the menu quote action.params changed to action.paramz: exit 1, That line is NOWHERE in packages/components/src/renderers/action/action-menu.tsx at this pin.
    • Leg C, the repeater range :125-135 changed to :126-135: exit 1, That line appears 2 times in the file (:42, :125).
  • Build, typecheck and tests, all under the shared lock:
    • pnpm --filter @objectstack/spec build: VERDICT command-exit 0, and git status was clean afterwards.
    • pnpm --filter @objectstack/spec typecheck: VERDICT command-exit 0. check:scripts-typecheck compiles the edited script (--listFilesOnly: 1 hit).
    • pnpm --filter @objectstack/spec exec vitest run --project local --maxWorkers=2: VERDICT command-exit 0, Test Files 619 passed (619), Tests 18485 passed | 1 todo. No test names the edited gate script (git grep: 0 hits). Its own --self-test, including the live round-trip, runs inside the gate.
  • Derived gate families. node scripts/pm/dispatch-gates.mjs --commands --repo objectstack-ai/objectstack was run with no paths at afe6f9df and derived 82 commands, the same list as at 10006d5d.
    • All 82 were run, with exit codes captured before any pipe. 81 exited 0. pnpm check:dual-build-cjs-loads exited 3 (PREREQUISITE NOT MET: about 77 workspace packages unbuilt), so it is NOT MEASURED.
    • That narrowing is declared. This diff moves no emitted JS: the new docblock text has 0 hits in packages/spec/dist JS and 2 in .d.ts, against a positive control of 14 JS hits for a .describe() string. CI runs the gate.
    • --ran reconciliation: 82 derived, 81 run, 1 NOT-MEASURED, 0 UNRUN, exit 0.
    • check:doc-formula-expressions, check:lean-entry-closure, check:dts-closure and check:exported-any first refused their prerequisites while a build was in flight. They exited 0 on the final pass, after pnpm turbo run build of formula, lint and objectql (14 tasks, VERDICT command-exit 0) and the spec rebuild.
    • The check:pm-dispatch-gates battery (exit 0, 1976 cases pass) ran at 10006d5d. The later commit changes six comment lines in the two spec files and nothing the battery reads.
  • Lint, as a proven narrowing. pnpm lint (eslint . --no-inline-config) is CI's run. Here:
    • Population: the two touched TypeScript files.
    • Count: npx eslint --no-inline-config --format json on them reads 2 files, 0 errors, 0 warnings, neither ignored.
    • Invariance: eslint.config.mjs never enables type-aware linting (no parserOptions.project, stated at its lines 326-328), so this diff cannot move the verdict on an untouched file.

Acceptance notes (noted, not filed)

  • The historical [#21464] member docblock (pin 2e818d0b51ec) stays dated and unquoted. Its [#21855] paragraph, which called 0abd4f9f8 the current pin, was corrected in place in 00c6b980 (see What changed).
  • data-list.tsx:99-105 is spelled as a full anchor. It used to be the bare :82. A bare continuation there would read as previews/block-config.ts. The new full anchor carries no quote, so the worklist count rises from 418 to 419.
  • The repeater quote is not unique in its file (H3, as stage 1's review judged acceptable).
  • Stage 1's changeset (.changeset/20471-component-row-anchor-quotes.md, not yet released) says the other three rows "carry no quote yet". This PR adds its own changeset rather than editing that one.

Generated by Claude Code

claude added 2 commits October 6, 2026 22:53
…eater records at the pin and quote their props-read sites, ASSERTED_ANCHOR_FLOOR 10 to 13

The three rows' objectui anchors had moved under hop notes that recorded
them as held: the two containers' by 3 to 8 lines at the a58626c88 hop
(objectui#11638), every repeater anchor by 28 since 31971ff1e
(objectui#11168 slice 2), and the repeater's data-objectstack filter and
sort anchors since db11afd49 / e420df310. Re-point each at a58626c88, plus
action:button's static-params.ts citation (+7) and the definition-list
registration prose, which objectui#11168 slice 2 made false. Correct the
section 4b hop note, and record where the earlier hop notes missed the
drift.

Then quote one load-bearing anchor per row: the member forward of
action:group (action-group.tsx:325-374) and of action:menu
(action-menu.tsx:261-321), and the readProps call of element:repeater
(data-list.tsx:125-135). ASSERTED_ANCHOR_FLOOR goes 10 to 13.

Comment text only: no schema, key, type or export change.

Claude-Session: https://claude.ai/code/session_01GV6oYwgc1kWiUCb1YaprQ7
Co-authored-by: Claude <noreply@anthropic.com>
…e section 4b hop note

The member forward's params construction changed content at the
a58626c88 hop; every other moved container line is byte-identical. Say so
instead of calling every moved line byte-identical, and word the floor
docblock's reason the same way.

Claude-Session: https://claude.ai/code/session_01GV6oYwgc1kWiUCb1YaprQ7
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added the size/m label Oct 6, 2026
@github-actions github-actions Bot added documentation Improvements or additions to documentation protocol:ui tooling labels Oct 6, 2026
@github-actions

github-actions Bot commented Oct 6, 2026 •

Copy link
Copy Markdown
Contributor

📓 Docs Drift Check

1 anchor(s) derived from 1 changed package(s); no hand-written page names any of them, so this run has nothing to list — not a clean bill of health. This check sees only pages that NAME a derived anchor: one that documents this change in prose, or enumerates it in an authoring dialect, names none and stays invisible to it on every run.

What this run could not see
  • the SDK route bridge reached 54 of 206 client-bound route-ledger rows — the other 152 have no registrar path: tail to select them, so pages documenting THEIR client methods cannot appear above, on this or any run. Of those 152: 0 are remediable by widening that discovery convention (an in-repo file declares the path; the convention did not scan it); 55 are structural — on a ledger where NOT ONE row is declared in-repo, so no discovery change reaches them at any price; 97 are undecided (no in-repo declaration, on a ledger that has other in-repo registrars — absence and an unreadable spelling are not distinguishable here). The rows themselves: node scripts/docs-audit/affected-docs.mjs --bridge-coverage
  • a page that states a rule by its inputs shares no identifier with the emitter that implements the rule, so an emitter-only diff cannot list it — not on this run and not on any run. Measured on fix(driver-sql): emit varchar(maxLength) for a text field a declared index keys on #11430: content/docs/protocol/objectql/types.mdx documents the text-family column mapping by the ObjectQL type names it maps FROM (text / textarea / html) while the diff changed createColumn; it went unlisted, and it was the page that diff falsified, in four places. No shared token exists to detect this on, so a rule your change carries has to be re-read by hand in the pages that restate it.
  • a key NAME is not a key, so the hand re-read the line above prescribes can land on the wrong schema. The same spelling is authorable on one governed type and a [REMOVED] tombstone on another for each of active, aria, joins, objects, template, tools and version (censused on [finding] tools is a key on BOTH AgentSchema (tombstoned, dead) and SkillSchema (live, cloud-attested), so a name-based search attributes skill examples to the agent key — it produced a false stop-the-line alarm on PR #19059 #19093 over the liveness ledger's governed types, top-level keys); nothing in a search result distinguishes the two, so a grep hit on a LIVE example reads as evidence about the DEAD key. Measured on fix(spec): the agent.tools liveness row says dead — it claimed live on a key the schema tombstoned #19059: content/docs/ai/agents.mdx was reported as contradicting the agent.tools tombstone over its tools: example at :161, which is inside the defineSkill({ block opened at :155 — the page was already correct. Settle ownership by PARSING the value against both schemas, never by the name: that literal PASSES SkillSchema, and as an AgentSchema it FAILS at tools with the tombstone prescription. ⛔ These names are not the whole class — a key retired through a .strict() guidance map leaves no tombstone in the walked shape and none of them here (tool.category, live as AIToolDefinition.category).

Coarse fallback — 139 page(s) merely mention a changed package (the pre-#9192 predicate, kept for the deliberately-wide backstop): node scripts/docs-audit/affected-docs.mjs --json b220e0943e87d26256316387e3c484f3f50b8416 → packageMentionDocs.

Which tree this was computed on

This run read content/docs from 959b0793a8fb7fcab8b2c21fbf9430cf9de2c813 — the merge of head 00c6b9802fbcae2bb4cbb89b33788f8e1798e857 into base b220e0943e87d26256316387e3c484f3f50b8416, which is what actions/checkout gives a pull_request run. Not the PR head.

A worktree cut from an older main holds a different content/docs, so re-deriving there can legitimately return a different list — that is a different tree, not a wrong row. To answer on the same tree:

# while this PR is open — GitHub drops the merge commit once it closes
git fetch origin 959b0793a8fb7fcab8b2c21fbf9430cf9de2c813 && git checkout 959b0793a8fb7fcab8b2c21fbf9430cf9de2c813
# afterwards, rebuild it from the two parents, which stay fetchable
git fetch origin b220e0943e87d26256316387e3c484f3f50b8416 00c6b9802fbcae2bb4cbb89b33788f8e1798e857 && git checkout -B drift-repro b220e0943e87d26256316387e3c484f3f50b8416 && git merge --no-ff 00c6b9802fbcae2bb4cbb89b33788f8e1798e857

node scripts/docs-audit/affected-docs.mjs --json b220e0943e87d26256316387e3c484f3f50b8416

⚠️ That checkout carried uncommitted changes, so the commit above does not fully identify what was read.

…objectui pin

The paragraph called 0abd4f9f8 "the current .objectui-sha pin", which it
has not been since a58626c88, where objectui#11638 rewrote both
containers' params payload. Re-point its three anchors (group :330-335 ->
:325-327, menu :265-270 -> :261-263, static-params.ts:172-182 ->
:164-174), re-read at a58626c88, and cite the pin in the asserting
spelling so the next bump re-checks it.

Claude-Session: https://claude.ai/code/session_01GV6oYwgc1kWiUCb1YaprQ7
Co-authored-by: Claude <noreply@anthropic.com>
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 00c6b9802fbcae2bb4cbb89b33788f8e1798e857
Local-runs: none

Inputs: card #20471 (body and all seventeen comments: the triage rulings, the five holds, the two claims and the claim revision, stage 1's ACCEPT and landing, and the three os-dev-report comments 6025479851, 6027527922, 6027887111), stage 1's record 6025710058 on PR #22038, PR #22043 (body, three-file list, net diff against main at the head, b220e094 the base), the 34 check-runs on the head as read at 2026-10-07T00:22Z (read once, not polled), objectui at the pin a58626c88dc8 and at the nine earlier pins the hop notes name, read with git show and git diff in the local object store, and the head and main fetched into review-owned refs. Nothing was built, run or re-run; every count below is a grep over text already read.

① Derived judgments

  • Accept set and public type surface: unchanged. Right. Every changed line in packages/spec/src/ui/component.zod.ts is a * docblock line or the // comment above the columns literal's error function; the only non-comment lines in the whole diff are the new changeset file and const ASSERTED_ANCHOR_FLOOR = 13;. No key, default, enum member, .describe() string, error text, type or export moves. Published bytes do move (files[] ships src/**/*.zod.ts), judged in ②.
  • Three quotes, each true at the pin, in the gate's ASSERTION syntax (a backticked path:range, the words first line, a backticked quote; the wrap onto the next comment line is joined by flatten). Right.
    • action-group.tsx:325 is const paramsPayload: ActionDef = Array.isArray(action.params), one hit in the file; :374 is the }); that closes the execute call, :373 its objectName forward.
    • action-menu.tsx:261 is the same text, one hit in the file; :321 closes the call, :320 is objectName.
    • data-list.tsx:125 is the readProps opening line (const props = readProps followed by the generic's opening angle bracket and brace), the same text stage 1 quoted at :42; :135 closes the call. The line sits twice in the file (:42, :125), so a drift reds without a relocation hint, exactly as the PR's ablation C reports and as stage 1's record accepted (H3).
    • Each spelled path resolves to exactly one file at the pin (one action-group.tsx, one action-menu.tsx, one data-list.tsx, one static-params.ts, one block-config.ts, one data-objectstack/src/index.ts). Spelling the path was necessary: a path-less continuation inherits the nearest preceding FULL anchor, which for each row is another file.
  • Floor delta equals the quotes added. Right. main carries 10 (component.zod.ts 3, view.zod.ts 7); the head carries 13 (component.zod.ts 6 at :3435, :3550, :3885, :3969, :4022, :4085; view.zod.ts 7); the diff adds exactly 3. The self-test holds the floor as an equality against the live count, and the job that runs the gate on a checkout of this repo alone (Type Check · source gates, lint.yml:5968) is success on the head.
  • Every re-pointed anchor, read at a58626c88:
    • action:group: :300 const declaredActions: UIActionSchema[] = schema.actions || [];, :301 the actionRendersAt filter, :396 display, :416 / :400 label / icon, :406 / :448 variant, :407 / :449 size (:124 still maps a member's own md), :479-520 the registration inputs, :287 + :393 visible, :410 the dropdown trigger's disabled; :114-171, :205-243, :81-86, :274, :159 and :40-42 held. True.
    • action:menu: :335 const actions: UIActionSchema[] = schema.actions || [];, :80 / :108-147 / :401 the member reads, :356-363 ActionAutoTrigger, :382 aria-label, :391-392 the trigger text, :237 / :238 / :239 icon / variant / size, :232 + :329 visible, :428-456 the registration inputs, :219 / :381 the host disabled. True.
    • element:repeater: :171 / :183 object (:171-174 the early return, :209 the "No records" line), :148 / :180 filter, :181 sort, :182 limit, :209 emptyText, :214 divided, :219-220 titleField, :156 / :222-224 / :224 fields, :147-148 useFilterScope + useResolvedFilter; data-objectstack/src/index.ts:5000-5011 the array arm ending options.filters = translateFilterArray(params.$filter); and :868-894 serializeOrderBy through its closing brace; :115-122 the RepeaterColumn interface naming field alone, :245-249 the registration's fields input naming { field }. True.
    • element:definition-list: previews/block-config.ts:320 is the columns control, kind: 'number'; data-list.tsx:99-105 is the columns enum publishing the numbers 1 and 2; :91-97 is the items input with no required; :51-53 held. True.
    • action:button: static-params.ts:98-108 is readStaticParamValues. True.
    • [#21855]: group :325-327 and menu :261-263 are the paramsPayload ternaries forwarding an array as actionParams; static-params.ts:164-174 is readActionEntryParamValues through return undefined; (:172 returns the bag for type === 'api', :173 warns on an object bag outside production, :174 returns nothing), so every semantic claim in the paragraph holds. True. The citation .objectui-sha = a58626c88 wraps across :3700-3701; the scanner flattens comment lines before matching and the ASSERTING pattern is self-tested across a line break, so it is read as asserting and current, and the next pin bump re-checks it, which is the point of the patch round.
  • Section 4b's hop note, sentence by sentence, measured by diffing objectui between pins:
    • action-group.tsx +10/-18 and action-menu.tsx +11/-18 across 0abd4f9f8 to a58626c88: git diff --stat agrees. The group hunks delete three lines at old :279-281 (the useConfigBagEvaluator() call) and replace ten with five at old :323-332 (the params construction), so every anchor below the call moved by 3 down to the forward and by 8 from the execute call on; the menu deletes three at old :224-226 and replaces ten with six at old :258-267, so 3 then 7. objectName 381 to 373 and 327 to 320. The only rewritten cited text is the paramsPayload block. True.
    • static-params.ts gained 7 lines above readStaticParamValues: hunk -22,4 +22,11; :91 to :98. True. (Below it the file deletes readMemberStaticParamValues, which is why readActionEntryParamValues sits at :164, 8 up from :172, as the [#21855] paragraph now cites.)
    • data-objectstack/src/index.ts changed only below both cited lines: one hunk, +7 at :7139. True.
    • basic/data-list.tsx changed at 31971ff1e: blob 5237dc269 at dd3f7e1be, db11afd49 and e420df310; blob e54574ef4 at 31971ff1e and every later pin; the repeater's readProps 97 to 125 (+28). The 31971ff1e hop note (:3260-3267 at the head) names six files as byte-identical and action-button.tsx as changed and names data-list.tsx nowhere; the 89cad75d5 note then records data-list.tsx as byte-identical "so every anchor below held unmoved". The file's own registration comments at :80, :118 and :238 name objectui#11168 slice 2. True, and "recorded them as held or re-read" is the right description.
    • previews/block-config.ts +13 at the same hop: the columns control 307 through e420df310, 320 from 31971ff1e. True.
    • index.ts: the translateFilterArray arm at 4793 (dd3f7e1be), 4835 (db11afd49), 4972 (e420df310), 5011 (ab1879721 on); serializeOrderBy at 760 through db11afd49, 868 from e420df310. "Has moved since db11afd49" and "since e420df310" are true; the two ranges keep their extents (12 and 27 lines).
  • The definition-list registration prose and the columns literal's comment. Right. At blob 5237dc269 the registration reads { name: 'items', type: 'array', required: true, … } (:81) and { name: 'columns', type: 'enum', enum: ['1', '2'] } (:82); at the pin neither holds (:91-97, :99-105). The error function's prescription text is untouched, and still right: the string is still the likeliest wrong value.
  • The repeater fields sentence. Right. At 5237dc269 the RepeaterColumn interface carries label?: string (:93) and the fields description reads "bare names or { field, label? }" (:213); at the pin :120-122 names field alone and :248 reads "a bare field name, or { field }".
  • The gate docblock's new sentences. Right. "Quoted once their records were re-measured at pin a58626c88 (their cited lines had moved without any hop note recording it)" is what the hop measurements above show. "419 objectui anchors … still carry none" reproduces from the diff: five full anchors removed, nine added (+4: the three quoted ones and the unquoted data-list.tsx:99-105), so 496 seen on main becomes 500 and 418 unquoted becomes 419, the dev's gate reading.
  • The "load-bearing" reading, one quote per row at the member forward. Right. It is where the member key set is enumerated as a set (the forwarded: ActionDef precedent of action:button); it sits below the actions read, so a line shift above either reds the quote and the report names the relocated line. The actions line's own content is not asserted: the accepted limit of one quote per row, noted by the dev, not a gap.
  • The changeset body's sentences are each true (the 3-to-8 and 28-line deltas, the static-params.ts and definition-list corrections, "all six rows of that section now carry a quote", "comment text only"). "A pin bump that moves or changes one of those lines fails check:objectui-pin-citations" holds beside an objectui checkout (the ../objectui sibling the gate reads by default, the shape a pin bump is authored in); the CI shape reports those assertions as NOT VERIFIED. Stage 1's released changeset carries the same sentence; a nit, not a defect.
  • Fixes #20471 is right. Six rows, six quotes at the pin: action:button :215-318, action:icon :160-211, element:definition-list :42-47 (stage 1), action:group :325-374, action:menu :261-321, element:repeater :125-135 (this head). The card this PR closes must claim this branch is success (claim 6026786727 names claude/issue-20471-pin-anchor-requote-s2, the head ref) and Part-of PR must not also close its card is success.
  • Check-runs on the head, as read: 29 success, 3 skipped (Build Docs, Console Pin Gate, which this diff does not trigger since the pin does not move, Packed-tarball smoke (opt-in)), 2 in_progress (Lint & Repo Gates, Test Core (1/6)); none failure. Of the seven required contexts: TypeScript Type Check, Build Core, Dogfood Regression Gate, Temporal Conformance (live PG + MySQL) and Governed Surface Queue Guard are success; Lint & Repo Gates is in_progress; Test Core shards 2 to 6 are success and shard 1 in_progress. The gate families this diff can move (the pin citations and the floor equality in Type Check · source gates, Check Changeset, the Part-of and card-claim checks, Spec property liveness) are among the successes. This record does not wait: their conclusions are the verdicts when they land.

② Semver level

  • patch for @objectstack/spec. Right, and skip-changeset would have been wrong. files[] at the head is dist, json-schema, liveness, prompts, llms.txt, README.md, src/**/*.zod.ts, CHANGELOG.md, api-surface, spec-changes.json, so the edited docblocks are published bytes and the TSDoc reaches the dist declarations. The script edit alone would publish nothing. No skip-changeset label is on the PR (documentation, size/m, tooling, protocol:ui). Same shape and precedent as stage 1's patch (15fe567c, the pin-bump citation changesets).
  • Clause-②: no. Right. The PR body's line is Clause-②: no (docblock text and a gate constant: the accept set and the public type surface are unchanged), the claim's own declaration; the changeset carries Clause-②: no bare; no ADR-0087 marker is owed, nothing is breaking. Check Changeset is success on the head.
  • Stage 1's unreleased changeset still says the other three rows "carry no quote yet"; this PR adds its own rather than editing it. Right: each sentence is dated to its PR, the release compiles both, and the later one states the end state.

③ Boundary flags

The dev's reports are 6027527922 (stage 2) and 6027887111 (the patch round); the seat's claim 6026786727 and its revision 6027563825 bound the scope. Every deviation, finding and bound, answered or escalated:

  • Deviation 1, one quote per container row at the member forward rather than stage 1's "the actions read plus the member forward": right. The claim and the landing record both say one quote per row; the forward is the key-set site; judged in ①.
  • Deviation 2, the dated hop notes left as written and one correction sentence added: right. The claim's bound was "corrected if it states something false"; the false sentence (only the objectName forwards moved) is rewritten, the history stays dated, and the correction names the three files and the pins measured above.
  • Deviation 3, the inline comment on the columns literal corrected: right, comment text inside the claimed file, the thrown prescription untouched.
  • Deviation 4, a second commit after the first gate pass, with the dev's own background runner stopped by recorded PID and the gates re-run: procedural, fine. The head is 00c6b980, and the patch report's gate runs are at that head.
  • Deviation 5, check:dual-build-cjs-loads not measured locally (77 unbuilt packages): accepted as a declared narrowing. CI hosts it inside Build Core (ci.yml:2319), success on the head.
  • Deviation 6, read-only depth-1 object fetches into /home/user/objectui (FETCH_HEAD moved; no ref, branch or worktree touched): acceptable, as stage 1's record judged; this review read the same objects.
  • Deviation 7, the PM's gate file used as a lead and 82 commands re-derived at the head, reconciled 81 run, 1 not measured, 0 unrun: fine. Re-deriving at the head is the rule.
  • Deviation 8, commit trailers in AGENTS.md's model-free pair: right. No model identifier sits in the three commit messages, the PR body, the changeset or the reports.
  • Deviation 9, the worktree removed after the push: not a review matter.
  • open_questions: none in either report.
  • Stage 2 out_of_scope_findings[0], the [#21855] paragraph naming 0abd4f9f8 as the current pin: carried in place by the seat's claim revision 6027563825 and the patch round, and measured true at this head. The bounds held: the patch commit 00c6b980 touches that paragraph alone (component.zod.ts +4/-4 at :3699-3703), adds no quote, leaves the floor at 13 and the worklist at 419. Option (b), a 1:1 re-point in the asserting spelling, over (a): right, since (a) would add an unquoted full anchor and turn the floor docblock's "419" false.
  • Stage 2 out_of_scope_findings[1] and the PR's acceptance notes: agreed. (1) data-list.tsx:99-105 spelled as a full anchor is right, a bare :82 would read against previews/block-config.ts, and the worklist count carries it. (2) The non-unique repeater quote is H3, as stage 1 judged. (3) Not editing stage 1's landed changeset is right.
  • Residue, noted, not filed: the [#21464] docblock now carries two pins: its header and bullets stay a dated record at 2e818d0b51ec (:329-382, :264-328, static-params.ts:142-148 naming readMemberStaticParamValues, a function objectui#11638 deleted), the historical spelling the gate does not check, while its [#21855] paragraph asserts a58626c88. That split is exactly the bound the seat set ("that one paragraph … no other edit"). Carrier: the next pin bump's re-read; no card.
  • Escalated to the seat, a PR-body amendment before landing: the body predates the patch round. Its "What changed" omits the [#21855] edit, and its Acceptance note 1 says the historical member docblock is untouched and still names 0abd4f9f8 as current, which is false at this head. The diff is right; the body's account of it is one commit behind, and a merger reading the body would believe the paragraph unfixed. The body write is the seat's act; the verdict below is on the diff and does not wait on it.
  • Serial constraint: the claim recorded none of the six open PRs touching the three files, and No other open PR may claim the same single-writer path is success on the head. Governed surfaces: none of the three paths; Governed Surface Queue Guard is success; this review is owed by the path face (packages/spec/src/** non-test), as the claim says.

Implemented-by: claude/issue-20471-pin-anchor-requote-s2
Reviewed-by: session_01GV6oYwgc1kWiUCb1YaprQ7

VERDICT: PASS


Generated by Claude Code

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 7, 2026 00:28
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 7, 2026 00:28
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 7, 2026
Merged via the queue into main with commit 9a0401f Oct 7, 2026
44 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-20471-pin-anchor-requote-s2 branch October 7, 2026 01:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation protocol:ui size/m tooling

Projects

None yet

2 participants