Documentation
¶
Index ¶
- Constants
- Variables
- func BuildBugSpec(repo string, plan *FixPlanOutput, logEvidence string) string
- func BuildEnv(ghToken, anthropicBaseURL, anthropicAuthToken, anthropicModel string) map[string]string
- func EnsureChangelog(ctx context.Context, workdir string, baseGoMod []byte) (*changelogResult, error)
- func NewClaudeAuthStep(prober ClaudeProber) agentlib.Step
- func NewExecutionStep(runner claudelib.ClaudeRunner, ops git.GitOps, gh GhCli, gate GateRunner, ...) agentlib.Step
- func NewFixExecutionStep(ops git.GitOps, gh GhCli, ghToken string, createCmd CreateCommandFunc) agentlib.Step
- func NewFixPlanningStep(runner claudelib.ClaudeRunner, ops git.GitOps, gh GhCli, ghToken string) agentlib.Step
- func NewFixReviewStep(ops git.GitOps, ghToken string) agentlib.Step
- func NewGHTokenCheckStep(ghToken string) agentlib.Step
- func NewPlanningRunner(config claudelib.ClaudeRunnerConfig) claudelib.ClaudeRunner
- func NewPlanningStep(runner claudelib.ClaudeRunner, ops git.GitOps, gate GateRunner, ghToken string, ...) agentlib.Step
- func NewReviewStep(ops git.GitOps, gh GhCli, gate GateRunner, modules ModuleResolver, ...) agentlib.Step
- type AdvisoryBlock
- type BulkUpdateResult
- type BulkUpdater
- type ClaudeProber
- type CreateCommandFunc
- type FixPlanOutput
- type FixResultOutput
- type FixVerdict
- type GateRunner
- type GhCli
- type GoBump
- type HardcodedGoVersionPin
- type InstallationScope
- type ModuleResolver
- type ModuleVersion
- type PRTarget
- type PRTargets
- type PinScanResult
- type PlanOutput
- type PlanVuln
- type ResultOutput
- type ReviewChecks
- type ReviewOutput
- type ScannerFinding
- type ScannerTable
- type ScopeVerdict
- type UpdateScope
- type UpdateScopes
Constants ¶
const ( PlanOutcomeReady = "ready" PlanOutcomeNoUpdateNeeded = "no_update_needed" PlanOutcomeNeedsInput = "needs_input" // PlanOutcomeFailed signals a hard planning-time failure that ends // the task in human_review (Status=AgentStatusFailed, // NextPhase=human_review). ErrorCategory + InvalidField + InvalidValue // are populated; the task page is the audit surface. PlanOutcomeFailed = "failed" )
Outcome values for PlanOutput.Outcome.
const ( VulnActionFix = "fix" VulnActionPark = "park" )
Action values for PlanVuln.Action.
const ( ResultOutcomeOpened = "opened" ResultOutcomeAdopted = "adopted" ResultOutcomeNoUpdateNeeded = "no_update_needed" ResultOutcomeFailed = "failed" )
Outcome values for ResultOutput.Outcome.
const AgentLogin = "github-update-go-agent"
AgentLogin is the GitHub-task-system identity of this agent. Per the platform doctrine the CONTROLLER writes previous_assignee — the constant exists for logs and messages only; steps never mutate assignee.
const ( // ErrorCategoryInvalidConfig is the only valid value for // PlanOutput.ErrorCategory today: .maintainer.yaml goUpdate.autoUpdate // is non-boolean or the YAML is malformed. Fail-closed to human_review. ErrorCategoryInvalidConfig = "invalid_config" )
ErrorCategory values for PlanOutput.ErrorCategory.
Variables ¶
var AvailableFixVerdicts = []FixVerdict{ FixVerdictNoFixNeeded, FixVerdictChainUpdate, FixVerdictFileSpec, FixVerdictNeedsInput, }
AvailableFixVerdicts is the complete set of valid verdicts, used for validation and error messages.
var AvailablePRTargets = PRTargets{PRTargetDraft, PRTargetReady}
AvailablePRTargets lists every PRTarget the agent accepts. Validate ranges over this collection — it is the single source of truth.
var AvailableUpdateScopes = UpdateScopes{UpdateScopeBoth, UpdateScopeGolang, UpdateScopeDeps}
AvailableUpdateScopes lists every UpdateScope the agent accepts. Validate ranges over this collection — it is the single source of truth.
Functions ¶
func BuildBugSpec ¶ added in v0.12.0
func BuildBugSpec(repo string, plan *FixPlanOutput, logEvidence string) string
BuildBugSpec renders the kind:bug spec dark-factory consumes, per dark-factory/docs/bug-workflow.md: frontmatter status: idea + kind: bug, then Reproduction / Expected vs Actual / Why this is a bug. Deterministic from the diagnosis plan + failing-workflow evidence — no LLM, so the spec cannot drift from what planning classified.
func BuildEnv ¶
func BuildEnv( ghToken, anthropicBaseURL, anthropicAuthToken, anthropicModel string, ) map[string]string
BuildEnv assembles the env map forwarded into the Claude CLI subprocess. Only set values are forwarded so the subprocess sees a clean env. Shared by both the Kafka entry point (main.go) and the local-CLI entry point (cmd/run-task/main.go).
GH_TOKEN is threaded explicitly because the ClaudeRunner strips the pod env to an allowlist — os.Setenv alone does not reach the Claude subprocess.
func EnsureChangelog ¶ added in v0.10.1
func EnsureChangelog( ctx context.Context, workdir string, baseGoMod []byte, ) (*changelogResult, error)
EnsureChangelog guarantees the workdir CHANGELOG.md is bot-review-clean after an update, deterministically:
- fresh file (no CHANGELOG.md): create it with the canonical preamble + `## Unreleased` + a `chore:` bullet naming the modules actually bumped.
- existing file: guarantee a `## Unreleased` section directly after the preamble (never at the top of the file), and a `chore:` bullet naming the bumps when the section is missing a conventional-prefix bullet.
- the bullet derives from the real go.mod diff (baseGoMod = origin/master, work = the workdir), so it describes only what the update actually changed — never a fabricated entry.
The model's CHANGELOG bullet is best-effort (and absent entirely on the salvage path); this Go step is the deterministic verdict, mirroring the bulk-update / gate-runner pattern. Defects 2 (vague/no-prefix bullet), 3 (no bullet → no release on autoRelease repos), 5 (bare preamble → critical on every fresh repo) are all structural, so all are satisfiable without a model.
func NewClaudeAuthStep ¶
func NewClaudeAuthStep(prober ClaudeProber) agentlib.Step
NewClaudeAuthStep wires the claude-auth preflight with its prober seam.
func NewExecutionStep ¶
func NewExecutionStep( runner claudelib.ClaudeRunner, ops git.GitOps, gh GhCli, gate GateRunner, bulk BulkUpdater, ghToken string, prTarget PRTarget, autoMergeLabel string, defaultScope UpdateScope, ) agentlib.Step
NewExecutionStep wires the execution step with its seams: the Claude runner (repair + CHANGELOG sub-call), the GitOps seam (clone/branch/commit/ push), the gh CLI seam (PR create + adopt), the gate runner (deterministic green-gate re-run), the bulk updater (deterministic `go get -u ./...` + `go mod tidy`, run in Go so the model cannot background it), and the default update scope (UPDATE_SCOPE env; frontmatter `update_scope` overrides per task). prTarget selects draft or ready.
func NewFixExecutionStep ¶ added in v0.12.0
func NewFixExecutionStep( ops git.GitOps, gh GhCli, ghToken string, createCmd CreateCommandFunc, ) agentlib.Step
NewFixExecutionStep wires the build-fix execution step with its GitOps seam (clone/branch/commit/push), gh CLI seam, the GitHub token, and the chain-emission function (nil disables chain publishing).
func NewFixPlanningStep ¶ added in v0.12.0
func NewFixPlanningStep( runner claudelib.ClaudeRunner, ops git.GitOps, gh GhCli, ghToken string, ) agentlib.Step
NewFixPlanningStep wires the build-fix planning step with its Claude runner (diagnosis LLM), the GitOps seam (clone at episode SHA), the gh CLI seam (run log fetch + green-at-HEAD check), and the GitHub token for HTTPS auth URL transformation.
func NewFixReviewStep ¶ added in v0.12.0
NewFixReviewStep wires the build-fix ai_review verifier with its GitOps seam (fresh branch clone) and the GitHub token for HTTPS auth.
func NewGHTokenCheckStep ¶
NewGHTokenCheckStep constructs the preflight step. ghToken is the resolved token from startup auth (passed by main → factory). Empty means the step fails fast on the first run.
func NewPlanningRunner ¶ added in v0.6.0
func NewPlanningRunner(config claudelib.ClaudeRunnerConfig) claudelib.ClaudeRunner
NewPlanningRunner constructs the tool-result-logging planning runner.
func NewPlanningStep ¶
func NewPlanningStep( runner claudelib.ClaudeRunner, ops git.GitOps, gate GateRunner, ghToken string, scope InstallationScope, maintainerConfig maintainerconfig.Fetcher, defaultScope UpdateScope, ) agentlib.Step
NewPlanningStep wires the planning step with its Claude runner (inspection LLM), the GitOps seam (resolve the current default-branch HEAD at run start and clone at it), the GateRunner (repo gate detection + full scanner-output capture), the GitHub token (HTTPS auth URL transformation), the installation-scope allowlist check, the .maintainer.yaml consent gate (goUpdate.autoUpdate — mirror of github-releaser-agent spec 059), and the default update scope (UPDATE_SCOPE env; frontmatter `update_scope` overrides per task).
func NewReviewStep ¶
func NewReviewStep( ops git.GitOps, gh GhCli, gate GateRunner, modules ModuleResolver, ghToken string, prTarget PRTarget, ) agentlib.Step
NewReviewStep wires the ai_review verifier with its GitOps seam (fresh clone + tag/rev inspection), gh CLI seam (PR state), gate runner (independent gate re-run), module-graph resolver (installed version of an external advisory's package), the GitHub token, and the configured PRTarget the step compares observed draft-ness against. On approval the step writes the plain-text ## Your Move operator-action block (PR link + merge action + change summary) above ## Plan for the human operator.
Types ¶
type AdvisoryBlock ¶ added in v0.18.0
AdvisoryBlock is one validated externally-supplied advisory read from the task frontmatter's `advisory` mapping. The block shape is frozen: exactly the four keys id, package, fixed_version, source, all required and non-empty. Unrecognized extra keys are ignored.
type BulkUpdateResult ¶ added in v0.5.0
type BulkUpdateResult struct {
// Ran is false when the sequence could not complete. FailDetail then
// explains why, and the model is told to treat the update as NOT done.
Ran bool
// FailDetail is empty when Ran is true.
FailDetail string
// Output is the tail of the combined command output, for the prompt.
Output string
}
BulkUpdateResult reports what the deterministic bulk update did.
Like FunnelResult in github-pr-review-agent, this is returned instead of a bare error for the expected non-fatal outcomes, so the caller can surface a fail-closed condition into the prompt rather than aborting the pipeline. The model must be told the update did not run — never left to assume it did.
type BulkUpdater ¶ added in v0.5.0
type BulkUpdater interface {
Run(ctx context.Context, workdir string) (BulkUpdateResult, error)
}
BulkUpdater runs the mechanical dependency-update sequence (`go get -u ./...` + `go mod tidy`) in Go, before the execution model call.
The agent runs this itself rather than instructing the model to. Left to the model, a long-running `go get` invites backgrounding: on 2026-08-16 the execution model put it in a harness background task and then blocked on TaskOutput for 600s, timed out, and re-issued the identical blocking call on the same task_id — burning the Job's full 1800s activeDeadlineSeconds and producing nothing (bborbe/ip, job bc3c6599; also bborbe/run, bborbe/beactive).
Prompt rules could not prevent it: execution.md already forbade backgrounding, but named only the shell forms (`&`, `nohup`, detached jobs), not the harness's own run_in_background/TaskOutput. Running the step in Go removes the model's ability to express it in any form at all — the same reasoning that moved the ast-grep funnel into Go in github-pr-review-agent.
func NewBulkUpdater ¶ added in v0.5.0
func NewBulkUpdater() BulkUpdater
NewBulkUpdater constructs the production BulkUpdater.
type ClaudeProber ¶
type ClaudeProber interface {
// Probe returns nil when claude is authenticated and reachable, or an
// error describing the failure otherwise.
Probe(ctx context.Context) error
}
ClaudeProber runs a trivial claude invocation to confirm the CLI is authenticated before any prompt-bearing phase runs.
func NewClaudeProber ¶
func NewClaudeProber(claudeConfigDir claudelib.ClaudeConfigDir) ClaudeProber
NewClaudeProber constructs a ClaudeProber that shells out to `claude --print`. claudeConfigDir, when non-empty, is exported as CLAUDE_CONFIG_DIR so the probe reads the same login the agent will.
type CreateCommandFunc ¶ added in v0.12.0
CreateCommandFunc publishes a downstream task (chain emission). The agent cannot write vault files directly; the controller's Kafka command bus is the only sanctioned producer path (watchers use task.CreateCommandSender). main.go wires the real implementation; nil in local CLI mode → the step logs the intended chain and completes (no-op) so the operator can replay the diagnosis locally without a cluster.
type FixPlanOutput ¶ added in v0.12.0
type FixPlanOutput struct {
Verdict FixVerdict `json:"verdict"`
// Reason carries the human-readable diagnosis on every path — the
// reproduction/expected-actual summary the spec writer or escalation
// message needs.
Reason string `json:"reason,omitempty"`
// FailingWorkflows are the workflow names observed red in the task body
// (or discovered during diagnosis). The spec writer cites them verbatim.
FailingWorkflows []string `json:"failing_workflows,omitempty"`
// EpisodeSHA is the CI episode SHA under diagnosis, echoed back for the
// spec / chain task to pin.
EpisodeSHA string `json:"episode_sha,omitempty"`
}
FixPlanOutput is the typed contract for the `## Fix Plan` JSON section the build-fixer's planning step writes for every build-fix task. Round-trips with agentlib.MarshalSectionTyped + agentlib.ExtractSection[FixPlanOutput].
Verdicts (the four-way diagnosis, design § 2026-08-22):
- "no_fix_needed" — build already green at HEAD; task closes as success
- "chain_update" — root cause is a stale dependency / vulnerability; execution emits a github-update-go task (chain to the updater agent)
- "file_spec" — root cause is a code / test bug; execution files a kind:bug spec for dark-factory to fix
- "needs_input" — ambiguous / insufficient log evidence; escalate to the operator inbox
No `Details map[string]any`: concrete fields only. Future fields require a design amendment.
type FixResultOutput ¶ added in v0.12.0
type FixResultOutput struct {
Outcome string `json:"outcome"`
Message string `json:"message,omitempty"`
Branch string `json:"branch,omitempty"`
}
FixResultOutput is the typed contract for the `## Fix Result` section.
type FixVerdict ¶ added in v0.12.0
type FixVerdict string
FixVerdict is the typed build-fix diagnosis verdict. A typo in a switch case or comparison now fails to compile instead of silently routing the task to the wrong phase.
const ( FixVerdictNoFixNeeded FixVerdict = "no_fix_needed" FixVerdictChainUpdate FixVerdict = "chain_update" FixVerdictFileSpec FixVerdict = "file_spec" FixVerdictNeedsInput FixVerdict = "needs_input" )
Fix verdict values for FixPlanOutput.Verdict.
type GateRunner ¶
type GateRunner interface {
// RunTarget runs `make <target>` in workdir. Returns the bounded
// combined-output tail, the process exit code (0 on success), and a
// non-nil error when the target failed or could not be started.
RunTarget(ctx context.Context, workdir, target string) (tail string, exitCode int, err error)
// RunTargetFull runs `make <target>` in workdir and returns the FULL
// combined output (no truncation), the process exit code (0 on success),
// and a non-nil error when the target failed or could not be started.
// Planning uses this to capture the complete raw scanner output; the
// bounded RunTarget tail remains for failure messages.
RunTargetFull(
ctx context.Context,
workdir, target string,
) (output string, exitCode int, err error)
}
GateRunner runs one repo gate target (`make -C <workdir> <target>`) and reports the exit code plus a bounded output tail. The execution step uses it as the deterministic green-gate after the Claude sub-call; the ai_review step re-runs the same targets independently.
func NewOSExecGateRunner ¶
func NewOSExecGateRunner() GateRunner
NewOSExecGateRunner returns a GateRunner shelling out to make. The gate inherits the full pod env (os.Environ()): repo Makefiles run scanners via `go run tool@version`, which needs GOPROXY/GOPATH/HOME plus GH_TOKEN for private module fetches — the design accepts in-pod arbitrary code execution for own repos (design § 7.2).
type GhCli ¶
type GhCli interface {
// CreatePR opens a pull request from head against base, running gh
// inside workdir so the repo is inferred from the git remote. target
// selects draft or ready-for-review at creation time. label, when
// non-empty, is added to the PR at creation (e.g. "auto-merge" to opt
// the PR into GitHub-native auto-merge). Returns the PR URL.
CreatePR(
ctx context.Context,
workdir, base, head, title, body string,
target PRTarget,
label string,
) (string, error)
// FindOpenPRByHead returns the URL of an open PR whose head is the
// given branch, or "" when none exists. repo is "owner/name".
FindOpenPRByHead(ctx context.Context, repo, head string) (string, error)
// ViewPR returns the state (e.g. "OPEN", "MERGED", "CLOSED") and
// draft flag of the PR identified by URL.
ViewPR(ctx context.Context, prURL string) (state string, isDraft bool, err error)
// FetchFailedLogs returns the failed-step log tail for the latest
// failing run of the episode SHA on the repo, via `gh run view
// --log-failed`. Returns "" when no failing run exists for the episode
// (the caller treats it as "no log evidence"). Used by the build-fix
// planning step to give the diagnosis LLM concrete failure evidence.
FetchFailedLogs(ctx context.Context, repo, episodeSHA string) (string, error)
}
GhCli is the seam between the steps and the gh binary. Three methods cover the agent's entire PR surface: create a PR at a configurable target (draft or ready-for-review), adopt an already-open PR by head branch (crash-window replay guard), and view PR state for the ai_review checks.
The creation target is chosen per deployment; the agent itself only opens PRs and never changes their draft/ready state after creation. Deliberately absent: no Ready, no Merge — the agent never flips the draft flag of an already-open pull request and never merges; the human does.
func NewOSExecGhCli ¶
NewOSExecGhCli returns a GhCli implementation that shells out to the gh binary with a minimal allowlisted env (GH_TOKEN, HOME, PATH).
type HardcodedGoVersionPin ¶ added in v0.10.0
type HardcodedGoVersionPin struct {
// File is the workflow path relative to the repo root, e.g.
// ".github/workflows/ci.yml".
File string
// Value is the pinned Go version literal, e.g. "1.26.5".
Value string
}
HardcodedGoVersionPin is one `.github/workflows/*.yml` `go-version:` finding.
type InstallationScope ¶ added in v0.3.0
type InstallationScope interface {
// Allows reports whether repo ("owner/name") is covered by the token's
// installation. Unknown means the check itself was impossible — never
// treat that as denial.
Allows(ctx context.Context, repo string) ScopeVerdict
}
InstallationScope answers whether the GitHub App installation backing the agent's token covers a repo. The App installation's repository selection IS the fleet's per-stage allowlist (design § 7.2): a repo outside it must park in planning, before any clone/update work — not after ten minutes of work at the push step.
func NewGhInstallationScope ¶ added in v0.3.0
func NewGhInstallationScope(ghToken string) InstallationScope
NewGhInstallationScope returns an InstallationScope that shells out to `gh api /installation/repositories` with the agent's token. With an App installation token the endpoint lists exactly the accessible repos; with the local GH_TOKEN PAT fallback it 403s, which maps to ScopeUnknown (local runs are operator-supervised — no allowlist to enforce).
type ModuleResolver ¶ added in v0.18.0
type ModuleResolver interface {
// Modules runs `go list -m -f {{.Path}} {{.Version}} all` in workdir under
// moduleResolveTimeout and returns the parsed module list. A non-nil error
// means the graph could not be read — the caller fails closed.
Modules(ctx context.Context, workdir string) ([]ModuleVersion, error)
}
ModuleResolver lists the modules of a worktree's module graph. It is the seam the ai_review step resolves an external advisory's package through: the installed version of a package lives in the module that provides it, and that module may be an indirect requirement.
func NewOSExecModuleResolver ¶ added in v0.18.0
func NewOSExecModuleResolver() ModuleResolver
NewOSExecModuleResolver constructs the production ModuleResolver.
type ModuleVersion ¶ added in v0.18.0
ModuleVersion is one module of a worktree's module graph with its installed (MVS-selected) version. Version is empty for the main module.
type PRTarget ¶ added in v0.4.0
type PRTarget string
PRTarget is the closed set of pull-request targets the agent may open a pull request as. It is chosen per deployment at creation time only — the agent never flips an already-open pull request and never merges.
func ParsePRTarget ¶ added in v0.4.0
ParsePRTarget resolves the configured pull-request target. An empty value means "unset" and resolves to PRTargetDraft, preserving the pre-configuration behaviour byte-for-byte. Any other unrecognised value is rejected.
type PRTargets ¶ added in v0.4.0
type PRTargets []PRTarget
PRTargets is a collection of PRTarget values.
type PinScanResult ¶ added in v0.10.0
type PinScanResult struct {
// PlainPins are single-value `go-version:` pins (hardcoded — the repo's CI
// toolchain is frozen; a bump desyncs it → escalate).
PlainPins []HardcodedGoVersionPin
// MatrixPins are `go-version:` pins inside a strategy matrix (multiple Go
// versions tested deliberately — NOT a hardcode; no escalation).
MatrixPins []HardcodedGoVersionPin
}
PinScanResult distinguishes the two pin shapes.
func ScanWorkflowGoVersionPins ¶ added in v0.10.0
func ScanWorkflowGoVersionPins(ctx context.Context, workdir string) (PinScanResult, error)
ScanWorkflowGoVersionPins walks `.github/workflows/*.yml|.yaml` in workdir and classifies every `go-version:` pin as plain (single value → hardcoded) or matrix (inside a strategy.matrix → deliberate multi-version testing).
Pure-Go preflight (no LLM): deterministic, cheap, and the first gate before any update work — the planning phase escalates on a plain pin instead of opening a PR that fails CI (`go.mod requires go >= X (running go Y; GOTOOLCHAIN=local)`), which the agent is architecturally forbidden to fix (no Workflows permission; committed-files guard rejects workflow edits).
func (PinScanResult) HasPlainPin ¶ added in v0.10.0
func (r PinScanResult) HasPlainPin() bool
HasPlainPin reports whether the scan found any hardcoded single-value pin.
type PlanOutput ¶
type PlanOutput struct {
Outcome string `json:"outcome"`
// HasWork is true when the execution phase has anything to do.
// omitempty is deliberately NOT applied so a `false` decision is
// always written explicitly.
HasWork bool `json:"has_work"`
// GoBump records the go-directive bump (from current directive to the
// image toolchain per design D5). Nil when the directive is already
// current.
GoBump *GoBump `json:"go_bump,omitempty"`
// DepUpdatesExpected is true when `go list -u -m` style inspection
// found outdated direct dependencies.
DepUpdatesExpected bool `json:"dep_updates_expected"`
// GateTargets are the Makefile targets forming the repo's own gate
// (e.g. precommit, check, vulncheck). Execution and ai_review re-run
// exactly these to exit 0 — never a hardcoded scanner.
GateTargets []string `json:"gate_targets,omitempty"`
// Vulns holds every scanner finding with its fix-vs-park classification.
Vulns []PlanVuln `json:"vulns,omitempty"`
// Reason carries the human-readable explanation on the
// needs_input / no_update_needed paths.
Reason string `json:"reason,omitempty"`
// GoUpdateAutoUpdate records the consent flag read from the target
// repo's .maintainer.yaml at planning entry (mirrors the sibling's
// ChangelogRewrite). Nil when the planning gate never reached a
// config read (absent file / fetch error → see ConfigFetchWarning).
//
// JSON encoding contract:
// - happy path, flag true → field SET to &true → JSON emits
// literal substring `"go_update_auto_update":true`
// - happy path, flag false → field SET to &false → JSON emits
// literal substring `"go_update_auto_update":false`
// - failure path → field LEFT nil → omitempty omits
// the token entirely; `go_update_auto_update` is absent from the JSON
GoUpdateAutoUpdate *bool `json:"go_update_auto_update,omitempty"`
// ConfigFetchWarning records a non-fatal .maintainer.yaml fetch failure
// that the planning step recovered from by using the default
// goUpdate.autoUpdate=false. Populated only when the fetch errored with
// something OTHER than ErrFileNotFound (transport, DNS, 5xx, timeout).
// Operators reading the task page can grep this field to confirm
// whether a repo that opted into updates was silently skipped.
// Empty on the happy path (file present) and on the legitimate-absent
// path (404 → ErrFileNotFound).
ConfigFetchWarning string `json:"config_fetch_warning,omitempty"`
// ErrorCategory names the failure category on outcome="failed". For
// the .maintainer.yaml gate the only value is "invalid_config"
// (goUpdate.autoUpdate is non-boolean or the YAML is malformed).
// Future failure categories may extend this set.
ErrorCategory string `json:"error_category,omitempty"`
// InvalidField names the .maintainer.yaml field that failed validation.
// Populated on outcome="failed" only; today always "goUpdate.autoUpdate".
InvalidField string `json:"invalid_field,omitempty"`
// InvalidValue captures the literal raw value that failed validation
// (the YAML-decoded string/number/etc., as it appeared in the file).
// Populated on outcome="failed" only.
InvalidValue string `json:"invalid_value,omitempty"`
}
PlanOutput is the typed contract for the `## Plan` JSON section the planning step writes for every github-update-go task. Round-trips with agentlib.MarshalSectionTyped + agentlib.ExtractSection[PlanOutput].
Shapes (design § 4.3):
- Outcome="ready" — update work exists; GateTargets populated, HasWork=true
- Outcome="no_update_needed" — repo already current; HasWork=false
- Outcome="needs_input" — park path (unfixable finding / precondition); Reason populated
No `Details map[string]any`: concrete fields only. Future fields require a design amendment.
type PlanVuln ¶
type PlanVuln struct {
// ID is the finding identifier (GO-*, CVE-*, GHSA-*).
ID string `json:"id"`
// Package is the vulnerable module path.
Package string `json:"package,omitempty"`
// FixedVersion is the patched version the scanner reported; empty when
// no fix exists (the park case).
FixedVersion string `json:"fixed_version,omitempty"`
// Scanner names which gate scanner flagged the finding
// (govulncheck | osv-scanner | trivy).
Scanner string `json:"scanner,omitempty"`
// Action is "fix" (patched version exists — bump it) or "park"
// (no fix / out-of-scope major — task parks per design D4).
Action string `json:"action"`
// Reason is the one-line classification justification.
Reason string `json:"reason,omitempty"`
}
PlanVuln is one scanner finding with its planned action.
type ResultOutput ¶
type ResultOutput struct {
Outcome string `json:"outcome"`
Branch string `json:"branch,omitempty"`
PRURL string `json:"pr_url,omitempty"`
// GateExit is the exit code of the last gate target run (0 = green).
// omitempty is deliberately NOT applied — an explicit 0 documents the
// green gate.
GateExit int `json:"gate_exit"`
// DepsUpdated counts the module bumps the update sequence applied.
DepsUpdated int `json:"deps_updated"`
// VulnsFixed lists the finding IDs resolved by the update — always a
// subset of the plan's fix-action vulns.
VulnsFixed []string `json:"vulns_fixed,omitempty"`
// FailedTarget names the gate target that stayed red (failure path only).
FailedTarget string `json:"failed_target,omitempty"`
ErrorCategory git.ErrorCategory `json:"error_category,omitempty"`
Error string `json:"error,omitempty"`
}
ResultOutput is the typed contract for the `## Result` JSON section the execution step writes. Round-trips with agentlib.MarshalSectionTyped + agentlib.ExtractSection[ResultOutput].
Shapes (design § 4.3):
- Outcome="opened" — draft PR created; Branch/PRURL populated, GateExit=0
- Outcome="adopted" — crash-window replay found the PR already open; adopted as-is
- Outcome="no_update_needed" — the update sequence produced no effective change (workdir diff empty or CHANGELOG.md-only) once MVS settled; no commit/push/PR, workdir discarded (go-skeleton PR #51 guard)
- Outcome="failed" — any failure; ErrorCategory + Error populated
Invariant (design § 4.4): Branch == "fix/update-go-" + ref[:7]; VulnsFixed ⊆ {v.ID | v ∈ Plan.Vulns, Action=fix}.
type ReviewChecks ¶
type ReviewChecks struct {
// PROpen — `gh pr view` reports state OPEN.
PROpen bool `json:"pr_open"`
// PRDraft — the raw isDraft value reported by `gh pr view`. The review
// compares this against the configured PR_TARGET (draft default, ready
// opt-in); a mismatch is surfaced in the notes and causes approval to
// fail. This field always reports what was observed — the match verdict
// lives in the approval flag and the notes, not here.
PRDraft bool `json:"pr_draft"`
// GateGreen — every planned gate target re-ran to exit 0 on a fresh
// worktree at the branch.
GateGreen bool `json:"gate_green"`
// VulnsClear — the scanner-bearing gate targets came back green on the
// re-run (the gate IS the vuln verdict, per design § 7.3 the repo's
// gate wraps govulncheck/osv-scanner/trivy).
VulnsClear bool `json:"vulns_clear"`
// ChangelogUnreleased — CHANGELOG.md carries a bullet under
// ## Unreleased and introduces no new version header vs master.
ChangelogUnreleased bool `json:"changelog_unreleased"`
// NoNewTag — `git ls-remote --tags` shows no tag pointing at any
// branch commit.
NoNewTag bool `json:"no_new_tag"`
}
ReviewChecks holds the boolean verification results of the pure-Go ai_review step. Every field is derived from independent re-execution — never copied from ## Result (design § 4.4).
type ReviewOutput ¶
type ReviewOutput struct {
Approved bool `json:"approved"`
Checks ReviewChecks `json:"checks"`
Notes string `json:"notes"`
}
ReviewOutput is the typed contract for the `## Review` JSON section the ai_review step writes. Round-trips with agentlib.MarshalSectionTyped + agentlib.ExtractSection[ReviewOutput].
type ScannerFinding ¶ added in v0.6.0
type ScannerFinding struct {
ID string
Package string
FixedVersion string // empty when the scanner reports no fix
Scanner string // govulncheck | osv-scanner | trivy | <target> fallback
}
ScannerFinding is one parsed finding row from a gate target's raw output.
type ScannerTable ¶ added in v0.6.0
type ScannerTable []ScannerFinding
ScannerTable is the parsed ground-truth findings table for a planning run, accumulated across every detected gate target.
func (ScannerTable) Contains ¶ added in v0.6.0
func (t ScannerTable) Contains(id string) bool
Contains reports whether id appears verbatim in the table (exact match).
func (ScannerTable) FilterSuppressed ¶ added in v0.12.6
func (t ScannerTable) FilterSuppressed(suppressed map[string]bool) ScannerTable
FilterSuppressed returns a copy of the table without rows whose ID is in suppressed. The planning stage must not present operator-approved no-fix suppressions to the model as park-worthy findings: the gate targets run against those very configs (and pass), yet their echoed output can still list the suppressed IDs — captured naively, the task re-parks on a suppression the operator already approved (design D4). Nil/empty suppressed returns the table unchanged.
func (ScannerTable) Row ¶ added in v0.6.0
func (t ScannerTable) Row(id string) (ScannerFinding, bool)
Row returns the first row whose ID equals id exactly.
type ScopeVerdict ¶ added in v0.3.0
type ScopeVerdict string
ScopeVerdict is the outcome of an installation-scope check.
const ( // ScopeAllowed — the repo is in the App installation's repository list. ScopeAllowed ScopeVerdict = "allowed" // ScopeDenied — the installation token definitively cannot access the repo. ScopeDenied ScopeVerdict = "denied" // ScopeUnknown — the check could not be performed (PAT fallback, API // error). Callers proceed; a real permission gap still fails at push. ScopeUnknown ScopeVerdict = "unknown" )
type UpdateScope ¶ added in v0.7.0
type UpdateScope string
UpdateScope is the closed set of update-work scopes the agent may apply to a repo. It selects what the update sequence touches: the Go toolchain directive, the module dependency graph, or both. Chosen per task from frontmatter `update_scope` (falling back to the UPDATE_SCOPE env default).
const ( // UpdateScopeBoth updates the Go toolchain directive AND the dependency // graph (the default — matches the pre-knob behaviour byte-for-byte). UpdateScopeBoth UpdateScope = "both" // UpdateScopeGolang updates only the Go toolchain directive (go.mod // `go`/`toolchain` + Dockerfile golang pins); deps are left untouched. UpdateScopeGolang UpdateScope = "golang" // UpdateScopeDeps updates only the module dependency graph; the Go // toolchain directive is left untouched. UpdateScopeDeps UpdateScope = "deps" )
func ParseUpdateScope ¶ added in v0.7.0
func ParseUpdateScope(ctx context.Context, value string) (UpdateScope, error)
ParseUpdateScope resolves the configured update scope. An empty value means "unset" and resolves to UpdateScopeBoth, preserving the pre-knob behaviour byte-for-byte. Any other unrecognised value is rejected.
func (UpdateScope) IsBoth ¶ added in v0.7.0
func (u UpdateScope) IsBoth() bool
IsBoth returns true if the UpdateScope is UpdateScopeBoth.
func (UpdateScope) IsDepsOnly ¶ added in v0.7.0
func (u UpdateScope) IsDepsOnly() bool
IsDepsOnly returns true if the UpdateScope is UpdateScopeDeps.
func (UpdateScope) IsGolangOnly ¶ added in v0.7.0
func (u UpdateScope) IsGolangOnly() bool
IsGolangOnly returns true if the UpdateScope is UpdateScopeGolang.
func (UpdateScope) String ¶ added in v0.7.0
func (u UpdateScope) String() string
String returns the string representation of the UpdateScope.
type UpdateScopes ¶ added in v0.7.0
type UpdateScopes []UpdateScope
UpdateScopes is a collection of UpdateScope values.
func (UpdateScopes) Contains ¶ added in v0.7.0
func (u UpdateScopes) Contains(scope UpdateScope) bool
Contains returns true if the collection contains scope.
func (UpdateScopes) Strings ¶ added in v0.7.0
func (u UpdateScopes) Strings() []string
Strings returns a slice of string representations of each UpdateScope.
Source Files
¶
- advisory.go
- buildenv.go
- bulk_update.go
- changelog.go
- claude_prober.go
- fix_helpers.go
- fix_plan_output.go
- fix_spec.go
- gate_runner.go
- gh_cli.go
- installation_scope.go
- llmjson.go
- module_versions.go
- plan_output.go
- planning_runner.go
- pr_target.go
- result_output.go
- review_output.go
- scanner_table.go
- steps_claude_auth.go
- steps_execution.go
- steps_fix_execution.go
- steps_fix_planning.go
- steps_fix_review.go
- steps_gh_token.go
- steps_mocks.go
- steps_planning.go
- steps_review.go
- update_scope.go
- url_helpers.go
- workflow_pin.go
- your_move.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package factory wires concrete dependencies for the github-update-go-agent binary.
|
Package factory wires concrete dependencies for the github-update-go-agent binary. |
|
Package git wraps git shell-outs behind the GitOps interface so the execution and ai_review steps can be tested with a counterfeiter mock.
|
Package git wraps git shell-outs behind the GitOps interface so the execution and ai_review steps can be tested with a counterfeiter mock. |
|
Package githubauth resolves the github-update-go agent's effective GitHub credential at startup.
|
Package githubauth resolves the github-update-go agent's effective GitHub credential at startup. |
|
Package maintainerconfig fetches and exposes the .maintainer.yaml bytes for the github-update-go agent's planning step.
|
Package maintainerconfig fetches and exposes the .maintainer.yaml bytes for the github-update-go agent's planning step. |
|
Package prompts holds the prompt modules for the github-update-go-agent's two domain agents.
|
Package prompts holds the prompt modules for the github-update-go-agent's two domain agents. |