evo

package module
v0.1.0 Latest Latest
Warning

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

Go to latest
Published: Jul 27, 2026 License: Apache-2.0 Imports: 15 Imported by: 0

README

Evident Output

Go presentation library for CLI state, progress, evidence, changes, plans, and conclusions.

Application code owns execution. Package evo owns presentation only.

Quick start

import (
    "os"
    evo "github.com/zachbornheimer/evident-output"
)

func main() {
    out := evo.For("bpp-csharp", evo.WriterOptions(os.Stdout)...)
    os.Exit(evo.Main(out, run))
}

func run(out *evo.Output) error {
    out.Item("working tree").OK()
    out.Item("branches").Block(
        "local-only branch",
        evo.Detail("commit or stash before continuing"),
    )
    return nil // Block is a presentation outcome, not a Go error
}
go get github.com/zachbornheimer/evident-output@v0.1.0
# or @latest once tagged

Requires Go 1.25+. License: Apache-2.0.

evo.Main owns Finish + Close + exit-code mapping so every binary is not six lines of teardown.
evo.WriterOptions(w) turns on Plain + NoColor for non-TTY *os.File (pipes/files) so agent log capture stays free of CSI.

Pick the entity

Shape Use when
Item Check / gate / verdict unit (pass–fail)
Task Work with phases or progress
Tasks Collection of independent tasks (state is derived)
Changes Past-tense durable effects that happened
Plan Dry-run would-happen effects

When both Item and Task fit: prefer Item for pass/fail gates, Task for progress. Multi-gate: resolve every Item, then if out.AnyBlocked() { return nil } before mutation; Main maps ExitCode.

Severity dialect

Outcome Meaning
Warn Soft concern or optional tool missing; command may continue
Block Policy / precondition failed; stop before mutation (evaluation succeeded)
Fail Evaluation failed or required tool/IO failed

Block ≠ Go error. After Block, return nil from run and let Main exit 1.

Child processes

Keep external tool chatter off the live region: set cmd.Stdout / cmd.Stderr to io.Discard, or wrap with out.DebugWriter(). Only domain Line / Item / Task belong in the human UI.

Status

Release: v0.1.0 (module path above; no replace required for consumers).
Architecture spec: v0.5 (design candidate).
Implemented surface: v0.3–v0.4 core (library, interactive VT, debug history/pane, real CLI, hardened MCP, §31 automated rows test-gated). External/manual items remain waived (Windows ConPTY / tmux / SSH RC, a11y contrast / screen-reader, host RC matrices and a11y manual reviews).

Ready now External / manual only
Items, Task, Tasks, Changes, Plan, Line Windows ConPTY RC (PORT-003)
Conclusion + exit codes + Cancel cleanup tmux RC (PORT-004)
Plain, JSON (§25.1), JSONL (§25.2) SSH RC (PORT-005)
Interactive live region (testkit.Screen) Light/dark contrast review (A11Y-006)
SlogHandler, DebugWriter, Suspend, Snapshots(), MaxEntities, MaxEvents, AlsoWrite Screen-reader review (A11Y-007)
Appendix H.1–H.22 + agent harness + multi-file GoPackage review
ANSI driver + width/CJK + OSC strip + s390x cross-compile
CLI: review / preview / explain (real JSON)
MCP: lifecycle, protocol negotiate, unknown-field reject, panic contain, token budget, remote-path reject, catalog checksum
Framework adapter examples (urfave/Kong shapes, no core deps)

Vocabulary

Type Meaning
Item Named condition that stays in the final report
Task One operation (phase / progress / done)
Tasks Collection of independent tasks (state is derived)
Problem Structured evidence for warn / block / fail
Changes / Plan Effects that happened vs would happen
Conclusion Headline + Changed / Partial / Cancelled + exit code
Main Finish + Close + process exit code for CLI entrypoints

Do not put schedulers, RunAll, retries, or shell execution in this library. Review rule API-026 flags those helpers only on evo receivers (AST), not strings.Map.

Develop

mise run setup    # go mod download
mise run test     # unit + roast
mise run test-race
mise run conformance
mise run traceability   # all §31 IDs present
mise run ci             # lint + test + scan + conformance + traceability

Trunk is configured daemonless (--monitor=false). Prefer mise over raw tools.

Conformance (roast)

conformance/ is the executable specification (Raku/roast model):

  • TRACEABILITY.md — all 272 §31 IDs dispositioned (267 pass, 5 waived with reason + owner for external/manual only; 0 untested)
  • schema/scenario.v1.json — declarative scenario dialect
  • scenarios/*.json + Go Appendix H tests (appendix_h_test.go)

Architecture source (current design candidate): docs/architecture/EVIDENT_OUTPUT_ARCHITECTURE_SPEC_v0.5.md.
Prior implemented baseline: docs/architecture/EVIDENT_OUTPUT_ARCHITECTURE_SPEC_v0.3.md.

Completeness vs §31 (v0.3 matrix): docs/architecture/COMPLETENESS_MATRIX.md (267 pass / 5 waived).

CLI
go run ./cmd/evident-output review path/to/file.go   # JSON findings (exit 1 if recheck_required)
go run ./cmd/evident-output preview --item=status --state=ok
go run ./cmd/evident-output explain API-006
go run ./cmd/evident-output version
MCP (stdio)

The companion server evident-output-mcp is a local stdio MCP process (no hosted URL). Stdin/stdout are JSON-RPC only; logs go to stderr. Transport supports NDJSON (MCP spec) and Content-Length framing (some client SDKs).

Advertised tool names use underscores (Grok rejects dotted tool names and then registers tool_count: 0). Dotted aliases still work on tools/call.

Tool name (tools/list) Grok use_tool id Purpose
evident_output_list_guides evident-output__evident_output_list_guides Guidance catalog
evident_output_get_guidance evident-output__evident_output_get_guidance Sections by id
evident_output_review evident-output__evident_output_review Go / transcript / JSON review
evident_output_preview evident-output__evident_output_preview Plain profile previews
evident_output_explain evident-output__evident_output_explain Rule id (rule_id)

explain arguments: { "rule_id": "DOM-011" } (not id).

Install the binary (full paths)
mkdir -p "$HOME/.local/bin"

# Preferred when cloned on this Mac:
go build -o "$HOME/.local/bin/evident-output-mcp" \
  "$HOME/Developer/Personal/evident-output/cmd/evident-output-mcp"

# From any clone (relative only after cd into the repo root):
#   git clone https://github.com/zachbornheimer/evident-output.git
#   cd evident-output && go build -o "$HOME/.local/bin/evident-output-mcp" ./cmd/evident-output-mcp

# Module install (network + sumdb):
#   GOBIN="$HOME/.local/bin" go install \
#     github.com/zachbornheimer/evident-output/cmd/evident-output-mcp@latest

"$HOME/.local/bin/evident-output-mcp" --version

Host configs must use an absolute command (or ${HOME}/… where the host expands it). Bare evident-output-mcp fails when the agent process PATH omits ~/.local/bin.

Verify without restarting an existing TUI session
# Process-level handshake
grok mcp doctor evident-output --json
# expect: healthy=true, "5 tools discovered", protocol 2025-06-18

# Fresh agent process (same attach path as the TUI)
grok -p 'Call use_tool on evident-output__evident_output_list_guides with {}. Reply CONNECTED and the text field, or FAILED.' \
  --output-format plain \
  --max-turns 5 \
  --always-approve \
  --cwd "$HOME/Developer/Personal/evident-output"
# expect: CONNECTED / "5 guides"

If doctor is green but headless says FAILED, check session events.jsonl for mcp_server_connected with "tool_count":0 (tool names/schemas rejected) vs mcp_server_failed (spawn/handshake).

NDJSON smoke (no Grok required):

printf '%s\n' \
  '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-06-18","capabilities":{},"clientInfo":{"name":"manual","version":"0"}}}' \
  '{"jsonrpc":"2.0","method":"notifications/initialized"}' \
  '{"jsonrpc":"2.0","id":2,"method":"tools/list","params":{}}' \
  | "$HOME/.local/bin/evident-output-mcp" 2>/dev/null
Host config snippets (print-only)
"$HOME/.local/bin/evident-output-mcp" config --client grok
# also: claude-code|codex|gemini|opencode  — uses ${HOME}/.local/bin/…

Integrations: integrations/ · skill: skills/cli-output/SKILL.md

Grok (xAI TUI / Build)
# $HOME/.grok/config.toml  (${HOME} expanded by Grok)
[mcp_servers.evident-output]
command = "${HOME}/.local/bin/evident-output-mcp"
enabled = true
startup_timeout_sec = 30
grok mcp add evident-output -- "$HOME/.local/bin/evident-output-mcp"
grok mcp list
grok mcp doctor evident-output --json

Project scope only starts when the folder is trusted. Prefer user scope for always-on tools.

See integrations/grok/README.md.

Claude Code / Cursor / Codex
"$HOME/.local/bin/evident-output-mcp" config --client claude-code
"$HOME/.local/bin/evident-output-mcp" config --client codex

Review kinds for evident_output_review: go (default), transcript, json / structured.

Examples

Small real programs (flags, help, exit codes) — not snippets. Copy a whole folder as a starting shape.

Example Pattern
repo-status Parallel Items (OK / blocked / warn), conclusion exit code
install-pipeline Tasks collection with Progress/Bytes/Fail (final report)
migrate Plan dry-run vs Changes apply (--apply)
doctor Mixed doctor items; --json snapshot on stdout
data-command Data command: JSON stdout, human report stderr
live-progress Live multi-progress: bars + indeterminate phases (ANSI on stderr)
debug-history DebugHistory: durable HH:MM:SS [DEBUG] … above live/items
debug-pane DebugPane: rolling slog pane; --fail keeps diagnostics tail
mise run examples                          # all, back-to-back with headers
go run ./examples/repo-status/ --name my-app
go run ./examples/install-pipeline/
go run ./examples/migrate/                 # dry-run plan
go run ./examples/migrate/ --apply
go run ./examples/doctor/ --json | jq .conclusion
go run ./examples/data-command/ 2>/dev/null | jq .
go run ./examples/live-progress/              # in-place ANSI live region (real TTY)
go run ./examples/live-progress/ --frames     # numbered frames you can scroll
go run ./examples/debug-history/              # history-mode debug interleave
go run ./examples/debug-pane/                 # pane removed on success
go run ./examples/debug-pane/ --fail          # failure preserves diagnostics tail

# mise run examples: uses live ANSI when stderr is a TTY; --frames otherwise.
# EVO_EXAMPLES_FRAMES=1 mise run examples   # force scrubable frames in the batch
Machine output
snap := out.Snapshot()
plain, _ := evo.RenderPlain(snap, evo.PlainOptions{Width: 80})
jsonBytes, _ := evo.EncodeJSON(snap)
jsonl, _ := evo.EncodeJSONL(out.Events())

Schemas: schema/output.v1.json, schema/event.v1.json.

Production ANSI driver
import "github.com/zachbornheimer/evident-output/terminal"

drv := terminal.NewANSI(os.Stderr, terminal.WithInteractive(true), terminal.WithSize(80, 24))
out := evo.New(evo.Terminal(drv))
Interactive (testkit / virtual terminal)
screen := testkit.NewScreen(testkit.Interactive(), testkit.Width(80), testkit.NoColor())
clock := testkit.NewClock()
out := evo.New(
    evo.Terminal(screen),
    evo.Clock(clock),
    evo.VisibilityDelay(150*time.Millisecond),
    evo.MaxFrameRate(20),
)
// Phase/Progress draw a live region; instant Done before the threshold does not flash.
// DebugHistory (default): out.Debug → durable above live (timestamp + [DEBUG]).
// DebugPane(...): rolling slog viewport in the live region; optional failure tail.

Contributing

See CONTRIBUTING.md (DCO sign-off). Red test → green → refactor. Small conventional commits.

Documentation

Overview

Package evo is Evident Output: a presentation library for CLI state, progress, evidence, changes, plans, messages, actions, and conclusions.

Application code owns execution. Evo owns presentation.

func main() {
    out := evo.For("repo", evo.WriterOptions(os.Stdout)...)
    os.Exit(evo.Main(out, run))
}

func run(out *evo.Output) error {
    out.Item("working tree").OK()
    return nil
}

Index

Constants

View Source
const (
	ExitOK        = 0
	ExitBlocked   = 1
	ExitFailed    = 2
	ExitCancelled = 130
)

Default exit codes from architecture §26.

View Source
const Debug = LevelDebug

Debug is the debug log level (Appendix H).

View Source
const EventSchemaVersion = "1.0"

EventSchemaVersion is the durable event schema version (§25.2).

View Source
const JSONSchemaVersion = "1.0"

JSONSchemaVersion is the final JSON document schema version (§25.1).

Variables

View Source
var (
	ErrClosed             = errors.New("evo: output is closed")
	ErrAlreadyResolved    = errors.New("evo: entity is already resolved")
	ErrNoProblems         = errors.New("evo: structured resolution requires problems")
	ErrUnresolvedItem     = errors.New("evo: item has no final state")
	ErrUnresolvedTask     = errors.New("evo: task has no final state")
	ErrInvalidProgress    = errors.New("evo: invalid progress")
	ErrProgressRegression = errors.New("evo: progress moved backward")
	ErrDuplicateKey       = errors.New("evo: duplicate entity key")
	ErrInvalidConfig      = errors.New("evo: invalid configuration")
	ErrRenderer           = errors.New("evo: renderer failure")
	ErrFinishing          = errors.New("evo: output is finishing")
	ErrLimitExceeded      = errors.New("evo: resource limit exceeded")
)

Sentinel misuse and lifecycle errors recorded by the output aggregate.

Functions

func EncodeJSON

func EncodeJSON(s Snapshot, _ ...JSONOptions) ([]byte, error)

EncodeJSON encodes a snapshot as final JSON (§25.1 / §25.4).

func EncodeJSONL

func EncodeJSONL(events []Event, _ ...JSONLOptions) ([]byte, error)

EncodeJSONL encodes durable events as JSON Lines (§25.2 / §25.4).

func IsCharDevice

func IsCharDevice(w io.Writer) bool

IsCharDevice reports whether w is an *os.File backed by a character device (typical interactive TTY). Pipes, files, and non-file writers return false.

Use when choosing Plain / NoColor defaults so agents capturing CLI output do not get ANSI noise.

func Main

func Main(out *Output, run func(*Output) error) int

Main runs a CLI presentation lifecycle and returns the process exit code.

Typical entrypoint:

func main() {
    out := evo.For("tool", evo.To(os.Stdout))
    os.Exit(evo.Main(out, run))
}

func run(out *evo.Output) error {
    out.Item("working tree").OK()
    return nil
}

Lifecycle: run → Finish → Close (via defer).

Exit codes:

  • nil out → ExitFailed (2)
  • Finish error (presentation misuse / render) → ExitFailed (2)
  • run error while conclusion is still OK → ExitFailed (2)
  • otherwise Conclusion.ExitCode (OK=0, Blocked=1, Failed=2, Cancelled=130)

Application code still owns execution; Main only seals presentation and maps conclusion state to an exit code so every binary does not reimplement teardown.

func RenderPlain

func RenderPlain(s Snapshot, opts PlainOptions) ([]byte, error)

RenderPlain projects a snapshot to plain text without terminal ownership.

Types

type Action

type Action struct {
	Label                string
	Command              *CommandSpec
	URL                  string
	File                 string
	Explanation          string
	RequiresConfirmation bool
	Destructive          bool
}

Action is a recommended next step for the user.

func Command

func Command(executable string, args ...string) Action

Command builds an action with an executable and arguments. Display-bound strings are sanitized at construction.

type CapabilityProfile

type CapabilityProfile struct {
	Interactive bool
	Color       ColorLevel
	Unicode     bool
	Width       int
	Height      int
	NoColor     bool
}

CapabilityProfile holds terminal capability facts (§22).

func DetectCapabilities

func DetectCapabilities(opts ...Option) CapabilityProfile

DetectCapabilities builds a profile from options and environment-like hints. It does not read the real environment in the core package without injection; callers pass NoColor/Width/NonInteractive options instead.

type Changes

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

Changes is a handle for durable effects that already occurred.

func (*Changes) Added

func (c *Changes) Added(quantity int64, object string) *Changes

Added records an added quantity.

func (*Changes) Created

func (c *Changes) Created(object string) *Changes

Created records a created object.

func (*Changes) Moved

func (c *Changes) Moved(source, destination string) *Changes

Moved records a move.

func (*Changes) Record

func (c *Changes) Record(verb string, quantity int64, object string) *Changes

Record records a verb/quantity/object effect.

func (*Changes) Removed

func (c *Changes) Removed(quantity int64, object string) *Changes

Removed records a removed quantity.

func (*Changes) Reused

func (c *Changes) Reused(quantity int64, object string) *Changes

Reused records a reused quantity.

func (*Changes) Updated

func (c *Changes) Updated(quantity int64, object string) *Changes

Updated records an updated quantity.

func (*Changes) Wrote

func (c *Changes) Wrote(object string) *Changes

Wrote records a written object.

type ChangesSnapshot

type ChangesSnapshot struct {
	ID      string
	Subject string
	Records []EffectRecord
}

ChangesSnapshot is an immutable changes section.

type ColorLevel

type ColorLevel int

ColorLevel describes terminal color support.

const (
	ColorNone ColorLevel = iota
	ColorBasic
	Color256
	ColorTrue
)

type CommandSpec

type CommandSpec struct {
	Executable string
	Args       []string
	WorkingDir string
}

CommandSpec is an executable plus argv (never a shell string).

type Conclusion

type Conclusion struct {
	State       ConclusionState
	Subject     string
	Changed     bool
	Partial     bool
	Cancelled   bool
	Explanation string
	Items       []ItemSnapshot
	Tasks       []TaskSnapshot
	Collections []TasksSnapshot
	Changes     []ChangesSnapshot
	Plans       []PlanSnapshot
	Actions     []Action
	ExitCode    int
}

Conclusion is the multidimensional meaning of a finished command.

func (Conclusion) AnyBlocked

func (c Conclusion) AnyBlocked() bool

AnyBlocked reports whether the finished conclusion is blocked, or any item snapshot is.

type ConclusionJSON

type ConclusionJSON struct {
	State       ConclusionState `json:"state"`
	Changed     bool            `json:"changed"`
	Partial     bool            `json:"partial"`
	Cancelled   bool            `json:"cancelled"`
	ExitCode    int             `json:"exit_code"`
	Explanation string          `json:"explanation,omitempty"`
}

ConclusionJSON is JSON-friendly conclusion.

type ConclusionState

type ConclusionState string

ConclusionState is the human headline for a finished output.

const (
	StateReady     ConclusionState = "ready"
	StateChanged   ConclusionState = "changed"
	StateUnchanged ConclusionState = "unchanged"
	StateWarning   ConclusionState = "warning"
	StateBlocked   ConclusionState = "blocked"
	StateFailed    ConclusionState = "failed"
	StateCancelled ConclusionState = "cancelled"
	StatePlanned   ConclusionState = "planned"
	StatePartial   ConclusionState = "partial"
)

type Config

type Config struct {
	Subject      string
	Primary      io.Writer
	Diagnostic   io.Writer
	Projection   ProjectionPolicy
	Clock        TimeSource
	Redactor     Redactor
	Capabilities *CapabilityProfile
	Strict       bool
	Plain        bool
	NoColor      bool
	Width        int
}

Config is advanced construction for tests and embedding.

type DebugPaneOption

type DebugPaneOption interface {
	// contains filtered or unexported methods
}

DebugPaneOption configures DebugPane presentation.

func NewestFirst

func NewestFirst() DebugPaneOption

NewestFirst orders the pane with the most recent record first (default).

func OldestFirst

func OldestFirst() DebugPaneOption

OldestFirst orders the pane chronologically (oldest visible first).

func PaneHeight

func PaneHeight(lines int) DebugPaneOption

PaneHeight sets how many debug records are visible in the pane (not including heading).

func PreserveDebugTail

func PreserveDebugTail() DebugPaneOption

PreserveDebugTail always emits a bounded diagnostic tail under the final report. Without this, pane mode still preserves a tail on failed/blocked/cancelled conclusions.

type DebugPresentation

type DebugPresentation int

DebugPresentation selects how structured debug records project to a TTY (§4.6 / §21.3).

const (
	// DebugPresentationHistory appends durable scrollback above the live region (default).
	DebugPresentationHistory DebugPresentation = iota
	// DebugPresentationPane keeps a bounded rolling viewport inside the live region.
	DebugPresentationPane
)

type EffectRecord

type EffectRecord struct {
	Verb     string
	Quantity int64
	HasQty   bool
	Object   string
}

EffectRecord is one semantic change or plan row.

type EntityState

type EntityState string

EntityState is the lifecycle state of an item or task.

const (
	Pending    EntityState = "pending"
	Running    EntityState = "running"
	OK         EntityState = "ok"
	Done       EntityState = "done"
	Warning    EntityState = "warning"
	Blocked    EntityState = "blocked"
	Failed     EntityState = "failed"
	Unknown    EntityState = "unknown"
	Skipped    EntityState = "skipped"
	Cancelled  EntityState = "cancelled"
	Empty      EntityState = "empty"
	Incomplete EntityState = "incomplete"
)

type Event

type Event struct {
	SchemaVersion string
	Sequence      uint64
	Timestamp     time.Time
	Type          string
	OutputID      string
	EntityID      string
	Name          string
	State         string
	Completed     *int64
	Total         *int64
	Activation    string
	Payload       map[string]any
}

Event is an immutable journal record.

type EventJSON

type EventJSON struct {
	SchemaVersion string    `json:"schema_version"`
	Sequence      uint64    `json:"sequence"`
	Type          string    `json:"type"`
	OutputID      string    `json:"output_id,omitempty"`
	EntityID      string    `json:"entity_id,omitempty"`
	Name          string    `json:"name,omitempty"`
	State         string    `json:"state,omitempty"`
	Completed     *int64    `json:"completed,omitempty"`
	Total         *int64    `json:"total,omitempty"`
	Activation    string    `json:"activation,omitempty"`
	Timestamp     time.Time `json:"timestamp,omitempty"`
}

EventJSON is a JSON Lines event record (§25.2).

type Evidence

type Evidence struct {
	Label string
	Value string
}

Evidence is an additional problem attachment.

type Field

type Field struct {
	Key       string
	Value     any
	Sensitive bool
}

Field is a structured diagnostic or log field.

func Duration

func Duration(key string, value interface{ String() string }) Field

Duration builds a duration diagnostic field.

func Int

func Int(key string, value int) Field

Int builds an integer diagnostic field.

func String

func String(key, value string) Field

String builds a string diagnostic field.

type FixedClock

type FixedClock struct {
	T time.Time
}

FixedClock always returns the same instant.

func (FixedClock) Now

func (c FixedClock) Now() time.Time

Now returns the fixed instant.

type Item

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

Item is a handle for one named final-report condition.

func (*Item) Because

func (i *Item) Because(text string) *Item

Because annotates an explanation after resolution.

func (*Item) Block

func (i *Item) Block(summary string, options ...ProblemOption) *Item

Block marks the item blocked with a simple problem.

func (*Item) BlockedBy

func (i *Item) BlockedBy(problems ...Problem) *Item

BlockedBy marks the item blocked with structured problems.

func (*Item) Fail

func (i *Item) Fail(summary string, options ...ProblemOption) *Item

Fail marks the item failed with a simple problem.

func (*Item) FailedBy

func (i *Item) FailedBy(problems ...Problem) *Item

FailedBy marks the item failed with structured problems.

func (*Item) Next

func (i *Item) Next(actions ...Action) *Item

Next attaches actions.

func (*Item) NextCommand

func (i *Item) NextCommand(executable string, args ...string) *Item

NextCommand attaches a command action.

func (*Item) OK

func (i *Item) OK() *Item

OK marks the item satisfactory.

func (*Item) Skip

func (i *Item) Skip(reason string) *Item

Skip marks the item skipped.

func (*Item) Snapshot

func (i *Item) Snapshot() ItemSnapshot

Snapshot returns the item's current snapshot.

func (*Item) Start

func (i *Item) Start() *Item

Start marks the item running so it becomes visible in the live region (indeterminate) while the application evaluates it. Optional: OK/Block/… may resolve pending items directly without Start (no transient frame when resolution is instant — §7.4 rule 5).

func (*Item) Unknown

func (i *Item) Unknown(summary string, options ...ProblemOption) *Item

Unknown marks the item undetermined.

func (*Item) Warn

func (i *Item) Warn(summary string, options ...ProblemOption) *Item

Warn marks the item with a simple warning problem.

func (*Item) WarnedBy

func (i *Item) WarnedBy(problems ...Problem) *Item

WarnedBy marks the item warning with structured problems.

type ItemSnapshot

type ItemSnapshot struct {
	ID          string
	Name        string
	State       EntityState
	Problems    []Problem
	Because     string
	Actions     []Action
	Declaration int
}

ItemSnapshot is an immutable item view.

type ItemSpec

type ItemSpec struct {
	Key         string
	Name        string
	Description string
	Order       int
	Hidden      bool
	ManualStart bool
}

ItemSpec is advanced item construction (§11.3).

type JSONAction

type JSONAction struct {
	Label   string       `json:"label,omitempty"`
	Command *JSONCommand `json:"command,omitempty"`
	URL     string       `json:"url,omitempty"`
}

JSONAction is a wire-format action.

type JSONChanges

type JSONChanges struct {
	ID      string             `json:"id"`
	Subject string             `json:"subject"`
	Records []JSONEffectRecord `json:"records"`
}

JSONChanges is wire-format changes.

type JSONCollection

type JSONCollection struct {
	ID       string      `json:"id"`
	Name     string      `json:"name"`
	State    EntityState `json:"state"`
	Summary  string      `json:"summary,omitempty"`
	Children []string    `json:"children"`
}

JSONCollection is a wire-format task collection with child IDs (§25.1).

type JSONCommand

type JSONCommand struct {
	Executable string   `json:"executable"`
	Args       []string `json:"args,omitempty"`
}

JSONCommand is argv for display.

type JSONDocument

type JSONDocument struct {
	SchemaVersion   string           `json:"schema_version"`
	Output          JSONOutputMeta   `json:"output"`
	Conclusion      ConclusionJSON   `json:"conclusion"`
	Items           []JSONItem       `json:"items"`
	TaskCollections []JSONCollection `json:"task_collections"`
	Tasks           []JSONTask       `json:"tasks"`
	Changes         []JSONChanges    `json:"changes"`
	Plans           []JSONPlan       `json:"plans"`
	Actions         []JSONAction     `json:"actions"`
}

JSONDocument is the final machine projection (§25.1).

type JSONEffectRecord

type JSONEffectRecord struct {
	Verb     string `json:"verb"`
	Quantity *int64 `json:"quantity,omitempty"`
	Object   string `json:"object"`
}

JSONEffectRecord is a change/plan row.

type JSONItem

type JSONItem struct {
	ID       string        `json:"id"`
	Name     string        `json:"name"`
	State    EntityState   `json:"state"`
	Problems []JSONProblem `json:"problems"`
	Because  string        `json:"because,omitempty"`
}

JSONItem is a wire-format item.

type JSONLOptions

type JSONLOptions struct{}

JSONLOptions reserves future encode knobs.

type JSONOptions

type JSONOptions struct{}

JSONOptions reserves future encode knobs.

type JSONOutputMeta

type JSONOutputMeta struct {
	ID      string `json:"id"`
	Subject string `json:"subject,omitempty"`
}

JSONOutputMeta identifies the output instance.

type JSONPlan

type JSONPlan struct {
	ID      string             `json:"id"`
	Subject string             `json:"subject"`
	Records []JSONEffectRecord `json:"records"`
}

JSONPlan is wire-format plan.

type JSONProblem

type JSONProblem struct {
	Subject string `json:"subject,omitempty"`
	Summary string `json:"summary,omitempty"`
	Detail  string `json:"detail,omitempty"`
	Count   int64  `json:"count,omitempty"`
	Unit    string `json:"unit,omitempty"`
	Code    string `json:"code,omitempty"`
}

JSONProblem is a wire-format problem (no raw Cause by default).

type JSONProgress

type JSONProgress struct {
	Kind      ProgressKind `json:"kind"`
	Completed int64        `json:"completed"`
	Total     int64        `json:"total"`
}

JSONProgress is wire-format progress.

type JSONTask

type JSONTask struct {
	ID       string        `json:"id"`
	Name     string        `json:"name"`
	State    EntityState   `json:"state"`
	Phase    string        `json:"phase,omitempty"`
	Summary  string        `json:"summary,omitempty"`
	Progress *JSONProgress `json:"progress,omitempty"`
	Problems []JSONProblem `json:"problems,omitempty"`
}

JSONTask is a wire-format task.

type LiveSurface

type LiveSurface interface {
	TerminalDriver
	Columns() int
	Rows() int
	IsInteractive() bool
	WriteLive(text string)
	ClearLive()
	WriteDurable(line string)
	WriteFinal(text string)
}

LiveSurface is an interactive terminal sink for live-region rendering. testkit.Screen implements this; production drivers can as well.

type Location

type Location struct {
	Path   string
	Line   int
	Column int
}

Location is a path-based source position.

type LogLevel

type LogLevel int

LogLevel is a diagnostic severity.

const (
	LevelTrace LogLevel = iota
	LevelDebug
	LevelInfo
	LevelWarn
	LevelError
)

type NoopRedactor

type NoopRedactor struct{}

NoopRedactor leaves strings unchanged.

func (NoopRedactor) RedactString

func (NoopRedactor) RedactString(s string) string

RedactString implements Redactor.

type Option

type Option interface {
	// contains filtered or unexported methods
}

Option configures an Output.

func AlsoWrite

func AlsoWrite(w io.Writer) Option

AlsoWrite adds an additional human projection writer. On Finish, each writer receives the plain projection; failures on one do not skip the others (CON-009).

func Clock

func Clock(ts TimeSource) Option

Clock injects a time source facade.

func DataProjection

func DataProjection() Option

DataProjection selects data-command mode (UI/progress on diagnostic stream).

func DebugHistory

func DebugHistory() Option

DebugHistory selects durable append-above-and-redraw presentation (v0.4 default).

func DebugLevel

func DebugLevel(level LogLevel) Option

DebugLevel sets the minimum debug emission level.

func DebugPane

func DebugPane(opts ...DebugPaneOption) Option

DebugPane selects a rolling TTY debug viewport at the bottom of the live region.

func Diagnostics

func Diagnostics(w io.Writer) Option

Diagnostics sets the diagnostic writer.

func ExternalProjection

func ExternalProjection() Option

ExternalProjection selects snapshot-only host rendering.

func MaxEntities

func MaxEntities(n int) Option

MaxEntities caps total items and tasks for one Output (0 uses default).

func MaxEvents

func MaxEvents(n int) Option

MaxEvents caps durable journal events; when exceeded, oldest non-critical events are dropped so critical terminal events are retained (CON-008).

func MaxFrameRate

func MaxFrameRate(framesPerSecond int) Option

MaxFrameRate caps interactive redraws per second.

func NoColor

func NoColor() Option

NoColor disables color.

func NonInteractive

func NonInteractive() Option

NonInteractive disables live interactive frames.

func Plain

func Plain() Option

Plain forces final-report projection (no live spinner region). Semantic color is still emitted unless NoColor is set.

func Redact

func Redact(r Redactor) Option

Redact injects a redactor (applied to Debug/Line/problem detail paths).

func Strict

func Strict() Option

Strict enables panic-on-misuse for tests.

func Terminal

func Terminal(driver TerminalDriver) Option

Terminal injects a terminal driver (interactive projection; v0.2).

func To

func To(w io.Writer) Option

To sets the primary human writer.

func VisibilityDelay

func VisibilityDelay(delay time.Duration) Option

VisibilityDelay sets the spinner visibility threshold.

func Width

func Width(columns int) Option

Width sets the terminal width in columns.

func WriterOptions

func WriterOptions(w io.Writer, extra ...Option) []Option

WriterOptions returns presentation options appropriate for human writer w.

On a TTY: color allowed (unless NO_COLOR is set by the process environment — callers that want env policy should pass NoColor themselves or use examples/demo). Off-TTY (pipe, file, bytes.Buffer is NOT auto-detected here): when w is an *os.File that is not a char device, returns Plain + NoColor so piped logs stay free of CSI. Non-file writers (buffers, multi-writers) are left unchanged so tests can still assert color rendering.

Always includes To(w). Extra options are appended and win over defaults when they conflict (last Option applied in New/For order — pass extra after).

type Output

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

Output is the aggregate root for one command's presentation lifecycle.

func For

func For(subject string, options ...Option) *Output

For creates an Output for a subject.

func New

func New(options ...Option) *Output

New creates an Output without a primary subject.

func NewWithConfig

func NewWithConfig(cfg Config) (*Output, error)

NewWithConfig builds an Output from advanced configuration.

func (*Output) AnyBlocked

func (o *Output) AnyBlocked() bool

AnyBlocked reports whether any Item is currently in the Blocked state. Use before mutation: if out.AnyBlocked() { return nil } then Finish via Main.

func (*Output) AnyFailed

func (o *Output) AnyFailed() bool

AnyFailed reports whether any Item or Task is currently Failed.

func (*Output) Cancel

func (o *Output) Cancel(reason string)

Cancel records output-level cancellation via a synthetic cancelled task.

func (*Output) Changes

func (o *Output) Changes(subject string) *Changes

Changes starts a durable-effects section.

func (*Output) Close

func (o *Output) Close() error

Close is idempotent cleanup; best-effort Finish when needed.

func (*Output) Conclusion

func (o *Output) Conclusion() Conclusion

Conclusion returns the computed conclusion after Finish.

func (*Output) Debug

func (o *Output) Debug(message string, fields ...Field)

Debug records a structured diagnostic (§4.6 / §21.3).

History mode (default): durable scrollback above the live region (or plain stream). Pane mode: record is journaled and shown in the rolling live pane; not durable scrollback unless a diagnostic tail is preserved at Finish.

func (*Output) DebugWriter

func (o *Output) DebugWriter() io.WriteCloser

DebugWriter returns a line-oriented writer that emits Debug lines on newline. Partial UTF-8 sequences are buffered; control bytes are sanitized.

func (*Output) Err

func (o *Output) Err() error

Err returns the first recorded misuse error, if any.

func (*Output) ErrorMessage

func (o *Output) ErrorMessage(message string, _ ...Field)

ErrorMessage emits an error durable line (not an item failure).

func (*Output) Events

func (o *Output) Events() []Event

Events returns a copy of durable events (v0.1 journal).

func (*Output) Explain

func (o *Output) Explain(text string)

Explain sets an explicit conclusion explanation (applied at Finish).

func (*Output) Fail

func (o *Output) Fail(summary string, options ...ProblemOption)

Fail records an output-level failure.

func (*Output) FinalPlain

func (o *Output) FinalPlain() string

FinalPlain returns the last rendered plain text after Finish.

func (*Output) Finish

func (o *Output) Finish() error

Finish validates, computes conclusion, emits final projections. Projection I/O runs outside the domain lock (§17.1).

func (*Output) Info

func (o *Output) Info(message string, _ ...Field)

Info emits an informational durable line.

func (*Output) Item

func (o *Output) Item(name string) *Item

Item declares a named final-report condition.

func (*Output) ItemWith

func (o *Output) ItemWith(spec ItemSpec) (*Item, error)

ItemWith declares an item using advanced specification (keys/order).

func (*Output) Line

func (o *Output) Line(message string)

Line emits a durable user-facing line immediately (not buffered until Finish).

func (*Output) Linef

func (o *Output) Linef(format string, args ...any)

Linef formats and emits a durable user-facing line.

func (*Output) Next

func (o *Output) Next(actions ...Action)

Next attaches output-level actions.

func (*Output) NextCommand

func (o *Output) NextCommand(executable string, args ...string)

NextCommand attaches an output-level command action.

func (*Output) Plan

func (o *Output) Plan(subject string) *Plan

Plan starts a would-occur effects section.

func (*Output) SlogHandler

func (o *Output) SlogHandler(min slog.Leveler) slog.Handler

SlogHandler returns a slog.Handler that routes records through Output.Debug/Info lines.

func (*Output) Snapshot

func (o *Output) Snapshot() Snapshot

Snapshot returns an immutable copy of current state.

func (*Output) Snapshots

func (o *Output) Snapshots() <-chan Snapshot

Snapshots returns a buffered channel of immutable snapshots. The channel is closed when the output is closed or finished. Callers should not block the library; buffer absorbs bursts.

func (*Output) Suspend

func (o *Output) Suspend(fn func() error) error

Suspend temporarily pauses interactive presentation for host-owned output. In v0.3 plain/non-interactive mode this is a no-op around fn. With a live surface it clears the live region, runs fn, then resumes.

func (*Output) Task

func (o *Output) Task(name string) *Task

Task declares a single operation.

func (*Output) Tasks

func (o *Output) Tasks(name string) *Tasks

Tasks declares a collection of independent child tasks.

func (*Output) WarnMessage

func (o *Output) WarnMessage(message string, _ ...Field)

WarnMessage emits a warning durable line (not an item warning).

type PlainOptions

type PlainOptions struct {
	Width          int
	NoColor        bool
	NonInteractive bool
}

PlainOptions configures pure plain projection (§25.4).

type Plan

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

Plan is a handle for effects that would occur but have not.

func (*Plan) Add

func (p *Plan) Add(quantity int64, object string) *Plan

Add records a planned addition.

func (*Plan) Create

func (p *Plan) Create(object string) *Plan

Create records a planned create.

func (*Plan) Delete

func (p *Plan) Delete(quantity int64, object string) *Plan

Delete records a planned deletion.

func (*Plan) Move

func (p *Plan) Move(source, destination string) *Plan

Move records a planned move.

func (*Plan) Record

func (p *Plan) Record(verb string, quantity int64, object string) *Plan

Record records a planned verb/quantity/object.

func (*Plan) Remove

func (p *Plan) Remove(quantity int64, object string) *Plan

Remove records a planned removal.

func (*Plan) Retain

func (p *Plan) Retain(description string) *Plan

Retain records a planned retention note.

func (*Plan) Revoke

func (p *Plan) Revoke(quantity int64, object string) *Plan

Revoke records a planned revocation.

func (*Plan) Update

func (p *Plan) Update(quantity int64, object string) *Plan

Update records a planned update.

func (*Plan) Write

func (p *Plan) Write(object string) *Plan

Write records a planned write.

type PlanSnapshot

type PlanSnapshot struct {
	ID      string
	Subject string
	Records []EffectRecord
}

PlanSnapshot is an immutable plan section.

type Problem

type Problem struct {
	Code      string
	Subject   string
	Summary   string
	Detail    string
	Severity  string
	Count     int64
	Unit      string
	Location  *Location
	Evidence  []Evidence
	Actions   []Action
	Fields    []Field
	Cause     error
	Sensitive bool
}

Problem is structured evidence explaining a negative item or task outcome.

type ProblemOption

type ProblemOption interface {
	// contains filtered or unexported methods
}

ProblemOption configures a problem constructed by Block/Warn/Fail helpers.

func At

func At(path string, line, column int) ProblemOption

At sets a source location.

func Cause

func Cause(err error) ProblemOption

Cause attaches a diagnostic error (not shown by default in human output).

func Code

func Code(value string) ProblemOption

Code sets a stable problem code.

func Count

func Count(value int64, unit ...string) ProblemOption

Count sets a quantity and optional unit.

func Detail

func Detail(text string) ProblemOption

Detail sets user-visible detail text (strings only).

func Next

func Next(action Action) ProblemOption

Next attaches actions to a problem.

func NextCommand

func NextCommand(executable string, args ...string) ProblemOption

NextCommand attaches a recommended command action.

func On

func On(subject string) ProblemOption

On sets the problem subject.

type Progress

type Progress struct {
	Kind      ProgressKind
	Completed int64
	Total     int64
}

Progress is absolute measurement for a task.

type ProgressKind

type ProgressKind string

ProgressKind classifies task measurement.

const (
	Indeterminate ProgressKind = "indeterminate"
	Determinate   ProgressKind = "determinate"
	BytesKind     ProgressKind = "bytes"
)

type ProjectionPolicy

type ProjectionPolicy int

ProjectionPolicy selects how output is emitted.

const (
	// ProjectionAuto chooses based on options/TTY hints.
	ProjectionAuto ProjectionPolicy = iota
	// ProjectionHuman is interactive or plain human output.
	ProjectionHuman
	// ProjectionData keeps machine data on the primary writer; UI on diagnostic.
	ProjectionData
	// ProjectionExternal disables inline rendering; snapshots only.
	ProjectionExternal
)

type Redactor

type Redactor interface {
	// RedactString returns a display-safe form of s.
	RedactString(s string) string
}

Redactor redacts sensitive values before journal and human rendering.

type Snapshot

type Snapshot struct {
	Version     uint64
	OutputID    string
	Subject     string
	Items       []ItemSnapshot
	Tasks       []TaskSnapshot
	Collections []TasksSnapshot
	Changes     []ChangesSnapshot
	Plans       []PlanSnapshot
	Lines       []string
	Actions     []Action
	Conclusion  *Conclusion
	Timestamp   time.Time
}

Snapshot is an immutable complete presentation state at a version.

type SystemClock

type SystemClock struct{}

SystemClock uses the real wall clock.

func (SystemClock) Now

func (SystemClock) Now() time.Time

Now returns the system time.

type Task

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

Task is a handle for one operation with phases or progress.

func (*Task) Advance

func (t *Task) Advance(delta int64) *Task

Advance increments completed progress by delta.

func (*Task) Bytes

func (t *Task) Bytes(completed, total int64) *Task

Bytes sets absolute byte progress.

func (*Task) Cancel

func (t *Task) Cancel(reason string) *Task

Cancel resolves the task as cancelled.

func (*Task) Done

func (t *Task) Done() *Task

Done resolves the task successfully.

func (*Task) Donef

func (t *Task) Donef(format string, args ...any) *Task

Donef resolves the task with a formatted summary.

func (*Task) Fail

func (t *Task) Fail(summary string, options ...ProblemOption) *Task

Fail resolves the task as failed.

func (*Task) Next

func (t *Task) Next(actions ...Action) *Task

Next attaches actions.

func (*Task) NextCommand

func (t *Task) NextCommand(executable string, args ...string) *Task

NextCommand attaches a command action.

func (*Task) Phase

func (t *Task) Phase(text string) *Task

Phase sets the active phase text and starts the task if pending.

func (*Task) Progress

func (t *Task) Progress(completed, total int64) *Task

Progress sets absolute completed/total progress.

func (*Task) Skip

func (t *Task) Skip(reason string) *Task

Skip resolves the task as skipped.

func (*Task) Snapshot

func (t *Task) Snapshot() TaskSnapshot

Snapshot returns the task snapshot.

func (*Task) Warn

func (t *Task) Warn(summary string, options ...ProblemOption) *Task

Warn resolves the task with a warning.

type TaskSnapshot

type TaskSnapshot struct {
	ID          string
	Name        string
	State       EntityState
	Phase       string
	Progress    Progress
	Summary     string
	Problems    []Problem
	Actions     []Action
	Collection  string
	Declaration int
}

TaskSnapshot is an immutable task view.

type Tasks

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

Tasks is a handle for a collection of independent child tasks. State is always derived from children; no Done/Fail/Progress methods.

func (*Tasks) Snapshot

func (g *Tasks) Snapshot() TasksSnapshot

Snapshot returns the collection snapshot with derived state.

func (*Tasks) Summary

func (g *Tasks) Summary(text string) *Tasks

Summary sets a success-oriented collection summary.

func (*Tasks) Summaryf

func (g *Tasks) Summaryf(format string, args ...any) *Tasks

Summaryf sets a formatted success-oriented collection summary.

func (*Tasks) Task

func (g *Tasks) Task(name string) *Task

Task declares a child task in declaration order.

type TasksSnapshot

type TasksSnapshot struct {
	ID          string
	Name        string
	State       EntityState
	Summary     string
	Tasks       []TaskSnapshot
	Declaration int
}

TasksSnapshot is an immutable collection view.

type TerminalDriver

type TerminalDriver interface {
	ID() string
}

TerminalDriver is the exclusive owner of terminal control sequences. Interactive implementation arrives in v0.2; the interface is defined early so options and tests compile.

type TimeSource

type TimeSource interface {
	Now() time.Time
}

TimeSource provides the current time for deterministic tests. Option constructor is Clock(TimeSource) to match the public API examples.

Directories

Path Synopsis
agent
catalog
Package catalog is the task-oriented guidance catalog for agent assistance.
Package catalog is the task-oriented guidance catalog for agent assistance.
harness
Package harness evaluates agent-assistance scenarios (§30.9, MCP-022/049).
Package harness evaluates agent-assistance scenarios (§30.9, MCP-022/049).
preview
Package preview generates multi-profile plain previews from snapshots.
Package preview generates multi-profile plain previews from snapshots.
review
Package review provides deterministic static review of Evident Output usage.
Package review provides deterministic static review of Evident Output usage.
rules
Package rules is the stable review-rule registry (Appendix C namespaces).
Package rules is the stable review-rule registry (Appendix C namespaces).
cmd
evident-output command
Command evident-output provides review/preview/explain CLI parity with MCP tools.
Command evident-output provides review/preview/explain CLI parity with MCP tools.
evident-output-mcp command
Command evident-output-mcp is the stdio MCP server.
Command evident-output-mcp is the stdio MCP server.
examples
data-command command
Command data-command shows the data-command stream split.
Command data-command shows the data-command stream split.
debug-history command
Command debug-history demos v0.4 DebugHistory (default): durable scrollback above the live region using the compact bracketed grammar.
Command debug-history demos v0.4 DebugHistory (default): durable scrollback above the live region using the compact bracketed grammar.
debug-pane command
Command debug-pane demos v0.4 DebugPane: rolling slog-text viewport in the live region (newest first).
Command debug-pane demos v0.4 DebugPane: rolling slog-text viewport in the live region (newest first).
doctor command
Command doctor is an environment/health check CLI.
Command doctor is an environment/health check CLI.
install-pipeline command
Command install-pipeline simulates a multi-step install/bootstrap.
Command install-pipeline simulates a multi-step install/bootstrap.
internal/demo
Package demo holds shared helpers for example CLIs.
Package demo holds shared helpers for example CLIs.
live-progress command
Command live-progress demos multi-task live progress (determinate bars + indeterminate spinner phases) with real wall-clock sleeps.
Command live-progress demos multi-task live progress (determinate bars + indeterminate spinner phases) with real wall-clock sleeps.
migrate command
Command migrate shows dry-run Plan vs applied Changes.
Command migrate shows dry-run Plan vs applied Changes.
repo-status command
Command repo-status is a realistic "is this repo safe to retire?" check.
Command repo-status is a realistic "is this repo safe to retire?" check.
internal
sanitize
Package sanitize neutralizes untrusted text for terminal-safe display.
Package sanitize neutralizes untrusted text for terminal-safe display.
width
Package width computes terminal cell widths for display text.
Package width computes terminal cell widths for display text.
scripts
traceability-check command
Command traceability-check verifies every expected §31 ID is present.
Command traceability-check verifies every expected §31 ID is present.
Package terminal provides production terminal drivers for Evident Output.
Package terminal provides production terminal drivers for Evident Output.
Package testkit provides deterministic clocks, screens, and assertions for evo tests.
Package testkit provides deterministic clocks, screens, and assertions for evo tests.

Jump to

Keyboard shortcuts

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