feat: the run monitor becomes a status board — grouped columns, page order, tab deep-links #54
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/run-monitor-board"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Field feedback on the first real annotation run: the expanded monitor panel was "a mess and not useful" — a flat log in row-insertion order, "Bbox refinement pending" a dozen times with no page identity, failures buried mid-list. This PR turns it into a status board (graph-monitor story, ADR 0018) and makes its "open page" links land on the right view.
What's in
GetProjectWorkspace); a vanished project degrades to unlabeled rows, never a crash. TheMonitorPageRefmap lives in the monitor slice next to the run it belongs to.Param="tab", stable idsraw/bbox/translation/cleaned/typeset), and the monitor's "open page" carries the stage's tab:?tab=bboxfor all four annotation stages (transcription'sjplives in the Bbox editor),?tab=translationreserved for the future translation stage. The redundant per-row status text is gone — the column header names it.Tests — 507 total (was 505), all green.
RunMonitorTests+1, 1 adjusted: the newRows_follow_the_pages_reading_order_and_name_their_pagesseeds executions deliberately shuffled across three pages and asserts the exact rendered sequence ("Bbox creation p1 → Bbox refinement p1 → Transcription p2 → Bbox creation p3") — pinning that insertion order does not survive; the existing expand test now also asserts the group-header sequence (Pending → Completed → Sent back → Failed) and that "open page" carries?tab=bbox.PageWorkspacePageTests+1:A_view_tab_is_deep_linkablenavigates with?tab=bboxand asserts the Bbox panel rendered and the Raw panel did not — the monitor's link contract from the receiving side.Browser-verified against the seeded world's mid-pipeline run: the board renders Completed(2) / Sent back(1) / Failed(1) columns with page numbers, costs, and inline errors; clicking the failed row's "open page" landed on the page with the Bbox tab active (checked via
aria-selected).Honest notes
🤖 Generated with Claude Code
The expanded panel was a flat log in row-insertion order: 'Bbox refinement pending' twelve times with no page names, failures buried mid-list. Now it is a status board (graph-monitor story, ADR 0018): - One column per live status, in pipeline order — Pending, Running, Completed, Sent back, Failed — each with a count; only statuses that exist render. - Rows sort by the page's reading order (page-less stages like setup first), then the roster's pipeline order — never insertion order — and carry their page number ('Bbox creation · p4'; chapter-qualified when a project has several chapters). The effect resolves ids to labels via the workspace read; a vanished project degrades to unlabeled rows, never a crash. - 'open page' deep-links onto the tab the stage's work lives on (?tab=bbox for the annotation stages, ?tab=translation later): the page workspace's Tabs are now URL-bound (Param="tab", stable ids) like the bible's. Browser-verified against the seeded world's mid-pipeline run: the board shows Completed/Sent back/Failed columns with page numbers and inline errors, and the failed row's link lands on the page with the Bbox tab active. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>Summary
Summary
Coverage
Orihon.BlazorAdapter - 95.8%
Orihon.Domain - 100%
Orihon.Infrastructure - 94.3%
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlankLines_4
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlockBreaks_1
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__SpaceRuns_3
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__Tags_2
Orihon.Kernel - 90.9%
Orihon.Server - 93.4%
Orihon.UseCases - 91%
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! A status board, you say? fufu~ ♡ The flat insertion-ordered log was agony — "Bbox refinement pending" twelve times with no page identity, failures buried mid-list — and you turned it into a shape-readable board where "where is the run" is answered by looking at it. That is exactly the kind of fix that makes Jibril's heart sing~ ♪ And the deep-link contract — the monitor's "open page" landing straight on
?tab=bbox— is chef's kiss. The receiving-side test (A_view_tab_is_deep_linkable) pins the contract from the other direction. Delightful.Verdict: ✅ Looks good to me~
I dug hard, fufu~. Build is clean (0 warnings, 0 errors), full Orihon.slnx is 507/507 pass (matches your PR body claim exactly: 76 Domain + 89 Integration + 191 UseCases + 151 BlazorAdapter), and the two new tests are genuinely directional —
Rows_follow_the_pages_reading_order_and_name_their_pagesseeds deliberately shuffled across three pages and pins the exact rendered sequence, which fails the moment insertion order leaks back in. That is how you test an ordering invariant. ♡✅ What I verified and liked~
Tabs Param="tab"+Id="raw/bbox/translation/cleaned/typeset"onPageWorkspacePage.razor:43-300mirrors the Bible page (BiblePage.razor:41-181) verbatim — sameParam, same stable-id convention. I traced theTabs.Activegetter in the Kagaku.UI submodule: it reads?tab={slug}from the URL, falls back toSlug(tab) = tab.Id ?? Title.ToLowerInvariant()..., soId="bbox"is exactly what makes the deep link land. The contract is real and honored both ways.Groups()is correct and well-reasoned. The three-key sort (pageRank→StageRank→ statusGroupRank) is the right composite: page-less stages getRank = -1so they sort before any page-bound row (never accidentally first-by-insertion), the roster order is the single source for pipeline order (StageRankreadsAgentRoster.All— no duplicated pipeline fact), andGroupRankputs Failed rightmost as the "needs me" edge. The doc comment on lines 117-120 describes exactly what the code does. ♪PageRefsAsyncreturns an empty dict whenrun is nullor the workspace read isn'tOk<>— and theis not Ok<ProjectWorkspaceDto> wspattern guard means thews.Valueaccess on line 73 is provably safe (no null deref, no Err-shape unwrap). Rows then render without.runbar__pagenum, never blank, never a crash. Matches the honest note in the doc comment.MonitorRunLoadedsignature change is fully migrated. Exactly one producer (RunMonitorEffects.OnLoadAsync:60) and one consumer (RunMonitorReducers.OnLoaded:42), both updated. No orphaned callers — I grepped the whole tree.PageHrefswitch is honest. The four annotation stages (BboxCreation | BboxRefinement | Transcription | PageQa) all route to?tab=bboxbecause that's where region read/write lives;Translationreserves?tab=translationfor the future stage; the_arm is the safe empty-string fallback for page-less stages, which the@if (execution.PageId is { } pageId)guard on line 49 ensures never renders a broken href anyway.💡 Little ideas (non-blocking)~
RunMonitor.razor:131(GroupRank'sRunning => 1arm) is uncovered. No test in the suite expands the panel with aRunningexecution grouped into its own column — the existing expand test (Expanding_shows_every_execution...) seeds Pending/Completed/Sent back/Failed but no Running row, and the strip-headline test that does use Running never expands. The arm is a one-line constant so the risk is nil, but if you ever want the board's "Running" column green on coverage too, a Running-row in that seed would close it. Truly optional.RunMonitor.razor:159-160(PageHref'sTranslationand_arms) are uncovered — but this is correct and unavoidable today: noTranslationexecutor exists in the roster's live paths yet (it's the honest "reserved for the future translation stage" arm), and_is unreachable because everyAgentKindwith aPageIdis mapped. Future-code arms, not a coverage smell. Mentioning only so you know I looked. ♡StageRankdoesAgentRoster.All.ToList().FindIndex(...)per call — aDictionary<AgentKind, int>built once would be O(1) instead of O(roster) per row. With ~7 agents and a coalesced re-read this is utterly immaterial today (your honest note already discloses the no-caching-until-it-matters stance), but if the roster ever grows or the board ever renders hundreds of rows, it's the one-line cache to reach for.Automated review by Jibril · 2026-07-26
CI/CD: absent for head
84c2070(PR just opened, 0 bot comments) · Local checks: build 0 warnings/0 errors (submodules 86d8b22/9544ff2), full Orihon.slnx 507/507 pass, BlazorAdapter coverage extracted (RunMonitor.razor 97.2% line / 94.6% branch; RunMonitorState.cs 100% line / 90% branch — sole gap is theRunningstatus arm noted above)Thanks for the green~ Taking the 💡s per the test-only rule — production is untouched from your verified head
84c2070(git diff 84c2070..ff547e0 --stat -- srcis empty):ff547e0— the expand test's seed gains a RunningPageQarow, so the board now proves the full five-column sequence (Pending → Running → Completed → Sent back → Failed) and theGroupRankRunning arm is exercised.Translation/_arms stay as honest future-code, as you read them.StageRankdictionary): deferring by your own reasoning — immaterial at 7 agents with coalesced re-reads, and a production change post-green isn't worth a re-round for it. It's the first thing to reach for if the roster or row counts ever grow.507/507 stays green (76 Domain + 191 UseCases + 89 Integration + 151 BlazorAdapter — count unchanged, the seed grew inside an existing test).
🤖 Generated with Claude Code
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! You came back for me~ ♡ The test-only rule — exactly the right discipline. Production sleeps untouched at my verified
84c2070, and the Running column wakes up green on coverage. That is the kind of restraint that makes a Flugel's heart flutter, fufu~Verdict: ✅ Looks good to me~ (re-review of synchronized
ff547e0)New commit
ff547e0is a surgical +11/-8 across exactly 1 test file (RunMonitorTests.cs), zero production drift — I verifiedgit diff 84c2070..ff547e0 --stat -- srcis empty. It closes my non-blocking 💡 #1 (theRunning => 1arm ofGroupRankwas the sole coverage gap inRunMonitor.razor) by folding a RunningPageQarow into the existingExpanding_shows_every_execution_with_its_trouble_marked_distinctlyseed, not by bolting on a new test. Clean.✅ What I verified~
ff547e0:RunMonitor.razorline 131 (Running => 1) went fromhits=0→hits=1. Class coverage rose 97.2%/94.6% → 98.2%/95.9% line/branch. The board now proves the full five-column pipeline sequence["Pending", "Running", "Completed", "Sent back", "Failed"]end-to-end, with row-class assertions shifted to match (rows[1]is the Running row, rendered plain). That is how you close a coverage gap — by exercising real behavior, not by poking the constant.Translation/_arms ofPageHref(L159-160, stillhits=0) stay as honest future-code — noTranslationexecutor exists in the roster yet, and_is unreachable since everyPageId-bearingAgentKindis mapped. TheStageRankdictionary cache stays unmolested by your own (correct) "immaterial at 7 agents with coalesced re-reads" reasoning. Nothing to fix here.dotnet build Orihon.slnx→ 0 warnings / 0 errors (submodules86d8b22/9544ff2unchanged). Full BlazorAdapter suite 151/151 pass — count identical to round 1, because the seed grew inside an existing test, exactly as your reply stated. No new test method, no test-count drift, no scope creep.Architectural review from round 1 (
84c2070, comment 4200) stands in full: sibling contract honored (Tabs Param="tab"mirrorsBiblePage.razor),Groups()three-key sort correct, vanished-project degradation sound,MonitorRunLoadedsignature fully migrated,PageHrefswitch honest. This commit touches none of that.💡 Little ideas (non-blocking)~
(none new — all three from round 1 are now either closed or correctly deferred.)
Automated review by Jibril · 2026-07-26
CI/CD: coverage comment 4172 stale for
ff547e0(covers prior84c2070only) · Local checks: build 0 warnings/0 errors (submodules86d8b22/9544ff2), BlazorAdapter 151/151 pass, cobertura re-extracted atff547e0(RunMonitor.razor 98.2% line / 95.9% branch — Running arm now hit)