Documentation
¶
Overview ¶
Package workflow holds the shared schema contract for the harness workflow route. The manifest (route_a.schema.json) is the machine-authoritative source for phase-id, retry, budget, and result-type sets; this package parses it.
This package MUST NOT import pkg/content or internal/cli.
Index ¶
- Constants
- Variables
- func CheckPendingLore(msg string, cfg lore.LoreConfig) []string
- func CheckStagedSourceSizes(fileLineCounts map[string]int, limit int) []string
- func DetectGeneratedDrift(stagedPaths []string, sotChanged bool) []string
- func MinimumVersionForRoute(route string) (string, error)
- func ParseCoverage(stdout string) (float64, bool)
- func PromptManifestHash(layers []promptlayer.Layer) string
- type CapabilityReport
- type CommandRunner
- type ConsolidatedVerdict
- type CoverageRunner
- type DepthProfile
- type DryRunReport
- type FailureKind
- type FallbackClass
- type GateRemediationDecision
- type GateResult
- type GateSignature
- type GitOutputRunner
- type HygieneReport
- type PhaseBinding
- type PhaseDef
- type PrimitiveStatus
- type Prober
- type QualityBinding
- type RenderedPhase
- type ReviewBarrierDecision
- type Schema
- func (s Schema) BudgetSet() map[string]int
- func (s Schema) DepthSet() map[string]DepthProfile
- func (s Schema) EffortSet() map[string]string
- func (s Schema) ModelSet() map[string]string
- func (s Schema) PhaseIDs() []string
- func (s Schema) ResultTypeSet() map[string]string
- func (s Schema) RetrySet() map[string]int
- type TaskOwnership
- type WorktreeMergeResult
Constants ¶
const ( MaxVerifyVotes = 3 MaxFanOut = 5 MaxRetry = 3 // MaxPhases bounds the declared phase count. The team workflow generator // labels segments with string(rune('A'+segmentIndex)); since segments never // exceed phases, capping phases at 26 keeps every segment label within the // safe A..Z charset — closing the one generated-JS token not otherwise behind // a charset whitelist (defense-in-depth at the SoT parse boundary). MaxPhases = 26 )
Depth caps. These are hard ceilings enforced at the parse boundary; values above them are REJECTED (fail-closed), never silently clamped.
const ( // RouteA is the model-agnostic deterministic workflow route. RouteA = "route_a" // RouteTeam is the deterministic team route whose planning phase pins Opus 5. RouteTeam = "route_team" // RouteAMinVersion preserves the original Dynamic Workflows compatibility // floor for the model-agnostic Route A. RouteAMinVersion = "2.1.154" // RouteTeamMinVersion is the first Claude Code release that recognizes the // fixed claude-opus-5 model used by Route Team. RouteTeamMinVersion = "2.1.219" // MinVersion is kept as the Route A compatibility floor for callers that use // the original route-agnostic EvaluateCapabilities API. MinVersion = RouteAMinVersion )
const ( // StatusAvailable / StatusUnavailable are the per-primitive probe states. StatusAvailable = "available" // OverallPass / OverallFail are the capability gate verdicts. OverallPass = "pass" OverallFail = "fail" )
const DefaultSourceLimit = 300
DefaultSourceLimit is the hard per-file source line limit.
const VerdictSourceExitCode = "exit_code"
VerdictSourceExitCode is the canonical verdict source for the deterministic gate: the verdict derives from build/test command exit codes, never from an LLM verdict.
Variables ¶
var AdvisoryPrimitives = []string{"budget", "agent-model-override"}
AdvisoryPrimitives are probed and reported but never affect the verdict.
var GeneratedSurfaceExactPaths = []string{
".agents/plugins/marketplace.json",
".autopus/context/signatures.md",
"config.toml",
}
GeneratedSurfaceExactPaths are generated/runtime files that are not cleanly expressible as directory prefixes without blocking human-managed project docs.
var GeneratedSurfacePrefixes = []string{
".claude/",
".codex/",
".gemini/",
".opencode/",
".agents/plugins/",
".autopus/brainstorms/",
".autopus/orchestra/",
".autopus/plugins/",
".autopus/txns/",
}
GeneratedSurfacePrefixes are the path prefixes the release hygiene drift gate treats as generated surfaces. Staging any of these without a corresponding source-of-truth change is blocked (REQ-012). The .autopus entries are scoped so legitimate `.autopus/specs` and `.autopus/project` edits are not blocked.
var RequiredPrimitives = []string{"claude", "agent", "schema", "phase", "parallel", "isolation"}
RequiredPrimitives are hard-gated: any unavailable one fails the gate.
parallel and isolation are required (not advisory) because the generated route_team workflow JS hard-depends on them: the implementation phase dispatches its executor fan-out through parallel(...) with each executor carrying isolation: 'worktree' (SPEC-HARNESS-WORKFLOW-FIDELITY-001 REQ-004). A runtime missing either primitive would pass an advisory-only gate and then crash mid-launch at the parallel(...) call — strictly worse than failing the gate up front and falling back to the safe Route A path. Gating them makes that failure fail-fast at the doctor boundary.
Functions ¶
func CheckPendingLore ¶
func CheckPendingLore(msg string, cfg lore.LoreConfig) []string
CheckPendingLore validates the pending commit message against the Lore format and returns human-readable violation messages (empty when the message is valid). It reuses the canonical lore.Validate.
func CheckStagedSourceSizes ¶
CheckStagedSourceSizes returns the paths whose line count exceeds limit.
func DetectGeneratedDrift ¶
DetectGeneratedDrift returns the staged paths that live under a generated surface prefix when no source-of-truth change accompanies them. When sotChanged is true the generated regeneration is legitimate and nothing is blocked.
func MinimumVersionForRoute ¶ added in v0.50.88
MinimumVersionForRoute returns the Claude Code compatibility floor for a canonical workflow route and fails closed for unknown routes.
func ParseCoverage ¶ added in v0.50.59
ParseCoverage extracts the coverage percentage from stdout.
func PromptManifestHash ¶
func PromptManifestHash(layers []promptlayer.Layer) string
PromptManifestHash folds the sorted per-layer content hashes of the non-ephemeral (stable + snapshot) layers into one sha256 hex digest. Ephemeral layers are excluded, so mutating only ephemeral context leaves the hash unchanged while mutating any stable/snapshot layer changes it.
Types ¶
type CapabilityReport ¶
type CapabilityReport struct {
Route string `json:"route"`
MinimumVersion string `json:"minimum_version"`
Primitives []PrimitiveStatus `json:"primitives"`
Version string `json:"version"`
VersionOK bool `json:"version_ok"`
Overall string `json:"overall"`
}
CapabilityReport is the structured `auto workflow doctor` output.
func EvaluateCapabilities ¶
func EvaluateCapabilities(p Prober) CapabilityReport
EvaluateCapabilities probes required and advisory primitives plus the version pin for the original Route A contract. Call EvaluateCapabilitiesForRoute when the selected route is known.
Named EvaluateCapabilities (not Evaluate) because the gate evaluator EvaluateGate shares this package; Go forbids two same-named funcs.
func EvaluateCapabilitiesForRoute ¶ added in v0.50.88
func EvaluateCapabilitiesForRoute(p Prober, route string) (CapabilityReport, error)
EvaluateCapabilitiesForRoute probes required and advisory primitives plus the selected route's version pin. Overall is "fail" iff any required primitive is unavailable OR the version is below that route's minimum. Advisory primitives are reported with Gating=false and never change Overall.
func (CapabilityReport) EncodeJSON ¶
func (r CapabilityReport) EncodeJSON() ([]byte, error)
EncodeJSON serializes the capability report for CLI stdout consumption.
type CommandRunner ¶
type CommandRunner interface {
// Run executes name with args and returns the process exit code. err is
// non-nil when the command could not be started or exited non-zero; the
// exit code remains authoritative for the verdict.
Run(ctx context.Context, name string, args ...string) (exitCode int, err error)
}
CommandRunner is the injectable seam the deterministic gate uses to run the build and test commands. The production implementation wraps exec; tests inject a fake returning fixed exit codes. This keeps the gate independent of pkg/pipeline.PhaseBackend for exit-code data (REQ-011).
type ConsolidatedVerdict ¶ added in v0.50.59
ConsolidatedVerdict holds the consolidated review status.
func ConsolidateReviewVerdict ¶ added in v0.50.59
func ConsolidateReviewVerdict(reviewerApprove, securityFail bool) ConsolidatedVerdict
ConsolidateReviewVerdict combines reviewer and security-auditor votes. Security FAIL always outranks code-quality reviewer APPROVE.
type CoverageRunner ¶ added in v0.50.59
type CoverageRunner interface {
RunOutput(ctx context.Context, name string, args ...string) (stdout string, exitCode int, err error)
}
CoverageRunner is distinct from the exit-code-only CommandRunner. It returns stdout in addition to the exit code and error.
type DepthProfile ¶ added in v0.50.57
DepthProfile is the bounded per-phase execution depth derived from a quality tier. It governs how many verify votes and fan-out branches a phase may use, whether a synthesis pass runs, and the retry budget. All values are capped (REQ-004, S4) so a quality tier can never request unbounded depth.
func ResolveDepth ¶ added in v0.50.57
func ResolveDepth(quality string) DepthProfile
ResolveDepth maps a quality tier to a bounded DepthProfile. "ultra" runs the deepest allowed profile (max verify votes, full fan-out, synthesis on); "balanced" and any other/unknown value fall back to the conservative default.
type DryRunReport ¶
type DryRunReport struct {
PhaseOrder []string `json:"phase_order"`
GateVerdictSource string `json:"gate_verdict_source"`
ManifestPath string `json:"manifest_path"`
SchemaPath string `json:"schema_path"`
PromptManifestHash string `json:"prompt_manifest_hash"`
JS string `json:"js"`
Phases []RenderedPhase `json:"phases"`
}
DryRunReport is the inspectable output of `auto workflow render --dry-run`: the deterministic phase order, the gate verdict source, the manifest/schema paths, a deterministic prompt-manifest hash, and the generated workflow JS.
func Render ¶
func Render(s Schema, layers []promptlayer.Layer, jsContent, manifestPath, schemaPath string) DryRunReport
Render builds the dry-run report from the parsed schema, prompt layers, and generated JS. PhaseOrder comes from the manifest; GateVerdictSource is the canonical "exit_code"; the prompt-manifest hash is deterministic over the non-ephemeral layers. Render is pure: it reads no files, the CLI passes data.
type FailureKind ¶
type FailureKind string
FailureKind enumerates the workflow route failure causes the classifier recognizes.
const ( FailureNonClaudePlatform FailureKind = "non_claude_platform" FailureDoctorFail FailureKind = "doctor_fail" FailureParityDrift FailureKind = "parity_drift" FailureExecutionAbort FailureKind = "execution_abort" )
func KnownFailureKinds ¶
func KnownFailureKinds() []FailureKind
KnownFailureKinds returns the failure kinds the classifier recognizes.
type FallbackClass ¶
type FallbackClass string
FallbackClass is the taxonomy bucket a workflow route failure is classified into. Every known failure maps to exactly one class; silent opt-out is forbidden (REQ-008).
const ( // FallbackFailFast: abort the workflow immediately and fall back to Route A. FallbackFailFast FallbackClass = "fail-fast" // FallbackFailClosed: refuse to proceed and block (e.g. parity drift). FallbackFailClosed FallbackClass = "fail-closed" // FallbackResumable: the run can be resumed from a recorded checkpoint. FallbackResumable FallbackClass = "resumable" // FallbackExplicit: surface to the operator for an explicit decision. FallbackExplicit FallbackClass = "explicit" )
func Classify ¶
func Classify(k FailureKind) (FallbackClass, bool)
Classify returns the fallback class for a failure kind. ok is false for an unknown kind so callers can detect (and never silently swallow) an unclassified failure.
type GateRemediationDecision ¶ added in v0.50.59
type GateRemediationDecision struct {
FixerAttempts int
SegmentBLaunched bool
Aborted bool
AbortReason string
}
GateRemediationDecision holds the verdict computed by RunGateRemediation.
func RunGateRemediation ¶ added in v0.50.59
func RunGateRemediation(budget int, evals []GateSignature) GateRemediationDecision
RunGateRemediation computes the bounded remediation decision for the gate.
type GateResult ¶
type GateResult struct {
Verdict string `json:"verdict"`
VerdictSource string `json:"verdict_source"`
BuildExit int `json:"build_exit"`
TestExit int `json:"test_exit"`
}
GateResult is the structured verdict the `auto workflow gate` CLI emits for the workflow JS to read and branch on.
func EvaluateCoverageGate ¶ added in v0.50.59
func EvaluateCoverageGate(ctx context.Context, runner CoverageRunner, coverageCmd []string, threshold int) GateResult
EvaluateCoverageGate parses the measured coverage percentage from stdout, compares it to the threshold, and returns a GateResult.
func EvaluateGate ¶
func EvaluateGate(ctx context.Context, runner CommandRunner, buildCmd, testCmd []string) GateResult
EvaluateGate runs the build and test commands through the runner seam and derives a deterministic verdict from their exit codes. VerdictSource is always "exit_code"; Verdict is "pass" iff both exit codes are 0, else "fail".
Named EvaluateGate (not Evaluate) because the doctor capability evaluator EvaluateCapabilities shares this package; Go forbids two same-named funcs.
func (GateResult) EncodeJSON ¶
func (r GateResult) EncodeJSON() ([]byte, error)
EncodeJSON serializes the gate result for CLI stdout consumption.
type GateSignature ¶ added in v0.50.59
GateSignature represents the exit codes of a build/test run.
type GitOutputRunner ¶ added in v0.50.57
type GitOutputRunner interface {
// Run executes a git subcommand in dir and returns (stdout, exitCode, err).
// err is non-nil when the process could not be started; exitCode is
// authoritative for failure detection.
Run(ctx context.Context, dir string, args ...string) (stdout string, exitCode int, err error)
}
GitOutputRunner runs a git subcommand in dir and captures stdout. The production implementation wraps os/exec; tests inject a fake. This interface is separate from CommandRunner because merge needs stdout text (parsed worktree list, changed-file list), not just an exit code.
type HygieneReport ¶
type HygieneReport struct {
Blocked bool `json:"blocked"`
BlockedPaths []string `json:"blocked_paths"`
Reasons []string `json:"reasons"`
}
HygieneReport is the aggregated release hygiene verdict. Blocked is true when any generated-surface drift, oversized source file, or Lore violation exists.
func Hygiene ¶
func Hygiene(staged []string, sotChanged bool, sizes map[string]int, limit int, msg string, cfg lore.LoreConfig) HygieneReport
Hygiene aggregates the drift, source-size, and Lore checks into one report. staged/sotChanged feed the generated-surface drift gate; sizes/limit feed the 300-line source limit; msg/cfg feed the pending-message Lore check. The function is pure and injectable — no live git access — so it stays hermetic.
type PhaseBinding ¶ added in v0.50.57
type PhaseBinding struct {
Model string `json:"model"`
Effort string `json:"effort"`
VerifyVotes int `json:"verify_votes"`
FanOutCap int `json:"fan_out_cap"`
Synthesis bool `json:"synthesis"`
}
PhaseBinding is the complete per-phase quality binding the dispatch layer computes for a single phase. All fields are kept (no omitempty) so the serialized JSON is deterministic regardless of zero values.
type PhaseDef ¶
type PhaseDef struct {
ID string `json:"id"`
Retry int `json:"retry"`
Budget int `json:"budget"`
ResultType string `json:"result_type"`
Model string `json:"model"`
Effort string `json:"effort"`
VerifyVotes int `json:"verify_votes"`
FanOutCap int `json:"fan_out_cap"`
Synthesis bool `json:"synthesis"`
CoverageThreshold int `json:"coverage_threshold"`
}
PhaseDef is a single workflow phase as declared in route_a.schema.json. ResultType carries the verdict_source for the deterministic gate phase (e.g. "exit_code"); it is "" for non-gate phases.
type PrimitiveStatus ¶
type PrimitiveStatus struct {
Name string `json:"name"`
Status string `json:"status"`
Gating bool `json:"gating"`
}
PrimitiveStatus is a single probed primitive in the capability report. Gating is true for required primitives, false for advisory ones.
type Prober ¶
type Prober interface {
// Probe reports whether a named workflow primitive is available.
Probe(primitive string) bool
// Version returns the probed claude-code version string (dotted ints).
Version() string
}
Prober is the injectable capability-probe seam. The production implementation inspects the claude-code runtime; tests inject a fake.
type QualityBinding ¶ added in v0.50.57
type QualityBinding struct {
Phases map[string]PhaseBinding `json:"phases"`
}
QualityBinding maps phase-id to its computed PhaseBinding.
type RenderedPhase ¶ added in v0.50.57
type RenderedPhase struct {
ID string `json:"id"`
Model string `json:"model"`
Effort string `json:"effort"`
VerifyVotes int `json:"verify_votes"`
FanOutCap int `json:"fan_out_cap"`
Synthesis bool `json:"synthesis"`
}
RenderedPhase exposes the per-phase model, effort, and depth surface so the dry-run report is inspectable (REQ-012, S9). It is the rendered (baseline or overlaid) view of a single phase.
func OverlayPhases ¶ added in v0.50.57
func OverlayPhases(s Schema, b *QualityBinding) []RenderedPhase
OverlayPhases builds the rendered per-phase view in schema order. Each phase starts from its schema baseline (the PhaseDef values). When b is non-nil and carries an entry for a phase id, that phase's quality fields are replaced wholesale with the binding's values — the dispatch computes the complete per-phase binding, so this is a replace, not a merge. Phases without a binding entry keep their baseline (deterministic gate phases stay empty).
type ReviewBarrierDecision ¶ added in v0.50.59
type ReviewBarrierDecision struct {
FixerAttempts int
Aborted bool
AbortReason string
ReleaseHygieneReached bool
}
ReviewBarrierDecision holds the outcome of the review barrier loop.
func RunReviewBarrier ¶ added in v0.50.59
func RunReviewBarrier(budget int, rounds []ConsolidatedVerdict) ReviewBarrierDecision
RunReviewBarrier computes the bounded review barrier outcome.
type Schema ¶
type Schema struct {
Phases []PhaseDef `json:"phases"`
}
Schema is the parsed manifest with phases in execution order.
func LoadSchema ¶
LoadSchema reads and parses route_a.schema.json from path.
func ParseSchema ¶
ParseSchema unmarshals route_a.schema.json bytes into a Schema, preserving phase array order as execution order. @AX:WARN [AUTO]: 11 fail-closed validation branches guard the JS-injection trust boundary (phase count/id/model/effort/result_type/depth caps). @AX:REASON [AUTO]: This is the single SoT parse gate for generated workflow JS; any branch weakened or reordered can let an unsafe field reach the generated-JS surface. Treat additions as security-relevant.
func (Schema) DepthSet ¶ added in v0.50.57
func (s Schema) DepthSet() map[string]DepthProfile
DepthSet returns the bounded DepthProfile for each phase keyed by phase-id.
func (Schema) ModelSet ¶ added in v0.50.57
ModelSet returns agent model identifiers keyed by phase-id.
func (Schema) ResultTypeSet ¶
ResultTypeSet returns result-types keyed by phase-id.
type TaskOwnership ¶ added in v0.50.58
TaskOwnership is one planner task's file ownership. It is used to ENFORCE that an executor's merged changes stay within its assigned files, turning the planner's disjoint-file decomposition into a hard merge-time guarantee.
func ParsePlanOwnership ¶ added in v0.50.58
func ParsePlanOwnership(data []byte) ([]TaskOwnership, error)
ParsePlanOwnership extracts task file-ownership from a persisted planner result. It accepts either {"tasks":[...]} or {"plan":{"tasks":[...]}} — the dispatcher persists the segment-A return value, which wraps the plan under "plan".
type WorktreeMergeResult ¶ added in v0.50.57
type WorktreeMergeResult struct {
RunID string `json:"run_id"`
MergedWorktrees []string `json:"merged_worktrees"`
MergedFiles []string `json:"merged_files"`
Conflicts []string `json:"conflicts"`
// SkippedOutOfScope lists files an executor created outside its task's file
// ownership (only populated when ownership enforcement is active). They are
// reported but never copied.
SkippedOutOfScope []string `json:"skipped_out_of_scope,omitempty"`
}
WorktreeMergeResult is the structured output emitted by MergeExecutorWorktrees and printed as JSON by `auto workflow merge`.
func MergeExecutorWorktrees ¶ added in v0.50.57
func MergeExecutorWorktrees(ctx context.Context, r GitOutputRunner, workingDir, runID string) (WorktreeMergeResult, error)
MergeExecutorWorktrees consolidates uncommitted changes from all executor worktrees belonging to runID into workingDir.
The Claude Code Workflow runtime creates one worktree per parallel executor. Worktree branch naming is an observed runtime convention (v2.1.174+):
- worktree path base: <runID>-<N> (under .claude/worktrees/)
- branch: worktree-<runID>-<N>
Executor changes are left as uncommitted working-tree edits (git status shows ?? / M / A). This function copies those files into workingDir so that `auto workflow gate` sees them. It does NOT git-add, commit, or remove worktrees — the CLI layer handles those steps.
Conflict policy: if more than one worktree touches the same repo-relative path, the path is added to Conflicts and skipped (not copied). Planner file-ownership makes this rare; the CLI/operator decides how to resolve.
func MergeExecutorWorktreesWithOwnership ¶ added in v0.50.58
func MergeExecutorWorktreesWithOwnership(ctx context.Context, r GitOutputRunner, workingDir, runID string, ownership []TaskOwnership) (WorktreeMergeResult, error)
MergeExecutorWorktreesWithOwnership is MergeExecutorWorktrees with hard file ownership enforcement. When ownership is non-nil, each worktree is matched to the task it performed (best file overlap) and only files within that task's ownership are merged; files an executor created outside its ownership (overlap into another task's files) are reported in SkippedOutOfScope and never copied. This eliminates the executor-overlap conflict at its source. ownership=nil preserves the plain conflict-skip behavior.
func (WorktreeMergeResult) EncodeJSON ¶ added in v0.50.57
func (r WorktreeMergeResult) EncodeJSON() ([]byte, error)
EncodeJSON serializes the merge result for CLI stdout consumption.