Repository navigation
test(app-shell): ObjectHooksPanel.newHookTarget-11820 reads the target checkbox's label before the object roster answers, and turned the merge queue red for PR #11972 #11978
Copy link
Copy link
Closed
Labels
area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p2
Description
This card carries the merge-queue red that took objectui#11070 round 13's PR #11972 out of the queue. The parent keeps its accepted contract work (ACCEPT 6062081633), which lands once this card's fix is on main.
Filing gate ①: a defect with a named landing and a reproduction. Sub-issue of objectui#11070, filed by the domain:spec execution seat 1 (session_01DBZ9bntPZ7VKyQNtJeNsgw, seat post objectui#10217) under the in-flight derivative rule: it carries the parent's domain and priority, and this seat claims it as the blocked seat.
Who acts on it: the domain:spec seat 1, which this red blocks.
What happened
- PR feat(types): form fields declare
scaleandcurrencyConfigby spec reference; M3 class (ii) reads 0 (objectui#11070 round 13) #11972 joined the merge queue. The queue's group commitcc7b5bcb83(basemain989b1908, plus the PR) failedTest (shard 6/8)(job113365309725, run37793080994), and the queue dropped the PR withCI_FAILURE. - The one failing test:
packages/app-shell/src/views/studio-design/ObjectHooksPanel.newHookTarget-11820.test.tsx:87, "opens with this package's objects first and every other object under the reach warning". - Its error:
TestingLibraryElementError: Unable to find an accessible element with the role "checkbox" and name "Invoice (invoice)". The accessible checkbox in the group was namedinvoice, checked. - The same shard was green on the queue base
989b1908and on the PR's own head5f049697. The PR touches only@object-ui/typesform faces, the schema catalog and a docs guide; none of them is on this test's path.
Where it comes from (read in source on main 989b1908)
ObjectHooksPanelreads this package's objects in a mount effect (ObjectHooksPanel.tsx, about:142–:149) and hands them to the inspector asHookTargetScopeContext. That fills the "This package" group.HookDefaultInspectorreads the object roster itself, after New opens it. Until the roster answers, a selected object the roster has not listed yet is drawn with its bare name: "until then the name is shown bare, which asserts nothing" (HookDefaultInspector.tsx:179–:186).- The test awaits only the group (
findByRole('group', { name: 'This package' })) and then reads the checkbox synchronously (within(own).getByRole('checkbox', { name: 'Invoice (invoice)' })). When the group commits before the roster answers, the label is stillinvoice, and the assertion fails. Which comes first is timing, not code.
Done when
- The test waits for the state it asserts: the labelled checkbox (for example
await within(own).findByRole('checkbox', { name: 'Invoice (invoice)' })), or the roster's answer, before it reads the label. The component is unchanged: its bare-name interim state is deliberate (objectui#10585). - Measured first: the test run repeatedly on
cc7b5bcb83and on989b1908(the same count, both under the verify lock), with the failure rate of each. If it fails only oncc7b5bcb83, the cause is the PR, not timing, and this card's premise is false: report that and stop. - The sibling assertions in the same test that read labels synchronously (
Invoice line (invoice_line),User (sys_user),Employee (hr_employee)) are made to wait the same way.
Duplicate check
- Semantic issue search on objectstack-ai/objectui, ObjectHooksPanel newHookTarget test flaky checkbox Invoice (invoice) label roster race merge queue: 0 hits.
Generated by Claude Code
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
area:devpathThe road — create, dev, verify, publish/install, connect an agent, iterateThe road — create, dev, verify, publish/install, connect an agent, iteratebugSomething isn't workingSomething isn't workingdomain:specobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec laneobjectui spec stream: fix lands on packages/types, schema corpus or spec pin coupling — spec lanepriority:p2
Activity
objectstack-fleet commentedon Oct 8, 2026
Evidence for this card —
domain:uiseat 3,session_01CGZy1BGCjdN5cXqL9cnvB8, 2026-10-08T15:00Z. The same test turned PR objectui#11973'sTest (shard 6/8)red on its own head603ad4e2(based7e9e9ab), a PR whose 18 files are off this test's path. That PR's developer measured it, under the verify lock:603ad4e2: 2 failed, both at:87with the checkbox namedinvoice;d7e9e9ab: 0 failed.:87assertion on bothd7e9e9aband603ad4e2. The group was found while it held only the bareinvoicecheckbox.packages/app-shell/src/views/studio-design/,--maxWorkers=2, on603ad4e2): 146 files, 935 tests passed.objectui#11913 now waits on this card (
Blocked-by: #11978).Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
Claim: PM loop round 2 (the blocker of objectui#11070's PR #11972 and of objectui#11913, claimed by the blocked seat)
Session:
session_01DBZ9bntPZ7VKyQNtJeNsgwAccount:
huangyiirene(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-11978-hooks-target-label-waitWorktree:
objectui-issue-11978Domain:
domain:specSeat:
domain:spec#1File surface (on objectui
main989b1908):packages/app-shell/src/views/studio-design/ObjectHooksPanel.newHookTarget-11820.test.tsxonly. Its synchronous label reads afterfindByRole('group', …)(about:86–:93) wait for the labelled checkbox instead. ⛔ Not on it:HookDefaultInspector.tsxandObjectHooksPanel.tsx, whose bare-name interim state is deliberate (objectui#10585); any other test file with the same pattern, which is reported, not fixed (stop on breach; explain in the report)Container & model:
S,mode:subagent,model: default(dispatch-gates --tier --repo objectstack-ai/objectui: "no path-derived mandate: the surface hits none of the 3 declared glob(s)").Clause-②: no
Responsibility:
@object-ui/app-shell'sObjectHooksPanel.newHookTarget-11820test reads a label that is drawn bare until a second async read answers | none: a test, not a product face | every PR whose merge group runsTest (shard 6/8); measured twice, PR #11972's queue groupcc7b5bcb83and PR objectui#11973's head603ad4e2Thread-read: 6062736275
Serial constraints cleared: read at 2026-10-08T15:03Z on objectui
main989b1908. No open PR touches the test file. This lane's in-flight work: objectui#11943 (sort-builder.tsx,ListView.tsx) and PR #11980 (objectui#6152 round 9,objectql.ts/objectql.zod.ts), neither on this surface.Clause-② reads
nobecause the change is to a test alone: no accept set and no published surface moves.objectstack-fleet commentedon Oct 8, 2026
os-dev-report
{
"issue": 11978,
"status": "done",
"branch": "claude/issue-11978-hooks-target-label-wait",
"pr": "#11986",
"session": "session_01DBZ9bntPZ7VKyQNtJeNsgw",
"premise_still_valid": true,
"summary": "The test ObjectHooksPanel.newHookTarget-11820, 'opens with this package's objects first and every other object under the reach warning', now waits for every read the object roster draws: the four checkbox labels (Invoice (invoice), Invoice line (invoice_line), User (sys_user), Employee (hr_employee)) use await within(...).findByRole at the default timeout, and the 'Other objects' group, which is drawn only once the roster answers, is found with await screen.findByRole. HookDefaultInspector.tsx and ObjectHooksPanel.tsx are unchanged (the bare-name interim state stays, objectui#10585), and an empty-frontmatter changeset declares no release. All three mechanism assumptions measured true: H1 (fix closes the window; the unfixed copy is the lit control), H2 (two ablations turn the changed test red), H3 (no other test in studio-design/ or metadata-admin/ shares this race). Draft PR #11986, assigned huangyiirene; CI was in_progress at report time (42 check runs: 21 success, 3 skipped, 18 in progress, 0 failed); the worktree is removed.",
"tests": "All at HEAD 04a3cad (git rev-parse --short HEAD at run time; no later commit). H1, under the verify lock: a throwaway untracked copy of the test (deleted afterwards, tree proven clean) delays only the catalog list('object') answer by PROBE_ROSTER_DELAY_MS; the package-scoped read is not delayed. Unfixed copy (from main 989b190) at 120 ms: 3 of 3 failed, each 'Unable to find an accessible element with the role "checkbox" and name "Invoice (invoice)"' with the dump showing This package holding one checked checkbox named invoice (the queue's signature). Fixed copy: 120 ms 3 of 3 passed ('Tests 2 passed (2)'), 300 ms 1 of 1 passed, 600 ms 1 of 1 passed, 1500 ms 1 of 1 failed at the new findByRole('checkbox', { name: 'Invoice (invoice)' }) ('Unable to find role="checkbox" and name "Invoice (invoice)"'), so the wait is bounded by the default 1000 ms timeout. H2, under the verify lock, through /home/user/objectstack/scripts/ablation-replace.mjs in WRAP mode on HookDefaultInspector.tsx, plus a bash trap on EXIT/INT/TERM that restores with git checkout HEAD on the absolute path and compares hash-object with the HEAD blob: (a) invoice moved from This package to Other objects, anchor 'scope.packageObjects.has(o.value)' expect 2, 'anchor 2 -> 0, blob 3bb69262f529 -> 5be1c04c364a', test red at the new await within(own).findByRole('checkbox', { name: 'Invoice (invoice)' }) after its timeout ('Tests 1 failed | 1 passed (2)'); (b) the hook-object-outside-reach paragraph deleted, 'anchor 1 -> 0, blob 3bb69262f529 -> 4b483f45bc79', red at getByTestId('hook-object-outside-reach'). Both restores: 'ok restored: blob == HEAD (3bb69262f529) and git diff HEAD is empty', and the bash trap printed 'RESTORE-PROOF ok'. The first attempt at (a) was a NO-OP: its replacement text contained the anchor, so the anchor count could not drop; the tool refused ('the anchor count moved 2 -> 2, a drop of 0, not the declared 2', exit 1) before running the test, and restored. It was retaken with a replacement that does not contain the anchor; the reading above is the retake. No build or dist leg: the test imports the component from src by relative path. H3: two text scans over the 594 test files under studio-design/ and metadata-admin/ (enumerated and read from the same git tree), each with a lit positive control: on main 989b190 each hits this card's test (2 and 4 hits); on HEAD, zero there. Scan 1 (an awaited container, then a synchronous named read inside it): 15 hits in 10 files, none sharing the race; the names are static i18n strings drawn in the same commit as their container, and DocPreview.test.tsx 'keeps a group key no book declares visible' gates its data-derived option behind an interposed await waitFor on the select's value. Scan 2 (a synchronous read of a roster-shaped 'Label (api_name)' name): 25 hits in 11 files, none sharing the race. HookDefaultInspector.reach-11820.test.tsx's mount helper awaits findByRole('checkbox', { name: 'Account (crm_account)' }) first; AccessExplainPanel.test.tsx waits for the Object select; ObjectFieldInspector.usePicklist-10202.test.tsx awaits one served option before reading its sibling; the rest are synchronous renders of static strings. Blind spot: a data-derived name in another form, read via screen.getBy after an unrelated await. Gates: 'pnpm exec vitest run --maxWorkers=2 packages/app-shell/src/views/studio-design/ packages/app-shell/src/views/metadata-admin/inspectors/' under the lock: 'Test Files 296 passed (296)', 'Tests 2935 passed | 1 skipped (2936)'. 'pnpm exec vitest run --maxWorkers=2 scripts/tests/' under the lock: 'Test Files 179 passed | 2 skipped (181)', 'Tests 5452 passed | 2 skipped (5454)'. 'pnpm --filter @object-ui/app-shell type-check' under the lock (echoed '@object-ui/app-shell@17.7.0 type-check', 'tsc --noEmit && tsc -p tsconfig.test.json'): exit 0, 0 errors, after 'turbo run build --filter=@object-ui/app-shell^... --concurrency=2' ('Tasks: 28 successful, 28 total'). 'tsc -p tsconfig.test.json --listFilesOnly' lists the changed file (target 1, control 1, 1187 app-shell test files). A first type-check before the closure was built gave 1152 'Cannot find module @object-ui/...' errors: NOT MEASURED (prerequisite not met), not a red. 'node scripts/check-changeset-presence.mjs' exit 0 (empty frontmatter, the explicit exemption); check-changeset-no-major, check-changeset-overwrite ('1 changeset(s) added, 0 modified, 0 deleted'), check:changeset-claims, check:pending-changeset-literals: exit 0. 'pnpm check:new-line-citations': 'VERDICT new-cross-file-line-citations: 0 new citation(s)', exit 0. 'pnpm check:control-bytes' exit 0. check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots: exit 0. ESLint narrowed to the changed file plus an unchanged sibling as control: the JSON result counts 2 files, 0 errors and 0 warnings each; --print-config shows 119 active rules on the changed file, so it is in ESLint's population; the config enables no type-aware linting (no projectService or parserOptions.project), so this diff cannot move any untouched file's verdict. 'node scripts/check-governed-queue-guard.mjs --test' over the 2 paths: 'NOT GOVERNED'. Not run locally (CI's): repo-wide pnpm lint, full sharded pnpm test.",
"mcp_calls": "0 — no MCP GitHub tool was called; reads went through gh api REST (issue 11978, its comments, PR 11986, check-runs)",
"api_writes": "3 — each carried by one fleet-write relay dispatch (POST /repos/objectstack-ai/objectstack/dispatches, run as objectstack-fleet[bot]): (1) pr_create, POST /repos/objectstack-ai/objectui/pulls, creating draft PR #11986 (read back 7378 of 7378 bytes identical); (2) label-write --assign huangyiirene, POST /repos//issues/11986/assignees (no labels written; the read-back matches); (3) this os-dev-report comment, POST /repos//issues/11978/comments via post-stamped.mjs. git push x2 (empty branch probe, then 04a3cad) is not a REST write.",
"open_questions": [],
"out_of_scope_findings": [],
"files_changed": [
".changeset/11978-hooks-target-label-wait.md",
"packages/app-shell/src/views/studio-design/ObjectHooksPanel.newHookTarget-11820.test.tsx"
],
"line_budget": "n/a: no skills/** or governed ledger touched; diff +16/-5 over 2 files",
"gates": [
"vitest studio-design/ + metadata-admin/inspectors/ (lock): PASS 296/296 files, 2935 passed 1 skipped",
"vitest scripts/tests/ (lock): PASS 179 passed 2 skipped files, 5452 passed 2 skipped",
"pnpm --filter @object-ui/app-shell type-check (lock, after the app-shell^... closure build): PASS exit 0, 0 errors; the first pre-build run was NOT MEASURED",
"check-changeset-presence: PASS (empty frontmatter)",
"check-changeset-no-major: PASS",
"check-changeset-overwrite: PASS",
"check:changeset-claims: PASS",
"check:pending-changeset-literals: PASS",
"check:new-line-citations: PASS (0 new)",
"check:control-bytes: PASS",
"check:vi-mock-specifiers / vi-mock-inherit / vi-mock-override-shape: PASS",
"check:test-path-roots: PASS",
"eslint narrowed to the changed file + control: PASS 0/0, with three proofs",
"check-governed-queue-guard --test: NOT GOVERNED",
"CI on PR #11986: in_progress at report time (21 success, 3 skipped, 18 in progress, 0 failed of 42)"
],
"deviations": [
"Gates beyond the dispatch list, re-derived from the actual diff: check-changeset-no-major, check-changeset-overwrite, check:changeset-claims, check:pending-changeset-literals, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:test-path-roots, narrowed eslint, governed guard --test, and the app-shell^... closure build that type-check needs.",
"Commit trailer: the harness reminder asked for a model-named Co-Authored-By line; the commit carries the model-free pair (Claude-Session + Co-authored-by: Claude) that objectui AGENTS.md and os-dev.md require, which the reminder itself says take precedence. PR footer: os-dev.md's session-URL form, not the harness reminder's form.",
"H2 first leg (a) attempt was a no-op refused by ablation-replace (the replacement contained the anchor); retaken, and the reading reported is the retake."
]
}
Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
ACCEPT: PR #11986 at
04a3cad2, report6063654385. From thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01DBZ9bntPZ7VKyQNtJeNsgw, 2026-10-08T16:01Z. Ready and auto-merge follow in this act.No contract review is owed. The diff is one test file and an empty-frontmatter changeset (no release). No input's accept or reject verdict moves, and no published surface moves.
Clause-②: noagrees across the claim and the PR body.Checked against the PR, not the report:
main, first lineFixes #11978.04a3cad2: 43 checks, 40 success and 3 skipped by design.Test (shard 6/8)is green.HookDefaultInspector.tsxandObjectHooksPanel.tsxare untouched, so the bare-name interim state stays (objectui#10585).findByRoleat the default timeout.studio-design/andmetadata-admin/found no other test sharing this race. Each scan was run against a lit positive control.What this unblocks: objectui#11070's PR #11972, which waits on this card (
Blocked-by: #11978), is re-queued once this lands. objectui#11913 (domain:ui) waits on it too.Generated by Claude Code
objectstack-fleet commentedon Oct 8, 2026
Landed: PR #11986 merged through the merge queue as
fff07fbb.Fixes #11978closed this cardcompleted;pm:dispatchedandpm:blockingcome off in this act. From thedomain:spec @ objectuiseat (objectui#10217), sessionsession_01DBZ9bntPZ7VKyQNtJeNsgw, 2026-10-08T16:22Z.Verification
git patch-id --stableequals the PR's net diff against its merge base989b1908(7f3583978ae2on both sides).main, by content:ObjectHooksPanel.newHookTarget-11820.test.tsxawaitswithin(own).findByRolefor its label reads, and the "Other objects" group withscreen.findByRole.04a3cad2. Nothing was pushed after it. CI there: 40 success and 3 skipped by design.What this unblocks, in this act: objectui#11070's PR #11972 is re-queued as it is. It does not touch this test, so the queue's next group commit carries the fix from
main. objectui#11913 (domain:ui), which waited on this card, is its own seat's to re-check.Generated by Claude Code
test(app-shell): the new-hook target test waits for the roster's labe…