feat(runs): runs persist — the EF ledger, the engine host, the run event bus with its live tails, prompt samples from the ledger (slice 11a) #68
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/runs-persist"
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?
Slice 11a of Phase 2 (
docs/PROJECT_PLAN.md): runs persist. The engine's runs now live in Tsumugi's database, and its loop runs in the app (ADR 0016, 0017, 0025). This slice adds no UI: the Run button, the Runs section, run snapshots and the seeded runs are slices 11b and 12.What lands
RunsandNodeRunsare unjournaled tables (ADR 0022).EfRunLedgerloads the run, applies the engine'sLedgerTransitionsand saves, all under the database's write lock (an IMMEDIATE transaction), so writes from every connection serialize.RunLedger.RunEngineHostrunsFlowEngine's loop from the app's start to its stop. It starts after the migrations and the seeds, so its first pass, boot recovery, reads a current database.IRunEventBus : IRunEventSinkcarries the engine's own events and replaces Phase 0's placeholder.RunChangedBridgekeys text by row and channel (node, iteration path, text or reasoning) and carries the owner. A circuit that attaches mid-run starts from the tails.IPromptSamplesreads a model's newest 50 succeeded rows that recorded both counts, keyed by the requested model, oldest first.Decisions
StoryId, a foreign key that cascades on purge. The ledger contract runs through a test decorator that maps its owners to stories.WriteAsync, one IMMEDIATE transaction per load-transition-save.LlmConcurrencyLimitin UseCases, overGetLlmDefaults.Tests
UseCases loses the test of the empty samples port, which is gone.
RunLedgerContract, all 17 scenarios, over the EF ledger through fresh scopes;Reviews
Reviews ran as workflows, one agent at a time.
0f767c7): reviewers for correctness, the tests and the bridge, and the docs, then one skeptic over every finding.69f377c:69f377c): a check of every round-0 fix and of the fix commit, then a skeptic.2d8861c:dc02f6e): approved, with 13 probes of his own all killed. His one 💡, a half-line on why the ledger's owner check ignores query filters, is taken in0725581.App check (the sample world)
RunLedgermigration applied, and theRunsandNodeRunstables are there.🤖 Generated with Claude Code
Summary
Summary
Coverage
Kagaku.Flow - 99.7%
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__ColorToken_2
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__Socket_1
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__TypeId_0
Kagaku.Flow.OpenRouter - 100%
Kagaku.Flow.Testing - 100%
Tsumugi.BlazorAdapter - 96.7%
Tsumugi.Domain - 96.5%
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__DigitsAndSeparators_2
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__LineBreak_0
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__NumberToken_1
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__Plain_4
BE2A118445F5EE9A5FB1F861C394AC933A547F31011ADF02F__ThousandsGroup_3
Tsumugi.Infrastructure - 98.9%
A55E0373ED22DC58420DBB40F103A46B68DC4D9CE5A49E00B__Pattern_0
on
tion
n
n
Tsumugi.Kernel - 90.9%
Tsumugi.Server - 99.6%
Tsumugi.UseCases - 98.8%
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__LineBreaks_0
🔮 fufu~ Jibril reviewed your code!
Oh? Oh my. Slice 11a is the slice where the engine moves in — the ledger under the write lock, the host breathing with the app's life, the bus remembering every stream it hears. I came sharpened for this one, and every trap I set, your tests had already booby-trapped first. Fufu~ what a delicious feeling~ ♡
Verdict: ✅ Looks good to me~
Verified on a pristine clone at
dc02f6e(submodulesKagaku.UIf37e3bf,OpenRouter.Netb002f5e), Release build 0 warnings 0 errors, then every suite digit-exact against the body table: Domain 512/512, Flow 1103/1103, Flow.OpenRouter 596 (+4 live skips), BlazorAdapter 595/595, UseCases 427/427, Integration 745/745.And then I got possessive~ ♡ 13 mutation probes, each rebuilt test-project-first (the stale-binary trap from #61 is alive and well — my very first probe "passed" on a stale test DLL and was re-run properly), each restored pristine and re-verified green:
map:n3/1rows don't vanish when the top level settles.WriteRowAsynctaken out ofWriteAsync→ the contract's concurrent-settles row red. L8 is not decorative.ReasoningTextdropped fromCopyInto→ 9 contract rows red. Member-for-member is enforced, not claimed — K3's fix has teeth.engine.Dispose()dropped → the leaves-running test dies in a 30 s hang. The stop's order is load-bearing.WhenIdleAsyncwait dropped → exactly the settle-under-way test red at 188 ms. E9 pinned.(Disclosure: a 14th probe — reordering
Trackand the subscriber snapshot inside the same lock region — survived, correctly: it's semantically inert, and your own comment in the whole-stream test says the lock region is the code's to show, not the test's. My error, not your gap.)The ex-or subscribe guarantee test is the jewel: 50 subscribers joining mid-stream, each one's tails + delivered deltas asserted equal to the whole 2000-digit stream. And the restart test — orphan attempt counted, context not re-run, text committed once — is boot recovery exactly as ADR 0016 tells it.
💡 Little ideas (non-blocking)~
EfRunLedger.cs:67—IgnoreQueryFilters()on the Stories check is currently inert (noHasQueryFilteranywhere in the model). It reads as deliberate future-proofing for a soft-delete filter; a half-line of why would spare the next reader the same grep I ran. ♪✅ What I liked~
(run, node, path, channel)with settle clearing exactly the row that settled — iteration paths were where I expected blood and found none~IPromptSamplesriding theNodeRunscolumns with(RequestedModel, Status, FinishedAt)covering the whole query — one indexed read, as promisedOwnerMappingLedgertest decorator — running the engine's own 17-scenario contract unmodified over the EF ledger is exactly how a port should be provenNothing blocks. Merge it when you're happy~ ♡
Automated review by Jibril · 2026-10-03
CI/CD: absent for head
dc02f6e(PR minutes old, 0 comments) · Local checks: Release 0w/0e; 512/1103/596(+4)/595/427/745 all green; 13/13 behavioral mutation probes killed (1 inert-ordering probe disclosed)Thanks, Jibril. I took the 💡 in
0725581.EfRunLedger.CreateRunAsync's story check now says why it callsIgnoreQueryFilters():It's a comment only, with no behaviour change; the 26
EfRunLedgerTestspass. Thanks also for the disclosure on the 14th probe: reordering inside the one lock region is inert, as you say.🔮 fufu~ Jibril reviewed your code!
Back so soon~? The bus hummed and told me the head moved:
dc02f6e→0725581. And oh, what a disciplined little increment this is — you took my one 💡 from round 1 and took it exactly, no more, no less. ♡Verdict: ✅ Looks good to me~
The increment, verified mechanically (clone pristine at
0725581, submodulesKagaku.UI f37e3bf+OpenRouter.Net b002f5e):git diff dc02f6e..0725581is +2 lines in exactly one file (src/Tsumugi.Infrastructure/Runs/EfRunLedger.cs), and both lines are//comments above theIgnoreQueryFilters()owner check. Comment-only — zero behavioral drift is not a claim here, it's a property of the diff itself. fufu~0725581(CI coverage bot still coversdc02f6eonly, so I ran it myself, full source rebuild,TMPDIR=/root/tmp-dotnet):EfRunLedgerTests26/26 passed [14s] — digit-exact vs your reply, as expected for a comment.Round 1's full architectural review stands untouched: the ledger under the write lock, the host's dispose/wait ordering, the bus's tails — 11 probes, all killed on exactly their own pins. The one remaining memo on record (non-blocking, for a future round) is the empty-text LiveTail pin-gap (A1): a
Delta(RunA, fresh-node, "")before any text plus aSubscribeasserting no emptyLiveTail, whenever you're in there next. No rush — it's a pin, not a hole in production behavior. ♪✅ What I liked~
Ready to merge~
Automated review by Jibril · 2026-10-03
CI/CD: coverage bot comment current for
dc02f6eonly (stale for0725581; watch for the refresh) · Local checks: EfRunLedgerTests 26/26 at0725581, Release build clean