Documentation
¶
Overview ¶
Package evo is Evident Output: a presentation and execution-tracking library for CLI state, progress, evidence, provenance, and conclusions.
Application code owns declaring work. Evo owns scheduling that work, tracking whether it is already satisfied, and presenting the result — so the same call sites render correctly whether stdout is a real terminal, a log file, or a machine consumer, and the exit code always matches what the screen just said.
Runnable examples for every concept below live alongside this file in example_1_0_test.go: ExampleInit, ExampleRun, ExampleMain, ExampleTask, ExampleGroup, ExampleSequence, ExampleTaskHandle_Define, ExampleTaskHandle_Verify, ExampleTaskHandle_Key, ExampleFile, and ExampleFact — go doc / pkg.go.dev attach each to the symbol it names.
func main() {
evo.Init(evo.Config{Title: "repo"}) // first statement — arms first paint before any I/O
os.Exit(evo.Main(run))
}
func run(ctx context.Context) error {
evo.Println("Reading configuration")
evo.Task("working tree").Done()
t := evo.Task("fetch")
cmd.Stdout = t.Writer()
cmd.Stderr = t.Writer()
return nil // Block is a presentation outcome, not a Go error
}
Migrating from 0.5 ¶
evo.MainWith and Task/Group/Sequence.Each were removed in 1.0.0. See docs/migration/1.0.md for every breaking change with before/after code, and docs/guides/teaching-ladder.md for the current adoption order.
Adoption ladder (spec §44 — guess-driven defaults, the naive spelling is correct) ¶
- evo.Task(name) + Task.Define(func(context.Context) error) for one atomic unit of work — the scheduling and execution boundary (§7). A Task resolved directly with no Define call (Done/Warn/Block/Fail/Skipped) renders as a fact row instead of a spinner.
- evo.Group(name) / evo.Sequence(name) for collections: one named child Task per item (group.Task(name)), not a hand-maintained counter — Group's children may overlap, Sequence's run in declaration order and cascade a failure to NotStarted for later siblings. Group.Each and Sequence.Each were removed in 1.0.0; a repeated child name under the same parent is a duplicate sibling declaration, not a get-or-create (§3.1).
- evo.File(ctx, evo.FileSpec{...}) for declarative managed-state file content — Evo creates, rewrites on drift, and no-ops when the desired state already holds. ctx must come from a Task's Define callback.
- evo.Exec for external work with declared outputs and a Basis of Fingerprints that determine freshness (planned; not yet implemented).
- A Task-level Basis of evo.Fingerprint values (evo.FSPath, evo.Value, evo.App) when an operation's freshness depends on semantic external inputs beyond File/Exec's own tracked state.
- Task.After for exceptional scheduler edges that a Sequence would otherwise express more simply.
- Task.Fact / evo.Fact for discovered information, Task.Warn for a non-terminal annotation, Output Effects, and Config.DryRun for the would/did split.
- Task.Verify(func(context.Context) (bool, error)) only for domains Evo cannot track automatically — the one boolean, read-only escape hatch; a Verify that reports the desired state already holds skips Define and resolves ResolutionAlreadySatisfied.
- Top-level Config.Format / Config.Verbosity only when the host CLI needs machine output or verbose detail — never set per Task.
Do not require named Evidence declarations (a legacy mutating callback registered under that name) for common resources; evo.File/evo.Exec cover the ordinary cases without one.
Ordinary surface ¶
evo.Init/evo.Main/evo.Run, Output.Run for a hosted/Isolated instance, Print*, evo.Task/evo.Group/evo.Sequence, Task.Define / mutation verbs / Task.Writer, Task.Fail / Task.Failf / Task.Block / Task.Blockf, evo.Confirm, evo.Reason, slog via SlogHandler (level from Config.Debug.Level).
Advanced surface ¶
For testing and tooling call sites that need a hosted instance instead of the package-level default: Config.Isolated returns an independent *Output that never touches package state; Output.Run(ctx, run) Result seals it (the hosted counterpart of Main, returning the full Result — Conclusion plus the application error — instead of just the derived exit code, and never exiting the process). Task.Key overrides a Task's stable identity when its name changes across runs but tracked state must not (§3.1). Task.Verify, evo.File, and Fingerprint (evo.FSPath/evo.Value/evo.App) are the tracked-state primitives; Config.AppID/Config.StateDir override the manifest's storage location and namespace.
Example (BeginnerAPI) ¶
Example_beginnerAPI proves the beginner shape compiles and renders real rows, not an empty // Output: that only proves compile (evo-dialect-axes- report.md axis 2: "the example discards stdout and asserts nothing"). Sequence (declaration order, one Running child at a time) keeps the two child rows deterministic across runs; Group.Each would be correct too but collapses an all-success aggregate into a single summary line.
package main
import (
"bytes"
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true})
check := func(string) error { return nil }
worktrees := out.Sequence("worktrees")
for _, path := range []string{"repo-a", "repo-b"} {
task := worktrees.Task(path)
task.Define(func(ctx context.Context) error { return check(path) })
}
if err := out.Finish(); err != nil {
fmt.Println(err)
}
fmt.Print(buf.String())
}
Output: ✓ worktrees ✓ repo-a ✓ repo-b
Index ¶
- Constants
- Variables
- func Confirm(question string, opts ...ConfirmOption) bool
- func Delay(d time.Duration) *time.Duration
- func EncodeEventJSON(e Event) ([]byte, error)
- func EncodeJSON(s Snapshot) ([]byte, error)
- func EncodeJSONL(events []Event) ([]byte, error)
- func Exec(ctx context.Context, spec ExecSpec) error
- func Fact(name, value string)
- func File(ctx context.Context, spec FileSpec) error
- func IsCharDevice(w io.Writer) bool
- func Main(run RunFunc) int
- func Pluralize(quantity int64, singular string) string
- func Print(args ...any)
- func Printf(format string, args ...any)
- func Println(args ...any)
- func RenderPlain(s Snapshot, opts PlainOptions) ([]byte, error)
- func SetDefault(out *Output)
- func SlogHandler() slog.Handler
- func TruncateNames(names []string, visible int) string
- func Warn(summary string)
- func WriteJSON(w io.Writer, result Result) error
- type Action
- type Attachment
- type ChangesSnapshot
- type ColorMode
- type CommandSpec
- type Conclusion
- type ConclusionJSON
- type ConclusionState
- type Config
- type ConfirmOption
- type DebugConfig
- type DebugPaneOption
- type DebugPresentation
- type EffectRecord
- type EntityOption
- type EntityState
- type Event
- type EventJSON
- type Evidence
- type EvidenceOption
- type EvidencePhase
- type EvidenceStream
- type ExecSpec
- type FactRecord
- type Failure
- type Field
- type FileFS
- type FileSpec
- type Fingerprint
- type FingerprintValue
- type FixedClock
- type Format
- type GlyphProfile
- type GroupHandle
- type JSONAction
- type JSONChanges
- type JSONCollection
- type JSONCommand
- type JSONDocument
- type JSONEffectRecord
- type JSONMessage
- type JSONOutputMeta
- type JSONPlan
- type JSONProblem
- type JSONProgress
- type JSONTask
- type LiveSurface
- type LogLevel
- type LogRecord
- type MessageSnapshot
- type MutationOption
- type NoopRedactor
- type Option
- func AlsoWrite(w io.Writer) Option
- func Clock(ts TimeSource) Option
- func DataProjection() Option
- func DebugAddSource() Option
- func DebugHistory() Option
- func DebugLevel(level LogLevel) Option
- func DebugPane(opts ...DebugPaneOption) Option
- func Diagnostics(w io.Writer) Option
- func DryRun() Option
- func ExternalProjection() Option
- func Glyphs(p GlyphProfile) Option
- func MaxEntities(n int) Option
- func MaxEvents(n int) Option
- func MaxFrameRate(framesPerSecond int) Option
- func NoColor() Option
- func Plain() Option
- func Redact(r Redactor) Option
- func ResultStream(w io.Writer) Option
- func Runner(r ProcessRunner) Option
- func Stdin(r io.Reader) Option
- func Strict() Option
- func Terminal(driver TerminalDriver) Option
- func Title(subject string) Option
- func To(w io.Writer) Option
- func VisibilityDelay(delay time.Duration) Option
- func Width(columns int) Option
- type Output
- func (o *Output) Cancel(reason string)
- func (o *Output) Close() error
- func (o *Output) Conclusion() Conclusion
- func (o *Output) Confirm(question string, opts ...ConfirmOption) bool
- func (o *Output) Context() context.Context
- func (o *Output) Err() error
- func (o *Output) Fact(name, value string)
- func (o *Output) Fail(summary string, options ...ProblemOption)
- func (o *Output) Failf(format string, args ...any)
- func (o *Output) Finish() error
- func (o *Output) Group(name string) *GroupHandle
- func (o *Output) Next(actions ...Action)
- func (o *Output) NextCommand(executable string, args ...string)
- func (o *Output) Print(args ...any)
- func (o *Output) Printf(format string, args ...any)
- func (o *Output) Println(args ...any)
- func (o *Output) ResultWriter() io.Writer
- func (o *Output) Run(ctx context.Context, run RunFunc) Result
- func (o *Output) Sequence(name string) *SequenceHandle
- func (o *Output) Snapshot() Snapshot
- func (o *Output) Suspend(fn func() error) error
- func (o *Output) Task(name string) *TaskHandle
- func (o *Output) Warn(summary string)
- func (o *Output) Writer() io.Writer
- type PlainOptions
- type PlanSnapshot
- type Printer
- type Problem
- type ProblemOption
- func Code(value string) ProblemOption
- func Count(value int64, unit ...string) ProblemOption
- func Detail(text string) ProblemOption
- func Location(path string, line, column int) ProblemOption
- func Next(action Action) ProblemOption
- func NextCommand(executable string, args ...string) ProblemOption
- func On(subject string) ProblemOption
- type ProcessCommand
- type ProcessOutcome
- type ProcessRunner
- type Progress
- type ProgressKind
- type Projection
- type ReasonOption
- type Redactor
- type Resolution
- type Result
- type RunFunc
- type SequenceHandle
- type Snapshot
- type SourceLocation
- type SystemClock
- type TaskEvidence
- type TaskHandle
- func (t *TaskHandle) Add(object string, fn func() error, opts ...MutationOption)
- func (t *TaskHandle) After(preds ...any) *TaskHandle
- func (t *TaskHandle) Block(summary string, options ...ProblemOption)
- func (t *TaskHandle) Blockf(format string, args ...any) *Failure
- func (t *TaskHandle) Bytes(completed, total int64) *TaskHandle
- func (t *TaskHandle) Cancel(reason string)
- func (t *TaskHandle) Context() context.Context
- func (t *TaskHandle) Create(object string, fn func() error, opts ...MutationOption)
- func (t *TaskHandle) Define(fn func(context.Context) error)
- func (t *TaskHandle) Delete(object string, fn func() error, opts ...MutationOption)
- func (t *TaskHandle) Doing(text string, args ...any) *TaskHandle
- func (t *TaskHandle) Done(args ...any)
- func (t *TaskHandle) Fact(name, value string)
- func (t *TaskHandle) Fail(summary string, options ...ProblemOption)
- func (t *TaskHandle) Failf(format string, args ...any) *Failure
- func (t *TaskHandle) Kept(reason TaxonomyReason)
- func (t *TaskHandle) Key(key string) *TaskHandle
- func (t *TaskHandle) Next(actions ...Action) *TaskHandle
- func (t *TaskHandle) NextCommand(executable string, args ...string) *TaskHandle
- func (t *TaskHandle) Progress(completed, total int) *TaskHandle
- func (t *TaskHandle) Push(object string, fn func() error, opts ...MutationOption)
- func (t *TaskHandle) Record(verb string, quantity int, object string)
- func (t *TaskHandle) RecordLabel(label string, quantity int, object string)
- func (t *TaskHandle) RecordName(verb, object string)
- func (t *TaskHandle) Remove(object string, fn func() error, opts ...MutationOption)
- func (t *TaskHandle) Skipped(reason TaxonomyReason)
- func (t *TaskHandle) Snapshot() TaskSnapshot
- func (t *TaskHandle) Step(completed, total int, name string) *TaskHandle
- func (t *TaskHandle) Update(object string, fn func() error, opts ...MutationOption)
- func (t *TaskHandle) Verify(fn func(context.Context) (bool, error)) *TaskHandle
- func (t *TaskHandle) Wait() error
- func (t *TaskHandle) Warn(summary string)
- func (t *TaskHandle) Write(object string, fn func() error, opts ...MutationOption)
- func (t *TaskHandle) Writer() io.Writer
- type TaskSnapshot
- type TasksSnapshot
- type TaxonomyReason
- type TaxonomyRecord
- type TerminalDriver
- type TimeSource
- type Verbosity
- type Visibility
Examples ¶
- Package (BeginnerAPI)
- Action
- Affected
- AlsoWrite
- App
- AssumeYes
- Attachment
- ChangesSnapshot
- Clock
- Code
- ColorMode
- Command
- CommandSpec
- Conclusion
- ConclusionJSON
- ConclusionState
- Config
- Confirm
- ConfirmDetail
- ConfirmOption
- Count
- DataProjection
- DebugAddSource
- DebugConfig
- DebugHistory
- DebugLevel
- DebugPane
- DebugPaneOption
- DebugPresentation
- Default
- DefaultConfig
- Delay
- Destructive
- Detail
- Diagnostics
- DryRun
- EffectRecord
- EncodeEventJSON
- EncodeJSON
- EncodeJSONL
- EntityOption
- EntityState
- Event
- EventJSON
- Evidence
- EvidenceOption
- EvidencePhase
- EvidenceStream
- Exec
- ExecSpec
- ExternalProjection
- FSPath
- Fact
- FactRecord
- Failure
- Field
- File
- FileFS
- FileSpec
- Fingerprint
- FingerprintValue
- FixedClock
- ForSkip
- Format
- GlyphProfile
- Glyphs
- Group
- GroupHandle
- ID
- Init
- IsCharDevice
- JSONAction
- JSONChanges
- JSONCollection
- JSONCommand
- JSONDocument
- JSONEffectRecord
- JSONMessage
- JSONOutputMeta
- JSONPlan
- JSONProblem
- JSONProgress
- JSONTask
- KeepLastLines
- Label
- LiveSurface
- Location
- LogLevel
- LogRecord
- Main
- MaxEntities
- MaxEvents
- MaxEvidenceBytes
- MaxFrameRate
- MessageSnapshot
- MirrorToDebug
- MirrorToDiagnostics
- MutationOption
- NewestFirst
- Next
- NextCommand
- NoColor
- NoopRedactor
- OldestFirst
- On
- OnTask
- Option
- Output
- PaneHeight
- ParseFormat
- Plain
- PlainOptions
- PlanSnapshot
- Pluralize
- PolicyFlag
- PolicyHint
- PreserveDebugTail
- Printer
- Printf
- Println
- Problem
- ProblemOption
- ProcessCommand
- ProcessOutcome
- ProcessRunner
- Progress
- ProgressKind
- Projection
- Reason
- ReasonOption
- Redact
- Redactor
- RenderPlain
- Resolution
- Result
- ResultStream
- Run
- RunFunc
- Runner
- Sequence
- SequenceHandle
- SetDefault
- SlogHandler
- Snapshot
- SourceLocation
- StartPhase
- Stdin
- Strict
- SystemClock
- Task
- TaskEvidence
- TaskHandle
- TaskHandle.Define
- TaskHandle.Fact
- TaskHandle.Key
- TaskHandle.Verify
- TaskSnapshot
- TasksSnapshot
- TaxonomyReason
- TaxonomyRecord
- Terminal
- TerminalDriver
- TimeSource
- Title
- To
- TruncateNames
- Value
- Verbose
- Verbosity
- Visibility
- VisibilityDelay
- Warn
- Width
- WriteJSON
Constants ¶
const ( ExitOK = core.ExitOK ExitBlocked = core.ExitBlocked ExitFailed = core.ExitFailed ExitCancelled = core.ExitCancelled )
Default exit codes from architecture §26.
const ( // ResolutionExecuted marks a Task whose Define callback was entered and // returned successfully. ResolutionExecuted = core.ResolutionExecuted // ResolutionAlreadySatisfied marks a Task whose Define callback was // skipped because a pre-Define Verify observed the desired state // already held. ResolutionAlreadySatisfied = core.ResolutionAlreadySatisfied // ResolutionNoWork marks a Task explicitly resolved successfully // without ever reaching Define. ResolutionNoWork = core.ResolutionNoWork )
const ( // GlyphsAuto detects the vocabulary from locale and TTY interactivity. GlyphsAuto = txt.GlyphsAuto // GlyphsUnicode forces the Unicode vocabulary regardless of locale. GlyphsUnicode = txt.GlyphsUnicode // GlyphsASCII forces the ASCII vocabulary regardless of locale. GlyphsASCII = txt.GlyphsASCII )
const ( Pending = core.Pending Running = core.Running Done = core.Done Blocked = core.Blocked Failed = core.Failed Skipped = core.Skipped Cancelled = core.Cancelled Empty = core.Empty Incomplete = core.Incomplete // NotStarted marks a group task that never ran because an earlier sibling // already failed or was cancelled — rendered "- <name> not started" and // excluded from the conclusion (the group's verdict comes from the // failed/cancelled sibling, not from its unstarted followers). NotStarted = core.NotStarted )
EntityState values — see the type doc comment above for the naming rationale (no State* prefix on this block).
const ( StateReady = core.StateReady StateChanged = core.StateChanged StateWarning = core.StateWarning StateBlocked = core.StateBlocked StateFailed = core.StateFailed StateCancelled = core.StateCancelled StatePlanned = core.StatePlanned )
ConclusionState values — the trailing "[state]" band a run can end in.
const ( Indeterminate = core.Indeterminate Determinate = core.Determinate BytesKind = core.BytesKind )
ProgressKind values — which measurement a task's Progress reports.
const ( // VisibilityNormal messages always project at VerbosityNormal (C11: // prefixed consistently with VisibilityVerbose — the two enum members // previously disagreed on their own naming convention). VisibilityNormal = core.VisibilityNormal // VisibilityVerbose messages project only when Config.Verbosity is VerbosityVerbose. VisibilityVerbose = core.VisibilityVerbose )
const ( ColorAuto = engine.ColorAuto ColorAlways = engine.ColorAlways ColorNever = engine.ColorNever )
const ( FormatHuman = engine.FormatHuman FormatData = engine.FormatData FormatExternal = engine.FormatExternal // FormatJSON writes one final v2 "evo.run" document to Stdout at // Finish; human presentation still goes to Stderr (spec §32.1). FormatJSON = engine.FormatJSON // FormatJSONL streams v2 "evo.event" JSON lines to Stdout as they // occur, plus a final run.finished line (spec §32.1). FormatJSONL = engine.FormatJSONL )
const ( VerbosityNormal = engine.VerbosityNormal VerbosityVerbose = engine.VerbosityVerbose )
const ( ProjectionHuman = engine.ProjectionHuman ProjectionPlain = engine.ProjectionPlain ProjectionJSON = engine.ProjectionJSON ProjectionJSONL = engine.ProjectionJSONL ProjectionStreamJSON = engine.ProjectionStreamJSON )
const ( LevelUnset = engine.LevelUnset LevelTrace = engine.LevelTrace LevelDebug = engine.LevelDebug LevelInfo = engine.LevelInfo LevelWarn = engine.LevelWarn LevelError = engine.LevelError )
const ( DebugPresentationHistory = engine.DebugPresentationHistory DebugPresentationPane = engine.DebugPresentationPane )
const ( EvidenceStreamCombined = engine.EvidenceStreamCombined EvidenceStreamStdout = engine.EvidenceStreamStdout EvidenceStreamStderr = engine.EvidenceStreamStderr )
const ( ProblemCodeDuplicateSiblingName = engine.ProblemCodeDuplicateSiblingName ProblemCodeVerificationUnsatisfied = engine.ProblemCodeVerificationUnsatisfied )
Problem codes are stable, machine-readable Problem.Code values a consumer matches on instead of parsing Summary text.
const DefaultVisibleNames = engine.DefaultVisibleNames
const EventSchemaVersion = core.EventSchemaVersion
EventSchemaVersion is the durable event schema version. Tracks the 0.2 contract series (pre-1.0 wire format may still evolve).
const JSONSchemaVersion = render.JSONSchemaVersion
JSONSchemaVersion is the final JSON document schema version. Tracks the 0.3 contract series (pre-1.0 wire format may still evolve). Bumped from 0.2: "items" no longer exists as a separate wire kind — the item/task fold means every entity (including a fact-check resolved without ever running) is a "tasks" row (CHANGELOG "Unreleased").
const PublishedRelease = "v1.0.0"
PublishedRelease is the single source of truth for the current published module and MCP pin used in install guidance.
Maintenance class this protects (v0.2.10 hygiene, generalized):
- skills / integrations / README disagree on which tag to install
- MCP config generator falls back to a stale hardcoded tag
- portable docs recommend @latest or a personal-machine clone path
- signed tags ship with stale README pins (next patch, never rewrite history)
When cutting a release:
- Promote CHANGELOG ## Unreleased → ## [X.Y.Z] (Keep a Changelog).
- Set PublishedRelease to the new tag (e.g. "v0.2.11").
- Prefer: mise run test && mise run cut-release (cut-release syncs pins, stages CHANGELOG, refuses Unreleased drift).
- Tag that commit; do not move prior tags.
version_drift_test.go enforces the portable surface stays synchronized.
Variables ¶
var ( ErrExecSpecMissingExecutable = engine.ErrExecSpecMissingExecutable ErrExecExecutableNotFound = engine.ErrExecExecutableNotFound ErrExecNonzeroExit = engine.ErrExecNonzeroExit ErrExecOutputMissingAfterSuccess = engine.ErrExecOutputMissingAfterSuccess )
Exec-specific usage and outcome errors (spec §8.4).
var ( ErrFileSpecMissingPath = engine.ErrFileSpecMissingPath ErrFileUnmanagedContentsMissing = engine.ErrFileUnmanagedContentsMissing ErrFilePathIsSymlink = engine.ErrFilePathIsSymlink ErrFilePathTypeMismatch = engine.ErrFilePathTypeMismatch )
File-specific usage errors (spec §8.1).
var ( ErrClosed = engine.ErrClosed ErrAlreadyResolved = engine.ErrAlreadyResolved ErrUnresolvedTask = engine.ErrUnresolvedTask ErrInvalidProgress = engine.ErrInvalidProgress ErrProgressRegression = engine.ErrProgressRegression ErrDuplicateKey = engine.ErrDuplicateKey ErrInvalidConfig = engine.ErrInvalidConfig ErrRenderer = engine.ErrRenderer ErrLimitExceeded = engine.ErrLimitExceeded ErrReasonSkipOnly = engine.ErrReasonSkipOnly ErrReasonWrongTask = engine.ErrReasonWrongTask ErrConcurrentRunning = engine.ErrConcurrentRunning ErrDryRunDeclaredLate = engine.ErrDryRunDeclaredLate ErrTerminalWithoutSink = engine.ErrTerminalWithoutSink ErrNotStarted = engine.ErrNotStarted ErrWaitDeadlock = engine.ErrWaitDeadlock ErrDuplicateSiblingName = engine.ErrDuplicateSiblingName ErrKeyAfterDefine = engine.ErrKeyAfterDefine ErrNoTaskContext = engine.ErrNoTaskContext ErrTaskClosed = engine.ErrTaskClosed )
Functions ¶
func Confirm ¶ added in v0.3.0
func Confirm(question string, opts ...ConfirmOption) bool
Confirm asks question on the default instance and returns whether the user accepted.
Example ¶
ExampleConfirm asks a question and resolves it non-interactively via AssumeYes — the gate that owns the whole ask-decide-resolve flow.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
ok := out.Confirm("delete the branch?", evo.AssumeYes(true))
fmt.Println(ok)
}
Output: true
func Delay ¶ added in v0.2.7
Example ¶
ExampleDelay returns a non-nil *time.Duration for Config fields where zero is meaningful, like VisibilityDelay.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
d := evo.Delay(0)
fmt.Println(*d)
}
Output: 0s
func EncodeEventJSON ¶ added in v0.5.0
EncodeEventJSON encodes one journal event as a single JSON object (no newline).
Example ¶
ExampleEncodeEventJSON encodes one journal event as a single JSON object, with no trailing newline.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
data, err := evo.EncodeEventJSON(evo.Event{Type: "task.done", Name: "apply patch"})
fmt.Println(err)
fmt.Println(string(data))
}
Output: <nil> {"schema_version":"0.3","sequence":0,"type":"task.done","name":"apply patch","timestamp":"0001-01-01T00:00:00Z"}
func EncodeJSON ¶
EncodeJSON encodes a snapshot as final JSON (§25.1 / §25.4).
Example ¶
ExampleEncodeJSON encodes a finished Snapshot as the final wire JSONDocument (§25.1).
package main
import (
"encoding/json"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
out.Task("apply patch").Done()
_ = out.Finish()
data, err := evo.EncodeJSON(out.Snapshot())
var doc evo.JSONDocument
_ = json.Unmarshal(data, &doc)
fmt.Println(err, doc.Conclusion.State)
}
Output: <nil> ready
func EncodeJSONL ¶
EncodeJSONL encodes durable events as JSON Lines (§25.2 / §25.4).
Example ¶
ExampleEncodeJSONL encodes durable events as JSON Lines (§25.2).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
events := []evo.Event{{Type: "task.done", Name: "apply patch"}}
data, err := evo.EncodeJSONL(events)
fmt.Println(err)
fmt.Println(len(data) > 0)
}
Output: <nil> true
func Exec ¶ added in v1.0.0
Exec declares/reconciles one managed-state subprocess invocation: it skips spawning when a prior record proves the operation is already current (matching definition, Basis, and every declared Output digest), otherwise runs the child and verifies its declared Outputs afterward. A nonzero exit, or a declared Output missing after a zero exit, fails the operation. ctx must come from a Task's Define callback; called any other way it returns ErrNoTaskContext or ErrTaskClosed.
Example ¶
ExampleExec reconciles one managed-state subprocess invocation from inside a Task's Define callback, through the same ProcessRunner facade a test replaces with testkit.ProcessRunner.
package main
import (
"bytes"
"context"
"fmt"
"io"
"os"
"path/filepath"
evo "github.com/zachbornheimer/evident-output"
"github.com/zachbornheimer/evident-output/testkit"
)
func main() {
dir, err := os.MkdirTemp("", "evo-example-exec")
if err != nil {
fmt.Println(err)
return
}
defer func() { _ = os.RemoveAll(dir) }()
outPath := filepath.Join(dir, "out.bin")
runner := testkit.NewProcessRunner()
runner.Script("/usr/bin/tool", testkit.ScriptedProcess{ExitCode: 0})
// The scripted runner never actually writes outPath, so declare it
// ahead of time the way a real generator's own subprocess would.
if err := os.WriteFile(outPath, []byte("generated"), 0o644); err != nil {
fmt.Println(err)
return
}
var buf bytes.Buffer
out := evo.Init(evo.Config{
Isolated: true, Stdout: &buf, Stderr: io.Discard, Plain: true, StateDir: dir,
Options: []evo.Option{evo.Runner(runner)},
})
task := out.Task("generate")
task.Define(func(ctx context.Context) error {
return evo.Exec(ctx, evo.ExecSpec{
Executable: "/usr/bin/tool",
Args: []string{"--out", outPath},
Outputs: []string{outPath},
})
})
_ = task.Wait()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ generate [changed] generate ran /usr/bin/tool [changed]
func Fact ¶ added in v0.4.0
func Fact(name, value string)
Example ¶
ExampleFact records a discovered name/value annotation about the run itself.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
evo.SetDefault(out)
evo.Fact("language", "go")
_ = out.Finish()
fmt.Println(len(out.Snapshot().Facts) == 1, out.Snapshot().Facts[0].Value)
}
Output: true go
func File ¶ added in v1.0.0
File declares/reconciles one managed-state file resource: it creates a missing file, rewrites one whose contents differ from FileSpec.Contents, and/or chmods one whose mode differs from FileSpec.Mode — a no-op when every managed attribute already matches. ctx must come from a Task's Define callback; called any other way it returns ErrNoTaskContext or ErrTaskClosed.
Example ¶
ExampleFile declares/reconciles one managed-state file resource: Evo creates it, rewrites it when Contents differ, and no-ops when the desired state already holds — common file work never needs a hand- written Evidence callback (spec §8, §56).
package main
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
dir, err := os.MkdirTemp("", "evo-example-file")
if err != nil {
fmt.Println(err)
return
}
defer func() { _ = os.RemoveAll(dir) }()
path := filepath.Join(dir, "config.json")
out := evo.Init(evo.Config{Isolated: true, StateDir: dir, Stdout: io.Discard, Stderr: io.Discard})
result := out.Run(context.Background(), func(ctx context.Context) error {
task := out.Task("config")
task.Define(func(ctx context.Context) error {
return evo.File(ctx, evo.FileSpec{Path: path, Contents: []byte(`{"ok":true}`)})
})
return nil
})
contents, err := os.ReadFile(path)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(result.ExitCode())
fmt.Println(string(contents))
}
Output: 0 {"ok":true}
func IsCharDevice ¶
Example ¶
ExampleIsCharDevice reports whether w is an interactive character device (a real terminal) — false for an ordinary buffer or file.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
fmt.Println(evo.IsCharDevice(io.Discard))
}
Output: false
func Main ¶
Main executes run against the default Output and returns the derived exit code; it does not itself call os.Exit — callers write os.Exit(evo.Main(run)).
Example ¶
ExampleMain shows deriving a process exit code from a RunFunc without evo.Main itself calling os.Exit — the caller writes os.Exit(evo.Main(run)).
package main
import (
"bytes"
"context"
"errors"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true}))
code := evo.Main(func(ctx context.Context) error {
return errors.New("disk full")
})
fmt.Println(code)
}
Output: 2
func Pluralize ¶ added in v0.3.0
Example ¶
ExamplePluralize formats a quantity with its singular noun pluralized when the quantity isn't exactly one.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
fmt.Println(evo.Pluralize(1, "branch"))
fmt.Println(evo.Pluralize(3, "branch"))
}
Output: branch branches
func Print ¶ added in v0.3.0
func Print(args ...any)
Print formats like fmt.Sprint and enqueues human-facing text on the default instance.
Example ¶
ExamplePrint shows fmt.Sprint-style human text on the default instance.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true}))
evo.Print("repo ", "clean")
_ = evo.Default().Finish()
fmt.Print(buf.String())
}
Output: repo clean
func Printf ¶ added in v0.3.0
Printf formats like fmt.Sprintf and enqueues human-facing text on the default instance.
Example ¶
ExamplePrintf shows fmt.Sprintf-style human text on the default instance.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true}))
evo.Printf("found %d issues", 3)
_ = evo.Default().Finish()
fmt.Print(buf.String())
}
Output: found 3 issues
func Println ¶ added in v0.3.0
func Println(args ...any)
Println formats like fmt.Sprintln and enqueues a complete line on the default instance.
Example ¶
ExamplePrintln shows a complete human line on the default instance.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true}))
evo.Println("reading configuration")
_ = evo.Default().Finish()
fmt.Print(buf.String())
}
Output: reading configuration
func RenderPlain ¶
func RenderPlain(s Snapshot, opts PlainOptions) ([]byte, error)
Example ¶
ExampleRenderPlain renders a Snapshot as the durable plain-text report — the same renderer Config.Plain wires up automatically.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
out.Task("apply patch").Done()
_ = out.Finish()
data, err := evo.RenderPlain(out.Snapshot(), evo.PlainOptions{NoColor: true})
fmt.Println(err)
fmt.Print(string(data))
}
Output: <nil> ✓ apply patch
func SetDefault ¶ added in v0.3.0
func SetDefault(out *Output)
SetDefault installs out as the package-level default Output.
Example ¶
ExampleSetDefault installs an explicit Output as the package-level default, so evo.Task and friends operate on it.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true, Isolated: true})
evo.SetDefault(out)
evo.Task("wire default").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ wire default
func SlogHandler ¶ added in v0.3.0
SlogHandler returns a slog.Handler journaling to the default instance.
Example ¶
ExampleSlogHandler shows journaling through the standard library's slog.Logger into the default instance's debug journal.
package main
import (
"bytes"
"fmt"
"io"
"log/slog"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{
Stdout: io.Discard, Stderr: &buf, Plain: true,
Debug: evo.DebugConfig{Level: evo.LevelDebug},
}))
logger := slog.New(evo.SlogHandler())
logger.Info("connected to registry")
_ = evo.Default().Finish()
fmt.Println(bytes.Contains(buf.Bytes(), []byte("connected to registry")))
}
Output: true
func TruncateNames ¶ added in v0.2.16
Example ¶
ExampleTruncateNames bounds a name list to visible entries, summarizing the rest.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
fmt.Println(evo.TruncateNames([]string{"main", "dev", "release", "hotfix"}, 2))
}
Output: main, dev … +2 more
func Warn ¶ added in v0.4.0
func Warn(summary string)
Example ¶
ExampleWarn annotates the run itself with a warning, without resolving any task.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
evo.SetDefault(out)
evo.Warn("cache directory missing, rebuilding")
_ = out.Finish()
fmt.Println(out.Conclusion().Warned)
}
Output: true
func WriteJSON ¶ added in v0.2.0
WriteJSON serializes result as the stable v2 "evo.run" wire document plus one trailing newline (spec §53) — the HTTP/embedding counterpart of FormatJSON's automatic Stdout write. It never serializes internal snapshots directly, and applies the same redaction Result's Conclusion already carries. HTTP status (or any other transport-level outcome) is the embedding application's own concern; Evo's outcome/exit semantics stay in the body (Conclusion.State/ExitCode).
Example ¶
ExampleWriteJSON serializes a finished Result as the stable v2 "evo.run" wire document plus one trailing newline — the HTTP/embedding counterpart of FormatJSON's automatic Stdout write.
package main
import (
"bytes"
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
result := out.Run(context.Background(), func(ctx context.Context) error {
out.Task("apply patch").Done()
return nil
})
var buf bytes.Buffer
err := evo.WriteJSON(&buf, result)
fmt.Println(err)
fmt.Println(bytes.Contains(buf.Bytes(), []byte(`"evo.run"`)))
}
Output: <nil> true
Types ¶
type Action ¶
Action is a recommended next step for the user.
Aliased into internal/core alongside the rest of the data model — see Snapshot's doc comment (snapshot.go) for why.
Example ¶
ExampleAction shows the recommended-next-step shape attached to a Problem or a resolved Task via Next/NextCommand.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
action := evo.Action{Label: "retry with --force"}
fmt.Println(action.Label)
}
Output: retry with --force
func Command ¶
Command builds an action with an executable and arguments. Display-bound strings are sanitized at construction.
Example ¶
ExampleCommand builds a recommended next step naming an executable command to run.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
action := evo.Command("git", "push", "--force-with-lease")
fmt.Println(action.Command.Executable, action.Command.Args)
}
Output: git [push --force-with-lease]
func Label ¶ added in v0.3.0
Label builds a plain-text recommended next step with no executable command (e.g. a policy hint like "pass --yes to confirm non-interactively").
Example ¶
ExampleLabel builds a plain-text recommended next step with no executable command — a policy hint like "pass --yes to confirm non-interactively".
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
action := evo.Label("pass --yes to confirm non-interactively")
fmt.Println(action.Label)
}
Output: pass --yes to confirm non-interactively
type Attachment ¶ added in v0.3.0
type Attachment = core.Attachment
Attachment is an additional label/value problem attachment.
Named Attachment (not Evidence) because Evidence names the retained process-output sink (see Evidence in capture.go) — this is a single labeled fact attached to a Problem, a different concept from that sink.
Example ¶
ExampleAttachment shows an additional label/value fact attached to a Problem — a different concept from the Evidence retention sink.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
a := evo.Attachment{Label: "stderr", Value: "permission denied"}
fmt.Println(a.Label, a.Value)
}
Output: stderr permission denied
type ChangesSnapshot ¶
type ChangesSnapshot = core.ChangesSnapshot
ChangesSnapshot is an immutable changes section.
Example ¶
ExampleChangesSnapshot reads an immutable changes section: the records a mutation verb recorded, run without DryRun.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
out.Task("prune branches").Delete("stale branch", func() error { return nil }, evo.Affected(2))
_ = out.Finish()
changes := out.Snapshot().Changes[0]
fmt.Println(changes.Records[0].Verb, changes.Records[0].Quantity)
}
Output: deleted 2
type ColorMode ¶ added in v0.2.0
Example ¶
ExampleColorMode selects the color policy — default ColorAuto uses TTY detection and honors NO_COLOR.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
c := evo.ColorNever
fmt.Println(c == evo.ColorNever)
}
Output: true
type CommandSpec ¶
type CommandSpec = core.CommandSpec
CommandSpec is an executable plus argv (never a shell string).
Example ¶
ExampleCommandSpec shows an executable plus argv — never a shell string — the shape Command builds and Action.Command carries.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
spec := evo.CommandSpec{Executable: "git", Args: []string{"push", "--force-with-lease"}}
fmt.Println(spec.Executable, spec.Args)
}
Output: git [push --force-with-lease]
type Conclusion ¶
type Conclusion = core.Conclusion
Conclusion is the multidimensional meaning of a finished command.
Aliased into internal/core alongside the rest of the data model — see Snapshot's doc comment (snapshot.go) for why, and EVIDENT_OUTPUT_ARCHITECTURE_SPEC_v0.5.md §38 for the full layout.
Example ¶
ExampleConclusion shows the multidimensional meaning of a finished command, read from a real run.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
out.Task("apply patch").Done()
_ = out.Finish()
c := out.Conclusion()
fmt.Println(c.State, c.ExitCode)
}
Output: ready 0
type ConclusionJSON ¶
type ConclusionJSON = render.ConclusionJSON
ConclusionJSON is JSON-friendly conclusion.
Example ¶
ExampleConclusionJSON shows the JSON-friendly conclusion projection.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
c := evo.ConclusionJSON{State: evo.StateReady, ExitCode: evo.ExitOK}
fmt.Println(c.State, c.ExitCode)
}
Output: ready 0
type ConclusionState ¶
type ConclusionState = core.ConclusionState
ConclusionState is the human headline for a finished output.
Example ¶
ExampleConclusionState shows the human headline for a finished output.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
out.Task("apply patch").Done()
_ = out.Finish()
fmt.Println(out.Conclusion().State == evo.StateReady)
}
Output: true
type Config ¶
Example ¶
ExampleConfig shows the ordinary application-facing construction surface: a Title and an explicit Stdout writer.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
cfg := evo.Config{Title: "demo", Stdout: &buf, Stderr: io.Discard, Plain: true, Isolated: true}
out := evo.Init(cfg)
out.Task("scan").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ scan [ready] demo
func DefaultConfig ¶ added in v0.2.0
func DefaultConfig() Config
Example ¶
ExampleDefaultConfig shows building a mutable baseline Config and overriding one field before passing it to Init.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
cfg := evo.DefaultConfig()
cfg.Title = "repo-retire"
fmt.Println(cfg.Title)
}
Output: repo-retire
type ConfirmOption ¶ added in v0.3.0
type ConfirmOption = engine.ConfirmOption
Example ¶
ExampleConfirmOption shows the interface every Confirm modifier (AssumeYes, ConfirmDetail, Destructive, PolicyFlag, PolicyHint) implements.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.AssumeYes(true)
fmt.Println(opt != nil)
}
Output: true
func AssumeYes ¶ added in v0.3.0
func AssumeYes(v bool) ConfirmOption
Example ¶
ExampleAssumeYes resolves a Confirm gate non-interactively — the programmatic equivalent of a caller's own --yes flag.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
ok := out.Confirm("proceed?", evo.AssumeYes(true))
fmt.Println(ok)
}
Output: true
func ConfirmDetail ¶ added in v0.3.0
func ConfirmDetail(lines ...string) ConfirmOption
Example ¶
ExampleConfirmDetail attaches context lines rendered under the prompt.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true, Isolated: true})
out.Confirm("delete 3 branches?", evo.AssumeYes(true), evo.ConfirmDetail("main", "release"))
fmt.Println("resolved")
}
Output: resolved
func Destructive ¶ added in v0.3.0
func Destructive() ConfirmOption
Example ¶
ExampleDestructive marks a Confirm gate as guarding a destructive action.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
ok := out.Confirm("wipe the cache?", evo.AssumeYes(true), evo.Destructive())
fmt.Println(ok)
}
Output: true
func PolicyFlag ¶ added in v0.3.0
func PolicyFlag(flag string) ConfirmOption
Example ¶
ExamplePolicyFlag names the flag a script can pass to bypass the gate non-interactively — rendered in the assumed-policy hint.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
ok := out.Confirm("continue?", evo.AssumeYes(true), evo.PolicyFlag("--yes"))
fmt.Println(ok)
}
Output: true
func PolicyHint ¶ added in v0.3.0
func PolicyHint(command string, args ...string) ConfirmOption
Example ¶
ExamplePolicyHint attaches a recommended non-interactive command instead of the default "pass --yes" wording.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
ok := out.Confirm("continue?", evo.AssumeYes(true), evo.PolicyHint("tool", "--yes"))
fmt.Println(ok)
}
Output: true
type DebugConfig ¶ added in v0.2.0
type DebugConfig = engine.DebugConfig
Example ¶
ExampleDebugConfig configures the debug journal presentation: the minimum level and whether it renders as durable history or a bounded pane.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
cfg := evo.DebugConfig{Level: evo.LevelDebug, View: evo.DebugPresentationHistory}
fmt.Println(cfg.Level == evo.LevelDebug, cfg.View == evo.DebugPresentationHistory)
}
Output: true true
type DebugPaneOption ¶
type DebugPaneOption = engine.DebugPaneOption
Example ¶
ExampleDebugPaneOption shows the interface every debug-pane knob (NewestFirst, OldestFirst, PaneHeight, PreserveDebugTail) implements.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.PaneHeight(5)
fmt.Println(opt != nil)
}
Output: true
func NewestFirst ¶
func NewestFirst() DebugPaneOption
Example ¶
ExampleNewestFirst orders a debug pane newest-entry-first.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{
Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard,
Debug: evo.DebugConfig{Level: evo.LevelDebug, View: evo.DebugPresentationPane},
Options: []evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor(), evo.DebugPane(evo.NewestFirst())},
})
out.Task("demo").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ demo
func OldestFirst ¶
func OldestFirst() DebugPaneOption
Example ¶
ExampleOldestFirst orders a debug pane oldest-entry-first.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{
Isolated: true, Stdout: io.Discard, Stderr: io.Discard,
Options: []evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor(), evo.DebugPane(evo.OldestFirst())},
})
out.Task("demo").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ demo
func PaneHeight ¶
func PaneHeight(lines int) DebugPaneOption
Example ¶
ExamplePaneHeight bounds a debug pane's visible line count (default 5).
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{
Isolated: true, Stdout: io.Discard, Stderr: io.Discard,
Options: []evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor(), evo.DebugPane(evo.PaneHeight(3))},
})
out.Task("demo").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ demo
func PreserveDebugTail ¶
func PreserveDebugTail() DebugPaneOption
Example ¶
ExamplePreserveDebugTail forces a diagnostic tail on every Finish in pane mode.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{
Isolated: true, Stdout: io.Discard, Stderr: io.Discard,
Options: []evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor(), evo.DebugPane(evo.PreserveDebugTail())},
})
out.Task("demo").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ demo
type DebugPresentation ¶
type DebugPresentation = engine.DebugPresentation
Example ¶
ExampleDebugPresentation selects history vs pane presentation for the debug journal (default History).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
view := evo.DebugPresentationPane
fmt.Println(view == evo.DebugPresentationPane)
}
Output: true
type EffectRecord ¶
type EffectRecord = core.EffectRecord
EffectRecord is one semantic change or plan row.
Example ¶
ExampleEffectRecord shows one semantic change or plan row.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
r := evo.EffectRecord{Verb: "delete", Quantity: 2, HasQty: true, Object: "stale branch"}
fmt.Println(r.Verb, r.Quantity, r.Object)
}
Output: delete 2 stale branch
type EntityOption ¶ added in v0.2.3
type EntityOption = engine.EntityOption
Example ¶
ExampleEntityOption shows the interface ID and StartPhase implement — an advanced, platform-scale Task-declaration configuration surface.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.ID("download-base-image")
fmt.Println(opt != nil)
}
Output: true
func ID ¶ added in v0.2.3
func ID(id string) EntityOption
ID sets a stable machine key. Superseded: Task is name-only.
Example ¶
ExampleID sets a stable machine key independent of a Task's human label (superseded today: Task is name-only, kept for advanced/platform callers building their own declaration layer over EntityOption).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.ID("download-base-image")
fmt.Println(opt != nil)
}
Output: true
func StartPhase ¶ added in v0.3.0
func StartPhase(text string) EntityOption
StartPhase sets a task's first doing-text at declare time. Superseded: call Doing.
Example ¶
ExampleStartPhase sets a task's first doing-text at declare time (superseded today: call TaskHandle.Doing after declaring instead).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.StartPhase("resolving dependencies")
fmt.Println(opt != nil)
}
Output: true
type EntityState ¶
type EntityState = core.EntityState
EntityState is the lifecycle state of an item or task.
C11 naming sweep: these members stay bare (Done, Failed, Blocked, ...) rather than gaining a State* prefix to match ConclusionState below — prefixing would collide outright with ConclusionState's own StateFailed/ StateBlocked/StateCancelled/StateWarning constants (same package, same identifiers, different types is still a duplicate declaration in Go). Renaming ConclusionState's constants instead would ripple into the JSON wire (schema 0.3, frozen this release) and every existing golden — this is the "document instead" branch the census decision allows.
Aliased into internal/core alongside the rest of the data model — see Snapshot's doc comment (snapshot.go) for why.
Example ¶
ExampleEntityState shows the lifecycle state of an item or task, read from a resolved TaskSnapshot.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
task := out.Task("apply patch")
task.Done()
_ = out.Finish()
state := task.Snapshot().State
fmt.Println(state == evo.Done)
}
Output: true
type Event ¶
Event is an immutable journal record.
Aliased into internal/core alongside the rest of the data model — see Snapshot's doc comment (snapshot.go) for why.
Example ¶
ExampleEvent shows the immutable journal record durable event streams carry.
package main
import (
"fmt"
"time"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
e := evo.Event{Type: "task.done", Name: "apply patch", Timestamp: time.Unix(0, 0)}
fmt.Println(e.Type, e.Name)
}
Output: task.done apply patch
type EventJSON ¶
EventJSON is a JSON Lines event record (§25.2).
Example ¶
ExampleEventJSON shows a JSON Lines event record (§25.2).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
e := evo.EventJSON{Type: "task.done", Name: "apply patch"}
fmt.Println(e.Type, e.Name)
}
Output: task.done apply patch
type Evidence ¶
Example ¶
ExampleEvidence shows the retained/redacted process-output sink's zero value: with no owning Output attached (only reachable internally via TaskHandle.Writer), Write is a safe no-op rather than a panic, so an embedder that receives a zero Evidence can always call its methods.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var e evo.Evidence
n, err := e.Write([]byte("compiling module\n"))
fmt.Println(n, err)
fmt.Println(e.Empty())
}
Output: 17 <nil> true
type EvidenceOption ¶ added in v0.3.0
type EvidenceOption = engine.EvidenceOption
Example ¶
ExampleEvidenceOption shows the interface every Evidence construction knob (KeepLastLines, MaxEvidenceBytes, MirrorToDebug, MirrorToDiagnostics) implements. Evidence itself has no exported constructor accepting these today — the option value is real and constructible, but its effect isn't reachable from the public surface yet, so this Example proves construction rather than behavior.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.KeepLastLines(50)
fmt.Println(opt != nil)
}
Output: true
func KeepLastLines ¶ added in v0.1.2
func KeepLastLines(n int) EvidenceOption
Example ¶
ExampleKeepLastLines sets how many trailing lines Evidence retains (default 200). See ExampleEvidenceOption for why this proves construction, not effect.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.KeepLastLines(50)
fmt.Println(opt != nil)
}
Output: true
func MaxEvidenceBytes ¶ added in v0.3.0
func MaxEvidenceBytes(n int) EvidenceOption
Example ¶
ExampleMaxEvidenceBytes sets an approximate byte budget for Evidence's retained lines (default 256KiB). See ExampleEvidenceOption for why this proves construction, not effect.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.MaxEvidenceBytes(64 << 10)
fmt.Println(opt != nil)
}
Output: true
func MirrorToDebug ¶ added in v0.2.2
func MirrorToDebug() EvidenceOption
Example ¶
ExampleMirrorToDebug journals each completed Evidence line via Debug when DebugLevel allows. See ExampleEvidenceOption for why this proves construction, not effect.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.MirrorToDebug()
fmt.Println(opt != nil)
}
Output: true
func MirrorToDiagnostics ¶ added in v0.2.2
func MirrorToDiagnostics() EvidenceOption
Example ¶
ExampleMirrorToDiagnostics copies each completed Evidence line to the Diagnostics writer. See ExampleEvidenceOption for why this proves construction, not effect.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.MirrorToDiagnostics()
fmt.Println(opt != nil)
}
Output: true
type EvidencePhase ¶ added in v1.0.0
type EvidencePhase = core.EvidencePhase
EvidencePhase is one Verify observation attempt (§30): a pre- or post-Define check, and whether it was ever evaluated.
Example ¶
ExampleEvidencePhase shows one Verify observation attempt: whether it was evaluated, and whether the desired state was already satisfied.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
phase := evo.EvidencePhase{Evaluated: true, Satisfied: true, Source: "verify"}
fmt.Println(phase.Evaluated, phase.Satisfied, phase.Source)
}
Output: true true verify
type EvidenceStream ¶ added in v0.3.0
type EvidenceStream = engine.EvidenceStream
Example ¶
ExampleEvidenceStream identifies which process stream a captured line came from — EvidenceStreamCombined is the default (merged) stream.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
s := evo.EvidenceStreamStdout
fmt.Println(s == evo.EvidenceStreamStdout)
}
Output: true
type ExecSpec ¶ added in v1.0.0
ExecSpec declares one managed-state subprocess invocation (spec §8.4). Constructing an ExecSpec performs no I/O — Exec performs the operation.
Aliased into internal/engine alongside the rest of the data model.
Example ¶
ExampleExecSpec declares one managed-state subprocess invocation — constructing it performs no I/O; passing it to Exec is what skips spawning when a prior record proves the operation current, or runs the child and verifies its declared Outputs afterward.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
spec := evo.ExecSpec{
Executable: "python3",
Args: []string{"generate.py", "input.xlsx", "out.bin"},
Basis: []evo.Fingerprint{evo.FSPath("input.xlsx")},
Outputs: []string{"out.bin"},
}
fmt.Println(spec.Executable, len(spec.Args))
}
Output: python3 3
type FactRecord ¶ added in v0.4.0
FactRecord is a discovered name/value annotation — information, not work (user-13-problems.md Problem 8). Named FactRecord, not Fact, because Fact is the evo.Fact/TaskHandle.Fact verb (EffectRecord sets the naming precedent: the verb keeps the plain name, its stored shape gets Record). See TaskHandle.Fact and Output.Fact.
Aliased into internal/core alongside the rest of the data model — see Snapshot's doc comment (snapshot.go) for why.
Example ¶
ExampleFactRecord shows a discovered name/value annotation — information, not work.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
f := evo.FactRecord{Name: "language", Value: "go"}
fmt.Println(f.Name, f.Value)
}
Output: language go
type Failure ¶ added in v0.3.0
type Failure struct {
// contains filtered or unexported fields
}
Example ¶
ExampleFailure shows the value TaskHandle.Failf/Blockf return: one recorded error built and returned in a single line, further chainable with Next/NextCommand.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Isolated: true, Stdout: io.Discard, Stderr: io.Discard, Plain: true})
task := out.Task("clone repository")
err := task.Failf("clone failed: %w", fmt.Errorf("connection refused"))
_ = out.Finish()
fmt.Println(err.Error())
}
Output: clone failed: connection refused
func (*Failure) NextCommand ¶ added in v0.3.0
type Field ¶
Field is a structured diagnostic or log field.
Example ¶
ExampleField shows a structured diagnostic or log field.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
f := evo.Field{Key: "retries", Value: 3}
fmt.Println(f.Key, f.Value)
}
Output: retries 3
type FileFS ¶ added in v1.0.0
Example ¶
ExampleFileFS is the facade every evo.File call performs filesystem I/O through instead of the os package directly — testkit.FileFS satisfies it deterministically for tests (including scripting a chmod failure); production uses the real filesystem.
package main
import (
"context"
"fmt"
"io"
"os"
"path/filepath"
evo "github.com/zachbornheimer/evident-output"
"github.com/zachbornheimer/evident-output/testkit"
)
func main() {
dir, err := os.MkdirTemp("", "evo-example-filefs")
if err != nil {
fmt.Println(err)
return
}
defer func() { _ = os.RemoveAll(dir) }()
path := filepath.Join(dir, "config.json")
fsys := testkit.NewFileFS()
out := evo.Init(evo.Config{
Isolated: true, FileFS: fsys, Plain: true, Color: evo.ColorNever,
// StateDir isolates this example's manifest to its own temp
// directory (spec §11.3) — without it, File's default manifest
// path is derived from the real machine cache dir and can
// contend with any other concurrently running evo.File caller.
StateDir: dir,
Stdout: io.Discard, Stderr: io.Discard,
})
agent := out.Task("write config")
agent.Define(func(ctx context.Context) error {
return evo.File(ctx, evo.FileSpec{Path: path, Contents: []byte(`{"ok":true}`)})
})
_ = out.Finish()
contents, err := os.ReadFile(path)
fmt.Println(err == nil, string(contents))
}
Output: true {"ok":true}
type FileSpec ¶ added in v1.0.0
FileSpec declares one managed-state file resource (spec §8). Constructing a FileSpec performs no I/O — File performs the operation.
Aliased into internal/engine alongside the rest of the data model.
Example ¶
ExampleFileSpec declares one managed-state file resource — constructing it performs no I/O; passing it to File is what creates, rewrites on drift, or no-ops when Path/Contents/Mode already match.
package main
import (
"fmt"
"os"
"path/filepath"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
dir, err := os.MkdirTemp("", "evo-example-filespec")
if err != nil {
fmt.Println(err)
return
}
defer func() { _ = os.RemoveAll(dir) }()
spec := evo.FileSpec{
Path: filepath.Join(dir, "config.json"),
Contents: []byte(`{"ok":true}`),
Mode: 0o644,
}
fmt.Println(spec.Path != "")
}
Output: true
type Fingerprint ¶ added in v1.0.0
type Fingerprint = fingerprint.Fingerprint
Fingerprint observes one Basis input's current content identity (spec §11.1). Implementations must not mutate the world.
Aliased into internal/fingerprint alongside FSPath/Value/App — the same pattern action.go/fact.go use for the rest of the data model.
Example ¶
ExampleFingerprint observes one Basis input's current content identity — FSPath, Value, and App are its three constructors; a custom implementation may observe anything else Basis needs to track.
package main
import (
"context"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
fp := evo.Value("go-version", "1.23")
v, err := fp.Fingerprint(context.Background())
fmt.Println(err == nil, v.Kind != "")
}
Output: true true
func App ¶ added in v1.0.0
func App() Fingerprint
App fingerprints the running application itself — see internal/fingerprint.App. Include it in an operation's Basis only when the application's own implementation is a semantic input to that operation's result.
Example ¶
ExampleApp fingerprints the running application itself — include it in an operation's Basis only when the application's own implementation is a semantic input to that operation's result.
package main
import (
"context"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
fp := evo.App()
v, err := fp.Fingerprint(context.Background())
fmt.Println(err == nil, v.Kind != "")
}
Output: true true
func FSPath ¶ added in v1.0.0
func FSPath(path string) Fingerprint
FSPath fingerprints the filesystem content at path: a regular file's type-marked byte digest, a directory's deterministic Merkle digest over sorted entries, a symlink's target text (never followed), or a stable "missing" digest — see internal/fingerprint.FSPath.
Example ¶
ExampleFSPath fingerprints the filesystem content at path: a regular file's type-marked byte digest, a directory's Merkle digest over sorted entries, a symlink's target text, or a stable "missing" digest.
package main
import (
"context"
"fmt"
"os"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
f, err := os.CreateTemp("", "evo-example-fspath")
if err != nil {
fmt.Println(err)
return
}
defer func() { _ = os.Remove(f.Name()) }()
_ = f.Close()
fp := evo.FSPath(f.Name())
v, err := fp.Fingerprint(context.Background())
fmt.Println(err == nil, v.Key == f.Name())
}
Output: true true
func Value ¶ added in v1.0.0
func Value(name string, v any) Fingerprint
Value fingerprints a caller-supplied scalar (string, bool, any signed/ unsigned integer, any finite float, time.Time, or []byte) under a stable, safe name — see internal/fingerprint.Value. Only the digest and name are ever persisted, never the raw value.
Example ¶
ExampleValue fingerprints a caller-supplied scalar under a stable, safe name — only the digest and name are ever persisted, never the raw value.
package main
import (
"context"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
fp := evo.Value("feature-flag", true)
v, err := fp.Fingerprint(context.Background())
fmt.Println(err == nil, v.Key)
}
Output: true feature-flag
type FingerprintValue ¶ added in v1.0.0
type FingerprintValue = fingerprint.FingerprintValue
FingerprintValue is one Fingerprint's observed identity: a stable machine Kind, a stable non-secret Key, and a SHA-256 Digest.
Example ¶
ExampleFingerprintValue is one Fingerprint's observed identity: a stable machine Kind, a stable non-secret Key, and a SHA-256 Digest — only the digest and name are ever persisted, never the raw value.
package main
import (
"context"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
v, err := evo.Value("go-version", "1.23").Fingerprint(context.Background())
if err != nil {
fmt.Println(err)
return
}
fmt.Println(v.Key)
}
Output: go-version
type FixedClock ¶
type FixedClock = engine.FixedClock
Example ¶
ExampleFixedClock always returns the same instant — the deterministic clock every timestamp-sensitive test in this repo injects via evo.Clock.
package main
import (
"fmt"
"time"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
clock := evo.FixedClock{T: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)}
fmt.Println(clock.Now())
}
Output: 2024-01-01 00:00:00 +0000 UTC
type Format ¶ added in v0.2.0
Example ¶
ExampleFormat selects the overall stream-routing mode — zero is FormatHuman, ordinary human (and optional interactive) presentation.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
f := evo.FormatData
fmt.Println(f == evo.FormatData)
}
Output: true
func ParseFormat ¶ added in v1.0.0
ParseFormat parses "human", "data", "external", "json", or "jsonl" (case-insensitive, surrounding whitespace ignored) into a Format — the entry point a host CLI's own --format/--json flag binds to (spec §32.1). Evo does not parse os.Args itself, and never infers FormatJSON merely because Stdout is a pipe.
Example ¶
ExampleParseFormat parses a host CLI's own --format/--json flag value — evo does not parse os.Args itself, and never infers FormatJSON merely because Stdout is a pipe.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
f, err := evo.ParseFormat("json")
fmt.Println(err, f == evo.FormatJSON)
}
Output: <nil> true
type GlyphProfile ¶ added in v0.3.0
type GlyphProfile = txt.GlyphProfile
GlyphProfile selects which glyph vocabulary state markers render in (evo-rec.md "Tightened glyph vocabulary", rule GLYPH-001: glyph selection via capability profile, cell-width measurement not rune counts).
The zero value, GlyphsAuto, keeps today's Unicode vocabulary off a TTY (a non-interactive stream can't show a human mojibake, so there is nothing to guard against) and on any TTY whose locale already advertises UTF-8. It downgrades to the ASCII vocabulary only on an interactive terminal without UTF-8 locale support — the one case where the status column would otherwise render as mojibake.
Aliased into internal/text (glyph tables and the rendering primitives that select from them live there — see EVIDENT_OUTPUT_ARCHITECTURE_SPEC_v0.5.md §38).
Example ¶
ExampleGlyphProfile shows the vocabulary selector Glyphs takes: the zero value, GlyphsAuto, detects Unicode-vs-ASCII from locale and interactivity.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
profile := evo.GlyphsUnicode
fmt.Println(profile == evo.GlyphsUnicode)
}
Output: true
type GroupHandle ¶ added in v0.3.0
type GroupHandle struct {
// contains filtered or unexported fields
}
Example ¶
ExampleGroupHandle shows the collection handle Group returns: it declares its own children and reports a collection-level Snapshot.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
group := out.Group("packages")
group.Task("curl").Done()
_ = out.Finish()
fmt.Println(group.Snapshot().Name)
}
Output: packages
func Group ¶ added in v0.3.0
func Group(name string) *GroupHandle
Example ¶
ExampleGroup declares an independent, concurrent collection of child Tasks on the default instance.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true}))
install := evo.Group("install")
install.Task("curl").Done()
_ = evo.Default().Finish()
fmt.Print(buf.String())
}
Output: ✓ install ✓ curl
func (*GroupHandle) Group ¶ added in v0.5.0
func (g *GroupHandle) Group(name string) *GroupHandle
func (*GroupHandle) Sequence ¶ added in v0.5.0
func (g *GroupHandle) Sequence(name string) *SequenceHandle
func (*GroupHandle) Snapshot ¶ added in v0.3.0
func (g *GroupHandle) Snapshot() TasksSnapshot
func (*GroupHandle) Summary ¶ added in v0.3.0
func (g *GroupHandle) Summary(text string) *GroupHandle
func (*GroupHandle) Task ¶ added in v0.3.0
func (g *GroupHandle) Task(name string) *TaskHandle
type JSONAction ¶
type JSONAction = render.JSONAction
JSONAction is a wire-format action.
Example ¶
ExampleJSONAction shows a wire-format recommended next step.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
a := evo.JSONAction{Label: "retry with --force"}
fmt.Println(a.Label)
}
Output: retry with --force
type JSONChanges ¶
type JSONChanges = render.JSONChanges
JSONChanges is wire-format changes.
Example ¶
ExampleJSONChanges shows wire-format changes.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
c := evo.JSONChanges{Subject: "branches", Records: []evo.JSONEffectRecord{{Verb: "deleted", Object: "stale branch"}}}
fmt.Println(c.Subject, c.Records[0].Verb)
}
Output: branches deleted
type JSONCollection ¶
type JSONCollection = render.JSONCollection
JSONCollection is a wire-format task collection with child IDs (§25.1).
Example ¶
ExampleJSONCollection shows a wire-format task collection with child IDs (§25.1).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
c := evo.JSONCollection{Name: "packages", Children: []string{"curl"}}
fmt.Println(c.Name, c.Children)
}
Output: packages [curl]
type JSONCommand ¶
type JSONCommand = render.JSONCommand
JSONCommand is argv for display.
Example ¶
ExampleJSONCommand shows argv for display on the wire.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
c := evo.JSONCommand{Executable: "git", Args: []string{"push", "--force-with-lease"}}
fmt.Println(c.Executable, c.Args)
}
Output: git [push --force-with-lease]
type JSONDocument ¶
type JSONDocument = render.JSONDocument
JSONDocument is the final machine projection (§25.1).
Aliased into internal/render alongside the JSON encoding machinery that produces it — see EVIDENT_OUTPUT_ARCHITECTURE_SPEC_v0.5.md §38.
Example ¶
ExampleJSONDocument shows the final machine projection's top-level shape.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
doc := evo.JSONDocument{SchemaVersion: evo.JSONSchemaVersion}
fmt.Println(doc.SchemaVersion)
}
Output: 0.4
type JSONEffectRecord ¶
type JSONEffectRecord = render.JSONEffectRecord
JSONEffectRecord is a change/plan row.
Example ¶
ExampleJSONEffectRecord shows a change/plan row on the wire.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
q := int64(2)
r := evo.JSONEffectRecord{Verb: "deleted", Quantity: &q, Object: "stale branch"}
fmt.Println(r.Verb, *r.Quantity, r.Object)
}
Output: deleted 2 stale branch
type JSONMessage ¶ added in v0.2.0
type JSONMessage = render.JSONMessage
JSONMessage is a wire-format user-facing message.
Example ¶
ExampleJSONMessage shows a wire-format user-facing message.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
m := evo.JSONMessage{Visibility: "normal", Text: "reading configuration"}
fmt.Println(m.Visibility, m.Text)
}
Output: normal reading configuration
type JSONOutputMeta ¶
type JSONOutputMeta = render.JSONOutputMeta
JSONOutputMeta identifies the output instance.
Example ¶
ExampleJSONOutputMeta identifies the output instance on the wire.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
meta := evo.JSONOutputMeta{Subject: "repo-retire"}
fmt.Println(meta.Subject)
}
Output: repo-retire
type JSONPlan ¶
JSONPlan is wire-format plan.
Example ¶
ExampleJSONPlan shows wire-format plan.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
p := evo.JSONPlan{Subject: "branches", Records: []evo.JSONEffectRecord{{Verb: "delete", Object: "stale branch"}}}
fmt.Println(p.Subject, p.Records[0].Verb)
}
Output: branches delete
type JSONProblem ¶
type JSONProblem = render.JSONProblem
JSONProblem is a wire-format problem (no raw Cause by default).
Example ¶
ExampleJSONProblem shows a wire-format problem (no raw Cause by default).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
p := evo.JSONProblem{Summary: "schema mismatch", Code: "E_SCHEMA"}
fmt.Println(p.Summary, p.Code)
}
Output: schema mismatch E_SCHEMA
type JSONProgress ¶
type JSONProgress = render.JSONProgress
JSONProgress is wire-format progress.
Example ¶
ExampleJSONProgress shows wire-format progress.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
p := evo.JSONProgress{Kind: evo.Determinate, Completed: 50, Total: 100}
fmt.Println(p.Kind, p.Completed, p.Total)
}
Output: determinate 50 100
type JSONTask ¶
JSONTask is a wire-format task.
Example ¶
ExampleJSONTask shows a wire-format task.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
t := evo.JSONTask{Name: "apply patch", State: evo.Done}
fmt.Println(t.Name, t.State)
}
Output: apply patch done
type LiveSurface ¶
type LiveSurface = engine.LiveSurface
Example ¶
ExampleLiveSurface shows the interactive terminal surface a live-region renderer paints onto — a superset of TerminalDriver.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var surface evo.LiveSurface = fakeLiveSurface{}
fmt.Println(surface.ID(), surface.IsInteractive())
}
// fakeLiveSurface is a minimal evo.LiveSurface for ExampleLiveSurface — real
// callers pass a concrete driver (e.g. from internal/terminal).
type fakeLiveSurface struct{}
func (fakeLiveSurface) ID() string { return "fake" }
func (fakeLiveSurface) Columns() int { return 80 }
func (fakeLiveSurface) Rows() int { return 24 }
func (fakeLiveSurface) IsInteractive() bool { return false }
func (fakeLiveSurface) WriteLive(string) {}
func (fakeLiveSurface) ClearLive() {}
func (fakeLiveSurface) WriteDurable(string) {}
func (fakeLiveSurface) WriteFinal(string) {}
Output: fake false
type LogLevel ¶
Example ¶
ExampleLogLevel shows the Debug journal threshold — its own type, distinct from slog.Level (SlogHandler translates between the two internally).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
level := evo.LevelDebug
fmt.Println(level == evo.LevelDebug)
}
Output: true
type LogRecord ¶ added in v0.2.4
Example ¶
ExampleLogRecord shows the shape journaled to Debug/Capture mirrors and the slog bridge: a time, level, message, and structured attrs.
package main
import (
"fmt"
"log/slog"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
rec := evo.LogRecord{Message: "starting up", Level: slog.LevelInfo}
fmt.Println(rec.Message, rec.Level)
}
Output: starting up INFO
type MessageSnapshot ¶ added in v0.2.0
type MessageSnapshot = core.MessageSnapshot
MessageSnapshot is one logical user-facing message in the canonical model.
Example ¶
ExampleMessageSnapshot shows one logical user-facing message in the canonical model, read from a finished Snapshot.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
evo.SetDefault(out)
evo.Println("reading configuration")
_ = out.Finish()
msg := out.Snapshot().Messages[0]
fmt.Println(msg.Text, msg.Visibility == evo.VisibilityNormal)
}
Output: reading configuration true
type MutationOption ¶ added in v0.5.0
type MutationOption = engine.MutationOption
Example ¶
ExampleMutationOption shows the interface Affected implements, configuring how many objects one atomic mutation touches.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.Affected(3)
fmt.Println(opt != nil)
}
Output: true
func Affected ¶ added in v0.4.0
func Affected(n int) MutationOption
Example ¶
ExampleAffected sets how many objects one atomic mutation touches — omit it for a Task that affects a single item.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
task := out.Task("prune branches")
task.Delete("stale branches", func() error { return nil }, evo.Affected(5))
_ = task.Wait()
_ = out.Finish()
fmt.Println(task.Snapshot().State)
}
Output: done
type NoopRedactor ¶
type NoopRedactor = engine.NoopRedactor
Example ¶
ExampleNoopRedactor leaves strings unchanged — the default Redactor.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var r evo.NoopRedactor
fmt.Println(r.RedactString("token=abc123"))
}
Output: token=abc123
type Option ¶
Example ¶
ExampleOption shows the functional-option interface every Config knob below (AlsoWrite, Plain, Width, ...) implements.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.NoColor()
fmt.Println(opt != nil)
}
Output: true
func AlsoWrite ¶
Example ¶
ExampleAlsoWrite mirrors every written byte to an additional writer — useful for tee-ing human output to a log file alongside the terminal.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
var mirror bytes.Buffer
fmt.Print(runOption(evo.AlsoWrite(&mirror)))
fmt.Println(mirror.Len() > 0)
}
Output: ✓ demo true
func Clock ¶
func Clock(ts TimeSource) Option
Example ¶
ExampleClock injects a deterministic TimeSource in place of the real wall clock — the seam every timestamp-sensitive test in this repo uses.
package main
import (
"bytes"
"fmt"
"time"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fixed := evo.FixedClock{T: time.Date(2024, 1, 1, 0, 0, 0, 0, time.UTC)}
fmt.Print(runOption(evo.Clock(fixed)))
}
Output: ✓ demo
func DataProjection ¶
func DataProjection() Option
Example ¶
ExampleDataProjection reserves Stdout for the application's domain payload; human presentation moves to Stderr.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{
Isolated: true, Plain: true, Stdout: io.Discard, Stderr: &buf, Options: []evo.Option{evo.DataProjection()},
})
out.Task("demo").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ demo
func DebugAddSource ¶ added in v0.3.0
func DebugAddSource() Option
Example ¶
ExampleDebugAddSource resolves each debug record's call site to a source=file.go:line field on human/pane/history rendering.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.DebugAddSource()))
}
Output: ✓ demo
func DebugHistory ¶
func DebugHistory() Option
Example ¶
ExampleDebugHistory selects durable scrollback (the default) for the debug journal — appended above the live region instead of a bounded pane.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.DebugHistory()))
}
Output: ✓ demo
func DebugLevel ¶
Example ¶
ExampleDebugLevel sets the minimum debug journal level, surfacing Debug/Capture mirrors when set to LevelTrace or LevelDebug.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.DebugLevel(evo.LevelDebug)))
}
Output: ✓ demo
func DebugPane ¶
func DebugPane(opts ...DebugPaneOption) Option
Example ¶
ExampleDebugPane selects a bounded rolling viewport for the debug journal instead of durable scrollback.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.DebugPane(evo.PaneHeight(3))))
}
Output: ✓ demo
func Diagnostics ¶
Example ¶
ExampleDiagnostics routes diagnostics (the debug journal's default destination) to an explicit writer.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
var diag bytes.Buffer
fmt.Print(runOption(evo.Diagnostics(&diag)))
}
Output: ✓ demo
func DryRun ¶ added in v0.3.0
func DryRun() Option
Example ¶
ExampleDryRun declares the run a dry run: mutation verbs render as [planned] rows with the imperative verb instead of [changed] rows.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard, DryRun: true})
out.Task("prune branches").Delete("stale branch", func() error { return nil }, evo.Affected(3))
_ = out.Finish()
fmt.Print(buf.String())
}
Output: [dry-run] no changes will be made ✓ prune branches [planned] prune branches delete 3 stale branches [planned]
func ExternalProjection ¶
func ExternalProjection() Option
Example ¶
ExampleExternalProjection disables inline rendering entirely — only snapshots are available, for an embedder that owns its own presentation.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.ExternalProjection()))
}
Output: ✓ demo
func Glyphs ¶ added in v0.3.0
func Glyphs(p GlyphProfile) Option
Glyphs selects the glyph capability profile (default GlyphsAuto).
Example ¶
ExampleGlyphs selects the state-glyph vocabulary — GlyphsASCII forces the ASCII vocabulary regardless of locale.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.Glyphs(evo.GlyphsASCII)))
}
Output: [ok] demo
func MaxEntities ¶
Example ¶
ExampleMaxEntities caps how many entities the debug journal / history retains before it starts dropping the oldest.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.MaxEntities(64)))
}
Output: ✓ demo
func MaxEvents ¶
Example ¶
ExampleMaxEvents caps how many durable events the journal retains.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.MaxEvents(64)))
}
Output: ✓ demo
func MaxFrameRate ¶
Example ¶
ExampleMaxFrameRate caps how often the live region repaints per second.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.MaxFrameRate(30)))
}
Output: ✓ demo
func NoColor ¶
func NoColor() Option
Example ¶
ExampleNoColor disables semantic color regardless of TTY/NO_COLOR detection.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption())
}
Output: ✓ demo
func Plain ¶
func Plain() Option
Example ¶
ExamplePlain disables live interactive frames, on a TTY or off — the durable report every non-interactive CI log needs.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption())
}
Output: ✓ demo
func Redact ¶
Example ¶
ExampleRedact injects a Redactor that scrubs sensitive values before journal, Capture retention, and human rendering.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.Redact(evo.NoopRedactor{})))
}
Output: ✓ demo
func ResultStream ¶ added in v0.2.3
Example ¶
ExampleResultStream routes the domain-payload writer FormatData's ResultWriter falls back to when Config.Result is unset.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
var result bytes.Buffer
fmt.Print(runOption(evo.ResultStream(&result)))
}
Output: ✓ demo
func Runner ¶ added in v1.0.0
func Runner(r ProcessRunner) Option
Example ¶
ExampleRunner installs a ProcessRunner other than the real spawner — the seam every evo.Exec test in this repo uses to replace the OS process with a deterministic testkit fake.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
"github.com/zachbornheimer/evident-output/testkit"
)
func main() {
runner := testkit.NewProcessRunner()
runner.Script("/usr/bin/tool", testkit.ScriptedProcess{ExitCode: 0})
var buf bytes.Buffer
out := evo.Init(evo.Config{
Isolated: true, Stdout: &buf, Stderr: io.Discard, Plain: true,
Options: []evo.Option{evo.Runner(runner)},
})
out.Task("demo").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ demo
func Stdin ¶ added in v0.3.0
Example ¶
ExampleStdin sets the facade Confirm reads one answer line from — Plain mode never reads stdin (it blocks on policy instead), so this Example leaves live rendering enabled and only points Stdin at a canned answer.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
answer := bytes.NewBufferString("y\n")
out := evo.Init(evo.Config{
Isolated: true, Stdout: io.Discard, Stderr: io.Discard,
Options: []evo.Option{evo.To(io.Discard), evo.Stdin(answer)},
})
ok := out.Confirm("continue?")
fmt.Println(ok)
}
Output: true
func Strict ¶
func Strict() Option
Example ¶
ExampleStrict makes every recorded misuse panic instead of only counting it — a debug-build safety net for library-authoring call sites.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.Strict()))
}
Output: ✓ demo
func Terminal ¶
func Terminal(driver TerminalDriver) Option
Example ¶
ExampleTerminal injects a custom TerminalDriver for identity/sink detection instead of evident-output's own terminal probing.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.Terminal(namedTerminal{"custom"})))
}
// namedTerminal is a minimal evo.TerminalDriver for ExampleTerminal — real
// callers pass a concrete driver (e.g. from internal/terminal); this
// package's Example only needs one that satisfies the interface.
type namedTerminal struct{ id string }
func (t namedTerminal) ID() string { return t.id }
Output: ✓ demo
func Title ¶ added in v0.2.7
Example ¶
ExampleTitle sets the subject shown in the conclusion band.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard, Title: "repo-retire"})
out.Task("scan").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ scan [ready] repo-retire
func To ¶
Example ¶
ExampleTo routes the ordinary human stream to an explicit writer.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption())
}
Output: ✓ demo
func VisibilityDelay ¶
Example ¶
ExampleVisibilityDelay sets the wait before the first live paint — use evo.Delay(d) to build the *time.Duration value from a literal.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.VisibilityDelay(0)))
}
Output: ✓ demo
func Width ¶
Example ¶
ExampleWidth sets a fixed render width instead of detecting the terminal's own column count.
package main
import (
"bytes"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
// runOption builds an isolated Output from the raw-Option escape hatch
// (Config.Options), declares one Task, Finishes, and returns the rendered
// plain-text bytes — the shared shape every Option Example below uses to
// prove its option compiles and participates in a real run.
func runOption(opts ...evo.Option) string {
var buf bytes.Buffer
all := append([]evo.Option{evo.To(&buf), evo.Plain(), evo.NoColor()}, opts...)
out := evo.Init(evo.Config{Isolated: true, Options: all})
out.Task("demo").Done()
_ = out.Finish()
return buf.String()
}
func main() {
fmt.Print(runOption(evo.Width(80)))
}
Output: ✓ demo
type Output ¶
type Output struct {
// contains filtered or unexported fields
}
Output, TaskHandle, and the other presentation handles are wrappers, not aliases: engine test helpers must not appear in go doc or the rec surface.
Example ¶
ExampleOutput shows the hosted-instance shape: build an isolated Output, declare a Task on it directly, and Finish it — never touching the package-level default.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true, Isolated: true})
out.Task("build").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ build
func Default ¶ added in v0.3.0
func Default() *Output
Default returns the package-level default Output, lazily creating one with a zero Config the first time it's needed.
Example ¶
ExampleDefault shows the package-level default instance, lazily created with a zero Config.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
evo.SetDefault(nil)
out := evo.Default()
fmt.Println(out != nil)
}
Output: true
func Init ¶ added in v0.3.0
Init is the sole Output constructor. It builds an Output from cfg, installs it as the package-level default, and arms first paint — call once, in main, before any I/O.
Example ¶
ExampleInit shows the sole Output constructor: build one, declare a task, and Finish it.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true, Isolated: true})
out.Task("read config").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ read config
func (*Output) Conclusion ¶
func (o *Output) Conclusion() Conclusion
func (*Output) Confirm ¶ added in v0.3.0
func (o *Output) Confirm(question string, opts ...ConfirmOption) bool
func (*Output) Fail ¶
func (o *Output) Fail(summary string, options ...ProblemOption)
func (*Output) Group ¶ added in v0.3.0
func (o *Output) Group(name string) *GroupHandle
func (*Output) NextCommand ¶
func (*Output) ResultWriter ¶ added in v0.2.3
func (*Output) Run ¶ added in v0.3.0
Run executes run against o and returns the Result (Conclusion plus the application error, if any); it never exits the process.
func (*Output) Sequence ¶ added in v0.4.0
func (o *Output) Sequence(name string) *SequenceHandle
func (*Output) Task ¶
func (o *Output) Task(name string) *TaskHandle
type PlainOptions ¶
type PlainOptions = engine.PlainOptions
Example ¶
ExamplePlainOptions configures RenderPlain's durable-report rendering.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opts := evo.PlainOptions{Width: 80, NoColor: true}
fmt.Println(opts.Width, opts.NoColor)
}
Output: 80 true
type PlanSnapshot ¶
type PlanSnapshot = core.PlanSnapshot
PlanSnapshot is an immutable plan section.
Example ¶
ExamplePlanSnapshot reads an immutable plan section: the records a mutation verb recorded under DryRun.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true, DryRun: true})
out.Task("prune branches").Delete("stale branch", func() error { return nil }, evo.Affected(2))
_ = out.Finish()
plan := out.Snapshot().Plans[0]
fmt.Println(plan.Records[0].Verb, plan.Records[0].Quantity)
}
Output: delete 2
type Printer ¶ added in v0.2.0
type Printer struct {
// contains filtered or unexported fields
}
Example ¶
ExamplePrinter shows the Printer handle's own Print/Printf/Println verbs — evo.Verbose() is the only constructor that returns one.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{
Stdout: &buf, Stderr: io.Discard, Plain: true, Verbosity: evo.VerbosityVerbose,
}))
printer := evo.Verbose()
printer.Print("cache ")
printer.Printf("hit for %s", "module x")
printer.Println()
_ = evo.Default().Finish()
fmt.Print(buf.String())
}
Output: cache hit for module x
func Verbose ¶ added in v0.2.0
func Verbose() *Printer
Verbose returns a Printer scoped to Verbose visibility on the default instance.
Example ¶
ExampleVerbose shows a Printer scoped to Verbose visibility: it only projects when Config.Verbosity is VerbosityVerbose.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{
Stdout: &buf, Stderr: io.Discard, Plain: true, Verbosity: evo.VerbosityVerbose,
}))
evo.Verbose().Println("cache hit for module x")
_ = evo.Default().Finish()
fmt.Print(buf.String())
}
Output: cache hit for module x
type Problem ¶
Problem is structured evidence explaining a negative item or task outcome.
Aliased into internal/core alongside the rest of the data model — see Snapshot's doc comment (snapshot.go) for why.
Example ¶
ExampleProblem shows the structured evidence shape explaining a negative task outcome — the payload Fail/Block/Warn build from ProblemOptions.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
p := evo.Problem{Summary: "schema mismatch", Code: "E_SCHEMA"}
fmt.Println(p.Summary, p.Code)
}
Output: schema mismatch E_SCHEMA
type ProblemOption ¶
type ProblemOption = engine.ProblemOption
ProblemOption configures a problem constructed by Block/Warn/Fail helpers.
Example ¶
ExampleProblemOption shows the interface every Problem-configuring constructor (Detail, Code, On, Count, Location, Next, NextCommand) implements.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.Detail("the file was not found")
fmt.Println(opt != nil)
}
Output: true
func Code ¶
func Code(value string) ProblemOption
Code sets a stable problem code.
Example ¶
ExampleCode sets a stable, machine-readable Problem code a consumer can match on instead of parsing Summary text.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard})
out.Task("apply migration").Fail("schema mismatch", evo.Code("E_SCHEMA"))
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✗ apply migration schema mismatch
func Count ¶
func Count(value int64, unit ...string) ProblemOption
Count sets a quantity and optional unit.
Example ¶
ExampleCount sets a quantity and optional unit on a Problem.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard})
out.Task("upload artifacts").Fail("upload failed", evo.Count(3, "files"))
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✗ upload artifacts upload failed
func Detail ¶
func Detail(text string) ProblemOption
Detail sets user-visible detail text (strings only).
Example ¶
ExampleDetail sets user-visible detail text on a Problem raised via TaskHandle.Fail.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard})
out.Task("read config").Fail("parse error", evo.Detail("unexpected token at line 4"))
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✗ read config parse error └─ unexpected token at line 4
func Location ¶
func Location(path string, line, column int) ProblemOption
Location sets a source location on a Problem (renamed from At — C5: a free-function At collided in name, though not in call syntax, with Output.At(visibility), confusing autocomplete and readers alike).
Example ¶
ExampleLocation sets a source location on a Problem.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard})
out.Task("validate manifest").Fail("unknown field", evo.Location("manifest.yaml", 4, 1))
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✗ validate manifest unknown field
func Next ¶
func Next(action Action) ProblemOption
Next attaches actions to a problem.
Example ¶
ExampleNext attaches a recommended next step to a Problem.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard})
out.Task("push branch").Fail("rejected: non-fast-forward", evo.Next(evo.Label("pull --rebase first")))
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✗ push branch rejected: non-fast-forward
func NextCommand ¶
func NextCommand(executable string, args ...string) ProblemOption
NextCommand attaches a recommended command action.
Example ¶
ExampleNextCommand attaches a recommended command action to a Problem.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard})
out.Task("push branch").Fail("rejected: non-fast-forward", evo.NextCommand("git", "pull", "--rebase"))
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✗ push branch rejected: non-fast-forward
func On ¶
func On(subject string) ProblemOption
On sets the problem subject.
Example ¶
ExampleOn sets the problem subject.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Plain: true, Stdout: &buf, Stderr: io.Discard})
out.Task("clean workspace").Fail("permission denied", evo.On("/var/cache"))
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✗ clean workspace permission denied ├─ /var/cache permission denied
type ProcessCommand ¶ added in v1.0.0
type ProcessCommand = engine.ProcessCommand
Example ¶
ExampleProcessCommand is the resolved shape evo.Exec passes to a ProcessRunner — Path already resolved on PATH, Args exactly as declared, Stdout/Stderr wired to the Task's own capture.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
cmd := evo.ProcessCommand{
Path: "/usr/bin/python3",
Args: []string{"generate.py"},
Stdout: io.Discard,
Stderr: io.Discard,
}
fmt.Println(cmd.Path, len(cmd.Args))
}
Output: /usr/bin/python3 1
type ProcessOutcome ¶ added in v1.0.0
type ProcessOutcome = engine.ProcessOutcome
Example ¶
ExampleProcessOutcome is one spawned command's terminal, already-observed result — a nonzero ExitCode is not itself an error; evo.Exec decides what a nonzero exit means.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
outcome := evo.ProcessOutcome{ExitCode: 0}
fmt.Println(outcome.ExitCode == 0)
}
Output: true
type ProcessRunner ¶ added in v1.0.0
type ProcessRunner = engine.ProcessRunner
Example ¶
ExampleProcessRunner is the facade every evo.Exec spawn goes through instead of exec.Cmd/os/exec directly — testkit.ProcessRunner satisfies it deterministically for tests; production uses the real spawner.
package main
import (
"context"
"fmt"
evo "github.com/zachbornheimer/evident-output"
"github.com/zachbornheimer/evident-output/testkit"
)
func main() {
runner := testkit.NewProcessRunner()
runner.Script("/usr/bin/tool", testkit.ScriptedProcess{ExitCode: 0})
outcome, err := runner.Run(context.Background(), evo.ProcessCommand{Path: "/usr/bin/tool"})
fmt.Println(err == nil, outcome.ExitCode)
}
Output: true 0
type Progress ¶
Progress is absolute measurement for a task.
Example ¶
ExampleProgress shows the absolute measurement TaskHandle.Progress records, read back from the resolved TaskSnapshot.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
task := out.Task("download image")
task.Progress(50, 100)
task.Done()
_ = out.Finish()
p := task.Snapshot().Progress
fmt.Println(p.Completed, p.Total)
}
Output: 50 100
type ProgressKind ¶
type ProgressKind = core.ProgressKind
ProgressKind classifies task measurement.
Example ¶
ExampleProgressKind classifies which measurement a task's Progress reports.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
kind := evo.Determinate
fmt.Println(kind == evo.Determinate)
}
Output: true
type Projection ¶ added in v0.5.0
type Projection = engine.Projection
Example ¶
ExampleProjection selects presentation encoding independent of Format — human, plain, json, jsonl, or stream-json.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
p := evo.ProjectionPlain
fmt.Println(p == evo.ProjectionPlain)
}
Output: true
type ReasonOption ¶ added in v0.3.0
type ReasonOption = engine.ReasonOption
Example ¶
ExampleReasonOption shows the interface every Reason constraint (ForSkip, OnTask) implements.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.ForSkip()
fmt.Println(opt != nil)
}
Output: true
func ForSkip ¶ added in v0.3.0
func ForSkip() ReasonOption
Example ¶
ExampleForSkip shows constructing the ReasonOption that restricts a taxonomy Reason to TaskHandle.Skipped (recording it via Kept is misuse). evo.Reason itself takes no options today — this constrained-reason form is reachable only through the internal reasonGetOrCreate a future advanced entrypoint would expose; the option value is still real and constructible.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.ForSkip()
fmt.Println(opt != nil)
}
Output: true
func OnTask ¶ added in v0.3.0
func OnTask(taskName string) ReasonOption
Example ¶
ExampleOnTask shows constructing the ReasonOption that restricts a taxonomy Reason to one named task (see ExampleForSkip for why it isn't wired through evo.Reason yet).
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
opt := evo.OnTask("integration tests")
fmt.Println(opt != nil)
}
Output: true
type Redactor ¶
Example ¶
ExampleRedactor redacts sensitive values before journal, Capture retention, and human rendering.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var r evo.Redactor = evo.NoopRedactor{}
fmt.Println(r.RedactString("token=abc123"))
}
Output: token=abc123
type Resolution ¶ added in v1.0.0
type Resolution = core.Resolution
Resolution names why a Task settled successfully (§29/§30).
Example ¶
ExampleResolution names why a Task settled successfully.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
task := out.Task("apply patch")
task.Done()
_ = out.Finish()
fmt.Println(task.Snapshot().Resolution == evo.ResolutionNoWork)
}
Output: true
type Result ¶ added in v1.0.0
Result is the outcome of Run/Main/Output.Run — the finished Conclusion plus the application error the run callback returned, if any. Run and Output.Run return it directly; Main derives its int exit code from it. See EVIDENT_OUTPUT_ARCHITECTURE spec §1.1, §32.2.
Example ¶
ExampleResult shows the outcome of Run/Main/Output.Run: the finished Conclusion plus the application error, if any.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
result := evo.Result{Conclusion: evo.Conclusion{State: evo.StateFailed, ExitCode: evo.ExitFailed}}
fmt.Println(result.ExitCode())
}
Output: 2
func Run ¶ added in v0.4.0
Run executes run against the default Output and returns the Result (Conclusion plus the application error, if any); it never exits the process.
Example ¶
ExampleRun shows executing application work against the default instance and inspecting the returned Result instead of exiting the process.
package main
import (
"bytes"
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true}))
result := evo.Run(context.Background(), func(ctx context.Context) error {
evo.Task("apply migration").Done()
return nil
})
fmt.Println(result.Err)
fmt.Println(result.Conclusion.State)
}
Output: <nil> ready
type RunFunc ¶ added in v1.0.0
RunFunc is the shape of application work handed to Run/Main/Output.Run — a context.Context carries cancellation (wired to SIGINT/SIGTERM by those entrypoints) in place of the pre-v0.6 no-context func() error form.
Example ¶
ExampleRunFunc shows the RunFunc shape application code hands to Run/Main/Output.Run: a context.Context in, an error out.
package main
import (
"context"
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var run evo.RunFunc = func(ctx context.Context) error { return nil }
fmt.Println(run(context.Background()))
}
Output: <nil>
type SequenceHandle ¶ added in v0.4.0
type SequenceHandle struct {
// contains filtered or unexported fields
}
Example ¶
ExampleSequenceHandle shows the ordered collection handle Sequence returns.
package main
import (
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
seq := out.Sequence("stages")
task := seq.Task("build")
task.Define(func(ctx context.Context) error { return nil })
_ = out.Finish()
fmt.Println(seq.Snapshot().Name)
}
Output: stages
func Sequence ¶ added in v0.4.0
func Sequence(name string) *SequenceHandle
Sequence declares a self-managing, ordered task container on the default instance.
Example ¶
ExampleSequence declares a self-managing, ordered task container: one Running child at a time, in declaration order.
package main
import (
"bytes"
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true}))
worktrees := evo.Sequence("worktrees")
for _, path := range []string{"repo-a", "repo-b"} {
task := worktrees.Task(path)
task.Define(func(ctx context.Context) error { return nil })
}
_ = evo.Default().Finish()
fmt.Print(buf.String())
}
Output: ✓ worktrees ✓ repo-a ✓ repo-b
func (*SequenceHandle) Group ¶ added in v0.5.0
func (s *SequenceHandle) Group(name string) *GroupHandle
func (*SequenceHandle) Sequence ¶ added in v0.4.0
func (s *SequenceHandle) Sequence(name string) *SequenceHandle
func (*SequenceHandle) Snapshot ¶ added in v0.4.0
func (s *SequenceHandle) Snapshot() TasksSnapshot
func (*SequenceHandle) Summary ¶ added in v0.4.0
func (s *SequenceHandle) Summary(text string) *SequenceHandle
func (*SequenceHandle) Task ¶ added in v0.4.0
func (s *SequenceHandle) Task(name string) *TaskHandle
type Snapshot ¶
Snapshot is an immutable complete presentation state at a version.
Declared as a type alias into internal/core (the repo's data-model package — see EVIDENT_OUTPUT_ARCHITECTURE_SPEC_v0.5.md §38): rendering and evidence-capture machinery import core, never this root package, so the data model has to live where they can reach it without an import cycle back through the behavioral facades (Output, TaskHandle, evidence) that stay declared here. pkg.go.dev cannot expand an aliased type's fields (internal/core is never rendered) — see docs/reference.md for the full field-level reference this doc comment summarizes.
Example ¶
ExampleSnapshot reads the immutable complete presentation state of a finished run.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
out.Task("apply patch").Done()
_ = out.Finish()
snap := out.Snapshot()
fmt.Println(len(snap.Tasks))
}
Output: 1
type SourceLocation ¶ added in v0.3.0
type SourceLocation = core.SourceLocation
SourceLocation is a path-based source position. Named SourceLocation (not Location) so the Location(...) ProblemOption constructor below can keep that name without colliding with its own return type.
Example ¶
ExampleSourceLocation shows a path-based source position attached to a Problem via Location.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
loc := evo.SourceLocation{Path: "config.yaml", Line: 12, Column: 3}
fmt.Println(loc.Path, loc.Line, loc.Column)
}
Output: config.yaml 12 3
type SystemClock ¶
type SystemClock = engine.SystemClock
Example ¶
ExampleSystemClock uses the real wall clock — the default TimeSource.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var clock evo.SystemClock
fmt.Println(clock.Now().IsZero())
}
Output: false
type TaskEvidence ¶ added in v1.0.0
type TaskEvidence = core.TaskEvidence
TaskEvidence preserves both observation phases a Task's Verify may have recorded (§30).
Example ¶
ExampleTaskEvidence preserves both observation phases a Task's Verify may record: a before-false/after-true transition is never collapsed into one final boolean.
package main
import (
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
task := out.Task("ensure directory")
first := true
task.Verify(func(ctx context.Context) (bool, error) {
satisfied := !first
first = false
return satisfied, nil
})
task.Define(func(ctx context.Context) error { return nil })
_ = out.Finish()
ev := task.Snapshot().Evidence
fmt.Println(ev.Before.Satisfied, ev.After.Satisfied)
}
Output: false true
type TaskHandle ¶ added in v0.3.0
type TaskHandle struct {
// contains filtered or unexported fields
}
Example ¶
ExampleTaskHandle shows a Task carrying work via Define instead of a bare Done — the handle Task returns.
package main
import (
"bytes"
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true, Isolated: true})
handle := out.Task("fetch")
handle.Define(func(ctx context.Context) error { return nil })
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ fetch
func Task ¶
func Task(name string) *TaskHandle
Task declares a Task on the default instance.
Example ¶
ExampleTask declares a Task on the default instance and resolves it.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
evo.SetDefault(evo.Init(evo.Config{Stdout: &buf, Stderr: io.Discard, Plain: true}))
evo.Task("working tree").Done()
_ = evo.Default().Finish()
fmt.Print(buf.String())
}
Output: ✓ working tree
func (*TaskHandle) Add ¶ added in v0.3.0
func (t *TaskHandle) Add(object string, fn func() error, opts ...MutationOption)
func (*TaskHandle) After ¶ added in v0.5.0
func (t *TaskHandle) After(preds ...any) *TaskHandle
func (*TaskHandle) Block ¶ added in v0.3.0
func (t *TaskHandle) Block(summary string, options ...ProblemOption)
func (*TaskHandle) Blockf ¶ added in v0.3.0
func (t *TaskHandle) Blockf(format string, args ...any) *Failure
func (*TaskHandle) Bytes ¶ added in v0.3.0
func (t *TaskHandle) Bytes(completed, total int64) *TaskHandle
func (*TaskHandle) Cancel ¶ added in v0.3.0
func (t *TaskHandle) Cancel(reason string)
func (*TaskHandle) Context ¶ added in v0.5.0
func (t *TaskHandle) Context() context.Context
func (*TaskHandle) Create ¶ added in v0.3.0
func (t *TaskHandle) Create(object string, fn func() error, opts ...MutationOption)
func (*TaskHandle) Define ¶ added in v0.5.0
func (t *TaskHandle) Define(fn func(context.Context) error)
Define freezes this Task's configuration and submits fn to the scheduler — see internal/engine.TaskHandle.Define (§7).
Example ¶
ExampleTaskHandle_Define submits a Task's atomic work to the scheduler — Define is the scheduling and execution boundary (spec §7): the callback runs on an eligible run unless a current pre-Define Verify already proved the desired state satisfied.
package main
import (
"bytes"
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Stdout: &buf, Stderr: io.Discard, Plain: true})
task := out.Task("migrate")
task.Define(func(ctx context.Context) error { return nil })
_ = task.Wait()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ migrate
func (*TaskHandle) Delete ¶ added in v0.3.0
func (t *TaskHandle) Delete(object string, fn func() error, opts ...MutationOption)
func (*TaskHandle) Doing ¶ added in v0.4.0
func (t *TaskHandle) Doing(text string, args ...any) *TaskHandle
func (*TaskHandle) Done ¶ added in v0.3.0
func (t *TaskHandle) Done(args ...any)
func (*TaskHandle) Fact ¶ added in v0.4.0
func (t *TaskHandle) Fact(name, value string)
Example ¶
ExampleTask_Fact records discovered information — not work — as a durable dim line attached to the Task that found it. Fact never resolves the Task and never fakes a checkmark merely to display a value.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Stdout: &buf, Stderr: io.Discard, Plain: true})
scan := out.Task("remote-tracking")
scan.Fact("stale", "1")
scan.Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ remote-tracking stale 1
func (*TaskHandle) Fail ¶ added in v0.3.0
func (t *TaskHandle) Fail(summary string, options ...ProblemOption)
func (*TaskHandle) Failf ¶ added in v0.3.0
func (t *TaskHandle) Failf(format string, args ...any) *Failure
func (*TaskHandle) Kept ¶ added in v0.3.0
func (t *TaskHandle) Kept(reason TaxonomyReason)
func (*TaskHandle) Key ¶ added in v1.0.0
func (t *TaskHandle) Key(key string) *TaskHandle
Key sets an advanced, refactor/rename-stable override for this Task's §3.1 identity — see internal/engine.TaskHandle.Key.
Example ¶
ExampleTaskHandle_Key sets an advanced, refactor/rename-stable override for a Task's stable identity (spec §3.1) — use it when a Task's name changes across runs but its tracked identity must not.
package main
import (
"bytes"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var buf bytes.Buffer
out := evo.Init(evo.Config{Isolated: true, Stdout: &buf, Stderr: io.Discard, Plain: true})
out.Task("migrate 003_add_users.sql").Key("migration:003").Done()
_ = out.Finish()
fmt.Print(buf.String())
}
Output: ✓ migrate 003_add_users.sql
func (*TaskHandle) Next ¶ added in v0.3.0
func (t *TaskHandle) Next(actions ...Action) *TaskHandle
func (*TaskHandle) NextCommand ¶ added in v0.3.0
func (t *TaskHandle) NextCommand(executable string, args ...string) *TaskHandle
func (*TaskHandle) Progress ¶ added in v0.3.0
func (t *TaskHandle) Progress(completed, total int) *TaskHandle
func (*TaskHandle) Push ¶ added in v0.3.0
func (t *TaskHandle) Push(object string, fn func() error, opts ...MutationOption)
func (*TaskHandle) Record ¶ added in v0.3.0
func (t *TaskHandle) Record(verb string, quantity int, object string)
func (*TaskHandle) RecordLabel ¶ added in v0.3.0
func (t *TaskHandle) RecordLabel(label string, quantity int, object string)
func (*TaskHandle) RecordName ¶ added in v0.3.0
func (t *TaskHandle) RecordName(verb, object string)
func (*TaskHandle) Remove ¶ added in v0.3.0
func (t *TaskHandle) Remove(object string, fn func() error, opts ...MutationOption)
func (*TaskHandle) Skipped ¶ added in v0.3.0
func (t *TaskHandle) Skipped(reason TaxonomyReason)
func (*TaskHandle) Snapshot ¶ added in v0.3.0
func (t *TaskHandle) Snapshot() TaskSnapshot
func (*TaskHandle) Step ¶ added in v0.3.0
func (t *TaskHandle) Step(completed, total int, name string) *TaskHandle
func (*TaskHandle) Update ¶ added in v0.3.0
func (t *TaskHandle) Update(object string, fn func() error, opts ...MutationOption)
func (*TaskHandle) Verify ¶ added in v1.0.0
func (t *TaskHandle) Verify(fn func(context.Context) (bool, error)) *TaskHandle
Verify registers an advanced current-state observation check — see internal/engine.TaskHandle.Verify (§9.1).
Example ¶
ExampleTaskHandle_Verify registers a boolean, read-only pre-Define check. A Verify that reports the desired state already holds skips Define entirely and resolves ResolutionAlreadySatisfied — the one advanced escape hatch for domains Evo cannot track automatically (spec §56).
package main
import (
"context"
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Isolated: true, Stdout: io.Discard, Stderr: io.Discard})
task := out.Task("already-configured")
task.Verify(func(ctx context.Context) (bool, error) { return true, nil })
task.Define(func(ctx context.Context) error {
panic("Define must not run once Verify reports already satisfied")
})
_ = task.Wait()
fmt.Println(task.Snapshot().Resolution)
}
Output: already_satisfied
func (*TaskHandle) Wait ¶ added in v0.5.0
func (t *TaskHandle) Wait() error
func (*TaskHandle) Warn ¶ added in v0.3.0
func (t *TaskHandle) Warn(summary string)
func (*TaskHandle) Write ¶ added in v0.3.0
func (t *TaskHandle) Write(object string, fn func() error, opts ...MutationOption)
func (*TaskHandle) Writer ¶ added in v0.4.0
func (t *TaskHandle) Writer() io.Writer
type TaskSnapshot ¶
type TaskSnapshot = core.TaskSnapshot
TaskSnapshot is an immutable task view.
Example ¶
ExampleTaskSnapshot reads a Task's immutable view after it resolves.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
task := out.Task("apply patch")
task.Done()
_ = out.Finish()
snap := task.Snapshot()
fmt.Println(snap.Name, snap.State)
}
Output: apply patch done
type TasksSnapshot ¶
type TasksSnapshot = core.TasksSnapshot
TasksSnapshot is an immutable collection view.
Example ¶
ExampleTasksSnapshot reads a collection's immutable view: its own state plus every child Task it declared.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
group := out.Group("packages")
group.Task("curl").Done()
_ = out.Finish()
snap := group.Snapshot()
fmt.Println(snap.Name, len(snap.Tasks))
}
Output: packages 1
type TaxonomyReason ¶ added in v0.3.0
type TaxonomyReason struct {
// contains filtered or unexported fields
}
Example ¶
ExampleTaxonomyReason shows a get-or-create taxonomy Reason: the same string at every call site merges into one bucket.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
evo.SetDefault(out)
first := evo.Reason("dirty working tree")
second := evo.Reason("dirty working tree")
fmt.Println(first.Name() == second.Name())
}
Output: true
func Reason ¶ added in v0.3.0
func Reason(name string) TaxonomyReason
Reason returns a get-or-create taxonomy Reason by name on the default instance.
Example ¶
ExampleReason shows the get-or-create taxonomy lookup an inline evo.Reason("...") call always legally reuses.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
evo.SetDefault(out)
reason := evo.Reason("protected")
fmt.Println(reason.Name())
}
Output: protected
func (TaxonomyReason) Name ¶ added in v0.3.0
func (r TaxonomyReason) Name() string
type TaxonomyRecord ¶ added in v0.3.0
type TaxonomyRecord = core.TaxonomyRecord
TaxonomyRecord is one accumulated (reason, name) disposition entry — recorded by TaskHandle.Skipped or TaskHandle.Kept, never assembled by hand.
Example ¶
ExampleTaxonomyRecord reads the accumulated (reason, name) disposition TaskHandle.Skipped records — never assembled by hand.
package main
import (
"fmt"
"io"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
out := evo.Init(evo.Config{Stdout: io.Discard, Stderr: io.Discard, Plain: true, Isolated: true})
evo.SetDefault(out)
task := out.Task("branch main")
task.Skipped(evo.Reason("protected"))
_ = out.Finish()
record := task.Snapshot().Skipped[0]
fmt.Println(record.Reason, record.Name)
}
Output: protected branch main
type TerminalDriver ¶
type TerminalDriver = engine.TerminalDriver
Example ¶
ExampleTerminalDriver shows the minimal identity interface a custom terminal integration implements — see evo.Terminal.
var driver evo.TerminalDriver = namedTerminal{"custom"}
fmt.Println(driver.ID())
Output: custom
type TimeSource ¶
type TimeSource = engine.TimeSource
Example ¶
ExampleTimeSource shows the deterministic clock interface Clock injects in place of the real wall clock.
package main
import (
"fmt"
"time"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var clock evo.TimeSource = evo.FixedClock{T: time.Unix(0, 0).UTC()}
fmt.Println(clock.Now())
}
Output: 1970-01-01 00:00:00 +0000 UTC
type Verbosity ¶ added in v0.2.0
Example ¶
ExampleVerbosity selects which message visibilities project to the human stream — zero is VerbosityNormal.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
v := evo.VerbosityVerbose
fmt.Println(v == evo.VerbosityVerbose)
}
Output: true
type Visibility ¶ added in v0.2.0
type Visibility = core.Visibility
Visibility selects whether a message is ordinary or verbose user detail. Zero is VisibilityNormal.
Example ¶
ExampleVisibility selects whether a message is ordinary or verbose user detail — zero is VisibilityNormal.
package main
import (
"fmt"
evo "github.com/zachbornheimer/evident-output"
)
func main() {
var v evo.Visibility
fmt.Println(v == evo.VisibilityNormal)
}
Output: true
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
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: domain JSON on stdout, human presentation on stderr.
|
Command data-command: domain JSON on stdout, human presentation on stderr. |
|
debug-history
command
Command debug-history demos a short sequential probe.
|
Command debug-history demos a short sequential probe. |
|
debug-pane
command
Command debug-pane demos a sequential audit with an optional blocker.
|
Command debug-pane demos a sequential audit with an optional blocker. |
|
doctor
command
Command doctor is an environment/health check CLI.
|
Command doctor is an environment/health check CLI. |
|
generate-pipeline
command
Command generate-pipeline demos spec §64's canonical Exec pipeline shape: a normalize stage (schema.xlsx -> schema.json) feeding a compile stage (schema.json + compile.py -> output.bin), sequenced with Sequence (declaration order, never concurrent) the way a real pipeline must be (a Basis relationship alone never implies scheduling order — see docs/acceptance/v0.6.md's Increment 3 section).
|
Command generate-pipeline demos spec §64's canonical Exec pipeline shape: a normalize stage (schema.xlsx -> schema.json) feeding a compile stage (schema.json + compile.py -> output.bin), sequenced with Sequence (declaration order, never concurrent) the way a real pipeline must be (a Basis relationship alone never implies scheduling order — see docs/acceptance/v0.6.md's Increment 3 section). |
|
install-pipeline
command
Command install-pipeline demos Tasks, Progress, Capture, and Main.
|
Command install-pipeline demos Tasks, Progress, Capture, and Main. |
|
internal/demo
Package demo is reserved for advanced example utilities.
|
Package demo is reserved for advanced example utilities. |
|
launch-agent-file
command
Command launch-agent-file demos spec §12's canonical launchd shape: a Sequence writing a managed plist via evo.File, followed by two Verify-gated Tasks stubbed to succeed.
|
Command launch-agent-file demos spec §12's canonical launchd shape: a Sequence writing a managed plist via evo.File, followed by two Verify-gated Tasks stubbed to succeed. |
|
live-progress
command
Command live-progress is the ordinary multi-progress demo (user API only).
|
Command live-progress is the ordinary multi-progress demo (user API only). |
|
migrate
command
Command migrate demonstrates the mutation-verb effect boundary (Add/Create/Write, ...): the same call site records a planned effect under --dry-run (evo.DryRun) or a committed one when it actually runs, and evo derives Changed/Ready/Planned from what happened — the caller never chooses which ledger a mutation lands in.
|
Command migrate demonstrates the mutation-verb effect boundary (Add/Create/Write, ...): the same call site records a planned effect under --dry-run (evo.DryRun) or a committed one when it actually runs, and evo derives Changed/Ready/Planned from what happened — the caller never chooses which ledger a mutation lands in. |
|
print
command
Command print is the first adoption rung: Print/Printf/Println like fmt.
|
Command print is the first adoption rung: Print/Printf/Println like fmt. |
|
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. |
|
scope-plugin
command
Command scope-plugin demos named Tasks for host and plugin work.
|
Command scope-plugin demos named Tasks for host and plugin work. |
|
terminal-driver
command
Command terminal-driver is an advanced teaching surface: custom TerminalDriver, frame-by-frame logging, and explicit renderer knobs.
|
Command terminal-driver is an advanced teaching surface: custom TerminalDriver, frame-by-frame logging, and explicit renderer knobs. |
|
verbose
command
Command verbose shows Normal vs Verbose message visibility.
|
Command verbose shows Normal vs Verbose message visibility. |
|
internal
|
|
|
agent/adopt
Package adopt inventories non-evo CLI output in an existing codebase and proposes a migration plan keyed to the adoption ladder (Init/Main → Task/Done → effects → facts/warnings → confirm/dry-run).
|
Package adopt inventories non-evo CLI output in an existing codebase and proposes a migration plan keyed to the adoption ladder (Init/Main → Task/Done → effects → facts/warnings → confirm/dry-run). |
|
agent/catalog
Package catalog is the task-oriented guidance catalog for agent assistance.
|
Package catalog is the task-oriented guidance catalog for agent assistance. |
|
agent/harness
Package harness evaluates agent-assistance scenarios (§30.9, MCP-022/049).
|
Package harness evaluates agent-assistance scenarios (§30.9, MCP-022/049). |
|
agent/preview
Package preview generates multi-profile plain previews from snapshots.
|
Package preview generates multi-profile plain previews from snapshots. |
|
agent/review
Package review provides deterministic static review of Evident Output usage.
|
Package review provides deterministic static review of Evident Output usage. |
|
agent/rules
Package rules is the stable review-rule registry (Appendix C namespaces).
|
Package rules is the stable review-rule registry (Appendix C namespaces). |
|
agent/sections
Package sections is the full-docs counterpart to catalog: catalog holds hand-curated, token-budgeted guidance snippets; sections serves the whole authoritative doc corpus (reference, development, MCP wiring, the adoption ladder, and the per-concept guides catalog already owns) through one list/get pair, mirroring the Svelte MCP's list-sections / get-documentation shape.
|
Package sections is the full-docs counterpart to catalog: catalog holds hand-curated, token-budgeted guidance snippets; sections serves the whole authoritative doc corpus (reference, development, MCP wiring, the adoption ladder, and the per-concept guides catalog already owns) through one list/get pair, mirroring the Svelte MCP's list-sections / get-documentation shape. |
|
architecture/importprobe/baseline
command
Command baseline is architecture's import-probe baseline: byte-for-byte the same program as ./candidate except it imports nothing from evo.
|
Command baseline is architecture's import-probe baseline: byte-for-byte the same program as ./candidate except it imports nothing from evo. |
|
architecture/importprobe/candidate
command
Command candidate is architecture's import-probe candidate program: it imports the root evo package for its side effects only and immediately reports its own process state, so TestImportingRootPackagePerformsNoIOOrGoroutines (in internal/architecture) can diff its behavior against baseline, the otherwise-identical program that imports nothing from evo.
|
Command candidate is architecture's import-probe candidate program: it imports the root evo package for its side effects only and immediately reports its own process state, so TestImportingRootPackagePerformsNoIOOrGoroutines (in internal/architecture) can diff its behavior against baseline, the otherwise-identical program that imports nothing from evo. |
|
core
Package core owns evident-output's data model: the immutable, fields-only value types a finished or in-flight run presents (Snapshot, Problem, Conclusion, and peers) plus the pure functions that derive one from another (InferConclusion, SanitizeProblem, ...).
|
Package core owns evident-output's data model: the immutable, fields-only value types a finished or in-flight run presents (Snapshot, Problem, Conclusion, and peers) plus the pure functions that derive one from another (InferConclusion, SanitizeProblem, ...). |
|
fingerprint
Package fingerprint computes observation-only content identities for evo.File/evo.Exec Basis and operation-definition hashing (spec §11.1).
|
Package fingerprint computes observation-only content identities for evo.File/evo.Exec Basis and operation-definition hashing (spec §11.1). |
|
manifest
Package manifest persists reconciliation truth across Runs: which operation last ran, under which definition, with which Basis and output digests (spec §11.3-11.4).
|
Package manifest persists reconciliation truth across Runs: which operation last ran, under which definition, with which Basis and output digests (spec §11.3-11.4). |
|
modpin
Package modpin parses a go.mod for the evident-output require pin and replace directive so MCP update and the usage-audit share one parser.
|
Package modpin parses a go.mod for the evident-output require pin and replace directive so MCP update and the usage-audit share one parser. |
|
render
Package render is evident-output's presentation machinery: plain, structured (JSON/JSONL), and interactive (live) projection of a internal/core Snapshot.
|
Package render is evident-output's presentation machinery: plain, structured (JSON/JSONL), and interactive (live) projection of a internal/core Snapshot. |
|
text
Package text is repo-owned CLI text machinery: sanitization, terminal cell width measurement, truncation, glyph-safe pluralization/conjugation.
|
Package text is repo-owned CLI text machinery: sanitization, terminal cell width measurement, truncation, glyph-safe pluralization/conjugation. |
|
wire
Package wire owns the v2 machine wire contract (spec §32.1–§38): the "evo.run" final document and the "evo.event" JSONL line.
|
Package wire owns the v2 machine wire contract (spec §32.1–§38): the "evo.run" final document and the "evo.event" JSONL line. |
|
wireschema
Package wireschema validates a rendered JSON document against evo's own published JSON Schema (schema/output.v1.json) — the facade that makes the schema file an enforced gate instead of prose nobody checks (P8: "today nothing references that file — make it a gate").
|
Package wireschema validates a rendered JSON document against evo's own published JSON Schema (schema/output.v1.json) — the facade that makes the schema file an enforced gate instead of prose nobody checks (P8: "today nothing references that file — make it a gate"). |
|
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. |
|
tools
|
|
|
gensections
command
Command gensections copies the docs the MCP server's list_sections / get_documentation tools serve into internal/agent/sections/embedded, the only directory go:embed can reach from that package.
|
Command gensections copies the docs the MCP server's list_sections / get_documentation tools serve into internal/agent/sections/embedded, the only directory go:embed can reach from that package. |
|
scripts/bisectability-check
command
Command bisectability-check proves every first-parent commit in a range builds on its own — a merge sequence where an intermediate commit only compiles once a *later* commit in the same merge lands (increment 3's 48baff0 is the known instance) breaks git bisect for anyone landing between those two commits, silently, until a bisect run hits exactly that range.
|
Command bisectability-check proves every first-parent commit in a range builds on its own — a merge sequence where an intermediate commit only compiles once a *later* commit in the same merge lands (increment 3's 48baff0 is the known instance) breaks git bisect for anyone landing between those two commits, silently, until a bisect run hits exactly that range. |
|
scripts/evo-usage-audit
command
Command evo-usage-audit scans a Go repository for uses of github.com/zachbornheimer/evident-output (and its subpackages) and prints a markdown usage inventory: one heading per file that uses evo, one fenced code block per top-level declaration that uses it, tagged with how.
|
Command evo-usage-audit scans a Go repository for uses of github.com/zachbornheimer/evident-output (and its subpackages) and prints a markdown usage inventory: one heading per file that uses evo, one fenced code block per top-level declaration that uses it, tagged with how. |
|
scripts/sync-release-pins
command
Command sync-release-pins rewrites install pins on portable surfaces to match evo.PublishedRelease.
|
Command sync-release-pins rewrites install pins on portable surfaces to match evo.PublishedRelease. |
|
scripts/traceability-check
command
Command traceability-check verifies every expected §31 ID is present, and that every .go file TRACEABILITY.md's Test(s) column names still exists (a moved or renamed test file that nobody updated the table for used to pass silently — IDs-present-only checking let the table rot green).
|
Command traceability-check verifies every expected §31 ID is present, and that every .go file TRACEABILITY.md's Test(s) column names still exists (a moved or renamed test file that nobody updated the table for used to pass silently — IDs-present-only checking let the table rot green). |