workflow

package
v0.3.4 Latest Latest
Warning

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

Go to latest
Published: Jun 3, 2026 License: MIT Imports: 33 Imported by: 0

Documentation

Overview

close_task.go wires `da workflow close-task`, the T1-molecule client command that composes the end-of-iteration primitive chain:

checkpoint --log-to-iter N → score iteration N → advance task to
completed → plan update --focus <next eligible> → workflow commit

Each step is a T0 atom that already exists in this package; this file orchestrates them and surfaces wrapped errors naming which step blew so the operator does not have to bisect by hand.

tier: molecule calls:

  • workflow-checkpoint-log-to-iter
  • score-iteration
  • workflow-advance
  • workflow-plan-update
  • workflow-commit

Per the skill-tiering-contract (T0 atom → T1 molecule → T2 compound → T3 cell), runtime agent judgment is bounded to picking among the declared atoms above. A future lint pass will read this block.

commit_cmd.go wires the `da workflow commit` subcommand. It composes the pure path-derivation in commit_pathset.go with a small interface seam over git so the orchestration is testable without a real worktree, and stages / commits only the derived set — the "never -A" rule the spec mandates.

commit_pathset.go derives the deterministic, scoped set of paths to stage for `da workflow commit`. It is the pure-function half of the workflow-commit-command spec (decision #3): "Deterministic, scoped path set — never `git add -A`."

The caller is responsible for actually running git status and shelling / go-git'ing the stage; this file owns only the derivation logic so it is testable from fixtures without a real worktree or subprocesses.

Package workflow's hook_outcome.go provides `da workflow hook-outcome write`, the CLI primitive R1.5 requires (per design D2/R2.1) so gates append outcome records to `.agents/active/iteration-log/iter-N.hook-outcomes.yaml` via this single bottleneck rather than writing the YAML by hand from gate.sh. Mirrors the shape of hook_sentinel.go (schema-validation, atomic temp+rename write, file-local seams for fault injection in tests).

iter_log_autoderive.go provides the thin orchestration helpers that the workflow-client-commands close-task uses to invoke `da workflow checkpoint --log-to-iter N --log-to-iter-role <role>` without operator-supplied N.

The actual iter-log writer (loadOrInitIterLogEntry → applyIterLogRole → writeIterLogEntry, plus the agent-block / git-diff / token-telemetry derivers) already exists in iter_log.go — this file does not duplicate any of that. It only picks (N, role) so callers do not have to.

start_task.go wires `da workflow start-task`, the T1-molecule client command that mirrors close-task on the start side of the iteration:

plan update --status active → plan update --focus T → plan derive-scope T
→ workflow commit

Each step is a T0 atom already in this package; this file orchestrates them and surfaces wrapped errors naming which step blew so the operator does not have to bisect by hand. fanout is intentionally NOT wired in this slice — the orchestrator typically wants to decide direct-vs-delegated explicitly, and `da workflow fanout` remains a separate primitive call.

tier: molecule calls:

  • workflow-plan-update
  • workflow-plan-derive-scope
  • workflow-commit

Per the skill-tiering-contract (T0 atom → T1 molecule → T2 compound → T3 cell), runtime agent judgment is bounded to picking among the declared atoms above. A future lint pass will read this block.

Index

Constants

View Source
const (
	// TaskStatusPending — task created, dependencies not yet satisfied or
	// not yet picked up by a worker.
	TaskStatusPending = "pending"
	// TaskStatusInProgress — a worker holds the task and is actively
	// implementing it.
	TaskStatusInProgress = "in_progress"
	// TaskStatusBlocked — task cannot proceed (external block, cascade,
	// or unrecoverable verify failure); manual recovery required.
	TaskStatusBlocked = "blocked"
	// TaskStatusCompleted — terminal success (e.g. PR merged on GitHub).
	TaskStatusCompleted = "completed"
	// TaskStatusCancelled — terminal manual abandonment.
	TaskStatusCancelled = "cancelled"

	// TaskStatusAwaitingAgentReview is the first sub-status of the
	// `awaiting_review` umbrella (§2.2): branch pushed, PR open, verifier
	// chain green; lens reviewers are dispatched or running. Counts
	// against max_parallel_tasks (§2.8) because lens dispatch can bounce
	// work back to in_progress.
	TaskStatusAwaitingAgentReview = "awaiting_agent_review"
	// TaskStatusAwaitingOwnerReview is the second sub-status of
	// `awaiting_review` (§2.2): lens verdicts accepted; the human
	// maintainer owns the merge decision. Frees its slot (§2.8) because
	// human-review latency is unbounded.
	TaskStatusAwaitingOwnerReview = "awaiting_owner_review"
)

Task status vocabulary for canonical TASKS.yaml rows and the `da workflow advance --status` command. Centralized here so every predicate (eligibility, concurrency accounting, advance validation) reads from a single source of truth.

See .agents/workflow/specs/layered-pr-fanout/design.md §2.1, §2.2, §3.1, §3.2 for the state machine these constants encode.

View Source
const HookOutcomeSchemaVersion = 1

HookOutcomeSchemaVersion is the current schema version emitted by `da workflow hook-outcome write` and persisted at the top of each iter-N.hook-outcomes.yaml sidecar.

View Source
const HookSentinelSchemaVersion = 1

HookSentinelSchemaVersion is the current schema version emitted by `da workflow hook-sentinel write`.

View Source
const VerifierTypeMergeBack = "merge-back"

VerifierTypeMergeBack is the verifier_type / filename stem for worker merge-back results (`.agents/active/verification/<task_id>/merge-back.result.yaml`).

Variables

View Source
var WorkflowHookOutcomeSchemaJSON []byte

WorkflowHookOutcomeSchemaJSON is the embedded twin of schemas/workflow-hook-outcome.schema.json (v1, per r1-5-hook-enforcement-telemetry design D2). The byte-equal guarantee between this embedded copy and the canonical file is enforced by TestWorkflowHookOutcomeEmbeddedSchemaMatchesCanonical so editors and JSON-schema tooling read the same contract the Go binary validates against.

Exported so the parallel t1-capture-outcomes worker (commands/workflow/hook_outcome.go) can reach the bytes if it ever needs the raw schema (e.g. for documentation emission). The expected callsite is WorkflowHookOutcomeSchema below, which returns a compiled validator instead of the raw bytes.

Functions

func DefaultIterationRole

func DefaultIterationRole() string

DefaultIterationRole returns the role close-task uses by default when no stronger context (a recent verifier record, a review-gate handoff) tells us to write a verifier or review entry instead.

Indirected through a function rather than a const so a future close-task enhancement (read the verify log; if the last record is a verifier with matching scope, write the verifier block) can land here without touching every caller.

func DerivePathSet

func DerivePathSet(status []StatusEntry, mutationSurface []string) []string

DerivePathSet returns the sorted, deduplicated set of paths to stage. The derivation rules (from the spec's Decisions §3 and the wc-path-derivation task notes) are:

  • Include every entry whose path is under one of the managed roots (.agents/workflow/, .agents/history/) — both tracked changes AND untracked entries. Anything under those roots is by convention a workflow artifact (a fresh PLAN.yaml from `da workflow plan create` is untracked on its first commit pass, so excluding untracked would orphan new plans).
  • Include paths outside the managed roots only when the caller named them in MutationSurface. This is what implements the "pre-existing- untracked dirs" exclusion: the mutation surface is authoritative about which non-managed paths the session just touched, so an untracked `node_modules/` or `tmp/` that some other tool created never sneaks in.
  • Always exclude submodule-pointer entries even if they fall under a managed root. A submodule pointer change is a separate kind of commit (submodule bump) and conflating it with workflow state silently mutates an SCM relationship.
  • For rename / copy entries, stage both the new path and the original path so git captures the rename intent (R) or deletion (the index entry the old path leaves behind).

Determinism: the output is sorted lexicographically and deduplicated, so the same (status, surface) input pair always produces the same output.

func EvaluateBlocker

func EvaluateBlocker(env BlockerEnv, status string) (bool, error)

EvaluateBlocker reports whether the blocker named by status has resolved (its auto-resume predicate is true). A status that is not a blocked-on state, a malformed ref, or a kind with no registered predicate returns an error; the caller leaves the task untouched on error.

func InitTestDeps

func InitTestDeps(d Deps)

InitTestDeps wires workflow package dependencies for tests. Call from TestMain before m.Run().

func IsBlockedOnStatus

func IsBlockedOnStatus(status string) bool

IsBlockedOnStatus reports whether a persisted status string is a parameterized blocked-on:<ref> state.

func IterationLogDir

func IterationLogDir(projectPath string) string

IterationLogDir returns the canonical iter-log directory for a project. One place to compute it so close-task, the auto-derivers, and the existing runWorkflowCheckpointLogToIter all agree on the path.

func NewCmd

func NewCmd(d Deps) *cobra.Command

NewCmd builds the `da workflow` command tree. Callers must supply Deps from package commands to avoid an import cycle.

func NewCmdForTest

func NewCmdForTest() *cobra.Command

NewCmdForTest returns the workflow command tree using deps registered by InitTestDeps (see workflow_testutil_test.go init).

func NextIterationNumber

func NextIterationNumber(iterLogDir string) (int, error)

NextIterationNumber returns the iteration number close-task should pass to `workflow checkpoint --log-to-iter`. If the iter-log directory has no existing iter-N.yaml entries (or does not exist yet), the next number is 1 — the schema's enforced minimum, matching the existing --log-to-iter validation that requires N >= 1. Otherwise it returns max(existing) + 1 so each close opens a fresh iteration entry.

A directory that exists but is empty is not an error; that is the expected state for a brand-new project's first close. Only filesystem errors (permission denied, parent missing, etc.) surface as errors.

func NormalizeResumeAs

func NormalizeResumeAs(override string) (string, error)

NormalizeResumeAs validates an optional --resume-as override and returns the status a resumed task should enter. An empty override yields the implicit default (in_progress, §3.4.5). An override outside {in_progress, pending} is rejected.

func RegisterBlockerPredicate

func RegisterBlockerPredicate(kind string, pred blockerPredicate) error

RegisterBlockerPredicate installs or replaces the evaluator for a ref kind, keeping the registry pluggable per §3.4.5. It also marks the kind valid so parse accepts refs of that kind. A nil predicate or empty kind is rejected.

func WorkflowHookOutcomeSchema

func WorkflowHookOutcomeSchema() (*jsonschema.Schema, error)

WorkflowHookOutcomeSchema returns the compiled validator for workflow-hook-outcome.schema.json (the sidecar at .agents/active/iteration-log/iter-N.hook-outcomes.yaml).

Exported for the parallel t1-capture-outcomes worker: t1's `da workflow hook-outcome write` CLI calls this to validate the sidecar payload before atomic-rename publish. Returning the compiled *jsonschema.Schema (rather than a doc-specific validate helper) keeps this slice free of any HookOutcomeDoc type — t1 owns that struct and the marshal/validate plumbing per the anti-scope split.

Cold-path callers should pass stdSchemaCompiler{}; tests can substitute a faulting compiler to drive error branches.

Types

type AggregateDriftReport

type AggregateDriftReport struct {
	Timestamp        string            `json:"timestamp"`
	TotalProjects    int               `json:"total_projects"`
	ProjectsChecked  int               `json:"projects_checked"`
	Reports          []RepoDriftReport `json:"reports"`
	HealthyCount     int               `json:"healthy_count"`
	WarnCount        int               `json:"warn_count"`
	UnreachableCount int               `json:"unreachable_count"`
	TopWarnings      []string          `json:"top_warnings"`
}

AggregateDriftReport summarizes drift across all managed projects.

type AnnotatedTask

type AnnotatedTask struct {
	ConflictsWith      []string `json:"conflicts_with"`
	HasEvidence        bool     `json:"has_evidence"`
	EvidenceConfidence string   `json:"evidence_confidence"`
	WriteScopeDeclared bool     `json:"write_scope_declared"`
	// contains filtered or unexported fields
}

AnnotatedTask enriches a workflowNextTaskSuggestion with conflict detection and evidence fields populated by computeWriteScopeConflicts and the eligible command. All slice fields are initialized to []string{} (not nil) so they marshal to [] not null.

type BlockerDecay

type BlockerDecay struct {
	// Stale reports whether the task has been blocked past the threshold.
	Stale bool
	// Since is the RFC3339 timestamp the task entered the blocked state,
	// echoed back for the blocker_stale_since annotation. Empty when Stale
	// is false.
	Since string
	// Age is how long the task has been blocked, rounded to whole seconds.
	Age time.Duration
}

BlockerDecay carries the §3.4.4 staleness verdict for a blocked task.

func EvaluateBlockerDecay

func EvaluateBlockerDecay(blockedSince string, configuredDays int, now time.Time) (BlockerDecay, error)

EvaluateBlockerDecay computes the §3.4.4 eligibility-decay verdict for a task that entered its blocked state at blockedSince (RFC3339). configuredDays is the per-project threshold from .agentsrc.json (<=0 means "use default"). now is injected for deterministic tests. A blank or unparseable blockedSince yields a non-stale verdict (we cannot prove staleness without an entry time).

type BlockerEnv

type BlockerEnv interface {
	// SecretExists reports whether a repo/org secret with the given name is
	// present (production: `gh secret list`).
	SecretExists(name string) (bool, error)
	// TaskStatus returns the persisted status of plan/task (production: read
	// the canonical TASKS.yaml). The bool is false when the task is unknown.
	TaskStatus(plan, task string) (string, bool)
	// DecisionResolved reports whether maintainer decision id has landed
	// (production: a resolved-decision record exists).
	DecisionResolved(id string) (bool, error)
	// EvalCondition evaluates a registered named condition predicate. The
	// bool reports the predicate result; an error is returned for an
	// unregistered predicate or an evaluator failure.
	EvalCondition(predicate string) (bool, error)
}

BlockerEnv is the seam through which predicate evaluators reach external state (GitHub, the canonical task store, resolved-decision records). The concrete production implementation shells out to `gh` and reads canonical YAML; tests inject a fake so no network or filesystem access is required.

type BlockerRef

type BlockerRef struct {
	Kind string
	Arg  string
}

BlockerRef is the parsed form of the `<ref>` portion of a `blocked-on:<ref>` status. Kind is one of the blockerKind* constants and Arg is the remainder after the first ':' (e.g. for `blocked-on:task:p1/t2` → Kind="task", Arg="p1/t2").

func ParseBlockedOnStatus

func ParseBlockedOnStatus(status string) (BlockerRef, error)

ParseBlockedOnStatus parses a full persisted status string (`blocked-on:<kind>:<arg>`) into its BlockerRef. It returns an error when the status lacks the blocked-on: prefix or the ref body is malformed.

func (BlockerRef) String

func (r BlockerRef) String() string

String renders the ref back to its canonical `<kind>:<arg>` form. It is the inverse of parseBlockerRef and is stable (round-trips).

type CanonicalPlan

type CanonicalPlan struct {
	SchemaVersion        int    `json:"schema_version" yaml:"schema_version"`
	ID                   string `json:"id" yaml:"id"`
	Title                string `json:"title" yaml:"title"`
	Status               string `json:"status" yaml:"status"`
	Summary              string `json:"summary" yaml:"summary"`
	CreatedAt            string `json:"created_at" yaml:"created_at"`
	UpdatedAt            string `json:"updated_at" yaml:"updated_at"`
	Owner                string `json:"owner" yaml:"owner"`
	SuccessCriteria      string `json:"success_criteria" yaml:"success_criteria"`
	VerificationStrategy string `json:"verification_strategy" yaml:"verification_strategy"`
	CurrentFocusTask     string `json:"current_focus_task" yaml:"current_focus_task"`
	DefaultAppType       string `json:"default_app_type,omitempty" yaml:"default_app_type,omitempty"`
}

CanonicalPlan is the PLAN.yaml schema for .agents/workflow/plans/<id>/PLAN.yaml

type CanonicalSlice

type CanonicalSlice struct {
	ID                string   `json:"id" yaml:"id"`
	ParentTaskID      string   `json:"parent_task_id" yaml:"parent_task_id"`
	Title             string   `json:"title" yaml:"title"`
	Summary           string   `json:"summary" yaml:"summary"`
	Status            string   `json:"status" yaml:"status"`
	DependsOn         []string `json:"depends_on" yaml:"depends_on"`
	WriteScope        []string `json:"write_scope" yaml:"write_scope"`
	VerificationFocus string   `json:"verification_focus" yaml:"verification_focus"`
	Owner             string   `json:"owner" yaml:"owner"`
}

CanonicalSlice is one bounded sub-slice under a canonical task.

type CanonicalSliceFile

type CanonicalSliceFile struct {
	SchemaVersion int              `json:"schema_version" yaml:"schema_version"`
	PlanID        string           `json:"plan_id" yaml:"plan_id"`
	Slices        []CanonicalSlice `json:"slices" yaml:"slices"`
}

CanonicalSliceFile is the SLICES.yaml schema for .agents/workflow/plans/<id>/SLICES.yaml

type CanonicalTask

type CanonicalTask struct {
	ID                   string   `json:"id" yaml:"id"`
	Title                string   `json:"title" yaml:"title"`
	Status               string   `json:"status" yaml:"status"`
	DependsOn            []string `json:"depends_on" yaml:"depends_on"`
	Blocks               []string `json:"blocks" yaml:"blocks"`
	Owner                string   `json:"owner" yaml:"owner"`
	WriteScope           []string `json:"write_scope" yaml:"write_scope"`
	VerificationRequired bool     `json:"verification_required" yaml:"verification_required"`
	Notes                string   `json:"notes" yaml:"notes"`
	AppType              string   `json:"app_type,omitempty" yaml:"app_type,omitempty"`
}

CanonicalTask is one entry in TASKS.yaml

type CanonicalTaskFile

type CanonicalTaskFile struct {
	SchemaVersion int             `json:"schema_version" yaml:"schema_version"`
	PlanID        string          `json:"plan_id" yaml:"plan_id"`
	Tasks         []CanonicalTask `json:"tasks" yaml:"tasks"`
}

CanonicalTaskFile is the TASKS.yaml schema for .agents/workflow/plans/<id>/TASKS.yaml

type ContextMapping

type ContextMapping struct {
	RepoScope  string `json:"repo_scope" yaml:"repo_scope"`
	GraphScope string `json:"graph_scope" yaml:"graph_scope"`
	Intent     string `json:"intent" yaml:"intent"`
}

type CoordinationIntent

type CoordinationIntent string
const (
	CoordinationIntentNone             CoordinationIntent = ""
	CoordinationIntentStatusRequest    CoordinationIntent = "status_request"
	CoordinationIntentReviewRequest    CoordinationIntent = "review_request"
	CoordinationIntentEscalationNotice CoordinationIntent = "escalation_notice"
	CoordinationIntentAck              CoordinationIntent = "ack"
)

type DelegationContract

type DelegationContract struct {
	SchemaVersion            int                    `json:"schema_version" yaml:"schema_version"`
	ID                       string                 `json:"id" yaml:"id"`
	Mode                     DelegationContractMode `json:"mode,omitempty" yaml:"mode,omitempty"`
	ParentPlanID             string                 `json:"parent_plan_id" yaml:"parent_plan_id"`
	ParentTaskID             string                 `json:"parent_task_id" yaml:"parent_task_id"`
	Title                    string                 `json:"title" yaml:"title"`
	Summary                  string                 `json:"summary" yaml:"summary"`
	WriteScope               []string               `json:"write_scope" yaml:"write_scope"`
	SuccessCriteria          string                 `json:"success_criteria" yaml:"success_criteria"`
	VerificationExpectations string                 `json:"verification_expectations" yaml:"verification_expectations"`
	MayMutateWorkflowState   bool                   `json:"may_mutate_workflow_state" yaml:"may_mutate_workflow_state"`
	Owner                    string                 `json:"owner" yaml:"owner"`
	Status                   string                 `json:"status" yaml:"status"`
	PendingIntent            CoordinationIntent     `json:"pending_intent,omitempty" yaml:"pending_intent,omitempty"`
	CreatedAt                string                 `json:"created_at" yaml:"created_at"`
	UpdatedAt                string                 `json:"updated_at" yaml:"updated_at"`
}

type DelegationContractMode

type DelegationContractMode string

DelegationContractMode discriminates contracts written by `workflow fanout` (delegated to a sub-agent worker) from contracts materialized for direct orchestrator-owned work via `workflow contract create`.

Both modes share the same on-disk shape, advance through the same closeout pipeline (merge-back → delegation closeout → auto-advance), and contribute equally to the workflow audit trail. The distinction is documentation + downstream tooling (skills, lens routing) deciding which artifacts to expect.

const (
	// DelegationContractModeDelegated is the legacy mode written by `workflow fanout`.
	// A sub-agent (loop-worker, codex helper, etc.) owns the write scope until merge-back.
	DelegationContractModeDelegated DelegationContractMode = "delegated"
	// DelegationContractModeDirect is the new mode written by `workflow contract create`.
	// The orchestrator itself owns the write scope; the contract pins guardrails
	// (write scope, success criteria, closeout discipline) so direct work flows
	// through the same audit trail as delegated work.
	DelegationContractModeDirect DelegationContractMode = "direct"
)

type DelegationGateDecision

type DelegationGateDecision struct {
	SchemaVersion         int    `json:"schema_version"`
	TaskID                string `json:"task_id"`
	PlanID                string `json:"plan_id"`
	DelegationID          string `json:"delegation_id,omitempty"`
	MergeBackPresent      bool   `json:"merge_back_present"`
	ReviewDecisionPresent bool   `json:"review_decision_present"`
	ReviewOverallDecision string `json:"review_overall_decision,omitempty"`
	Outcome               string `json:"outcome"`
	CloseoutAllowed       bool   `json:"closeout_allowed"`
	PlanningRequired      bool   `json:"planning_required"`
	Reason                string `json:"reason"`
	EscalationReason      string `json:"escalation_reason,omitempty"`
}

DelegationGateDecision is the deterministic parent-gate readback for one task.

type Deps

type Deps struct {
	Flags                 GlobalFlags
	ErrNoProject          error
	ErrorWithHints        func(message string, hints ...string) error
	UsageError            func(message string, hints ...string) error
	NoArgsWithHints       func(hints ...string) cobra.PositionalArgs
	ExactArgsWithHints    func(n int, hints ...string) cobra.PositionalArgs
	MaximumNArgsWithHints func(n int, hints ...string) cobra.PositionalArgs
	ExampleBlock          func(lines ...string) string
	Store                 graphstore.Handle
}

Deps carries UX helpers and sentinels from package commands without an import cycle.

gcc3 / di-refactor OD-1: Store is a contract-typed handle whose provider owns pooling and serialization. The package-level deps singleton is justified as a holder of this contract-typed handle — it is NOT the concurrency story (the provider behind the contract is). graphstore.Handle's Store() accessor is nil-safe: when unset, callers fall back to their existing direct-open path (preserving today's behavior). End-to-end wiring from the singleton to every call site is the deferred follow-up tracked on di-refactor OD-1. See internal/graphstore/CONTRACT.md "Deps boundary".

type GlobalFlags

type GlobalFlags struct {
	JSON   func() bool
	Yes    func() bool
	DryRun func() bool
}

GlobalFlags mirrors the subset of commands.Flags read by workflow subcommands at runtime.

type GraphBridgeAdapter

type GraphBridgeAdapter interface {
	Query(query GraphBridgeQuery) (GraphBridgeResponse, error)
	Health() (GraphBridgeHealth, error)
}

type GraphBridgeConfig

type GraphBridgeConfig struct {
	SchemaVersion   int              `json:"schema_version" yaml:"schema_version"`
	Enabled         bool             `json:"enabled" yaml:"enabled"`
	GraphHome       string           `json:"graph_home" yaml:"graph_home"`
	AllowedIntents  []string         `json:"allowed_intents" yaml:"allowed_intents"`
	ContextMappings []ContextMapping `json:"context_mappings" yaml:"context_mappings"`
}

type GraphBridgeHealth

type GraphBridgeHealth struct {
	SchemaVersion      int      `json:"schema_version"`
	Timestamp          string   `json:"timestamp"`
	AdapterAvailable   bool     `json:"adapter_available"`
	GraphHomeExists    bool     `json:"graph_home_exists"`
	NoteCount          int      `json:"note_count"`
	WarmStoreNodeCount int      `json:"warm_store_node_count"`
	WarmStoreNoteCount int      `json:"warm_store_note_count"`
	CodeLaneReady      bool     `json:"code_lane_ready"`
	ContextLaneReady   bool     `json:"context_lane_ready"`
	LastQueryTime      string   `json:"last_query_time,omitempty"`
	LastQueryStatus    string   `json:"last_query_status,omitempty"`
	Status             string   `json:"status"`
	Note               string   `json:"note,omitempty"`
	Warnings           []string `json:"warnings,omitempty"`
}

type GraphBridgeQuery

type GraphBridgeQuery struct {
	Intent  string `json:"intent"`
	Project string `json:"project"`
	Scope   string `json:"scope,omitempty"`
	Query   string `json:"query"`
}

type GraphBridgeResponse

type GraphBridgeResponse struct {
	SchemaVersion int                 `json:"schema_version"`
	Intent        string              `json:"intent"`
	Query         string              `json:"query"`
	Results       []GraphBridgeResult `json:"results"`
	Warnings      []string            `json:"warnings"`
	Provider      string              `json:"provider"`
	Timestamp     string              `json:"timestamp"`
}

type GraphBridgeResult

type GraphBridgeResult struct {
	ID         string   `json:"id"`
	Type       string   `json:"type"`
	Title      string   `json:"title"`
	Summary    string   `json:"summary"`
	Path       string   `json:"path"`
	SourceRefs []string `json:"source_refs,omitempty"`
}

type HookOutcomeRecord

type HookOutcomeRecord struct {
	SchemaVersion        int    `json:"schema_version" yaml:"schema_version"`
	SentinelID           string `json:"sentinel_id" yaml:"sentinel_id"`
	Skill                string `json:"skill" yaml:"skill"`
	LifecyclePoint       string `json:"lifecycle_point" yaml:"lifecycle_point"`
	InterventionClass    string `json:"intervention_class" yaml:"intervention_class"`
	Result               string `json:"result" yaml:"result"`
	RuleID               string `json:"rule_id" yaml:"rule_id"`
	Platform             string `json:"platform" yaml:"platform"`
	TS                   string `json:"ts" yaml:"ts"`
	ArchivedSentinelPath string `json:"archived_sentinel_path,omitempty" yaml:"archived_sentinel_path,omitempty"`
	CorrelationID        string `json:"correlation_id" yaml:"correlation_id"`
}

HookOutcomeRecord is one record in iter-N.hook-outcomes.yaml. Field names mirror the schema; tags are explicit so YAML and JSON shapes agree (the schema validates the JSON projection). No tag for the disallowed fields exists by construction — they are not modelled here.

type HookOutcomeSidecar

type HookOutcomeSidecar struct {
	SchemaVersion int                 `json:"schema_version" yaml:"schema_version"`
	Records       []HookOutcomeRecord `json:"records" yaml:"records"`
}

HookOutcomeSidecar is the iter-N.hook-outcomes.yaml top-level shape.

type HookSentinelContext

type HookSentinelContext struct {
	GitHeadAtStart         string   `json:"git_head_at_start,omitempty"`
	WriteScope             []string `json:"write_scope,omitempty"`
	EligibleSnapshotLoaded *bool    `json:"eligible_snapshot_loaded,omitempty"`
	MaxBatch               *int     `json:"max_batch,omitempty"`
	TracePathHint          string   `json:"trace_path_hint,omitempty"`

	// Companion: operation discriminator and per-operation evidence.
	Operation                string   `json:"operation,omitempty"`
	DelegationPath           string   `json:"delegation_path,omitempty"`
	BundlePath               string   `json:"bundle_path,omitempty"`
	RequiredSidecarPath      string   `json:"required_sidecar_path,omitempty"`
	EvidenceConfidence       string   `json:"evidence_confidence,omitempty"`
	Decision                 string   `json:"decision,omitempty"`
	ExpectedArchiveArtifacts []string `json:"expected_archive_artifacts,omitempty"`
	ExpectedCleanupPaths     []string `json:"expected_cleanup_paths,omitempty"`
}

HookSentinelContext carries the skill-specific signals declared at sentinel write time. Fields are pointer-shaped where the zero value collides with a meaningful value (e.g. `eligible_snapshot_loaded: false` is a real ISP signal and must be distinguishable from "not declared"). Use `omitempty` on absent fields so the rendered JSON matches the schema's `additionalProperties: false` contract.

Companion-gate fields per T1 contract: the operation discriminator plus the evidence each pair is allowed to declare at write time. Names mirror the schema. No field carries transcript or tool-command body content.

type HookSentinelDoc

type HookSentinelDoc struct {
	SchemaVersion     int                  `json:"schema_version"`
	Skill             string               `json:"skill"`
	RunID             string               `json:"run_id"`
	StartedAt         string               `json:"started_at"`
	PlanID            string               `json:"plan_id"`
	TaskID            string               `json:"task_id"`
	AgentType         string               `json:"agent_type"`
	LifecyclePoint    string               `json:"lifecycle_point,omitempty"`
	ExpectedArtifacts []string             `json:"expected_artifacts,omitempty"`
	Context           *HookSentinelContext `json:"context,omitempty"`
}

HookSentinelDoc is the typed payload persisted at `.agents/active/hook-sentinels/<skill>-<run-id>.json`.

type LocalGraphAdapter

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

func NewLocalGraphAdapter

func NewLocalGraphAdapter(graphHome string) *LocalGraphAdapter

func (*LocalGraphAdapter) Health

func (a *LocalGraphAdapter) Health() (GraphBridgeHealth, error)

func (*LocalGraphAdapter) Query

type ManagedProject

type ManagedProject struct {
	Name string
	Path string
}

ManagedProject is one entry from ~./agents/config.json loaded for drift checks.

type MergeBackSummary

type MergeBackSummary struct {
	SchemaVersion       int                   `json:"schema_version" yaml:"schema_version"`
	TaskID              string                `json:"task_id" yaml:"task_id"`
	ParentPlanID        string                `json:"parent_plan_id" yaml:"parent_plan_id"`
	Title               string                `json:"title" yaml:"title"`
	Summary             string                `json:"summary" yaml:"summary"`
	FilesChanged        []string              `json:"files_changed" yaml:"files_changed"`
	VerificationResult  MergeBackVerification `json:"verification_result" yaml:"verification_result"`
	IntegrationNotes    string                `json:"integration_notes" yaml:"integration_notes"`
	BlockersEncountered []string              `json:"blockers_encountered,omitempty" yaml:"blockers_encountered,omitempty"`
	CreatedAt           string                `json:"created_at" yaml:"created_at"`
}

type MergeBackVerification

type MergeBackVerification struct {
	Status  string `json:"status" yaml:"status"`
	Summary string `json:"summary" yaml:"summary"`
}

type PlanScheduleResult

type PlanScheduleResult struct {
	PlanID              string             `json:"plan_id"`
	Waves               []PlanScheduleWave `json:"waves"`
	CriticalPathLength  int                `json:"critical_path_length"`
	MaxIntraParallelism int                `json:"max_intra_plan_parallelism"`
}

PlanScheduleResult is the full schedule output.

type PlanScheduleTask

type PlanScheduleTask struct {
	ID         string   `json:"id"`
	Title      string   `json:"title"`
	Status     string   `json:"status"`
	WriteScope []string `json:"write_scope"`
}

PlanScheduleTask is a task entry in the schedule output.

type PlanScheduleWave

type PlanScheduleWave struct {
	Wave  int                `json:"wave"`
	Tasks []PlanScheduleTask `json:"tasks"`
}

PlanScheduleWave is a single wave (parallel group) in the schedule.

type RepoDriftReport

type RepoDriftReport struct {
	Project                     ManagedProject `json:"project"`
	Reachable                   bool           `json:"reachable"`                      // false if path doesn't exist
	MissingCheckpoint           bool           `json:"missing_checkpoint"`             // no checkpoint file
	StaleCheckpoint             bool           `json:"stale_checkpoint"`               // checkpoint older than threshold
	CheckpointAgeDays           int            `json:"checkpoint_age_days"`            // -1 if no checkpoint
	StaleProposalCount          int            `json:"stale_proposal_count"`           // proposals older than threshold
	MissingWorkflowDir          bool           `json:"missing_workflow_dir"`           // no .agents/workflow/
	MissingPlanStructure        bool           `json:"missing_plan_structure"`         // no .agents/workflow/plans/
	CompletedPlanIDs            []string       `json:"completed_plan_ids"`             // plans with status==completed (hygiene signal)
	InconsistentArchivedPlanIDs []string       `json:"inconsistent_archived_plan_ids"` // plans with status==archived still in workflow/plans/ (error-level)
	Warnings                    []string       `json:"warnings"`
	Status                      string         `json:"status"` // healthy|warn|unreachable
}

RepoDriftReport captures drift conditions for one managed project.

type ReviewDecisionDoc

type ReviewDecisionDoc struct {
	SchemaVersion    int      `json:"schema_version" yaml:"schema_version"`
	TaskID           string   `json:"task_id" yaml:"task_id"`
	ParentPlanID     string   `json:"parent_plan_id" yaml:"parent_plan_id"`
	DelegationID     string   `json:"delegation_id,omitempty" yaml:"delegation_id,omitempty"`
	Phase1Decision   string   `json:"phase_1_decision" yaml:"phase_1_decision"`
	Phase2Decision   string   `json:"phase_2_decision" yaml:"phase_2_decision"`
	OverallDecision  string   `json:"overall_decision" yaml:"overall_decision"`
	FailedGates      []string `json:"failed_gates" yaml:"failed_gates"`
	EscalationReason string   `json:"escalation_reason,omitempty" yaml:"escalation_reason,omitempty"`
	ReviewerNotes    string   `json:"reviewer_notes,omitempty" yaml:"reviewer_notes,omitempty"`
	RecordedAt       string   `json:"recorded_at" yaml:"recorded_at"`
	RecordedBy       string   `json:"recorded_by,omitempty" yaml:"recorded_by,omitempty"`
}

ReviewDecisionDoc is the typed payload for `.agents/active/verification/<task_id>/review-decision.yaml`.

type ScopeEvidence

type ScopeEvidence struct {
	SchemaVersion       int                 `json:"schema_version"          yaml:"schema_version"`
	PlanID              string              `json:"plan_id"                 yaml:"plan_id"`
	TaskID              string              `json:"task_id"                 yaml:"task_id"`
	Status              string              `json:"status"                  yaml:"status"`
	Mode                string              `json:"mode,omitempty"          yaml:"mode,omitempty"`
	Goal                string              `json:"goal,omitempty"          yaml:"goal,omitempty"`
	Confidence          string              `json:"confidence"              yaml:"confidence"`
	DecisionLocks       []string            `json:"decision_locks"          yaml:"decision_locks"`
	RequiredReads       []ScopeRequiredRead `json:"required_reads"          yaml:"required_reads"`
	Seeds               *ScopeSeeds         `json:"seeds,omitempty"         yaml:"seeds,omitempty"`
	Queries             []ScopeQuery        `json:"queries"                 yaml:"queries"`
	RequiredPaths       []ScopePath         `json:"required_paths"          yaml:"required_paths"`
	OptionalPaths       []ScopePath         `json:"optional_paths"          yaml:"optional_paths"`
	ExcludedPaths       []ScopeExcludedPath `json:"excluded_paths"          yaml:"excluded_paths"`
	Provides            []string            `json:"provides"                yaml:"provides"`
	Consumes            []string            `json:"consumes"                yaml:"consumes"`
	FinalWriteScope     []string            `json:"final_write_scope"       yaml:"final_write_scope"`
	VerificationFocus   []string            `json:"verification_focus"      yaml:"verification_focus"`
	AllowedLocalChoices []string            `json:"allowed_local_choices"   yaml:"allowed_local_choices"`
	StopConditions      []string            `json:"stop_conditions"         yaml:"stop_conditions"`
	OpenGaps            []string            `json:"open_gaps"               yaml:"open_gaps"`
}

ScopeEvidence is the Go representation of a .scope.yaml sidecar file located at .agents/workflow/plans/<plan_id>/evidence/<task_id>.scope.yaml. All slice fields use []string{} (not nil) so JSON marshals to [] not null.

func NewScopeEvidence

func NewScopeEvidence(planID, taskID string) *ScopeEvidence

NewScopeEvidence returns a ScopeEvidence with all slice fields initialized to empty slices so they marshal to [] rather than null.

type ScopeExcludedPath

type ScopeExcludedPath struct {
	Path      string   `json:"path"      yaml:"path"`
	Rationale []string `json:"rationale" yaml:"rationale"`
}

ScopeExcludedPath is a path intentionally excluded from write_scope.

type ScopePath

type ScopePath struct {
	Path    string   `json:"path"    yaml:"path"`
	Because []string `json:"because" yaml:"because"`
}

ScopePath is a required or optional path entry with explanatory reasons.

type ScopeQuery

type ScopeQuery struct {
	Tool    string             `json:"tool"              yaml:"tool"`
	Kind    string             `json:"kind"              yaml:"kind"`
	Intent  string             `json:"intent"            yaml:"intent"`
	Subject string             `json:"subject"           yaml:"subject"`
	Summary *ScopeQuerySummary `json:"summary,omitempty" yaml:"summary,omitempty"`
}

ScopeQuery represents a single graph query run during scope derivation.

type ScopeQuerySummary

type ScopeQuerySummary struct {
	Files []string `json:"files" yaml:"files"`
}

ScopeQuerySummary holds the result files returned by a graph query.

type ScopeRequiredRead

type ScopeRequiredRead struct {
	Path string `json:"path" yaml:"path"`
	Why  string `json:"why"  yaml:"why"`
}

ScopeRequiredRead is an entry in ScopeEvidence.RequiredReads.

type ScopeSeeds

type ScopeSeeds struct {
	Symbols   []string `json:"symbols,omitempty"   yaml:"symbols,omitempty"`
	Paths     []string `json:"paths,omitempty"     yaml:"paths,omitempty"`
	Rationale []string `json:"rationale,omitempty" yaml:"rationale,omitempty"`
}

ScopeSeeds captures the starting symbols or paths the planner identified.

type SlotLedger

type SlotLedger struct {
	Occupied      int `json:"occupied"`
	AwaitingOwner int `json:"awaiting_owner"`
	Blocked       int `json:"blocked"`
	Pending       int `json:"pending"`
	Terminal      int `json:"terminal"`
	MaxParallel   int `json:"max_parallel"`
	// Available is MaxParallel - Occupied, floored at zero: how many new tasks
	// could start a slot right now.
	Available int `json:"available"`
}

SlotLedger is the §2.8 / §3.4.3 accounting snapshot across one or more plans. Occupied is the live count against MaxParallel; the remaining buckets make the freed-slot reasons (owner-review backlog, blocked pathology) inspectable.

type StatusEntry

type StatusEntry struct {
	XY        string
	Path      string
	OrigPath  string
	Submodule bool
	Untracked bool
}

StatusEntry is one line of `git status --porcelain=v2 -z` after parsing. XY is the 2-char status code; OrigPath is non-empty only for renames / copies. Submodule reflects whether porcelain v2 reported the entry with the "S" sub-state marker (field 3 starts with 'S' instead of 'N').

func ParseStatus

func ParseStatus(raw []byte) ([]StatusEntry, error)

ParseStatus parses `git status --porcelain=v2 -z` output into StatusEntry slices. The v2 format keeps fields fixed-width and NUL-terminates each entry, so the parser is straightforward; v1 is intentionally not supported because v1 cannot reliably distinguish submodule sub-states from regular modifications.

Reference: https://git-scm.com/docs/git-status#_porcelain_format_version_2

type SweepActionItem

type SweepActionItem struct {
	Project              ManagedProject  `json:"project"`
	Action               SweepActionType `json:"action"`
	Description          string          `json:"description"`
	RequiresConfirmation bool            `json:"requires_confirmation"`
	PlanID               string          `json:"plan_id,omitempty"`
}

SweepActionItem is one actionable fix in a sweep plan.

type SweepActionType

type SweepActionType string

SweepActionType enumerates the kinds of fixes the sweep can apply.

const (
	SweepActionScaffoldWorkflowDir      SweepActionType = "scaffold_workflow_dir"
	SweepActionCreatePlanStructure      SweepActionType = "create_plan_structure"
	SweepActionCreateCheckpointReminder SweepActionType = "create_checkpoint_reminder"
	SweepActionFlagStaleProposals       SweepActionType = "flag_stale_proposals"
	SweepActionArchiveCompletedPlans    SweepActionType = "archive_completed_plans"
)

type SweepLogEntry

type SweepLogEntry struct {
	Timestamp   string          `json:"timestamp"`
	Project     string          `json:"project"`
	Action      SweepActionType `json:"action"`
	Description string          `json:"description"`
	Applied     bool            `json:"applied"`
	DryRun      bool            `json:"dry_run"`
}

SweepLogEntry is one record in sweep-log.jsonl.

type SweepPlan

type SweepPlan struct {
	CreatedAt string            `json:"created_at"`
	Actions   []SweepActionItem `json:"actions"`
}

SweepPlan is the collection of planned actions for a sweep run.

type VerificationRecord

type VerificationRecord struct {
	SchemaVersion int      `json:"schema_version"`
	Timestamp     string   `json:"timestamp"`
	Kind          string   `json:"kind"`
	Status        string   `json:"status"`
	Command       string   `json:"command"`
	Scope         string   `json:"scope"`
	Summary       string   `json:"summary"`
	Artifacts     []string `json:"artifacts"`
	RecordedBy    string   `json:"recorded_by"`
}

VerificationRecord is one line in verification-log.jsonl

type VerificationResultDoc

type VerificationResultDoc struct {
	SchemaVersion int      `json:"schema_version" yaml:"schema_version"`
	TaskID        string   `json:"task_id" yaml:"task_id"`
	ParentPlanID  string   `json:"parent_plan_id" yaml:"parent_plan_id"`
	VerifierType  string   `json:"verifier_type" yaml:"verifier_type"`
	Status        string   `json:"status" yaml:"status"`
	Summary       string   `json:"summary" yaml:"summary"`
	RecordedAt    string   `json:"recorded_at" yaml:"recorded_at"`
	DelegationID  string   `json:"delegation_id,omitempty" yaml:"delegation_id,omitempty"`
	RecordedBy    string   `json:"recorded_by,omitempty" yaml:"recorded_by,omitempty"`
	Commands      []string `json:"commands,omitempty" yaml:"commands,omitempty"`
	ArtifactPaths []string `json:"artifact_paths,omitempty" yaml:"artifact_paths,omitempty"`
}

VerificationResultDoc is the typed payload for `.agents/active/verification/<task_id>/<verifier_type>.result.yaml`.

type WorkflowCommitPrefs

type WorkflowCommitPrefs struct {
	Disable *bool `json:"disable,omitempty" yaml:"disable,omitempty"`
}

WorkflowCommitPrefs gates the `da workflow commit` and iteration-close auto-commit behaviour. Disable=true short-circuits both to a documented no-op for repos that manage workflow-state commits elsewhere.

type WorkflowExecutionPrefs

type WorkflowExecutionPrefs struct {
	PackageManager     *string `json:"package_manager,omitempty" yaml:"package_manager,omitempty"`
	Formatter          *string `json:"formatter,omitempty" yaml:"formatter,omitempty"`
	MaxParallelWorkers *int    `json:"max_parallel_workers,omitempty" yaml:"max_parallel_workers,omitempty"`
}

type WorkflowHealthSnapshot

type WorkflowHealthSnapshot struct {
	SchemaVersion int    `json:"schema_version"`
	Timestamp     string `json:"timestamp"`
	Git           struct {
		InsideRepo     bool   `json:"inside_repo"`
		Branch         string `json:"branch"`
		DirtyFileCount int    `json:"dirty_file_count"`
	} `json:"git"`
	Workflow struct {
		HasActivePlan                bool `json:"has_active_plan"`
		HasCheckpoint                bool `json:"has_checkpoint"`
		PendingProposals             int  `json:"pending_proposals"`
		CanonicalPlanCount           int  `json:"canonical_plan_count"`
		CompletedPlansPendingArchive int  `json:"completed_plans_pending_archive"`
	} `json:"workflow"`
	Tooling struct {
		MCP       string `json:"mcp"`
		Auth      string `json:"auth"`
		Formatter string `json:"formatter"`
	} `json:"tooling"`
	Status   string   `json:"status"`
	Warnings []string `json:"warnings"`
}

WorkflowHealthSnapshot is the health.json schema

type WorkflowPlanningPrefs

type WorkflowPlanningPrefs struct {
	PlanDirectory         *string `json:"plan_directory,omitempty" yaml:"plan_directory,omitempty"`
	RequirePlanBeforeCode *bool   `json:"require_plan_before_code,omitempty" yaml:"require_plan_before_code,omitempty"`
}

type WorkflowPreferences

type WorkflowPreferences struct {
	Verification WorkflowVerificationPrefs `json:"verification" yaml:"verification"`
	Planning     WorkflowPlanningPrefs     `json:"planning" yaml:"planning"`
	Review       WorkflowReviewPrefs       `json:"review" yaml:"review"`
	Execution    WorkflowExecutionPrefs    `json:"execution" yaml:"execution"`
	Commit       WorkflowCommitPrefs       `json:"commit" yaml:"commit"`
}

type WorkflowPreferencesFile

type WorkflowPreferencesFile struct {
	SchemaVersion       int `json:"schema_version" yaml:"schema_version"`
	WorkflowPreferences `yaml:",inline" json:",inline"`
}

type WorkflowReviewPrefs

type WorkflowReviewPrefs struct {
	ReviewOrder          *string `json:"review_order,omitempty" yaml:"review_order,omitempty"`
	RequireFindingsFirst *bool   `json:"require_findings_first,omitempty" yaml:"require_findings_first,omitempty"`
}

type WorkflowVerificationPrefs

type WorkflowVerificationPrefs struct {
	TestCommand                    *string `json:"test_command,omitempty" yaml:"test_command,omitempty"`
	LintCommand                    *string `json:"lint_command,omitempty" yaml:"lint_command,omitempty"`
	RequireRegressionBeforeHandoff *bool   `json:"require_regression_before_handoff,omitempty" yaml:"require_regression_before_handoff,omitempty"`
}

Jump to

Keyboard shortcuts

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