Documentation
¶
Overview ¶
Package config handles loading and resolution of team and user configuration.
Package config handles loading and resolution of team and user configuration.
Index ¶
- Constants
- func AgentConfigWarnings(cfg *TeamConfig) []string
- func AgentMigrationYAML() string
- func ArchiveDir(tc *TeamConfig) string
- func BountyFinishNames() []string
- func FindTeamConfigPath(startDir string) (string, error)
- func HasRemovedAgentKeys(cfg *TeamConfig) bool
- func IsValidRole(role string) bool
- func KnownPresets() []string
- func ParseDuration(s string) (time.Duration, error)
- func PresetInfo(name string) (description string, features []string, stageNames []string, err error)
- func PresetNames() []string
- func RemovedAgentKeys(cfg *TeamConfig) []string
- func UserConfigDir() string
- func UserConfigPath() string
- func ValidRoles() []string
- func WriteUserConfig(path string, cfg *UserConfig) error
- type AgentAuthoringConfig
- type AutoAdvanceConfig
- type BlockedConfig
- type BountyConfig
- func (b *BountyConfig) Cap() int
- func (b *BountyConfig) GrantableRoles() []string
- func (b *BountyConfig) IsEnabled() bool
- func (b *BountyConfig) IsRoleAllowed(role string) bool
- func (b *BountyConfig) MetalFinish() BountyFinish
- func (b *BountyConfig) ReasonRequired() bool
- func (b *BountyConfig) ShimmerEnabled() bool
- type BountyFinish
- type BuildConfig
- type DashboardConfig
- type DeployConfig
- type Diagnostic
- type DoScope
- type EffectConfig
- type Environment
- type FastTrackConfig
- type FrontmatterDefaults
- type GateConfig
- type GenerateConfig
- type IntakeConfig
- type IntakeSource
- type IntegrationsConfig
- type JiraConfig
- type KV
- type LinkExistsGate
- type LintResult
- type NotifyEffect
- type Owners
- type PassiveAwarenessConfig
- type PipelineConfig
- func (p PipelineConfig) IsValidReversion(from, to string) bool
- func (p PipelineConfig) IsValidTransition(from, to string) bool
- func (p PipelineConfig) NextStage(current string) (string, bool)
- func (p PipelineConfig) RequiredStages() []StageConfig
- func (p PipelineConfig) StageByName(name string) *StageConfig
- func (p PipelineConfig) StageIndex(name string) int
- func (p PipelineConfig) StageNames() []string
- type PreferencesConfig
- type PresetConfig
- type ProviderConfig
- type ResolvedConfig
- func (r *ResolvedConfig) AgentDraftsEnabled() bool
- func (r *ResolvedConfig) AgentTransitionsAllowed() bool
- func (r *ResolvedConfig) AutoPushEnabled() bool
- func (r *ResolvedConfig) AutoPushPolicy() string
- func (r *ResolvedConfig) Bounties() *BountyConfig
- func (r *ResolvedConfig) BountyEnabled() bool
- func (r *ResolvedConfig) CanonicalHandle() string
- func (r *ResolvedConfig) CycleLabel() string
- func (r *ResolvedConfig) EffectiveAgentConfig() ProviderConfig
- func (r *ResolvedConfig) HasAgent() bool
- func (r *ResolvedConfig) HasIntegration(category string) bool
- func (r *ResolvedConfig) IdentityForCategory(category string) string
- func (r *ResolvedConfig) IntegrationProvider(category string) string
- func (r *ResolvedConfig) OwnerRole(override string) string
- func (r *ResolvedConfig) Pipeline() PipelineConfig
- func (r *ResolvedConfig) ProviderHandle(provider string) string
- func (r *ResolvedConfig) SpecsRepoRoot() string
- func (r *ResolvedConfig) TeamName() string
- func (r *ResolvedConfig) UserHandle() string
- func (r *ResolvedConfig) UserIdentities() []string
- func (r *ResolvedConfig) UserName() string
- type ReviewConfig
- type Severity
- type SpecsRepoConfig
- type StageConfig
- type StageDashboardConfig
- type StageReviewConfig
- type SyncConfig
- type TeamConfig
- type TemplatesConfig
- type TransitionConfig
- type TransitionsConfig
- type UpdatePMEffect
- type UrgencyConfig
- type UserConfig
- type WarningConfig
- type WebhookEffect
Constants ¶
const ( // AutoPushAuto publishes local edits automatically (the default). AutoPushAuto = "auto" // AutoPushPrompt asks for confirmation before publishing on interactive // surfaces; async surfaces (TUI, MCP) treat it as AutoPushAuto. AutoPushPrompt = "prompt" // AutoPushOff preserves the manual model: edits stay local until the user // runs 'spec push'. AutoPushOff = "off" )
Auto-push policy values for SyncConfig.AutoPush. They govern whether a local mutation (an editor edit, a thread comment) is published to the specs repo without the user remembering to run 'spec push'.
const ( // BlockedScopeAll shows every blocked spec (default; back-compat). BlockedScopeAll = "all" // BlockedScopeInvolved shows blocked specs the viewer authors or is assigned. BlockedScopeInvolved = "involved" // BlockedScopeOwningRole shows blocked specs whose pre-block stage the // viewer's role owned. BlockedScopeOwningRole = "owning_role" )
Blocked scope constants govern which blocked specs appear in a viewer's BLOCKED section.
const ( MultiplexerTmux = "tmux" MultiplexerZellij = "zellij" MultiplexerWezterm = "wezterm" MultiplexerIterm2 = "iterm2" MultiplexerNone = "none" )
Multiplexer constants.
const ( // DefaultBountyMaxActive is the number of concurrently bountied specs // allowed when max_active is unset. DefaultBountyMaxActive = 3 )
Default bounty settings. A bounty is deliberately scarce: an uncapped marker debases to a second priority field, so the cap is a first-class default rather than an opt-in.
Variables ¶
This section is empty.
Functions ¶
func AgentConfigWarnings ¶ added in v0.44.0
func AgentConfigWarnings(cfg *TeamConfig) []string
AgentConfigWarnings returns the migration warnings for a team config, at most once per process. Subsequent calls return nil, so callers can emit unconditionally without repeating themselves.
The returned strings are one line each and point at lint for the full replacement YAML rather than printing a wall of config.
func AgentMigrationYAML ¶ added in v0.44.0
func AgentMigrationYAML() string
AgentMigrationYAML is the replacement block for a user cutting over. It is exported so the TUI notice and `spec config lint` show the same literal YAML: two renderings of one migration must not disagree about the fix.
func ArchiveDir ¶
func ArchiveDir(tc *TeamConfig) string
ArchiveDir returns the configured archive directory.
func BountyFinishNames ¶ added in v0.45.0
func BountyFinishNames() []string
BountyFinishNames lists the accepted finishes, for lint suggestions and docs.
func FindTeamConfigPath ¶
FindTeamConfigPath searches for spec.config.yaml starting from dir, then up.
func HasRemovedAgentKeys ¶ added in v0.44.0
func HasRemovedAgentKeys(cfg *TeamConfig) bool
HasRemovedAgentKeys reports whether a team config still carries a removed integration key. The TUI uses this to surface the migration notice on a surface the user actually sees: the stderr warning is emitted before the alt screen opens, so it would flash past a TUI-primary user.
func KnownPresets ¶ added in v0.23.0
func KnownPresets() []string
KnownPresets returns the built-in pipeline preset names recognised by the linter. It delegates to PresetNames (the authoritative registry in this package) so the linter can never drift from the preset map.
func ParseDuration ¶ added in v0.30.0
ParseDuration parses a duration string with support for day ("d") and week ("w") units in addition to Go's standard units (ns, us, ms, s, m, h). Tokens may be combined, e.g. "1w2d", "5d", "30m", "48h". A bare "0" yields zero. Whitespace is trimmed and parsing is case-insensitive.
func PresetInfo ¶ added in v0.38.1
func PresetInfo(name string) (description string, features []string, stageNames []string, err error)
PresetInfo returns metadata about a preset for display.
func PresetNames ¶ added in v0.38.1
func PresetNames() []string
PresetNames returns the names of all available presets.
func RemovedAgentKeys ¶ added in v0.44.0
func RemovedAgentKeys(cfg *TeamConfig) []string
RemovedAgentKeys returns the removed integration keys a team config still sets, in stable order, so a renderer can name them.
Unlike AgentConfigWarnings this is not once-per-process: a TUI notice renders from state rather than as a side effect, and it must survive a redraw.
func UserConfigDir ¶
func UserConfigDir() string
UserConfigDir returns the path to the ~/.spec/ directory.
func UserConfigPath ¶
func UserConfigPath() string
UserConfigPath returns the path to ~/.spec/config.yaml.
func WriteUserConfig ¶
func WriteUserConfig(path string, cfg *UserConfig) error
WriteUserConfig writes a user config to disk.
Types ¶
type AgentAuthoringConfig ¶ added in v0.44.0
type AgentAuthoringConfig struct {
// Transitions allows spec_advance / spec_revert in agent sessions. When
// false (default) those tools are absent from tools/list entirely, which is
// self-documenting: a missing tool beats one that fails at call time.
Transitions bool `yaml:"transitions,omitempty"`
}
AgentAuthoringConfig tiers agent authority over spec content. The authoring tier (section reads and writes) is always available in an agent session and needs no preference: it is what makes the port useful, and every write is recoverable from the specs-repo diff. Stage transitions are separate because they are not symmetric with writes — they fire the pipeline's configured effects (Jira status sync, Slack posts) and move work through a human review pipeline.
type AutoAdvanceConfig ¶
type AutoAdvanceConfig struct {
// Enabled allows explicitly disabling auto-advance even if When is set.
Enabled *bool `yaml:"enabled,omitempty"`
// When is an expression that triggers auto-advance when true.
// Example: "prs.all_approved and prs.threads_resolved"
When string `yaml:"when,omitempty"`
// Notify lists targets to notify on auto-advance.
// Example: ["author", "next_owner"]
Notify []string `yaml:"notify,omitempty"`
// QuietHours prevents auto-advance during specified hours.
// Format: "HH:MM-HH:MM" in local timezone.
// Example: "22:00-08:00"
QuietHours string `yaml:"quiet_hours,omitempty"`
// RequireApproval requires a specific role to have approved (e.g., "tl").
RequireApproval string `yaml:"require_approval,omitempty"`
// ExcludeLabels prevents auto-advance for specs with these labels.
ExcludeLabels []string `yaml:"exclude_labels,omitempty"`
}
AutoAdvanceConfig configures automatic stage advancement.
func (*AutoAdvanceConfig) IsEnabled ¶
func (a *AutoAdvanceConfig) IsEnabled() bool
IsEnabled returns whether auto-advance is enabled. Defaults to true if When is set and Enabled is not explicitly false.
type BlockedConfig ¶ added in v0.22.1
type BlockedConfig struct {
// VisibleTo lists roles that may see the BLOCKED section. Empty = all roles.
VisibleTo []string `yaml:"visible_to,omitempty"`
// Scope filters which blocked specs appear: "all" (default), "involved",
// or "owning_role".
Scope string `yaml:"scope,omitempty"`
}
BlockedConfig configures the dashboard BLOCKED section.
func (BlockedConfig) EffectiveScope ¶ added in v0.22.1
func (b BlockedConfig) EffectiveScope() string
EffectiveScope returns the configured blocked scope, defaulting to "all".
func (BlockedConfig) RoleCanSee ¶ added in v0.22.1
func (b BlockedConfig) RoleCanSee(role string) bool
RoleCanSee reports whether a role may see the BLOCKED section at all. An empty VisibleTo list means every role can (back-compat).
type BountyConfig ¶ added in v0.45.0
type BountyConfig struct {
// Enabled turns bounties on. Defaults to false so an unconfigured team
// sees no bounty surface at all.
Enabled bool `yaml:"enabled,omitempty"`
// GrantableBy lists the roles allowed to grant and clear bounties.
// Defaults to ["tl", "pm"].
GrantableBy []string `yaml:"grantable_by,omitempty"`
// MaxActive caps how many specs may carry an unearned bounty at once.
// Defaults to DefaultBountyMaxActive. Scarcity is the whole point: past
// the cap, granting fails until the granter clears one.
MaxActive int `yaml:"max_active,omitempty"`
// RequireReason forces a written reason on every grant. Defaults to true —
// the reason is the prioritisation message, not decoration. A pointer so
// an explicit `false` is distinguishable from an unset field.
RequireReason *bool `yaml:"require_reason,omitempty"`
// Shimmer animates the bounty marker in the TUI. Defaults to true; set
// false for a static (but still shaded) marker.
Shimmer *bool `yaml:"shimmer,omitempty"`
// Finish selects the marker's metal: "gold" (default), "platinum", or
// "prismatic". It changes only the three tones the marker is shaded with.
Finish string `yaml:"finish,omitempty"`
}
BountyConfig configures spec bounties: a scarce, role-gated marker that invites an engineer to claim a spec, and a durable record of who finished one. Absent or disabled means no bounty UI and no bounty commands.
func (*BountyConfig) Cap ¶ added in v0.45.0
func (b *BountyConfig) Cap() int
Cap returns the maximum number of concurrently active bounties.
func (*BountyConfig) GrantableRoles ¶ added in v0.45.0
func (b *BountyConfig) GrantableRoles() []string
GrantableRoles returns the roles allowed to grant, or the default list.
func (*BountyConfig) IsEnabled ¶ added in v0.45.0
func (b *BountyConfig) IsEnabled() bool
IsEnabled reports whether bounties are configured and turned on.
func (*BountyConfig) IsRoleAllowed ¶ added in v0.45.0
func (b *BountyConfig) IsRoleAllowed(role string) bool
IsRoleAllowed reports whether role may grant or clear a bounty.
func (*BountyConfig) MetalFinish ¶ added in v0.45.0
func (b *BountyConfig) MetalFinish() BountyFinish
MetalFinish returns the configured finish, falling back to gold for an unset or unrecognised value (lint reports the latter; rendering must never fail).
func (*BountyConfig) ReasonRequired ¶ added in v0.45.0
func (b *BountyConfig) ReasonRequired() bool
ReasonRequired reports whether a grant must carry a reason (default true).
func (*BountyConfig) ShimmerEnabled ¶ added in v0.45.0
func (b *BountyConfig) ShimmerEnabled() bool
ShimmerEnabled reports whether the TUI marker animates (default true).
type BountyFinish ¶ added in v0.45.0
type BountyFinish string
BountyFinish names the metal the bounty marker is shaded with. The value is resolved and validated in config so the TUI only ever maps a known finish to a palette.
const ( // BountyFinishGold is warm and legible on every palette — the default. BountyFinishGold BountyFinish = "gold" // BountyFinishPlatinum is a cool, understated white metal. Deliberately // quiet; on most themes it reads close to bright primary text. BountyFinishPlatinum BountyFinish = "platinum" // BountyFinishPrismatic is a near-white body whose travelling highlight // rotates through hue, mimicking the dispersion ("fire") of a cut stone. BountyFinishPrismatic BountyFinish = "prismatic" )
Supported bounty finishes.
func ParseBountyFinish ¶ added in v0.45.0
func ParseBountyFinish(name string) (BountyFinish, bool)
ParseBountyFinish resolves a configured finish name, reporting whether it is recognised. An empty value resolves to the default rather than an error, so an omitted key is not a failure.
type BuildConfig ¶ added in v0.16.0
type BuildConfig struct {
// MaxParallel bounds how many ready nodes the orchestrator fans out at
// once. Surfaced to the agent via the DAG resource. Defaults to 4.
MaxParallel int `yaml:"max_parallel,omitempty"`
// Router selects the skill-routing model handed to the build engine:
// "registry" (default) routes per-node from .agents/skills/registry.yaml;
// "none" routes nothing and lets the harness discover skills. Empty = default.
Router string `yaml:"router,omitempty"`
// Strategy selects the VCS/review workflow: "stacked-draft-pr" (default)
// stacks a draft PR per node; "none" keeps work on local branches with no
// finishing tools. Empty = default.
Strategy string `yaml:"strategy,omitempty"`
}
BuildConfig tunes the build engine's DAG orchestration.
func (BuildConfig) GetMaxParallel ¶ added in v0.16.0
func (b BuildConfig) GetMaxParallel() int
GetMaxParallel returns the configured fan-out bound or the default.
type DashboardConfig ¶
type DashboardConfig struct {
StaleThreshold string `yaml:"stale_threshold"`
RefreshTTL int `yaml:"refresh_ttl"`
Blocked BlockedConfig `yaml:"blocked,omitempty"`
Urgency UrgencyConfig `yaml:"urgency,omitempty"`
Review ReviewConfig `yaml:"review,omitempty"`
}
DashboardConfig defines dashboard behaviour.
func (DashboardConfig) EasingCurve ¶ added in v0.30.0
func (d DashboardConfig) EasingCurve() urgency.Curve
EasingCurve resolves the configured easing name to an urgency.Curve, defaulting to ease-in when unset or unrecognised.
func (DashboardConfig) ReviewWindow ¶ added in v0.30.0
func (d DashboardConfig) ReviewWindow() (window time.Duration, ok bool)
ReviewWindow parses the REVIEW staleness window. ok is false when no window is configured (empty, "none", "0", or unparseable), meaning REVIEW rows are never stale.
type DeployConfig ¶
type DeployConfig struct {
Provider string `yaml:"provider"`
Environments []Environment `yaml:"environments"`
}
DeployConfig holds deployment provider and environments.
type Diagnostic ¶ added in v0.23.0
type Diagnostic struct {
File string `json:"file"`
Line int `json:"line"`
Column int `json:"column,omitempty"`
Severity Severity `json:"severity"`
Field string `json:"field,omitempty"`
Message string `json:"message"`
Suggestion string `json:"suggestion,omitempty"`
}
Diagnostic is a single line-precise lint finding. Line and Column are 1-based; Column is 0 when only a line is known.
type DoScope ¶ added in v0.22.1
type DoScope string
DoScope controls who sees specs at a stage in their dashboard DO section.
const ( // DoScopeRole shows the spec to anyone whose role owns the stage. Default. DoScopeRole DoScope = "role" // DoScopeAssignee shows the spec to its assignee(s) only; unassigned specs // fall back to the whole owning role when the stage is claimable. DoScopeAssignee DoScope = "assignee" // DoScopeAuthor shows the spec to its author only. DoScopeAuthor DoScope = "author" // DoScopeNone hides the spec from DO entirely (pipeline view only). DoScopeNone DoScope = "none" )
type EffectConfig ¶
type EffectConfig struct {
// Notify sends a notification. Can be a string (target) or NotifyEffect.
Notify *NotifyEffect `yaml:"notify,omitempty"`
// Sync triggers document sync ("outbound" or "inbound").
Sync string `yaml:"sync,omitempty"`
// UpdatePM updates the PM tool (Jira, Linear, etc.).
UpdatePM *UpdatePMEffect `yaml:"update_pm,omitempty"`
// LogDecision adds an entry to the decision log.
LogDecision string `yaml:"log_decision,omitempty"`
// Increment increments a frontmatter counter (e.g., "revert_count").
Increment string `yaml:"increment,omitempty"`
// Webhook calls an external URL.
Webhook *WebhookEffect `yaml:"webhook,omitempty"`
// Archive moves the spec to archive/.
Archive bool `yaml:"archive,omitempty"`
// Trigger invokes a named workflow or action.
Trigger string `yaml:"trigger,omitempty"`
// When is an expression that must be true for this effect to run.
When string `yaml:"when,omitempty"`
}
EffectConfig defines a side effect for stage transitions.
type Environment ¶
type Environment struct {
Name string `yaml:"name"`
Auto bool `yaml:"auto"`
Gate string `yaml:"gate,omitempty"`
}
Environment defines a deployment target.
type FastTrackConfig ¶
type FastTrackConfig struct {
// Enabled allows fast-track bug fixes. Defaults to false.
Enabled bool `yaml:"enabled,omitempty"`
// AllowedRoles lists roles that can create fast-track specs.
// Defaults to ["engineer", "tl"].
AllowedRoles []string `yaml:"allowed_roles,omitempty"`
// MaxDuration is the maximum time before escalation (e.g., "2d", "48h").
// If exceeded, notifies TL and/or PM.
MaxDuration string `yaml:"max_duration,omitempty"`
// RequireLabels requires fast-track specs to have specific labels (e.g., ["bug", "hotfix"]).
RequireLabels []string `yaml:"require_labels,omitempty"`
}
FastTrackConfig configures the `spec fix` fast-track workflow.
func (*FastTrackConfig) GetAllowedRoles ¶
func (f *FastTrackConfig) GetAllowedRoles() []string
GetAllowedRoles returns allowed roles or default ["engineer", "tl"].
func (*FastTrackConfig) IsEnabled ¶
func (f *FastTrackConfig) IsEnabled() bool
IsEnabled returns whether fast-track is enabled.
func (*FastTrackConfig) IsRoleAllowed ¶
func (f *FastTrackConfig) IsRoleAllowed(role string) bool
IsRoleAllowed checks if a role can create fast-track specs.
type FrontmatterDefaults ¶ added in v0.37.0
type FrontmatterDefaults []KV
FrontmatterDefaults is an ordered list of key/value pairs parsed from a YAML mapping, preserving the config's declaration order.
func (*FrontmatterDefaults) UnmarshalYAML ¶ added in v0.37.0
func (f *FrontmatterDefaults) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML parses a YAML mapping into an ordered slice of KV pairs, preserving key order so seeded frontmatter keys land deterministically.
type GateConfig ¶
type GateConfig struct {
// Simple gate types (mutually exclusive with Expr)
SectionNotEmpty string `yaml:"section_not_empty,omitempty"`
SectionComplete string `yaml:"section_complete,omitempty"` // Deprecated: use SectionNotEmpty
PRStackExists *bool `yaml:"pr_stack_exists,omitempty"` // Deprecated: use StepsExists
StepsExists *bool `yaml:"steps_exists,omitempty"` // Build plan has at least one step
PRsApproved *bool `yaml:"prs_approved,omitempty"`
ReviewApproved *bool `yaml:"review_approved,omitempty"` // Technical plan review is approved
// ChildrenComplete passes iff the spec has at least one deliverable slice
// and every slice is in a terminal stage. A childless spec is false, never
// vacuously true, so composing it under `any:` beside a delivery gate can
// only ever relax an initiative — never an ordinary spec.
ChildrenComplete *bool `yaml:"children_complete,omitempty"`
Duration string `yaml:"duration,omitempty"`
LinkExists *LinkExistsGate `yaml:"link_exists,omitempty"`
// Expression gate
Expr string `yaml:"expr,omitempty"`
Message string `yaml:"message,omitempty"`
// Logical operators (contain nested gates)
All []GateConfig `yaml:"all,omitempty"`
Any []GateConfig `yaml:"any,omitempty"`
Not *GateConfig `yaml:"not,omitempty"`
}
GateConfig defines a gate condition for stage advancement.
func (GateConfig) GetSectionNotEmpty ¶
func (g GateConfig) GetSectionNotEmpty() string
GetSectionNotEmpty returns the section slug for section_not_empty or section_complete gates.
func (GateConfig) HasReviewApproved ¶
func (g GateConfig) HasReviewApproved() bool
HasReviewApproved returns true if ReviewApproved gate is set.
func (GateConfig) HasStepsExists ¶
func (g GateConfig) HasStepsExists() bool
HasStepsExists returns true if either StepsExists or legacy PRStackExists is set.
func (GateConfig) IsSimple ¶
func (g GateConfig) IsSimple() bool
IsSimple returns true if this is a simple (non-logical) gate.
func (GateConfig) Type ¶
func (g GateConfig) Type() string
Type returns the gate type as a string for display.
func (GateConfig) Value ¶
func (g GateConfig) Value() string
Value returns the gate's primary value as a string for display.
type GenerateConfig ¶ added in v0.44.0
type GenerateConfig struct {
// Model is passed through verbatim in the provider's own spelling. spec does
// not translate model names; `spec agent check` reports which model actually
// answered, which is how a wrong spelling surfaces.
Model string `yaml:"model,omitempty"`
// MaxTokens caps the response. Honoured by completion-API providers only —
// neither `claude -p` nor `pi -p` exposes a token cap, so it is inert for
// harness providers and reported as such by lint and `spec agent check`.
MaxTokens int `yaml:"max_tokens,omitempty"`
// BaseURL is the OpenAI-compatible endpoint. Required for the generic
// openai-compatible provider; vendor presets supply a default.
BaseURL string `yaml:"base_url,omitempty"`
// Token is an optional bearer credential for gateways that require one.
// Write it as ${SPEC_LLM_TOKEN}: see tokenSource for why.
Token string `yaml:"token,omitempty"`
// Timeout bounds a single completion (e.g. "120s"). Empty uses the adapter
// default, which is deliberately generous because local models are slow.
Timeout string `yaml:"timeout,omitempty"`
// contains filtered or unexported fields
}
GenerateConfig holds completion-plane settings for an agent provider.
It is an explicit struct rather than another Extra key because a nested YAML mapping cannot survive ProviderConfig's flattening unmarshal: it would be stringified into Extra as "map[model:x ...]".
func (GenerateConfig) IsZero ¶ added in v0.44.0
func (g GenerateConfig) IsZero() bool
IsZero reports whether any completion setting is present, so marshalling can omit an empty generate block entirely.
func (GenerateConfig) TokenSource ¶ added in v0.44.0
func (g GenerateConfig) TokenSource() string
TokenSource returns the literal spelling of the token as written in config, which is the env-var reference when one was used. Empty when the token was absent or written literally.
type IntakeConfig ¶
type IntakeConfig struct {
Sources []IntakeSource `yaml:"sources"`
}
IntakeConfig holds intake source definitions.
type IntakeSource ¶
type IntakeSource struct {
Provider string `yaml:"provider"`
AutoCreate bool `yaml:"auto_create"`
Filter string `yaml:"filter,omitempty"`
Channel string `yaml:"channel,omitempty"`
Trigger string `yaml:"trigger,omitempty"`
Token string `yaml:"token,omitempty"`
}
IntakeSource defines an external intake source.
type IntegrationsConfig ¶
type IntegrationsConfig struct {
Comms ProviderConfig `yaml:"comms"`
PM ProviderConfig `yaml:"pm"`
Docs ProviderConfig `yaml:"docs"`
Repo ProviderConfig `yaml:"repo"`
Design ProviderConfig `yaml:"design"`
Deploy DeployConfig `yaml:"deploy"`
Intake IntakeConfig `yaml:"intake"`
}
IntegrationsConfig holds all integration provider configs.
The agent is deliberately absent: a coding harness and its auth are personal tools, so `agent:` lives only in ~/.spec/config.yaml (see UserConfig.Agent). Shared agent-adjacent *policy* (build.router, build.strategy) stays in team config, because policy is a team concern even though the harness is not.
type JiraConfig ¶ added in v0.22.1
type JiraConfig struct {
BaseURL string
Email string
Token string
ProjectKey string
// BoardID scopes board analytics; 0 means unset.
BoardID int
// TeamID is the Jira Team field value (Advanced Roadmaps / Plans).
TeamID string
EpicIssueType string
StoryIssueType string
// TaskIssueType is the issue type for a spec that is a deliverable slice of
// an initiative. Defaults to "Task".
TaskIssueType string
// Fields maps logical field names (epic_name, team, sprint, story_points)
// to instance-specific custom-field ids (e.g. customfield_10011).
Fields map[string]string
// Labels are applied to every spec-created issue; Components likewise.
Labels []string
Components []string
// SyncStories opts into creating Jira stories from build steps.
SyncStories bool
// StatusMap maps spec pipeline stage names to Jira status names. A stage
// absent from the map is a no-op for status sync.
StatusMap map[string]string
RequestTimeout time.Duration
}
JiraConfig is the typed Jira PM configuration parsed from the generic ProviderConfig. It binds a spec workspace to a specific project, board, and team, and carries the custom-field ids and status map the integration needs to land issues where the board's analytics expect them.
Every field is explicit: custom-field ids vary per Jira instance and must never be guessed (see docs/JIRA_HARDENING_PLAN.md §P1).
func (JiraConfig) Field ¶ added in v0.22.1
func (j JiraConfig) Field(name string) string
Field returns the configured custom-field id for a logical name, or "".
func (JiraConfig) IsComplete ¶ added in v0.22.1
func (j JiraConfig) IsComplete() bool
IsComplete reports whether the minimum fields required to talk to Jira are present. Missing required fields degrade the integration to a noop.
func (JiraConfig) MappedStatus ¶ added in v0.22.1
func (j JiraConfig) MappedStatus(stage string) (string, bool)
MappedStatus returns the Jira status mapped to a spec stage and whether a mapping exists. Lookups are case-insensitive on the stage name.
type KV ¶ added in v0.37.0
KV is an ordered key/value pair. It mirrors markdown.KV without importing the markdown package (config must not depend on internal/markdown), so callers convert at the boundary.
type LinkExistsGate ¶
type LinkExistsGate struct {
Section string `yaml:"section"`
Type string `yaml:"type,omitempty"` // e.g., "figma", "github"
}
LinkExistsGate checks for a link in a specific section.
func (*LinkExistsGate) UnmarshalYAML ¶ added in v0.4.1
func (g *LinkExistsGate) UnmarshalYAML(unmarshal func(interface{}) error) error
UnmarshalYAML supports both string and object formats:
link_exists: pr # simple string
link_exists: { section: pr } # object form
link_exists: { section: pr, type: github }
type LintResult ¶ added in v0.23.0
type LintResult struct {
File string `json:"file"`
Diagnostics []Diagnostic `json:"diagnostics"`
}
LintResult is the full outcome of linting one config file.
func LintTeamConfigFile ¶ added in v0.23.0
func LintTeamConfigFile(path string) (LintResult, error)
LintTeamConfigFile reads and lints a team config file at path. A read or parse failure is itself returned as an error-severity diagnostic so the caller always gets a structured result.
func LintUserConfigFile ¶ added in v0.44.0
func LintUserConfigFile(path string) (LintResult, error)
LintUserConfigFile reports defects in a personal config file. It exists so the renamed preference key and inert completion settings surface in the command whose job is to report config problems.
func LintUserIdentitiesFile ¶ added in v0.25.0
func LintUserIdentitiesFile(path string, teamCfg *TeamConfig) (LintResult, error)
LintUserIdentitiesFile validates the per-provider identity map in a user config file against the providers a team config actually configures. It is advisory only — every finding is a warning, never an error — because a stale or mis-keyed identity degrades gracefully (the canonical handle stands in).
teamCfg may be nil (no joined team), in which case there is nothing to cross-reference and the result is empty.
func (LintResult) HasErrors ¶ added in v0.23.0
func (r LintResult) HasErrors() bool
HasErrors reports whether any diagnostic is an error (blocks exit 0).
type NotifyEffect ¶
type NotifyEffect struct {
// Target is who to notify (e.g., "next_owner", "tl", "#channel", "@user").
Target string `yaml:"target,omitempty"`
// Targets allows multiple notification targets.
Targets []string `yaml:"targets,omitempty"`
// Channel overrides the default channel.
Channel string `yaml:"channel,omitempty"`
// Template is the notification template name.
Template string `yaml:"template,omitempty"`
}
NotifyEffect configures a notification.
func (*NotifyEffect) UnmarshalYAML ¶
func (n *NotifyEffect) UnmarshalYAML(unmarshal func(interface{}) error) error
UnmarshalYAML allows notify to be a string or object.
type Owners ¶
type Owners []string
Owners represents one or more owner roles for a pipeline stage. In YAML, it can be specified as a single string or an array:
owner: pm # single owner owner: [pm, tl] # multiple owners
func (*Owners) UnmarshalYAML ¶
UnmarshalYAML allows owner to be a string or array in YAML.
type PassiveAwarenessConfig ¶
type PassiveAwarenessConfig struct {
// Show whitelists item types to display. If empty, shows all.
// Valid types: review_requests, spec_owned, mentions, triage, fyi, blocked
Show []string `yaml:"show,omitempty"`
// Hide blacklists item types to suppress.
Hide []string `yaml:"hide,omitempty"`
// DuringBuild shows awareness during `spec do` and `spec build`.
// Defaults to false to avoid interrupting flow state.
DuringBuild bool `yaml:"during_build,omitempty"`
// DismissDuration is how long dismissed items stay hidden.
// Defaults to "2h". Valid formats: "30m", "2h", "1d".
DismissDuration string `yaml:"dismiss_duration,omitempty"`
}
PassiveAwarenessConfig controls what pending items are shown in the awareness line on every spec command.
type PipelineConfig ¶
type PipelineConfig struct {
// Preset is the name of a built-in pipeline preset (e.g., "minimal", "product").
// If set, the preset's stages are used as the base configuration.
Preset string `yaml:"preset,omitempty"`
// Skip lists stage names to remove from the preset.
// Only meaningful when Preset is set.
Skip []string `yaml:"skip,omitempty"`
// Stages defines the pipeline stages. When Preset is set, these override
// or extend the preset's stages. When Preset is empty, these are the
// complete stage definitions.
Stages []StageConfig `yaml:"stages,omitempty"`
}
PipelineConfig defines the configurable pipeline stages.
func DefaultPipeline ¶
func DefaultPipeline() PipelineConfig
DefaultPipeline returns the default pipeline configuration when none is specified. This is the "product" preset - a full lifecycle pipeline.
func EffectivePipeline ¶
func EffectivePipeline(tc *TeamConfig) PipelineConfig
EffectivePipeline returns the pipeline from team config, or default if empty.
It expands presets, applies Skip, and merges stage overrides via ResolveStages, so callers that read Stages directly (the TUI pipeline view, dashboard, list/status/assign, etc.) see the same final stage list as internal/pipeline.Resolve. Without this, a team config that sets only preset: minimal would silently fall back to the full default pipeline.
func (PipelineConfig) IsValidReversion ¶
func (p PipelineConfig) IsValidReversion(from, to string) bool
IsValidReversion returns true if reverting from `from` to `to` is valid (i.e., `to` comes before `from` in the pipeline).
func (PipelineConfig) IsValidTransition ¶
func (p PipelineConfig) IsValidTransition(from, to string) bool
IsValidTransition returns true if transitioning from `from` to `to` is valid (i.e., `to` comes after `from` in the pipeline).
func (PipelineConfig) NextStage ¶
func (p PipelineConfig) NextStage(current string) (string, bool)
NextStage returns the next stage after the given one.
func (PipelineConfig) RequiredStages ¶
func (p PipelineConfig) RequiredStages() []StageConfig
RequiredStages returns non-optional stages.
func (PipelineConfig) StageByName ¶
func (p PipelineConfig) StageByName(name string) *StageConfig
StageByName returns the stage config with the given name, or nil.
func (PipelineConfig) StageIndex ¶
func (p PipelineConfig) StageIndex(name string) int
StageIndex returns the index of the stage with the given name, or -1.
func (PipelineConfig) StageNames ¶
func (p PipelineConfig) StageNames() []string
StageNames returns the names of all stages in order.
type PreferencesConfig ¶
type PreferencesConfig struct {
Editor string `yaml:"editor"`
DashboardSections []string `yaml:"dashboard_sections"`
StandupAutoPost bool `yaml:"standup_auto_post"`
// AgentDrafts gates agent-assisted drafting. Renamed from ai_drafts, which
// gated on an integration this release deletes; lint reports the old
// spelling with its replacement.
AgentDrafts *bool `yaml:"agent_drafts,omitempty"`
// AgentAuthoring tiers what an agent session may do through the MCP
// authoring port. Reads and section writes are always available; stage
// transitions are opt-in because they fire team-visible pipeline effects.
AgentAuthoring AgentAuthoringConfig `yaml:"agent_authoring,omitempty"`
// Theme sets the TUI colour theme.
// Valid values: auto (default), catppuccin-mocha, catppuccin-latte,
// catppuccin-macchiato, catppuccin-frappe, gruvbox-dark, dracula,
// tokyo-night, nord, solarized-dark, solarized-light, rose-pine,
// kanagawa, everforest-dark, everforest-light, github-dark, github-light,
// ayu-mirage, ayu-light, modus-vivendi, modus-operandi, graphite.
Theme string `yaml:"theme,omitempty"`
// RefreshInterval sets the TUI auto-refresh period (e.g. "30s", "1m").
// Defaults to 30s.
RefreshInterval string `yaml:"refresh_interval,omitempty"`
// Mouse enables mouse support in the TUI (click tabs, click items).
// Defaults to false.
Mouse bool `yaml:"mouse,omitempty"`
// Multiplexer specifies the terminal multiplexer for cross-repo navigation.
// Valid values: tmux, zellij, wezterm, iterm2, none
// If empty or "none", falls back to manual navigation prompts.
Multiplexer string `yaml:"multiplexer,omitempty"`
// AutoPull automatically pulls stale specs when running `spec do`.
// If false, prompts the user before pulling.
AutoPull bool `yaml:"auto_pull,omitempty"`
// Defaults to true. Set to false for manual navigation.
AutoNavigate *bool `yaml:"auto_navigate,omitempty"`
// PassiveAwareness configures the passive awareness line shown on commands.
PassiveAwareness *PassiveAwarenessConfig `yaml:"passive_awareness,omitempty"`
}
PreferencesConfig holds personal preferences.
func (PreferencesConfig) AgentDraftsEnabled ¶ added in v0.44.0
func (p PreferencesConfig) AgentDraftsEnabled() bool
AgentDraftsEnabled returns whether agent-assisted drafting is enabled. Defaults to true if not explicitly set: an agent that is configured should work without a second opt-in, and skipping agent setup leaves the provider unset so nothing is offered anyway.
func (PreferencesConfig) AutoNavigateEnabled ¶
func (p PreferencesConfig) AutoNavigateEnabled() bool
AutoNavigateEnabled returns whether auto-navigation to new repos is enabled. Defaults to true if not explicitly set.
func (PreferencesConfig) GetDismissDuration ¶
func (p PreferencesConfig) GetDismissDuration() string
GetDismissDuration returns the dismiss duration or the default "2h".
func (PreferencesConfig) ShowPassiveAwarenessDuringBuild ¶
func (p PreferencesConfig) ShowPassiveAwarenessDuringBuild() bool
ShowPassiveAwarenessDuringBuild returns whether to show awareness during builds.
type PresetConfig ¶ added in v0.38.1
type PresetConfig struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
Features []string `yaml:"features"`
Stages []StageConfig `yaml:"stages"`
}
PresetConfig holds a preset pipeline definition.
func LoadPreset ¶ added in v0.38.1
func LoadPreset(name string) (*PresetConfig, error)
LoadPreset returns the preset configuration for the given name.
type ProviderConfig ¶
type ProviderConfig struct {
Provider string `yaml:"provider"`
Extra map[string]string `yaml:"-"`
// Generate holds completion-plane settings. Only meaningful for the agent.
Generate GenerateConfig `yaml:"-"`
// contains filtered or unexported fields
}
ProviderConfig is a generic integration config with a provider name and extra fields.
func (ProviderConfig) Get ¶
func (p ProviderConfig) Get(key string) string
Get returns an extra config value by key.
func (ProviderConfig) Jira ¶ added in v0.22.1
func (p ProviderConfig) Jira() JiraConfig
Jira parses the generic PM ProviderConfig into a typed JiraConfig. Scalar keys come from the flattened Extra map; nested keys (fields, status_map, labels, components) are read from the preserved raw YAML so structured values survive (Extra stringifies them).
func (ProviderConfig) MarshalYAML ¶ added in v0.15.0
func (p ProviderConfig) MarshalYAML() (interface{}, error)
MarshalYAML emits provider plus all extra settings so a ProviderConfig round-trips through WriteUserConfig (e.g. a TUI settings save) without dropping keys like `command` or `skill`, which live in Extra (yaml:"-").
The generate block is emitted as a nested mapping, and its token is written back as the original ${VAR} reference so a resolved credential is never persisted to disk.
func (*ProviderConfig) SetTokenSource ¶ added in v0.44.0
func (p *ProviderConfig) SetTokenSource(literal string)
SetTokenSource records the literal pre-interpolation spelling of the token so a later marshal re-emits the reference instead of the resolved secret. The loader calls this after parsing, because ${VAR} expansion happens on the raw bytes before YAML sees them.
func (*ProviderConfig) UnmarshalYAML ¶
func (p *ProviderConfig) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML captures all keys into raw and extracts provider + extras.
The `generate` key is decoded into the typed Generate field and excluded from Extra: flattening it with fmt.Sprintf would turn a nested mapping into the string "map[model:x]", which no caller can use.
type ResolvedConfig ¶
type ResolvedConfig struct {
Team *TeamConfig
User *UserConfig
// TeamConfigPath is the path to the team config file, if found.
TeamConfigPath string
// UserConfigPath is the path to the user config file.
UserConfigPath string
// SpecsRepoDir is the local path to the specs/ sub-directory within
// the specs repo clone. All spec, triage, and archive content lives here.
SpecsRepoDir string
}
ResolvedConfig holds the fully resolved team + user configuration.
func Resolve ¶
func Resolve() (*ResolvedConfig, error)
Resolve loads the full configuration from all sources. Resolution chain: cwd → repo root → specs repo clone → user config.
func (*ResolvedConfig) AgentDraftsEnabled ¶ added in v0.44.0
func (r *ResolvedConfig) AgentDraftsEnabled() bool
AgentDraftsEnabled returns whether agent-assisted drafting is enabled for the user: an agent must be configured (personal config) and the preference must not be switched off.
func (*ResolvedConfig) AgentTransitionsAllowed ¶ added in v0.44.0
func (r *ResolvedConfig) AgentTransitionsAllowed() bool
AgentTransitionsAllowed reports whether agent sessions may drive stage transitions through the MCP authoring port. Off by default: section writes are recoverable from the specs-repo diff, but a transition fires team-visible pipeline effects, so it needs an explicit opt-in.
func (*ResolvedConfig) AutoPushEnabled ¶ added in v0.26.0
func (r *ResolvedConfig) AutoPushEnabled() bool
AutoPushEnabled reports whether automatic publishing is active for async surfaces (TUI, MCP). Only AutoPushOff disables it; AutoPushPrompt is treated as enabled because those surfaces cannot prompt.
func (*ResolvedConfig) AutoPushPolicy ¶ added in v0.26.0
func (r *ResolvedConfig) AutoPushPolicy() string
AutoPushPolicy returns the effective auto-push policy, defaulting to AutoPushAuto when unset or no team config is present.
func (*ResolvedConfig) Bounties ¶ added in v0.45.0
func (r *ResolvedConfig) Bounties() *BountyConfig
Bounties returns the effective bounty config, never nil, so callers can read defaults without a presence check.
func (*ResolvedConfig) BountyEnabled ¶ added in v0.45.0
func (r *ResolvedConfig) BountyEnabled() bool
BountyEnabled reports whether the resolved team config has bounties on. It is nil-safe so read paths (dashboard, TUI, list) can call it unguarded.
func (*ResolvedConfig) CanonicalHandle ¶ added in v0.25.0
func (r *ResolvedConfig) CanonicalHandle() string
CanonicalHandle returns the user's spec-internal identity token, falling back to the display name when no handle is configured.
func (*ResolvedConfig) CycleLabel ¶
func (r *ResolvedConfig) CycleLabel() string
CycleLabel returns the current cycle label.
func (*ResolvedConfig) EffectiveAgentConfig ¶ added in v0.15.0
func (r *ResolvedConfig) EffectiveAgentConfig() ProviderConfig
EffectiveAgentConfig returns the coding-agent provider config, which comes solely from personal config (~/.spec/config.yaml `agent:`).
There is no team fallback: a harness and its auth are individual, so the team-default-plus-override precedence was a resolve path nobody needed. Shared agent-adjacent policy (build.router, build.strategy) still lives in team config.
func (*ResolvedConfig) HasAgent ¶ added in v0.44.0
func (r *ResolvedConfig) HasAgent() bool
HasAgent reports whether a usable agent provider is configured. Agent config is personal, so this deliberately does not consult team config — callers that used HasIntegration("agent") must use this instead or they silently report "no agent" for every user.
func (*ResolvedConfig) HasIntegration ¶
func (r *ResolvedConfig) HasIntegration(category string) bool
HasIntegration checks if a specific integration category has a non-empty provider.
func (*ResolvedConfig) IdentityForCategory ¶ added in v0.25.0
func (r *ResolvedConfig) IdentityForCategory(category string) string
IdentityForCategory resolves the handle to use for an integration category ("repo", "comms", "pm", "docs", "design", "deploy"): it maps the category to the team's configured provider, then resolves that provider's handle. Falls back to the canonical handle when the category has no provider or no mapping exists. "agent" is not a team category — see EffectiveAgentConfig.
func (*ResolvedConfig) IntegrationProvider ¶ added in v0.25.0
func (r *ResolvedConfig) IntegrationProvider(category string) string
IntegrationProvider returns the team's configured provider name for an integration category (e.g. "repo" -> "github"), or "" when no team config or category is set.
func (*ResolvedConfig) OwnerRole ¶
func (r *ResolvedConfig) OwnerRole(override string) string
OwnerRole returns the user's owner role, with optional override.
func (*ResolvedConfig) Pipeline ¶
func (r *ResolvedConfig) Pipeline() PipelineConfig
Pipeline returns the effective pipeline config.
func (*ResolvedConfig) ProviderHandle ¶ added in v0.25.0
func (r *ResolvedConfig) ProviderHandle(provider string) string
ProviderHandle returns the user's handle for a named integration provider (e.g. "github", "slack"), falling back to the canonical handle when the provider is unmapped. An empty or "none" provider yields the canonical handle.
func (*ResolvedConfig) SpecsRepoRoot ¶ added in v0.37.0
func (r *ResolvedConfig) SpecsRepoRoot() string
SpecsRepoRoot returns the local path to the specs repo clone root (the parent of the specs/ sub-directory), or "" when no specs repo is configured. Template files (templates/spec.md, templates/triage.md) are resolved relative to this root.
func (*ResolvedConfig) TeamName ¶
func (r *ResolvedConfig) TeamName() string
TeamName returns the team name.
func (*ResolvedConfig) UserHandle ¶
func (r *ResolvedConfig) UserHandle() string
UserHandle returns the configured spec-canonical handle. Retained as an alias of CanonicalHandle for callers that predate per-integration identity resolution; spec-internal identity (frontmatter, threads) uses this.
func (*ResolvedConfig) UserIdentities ¶ added in v0.25.0
func (r *ResolvedConfig) UserIdentities() []string
UserIdentities returns every identity the user is known by — the canonical handle, the display name, and every per-provider handle — de-duplicated. Identity-matching callers (dashboard scope, awareness) use this so a spec authored or assigned under any of the user's handles is recognised as theirs.
func (*ResolvedConfig) UserName ¶
func (r *ResolvedConfig) UserName() string
UserName returns the configured user name.
type ReviewConfig ¶ added in v0.30.0
type ReviewConfig struct {
// StaleAfter is the review-age window for the time-urgency gradient on
// REVIEW rows, measured from when the PR was opened. Accepts m/h/d/w units
// (e.g. "4h", "2d"). Empty, "none", or "0" (the default) means review rows
// are never coloured — the gradient is opt-in, with no global fallback.
StaleAfter string `yaml:"stale_after,omitempty"`
}
ReviewConfig tunes the REVIEW section of the dashboard.
type SpecsRepoConfig ¶
type SpecsRepoConfig struct {
Provider string `yaml:"provider"`
Owner string `yaml:"owner"`
Repo string `yaml:"repo"`
Branch string `yaml:"branch"`
Token string `yaml:"token"`
}
SpecsRepoConfig defines the specs repository location.
type StageConfig ¶
type StageConfig struct {
// Name is the stage identifier (lowercase, underscores allowed).
Name string `yaml:"name"`
// Owner is the role(s) that own this stage. Can be a single role
// or an array of roles in YAML.
Owner Owners `yaml:"owner,omitempty"`
// Dashboard controls how this stage's specs surface in the DO section.
Dashboard StageDashboardConfig `yaml:"dashboard,omitempty"`
// OwnerRole is the legacy field for backward compatibility.
//
// Deprecated: Use Owner instead.
OwnerRole string `yaml:"owner_role,omitempty"`
// Icon is an emoji displayed in pipeline views.
Icon string `yaml:"icon,omitempty"`
// Optional marks the stage as skippable in the pipeline flow.
Optional bool `yaml:"optional,omitempty"`
// SkipWhen is an expression that, when true, causes the stage to be
// automatically skipped during advancement.
SkipWhen string `yaml:"skip_when,omitempty"`
// StaleAfter is the dwell window for the time-urgency gradient: once a spec
// has spent this long in this stage, its dashboard/pipeline row reaches full
// urgency. Accepts m/h/d/w units (e.g. "30m", "48h", "5d", "2w"). Empty,
// "none", or "0" means the stage is never stale and shows no colouring —
// there is no global fallback window.
StaleAfter string `yaml:"stale_after,omitempty"`
// Gates are conditions that must be satisfied to advance from this stage.
Gates []GateConfig `yaml:"gates,omitempty"`
// Warnings are time-based alerts that don't block advancement.
Warnings []WarningConfig `yaml:"warnings,omitempty"`
// Transitions customizes advance and revert behavior.
Transitions TransitionsConfig `yaml:"transitions,omitempty"`
// OnEnter lists effects to execute when entering this stage.
OnEnter []EffectConfig `yaml:"on_enter,omitempty"`
// OnExit lists effects to execute when leaving this stage.
OnExit []EffectConfig `yaml:"on_exit,omitempty"`
// AutoArchive moves the spec to archive/ when entering this stage.
AutoArchive bool `yaml:"auto_archive,omitempty"`
// Review configures plan review requirements for this stage.
// Used primarily for the engineering stage to require technical plan approval.
Review *StageReviewConfig `yaml:"review,omitempty"`
// AutoAdvance configures automatic stage advancement when gates are satisfied.
AutoAdvance *AutoAdvanceConfig `yaml:"auto_advance,omitempty"`
}
StageConfig defines a single pipeline stage.
func ResolveStages ¶ added in v0.38.1
func ResolveStages(cfg PipelineConfig) ([]StageConfig, string, []string, error)
ResolveStages expands a PipelineConfig into its final ordered stage list, applying preset expansion, skip removal, and stage overrides. It returns the resolved stages, the preset name used (empty if none), the names of stages removed via Skip, and any error from preset lookup.
This is the single source of truth for stage resolution: both EffectivePipeline (for convenience access via ResolvedConfig.Pipeline) and internal/pipeline.Resolve (for the richer ResolvedPipeline with index and skip-when evaluation) call it, so every consumer sees the same stages regardless of whether a team config uses a preset, explicit stages, or both.
func (StageConfig) GetOwner ¶
func (s StageConfig) GetOwner() string
GetOwner returns the effective owner as a display string. For multiple owners, returns comma-separated list. Falls back to legacy OwnerRole if Owner is not set.
func (StageConfig) HasOwner ¶
func (s StageConfig) HasOwner(role string) bool
HasOwner returns true if role is an owner of this stage. Also returns true if no owners are defined (open stage) or if role is empty.
func (StageConfig) StaleWindow ¶ added in v0.30.0
func (s StageConfig) StaleWindow() (window time.Duration, ok bool)
StaleWindow parses StaleAfter into a duration. ok is false when the stage has no configured window (empty, "none", or "0", or an unparseable value), meaning the stage is never stale.
type StageDashboardConfig ¶ added in v0.22.1
type StageDashboardConfig struct {
// DoScope controls who sees specs at this stage in their DO section.
// One of: "role" (default), "assignee", "author", "none".
DoScope string `yaml:"do_scope,omitempty"`
// Claimable, when true (the default), surfaces unassigned specs to the
// whole owning role under assignee scope so they can be claimed. Set false
// to hide unassigned specs from everyone until explicitly assigned.
Claimable *bool `yaml:"claimable,omitempty"`
}
StageDashboardConfig configures how a stage's specs surface in the dashboard.
func (StageDashboardConfig) IsClaimable ¶ added in v0.22.1
func (d StageDashboardConfig) IsClaimable() bool
IsClaimable reports whether unassigned specs surface to the owning role under assignee scope. Defaults to true.
func (StageDashboardConfig) Scope ¶ added in v0.22.1
func (d StageDashboardConfig) Scope() DoScope
Scope returns the effective DO scope, defaulting to role when unset or invalid.
type StageReviewConfig ¶
type StageReviewConfig struct {
// Required indicates whether review is required to advance.
// Defaults to true when Review is present.
Required *bool `yaml:"required,omitempty"`
// Reviewers lists who can review (roles like "tl" or named users like "@mike").
// Special value "author" allows self-review.
Reviewers []string `yaml:"reviewers,omitempty"`
// MinApprovals is the minimum number of approvals required.
// Defaults to 1.
MinApprovals int `yaml:"min_approvals,omitempty"`
}
StageReviewConfig configures plan review requirements.
func (*StageReviewConfig) GetMinApprovals ¶
func (r *StageReviewConfig) GetMinApprovals() int
GetMinApprovals returns the minimum approvals or default of 1.
func (*StageReviewConfig) IsRequired ¶
func (r *StageReviewConfig) IsRequired() bool
IsRequired returns whether review is required. Defaults to true if not explicitly set.
type SyncConfig ¶
type SyncConfig struct {
OutboundOnAdvance bool `yaml:"outbound_on_advance"`
ConflictStrategy string `yaml:"conflict_strategy"`
// AutoPush governs whether local edits and comments are published to the
// specs repo automatically. One of AutoPushAuto, AutoPushPrompt, AutoPushOff.
AutoPush string `yaml:"auto_push"`
}
SyncConfig defines sync behaviour.
type TeamConfig ¶
type TeamConfig struct {
Version string `yaml:"version"`
Team struct {
Name string `yaml:"name"`
CycleLabel string `yaml:"cycle_label"`
} `yaml:"team"`
SpecsRepo SpecsRepoConfig `yaml:"specs_repo"`
Integrations IntegrationsConfig `yaml:"integrations"`
Sync SyncConfig `yaml:"sync"`
Archive struct {
Directory string `yaml:"directory"`
} `yaml:"archive"`
Dashboard DashboardConfig `yaml:"dashboard"`
Pipeline PipelineConfig `yaml:"pipeline"`
// FastTrack configures engineer self-service for small bug fixes.
FastTrack *FastTrackConfig `yaml:"fast_track,omitempty"`
// Bounty configures spec bounties: a scarce, role-gated pull signal on
// claimable work. Absent means bounties are off.
Bounty *BountyConfig `yaml:"bounty,omitempty"`
// Build configures the agentic build orchestration (DAG fan-out).
Build BuildConfig `yaml:"build,omitempty"`
// Templates configures custom spec/triage skeleton templates committed
// to the specs repo (SPEC-025). Empty falls back to embedded defaults.
Templates TemplatesConfig `yaml:"templates,omitempty"`
// contains filtered or unexported fields
}
TeamConfig represents the spec.config.yaml file committed to the specs repo.
func LoadTeamConfig ¶
func LoadTeamConfig(path string) (*TeamConfig, error)
LoadTeamConfig reads and parses a spec.config.yaml file.
func (*TeamConfig) UnmarshalYAML ¶ added in v0.44.0
func (c *TeamConfig) UnmarshalYAML(value *yaml.Node) error
UnmarshalYAML decodes a team config and records any removed integration keys still present, so resolve can warn and lint can error on them.
type TemplatesConfig ¶ added in v0.37.0
type TemplatesConfig struct {
SpecPath string `yaml:"spec,omitempty"`
TriagePath string `yaml:"triage,omitempty"`
FrontmatterDefaults FrontmatterDefaults `yaml:"frontmatter_defaults,omitempty"`
}
TemplatesConfig names the spec/triage template paths inside the specs repo and optional frontmatter defaults seeded into every scaffolded spec.
Paths default to the conventional locations (templates/spec.md, templates/triage.md) when left empty, so a team only commits the file to opt in — no config block required.
FrontmatterDefaults is an ordered list parsed from a YAML mapping so seeded keys land in config declaration order, keeping frontmatter diffs stable (no YAML round-trip). Computed scaffold fields (id, title, dates, …) always win: a default whose key already appears in the rendered frontmatter is skipped.
func (TemplatesConfig) EffectiveSpecPath ¶ added in v0.37.0
func (t TemplatesConfig) EffectiveSpecPath() string
EffectiveSpecPath returns the configured spec template path or the default.
func (TemplatesConfig) EffectiveTriagePath ¶ added in v0.37.0
func (t TemplatesConfig) EffectiveTriagePath() string
EffectiveTriagePath returns the configured triage template path or the default.
type TransitionConfig ¶
type TransitionConfig struct {
// To lists allowed target stages. Empty means default (next for advance,
// any previous for revert).
To []string `yaml:"to,omitempty"`
// Gates are additional conditions for this specific transition.
Gates []GateConfig `yaml:"gates,omitempty"`
// Require lists required fields (e.g., ["reason"] for reverts).
Require []string `yaml:"require,omitempty"`
// Effects are side effects to execute on transition.
Effects []EffectConfig `yaml:"effects,omitempty"`
}
TransitionConfig defines behavior for a specific transition type.
type TransitionsConfig ¶
type TransitionsConfig struct {
Advance TransitionConfig `yaml:"advance,omitempty"`
Revert TransitionConfig `yaml:"revert,omitempty"`
}
TransitionsConfig customizes stage transition behavior.
type UpdatePMEffect ¶
type UpdatePMEffect struct {
Status string `yaml:"status,omitempty"`
}
UpdatePMEffect configures PM tool updates.
type UrgencyConfig ¶ added in v0.30.0
type UrgencyConfig struct {
// Easing selects how the raw dwell fraction is shaped into colour intensity:
// "linear", "ease-in" (default), or "ease-in-strong".
Easing string `yaml:"easing,omitempty"`
}
UrgencyConfig tunes the time-urgency gradient shared by the dashboard DO section and the pipeline screen.
type UserConfig ¶
type UserConfig struct {
User struct {
OwnerRole string `yaml:"owner_role"`
Name string `yaml:"name"`
// Handle is the spec-canonical identity token — a stable, user-chosen
// name that identifies the person inside spec (frontmatter author and
// assignees, thread author, decision log). It never leaves spec, so it
// can be anything the user likes. It is also the universal fallback for
// any per-integration identity that is not explicitly mapped.
Handle string `yaml:"handle"`
// Identities maps an integration provider name (e.g. "github", "slack",
// "teams", "jira") to the user's handle on that service. A person's
// handle differs on every service, so adapter calls must receive the
// service-specific value, not the canonical handle. Optional and
// additive: an absent or partial map falls back to Handle, so existing
// configs behave identically.
Identities map[string]string `yaml:"identities,omitempty"`
} `yaml:"user"`
Preferences PreferencesConfig `yaml:"preferences"`
// Agent configures the coding harness and its completion plane. A harness
// and its auth are personal tools — teammates on one spec legitimately run
// different agents — so this is the ONLY place an agent is configured;
// integrations.agent was removed from team config.
Agent *ProviderConfig `yaml:"agent,omitempty"`
// Workspaces maps repo names to local filesystem paths.
// Used for cross-repo navigation in multi-repo build plans.
// Example: workspaces: { auth-service: ~/code/auth-service }
Workspaces map[string]string `yaml:"workspaces,omitempty"`
}
UserConfig represents the ~/.spec/config.yaml personal config file.
func LoadUserConfig ¶
func LoadUserConfig(path string) (*UserConfig, error)
LoadUserConfig reads and parses the user config file.
func LoadUserConfigWithDefaults ¶
func LoadUserConfigWithDefaults() (*UserConfig, string)
LoadUserConfigWithDefaults loads user config or returns defaults if file doesn't exist.
func (*UserConfig) GetWorkspacePath ¶
func (c *UserConfig) GetWorkspacePath(repoName string) string
GetWorkspacePath returns the local path for a repo, or empty string if not configured.
type WarningConfig ¶
type WarningConfig struct {
// After is the duration after which the warning triggers (e.g., "5d", "48h").
After string `yaml:"after"`
// Message is displayed when the warning is active.
Message string `yaml:"message"`
// Notify is the target to notify (e.g., "tl", "#channel").
Notify string `yaml:"notify,omitempty"`
}
WarningConfig defines a time-based warning for a stage.
type WebhookEffect ¶
type WebhookEffect struct {
URL string `yaml:"url"`
Method string `yaml:"method,omitempty"` // default: POST
Headers map[string]string `yaml:"headers,omitempty"`
Body map[string]string `yaml:"body,omitempty"`
Timeout string `yaml:"timeout,omitempty"` // default: 10s
}
WebhookEffect configures an external webhook call.