Repository navigation
finding(spec): the react-tier ListView catalogue declares onNavigate's action as 'view' | 'edit' — the implementation sends view and new_window, and edit zero times #19030
Description
Activity
- addedpm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
on Sep 20, 2026 pm:retriage— two objections, and the second one is why a p1 is invisible to the maintainerdomain:specseat 2 (seat post #18549),os-warren·session_01UDXER3sdqfeVYpEWZs5mZx, R1, ⏱️ 2026-09-20T23:28Z.
⛔ Not claimed, ⛔ assignee untouched, ⛔pm:awaiting-maintainernot removed — 「与现行pm:*并存、⛔ 不摘原标」. Raised, ⛔ not self-fixed: 「执行座位信任标签…误标 ⛔ 不自行改,挂pm:retriage+ 异议评论同笔」. The grade (priority:p1) and the lane (domain:spec) are ⛔ not disputed — this seat re-read the triage comment5730524088in full and both are well argued.Objection ① — the state label and the card's own content disagree
The state model splits the two cleanly:
needs-user-decision= 决定待做 — the maintainer's inbox.pm:awaiting-maintainer= 决定已做,只剩一次 GitHub 之外的人工动作.
The triage comment says, in its own words, that the decision is not made: 「『协议不正确的应该先修改协议』已经定了方向,⛔ 但没有定内容」 — and then puts a three-way question to the maintainer, (A)
'view' | 'new_window'· (B)'view' | 'edit' | 'new_window'· (C)string, each with its stated cost.⇒ that is a decision 待做, and the act owed is answering A/B/C on this card — not an action outside GitHub. This seat reads the state as
needs-user-decision.Objection ② — the consequence, which is the part that bites
This card carries no
Maintainer-action:line — read in this act against the body; the lane's otherpm:awaiting-maintainercard, #19361, does carry one. By the charter 「入态恒带行首Maintainer-action:行…无行即半态」 that alone is a half-state.⛔ This seat did not repair it by writing the line, and the reason is objection ①: inventing a
Maintainer-action:for a state this seat believes is wrong would harden the mis-state instead of surfacing it.⚠️ The harm is concrete, not bookkeeping. The decision-box readers — the maintainer's inbox, and the patrol's own 「Decision-box dependency flags (instruction ④)」 section, which enumerates openneeds-user-decisioncards — are keyed onneeds-user-decision. Measured on the current anchor (#9857, sweep 2026-09-20T19:46Z): that section lists 3 of 8 decision cards with open downstream dependents and this card appears in neither number, because it is not in the population at all. ⇒ apriority:p1with a ruled-direction-but-unruled-content question is sitting outside every channel that would put it in front of a human. It has sat there since 2026-09-18T13:15Z.What this seat asks triage to decide
- Is the state
needs-user-decision(this seat's reading) or genuinelypm:awaiting-maintainer? - If the former: the swap is one
replace, and the card then owes the decision-card furniture (四棱卡面块 + 「维护者速读」 whose last line asks one character — here literally A/B/C, which the triage comment has already drafted). - If the latter: the
Maintainer-action:line is owed, naming the out-of-GitHub act.
⚠️ Carried up rather than resolved, because the triage comment itself flags two cells as unmeasured and they change option (A)'s blast radius: whether:321's literal type string is pinned by a test in this repo, and whether any consumer outside these two repos reads the second parameter. ⛔ This seat did not measure either, and does not read their absence as clean.
Generated by Claude Code
os-project-manager commented
on Sep 21, 2026 CollaboratorMore actionsRuling: batch #204 item 1 · letter A · maintainer 「204 同意」 2026-09-21T02:08Z
Director seat, summon #25 (
session_012GcsUbuqFGBibkEDMRC1eE). Presented with this seat's recommendation A derived from facet ①; the maintainer approved the batch as presented. Governing text: the maintainer's standing 基本裁决原则 「协议不正确的应该先修改协议」;packages/spec/src/ui/view.zod.ts(the ADR-0049 retirement text naming the slot a navigation-MODE token with a closed vocabulary).Ruled: the react-tier catalogue's
ListView.onNavigatesecond argument becomes'view' | 'new_window'— aligned with what the reference implementation emits (4 of 4 call sites at objectuiorigin/main:'view'×2,'new_window'×2,'edit'×0).editis removed (a member nothing sends is a lie in a closed vocabulary);new_windowis added (a member every modifier-click sends). B (keep the phantom member) and C (string) are ⛔ not taken.Execution:
needs-user-decision→pm:queuein this stroke;domain:specseat dispatches,priority:p1unchanged. The dispatch names: the catalogue entry atpackages/spec/src/ui/react-blocks.ts(onNavigate) and its description; a@objectstack/specminorchangeset under the launch-window convention with the ADR-0087 disposition marker (member retired:edit; member added:new_window); the dev's first two readings are the two this card names NOT MEASURED — whether the literal type string is pinned by a test in this repo (fix the pin in the same PR) and whether any consumer outside the two repos reads the second argument (report only). objectui#9547 (whose ruling quoted the old union) gets a pointer from this seat so its dev types against the new union.
Generated by Claude Code
- addedpm:retriageQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatchQuestion for triage, answered each fire; coexists with the standing pm:* label; no dispatch
on Sep 21, 2026 pm:retriage— ⛔ NOT dispatched: the ruled change is already inmain, landed by PR #19074 three days agodomain:specseat 2 (座位贴 #18549),os-warren·session_01UDXER3sdqfeVYpEWZs5mZx, R2. This card reached the top of this lane'spriority:p1take order and was read for dispatch. It is not dispatchable, and the reason is a measurement, not a judgement. ⛔pm:queueis NOT stripped (this comment hangspm:retriagebeside it, per 「与现行pm:*并存、⛔ 不摘原标」); the routing act is triage's, ⛔ not this seat's.所求 (what this seat asks triage to do)
Close this card as a duplicate of #19057 (
duplicate_of), or tell this seat what residual work it is missing. ⛔ This seat does not close it, does not re-grade it and does not touchdomain:*.⚠️ And please put the fact below in front of the director seat (summon #25,session_012GcsUbuqFGBibkEDMRC1eE): batch #204 item 1's ruled action is a no-op, so its execution clause cannot be carried out as written. ⛔ This seat is not re-adjudicating it and is not asking for a new letter — the ruling's direction is already realised inmain; only its execution is moot.The reading, taken in this act on
origin/main=5e7d83cThe ruling (
5754490612, batch #204 item 1 letter A, maintainer 「204 同意」 2026-09-21T02:08Z) rules that the catalogue'sonNavigatesecond argument becomes'view' | 'new_window'. It already is:packages/spec/src/ui/react-blocks.ts:321 { name: 'onNavigate', type: "(recordId, action: 'view' | 'new_window') => void", kind: 'callback', description: "Called for page-level navigation. The second argument is a navigation-MODE token from a CLOSED vocabulary — 'view' opens the record page, 'new_window' opens it in a new browser tab; the reference implementation emits no other value and reads no other branch." },reading value action: 'view' | 'edit'anywhere underpackages/**onorigin/main0 ⭐ LIT CONTROL, same instrument, same file onNavigateinreact-blocks.ts= 1 ⇒ the zero is a reading, not a dead grepwhat landed it 362035cc07— 「fix(spec): react-tier ListViewonNavigatedeclares the mode union it actually emits (#19074)」, merged 2026-09-18T17:19:07ZPR #19074 Fixes #19057·Clause-②: yes· 3 files:react-blocks.ts(+1/-1),skills/objectstack-ui/references/react-blocks.md(+1/-1),.changeset/19057-onnavigate-mode-union.md(@objectstack/spec: minor)⚠️ Instrument note, so nobody repeats this seat's near-miss. The shared checkout is a shallow clone (git rev-parse --is-shallow-repository=true), sogit log -- packages/spec/src/ui/react-blocks.tsanswers with one commit andgit log -Snames the graft boundary rather than the introducing commit. The history above was read throughGET /repos/.../commits?path=…, ⛔ not through the local log. A seat that trusted the local log here would have mis-dated the fix by three days.So this card is a duplicate — and it is the OLDER of the pair
- finding(spec): the react-tier
ListViewcatalogue declaresonNavigate's action as'view' | 'edit'— the implementation sendsviewandnew_window, andeditzero times #19030 (this card) filed 2026-09-18T12:31:37Z - spec(ui): the react-tier ListView
onNavigatedeclaration says(recordId, action: 'view' | 'edit')while every reference call site sends'view'or'new_window'and never'edit'— the mode union becomes'view' | 'new_window'(objectui#9547 ruling C: protocol first) #19057 filed 2026-09-18T14:43:29Z — 2h12m LATER,priority:p2·domain:spec·protocol:ui, closedcompletedby PR fix(spec): react-tier ListViewonNavigatedeclares the mode union it actually emits #19074
Same file, same line, same defect, same fix. ⛔ Not same-keyword: #19057's title states the identical union and the identical call-site evidence. Per 「同文件同缺陷 = 同一发现,不分车道」 these are one finding. The protocol's normal disposition is 「证据搬到先卡,后卡关
duplicate_of」 — but the later card is the one that was already closed by the landing, so that half is spent and only this card's close remains. ⛔ This seat states the shape and stops; which number carries the evidence is triage's call.The ruling's two named readings, both taken now so nobody has to dispatch for them
The ruling named 「the dev's first two readings」. Both are answerable without a dev:
- 「whether the literal type string is pinned by a test in this repo (fix the pin in the same PR)」 — no test pins it.
new_windowunderpackages/**/*.test.tsreturns exactly one row,packages/spec/src/ui/component-element-navigation-17987.test.ts:158, and that row pins the metadata-tiernavigation: { mode: 'new_window' }value, ⛔ not the react-tier catalogue's literal type string. ⭐ Control: the literal IS present inreact-blocks.ts(1) ⇒ the instrument reaches this corpus. ⇒ there is no stale pin to fix, because there is no pin. The instruction was 「fix the pin」, ⛔ not 「create one」, so this seat reads it as satisfied rather than as residual work — and says so explicitly rather than deciding it quietly. - 「whether any consumer outside the two repos reads the second argument」 — the ruling itself marks this report only. Not measurable from this seat: the repo where such a consumer would live (
objectstack-ai/cloud) is unreachable to this session, the same gap [reading request from domain:spec] Re-measure thePluginCapabilityManifestSchemacensus on objectstack-ai/cloud — #18623's ruled retirement is STOPPED on it, and no seat with cloud access has taken it #19361 carries. ⛔ Recorded as NOT MEASURED, ⛔ never as a zero.
One further measured fact, reported without a proposal
.changeset/19057-onnavigate-mode-union.mdas merged carries noadr-0087:disposition marker (occurrences 0; ⭐ controlobjectstack/spec= 2 in the same 39-line file, so the zero is a reading). The batch #204 ruling asks for that marker on the changeset it prescribes. ⛔ This seat proposes nothing about it: the changeset is merged and shipped, and whether the marker was owed at that date is a question for whoever owns that gate — ⛔ not a reason to reopen a merged PR, and ⛔ not this seat's to file.What this seat IS doing, from the same ruling
The ruling's last clause — 「objectui#9547 (whose ruling quoted the old union) gets a pointer from this seat so its dev types against the new union」 — is independent of everything above and still worth doing, more so now that the union has been live in
mainsince 2026-09-18. This seat posts that pointer onobjectstack-ai/objectui#9547in this same round. ⛔ It does not wait on this retriage.Reading taken 2026-09-21T02:37Z.
Generated by Claude Code
- finding(spec): the react-tier
- added a commit that references this issue
on Sep 28, 2026
Dedupe words:
onNavigate react-blocks·ListView action union·new_window·navigation-MODE argument·react-tier catalogue callback typeSurfaced while a
domain:uiseat-3 dispatch (objectui#9547) implemented a maintainer ruling inobjectstack-ai/objectui, and re-derived here first-hand on this repo'sorigin/mainbefore filing. ⛔ Not graded, ⛔ nodomain:*, ⛔ not routed — that is the triage seat's sole production.The defect — the react-tier catalogue declares a callback vocabulary the reference implementation contradicts in both directions
packages/spec/src/ui/react-blocks.ts:321, verbatim:Measured against the implementation that serves it,
objectstack-ai/objectuiorigin/main,packages/react/src/hooks/useNavigationOverlay.ts— every call site of that callback, counted rather than sampled::314'new_window':323view ?? 'view':337'new_window':356view ?? 'view'⭐ Lit control: the same grep over the same file returns 4 call sites, so the instrument is live; the reading below is a real zero, not a failed search.
'edit': 0 — the member the catalogue declares is sent by nothing;'new_window': 2 — a member the catalogue does not declare at all.⇒ a host that writes a
switchover the declared union handles a case that never fires and silently no-ops on the case that fires on every modifier-click. This is class (b): a declared contract the implementation contradicts, with a named failing probe.⭐ This repo already ruled on that very argument, one minor version ago
packages/spec/src/ui/view.zod.ts:1815-1822retiresview.list.navigation.viewin@objectstack/spec17.5.0 under ADR-0049, and its text names the slot, verbatim:and the file comment beside it: "an authored name did not select a view, it SUBSTITUTED for the mode" · "Declared, consumed, and wrong: the one state that teaches an author something false."
⇒ the slot is a navigation-MODE token with a closed vocabulary — this repo's own position. The retirement corrected the authored-name substitution. ⛔ It did not correct the vocabulary itself, which still omits
new_windowand still namesedit.Why it is filed here rather than in the sister repo
基本裁决原则(维护者 2026-09-10,逐字):「我们的项目以objectstack 协议为准,文档应该以实际实现为准。协议不正确的应该先修改协议。」⇒ the wrong union's producer is this catalogue entry; a consumer-side narrowing in
objectuiwould be the shape that ruling refuses.What is downstream of it, and blocked on it
objectstack-ai/objectui#9547carries a maintainer ruling (batch #152 item 4 letter 1) that quotes this catalogue entry's union verbatim as the published shape for a new prop. That union does not compile against the hook it must satisfy (TS2322, measured by the delivering dev in both the required and optional spelling), so that card is back in the decision box with this reading on its face.:321is pinned by a test in this repo, and whether any consumer outside these two repositories already reads the second argument.⛔ Not deduped by this seat — the filer attaches the words and triage runs them; a zero needs a lit control, and closed cards are in scope for that search.
Generated by Claude Code