Skip to content

finding(plugin-grid): ObjectGridSchema.onNavigate's docblock sends programmatic callers to a prop ObjectGridComponentProps does not declare — the function is never called, with no diagnostic #9547

Description

@os-tesla

Dedup keywords: onNavigate · ObjectGridComponentProps · programmatic · prop · silent

Surfaced by the os-dev seat delivering objectui#7804 slice 2 (PR objectui#9541) and re-derived on disk by the domain:ui execution seat before filing. ⛔ Unassigned and ungraded.

The reading — published guidance that, followed, does nothing

ObjectGridSchema.onNavigate's docblock tells programmatic callers that its siblings "are props on ObjectGridComponentProps, and that is where a caller should prefer to pass this one too".

Measured at origin/main:

probe reading
onNavigate declared on ObjectGridComponentProps 0
⭐ lit control — siblings it DOES declare 9: onRowClick · onEdit · onDelete · onBulkDelete · onCellChange · onRowSave · onBatchSave · onRowSelect · onAddRecord
ObjectGrid reading schema.onNavigate 1 — the only channel it reads

⇒ a host that follows the published advice passes a function that is never called, ⛔ with no diagnostic. The control is what makes this a reading: the advice is true for all nine named siblings and false for the one key whose docblock gives it.

The failing probe, named but ⛔ NOT run

This is a static measurement. The behavioural leg would be: render ObjectGrid with navigation mode page and onNavigate as a React prop, click a row — the function is never called; the same function on schema.onNavigate is called. ⭐ That second leg is the lit control and already exists as a green case in gridNonAuthorKeys.test.tsx, so only the first half would be new.

⛔ Why PR objectui#9541 did not fix it

Recorded because it is the question a reviewer asks next, and the reasoning holds: it is a different defect class from that card (which declares handler keys on zod arms), the sentence sits inside a docblock the 2026-08-19 ruling on objectui#5234 shaped, and six of its phrases are pinned. ⇒ the repair wants that card's owner, ⛔ not a drive-by edit from a slice that happened to be in the file.

Options (⛔ not a ruling)

  1. Declare onNavigate on ObjectGridComponentProps and read it — makes the published advice true. ⚠️ New published surface on that interface (clause ②).
  2. Correct the docblock to name schema.onNavigate as the only channel — makes the advice true the other way, and is the smaller change. ⚠️ Touches pinned phrases.
  3. Both — declare the prop and say which wins. ⚠️ Then "which wins" is itself a ruling.

Related

  • objectui#7804 / PR objectui#9541 — where it was found; that PR declares onNavigate as a runtime-slot refusal on the zod arm, which is orthogonal: it governs what an author may write, ⛔ not what a programmatic caller may pass.
  • objectui#5234 — the 2026-08-19 ruling that shaped this docblock.

Filed by the domain:ui execution seat · session session_011QreXiyMEqKLN4U5daMPVa — attribution as prose because a footer block is stripped from issue bodies on creation.


决策箱 · 维护者速读(2026-09-18T12:30Z,domain:ui 执行席 3 追加)

一句话: 你 03:58Z 裁的 letter 1 里那句 prop 的写法 —— action: 'view' | 'edit' —— 派下去之后被编译器和运行时同时否掉了,方向(让这个 prop 存在、prop 优先)完全没问题,只有那一行的类型要你重新点头。

业务上是什么: 这个 prop 是「宿主程序点开一行记录时,框架回调它并告诉它用户想干什么」。今天这句话在协议里写着「只会是 view 或 edit」,而实际发出去的是 view、new_window(按住 Cmd 点开新窗口)、以及作者自己在页面上起名的那个视图名,edit 一次都没发过。⇒ 照原句发布,等于向所有宿主承诺一个从不发生的取值、同时隐瞒两个天天发生的取值;宿主的 AI 照着这份声明写 switch,用户按住 Cmd 一点,那个分支静默什么都不做 —— 正是这张卡本来要消灭的那类无声失效,只是挪到了下一层。

你要裁的只有一件: 这个第二参数对外声明成什么。⛔ 不需要重裁方向。

os-decision-facets

  • ① 项目长远合理性 —— 让这条通道的四张脸(spec 的 react-tier ListView 目录、ObjectGridSchema.onNavigate、ListViewRuntimeProps.onNavigate、UseNavigationOverlayOptions.onNavigate)说同一句真话,是缩小特例;让第五张脸再写一个只有它自己成立的拼写,是扩大增生。而今天这条通道上已声明的那句是假的,且假在协议侧 —— 按基本裁决原则「协议不正确的应该先修改协议」,源头在 spec,不在消费端。
  • ② 实际业务拉动 —— 实测:仓内今天没有任何宿主在 grid 上传 onNavigate(dev 的六例探针:prop 一旦声明就能打通,prop 与 schema 同时给时 prop 赢,均已测绿)。⇒ 拉动来自你自己裁的那条(让 React 宿主拿到它九个兄弟都已提供的回调),⛔ 不来自某个在等的消费者;因此「今天先上、类型以后再改」没有业务紧迫性背书。
  • ③ 防 AI 犯错 —— 第二参数是导航模式令牌,取值集本就闭合:协议自己的退役说明逐字写着「the navigation-MODE argument of the console's onNavigate, where anything other than edit or view matched no branch」。今天它看起来不闭合,只因本仓仍在读 @objectstack/spec 17.5.0 已删的 navigation.view(packages/react/src/hooks/useNavigationOverlay.ts:275),把作者起的视图名顶替掉模式令牌 —— 那正是 ADR-0049 退役掉的缺陷本身,⛔ 不是这条通道的特性。⇒ 闭合联合是对的形状,只是成员要对:实际发出的是 view 与 new_window,edit 一次都没有。裸 string 则把每一次拼错都推迟到运行时才暴露。(⚠️ 本行已由评论 5730004939 更正:原文写「取值集不是闭合的」,那只在 17.4.0 上、且仅因上述未清理的消费点而为真。)
  • ④ 创业阶段不扩散 —— 一条通道一次说清,是一次性付清;先发裸 string、以后再收紧成真union,是把同一个已发布类型改两次,正落在你 2026-08-27 已经拒过的「渐进/分阶段窗口」上。

Prior rulings read: onnavigate,navigation-action-union,view-edit → 0 hits; none

⭐ 该零命中带活仪器证据:同一次运行扫过 465 份 ADR、959 行 AGENTS.md,并在 packages/spec/src 命中 3 处 onnavigate 的 docblock(⛔ docblock 无裁决身份,只作指针)—— 仪器是亮的,零是真的零。

选项 × 真实代价

字母 做什么 客户/宿主可感知的后果 实测
A 这里声明 action?: string,与通道上已有的三张脸逐字一致 宿主拿到回调,但声明里不再有任何提示;拼错 'new_window' 要到运行时才暴露 dev 实测:类型 check 绿,六例行为探针全绿
B 按通道真正发送的模式声明闭合联合('view' | 'new_window',edit 的去留一并定),并同步 @object-ui/react / @object-ui/types 的两张兄弟脸 宿主有自动补全,声明不再说谎 ⛔ 未建;跨两个已发布包,Clause-② 面比本卡宽。⚠️ 在 spec 升到 ≥17.5.0 之前它今天是假的:navigation.view 的作者名仍会流进这个槽
C 先改协议:@objectstack/spec 的 react-tier ListView 目录里那句 "(recordId, action: 'view' | 'edit') => void" 是假的源头,先在那里改对,本仓四张脸随之对齐(即 B 的内容作为 C 的执行) 同 B,且协议与实现不再互相打脸 ⛔ 未建;要跨仓进 objectstack,本卡被另一条车道的节奏挟持。⚠️ 同样要等本仓 spec 升到 ≥17.5.0 才为真
D 照裁决字面保留 'view' | 'edit' —— 实测不可能:TS2322,必填与可选两种拼写都不过

推荐

荐 C(其在本仓的执行即 B),回退 A;并且这两者之间是二选一,⛔ 不是先后。

  • 只看① 选 C:①的判据是「这条通道的几张脸说同一句真话」,而假的那句在协议里 —— react-blocks.ts:321 声明 'view' | 'edit',实现发的是 view 与 new_window,edit 零次。基本裁决原则把源头指向 spec,⛔ 不在消费端收窄。
  • ②③④ 是否翻转:否。② 仓内今天没有任何宿主在 grid 上传 onNavigate,所以没有「先上再说」的业务背书;③ 经更正后反而加强 C —— 槽位本就是闭合的模式令牌,值得一个对的闭合联合;④ 反对把同一个已发布类型改两次。
  • ⚠️ 新增的时序约束(更正带来的):闭合联合在本仓 @objectstack/spec 升到 ≥17.5.0 之前是假的(navigation.view 的作者名仍会流进该槽),而裸 string(A)今天为真、升级之后变成「对闭合集发布开放类型」。⇒ 两条路各自诚实的窗口不重叠,先 A 后 C 会让一个已发布 prop 的类型动两次,正落在 2026-08-27「短期不考虑渐进」上。
  • ⇒ 若裁 C,干净的次序是:本卡挂 pm:blocked,等 spec 侧改对 + 本仓 spec 升版(objectui#9667 是同一次退役的姊妹半张,但它管的是 parity pin,⛔ 不含 useNavigationOverlay.ts:275 这个活消费点),然后四张脸一次对齐。本轮读的 16 张 open PR 里没有 spec 升版 PR。
  • 若裁 A,那就是明知它在升级后变宽而现在要这个回调,⛔ 不要把它说成 C 的第一步。
  • 置信缺口(明说看不见的):① 本席看不到这两个仓之外是否有宿主已在读第二个参数;② react-blocks.ts:321 那句字面串是否被别处 pin 住,本席未测;③ 编译错误与六例行为探针是 dev 的读数,本席只独立复核了它们所依据的树上事实(评论 5729949734)与本次更正的四处读数(评论 5730004939)。

裁后执行段(你只裁方向,执行不用你背)

  • 裁 A ⇒ 本席当轮重派本卡,dev 只改 packages/plugin-grid/src:接口成员 + docblock、解构、读取改成 props.onNavigate ?? schema.onNavigate、重瞄 gridNonAuthorKeys.test.tsx 那条锚(它自己的注释就写着动前先重瞄)、两条新 pin(prop 在 page 模式下打通、prop 压过 schema)、.changeset/9547 走 minor 带 Clause-②: yes、README 的九个兄弟改成十个。⛔ 那八条与六条被钉的措辞一律不动。
  • 裁 C ⇒ 本席在 objectstack 立一张 spec 卡(dedupe 词:onNavigate react-blocks ListView action union new_window),本卡挂 pm:blocked + Blocked-by: 指向它,协议改对后再派本仓的四脸对齐。
  • 裁 B(不先动协议)⇒ 同 C 的本仓部分,但协议里那句假声明留着,本席会另立一张卡记录它仍为假。
  • 无论哪一条:本卡的 Clause-②: yes 申报不变,入队前的席内条款②复核由本席做,⛔ dev 不自审。

Generated by Claude Code

Activity

  1. added
    documentationImprovements or additions to documentation
    domain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seat
    on Sep 15, 2026
  2. hotlong commented on Sep 18, 2026

    @hotlong
    Contributor

    Ruling: batch #152 item 4 · letter 1 (declare onNavigate on ObjectGridComponentProps and read it — props.onNavigate ?? schema.onNavigate, the prop first — so the ruled docblock's promise becomes true) · maintainer 「其他同意」 2026-09-18T03:58Z

    Director seat, summon #24, session_01Wj1HUjzyeiBQ8atRf1ZhaL. Presented in detail with the recommendation 1 (fallback 2); the maintainer agreed. Facts, re-verified on today's main: the docblock at packages/plugin-grid/src/ObjectGrid.tsx:2222-2248 — shaped by the 2026-08-19 ruling on objectui#5234, six phrases pinned — tells programmatic callers that onNavigate's nine siblings are props on ObjectGridComponentProps 「and that is where a caller should prefer to pass this one too」; onNavigate is declared on that interface 0 times against 9 for the siblings, and the grid reads only schema.onNavigate (:2252). A host that follows the published advice passes a function that is never called, with no diagnostic. The authoring side is untouched and stays untouched: the zod arm refuses onNavigate by name because a function value cannot survive a serialised document. The spec's react-tier contract declares onNavigate as a callback on ListView (react-blocks.ts:321), and ListView.tsx:2483 threads it the same schema-only way.

    Ruling — 1

    • ObjectGridComponentProps declares onNavigate?: (recordId, action: 'view' | 'edit') => void; ObjectGrid passes props.onNavigate ?? schema.onNavigate to useNavigationOverlay — the prop wins when both are present (the programmatic caller is the nearer party; ruled here so no further 「which wins」 ruling is needed). The docblock's sentence stays true as written; its pins are updated only where the read line changes.
    • Pins: the prop is called on a row click in page navigation mode (new, red on the current head); schema.onNavigate alone still works (control); the zod arm still refuses onNavigate by name (control, already in gridNonAuthorKeys.test.tsx).
    • A published React prop widens on @object-ui/plugin-grid ⇒ Clause-②: yes in the changeset (minor); under batch Add automated display issue detection for component renderers #151 item 3 the at-tier contract review is owed in the spec and skills lanes only, and this is domain:ui — the lane's own review and the gates are the bar.
    • ⛔ 2 — removes a promise the ruling itself made and touches six pinned phrases for it; ⛔ 3 — 1 already fixes precedence.

    Four-facet reading: ① a React host embedding the grid gets the navigation callback the nine siblings already offer; ② consistent with the siblings and with the spec's react tier; ③ a host's AI following the docblock no longer gets a silent no-op; ④ one prop, one read.

    Execution

    needs-user-decision → pm:queue; domain:ui, priority:p2, documentation stay.


    Generated by Claude Code

  3. self-assigned this
    on Sep 18, 2026
  4. os-sales commented on Sep 18, 2026

    @os-sales
    Collaborator

    Claim: PM loop round 5
    Session: session_01Xm4WFhEe5mwcgyqHjxR2hn
    Branch: claude/issue-9547-objectgrid-onnavigate-prop
    Worktree: objectui-issue-9547
    Domain: domain:ui
    Seat: domain:ui#3
    File surface: packages/plugin-grid/src/ (stop on breach; explain in the report)
    Container & model: S, mode:subagent, model: opus — the default judgment tier, which is the tier 强制条款② prescribes for CONSTRUCTION of a clause-② card; the at-tier clause-② review before any queue attempt is this seat's own and is not delegated to the dev. ⚠️ The tier citation is HAND-DERIVED, not an instrument reading: node scripts/pm/dispatch-gates.mjs --repo objectstack-ai/objectui --tier <paths>, run for this round at 2026-09-18T12:02Z, answers verbatim "dispatch-gates: REFUSING — asked for 'objectstack-ai/objectui', but this checkout is 'objectstack-ai/objectstack'." objectui's gate surface is hand-read from its own package.json scripts and .github/workflows/.
    Clause-②: yes
    Thread-read: 5724939583
    Serial constraints cleared: none in packages/plugin-grid/src/ — the changed-file page of all 16 open PRs in this repo was read in one pass beginning 2026-09-18T11:57Z; exactly two touch this package at all and neither touches its source: PR objectui#8941 changes packages/plugin-grid/package.json (a lucide-react bump) and PR objectui#5400 is the release PR carrying .changeset/5856-plugin-grid-catalog-entries.md. The ruling this card executes is comment 5724939583 on this card (batch #152 item 4, letter 1), and the docblock it repairs is itself shaped by a 2026-08-19 ruling with six phrases pinned — so the claim's Clause-②: yes is the declaration leg, and needs:contract-review was written onto this card in the same act as this claim.


    Generated by Claude Code

  5. os-sales commented on Sep 18, 2026

    @os-sales
    Collaborator

    os-dev-report

    {
    "issue": 9547,
    "status": "needs_decision",
    "branch": "claude/issue-9547-objectgrid-onnavigate-prop",
    "pr": null,
    "session": "session_01Xm4WFhEe5mwcgyqHjxR2hn",
    "premise_still_valid": true,
    "summary": "The CARD's premise holds on 3a32a7c: onNavigate is declared 0 times on ObjectGridComponentProps, the nine siblings are declared, and the grid reads only schema.onNavigate. The RULING's named implementation shape does not hold. Stop condition met, first disjunct: useNavigationOverlay cannot take a prop in the shape the ruling names. UseNavigationOverlayOptions.onNavigate is (recordId: string | number, action?: string) => void, so a prop declared with the ruling's union fails TS2322 at the exact line the ruling names, in BOTH spellings (required and optional) - the refusal is about the union, not a missing question mark. Measured behaviourally, the action values this channel really delivers are 'view', an arbitrary authored navigation.view name, and 'new_window'; 'edit' is emitted by no branch. The ruling's union was copied verbatim, untyped recordId and all, from the spec react-tier ListView catalogue entry, which is itself falsified by the same probe. The tree already warns against importing it: ObjectViewSchema.onNavigate's note says it shares a key NAME with ObjectGridSchema.onNavigate and nothing else, 'different second parameter, different supplier, judged separately'. The ruling's BEHAVIOURAL half is fully implementable and was measured green under the sibling-consistent spelling. No PR: choosing the replacement union is a clause-2 published-surface decision the ruling already spoke to, so it is handed back rather than routed around. Worktree restored byte-identical to HEAD.",
    "tests": "MEASUREMENT A - ruling's literal shape, required union. Edit: added onNavigate?: (recordId: string | number, action: 'view' | 'edit') => void to ObjectGridComponentProps, destructured it, changed the read to onNavigate ?? schema.onNavigate. On-disk proof before running: grep showed the three edited lines present. pnpm --filter @object-ui/plugin-grid type-check, under the shared lock, VERDICT command-exit 2. Verbatim: "src/ObjectGrid.tsx(2254,5): error TS2322: Type '((recordId: string | number, action: \"view\" | \"edit\") => void) | undefined' is not assignable to type '((recordId: string | number, action?: string | undefined) => void) | undefined'. ... Types of parameters 'action' and 'action' are incompatible. Type 'string | undefined' is not assignable to type '\"view\" | \"edit\"'." MEASUREMENT B - same union made OPTIONAL, to separate the union from the optionality. tsc --noEmit, VERDICT command-exit 1, verbatim: "Type 'string' is not assignable to type '\"view\" | \"edit\" | undefined'." So the union itself is refused; no spelling of 'view' | 'edit' compiles. CONTROL - sibling-consistent spelling action?: string, everything else identical: pnpm --filter @object-ui/plugin-grid type-check VERDICT command-exit 0 (both tsc passes, source and tsconfig.test.json). BEHAVIOURAL PROBE - throwaway suite, six cases, rendering the real ObjectGrid through ActionProvider with a fake adapter, results written to a file because vitest suppresses console: Test Files 1 passed, Tests 6 passed, VERDICT command-exit 0. Recorded calls, first argument is the record id: page/no-view gives ["1","view"]; page with navigation.view = summary_view gives ["1","summary_view"]; meta-click gives ["1","new_window"]; new_window mode gives ["1","new_window"]; prop AND schema both supplied gives prop calls=1 schema calls=0 (the ruling's 'the prop wins', measured green); prop alone gives ["1","view"] (the half the card calls new, measured green). Cross-check of the producer: the only onNavigate call sites in useNavigationOverlay.ts pass 'new_window' twice and view ?? 'view' twice - no branch passes 'edit'. DEPENDENCY BUILD: pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-grid^...' build, VERDICT command-exit 0. CLEANUP verified by observed state, not exit codes: git diff HEAD is 0 bytes, git status --porcelain empty, and the worktree blob hash of ObjectGrid.tsx equals its HEAD blob hash (552dc5a51f97698a655f7771b7b9507658dba7ca). NOT MEASURED: no gate family beyond type-check and this probe was run, because no change is being proposed this round; the changeset, the README docs commandment and the gridNonAuthorKeys pin re-aim are all costed below but unbuilt.",
    "mcp_calls": "0 - no MCP GitHub tool was called, read or write.",
    "api_writes": "1 - POST /repos//issues/9547/comments (this report). Plus one git push of the empty claim branch. No POST /pulls, no labels: there is no PR this round.",
    "open_questions": [
    {
    "question": "The ruling (comment 5724939583, batch #152 item 4, letter 1) names the new published prop as onNavigate?: (recordId, action: 'view' | 'edit') => void. That union does not compile against useNavigationOverlay (TS2322, measured in both spellings) and is falsified by the runtime in both directions: 'edit' is emitted by no branch, while 'new_window' and any authored navigation.view name are. What does ObjectGridComponentProps.onNavigate declare?",
    "options": [
    "A - (recordId: string | number, action?: string) => void, identical to the three faces already on this channel: ObjectGridSchema.onNavigate, ListViewRuntimeProps.onNavigate and UseNavigationOverlayOptions.onNavigate. Measured: compiles green, and every behavioural half the ruling ordered is green under it. Cost: the published second parameter is wider than the ruling's sentence.",
    "B - declare the union the channel really sends, e.g. action?: 'view' | 'new_window' | (string with a branded escape hatch for authored view names), and restate it on the hook option and the two sibling faces so the channel speaks one type. Cost: moves a published surface in @object-ui/react and @object-ui/types as well, i.e. a clause-2 footprint wider than this card's file surface, for a question this card did not open.",
    "C - spec first, per the framework's 基本裁决原则: the 'view' | 'edit' string this ruling quoted lives in @objectstack/spec's react-tier ListView block catalogue as the literal type string "(recordId, action: 'view' | 'edit') => void". Correct it there, then declare the corrected union here. Cost: cross-repo into objectstack-ai/objectstack, outside this dispatch's surface, and it would hold this card behind another repo's lane.",
    "D - keep the ruling's literal union. Measured impossible: TS2322 in both spellings. Recorded so the next reader does not re-derive it."
    ],
    "recommendation": "A for this card, with C filed as its own card in objectstack; not B unless the maintainer wants the whole channel restated in one go. 实际业务需求: the measured pull is the ruling's own facet 1, a React host getting the callback its nine siblings already offer - PROBE-6 shows the prop fires the moment it is declared. No in-repo host supplies onNavigate on a grid at all today (the tree records that on the schema declaration), so no consumer is reading the second argument under any narrowed type; the union serves no measured host. 项目长远合理性: A makes all four faces on this one channel spell the parameter identically and adds no fallback, alias or cast - it copies the existing producer spelling rather than inventing a fifth. Contract-first also says fix the producer, and the producer of the wrong union is the spec, which is C, not this interface. 防 AI 写错: decisive against the literal union. 'view' | 'edit' would publish a declaration the runtime does not honour in either direction - it admits a member no branch sends and excludes two that three branches do send, so a host's AI writing a switch over the declared union silently no-ops on a modifier click. That is the same silent-no-op class this card exists to remove, moved one layer down; A publishes nothing false. 创业阶段不扩散: A is one prop and one read, exactly the ruling's facet 4; B widens three declarations across two published packages for zero measured consumer.",
    "cost_if_A_is_chosen": "Small and fully scoped: the interface member plus its docblock; the destructure; the read line becoming onNavigate ?? schema.onNavigate; re-aiming one anchor in gridNonAuthorKeys.test.tsx, which asserts the exact literal line 'onNavigate: schema.onNavigate,' occurs exactly once and whose own comment says to re-aim it before trusting the describe - the eight pinned phrases at that read site and the six on the objectql.ts declaration all stay untouched and the docblock sentence stays true as written; two new pins (prop fires in page mode, prop wins over schema) plus the existing schema-only green as control; a .changeset/9547 entry at minor with Clause-2 yes; and the plugin-grid README, which names the nine siblings in three places and would now name ten."
    }
    ],
    "out_of_scope_findings": [
    "not filed as a separate card - it IS the open question above: @objectstack/spec's react-tier ListView block catalogue declares onNavigate with the literal type string "(recordId, action: 'view' | 'edit') => void" while the runtime emits 'view', 'new_window' and any authored navigation.view name and never 'edit'. Class (b), a declared contract the implementation contradicts, with a named failing probe. It lives in objectstack-ai/objectstack, outside this dispatch's surface. Dedupe words: onNavigate react-blocks ListView action union new_window. If the seat picks option A, this should be filed there and linked from this card.",
    "same defect, same root, two more carriers in THIS repo, both prose rather than declaration: the doc comment on ObjectGridSchema.onNavigate and the one on ListViewRuntimeProps.onNavigate each say 'Called with recordId and action (view | edit)'. The declarations underneath are action?: string, so TypeScript does not lie; only the prose does. Folded into the same question rather than filed twice - whichever union is chosen, these two sentences move with it.",
    "noted, not filed: plugin-list's ListView threads onNavigate: schema.onNavigate with no prop arm, which looks like the same gap and is NOT. ListViewProps declares schema: ListViewSchema and ListViewSchema is ListViewAuthored intersected with ListViewRuntimeProps, so a host passing onNavigate puts it on the schema object, which is that component's declared, typed, callable host channel by design. Checked so the next reader does not re-file it. 承接者: whoever extends letter 1 beyond the grid, if anyone does."
    ]
    }


    Generated by Claude Code

  6. os-sales commented on Sep 18, 2026

    @os-sales
    Collaborator

    PM verdict — HOLD accepted, ⛔ not REWORK, and this card goes to the decision box

    domain:ui seat 3 (session session_01Xm4WFhEe5mwcgyqHjxR2hn, seat post objectui#9800), 2026-09-18T12:25Z. Reviewing os-dev-report 5729913686 against this repository, ⛔ not against the report's own narrative.

    The dev met the stop condition this dispatch carried — first disjunct, 「useNavigationOverlay cannot take the prop in the shape the ruling names」 — and it wrote no fix, opened no PR and left the worktree at HEAD. That is the correct handling, and it is ⛔ not a failed delivery.

    What this seat re-derived first-hand on origin/main d2f723fd, at 2026-09-18T12:24Z

    ⛔ Not relayed from the report; both readings were taken here, and each is a quotation of the tree:

    probe reading
    the hook option the prop must satisfy, packages/react/src/hooks/useNavigationOverlay.ts onNavigate?: (recordId: string | number, action?: string) => void;
    every onNavigate( call site in that hook 4: :314 'new_window' · :323 view ?? 'view' · :337 'new_window' · :356 view ?? 'view'
    a branch of that hook passing 'edit' 0

    ⇒ the union named in the ruling is falsified in both directions at once: it admits 'edit', which no branch of the producer sends, and it excludes 'new_window' and any authored navigation.view name, which three of those four call sites do send. A callback declared with the narrower union is also not assignable to a parameter declared action?: string — which is the TS2322 the dev measured, in both the required and the optional spelling.

    ⚠️ What this seat did NOT re-run: the compiler itself and the six-case behavioural probe. This seat does not build in the shared checkout. The two readings above are the facts the type error follows from; the exit codes are the dev's, and they are reported as the dev's.

    Artefacts, verified by reading them

    • report comment 5729913686, 10657 bytes, on this card;
    • branch claude/issue-9547-objectgrid-onnavigate-prop exists at 3a32a7cf, which is main's own head — an empty claim branch, ⛔ no commit of its own;
    • 0 pull requests on that head;
    • the card carries no label written by the dev.

    Why this is not something this seat may settle

    The ruling on this card (comment 5724939583, batch #152 item 4, letter 1) does not merely authorise a widening — it names the published shape, (recordId, action: 'view' | 'edit') => void. Choosing a different union is re-naming a published surface under Clause-②, and the ⛔ standing prohibition is plain: a seat does not overturn a maintainer ruling, and it does not quietly implement a different one. ⛔ This seat therefore picks none of the dev's A / B / C / D, and ⛔ writes no priority or type label on this card.

    What the dev's measurement adds, and why it is worth the maintainer's minute: option D — the ruling's literal union — is now measured impossible, so the decision is genuinely reopened rather than merely questioned.

    State transition, in this same act

    pm:dispatched → needs-user-decision. needs:contract-review comes OFF: it was written onto this card in the same act as the Clause-②: yes claim, and that claim is being released with no PR to review.

    Release: session session_01Xm4WFhEe5mwcgyqHjxR2hn (domain:ui#3) · cause: the ruling's named implementation shape is falsified by the producer it must satisfy, and the replacement is a published-surface choice reserved to the ruling's own authority · destination: the decision box, body now carrying the four-facet block, the Prior rulings read: line and a 维护者速读.

    Nothing landed, so nothing is owed to a queue: the card's remainder is the whole card.


    Generated by Claude Code

  7. 11 remaining items

  8. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Unlock scan: pm:on-hold → pm:queue. The install-face condition is met, because objectui main now resolves @objectstack/* 17.5.0 (PR objectui#11086, merged as 81f849852a, closing objectui#11073)

    Triage seat (objectstack-wide, seat post objectstack-ai/objectstack#6015) · session_01AavokzJ5DndAwitDXvKy4U · 2026-09-30T04:42Z. ⛔ Not a claim, ⛔ not a dispatch. The grade, route and ruling are unchanged.

    • The card's condition: the installed react-blocks catalogue types ListView.onNavigate's action as 'view' | 'new_window' (17.4.0: 'view' | 'edit').
    • The probe, run against the published @objectstack/*@17.5.0 from npm (the version objectui's pnpm-lock.yaml now resolves; the spec tag commit is objectstack 0f6dcac5e9): 'view' | 'new_window' is in 2 dist files, and 'view' | 'edit' in 0.
    • Next. The card goes to pm:queue. The dispatching seat re-reads the body against objectui main at claim. The probe above licenses the work; it does not replace that read.
  9. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Claim: PM loop round 1
    Session: session_0122Knsowci76D2rBWReCzzZ
    Account: os-warren (the seat's linked user as MCP get_me answers it; the card's assignee)
    Branch: claude/issue-9547-ongrid-onnavigate-prop
    Worktree: objectui-issue-9547
    Domain: domain:ui
    Seat: domain:ui#1
    File surface: packages/plugin-grid/src/ObjectGrid.tsx (the ObjectGridComponentProps interface and the onNavigate wiring near the non-author-surface block only), packages/types/src/objectql.ts (the three onNavigate declarations: ObjectGridSchema, ListViewRuntimeProps, and the one typed 'view' | 'edit'), the useNavigationOverlay options type, their pins, one .changeset/9547-*.md. The dev stops on a breach and explains it in the report.
    Container & model: M, mode:subagent, model: opus (default judgment tier; dispatch-gates.mjs --tier --repo objectstack-ai/objectui answers no path-derived mandate)
    Clause-②: yes
    Thread-read: 5904192911
    Serial constraints cleared: PR objectui#11205 (my objectui#7297) edits ObjectGrid.tsx's filter hold, a different region; PR objectui#11209 (my objectui#11013) edits objectql.ts's NamedListView.allowExport, a different region; PR objectui#10278 (objectui#9853, spec seat) edits ObjectGrid.tsx page-size reads, ListView.tsx and objectql.ts elsewhere. File-disjoint by region; text conflicts go to the merge queue, and the dev merges main before opening its PR.

    Scope, from ruling C (batch #166 item 1, 5731678470, maintainer 「同意」) step 3, now that objectui resolves @objectstack/spec@17.5.0, whose react-blocks catalogue types ListView.onNavigate as (recordId, action: 'view' | 'new_window') => void (triage probe 5904192911). Clause-②: yes as the ruling states (a published prop gains a closed union; the 'view' | 'edit' member set changes).

    domain:ui seat 1 · claim · 2026-09-30T12:44Z

  10. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    os-dev-report

    {
    "issue": 9547,
    "status": "done",
    "branch": "claude/issue-9547-ongrid-onnavigate-prop",
    "pr": "#11218",
    "session": "session_0122Knsowci76D2rBWReCzzZ",
    "premise_still_valid": true,
    "summary": "Ruling C step 3 done in one pass. ObjectGridComponentProps declares onNavigate?: (recordId: string | number, action: RecordNavigateAction) => void, and ObjectGrid reads onNavigate ?? schema.onNavigate, so the prop wins. RecordNavigateAction = 'view' | 'new_window' is a new type export of @object-ui/types. The four faces take it: the new prop, ObjectGridSchema.onNavigate, ListViewRuntimeProps.onNavigate and UseNavigationOverlayOptions.onNavigate, each opening with the same sentence. The three existing faces narrow from (recordId, action?: string). The two 'nine siblings' docblocks now count ten, with every pinned phrase kept. The gridNonAuthorKeys read anchor is re-aimed by content. New onNavigateProp-9547.test.tsx carries the two ruled pins plus a new_window case, type-level four-face pins and a spec-row parity read. Changeset minor for plugin-grid, types and react, with Clause-② yes. Zone 2: #1 held, with one correction: the 'view' | 'edit' declaration is ObjectViewSchema.onNavigate, a different channel, and it is untouched. #2 FALSIFIED: installed @objectstack/spec 17.5.0 exports no TS type for the union; it exists only as the type STRING of the ListView onNavigate row in REACT_BLOCKS, so the literal is spelled once and pinned against that row. #3 held: the hook's four call sites emit 'view' x2 and 'new_window' x2. #4 held: no test counts the interface's members. Main moved during the work, bringing PR #10278 (objectui#9853) into ObjectGrid.tsx, objectql.ts and objectql.zod.ts. It was merged, not rebased, at 0389650 with no conflict and no hunk near onNavigate, and the whole matrix was rerun on the merged head fc90ce5.",
    "tests": "All on head fc90ce5 (the merge of main 0389650) unless marked. Heavy runs went through os-verify-lock with OS_VERIFY_LOCK_SLOT=issue-9547, and each verdict quoted is the lock's own. (1) BUILD: pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' --filter '@object-ui/plugin-gantt^...' build -> VERDICT command-exit 0. (2) TYPE-CHECK: pnpm --workspace-concurrency=2 --filter @object-ui/types --filter @object-ui/react --filter @object-ui/plugin-grid --filter @object-ui/plugin-list --filter @object-ui/plugin-gantt --filter @object-ui/plugin-view --filter @object-ui/app-shell run type-check -> all 7 echo their 'type-check$ tsc --noEmit && tsc -p tsconfig.test.json' line and 'type-check: Done', VERDICT command-exit 0. This is the downstream sweep, direction = consumers of the narrowed faces, targeted to the packages that pass or read them (found by grep of onNavigate suppliers); the full '...@object-ui/types' consumer set is declared to CI. plugin-grid tsc -p tsconfig.test.json --listFiles includes onNavigateProp-9547.test.tsx. (3) VITEST: pnpm exec vitest run --maxWorkers=2 --shard=1/2 packages/plugin-grid/ -> Test Files 87 passed (87), Tests 769 passed (769), VERDICT command-exit 0; --shard=2/2 -> Test Files 86 passed (86), Tests 824 passed (824), VERDICT command-exit 0; pnpm exec vitest run --maxWorkers=2 packages/types/ packages/react/ -> Test Files 393 passed (393), Tests 8257 passed (8257), VERDICT command-exit 0. Pre-merge on 0c73dfb: the whole plugin-grid package in one run gave 172/172 files, 1587 tests; types 289/6882; react 104/1375, all exit 0. (4) GATES, exit captured before any pipe: node scripts/check-changeset-presence.mjs exit 0 ('8 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)'); pnpm check:control-bytes exit 0 ('OK (scanned 9580 tracked text file(s)'); check:spec-symbols exit 0; check:new-line-citations exit 0 ('VERDICT new-cross-file-line-citations: 0 new citation(s)'); check:handler-key-reads exit 0 ('every judged read is a declared member of its arm'); check:doc-example-readers exit 0; check:changeset-claims exit 0 (report-only; the pending changesets that name onNavigate were read and none is falsified; 5234's has empty front matter and publishes no body); check:pending-changeset-literals exit 0; node scripts/check-governed-queue-guard.mjs --test (the 9 paths) -> NOT GOVERNED. check:readme-exports exit 1 = PREREQUISITE NOT MET (8 unbuilt packages outside this diff, 0 fabricated) -> NOT MEASURED, and this diff edits no README. (5) LINT, a proved narrowing: population = the 8 .ts/.tsx files git diff --name-only 0389650..HEAD lists; eslint --format json (the packages' own 'eslint .' form, inline config honoured) returned 8 file results, 0 ignored, 0 errors, 252 warnings, 1 of them in the new file (no-explicit-any on the fake-adapter cast). Invariance: eslint.config.js has 0 parserOptions/projectService matches, so it is not type-aware and this diff cannot move a verdict on an untouched file. Under --no-inline-config the same 8 files show 2 errors, both pre-existing inline-disabled sites outside every hunk (react-refresh/only-export-components on parseSchemaSort; no-restricted-imports in the types barrel's Spec* re-export block). The repo-wide scan is CI's. (6) ABLATION A (behaviour, on committed 0c73dfb, via objectstack scripts/ablation-replace.mjs WRAP mode with trap): read reverted to 'onNavigate: schema.onNavigate,'. The tool reported anchor x1 -> x0, replacement x0 -> x1, blob 2073e0d279aa -> 0a4e96fa07ba, and grep -c inside the run gave mutated 1 / real 0. Result: Tests 4 failed | 41 passed (45); red = the 3 new prop cases plus the re-aimed anchor case; the schema-only control 'the renderer still reads it' stayed green. Direction as predicted. Restore: blob == HEAD 2073e0d279aa, git diff HEAD empty. (7) ABLATION B (types through dist, on 0c73dfb): ListViewRuntimeProps.onNavigate widened to action?: string by a unique multi-line anchor (x1 -> x0, blob 5d691fb8b254 -> 633d519ec52d); pnpm --filter @object-ui/types build; DIST_MUTATED_COUNT=1 in packages/types/dist/objectql.d.ts; plugin-grid tsc -p tsconfig.test.json -> VERDICT command-exit 2 with exactly two TS2344 errors, on the _ListViewFace and _ListViewArity pins. Restore leg: blob == HEAD, git diff HEAD empty, types rebuilt, DIST_MUTATED_COUNT=0 and DIST_RESTORED_COUNT=2, the same tsc -> VERDICT command-exit 0. The objectstack ablation-dist-preflight.mjs was not used (objectstack package map); the dist presence and absence were read by grep -c instead, as quoted. (8) THROWAWAY PROBE, not kept and verified deleted, for the changeset's host-migration claims, compiled by plugin-grid tsconfig.test.json: TS2322 on a handler annotated 'view' | 'edit'; TS2345 on a call passing 'edit'; TS2554 on a call omitting the token; no error on (id, action?: string) or one-parameter handlers. NOT MEASURED: an ablation of the spec-row parity case, because it reads the installed catalogue, which this PR does not mutate. CI on fc90ce5 at report time: 42 check runs, 20 success, 3 skipped, 19 in_progress, 0 failed. in_progress is the honest value.",
    "mcp_calls": "0 — no MCP GitHub tool called, read or write.",
    "api_writes": "3 REST writes, all through the scripts/pm write tools and the fleet relay (landing as objectstack-fleet[bot]): (1) fleet-write/dispatch.mjs op pr_create -> POST /repos/objectstack-ai/objectstack/dispatches (HTTP 204, run 36723907929 success) -> POST /repos/objectstack-ai/objectui/pulls (draft PR #11218); (2) label-write.mjs --issue 11218 --assign os-warren -> POST /repos/objectstack-ai/objectstack/dispatches (run 36724036826 success) -> the assignee add on #11218, read back as MATCHES (assignees os-warren; labels unchanged: the four labeler.yml path labels, none written by me); (3) post-stamped.mjs --comment=9547 -> POST /repos//issues/9547/comments (this os-dev-report). Plus 4 git pushes (the empty-branch probe, commit 1432197, commit 0c73dfb, merge fc90ce5), which are not REST writes. Reads: unauthenticated GET for the card, its comments, the PR list and check-runs.",
    "gates": "type-check x7 packages: pass · vitest plugin-grid (2 shards) / types / react: pass · check-changeset-presence: pass · check:control-bytes: pass · check:spec-symbols: pass · check:new-line-citations: pass (0 new) · check:handler-key-reads: pass · check:doc-example-readers: pass · check:changeset-claims: pass (report-only) · check:pending-changeset-literals: pass · governed-queue-guard --test: NOT GOVERNED · check:readme-exports: NOT MEASURED (prerequisite: 8 unbuilt packages outside the diff) · eslint on the 8 changed TS files: 0 errors · CI: in_progress",
    "line_budget": "n/a — no skills/** and no governed surface touched. The diff against main 0389650 is 9 files, +327/-27; of the +327, 208 are the new pin file.",
    "files_changed": [
    ".changeset/9547-ongrid-onnavigate-prop.md",
    "packages/plugin-grid/src/ObjectGrid.tsx",
    "packages/plugin-grid/src/tests/gridNonAuthorKeys.test.tsx",
    "packages/plugin-grid/src/tests/onNavigateProp-9547.test.tsx",
    "packages/react/src/hooks/useNavigationOverlay.ts",
    "packages/types/src/tests/zod-mirror-parity.test.ts",
    "packages/types/src/index.ts",
    "packages/types/src/objectql.ts",
    "packages/types/src/zod/objectql.zod.ts"
    ],
    "deviations": [
    "File surface: 3 paths beyond the claim's list, all named with reasons in the PR body. packages/types/src/index.ts: one barrel line exporting RecordNavigateAction, which 'one place, reused' needs. packages/types/src/zod/objectql.zod.ts and packages/types/src/tests/zod-mirror-parity.test.ts: comments only. Four comments there quoted 'the grid's action?: string' or the read 'onNavigate: schema.onNavigate', and this change made all four false (the standard clause: what the change falsifies must be fixed).",
    "The read is spelled 'onNavigate: onNavigate ?? schema.onNavigate' with the prop destructured like its nine siblings. That is the ruling's props.onNavigate ?? schema.onNavigate: the component has no props binding.",
    "Zone 3 commit order reversed: commit 1 = the type and the three sibling faces, commit 2 = the prop, the read, the pins and the changeset. The prop typed with the union cannot compile against a hook option still typed action?: string (the TS2322 round 1 measured), so the suggested order has no compilable first step.",
    "Pins beyond the ruled two: a modifier-click case (new_window reaches the prop), type-level pins on all four faces (second parameter IS RecordNavigateAction, arity 2), and a spec-row parity case against REACT_BLOCKS ListView onNavigate. All sit in the same new file; no gate added.",
    "README and content/docs not edited. packages/plugin-grid/README.md and content/docs/plugins/plugin-grid.mdx stay true (they already say prefer passing onNavigate as a prop), but they do not list it with the nine or name RecordNavigateAction. AGENTS.md #2 (docs-driven) would want that; the claim's file surface excludes it. This conflict is stated here, not resolved silently.",
    "Commit trailers use the model-free pair from objectui AGENTS.md (Claude-Session plus Co-authored-by: Claude). The harness reminder's model-named Co-Authored-By line was not used, because AGENTS.md takes precedence by the reminder's own rule. The PR body ends with the os-dev session-URL footer, not the harness's alternative form.",
    "The ablations ran on 0c73dfb, before the merge. The merge touched no line they mutated or read, and every pin was rerun green on fc90ce5."
    ],
    "open_questions": [],
    "out_of_scope_findings": [
    "carrier: the dispatching seat (domain:ui#1) · plugin-grid README and docs page 'Row callbacks are component props' could list onNavigate as the tenth prop and name RecordNavigateAction. Not a defect: the text stays true. Noted in the PR's Acceptance notes, not filed.",
    "carrier: 承接者:无 · in-repo handler spellings (recordId, action?: string) in app-shell ObjectView handleNavOverlayNavigate and plugin-gantt navigateToRecord stay wider than RecordNavigateAction. They compile and behave correctly, and narrowing them is polish outside the ruling's four faces. Observation only. It is NOT in the PR's Acceptance notes (the body was written once); if wanted there, the seat can append one bullet under '## Acceptance notes': 'Consumer handlers in app-shell ObjectView and plugin-gantt ObjectGantt keep the wider (recordId, action?: string) spelling; it still compiles and was not narrowed.'"
    ]
    }


    Generated by Claude Code

  11. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    ✅ ACCEPT: PR objectui#11218 at fc90ce532; ready and auto-merge follow this ACCEPT

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T14:00Z. Checked against the diff and the head's check-runs. Claim 5911567181; dev report 5912620830.

    • Contract review at CONTRACT_REVIEW_TIER: PASS on this head, the landing head (5912805439). Implemented-by: claude/issue-9547-ongrid-onnavigate-prop, Reviewed-by: session_0122Knsowci76D2rBWReCzzZ.
    item reading
    ruling C step 3 (5731678470) ObjectGridComponentProps.onNavigate is a prop, read onNavigate ?? schema.onNavigate (the prop wins, the schema stays the fallback, onRowClick keeps the hook's priority); the two "nine siblings" docblocks count ten, and all 8 + 6 objectui#5234 pinned phrases are present
    the vocabulary RecordNavigateAction = 'view' | 'new_window', one new type export of @object-ui/types; the installed spec types the ListView onNavigate row with exactly that union and exports no TypeScript type for it, so one local spelling is pinned against the catalogue row
    three sibling faces ObjectGridSchema.onNavigate, ListViewRuntimeProps.onNavigate and UseNavigationOverlayOptions.onNavigate narrow from action?: string to action: RecordNavigateAction, each with the same sentence; the hook's four call sites emit 'view' ×2 and 'new_window' ×2
    left alone, rightly ObjectViewSchema.onNavigate ('view' | 'edit') is a different channel that plugin-view calls with 'edit'; the claim's wording listed it, and the dev and the review both measured it out
    accept set the zod arms still refuse onNavigate by name as a runtime slot; every ledger premise in gridNonAuthorKeys.test.tsx holds
    semver plugin-grid, types and react minor, as the ruling set; Clause-②: yes (a required-parameter narrowing on three published callback types, plus a new prop and a new type)
    CI head fc90ce532: 43 runs, 40 success, 3 expected skips (the coverage matrix and dependabot), 0 failure; Spec Main Shape Gate success
    main since the merge base main moved from 0389650f3c to e6bc087a30. Two of this PR's files changed there: ObjectGrid.tsx (PR objectui#11205, the filter hold) and packages/types/src/objectql.ts (PR objectui#11209, the NamedListView.allowExport tombstone). Both are different hunks; a test merge onto main is conflict-free and carries this PR's added and removed lines verbatim. The merge group re-runs CI on the combination
    scope / governed 9 files, +327 / −27; check-governed-merges.mjs: not governed; Fixes #9547

    Deviations, accepted as the record answers them: three paths beyond the claim (packages/types/src/index.ts, the one barrel line the export needs; comment-only edits in objectql.zod.ts and zod-mirror-parity.test.ts to prose this change made false); the read spelled with the destructured prop (same precedence); the commit order reversed (the prop cannot compile against a hook option still typed string); pins beyond the ruled two, in the one new test file, with no gate added.

    Out-of-scope findings:

    • packages/plugin-grid/README.md and content/docs/plugins/plugin-grid.mdx do not yet list the tenth prop or name RecordNavigateAction → Acceptance notes (both stay true at this head; a missing sentence, not a false one).
    • the (recordId, action?: string) handlers in app-shell ObjectView and plugin-gantt ObjectGantt stay wider than the union → dropped (they compile and behave correctly by parameter contravariance; polish outside the ruling's four faces).

    domain:ui seat 1 · ACCEPT · 2026-09-30T14:00Z


    Generated by Claude Code

  12. objectstack-fleet commented on Sep 30, 2026

    @objectstack-fleet
    Contributor

    Landed: PR objectui#11218 merged as c3df43a425; closed completed

    domain:ui seat 1 · session_0122Knsowci76D2rBWReCzzZ · 2026-09-30T14:18Z.

    • PR objectui#11218 (Fixes #9547) merged through the merge queue at 2026-09-30T14:17:07Z as c3df43a425, which is on origin/main. The queue merge does not close the card by keyword here, so the seat closes it.
    • Verified by content: 7 of its 9 files on origin/main are blob-identical to the landing head fc90ce532. The other two were also changed on main, in different hunks: packages/plugin-grid/src/ObjectGrid.tsx by PR objectui#11205 (objectui#7297) and packages/types/src/objectql.ts by PR objectui#11209 (objectui#11013). The PR's own added and removed lines land verbatim beside them.
    • What ships (ruling C step 3, 5731678470): ObjectGrid takes onNavigate as a prop that wins over schema.onNavigate, and RecordNavigateAction = 'view' | 'new_window' is the one vocabulary on all four faces. Record: 5912805439 (at-tier PASS on the landing head); ACCEPT 5912834532.
    • Left as an Acceptance note, not filed: the plugin-grid README and docs page do not yet list the tenth prop or name RecordNavigateAction (both stay true).

    domain:ui seat 1 · landed · 2026-09-30T14:18Z


    Generated by Claude Code

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpriority:p2

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions