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.
Studio 左栏导航在 AI 副驾 apply 之后不刷新:新对象已 active 且已入 app.navigation,整页刷新才出现 #7255
Claim: PM loop round 3 (epic objectstack-ai/cloud#1841)
Session: session_c5c0ce54-bb9c-478c-9e5b-cf44b80d4569
Branch: claude/issue-7255-studio-nav-refresh-after-apply
Worktree: objectui-issue-7255
Domain: domain:ui
File surface: packages/app-shell/src/views/studio-design/** (nav rail / metadata tree refresh after an AI apply), the AI copilot → workbench invalidation seam, tests (stop on breach; explain in the report)
Container & model: M, mode:subagent, model: opus (PM judgement)
Clause-②: no
Serial constraints cleared: objectui#7366 (#7254, studio-design + i18n + tool cards) MERGED — base on current main; #7256 (PR #7372, home/logo, enqueued) and #7371 (usage indicator, in flight) own disjoint files; #7257 (merged) retired the dev metadata-events poll — a production-safe refresh channel is part of this card
Claim: dev
Session: session_c5c0ce54-bb9c-478c-9e5b-cf44b80d4569
Branch: claude/issue-7255-studio-nav-refresh-after-apply (pushed, empty)
Worktree: objectui-issue-7255
Base: 20c04b232f64435e999f2205114b9a0d8966ad6a (origin/main)
File surface (planned): packages/app-shell/src/views/studio-design/**, the AI copilot to workbench invalidation seam, tests
Mode: mode:subagent, model opus
{
"issue": 7255,
"status": "done",
"branch": "claude/issue-7255-studio-nav-refresh-after-apply",
"pr": "https://github.com/objectstack-ai/objectui/pull/7376",
"premise_still_valid": true,
"summary": "PM's mechanism guess confirmed on current main, with one correction: the apply signal is NOT read off the copilot's tool-card state. ChatPane already fires emitMetadataRefresh() on every turn whose tool results carried an authoring envelope (draftReview / replayOutcome) — the confirm-replay path in the card mints replay_* tool-call ids, so the pulse DOES fire in the reported scenario. The missing half was a subscriber: the four Studio pillar rails keyed their loads on publishNonce / draftNonce only, which the workbench's own Publish and draft-save bump and nothing the copilot does. Added useMetadataRefreshNonce(hold) and listed it in the load deps of the Interfaces (nav tree + object picker), Data, Automations and Access rails. Two non-obvious halves: the Interfaces load rehydrates appDraft, which IS the nav edit buffer, so the pulse is HELD while navDirty/navSaving and released — not dropped — once autosave settles; and that effect no longer flaps appStatus back through 'loading' on a re-read of the same package, which would have blinked the nav toolbar once per copilot turn (AGENTS.md #8). No new channel, no poll, no reload: the refresh channel is the existing assistant-bus invalidation that usePendingDrafts and MetadataProvider already converge on — production-safe by construction, nothing near the dev-only metadata-events SSE that objectui#7257 taught to stop retrying. A packageId payload on the pulse was considered and deliberately NOT added; the PR body carries the four-axis reasoning.",
"tests": "All at c8534ddce (final commit). TARGETED: `pnpm exec vitest run packages/app-shell/src/views/studio-design/ packages/app-shell/src/assistant/` -> `Test Files 48 passed (48) / Tests 257 passed (257)`; the wider first pass adding `packages/app-shell/src/preview/` was `Test Files 60 passed (60) / Tests 353 passed (353)`. NEW: StudioDesignSurface.aiApplyRefresh.test.tsx (both rails grow the new entry after emitMetadataRefresh() in the SAME mounted tree — pre-existing entries asserted to survive, so a remount 'fix' fails it) and useMetadataRefreshNonce.test.tsx (hold defers + coalesces, never drops). ABLATION: committed first, then stripped metadataRefreshNonce from the two dep arrays under test; mutation confirmed ON DISK before measuring — `metadataRefreshNonce]` occurrence count 5 -> 2 and file hash b2522f25 -> ba30689f, not an editor exit code. Predicted direction RED, observed RED: `Tests 2 failed | 3 passed` (both acceptance tests failed; the three hook unit tests stayed green, the correct split — they measure the adapter, not the wiring). NO rebuild leg is claimed or needed: the test imports ./StudioDesignSurface as a sibling SOURCE module, so the mutated bytes are what ran. Restore under an EXIT/INT/TERM trap with an absolute repo root, proven by STATE not exit code: `git diff HEAD` empty, tree clean, on-disk hash back to b2522f25d375f1b7b3fc08309c3acd133a66e0c2 = the HEAD blob, count back to 5; suites re-run green on the restored tree. TYPE-CHECK: `pnpm --filter @object-ui/app-shell type-check` exit 0 AFTER `pnpm --filter '@object-ui/app-shell^...' build` (exit 0) — without the closure it was 20+ phantom TS2307. Both new test files are genuinely covered, not excluded: `tsc -p tsconfig.test.json --listFiles` names them and the first run caught a real fixture widening error. LINT: full-repo `pnpm lint` (eslint . --no-inline-config), NOT a narrowed run — `Tasks: 47 successful, 47 total` / `Cached: 0 cached, 47 total`, 0 errors (2877 pre-existing no-explicit-any warnings, none in this diff). GATES (exit code captured before any pipe, verdict lines quoted in the PR body): check:control-bytes OK (6075 files scanned); check:i18n-keys OK (no new keys); check:i18n-drift `0 en value(s) changed`; check:vi-mock-specifiers OK; check:vi-mock-inherit OK; check:self-import OK; check:phantom-deps OK; check:side-effects-array OK; check:entry-guard OK; check:icon-record-names OK; check-changeset-presence `1 source file(s) of 1 released package(s) changed ... declares 1 changeset(s)`; check-changeset-no-major OK (minor). check:eager-closure is NOT MEASURED locally — it needs apps/console/dist/eager-closure.json and reports itself a broken gauge without it; CI has the artifact. NOTE objectui has no scripts/pm/dispatch-gates.mjs (that script only lives in objectstack and answers about its own tree), so the gate family above was derived by hand from this repo's package.json check:* list against the diff's paths. CI status at report time: in_progress.",
"mcp_calls": "0 — every GitHub read and write went through REST (`gh api`); the repo-scoped probe passed on the first call, so no MCP fallback was needed.",
"open_questions": [],
"out_of_scope_findings": [
"filed as objectstack-ai/cloud#1858 (no assignee): AI-appended nav items carry no `icon` while the same producer's blueprint-first items do (layout_dashboard / building_2). Judged producer-side per this card's ruling — BOTH objectui consumers already have a renderer default (NavigationRenderer.resolveIcon falls back to FileText; the Studio NavTree falls back node.icon -> the object's own metadata icon -> a type-generic glyph), so the defect is 'a generic glyph beside two semantic ones', and choosing a meaningful icon needs to know what the table is FOR — information only the blueprint/apply chain has. Guessing from the label in the renderer would fossilize a second de-facto contract (Commandment #0.1), so nothing was changed here. Searched objectstack-ai/cloud open issues first via one targeted REST search ('nav icon' -> 0, 'blueprint icon' -> 0) with a same-session control word ('navigation' -> 3 hits) proving the channel answers."
]
}
Ruling check: no new channel, no poll, no reload — the existing assistant-bus emitMetadataRefresh() pulse (already fired by ChatPane on authoring envelopes, incl. the confirm-replay path) gains its missing subscriber: useMetadataRefreshNonce(hold) in the load deps of the Interfaces (nav tree + object picker), Data, Automations and Access rails; the pulse is HELD while the nav edit buffer is dirty/saving and released, not dropped; no appStatus flap on re-read. Production-safe by construction (nothing near the dev-only SSE 生产姿态下 console 持续轮询 GET /api/v1/dev/metadata-events → 404,浏览器控制台被刷红 #7257 retired). PM's "read it off the tool-card state" guess corrected — accepted.
Icon half judged producer-side per the ruling and filed as objectstack-ai/cloud#1858 (no consumer-side label guessing) — agreed; renderer defaults already exist.
Evidence: 48 files / 257 tests on studio-design + assistant (60/353 with preview); new acceptance test asserts both rails grow the entry in the SAME mounted tree; ablation (drop the nonce from the two dep arrays) proven on disk, predicted red observed red (2 failed / 3 hook unit tests green), restore proven by state; type-check after the dependency closure exit 0 with --listFiles covering the new tests; FULL-repo pnpm lint 47/47 uncached, 0 errors; 12 gate verdict lines quoted; eager-closure declared NOT MEASURED (needs CI artifact).
CI in progress at review time. Flipping ready; enqueuing when every check is green.
Activity
hotlong commentedon Sep 2, 2026
Claim: PM loop round 3 (epic objectstack-ai/cloud#1841)
Session:
session_c5c0ce54-bb9c-478c-9e5b-cf44b80d4569Branch:
claude/issue-7255-studio-nav-refresh-after-applyWorktree:
objectui-issue-7255Domain: domain:ui
File surface:
packages/app-shell/src/views/studio-design/**(nav rail / metadata tree refresh after an AI apply), the AI copilot → workbench invalidation seam, tests (stop on breach; explain in the report)Container & model: M, mode:subagent, model: opus (PM judgement)
Clause-②: no
Serial constraints cleared: objectui#7366 (#7254, studio-design + i18n + tool cards) MERGED — base on current main; #7256 (PR #7372, home/logo, enqueued) and #7371 (usage indicator, in flight) own disjoint files; #7257 (merged) retired the dev metadata-events poll — a production-safe refresh channel is part of this card
hotlong commentedon Sep 2, 2026
Claim: dev
Session:
session_c5c0ce54-bb9c-478c-9e5b-cf44b80d4569Branch:
claude/issue-7255-studio-nav-refresh-after-apply(pushed, empty)Worktree:
objectui-issue-7255Base:
20c04b232f64435e999f2205114b9a0d8966ad6a(origin/main)File surface (planned):
packages/app-shell/src/views/studio-design/**, the AI copilot to workbench invalidation seam, testsMode:
mode:subagent, model opushotlong commentedon Sep 2, 2026
os-dev-report
{ "issue": 7255, "status": "done", "branch": "claude/issue-7255-studio-nav-refresh-after-apply", "pr": "https://github.com/objectstack-ai/objectui/pull/7376", "premise_still_valid": true, "summary": "PM's mechanism guess confirmed on current main, with one correction: the apply signal is NOT read off the copilot's tool-card state. ChatPane already fires emitMetadataRefresh() on every turn whose tool results carried an authoring envelope (draftReview / replayOutcome) — the confirm-replay path in the card mints replay_* tool-call ids, so the pulse DOES fire in the reported scenario. The missing half was a subscriber: the four Studio pillar rails keyed their loads on publishNonce / draftNonce only, which the workbench's own Publish and draft-save bump and nothing the copilot does. Added useMetadataRefreshNonce(hold) and listed it in the load deps of the Interfaces (nav tree + object picker), Data, Automations and Access rails. Two non-obvious halves: the Interfaces load rehydrates appDraft, which IS the nav edit buffer, so the pulse is HELD while navDirty/navSaving and released — not dropped — once autosave settles; and that effect no longer flaps appStatus back through 'loading' on a re-read of the same package, which would have blinked the nav toolbar once per copilot turn (AGENTS.md #8). No new channel, no poll, no reload: the refresh channel is the existing assistant-bus invalidation that usePendingDrafts and MetadataProvider already converge on — production-safe by construction, nothing near the dev-only metadata-events SSE that objectui#7257 taught to stop retrying. A packageId payload on the pulse was considered and deliberately NOT added; the PR body carries the four-axis reasoning.", "tests": "All at c8534ddce (final commit). TARGETED: `pnpm exec vitest run packages/app-shell/src/views/studio-design/ packages/app-shell/src/assistant/` -> `Test Files 48 passed (48) / Tests 257 passed (257)`; the wider first pass adding `packages/app-shell/src/preview/` was `Test Files 60 passed (60) / Tests 353 passed (353)`. NEW: StudioDesignSurface.aiApplyRefresh.test.tsx (both rails grow the new entry after emitMetadataRefresh() in the SAME mounted tree — pre-existing entries asserted to survive, so a remount 'fix' fails it) and useMetadataRefreshNonce.test.tsx (hold defers + coalesces, never drops). ABLATION: committed first, then stripped metadataRefreshNonce from the two dep arrays under test; mutation confirmed ON DISK before measuring — `metadataRefreshNonce]` occurrence count 5 -> 2 and file hash b2522f25 -> ba30689f, not an editor exit code. Predicted direction RED, observed RED: `Tests 2 failed | 3 passed` (both acceptance tests failed; the three hook unit tests stayed green, the correct split — they measure the adapter, not the wiring). NO rebuild leg is claimed or needed: the test imports ./StudioDesignSurface as a sibling SOURCE module, so the mutated bytes are what ran. Restore under an EXIT/INT/TERM trap with an absolute repo root, proven by STATE not exit code: `git diff HEAD` empty, tree clean, on-disk hash back to b2522f25d375f1b7b3fc08309c3acd133a66e0c2 = the HEAD blob, count back to 5; suites re-run green on the restored tree. TYPE-CHECK: `pnpm --filter @object-ui/app-shell type-check` exit 0 AFTER `pnpm --filter '@object-ui/app-shell^...' build` (exit 0) — without the closure it was 20+ phantom TS2307. Both new test files are genuinely covered, not excluded: `tsc -p tsconfig.test.json --listFiles` names them and the first run caught a real fixture widening error. LINT: full-repo `pnpm lint` (eslint . --no-inline-config), NOT a narrowed run — `Tasks: 47 successful, 47 total` / `Cached: 0 cached, 47 total`, 0 errors (2877 pre-existing no-explicit-any warnings, none in this diff). GATES (exit code captured before any pipe, verdict lines quoted in the PR body): check:control-bytes OK (6075 files scanned); check:i18n-keys OK (no new keys); check:i18n-drift `0 en value(s) changed`; check:vi-mock-specifiers OK; check:vi-mock-inherit OK; check:self-import OK; check:phantom-deps OK; check:side-effects-array OK; check:entry-guard OK; check:icon-record-names OK; check-changeset-presence `1 source file(s) of 1 released package(s) changed ... declares 1 changeset(s)`; check-changeset-no-major OK (minor). check:eager-closure is NOT MEASURED locally — it needs apps/console/dist/eager-closure.json and reports itself a broken gauge without it; CI has the artifact. NOTE objectui has no scripts/pm/dispatch-gates.mjs (that script only lives in objectstack and answers about its own tree), so the gate family above was derived by hand from this repo's package.json check:* list against the diff's paths. CI status at report time: in_progress.", "mcp_calls": "0 — every GitHub read and write went through REST (`gh api`); the repo-scoped probe passed on the first call, so no MCP fallback was needed.", "open_questions": [], "out_of_scope_findings": [ "filed as objectstack-ai/cloud#1858 (no assignee): AI-appended nav items carry no `icon` while the same producer's blueprint-first items do (layout_dashboard / building_2). Judged producer-side per this card's ruling — BOTH objectui consumers already have a renderer default (NavigationRenderer.resolveIcon falls back to FileText; the Studio NavTree falls back node.icon -> the object's own metadata icon -> a type-generic glyph), so the defect is 'a generic glyph beside two semantic ones', and choosing a meaningful icon needs to know what the table is FOR — information only the blueprint/apply chain has. Guessing from the label in the renderer would fossilize a second de-facto contract (Commandment #0.1), so nothing was changed here. Searched objectstack-ai/cloud open issues first via one targeted REST search ('nav icon' -> 0, 'blueprint icon' -> 0) with a same-session control word ('navigation' -> 3 hits) proving the channel answers." ] }hotlong commentedon Sep 2, 2026
ACCEPT — reviewer of record: PM (epic objectstack-ai/cloud#1841), verified against GitHub.
Fixes #7255; files inviews/studio-design/**+ the assistant-bus hook + tests + changeset — inside the surface.emitMetadataRefresh()pulse (already fired by ChatPane on authoring envelopes, incl. the confirm-replay path) gains its missing subscriber:useMetadataRefreshNonce(hold)in the load deps of the Interfaces (nav tree + object picker), Data, Automations and Access rails; the pulse is HELD while the nav edit buffer is dirty/saving and released, not dropped; no appStatus flap on re-read. Production-safe by construction (nothing near the dev-only SSE 生产姿态下 console 持续轮询 GET /api/v1/dev/metadata-events → 404,浏览器控制台被刷红 #7257 retired). PM's "read it off the tool-card state" guess corrected — accepted.type-checkafter the dependency closure exit 0 with--listFilescovering the new tests; FULL-repopnpm lint47/47 uncached, 0 errors; 12 gate verdict lines quoted; eager-closure declared NOT MEASURED (needs CI artifact).Generated by Claude Code