Documentation
¶
Index ¶
- Constants
- Variables
- func AlreadySubmittedAt(records []SubmissionRecord, head string) bool
- func AppendCriterion(path string, rec CriterionRecord) error
- func AppendEvidence(path string, record EvidenceRecord) error
- func AppendFile(path, data string) error
- func AppendOverride(path string, record OverrideRecord) error
- func AppendSubmission(path string, rec SubmissionRecord) error
- func AtomicWrite(path, data string) error
- func CanAdvanceStatus(from, to Status) bool
- func CommandNames() []string
- func CommitLink(remote, head string) string
- func CompleteTask(rawTasks []byte, taskID string, records map[string]EvidenceRecord) ([]byte, error)
- func ConfigDigest(config Config) string
- func ConsecutiveVerifyFails(evidence []EvidenceRecord, overrides []OverrideRecord, taskID string) int
- func CountSpecsWithBlock(root, key string) int
- func CriteriaPath(root, slug string) string
- func CurrentPassing(records []CriterionRecord, since time.Time) map[string]bool
- func DedupRolePrompts(prompts []string) []string
- func EscalatedCounts(evidence []EvidenceRecord, overrides []OverrideRecord, tasks []TaskRow, ...) map[string]int
- func EvidencePath(root, slug string) string
- func ExtractMemBlock(text, key string) string
- func FindRoot(start string) (string, error)
- func ForbiddenTool(name string) bool
- func HasPassingEvidence(records map[string]EvidenceRecord, taskID string) bool
- func HeadPinned(gitHead string) bool
- func IsEscalated(consecutiveFails, maxFails int) bool
- func ListSpecs(root string) []string
- func LoadConfig(paths ConfigPaths, env map[string]string) (Config, []Diagnostic)
- func LoadEvidence(path string) (map[string]EvidenceRecord, error)
- func MCPConfigSnippet(host, root, spec string) (string, error)
- func MCPHosts() []string
- func MergeAgents(existing, generated string) string
- func OverridePath(root, slug string) string
- func PRSummary(model ReportModel) string
- func PaletteDigest() string
- func ProgramPath(root string) string
- func ReadOrNull(path string) *string
- func RenderHistory(slug string, events []HistoryEvent) string
- func RenderHistoryJSON(events []HistoryEvent) (string, error)
- func RenderMemBlock(f MemFields) string
- func RenderMetrics(model ReportModel) string
- func RenderPRSummary(model ReportModel) string
- func RenderPrometheus(m PrometheusMetrics) string
- func RenderPromotion(block, slug string, count int, date string) string
- func RenderReviewScaffold(slug, head string, tasks []TaskRow) string
- func RenderStatus(model ReportModel) string
- func RenderTelemetry(slug string, report TelemetryReport) string
- func ReviewReportHead(raw string) string
- func ReviewReportPath(root, slug string) string
- func RewriteTaskStatusLine(raw []byte, id string, marker string) ([]byte, error)
- func RolePrompt(role string) string
- func SaveProgram(path string, program Program) error
- func SaveState(path string, state State) error
- func SaveStateCAS(path string, expectedRevision int64, state State) error
- func SerializeTasksMd(doc TasksMd) []byte
- func SortHistory(events []HistoryEvent)
- func SortedReportTaskIDs(model ReportModel) []string
- func SpecMemoryPath(root, slug string) string
- func SpecdDir(root string) string
- func StatePath(root, slug string) string
- func SteeringMemoryPath(root string) string
- func SubmissionsPath(root, slug string) string
- func SubmitBlockers(model ReportModel, gateFailures []string) []string
- func SummaryHash(summary string) string
- func Unifiedish(change AssetChange) string
- func ValidPhase(phase Phase) bool
- func ValidSlug(slug string) bool
- func ValidStatus(status Status) bool
- func ValidateSlug(slug string) error
- func WithSpecLock[T any](root string, fn func() (T, error)) (T, error)
- func WriteScaffold(root string) error
- type AgentHost
- type Annotations
- type AssetChange
- type Command
- type Config
- type ConfigParseError
- type ConfigPaths
- type ContextConfig
- type CriteriaConfig
- type CriterionRecord
- type Diagnostic
- type EscalationConfig
- type EvidenceRecord
- type ExitCode
- type Flag
- type FrontierTask
- type GatesConfig
- type Handshake
- type HelpPayload
- type HistoryEvent
- type ManagedAsset
- type MarkdownTable
- type MemFields
- type Mode
- type NotFoundError
- type OrchestrationConfig
- type OverrideRecord
- type Phase
- type Program
- func (p *Program) AddLink(from, to string)
- func (p Program) Deps(slug string) []string
- func (p Program) Frontier(specs []string, complete func(string) bool) []string
- func (p Program) HasLink(from, to string) bool
- func (p Program) IncompleteDeps(slug string, complete func(string) bool) []string
- func (p *Program) RemoveLink(from, to string) bool
- func (p Program) WouldCycle(from, to string) []string
- type ProgramLink
- type PrometheusMetrics
- type Record
- type ReportModel
- type ReportTask
- type ReviewConfig
- type ReviewReport
- type SecurityConfig
- type State
- type Status
- type SubmissionRecord
- type SubmitConfig
- type TaskDAG
- type TaskRow
- type TaskRunStatus
- type TaskTelemetry
- type TasksMd
- type TelemetryReport
- type ToolPolicy
- type Wave
Constants ¶
const ( CriterionStatusPass = "pass" CriterionStatusFail = "fail" )
CriterionStatusPass / Fail are the only valid statuses; the verify command's declared flag enum rejects anything else before this layer is reached.
const ( HistorySourceApproval = iota HistorySourceDecision HistorySourceMidReq HistorySourceVerify HistorySourceCompletion HistorySourceCriterion HistorySourceEscalation HistorySourceSubmission HistorySourceACP )
History source ranks. The values fix the tie-break order for events sharing a timestamp; they are an internal ordering key, not a public contract.
const ( ReviewApprove = "approve" ReviewReject = "reject" ReviewNeedsChanges = "needs-changes" )
Review verdicts. Anything else — including an unedited placeholder — fails the review parse and is never treated as approve (spec 09 R5, fail closed).
const EscalationDefaultMaxVerifyFails = 3
EscalationDefaultMaxVerifyFails is the ratchet threshold when config leaves escalation.max_verify_fails unset.
const HelpSchemaVersion = 1
HelpSchemaVersion versions the machine-readable help palette (`help --json`). Consumers (MCP, role prompts, external tools) pin against it and can detect a shape change; bump it whenever the Command/Flag JSON contract changes (spec 03 R4, pairs with the state-schema discipline of spec 02).
const ProgramSchemaVersion = 1
ProgramSchemaVersion versions the program.json shape, following the same forward-migration discipline as state.json (spec 02). Bump it when the shape changes and add a migration in LoadProgram.
const StateSchemaVersion = 2
const SubmitDefaultTimeoutSecs = 120
SubmitDefaultTimeoutSecs bounds an operator submit command when the config leaves submit.timeout_seconds unset.
const TemplateVersion = 1
TemplateVersion is the current version stamp for specd-managed scaffold assets. It rides in every managed-region marker so `init --refresh` can detect a region written by an older binary. Bump it whenever a role/steering template changes.
const UnknownHead = "unknown"
UnknownHead is the sentinel gitHead writes when HEAD cannot be resolved (commitless repo, no git). Evidence carrying it is not pinned to a commit.
Variables ¶
var Clock = func() time.Time { return time.Now().UTC() }
Clock is the injectable time source for record timestamps. Production uses wall-clock UTC; tests swap it for determinism. All record timestamps flow through here — never call time.Now directly in a record path.
var Commands = []Command{ { Name: "help", Usage: "specd help [command] [--json]", Description: "Show command help.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd help", "specd help --json"}, Flags: []Flag{ {Name: "json", Type: "bool", Description: "Emit machine-readable help."}, }, }, { Name: "version", Usage: "specd version [--json]", Description: "Print build version metadata.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd version", "specd version --json"}, Flags: []Flag{{Name: "json", Type: "bool", Description: "Emit machine-readable JSON."}}, }, { Name: "init", Usage: "specd init [--agent=<name>] [--repair|--refresh] [--dry-run]", Description: "Initialize or re-sync specd project state and managed assets.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd init", "specd init --repair --dry-run", "specd init --refresh"}, Flags: []Flag{ {Name: "agent", TakesValue: true, Type: "string", Description: "Select agent harness."}, {Name: "repair", Type: "bool", Description: "Restore drifted managed regions from the current templates."}, {Name: "refresh", Type: "bool", Description: "Update managed regions to the current binary's template version."}, {Name: "dry-run", Type: "bool", Description: "Print the managed-region changes and write nothing."}, }, }, { Name: "new", Usage: "specd new <name> [--agent=<name>]", Description: "Create a new spec workspace.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd new payments", "specd new payments --agent=codex"}, Flags: []Flag{ {Name: "agent", TakesValue: true, Type: "string", Description: "Select agent harness."}, }, }, { Name: "approve", Usage: "specd approve <spec> <gate>", Description: "Record human approval for a lifecycle gate.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd approve payments requirements", "specd approve payments design"}, }, { Name: "midreq", Usage: "specd midreq <spec> --text <change> [--scope <scope>]", Description: "Capture a scoped mid-stream requirement change.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd midreq payments --text 'add refund path' --scope requirements"}, Flags: []Flag{ {Name: "text", TakesValue: true, Type: "string", Description: "Change description (required)."}, {Name: "scope", TakesValue: true, Type: "string", Description: "Optional scope label."}, }, }, { Name: "decision", Usage: "specd decision <spec> --text <rationale> [--scope <scope>]", Description: "Record an explicit human decision.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd decision payments --text 'defer webhooks' --scope design"}, Flags: []Flag{ {Name: "text", TakesValue: true, Type: "string", Description: "Decision rationale (required)."}, {Name: "scope", TakesValue: true, Type: "string", Description: "Optional scope label."}, }, }, { Name: "next", Usage: "specd next <slug> [--json | --waves | --dispatch]", Description: "Select the next eligible task or wave.", AllowedPhases: postRequirementsPhases(), SpecSlugArg: argAt(0), ExitCodes: stdCodes(), Examples: []string{"specd next payments", "specd next payments --json"}, Flags: []Flag{ {Name: "waves", Type: "bool", Description: "Show all wave groups as JSON."}, {Name: "dispatch", Type: "bool", Description: "Emit the context manifest for the first frontier task."}, {Name: "json", Type: "bool", Description: "Emit machine-readable frontier list."}, }, }, { Name: "status", Usage: "specd status [spec] [--json] | specd status --program", Description: "Report current spec and task state, or the cross-spec program view.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd status payments", "specd status payments --json", "specd status --program"}, Flags: []Flag{ {Name: "json", Type: "bool", Description: "Emit machine-readable status."}, {Name: "program", Type: "bool", Description: "Show the cross-spec program view: specs, links, phases, and frontier."}, }, }, { Name: "task", Usage: "specd task <id> [--override --reason <text>] | specd task complete <spec> <id>", Description: "Show task details, clear an escalated task with a human override, or mark a task complete (requires passing evidence).", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd task T3 --json", "specd task T3 --override --reason 'flaky infra, verified manually'", "specd task complete payments T3"}, Flags: []Flag{ {Name: "json", Type: "bool", Description: "Emit machine-readable task row."}, {Name: "override", Type: "bool", Description: "Clear an escalated task (resets the verify-failure ratchet; does not complete it). Requires --reason."}, {Name: "reason", TakesValue: true, Type: "string", Description: "Human justification for --override (required, non-empty)."}, {Name: "tokens", TakesValue: true, Type: "string", Description: "Optional worker-reported token count, stored verbatim (task complete)."}, {Name: "cost", TakesValue: true, Type: "string", Description: "Optional worker-reported cost as a decimal string, stored verbatim (task complete)."}, {Name: "duration-ms", TakesValue: true, Type: "string", Description: "Optional worker-reported wall-clock milliseconds, stored verbatim (task complete)."}, }, }, { Name: "check", Usage: "specd check <spec> [--security] [--json]", Description: "Run the validation gate registry against a spec.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd check payments", "specd check payments --security --json"}, Flags: []Flag{ {Name: "security", Type: "bool", Description: "Run opt-in security gates."}, {Name: "schema", Type: "bool", Description: "Validate state.json schema."}, {Name: "schema-only", Type: "bool", Description: "Validate only state.json schema."}, {Name: "json", Type: "bool", Description: "Emit machine-readable findings."}, }, }, { Name: "verify", Usage: "specd verify <slug> <task-id> [--revert-on-fail] [--sandbox] [--sandbox-binary=<path>] | specd verify <slug> --criterion <r>.<n> --status pass|fail --evidence <text>", Description: "Run and record task verification (task mode), or record a per-acceptance-criterion evidence record (--criterion mode).", AllowedPhases: postRequirementsPhases(), SpecSlugArg: argAt(0), ExitCodes: stdCodes(), Examples: []string{"specd verify payments T3", "specd verify payments T3 --revert-on-fail", "specd verify payments --criterion 1.2 --status pass --evidence 'covered by T3 integration test'"}, Flags: []Flag{ {Name: "revert-on-fail", Type: "bool", Description: "Restore working tree on verify failure."}, {Name: "sandbox", Type: "bool", Description: "Run the verify line inside a bwrap sandbox (fail-closed if the binary is absent)."}, {Name: "sandbox-binary", TakesValue: true, Type: "string", Description: "Path to sandbox binary (overrides auto-detect)."}, {Name: "criterion", TakesValue: true, Type: "string", Description: "Record evidence for acceptance criterion <r>.<n> instead of running a task verify."}, {Name: "status", TakesValue: true, Type: "string", Enum: []string{"pass", "fail"}, Description: "Criterion verdict (with --criterion): pass|fail."}, {Name: "evidence", TakesValue: true, Type: "string", Description: "Evidence text or path backing the criterion verdict (with --criterion)."}, {Name: "tokens", TakesValue: true, Type: "string", Description: "Optional worker-reported token count, stored verbatim."}, {Name: "cost", TakesValue: true, Type: "string", Description: "Optional worker-reported cost as a decimal string, stored verbatim."}, {Name: "duration-ms", TakesValue: true, Type: "string", Description: "Optional worker-reported wall-clock milliseconds, stored verbatim."}, }, }, { Name: "context", Usage: "specd context <slug> <task-id> [--json|--hud]", Description: "Build the bounded context manifest for a task.", AllowedPhases: postRequirementsPhases(), SpecSlugArg: argAt(0), ExitCodes: stdCodes(), Examples: []string{"specd context payments T3", "specd context payments T3 --hud"}, Flags: []Flag{ {Name: "json", Type: "bool", Description: "Emit machine-readable context."}, {Name: "hud", Type: "bool", Description: "Render the operator HUD (files, bytes, tokens, mode)."}, }, }, { Name: "memory", Usage: "specd memory <slug> <add|promote> [flags]", Description: "Append or promote steering-memory patterns (learning flywheel).", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd memory payments add --key 'atomic writes' --pattern 'use AtomicWrite'"}, Flags: []Flag{ {Name: "key", TakesValue: true, Type: "string", Description: "Pattern key (H2 heading)."}, {Name: "pattern", TakesValue: true, Type: "string", Description: "One-line pattern statement (add)."}, {Name: "body", TakesValue: true, Type: "string", Description: "Detail of the pattern (add)."}, {Name: "source", TakesValue: true, Type: "string", Description: "Where the pattern came from (add)."}, {Name: "criticality", TakesValue: true, Type: "string", Enum: []string{"minor", "important", "critical"}, Description: "minor|important|critical (add)."}, {Name: "related", TakesValue: true, Type: "string", Description: "Comma-separated related keys → wikilinks (add)."}, {Name: "force", Type: "bool", Description: "Promote past the threshold (promote)."}, }, }, { Name: "mcp", Usage: "specd mcp | specd mcp --config <host> [--root <path>] [--spec <slug>]", Description: "Serve the MCP integration surface over stdio, or print a host config snippet.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd mcp", "specd mcp --config claude-code --spec demo"}, Flags: []Flag{ {Name: "config", TakesValue: true, Type: "string", Description: "Print a paste-ready MCP config snippet for a host (e.g. claude-code)."}, {Name: "root", TakesValue: true, Type: "string", Description: "Pin the server working directory in the snippet."}, {Name: "spec", TakesValue: true, Type: "string", Description: "Pin the active spec in the snippet."}, }, }, { Name: "handshake", Usage: "specd handshake bootstrap [--json] [--expect-palette-digest <d>] [--expect-config-digest <d>]", Description: "Emit bootstrap handshake material, including palette and config digests.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd handshake bootstrap", "specd handshake bootstrap --json"}, Flags: []Flag{ {Name: "json", Type: "bool", Description: "Emit machine-readable handshake."}, {Name: "expect-palette-digest", TakesValue: true, Type: "string", Description: "Fail (exit 1) if the command-palette digest differs."}, {Name: "expect-config-digest", TakesValue: true, Type: "string", Description: "Fail (exit 1) if the effective-config digest differs."}, }, }, { Name: "brain", Usage: "specd brain <start|step|run|status|cancel|resume> <spec> [--authority]", Description: "Run the opt-in deterministic orchestration controller.", AllowedPhases: postRequirementsPhases(), SpecSlugArg: argAt(1), ExitCodes: stdCodes(), Examples: []string{"specd brain start payments --authority", "specd brain status payments", "specd brain resume payments", "specd brain cancel payments"}, Flags: []Flag{ {Name: "authority", Type: "bool", Description: "Grant dispatch authority (fail-closed by default)."}, }, }, { Name: "report", Usage: "specd report <spec> [--pr|--metrics|--json|--history|--format prometheus]", Description: "Render evidence-backed status, PR, history, and metrics reports.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd report payments --pr", "specd report payments --metrics", "specd report payments --history", "specd report payments --format prometheus"}, Flags: []Flag{ {Name: "pr", Type: "bool", Description: "Emit PR-oriented report."}, {Name: "metrics", Type: "bool", Description: "Emit metrics summary."}, {Name: "json", Type: "bool", Description: "Emit machine-readable report (JSON Lines with --history)."}, {Name: "history", Type: "bool", Description: "Replay the spec's audit trail from existing records in timestamp order."}, {Name: "format", TakesValue: true, Type: "string", Enum: []string{"prometheus"}, Description: "Alternate output format; prometheus emits textfile-collector metrics."}, }, }, { Name: "link", Usage: "specd link <from-slug> <to-slug>", Description: "Record that one spec depends on another (cross-spec ordering).", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd link api auth"}, }, { Name: "unlink", Usage: "specd unlink <from-slug> <to-slug>", Description: "Remove a cross-spec dependency link.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd unlink api auth"}, }, { Name: "review", Usage: "specd review <spec> [--force]", Description: "Scaffold the review report the auditor fills before completion.", AllowedPhases: postExecutionPhases(), SpecSlugArg: argAt(0), ExitCodes: stdCodes(), Examples: []string{"specd review payments", "specd review payments --force"}, Flags: []Flag{ {Name: "force", Type: "bool", Description: "Overwrite an existing report for the current git HEAD."}, }, }, { Name: "submit", Usage: "specd submit <spec> [--resubmit]", Description: "Run every gate, then stream the PR summary to the operator-configured submit command.", AllowedPhases: postExecutionPhases(), SpecSlugArg: argAt(0), ExitCodes: stdCodes(), Examples: []string{"specd submit payments", "specd submit payments --resubmit"}, Flags: []Flag{ {Name: "resubmit", Type: "bool", Description: "Allow resubmitting a spec already submitted at the current git HEAD."}, }, }, { Name: "triage", Usage: "specd triage <spec>", Description: "Run the opt-in extended-loop triage tier.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(), Examples: []string{"specd triage payments"}, Deferred: true, }, }
Commands is the stable top-level command palette.
var DefaultConfig = Config{ Version: "1", Agent: "codex", Gates: GatesConfig{ Verify: "error", }, Context: ContextConfig{ MaxTokens: 12000, }, Orchestration: OrchestrationConfig{ Enabled: false, Model: "", }, Security: SecurityConfig{ Secrets: "error", Injection: "warn", Slopsquat: "warn", }, Escalation: EscalationConfig{ MaxVerifyFails: EscalationDefaultMaxVerifyFails, }, PromotionThreshold: 3, }
var ErrRevisionConflict = errors.New("state revision conflict")
var SecuritySeverities = []string{"off", "warn", "error"}
SecuritySeverities enumerates the valid per-scanner severities.
Functions ¶
func AlreadySubmittedAt ¶ added in v0.3.0
func AlreadySubmittedAt(records []SubmissionRecord, head string) bool
AlreadySubmittedAt reports whether the ledger holds a successful submission (exit 0) pinned to head. It is the idempotence guard behind the --resubmit requirement (spec 08 R5): a double-fire from orchestration at the same HEAD is refused unless the operator explicitly opts back in.
func AppendCriterion ¶ added in v0.3.0
func AppendCriterion(path string, rec CriterionRecord) error
AppendCriterion stamps and appends a criterion record. It fills the timestamp (Clock) and actor here so callers only supply the domain fields; the caller is responsible for holding the per-spec lock (see WithSpecLock) and for resolving gitHead.
func AppendEvidence ¶ added in v0.3.0
func AppendEvidence(path string, record EvidenceRecord) error
func AppendFile ¶
AppendFile appends data to a non-secret artifact and fsyncs before returning.
func AppendOverride ¶ added in v0.3.0
func AppendOverride(path string, record OverrideRecord) error
AppendOverride appends one override record. An empty reason is rejected: a clearance with no stated reason is not a reasoned override (R3).
func AppendSubmission ¶ added in v0.3.0
func AppendSubmission(path string, rec SubmissionRecord) error
AppendSubmission stamps and appends a submission record. It fills the timestamp (Clock) and actor here; the caller resolves gitHead and holds the per-spec lock (see WithSpecLock).
func AtomicWrite ¶
AtomicWrite writes data via a temp file in the target directory, fsyncs it, chmods to the non-secret artifact mode, then renames over the target.
func CanAdvanceStatus ¶ added in v0.3.0
func CommandNames ¶ added in v0.3.0
func CommandNames() []string
CommandNames returns command names in help order.
func CommitLink ¶
func CompleteTask ¶
func ConfigDigest ¶ added in v0.3.0
ConfigDigest is the SHA-256 of the effective config.
func ConsecutiveVerifyFails ¶ added in v0.3.0
func ConsecutiveVerifyFails(evidence []EvidenceRecord, overrides []OverrideRecord, taskID string) int
ConsecutiveVerifyFails counts the trailing run of failing verify attempts for taskID over a merged timeline of evidence and overrides. A passing verify or an override resets the count to zero. Pure over its inputs; deterministic for identical logs (R6).
func CountSpecsWithBlock ¶ added in v0.3.0
CountSpecsWithBlock counts specs whose memory.md contains a `## <key>` block. The promotion threshold is a pure count of on-disk state — no LLM (RM.4).
func CriteriaPath ¶ added in v0.3.0
CriteriaPath is the per-spec append-only criterion evidence ledger. It is kept separate from evidence.jsonl so the task-verify loader (last-write-wins per task) is untouched and the two evidence types stay physically distinct.
func CurrentPassing ¶ added in v0.3.0
func CurrentPassing(records []CriterionRecord, since time.Time) map[string]bool
CurrentPassing returns the set of criterion ids whose latest record is a pass recorded strictly after `since` (the last requirements approval). Re-approving requirements moves `since` forward and invalidates stale attestations by construction — no mutation of records needed (spec 04 R5/R6, "current").
A zero `since` means requirements were never approved; nothing counts.
func DedupRolePrompts ¶ added in v0.3.0
func EscalatedCounts ¶ added in v0.3.0
func EscalatedCounts(evidence []EvidenceRecord, overrides []OverrideRecord, tasks []TaskRow, maxFails int) map[string]int
EscalatedCounts returns, for each task that is currently escalated, its consecutive verify-fail count. Tasks below the threshold (or all tasks when the ratchet is disabled) are absent from the map. Pure over its inputs.
func EvidencePath ¶ added in v0.3.0
func ExtractMemBlock ¶ added in v0.3.0
ExtractMemBlock returns the `## <key>` block from text, from the heading up to (excluding) the next H2 heading, trailing whitespace trimmed. Returns "" when the key is absent. Pure function.
func ForbiddenTool ¶ added in v0.3.0
func HasPassingEvidence ¶ added in v0.3.0
func HasPassingEvidence(records map[string]EvidenceRecord, taskID string) bool
func HeadPinned ¶ added in v0.3.0
HeadPinned reports whether an evidence record's git_head names a real commit. Empty (pre-W3 records) and the "unknown" sentinel both fail: an evidence record that cannot be pinned to a commit does not count toward completion.
func IsEscalated ¶ added in v0.3.0
IsEscalated reports whether a task with the given consecutive-fail count is escalated under the ratchet threshold. maxFails <= 0 disables the ratchet: no task is ever escalated (the escape hatch, R5).
func ListSpecs ¶
ListSpecs enumerates spec slugs under .specd/specs/, sorted. Missing dir yields an empty list, not an error.
func LoadConfig ¶
func LoadConfig(paths ConfigPaths, env map[string]string) (Config, []Diagnostic)
LoadConfig applies global YAML, project YAML, then environment overrides. The function is deterministic for explicit paths and env input.
func LoadEvidence ¶ added in v0.3.0
func LoadEvidence(path string) (map[string]EvidenceRecord, error)
func MCPConfigSnippet ¶ added in v0.3.0
MCPConfigSnippet returns a ready-to-paste MCP server configuration wiring `specd mcp` for the named host. Optional root pins the server's working directory; optional spec pins the active spec via env. An unknown host is an error naming the known hosts, which the caller maps to a fail-closed exit 2.
The snippet is built from a typed structure and marshaled, so it is always valid JSON with stable (sorted) key order — golden-testable and never a hand-concatenated string that can drift into invalid JSON.
func MCPHosts ¶ added in v0.3.0
func MCPHosts() []string
MCPHosts is the set of agent hosts specd can emit a paste-ready MCP config snippet for. `claude-code` is the minimum (spec 11 R1); the list is designed to grow — add a case in MCPConfigSnippet and an entry here.
func MergeAgents ¶ added in v0.3.0
func OverridePath ¶ added in v0.3.0
OverridePath is the per-spec append-only override ledger.
func PRSummary ¶
func PRSummary(model ReportModel) string
func PaletteDigest ¶ added in v0.3.0
func PaletteDigest() string
PaletteDigest is the SHA-256 of the canonical `help --json` payload (spec 03). It is stable across runs (Go marshals struct fields in declaration order and map keys sorted) and changes when a verb or flag is added — exactly the drift an agent's --expect-palette-digest guard catches.
func ProgramPath ¶
ProgramPath is the program-level link store.
func ReadOrNull ¶
ReadOrNull returns the file contents, or nil when path does not exist.
func RenderHistory ¶ added in v0.3.0
func RenderHistory(slug string, events []HistoryEvent) string
RenderHistory prints the replay as one aligned line per event: timestamp, actor, event, reference. Empty fields render as "-" so columns stay stable.
func RenderHistoryJSON ¶ added in v0.3.0
func RenderHistoryJSON(events []HistoryEvent) (string, error)
RenderHistoryJSON emits one JSON object per line (JSON Lines), the same events as RenderHistory in the same order (spec 13 R6).
func RenderMemBlock ¶ added in v0.3.0
RenderMemBlock renders a byte-stable `## <key>` block. Output starts at the heading and ends with a trailing newline; callers prepend a blank line to separate appended blocks. Pure function of its input.
func RenderMetrics ¶ added in v0.3.0
func RenderMetrics(model ReportModel) string
func RenderPRSummary ¶ added in v0.3.0
func RenderPRSummary(model ReportModel) string
func RenderPrometheus ¶ added in v0.3.0
func RenderPrometheus(m PrometheusMetrics) string
RenderPrometheus emits node_exporter textfile-collector-compatible output: each metric family preceded by its HELP and TYPE lines, every series labelled with the spec slug, values in a deterministic order so repeated runs are byte-identical and no series is duplicated (R4, R5).
func RenderPromotion ¶ added in v0.3.0
RenderPromotion renders the block plus a deterministic provenance line for the steering store. date is pre-formatted (UTC) by the caller so output is byte-deterministic under an injected clock (RM.7). Pure function.
func RenderReviewScaffold ¶ added in v0.3.0
RenderReviewScaffold builds the review report from the embedded template, substituting the spec slug, the git HEAD under review, and a per-task section (id, files, acceptance) so the reviewer sees exactly what to audit (R1).
func RenderStatus ¶ added in v0.3.0
func RenderStatus(model ReportModel) string
func RenderTelemetry ¶ added in v0.3.0
func RenderTelemetry(slug string, report TelemetryReport) string
RenderTelemetry formats a telemetry report for `report --metrics`, in the same Prometheus-flavored style as the task-count metrics. Tasks without telemetry are emitted as an explicit gauge so absence is visible, never imputed (R4).
func ReviewReportHead ¶ added in v0.3.0
ReviewReportHead extracts just the recorded Git HEAD from a review report, or "" if there is no resolved HEAD line. The overwrite guard (spec 09 R2) uses it to detect a report already scaffolded for the current commit — even before the auditor has filled the verdict, so a re-scaffold never clobbers in-progress notes.
func ReviewReportPath ¶ added in v0.3.0
ReviewReportPath is the per-spec review report the auditor role fills.
func RewriteTaskStatusLine ¶ added in v0.3.0
func RolePrompt ¶ added in v0.3.0
RolePrompt returns the role constitution for role, read from the embedded role files — the single source of truth also written to .specd/roles/ by WriteScaffold. An unknown role falls back to craftsman.
func SaveProgram ¶
SaveProgram writes the program atomically at the current schema version.
func SaveStateCAS ¶ added in v0.3.0
func SerializeTasksMd ¶ added in v0.3.0
SerializeTasksMd preserves the source bytes exactly. The task DAG uses parsed rows for decisions, never rewritten markdown.
func SortHistory ¶ added in v0.3.0
func SortHistory(events []HistoryEvent)
SortHistory orders events by timestamp, then by the (SourceRank, Seq) tie-break, giving a total order that is stable across runs (spec 13 R3).
func SortedReportTaskIDs ¶ added in v0.3.0
func SortedReportTaskIDs(model ReportModel) []string
func SpecMemoryPath ¶ added in v0.3.0
SpecMemoryPath is the per-spec steering-memory store (RM.1).
func SteeringMemoryPath ¶ added in v0.3.0
SteeringMemoryPath is the shared steering store promotions land in (RM.3).
func SubmissionsPath ¶ added in v0.3.0
SubmissionsPath is the per-spec append-only submission ledger. It is kept separate from evidence/criteria so the terminal-submit audit trail is physically distinct from execution evidence.
func SubmitBlockers ¶ added in v0.3.0
func SubmitBlockers(model ReportModel, gateFailures []string) []string
SubmitBlockers enumerates why a spec is not submittable: every gate failure (rendered upstream, since the gate registry lives in a subpackage) plus every task that is not complete. An empty result means all gates are green and every task is done — the R1 precondition. It is a pure function of the model and the pre-rendered gate failures so it is unit-testable without running gates.
func SummaryHash ¶ added in v0.3.0
SummaryHash is the content address of a submission summary: a hex sha256. The ledger stores it so `report --history` (spec 13) can show exactly what was submitted without re-deriving or storing the full summary text.
func Unifiedish ¶ added in v0.3.0
func Unifiedish(change AssetChange) string
Unifiedish renders a minimal line-oriented diff for a managed asset change, so `--dry-run` shows what would change before any write (spec 11 R5). It is not a full unified diff — it flags added/removed lines by prefix, which is enough for an operator to see the managed-region delta.
func ValidPhase ¶ added in v0.3.0
func ValidStatus ¶ added in v0.3.0
func ValidateSlug ¶
func WithSpecLock ¶
WithSpecLock serializes harness work for one spec root and permits reentry from the same goroutine.
func WriteScaffold ¶ added in v0.3.0
Types ¶
type AgentHost ¶ added in v0.3.0
type AgentHost struct {
Name string
Detect string
Plan string
Install string
Inspect string
Verify string
}
func AgentHosts ¶ added in v0.3.0
func AgentHosts() []AgentHost
type Annotations ¶ added in v0.3.0
type Annotations struct {
Tokens int `json:"tokens,omitempty"`
Cost string `json:"cost,omitempty"`
DurationMs int `json:"duration_ms,omitempty"`
}
Annotations is worker-reported cost telemetry attached verbatim to a record. The doctrine is "stored, never computed" (spec 10 R1): specd accepts these values from the host worker and never estimates, derives, or counts tokens itself. Every field is optional (R5) — a worker that cannot report cost still produces valid records. Cost is a decimal string with currency-agnostic semantics; aggregation uses exact rational math, never float64 (R6).
func ParseAnnotations ¶ added in v0.3.0
func ParseAnnotations(tokens, cost, durationMs string, present func(string) bool) (*Annotations, error)
ParseAnnotations reads the optional --tokens/--cost/--duration-ms flags. It returns nil (no telemetry) when none are present, and a validation error when any is malformed — the caller maps that to a fail-closed exit 2 (R2). Values are stored verbatim; nothing here computes a cost.
type AssetChange ¶ added in v0.3.0
AssetChange is one file a repair/refresh/dry-run would touch.
func ApplyManagedRepair ¶ added in v0.3.0
func ApplyManagedRepair(root string) ([]AssetChange, error)
ApplyManagedRepair writes every planned change atomically and returns the list of files it touched. It is the mutating counterpart to PlanManagedRepair.
func PlanManagedRepair ¶ added in v0.3.0
func PlanManagedRepair(root string) ([]AssetChange, error)
PlanManagedRepair computes the changes needed to bring every managed asset's region back in sync with the current templates, without writing anything. A file whose managed region already matches is not listed. This is the pure core of `init --repair`/`--refresh`/`--dry-run` (spec 11 R3/R4/R5).
type Command ¶ added in v0.3.0
type Command struct {
Name string `json:"name"`
Usage string `json:"usage"`
Description string `json:"description"`
Flags []Flag `json:"flags,omitempty"`
// AllowedPhases is the set of lifecycle phases the verb may run in. A verb
// valid everywhere declares []Phase{PhaseAny} explicitly — nothing defaults
// silently to unrestricted (spec 03 R1, R6).
AllowedPhases []Phase `json:"allowed_phases,omitempty"`
// ExitCodes documents every status the verb can return (spec 03 R1/B.3).
ExitCodes []ExitCode `json:"exit_codes,omitempty"`
// Examples is at least one runnable invocation (spec 03 R1).
Examples []string `json:"examples,omitempty"`
// SpecSlugArg is the positional-argument index (0-based) that carries the
// spec slug for phase enforcement, or nil when the verb resolves no spec by
// a fixed position. Dispatch only phase-checks verbs with a non-nil index
// (spec 03 R2: "verbs that take no spec slug skip the check"). Not exported
// to JSON — it is an internal dispatch hint, not part of the help contract.
SpecSlugArg *int `json:"-"`
// Deferred marks a registered verb whose implementation is intentionally
// not wired yet. The dispatcher reports the deferral and exits 0; the
// handler-parity test treats a deferred verb as satisfied.
Deferred bool `json:"deferred,omitempty"`
}
Command describes one supported top-level command. This metadata is the single source of truth for help, dispatch enforcement, MCP tool schemas, and role prompts — no surface hand-restates command semantics (spec 03 C.8).
func CommandByName ¶ added in v0.3.0
CommandByName returns the command metadata for name, and whether it exists.
func (Command) AllowsPhase ¶ added in v0.3.0
AllowsPhase reports whether the command may run in phase. A command that declares PhaseAny is unrestricted.
func (Command) FlagByName ¶ added in v0.3.0
FlagByName returns the flag metadata for name, or nil if the command has no such flag.
type Config ¶
type Config struct {
Version string
Agent string
Gates GatesConfig
Context ContextConfig
Orchestration OrchestrationConfig
Criteria CriteriaConfig
Review ReviewConfig
Submit SubmitConfig
Security SecurityConfig
Escalation EscalationConfig
PromotionThreshold int
}
Config is the deterministic runtime configuration used by the harness.
type ConfigParseError ¶ added in v0.3.0
func (ConfigParseError) Error ¶ added in v0.3.0
func (e ConfigParseError) Error() string
type ConfigPaths ¶
type ContextConfig ¶ added in v0.3.0
type ContextConfig struct {
MaxTokens int
}
type CriteriaConfig ¶ added in v0.3.0
type CriteriaConfig struct {
Required bool
}
CriteriaConfig is the opt-in per-acceptance-criterion evidence ratchet. When Required is true, the completion approval gate refuses while any acceptance criterion lacks a current passing record (spec 04 R6). Default off so existing flows are unbroken.
type CriterionRecord ¶
type CriterionRecord struct {
Type string `json:"type"` // always "criterion" — discriminates the store
Criterion string `json:"criterion"` // "<req>.<sub>", e.g. "1.2"
Status string `json:"status"` // "pass" | "fail"
Evidence string `json:"evidence"` // operator-supplied text or path
GitHead string `json:"git_head"` // pinned commit, same discipline as verify (R3)
Timestamp string `json:"timestamp"` // RFC3339, from the injectable Clock
Actor string `json:"actor"`
}
CriterionRecord attests a single acceptance criterion of an approved requirement. It is a distinct evidence type from a task verify record (EvidenceRecord): a criterion record carries operator-supplied evidence and is never produced by running a command, so it can never substitute for a task's passing verify record (spec 04 R7). Records are append-only — a later pass never erases a prior fail (R4).
func LoadCriteria ¶ added in v0.3.0
func LoadCriteria(path string) ([]CriterionRecord, error)
LoadCriteria reads the criterion ledger in append order, preserving history (fails retained after later passes). A missing file is an empty ledger.
type Diagnostic ¶ added in v0.3.0
type EscalationConfig ¶ added in v0.2.0
type EscalationConfig struct {
MaxVerifyFails int
}
EscalationConfig is the opt-in verify-failure ratchet (spec 06 R5). MaxVerifyFails is the count of consecutive failing verify records (since the last pass or override) that escalates a task and blocks its completion until a human clears it with `task <id> --override --reason`. Default 3; 0 disables the ratchet.
type EvidenceRecord ¶ added in v0.3.0
type EvidenceRecord struct {
TaskID string `json:"task_id"`
Command string `json:"command"`
ExitCode int `json:"exit_code"`
GitHead string `json:"git_head"`
EvidenceRef string `json:"evidence_ref,omitempty"`
// Timestamp and Actor stamp the attempt so `report --history` (spec 13) can
// replay verify attempts in time order alongside approvals and submissions.
// Both are omitempty: records written before spec 13 carry neither and still
// decode as fully valid evidence — they simply sort by append order.
Timestamp string `json:"timestamp,omitempty"`
Actor string `json:"actor,omitempty"`
// Telemetry is optional worker-reported cost, stored verbatim (spec 10). A
// nil pointer means the worker reported none — never imputed as zero. Old
// records predating telemetry decode to nil, so they stay fully valid (R5).
Telemetry *Annotations `json:"telemetry,omitempty"`
}
func LoadEvidenceRecords ¶ added in v0.3.0
func LoadEvidenceRecords(path string) ([]EvidenceRecord, error)
LoadEvidenceRecords reads the evidence log in append order, preserving every attempt (unlike LoadEvidence, which keeps only the latest record per task). Telemetry aggregation needs the full history for per-attempt breakdown.
type ExitCode ¶ added in v0.3.0
ExitCode documents one exit status a command can return. The convention is 0 success, 1 gate/verify failure, 2 usage / fail-closed rejection; per-verb deviations are declared explicitly (spec 03 design notes).
type Flag ¶ added in v0.3.0
type Flag struct {
Name string `json:"name"`
TakesValue bool `json:"takes_value,omitempty"`
Description string `json:"description,omitempty"`
Type string `json:"type,omitempty"` // "bool" | "string"; empty ⇒ bool
Enum []string `json:"enum,omitempty"` // allowed values (value flags only)
Default string `json:"default,omitempty"` // documented default
}
Flag describes one command-line flag surfaced by help metadata. Enum and Default make the flag a machine-readable contract: dispatch validates values against Enum (spec 03 R3) and MCP maps Enum/Default into JSON Schema.
type FrontierTask ¶ added in v0.3.0
type FrontierTask struct {
ID string `json:"id"`
Role string `json:"role,omitempty"`
Verify string `json:"verify,omitempty"`
Terminal string `json:"terminal,omitempty"`
}
func Frontier ¶ added in v0.3.0
func Frontier(tasks []TaskRow, status map[string]TaskRunStatus) ([]FrontierTask, error)
func FrontierExcluding ¶ added in v0.3.0
func FrontierExcluding(tasks []TaskRow, status map[string]TaskRunStatus, escalated map[string]bool) ([]FrontierTask, error)
FrontierExcluding is Frontier with an escalation filter: any task id present in escalated is dropped from the runnable frontier so neither `status` nor the Brain will pick it up until a human clears it with an override (spec 06 R2). A nil escalated set is exactly Frontier.
type GatesConfig ¶ added in v0.3.0
type GatesConfig struct {
Verify string
}
type Handshake ¶ added in v0.3.0
type Handshake struct {
Version string `json:"version"`
Agent string `json:"agent,omitempty"`
Tools []string `json:"tools"`
// PaletteDigest and ConfigDigest let an agent detect that its cached command
// palette or effective config has drifted from this binary's (spec 11 R6).
// Both are SHA-256 over the canonical (stable-key-order) JSON.
PaletteDigest string `json:"palette_digest"`
ConfigDigest string `json:"config_digest"`
}
func BootstrapHandshake ¶ added in v0.3.0
type HelpPayload ¶ added in v0.3.0
type HelpPayload struct {
SchemaVersion int `json:"schema_version"`
Commands []Command `json:"commands"`
}
HelpPayload is the stable machine-readable help contract emitted by `help --json`. SchemaVersion lets consumers detect shape changes.
func BuildHelpPayload ¶ added in v0.3.0
func BuildHelpPayload() HelpPayload
BuildHelpPayload assembles the full palette for `help --json`.
type HistoryEvent ¶ added in v0.3.0
type HistoryEvent struct {
Timestamp string `json:"timestamp,omitempty"`
Actor string `json:"actor,omitempty"`
Event string `json:"event"`
Reference string `json:"reference,omitempty"`
GitHead string `json:"git_head,omitempty"`
// SourceRank and Seq are the deterministic tie-break keys (R3), never
// serialized. When two events share a timestamp (or both lack one), order is
// resolved first by SourceRank (a fixed per-source-type ordering) then by Seq
// (the record's position within its source). The pair is unique across all
// events for a spec, so the total order — and therefore the byte output — is
// identical on every run.
SourceRank int `json:"-"`
Seq int `json:"-"`
}
HistoryEvent is one replayed line of a spec's audit trail (spec 13 R1). It is projected from records that already exist on disk — approvals/decisions in state.json, criterion and submission ledgers, verify evidence, the ACP ledger — never from a new event store, and `report --history` writes nothing (R2).
Timestamp/Actor are shown "where recorded": a source that does not stamp them leaves them empty rather than inventing a value.
type ManagedAsset ¶ added in v0.3.0
type ManagedAsset struct {
Name string // logical asset id, e.g. "roles/craftsman.md"
RelPath string // path under the project root, e.g. ".specd/roles/craftsman.md"
Version int
Template string
}
ManagedAsset is one specd-managed scaffold file (a role or steering template). Its Template is wrapped in stable marker comments so `init --repair`/`--refresh` can regenerate the managed region while leaving any user content outside the markers byte-for-byte untouched (spec 11 R2/R3/R4).
func ManagedAssets ¶ added in v0.3.0
func ManagedAssets() ([]ManagedAsset, error)
ManagedAssets enumerates the role and steering templates baked into the binary.
func (ManagedAsset) Block ¶ added in v0.3.0
func (a ManagedAsset) Block() string
Block is the marker-wrapped managed region for the asset at its current version.
func (ManagedAsset) Merge ¶ added in v0.3.0
func (a ManagedAsset) Merge(existing string) string
Merge returns existing with this asset's managed region replaced by the current template block (matching a marker of *any* version, so a refresh restamps an older region). Content outside the markers is preserved exactly; when no region is present the block is appended. A brand-new file becomes just the block.
type MarkdownTable ¶ added in v0.3.0
MarkdownTable stores one parsed pipe table while retaining the original bytes.
type MemFields ¶ added in v0.3.0
type MemFields struct {
Key string
Pattern string
Detail string
Source string
Criticality string
Related string
}
MemFields is one steering-memory entry. Related is the raw comma-separated value as supplied on the CLI; RenderMemBlock formats it into wikilinks.
type NotFoundError ¶
type NotFoundError struct {
Start string
}
func (NotFoundError) Error ¶ added in v0.3.0
func (e NotFoundError) Error() string
func (NotFoundError) ExitCode ¶ added in v0.3.0
func (e NotFoundError) ExitCode() int
type OrchestrationConfig ¶ added in v0.3.0
type OverrideRecord ¶ added in v0.3.0
type OverrideRecord struct {
TaskID string `json:"task_id"`
Reason string `json:"reason"`
Actor string `json:"actor"`
Timestamp string `json:"timestamp"`
PriorFailCount int `json:"prior_fail_count"`
}
OverrideRecord is an append-only human clearance of an escalated task (spec 06 R3). It resets the verify-failure counter but does NOT complete the task or stand in for evidence: after an override the task still needs a passing verify record to complete (the no-bypass invariant). PriorFailCount pins how many consecutive fails were cleared, for the audit trail.
func LoadOverrides ¶ added in v0.3.0
func LoadOverrides(path string) ([]OverrideRecord, error)
LoadOverrides reads the override ledger in append order. A missing file is not an error (no overrides yet).
type Phase ¶
type Phase string
const ( PhasePerceive Phase = "perceive" PhaseAnalyze Phase = "analyze" PhasePlan Phase = "plan" PhaseExecute Phase = "execute" PhaseVerify Phase = "verify" PhaseReflect Phase = "reflect" // PhaseAny is the sentinel a command declares when it is valid in every // lifecycle phase. It is never a real state phase (ValidPhase rejects it); // it exists only so command metadata declares "unrestricted" explicitly // rather than defaulting silently to it (spec 03 R6). PhaseAny Phase = "any" )
func AdvanceStatus ¶ added in v0.3.0
func PhaseForStatus ¶
type Program ¶ added in v0.3.0
type Program struct {
SchemaVersion int `json:"schema_version"`
Links []ProgramLink `json:"links"`
}
Program is the cross-spec dependency graph. It is stored at `.specd/program.json`, written atomically under the root lock (which already serializes all harness work for the root, so program state needs no second lock and cannot deadlock against a spec lock).
func LoadProgram ¶
LoadProgram reads program.json. A missing file is an empty program at the current schema version. An unknown (future) schema is an error — fail closed rather than silently misread newer state.
func (*Program) AddLink ¶ added in v0.3.0
AddLink records from→to. It is idempotent: a duplicate link is a no-op.
func (Program) Deps ¶ added in v0.3.0
Deps returns the slugs that slug directly depends on (its To edges), sorted.
func (Program) Frontier ¶ added in v0.3.0
Frontier returns the specs that are actionable now: not yet complete and with every dependency complete. complete is injected by the caller (the same all-gates-green + all-tasks-complete predicate `submit` uses), keeping this pure over the graph with no gate logic in core (spec 12 R4).
func (Program) IncompleteDeps ¶ added in v0.3.0
IncompleteDeps returns slug's direct dependencies that are not yet complete — the specs blocking it from executing (spec 12 R5).
func (*Program) RemoveLink ¶ added in v0.3.0
RemoveLink deletes from→to and reports whether it existed.
func (Program) WouldCycle ¶ added in v0.3.0
WouldCycle reports the cycle path that adding from→to would create, or nil if the link is safe. A cycle exists when To already depends (transitively) on From: following dependency edges from To reaches From. The returned path reads from→to→…→from for printing (spec 12 R2).
type ProgramLink ¶ added in v0.3.0
ProgramLink records that From depends on To — To must reach completion before From may execute. Links live at the program level, never inside a spec's state.json, so each file keeps a single writer (spec 12 R6).
type PrometheusMetrics ¶ added in v0.3.0
type PrometheusMetrics struct {
Slug string
TasksByStatus map[string]int
VerifyAttempts int
VerifyFailures int
CriteriaPassing int
CriteriaTotal int
EscalatedTasks int
Tokens int
Cost string // exact decimal string; "" renders as 0
DurationMs int
}
PrometheusMetrics is the pure, on-disk-derived snapshot rendered as a Prometheus textfile exposition (spec 13 R4). It is assembled by the caller from the same state.json + ledgers the rest of `report` reads; RenderMetrics here adds no I/O and no gate logic.
Metric names are an API: renaming one breaks every dashboard built against it, so the contract is written down in docs/command-reference.md and must not churn. All names carry the `specd_` prefix, snake_case, with `_total` on monotonic counters and `_seconds` on durations, per Prometheus conventions.
type Record ¶ added in v0.3.0
type Record struct {
Kind string `json:"kind"`
Text string `json:"text,omitempty"`
Scope string `json:"scope,omitempty"`
Gate string `json:"gate,omitempty"`
ApprovedRevision int64 `json:"approved_revision,omitempty"`
Timestamp string `json:"timestamp"`
GitHead string `json:"git_head"`
Actor string `json:"actor"`
}
Record is a stamped ledger entry stored in State.Records. Content fields (Text/Scope/Gate/ApprovedRevision) are per-kind; StampRecord fills the provenance triple (Timestamp/GitHead/Actor) that ADR-6 observability and PROJECT.md §3 evidence integrity require on every record.
func StampRecord ¶ added in v0.3.0
StampRecord fills the provenance triple on rec: an RFC 3339 timestamp from the injectable Clock, the caller-resolved git HEAD, and the host actor. The actor is host-reported and stored verbatim — never trusted as proof.
type ReportModel ¶ added in v0.3.0
type ReportModel struct {
Slug string `json:"slug"`
Total int `json:"total"`
Complete int `json:"complete"`
Pending int `json:"pending"`
Blocked int `json:"blocked"`
Running int `json:"running"`
Tasks []ReportTask `json:"tasks"`
}
func BuildReportModel ¶ added in v0.3.0
func BuildReportModel(slug string, tasks []TaskRow, status map[string]TaskRunStatus, evidence map[string]EvidenceRecord) ReportModel
type ReportTask ¶ added in v0.3.0
type ReviewConfig ¶ added in v0.3.0
type ReviewConfig struct {
Required bool
}
ReviewConfig is the opt-in review gate (spec 09). When Required is true, the completion approval gate refuses unless review_report.md carries an approve verdict recorded at the current git HEAD. Default off so existing flows are unbroken.
type ReviewReport ¶ added in v0.2.0
ReviewReport is the field-extraction result of a review_report.md. The report is human-edited, so — unlike the tasks parser — the parser does not require byte-stability or round-tripping; it extracts three load-bearing fields and the findings prose. The Head field is what makes an approval a *fact about this code* (spec 09 R3), mirroring evidence pinning.
func ParseReviewReport ¶ added in v0.2.0
func ParseReviewReport(raw string) (ReviewReport, error)
ParseReviewReport extracts the verdict, HEAD, and findings from a review report. It is strict (R5): a missing/unknown verdict or a missing HEAD line is an error, never a silent approve. It is tolerant of surrounding human edits — it scans for the labelled fields rather than requiring a fixed byte layout.
type SecurityConfig ¶ added in v0.3.0
SecurityConfig sets per-scanner severity for the opt-in security gate (spec 05 R5). Each field is off|warn|error: error findings fail the gate (exit 1), warn findings print but pass, off skips the scanner. Defaults tuned so a real secret blocks while noisier heuristics only warn.
type State ¶
type State struct {
SchemaVersion int `json:"schema_version"`
Slug string `json:"slug"`
Mode Mode `json:"mode"`
Status Status `json:"status"`
Phase Phase `json:"phase"`
Revision int64 `json:"revision"`
Records map[string]json.RawMessage `json:"records,omitempty"`
// TaskStatus is the machine truth for per-task run status (ADR-1: status
// lives in state.json, tasks.md stays clean Markdown). The Sync gate
// enforces that tasks.md markers agree with this map.
TaskStatus map[string]TaskRunStatus `json:"task_status,omitempty"`
Extra map[string]json.RawMessage `json:"extra,omitempty"`
}
func InitialState ¶
func MigrateState ¶ added in v0.3.0
type SubmissionRecord ¶ added in v0.3.0
type SubmissionRecord struct {
Type string `json:"type"` // always "submission" — discriminates the store
GitHead string `json:"git_head"` // commit the summary described
SummaryHash string `json:"summary_hash"` // sha256 of the streamed summary
Command string `json:"command"` // configured submit.command ("" = dry-run)
Exit int `json:"exit"` // command exit code (0 for dry-run)
Timestamp string `json:"timestamp"` // RFC3339, from the injectable Clock
Actor string `json:"actor"`
}
SubmissionRecord is one terminal submission of a spec: the deterministic PR summary (identified by its content hash) that was streamed to the operator-configured command, pinned to the git HEAD it described and the command's exit code. Records are append-only — a resubmission never erases a prior one, so the ledger is a full audit trail (spec 08 R4, feeds spec 13).
func LoadSubmissions ¶ added in v0.3.0
func LoadSubmissions(path string) ([]SubmissionRecord, error)
LoadSubmissions reads the submission ledger in append order. A missing file is an empty ledger.
type SubmitConfig ¶ added in v0.3.0
SubmitConfig configures the terminal `submit` verb (spec 08). Command is an operator-supplied shell line run through the shared exec path with the PR summary streamed on stdin; empty means dry-run (print summary, exit 0). The binary embeds no git/GitHub logic — the operator owns transport. TimeoutSecs bounds the command; zero applies SubmitDefaultTimeoutSecs.
type TaskDAG ¶ added in v0.3.0
func NewTaskDAG ¶ added in v0.3.0
func (TaskDAG) AllBlocked ¶ added in v0.3.0
func (dag TaskDAG) AllBlocked(status map[string]TaskRunStatus) bool
func (TaskDAG) RunnableFrontier ¶ added in v0.3.0
func (dag TaskDAG) RunnableFrontier(status map[string]TaskRunStatus) ([]string, error)
func (TaskDAG) TopologicalWaves ¶ added in v0.3.0
type TaskRunStatus ¶ added in v0.3.0
type TaskRunStatus string
const ( TaskPending TaskRunStatus = "pending" TaskRunning TaskRunStatus = "running" TaskComplete TaskRunStatus = "complete" TaskBlocked TaskRunStatus = "blocked" )
type TaskTelemetry ¶ added in v0.3.0
type TaskTelemetry struct {
TaskID string `json:"task_id"`
Attempts []Annotations `json:"attempts,omitempty"`
Tokens int `json:"tokens"`
Cost string `json:"cost"`
DurationMs int `json:"duration_ms"`
HasTelemetry bool `json:"has_telemetry"`
}
TaskTelemetry is one task's telemetry across every recorded attempt. Absence is explicit: HasTelemetry is false when no attempt carried annotations, so the report shows missing data rather than imputing zero (R4).
type TasksMd ¶ added in v0.3.0
type TasksMd struct {
Raw []byte
Tasks []TaskRow
Tables []MarkdownTable
}
TasksMd is the parsed representation of a tasks.md file. SerializeTasksMd returns Raw unchanged unless a caller deliberately builds a new value.
func ParseTasksMd ¶
type TelemetryReport ¶ added in v0.3.0
type TelemetryReport struct {
Tokens int `json:"tokens"`
Cost string `json:"cost"`
DurationMs int `json:"duration_ms"`
Tasks []TaskTelemetry `json:"tasks,omitempty"`
Missing []string `json:"missing,omitempty"`
}
TelemetryReport aggregates annotations per spec and per task. Totals are exact (integer sums for tokens/duration, rational sum for cost). Missing lists the tasks with no telemetry at all.
func AggregateTelemetry ¶ added in v0.3.0
func AggregateTelemetry(records []EvidenceRecord, taskOrder []string) TelemetryReport
AggregateTelemetry folds every evidence record's annotations into per-task and per-spec totals. records is the full append-order evidence log (one entry per attempt), so per-attempt breakdown is preserved. taskOrder fixes the task ordering for deterministic output; a task with no annotated attempt is listed in Missing and never imputed a zero cost.
type ToolPolicy ¶ added in v0.3.0
func LoadToolPolicy ¶ added in v0.3.0
func LoadToolPolicy(path string) ToolPolicy
Source Files
¶
- agents.go
- commands.go
- commitlink.go
- config_loader.go
- config_validate.go
- criteria.go
- dag.go
- escalation.go
- evidence.go
- frontier.go
- handshake.go
- history.go
- io.go
- lock.go
- managed.go
- manifest_tools.go
- mcpconfig.go
- md.go
- memory.go
- paths.go
- phases.go
- program.go
- prometheus.go
- prsummary.go
- report.go
- report_metrics.go
- review.go
- roles.go
- scaffold.go
- slug.go
- state.go
- submit.go
- task_complete.go
- tasksparser.go
- telemetry.go