review

package
v0.8.0 Latest Latest
Warning

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

Go to latest
Published: Jul 6, 2026 License: MIT Imports: 42 Imported by: 0

Documentation

Overview

Package review — see env.go for package-level rationale.

cmd.go provides NewCommand(), the cobra entry point for `entire review`. It routes through the new AgentReviewer / Sink / Run architecture for agents with review-runner adapters (claude-code, codex, gemini, pi) and falls back to RunMarkerFallback for agents that are not yet wired into that review runner contract.

Package review — see env.go for package-level rationale.

dump.go provides DumpSink, a Sink implementation that writes a per-agent narrative dump to an io.Writer after the run completes. AgentEvent is a no-op; events are read from RunSummary.AgentRuns[].Buffer in RunFinished.

Each agent's block is plain markdown written as-is — NOT glamour-rendered. Worker narratives are raw material (the final report is styled, and drill-in shows the buffer); styling multi-MB output here wedged the finalize phase on glamour's super-linear cost.

Package review contains the env-var contract between `entire review` (which spawns the agent process) and the lifecycle hook (which adopts the session). These names are stable API; renaming any constant is a breaking change.

Design rationale: each spawned agent inherits its own copy of the process environment, so multi-tenant correctness (multiple worktrees, multi-agent runs) holds by construction — one agent's env vars cannot bleed into another agent's session. The lifecycle UserPromptSubmit hook reads these env vars to tag the in-flight session as a review session (Kind = "agent_review") and records which skills were run.

Package review — see env.go for package-level rationale.

marker_fallback.go provides the PendingReviewMarker type and its write/read/clear helpers, plus RunMarkerFallback which handles review for agents that don't (yet) implement AgentReviewer.

For adapter-backed review workers, the new architecture uses env-var handshake (env.go) + AgentReviewer.Start, and the lifecycle hook reads ENTIRE_REVIEW_* env vars off the spawned process — there is no marker-file adoption code path.

For agents without a review-runner adapter, the marker is purely a record of what the user was asked to do: RunMarkerFallback writes it before printing manual-start guidance, and `entire attach --review <session-id>` reads the marker to tag a manual session after the fact. ReadPendingReviewMarker / ClearPendingReviewMarker are exported for that attach flow; nothing else reads the marker.

Package review — see env.go for package-level rationale.

picker.go implements the interactive review skills picker and agent selection helpers. pickConfig presents a huh multi-select per installed agent and saves the selection to clone-local review preferences.

Package review — see env.go for package-level rationale.

prompt.go implements the shared prompt composer used by all per-agent reviewers. The scope clause pins agents to "commits unique to this branch vs the mainline base ref, plus uncommitted working-tree changes" — preventing the divergent-default problem where codex defaulted to origin/main...HEAD and claude defaulted to working-tree-only on the same invocation (regression class from #1018 commit b9ed9c074; enforced structurally here).

Package review — see env.go for package-level rationale.

run.go implements the single-agent orchestrator. CU8 generalizes to N agents with a sibling RunMulti that re-uses the same AgentRun classification and Sink fan-out.

Package review — see env.go for package-level rationale.

run_multi.go implements RunMulti, the N-agent orchestrator. It runs each AgentReviewer in its own goroutine under a shared context, fans their event streams into a single dispatch loop that calls each Sink serially (preserving the serial-dispatch contract from CU4), and aggregates the per-agent results into a single RunSummary.

Cancellation: when ctx is cancelled (typically by the cobra command's SIGINT handling), all per-agent reviewers see ctx.Err() via their individual Process implementations and exit. RunMulti waits for every goroutine to drain before returning, ensuring no AgentEvent calls fire after RunFinished.

Goroutine accounting for N agents:

  • N forwarding goroutines: one per agent that started successfully, reads proc.Events() and sends tagged events to the fan-in channel.
  • 1 channel-close goroutine: waits for all N forwarders via WaitGroup then closes the fan-in channel so the dispatch loop terminates.
  • 1 dispatch goroutine (the caller's): ranges over fan-in, updates per-agent state, calls sinks serially. RunMulti does NOT spawn a separate dispatch goroutine — the fan-in loop runs on the RunMulti call stack, keeping the goroutine count low.

Package review — see env.go for package-level rationale.

scope.go implements scope detection for `entire review`. The scope is the git ref the review is bounded by: "commits unique to this branch vs <baseRef>". Pinning the scope at launch time prevents the divergent-default problem where different agents default to different comparison points (e.g. codex used origin/main...HEAD, claude used working-tree-only) on the same invocation.

Package review — see env.go for package-level rationale.

synthesis_prompt.go builds the LLM prompt that asks a configured summary provider to synthesize a unified verdict across N per-agent review reports. It is a pure-function composer with no I/O; all logic is testable without network calls or TTY state.

Package review — see env.go for package-level rationale.

synthesis_sink.go provides SynthesisSink, the master adjudication phase of a multi-agent review: after all worker agents finish, it asks a configured provider to consolidate the per-agent narratives into a final report. Skipped silently on cancellation or when fewer than 2 successful agents produced usable output. The report runs unconditionally (no y/N prompt) and works in both TTY and redirected/CI output.

Composition: appended AFTER DumpSink in the multi-agent sink slice, so the final report renders below the per-agent narrative dump.

Package review — see env.go for package-level rationale.

tui_detail.go provides the alt-screen drill-in renderer. The body content is produced by [eventLines] (one or more wrapped lines per event) and fed into a bubbles/v2/viewport on [reviewTUIModel]; this file's [detailFrame] is the pure-function chrome (header + body + footer) that wraps the viewport's pre-rendered output and pads to exactly termHeight lines so every frame has the same line count (avoids ghost rows in Bubble Tea's alt-screen diff).

Package review — see env.go for package-level rationale.

tui_model.go provides reviewTUIModel, the Bubble Tea Model for the review dashboard. The model renders a per-agent status table during the run and supports Ctrl+O drill-in mode for inspecting one agent's live event buffer on the alt screen.

Package review — see env.go for package-level rationale.

tui_sink.go provides TUISink, a Sink implementation that renders a Bubble Tea status dashboard during a review run and supports Ctrl+O drill-in mode for inspecting one agent's live event buffer. Used in interactive (TTY) runs; non-TTY runs use DumpSink instead.

Index

Constants

View Source
const (
	EnvSession     = provenance.ReviewSession
	EnvAgent       = provenance.ReviewAgent
	EnvSkills      = provenance.ReviewSkills
	EnvPrompt      = provenance.ReviewPrompt
	EnvStartingSHA = provenance.ReviewStartingSHA
)

Review env vars. Names live in cmd/entire/cli/provenance; review aliases them so existing call sites (review.EnvSession, etc.) keep working.

View Source
const (
	ReviewOutputLocal = "local"
	ReviewOutputTrail = "trail"
)

Review output destinations. ReviewOutputLocal prints the verdict and writes the local review manifest; ReviewOutputTrail additionally posts the verdict to the branch's trail as a finding (`entire trail finding`).

View Source
const DefaultProfileName = "general"

Variables

View Source
var ErrPickerCancelled = errors.New("picker cancelled")

ErrPickerCancelled is returned when the user aborts an interactive picker or confirmation (Ctrl+C / Esc). Callers map it to a clean, silent exit rather than a command error.

Functions

func AppendModelFlag added in v0.7.8

func AppendModelFlag(args []string, model string) []string

AppendModelFlag appends a standard --model flag pair when model is non-empty. Review runner adapters share this so model override argv handling stays identical across claude-code, codex, and gemini.

func AppendReviewEnv

func AppendReviewEnv(base []string, agentName string, cfg reviewtypes.RunConfig, prompt string) []string

AppendReviewEnv adds the ENTIRE_REVIEW_* env vars to base, returning the new slice. Used by per-agent reviewers in their AgentReviewer.Start implementations to propagate the review-session contract to spawned agent processes.

agentName must be the agent's stable registry key (e.g. "claude-code"). cfg carries skills and the starting SHA. prompt is the full composed prompt text (result of ComposeReviewPrompt).

Any pre-existing ENTIRE_REVIEW_* AND ENTIRE_INVESTIGATE_* entries in base are stripped before the new values are appended. Stripping review entries handles nested invocations and stale inheritance from a parent shell — duplicate keys would otherwise have implementation-defined precedence. Stripping investigate entries prevents an outer `entire investigate` session from mis-tagging a child review session if invoked nested (symmetric to AppendInvestigateEnv's behavior).

func BuildReviewPickerFields

func BuildReviewPickerFields(
	agentName string,
	builtins []skilldiscovery.CuratedSkill,
	discovered []agent.DiscoveredSkill,
	activeHints []skilldiscovery.InstallHint,
	previousPrompt string,
	builtinPicksOut, discoveredPicksOut *[]string,
	promptOut *string,
) []huh.Field

BuildReviewPickerFields composes the per-agent group fields for the review picker. Returns a slice of huh.Field in render order:

0: built-in commands (multiselect) OR note
1: installed plugin skills (multiselect) OR note
2: install hints (note with all active hint messages) — OMITTED if empty
3: additional instructions (text) — always present

func ClearPendingReviewMarker

func ClearPendingReviewMarker(ctx context.Context) error

ClearPendingReviewMarker removes the marker. Missing file is not an error.

func ComposeReviewPrompt

func ComposeReviewPrompt(cfg reviewtypes.RunConfig) string

ComposeReviewPrompt assembles the prompt sent to a worker agent. It joins the configured skill invocations, the profile's canonical task, per-agent instructions, the per-run prompt, and a scope clause that pins the agent to commits unique to the current branch vs cfg.ScopeBaseRef plus any uncommitted changes.

Empty sections are skipped (no triple-newline gaps). The scope clause is only added when cfg.ScopeBaseRef is non-empty.

func ConfirmFirstRunSetup

func ConfirmFirstRunSetup(ctx context.Context, out io.Writer) bool

ConfirmFirstRunSetup prints a banner framing the picker as first-run setup (rather than the review itself) and waits for the user to confirm. Returns false if the user cancels; caller should bail gracefully.

Signposting matters here because `entire review` with no config silently drops into the picker — users running the command to start a review can mistake the picker for the review. The banner + confirmation makes the setup phase explicit, and the trailing "running review now" line in the caller closes the loop on what comes next.

func ConfirmRunReviewNow added in v0.7.8

func ConfirmRunReviewNow(ctx context.Context, out io.Writer) (bool, error)

func DecodeSkills

func DecodeSkills(encoded string) ([]string, error)

DecodeSkills deserialises a value previously produced by EncodeSkills. An empty string decodes to a nil slice (no skills configured). Any other value that is not valid JSON returns an error.

func EncodeSkills

func EncodeSkills(skills []string) (string, error)

EncodeSkills serialises a slice of skill invocation strings to a JSON value suitable for storing in the ENTIRE_REVIEW_SKILLS environment variable. An empty or nil slice encodes to the literal string "[]".

func MergePickerResults

func MergePickerResults(existing map[string]settings.ReviewConfig, offered map[string]struct{}, selected map[string]settings.ReviewConfig) map[string]settings.ReviewConfig

MergePickerResults combines the picker's output with existing review config entries that the picker did not surface. Agents in `offered` are fully controlled by the picker: if they appear in `selected` with a non-zero config the entry is set, otherwise the entry is removed. Agents not in `offered` keep their existing config untouched.

Exported so tests can drive it directly — the picker itself can't run headless.

func NewCommand

func NewCommand(deps Deps) *cobra.Command

NewCommand returns the `entire review` cobra command wired with the provided deps. Callers in the cli package pass a fully-populated Deps; tests pass a Deps with stub fields.

func Run

Run executes a single-agent review. Events from the agent are forwarded to all sinks via AgentEvent as they arrive; on completion, RunFinished is called on each sink with the populated RunSummary.

Returns the summary plus the agent's terminal error (nil on clean exit, ctx.Err() on cancellation, an error wrapping *exec.ExitError on non-zero exit, or an agent-level error when the event stream reports failure). Callers can inspect both: the summary is always populated even on error.

func RunMarkerFallback

func RunMarkerFallback(ctx context.Context, agentName string, cfg reviewtypes.RunConfig, worktreePath string, out io.Writer) error

RunMarkerFallback handles review for agents that do not yet have an Entire review-runner adapter by writing the pending-review marker file and printing manual-start guidance. The user is told to open the agent themselves and run the configured skills.

The marker is NOT auto-adopted by anything — the lifecycle hook reads ENTIRE_REVIEW_* env vars on the spawned process, not the marker file. For adapterless review agents the user starts the agent manually, so no env inheritance happens. The marker exists purely so that `entire attach --review <session-id>` has a record of what the user was asked to review when tagging the session after the fact.

agentName must be the agent's registry key (e.g. "cursor"). cfg carries skills and the starting SHA. worktreePath scopes the marker so sessions in other worktrees don't claim it. out is the destination for user-facing guidance.

func RunMulti

RunMulti executes a multi-agent review. Each reviewer runs concurrently; events from N agents are funneled into a single dispatch loop that calls every sink's AgentEvent in arrival order from a single goroutine (serial-dispatch guarantee).

Returns the aggregated RunSummary plus the FIRST non-cancellation per-agent error encountered. Callers that want individual errors should inspect summary.AgentRuns[i].Err. The returned summary is always populated, even on error; sinks are always notified via RunFinished.

Cancellation propagates through ctx; each reviewer's Process honors it. When ctx is cancelled all per-agent goroutines will eventually drain and the channel will close; RunMulti waits for all before calling RunFinished.

func RunReviewGuidedSetup added in v0.7.8

func RunReviewGuidedSetup(
	ctx context.Context,
	out io.Writer,
	installed []types.AgentName,
	reviewerFor func(string) reviewtypes.AgentReviewer,
	profileName string,
	firstRun bool,
	s *settings.EntireSettings,
) (string, settings.ReviewProfileConfig, error)

RunReviewGuidedSetup is the simple config path for `entire review`. It intentionally avoids the per-agent skills picker: users choose the review profile and worker agents, then Entire fills in opinionated per-agent defaults. Advanced skill-level editing remains available via --edit.

func RunReviewProfileConfigPicker added in v0.7.8

func RunReviewProfileConfigPicker(ctx context.Context, out io.Writer, getInstalled func(context.Context) []types.AgentName, profileName string) error

func SplitSavedPicks

func SplitSavedPicks(saved []string, builtins []skilldiscovery.CuratedSkill, discovered []agent.DiscoveredSkill) ([]string, []string)

SplitSavedPicks partitions a flat saved-skills list into the subset that matches built-in curated commands and the subset that matches discovered plugin skills. Skill names that match neither are dropped from both — they're preserved on the settings side via MergePickerResults when they belong to a picker-unaware agent entry.

func VerifyConfiguredSkillsInstalled

func VerifyConfiguredSkillsInstalled(ctx context.Context, ag agent.Agent, cfg settings.ReviewConfig) error

VerifyConfiguredSkillsInstalled is the spawn-time backstop for the silent-failure vector. For each skill in cfg.Skills, check it's either a curated built-in or returned by the agent's SkillDiscoverer; fail with a user-facing error if any skill is missing. Empty Skills (prompt-only config) short-circuits to nil — a freeform prompt has no skill list to validate against.

func WritePendingReviewMarker

func WritePendingReviewMarker(ctx context.Context, m PendingReviewMarker) error

WritePendingReviewMarker persists the marker. Overwrites any existing marker.

Types

type AgentChoice

type AgentChoice struct {
	Name  string
	Label string
}

AgentChoice is one row in the spawn-time picker. Name is the agent registry key (used for marker/override); Label is the picker-visible string ("<name> (N skills configured)" or "<name> (prompt-only)").

func ComputeEligibleConfiguredForProfile added in v0.7.8

func ComputeEligibleConfiguredForProfile(profile settings.ReviewProfileConfig, installed []types.AgentName) []AgentChoice

ComputeEligibleConfiguredForProfile returns the sorted list of agents in a profile that are both configured and have hooks installed.

type AgentSynthesisProvider added in v0.7.8

type AgentSynthesisProvider struct {
	AgentName string
	Model     string
}

AgentSynthesisProvider asks a named agent's text-generation API to produce the final report. This is the profile-native master implementation used by `entire review`: workers run as review sessions, while the master is an isolated text-generation call so it consolidates reports without creating a second review worker session.

func (AgentSynthesisProvider) Synthesize added in v0.7.8

func (p AgentSynthesisProvider) Synthesize(ctx context.Context, prompt string) (string, error)

type Deps

type Deps struct {
	// GetAgentsWithHooksInstalled returns the registry names of all agents
	// whose lifecycle hooks are installed in the current repo.
	GetAgentsWithHooksInstalled func(ctx context.Context) []types.AgentName

	// NewSilentError wraps an error so the cobra root does not double-print it.
	NewSilentError func(err error) error

	// HeadHasReviewCheckpoint checks whether HEAD's checkpoint metadata
	// includes a review session. Returns (true, infoString) if HasReview is set.
	// Injected to avoid an import cycle: review → checkpoint → codex → review.
	HeadHasReviewCheckpoint func(ctx context.Context) (bool, string)

	// ReviewCheckpointContext returns best-effort checkpoint context for the
	// branch review scope. Injected from the cli package because checkpoint
	// readers cannot be imported here without cycling through agent reviewers.
	ReviewCheckpointContext func(ctx context.Context, worktreeRoot string, scopeBaseRef string) string

	// ReviewerFor maps an agent registry name to its AgentReviewer
	// implementation. Returns nil for agents that do not yet have a review-runner
	// adapter. Injected to break the import cycle:
	// per-agent reviewer packages import review (for ComposeReviewPrompt /
	// AppendReviewEnv), so review/cmd.go cannot import them back.
	ReviewerFor func(agentName string) reviewtypes.AgentReviewer

	// PostReviewToTrail posts the final review verdict to the current branch's
	// trail as a finding (the "trail" output destination). Injected from the cli
	// package because the data API + auth live there. It prints its own success
	// line to out. nil when trail delivery is unavailable (e.g. tests), in which
	// case the run falls back to local output with a notice.
	PostReviewToTrail func(ctx context.Context, out io.Writer, profileName, verdict string) error
}

Deps collects the runtime-injectable hooks NewCommand needs from the parent cli package. Tests stub fields to drive branches that would otherwise require a real TTY or enabled repo. Production wiring is provided by buildReviewDeps in cmd/entire/cli/review_bridge.go and passed to NewCommand from root.go.

type DumpSink

type DumpSink struct {
	W io.Writer
}

DumpSink writes per-agent narrative blocks to W after the run completes.

func (DumpSink) AgentEvent

func (DumpSink) AgentEvent(_ string, _ reviewtypes.Event)

AgentEvent is intentionally a no-op. DumpSink renders post-run from the AgentRun.Buffer slices in RunFinished.

func (DumpSink) RunFinished

func (s DumpSink) RunFinished(summary reviewtypes.RunSummary)

RunFinished writes a narrative block per agent, then a counts line.

type LocalReviewManifest added in v0.6.2

type LocalReviewManifest struct {
	Version         int              `json:"version"`
	WorktreePath    string           `json:"worktree_path"`
	CreatedAt       time.Time        `json:"created_at"`
	StartingSHA     string           `json:"starting_sha,omitempty"`
	Sources         []ManifestSource `json:"sources"`
	AggregateOutput string           `json:"aggregate_output,omitempty"`
}

LocalReviewManifest records one local `entire review` invocation. It groups the sibling reviewer outputs from a single review run so `entire review --findings` can render them together.

type ManifestSource added in v0.6.2

type ManifestSource struct {
	SessionID string `json:"session_id"`
	Agent     string `json:"agent"`
	Label     string `json:"label"`
	Status    string `json:"status,omitempty"`
	Output    string `json:"output,omitempty"`
}

type PendingReviewMarker

type PendingReviewMarker struct {
	AgentName string   `json:"agent_name"`
	Skills    []string `json:"skills"`
	// Prompt is the composed review prompt the agent will receive.
	// Stored on the marker (rather than recomputed on adoption) so session
	// metadata records exactly what the agent was asked to do.
	Prompt       string    `json:"prompt,omitempty"`
	StartingSHA  string    `json:"starting_sha"`
	StartedAt    time.Time `json:"started_at"`
	WorktreePath string    `json:"worktree_path,omitempty"`
}

PendingReviewMarker is written by `entire review` before instructing the user to open an agent manually. The marker records which agent and skills should run so that `entire attach --review` can tag the resulting session after the fact.

WorktreePath scopes the marker to the worktree `entire review` was invoked from: multiple worktrees in one repo share .git/entire-sessions/, so without this field any session in any worktree could race to claim the marker. A blank WorktreePath (pre-fix markers) falls back to the legacy unscoped behavior — any session can adopt.

func ReadPendingReviewMarker

func ReadPendingReviewMarker(ctx context.Context) (PendingReviewMarker, bool, error)

ReadPendingReviewMarker returns the marker if one exists. ok=false with err=nil indicates "no pending review."

type ScopeStats

type ScopeStats struct {
	BaseRef       string
	CurrentBranch string // empty for detached HEAD
	Commits       int    // commits unique to current branch vs BaseRef
	FilesChanged  int    // files changed across those commits
	Uncommitted   int    // uncommitted file changes in the working tree
}

ScopeStats summarises the scope of a review for the banner.

func ComputeScopeStats

func ComputeScopeStats(ctx context.Context, repo *git.Repository, baseOverride string) (ScopeStats, error)

ComputeScopeStats gathers the data formatScopeBanner needs. Used to build the banner before launching agents.

baseOverride, if non-empty, bypasses the mainline auto-detection and is used as the scope base directly. This is the entry point for the `--base <ref>` command-line flag. The override is verified via `repo.ResolveRevision(plumbing.Revision(<ref>))` (matching the codebase pattern in explain.go:156) before being used; an unknown ref produces an error before any agents are spawned, so users learn about the typo immediately instead of after a 10-minute review run scoped against a default the flag was supposed to override.

type SynthesisProvider

type SynthesisProvider interface {
	// Synthesize takes the composed synthesis prompt and returns the
	// verdict text. On error the sink prints "final report unavailable" and
	// signals OnError; the command then surfaces an attempted-but-failed
	// synthesis as a non-zero exit (see runMultiAgentPath).
	Synthesize(ctx context.Context, prompt string) (string, error)
}

SynthesisProvider abstracts the LLM call that produces the cross-agent verdict. Injected so tests can stub the provider call without a real API roundtrip; production wiring uses AgentSynthesisProvider.

type SynthesisSink

type SynthesisSink struct {
	Provider SynthesisProvider
	Writer   io.Writer
	// RenderWriter is the writer whose terminal capabilities should be used for
	// markdown rendering. It defaults to Writer. TTY review runs use this when
	// Writer is a post-run buffer that will later flush to the real terminal.
	RenderWriter    io.Writer
	PerRunPrompt    string // if non-empty, included in the synthesis prompt for context
	ProfileName     string
	Task            string
	MasterName      string
	RunContext      context.Context // optional; nil falls back to context.Background()
	ProviderTimeout time.Duration   // positive: use it; zero: defaultSynthesisProviderTimeout; negative: disabled (no deadline)
	OnResult        func(result string)
	OnStart         func()
	OnComplete      func(error)
	// OnError is called when an attempted synthesis fails (provider error or
	// timeout). It is NOT called when synthesis is skipped (cancelled run or
	// fewer than two usable reviewers). Lets the caller surface a missing verdict
	// in the command's exit status instead of exiting 0 with no final report.
	OnError func(error)
}

SynthesisSink composes a multi-agent verdict by calling a configured provider after the run finishes — the profile's master adjudication phase. Provider is the profile master, so the final report is produced unconditionally (no y/N prompt). AgentEvent is a no-op; all work happens in RunFinished.

func (SynthesisSink) AgentEvent

func (SynthesisSink) AgentEvent(_ string, _ reviewtypes.Event)

AgentEvent is a no-op; SynthesisSink only acts in RunFinished.

func (SynthesisSink) RunFinished

func (s SynthesisSink) RunFinished(summary reviewtypes.RunSummary)

RunFinished synthesizes a cross-agent final report.

Skip silently when:

  • the run was cancelled (summary.Cancelled)
  • fewer than 2 successful agents produced usable output

The master phase is mandatory and runs without a y/N prompt, in TTY and redirected output alike. On provider failure: print "final report unavailable: <err>" with the underlying error; the user can still commit.

type TUISink

type TUISink struct {
	// contains filtered or unexported fields
}

TUISink is a Sink that renders a Bubble Tea dashboard. The orchestrator calls AgentEvent/RunFinished from a single goroutine (CU4 serial-dispatch contract); the sink translates each event into a tea.Msg and sends it via Program.Send. Bubble Tea's Send is thread-safe, but we never rely on that property — the serial-dispatch promise means Send is only called from the orchestrator's dispatch goroutine.

Cancellation: cancel is the same context.CancelFunc that controls the orchestrator's run context. The first KeyCtrlC in the dashboard fires this function (guarded by a sync.Once in the model) and switches the dashboard to a "Cancelling agents..." indicator while agents drain; a second KeyCtrlC force-quits without waiting. Out-of-TUI SIGINT routes through the cobra root's context, which cancels the same function — no parallel signal.Notify goroutine is needed here.

func NewTUISink

func NewTUISink(agents []string, cancel context.CancelFunc, output io.Writer, input io.Reader) *TUISink

NewTUISink creates a TUISink wired to cancel for Ctrl+C handling. agents is the ordered list of agent names that will run; the dashboard pre-renders one row per agent so the user sees the full run shape from the first frame. output is the writer the Bubble Tea program renders into (typically cmd.OutOrStdout()). input is the reader Bubble Tea reads keypresses from (typically os.Stdin in production); tests must pass a non-TTY reader (e.g. bytes.NewReader(nil)) so Bubble Tea does not put the inherited terminal into raw mode and corrupt sibling test output.

tea.WithoutSignalHandler keeps SIGINT routing on the cobra root's existing handler (which cancels the run context), so the TUI's KeyCtrlC path and the OS signal path share a single cancel function with no race.

func (*TUISink) AgentEvent

func (s *TUISink) AgentEvent(agent string, ev reviewtypes.Event)

AgentEvent (Sink interface): translate ev into a tea.Msg and Send it to the Bubble Tea program. Implements the serial-dispatch contract: the orchestrator calls this from a single goroutine.

Note: Send is safe to call from goroutines other than the TUI's update loop; Bubble Tea's implementation queues the message internally.

func (*TUISink) FinalPhaseFinished added in v0.7.8

func (s *TUISink) FinalPhaseFinished(err error)

FinalPhaseFinished marks the visible post-run phase complete.

func (*TUISink) FinalPhaseStarted added in v0.7.8

func (s *TUISink) FinalPhaseStarted(name string)

FinalPhaseStarted updates the TUI with a visible post-run phase such as the profile judge consolidating reviewer reports.

func (*TUISink) PostRunComplete added in v0.7.8

func (s *TUISink) PostRunComplete()

PostRunComplete exits the TUI and waits for the Bubble Tea program to finish. Call after post-run sinks have produced any buffered output.

func (*TUISink) RunFinished

func (s *TUISink) RunFinished(summary reviewtypes.RunSummary)

RunFinished (Sink interface): mark reviewer execution complete and send the final summary message. It does not block or exit the TUI: post-run sinks may still run (for example the final judge), and they can update the dashboard via FinalPhaseStarted/FinalPhaseFinished. A later PostRunComplete call exits the TUI once buffered post-run output is ready to flush.

func (*TUISink) Start

func (s *TUISink) Start()

Start spawns the Bubble Tea program in its own goroutine. Must be called before any AgentEvent calls. Subsequent calls are no-ops.

func (*TUISink) Wait

func (s *TUISink) Wait()

Wait blocks until the Bubble Tea program exits. Safe to call after Start. If Start was never called, Wait returns immediately.

Directories

Path Synopsis
Package types defines the per-agent abstraction interfaces for `entire review`.
Package types defines the per-agent abstraction interfaces for `entire review`.

Jump to

Keyboard shortcuts

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