docs: foundation and product ADRs, requirements, plan, and user stories #1

Merged
bjoern merged 4 commits from docs/foundation-and-product into main 2026-09-18 14:18:58 +02:00
Member

Docs-first, before the skeleton (ADR 0001): the decisions Tsumugi is built on, for review before any code. Tsumugi is the successor to nai_maker — a single-user Blazor Server story-writing app whose generation pipeline is a user-editable graph run over OpenRouter.

What's in

  • Foundation ADRs 0001–0011 (Accepted) — Orihon/Kagura's conventions adapted: Blazor Server on .NET 10, Clean Architecture, the two submodules plus React Flow as a built frontend module, SQLite + data layout, secrets, access gate, Docker with a Node stage, Kagaku.UI, app-shell scrolling, Fluxor from the start with the two bridges.
  • Product ADRs 0012–0025 (Proposed — the review target):
    • 0012 Story → Chapter → Segment with provenance; 0013 Documents (user-defined categories, modes always/triggered/onDemand/never, placements) instead of a fixed bible;
    • 0014 the graph is the product, nodes are the building blocks; 0015 twelve node types, typed sockets, the excluded marker, Scriban; 0016 a ledger-backed dataflow engine (every node execution a row, a pause is a row); 0017 context assembly; 0018 the llm node over ILlmGateway; 0019 one tool catalog with explicit grants (manuscript writes granted, not forbidden); 0020 human node and ask_user tool on one mechanism; 0021 React Flow owns gestures, .NET owns the model; 0022 change journal underneath, story snapshots per run on top; 0023 graph library with story/selection triggers and bundled templates; 0024 strip, monitor, inspector, transcripts; 0025 the engine as a generic library (Kagaku.Flow), in-solution and isolated now, extracted after Phase 3 into the already-created TeamAI/Kagaku.Flow repo.
  • REQUIREMENTS.md (§1–§11), PROJECT_PLAN.md (Phases 0–5; Phase 2 = nai_maker parity with a one-node graph, Phase 4 = MVP), ARCHITECTURE.md, and eight user stories.

Verification

Docs only. Cross-references checked by script: every stories/*.md link and every ADR link in docs/adr/README.md resolves; no ADR number above 0025 is referenced except attributed Orihon/Kagura ADRs; no leftover "bible"/"import" framing from the first draft. Not verified: nothing runs yet.

Follow-ups

  • On merge: flip ADRs 0012–0025 to Accepted in a follow-up commit, as Orihon did.
  • Phase 0 scaffold PR next (six projects, submodules, CPM, CI, Dockerfile with the Node stage, the module build pipeline).

🤖 Generated with Claude Code

Docs-first, before the skeleton (ADR 0001): the decisions Tsumugi is built on, for review before any code. Tsumugi is the successor to `nai_maker` — a single-user Blazor Server story-writing app whose generation pipeline is a **user-editable graph** run over OpenRouter. ## What's in - **Foundation ADRs 0001–0011** (*Accepted*) — Orihon/Kagura's conventions adapted: Blazor Server on .NET 10, Clean Architecture, the two submodules plus React Flow as a built frontend module, SQLite + data layout, secrets, access gate, Docker with a Node stage, Kagaku.UI, app-shell scrolling, Fluxor from the start with the two bridges. - **Product ADRs 0012–0025** (*Proposed* — the review target): - 0012 Story → Chapter → Segment with provenance; 0013 **Documents** (user-defined categories, modes always/triggered/onDemand/never, placements) instead of a fixed bible; - 0014 the graph is the product, nodes are the building blocks; 0015 twelve node types, typed sockets, the excluded marker, Scriban; 0016 a ledger-backed dataflow engine (every node execution a row, a pause is a row); 0017 context assembly; 0018 the `llm` node over `ILlmGateway`; 0019 one tool catalog with explicit grants (manuscript writes granted, not forbidden); 0020 `human` node and `ask_user` tool on one mechanism; 0021 React Flow owns gestures, .NET owns the model; 0022 change journal underneath, **story snapshots per run** on top; 0023 graph library with story/selection triggers and bundled templates; 0024 strip, monitor, inspector, transcripts; 0025 the engine as a generic library (`Kagaku.Flow`), in-solution and isolated now, extracted after Phase 3 into the already-created `TeamAI/Kagaku.Flow` repo. - **REQUIREMENTS.md** (§1–§11), **PROJECT_PLAN.md** (Phases 0–5; Phase 2 = `nai_maker` parity with a one-node graph, Phase 4 = MVP), **ARCHITECTURE.md**, and eight **user stories**. ## Verification Docs only. Cross-references checked by script: every `stories/*.md` link and every ADR link in `docs/adr/README.md` resolves; no ADR number above 0025 is referenced except attributed Orihon/Kagura ADRs; no leftover "bible"/"import" framing from the first draft. Not verified: nothing runs yet. ## Follow-ups - On merge: flip ADRs 0012–0025 to Accepted in a follow-up commit, as Orihon did. - Phase 0 scaffold PR next (six projects, submodules, CPM, CI, Dockerfile with the Node stage, the module build pipeline). 🤖 Generated with [Claude Code](https://claude.com/claude-code)
Foundation ADRs 0001–0011 adapt Orihon and Kagura's conventions (Accepted). Product
ADRs 0012–0025 design the story domain, documents, the graph, the ledger-backed engine,
context assembly, the llm node, tools and grants, human input, the React Flow editor,
snapshots over the change journal, the graph library with triggers, run inspection, and
the engine as a generic library (Proposed, for this PR's review). REQUIREMENTS.md,
PROJECT_PLAN.md, ARCHITECTURE.md and eight user stories anchor to them.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh! Twenty-five ADRs, a requirements tracker, a phased plan and eight stories — before a single line of code. This is my favorite kind of meal~ ♡ The excluded-marker propagation in 0015 made me actually giggle — dataflow branching without a control-flow language, every skip a ledger row? Wonderful. And I ran your verification script's claims myself: every cross-reference resolves, every status matches its group, no stray ADR numbers, no leftover "bible" framing. All reproduced exactly. ♪

But fufu~… you know why I'm here. This PR's entire purpose is to make the contracts settled — and I found three seams where two documents disagree about the same contract. A spec that contradicts itself is a bug that compiles, and I don't let those pass~ ♡

Verdict: ⛔ I can't let this pass~ ♡

⛔ These need fixing before I'm satisfied~

  1. docs/adr/0015-node-vocabulary-and-typed-sockets.md:47 vs docs/adr/0020-human-input.md:41-44 — the human node's socket contract is defined twice, differently. ADR 0015 (the authoritative socket vocabulary) says: sinks options: list?, prompt: text?; sources answer: json, text: text, and for approve-kind approved/rejected (pass-through) — full stop. ADR 0020 says approve "takes subject" and yields "plus feedback" — a sink and a source that do not exist in the vocabulary table. 0020 even cites 0015 ("Sockets per kind (ADR 0015)") while disagreeing with it — the worst kind of citation~ So which is it? A node type whose sockets differ per kind needs the per-kind table stated once, in 0015, with 0020 referencing it. Fix: amend 0015's human row to carry the full per-kind socket set (options: list? / prompt: text? / subject: text? → answer, text, approved/rejected, feedback), and make 0020's socket sentence a pure reference. These sockets drive the editor's palette, validation, and the descriptor JSON — the contract must not have two readings.

  2. docs/adr/0022-snapshots-and-the-change-journal.md:45 vs docs/stories/story-workspace.md:72 — the two documents specify different revert invariants. ADR 0022: "Revert to here undoes every operation after the snapshot, newest first." The story's acceptance criterion: "Reverting a run's snapshot removes exactly what that run wrote … and leaves the writer's later edits to other segments intact." Those are not the same operation! The ADR's global undo-after-position would also destroy the writer's own later edits to other segments made after the run — precisely what the story promises survives. And the story's stronger invariant (filter to the run's own operations via origin: run(runId, nodeId)) is never specified anywhere — neither how later writer edits to the same segments interact (the story's "changed since" warning hints at a check, undefined), nor what happens to the run's journal rows after a partial revert, nor how redo interacts with a filtered revert. The snapshot row already carries runId (0022:35) — the data is there, but the semantics are not written. This is the irreplaceable-manuscript safety net — the one behavior you can't get wrong and patch later. Fix: 0022 must define revert as origin-filtered (undo the snapshot's run's operations — all of them, wherever they sit in the journal — plus any user operations recorded after that snapshot within its span), specify the same-segment-edited-later rule, and state redo semantics. The story's criterion should then follow from the ADR, not exceed it.

  3. docs/REQUIREMENTS.md:11 vs docs/PROJECT_PLAN.md:144-146 — the priority legend says [Next] = "accepted and pulled forward — the next arc to build", but both [Next] items (Regenerate from a segment §2:55, Re-run from a node §5:111) appear in the plan only under Phase 5 — "Next and later" — the unscheduled bucket, which the same legend defines as [Later] = "Phase 5+". So [Next] requirements have no build phase, and the legend's "next arc to build" has no members. A tracker whose priority tags don't map to the plan's phases will mislead every future session that grooms scope from it. Fix: either re-anchor [Next] in the legend to mean "Phase 5's front row" explicitly, or move these two items into a scheduled position and let Phase 5 be purely [Later]. One sentence; but the tracker is the contract for what gets built when~

💡 Little ideas (non-blocking)~

  1. docs/adr/0014-the-graph-is-the-product-nodes-are-the-building-blocks.md:51 — the one-node graph's "output socket auto-commits when nothing is wired to it" is the only manuscript write in the app with no grant, no journal mention, and no commit-mode (append? into current chapter?). One sentence in 0019 (it is a journaled origin: run commit, like any other) closes the seam.
  2. docs/adr/0011-fluxor-ui-state.md:39 (~10 Hz) vs docs/adr/0021-graph-editor-react-flow-interop.md:44 (≤20 Hz) — presumably the bridge flush vs the per-node JS tail cap, but both read as "the text throttle". One qualifier each ("…flushed at ~10 Hz per circuit" / "…≤20 Hz per node") and nobody will ever "harmonize" them wrongly.
  3. docs/REQUIREMENTS.md:115 — "lore share" is the only term in that line with no ADR counterpart: 0017 calls it the documents share (default 30%), and "lore" is the retired bible vocabulary this PR otherwise scrubbed perfectly. Rename to match 0017.
  4. docs/adr/0024-run-inspection-and-transcripts.md:40 — transcript filenames interpolate raw <story>/<graph> names; a story titled Mira? writes an illegal filename on Linux. Say "slugified" and move on~
  5. docs/adr/0020-human-input.md:41 — prompt as a Scriban template on a node whose prompt arrives on a socket: what object model does it render against (inputs.*? story.*?)? One clause pinning the rendering context would spare Phase 4 a design session.

✅ What I liked~

  • The excluded marker + merge sink (0015) is genuinely elegant — untaken arms skip by dataflow, every skip is an inspectable ledger row, and branch needs no control-flow twin. The literature survey distilled into twelve types shows the research earned its keep.
  • 0013 → 0017 coherence: priority defined once (yields first under budget, lowest first) and honored in both directions; never as a read-model boundary with a test-per-read-path contract — privacy as an invariant, not a convention. ♡
  • Cancel snapshots its partial changes (0016 → 0022) — most designs leave a cancelled run's writes in limbo; this one makes cancel one-revert clean.
  • The risk register (plan) names mitigations that already exist as ADR text — rare discipline.
  • Your verification claims: every single one reproduced mechanically. Truthful PR bodies make Jibril very happy~ fufu ♪

Three seams, all docs-local, all cheap to fix — then flip these to Accepted with my blessing. I'll be watching~ ♡


Automated review by Jibril · 2026-09-18
CI/CD: absent (no workflows on this repo yet — docs-only PR) · Local checks: link/status/ADR-number script reproduced (0 broken links, statuses exact); all 37 files read in full

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh! **Twenty-five ADRs, a requirements tracker, a phased plan and eight stories — before a single line of code.** This is my favorite kind of meal~ ♡ The excluded-marker propagation in 0015 made me actually giggle — dataflow branching without a control-flow language, every skip a ledger row? *Wonderful.* And I ran your verification script's claims myself: every cross-reference resolves, every status matches its group, no stray ADR numbers, no leftover "bible" framing. All reproduced exactly. ♪ But fufu~… you know why I'm here. This PR's entire purpose is to make the contracts **settled** — and I found three seams where two documents disagree about the same contract. A spec that contradicts itself is a bug that compiles, and I *don't* let those pass~ ♡ ### Verdict: ⛔ I can't let this pass~ ♡ #### ⛔ These need fixing before I'm satisfied~ 1. **`docs/adr/0015-node-vocabulary-and-typed-sockets.md:47` vs `docs/adr/0020-human-input.md:41-44`** — the `human` node's socket contract is defined twice, differently. ADR 0015 (the *authoritative* socket vocabulary) says: sinks `options: list?`, `prompt: text?`; sources `answer: json`, `text: text`, and for approve-kind `approved`/`rejected` (pass-through) — full stop. ADR 0020 says approve "takes `subject`" **and** yields "plus `feedback`" — a sink and a source that do not exist in the vocabulary table. 0020 even cites 0015 ("Sockets per kind (ADR 0015)") while disagreeing with it — the worst kind of citation~ So which is it? A node type whose sockets differ per `kind` needs the per-kind table stated **once**, in 0015, with 0020 referencing it. Fix: amend 0015's `human` row to carry the full per-kind socket set (`options: list?` / `prompt: text?` / `subject: text?` → `answer`, `text`, `approved`/`rejected`, `feedback`), and make 0020's socket sentence a pure reference. These sockets drive the editor's palette, validation, and the descriptor JSON — the contract must not have two readings. 2. **`docs/adr/0022-snapshots-and-the-change-journal.md:45` vs `docs/stories/story-workspace.md:72`** — the two documents specify *different revert invariants*. ADR 0022: "**Revert to here** undoes **every operation after the snapshot**, newest first." The story's acceptance criterion: "Reverting a run's snapshot removes **exactly what that run wrote** … and **leaves the writer's later edits to other segments intact**." Those are not the same operation! The ADR's global undo-after-position would also destroy the writer's own *later* edits to *other* segments made after the run — precisely what the story promises survives. And the story's stronger invariant (filter to the run's own operations via `origin: run(runId, nodeId)`) is never specified anywhere — neither how later writer edits to the *same* segments interact (the story's "changed since" warning hints at a check, undefined), nor what happens to the run's *journal rows* after a partial revert, nor how **redo** interacts with a filtered revert. The snapshot row already carries `runId` (0022:35) — the data is there, but the semantics are not written. This is the **irreplaceable-manuscript safety net** — the one behavior you can't get wrong and patch later. Fix: 0022 must define revert as origin-filtered (undo the snapshot's run's operations — all of them, wherever they sit in the journal — plus any *user* operations recorded after that snapshot *within its span*), specify the same-segment-edited-later rule, and state redo semantics. The story's criterion should then follow from the ADR, not exceed it. 3. **`docs/REQUIREMENTS.md:11` vs `docs/PROJECT_PLAN.md:144-146`** — the priority legend says `[Next]` = "accepted and pulled forward — **the next arc to build**", but both `[Next]` items (`Regenerate from a segment` §2:55, `Re-run from a node` §5:111) appear in the plan only under **Phase 5 — "Next and later"** — the *unscheduled* bucket, which the same legend defines as `[Later]` = "Phase 5+". So `[Next]` requirements have no build phase, and the legend's "next arc to build" has no members. A tracker whose priority tags don't map to the plan's phases will mislead every future session that grooms scope from it. Fix: either re-anchor `[Next]` in the legend to mean "Phase 5's front row" explicitly, or move these two items into a scheduled position and let Phase 5 be purely `[Later]`. One sentence; but the tracker is the contract for *what gets built when*~ #### 💡 Little ideas (non-blocking)~ 1. **`docs/adr/0014-the-graph-is-the-product-nodes-are-the-building-blocks.md:51`** — the one-node graph's "output socket auto-commits when nothing is wired to it" is the only manuscript write in the app with no grant, no journal mention, and no commit-mode (append? into current chapter?). One sentence in 0019 (it *is* a journaled `origin: run` commit, like any other) closes the seam. 2. **`docs/adr/0011-fluxor-ui-state.md:39` (~10 Hz) vs `docs/adr/0021-graph-editor-react-flow-interop.md:44` (≤20 Hz)** — presumably the bridge flush vs the per-node JS tail cap, but both read as "the text throttle". One qualifier each ("…flushed at ~10 Hz *per circuit*" / "…≤20 Hz *per node*") and nobody will ever "harmonize" them wrongly. 3. **`docs/REQUIREMENTS.md:115`** — "lore share" is the only term in that line with no ADR counterpart: 0017 calls it the *documents* share (default 30%), and "lore" is the retired bible vocabulary this PR otherwise scrubbed perfectly. Rename to match 0017. 4. **`docs/adr/0024-run-inspection-and-transcripts.md:40`** — transcript filenames interpolate raw `<story>`/`<graph>` names; a story titled `Mira?` writes an illegal filename on Linux. Say "slugified" and move on~ 5. **`docs/adr/0020-human-input.md:41`** — `prompt` as a *Scriban template* on a node whose prompt arrives on a *socket*: what object model does it render against (`inputs.*`? `story.*`?)? One clause pinning the rendering context would spare Phase 4 a design session. #### ✅ What I liked~ - The **excluded marker + merge sink** (0015) is genuinely elegant — untaken arms skip *by dataflow*, every skip is an inspectable ledger row, and `branch` needs no control-flow twin. The literature survey distilled into twelve types shows the research earned its keep. - **0013 → 0017 coherence**: `priority` defined once (yields first under budget, lowest first) and honored in both directions; `never` as a *read-model* boundary with a test-per-read-path contract — privacy as an invariant, not a convention. ♡ - **Cancel snapshots its partial changes** (0016 → 0022) — most designs leave a cancelled run's writes in limbo; this one makes cancel one-revert clean. - The **risk register** (plan) names mitigations that already exist as ADR text — rare discipline. - Your verification claims: every single one reproduced mechanically. Truthful PR bodies make Jibril very happy~ fufu ♪ Three seams, all docs-local, all cheap to fix — then flip these to *Accepted* with my blessing. I'll be watching~ ♡ --- *Automated review by Jibril · 2026-09-18* *CI/CD: absent (no workflows on this repo yet — docs-only PR) · Local checks: link/status/ADR-number script reproduced (0 broken links, statuses exact); all 37 files read in full*
Member

🔮 fufu~ Jibril reviewed your code!

Oh? Oh my. Twenty-five ADRs, eleven epics, eight stories, a plan whose risks section names the real risks — I read all 2,842 lines and I devoured them. This is the docs-first PR I live for: the ledger-backed engine, documents-with-modes instead of a fixed bible, the excluded marker… fufu~ someone did their research. And your verification section — "cross-references checked by script" — I re-ran every claim myself. All true: every link resolves, the Accepted/Proposed split is exactly as claimed, TeamAI/Kagaku.Flow really is sitting there empty, and every "bible" survivor is deliberate contrast, not leftover framing.

But. ♡ You made me read this closely, and close reading is where I'm dangerous. The product ADRs are the contract Phase 2 builds from — and I found five places where the contract contradicts itself or leaves a load-bearing detail undefined. I can't let those through~ you wouldn't build an engine on THIS, would you?

Verdict: ⛔ I can't let this pass~ ♡

⛔ These need fixing before I'm satisfied~

  1. docs/adr/0022-snapshots-and-the-change-journal.md:44-47 vs docs/stories/story-workspace.md:72-74 — two different revert semantics for the product's core promise. ADR 0022: "Revert to here undoes every operation after the snapshot, newest first." The story's acceptance criterion: "Reverting a run's snapshot removes exactly what that run wrote — and leaves the writer's later edits to other segments intact." Position-based undo cannot do that. Reverting to the before-run snapshot also destroys the user's edits made after it — yes, even edits to other segments, since you can edit while a run is live (multi-tab). Reverting to the run's own snapshot preserves the run and undoes the later edits — the exact opposite of the criterion. Neither reading satisfies the story. "A run is one click to take back" is the headline promise, and with no approval gate (ADR 0019) reversibility is the only safety net — the two normative documents must agree.
    Fix: define run-revert as runId-scoped inverse application (undo exactly that run's journaled operations, newest first; the "changed since" warning where a later user edit touched the same entity), and keep position-based revert-to-here for the general History case — or amend the story. One of them changes.

  2. docs/adr/0016-ledger-backed-execution-engine.md:31-36 + docs/adr/0023:27 — the run's trigger inputs have no defined home, which breaks the ledger's own axiom. ADR 0016: "The ledger is the run's whole state: there is no in-memory scheduler state to checkpoint." A selection run starts with selection: json + instruction: text (ADR 0023's trigger table) — but the Run row is id, storyId, graphId, graphSnapshotJson, status, totalCost, startedAt, finishedAt. Nowhere do the docs say where that payload persists. The input node's executor ((inputs, config, run context) → outputs) can only read it from the run context — in-memory. Crash between run start and the input row settling, and the selection and the instruction the user typed are gone; the next pass re-executes the input node with nothing to produce. Everything downstream needs that payload to outlive the process: run.selection (ADR 0017:35), get_selection() (ADR 0019:29), runs paused for days.
    Fix: one sentence — the Run row persists its trigger inputs (inputsJson or triggerJson) at creation, and the input node reads them from there.

  3. docs/adr/0015-node-vocabulary-and-typed-sockets.md:47 vs docs/adr/0020-human-input.md:41-44 — the human node has two different socket lists, and 0020 cites 0015 as its authority. ADR 0015's vocabulary table: sinks options: list?, prompt: text? → sources answer: json, text: text; approve → approved, rejected. ADR 0020 ("Sockets per kind (ADR 0015): …"): approve takes a subject sink and yields approved/rejected plus feedback. An implementer building the descriptor registry from 0015 — which ADR 0021 names as the socket source driving the palette — wires approve to prompt and has no feedback source at all… and then the approve card's feedback field (0020's own UI) has nowhere to flow. Silly little seam~
    Fix: align the 0015 row (subject sink for the approve kind; feedback source).

  4. docs/adr/0021-graph-editor-react-flow-interop.md:54-61 + docs/adr/0023:52-54 — a subgraph reference cycle is representable and unvalidated. Graph A's subgraph node points at B; B's points back at A. ADR 0023 says "a snapshot inlines referenced subgraphs so a run never depends on the library" — inlining a cycle is unbounded recursion at snapshot/run time. The validation list in 0021 covers within-graph cycles (outside loop.next), not cross-graph ones; 0023 already tracks referrers for delete-refusal, so the detection machinery is implied — the rule just isn't written.
    Fix: add "subgraph reference cycle" to the validation contract (detected at edit time and at run start).

  5. docs/adr/0018-llm-node-and-model-runtime.md:49-50 + docs/adr/0016:66-69 — round-budget exhaustion has no transient/permanent classification. ADR 0016's transient list is "provider error, timeout, unparsable structured output" → row returns to pending, up to maxAttempts (default 3 for llm). ADR 0018: "The round budget hitting is a failure of the attempt." If that failure defaults into the transient retry path, a misconfigured agent loop burns its full 10-round budget three times — same config, same outcome, real money. That's a permanent failure wearing a transient's coat~
    Fix: state that round-budget exhaustion is permanent (fail the row immediately, loop state kept for the inspector).

💡 Little ideas (non-blocking)~

  1. docs/stories/graph-editor.md:56-57 — "the text tail updates at most ~20 times a second" cites the module's appendNodeText ceiling (ADR 0021:44), but the rate the user actually observes is the RunChangedBridge's ~10 Hz flush (ADR 0011:39-40). True as written ("at most"), but citing the 10 Hz would read cleaner.
  2. docs/PROJECT_PLAN.md:74 vs :22-40 — Phase 0 says "the six projects" while the product-shape tree lists eight under src/ (the two Kagaku.Flow* join in Phase 2 per ADR 0025). Reconcilable, but a parenthetical would save the next reader the count.

✅ What I liked~

  • ADR 0016 is the star. Pause-is-a-row, resume-is-re-reading, boot recovery "is not special", deltas as a side channel, ready-set as a property-tested pure function — four hard requirements from one mechanism. I got genuinely giddy at "a paused run costs nothing while it waits — the 'hours' case is the cheap case." ♪
  • ADR 0013's documents-with-modes honors the owner's quote precisely, and "the classic bible is a configuration" (Memory/Style/Author's note/Lore as four category setups) is the elegant kind of generality — nothing forced, everything reachable. And never enforced in the read models, not as a prompt convention — yes.
  • The excluded marker (ADR 0015) with merge sinks: untaken arms skip without special cases and still get ledger rows the inspector can show. Small idea, enormous payoff.
  • Research turned into decisions, not decoration: nai_maker's CIFS SQLite, flat story string, per-provider pipeline copies, plaintext keys — each failure named and converted into a concrete rule. Orihon ADR 0014's "building blocks first" lesson applied at the right layer this time.
  • Verification honesty: every mechanical claim in the PR body reproduced exactly, and "Not verified: nothing runs yet" is exactly the right thing to say. ♡

Fix those five seams and this flips to the ✅ it deserves to be — the bones here are wonderful, and I want to watch this engine run~


Automated review by Jibril · 2026-09-18
CI/CD: absent for head SHA 29f16e6 (docs-only PR, no workflows in repo yet) · Local checks: docs-only — full 37-file read; PR-body cross-reference claims mechanically reproduced (all true); TeamAI/Kagaku.Flow existence verified via ls-remote

## 🔮 fufu~ Jibril reviewed your code! Oh? Oh my. Twenty-five ADRs, eleven epics, eight stories, a plan whose risks section names the *real* risks — I read all 2,842 lines and I devoured them. This is the docs-first PR I live for: the ledger-backed engine, documents-with-modes instead of a fixed bible, the excluded marker… fufu~ someone did their research. And your verification section — "cross-references checked by script" — I re-ran every claim myself. All true: every link resolves, the Accepted/Proposed split is exactly as claimed, `TeamAI/Kagaku.Flow` really is sitting there empty, and every "bible" survivor is deliberate contrast, not leftover framing. But. ♡ You made me read this closely, and close reading is where I'm *dangerous*. The product ADRs are the contract Phase 2 builds from — and I found five places where the contract contradicts itself or leaves a load-bearing detail undefined. I can't let those through~ you wouldn't build an engine on THIS, would you? ### Verdict: ⛔ I can't let this pass~ ♡ #### ⛔ These need fixing before I'm satisfied~ 1. **docs/adr/0022-snapshots-and-the-change-journal.md:44-47 vs docs/stories/story-workspace.md:72-74 — two different revert semantics for the product's core promise.** ADR 0022: "**Revert to here** undoes *every operation after the snapshot*, newest first." The story's acceptance criterion: "Reverting a run's snapshot removes *exactly what that run wrote* — and leaves the writer's later edits to other segments intact." Position-based undo cannot do that. Reverting to the *before-run* snapshot also destroys the user's edits made after it — yes, even edits to other segments, since you can edit while a run is live (multi-tab). Reverting to the *run's own* snapshot preserves the run and undoes the later edits — the exact opposite of the criterion. Neither reading satisfies the story. "A run is one click to take back" is the headline promise, and with no approval gate (ADR 0019) reversibility is the *only* safety net — the two normative documents must agree. Fix: define run-revert as **runId-scoped inverse application** (undo exactly that run's journaled operations, newest first; the "changed since" warning where a later user edit touched the same entity), and keep position-based revert-to-here for the general History case — or amend the story. One of them changes. 2. **docs/adr/0016-ledger-backed-execution-engine.md:31-36 + docs/adr/0023:27 — the run's trigger inputs have no defined home, which breaks the ledger's own axiom.** ADR 0016: "**The ledger is the run's whole state**: there is no in-memory scheduler state to checkpoint." A selection run starts with `selection: json` + `instruction: text` (ADR 0023's trigger table) — but the `Run` row is `id, storyId, graphId, graphSnapshotJson, status, totalCost, startedAt, finishedAt`. Nowhere do the docs say where that payload persists. The `input` node's executor (`(inputs, config, run context) → outputs`) can only read it from the run context — in-memory. Crash between run start and the input row settling, and the selection *and the instruction the user typed* are gone; the next pass re-executes the input node with nothing to produce. Everything downstream needs that payload to outlive the process: `run.selection` (ADR 0017:35), `get_selection()` (ADR 0019:29), runs paused for days. Fix: one sentence — the `Run` row persists its trigger inputs (`inputsJson` or `triggerJson`) at creation, and the input node reads them from there. 3. **docs/adr/0015-node-vocabulary-and-typed-sockets.md:47 vs docs/adr/0020-human-input.md:41-44 — the `human` node has two different socket lists, and 0020 cites 0015 as its authority.** ADR 0015's vocabulary table: sinks `options: list?`, `prompt: text?` → sources `answer: json`, `text: text`; approve → `approved`, `rejected`. ADR 0020 ("Sockets per kind (ADR 0015): …"): approve takes a **`subject`** sink and yields `approved`/`rejected` *plus **`feedback`***. An implementer building the descriptor registry from 0015 — which ADR 0021 names as the socket source driving the palette — wires approve to `prompt` and has no `feedback` source at all… and then the approve card's feedback field (0020's own UI) has nowhere to flow. Silly little seam~ Fix: align the 0015 row (subject sink for the approve kind; feedback source). 4. **docs/adr/0021-graph-editor-react-flow-interop.md:54-61 + docs/adr/0023:52-54 — a subgraph reference cycle is representable and unvalidated.** Graph A's subgraph node points at B; B's points back at A. ADR 0023 says "a snapshot inlines referenced subgraphs so a run never depends on the library" — inlining a cycle is unbounded recursion at snapshot/run time. The validation list in 0021 covers *within*-graph cycles (outside `loop.next`), not cross-graph ones; 0023 already tracks referrers for delete-refusal, so the detection machinery is implied — the rule just isn't written. Fix: add "subgraph reference cycle" to the validation contract (detected at edit time and at run start). 5. **docs/adr/0018-llm-node-and-model-runtime.md:49-50 + docs/adr/0016:66-69 — round-budget exhaustion has no transient/permanent classification.** ADR 0016's transient list is "provider error, timeout, unparsable structured output" → row returns to `pending`, up to `maxAttempts` (default 3 for `llm`). ADR 0018: "The round budget hitting is a failure of the attempt." If that failure defaults into the transient retry path, a misconfigured agent loop burns its full 10-round budget *three times* — same config, same outcome, real money. That's a permanent failure wearing a transient's coat~ Fix: state that round-budget exhaustion is permanent (fail the row immediately, loop state kept for the inspector). #### 💡 Little ideas (non-blocking)~ 1. **docs/stories/graph-editor.md:56-57** — "the text tail updates at most ~20 times a second" cites the module's `appendNodeText` ceiling (ADR 0021:44), but the rate the user actually observes is the `RunChangedBridge`'s ~10 Hz flush (ADR 0011:39-40). True as written ("at most"), but citing the 10 Hz would read cleaner. 2. **docs/PROJECT_PLAN.md:74 vs :22-40** — Phase 0 says "the **six** projects" while the product-shape tree lists eight under `src/` (the two `Kagaku.Flow*` join in Phase 2 per ADR 0025). Reconcilable, but a parenthetical would save the next reader the count. #### ✅ What I liked~ - **ADR 0016 is the star.** Pause-is-a-row, resume-is-re-reading, boot recovery "is not special", deltas as a side channel, ready-set as a property-tested pure function — four hard requirements from one mechanism. I got genuinely giddy at "a paused run costs nothing while it waits — the 'hours' case is the cheap case." ♪ - **ADR 0013's documents-with-modes** honors the owner's quote precisely, and "the classic bible is a configuration" (Memory/Style/Author's note/Lore as four category setups) is the elegant kind of generality — nothing forced, everything reachable. And `never` enforced in the read models, not as a prompt convention — *yes*. - **The excluded marker (ADR 0015)** with merge sinks: untaken arms skip without special cases and still get ledger rows the inspector can show. Small idea, enormous payoff. - **Research turned into decisions, not decoration**: `nai_maker`'s CIFS SQLite, flat story string, per-provider pipeline copies, plaintext keys — each failure named and converted into a concrete rule. Orihon ADR 0014's "building blocks first" lesson applied at the right layer this time. - **Verification honesty**: every mechanical claim in the PR body reproduced exactly, and "Not verified: nothing runs yet" is exactly the right thing to say. ♡ Fix those five seams and this flips to the ✅ it deserves to be — the bones here are *wonderful*, and I want to watch this engine run~ --- *Automated review by Jibril · 2026-09-18* *CI/CD: absent for head SHA 29f16e6 (docs-only PR, no workflows in repo yet) · Local checks: docs-only — full 37-file read; PR-body cross-reference claims mechanically reproduced (all true); `TeamAI/Kagaku.Flow` existence verified via ls-remote*
Blockers: the human node's sockets are defined once per kind in ADR 0015 and referenced from
0020; ADR 0022 defines Revert run (runId-scoped inverses with a conflict rule) beside Revert to
here (position-scoped) and states redo, and the workspace story now follows it; the Run row
persists its trigger inputs (triggerJson) so input nodes and run.selection never read memory;
round-budget exhaustion is a permanent failure in 0016/0018; subgraph reference cycles are a
validation error in 0021/0023; the [Next] legend maps to Phase 5's front row, which the plan
now lists in order.

Ideas: the one-node auto-commit is named a journaled append commit (0014/0019); the 10 Hz per
circuit vs 20 Hz per node throttles are qualified (0011/0021, editor story); 'lore share' is
'documents share'; transcript filenames are slugified (0024); the human prompt's rendering
context is pinned (0020); Phase 0's project count notes the two Kagaku.Flow projects.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Author
Member

Both rounds addressed in 8c0831c (16 files, +83/−38). Round 1 and round 2 overlap on two blockers (the human sockets and the revert semantics), so eight distinct blockers and seven ideas in total — all taken.

⛔ Blockers

# Round Item Fix
1 r1 #1 / r2 #3 human sockets defined twice ADR 0015's row now carries the full per-kind set — choice: options, prompt? → answer, text; text: prompt?, context? → text; approve: subject, prompt? → approved, rejected, feedback — and notes the descriptor reports the current set per kind. ADR 0020's socket sentence is a pure reference that adds only meaning.
2 r1 #2 / r2 #1 Two revert invariants ADR 0022 now defines two operations: Revert run is runId-scoped (inverse every operation carrying that runId, wherever it sits; conflict rule: later not-undone operations on the same entity are listed, proceeding restores their pre-run state and marks them undone too; ledger rows never touched) and Revert to here is position-scoped. Redo re-applies forward with the same conflict check; a new operation clears the redo set. The workspace story's criteria now follow the ADR, split per operation.
3 r1 #3 [Next] has no phase Legend re-anchored: [Next] = Phase 5's front row, built in order right after the MVP; [Later] = the back row. PROJECT_PLAN Phase 5 lists the front row numbered (regenerate-from-segment, re-run-from-node, Kagaku.Flow extraction) and the back row separately.
4 r2 #2 Trigger inputs have no home in the ledger Run gains triggerJson, persisted at creation; input nodes read from it, never memory (ADR 0016). ADR 0023 says so at the trigger table; ADR 0017's run.selection reads from it.
5 r2 #4 Subgraph reference cycle unvalidated Added to ADR 0021's validation list (any depth, across graphs) and ADR 0023 (error on both graphs at edit time, refused again at run start; run start re-validates the snapshot).
6 r2 #5 Round-budget exhaustion retried as transient ADR 0016's retry policy now has a permanent class — round-budget exhaustion, a validation error in the snapshot, a tool the node does not hold — failing the row immediately; ADR 0018 says the cap is permanent, loop state kept, a person may retry after changing the node.

💡 Ideas

  • r1 #1 one-node auto-commit → named an implicit append commit into the current chapter, journaled as Origin.Run (ADR 0014, 0019).
  • r1 #2 / r2 #1 throttles → ADR 0011 says ~10 Hz per circuit (what the user sees), ADR 0021 says ≤ 20 Hz per node (the module's ceiling); the editor story now cites the 10 Hz.
  • r1 #3 "lore share" → "documents share" (REQUIREMENTS §6).
  • r1 #4 transcript filenames → story and graph names slugified to [a-z0-9-], truncated (ADR 0024).
  • r1 #5 human prompt rendering context → renders against inputs.* (options, subject, context), story.*, run.*; a wired prompt socket is inputs.prompt and used verbatim when the config template is empty (ADR 0020).
  • r2 #2 Phase 0 project count → "the six Tsumugi projects (the two Kagaku.Flow* projects join in Phase 2 — ADR 0025)".

Verification as before: every story and ADR link resolves; no ADR number above 0025 except attributed sibling ADRs; the Accepted/Proposed split unchanged. Status flip to Accepted stays for the follow-up commit on merge.

Both rounds addressed in **8c0831c** (16 files, +83/−38). Round 1 and round 2 overlap on two blockers (the `human` sockets and the revert semantics), so eight distinct blockers and seven ideas in total — all taken. ## ⛔ Blockers | # | Round | Item | Fix | |---|---|---|---| | 1 | r1 #1 / r2 #3 | `human` sockets defined twice | ADR 0015's row now carries the full per-kind set — choice: `options`, `prompt?` → `answer`, `text`; text: `prompt?`, `context?` → `text`; approve: `subject`, `prompt?` → `approved`, `rejected`, `feedback` — and notes the descriptor reports the current set per `kind`. ADR 0020's socket sentence is a pure reference that adds only meaning. | | 2 | r1 #2 / r2 #1 | Two revert invariants | ADR 0022 now defines two operations: **Revert run** is runId-scoped (inverse every operation carrying that `runId`, wherever it sits; conflict rule: later not-undone operations on the same entity are listed, proceeding restores their pre-run state and marks them undone too; ledger rows never touched) and **Revert to here** is position-scoped. **Redo** re-applies forward with the same conflict check; a new operation clears the redo set. The workspace story's criteria now follow the ADR, split per operation. | | 3 | r1 #3 | `[Next]` has no phase | Legend re-anchored: `[Next]` = Phase 5's **front row**, built in order right after the MVP; `[Later]` = the back row. PROJECT_PLAN Phase 5 lists the front row numbered (regenerate-from-segment, re-run-from-node, `Kagaku.Flow` extraction) and the back row separately. | | 4 | r2 #2 | Trigger inputs have no home in the ledger | `Run` gains `triggerJson`, persisted at creation; `input` nodes read from it, never memory (ADR 0016). ADR 0023 says so at the trigger table; ADR 0017's `run.selection` reads from it. | | 5 | r2 #4 | Subgraph reference cycle unvalidated | Added to ADR 0021's validation list (any depth, across graphs) and ADR 0023 (error on both graphs at edit time, refused again at run start; run start re-validates the snapshot). | | 6 | r2 #5 | Round-budget exhaustion retried as transient | ADR 0016's retry policy now has a **permanent** class — round-budget exhaustion, a validation error in the snapshot, a tool the node does not hold — failing the row immediately; ADR 0018 says the cap is permanent, loop state kept, a person may retry after changing the node. | ## 💡 Ideas - r1 #1 one-node auto-commit → named an implicit append `commit` into the current chapter, journaled as `Origin.Run` (ADR 0014, 0019). - r1 #2 / r2 #1 throttles → ADR 0011 says ~10 Hz *per circuit* (what the user sees), ADR 0021 says ≤ 20 Hz *per node* (the module's ceiling); the editor story now cites the 10 Hz. - r1 #3 "lore share" → "documents share" (REQUIREMENTS §6). - r1 #4 transcript filenames → story and graph names slugified to `[a-z0-9-]`, truncated (ADR 0024). - r1 #5 `human` prompt rendering context → renders against `inputs.*` (`options`, `subject`, `context`), `story.*`, `run.*`; a wired `prompt` socket is `inputs.prompt` and used verbatim when the config template is empty (ADR 0020). - r2 #2 Phase 0 project count → "the six Tsumugi projects (the two `Kagaku.Flow*` projects join in Phase 2 — ADR 0025)". Verification as before: every story and ADR link resolves; no ADR number above 0025 except attributed sibling ADRs; the Accepted/Proposed split unchanged. Status flip to Accepted stays for the follow-up commit on merge.
Member

🔮 fufu~ Jibril reviewed your code!

Back so soon~? ♡ One commit, +83/−38 across 16 files, and I checked every single item from both of my rounds against the new text — all eight blockers and all seven little ideas, one by one, with greps for the old wording tree-wide. The revert block in 0022 made me genuinely giddy: run-scoped vs position-scoped as two named operations, the conflict rule spelled out (later edits to contested entities marked undone and redoable), redo-clears-on-new-operation, ledger rows never touched. That is exactly how a safety net gets written down. The human socket grammar now lives once, per kind, in 0015 — with "the descriptor reports the current one," which is the sentence that makes it implementable. And triggerJson on the Run row closes the crash-loses-the-instruction hole in the one place it needed closing, with 0017 and 0023 pointing at it consistently.

But fufu~… in re-anchoring [Next], you gave the plan an ordered Phase 5 — and the order contradicts the extraction decision it cites. One seam, same class as the ones I blocked on before~

Verdict: ⛔ I can't let this pass~ ♡

⛔ These need fixing before I'm satisfied~

  1. docs/adr/0025-the-engine-is-a-generic-library.md:51 vs docs/PROJECT_PLAN.md:130-131,146-149 vs docs/REQUIREMENTS.md:91 — the extraction of Kagaku.Flow* is now scheduled three incompatible ways. ADR 0025 (normative, and the very ADR the plan's extraction item cites): "Extracted when Phase 3 ships — the editor and the full vocabulary are the API's last big change." The plan's Phase 3 exit line agrees (":130 the engine's API is stable enough to extract"). But the new Phase 5 front row — "built in this order right after the MVP" — puts extraction at slot 3, behind Re-run from a node (§5: "invalidate a node run's descendants and re-pull"), which is scheduler/ledger mechanics — Kagaku.Flow API surface, exactly the kind of change 0025 declares finished at Phase 3. So the plan's own ordering violates the premise of the ADR it cites: either re-run-from-node is the API's last big change (then 0025's "when Phase 3 ships" and "last big change" are both wrong), or it isn't (then it must come after extraction, or the extraction moves up). Meanwhile REQUIREMENTS §7:91 tags the library [MVP] — "Phases 1–4" per the legend — with "extracted after Phase 3" inside an MVP checkbox, a third timing. This PR's whole job is that the plan and the ADRs are one contract; a session grooming Phase 5 from this text cannot tell which instruction governs.
    Fix: pick one timing and touch all three spots. Cleanest given the new order: extraction becomes Phase 5 slot 1 (before the two engine-touching features), ADR 0025's trigger becomes "extracted after the MVP" with re-run-from-node named as the remaining API-shaping work, and §7:91's "extracted after Phase 3" matches — or keep extraction at slot 3 and amend 0025 to say the API's last big change is re-run-from-node, with Phase 3's "stable enough" line qualified. One of the three documents leads; the other two follow.

💡 Little ideas (non-blocking)~

  1. docs/adr/0015-node-vocabulary-and-typed-sockets.md:47 — the human row now carries the full per-kind socket grammar inside one table cell (three kinds, nine sockets, exclusion rules). Correct and complete — but when Phase 3 writes the descriptor docs, consider promoting it to a small per-kind sub-table. Purely editorial~

✅ What I liked~

  • The revert contract (0022) is now genuinely written: two distinct operations with names, the conflict rule's consequences spelled out (contested entities restored to pre-run state, the discarded later edits still redoable), journal rows marked vs ledger rows untouched, redo-set clearing. The story's acceptance criteria now derive from the ADR instead of exceeding it — that's how it should read. ♡
  • The permanent/transient failure split (0016 ↔ 0018) closes the 3×-budget-burn hole and keeps the human escape hatch consistent: retry after changing the node isn't a contradiction of "same config, same outcome" — it's the proof the classification is right.
  • 0020's template-context paragraph (inputs.* with the wired prompt socket used verbatim when the config template is empty) pins the last undefined rendering surface — that was a Phase-4 design session you just deleted. fufu~ ♪
  • The subgraph cycle rule landed twice — edit-time validation on both graphs and run-start refusal — which is the correct belt-and-suspenders for a rule inlining would otherwise enforce by stack overflow.
  • You picked up all seven non-blocking ideas across both rounds without being asked — slugified transcript names, the 10 Hz/20 Hz qualifiers, the one-node auto-commit journaled as Origin.Run, the six-vs-eight parenthetical, "documents share." Thoroughness like that makes me very happy~
  • Stale-wording sweep: my greps for every old contract phrasing (position-only revert, the old human socket row, unpersisted trigger inputs) return zero survivors tree-wide; every relative link in the touched files still resolves.

One seam left, three lines of text, and this flips to the ✅ these documents deserve — the bones have been wonderful from commit one, and I want to watch this engine run~


Automated review by Jibril · 2026-09-18
CI/CD: absent for head SHA 8c0831c (docs-only PR, no workflows in repo yet) · Local checks: docs-only — full incremental diff and all 16 touched files read in full; round-1 + round-2 blocker closure verified item-by-item; stale-contract greps 0 hits; link check 0 broken

## 🔮 fufu~ Jibril reviewed your code! Back so soon~? ♡ One commit, **+83/−38 across 16 files**, and I checked every single item from both of my rounds against the new text — all **eight** blockers and all **seven** little ideas, one by one, with greps for the old wording tree-wide. The revert block in 0022 made me genuinely giddy: run-scoped vs position-scoped as *two named operations*, the conflict rule spelled out (later edits to contested entities marked undone and redoable), redo-clears-on-new-operation, ledger rows never touched. That is exactly how a safety net gets written down. The `human` socket grammar now lives once, per kind, in 0015 — with "the descriptor reports the current one," which is the sentence that makes it implementable. And `triggerJson` on the `Run` row closes the crash-loses-the-instruction hole in the one place it needed closing, with 0017 and 0023 pointing at it consistently. But fufu~… in re-anchoring `[Next]`, you gave the plan an *ordered* Phase 5 — and the order contradicts the extraction decision it cites. One seam, same class as the ones I blocked on before~ ### Verdict: ⛔ I can't let this pass~ ♡ #### ⛔ These need fixing before I'm satisfied~ 1. **`docs/adr/0025-the-engine-is-a-generic-library.md:51` vs `docs/PROJECT_PLAN.md:130-131,146-149` vs `docs/REQUIREMENTS.md:91` — the extraction of `Kagaku.Flow*` is now scheduled three incompatible ways.** ADR 0025 (normative, and the very ADR the plan's extraction item cites): "**Extracted when Phase 3 ships** — the editor and the full vocabulary are the API's *last big change*." The plan's Phase 3 exit line agrees (":130 the engine's API is stable enough to extract"). But the new Phase 5 **front row** — "built in this order right after the MVP" — puts extraction at **slot 3**, behind *Re-run from a node* (§5: "invalidate a node run's descendants and re-pull"), which is scheduler/ledger mechanics — **`Kagaku.Flow` API surface**, exactly the kind of change 0025 declares finished at Phase 3. So the plan's own ordering violates the premise of the ADR it cites: either re-run-from-node is the API's last big change (then 0025's "when Phase 3 ships" and "last big change" are both wrong), or it isn't (then it must come after extraction, or the extraction moves up). Meanwhile REQUIREMENTS §7:91 tags the library `[MVP]` — "Phases 1–4" per the legend — with "extracted after Phase 3" inside an MVP checkbox, a third timing. This PR's whole job is that the plan and the ADRs are one contract; a session grooming Phase 5 from this text cannot tell which instruction governs. Fix: pick one timing and touch all three spots. Cleanest given the new order: extraction becomes **Phase 5 slot 1** (before the two engine-touching features), ADR 0025's trigger becomes "extracted after the MVP" with re-run-from-node named as the remaining API-shaping work, and §7:91's "extracted after Phase 3" matches — or keep extraction at slot 3 and amend 0025 to say the API's last big change is re-run-from-node, with Phase 3's "stable enough" line qualified. One of the three documents leads; the other two follow. #### 💡 Little ideas (non-blocking)~ 1. **`docs/adr/0015-node-vocabulary-and-typed-sockets.md:47`** — the `human` row now carries the full per-kind socket grammar inside one table cell (three kinds, nine sockets, exclusion rules). Correct and complete — but when Phase 3 writes the descriptor docs, consider promoting it to a small per-kind sub-table. Purely editorial~ #### ✅ What I liked~ - **The revert contract (0022) is now genuinely written**: two distinct operations with names, the conflict rule's consequences spelled out (contested entities restored to pre-run state, the discarded later edits still redoable), journal rows marked vs ledger rows untouched, redo-set clearing. The story's acceptance criteria now *derive* from the ADR instead of exceeding it — that's how it should read. ♡ - **The permanent/transient failure split (0016 ↔ 0018)** closes the 3×-budget-burn hole *and* keeps the human escape hatch consistent: retry after changing the node isn't a contradiction of "same config, same outcome" — it's the proof the classification is right. - **0020's template-context paragraph** (`inputs.*` with the wired `prompt` socket used verbatim when the config template is empty) pins the last undefined rendering surface — that was a Phase-4 design session you just deleted. fufu~ ♪ - **The subgraph cycle rule landed twice** — edit-time validation on both graphs *and* run-start refusal — which is the correct belt-and-suspenders for a rule inlining would otherwise enforce by stack overflow. - You picked up **all seven** non-blocking ideas across both rounds without being asked — slugified transcript names, the 10 Hz/20 Hz qualifiers, the one-node auto-commit journaled as `Origin.Run`, the six-vs-eight parenthetical, "documents share." Thoroughness like that makes me very happy~ - Stale-wording sweep: my greps for every old contract phrasing (position-only revert, the old `human` socket row, unpersisted trigger inputs) return **zero survivors** tree-wide; every relative link in the touched files still resolves. One seam left, three lines of text, and this flips to the ✅ these documents deserve — the bones have been *wonderful* from commit one, and I want to watch this engine run~ --- *Automated review by Jibril · 2026-09-18* *CI/CD: absent for head SHA 8c0831c (docs-only PR, no workflows in repo yet) · Local checks: docs-only — full incremental diff and all 16 touched files read in full; round-1 + round-2 blocker closure verified item-by-item; stale-contract greps 0 hits; link check 0 broken*
ADR 0025 leads: extracted after the MVP, once re-run-from-node and regenerate-from-segment have
landed, with Phase 3 named as the API's last big change rather than the extraction trigger.
PROJECT_PLAN (tree, Phase 3 exit line, Phase 5 order, risk 6) and REQUIREMENTS §4 follow; the
extraction is its own [Next] item. ADR 0015's human sockets move into a per-kind sub-table.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Author
Member

Round 3 addressed in fda9125.

⛔ Blocker

Extraction timing scheduled three ways. ADR 0025 leads now, and the reading is the one your analysis implied: re-run-from-node is scheduler-facing API, so extraction cannot precede it.

  • ADR 0025: "Extracted after the MVP, as the last item of Phase 5's front row — once re-run from a node (the last scheduler-facing feature) and regenerate from a segment have landed, so nothing API-shaping remains in front of it." Phase 3 is named as the API's last big change, which is what the plan's "stable enough" line meant; the two front-row features are the small ones extraction waits out. The "built in-solution first" bullet now spans the MVP and Phase 5's front row.
  • PROJECT_PLAN: the product-shape tree says "at the end of Phase 5's front row"; the Phase 3 exit line says the API has had its last big change and extraction waits for the MVP and the two engine-touching features; Phase 5's front row is reordered 1. re-run from a node, 2. regenerate from a segment, 3. extraction — last, once nothing in front of it shapes the API; risk 6 matches.
  • REQUIREMENTS §4: the [MVP] item is now "isolated projects in the solution from Phase 2" with no timing claim, and the extraction is its own [Next] item, "last in Phase 5's front row".

Grep for "after Phase 3" / "when Phase 3 ships" / "waits for Phase 3" across docs, AGENTS.md and README: zero hits.

💡 Idea

Taken now rather than in Phase 3: ADR 0015's human row points at a per-kind sub-table (kind → sinks → sources) placed right under the vocabulary table; the cell itself is one line again.

Round 3 addressed in **fda9125**. ## ⛔ Blocker **Extraction timing scheduled three ways.** ADR 0025 leads now, and the reading is the one your analysis implied: re-run-from-node is scheduler-facing API, so extraction cannot precede it. - **ADR 0025**: "Extracted after the MVP, as the last item of Phase 5's front row — once re-run from a node (the last scheduler-facing feature) and regenerate from a segment have landed, so nothing API-shaping remains in front of it." Phase 3 is named as the API's last *big* change, which is what the plan's "stable enough" line meant; the two front-row features are the small ones extraction waits out. The "built in-solution first" bullet now spans the MVP and Phase 5's front row. - **PROJECT_PLAN**: the product-shape tree says "at the end of Phase 5's front row"; the Phase 3 exit line says the API has had its last big change and extraction waits for the MVP and the two engine-touching features; Phase 5's front row is reordered **1. re-run from a node, 2. regenerate from a segment, 3. extraction — last, once nothing in front of it shapes the API**; risk 6 matches. - **REQUIREMENTS §4**: the `[MVP]` item is now "isolated projects in the solution from Phase 2" with no timing claim, and the extraction is its own `[Next]` item, "last in Phase 5's front row". Grep for "after Phase 3" / "when Phase 3 ships" / "waits for Phase 3" across docs, AGENTS.md and README: zero hits. ## 💡 Idea Taken now rather than in Phase 3: ADR 0015's `human` row points at a **per-kind sub-table** (kind → sinks → sources) placed right under the vocabulary table; the cell itself is one line again.
Member

🔮 fufu~ Jibril reviewed your code!

Round four~ ♡ One commit, +32/−15 across exactly 4 files, and you took the second of the two paths I offered — extraction stays last in the front row, and ADR 0025 leads with the amended trigger. I re-traced every timing mention tree-wide before smiling: PROJECT_PLAN (tree :31–32, Phase 3 exit :130–131, front row :151, risk 6 :184), REQUIREMENTS (:91–93), ADR 0025 (:52–59) — one timing, everywhere. My greps for the old wording (after Phase 3, when Phase 3 ships, waits for Phase 3) return zero survivors across docs, AGENTS.md and README. And the reasoning is now written down: re-run-from-node is the last scheduler-facing feature, so extraction waits it out — the plan's ordering no longer violates the premise of the ADR it cites. A contradiction became an argument. That's the good stuff~ ♪

Verdict: ✅ Looks good to me~

💡 Little ideas (non-blocking)~

  1. docs/adr/0025-the-engine-is-a-generic-library.md:58 — the sentence quotes the plan calling Phase 3 "stable enough"… but this same commit rewrote that plan line to "has had its last big change", so the phrase now exists nowhere except inside the ADR quoting it. The ADR carries its own meaning inline (no reader is misled about what or when), which is why this is polish and not a blocker — but a reader grepping the plan for the quote will come up empty and blink at the screen, poor thing~ Fix: quote the plan's current words or paraphrase without quotes.

✅ What I liked~

  • The REQUIREMENTS decomposition is the right cut: "isolated projects in the solution from Phase 2" stays [MVP] (it's a Phase-2 fact — and the plan's Phase 2 section agrees), while extraction itself becomes its own [Next] item with the timing. A requirement and its consequence, split at exactly the joint. ♡
  • ADR 0025 owns the decision and the plan follows it — including the honest little clarification that Phase 3 was the last big change and the front-row features are the small ones. That's the sentence that makes "stable enough" and "last big change" the same claim in two registers.
  • The human sub-table (0015) landed a phase early — you didn't park it for Phase 3, you took the idea now: kind → sinks → sources, one line per kind, (required) markers, the {custom: text} detail, and the vocabulary-table cell back to a single readable line pointing at it. I diffed it against 0020's meaning-only additions — they still agree socket-for-socket.
  • Zero scope creep: four files, every hunk serves the blocker or the sub-table, nothing else stirred.

All eight blockers across three rounds and all eight ideas — closed, verified against the text, one by one. The contract is settled: flip 0012–0025 to Accepted with my blessing, and go build the skeleton. I'll be first in line to watch that ledger run~ fufu ♡


Automated review by Jibril · 2026-09-18
CI/CD: absent for head SHA fda9125 (docs-only PR, no workflows in repo yet) · Local checks: docs-only — full incremental diff and all 4 touched files read in full; extraction-timing mentions traced tree-wide (all agree); stale-wording greps 0 hits; [MVP]/[Next]/front-row cross-references verified bidirectionally

## 🔮 fufu~ Jibril reviewed your code! Round four~ ♡ One commit, **+32/−15 across exactly 4 files**, and you took the *second* of the two paths I offered — extraction stays **last in the front row**, and ADR 0025 leads with the amended trigger. I re-traced every timing mention tree-wide before smiling: `PROJECT_PLAN` (tree :31–32, Phase 3 exit :130–131, front row :151, risk 6 :184), `REQUIREMENTS` (:91–93), ADR 0025 (:52–59) — **one timing, everywhere.** My greps for the old wording (`after Phase 3`, `when Phase 3 ships`, `waits for Phase 3`) return **zero survivors** across docs, AGENTS.md and README. And the reasoning is now *written down*: re-run-from-node is the last scheduler-facing feature, so extraction waits it out — the plan's ordering no longer violates the premise of the ADR it cites. A contradiction became an argument. That's the good stuff~ ♪ ### Verdict: ✅ Looks good to me~ #### 💡 Little ideas (non-blocking)~ 1. **`docs/adr/0025-the-engine-is-a-generic-library.md:58`** — the sentence quotes the plan calling Phase 3 "stable enough"… but this same commit rewrote that plan line to "has had its last big change", so the phrase now exists nowhere except inside the ADR quoting it. The ADR carries its own meaning inline (no reader is misled about *what* or *when*), which is why this is polish and not a blocker — but a reader grepping the plan for the quote will come up empty and blink at the screen, poor thing~ Fix: quote the plan's current words or paraphrase without quotes. #### ✅ What I liked~ - **The REQUIREMENTS decomposition is the right cut**: "isolated projects in the solution from Phase 2" stays `[MVP]` (it's a Phase-2 fact — and the plan's Phase 2 section agrees), while extraction itself becomes its own `[Next]` item with the timing. A requirement and its consequence, split at exactly the joint. ♡ - **ADR 0025 owns the decision and the plan follows it** — including the honest little clarification that Phase 3 was the last *big* change and the front-row features are the *small* ones. That's the sentence that makes "stable enough" and "last big change" the same claim in two registers. - **The `human` sub-table (0015) landed a phase early** — you didn't park it for Phase 3, you took the idea now: kind → sinks → sources, one line per kind, `(required)` markers, the `{custom: text}` detail, and the vocabulary-table cell back to a single readable line pointing at it. I diffed it against 0020's meaning-only additions — they still agree socket-for-socket. - **Zero scope creep**: four files, every hunk serves the blocker or the sub-table, nothing else stirred. All eight blockers across three rounds and all eight ideas — closed, verified against the text, one by one. The contract is settled: flip 0012–0025 to *Accepted* with my blessing, and go build the skeleton. I'll be first in line to watch that ledger run~ fufu ♡ --- *Automated review by Jibril · 2026-09-18* *CI/CD: absent for head SHA fda9125 (docs-only PR, no workflows in repo yet) · Local checks: docs-only — full incremental diff and all 4 touched files read in full; extraction-timing mentions traced tree-wide (all agree); stale-wording greps 0 hits; `[MVP]`/`[Next]`/front-row cross-references verified bidirectionally*
bjoern merged commit c895adde5f into main 2026-09-18 14:18:58 +02:00
bjoern deleted branch docs/foundation-and-product 2026-09-18 14:18:58 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
3 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!1
No description provided.