Help us shape the future of Go! Take the 2026 Go Developer Survey

flow

package
v1.5.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 30, 2026 License: Apache-2.0 Imports: 4 Imported by: 0

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):

  1. Phase=Complete → nil (the Host deterministically produces the summary)
  2. planning-phase settings missing and the planner is determinable → the same planner completes them; otherwise nil (the Engine applies the start-up fallback)
  3. PendingRewrites non-empty → writer rewrites/polishes per the queue
  4. Flow=Reviewing → nil (dormant: there is no writer right now, and during a review the Flow is really writing)
  5. Flow=Steering → nil (a user intervention is being handled)
  6. an external revision invalidated aggregate artifacts → editor rebuilds them
  7. an external revision affects later planning → architect handles it
  8. a layered book reaches the end of an arc → review, summarize, expand the arc or continue into the next volume
  9. 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

func LoadState(store *storepkg.Store) (State, error)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL