Documentation
¶
Overview ¶
Package flow implements vertical routing: the Host decides from the facts which subagent to call next and what to do.
Design principles:
- Route is a pure function: it takes a State and returns an *Instruction. No IO, no Store calls, so it is unit-testable.
- State is built by LoadState (not pure) from the Store, reading every fact routing needs in one pass.
- Returning nil is legal: it means there is currently no Worker instruction derivable from the deterministic facts; the Engine then handles it by terminal state, start-up fallback arbitration or waiting for user intervention.
Router covers "table lookup" decisions (the next step of each chapter, post-arc-end handling, queue-driven work), and not "semantic understanding" decisions (picking a planner, handling a user Steer, producing a summary).
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func StartsForwardChapter ¶
func StartsForwardChapter(inst *Instruction, progress *domain.Progress, pending *domain.PendingCommit) bool
StartsForwardChapter reports whether an instruction will start a new forward chapter that is not yet finished. It only reads facts and does not decide whether to pass; the Task/Reason wording plays no part in the decision.
Types ¶
type AdvanceHoldResolution ¶
type AdvanceHoldResolution int
AdvanceHoldResolution is the outcome of resolving a one-shot pause against the current facts.
const ( AdvanceHoldKeep AdvanceHoldResolution = iota AdvanceHoldConsume AdvanceHoldConsumeAndStop )
func ResolveAdvanceHold ¶
func ResolveAdvanceHold(hold *domain.AdvanceHold, progress *domain.Progress) (AdvanceHoldResolution, error)
ResolveAdvanceHold is a pure function that resolves a one-shot pause. An unknown condition or a missing fact is an explicit error; silently degrading to "keep running" is not allowed.
type AggregateKind ¶
type AggregateKind string
const ( AggregateArcReview AggregateKind = "arc_review" AggregateArcSummary AggregateKind = "arc_summary" AggregateVolumeSummary AggregateKind = "volume_summary" AggregateGlobalReview AggregateKind = "global_review" )
type AggregateRefresh ¶
type AggregateRefresh struct {
Kind AggregateKind
Volume int
Arc int
StartChapter int
EndChapter int
}
type Instruction ¶
type Instruction struct {
Agent string // architect_long / architect_short / writer / editor
Task string // the task description handed to the subagent
Reason string // the routing rationale (used for events, logs and failure arbitration)
Chapter int // the chapter number a writer task touches (continue / rewrite / polish); 0 means none (editor/architect tasks)
}
Instruction tells the Engine which Worker to run next and with what task.
func Route ¶
func Route(s State) *Instruction
Route returns the deterministic next-step instruction from the facts; returning nil is handled by the Engine per call context.
Decision priority (mutually exclusive, matching the first hit from the top):
- Phase=Complete → nil (the Host deterministically produces the summary)
- planning-phase settings missing and the planner is determinable → the same planner completes them; otherwise nil (the Engine applies the start-up fallback)
- PendingRewrites non-empty → writer rewrites/polishes per the queue
- Flow=Reviewing → nil (dormant: there is no writer right now, and during a review the Flow is really writing)
- Flow=Steering → nil (a user intervention is being handled)
- an external revision invalidated aggregate artifacts → editor rebuilds them
- an external revision affects later planning → architect handles it
- a layered book reaches the end of an arc → review, summarize, expand the arc or continue into the next volume
- the non-layered global review is due → editor(global review)
10. the non-layered outline is exhausted → architect(decides to finish or to continue from an outline) 11. everything else → writer(write next_chapter)
type State ¶
type State struct {
Progress *domain.Progress
// the largest chapter number among completed chapters; 0 means writing has not started yet.
LastCompleted int
// arc boundary info of the previous chapter; the other fields are meaningless when IsArcEnd=false.
// should be nil when LastCompleted=0 or in non-Layered mode.
ArcBoundary *storepkg.ArcBoundary
// the three post-arc-end facts: whether the review / arc summary / volume summary are done.
HasArcReview bool
HasArcSummary bool
HasVolumeSummary bool
// missing foundation entries (the completion signal of the planning phase).
FoundationMissing []string
// the persisted planning tier (written to RunMeta when save_foundation persists scale).
// empty = the first planning round has not produced any setting yet, so the planner identity cannot be determined.
PlanningTier domain.PlanningTier
// non-layered book: whether the most recently completed chapter already has a global review with scope=global
// (only meaningful at the ShouldReview trigger point; always false for a layered book).
HasGlobalReview bool
// external revision impacts the Architect must handle before continuing. Ordinary writer feedback is left to the next
// natural structural operation to absorb together, instead of dispatching a planner for every chapter.
ImmediateFeedbackCount int
// the earliest arc/volume artifact the Editor has to regenerate after an external revision.
AggregateRefresh *AggregateRefresh
}
State is the input of Route: every fact must be declared here explicitly, and Route is forbidden from reading the Store.
func LoadState ¶
LoadState reads every fact Route needs from the Store. This is the routing "IO boundary": all reads are concentrated here and Route stays pure. Any read failure returns an error; a corrupt artifact and "not generated yet" are two different facts, and the Router must not keep dispatching on an incomplete snapshot.