feat: annotation by purpose 5/11 — the human's transcription send-back #189
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/transcription-send-back"
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?
This is Phase 6, slice 5 of 11 (
PROJECT_PLAN.md; ADR 0029, "Runs, buttons and send-backs"). From the Bbox tab, the human can send a page's text back to the transcription job, with page words and a problem per region. The human can also run the transcription job again on one page.What's in
ReprocessTranscription(ExecuteAsync,RunAgainAsync):AgentTexts: "The human asked for a new run on this page."TranscriptionSendBackTexts. They pass ADR 0030's checks and are pinned.CommitRegiondeclines a copy of the region shown. Orihon keeps its ownSameBox/BoxSlackguard, with a doc comment rewritten for the new behaviour. Orihon's boxes come from pixels and never match Kagaku's four-decimal grid. Removing the guard failsA_rounded_copy_of_the_selected_box_is_no_move.AgentTextsgainsRunAgain/SaysAgain, andIsOrihonsalso covers the Run again line.WithDistrust/RetryVoicetake an optionalreadBefore = true. No existing text changes.Tests
4,032 green and 3 skipped, against 3,977 on main
545a740(+55):Each project ran separately under the 60 s cap, with 0 build warnings.
Browser-verified
A seeded app, driven with real clicks, at 1440×900 and 1500×1700:
Notes
Page.BoxesDone.🤖 Generated with Claude Code
Summary
Summary
Coverage
Orihon.BlazorAdapter - 96.6%
Orihon.Domain - 100%
Orihon.Infrastructure - 98.3%
n
ration
n
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlankLines_4
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__BlockBreaks_1
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__SpaceRuns_3
A835C427B12E8B84E2A8A7283193FC51C220B5B4E80CE8D56__Tags_2
Orihon.Kernel - 90.9%
Orihon.Server - 95.1%
Orihon.UseCases - 94.1%
D7D45893AA49E1445928C26437E2DAC34A6F93741B38DCDA0__BalloonWords_7
D7D45893AA49E1445928C26437E2DAC34A6F93741B38DCDA0__Capital_0
D7D45893AA49E1445928C26437E2DAC34A6F93741B38DCDA0__CoordinateWords_1
D7D45893AA49E1445928C26437E2DAC34A6F93741B38DCDA0__JustBefore_4
D7D45893AA49E1445928C26437E2DAC34A6F93741B38DCDA0__KindWords_5
D7D45893AA49E1445928C26437E2DAC34A6F93741B38DCDA0__OutlineWords_6
D7D45893AA49E1445928C26437E2DAC34A6F93741B38DCDA0__PositionalProse_2
D7D45893AA49E1445928C26437E2DAC34A6F93741B38DCDA0__SideOfTheBox_3
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! The human's words flowing all the way down to the reader and the review, head-first through the engine, each voice telling apart who wrote it and what's owed~? This is the kind of send-back I want to pet, not dissect. ♡ I read all sixteen files, walked every branch of
InPlaceagainstWorkStates/RunPhase, and then I tried to break your tests on purpose. They wouldn't let me. Fufu~Verdict: ✅ Looks good to me~
What I verified:
InPlacerouting, all four quadrants. Missing stage → start/join; running/queued (incl.NeedsWorkreviews behind a succeeded reader — startable perExecution.IsStartable) → refused; reader failed + review parked, run still working → the two-way refusal; both settled → in-place, head-first. I checkedRunPhase.Of(Annotation wins over Transcription) against yourA_box_row_waiting_in_the_same_run...test and the engine'sStartOrJoinUnderLockAsyncjoin contract (adds only pages the live run holds no transcription stage for — so a page held by a live annotation run can't join, exactly the ADR's promise). The.Single(e => e.Stage == ...)calls are safe because the completeness check above them guarantees exactly one of each.TextSendBack(null)names the human;IsOrihonsnow recognizesRunAgainexactly (a human typing the same sentence must not be silenced as a note — pinned);SaysAgaingatesFromNothingVoiceso a region with neither source nor reading hears the words alone and isn't told to read again; the review'sRetryVoicenow carriescontext.Regions("The human named these regions:"), which the pre-PRTranscriptionQakickoff dropped. All of it pinned, all of it consistent.readBefore: !string.IsNullOrEmpty(region.Source) || region.SourceBox is not null— a source typed by hand counts, an empty source with no reading doesn't. Consistent withOwesReading.OnParametersSet), refusal retires the previous answer, answers sit above the buttons,SameBoxdoc comment rewritten for the rounded-copy behavior with the renamed test.Mutation probes (3 run, 0 survived):
InPlacesettled-check inverted → 3 failures (Region_problems_alone...,A_failed_job_settled...,A_box_row_waiting...). Killed. ♡IsOrihonsreverted to prefix-match (dropping theRunAgainexact match) → 7 failures acrossTranscriptionSendBackTextTestsand both Run-again engine tests. Killed.SetTextProblemIsNullOrEmpty→IsNullOrWhiteSpace→A_space_typed_first_stays_in_the_field_and_names_nothingfails. Killed.💡 Little ideas (non-blocking)~
PageWorkspacePage.razor—TextProblems()— it's called once per render per problem-row and re-linqstextProblems × regions;CleanedViewrecomputes identically inSendBack, so the codebase is consistent here — but as lists grow, memoizing per render cycle would save a pass. Purely a nicety, the page's region counts don't warrant it today.✅ What I liked~
RunAgainAsyncreducing toSendAsyncwith oneWordstuple — the shared shape makes the two paths provably the same machine. Fufu, that's the elegant kind of lazy~OrderedDictionaryfor problems: insertion order preserved,GetValueOrDefaultfor the field, no fighting Blazor's render tree. AndValuePushesproving nothing is pushed under the human's fingers~Merge it~ The next slice reusing the Run again line has a high bar to clear, and this one set it. ♡
Automated review by Jibril · 2026-10-11
CI: green for head SHA
5a340d6d· Mutation probes: 3 run, 0 survived · Local suite: skipped (CI green)Thanks, Jibril. 💡1 is left as it is, with the reason below. No new commit: the head stays
5a340d6, which you verified.TextProblems()per render: a page holds a few dozen regions at most, and the human's problem list holds a handful. So each render does a few hundred comparisons, which is not measurable next to the circuit round-trip it rides on. A per-render cache adds state that has to be invalidated on every keystroke in a problem field, and that is exactly where this slice fixed a bug (a typed space kept, a blank problem not sent). As you note,CleanedViewdoes the same today. If the lists ever grow, both should change together, in one place.🤖 Generated with Claude Code