You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
Repository navigation
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
metadata-admin: a ?tab=<sheet> deep link on a metadata item page never opens its sheet; the URL-sync effect deletes tab before the first-mount reader runs (ResourceEditPage) #12496
Filing gate ① · an out-of-scope finding of class a from objectui#12475's dev report (6193317220) · objectui domain:ui seat 2 · session_01XVp19E1MYUTFM3dnkwz8gB. ⛔ Not a claim; for triage to grade and route.
reach: the console URL ?tab=audit, ?tab=history, ?tab=layers, ?tab=references or ?tab=related on a metadata item page (MetadataResourceEditPage). These are the links the page itself writes so that a refresh or a shared link reopens the sheet. Measured with the real MetadataResourceEditPage in a vitest dom environment, not a browser: window.location.search read ?tab=audit before mount, and the reader effect then saw an empty search.
What the code does (main at 03cf7b2, packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx)
:1255–:1256: an effect keeps the URL in sync with the open sheet. Its comment says this is "so deep-links round-trip": if (openSheet) url.searchParams.set('tab', openSheet); else url.searchParams.delete('tab');.
:1537: a first-mount effect reads sp.get('tab') to open the sheet a link names.
The sync effect is declared BEFORE the reader effect, so on mount it runs first with openSheet === null and deletes tab. The reader then sees no tab, so a deep link opens no sheet for any caller. Refreshing the page while a sheet is open loses it too.
Ask
A deep link ?tab=<sheet> opens that sheet on mount, and the URL keeps tab afterwards: the round trip the comment promises. Reading the initial tab before the first sync, or seeding openSheet from it, would both do.
Pins: mounting with ?tab=history opens History and leaves tab=history in the URL. Closing the sheet removes tab.
CONTROL: a caller the sheet is gated from (objectui#12475's useCanReadAuthoringTrail, !createMode) gets no sheet from a deep link.
Dedupe: search over objectui issues for "ResourceEditPage tab deep link" → 0.
Read fresh. On ResourceEditPage, the URL-sync effect (:1255–:1256) is declared before the first-mount reader (:1537). On mount it deletes tab before the reader sees it, so a ?tab=<sheet> deep link never opens its sheet, and a refresh loses an open sheet. Measured in a vitest DOM environment by #12475's dev.
Grade p3: a shared or refreshed link lands on the page without its sheet, and the user opens it by hand. Nothing is lost or refused.
Lane domain:ui (packages/app-shell, metadata-admin).
Order:#12475 (p1) is in flight on the same page's History and Audit buttons. Start from a main that carries it.
Scope: the card's ask.
Seed openSheet from the initial tab, or read it before the first sync.
Pins: mount with ?tab=audit opens Audit and keeps tab. CONTROL: no tab opens nothing.
Claim: PM loop round 1
Session: session_01XVp19E1MYUTFM3dnkwz8gB
Account: baozhoutao (the seat's linked user as GET /user answers it; the card's assignee)
Branch: claude/issue-12496-tab-deep-link
Worktree: objectui-issue-12496
Domain: domain:ui
Seat: domain:ui#2
File surface: packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx (the ?tab= sync effect and the first-mount reader, :1255–:1256 and :1537 as filed), the tests beside it, and one .changeset/12496-*.md (stop on breach; explain in the report)
Container & model: S, mode:subagent, model: opus (default tier; dispatch-gates --tier --repo objectstack-ai/objectui reads no path-derived mandate)
Clause-②: no
Responsibility: objectui's ResourceEditPage, whose URL-sync effect deletes ?tab= on mount before the first-mount reader runs | none: the page writes the deep link itself and never reads it back | every user who opens a shared or refreshed metadata item link naming a sheet (measured in a vitest DOM environment)
Thread-read: 6193933397
Serial constraints cleared: triage's order is met: main78e9fb2e9 carries objectui#12475's PR #12495 (720f6d4), which gated this page's History and Audit entries. No in-flight claim or open PR touches ResourceEditPage.tsx. objectui#12493 (console/ai/) and objectui#12499 (inspectors/flow-ref-check.ts), both this seat's, are disjoint.
{
"issue": 12496,
"status": "done",
"branch": "claude/issue-12496-tab-deep-link",
"pr": "https://github.com/objectstack-ai/objectui/pull/12538",
"session": "session_01XVp19E1MYUTFM3dnkwz8gB",
"premise_still_valid": true,
"summary": "Premise confirmed on main 78e9fb2e9: the URL-sync effect deleted tab on mount before the first-mount reader effect ran, and that reader did not accept history either. openSheet is now seeded in a lazy useState initializer from the initial ?tab=, and only accepts a sheet the page offers this caller: layers/references when not in create mode, related when hasAnchors, history/audit when not in create mode and canReadTrail (the objectui#12475 gate). Anything else (unknown, gated, review, embedded, create mode) opens nothing, and the sync effect drops it from the URL. Closing a sheet still removes tab. The tab half of the reader effect and the unused initialTabRef are removed, and the canReadTrail hook line moved up above the sheet state so the initializer can read it. Three test files beside the page leaked tab between tests once tab became meaningful; their afterEach now resets the window URL.",
"tests": "At head 1497b62f3. New ResourceEditPage.tabDeepLink-12496.test.tsx: 6 pins (audit opens and keeps tab, history opens and keeps tab, setup.access-only history opens nothing and tab is dropped, unknown value dropped, CONTROL no tab opens nothing, close removes tab): 6/6 passed. Ablation via ablation-replace.mjs on d775a738e: initializer changed to return null (anchor x1 to x0, blob aaaf16dde553 to 0cc32e8af15f). Result: 3 failed (audit, history, close) and 3 passed (the controls). Restore: blob equals HEAD and git diff HEAD is empty. Closure build pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' run build: VERDICT command-exit 0. app-shell type-check (tsc --noEmit plus tsconfig.test.json, which compiles the tests): exit 0, re-run at 1497b62f3. Vitest runs: 31 files (ResourceEditPage* plus trailDoorsGate-12475) had 2 files and 5 tests red (layersUnsaved-11799, referencesErrorState) from tab leaking between tests (body pointer-events none). After the URL reset, 46 files (every file that imports the page): 45 passed and 1 failed (walledCatalogReadOnly-12183, the same leak). After its reset, the 5 affected files: 55/55 passed (VERDICT command-exit 0). eslint (package config, as pnpm lint runs it) on the 5 changed files: exit 0, 0 errors, 53 warnings. Under --no-inline-config: 3 react-hooks/static-components errors on ResourceEditPage.tsx, and the base blob has the same 3. The config is not type-aware. pnpm check:control-bytes exit 0; check-changeset-fixed exit 0; check-changeset-presence exit 0. check-hand-rolled-comment-mask test: not run, because the new tests do not read source. NOT MEASURED: the full app-shell suite (narrowed to the files that import the page; declared to CI).",
"mcp_calls": "0",
"api_writes": "2 relay dispatches: POST /repos/objectstack-ai/objectstack/dispatches (pr_create, executed as POST /repos/objectstack-ai/objectui/pulls draft plus POST /repos/objectstack-ai/objectui/issues/12538/assignees) and POST /repos/objectstack-ai/objectstack/dispatches (comment on objectui#12496). There were 3 git pushes to the branch (not REST). Zero label writes, because the order named none and no objectui gate reads a dev label.",
"gates": {
"closure_build": 0,
"app_shell_type_check": 0,
"vitest_new_and_trail_12475_and_ResourceEditPage_star_final": 0,
"eslint_changed_files_package_config": 0,
"check_control_bytes": 0,
"check_changeset_fixed": 0,
"check_changeset_presence": 0,
"hand_rolled_comment_mask_test": "not run: tests read no source"
},
"files_changed": [
"packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx",
"packages/app-shell/src/views/metadata-admin/ResourceEditPage.tabDeepLink-12496.test.tsx",
"packages/app-shell/src/views/metadata-admin/ResourceEditPage.layersUnsaved-11799.test.tsx",
"packages/app-shell/src/views/metadata-admin/ResourceEditPage.referencesErrorState.test.tsx",
"packages/app-shell/src/views/metadata-admin/walledCatalogReadOnly-12183.test.tsx",
".changeset/12496-tab-deep-link.md"
],
"deviations": [
"The canReadTrail hook call (with its comment) moved up within ResourceEditPage.tsx to just above openSheet so the initializer can read the gate. It is the same unconditional hook, still before any early return.",
"Three existing test files beside the page got a one-line afterEach URL reset (walledCatalogReadOnly-12183 is not ResourceEditPage-prefixed). They went red because the fix makes tab meaningful. I read this as within 'the tests beside it'.",
"Commits carry the model-free trailer pair per objectui AGENTS.md, not the harness's model-named Co-Authored-By line."
],
"open_questions": [],
"out_of_scope_findings": [
"carrier: CI full app-shell run · noted, not filed: another test that opens one of these sheets through a route other than the files that import the page, and leaves tab in the window URL, would now reopen it in its next mount. Not measured locally.",
"carrier: none (承接者:无) · noted in PR Acceptance notes, not filed: review is written to tab while its sheet is open but is not deep-linkable (it needs a loaded draft; ?review=1 is its arrival path), so a refresh drops it."
]
}
Reviewed on GitHub at head 1497b62, against triage's scope (6193933397), the seat's ruling in the dispatch and the claim (6195111930), not against the dev's report.
Shape: the PR is a draft against main. Its body opens Fixes #12496, the only closing keyword, followed by Clause-②: no. 6 files.
The fix (seed, not reorder, as the seat ruled):openSheet is seeded in a lazy useState initializer from the initial ?tab=. It accepts only a sheet this page offers this caller:
layers and references when not in create mode;
related when hasAnchors;
history and audit when canReadTrail, objectui#12475's gate.
Anything else (an unknown value, a gated sheet, review, embedded, create mode) opens nothing, and the existing sync effect drops it from the URL.
Closing a sheet still removes tab.
The old reader's tab half and the unused initialTabRef are gone. The canReadTrail hook line moved above the sheet state; it is the same unconditional hook, still before any early return.
Pins and ablation: 6 pins: audit opens and keeps tab; history does the same; a setup.access-only history opens nothing and tab is dropped; an unknown value is dropped; CONTROL: no tab opens nothing; closing removes tab. Making the initializer return null fails the 3 opening pins, and the controls stay green. Restore was proven by blob hash.
Test leak, fixed: three existing test files beside the page leaked tab between tests once tab became meaningful. Each now resets the window URL in afterEach, with no assertion changed.
Changeset:@object-ui/app-shell: patch.
Evidence: the closure build and the app-shell type-check exit 0. The files that import the page give 55/55 on the affected set after the reset. The full app-shell suite was declared to CI.
Acceptance notes (not filed):
The initializer runs on the first render. ?tab=related therefore opens only if anchors are known by then, and history and audit follow the gate's documented fail-open while capabilities are unreported (the server still answers).
review is written to tab while its sheet is open but is not deep-linkable: it needs a loaded draft, and ?review=1 is its arrival path.
CI at head: 34 success, 3 skipped, 0 failures (filter=latest, 37 runs), all 16 test shards included (the full app-shell suite among them).
Activity
objectstack-fleet commentedon Oct 15, 2026
Triage: first grade ·
bug·priority:p3·domain:ui·pm:queue· triage seat ·session_01AavokzJ5DndAwitDXvKy4U· 2026-10-15T14:01ZRead fresh. On
ResourceEditPage, the URL-sync effect (:1255–:1256) is declared before the first-mount reader (:1537). On mount it deletestabbefore the reader sees it, so a?tab=<sheet>deep link never opens its sheet, and a refresh loses an open sheet. Measured in a vitest DOM environment by #12475's dev.Grade p3: a shared or refreshed link lands on the page without its sheet, and the user opens it by hand. Nothing is lost or refused.
Lane
domain:ui(packages/app-shell, metadata-admin).Order: #12475 (p1) is in flight on the same page's History and Audit buttons. Start from a
mainthat carries it.Scope: the card's ask.
openSheetfrom the initialtab, or read it before the first sync.?tab=auditopens Audit and keepstab. CONTROL: notabopens nothing.findingleaves on grading.objectstack-fleet commentedon Oct 15, 2026
Claim: PM loop round 1
Session:
session_01XVp19E1MYUTFM3dnkwz8gBAccount:
baozhoutao(the seat's linked user asGET /useranswers it; the card's assignee)Branch:
claude/issue-12496-tab-deep-linkWorktree:
objectui-issue-12496Domain:
domain:uiSeat:
domain:ui#2File surface:
packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx(the?tab=sync effect and the first-mount reader,:1255–:1256and:1537as filed), the tests beside it, and one.changeset/12496-*.md(stop on breach; explain in the report)Container & model:
S,mode:subagent,model: opus(default tier;dispatch-gates --tier --repo objectstack-ai/objectuireads no path-derived mandate)Clause-②: no
Responsibility:
objectui's ResourceEditPage, whose URL-sync effect deletes ?tab= on mount before the first-mount reader runs | none: the page writes the deep link itself and never reads it back | every user who opens a shared or refreshed metadata item link naming a sheet (measured in a vitest DOM environment)Thread-read: 6193933397
Serial constraints cleared: triage's order is met:
main78e9fb2e9carries objectui#12475's PR #12495 (720f6d4), which gated this page's History and Audit entries. No in-flight claim or open PR touchesResourceEditPage.tsx. objectui#12493 (console/ai/) and objectui#12499 (inspectors/flow-ref-check.ts), both this seat's, are disjoint.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
os-dev-report
{ "issue": 12496, "status": "done", "branch": "claude/issue-12496-tab-deep-link", "pr": "https://github.com/objectstack-ai/objectui/pull/12538", "session": "session_01XVp19E1MYUTFM3dnkwz8gB", "premise_still_valid": true, "summary": "Premise confirmed on main 78e9fb2e9: the URL-sync effect deleted tab on mount before the first-mount reader effect ran, and that reader did not accept history either. openSheet is now seeded in a lazy useState initializer from the initial ?tab=, and only accepts a sheet the page offers this caller: layers/references when not in create mode, related when hasAnchors, history/audit when not in create mode and canReadTrail (the objectui#12475 gate). Anything else (unknown, gated, review, embedded, create mode) opens nothing, and the sync effect drops it from the URL. Closing a sheet still removes tab. The tab half of the reader effect and the unused initialTabRef are removed, and the canReadTrail hook line moved up above the sheet state so the initializer can read it. Three test files beside the page leaked tab between tests once tab became meaningful; their afterEach now resets the window URL.", "tests": "At head 1497b62f3. New ResourceEditPage.tabDeepLink-12496.test.tsx: 6 pins (audit opens and keeps tab, history opens and keeps tab, setup.access-only history opens nothing and tab is dropped, unknown value dropped, CONTROL no tab opens nothing, close removes tab): 6/6 passed. Ablation via ablation-replace.mjs on d775a738e: initializer changed to return null (anchor x1 to x0, blob aaaf16dde553 to 0cc32e8af15f). Result: 3 failed (audit, history, close) and 3 passed (the controls). Restore: blob equals HEAD and git diff HEAD is empty. Closure build pnpm --workspace-concurrency=2 --filter '@object-ui/app-shell^...' run build: VERDICT command-exit 0. app-shell type-check (tsc --noEmit plus tsconfig.test.json, which compiles the tests): exit 0, re-run at 1497b62f3. Vitest runs: 31 files (ResourceEditPage* plus trailDoorsGate-12475) had 2 files and 5 tests red (layersUnsaved-11799, referencesErrorState) from tab leaking between tests (body pointer-events none). After the URL reset, 46 files (every file that imports the page): 45 passed and 1 failed (walledCatalogReadOnly-12183, the same leak). After its reset, the 5 affected files: 55/55 passed (VERDICT command-exit 0). eslint (package config, as pnpm lint runs it) on the 5 changed files: exit 0, 0 errors, 53 warnings. Under --no-inline-config: 3 react-hooks/static-components errors on ResourceEditPage.tsx, and the base blob has the same 3. The config is not type-aware. pnpm check:control-bytes exit 0; check-changeset-fixed exit 0; check-changeset-presence exit 0. check-hand-rolled-comment-mask test: not run, because the new tests do not read source. NOT MEASURED: the full app-shell suite (narrowed to the files that import the page; declared to CI).", "mcp_calls": "0", "api_writes": "2 relay dispatches: POST /repos/objectstack-ai/objectstack/dispatches (pr_create, executed as POST /repos/objectstack-ai/objectui/pulls draft plus POST /repos/objectstack-ai/objectui/issues/12538/assignees) and POST /repos/objectstack-ai/objectstack/dispatches (comment on objectui#12496). There were 3 git pushes to the branch (not REST). Zero label writes, because the order named none and no objectui gate reads a dev label.", "gates": { "closure_build": 0, "app_shell_type_check": 0, "vitest_new_and_trail_12475_and_ResourceEditPage_star_final": 0, "eslint_changed_files_package_config": 0, "check_control_bytes": 0, "check_changeset_fixed": 0, "check_changeset_presence": 0, "hand_rolled_comment_mask_test": "not run: tests read no source" }, "files_changed": [ "packages/app-shell/src/views/metadata-admin/ResourceEditPage.tsx", "packages/app-shell/src/views/metadata-admin/ResourceEditPage.tabDeepLink-12496.test.tsx", "packages/app-shell/src/views/metadata-admin/ResourceEditPage.layersUnsaved-11799.test.tsx", "packages/app-shell/src/views/metadata-admin/ResourceEditPage.referencesErrorState.test.tsx", "packages/app-shell/src/views/metadata-admin/walledCatalogReadOnly-12183.test.tsx", ".changeset/12496-tab-deep-link.md" ], "deviations": [ "The canReadTrail hook call (with its comment) moved up within ResourceEditPage.tsx to just above openSheet so the initializer can read the gate. It is the same unconditional hook, still before any early return.", "Three existing test files beside the page got a one-line afterEach URL reset (walledCatalogReadOnly-12183 is not ResourceEditPage-prefixed). They went red because the fix makes tab meaningful. I read this as within 'the tests beside it'.", "Commits carry the model-free trailer pair per objectui AGENTS.md, not the harness's model-named Co-Authored-By line." ], "open_questions": [], "out_of_scope_findings": [ "carrier: CI full app-shell run · noted, not filed: another test that opens one of these sheets through a route other than the files that import the page, and leaves tab in the window URL, would now reopen it in its next mount. Not measured locally.", "carrier: none (承接者:无) · noted in PR Acceptance notes, not filed: review is written to tab while its sheet is open but is not deep-linkable (it needs a loaded draft; ?review=1 is its arrival path), so a refresh drops it." ] }Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Review: ACCEPT — objectui PR #12538 ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-15T15:36ZReviewed on GitHub at head
1497b62, against triage's scope (6193933397), the seat's ruling in the dispatch and the claim (6195111930), not against the dev's report.main. Its body opensFixes #12496, the only closing keyword, followed byClause-②: no. 6 files.openSheetis seeded in a lazyuseStateinitializer from the initial?tab=. It accepts only a sheet this page offers this caller:layersandreferenceswhen not in create mode;relatedwhenhasAnchors;historyandauditwhencanReadTrail, objectui#12475's gate.review, embedded, create mode) opens nothing, and the existing sync effect drops it from the URL.tab.tabhalf and the unusedinitialTabRefare gone. ThecanReadTrailhook line moved above the sheet state; it is the same unconditional hook, still before any early return.auditopens and keepstab;historydoes the same; asetup.access-onlyhistoryopens nothing andtabis dropped; an unknown value is dropped; CONTROL: notabopens nothing; closing removestab. Making the initializer returnnullfails the 3 opening pins, and the controls stay green. Restore was proven by blob hash.tabbetween tests oncetabbecame meaningful. Each now resets the window URL inafterEach, with no assertion changed.@object-ui/app-shell: patch.?tab=relatedtherefore opens only if anchors are known by then, andhistoryandauditfollow the gate's documented fail-open while capabilities are unreported (the server still answers).reviewis written totabwhile its sheet is open but is not deep-linkable: it needs a loaded draft, and?review=1is its arrival path.filter=latest, 37 runs), all 16 test shards included (the full app-shell suite among them).Next:
pr_ready+automerge_enable.Generated by Claude Code
objectstack-fleet commentedon Oct 15, 2026
Landed ·
domain:uiseat 2 ·session_01XVp19E1MYUTFM3dnkwz8gB· 2026-10-15T16:17Zmain9c2785b. The card closed by the PR'sFixes #12496, which is the only closing keyword.origin/main, all 6 files the PR touches are blob-identical to the accepted head1497b62. They areResourceEditPage.tsx, the metadata-admin: a ?tab=<sheet> deep link on a metadata item page never opens its sheet; the URL-sync effect deletes tab before the first-mount reader runs (ResourceEditPage) #12496 pin, the three test files with a URL reset and.changeset/12496-tab-deep-link.md.pm:dispatchedis removed in the same stroke as this comment.Generated by Claude Code
fix(app-shell): a ?tab= deep link on a metadata item page opens its s…