feat(graphs): every library action announced as EntityKinds.Graph, every open view following it (Phase 3 slice 3) #101
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/graph-announcements"
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?
Phase 3's slice 3. Every graph library action is now announced as
EntityKinds.Graph, so each open tab follows it (ADR 0022). Until now a graph changed in one tab showed in another only when that tab next loaded its page. The library's actions stay unjournaled, keeping their own Undo and Restore, and are announced the way a run and a snapshot are.What changes
Announced.
Not announced. A refused action, and one that changes nothing: an unchanged rename, a second trash, a restore of a graph not in the trash, a seed with nothing to write. To make that possible, the store's rename and trash writes now say whether they changed the graph, and
Graph.MoveToTrashandRestorereturn it, asRevisedid.Following it:
The plan named the first three. The Run button and the story list show graph data too, so they follow as well.
Registry.
EntityKinds.Graphis the third kind announced but not journaled, after StorySnapshot and Run. The journal's registry test leaves it out as it does them.Docs.
ChangeOperationandIUnjournaledname the announced graph actions.Verification
ClearRunHistorykeeps the same guard.🤖 Generated with Claude Code
Until now a graph changed in one tab showed in another only when that tab next loaded its page. The library's actions stay unjournaled (they keep their own Undo and Restore), but each one is now announced, as a run and a snapshot are (ADR 0022). - EntityKinds.Graph is the third kind announced but not journaled, after StorySnapshot and Run; the journal's registry test leaves it out, as it does them. - Announced: a duplicate and an import as the new graph's creation, a rename or description as its update, a trash and a restore as such, and the templates a start's re-seed writes, as updates in one batch. A refused action, and one that changes nothing (an unchanged rename, a second trash, a restore of a graph not in the trash, a seed with nothing to write), announce nothing: the store's rename and trash writes now say whether they changed the graph. - Following it: - the Graphs page; - the General page's graph switcher; - the context preview; - the chapter's Run button, which names the story's graph and says why it cannot run; - the story list, which names each story's graph. The plan named the first three; the Run button and the story list show graph data too. - The "unjournaled until Phase 3" notes on the graph, the store port, the DbContext and the effects now say the library's actions are announced, not journaled. ADR 0022's Decision text puts its "publish no DomainChanged" in Phase 2's past. The graph-library story gains the acceptance line, and the plan's slice 3 is ticked. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>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 - 97.8%
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
uration
n
Tsumugi.Kernel - 90.9%
Tsumugi.Server - 99.6%
Tsumugi.UseCases - 95.5%
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__AttemptCount_1
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__HexColour_2
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__LineBreaks_0
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__Preface_3
663A4576626E1322FB9C6CE472CAC0A2D2F3DEFF8CB40D9F7__SentenceEnd_4
🔮 fufu~ Jibril reviewed your code!
Oh? Oh! An announcement pattern grown a third kind —
EntityKinds.Graphtaking its place beside StorySnapshot and Run, each use case announcing only once its write is in, each view waking only after it has loaded. This is exactly the discipline ADR 0022 asks for. I read all 29 files, the full diff and the siblings, and ran my little probes~ ♡Verdict: ✅ Looks good to me~
✅ What I liked~
Every_library_action_is_announced_as_its_graph_changing_once_its_write_is_inreads the row from inside the subscriber and asserts it already holds what the write left — name, trash flag, exact operation, six distinct OperationIds. That's the rare test that catches an announcement racing its own save. Wonderful~Graph.MoveToTrash/Restorereturningbool(asRevisealready did), threaded throughMutateAsyncso an unchanged graph is not even saved — I probed this (made TrashGraph announce unconditionally) and the "a trash of a graph already in the trash" case killed it instantly. I also probed flipping ReviseGraph's operation to Create — the sequence assertion caught it. And I removed theEntityKinds.Graphtouch fromStoryGraphsEffects— the switcher test caught that too. Three probes, three kills, zero survivors~ ♪GraphsEffects,StoryGraphsEffects,StoriesEffects,LiveRunEffects,ContextPreviewEffectsall gained the touch the same way, each with a Loaded/Choices-not-null guard and a matching before-first-load test.ClearRunHistory's shared-OperationId batch is mirrored exactly by the re-seed's one-batch announcement. The registry test grows its third exclusion exactly as StorySnapshot and Run did.EfGraphStore.MutateAsyncskippingSaveChangesAsyncon an unchanged graph is a nice touch — no write, no announcement, no updated row.Program.csruns before circuits exist, so the only publisher whose announcement nobody can miss is safely unobservable — andSeedBundledGraphsstill guardswritten.Count > 0(equivalent to the bus's own empty-batch drop, as your notes say).ListStories.NamesAsync,PreviewContext,GetStoryRunState,ListStoryGraphs): each is reached through a view this PR wired, andSeedDevData(dev-only world seeding) correctly announces nothing. The set is closed — no view left behind~Fufu~ a slice this clean almost disappoints me — I sharpened my knives and found nothing to carve. Almost~ ♡
Automated review by Jibril · 2026-10-10
CI: green for head SHA
66b2ca7· Mutation probes: 3 run, 0 survived · Local suite: skipped (CI green)