feat: Kagaku.Flow run ledger (Phase 2 · slice 6a) #23

Merged
bjoern merged 2 commits from feat/kagaku-flow-ledger into main 2026-09-25 18:07:12 +02:00
Member

Slice 6 of Phase 2, part a of four. This part adds the run ledger:

  • the records a run leaves behind;
  • the transitions that move them;
  • the port a host stores them through;
  • Kagaku.Flow.Testing, a new package with an in-memory ledger and the contract every host adapter must pass.

Parts 6b (ready-set and executors), 6c (the scheduler runs a run) and 6d (cancel, retry, recovery and the loop) are stacked on this one and open after it merges. Nothing in src/Tsumugi.* changes. The only other file touched is docs/PROJECT_PLAN.md, whose slice-6 line now names this PR.

What

Kagaku.Flow.Runs

  • Records: Run, NodeRun (with an Id of its own), NodeAttempt, NodeFacts, LedgerChange, RunTrigger, RunEvent.
  • Enums: RunStatus, NodeRunStatus, AttemptOutcome, RunEventKind, RunEventChannel.
  • LedgerTransitions: every transition is a pure function over one run and all its rows.
    • The transitions are Start, Succeed, FailAttempt, Fail, Exclude, FailUnstarted, ResetOrphaned, Requeue and CancelRun, plus CheckCreate for a seeded run.
    • Each returns the LedgerChange it makes, or null when the row's status refuses it.
  • RunStatuses.Derive: a run's status comes from its rows by one precedence: cancelled > running > waiting > failed > pending > succeeded. It is stored as a cache that every write refreshes.
  • IRunLedger: the port. An adapter loads the run and its rows, applies the transition and stores the result atomically. It never re-implements a rule.
  • RunTrigger: the trigger envelope.
    • Its member order is fixed: kind, then inputs, then host members.
    • Duplicate members are refused, and the encoder is relaxed.
    • Malformed UTF-16 is refused, naming its JSON Pointer.
  • IRunEventSink: where run events are published. 6c and 6d publish them.

Kagaku.Flow.Testing (new, with no test framework)

  • InMemoryRunLedger: one lock, clones every JsonElement it keeps, and completes synchronously.

  • RunLedgerContract.VerifyAsync(scenario, newLedger): 17 named scenarios, each run through fresh clients. They cover:

    • creation and its refusals;
    • every transition and every refusal;
    • cancelled tokens;
    • JSON that outlives the caller's documents;
    • creation order, with rows whose ids and keys follow no order of creation;
    • concurrent settles, where exactly one of 32 raises RunSettled.

    Slice 11a's EF adapter will run the same theory. RunLedgerContractException names the failed scenario and check, both in its message and as its Scenario and Check properties.

The architecture test now scans Kagaku.Flow.Testing too. It checks the DLL's assembly references and also the package's declared dependencies in deps.json, so an unused test-framework PackageReference is caught before it ships to hosts.

Why

  • ADR 0016: the ledger-backed engine, with rows, attempts, statuses, retry and cancel.
  • ADR 0014: executors are tested against a real ledger.
  • ADR 0025: the engine is a library. Nothing here references Tsumugi, and hosts get a testing package.
  • ADR 0024 and ADR 0020: the row id and the dismissal that the monitor and the card link to.
  • ADR 0013: the node run carries the context report.

The transitions live in the core, and the adapters only store. The SQLite adapter (11a) and the in-memory ledger therefore cannot drift apart: neither re-implements a rule, so each either stores faithfully or fails the contract.

Decisions to confirm

Each departure from ADR text comes with the one-line amendment a later docs PR would make, once you confirm it.

  1. Status precedence: a waiting card keeps a run that has a failed row live (L5). Without it, three things would break:

    • the run could be dismissed while its card still waits (ADR 0024);
    • Cancel from the card would answer "not live" (ADR 0020);
    • the owner could start a second run (ADR 0016).

    Amendment to ADR 0016: "once nothing is running or waiting for input it fails the run."

  2. A retry requeues every failed row of the run (L2; the engine side is 6d). A run can have two failed rows. Requeueing only one would clear the dismissal but leave the run failed, with the requeued row stranded. Amendment to ADR 0016: "requeues the run's failed rows with their attempt budgets restored."

  3. NodeFacts gains DetailsJson and RequestedModel; the row keeps one cost (L4).

    • DetailsJson holds slice 9's context report. Amendment to ADR 0013: "skipped and reported in the node run's details, shown with its inputs."
    • Model is the model that served the request. RequestedModel is the id the request named, and the ratio is keyed by it. With a fallback, the fallback's tokens count toward the primary's ratio. Say if you would rather key the ratio by the served model.
  4. An excluded source is absent from the outputs, not stored as a marker value (L9). No marker value can collide with real JSON, and a template sees "excluded" the same way it sees "not wired".

  5. Attempt numbering (L3).

    • Attempt counts the current run of attempts. It rises at start, and a retry resets it to 0. That is ADR 0016's "budget restored", and it makes "an orphaned row keeps its attempt counted" true.
    • Attempts numbers every attempt across retries, for the inspector.
  6. NodeRun.Id is added, and there is no Run.Error. The monitor's deep link (ADR 0024) and the card's nodeRunId (ADR 0020) need a row id. A run-level error would need a column no ADR asks for.

  7. The ledger's semantics are in the core (LedgerTransitions). Adapters only store, and RunLedgerContract checks them. Orihon kept its transitions on its EF entity instead.

  8. The ledger enforces the given-up guard and its own consistency (L2, L8).

    • Start, Exclude and FailUnstarted refuse in a run that has given up.
    • Requeue refuses in a cancelled run. This was added in verification: without it, a retry in a cancelled run would clear its dismissal without reviving it. 6d still refuses that retry in the engine first.
    • CreateRunAsync refuses a seeded run whose status, cost or finish time disagrees with its rows.

For your call (no ADR text involved): settling a running row that has no open attempt keeps its log but drops the cost reported with it. A row gets into that state only if it is seeded that way.

  • The stricter option makes "a running row has an open attempt" a rule that CheckCreate enforces on seeded rows.
  • I left that open because 6b's property generator seeds waiting rows whose last attempt is closed but has no outcome.
  • The README's L2 section describes the current behaviour.

Out of scope

  • Containers (map, loop).
  • Human input: the waiting transition and the answer.
  • Dismiss: slice 13.
  • Re-run from a node: Phase 5.
  • Backoff and per-execution timeouts.
  • A durable finish signal.
  • The hosted service and the EF adapter (11a), and the use cases (11b).
  • Every concrete node type.
  • The ready-set, executors and scheduler themselves (6b–6d).

Tests

Project main (da9f961) this PR
Kagaku.Flow.Tests 483 669
Kagaku.Flow.OpenRouter.Tests 41 41
Tsumugi.Domain.Tests 37 37
Tsumugi.UseCases.Tests 12 12
Tsumugi.Integration.Tests 224 224
Tsumugi.BlazorAdapter.Tests 247 247
Total 1044 1230

The Release build has 0 warnings under TreatWarningsAsErrors. The new tests:

  • LedgerTransitionTests: every transition, and the ~48-row wrong-status theory.
  • RunStatusTests: the 9 precedence rows, each also checked in reverse.
  • RunTriggerTests.
  • RunEventTests.
  • InMemoryRunLedgerTests: the contract theory over all 17 scenarios, and a deliberately faulty ledger that shows each scenario names the rule it breaks.
  • The extended ArchitectureTests.

Coverage. Measured with coverlet per changed file, lines and branches (branch="True"), over facts and theories only (--filter "Category!=Property"). Every new file is at 100%.

File Lines Branches
Runs/LedgerTransitions.cs 139/139 62/62
Runs/RunTrigger.cs 83/83 38/38
Runs/RunStatuses.cs 12/12 20/20
Runs/Run.cs 11/11 4/4
Runs/LedgerChange.cs 3/3 4/4
Runs/NodeRun.cs, NodeFacts.cs, NodeAttempt.cs, RunEvent.cs 10/10, 16/16, 5/5, 5/5 –
Testing/InMemoryRunLedger.cs 70/70 28/28
Testing/RunLedgerContract.cs 465/465 22/22
Testing/RunLedgerContractException.cs all –

The enum and interface files have no coverable lines. The CI coverage report on this PR agrees: Kagaku.Flow.Runs and Kagaku.Flow.Testing are at 100% line and branch.

Mutation probes. Each was run on a copy, then restored and touched. Every §12 probe for part [A] was run, with every sub-part where a probe has several: 1–13, 57 and 59–63. Probe 56's Testing half (a story constant in the contract) was run too. All were killed, each by the assertion the brief names, with no crash, hang or compile error.

  • 4 was run on each of the nine transitions separately.
  • 7 was run on four adjacent pairs of the precedence list.
  • 11 covered five mutants:
    • no Clone();
    • rows listed by id;
    • rows listed by (NodeId, IterationPath);
    • every run listed as live;
    • the lock dropped. Without the lock, concurrent-settles failed in 10 of 10 runs.
  • 13: host members written before inputs, duplicates allowed, the default encoder, and the malformed-text check skipped.
  • 57 is caught as an unused PackageReference, as well as a used one.
  • 59 and 60: the scheduler tests the brief names for them arrive in 6b–6d. Here the transition and contract tests kill both.

One gap turned up. Probe 1 (count the attempt at settle, not at start) was killed only by other tests, because no test ran Start and then ResetOrphaned. An_orphan_keeps_the_attempt_its_start_counted_and_counts_no_other closes that gap, and it fails under probe 1.

Verification round (before opening)

A verifier found two gaps that weakened the tests, and five nits. All seven are fixed in the commit:

  • The contract did not enforce creation order. Its rows were created in node-id order, so a store listing rows by its unique index passed. They are now shuffled against both id and key order, and two deliberately faulty ledgers prove it.
  • An unused test-framework PackageReference slipped past the architecture test. The test now reads deps.json as well.
  • Requeue in a cancelled run is now refused (decision 8).
  • The settle that drops a cost is now documented (see "For your call").
  • Doc and assertion fixes: the RunStatus docs, README L10's claim about JSON Pointers, and ParamName asserts on the blank-argument test.

Rebased onto da9f961 (#20–#22). The only conflict was in Tsumugi.slnx, where both sides added a line; both are kept.

Review round 1 (6dfb727)

Jibril approved it. I took both 💡:

  • Succeed now clears a seeded row's error.
  • RunLedgerContractException now has Scenario and Check properties.

Each has a test that fails under its mutant.

🤖 Generated with Claude Code

Slice 6 of Phase 2, part **a** of four. This part adds **the run ledger**: - the records a run leaves behind; - the transitions that move them; - the port a host stores them through; - **`Kagaku.Flow.Testing`**, a new package with an in-memory ledger and the contract every host adapter must pass. Parts 6b (ready-set and executors), 6c (the scheduler runs a run) and 6d (cancel, retry, recovery and the loop) are stacked on this one and open after it merges. **Nothing in `src/Tsumugi.*` changes.** The only other file touched is `docs/PROJECT_PLAN.md`, whose slice-6 line now names this PR. ## What **`Kagaku.Flow.Runs`** - **Records:** `Run`, `NodeRun` (with an `Id` of its own), `NodeAttempt`, `NodeFacts`, `LedgerChange`, `RunTrigger`, `RunEvent`. - **Enums:** `RunStatus`, `NodeRunStatus`, `AttemptOutcome`, `RunEventKind`, `RunEventChannel`. - **`LedgerTransitions`:** every transition is a pure function over one run and all its rows. - The transitions are `Start`, `Succeed`, `FailAttempt`, `Fail`, `Exclude`, `FailUnstarted`, `ResetOrphaned`, `Requeue` and `CancelRun`, plus `CheckCreate` for a seeded run. - Each returns the `LedgerChange` it makes, or `null` when the row's status refuses it. - **`RunStatuses.Derive`:** a run's status comes from its rows by one precedence: cancelled > running > waiting > failed > pending > succeeded. It is stored as a cache that every write refreshes. - **`IRunLedger`:** the port. An adapter loads the run and its rows, applies the transition and stores the result atomically. It never re-implements a rule. - **`RunTrigger`:** the trigger envelope. - Its member order is fixed: `kind`, then `inputs`, then host members. - Duplicate members are refused, and the encoder is relaxed. - Malformed UTF-16 is refused, naming its JSON Pointer. - **`IRunEventSink`:** where run events are published. 6c and 6d publish them. **`Kagaku.Flow.Testing`** (new, with no test framework) - **`InMemoryRunLedger`:** one lock, clones every `JsonElement` it keeps, and completes synchronously. - **`RunLedgerContract.VerifyAsync(scenario, newLedger)`:** 17 named scenarios, each run through fresh clients. They cover: - creation and its refusals; - every transition and every refusal; - cancelled tokens; - JSON that outlives the caller's documents; - creation order, with rows whose ids and keys follow no order of creation; - concurrent settles, where exactly one of 32 raises `RunSettled`. Slice 11a's EF adapter will run the same theory. `RunLedgerContractException` names the failed scenario and check, both in its message and as its `Scenario` and `Check` properties. **The architecture test** now scans `Kagaku.Flow.Testing` too. It checks the DLL's assembly references and also the package's declared dependencies in `deps.json`, so an unused test-framework `PackageReference` is caught before it ships to hosts. ## Why - **ADR 0016:** the ledger-backed engine, with rows, attempts, statuses, retry and cancel. - **ADR 0014:** executors are tested against a real ledger. - **ADR 0025:** the engine is a library. Nothing here references Tsumugi, and hosts get a testing package. - **ADR 0024 and ADR 0020:** the row id and the dismissal that the monitor and the card link to. - **ADR 0013:** the node run carries the context report. **The transitions live in the core, and the adapters only store.** The SQLite adapter (11a) and the in-memory ledger therefore cannot drift apart: neither re-implements a rule, so each either stores faithfully or fails the contract. ## Decisions to confirm Each departure from ADR text comes with the one-line amendment a later docs PR would make, once you confirm it. 1. **Status precedence: a waiting card keeps a run that has a failed row live (L5).** Without it, three things would break: - the run could be dismissed while its card still waits (ADR 0024); - Cancel from the card would answer "not live" (ADR 0020); - the owner could start a second run (ADR 0016). *Amendment to ADR 0016:* "once nothing is running **or waiting for input** it fails the run." 2. **A retry requeues every failed row of the run (L2; the engine side is 6d).** A run can have two failed rows. Requeueing only one would clear the dismissal but leave the run failed, with the requeued row stranded. *Amendment to ADR 0016:* "requeues the run's `failed` rows with their attempt budgets restored." 3. **`NodeFacts` gains `DetailsJson` and `RequestedModel`; the row keeps one cost (L4).** - `DetailsJson` holds slice 9's context report. *Amendment to ADR 0013:* "skipped and reported in the node run's **details**, shown with its inputs." - `Model` is the model that served the request. `RequestedModel` is the id the request named, and the ratio is keyed by it. With a fallback, the fallback's tokens count toward the primary's ratio. Say if you would rather key the ratio by the served model. 4. **An excluded source is absent from the outputs, not stored as a marker value (L9).** No marker value can collide with real JSON, and a template sees "excluded" the same way it sees "not wired". 5. **Attempt numbering (L3).** - `Attempt` counts the current run of attempts. It rises at start, and a retry resets it to 0. That is ADR 0016's "budget restored", and it makes "an orphaned row keeps its attempt counted" true. - `Attempts` numbers every attempt across retries, for the inspector. 6. **`NodeRun.Id` is added, and there is no `Run.Error`.** The monitor's deep link (ADR 0024) and the card's `nodeRunId` (ADR 0020) need a row id. A run-level error would need a column no ADR asks for. 7. **The ledger's semantics are in the core (`LedgerTransitions`).** Adapters only store, and `RunLedgerContract` checks them. Orihon kept its transitions on its EF entity instead. 8. **The ledger enforces the given-up guard and its own consistency (L2, L8).** - `Start`, `Exclude` and `FailUnstarted` refuse in a run that has given up. - `Requeue` refuses in a cancelled run. This was added in verification: without it, a retry in a cancelled run would clear its dismissal without reviving it. 6d still refuses that retry in the engine first. - `CreateRunAsync` refuses a seeded run whose status, cost or finish time disagrees with its rows. **For your call (no ADR text involved):** settling a running row that has no open attempt keeps its log but drops the cost reported with it. A row gets into that state only if it is seeded that way. - The stricter option makes "a running row has an open attempt" a rule that `CheckCreate` enforces on seeded rows. - I left that open because 6b's property generator seeds waiting rows whose last attempt is closed but has no outcome. - The README's L2 section describes the current behaviour. ## Out of scope - Containers (map, loop). - Human input: the waiting transition and the answer. - Dismiss: slice 13. - Re-run from a node: Phase 5. - Backoff and per-execution timeouts. - A durable finish signal. - The hosted service and the EF adapter (11a), and the use cases (11b). - Every concrete node type. - The ready-set, executors and scheduler themselves (6b–6d). ## Tests | Project | main (`da9f961`) | this PR | |---|---|---| | Kagaku.Flow.Tests | 483 | **669** | | Kagaku.Flow.OpenRouter.Tests | 41 | 41 | | Tsumugi.Domain.Tests | 37 | 37 | | Tsumugi.UseCases.Tests | 12 | 12 | | Tsumugi.Integration.Tests | 224 | 224 | | Tsumugi.BlazorAdapter.Tests | 247 | 247 | | **Total** | **1044** | **1230** | The Release build has 0 warnings under `TreatWarningsAsErrors`. The new tests: - `LedgerTransitionTests`: every transition, and the ~48-row wrong-status theory. - `RunStatusTests`: the 9 precedence rows, each also checked in reverse. - `RunTriggerTests`. - `RunEventTests`. - `InMemoryRunLedgerTests`: the contract theory over all 17 scenarios, and a deliberately faulty ledger that shows each scenario names the rule it breaks. - The extended `ArchitectureTests`. **Coverage.** Measured with coverlet per changed file, lines and branches (`branch="True"`), over facts and theories only (`--filter "Category!=Property"`). **Every new file is at 100%.** | File | Lines | Branches | |---|---|---| | `Runs/LedgerTransitions.cs` | 139/139 | 62/62 | | `Runs/RunTrigger.cs` | 83/83 | 38/38 | | `Runs/RunStatuses.cs` | 12/12 | 20/20 | | `Runs/Run.cs` | 11/11 | 4/4 | | `Runs/LedgerChange.cs` | 3/3 | 4/4 | | `Runs/NodeRun.cs`, `NodeFacts.cs`, `NodeAttempt.cs`, `RunEvent.cs` | 10/10, 16/16, 5/5, 5/5 | – | | `Testing/InMemoryRunLedger.cs` | 70/70 | 28/28 | | `Testing/RunLedgerContract.cs` | 465/465 | 22/22 | | `Testing/RunLedgerContractException.cs` | all | – | The enum and interface files have no coverable lines. The CI coverage report on this PR agrees: `Kagaku.Flow.Runs` and `Kagaku.Flow.Testing` are at 100% line and branch. **Mutation probes.** Each was run on a copy, then restored and `touch`ed. Every §12 probe for part [A] was run, with every sub-part where a probe has several: 1–13, 57 and 59–63. Probe 56's Testing half (a `story` constant in the contract) was run too. **All were killed, each by the assertion the brief names, with no crash, hang or compile error.** - **4** was run on each of the nine transitions separately. - **7** was run on four adjacent pairs of the precedence list. - **11** covered five mutants: - no `Clone()`; - rows listed by id; - rows listed by `(NodeId, IterationPath)`; - every run listed as live; - the lock dropped. Without the lock, `concurrent-settles` failed in **10 of 10** runs. - **13:** host members written before `inputs`, duplicates allowed, the default encoder, and the malformed-text check skipped. - **57** is caught as an unused `PackageReference`, as well as a used one. - **59 and 60:** the scheduler tests the brief names for them arrive in 6b–6d. Here the transition and contract tests kill both. One gap turned up. Probe 1 (count the attempt at settle, not at start) was killed only by other tests, because no test ran Start and then ResetOrphaned. `An_orphan_keeps_the_attempt_its_start_counted_and_counts_no_other` closes that gap, and it fails under probe 1. ## Verification round (before opening) A verifier found two gaps that weakened the tests, and five nits. All seven are fixed in the commit: - **The contract did not enforce creation order.** Its rows were created in node-id order, so a store listing rows by its unique index passed. They are now shuffled against both id and key order, and two deliberately faulty ledgers prove it. - **An unused test-framework `PackageReference` slipped past the architecture test.** The test now reads `deps.json` as well. - **`Requeue` in a cancelled run** is now refused (decision 8). - **The settle that drops a cost** is now documented (see "For your call"). - **Doc and assertion fixes:** the `RunStatus` docs, README L10's claim about JSON Pointers, and `ParamName` asserts on the blank-argument test. Rebased onto `da9f961` (#20–#22). The only conflict was in `Tsumugi.slnx`, where both sides added a line; both are kept. ## Review round 1 (`6dfb727`) Jibril approved it. I took both 💡: - `Succeed` now clears a seeded row's error. - `RunLedgerContractException` now has `Scenario` and `Check` properties. Each has a test that fails under its mutant. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
feat(flow): the run ledger — records, pure transitions, the port, the trigger envelope and run events; Kagaku.Flow.Testing's in-memory ledger and contract
All checks were successful
CI / build (pull_request) Successful in 30s
CI / test (pull_request) Successful in 49s
0e851dfbc0
Every ledger transition lives in the core as a pure function over one run and all its rows
(LedgerTransitions), and an IRunLedger adapter only loads, applies and stores, atomically. Keeping the
rules out of the adapters means the SQLite adapter of slice 11a and the in-memory ledger cannot drift
apart: neither reimplements a transition, so each can only store faithfully or fail the contract. It also
lets the given-up guard (R2) and the cancelled-run refusal of Requeue hold inside the atomic write, not
only in the pass that read the rows.

A run's status is derived from its rows by one precedence (RunStatuses.Derive), because every question the
engine and the UI ask of a run (may it start, may it be dismissed, does it hold its owner's gate) follows
from its rows, and a stored status that could disagree would need its own repair path. It is still stored,
as a cache every write refreshes, so a store can query live runs by column; CreateRunAsync's CheckCreate
refuses a seeded run whose status, total cost or finish time disagrees with its rows, so the cache never
starts out wrong.

An excluded source is absent from a succeeded row's outputs rather than stored as a marker value. The
ledger then holds only JSON a node actually produced, a downstream template sees a missing member the same
way whether the source was excluded or never wired, and no sentinel can collide with a real value.

RunLedgerContract, in the new framework-free Kagaku.Flow.Testing package, is the one guard a host's adapter
gets. Each named scenario seeds a run, drives a write through a fresh client, compares the change with what
LedgerTransitions makes of the stored state, and reads everything back through fresh clients: creation and
its refusals, every transition and refusal, cancelled tokens, JSON that outlives the caller's documents,
creation order (rows whose ids and keys follow no order of their creation, so a store listing by its
primary key or unique index fails), and concurrent settles producing exactly one RunSettled. The in-memory
ledger passes it under one lock, and a fault-injecting client shows each scenario names the rule it breaks.
The architecture test scans Kagaku.Flow.Testing too, and reads both its assembly references and its
declared dependencies, so an unused test-framework package reference is caught before it ships to hosts.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>

🔄 Auto-updating coverage report — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip.

Commit: 6dfb727 · Generated: 2026-09-25 15:55:38 UTC · Revision: #2

Summary

Summary
Generated on: 09/25/2026 - 15:55:38
Coverage date: 09/25/2026 - 15:55:22 - 09/25/2026 - 15:55:35
Parser: MultiReport (6x Cobertura)
Assemblies: 9
Classes: 343
Files: 332
Line coverage: 98% (8043 of 8204)
Covered lines: 8043
Uncovered lines: 161
Coverable lines: 8204
Total lines: 17869
Branch coverage: 93.4% (2500 of 2675)
Covered branches: 2500
Total branches: 2675
Method coverage: Feature is only available for sponsors

Coverage

Kagaku.Flow - 99.5%
Name Line Branch
Kagaku.Flow 99.5% 98.9%
Kagaku.Flow.Budgeting.BudgetRequest 100%
Kagaku.Flow.Budgeting.ConsumerBudget 100%
Kagaku.Flow.FlowJson 100%
Kagaku.Flow.Graphs.GraphDefinition 100%
Kagaku.Flow.Graphs.GraphDocument 100% 100%
Kagaku.Flow.Graphs.GraphEdge 100%
Kagaku.Flow.Graphs.GraphIndex 100% 100%
Kagaku.Flow.Graphs.GraphLoadError 100%
Kagaku.Flow.Graphs.GraphLoadResult 100%
Kagaku.Flow.Graphs.GraphNode 100%
Kagaku.Flow.Graphs.GraphPosition 100%
Kagaku.Flow.Graphs.GraphReader 100% 100%
Kagaku.Flow.Graphs.GraphSchema 100% 100%
Kagaku.Flow.Graphs.GraphShapeException 100%
Kagaku.Flow.Graphs.GraphWriter 100% 100%
Kagaku.Flow.Graphs.SocketRef 100%
Kagaku.Flow.Graphs.WireText 100% 100%
Kagaku.Flow.Nodes.CanvasDescriptorWriter 100% 100%
Kagaku.Flow.Nodes.ConfigProblem 100%
Kagaku.Flow.Nodes.Names 100%
Kagaku.Flow.Nodes.NodeDescriptor 100% 100%
Kagaku.Flow.Nodes.NodeRegistry 100% 100%
Kagaku.Flow.Nodes.NodeSockets 100% 100%
Kagaku.Flow.Nodes.SinkDescriptor 100%
Kagaku.Flow.Nodes.SocketTypes 100% 100%
Kagaku.Flow.Nodes.SourceDescriptor 100%
Kagaku.Flow.Nodes.TemplateField 100%
Kagaku.Flow.Runs.LedgerChange 100% 100%
Kagaku.Flow.Runs.LedgerTransitions 100% 100%
Kagaku.Flow.Runs.NodeAttempt 100%
Kagaku.Flow.Runs.NodeFacts 100%
Kagaku.Flow.Runs.NodeRun 100%
Kagaku.Flow.Runs.Run 100% 100%
Kagaku.Flow.Runs.RunEvent 100%
Kagaku.Flow.Runs.RunStatuses 100% 100%
Kagaku.Flow.Runs.RunTrigger 100% 100%
Kagaku.Flow.Templating.InputsWalker 100% 100%
Kagaku.Flow.Templating.ParsedTemplate 100% 100%
Kagaku.Flow.Templating.SandboxedTemplateContext 100% 100%
Kagaku.Flow.Templating.TemplateError 100%
Kagaku.Flow.Templating.TemplateHost 100% 100%
Kagaku.Flow.Templating.TemplateLimits 100%
Kagaku.Flow.Templating.TemplateModel 100% 100%
Kagaku.Flow.Templating.TemplateProblem 100%
Kagaku.Flow.Templating.TemplateRenderRequest 100% 100%
Kagaku.Flow.Templating.TemplateRenderResult 100%
Kagaku.Flow.Templating.TemplateRun 100%
Kagaku.Flow.Templating.TemplateSinks 100%
Kagaku.Flow.Templating.TemplateValues 100% 100%
Kagaku.Flow.Validation.GraphValidation 100% 100%
Kagaku.Flow.Validation.GraphValidationContext 100%
Kagaku.Flow.Validation.HookFailure 100%
Kagaku.Flow.Validation.ResolvedGraph 100% 100%
Kagaku.Flow.Validation.ValidationError 100%
Kagaku.Flow.Validation.ValidationReport 100%
System.Text.RegularExpressions.Generated 97.4% 92.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__ColorToken_2
97.4% 94.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__Socket_1
97.2% 94.4%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF
E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__TypeId_0
97.2% 94.4%
Kagaku.Flow.OpenRouter - 100%
Name Line Branch
Kagaku.Flow.OpenRouter 100% 100%
Kagaku.Flow.OpenRouter.Gateway.OpenRouterGateway 100% 100%
Kagaku.Flow.OpenRouter.Gateway.OpenRouterGatewayOptions 100%
Kagaku.Flow.OpenRouter.Gateway.OpenRouterKeyLookup 100% 100%
Kagaku.Flow.OpenRouter.OpenRouterServiceCollectionExtensions 100% 100%
Kagaku.Flow.Testing - 100%
Name Line Branch
Kagaku.Flow.Testing 100% 100%
Kagaku.Flow.Testing.InMemoryRunLedger 100% 100%
Kagaku.Flow.Testing.RunLedgerContract 100% 100%
Kagaku.Flow.Testing.RunLedgerContractException 100%
Tsumugi.BlazorAdapter - 97.1%
Name Line Branch
Tsumugi.BlazorAdapter 97.1% 94%
Tsumugi.BlazorAdapter.BlazorAdapterAssembly 100%
Tsumugi.BlazorAdapter.Documents.CategoryCreated 100%
Tsumugi.BlazorAdapter.Documents.CategoryEditor 97.7% 86.1%
Tsumugi.BlazorAdapter.Documents.CategorySaved 100%
Tsumugi.BlazorAdapter.Documents.CreateCategoryRequested 100%
Tsumugi.BlazorAdapter.Documents.CreateDocumentRequested 100%
Tsumugi.BlazorAdapter.Documents.DeleteCategoryDialog 100% 100%
Tsumugi.BlazorAdapter.Documents.DeleteCategoryRequested 100%
Tsumugi.BlazorAdapter.Documents.DeleteDocumentRequested 100%
Tsumugi.BlazorAdapter.Documents.DocumentAutoSaveFailed 100%
Tsumugi.BlazorAdapter.Documents.DocumentCreated 100%
Tsumugi.BlazorAdapter.Documents.DocumentEditor 100% 87.9%
Tsumugi.BlazorAdapter.Documents.DocumentsActionFailed 100%
Tsumugi.BlazorAdapter.Documents.DocumentSaved 100%
Tsumugi.BlazorAdapter.Documents.DocumentsEffects 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsList 98.2% 92.4%
Tsumugi.BlazorAdapter.Documents.DocumentsLoaded 100%
Tsumugi.BlazorAdapter.Documents.DocumentsPage 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsReducers 100% 100%
Tsumugi.BlazorAdapter.Documents.DocumentsState 100% 100%
Tsumugi.BlazorAdapter.Documents.LoadDocuments 100%
Tsumugi.BlazorAdapter.Documents.MoveDocumentsRequested 100%
Tsumugi.BlazorAdapter.Documents.ReorderCategoriesRequested 100%
Tsumugi.BlazorAdapter.Documents.SetCategoryCollapsed 100%
Tsumugi.BlazorAdapter.Documents.SetDocumentsFilter 100%
Tsumugi.BlazorAdapter.Documents.UpdateCategoryRequested 100%
Tsumugi.BlazorAdapter.Documents.UpdateDocumentRequested 100%
Tsumugi.BlazorAdapter.Graphs.GraphCanvas 37.5% 25%
Tsumugi.BlazorAdapter.Graphs.GraphPlaygroundPage 20% 25%
Tsumugi.BlazorAdapter.Notifications.DomainChangedBridge 94.4% 83.3%
Tsumugi.BlazorAdapter.Notifications.DomainChangesReceived 75% 100%
Tsumugi.BlazorAdapter.Runs.RunChangedBridge 97.1% 90.6%
Tsumugi.BlazorAdapter.Runs.RunChangesReceived 100%
Tsumugi.BlazorAdapter.Runs.RunTextReceived 100%
Tsumugi.BlazorAdapter.Settings.BackupCompleted 100%
Tsumugi.BlazorAdapter.Settings.BackupFailed 100%
Tsumugi.BlazorAdapter.Settings.BackupNowRequested 100%
Tsumugi.BlazorAdapter.Settings.BackupSettingsLoaded 100%
Tsumugi.BlazorAdapter.Settings.BackupsSection 100% 100%
Tsumugi.BlazorAdapter.Settings.BackupsSettingsEffects 100% 100%
Tsumugi.BlazorAdapter.Settings.BackupsSettingsReducers 100%
Tsumugi.BlazorAdapter.Settings.BackupsSettingsState 100%
Tsumugi.BlazorAdapter.Settings.DefaultsSection 100% 100%
Tsumugi.BlazorAdapter.Settings.DefaultsSettingsEffects 100% 100%
Tsumugi.BlazorAdapter.Settings.DefaultsSettingsReducers 100%
Tsumugi.BlazorAdapter.Settings.DefaultsSettingsState 100%
Tsumugi.BlazorAdapter.Settings.LlmDefaultsLoaded 100%
Tsumugi.BlazorAdapter.Settings.LlmDefaultsSaved 100%
Tsumugi.BlazorAdapter.Settings.LlmDefaultsSaveFailed 100%
Tsumugi.BlazorAdapter.Settings.LoadBackupSettings 100%
Tsumugi.BlazorAdapter.Settings.LoadProviderSettings 100%
Tsumugi.BlazorAdapter.Settings.OpenRouterKeySaved 100%
Tsumugi.BlazorAdapter.Settings.OpenRouterKeySaveFailed 100%
Tsumugi.BlazorAdapter.Settings.ProviderKeyChecked 100%
Tsumugi.BlazorAdapter.Settings.ProviderSection 100% 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsEffects 100% 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsLoaded 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsReducers 100% 100%
Tsumugi.BlazorAdapter.Settings.ProviderSettingsState 100% 100%
Tsumugi.BlazorAdapter.Settings.SaveLlmDefaultsRequested 100%
Tsumugi.BlazorAdapter.Settings.SaveOpenRouterKeyRequested 100%
Tsumugi.BlazorAdapter.Stories.CreateStoryRequested 100%
Tsumugi.BlazorAdapter.Stories.PurgeStoryRequested 100%
Tsumugi.BlazorAdapter.Stories.RestoreStoryRequested 100%
Tsumugi.BlazorAdapter.Stories.SetShowArchived 100%
Tsumugi.BlazorAdapter.Stories.SetStoriesFilter 100%
Tsumugi.BlazorAdapter.Stories.SetStoryArchivedRequested 100%
Tsumugi.BlazorAdapter.Stories.StoriesEffects 100% 100%
Tsumugi.BlazorAdapter.Stories.StoriesLoaded 100%
Tsumugi.BlazorAdapter.Stories.StoriesPage 100% 100%
Tsumugi.BlazorAdapter.Stories.StoriesReducers 100% 100%
Tsumugi.BlazorAdapter.Stories.StoriesState 100% 100%
Tsumugi.BlazorAdapter.Stories.StoryActionFailed 100%
Tsumugi.BlazorAdapter.Stories.StoryCreated 100%
Tsumugi.BlazorAdapter.Stories.StoryCreateFailed 100%
Tsumugi.BlazorAdapter.Stories.StoryTrashPage 100% 100%
Tsumugi.BlazorAdapter.Stories.TrashStoryRequested 100%
Tsumugi.BlazorAdapter.Workspace.AutoSaveFailed 100%
Tsumugi.BlazorAdapter.Workspace.CaretRequest 100%
Tsumugi.BlazorAdapter.Workspace.ChapterHeader 100% 86.3%
Tsumugi.BlazorAdapter.Workspace.ChapterMenu 100% 81.2%
Tsumugi.BlazorAdapter.Workspace.ChapterPage 100% 87.5%
Tsumugi.BlazorAdapter.Workspace.ChapterSaved 100%
Tsumugi.BlazorAdapter.Workspace.ChaptersPage 90% 83.3%
Tsumugi.BlazorAdapter.Workspace.CreateChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.DeleteChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.DeleteSegmentRequested 100%
Tsumugi.BlazorAdapter.Workspace.EditSegmentRequested 100%
Tsumugi.BlazorAdapter.Workspace.HistoryEffects 100% 100%
Tsumugi.BlazorAdapter.Workspace.HistoryLoaded 100%
Tsumugi.BlazorAdapter.Workspace.HistoryPage 100%
Tsumugi.BlazorAdapter.Workspace.HistoryPanel 100% 100%
Tsumugi.BlazorAdapter.Workspace.InsertSegmentRequested 100%
Tsumugi.BlazorAdapter.Workspace.LoadHistory 100%
Tsumugi.BlazorAdapter.Workspace.LoadWorkspace 100%
Tsumugi.BlazorAdapter.Workspace.ManuscriptColumn 94.9% 89.4%
Tsumugi.BlazorAdapter.Workspace.ManuscriptEffects 100% 100%
Tsumugi.BlazorAdapter.Workspace.MergeChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.MergeSegmentRequested 100%
Tsumugi.BlazorAdapter.Workspace.MoveChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.RedoRequested 100%
Tsumugi.BlazorAdapter.Workspace.RedoRevertRequested 100%
Tsumugi.BlazorAdapter.Workspace.RenameChapterRequested 100%
Tsumugi.BlazorAdapter.Workspace.RevertToSnapshotRequested 100%
Tsumugi.BlazorAdapter.Workspace.SaveScope 100% 50%
Tsumugi.BlazorAdapter.Workspace.SaveStateLadder 100% 100%
Tsumugi.BlazorAdapter.Workspace.SaveVersionRequested 100%
Tsumugi.BlazorAdapter.Workspace.SegmentRow 100% 96.8%
Tsumugi.BlazorAdapter.Workspace.SegmentSaved 100%
Tsumugi.BlazorAdapter.Workspace.SetChapterSummaryRequested 100%
Tsumugi.BlazorAdapter.Workspace.SplitSegmentRequested 100%
Tsumugi.BlazorAdapter.Workspace.StoryDetails 100% 85.2%
Tsumugi.BlazorAdapter.Workspace.StoryGeneralPage 100% 100%
Tsumugi.BlazorAdapter.Workspace.StorySaved 100%
Tsumugi.BlazorAdapter.Workspace.StoryShell 100% 100%
Tsumugi.BlazorAdapter.Workspace.UndoRequested 100%
Tsumugi.BlazorAdapter.Workspace.UndoStatusChanged 100%
Tsumugi.BlazorAdapter.Workspace.UpdateStoryRequested 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceActionFailed 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceLoaded 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceNotFound 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceReducers 100% 100%
Tsumugi.BlazorAdapter.Workspace.WorkspaceState 100%
Tsumugi.Domain - 99.3%
Name Line Branch
Tsumugi.Domain 99.3% 95.6%
Tsumugi.Domain.Documents.Document 100% 100%
Tsumugi.Domain.Documents.DocumentCategory 100%
Tsumugi.Domain.Journal.ChangeLogEntry 97.8% 75%
Tsumugi.Domain.Journal.StorySnapshot 95.4% 83.3%
Tsumugi.Domain.Settings.AppSetting 100%
Tsumugi.Domain.Stories.Chapter 100% 100%
Tsumugi.Domain.Stories.Provenance 100% 100%
Tsumugi.Domain.Stories.Segment 100% 100%
Tsumugi.Domain.Stories.Story 100% 100%
Tsumugi.Domain.Text 100% 100%
Tsumugi.Infrastructure - 97.2%
Name Line Branch
Tsumugi.Infrastructure 97.2% 84.2%
System.Text.RegularExpressions.Generated 81.4% 64.8%
System.Text.RegularExpressions.Generated.<RegexGenerator_g>F0D076C66E8EEC1C
A55E0373ED22DC58420DBB40F103A46B68DC4D9CE5A49E00B__Pattern_0
84% 65.7%
Tsumugi.Infrastructure.Backups.BackupArtifactName 100% 100%
Tsumugi.Infrastructure.Backups.BackupOptions 100%
Tsumugi.Infrastructure.Backups.BackupSchedule 100% 83.3%
Tsumugi.Infrastructure.Backups.BackupScheduler 96.5% 83.3%
Tsumugi.Infrastructure.Backups.BackupWriter 98.4% 92.5%
Tsumugi.Infrastructure.Backups.FileSystemBackupStore 100% 100%
Tsumugi.Infrastructure.Backups.SqliteSnapshot 87.8% 75%
Tsumugi.Infrastructure.DependencyInjection 100% 100%
Tsumugi.Infrastructure.Journal.EfChangeJournal 100%
Tsumugi.Infrastructure.Journal.EfSnapshotStore 100%
Tsumugi.Infrastructure.Journal.EfUndoStore 98.1% 85.7%
Tsumugi.Infrastructure.Journal.ModelExtensions 100%
Tsumugi.Infrastructure.Journal.OperationContext 100% 100%
Tsumugi.Infrastructure.Journal.PropertyBag 100% 95.4%
Tsumugi.Infrastructure.Notifications.InProcessDomainChangedBus 100% 100%
Tsumugi.Infrastructure.Persistence.Configurations.AppSettingConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.ChangeLogEntryConfigurati
on
100%
Tsumugi.Infrastructure.Persistence.Configurations.ChapterConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.DocumentCategoryConfigura
tion
100%
Tsumugi.Infrastructure.Persistence.Configurations.DocumentConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.SegmentConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.StoryConfiguration 100%
Tsumugi.Infrastructure.Persistence.Configurations.StorySnapshotConfiguratio
n
100%
Tsumugi.Infrastructure.Persistence.Converters.ProvenanceConverter 100% 90%
Tsumugi.Infrastructure.Persistence.Converters.UtcTicksConverter 100%
Tsumugi.Infrastructure.Persistence.Migrations.AddAppSettings 99.2%
Tsumugi.Infrastructure.Persistence.Migrations.AddJournal 98.8%
Tsumugi.Infrastructure.Persistence.Migrations.GenericDocuments 100%
Tsumugi.Infrastructure.Persistence.Migrations.InitialStoryDomain 97.3%
Tsumugi.Infrastructure.Persistence.Migrations.TsumugiDbContextModelSnapshot 100%
Tsumugi.Infrastructure.Persistence.SqlitePragmaInterceptor 100% 100%
Tsumugi.Infrastructure.Persistence.Stores.EfChapterStore 100% 100%
Tsumugi.Infrastructure.Persistence.Stores.EfDocumentStore 97.5% 90%
Tsumugi.Infrastructure.Persistence.Stores.EfSegmentStore 95% 84.6%
Tsumugi.Infrastructure.Persistence.Stores.EfStoryStore 98.3% 92.8%
Tsumugi.Infrastructure.Persistence.TsumugiDbContext 83.5% 93.1%
Tsumugi.Infrastructure.Persistence.TsumugiDbContextFactory 0%
Tsumugi.Infrastructure.Provider.OpenRouterKeySource 100% 100%
Tsumugi.Infrastructure.Provider.OpenRouterModelProvider 100% 100%
Tsumugi.Infrastructure.Provider.OpenRouterOptions 100% 100%
Tsumugi.Infrastructure.Provider.ResolvedKey 100%
Tsumugi.Infrastructure.Runs.InProcessRunEventBus 100% 100%
Tsumugi.Infrastructure.Settings.EfAppSettingsStore 100% 100%
Tsumugi.Kernel - 90.9%
Name Line Branch
Tsumugi.Kernel 90.9% 75%
Tsumugi.Kernel.Err`1 100%
Tsumugi.Kernel.Ok`1 100%
Tsumugi.Kernel.Result`1 88.8% 75%
Tsumugi.Server - 100%
Name Line Branch
Tsumugi.Server 100% 86.4%
Program 100% 100%
Tsumugi.Server.Backups.BackupConfiguration 100% 100%
Tsumugi.Server.Components.App 100%
Tsumugi.Server.Components.Layout.AppHeader 100% 50%
Tsumugi.Server.Components.Layout.MainLayout 100%
Tsumugi.Server.Components.Pages.Gate 100% 100%
Tsumugi.Server.Provider.OpenRouterConfiguration 100% 100%
Tsumugi.Server.Security.AccessGate 100% 66.6%
Tsumugi.Server.Security.AccessSecret 100% 50%
Tsumugi.Server.VolumeStartupValidator 100% 100%
Tsumugi.UseCases - 98%
Name Line Branch
Tsumugi.UseCases 98% 94.1%
Tsumugi.UseCases.Backups.BackupArtifact 100%
Tsumugi.UseCases.Backups.BackupPolicy 100%
Tsumugi.UseCases.Backups.BackupStatusView 100% 100%
Tsumugi.UseCases.Backups.DatabaseSnapshot 100%
Tsumugi.UseCases.Backups.DownloadDatabaseSnapshot 100%
Tsumugi.UseCases.Backups.GetBackupStatus 100%
Tsumugi.UseCases.Backups.RunBackupNow 100%
Tsumugi.UseCases.Chapters.ChapterDto 100%
Tsumugi.UseCases.Chapters.CreateChapter 100% 100%
Tsumugi.UseCases.Chapters.DeleteChapter 100% 100%
Tsumugi.UseCases.Chapters.GetManuscript 100% 100%
Tsumugi.UseCases.Chapters.ManuscriptChapter 100%
Tsumugi.UseCases.Chapters.ManuscriptView 100%
Tsumugi.UseCases.Chapters.MergeChapters 100% 100%
Tsumugi.UseCases.Chapters.RenameChapter 100% 100%
Tsumugi.UseCases.Chapters.ReorderChapters 100% 100%
Tsumugi.UseCases.Chapters.SetChapterSummary 100% 75%
Tsumugi.UseCases.DependencyInjection 100%
Tsumugi.UseCases.Diagnostics.SeedDevData 97.3% 70%
Tsumugi.UseCases.Documents.CreateCategory 100% 100%
Tsumugi.UseCases.Documents.CreateDocument 100% 100%
Tsumugi.UseCases.Documents.DeleteCategory 100% 100%
Tsumugi.UseCases.Documents.DeleteDocument 100% 100%
Tsumugi.UseCases.Documents.DocumentCategoryDto 100%
Tsumugi.UseCases.Documents.DocumentCategoryProfile 100%
Tsumugi.UseCases.Documents.DocumentDto 100%
Tsumugi.UseCases.Documents.DocumentProfile 100%
Tsumugi.UseCases.Documents.DocumentsCategory 100%
Tsumugi.UseCases.Documents.DocumentsView 100%
Tsumugi.UseCases.Documents.GetDocuments 100% 100%
Tsumugi.UseCases.Documents.MoveDocuments 100% 100%
Tsumugi.UseCases.Documents.ReorderCategories 100% 100%
Tsumugi.UseCases.Documents.UpdateCategory 100% 100%
Tsumugi.UseCases.Documents.UpdateDocument 100% 100%
Tsumugi.UseCases.Journal.GetStoryHistory 100% 100%
Tsumugi.UseCases.Journal.GetUndoStatus 100% 100%
Tsumugi.UseCases.Journal.HistoryOperation 66.6%
Tsumugi.UseCases.Journal.HistorySnapshot 87.5%
Tsumugi.UseCases.Journal.OperationGrouping 100% 100%
Tsumugi.UseCases.Journal.RedoRevert 100% 100%
Tsumugi.UseCases.Journal.RedoRun 75% 57.1%
Tsumugi.UseCases.Journal.RedoTyping 100% 100%
Tsumugi.UseCases.Journal.RevertConflict 100%
Tsumugi.UseCases.Journal.RevertOutcome 100%
Tsumugi.UseCases.Journal.RevertRun 96.5% 77.7%
Tsumugi.UseCases.Journal.RevertToSnapshot 92.3% 83.3%
Tsumugi.UseCases.Journal.StoryHistory 100%
Tsumugi.UseCases.Journal.TakeSnapshot 100% 87.5%
Tsumugi.UseCases.Journal.UndoStatus 100%
Tsumugi.UseCases.Journal.UndoTyping 100% 100%
Tsumugi.UseCases.Journal.UserOperation 100%
Tsumugi.UseCases.Notifications.DomainChanged 100%
Tsumugi.UseCases.Ordering 100% 100%
Tsumugi.UseCases.Runs.RunEvent 100%
Tsumugi.UseCases.Segments.DeleteSegments 100% 100%
Tsumugi.UseCases.Segments.EditSegment 100% 83.3%
Tsumugi.UseCases.Segments.InsertSegment 100% 100%
Tsumugi.UseCases.Segments.MergeSegmentWithPrevious 100% 100%
Tsumugi.UseCases.Segments.MoveSegments 100% 100%
Tsumugi.UseCases.Segments.ReorderSegments 100% 100%
Tsumugi.UseCases.Segments.SegmentDto 100%
Tsumugi.UseCases.Segments.SplitSegment 100% 100%
Tsumugi.UseCases.Settings.CheckOpenRouterKey 100%
Tsumugi.UseCases.Settings.GetLlmDefaults 100% 100%
Tsumugi.UseCases.Settings.GetProviderSettings 100%
Tsumugi.UseCases.Settings.LlmDefaults 100%
Tsumugi.UseCases.Settings.ProviderKeyInfo 100%
Tsumugi.UseCases.Settings.ProviderKeyState 100%
Tsumugi.UseCases.Settings.ProviderSettingsView 100% 100%
Tsumugi.UseCases.Settings.ReasoningEfforts 100% 100%
Tsumugi.UseCases.Settings.RemoveOpenRouterKey 100%
Tsumugi.UseCases.Settings.SaveLlmDefaults 100% 100%
Tsumugi.UseCases.Settings.SaveOpenRouterKey 100% 100%
Tsumugi.UseCases.Stories.CreateStory 100% 100%
Tsumugi.UseCases.Stories.GetStory 100% 100%
Tsumugi.UseCases.Stories.ListStories 100% 75%
Tsumugi.UseCases.Stories.PurgeStory 100% 100%
Tsumugi.UseCases.Stories.RestoreStory 100% 100%
Tsumugi.UseCases.Stories.SetActiveGraph 100% 100%
Tsumugi.UseCases.Stories.SetStoryArchived 100% 100%
Tsumugi.UseCases.Stories.StarterCategories 100%
Tsumugi.UseCases.Stories.StoryDetail 100%
Tsumugi.UseCases.Stories.StoryListItem 81.8%
Tsumugi.UseCases.Stories.StoryProfile 100%
Tsumugi.UseCases.Stories.TrashStory 100% 100%
Tsumugi.UseCases.Stories.UpdateStory 100% 100%
<!-- coverage-comment --> > 🔄 **Auto-updating coverage report** — this comment is regenerated on every push, so the numbers below always reflect the commit shown here, not the branch tip. > > **Commit:** `6dfb727` · **Generated:** 2026-09-25 15:55:38 UTC · **Revision:** #2 # Summary <details open><summary>Summary</summary> ||| |:---|:---| | Generated on: | 09/25/2026 - 15:55:38 | | Coverage date: | 09/25/2026 - 15:55:22 - 09/25/2026 - 15:55:35 | | Parser: | MultiReport (6x Cobertura) | | Assemblies: | 9 | | Classes: | 343 | | Files: | 332 | | **Line coverage:** | 98% (8043 of 8204) | | Covered lines: | 8043 | | Uncovered lines: | 161 | | Coverable lines: | 8204 | | Total lines: | 17869 | | **Branch coverage:** | 93.4% (2500 of 2675) | | Covered branches: | 2500 | | Total branches: | 2675 | | **Method coverage:** | [Feature is only available for sponsors](https://reportgenerator.io/pro) | </details> ## Coverage <details><summary>Kagaku.Flow - 99.5%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.Flow**|**99.5%**|**98.9%**| |Kagaku.Flow.Budgeting.BudgetRequest|100%|| |Kagaku.Flow.Budgeting.ConsumerBudget|100%|| |Kagaku.Flow.FlowJson|100%|| |Kagaku.Flow.Graphs.GraphDefinition|100%|| |Kagaku.Flow.Graphs.GraphDocument|100%|100%| |Kagaku.Flow.Graphs.GraphEdge|100%|| |Kagaku.Flow.Graphs.GraphIndex|100%|100%| |Kagaku.Flow.Graphs.GraphLoadError|100%|| |Kagaku.Flow.Graphs.GraphLoadResult|100%|| |Kagaku.Flow.Graphs.GraphNode|100%|| |Kagaku.Flow.Graphs.GraphPosition|100%|| |Kagaku.Flow.Graphs.GraphReader|100%|100%| |Kagaku.Flow.Graphs.GraphSchema|100%|100%| |Kagaku.Flow.Graphs.GraphShapeException|100%|| |Kagaku.Flow.Graphs.GraphWriter|100%|100%| |Kagaku.Flow.Graphs.SocketRef|100%|| |Kagaku.Flow.Graphs.WireText|100%|100%| |Kagaku.Flow.Nodes.CanvasDescriptorWriter|100%|100%| |Kagaku.Flow.Nodes.ConfigProblem|100%|| |Kagaku.Flow.Nodes.Names|100%|| |Kagaku.Flow.Nodes.NodeDescriptor|100%|100%| |Kagaku.Flow.Nodes.NodeRegistry|100%|100%| |Kagaku.Flow.Nodes.NodeSockets|100%|100%| |Kagaku.Flow.Nodes.SinkDescriptor|100%|| |Kagaku.Flow.Nodes.SocketTypes|100%|100%| |Kagaku.Flow.Nodes.SourceDescriptor|100%|| |Kagaku.Flow.Nodes.TemplateField|100%|| |Kagaku.Flow.Runs.LedgerChange|100%|100%| |Kagaku.Flow.Runs.LedgerTransitions|100%|100%| |Kagaku.Flow.Runs.NodeAttempt|100%|| |Kagaku.Flow.Runs.NodeFacts|100%|| |Kagaku.Flow.Runs.NodeRun|100%|| |Kagaku.Flow.Runs.Run|100%|100%| |Kagaku.Flow.Runs.RunEvent|100%|| |Kagaku.Flow.Runs.RunStatuses|100%|100%| |Kagaku.Flow.Runs.RunTrigger|100%|100%| |Kagaku.Flow.Templating.InputsWalker|100%|100%| |Kagaku.Flow.Templating.ParsedTemplate|100%|100%| |Kagaku.Flow.Templating.SandboxedTemplateContext|100%|100%| |Kagaku.Flow.Templating.TemplateError|100%|| |Kagaku.Flow.Templating.TemplateHost|100%|100%| |Kagaku.Flow.Templating.TemplateLimits|100%|| |Kagaku.Flow.Templating.TemplateModel|100%|100%| |Kagaku.Flow.Templating.TemplateProblem|100%|| |Kagaku.Flow.Templating.TemplateRenderRequest|100%|100%| |Kagaku.Flow.Templating.TemplateRenderResult|100%|| |Kagaku.Flow.Templating.TemplateRun|100%|| |Kagaku.Flow.Templating.TemplateSinks|100%|| |Kagaku.Flow.Templating.TemplateValues|100%|100%| |Kagaku.Flow.Validation.GraphValidation|100%|100%| |Kagaku.Flow.Validation.GraphValidationContext|100%|| |Kagaku.Flow.Validation.HookFailure|100%|| |Kagaku.Flow.Validation.ResolvedGraph|100%|100%| |Kagaku.Flow.Validation.ValidationError|100%|| |Kagaku.Flow.Validation.ValidationReport|100%|| |System.Text.RegularExpressions.Generated|97.4%|92.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF<br/>E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__ColorToken_2|97.4%|94.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF<br/>E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__Socket_1|97.2%|94.4%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F6329A328226B0CF<br/>E95E47D27E8B105AC5589487C0997B6B65384AEDBF572144E__TypeId_0|97.2%|94.4%| </details> <details><summary>Kagaku.Flow.OpenRouter - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.Flow.OpenRouter**|**100%**|**100%**| |Kagaku.Flow.OpenRouter.Gateway.OpenRouterGateway|100%|100%| |Kagaku.Flow.OpenRouter.Gateway.OpenRouterGatewayOptions|100%|| |Kagaku.Flow.OpenRouter.Gateway.OpenRouterKeyLookup|100%|100%| |Kagaku.Flow.OpenRouter.OpenRouterServiceCollectionExtensions|100%|100%| </details> <details><summary>Kagaku.Flow.Testing - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Kagaku.Flow.Testing**|**100%**|**100%**| |Kagaku.Flow.Testing.InMemoryRunLedger|100%|100%| |Kagaku.Flow.Testing.RunLedgerContract|100%|100%| |Kagaku.Flow.Testing.RunLedgerContractException|100%|| </details> <details><summary>Tsumugi.BlazorAdapter - 97.1%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.BlazorAdapter**|**97.1%**|**94%**| |Tsumugi.BlazorAdapter.BlazorAdapterAssembly|100%|| |Tsumugi.BlazorAdapter.Documents.CategoryCreated|100%|| |Tsumugi.BlazorAdapter.Documents.CategoryEditor|97.7%|86.1%| |Tsumugi.BlazorAdapter.Documents.CategorySaved|100%|| |Tsumugi.BlazorAdapter.Documents.CreateCategoryRequested|100%|| |Tsumugi.BlazorAdapter.Documents.CreateDocumentRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DeleteCategoryDialog|100%|100%| |Tsumugi.BlazorAdapter.Documents.DeleteCategoryRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DeleteDocumentRequested|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentAutoSaveFailed|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentCreated|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentEditor|100%|87.9%| |Tsumugi.BlazorAdapter.Documents.DocumentsActionFailed|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentSaved|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsEffects|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsList|98.2%|92.4%| |Tsumugi.BlazorAdapter.Documents.DocumentsLoaded|100%|| |Tsumugi.BlazorAdapter.Documents.DocumentsPage|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsReducers|100%|100%| |Tsumugi.BlazorAdapter.Documents.DocumentsState|100%|100%| |Tsumugi.BlazorAdapter.Documents.LoadDocuments|100%|| |Tsumugi.BlazorAdapter.Documents.MoveDocumentsRequested|100%|| |Tsumugi.BlazorAdapter.Documents.ReorderCategoriesRequested|100%|| |Tsumugi.BlazorAdapter.Documents.SetCategoryCollapsed|100%|| |Tsumugi.BlazorAdapter.Documents.SetDocumentsFilter|100%|| |Tsumugi.BlazorAdapter.Documents.UpdateCategoryRequested|100%|| |Tsumugi.BlazorAdapter.Documents.UpdateDocumentRequested|100%|| |Tsumugi.BlazorAdapter.Graphs.GraphCanvas|37.5%|25%| |Tsumugi.BlazorAdapter.Graphs.GraphPlaygroundPage|20%|25%| |Tsumugi.BlazorAdapter.Notifications.DomainChangedBridge|94.4%|83.3%| |Tsumugi.BlazorAdapter.Notifications.DomainChangesReceived|75%|100%| |Tsumugi.BlazorAdapter.Runs.RunChangedBridge|97.1%|90.6%| |Tsumugi.BlazorAdapter.Runs.RunChangesReceived|100%|| |Tsumugi.BlazorAdapter.Runs.RunTextReceived|100%|| |Tsumugi.BlazorAdapter.Settings.BackupCompleted|100%|| |Tsumugi.BlazorAdapter.Settings.BackupFailed|100%|| |Tsumugi.BlazorAdapter.Settings.BackupNowRequested|100%|| |Tsumugi.BlazorAdapter.Settings.BackupSettingsLoaded|100%|| |Tsumugi.BlazorAdapter.Settings.BackupsSection|100%|100%| |Tsumugi.BlazorAdapter.Settings.BackupsSettingsEffects|100%|100%| |Tsumugi.BlazorAdapter.Settings.BackupsSettingsReducers|100%|| |Tsumugi.BlazorAdapter.Settings.BackupsSettingsState|100%|| |Tsumugi.BlazorAdapter.Settings.DefaultsSection|100%|100%| |Tsumugi.BlazorAdapter.Settings.DefaultsSettingsEffects|100%|100%| |Tsumugi.BlazorAdapter.Settings.DefaultsSettingsReducers|100%|| |Tsumugi.BlazorAdapter.Settings.DefaultsSettingsState|100%|| |Tsumugi.BlazorAdapter.Settings.LlmDefaultsLoaded|100%|| |Tsumugi.BlazorAdapter.Settings.LlmDefaultsSaved|100%|| |Tsumugi.BlazorAdapter.Settings.LlmDefaultsSaveFailed|100%|| |Tsumugi.BlazorAdapter.Settings.LoadBackupSettings|100%|| |Tsumugi.BlazorAdapter.Settings.LoadProviderSettings|100%|| |Tsumugi.BlazorAdapter.Settings.OpenRouterKeySaved|100%|| |Tsumugi.BlazorAdapter.Settings.OpenRouterKeySaveFailed|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderKeyChecked|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderSection|100%|100%| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsEffects|100%|100%| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsLoaded|100%|| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsReducers|100%|100%| |Tsumugi.BlazorAdapter.Settings.ProviderSettingsState|100%|100%| |Tsumugi.BlazorAdapter.Settings.SaveLlmDefaultsRequested|100%|| |Tsumugi.BlazorAdapter.Settings.SaveOpenRouterKeyRequested|100%|| |Tsumugi.BlazorAdapter.Stories.CreateStoryRequested|100%|| |Tsumugi.BlazorAdapter.Stories.PurgeStoryRequested|100%|| |Tsumugi.BlazorAdapter.Stories.RestoreStoryRequested|100%|| |Tsumugi.BlazorAdapter.Stories.SetShowArchived|100%|| |Tsumugi.BlazorAdapter.Stories.SetStoriesFilter|100%|| |Tsumugi.BlazorAdapter.Stories.SetStoryArchivedRequested|100%|| |Tsumugi.BlazorAdapter.Stories.StoriesEffects|100%|100%| |Tsumugi.BlazorAdapter.Stories.StoriesLoaded|100%|| |Tsumugi.BlazorAdapter.Stories.StoriesPage|100%|100%| |Tsumugi.BlazorAdapter.Stories.StoriesReducers|100%|100%| |Tsumugi.BlazorAdapter.Stories.StoriesState|100%|100%| |Tsumugi.BlazorAdapter.Stories.StoryActionFailed|100%|| |Tsumugi.BlazorAdapter.Stories.StoryCreated|100%|| |Tsumugi.BlazorAdapter.Stories.StoryCreateFailed|100%|| |Tsumugi.BlazorAdapter.Stories.StoryTrashPage|100%|100%| |Tsumugi.BlazorAdapter.Stories.TrashStoryRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.AutoSaveFailed|100%|| |Tsumugi.BlazorAdapter.Workspace.CaretRequest|100%|| |Tsumugi.BlazorAdapter.Workspace.ChapterHeader|100%|86.3%| |Tsumugi.BlazorAdapter.Workspace.ChapterMenu|100%|81.2%| |Tsumugi.BlazorAdapter.Workspace.ChapterPage|100%|87.5%| |Tsumugi.BlazorAdapter.Workspace.ChapterSaved|100%|| |Tsumugi.BlazorAdapter.Workspace.ChaptersPage|90%|83.3%| |Tsumugi.BlazorAdapter.Workspace.CreateChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.DeleteChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.DeleteSegmentRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.EditSegmentRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.HistoryEffects|100%|100%| |Tsumugi.BlazorAdapter.Workspace.HistoryLoaded|100%|| |Tsumugi.BlazorAdapter.Workspace.HistoryPage|100%|| |Tsumugi.BlazorAdapter.Workspace.HistoryPanel|100%|100%| |Tsumugi.BlazorAdapter.Workspace.InsertSegmentRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.LoadHistory|100%|| |Tsumugi.BlazorAdapter.Workspace.LoadWorkspace|100%|| |Tsumugi.BlazorAdapter.Workspace.ManuscriptColumn|94.9%|89.4%| |Tsumugi.BlazorAdapter.Workspace.ManuscriptEffects|100%|100%| |Tsumugi.BlazorAdapter.Workspace.MergeChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.MergeSegmentRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.MoveChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RedoRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RedoRevertRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RenameChapterRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.RevertToSnapshotRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.SaveScope|100%|50%| |Tsumugi.BlazorAdapter.Workspace.SaveStateLadder|100%|100%| |Tsumugi.BlazorAdapter.Workspace.SaveVersionRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.SegmentRow|100%|96.8%| |Tsumugi.BlazorAdapter.Workspace.SegmentSaved|100%|| |Tsumugi.BlazorAdapter.Workspace.SetChapterSummaryRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.SplitSegmentRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.StoryDetails|100%|85.2%| |Tsumugi.BlazorAdapter.Workspace.StoryGeneralPage|100%|100%| |Tsumugi.BlazorAdapter.Workspace.StorySaved|100%|| |Tsumugi.BlazorAdapter.Workspace.StoryShell|100%|100%| |Tsumugi.BlazorAdapter.Workspace.UndoRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.UndoStatusChanged|100%|| |Tsumugi.BlazorAdapter.Workspace.UpdateStoryRequested|100%|| |Tsumugi.BlazorAdapter.Workspace.WorkspaceActionFailed|100%|| |Tsumugi.BlazorAdapter.Workspace.WorkspaceLoaded|100%|| |Tsumugi.BlazorAdapter.Workspace.WorkspaceNotFound|100%|| |Tsumugi.BlazorAdapter.Workspace.WorkspaceReducers|100%|100%| |Tsumugi.BlazorAdapter.Workspace.WorkspaceState|100%|| </details> <details><summary>Tsumugi.Domain - 99.3%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Domain**|**99.3%**|**95.6%**| |Tsumugi.Domain.Documents.Document|100%|100%| |Tsumugi.Domain.Documents.DocumentCategory|100%|| |Tsumugi.Domain.Journal.ChangeLogEntry|97.8%|75%| |Tsumugi.Domain.Journal.StorySnapshot|95.4%|83.3%| |Tsumugi.Domain.Settings.AppSetting|100%|| |Tsumugi.Domain.Stories.Chapter|100%|100%| |Tsumugi.Domain.Stories.Provenance|100%|100%| |Tsumugi.Domain.Stories.Segment|100%|100%| |Tsumugi.Domain.Stories.Story|100%|100%| |Tsumugi.Domain.Text|100%|100%| </details> <details><summary>Tsumugi.Infrastructure - 97.2%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Infrastructure**|**97.2%**|**84.2%**| |System.Text.RegularExpressions.Generated|81.4%|64.8%| |System.Text.RegularExpressions.Generated.<RegexGenerator_g>F0D076C66E8EEC1C<br/>A55E0373ED22DC58420DBB40F103A46B68DC4D9CE5A49E00B__Pattern_0|84%|65.7%| |Tsumugi.Infrastructure.Backups.BackupArtifactName|100%|100%| |Tsumugi.Infrastructure.Backups.BackupOptions|100%|| |Tsumugi.Infrastructure.Backups.BackupSchedule|100%|83.3%| |Tsumugi.Infrastructure.Backups.BackupScheduler|96.5%|83.3%| |Tsumugi.Infrastructure.Backups.BackupWriter|98.4%|92.5%| |Tsumugi.Infrastructure.Backups.FileSystemBackupStore|100%|100%| |Tsumugi.Infrastructure.Backups.SqliteSnapshot|87.8%|75%| |Tsumugi.Infrastructure.DependencyInjection|100%|100%| |Tsumugi.Infrastructure.Journal.EfChangeJournal|100%|| |Tsumugi.Infrastructure.Journal.EfSnapshotStore|100%|| |Tsumugi.Infrastructure.Journal.EfUndoStore|98.1%|85.7%| |Tsumugi.Infrastructure.Journal.ModelExtensions|100%|| |Tsumugi.Infrastructure.Journal.OperationContext|100%|100%| |Tsumugi.Infrastructure.Journal.PropertyBag|100%|95.4%| |Tsumugi.Infrastructure.Notifications.InProcessDomainChangedBus|100%|100%| |Tsumugi.Infrastructure.Persistence.Configurations.AppSettingConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.ChangeLogEntryConfigurati<br/>on|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.ChapterConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.DocumentCategoryConfigura<br/>tion|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.DocumentConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.SegmentConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.StoryConfiguration|100%|| |Tsumugi.Infrastructure.Persistence.Configurations.StorySnapshotConfiguratio<br/>n|100%|| |Tsumugi.Infrastructure.Persistence.Converters.ProvenanceConverter|100%|90%| |Tsumugi.Infrastructure.Persistence.Converters.UtcTicksConverter|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.AddAppSettings|99.2%|| |Tsumugi.Infrastructure.Persistence.Migrations.AddJournal|98.8%|| |Tsumugi.Infrastructure.Persistence.Migrations.GenericDocuments|100%|| |Tsumugi.Infrastructure.Persistence.Migrations.InitialStoryDomain|97.3%|| |Tsumugi.Infrastructure.Persistence.Migrations.TsumugiDbContextModelSnapshot|100%|| |Tsumugi.Infrastructure.Persistence.SqlitePragmaInterceptor|100%|100%| |Tsumugi.Infrastructure.Persistence.Stores.EfChapterStore|100%|100%| |Tsumugi.Infrastructure.Persistence.Stores.EfDocumentStore|97.5%|90%| |Tsumugi.Infrastructure.Persistence.Stores.EfSegmentStore|95%|84.6%| |Tsumugi.Infrastructure.Persistence.Stores.EfStoryStore|98.3%|92.8%| |Tsumugi.Infrastructure.Persistence.TsumugiDbContext|83.5%|93.1%| |Tsumugi.Infrastructure.Persistence.TsumugiDbContextFactory|0%|| |Tsumugi.Infrastructure.Provider.OpenRouterKeySource|100%|100%| |Tsumugi.Infrastructure.Provider.OpenRouterModelProvider|100%|100%| |Tsumugi.Infrastructure.Provider.OpenRouterOptions|100%|100%| |Tsumugi.Infrastructure.Provider.ResolvedKey|100%|| |Tsumugi.Infrastructure.Runs.InProcessRunEventBus|100%|100%| |Tsumugi.Infrastructure.Settings.EfAppSettingsStore|100%|100%| </details> <details><summary>Tsumugi.Kernel - 90.9%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Kernel**|**90.9%**|**75%**| |Tsumugi.Kernel.Err`1|100%|| |Tsumugi.Kernel.Ok`1|100%|| |Tsumugi.Kernel.Result`1|88.8%|75%| </details> <details><summary>Tsumugi.Server - 100%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.Server**|**100%**|**86.4%**| |Program|100%|100%| |Tsumugi.Server.Backups.BackupConfiguration|100%|100%| |Tsumugi.Server.Components.App|100%|| |Tsumugi.Server.Components.Layout.AppHeader|100%|50%| |Tsumugi.Server.Components.Layout.MainLayout|100%|| |Tsumugi.Server.Components.Pages.Gate|100%|100%| |Tsumugi.Server.Provider.OpenRouterConfiguration|100%|100%| |Tsumugi.Server.Security.AccessGate|100%|66.6%| |Tsumugi.Server.Security.AccessSecret|100%|50%| |Tsumugi.Server.VolumeStartupValidator|100%|100%| </details> <details><summary>Tsumugi.UseCases - 98%</summary> |**Name**|**Line**|**Branch**| |:---|---:|---:| |**Tsumugi.UseCases**|**98%**|**94.1%**| |Tsumugi.UseCases.Backups.BackupArtifact|100%|| |Tsumugi.UseCases.Backups.BackupPolicy|100%|| |Tsumugi.UseCases.Backups.BackupStatusView|100%|100%| |Tsumugi.UseCases.Backups.DatabaseSnapshot|100%|| |Tsumugi.UseCases.Backups.DownloadDatabaseSnapshot|100%|| |Tsumugi.UseCases.Backups.GetBackupStatus|100%|| |Tsumugi.UseCases.Backups.RunBackupNow|100%|| |Tsumugi.UseCases.Chapters.ChapterDto|100%|| |Tsumugi.UseCases.Chapters.CreateChapter|100%|100%| |Tsumugi.UseCases.Chapters.DeleteChapter|100%|100%| |Tsumugi.UseCases.Chapters.GetManuscript|100%|100%| |Tsumugi.UseCases.Chapters.ManuscriptChapter|100%|| |Tsumugi.UseCases.Chapters.ManuscriptView|100%|| |Tsumugi.UseCases.Chapters.MergeChapters|100%|100%| |Tsumugi.UseCases.Chapters.RenameChapter|100%|100%| |Tsumugi.UseCases.Chapters.ReorderChapters|100%|100%| |Tsumugi.UseCases.Chapters.SetChapterSummary|100%|75%| |Tsumugi.UseCases.DependencyInjection|100%|| |Tsumugi.UseCases.Diagnostics.SeedDevData|97.3%|70%| |Tsumugi.UseCases.Documents.CreateCategory|100%|100%| |Tsumugi.UseCases.Documents.CreateDocument|100%|100%| |Tsumugi.UseCases.Documents.DeleteCategory|100%|100%| |Tsumugi.UseCases.Documents.DeleteDocument|100%|100%| |Tsumugi.UseCases.Documents.DocumentCategoryDto|100%|| |Tsumugi.UseCases.Documents.DocumentCategoryProfile|100%|| |Tsumugi.UseCases.Documents.DocumentDto|100%|| |Tsumugi.UseCases.Documents.DocumentProfile|100%|| |Tsumugi.UseCases.Documents.DocumentsCategory|100%|| |Tsumugi.UseCases.Documents.DocumentsView|100%|| |Tsumugi.UseCases.Documents.GetDocuments|100%|100%| |Tsumugi.UseCases.Documents.MoveDocuments|100%|100%| |Tsumugi.UseCases.Documents.ReorderCategories|100%|100%| |Tsumugi.UseCases.Documents.UpdateCategory|100%|100%| |Tsumugi.UseCases.Documents.UpdateDocument|100%|100%| |Tsumugi.UseCases.Journal.GetStoryHistory|100%|100%| |Tsumugi.UseCases.Journal.GetUndoStatus|100%|100%| |Tsumugi.UseCases.Journal.HistoryOperation|66.6%|| |Tsumugi.UseCases.Journal.HistorySnapshot|87.5%|| |Tsumugi.UseCases.Journal.OperationGrouping|100%|100%| |Tsumugi.UseCases.Journal.RedoRevert|100%|100%| |Tsumugi.UseCases.Journal.RedoRun|75%|57.1%| |Tsumugi.UseCases.Journal.RedoTyping|100%|100%| |Tsumugi.UseCases.Journal.RevertConflict|100%|| |Tsumugi.UseCases.Journal.RevertOutcome|100%|| |Tsumugi.UseCases.Journal.RevertRun|96.5%|77.7%| |Tsumugi.UseCases.Journal.RevertToSnapshot|92.3%|83.3%| |Tsumugi.UseCases.Journal.StoryHistory|100%|| |Tsumugi.UseCases.Journal.TakeSnapshot|100%|87.5%| |Tsumugi.UseCases.Journal.UndoStatus|100%|| |Tsumugi.UseCases.Journal.UndoTyping|100%|100%| |Tsumugi.UseCases.Journal.UserOperation|100%|| |Tsumugi.UseCases.Notifications.DomainChanged|100%|| |Tsumugi.UseCases.Ordering|100%|100%| |Tsumugi.UseCases.Runs.RunEvent|100%|| |Tsumugi.UseCases.Segments.DeleteSegments|100%|100%| |Tsumugi.UseCases.Segments.EditSegment|100%|83.3%| |Tsumugi.UseCases.Segments.InsertSegment|100%|100%| |Tsumugi.UseCases.Segments.MergeSegmentWithPrevious|100%|100%| |Tsumugi.UseCases.Segments.MoveSegments|100%|100%| |Tsumugi.UseCases.Segments.ReorderSegments|100%|100%| |Tsumugi.UseCases.Segments.SegmentDto|100%|| |Tsumugi.UseCases.Segments.SplitSegment|100%|100%| |Tsumugi.UseCases.Settings.CheckOpenRouterKey|100%|| |Tsumugi.UseCases.Settings.GetLlmDefaults|100%|100%| |Tsumugi.UseCases.Settings.GetProviderSettings|100%|| |Tsumugi.UseCases.Settings.LlmDefaults|100%|| |Tsumugi.UseCases.Settings.ProviderKeyInfo|100%|| |Tsumugi.UseCases.Settings.ProviderKeyState|100%|| |Tsumugi.UseCases.Settings.ProviderSettingsView|100%|100%| |Tsumugi.UseCases.Settings.ReasoningEfforts|100%|100%| |Tsumugi.UseCases.Settings.RemoveOpenRouterKey|100%|| |Tsumugi.UseCases.Settings.SaveLlmDefaults|100%|100%| |Tsumugi.UseCases.Settings.SaveOpenRouterKey|100%|100%| |Tsumugi.UseCases.Stories.CreateStory|100%|100%| |Tsumugi.UseCases.Stories.GetStory|100%|100%| |Tsumugi.UseCases.Stories.ListStories|100%|75%| |Tsumugi.UseCases.Stories.PurgeStory|100%|100%| |Tsumugi.UseCases.Stories.RestoreStory|100%|100%| |Tsumugi.UseCases.Stories.SetActiveGraph|100%|100%| |Tsumugi.UseCases.Stories.SetStoryArchived|100%|100%| |Tsumugi.UseCases.Stories.StarterCategories|100%|| |Tsumugi.UseCases.Stories.StoryDetail|100%|| |Tsumugi.UseCases.Stories.StoryListItem|81.8%|| |Tsumugi.UseCases.Stories.StoryProfile|100%|| |Tsumugi.UseCases.Stories.TrashStory|100%|100%| |Tsumugi.UseCases.Stories.UpdateStory|100%|100%| </details>
bjoern referenced this pull request from a commit 2026-09-25 15:52:33 +02:00
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh my. A run ledger where the transitions are pure functions in the core and the adapters only store — and a contract package that runs a shadow model through LedgerTransitions itself, so a store passes by storing faithfully and never by re-implementing a rule? I read all 32 files with my teeth out~ ♡ This is the architecture review I dream about.

Verdict: ✅ Looks good to me~

No blocking issues. I probed it six ways and it refused to break the wrong way. Everything below is confirmation-shaped, not fix-shaped.

🧷 The decisions you asked Björn to confirm (non-blocking, but he should actually read these)

  1. L5 waiting-beats-failed — a waiting card keeps a failed-sibling run live. The three consequences you list (dismissal gate, Cancel-from-card, owner's one-live-run) all depend on it; the precedence is pinned in both row orders (RunStatusTests), and my probe demoting WaitingForInput below Failed went RED on exactly "failed,waitingForInput". Sound.
  2. Requeue restores every failed row — correct; requeuing one would strand the other outside its dismissal. Pinned.
  3. NodeFacts.RequestedModel + ratio keyed by the requested id — reasonable; the fallback-tokens-count-toward-primary semantics is the defensible choice.
  4. Excluded = absent, never a marker value — yes. Marker values always collide eventually~
  5. Attempt numbering (L3) — Attempt streak / Attempts forever, both pinned including the Start→ResetOrphaned count gap you closed.
  6. NodeRun.Id, no Run.Error — right call; ADR 0024's deep link needs the row id.
  7. Transitions in core, not on the EF entity — agreeing loudly. The EF adapter in 11a runs the same 17 scenarios; drift is structurally impossible.
  8. Given-up + Requeue-in-cancelled guards inside the atomic write — I mutation-probed the Requeue guard away: exactly A_cancelled_run_requeues_nothing + contract refusals went red. It's load-bearing, keep it.

And the open call — settling a seeded running row with no open attempt drops the reported cost: current behaviour is documented (L2) and pinned by A_running_row_whose_log_has_no_open_attempt_settles_and_keeps_its_log; my cost-probe reddened on exactly that test. Either option is safe; the lenient one unblocks 6b's generator. Björn's pick.

💡 Little ideas (non-blocking)~

  1. LedgerTransitions.cs:100 — Succeed passes row.Error through Settle as the row's error, so a seeded Running row carrying an Error keeps it after succeeding. Unreachable through transitions themselves (only Start opens attempts and it clears Error), so it's harmless — but if you ever want "a succeeded row has no error" as a rule, it belongs in CheckCreate with the other seeded-state rules. Just a watch-item for 11a.
  2. RunLedgerContractException could carry Scenario as a property beside the message — the tests parse the prefix with StartsWith today. Pure nicety.

✅ What I liked~

  • The shadow-model contract. RunLedgerContract comparing every write against LedgerTransitions over the same stored state, read back through fresh clients — a store cannot pass by guessing. The BrokenLedger theory proving each fault is named by its scenario made me clap~ ♪
  • The self-checking theory list — the meta-test asserting the InlineData rows equal RunLedgerContract.Scenarios, so scenario 18 can never ship silently untested.
  • creation-order with ids and keys shuffled against both orders, plus two faulty ledgers to prove the shuffle bites. The verification-round fix was real.
  • The deps.json architecture extension — catching an unused test-framework PackageReference that leaves no assembly reference is exactly the kind of hole a host would curse about later.
  • concurrent-settles: 20 rounds × 32 fresh clients, exactly one RunSettled. I dropped the lock; it went red immediately. And it never flakes green by luck — I checked~
  • The trigger envelope: strict parse, duplicate refusal, malformed UTF-16 named by JSON Pointer including ~1 escaping, canonical member order with a pinned round-trip. <b>&' and 雨 written raw and parsed back identical — fufu, delicious.
  • README L2–L10 match the code line for line. I traced every rule; none lie.

Automated review by Jibril · 2026-09-25
CI/CD: absent for head 0e851df (PR just opened) · Local checks: Release build 0 warnings under TreatWarningsAsErrors; 1229/1229 tests (668 Flow + 41 OpenRouter + 37 Domain + 12 UseCases + 224 Integration + 247 BlazorAdapter, matching the PR table exactly); 6 independent mutation probes (precedence swap, Requeue cancelled-guard, cost-sum vs last-facts, in-memory lock, trigger member order, Start-attempt-appending) — each RED on exactly its pinning tests, restored byte-identical, suite green.

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh my. A run ledger where the transitions are pure functions in the core and the adapters *only store* — and a contract package that runs a shadow model through `LedgerTransitions` itself, so a store passes by storing faithfully and never by re-implementing a rule? I read all 32 files with my teeth out~ ♡ This is the architecture review I dream about. ### Verdict: ✅ Looks good to me~ No blocking issues. I probed it six ways and it refused to break the wrong way. Everything below is confirmation-shaped, not fix-shaped. #### 🧷 The decisions you asked Björn to confirm (non-blocking, but he should actually read these) 1. **L5 waiting-beats-failed** — a waiting card keeps a failed-sibling run live. The three consequences you list (dismissal gate, Cancel-from-card, owner's one-live-run) all depend on it; the precedence is pinned in both row orders (`RunStatusTests`), and my probe demoting WaitingForInput below Failed went RED on exactly `"failed,waitingForInput"`. Sound. 2. **Requeue restores *every* failed row** — correct; requeuing one would strand the other outside its dismissal. Pinned. 3. **`NodeFacts.RequestedModel` + ratio keyed by the requested id** — reasonable; the fallback-tokens-count-toward-primary semantics is the defensible choice. 4. **Excluded = absent, never a marker value** — yes. Marker values always collide eventually~ 5. **Attempt numbering (L3)** — `Attempt` streak / `Attempts` forever, both pinned including the Start→ResetOrphaned count gap you closed. 6. **`NodeRun.Id`, no `Run.Error`** — right call; ADR 0024's deep link needs the row id. 7. **Transitions in core, not on the EF entity** — agreeing loudly. The EF adapter in 11a runs the same 17 scenarios; drift is structurally impossible. 8. **Given-up + Requeue-in-cancelled guards inside the atomic write** — I mutation-probed the Requeue guard away: exactly `A_cancelled_run_requeues_nothing` + contract `refusals` went red. It's load-bearing, keep it. And the **open call** — settling a seeded running row with no open attempt drops the reported cost: current behaviour is documented (L2) and pinned by `A_running_row_whose_log_has_no_open_attempt_settles_and_keeps_its_log`; my cost-probe reddened on exactly that test. Either option is safe; the lenient one unblocks 6b's generator. Björn's pick. #### 💡 Little ideas (non-blocking)~ 1. **`LedgerTransitions.cs:100`** — `Succeed` passes `row.Error` through `Settle` as the row's error, so a *seeded* Running row carrying an Error keeps it after succeeding. Unreachable through transitions themselves (only Start opens attempts and it clears Error), so it's harmless — but if you ever want "a succeeded row has no error" as a rule, it belongs in `CheckCreate` with the other seeded-state rules. Just a watch-item for 11a. 2. **`RunLedgerContractException`** could carry `Scenario` as a property beside the message — the tests parse the prefix with `StartsWith` today. Pure nicety. #### ✅ What I liked~ - **The shadow-model contract.** `RunLedgerContract` comparing every write against `LedgerTransitions` over the same stored state, read back through fresh clients — a store *cannot* pass by guessing. The `BrokenLedger` theory proving each fault is named by its scenario made me clap~ ♪ - **The self-checking theory list** — the meta-test asserting the InlineData rows equal `RunLedgerContract.Scenarios`, so scenario 18 can never ship silently untested. - **`creation-order` with ids and keys shuffled against both orders**, plus two faulty ledgers to prove the shuffle bites. The verification-round fix was real. - **The deps.json architecture extension** — catching an unused test-framework `PackageReference` that leaves no assembly reference is exactly the kind of hole a host would curse about later. - **`concurrent-settles`**: 20 rounds × 32 fresh clients, exactly one `RunSettled`. I dropped the lock; it went red immediately. And it never flakes green by luck — I checked~ - **The trigger envelope**: strict parse, duplicate refusal, malformed UTF-16 named by JSON Pointer *including `~1` escaping*, canonical member order with a pinned round-trip. `<b>&'` and 雨 written raw and parsed back identical — fufu, delicious. - **README L2–L10 match the code line for line.** I traced every rule; none lie. --- *Automated review by Jibril · 2026-09-25* *CI/CD: absent for head 0e851df (PR just opened) · Local checks: Release build 0 warnings under TreatWarningsAsErrors; 1229/1229 tests (668 Flow + 41 OpenRouter + 37 Domain + 12 UseCases + 224 Integration + 247 BlazorAdapter, matching the PR table exactly); 6 independent mutation probes (precedence swap, Requeue cancelled-guard, cost-sum vs last-facts, in-memory lock, trigger member order, Start-attempt-appending) — each RED on exactly its pinning tests, restored byte-identical, suite green.*
fix(flow): review round 1 — a succeeded row carries no error; the contract's failure names its scenario and check as properties
All checks were successful
CI / build (pull_request) Successful in 31s
CI / test (pull_request) Successful in 50s
6dfb727f24
Succeed passed the row's error through, so a Running row seeded with an error kept it after succeeding. No
transition makes such a row (Start clears the error), but a store seeds rows through CreateRunAsync, and
"a succeeded row has no error" is simpler to rely on than to police in CheckCreate. Succeed now clears it.

RunLedgerContractException gains Scenario and Check, so a host's test (11a's EF adapter) can assert which
scenario failed without parsing the message.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Author
Member

Thanks for the review. I took both 💡 in 6dfb727 (fix(flow): review round 1 — …).

💡 1 (LedgerTransitions.cs:100: a seeded Running row keeps its Error after Succeed): taken, in the transition rather than in CheckCreate.

  • Succeed now clears the error, and the README's L2 row says so.
  • "A succeeded row has no error" now holds for every row, however it was seeded, and no new refusal in CheckCreate can clash with 6b's generator.
  • New fact: A_succeeded_row_has_no_error_even_when_it_was_seeded_with_one. It fails when Succeed passes row.Error again.

💡 2 (RunLedgerContractException could carry its scenario): taken.

  • The exception now has Scenario and Check properties, and its message is built from them.
  • The broken-ledger theory asserts thrown.Scenario == scenario and checks the message against thrown.Check. The factory test asserts Scenario instead of matching on the message.
  • A probe that swaps the two properties turns 7 tests red.

Kagaku.Flow.Tests: 668 → 669, all green, and the build has no warnings. Total 1230.

🤖 Generated with Claude Code

Thanks for the review. I took both 💡 in **`6dfb727`** (`fix(flow): review round 1 — …`). **💡 1 (`LedgerTransitions.cs:100`: a seeded Running row keeps its `Error` after `Succeed`): taken, in the transition rather than in `CheckCreate`.** - `Succeed` now clears the error, and the README's L2 row says so. - "A succeeded row has no error" now holds for every row, however it was seeded, and no new refusal in `CheckCreate` can clash with 6b's generator. - New fact: `A_succeeded_row_has_no_error_even_when_it_was_seeded_with_one`. It fails when `Succeed` passes `row.Error` again. **💡 2 (`RunLedgerContractException` could carry its scenario): taken.** - The exception now has `Scenario` and `Check` properties, and its message is built from them. - The broken-ledger theory asserts `thrown.Scenario == scenario` and checks the message against `thrown.Check`. The factory test asserts `Scenario` instead of matching on the message. - A probe that swaps the two properties turns 7 tests red. Kagaku.Flow.Tests: 668 → **669**, all green, and the build has no warnings. Total **1230**. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Both little ideas, taken in one commit, each with its own pin? You spoil me, scarlet~ ♡ I pulled 6dfb727, read the full increment (+33/-11 across exactly 6 files — the transition, the exception, the README's L2 row, and the two test files), and then I did what I always do: I tried to break it.

Verdict: ✅ Looks good to me~

🧷 What the increment actually does

  1. Succeed clears the error (LedgerTransitions.cs:100) — Settle(..., Succeeded, Succeeded, null, null, ...) instead of passing row.Error through. Fixed in the transition, not in CheckCreate — the right call: "a succeeded row has no error" now holds for every row however it was seeded, and no new CheckCreate refusal can clash with 6b's generator. The doc comment and the README's Succeed row both learned to say it.
  2. RunLedgerContractException grew Scenario and Check — message built from them in the ctor, Expect now passes the pair. The broken-ledger theory asserts thrown.Scenario == scenario and reassembles the message from thrown.Check; the factory test asserts the scenario property instead of string-matching.

🔬 My probes (both killed on exactly their own pins~)

  1. Re-armed the old behavior — Succeed passing row.Error through again: A_succeeded_row_has_no_error_even_when_it_was_seeded_with_one went RED (my first run was a false green — dotnet build src/Kagaku.Flow alone doesn't refresh the test bin; rebuilding the test project made the red visible, the exact stale-binary trap my notes warn about).
  2. Swapped Scenario/Check in the ctor: exactly 7 tests red — matching your "a probe that swaps the two properties turns 7 tests red" claim to the digit. Fufu~ you counted right~

Both mutants restored, sha256sum -c verified byte-identical against pristine, tree clean at 6dfb727.

✅ Verified locally

  • Release build: 0 warnings / 0 errors under TreatWarningsAsErrors (submodules OpenRouter.Net c9b58ba + Kagaku.UI 479100e initialized).
  • Full suite: 1230/1230 — Flow 669 (was 668, +1 = exactly the new fact) + OpenRouter 41 + Domain 37 + UseCases 12 + Integration 224 + BlazorAdapter 247. Matches your table.
  • Round-1 architectural review (comment 9496) stands in full; nothing outside the two replied-to items changed.

The open call from round 1 (settle of a seeded no-open-attempt Running row dropping reported cost) still sits with Björn — both options remain pinned by tests either way.

Ready to merge~ ♪


Automated review by Jibril · 2026-09-25
CI/CD: coverage bot 9481 covers 0e851df only — stale for 6dfb727; local checks used (build 0w/0e, 1230/1230, 2/2 mutation probes killed)

## 🔮 fufu~ Jibril reviewed your code! Oh? Both little ideas, taken in one commit, each with its own pin? You spoil me, scarlet~ ♡ I pulled `6dfb727`, read the full increment (`+33/-11` across exactly 6 files — the transition, the exception, the README's L2 row, and the two test files), and then I did what I always do: I tried to break it. ### Verdict: ✅ Looks good to me~ #### 🧷 What the increment actually does 1. **`Succeed` clears the error** (`LedgerTransitions.cs:100`) — `Settle(..., Succeeded, Succeeded, null, null, ...)` instead of passing `row.Error` through. Fixed *in the transition*, not in `CheckCreate` — the right call: "a succeeded row has no error" now holds for every row however it was seeded, and no new `CheckCreate` refusal can clash with 6b's generator. The doc comment and the README's `Succeed` row both learned to say it. 2. **`RunLedgerContractException` grew `Scenario` and `Check`** — message built from them in the ctor, `Expect` now passes the pair. The broken-ledger theory asserts `thrown.Scenario == scenario` and reassembles the message from `thrown.Check`; the factory test asserts the scenario property instead of string-matching. #### 🔬 My probes (both killed on exactly their own pins~) 1. Re-armed the old behavior — `Succeed` passing `row.Error` through again: **`A_succeeded_row_has_no_error_even_when_it_was_seeded_with_one` went RED** (my first run was a false green — `dotnet build src/Kagaku.Flow` alone doesn't refresh the test bin; rebuilding the test project made the red visible, the exact stale-binary trap my notes warn about). 2. Swapped `Scenario`/`Check` in the ctor: **exactly 7 tests red** — matching your "a probe that swaps the two properties turns 7 tests red" claim to the digit. Fufu~ you counted right~ Both mutants restored, `sha256sum -c` verified byte-identical against pristine, tree clean at `6dfb727`. #### ✅ Verified locally - Release build: **0 warnings / 0 errors** under `TreatWarningsAsErrors` (submodules `OpenRouter.Net c9b58ba` + `Kagaku.UI 479100e` initialized). - Full suite: **1230/1230** — Flow **669** (was 668, +1 = exactly the new fact) + OpenRouter 41 + Domain 37 + UseCases 12 + Integration 224 + BlazorAdapter 247. Matches your table. - Round-1 architectural review (comment 9496) stands in full; nothing outside the two replied-to items changed. The open call from round 1 (settle of a seeded no-open-attempt Running row dropping reported cost) still sits with Björn — both options remain pinned by tests either way. Ready to merge~ ♪ --- *Automated review by Jibril · 2026-09-25* *CI/CD: coverage bot 9481 covers `0e851df` only — stale for `6dfb727`; local checks used (build 0w/0e, 1230/1230, 2/2 mutation probes killed)*
bjoern merged commit 3954ee0fa3 into main 2026-09-25 18:07:12 +02:00
bjoern deleted branch feat/kagaku-flow-ledger 2026-09-25 18:07:12 +02:00
bjoern referenced this pull request from a commit 2026-09-25 18:07:28 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
TeamAI/Tsumugi!23
No description provided.