core

package
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 13, 2026 License: MIT Imports: 29 Imported by: 0

Documentation

Index

Constants

View Source
const (
	DeploymentAdapterEnvelopeSchemaV1 = "deployment-adapter/v1"
	DeploymentAdapterResultKind       = "deployment.result"
	MaxDeploymentAdapterEnvelopeBytes = 64 * 1024
	MaxDeploymentAdapterMessageBytes  = 1024
	AdapterRedactedText               = "[REDACTED UNTRUSTED ADAPTER TEXT]"
)
View Source
const (
	ProfileDefault    = "default"
	ProfileProduction = "production"
)

Lifecycle strictness profiles (spec 01 R7). ProfileDefault keeps every new completeness check opt-in (backward compatible, R7.1); ProfileProduction arms the risk-proportionate criterion/review/integration/negative-path evidence gates together (R7.2).

View Source
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.

View Source
const (
	ReleaseCandidateSchemaV1  = "ReleaseCandidateV1"
	EnvironmentSchemaV1       = "EnvironmentV1"
	DeploymentSchemaV1        = "DeploymentV1"
	HealthObservationSchemaV1 = "HealthObservationV1"
	RollbackSchemaV1          = "RollbackV1"
	RollbackSchemaV2          = "RollbackV2"
)
View Source
const (
	RollbackCapabilityAutomatic     = "automatic"
	RollbackCapabilityHumanRequired = "human_required"
)
View Source
const (
	ManifestDataset = "dataset"
	ManifestRubric  = "rubric"
	ReviewDraft     = "draft"
	ReviewApproved  = "approved"
)
View Source
const (
	HistorySourceApproval = iota
	HistorySourceDecision
	HistorySourceMidReq
	HistorySourceProvenance
	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.

View Source
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).

View Source
const (
	TelemetrySourceWorker   = "worker"
	TelemetrySourceAdapter  = "provider_adapter"
	TelemetrySourceOperator = "operator"
)

Telemetry provenance (spec 07 R1.3): who reported the measured values. specd stores worker numbers verbatim and never presents them as independently measured — every report renders them "as reported" against this label.

View Source
const ArchiveSchemaV1 = 1
View Source
const AttestationEnvelopeV1 = "attestation/v1"
View Source
const AuthoritySchemaVersion = "1"
View Source
const CIIdentitySchemaV1 = "ci-identity/v1"
View Source
const ContextSchemaVersion = "2"
View Source
const DriverProtocolVersion = "1"
View Source
const EscalationDefaultMaxVerifyFails = 3

EscalationDefaultMaxVerifyFails is the ratchet threshold when config leaves escalation.max_verify_fails unset.

View Source
const EvalSchemaVersion = "1"
View Source
const EventSchemaV1 = "event/v1"

EventSchemaV1 identifies specd's provider-neutral, metadata-only local event contract. External adapters may map this data to OpenTelemetry; core only validates and renders it and therefore stays offline and dependency-free.

View Source
const EvidenceOutputLimit = 64 * 1024
View Source
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).

View Source
const IncidentPreventionSchemaV1 = 1
View Source
const PortfolioItemLimit = 1000
View Source
const PortfolioScaleLimit = 10000

PortfolioScaleLimit is the bounded, documented projection envelope. Callers provide compact records only; BuildPortfolioGovernanceStatus never discovers or loads spec prose, ledgers, or context.

View Source
const ProgramLinkLimit = 100000
View Source
const ProgramLinksPerSpecLimit = 1000
View Source
const ProgramSchemaVersion = 2

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.

View Source
const ProvenanceSchemaV1 = 1
View Source
const RecurringSchemaV1 = 1
View Source
const RunEnvelopeV1 = "v1"

RunEnvelopeV1 is the run-ledger schema version (spec 07 R2). An empty version on decode is grandfathered; any other non-empty value is an unknown *required* schema and fails closed, mirroring the telemetry envelope (R1.2).

View Source
const SpanExtensionPrefix = "x-"

SpanExtensionPrefix namespaces a vendor or experimental span kind. A kind carrying it is tolerated by ParseSpanKind even though it sits outside the closed enum; any other unknown kind fails closed (spec 07 R6.1).

View Source
const StateSchemaVersion = 2
View Source
const SubmitDefaultTimeoutSecs = 120

SubmitDefaultTimeoutSecs bounds an operator submit command when the config leaves submit.timeout_seconds unset.

View Source
const TelemetryEnvelopeV1 = "v1"

Telemetry envelope schema versions (spec 07 R1.1). An empty EnvelopeVersion marks a legacy, pre-envelope record: it decodes and re-encodes byte-for-byte unchanged and is validated leniently for backward compatibility. A canonical record carries TelemetryEnvelopeV1 and is held to the strict v1 contract (R1.2/R1.3). Any other, unrecognized version is a *required* schema mismatch and fails closed.

View Source
const TemplateVersion = 2

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.

View Source
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

View Source
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.

View Source
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 --agent=pinky", "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:          "agents",
		Usage:         "specd agents [doctor | guide <slug>] [--json]",
		Description:   "Inspect agent artifacts, diagnose prerequisites, or emit deterministic driver guidance without writing.",
		AllowedPhases: anyPhase(),
		Examples:      []string{"specd agents", "specd agents doctor --json", "specd agents guide payments --json"},
		Flags:         []Flag{{Name: "json", TakesValue: false, Type: "bool", Description: "Emit JSON."}},
		ExitCodes:     stdCodes(),
	},
	{
		Name:          "adapters",
		Usage:         "specd adapters [--json]",
		Description:   "Inspect configured interoperability adapters read-only, distinguishing configured, missing, incompatible, and disabled without loading secrets or running anything.",
		AllowedPhases: anyPhase(),
		Examples:      []string{"specd adapters", "specd adapters --json"},
		Flags:         []Flag{{Name: "json", Type: "bool", Description: "Emit machine-readable JSON."}},
		ExitCodes:     stdCodes(),
	},
	{
		Name:          "eval",
		Usage:         "specd eval <import|status> <spec> [artifact]",
		Description:   "Import validated local eval evidence or inspect stored eval evidence.",
		AllowedPhases: anyPhase(),
		Examples:      []string{"specd eval import payments adapter.jsonl --task T1", "specd eval status payments --json"},
		Flags: []Flag{
			{Name: "json", Type: "bool", Description: "Emit machine-readable JSON."},
			{Name: "task", TakesValue: true, Type: "string", Description: "Expected task identity for import."},
			{Name: "check", TakesValue: true, Type: "string", Description: "Expected check identity for import."},
		},
		ExitCodes: stdCodes(),
	},
	{
		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", "specd new payments --agent=pinky"},
		Flags: []Flag{
			{Name: "agent", TakesValue: true, Type: "string", Description: "Select agent harness."},
		},
	},
	{
		Name:          "incident",
		Usage:         "specd incident seed <new-spec> --source-spec <spec> --release <id> --deployment <id> --criterion <id> --evidence-ref <ref[,ref]>",
		Description:   "Seed a new spec from bounded delivery observation references without loading raw payloads.",
		AllowedPhases: anyPhase(),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd incident seed checkout-recovery --source-spec checkout --release rel-7 --deployment dep-4 --criterion availability --evidence-ref obs://health/42"},
		Flags: []Flag{
			{Name: "source-spec", TakesValue: true, Type: "string", Description: "Source spec owning the immutable delivery ledger."},
			{Name: "release", TakesValue: true, Type: "string", Description: "Source release identity."},
			{Name: "deployment", TakesValue: true, Type: "string", Description: "Source deployment identity."},
			{Name: "criterion", TakesValue: true, Type: "string", Description: "Failed or observed health criterion."},
			{Name: "evidence-ref", TakesValue: true, Type: "string", Description: "Comma-separated bounded external references; queries, fragments, and raw payloads are refused."},
		},
	},
	{
		Name:          "archive",
		Usage:         "specd archive <spec> --successor <spec> --owner <owner> --evidence <ref>",
		Description:   "Retire a spec from active context while preserving content hashes and successor provenance.",
		AllowedPhases: anyPhase(),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd archive payments-v1 --successor payments-v2 --owner platform --evidence release:rel-7"},
		Flags: []Flag{
			{Name: "successor", TakesValue: true, Type: "string", Description: "Active successor spec receiving a supersedes link."},
			{Name: "owner", TakesValue: true, Type: "string", Description: "Accountable archive owner."},
			{Name: "evidence", TakesValue: true, Type: "string", Description: "Audit evidence reference authorizing retirement."},
		},
	},
	{
		Name:          "approve",
		Usage:         "specd approve <spec> <gate>",
		Description:   "Record human approval for a lifecycle gate or orchestrated mode.",
		AllowedPhases: anyPhase(),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd approve payments requirements", "specd approve payments design", "specd approve payments orchestrated"},
		HumanOnly:     true,
		Flags:         securityExceptionFlags(),
	},
	{
		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"},
		HumanOnly:     true,
		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"},
		HumanOnly:     true,
		Flags: []Flag{
			{Name: "text", TakesValue: true, Type: "string", Description: "Decision rationale (required)."},
			{Name: "scope", TakesValue: true, Type: "string", Description: "Optional scope label."},
		},
	},
	{
		Name:          "drift",
		Usage:         "specd drift <spec> [--json]",
		Description:   "Project declared invariants and active decisions against local verify evidence without writing.",
		AllowedPhases: anyPhase(),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd drift payments", "specd drift payments --json"},
		Flags:         []Flag{{Name: "json", Type: "bool", Description: "Emit stable JSON Lines."}},
	},
	{
		Name: "recurring", Usage: "specd recurring record <spec> --check <id> --head <sha> --release <id> --config <id> --verdict pass|fail --observed-at <RFC3339>",
		Description: "Validate and append an externally executed recurring-check result.", AllowedPhases: anyPhase(), ExitCodes: stdCodes(),
		Examples: []string{"specd recurring record payments --check api-health --head 0123456789012345678901234567890123456789 --release rel-7 --config prod-v3 --verdict pass --observed-at 2026-01-01T00:00:00Z"},
		Flags:    []Flag{{Name: "check", TakesValue: true, Type: "string", Description: "Recurring check identity."}, {Name: "head", TakesValue: true, Type: "string", Description: "Tested git HEAD."}, {Name: "release", TakesValue: true, Type: "string", Description: "Tested release identity."}, {Name: "config", TakesValue: true, Type: "string", Description: "Tested configuration identity."}, {Name: "verdict", TakesValue: true, Type: "string", Enum: []string{"pass", "fail"}, Description: "Check verdict."}, {Name: "observed-at", TakesValue: true, Type: "string", Description: "Explicit RFC3339 observation time."}},
	},
	{
		Name:          "spike",
		Usage:         "specd spike <spec> --question <q> --scope <s> --expiry <RFC3339> [--output <ref>]",
		Description:   "Record a bounded exploratory spike (learning without a completion or approval bypass).",
		AllowedPhases: anyPhase(),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd spike payments --question 'is webhook retry idempotent?' --scope 'payments/webhook' --expiry 2026-07-19T00:00:00Z"},
		Flags: []Flag{
			{Name: "question", TakesValue: true, Type: "string", Description: "Bounded question the spike explores (required)."},
			{Name: "scope", TakesValue: true, Type: "string", Description: "Bounded scope of the exploration (required)."},
			{Name: "expiry", TakesValue: true, Type: "string", Description: "RFC3339 instant after which the spike is stale (required, must be in the future)."},
			{Name: "output", TakesValue: true, Type: "string", Description: "Optional reference to the spike's output (attaches to a decision; never satisfies task evidence)."},
		},
	},
	{
		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 <spec> --guide [--json] | specd status --program",
		Description:   "Report current spec and task state, machine driving guidance, or the cross-spec program view.",
		AllowedPhases: anyPhase(),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd status payments", "specd status payments --json", "specd status payments --guide --json", "specd status --program"},
		Flags: []Flag{
			{Name: "json", Type: "bool", Description: "Emit machine-readable status."},
			{Name: "guide", Type: "bool", Description: "Emit machine driving guidance: phase, required artifact, legal commands, human-only actions, and blockers."},
			{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: "input-tokens", TakesValue: true, Type: "string", Description: "Optional provider-neutral input token count."},
			{Name: "output-tokens", TakesValue: true, Type: "string", Description: "Optional provider-neutral output token count."},
			{Name: "cached-tokens", TakesValue: true, Type: "string", Description: "Optional provider-neutral cached token count."},
			{Name: "provider", TakesValue: true, Type: "string", Description: "Optional bounded provider identifier."},
			{Name: "model", TakesValue: true, Type: "string", Description: "Optional bounded model identifier."},
			{Name: "currency", TakesValue: true, Type: "string", Description: "Currency unit required with canonical cost."},
			{Name: "pricing-ref", TakesValue: true, Type: "string", Description: "Pricing reference required with canonical cost."},
			{Name: "telemetry-source", TakesValue: true, Type: "string", Enum: []string{"worker", "provider_adapter", "operator"}, Description: "Telemetry provenance."},
			{Name: "attestation-ref", TakesValue: true, Type: "string", Description: "Optional external attestation reference."},
		},
	},
	{
		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),
		RequiresTask:  true,
		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: "input-tokens", TakesValue: true, Type: "string", Description: "Optional provider-neutral input token count."},
			{Name: "output-tokens", TakesValue: true, Type: "string", Description: "Optional provider-neutral output token count."},
			{Name: "cached-tokens", TakesValue: true, Type: "string", Description: "Optional provider-neutral cached token count."},
			{Name: "provider", TakesValue: true, Type: "string", Description: "Optional bounded provider identifier."},
			{Name: "model", TakesValue: true, Type: "string", Description: "Optional bounded model identifier."},
			{Name: "currency", TakesValue: true, Type: "string", Description: "Currency unit required with canonical cost."},
			{Name: "pricing-ref", TakesValue: true, Type: "string", Description: "Pricing reference required with canonical cost."},
			{Name: "telemetry-source", TakesValue: true, Type: "string", Enum: []string{"worker", "provider_adapter", "operator"}, Description: "Telemetry provenance."},
			{Name: "attestation-ref", TakesValue: true, Type: "string", Description: "Optional external attestation reference."},
		},
	},
	{
		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 [<spec>] [--json] [--expect-<identity> <value>]",
		Description:   "Emit a complete, drift-safe bootstrap identity packet.",
		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: "expect-managed-digest", TakesValue: true, Type: "string", Description: "Fail if managed guidance differs."},
			{Name: "expect-binary-version", TakesValue: true, Type: "string", Description: "Fail if binary version differs."},
			{Name: "expect-binary-commit", TakesValue: true, Type: "string", Description: "Fail if binary commit differs."},
			{Name: "expect-state-schema", TakesValue: true, Type: "string", Description: "Fail if state schema differs."},
			{Name: "expect-context-schema", TakesValue: true, Type: "string", Description: "Fail if context schema differs."},
			{Name: "expect-template-schema", TakesValue: true, Type: "string", Description: "Fail if template schema differs."},
			{Name: "expect-root", TakesValue: true, Type: "string", Description: "Fail if workspace root differs."},
			{Name: "expect-spec", TakesValue: true, Type: "string", Description: "Fail if active spec differs."},
			{Name: "expect-revision", TakesValue: true, Type: "string", Description: "Fail if state revision differs."},
		},
	},
	{
		Name:          "brain",
		Usage:         "specd brain <start|step|run|status|cancel|resume|claim|heartbeat|report> <spec> [args] [--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 claim payments payments.s1.T1 worker-1 craftsman", "specd brain heartbeat payments <lease-id> worker-1", "specd brain report payments <lease-id> worker-1"},
		Flags: []Flag{
			{Name: "authority", Type: "bool", Description: "Grant dispatch authority (fail-closed by default)."},
		},
	},
	{
		Name:          "report",
		Usage:         "specd report <spec> [--pr|--metrics|--efficiency|--rollup|--delivery|--outcome-review|--json|--history|--trace|--format prometheus|event|otel] | specd report --portfolio",
		Description:   "Render evidence-backed status, PR, history, trace, and metrics reports.",
		AllowedPhases: anyPhase(),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd report payments --pr", "specd report payments --metrics", "specd report payments --history", "specd report payments --trace", "specd report payments --format prometheus", "specd report payments --format otel"},
		Flags: []Flag{
			{Name: "pr", Type: "bool", Description: "Emit PR-oriented report."},
			{Name: "metrics", Type: "bool", Description: "Emit metrics summary."},
			{Name: "efficiency", Type: "bool", Description: "Emit deterministic context-efficiency report with explicit unknown values."},
			{Name: "rollup", Type: "bool", Description: "Emit exact cross-spec economic roll-up with explicit missing telemetry."},
			{Name: "delivery", Type: "bool", Description: "Emit deterministic deployment status with adapter and trust source labeled separately."},
			{Name: "portfolio", Type: "bool", Description: "Emit deterministic cross-spec release/environment status and blockers from local ledgers."},
			{Name: "outcome-review", Type: "bool", Description: "Join local change evidence to release and incident references, preserving missing outcomes as unknown."},
			{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: "trace", Type: "bool", Description: "Export the metadata-only run trace as stable JSON Lines."},
			{Name: "format", TakesValue: true, Type: "string", Enum: []string{"prometheus", "event", "otel"}, Description: "Alternate output format; event emits neutral local JSONL, prometheus emits metrics, otel emits adapter-mapped spans."},
		},
	},
	{
		Name:          "link",
		Usage:         "specd link <from-slug> <to-slug> [--kind <kind>] [--reason <text>]",
		Description:   "Record a typed, traceable cross-spec dependency link.",
		AllowedPhases: anyPhase(),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd link api auth", "specd link api-v2 api --kind supersedes --reason 'replace obsolete contract'"},
		Flags: []Flag{
			{Name: "kind", TakesValue: true, Type: "string", Enum: []string{"follows", "regresses", "maintains", "supersedes"}, Description: "Link kind (default: follows)."},
			{Name: "reason", TakesValue: true, Type: "string", Description: "Optional human-authored reason stored with the link."},
		},
	},
	{
		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,
	},
	{
		Name:          "release",
		Usage:         "specd release candidate <spec> --artifact-digest <d> --sbom-ref <r> --provenance-ref <r>",
		Description:   "Freeze an immutable, reproducible release candidate identity into releases.jsonl. Builds and uploads nothing.",
		AllowedPhases: anyPhase(),
		SpecSlugArg:   argAt(1),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd release candidate payments --artifact-digest sha256:abc --sbom-ref sbom://payments --provenance-ref prov://payments"},
		Flags: []Flag{
			{Name: "artifact-digest", TakesValue: true, Type: "string", Description: "Content digest of the already-built artifact (a reference; release never builds)."},
			{Name: "sbom-ref", TakesValue: true, Type: "string", Description: "Reference to the artifact's SBOM."},
			{Name: "provenance-ref", TakesValue: true, Type: "string", Description: "Reference to the artifact's provenance attestation."},
		},
	},
	{
		Name:          "deploy",
		Usage:         "specd deploy <spec> --release <id> --environment <env> --adapter <a> --authority <auth> [--strategy <s>] [--population <p>] [--window <w>] [--idempotency-key <k>]",
		Description:   "Append a monotonic deployment attempt to deployments.jsonl under the spec lock. Drives no external system.",
		AllowedPhases: anyPhase(),
		SpecSlugArg:   argAt(0),
		ExitCodes:     stdCodes(),
		Examples:      []string{"specd deploy payments --release a1b2c3 --environment staging --adapter shell --authority ci"},
		Flags: []Flag{
			{Name: "release", TakesValue: true, Type: "string", Description: "Frozen release-candidate id to deploy."},
			{Name: "environment", TakesValue: true, Type: "string", Description: "Target environment (development|staging|production)."},
			{Name: "adapter", TakesValue: true, Type: "string", Description: "Deployment adapter name (a reference; core drives nothing)."},
			{Name: "authority", TakesValue: true, Type: "string", Description: "Authority under which the attempt is recorded."},
			{Name: "strategy", TakesValue: true, Type: "string", Description: "Rollout strategy label."},
			{Name: "population", TakesValue: true, Type: "string", Description: "Target population label."},
			{Name: "window", TakesValue: true, Type: "string", Description: "Observation window label."},
			{Name: "idempotency-key", TakesValue: true, Type: "string", Description: "Caller-supplied idempotency key for the attempt."},
		},
	},
}

Commands is the stable top-level command palette.

View Source
var DefaultConfig = Config{
	Version: "1",
	Agent:   "codex",
	Profile: ProfileDefault,
	Gates: GatesConfig{
		Verify: "error",
	},
	Verify: VerifyConfig{
		Trivial: DefaultTrivialVerify,
	},
	Context: ContextConfig{
		MaxTokens: 12000,
	},
	Orchestration: OrchestrationConfig{
		Enabled: false,
		Model:   "",
	},
	Routing: RoutingConfig{
		Version:               "1",
		Classes:               []string{"default"},
		DefaultClass:          "default",
		Fallback:              []string{"default"},
		ClassCapabilities:     map[string][]string{"default": {"context", "eval", "review", "sandbox"}},
		MaxRetries:            3,
		AllowUnknownTelemetry: true,
		Recommendations:       map[string]string{},
	},
	Security: SecurityConfig{
		Profile:       "prototype",
		Secrets:       "error",
		Injection:     "warn",
		Slopsquat:     "warn",
		CleanWorktree: "off",
		Sandbox:       "off",
	},
	Escalation: EscalationConfig{
		MaxVerifyFails: EscalationDefaultMaxVerifyFails,
	},
	PromotionThreshold: 3,
}
View Source
var DefaultTrivialVerify = []string{"printf ok", "true", ":"}

DefaultTrivialVerify is the built-in set of no-op verify commands. A write task using any of these is rejected by the verify gate; read-only tasks may keep them (their `verify` is meant to be a trivial `printf ok`).

View Source
var ErrRevisionConflict = errors.New("state revision conflict")
View Source
var MetricLabelAllowlist = map[string]bool{
	"spec":    true,
	"source":  true,
	"status":  true,
	"verdict": true,
	"task":    true,
}

MetricLabelAllowlist is the closed set of label keys any specd metric series may carry (spec 07 R5.1). Metrics are a bounded-cardinality surface: `spec` and `task` are per-project identifiers, `status` and `verdict` are small closed enums. High-cardinality or sensitive correlation (run/mission/commit/path/model/actor/error) belongs in the trace JSONL, never in a metric label — each distinct value mints a new time series and can overwhelm a Prometheus store. Adding a label key outside this set must fail TestPrometheusLabelAllowlist.

View Source
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 AppendDeployment added in v0.4.0

func AppendDeployment(path string, d DeploymentV1) error

AppendDeployment validates and durably appends one deployment attempt.

func AppendEval added in v0.4.0

func AppendEval(path string, record EvidenceEnvelopeV1) error

func AppendEvidence added in v0.3.0

func AppendEvidence(path string, record EvidenceRecord) error

func AppendFile

func AppendFile(path, data string) error

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 AppendQualityLedger added in v0.4.0

func AppendQualityLedger(path string, entry QualityLedgerEntry) error

func AppendRelease added in v0.4.0

func AppendRelease(path string, r ReleaseCandidateV1) error

AppendRelease validates and durably appends one release candidate.

func AppendRun added in v0.4.0

func AppendRun(path string, run RunV1) error

AppendRun appends one record to the ledger with a single fsynced write, so a crash leaves either the prior complete record or one complete new record — never a partial line (spec 07 R2.4).

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 ApplyDeploymentAdapterEnvelope added in v0.4.0

func ApplyDeploymentAdapterEnvelope(root, slug string, envelope DeploymentAdapterEnvelopeV1) (DeploymentV1, AdapterAppendOutcome, error)

ApplyDeploymentAdapterEnvelope atomically checks idempotency and appends a validated attempt. Conflicts expose only content digests, preserving both audit facts without persisting hostile payload text or credentials.

func ArchiveRecordPath added in v0.4.0

func ArchiveRecordPath(root, slug string) string

func AtomicWrite

func AtomicWrite(path, data string) error

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 AuthorizeTool added in v0.4.0

func AuthorizeTool(a AuthorityV1, tool string, paths []string, now time.Time, phase string, mutable bool) error

func CanAdvanceStatus added in v0.3.0

func CanAdvanceStatus(from, to Status) bool

func CanonicalizeBootstrap added in v0.4.0

func CanonicalizeBootstrap(b *BootstrapV1)

func CanonicalizeDispatchV1 added in v0.4.0

func CanonicalizeDispatchV1(d *DispatchV1)

func CanonicalizeDriverGuide added in v0.4.0

func CanonicalizeDriverGuide(g *DriverGuideV1)

func CapabilityNames added in v0.4.0

func CapabilityNames() []string

func CommandNames added in v0.3.0

func CommandNames() []string

CommandNames returns command names in help order.

func CommitLink(remote, head string) string

func CompleteTask

func CompleteTask(rawTasks []byte, taskID string, records map[string]EvidenceRecord) ([]byte, error)

CompleteTask advances a task to done. Completion authority is verify/eval evidence alone: this function never reads the run ledger (runs.jsonl), so the evidence gate passes or fails identically whether that additive ledger is present or absent (spec 07 R2.3).

func CompleteTaskWithQuality added in v0.4.0

func CompleteTaskWithQuality(rawTasks []byte, taskID string, records map[string]EvidenceRecord, c QualityContract, evals []EvidenceEnvelopeV1, subject FreshnessSubject) ([]byte, error)

CompleteTaskWithQuality is CompleteTask plus the quality contract: after the no-bypass verify gate, it requires every declared evidence class/check to have a fresh passing record for the current subject (spec 04 R3.3, R3.4). A missing required record refuses with EVIDENCE_MISSING; a passing-but-stale one with EVIDENCE_STALE. A contract with no requirements degrades to CompleteTask, so legacy tasks stay unaffected.

func ConfigDigest added in v0.3.0

func ConfigDigest(config Config) string

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 ContextSchemaDigest added in v0.4.0

func ContextSchemaDigest() string

ContextSchemaDigest pins semantic context metadata, not context payloads. Keep field order explicit: this contract is consumed by external hosts.

func CountSpecsWithBlock added in v0.3.0

func CountSpecsWithBlock(root, key string) int

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

func CriteriaPath(root, slug string) string

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 DecisionPath added in v0.4.0

func DecisionPath(root, slug string) string

func DedupRolePrompts added in v0.3.0

func DedupRolePrompts(prompts []string) []string

func DeploymentAdapterConflictLedgerPath added in v0.4.0

func DeploymentAdapterConflictLedgerPath(root, slug string) string

func DeploymentLedgerPath added in v0.4.0

func DeploymentLedgerPath(root, slug string) string

DeploymentLedgerPath is the per-spec append-only deployment-attempt ledger (spec 08 R6.2). Attempts append under the spec lock; the evidence gate is neutral to its presence (R6.3).

func Digest added in v0.4.0

func Digest(data []byte) string

Digest returns the hex-encoded SHA-256 of data — the canonical content address used to pin approved requirement/design source bytes into a record so a later amendment can detect drift (spec 01 R5). Deterministic and pure.

func DispatchDigest added in v0.4.0

func DispatchDigest(d DispatchV1) string

func DriftPath added in v0.4.0

func DriftPath(root, slug string) string

func DriverDigest added in v0.4.0

func DriverDigest(v any) string

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 EvalManifestDigest added in v0.4.0

func EvalManifestDigest(m EvalManifestV1) (string, error)

func EvalStorePath added in v0.4.0

func EvalStorePath(root, slug string) string

func EvalTracePath added in v0.4.0

func EvalTracePath(root, slug, runID string) string

func EvidenceEnvelopeDigest added in v0.4.0

func EvidenceEnvelopeDigest(e EvidenceEnvelopeV1) string

func EvidencePath added in v0.3.0

func EvidencePath(root, slug string) string

func ExceptionPath added in v0.4.0

func ExceptionPath(root, slug string) string

func ExtractMemBlock added in v0.3.0

func ExtractMemBlock(text, key string) string

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 FinalizeAuthority added in v0.4.0

func FinalizeAuthority(a *AuthorityV1) error

func FindRoot added in v0.3.0

func FindRoot(start string) (string, error)

func FindingCode added in v0.4.0

func FindingCode(err error) string

func ForbiddenTool added in v0.3.0

func ForbiddenTool(name string) bool

func GuidanceDigest added in v0.4.0

func GuidanceDigest(root string) (string, error)

GuidanceDigest isolates managed guidance identity from palette/config and excludes user-owned bytes. ManagedDigest remains the compatibility name.

func HasPassingEvidence added in v0.3.0

func HasPassingEvidence(records map[string]EvidenceRecord, taskID string) bool

func HasTaskTrace added in v0.4.0

func HasTaskTrace(tasks []TaskRow) bool

func HeadPinned added in v0.3.0

func HeadPinned(gitHead string) bool

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 ImportEvals added in v0.4.0

func ImportEvals(raw []byte, expect ImportExpect) ([]EvidenceEnvelopeV1, []ImportFinding)

ImportEvals validates an adapter artifact deterministically and offline. It returns the accepted records only when there are zero findings: imported content cannot become proof before schema/policy validation passes (R3.2). A malformed/truncated/duplicate/wrong-task/wrong-check/wrong-digest record yields a stable ordered finding rather than a partial accept.

func IncidentPreventionPath added in v0.4.0

func IncidentPreventionPath(root, slug string) string

func IncidentSpecDocuments added in v0.4.0

func IncidentSpecDocuments(slug string, seed IncidentSeed) (requirements, design, tasks, memory string, err error)

func IsEscalated added in v0.3.0

func IsEscalated(consecutiveFails, maxFails int) bool

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 IsKnownRole added in v0.4.0

func IsKnownRole(role string) bool

IsKnownRole reports whether role is one of the canonical roles (spec 01 R4.1).

func IsTrivialVerify added in v0.4.0

func IsTrivialVerify(cmd string, trivial []string) bool

IsTrivialVerify reports whether cmd (trimmed) matches one of the trivial verify commands. Matching is exact on the trimmed command; a genuine verify that merely contains "true" as a substring is not trivial.

func IsWriteRole added in v0.4.0

func IsWriteRole(role string) bool

IsWriteRole reports whether role is permitted to write product code. Only the craftsman writes; scout, validator, and auditor are read-only. Used by the verify gate to reject a write task hiding behind a trivial verify (spec 01 R4.2).

func KnownRoles added in v0.4.0

func KnownRoles() []string

KnownRoles returns the canonical role names, derived from the embedded role files (the single source of truth also written to .specd/roles/). Sorted for deterministic gate findings.

func ListSpecs

func ListSpecs(root string) []string

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 project YAML, then environment overrides. The function is deterministic for the explicit path 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

func MCPConfigSnippet(host, root, spec string) (string, error)

MCPConfigSnippet returns a ready-to-paste MCP server configuration wiring `specd mcp` for the named host. Optional root pins the server's working directory. spec is reserved until MCP consumes the common resolver; no inert SPECD_SPEC pin is emitted. 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 ManagedDigest added in v0.4.0

func ManagedDigest(root string) (string, error)

ManagedDigest returns one stable identity for managed AGENTS.md, role, and steering regions. User-owned bytes outside managed markers are excluded. Missing or malformed regions remain part of the identity as "<missing>" so bootstrap pinning detects drift without preventing an operator from reading the current packet and repairing it.

func MergeAgents added in v0.3.0

func MergeAgents(existing, generated string) string

func MergePinkyCodexConfig added in v0.4.0

func MergePinkyCodexConfig(existing string) string

func MetricLabelNames added in v0.4.0

func MetricLabelNames(exposition string) []string

MetricLabelNames returns the sorted, de-duplicated label keys present in a Prometheus exposition. It is the inspector behind the static label allowlist (R5.1): any key it reports that MetricLabelAllowlist does not permit is a cardinality-policy violation.

func NewSpanID added in v0.4.0

func NewSpanID(specID string, kind SpanKind, sourceRank, seq int, reference string) string

NewSpanID derives a span's deterministic identity from its stable coordinates. (SourceRank, Seq) is unique per source record within a spec and never depends on wall-clock time, so the id — and therefore the whole export — is byte-identical on every run over the same tree (spec 07 R6.2).

func OverridePath added in v0.3.0

func OverridePath(root, slug string) string

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 PolicyDigest added in v0.4.0

func PolicyDigest(config Config) string

PolicyDigest is the SHA-256 of the effective lifecycle judgment policy: the profile and the criterion/review/integration gates it arms (spec 01 R7.2). It changes when the profile or any armed gate changes, so an approval pinned to it goes stale exactly when the policy that produced it moves.

func PreflightStateSchema added in v0.4.0

func PreflightStateSchema(raw []byte) error

PreflightStateSchema checks compatibility without decoding or mutating state. Installers use it before replacing a binary so future state cannot be opened by an older binary and silently downgraded.

func ProgramPath

func ProgramPath(root string) string

ProgramPath is the program-level link store.

func ProvenancePath added in v0.4.0

func ProvenancePath(root, slug string) string

func QualityCheckIDs added in v0.4.0

func QualityCheckIDs(policy QualityPolicy) map[string]bool

func ReadOrNull

func ReadOrNull(path string) *string

ReadOrNull returns the file contents, or nil when path does not exist.

func RecordFresh added in v0.4.0

func RecordFresh(e EvidenceEnvelopeV1, s FreshnessSubject) bool

RecordFresh reports whether e is current for subject s. A record is stale when it pins a different subject revision, or when it pins a digest that the subject also configures and the two disagree. A configured digest missing from the record is stale: absent provenance cannot prove currentness. An unconfigured subject dimension is not checked (R3.3). Freshness never deletes or rewrites records; stale records stay auditable in the store.

func RecordIncidentPrevention added in v0.4.0

func RecordIncidentPrevention(root, slug string, record IncidentPreventionV1) error

func RecordIsFresh added in v0.4.0

func RecordIsFresh(record FreshnessRecord, amendments []Amendment) bool

func RecordRecurringResult added in v0.4.0

func RecordRecurringResult(root, slug string, result RecurringResultV1) error

func RecurringResultsPath added in v0.4.0

func RecurringResultsPath(root, slug string) string

func ReleaseCandidateID added in v0.4.0

func ReleaseCandidateID(r ReleaseCandidateV1) string

ReleaseCandidateID is the reproducible content address of a candidate's identity (spec 08 R6.1). It hashes only the identity fields — spec revision, git HEAD, evidence-set/artifact/bootstrap digests, SBOM/provenance refs — so the same inputs always yield the same id. Metadata (schema, created_at) is excluded, making a re-freeze of an identical candidate idempotent.

func ReleaseLedgerPath added in v0.4.0

func ReleaseLedgerPath(root, slug string) string

ReleaseLedgerPath is the per-spec append-only release-candidate ledger (spec 08 R6.1). Candidates frozen here are immutable and reproducible.

func RenderEventsJSON added in v0.4.0

func RenderEventsJSON(events []EventV1) (string, error)

RenderEventsJSON emits canonical JSON Lines in caller-provided deterministic order. Struct field order and encoding/json's stable encoding make repeated renders byte-identical.

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 RenderLifecycleProof added in v0.4.0

func RenderLifecycleProof(p LifecycleProof) string

func RenderLifecycleProofJSON added in v0.4.0

func RenderLifecycleProofJSON(p LifecycleProof) (string, error)

func RenderMemBlock added in v0.3.0

func RenderMemBlock(f MemFields) string

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

func RenderPromotion(block, slug string, count int, date string, audits ...PromotionAudit) string

func RenderQualityReport added in v0.4.0

func RenderQualityReport(q QualityReport) string

func RenderReviewScaffold added in v0.3.0

func RenderReviewScaffold(slug, head string, tasks []TaskRow) string

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 RenderTraceJSON added in v0.4.0

func RenderTraceJSON(spans []RunSpan) (string, error)

RenderTraceJSON emits the run trace as JSON Lines in stable order (spec 07 R6.2). Every span is validated first, so a malformed kind or a code-effect span missing its git_head fails the export rather than emitting a silent gap. Span ids must be unique and every parent reference must resolve to a span in the same export.

func RequiredArtifact added in v0.4.0

func RequiredArtifact(status Status) string

RequiredArtifact is the source artifact a lifecycle status is producing, or "" once the planning artifacts are authored (execution phases produce evidence, not a single artifact).

func RequirementIDSet added in v0.4.0

func RequirementIDSet(raw string) map[string]bool

RequirementIDSet parses requirements.md bytes and returns the set of every requirement id and criterion id, for resolving design references. An empty or unparseable doc yields an empty set (the design gate then flags any declared reference as unresolved — fail closed).

func ResolveGitCommit added in v0.4.0

func ResolveGitCommit(root, revision string) error

func RestoreArchive added in v0.4.0

func RestoreArchive(root, slug string) error

RestoreArchive rolls a just-created archive back when coupled program commit fails.

func ReviewReportHead added in v0.3.0

func ReviewReportHead(raw string) string

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

func ReviewReportPath(root, slug string) string

ReviewReportPath is the per-spec review report the auditor role fills.

func RewriteTaskStatusLine added in v0.3.0

func RewriteTaskStatusLine(raw []byte, id string, marker string) ([]byte, error)

func RolePrompt added in v0.3.0

func RolePrompt(role string) string

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. Unknown roles fail closed and never inherit craftsman prose.

func RunID added in v0.4.0

func RunID(specID, taskID, baseline string) string

RunID derives the deterministic run-chain identity from the spec, task, and a baseline (the git HEAD at chain start). It is a content address — never a provider trace ID — so the same task/baseline always yields the same key (spec 07 R2.1). The 16-hex prefix is ample: collisions across one spec's tasks are astronomically unlikely and a chain is disambiguated by spec+task anyway.

func RunLedgerPath added in v0.4.0

func RunLedgerPath(root, slug string) string

RunLedgerPath is the per-spec append-only run/attempt ledger.

func SafeJoin added in v0.4.0

func SafeJoin(root, rel string) (string, error)

SafeJoin resolves a slash-separated repo-relative path against root, refusing empty input, absolute paths, and traversal ("..") that escapes the base. It returns the cleaned absolute path. It performs no symlink resolution and does not require existence — callers that need those (see context.ResolveSource) layer them on top.

func SaveProgram

func SaveProgram(path string, program Program) error

SaveProgram writes the program atomically at the current schema version.

func SaveState

func SaveState(path string, state State) error

func SaveStateCAS added in v0.3.0

func SaveStateCAS(path string, expectedRevision int64, state State) error

func SerializeTasksMd added in v0.3.0

func SerializeTasksMd(doc TasksMd) []byte

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 SortSpans added in v0.4.0

func SortSpans(spans []RunSpan)

SortSpans orders spans by timestamp, then by the (SourceRank, Seq) tie-break, giving a total order stable across runs even when timestamps are equal or absent (spec 07 R6.2). No ordering decision is load-bearing for any outcome — timestamps are informational (R6.3).

func SortedCriterionIDs added in v0.4.0

func SortedCriterionIDs(policy QualityPolicy) []string

func SortedReportTaskIDs added in v0.3.0

func SortedReportTaskIDs(model ReportModel) []string

func SpecMemoryPath added in v0.3.0

func SpecMemoryPath(root, slug string) string

SpecMemoryPath is the per-spec steering-memory store (RM.1).

func SpecdDir

func SpecdDir(root string) string

func StatePath added in v0.3.0

func StatePath(root, slug string) string

func SteeringMemoryPath added in v0.3.0

func SteeringMemoryPath(root string) string

SteeringMemoryPath is the shared steering store promotions land in (RM.3).

func SubmissionsPath added in v0.3.0

func SubmissionsPath(root, slug string) string

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

func SummaryHash(summary string) string

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 SupportedToolCapabilities added in v0.4.0

func SupportedToolCapabilities(contracts []ToolContract, phase Phase) []string

SupportedToolCapabilities returns deterministic non-human capabilities available from the canonical palette in one phase. Skill prose consumes this set but can never enlarge it.

func TruncateEvidenceOutput added in v0.4.0

func TruncateEvidenceOutput(output string) string

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 ValidMode added in v0.4.0

func ValidMode(mode Mode) bool

func ValidPhase added in v0.3.0

func ValidPhase(phase Phase) bool

func ValidSlug added in v0.3.0

func ValidSlug(slug string) bool

func ValidStatus added in v0.3.0

func ValidStatus(status Status) bool

func ValidateAnnotations added in v0.4.0

func ValidateAnnotations(a *Annotations) error

ValidateAnnotations enforces the telemetry envelope's decode/persist rules (spec 07 R1.2). A nil record is valid (absence is honest, never zero). A legacy record (no EnvelopeVersion) is grandfathered so old ledgers keep decoding (R1.1) — only an outright malformed decimal or negative unit is rejected. A canonical v1 record is held to the full contract: a known provenance, and cost paired with a currency. Any unrecognized required version fails closed. Optional fields left absent stay absent.

func ValidateAuthority added in v0.4.0

func ValidateAuthority(a AuthorityV1, now time.Time, phase string) error

func ValidateBootstrapV1 added in v0.4.0

func ValidateBootstrapV1(b BootstrapV1) error

func ValidateCIDeliveryBinding added in v0.4.0

func ValidateCIDeliveryBinding(candidate ReleaseCandidateV1, binding CIDeliveryBindingV1) error

func ValidateCIDeliveryEvent added in v0.4.0

func ValidateCIDeliveryEvent(event CIDeliveryEvent) error

func ValidateCanaryWindow added in v0.4.0

func ValidateCanaryWindow(d DeploymentV1, observations []HealthObservationV1, now time.Time) error

ValidateCanaryWindow proves observation lasted for the declared duration and every supplied fact binds the exact deployment/release/artifact/environment.

func ValidateDeliveryTransition added in v0.4.0

func ValidateDeliveryTransition(t DeliveryTransition) error

func ValidateDeployment added in v0.4.0

func ValidateDeployment(d DeploymentV1) error

func ValidateDispatchV1 added in v0.4.0

func ValidateDispatchV1(d DispatchV1) error

func ValidateEnvironment added in v0.4.0

func ValidateEnvironment(e EnvironmentV1) error

func ValidateEvalEvidenceManifests added in v0.4.0

func ValidateEvalEvidenceManifests(e EvidenceEnvelopeV1, dataset, rubric EvalManifestV1) error

ValidateEvalEvidenceManifests binds imported labelled evidence to the exact immutable dataset and rubric versions used to produce it.

func ValidateEvalManifest added in v0.4.0

func ValidateEvalManifest(m EvalManifestV1) error

func ValidateEvidenceEnvelope added in v0.4.0

func ValidateEvidenceEnvelope(e EvidenceEnvelopeV1) error

func ValidateGovernanceOwner added in v0.4.0

func ValidateGovernanceOwner(owner string) error

func ValidateHealthObservation added in v0.4.0

func ValidateHealthObservation(h HealthObservationV1) error

func ValidateIncidentSeed added in v0.4.0

func ValidateIncidentSeed(seed IncidentSeed) error

func ValidateMemoryProvenance added in v0.4.0

func ValidateMemoryProvenance(source string) error

ValidateMemoryProvenance admits only durable local evidence, review, or governed-exception references. Free-form notes cannot become selected memory.

func ValidatePreventiveEvidence added in v0.4.0

func ValidatePreventiveEvidence(record IncidentPreventionV1, required bool) error

func ValidateQualityLedgerEntry added in v0.4.0

func ValidateQualityLedgerEntry(e QualityLedgerEntry) error

func ValidateReleaseCandidate added in v0.4.0

func ValidateReleaseCandidate(r ReleaseCandidateV1) error

func ValidateReviewContract added in v0.4.0

func ValidateReviewContract(contract ReviewContract, status QualityStatus) error

ValidateReviewContract enforces test proof separately from human review.

func ValidateRollback added in v0.4.0

func ValidateRollback(r RollbackV1) error

func ValidateSlug

func ValidateSlug(slug string) error

func WithSpecLock

func WithSpecLock[T any](root string, fn func() (T, error)) (T, error)

WithSpecLock serializes harness work for one spec root and permits reentry from the same goroutine.

func WriteScaffold added in v0.3.0

func WriteScaffold(root string, agents ...string) error

Types

type AcceptanceCriterion added in v0.4.0

type AcceptanceCriterion struct {
	ID        string
	Critical  bool
	CheckIDs  []string
	Exception *QualityException
}

type AdapterAppendOutcome added in v0.4.0

type AdapterAppendOutcome string
const (
	AdapterAppendCreated  AdapterAppendOutcome = "created"
	AdapterAppendNoop     AdapterAppendOutcome = "noop"
	AdapterAppendConflict AdapterAppendOutcome = "conflict"
)

type AdapterTrustSource added in v0.4.0

type AdapterTrustSource string
const (
	AdapterTrustAttestedCI    AdapterTrustSource = "attested_ci"
	AdapterTrustSignedRuntime AdapterTrustSource = "signed_runtime"
	AdapterTrustOperatorFile  AdapterTrustSource = "operator_file"
)

type AgentDiscovery added in v0.4.0

type AgentDiscovery struct {
	Name    string   `json:"name"`
	Status  string   `json:"status"`
	Files   []string `json:"files,omitempty"`
	Missing []string `json:"missing,omitempty"`
	Invalid []string `json:"invalid,omitempty"`
}

func DiscoverAgents added in v0.4.0

func DiscoverAgents(root string) []AgentDiscovery

type AgentHost added in v0.3.0

type AgentHost struct {
	Name    string
	Detect  string
	Plan    string
	Install string
	Verify  string
}

func AgentHosts added in v0.3.0

func AgentHosts() []AgentHost

type Aggregation added in v0.4.0

type Aggregation string
const (
	AggregationMean Aggregation = "mean"
	AggregationMin  Aggregation = "min"
)

type Amendment added in v0.4.0

type Amendment struct {
	ChangeID         string            `json:"change_id"`
	AffectedIDs      []string          `json:"affected_ids"`
	Rationale        string            `json:"rationale"`
	BeforeDigests    map[string]string `json:"before_digests,omitempty"`
	AfterDigests     map[string]string `json:"after_digests,omitempty"`
	RequiredRechecks []string          `json:"required_rechecks"`
	RecordedRevision int64             `json:"recorded_revision,omitempty"`
	Timestamp        string            `json:"timestamp"`
	GitHead          string            `json:"git_head"`
	Actor            string            `json:"actor"`
}

Amendment is an append-only change-impact record. IDs are stable contract addresses (requirements, design units, or tasks); digests pin the source bytes before and after the change.

func StampAmendment added in v0.4.0

func StampAmendment(a Amendment, gitHead string) Amendment

func (Amendment) Validate added in v0.4.0

func (a Amendment) Validate() error

type Annotations added in v0.3.0

type Annotations struct {
	Tokens       int    `json:"tokens,omitempty"`
	InputTokens  int    `json:"input_tokens,omitempty"`
	OutputTokens int    `json:"output_tokens,omitempty"`
	CachedTokens int    `json:"cached_tokens,omitempty"`
	Cost         string `json:"cost,omitempty"`
	DurationMs   int    `json:"duration_ms,omitempty"`

	// Source is the trust provenance (worker|provider_adapter|operator, R1.3).
	// Currency pairs with Cost on canonical records (R1.2). AttestationRef is an
	// external, always-optional pointer to a provider attestation (R1.3).
	// EnvelopeVersion marks the schema; empty means legacy (grandfathered).
	Source          string `json:"telemetry_source,omitempty"`
	Currency        string `json:"currency,omitempty"`
	PricingRef      string `json:"pricing_ref,omitempty"`
	Provider        string `json:"provider,omitempty"`
	Model           string `json:"model,omitempty"`
	AttestationRef  string `json:"attestation_ref,omitempty"`
	EnvelopeVersion string `json:"envelope_version,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).

The envelope fields (spec 07 R1) are all omitempty so a legacy record (bare tokens/cost/duration) decodes unchanged and re-encodes byte-identically, while a canonical record round-trips its version and provenance byte-stably.

func ParseAnnotationFlags added in v0.4.0

func ParseAnnotationFlags(values map[string]string, present func(string) bool) (*Annotations, error)

ParseAnnotationFlags parses the additive provider-neutral flag set. New fields opt into canonical v1 validation; legacy-only flags retain old shape.

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.

func VerifyAttestation added in v0.4.0

func VerifyAttestation(env AttestedEnvelope, allowlistedKeys map[string][]byte) (Annotations, error)

type ArchiveRecord added in v0.4.0

type ArchiveRecord struct {
	SchemaVersion int            `json:"schema_version"`
	SpecID        string         `json:"spec_id"`
	SuccessorID   string         `json:"successor_id"`
	Owner         string         `json:"owner"`
	EvidenceRef   string         `json:"evidence_ref"`
	Files         []ArchivedFile `json:"files"`
	ManifestHash  string         `json:"manifest_hash"`
}

func ArchiveSpec added in v0.4.0

func ArchiveSpec(root string, req ArchiveRequest) (ArchiveRecord, error)

ArchiveSpec relocates immutable history from active discovery and writes a content-addressed audit manifest. Repeating the same request is idempotent.

func VerifyArchive added in v0.4.0

func VerifyArchive(root, slug string) (ArchiveRecord, error)

type ArchiveRequest added in v0.4.0

type ArchiveRequest struct {
	SpecID      string
	SuccessorID string
	Owner       string
	EvidenceRef string
}

type ArchivedFile added in v0.4.0

type ArchivedFile struct {
	Path   string `json:"path"`
	SHA256 string `json:"sha256"`
}

type AssetChange added in v0.3.0

type AssetChange struct {
	Name    string
	RelPath string
	Before  string
	After   string
}

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 AttestedEnvelope added in v0.4.0

type AttestedEnvelope struct {
	SchemaVersion  string          `json:"schema_version"`
	KeyID          string          `json:"key_id"`
	AttestationRef string          `json:"attestation_ref"`
	PayloadDigest  string          `json:"payload_digest"`
	Payload        json.RawMessage `json:"payload"`
	Signature      string          `json:"signature"`
}

AttestedEnvelope is adapter-produced, transport-neutral billing evidence. Key material stays in operator config; core only validates local bytes.

func SignAttestation added in v0.4.0

func SignAttestation(keyID string, key []byte, ref string, telemetry Annotations) (AttestedEnvelope, error)

type AuthorityV1 added in v0.4.0

type AuthorityV1 struct {
	SchemaVersion      string          `json:"schema_version"`
	ActorID            string          `json:"actor_id"`
	WorkerID           string          `json:"worker_id"`
	SpecID             string          `json:"spec_id"`
	TaskID             string          `json:"task_id"`
	Phase              string          `json:"phase"`
	Role               string          `json:"role"`
	Mode               string          `json:"mode"`
	AllowedTools       []ToolAuthority `json:"allowed_tools"`
	DeniedTools        []string        `json:"denied_tools,omitempty"`
	DeclaredReadPaths  []string        `json:"declared_read_paths"`
	DeclaredWritePaths []string        `json:"declared_write_paths"`
	NetworkPolicy      string          `json:"network_policy"`
	SandboxProfile     string          `json:"sandbox_profile"`
	BaselineRevision   string          `json:"baseline_revision"`
	IssuedAt           time.Time       `json:"issued_at"`
	ExpiresAt          time.Time       `json:"expires_at"`
	PolicyDigest       string          `json:"policy_digest"`
	Digest             string          `json:"digest"`
}

func BuildAuthority added in v0.4.0

func BuildAuthority(task TaskRow, actor, worker, slug, phase, baseline, policyDigest, sandbox string, issued, expires time.Time) (AuthorityV1, error)

type BootstrapV1 added in v0.4.0

type BootstrapV1 struct {
	ProtocolVersion     string          `json:"protocol_version"`
	Root                string          `json:"root"`
	Specs               []string        `json:"specs"`
	ActiveSpec          string          `json:"active_spec,omitempty"`
	Resolution          string          `json:"resolution,omitempty"`
	PaletteDigest       string          `json:"palette_digest"`
	ConfigDigest        string          `json:"config_digest"`
	GuidanceDigest      string          `json:"guidance_digest"`
	ContextSchemaDigest string          `json:"context_schema_digest"`
	Findings            []DriverFinding `json:"findings"`
}

type CIDeliveryBindingV1 added in v0.4.0

type CIDeliveryBindingV1 struct {
	SourceEvidenceDigest string          `json:"source_evidence_digest"`
	GitHead              string          `json:"git_head"`
	ArtifactDigest       string          `json:"artifact_digest"`
	SBOMRef              string          `json:"sbom_ref"`
	ProvenanceRef        string          `json:"provenance_ref"`
	Environment          EnvironmentName `json:"environment"`
	DeploymentID         string          `json:"deployment_id"`
	Attempt              int             `json:"attempt"`
}

CIDeliveryBindingV1 binds immutable source proof to one deployment attempt.

type CIDeliveryEvent added in v0.4.0

type CIDeliveryEvent struct {
	EventName                string
	Fork                     bool
	Environment              EnvironmentName
	HasProductionCredentials bool
}

type CIIdentityEnvelopeV1 added in v0.4.0

type CIIdentityEnvelopeV1 struct {
	SchemaVersion string       `json:"schema_version"`
	KeyID         string       `json:"key_id"`
	Claims        CIIdentityV1 `json:"claims"`
	Signature     string       `json:"signature"`
}

CIIdentityEnvelopeV1 is transport-neutral. Key lookup is an explicit local allowlist, keeping verification offline and deterministic.

func SignCIIdentity added in v0.4.0

func SignCIIdentity(keyID string, key ed25519.PrivateKey, claims CIIdentityV1) (CIIdentityEnvelopeV1, error)

type CIIdentityExpectation added in v0.4.0

type CIIdentityExpectation struct {
	Repository  string
	Environment EnvironmentName
	Audience    string
	Now         time.Time
}

type CIIdentityV1 added in v0.4.0

type CIIdentityV1 struct {
	Repository  string `json:"repository"`
	Environment string `json:"environment"`
	Audience    string `json:"audience"`
	Subject     string `json:"subject"`
	IssuedAt    string `json:"issued_at"`
	ExpiresAt   string `json:"expires_at"`
}

CIIdentityV1 contains only bounded identity claims needed to authorize a delivery. It deliberately carries no credential or provider token.

func VerifyCIIdentity added in v0.4.0

func VerifyCIIdentity(env CIIdentityEnvelopeV1, keys map[string]ed25519.PublicKey, want CIIdentityExpectation) (CIIdentityV1, error)

type CapabilityReport added in v0.4.0

type CapabilityReport struct {
	Results []CapabilityResult `json:"results"`
}

func NegotiateHostCapabilities added in v0.4.0

func NegotiateHostCapabilities(host HostCapabilities) CapabilityReport

NegotiateHostCapabilities applies deterministic policy before host actions. Sandbox is safety-critical and therefore refuses mutable execution without it; remaining optional features downgrade to the offline/local path.

type CapabilityResult added in v0.4.0

type CapabilityResult struct {
	Capability string           `json:"capability"`
	Status     CapabilityStatus `json:"status"`
	Reason     string           `json:"reason"`
	Recovery   string           `json:"recovery_action"`
}

type CapabilityStatus added in v0.4.0

type CapabilityStatus string
const (
	CapabilitySupported  CapabilityStatus = "supported"
	CapabilityDowngraded CapabilityStatus = "downgraded"
	CapabilityRefused    CapabilityStatus = "refused"
)

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"`
	// HumanOnly marks a verb that records human intent (approval, mid-course
	// decisions). Driving guidance lists these separately from machine-legal
	// commands so an agent never self-approves or fabricates a human decision
	// (spec 01 R6.1, R6.2 "not agent self-approval").
	HumanOnly bool `json:"human_only,omitempty"`
	// RequiresTask marks a verb that operates on an executable task (task
	// verify/context). Driving guidance suppresses these when a spec has no
	// executable task, so an agent is never told to verify or fetch context for
	// a task that does not exist (spec 01 R6.2).
	RequiresTask bool `json:"requires_task,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

func CommandByName(name string) (Command, bool)

CommandByName returns the command metadata for name, and whether it exists.

func (Command) AllowsPhase added in v0.3.0

func (c Command) AllowsPhase(phase Phase) bool

AllowsPhase reports whether the command may run in phase. A command that declares PhaseAny is unrestricted.

func (Command) FlagByName added in v0.3.0

func (c Command) FlagByName(name string) *Flag

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
	// Profile is the lifecycle strictness profile (spec 01 R7). "default" keeps
	// the backward-compatible policy where new completeness checks are opt-in
	// per-flag (R7.1). "production" raises the whole bar: it arms the criterion,
	// review, and integration/negative-path evidence gates together (R7.2),
	// regardless of the individual criteria.required / review.required switches.
	Profile            string
	Gates              GatesConfig
	Verify             VerifyConfig
	Context            ContextConfig
	Orchestration      OrchestrationConfig
	Routing            RoutingConfig
	Criteria           CriteriaConfig
	Review             ReviewConfig
	Submit             SubmitConfig
	Security           SecurityConfig
	Escalation         EscalationConfig
	PromotionThreshold int
	// Environments is the closed delivery policy per environment name (spec 08
	// R7.1). Empty by default — a project opts in. Keys are validated against the
	// closed EnvironmentName set; an unknown name or missing required field fails
	// closed at load time.
	Environments map[EnvironmentName]EnvironmentV1
}

Config is the deterministic runtime configuration used by the harness.

func (Config) CriteriaGateArmed added in v0.4.0

func (c Config) CriteriaGateArmed() bool

CriteriaGateArmed reports whether the per-criterion evidence ratchet must run: either the explicit criteria.required switch, or the production profile (which requires current criterion evidence, R7.2).

func (Config) IntegrationPolicyArmed added in v0.4.0

func (c Config) IntegrationPolicyArmed() bool

IntegrationPolicyArmed reports whether declared external/integration boundaries must carry error-path and integration evidence planning (R3.3). The production lifecycle profile arms it; security.profile=production keeps arming it for backward compatibility.

func (Config) ProductionProfile added in v0.4.0

func (c Config) ProductionProfile() bool

ProductionProfile reports whether the production lifecycle profile is armed. An empty profile resolves to the default profile.

func (Config) ReviewGateArmed added in v0.4.0

func (c Config) ReviewGateArmed() bool

ReviewGateArmed reports whether the review ratchet must run: either the explicit review.required switch, or the production profile (which requires a current-HEAD review, R7.2).

type ConfigParseError added in v0.3.0

type ConfigParseError struct {
	Line    int
	Message string
}

func (ConfigParseError) Error added in v0.3.0

func (e ConfigParseError) Error() string

type ConfigPaths

type ConfigPaths struct {
	Project string
}

type ContextConfig added in v0.3.0

type ContextConfig struct {
	MaxTokens int
}

type CoverageFinding added in v0.4.0

type CoverageFinding struct {
	Requirement string
	Message     string
}

func AnalyzeCoverage added in v0.4.0

func AnalyzeCoverage(requirements RequirementsDoc, design DesignDoc, tasks []TaskRow) []CoverageFinding

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 Criterion

type Criterion struct {
	ID       string
	Clause   string // the full normalized clause text after the ID
	Trigger  string // the "When <trigger>," portion, empty if not EARS-shaped
	Response string // the "shall <response>" portion, empty if not EARS-shaped
}

Criterion is a parsed `R<n>.<m>` acceptance clause with its EARS shape split into trigger ("When …") and response ("… shall …") when present.

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 DecisionV1 added in v0.4.0

type DecisionV1 struct {
	ID                 string           `json:"id"`
	Status             GovernanceStatus `json:"status"`
	Owner              string           `json:"owner"`
	CreatedAt          string           `json:"created_at"`
	ReviewAt           string           `json:"review_at"`
	ExpiresAt          string           `json:"expires_at"`
	Supersedes         string           `json:"supersedes,omitempty"`
	AffectedInvariants []string         `json:"affected_invariants,omitempty"`
}

DecisionV1 is one immutable governance assertion. Supersession is expressed by a later record's Supersedes link; EffectiveDecisionStatus projects the old record as superseded without rewriting history.

func AppendDecision added in v0.4.0

func AppendDecision(records []DecisionV1, next DecisionV1) ([]DecisionV1, error)

func DecisionChain added in v0.4.0

func DecisionChain(records []DecisionV1, id string) []DecisionV1

func LoadDecisions added in v0.4.0

func LoadDecisions(path string) ([]DecisionV1, error)

LoadDecisions decodes immutable records in append order. Missing file means governance is unconfigured; malformed or invalid content fails closed.

func (DecisionV1) ActiveAt added in v0.4.0

func (d DecisionV1) ActiveAt(now time.Time) bool

func (DecisionV1) Validate added in v0.4.0

func (d DecisionV1) Validate() error

type DeliveryIdentity added in v0.4.0

type DeliveryIdentity struct {
	ReleaseID      string          `json:"release_id"`
	ArtifactDigest string          `json:"artifact_digest"`
	Environment    EnvironmentName `json:"environment"`
}

type DeliveryTransition added in v0.4.0

type DeliveryTransition struct {
	From           DeploymentStatus
	To             DeploymentStatus
	Release        ReleaseCandidateV1
	Deployment     DeploymentV1
	Health         *HealthObservationV1
	RollbackTarget string
	Now            time.Time
}

type DeploymentAdapterConflictV1 added in v0.4.0

type DeploymentAdapterConflictV1 struct {
	SchemaVersion  string             `json:"schema_version"`
	IdempotencyKey string             `json:"idempotency_key"`
	ExistingDigest string             `json:"existing_digest"`
	IncomingDigest string             `json:"incoming_digest"`
	TrustSource    AdapterTrustSource `json:"trust_source"`
}

type DeploymentAdapterEnvelopeV1 added in v0.4.0

type DeploymentAdapterEnvelopeV1 struct {
	SchemaVersion  string             `json:"schema_version"`
	Kind           string             `json:"kind"`
	IdempotencyKey string             `json:"idempotency_key"`
	TrustSource    AdapterTrustSource `json:"trust_source"`
	AttestationRef string             `json:"attestation_ref,omitempty"`
	Deployment     DeploymentV1       `json:"deployment"`
	Message        string             `json:"message,omitempty"`
}

DeploymentAdapterEnvelopeV1 is Domain 08's additive payload contract. Domain 10 owns process execution and its common envelope; core accepts only this already-delivered JSON value and performs no network, subprocess, or credential discovery.

func DecodeDeploymentAdapterEnvelope added in v0.4.0

func DecodeDeploymentAdapterEnvelope(r io.Reader) (DeploymentAdapterEnvelopeV1, error)

DecodeDeploymentAdapterEnvelope reads one bounded JSON value. It never reads process environment, so provider credentials cannot enter through this API.

func ReadDeploymentAdapterEnvelope added in v0.4.0

func ReadDeploymentAdapterEnvelope(path string) (DeploymentAdapterEnvelopeV1, error)

type DeploymentStatus added in v0.4.0

type DeploymentStatus string
const (
	StatusRequested   DeploymentStatus = "requested"
	StatusStarted     DeploymentStatus = "started"
	StatusObserving   DeploymentStatus = "observing"
	StatusHealthy     DeploymentStatus = "healthy"
	StatusFailed      DeploymentStatus = "failed"
	StatusRollingBack DeploymentStatus = "rolling_back"
	StatusRolledBack  DeploymentStatus = "rolled_back"
)

type DeploymentV1 added in v0.4.0

type DeploymentV1 struct {
	Schema             string             `json:"schema"`
	DeploymentID       string             `json:"deployment_id"`
	Attempt            int                `json:"attempt"`
	ReleaseID          string             `json:"release_id"`
	GitHead            string             `json:"git_head"`
	ArtifactDigest     string             `json:"artifact_digest"`
	Environment        EnvironmentName    `json:"environment"`
	Status             DeploymentStatus   `json:"status"`
	Strategy           string             `json:"strategy"`
	Population         string             `json:"population"`
	Window             string             `json:"window"`
	Adapter            string             `json:"adapter"`
	Authority          string             `json:"authority"`
	Actor              string             `json:"actor"`
	IdempotencyKey     string             `json:"idempotency_key"`
	StartedAt          string             `json:"started_at"`
	FinishedAt         string             `json:"finished_at,omitempty"`
	TelemetrySource    string             `json:"telemetry_source"`
	EvidenceRef        string             `json:"evidence_ref"`
	AttestationRef     string             `json:"attestation_ref"`
	AdapterTrustSource AdapterTrustSource `json:"adapter_trust_source,omitempty"`
	AdapterMessage     string             `json:"adapter_message,omitempty"`
	Promotion          *PromotionV1       `json:"promotion,omitempty"`
	ExceptionRef       string             `json:"exception_ref,omitempty"`
}

func AppendDeploymentAttempt added in v0.4.0

func AppendDeploymentAttempt(root, slug string, d DeploymentV1) (DeploymentV1, error)

AppendDeploymentAttempt allocates the next monotonic attempt for d's deployment_id and durably appends it under the spec lock (spec 08 R6.2). The read-derive-append runs inside WithSpecLock, so racing writers cannot duplicate a (deployment_id, attempt) pair. The caller supplies every field except Attempt, which is derived from the ledger's highest attempt for that deployment_id.

func ReadDeployments added in v0.4.0

func ReadDeployments(path string) ([]DeploymentV1, error)

ReadDeployments replays the deployment ledger, dropping a torn final line.

type DerivedDiff added in v0.4.0

type DerivedDiff struct {
	Baseline string   `json:"baseline"`
	Paths    []string `json:"paths"`
	Digest   string   `json:"digest"`
}

func DeriveDiff added in v0.4.0

func DeriveDiff(root, baseline string) (DerivedDiff, error)

type DesignDoc added in v0.4.0

type DesignDoc struct {
	Raw    []byte
	Refs   []string          // requirement ids (R<n>/R<n>.<m>) the design traces to
	Fields map[string]string // decision-metadata label -> author value
}

DesignDoc is the normalized view of a design.md decision contract (spec 01 R2). It captures the metadata a human design approval must pin: the requirement references that trace the design to approved requirements, the module boundaries and interfaces it commits to, the invariants it preserves, its failure and integration modes, the alternatives weighed, the chosen disposition, and the human owner accountable for the choice. The parser is pure and byte-stable: Raw is a defensive copy the parser never rewrites.

func ParseDesign added in v0.4.0

func ParseDesign(raw []byte) DesignDoc

ParseDesign parses design.md bytes into a normalized decision contract. It never rewrites the author's bytes; completeness is judged by ValidateDesign, not here. Labels match case-insensitively. Requirement references are read only from an explicit `references:` bullet, so legacy design.md prose that merely contains an `R<n>` token is never misread as a trace (keeps default design.md files backward compatible).

func (DesignDoc) Digest added in v0.4.0

func (d DesignDoc) Digest() string

Digest returns the content address of the parsed source bytes — the digest an approval record pins so a later amendment can detect design drift (spec 01 R2.1 "and digest").

type DesignFinding added in v0.4.0

type DesignFinding struct {
	Ref     string
	Message string
}

DesignFinding is an addressable design-contract defect (spec 01 R2.2). Ref names the offending requirement reference, empty for a document-level defect.

func ValidateDesign added in v0.4.0

func ValidateDesign(doc DesignDoc, knownReqIDs map[string]bool, requireContract bool) []DesignFinding

ValidateDesign reports design-contract defects. An unknown requirement reference is always refused: a design tracing to a requirement that does not exist is a real defect (spec 01 R2.2). When requireContract is set — the production design profile (spec 01 R7.2) — the design must additionally declare every decision-metadata field and at least one resolvable requirement reference; under the default profile the contract fields are optional so legacy design.md files keep approving (R7.1). Pure: no disk, no clock.

type Diagnostic added in v0.3.0

type Diagnostic struct {
	Severity string
	Path     string
	Message  string
}

type DispatchV1 added in v0.4.0

type DispatchV1 struct {
	ProtocolVersion string   `json:"protocol_version"`
	Root            string   `json:"root"`
	SpecSlug        string   `json:"spec_slug"`
	TaskID          string   `json:"task_id"`
	Role            string   `json:"role"`
	DeclaredFiles   []string `json:"declared_files"`
	Acceptance      []string `json:"acceptance"`
	Verify          string   `json:"verify"`
	ContextRef      string   `json:"context_ref"`
	ContextDigest   string   `json:"context_digest"`
	ConfigDigest    string   `json:"config_digest"`
	PaletteDigest   string   `json:"palette_digest"`
	AuthorityRef    string   `json:"authority_ref"`
	SubjectHead     string   `json:"subject_head"`
	EnvelopeDigest  string   `json:"envelope_digest,omitempty"`
}

DispatchV1 is the transport-neutral, digest-pinned task packet. It contains identities and references only; repository bytes and worker output never cross this boundary.

type DriftDeclarationsV1 added in v0.4.0

type DriftDeclarationsV1 struct {
	SchemaVersion int                `json:"schema_version"`
	Invariants    []DriftInvariantV1 `json:"invariants"`
}

type DriftFinding added in v0.4.0

type DriftFinding struct {
	Source           string        `json:"source"`
	Path             string        `json:"path,omitempty"`
	Severity         DriftSeverity `json:"severity"`
	Status           DriftStatus   `json:"status"`
	LastPassingHead  string        `json:"last_passing_head,omitempty"`
	SuggestedCommand string        `json:"suggested_command,omitempty"`
}

func ProjectDrift added in v0.4.0

func ProjectDrift(invariants []DriftInvariantV1, decisions []DecisionV1, evidence []EvidenceRecord, asOf time.Time, slug string) []DriftFinding

ProjectDrift is a pure, read-only projection. Evidence order is append order; its last record supplies current status while the most recent pass remains auditable. Caller supplies evaluation time so identical inputs stay stable.

type DriftInvariantV1 added in v0.4.0

type DriftInvariantV1 struct {
	ID           string        `json:"id"`
	Path         string        `json:"path"`
	EvidenceTask string        `json:"evidence_task"`
	Severity     DriftSeverity `json:"severity"`
}

func LoadDriftDeclarations added in v0.4.0

func LoadDriftDeclarations(path string) ([]DriftInvariantV1, error)

func (DriftInvariantV1) Validate added in v0.4.0

func (d DriftInvariantV1) Validate() error

type DriftSeverity added in v0.4.0

type DriftSeverity string
const (
	DriftSeverityUnknown  DriftSeverity = "unknown"
	DriftSeverityLow      DriftSeverity = "low"
	DriftSeverityMedium   DriftSeverity = "medium"
	DriftSeverityHigh     DriftSeverity = "high"
	DriftSeverityCritical DriftSeverity = "critical"
)

type DriftStatus added in v0.4.0

type DriftStatus string
const (
	DriftHolds        DriftStatus = "holds"
	Drifted           DriftStatus = "drifted"
	DriftNotEvaluable DriftStatus = "not-evaluable"
	DriftNone         DriftStatus = "none"
)

type DriverFinding added in v0.4.0

type DriverFinding struct {
	Code           string `json:"code"`
	Severity       string `json:"severity"`
	Ref            string `json:"ref,omitempty"`
	Message        string `json:"message,omitempty"`
	RecoveryAction string `json:"recovery_action"`
}

func Doctor added in v0.4.0

func Doctor(root, pinned string) []DriverFinding

Doctor inspects agent-driving prerequisites and writes nothing.

type DriverGuideV1 added in v0.4.0

type DriverGuideV1 struct {
	ProtocolVersion string          `json:"protocol_version"`
	Root            string          `json:"root"`
	SpecSlug        string          `json:"spec_slug"`
	Phase           Phase           `json:"phase"`
	Status          Status          `json:"status"`
	Approvals       []string        `json:"approvals"`
	Frontier        []string        `json:"frontier"`
	Blockers        []DriverFinding `json:"blockers"`
	NextActions     []NextAction    `json:"next_actions"`
	EvidenceRefs    []string        `json:"evidence_refs"`
	Compatibility   string          `json:"compatibility"`
}

func ProjectDriverGuide added in v0.4.0

func ProjectDriverGuide(root, slug string, status Status, approvals, frontier []string, blockers []DriverFinding) DriverGuideV1

ProjectDriverGuide derives legal actions from lifecycle + canonical palette.

type EconomicDriftAlert added in v0.4.0

type EconomicDriftAlert struct {
	SpecID     string   `json:"spec_id"`
	CostDelta  string   `json:"cost_delta"`
	SourceRefs []string `json:"source_refs"`
}

type EnvironmentName added in v0.4.0

type EnvironmentName string
const (
	EnvironmentDevelopment EnvironmentName = "development"
	EnvironmentStaging     EnvironmentName = "staging"
	EnvironmentProduction  EnvironmentName = "production"
)

type EnvironmentV1 added in v0.4.0

type EnvironmentV1 struct {
	Schema            string          `json:"schema"`
	Name              EnvironmentName `json:"name"`
	Strategy          string          `json:"strategy"`
	RequiredApprover  string          `json:"required_approver,omitempty"`
	RequiredAuthority string          `json:"required_authority,omitempty"`
	HealthCriteria    []string        `json:"health_criteria"`
	ObservationWindow string          `json:"observation_window"`
	Freshness         string          `json:"freshness"`
	RollbackTarget    string          `json:"rollback_target"`
}

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 EscapedDefect added in v0.4.0

type EscapedDefect struct {
	AffectedID string   `json:"affected_id"`
	ChangeID   string   `json:"change_id"`
	Rechecks   []string `json:"rechecks"`
}

EscapedDefect links a corrective amendment to a requirement that already had passing evidence — a defect that escaped a green gate and its rechecks.

type EvalAggregation added in v0.4.0

type EvalAggregation struct {
	Status EvalPolicyStatus `json:"status"`
	Score  float64          `json:"score"`
}

func AggregateEval added in v0.4.0

func AggregateEval(p EvalPolicy, samples []EvalSample) EvalAggregation

AggregateEval consumes fixed imported samples only. It never scores or calls an adapter; insufficient samples and critical failures cannot pass.

type EvalCase added in v0.4.0

type EvalCase struct {
	ID     string   `json:"id"`
	Labels []string `json:"labels,omitempty"`
	Ref    string   `json:"ref"`
	Digest string   `json:"digest"`
}

type EvalManifestV1 added in v0.4.0

type EvalManifestV1 struct {
	SchemaVersion string      `json:"schema_version"`
	Kind          string      `json:"kind"`
	ID            string      `json:"id"`
	Owner         string      `json:"owner"`
	Version       string      `json:"version"`
	Digest        string      `json:"digest"`
	Cases         []EvalCase  `json:"cases"`
	CriticalCases []string    `json:"critical_cases,omitempty"`
	Redaction     string      `json:"redaction"`
	Source        string      `json:"source"`
	ReviewState   string      `json:"review_state"`
	Repetitions   int         `json:"repetitions"`
	Aggregation   Aggregation `json:"aggregation"`
	Threshold     float64     `json:"threshold"`
}

type EvalPolicy added in v0.4.0

type EvalPolicy struct {
	Scorer        ScorerMetadata `json:"scorer"`
	MinSamples    int            `json:"min_samples"`
	Repetitions   int            `json:"repetitions"`
	Aggregation   Aggregation    `json:"aggregation"`
	Threshold     float64        `json:"threshold"`
	CriticalCases []string       `json:"critical_cases,omitempty"`
}

type EvalPolicyFinding added in v0.4.0

type EvalPolicyFinding struct {
	Code    string `json:"code"`
	Message string `json:"message"`
}

func ValidateEvalPolicy added in v0.4.0

func ValidateEvalPolicy(p EvalPolicy) []EvalPolicyFinding

type EvalPolicyStatus added in v0.4.0

type EvalPolicyStatus string
const (
	EvalPolicyPass         EvalPolicyStatus = "pass"
	EvalPolicyFail         EvalPolicyStatus = "fail"
	EvalPolicyInsufficient EvalPolicyStatus = "insufficient"
)

type EvalSample added in v0.4.0

type EvalSample struct {
	CaseID string  `json:"case_id"`
	Score  float64 `json:"score"`
}

type EvalVerdict added in v0.4.0

type EvalVerdict string
const (
	EvalPass         EvalVerdict = "pass"
	EvalFail         EvalVerdict = "fail"
	EvalInsufficient EvalVerdict = "insufficient"
)

type EventV1 added in v0.4.0

type EventV1 struct {
	SchemaVersion   string   `json:"schema_version"`
	EventID         string   `json:"event_id"`
	RunID           string   `json:"run_id,omitempty"`
	SpanID          string   `json:"span_id,omitempty"`
	ParentSpanID    string   `json:"parent_span_id,omitempty"`
	SpecID          string   `json:"spec_id"`
	TaskID          string   `json:"task_id,omitempty"`
	Attempt         int      `json:"attempt,omitempty"`
	Kind            SpanKind `json:"kind"`
	Timestamp       string   `json:"timestamp,omitempty"`
	Status          string   `json:"status,omitempty"`
	GitHead         string   `json:"git_head,omitempty"`
	TelemetrySource string   `json:"telemetry_source,omitempty"`
	AttestationRef  string   `json:"attestation_ref,omitempty"`
	EvidenceRef     string   `json:"evidence_ref,omitempty"`
	Redactions      []string `json:"redactions,omitempty"`
}

EventV1 is the stable bridge between local run spans and external telemetry adapters. It deliberately has no prompt, response, file-content, raw-output, or arbitrary attributes field. Privacy decisions remain explicit metadata.

func EventFromSpan added in v0.4.0

func EventFromSpan(s RunSpan) EventV1

EventFromSpan projects the existing correlated local span without inventing identity or outcome. Timestamp remains informational.

func (EventV1) Validate added in v0.4.0

func (e EventV1) Validate() error

type EvidenceClass added in v0.4.0

type EvidenceClass string
const (
	EvidenceTest           EvidenceClass = "test"
	EvidenceOutputEval     EvidenceClass = "output_eval"
	EvidenceTrajectoryEval EvidenceClass = "trajectory_eval"
	EvidenceReview         EvidenceClass = "review"
)

type EvidenceEnvelopeV1 added in v0.4.0

type EvidenceEnvelopeV1 struct {
	SchemaVersion   string        `json:"schema_version"`
	EvidenceID      string        `json:"evidence_id"`
	EvidenceClass   EvidenceClass `json:"evidence_class"`
	SpecSlug        string        `json:"spec_slug"`
	TaskID          string        `json:"task_id"`
	RunID           string        `json:"run_id"`
	Attempt         int           `json:"attempt"`
	SubjectRevision string        `json:"subject_revision"`
	DiffDigest      string        `json:"diff_digest,omitempty"`
	Producer        string        `json:"producer"`
	ProducerVersion string        `json:"producer_version"`
	ConfigDigest    string        `json:"config_digest"`
	CheckID         string        `json:"check_id"`
	Verdict         EvalVerdict   `json:"verdict"`
	Score           *float64      `json:"score,omitempty"`
	CreatedAt       string        `json:"created_at"`
	Actor           string        `json:"actor"`
	ArtifactRef     string        `json:"artifact_ref"`
	ArtifactDigest  string        `json:"artifact_digest"`
	DatasetDigest   string        `json:"dataset_digest,omitempty"`
	RubricDigest    string        `json:"rubric_digest,omitempty"`
	OutputDigest    string        `json:"output_digest,omitempty"`
	TraceDigest     string        `json:"trace_digest,omitempty"`
	RequiredSteps   []string      `json:"required_steps,omitempty"`
	ForbiddenSteps  []string      `json:"forbidden_steps,omitempty"`
}

func AdaptLegacyVerify added in v0.4.0

func AdaptLegacyVerify(slug string, r EvidenceRecord) EvidenceEnvelopeV1

func LoadEvals added in v0.4.0

func LoadEvals(path string) ([]EvidenceEnvelopeV1, error)

type EvidencePolicyFinding added in v0.4.0

type EvidencePolicyFinding struct{ Message string }

func BoundaryEvidenceFindings added in v0.4.0

func BoundaryEvidenceFindings(design DesignDoc, tasks []TaskRow, production bool) []EvidencePolicyFinding

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"`
	// ContextReceiptDigest pins context identity used for this attempt. It is
	// optional for backward compatibility and never substitutes for exit-code
	// evidence or a resolvable Git HEAD.
	ContextReceiptDigest string `json:"context_receipt_digest,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 EvidenceRequirement added in v0.4.0

type EvidenceRequirement struct {
	EvidenceClass EvidenceClass `json:"evidence_class"`
	CheckID       string        `json:"check_id"`
}

func MissingQualityEvidence added in v0.4.0

func MissingQualityEvidence(c QualityContract, records []EvidenceEnvelopeV1) []EvidenceRequirement

type ExceptionV1 added in v0.4.0

type ExceptionV1 struct {
	ID                 string           `json:"id"`
	Status             GovernanceStatus `json:"status"`
	Owner              string           `json:"owner"`
	CreatedAt          string           `json:"created_at"`
	ReviewAt           string           `json:"review_at"`
	ExpiresAt          string           `json:"expires_at"`
	Supersedes         string           `json:"supersedes,omitempty"`
	AffectedInvariants []string         `json:"affected_invariants,omitempty"`
	Blocking           bool             `json:"blocking,omitempty"`
}

ExceptionV1 is a time-bound governed deviation. Like decisions, records are immutable; revocation and supersession are later records, never deletion.

func LoadGovernanceExceptions added in v0.4.0

func LoadGovernanceExceptions(path string) ([]ExceptionV1, error)

func (ExceptionV1) Validate added in v0.4.0

func (e ExceptionV1) Validate() error

type ExitCode added in v0.3.0

type ExitCode struct {
	Code    int    `json:"code"`
	Meaning string `json:"meaning"`
}

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 FreshnessRecord added in v0.4.0

type FreshnessRecord struct {
	Key          string
	Kind         string
	SourceDigest string
	Revision     int64
	DependsOn    []string
}

type FreshnessReport added in v0.4.0

type FreshnessReport struct {
	Current []string `json:"current,omitempty"`
	Stale   []string `json:"stale,omitempty"`
}

func EvaluateFreshness added in v0.4.0

func EvaluateFreshness(records []FreshnessRecord, amendments []Amendment) FreshnessReport

type FreshnessSubject added in v0.4.0

type FreshnessSubject struct {
	Revision      string
	DiffDigest    string
	OutputDigest  string
	DatasetDigest string
	RubricDigest  string
	TraceDigest   string
}

FreshnessSubject is the current, reachable state a required evidence record must match to still count as proof (spec 04 R3.3). Revision is the subject commit; the digest fields are the configured current subject digests the completion policy pins. A zero field means "not configured": that dimension is not checked, so an empty subject verifies nothing (parity — legacy specs with no quality policy keep completing on verify alone).

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 GovernanceItem added in v0.4.0

type GovernanceItem struct {
	ID        string           `json:"id"`
	Status    GovernanceStatus `json:"status"`
	ReviewAt  string           `json:"review_at,omitempty"`
	ExpiresAt string           `json:"expires_at,omitempty"`
}

type GovernanceStatus added in v0.4.0

type GovernanceStatus string

GovernanceStatus is shared by decisions and exceptions. Values are closed; unknown values fail validation instead of being silently reinterpreted.

const (
	GovernanceProposed   GovernanceStatus = "proposed"
	GovernanceAccepted   GovernanceStatus = "accepted"
	GovernanceSuperseded GovernanceStatus = "superseded"
	GovernanceExpired    GovernanceStatus = "expired"
	GovernanceRevoked    GovernanceStatus = "revoked"
)

func EffectiveDecisionStatus added in v0.4.0

func EffectiveDecisionStatus(records []DecisionV1, id string) GovernanceStatus

type Guidance added in v0.4.0

type Guidance struct {
	Status           Status   `json:"status"`
	Phase            Phase    `json:"phase"`
	RequiredArtifact string   `json:"required_artifact,omitempty"`
	NextGate         Status   `json:"next_gate,omitempty"`
	LegalCommands    []string `json:"legal_commands"`
	HumanOnly        []string `json:"human_only"`
	Blockers         []string `json:"blockers,omitempty"`
}

Guidance is the machine-readable driving guidance for one lifecycle phase (spec 01 R6.1). It separates what a machine actor may legally do (LegalCommands) from what only a human may do (HumanOnly, e.g. approval), so an agent never treats approval as a self-serve action; it also names the artifact the phase must produce (RequiredArtifact) and any Blockers the caller resolved from state. NextGate is the gate a human must clear to advance.

func GuidanceForPhase added in v0.4.0

func GuidanceForPhase(status Status, blockers []string) Guidance

GuidanceForPhase builds the driving guidance for status. Blockers are supplied by the caller (the deterministic gate failures for the next transition); this function is pure over the command palette. Deferred verbs and verbs not legal in the phase are omitted; human-only verbs are listed separately so an agent cannot mistake approval for a machine action (spec 01 R6).

type Handshake added in v0.3.0

type Handshake struct {
	Version               string             `json:"version"`
	Agent                 string             `json:"agent,omitempty"`
	Tools                 []string           `json:"tools"`
	Binary                version.Info       `json:"binary"`
	StateSchemaVersion    int                `json:"state_schema_version"`
	ContextSchemaVersion  string             `json:"context_schema_version"`
	TemplateSchemaVersion int                `json:"template_schema_version"`
	WorkspaceRoot         string             `json:"workspace_root"`
	ActiveSpec            *HandshakeSpec     `json:"active_spec,omitempty"`
	ManagedDigest         string             `json:"managed_digest"`
	GuidanceDigest        string             `json:"guidance_digest"`
	ContextSchemaDigest   string             `json:"context_schema_digest"`
	NextCommands          []string           `json:"next_commands"`
	Authority             HandshakeAuthority `json:"authority"`
	// 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"`
	// PolicyDigest pins the effective lifecycle judgment policy (spec 01 R7.2):
	// the profile plus the criterion/review/integration gates it arms. It lets a
	// later approval detect that the policy governing an earlier decision has
	// changed, without diffing the whole config.
	PolicyDigest  string         `json:"policy_digest"`
	ToolContracts []ToolContract `json:"tool_contracts"`
}

func BootstrapHandshake added in v0.3.0

func BootstrapHandshake(config Config) Handshake

func BootstrapHandshakeForRoot added in v0.4.0

func BootstrapHandshakeForRoot(root string, config Config, state *State, nextCommands []string) (Handshake, error)

BootstrapHandshakeForRoot emits one production-driver preflight packet. It is read-only: callers can validate every pinned identity before mutation.

type HandshakeAuthority added in v0.4.0

type HandshakeAuthority struct {
	HarnessInstructions []string `json:"harness_instructions"`
	UntrustedInputs     []string `json:"untrusted_inputs"`
}

type HandshakeSpec added in v0.4.0

type HandshakeSpec struct {
	Slug     string `json:"slug"`
	Status   Status `json:"status"`
	Revision int64  `json:"revision"`
}

type HealthObservationV1 added in v0.4.0

type HealthObservationV1 struct {
	Schema          string               `json:"schema"`
	DeploymentID    string               `json:"deployment_id"`
	CriterionID     string               `json:"criterion_id"`
	HealthCheck     string               `json:"health_check"`
	Threshold       string               `json:"threshold"`
	Observation     string               `json:"observation"`
	Freshness       ObservationFreshness `json:"freshness"`
	ReleaseIdentity DeliveryIdentity     `json:"release_identity"`
	Source          string               `json:"source"`
}

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:"-"`

	// TaskID is the in-process run-correlation key (spec 07 R6): the trace
	// exporter reuses it to attach a span to the W2 run chain and to link
	// activity spans to their task's dispatch. Not serialized — history JSON
	// stays byte-identical; the task already travels in Reference for readers.
	TaskID string `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.

func (HistoryEvent) SpanKind added in v0.4.0

func (e HistoryEvent) SpanKind() (SpanKind, bool)

SpanKind maps a history event to its trace span kind and reports whether the event is a trace-worthy activity (spec 07 R6.1). This is the single place event names become span kinds, so the trace exporter and the audit replay never drift. Bookkeeping events without a code, evaluation, or dispatch effect — decisions, mid-requirement notes, submissions, ACP claim/report transport — are not spans and return false.

type HostCapabilities added in v0.4.0

type HostCapabilities struct {
	ContextLoading bool `json:"context_loading"`
	Sandbox        bool `json:"sandbox"`
	Telemetry      bool `json:"telemetry"`
	Eval           bool `json:"eval"`
	A2A            bool `json:"a2a"`
}

HostCapabilities describes optional host features. False is explicit: the negotiation result still reports every capability, so omission cannot hide a downgrade or refusal.

type ImportExpect added in v0.4.0

type ImportExpect struct {
	SpecSlug string
	TaskID   string
	// CheckIDs, when non-empty, restricts accepted records to these check ids: a
	// record naming any other check fails closed (R3.2 wrong-check).
	CheckIDs []string
	// Artifacts maps a record's artifact_ref to the referenced content. When an
	// imported record's ArtifactRef has an entry, import recomputes its digest and
	// rejects a mismatch (R3.2 wrong-digest). Absent ref ⇒ digest not verifiable
	// here, left to the storing gate.
	Artifacts map[string][]byte
	// Traces maps a trajectory record's artifact_ref to the normalized trace
	// bytes; import recomputes their digest and rejects a TraceDigest mismatch
	// (spec 04 R4.2 trace digest validation).
	Traces map[string][]byte
}

ImportExpect constrains what an imported adapter artifact may contain. Zero value means "no constraint": import still validates schema/provenance, but does not pin the record to a task/check/artifact. Every field is a local, caller-supplied fact — import never contacts a provider, model, or network (spec 04 R3.1).

type ImportFinding added in v0.4.0

type ImportFinding struct {
	Index      int
	EvidenceID string
	Code       string
	Message    string
}

ImportFinding is one stable, ordered reason an artifact record was rejected. Index is the record's position in the artifact (0-based); findings sort by Index then Code so the same bad artifact always reports the same sequence.

func ImportEvalsToStore added in v0.4.0

func ImportEvalsToStore(path string, raw []byte, expect ImportExpect) ([]ImportFinding, error)

ImportEvalsToStore validates an adapter artifact and appends every accepted record to the store, refusing anything already present (R3.2 duplicate). It returns import findings (the artifact was rejected as a whole and nothing was written) or nil on success. Duplicate detection against the existing store is done up front so a partly-duplicate artifact never leaves a partial write.

type IncidentPreventionV1 added in v0.4.0

type IncidentPreventionV1 struct {
	SchemaVersion int            `json:"schema_version"`
	Kind          PreventionKind `json:"kind"`
	Owner         string         `json:"owner"`
	EvidenceRef   string         `json:"evidence_ref"`
	WhyCaughtRef  string         `json:"why_caught_ref"`
}

IncidentPreventionV1 is append-only closure evidence. Owner is always a human/team identity; EvidenceRef and WhyCaughtRef point to durable evidence rather than copying potentially sensitive payloads into context.

func LoadIncidentPrevention added in v0.4.0

func LoadIncidentPrevention(path string) ([]IncidentPreventionV1, error)

type IncidentSeed added in v0.4.0

type IncidentSeed struct {
	SourceSpec   string
	ReleaseID    string
	DeploymentID string
	CriterionID  string
	EvidenceRefs []string
}

IncidentSeed contains bounded identity and reference facts only. Raw external payloads are intentionally absent so they cannot enter standing context.

type IncidentSuccessorPlan added in v0.4.0

type IncidentSuccessorPlan struct {
	Provenance ProvenanceV1 `json:"provenance"`
	Link       ProgramLink  `json:"link"`
}

func PlanIncidentSuccessor added in v0.4.0

func PlanIncidentSuccessor(successor string, seed IncidentSeed) (IncidentSuccessorPlan, error)

PlanIncidentSuccessor is a deterministic projection. Caller persists only successor-owned artifacts and program link; source spec remains untouched.

type LifecycleProof added in v0.4.0

type LifecycleProof struct {
	Slug       string          `json:"slug"`
	Coverage   []ProofCoverage `json:"coverage"`
	Stale      []string        `json:"stale,omitempty"`
	Amendments []Amendment     `json:"amendments,omitempty"`
	Escaped    []EscapedDefect `json:"escaped_defects,omitempty"`
}

LifecycleProof is the deterministic R8.2 report: requirement-to-evidence coverage, stale approval records, amendments, and escaped-defect links. It is a pure projection of on-disk state; identical inputs render identical bytes.

func BuildLifecycleProof added in v0.4.0

func BuildLifecycleProof(slug string, coverage []ProofCoverage, stale []string, amendments []Amendment) LifecycleProof

type LinkKind added in v0.4.0

type LinkKind string
const (
	LinkKindFollows    LinkKind = "follows"
	LinkKindRegresses  LinkKind = "regresses"
	LinkKindMaintains  LinkKind = "maintains"
	LinkKindSupersedes LinkKind = "supersedes"
)

func (LinkKind) Valid added in v0.4.0

func (kind LinkKind) Valid() bool

type MaintenanceTemplate added in v0.4.0

type MaintenanceTemplate struct {
	Name    string
	Schema  string
	Version int
	Body    string
}

MaintenanceTemplate describes one inspectable, embedded maintenance intake template. Templates contain guidance only; gates remain deterministic.

func MaintenanceTemplates added in v0.4.0

func MaintenanceTemplates() ([]MaintenanceTemplate, error)

MaintenanceTemplates returns embedded templates in stable name order.

func PolicyTemplates added in v0.4.0

func PolicyTemplates() ([]MaintenanceTemplate, error)

PolicyTemplates returns optional organization policy starters. Policy text is inspectable and operator-owned outside managed markers; it never changes gates.

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

type MarkdownTable struct {
	Header []string
	Rows   [][]string
}

MarkdownTable stores one parsed pipe table while retaining the original bytes.

type MemBlock added in v0.4.0

type MemBlock struct {
	Key, Pattern, Detail, Source, Criticality, Related, Status, SupersededBy, AppliesTo, Raw, Digest string
	Owner, LastValidatedAt, Provenance, Confidence, ExpiresAt, Supersedes                            string
}

MemBlock is one indexed H2 memory record. Raw preserves selected bytes; Digest pins that representation without exposing it in a manifest.

func IndexMemBlocks added in v0.4.0

func IndexMemBlocks(text string) ([]MemBlock, error)

IndexMemBlocks parses memory into a stable key-sorted block index. Duplicate keys fail closed because a selector must identify exactly one representation.

type MemFields added in v0.3.0

type MemFields struct {
	Key                                                                   string
	Pattern                                                               string
	Detail                                                                string
	Source                                                                string
	Criticality                                                           string
	Related                                                               string
	Owner, LastValidatedAt, Provenance, Confidence, ExpiresAt, Supersedes 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 MemoryLintFinding added in v0.4.0

type MemoryLintFinding struct{ Key, Message string }

func AnalyzeMemoryConflicts added in v0.4.0

func AnalyzeMemoryConflicts(blocks []MemBlock, asOf time.Time) []MemoryLintFinding

AnalyzeMemoryConflicts finds only deterministic, explicit conflicts. Unknown confidence is never treated as evidence; stale/superseded records are ignored.

type Mode added in v0.3.0

type Mode string
const (
	ModeDefault      Mode = "default"
	ModeAgent        Mode = "agent"
	ModeOrchestrated Mode = "orchestrated"
)

type NextAction added in v0.4.0

type NextAction struct {
	ID                string   `json:"id"`
	Command           string   `json:"command"`
	Args              []string `json:"args,omitempty"`
	Actor             string   `json:"actor"`
	SideEffect        string   `json:"side_effect"`
	AuthorityRequired bool     `json:"authority_required"`
	AllowedPhases     []Phase  `json:"allowed_phases"`
	SourceRef         string   `json:"source_ref"`
	Reason            string   `json:"reason,omitempty"`
}

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 ObservationFreshness added in v0.4.0

type ObservationFreshness struct {
	ObservedAt      string `json:"observed_at"`
	MaxAge          string `json:"max_age"`
	WindowStartedAt string `json:"window_started_at,omitempty"`
}

type OrchestrationConfig added in v0.3.0

type OrchestrationConfig struct {
	Enabled bool
	Model   string
}

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 AdvanceStatus(current, next Status) (Phase, error)

func PhaseForStatus

func PhaseForStatus(status Status) Phase

type PortfolioBlocker added in v0.4.0

type PortfolioBlocker struct {
	SpecID    string   `json:"spec_id"`
	BlockedBy []string `json:"blocked_by"`
}

type PortfolioEnvironment added in v0.4.0

type PortfolioEnvironment struct {
	SpecID      string           `json:"spec_id"`
	Environment EnvironmentName  `json:"environment"`
	ReleaseID   string           `json:"release_id"`
	Status      DeploymentStatus `json:"status"`
}

type PortfolioGovernanceEdge added in v0.4.0

type PortfolioGovernanceEdge struct {
	From  string    `json:"from"`
	To    string    `json:"to"`
	Kind  LinkKind  `json:"kind"`
	Risk  RiskLevel `json:"risk"`
	Owner string    `json:"owner"`
}

type PortfolioGovernanceInput added in v0.4.0

type PortfolioGovernanceInput struct {
	SpecID            string
	Complete          bool
	Risk              RiskLevel
	Owner             string
	Governance        []GovernanceItem
	ProductionSignals []ProductionSignal
	SharedOutcomes    []SharedOutcome
}

type PortfolioGovernanceSpec added in v0.4.0

type PortfolioGovernanceSpec struct {
	SpecID             string             `json:"spec_id"`
	Complete           bool               `json:"complete"`
	Risk               RiskLevel          `json:"risk"`
	Owner              string             `json:"owner"`
	StaleGovernance    []string           `json:"stale_governance,omitempty"`
	ProductionSignals  []ProductionSignal `json:"production_signals,omitempty"`
	SharedOutcomes     []SharedOutcome    `json:"shared_outcomes,omitempty"`
	UnresolvedSignals  []string           `json:"unresolved_signals,omitempty"`
	IncompleteOutcomes []string           `json:"incomplete_outcomes,omitempty"`
}

type PortfolioGovernanceStatus added in v0.4.0

type PortfolioGovernanceStatus struct {
	Specs    []PortfolioGovernanceSpec `json:"specs"`
	Edges    []PortfolioGovernanceEdge `json:"edges"`
	Blockers []PortfolioBlocker        `json:"blockers"`
	Complete bool                      `json:"complete"`
}

func BuildPortfolioGovernanceStatus added in v0.4.0

func BuildPortfolioGovernanceStatus(program Program, inputs []PortfolioGovernanceInput, asOf time.Time) (PortfolioGovernanceStatus, error)

BuildPortfolioGovernanceStatus is a deterministic, read-only projection over bounded caller-supplied metadata. Unknown remains explicit and never passes a shared outcome. Ordering completion and outcome completion are independent.

type PortfolioSpec added in v0.4.0

type PortfolioSpec struct {
	SpecID      string
	Complete    bool
	Deployments []DeploymentV1
}

type PortfolioView added in v0.4.0

type PortfolioView struct {
	Environments []PortfolioEnvironment `json:"environments"`
	Blockers     []PortfolioBlocker     `json:"blockers"`
}

func BuildPortfolioView added in v0.4.0

func BuildPortfolioView(program Program, inputs []PortfolioSpec) (PortfolioView, error)

BuildPortfolioView projects only supplied local ledgers and program state. Ledger order is authoritative; no discovery or network call occurs.

type PreventionKind added in v0.4.0

type PreventionKind string
const (
	PreventionRegressionTest PreventionKind = "regression_test"
	PreventionEval           PreventionKind = "eval"
)

type ProductionSignal added in v0.4.0

type ProductionSignal struct {
	ID     string                 `json:"id"`
	Status ProductionSignalStatus `json:"status"`
}

type ProductionSignalStatus added in v0.4.0

type ProductionSignalStatus string
const (
	SignalUnknown    ProductionSignalStatus = "unknown"
	SignalUnresolved ProductionSignalStatus = "unresolved"
	SignalResolved   ProductionSignalStatus = "resolved"
)

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

func LoadProgram(path string) (Program, error)

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 (p *Program) AddFeedbackLink(successor, source, reason string, complete func(string) bool) error

AddFeedbackLink links successor-owned maintenance work to completed history. It only appends a typed edge: runtime feedback cannot reopen, edit, or remove source history. Completion authority stays with the caller's gate predicate.

func (p *Program) AddLink(from, to string)

AddLink records from→to. It is idempotent: a duplicate link is a no-op.

func (p *Program) AddTypedLink(from, to string, kind LinkKind, reason string) error

AddTypedLink records a validated, traceable dependency edge. Link kinds are metadata: every kind preserves the existing cycle and ordering semantics.

func (Program) Deps added in v0.3.0

func (p Program) Deps(slug string) []string

Deps returns the slugs that slug directly depends on (its To edges), sorted.

func (Program) Frontier added in v0.3.0

func (p Program) Frontier(specs []string, complete func(string) bool) []string

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 (p Program) HasLink(from, to string) bool

HasLink reports whether from→to is already recorded.

func (Program) IncompleteDeps added in v0.3.0

func (p Program) IncompleteDeps(slug string, complete func(string) bool) []string

IncompleteDeps returns slug's direct dependencies that are not yet complete — the specs blocking it from executing (spec 12 R5).

func (p *Program) RemoveLink(from, to string) bool

RemoveLink deletes from→to and reports whether it existed.

func (Program) WouldCycle added in v0.3.0

func (p Program) WouldCycle(from, to string) []string

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 ProgramEconomics added in v0.4.0

type ProgramEconomics struct {
	Cost         string               `json:"cost"`
	InputTokens  int                  `json:"input_tokens"`
	OutputTokens int                  `json:"output_tokens"`
	CachedTokens int                  `json:"cached_tokens"`
	DurationMs   int                  `json:"duration_ms"`
	Specs        []SpecEconomics      `json:"specs"`
	MissingSpecs []string             `json:"missing_specs,omitempty"`
	Alerts       []EconomicDriftAlert `json:"alerts,omitempty"`
}

func RollupEconomics added in v0.4.0

func RollupEconomics(inputs []SpecEconomics, driftThreshold string) (ProgramEconomics, error)

RollupEconomics is a pure portfolio projection. Dimensions stay bounded to spec IDs; missing telemetry remains distinct from a measured zero.

type ProgramLink struct {
	From   string   `json:"from"`
	To     string   `json:"to"`
	Kind   LinkKind `json:"kind"`
	Reason string   `json:"reason,omitempty"`
}

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
	DeliveryBySource map[string]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 PromotionAudit added in v0.4.0

type PromotionAudit struct {
	Forced                bool
	Authority, Provenance string
}

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.

type PromotionV1 added in v0.4.0

type PromotionV1 struct {
	Baseline     string   `json:"baseline"`
	EvidenceRefs []string `json:"evidence_refs"`
}

PromotionV1 preserves exact health evidence and comparison baseline used by a promotion. References remain external; no raw telemetry enters the ledger.

type ProofCoverage added in v0.4.0

type ProofCoverage struct {
	Req     int `json:"req"`
	Passing int `json:"passing"`
	Total   int `json:"total"`
}

ProofCoverage is one requirement's criterion tally, projected into the lifecycle proof without depending on the cmd package's private type.

type ProvenanceLink struct {
	From      string   `json:"from,omitempty"`
	To        string   `json:"to"`
	Kind      LinkKind `json:"kind,omitempty"`
	Reason    string   `json:"reason,omitempty"`
	CreatedAt string   `json:"created_at,omitempty"`
}

ProvenanceLink traces intake to a prior spec without mutating that spec. String-form legacy entries decode as a follows link to that spec.

func (*ProvenanceLink) UnmarshalJSON added in v0.4.0

func (l *ProvenanceLink) UnmarshalJSON(raw []byte) error

type ProvenanceSourceType added in v0.4.0

type ProvenanceSourceType string
const (
	SourceFeature       ProvenanceSourceType = "feature"
	SourceIncident      ProvenanceSourceType = "incident"
	SourceVulnerability ProvenanceSourceType = "vulnerability"
	SourceDrift         ProvenanceSourceType = "drift"
	SourceDependency    ProvenanceSourceType = "dependency"
	SourceMigration     ProvenanceSourceType = "migration"
	SourceDeprecation   ProvenanceSourceType = "deprecation"
	SourcePolicy        ProvenanceSourceType = "policy"
)

type ProvenanceV1 added in v0.4.0

type ProvenanceV1 struct {
	SchemaVersion  int                  `json:"schema_version"`
	SourceType     ProvenanceSourceType `json:"source_type"`
	SourceRef      string               `json:"source_ref,omitempty"`
	Systems        []string             `json:"systems,omitempty"`
	AffectedSpecs  []string             `json:"affected_specs,omitempty"`
	Severity       string               `json:"severity,omitempty"`
	Risk           string               `json:"risk,omitempty"`
	Owner          string               `json:"owner,omitempty"`
	PriorLinks     []ProvenanceLink     `json:"prior_links,omitempty"`
	RequiredFields []string             `json:"required_fields,omitempty"`
}

ProvenanceV1 records bounded, operator-supplied intake facts. Unknown JSON fields are deliberately ignored so newer producers remain readable by v1.

func DecodeProvenance added in v0.4.0

func DecodeProvenance(raw []byte) (ProvenanceV1, error)

func LoadProvenance added in v0.4.0

func LoadProvenance(path string) (*ProvenanceV1, error)

LoadProvenance returns nil for an absent file: intake is opt-in and legacy feature specs must retain their existing behavior.

type QualityCheck added in v0.4.0

type QualityCheck struct {
	ID            string
	EvidenceClass EvidenceClass
	Threshold     *float64
}

type QualityContract added in v0.4.0

type QualityContract struct {
	TaskID   string                `json:"task_id"`
	Verify   string                `json:"verify,omitempty"`
	Required []EvidenceRequirement `json:"required"`
	Checks   []string              `json:"checks,omitempty"`
}

func ParseQualityContract added in v0.4.0

func ParseQualityContract(task TaskRow) (QualityContract, error)

type QualityException added in v0.4.0

type QualityException struct {
	ApprovalRef string
	Owner       string
	ExpiresAt   string
}

QualityException is deliberately narrow. Critical criteria cannot use it; noncritical exceptions must remain attributable and time-bounded.

type QualityLedgerEntry added in v0.4.0

type QualityLedgerEntry struct {
	ID           string `json:"id"`
	Kind         string `json:"kind"`
	Taxonomy     string `json:"taxonomy"`
	EvidenceRef  string `json:"evidence_ref"`
	SourceDigest string `json:"source_digest"`
	CreatedAt    string `json:"created_at"`
}

QualityLedgerEntry is a redacted, append-only quality learning record. Provenance is immutable: promotion points at prior evidence, never copied data.

func LoadQualityLedger added in v0.4.0

func LoadQualityLedger(path string) ([]QualityLedgerEntry, error)

type QualityPolicy added in v0.4.0

type QualityPolicy struct {
	TaskID   string
	Required []EvidenceRequirement
	Checks   []QualityCheck
	Criteria []AcceptanceCriterion
}

QualityPolicy is the deterministic, task-scoped proof contract evaluated by the quality gate. Required entries compose: every exact class/check pair must have fresh passing evidence; one class or check cannot substitute for another. Criteria and Checks add production coverage rules in R5.

type QualityPolicyFinding added in v0.4.0

type QualityPolicyFinding struct {
	Code    string
	TaskID  string
	Message string
}

QualityPolicyFinding is stable machine-readable policy output.

func ValidateCriteria added in v0.4.0

func ValidateCriteria(policy QualityPolicy, knownCriteria map[string]bool) []QualityPolicyFinding

ValidateCriteria verifies stable acceptance→check coverage. Eval-like checks require explicit thresholds; core never guesses score semantics.

func ValidateQualityPolicy added in v0.4.0

func ValidateQualityPolicy(policy QualityPolicy, knownChecks map[string]bool) []QualityPolicyFinding

ValidateQualityPolicy rejects malformed proof composition. Findings sort by code then message so map/input iteration cannot alter gate output.

type QualityReport added in v0.4.0

type QualityReport struct {
	Passed  []string           `json:"passed,omitempty"`
	Missing []string           `json:"missing,omitempty"`
	Stale   []string           `json:"stale,omitempty"`
	Scores  map[string]float64 `json:"scores,omitempty"`
	Review  string             `json:"review,omitempty"`
}

type QualityStatus added in v0.4.0

type QualityStatus struct {
	Missing []EvidenceRequirement
	Stale   []EvidenceRequirement
}

QualityStatus splits a task's required evidence into missing (no passing record at all) and stale (a passing record exists but is not current for the subject). OK reports both empty.

func EvaluateQuality added in v0.4.0

func EvaluateQuality(c QualityContract, records []EvidenceEnvelopeV1, s FreshnessSubject) QualityStatus

EvaluateQuality resolves a task's quality contract against the imported eval records and the current subject. Only a passing record satisfies a requirement, and only a fresh passing record does — a required deterministic test that failed leaves the requirement missing regardless of any later eval score or review, so a failing test always blocks completion (R3.4). It is a pure, allocation-light superset of MissingQualityEvidence with freshness.

func EvaluateQualityPolicy added in v0.4.0

func EvaluateQualityPolicy(policy QualityPolicy, records []EvidenceEnvelopeV1, subject FreshnessSubject) QualityStatus

EvaluateQualityPolicy applies exact composition and freshness using the W2 evidence predicate. It is pure and never invokes an adapter or scorer.

func (QualityStatus) OK added in v0.4.0

func (q QualityStatus) OK() bool

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"`
	// SourceDigest and CriteriaIDs are the compact, validated Domain 01
	// structured-intent metadata (spec 01 R1/R5): SourceDigest pins the approved
	// requirements/design source bytes via core.Digest so a later amendment can
	// detect drift; CriteriaIDs records which criterion IDs the record covers.
	// Both are additive and omitempty — records written by an older specd load
	// unchanged (backward compatible, no schema bump required).
	SourceDigest string   `json:"source_digest,omitempty"`
	CriteriaIDs  []string `json:"criteria_ids,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

func StampRecord(rec Record, gitHead string) Record

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 RecurringCheckV1 added in v0.4.0

type RecurringCheckV1 struct {
	SchemaVersion int    `json:"schema_version"`
	ID            string `json:"id"`
	Command       string `json:"command"`
	Cadence       string `json:"cadence,omitempty"`
	Trigger       string `json:"trigger,omitempty"`
}

func (RecurringCheckV1) Validate added in v0.4.0

func (c RecurringCheckV1) Validate() error

type RecurringResultV1 added in v0.4.0

type RecurringResultV1 struct {
	SchemaVersion int              `json:"schema_version"`
	CheckID       string           `json:"check_id"`
	GitHead       string           `json:"git_head"`
	ReleaseID     string           `json:"release_id"`
	ConfigID      string           `json:"config_id"`
	Verdict       RecurringVerdict `json:"verdict"`
	ObservedAt    string           `json:"observed_at"`
}

func LoadRecurringResults added in v0.4.0

func LoadRecurringResults(path string) ([]RecurringResultV1, error)

func (RecurringResultV1) Validate added in v0.4.0

func (r RecurringResultV1) Validate() error

type RecurringSuccessorPlan added in v0.4.0

type RecurringSuccessorPlan struct {
	Provenance ProvenanceV1 `json:"provenance"`
	Link       ProgramLink  `json:"link"`
}

func PlanRecurringSuccessor added in v0.4.0

func PlanRecurringSuccessor(source, successor string, result RecurringResultV1, enabled bool) (*RecurringSuccessorPlan, error)

type RecurringVerdict added in v0.4.0

type RecurringVerdict string
const (
	RecurringPass RecurringVerdict = "pass"
	RecurringFail RecurringVerdict = "fail"
)

type ReleaseCandidateV1 added in v0.4.0

type ReleaseCandidateV1 struct {
	Schema                string `json:"schema"`
	ReleaseID             string `json:"release_id"`
	SpecID                string `json:"spec_id"`
	SpecRevision          int    `json:"spec_revision"`
	GitHead               string `json:"git_head"`
	TaskEvidenceSetDigest string `json:"task_evidence_set_digest"`
	ArtifactDigest        string `json:"artifact_digest"`
	SBOMRef               string `json:"sbom_ref"`
	ProvenanceRef         string `json:"provenance_ref"`
	BootstrapDigest       string `json:"bootstrap_digest"`
	StateSchema           string `json:"state_schema"`
	CreatedAt             string `json:"created_at"`
}

func FreezeReleaseCandidate added in v0.4.0

func FreezeReleaseCandidate(root, slug string, r ReleaseCandidateV1) (ReleaseCandidateV1, error)

FreezeReleaseCandidate validates and durably appends a candidate under the spec lock (spec 08 R6.1). It is idempotent by release_id: an identical candidate already frozen is returned unchanged rather than duplicated, so a frozen candidate stays immutable. It builds and uploads nothing.

func ReadReleases added in v0.4.0

func ReadReleases(path string) ([]ReleaseCandidateV1, error)

ReadReleases replays the release ledger, dropping a torn final line.

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 ReportTask struct {
	ID          string        `json:"id"`
	Status      TaskRunStatus `json:"status"`
	Role        string        `json:"role,omitempty"`
	Files       string        `json:"files,omitempty"`
	Verify      string        `json:"verify,omitempty"`
	Acceptance  string        `json:"acceptance,omitempty"`
	EvidenceRef string        `json:"evidence_ref,omitempty"`
}

type ReqFinding added in v0.4.0

type ReqFinding struct {
	ID      string
	Message string
}

ReqFinding is an addressable requirements defect. ID names the offending requirement or criterion (empty for a document-level finding); Message states exactly what is wrong so the author can fix it without guessing (R1.2).

func ValidateRequirements added in v0.4.0

func ValidateRequirements(doc RequirementsDoc) []ReqFinding

ValidateRequirements reports missing, duplicate, malformed, or conflicting requirement IDs, criterion IDs, and EARS clauses in a structured requirements doc. It is pure: no disk, no clock. Callers with an unstructured doc (len(Requirements) == 0 and content present) get a single "no requirements found" finding, which the EARS gate suppresses for docs that use the legacy bullet shape.

type Requirement added in v0.4.0

type Requirement struct {
	ID       string
	Title    string
	Criteria []Criterion
	Owner    string
	Priority string
	Risk     string
	Edges    []string // edge/failure behaviors the author declared
}

Requirement is a parsed `R<n>` group from requirements.md — a stable ID, a human title, its acceptance criteria, and optional author metadata. The parser is pure and byte-stable: identical input bytes always yield identical records (R1.3) and the author's source bytes are never rewritten.

type RequirementsDoc added in v0.4.0

type RequirementsDoc struct {
	Raw          []byte
	Requirements []Requirement
	Exclusions   []string // "## Non-goals" bullets — document-level exclusions
}

RequirementsDoc is the normalized view of a requirements.md file. Raw holds a defensive copy of the author's bytes (never mutated by the parser).

func ParseRequirements

func ParseRequirements(raw []byte) (RequirementsDoc, error)

ParseRequirements parses requirements.md bytes into a normalized doc. It never rewrites the author's bytes; semantic problems (missing/duplicate/malformed IDs) are surfaced by ValidateRequirements, not here. The returned error is reserved for input the parser cannot read as text (currently none).

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 ReviewContract added in v0.4.0

type ReviewContract struct {
	TaskID          string
	SubjectRevision string
	RequiredTests   []string
	HardRisks       []string
}

ReviewContract is the deterministic review envelope. Hard risks are always visible to the auditor; required test evidence remains an independent gate.

func BuildReviewContract added in v0.4.0

func BuildReviewContract(quality QualityContract, subjectRevision string, risks []string) ReviewContract

type ReviewReport added in v0.2.0

type ReviewReport struct {
	Verdict  string
	Head     string
	Findings string
}

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 RiskLevel added in v0.4.0

type RiskLevel string
const (
	RiskUnknown  RiskLevel = "unknown"
	RiskLow      RiskLevel = "low"
	RiskMedium   RiskLevel = "medium"
	RiskHigh     RiskLevel = "high"
	RiskCritical RiskLevel = "critical"
)

type RollbackHealth added in v0.4.0

type RollbackHealth struct {
	CriterionID string `json:"criterion_id"`
	Observation string `json:"observation"`
	ObservedAt  string `json:"observed_at"`
}

type RollbackV1 added in v0.4.0

type RollbackV1 struct {
	Schema             string         `json:"schema"`
	DeploymentID       string         `json:"deployment_id"`
	FailedReleaseID    string         `json:"failed_release_id"`
	RollbackTarget     string         `json:"rollback_target"`
	Reason             string         `json:"reason"`
	Adapter            string         `json:"adapter"`
	AdapterIdentity    string         `json:"adapter_identity"`
	ActionResult       string         `json:"action_result"`
	PostRollbackHealth RollbackHealth `json:"post_rollback_health"`
	CapabilityClass    string         `json:"capability_class"`
	HumanRequired      bool           `json:"human_required"`
}

type RoutingConfig added in v0.4.0

type RoutingConfig struct {
	Version               string
	Classes               []string
	DefaultClass          string
	Fallback              []string
	ClassCapabilities     map[string][]string
	MaxTokens             int64
	MaxCostMicros         int64
	DeadlineSeconds       int
	MaxRetries            int
	AllowUnknownTelemetry bool
	// Recommendations maps task complexity to provider-neutral capability class.
	// Adapters decide whether and how that class maps to an available model.
	Recommendations map[string]string
}

RoutingConfig is approved, provider-neutral dispatch policy. Core selects a capability class only; adapters own any provider/model mapping.

type RoutingRecommendation added in v0.4.0

type RoutingRecommendation struct {
	Class      string `json:"class"`
	Complexity string `json:"complexity,omitempty"`
	Provider   string `json:"provider,omitempty"`
	Model      string `json:"model,omitempty"`
}

func RecommendRouting added in v0.4.0

func RecommendRouting(task TaskRow, cfg RoutingConfig) (RoutingRecommendation, error)

RecommendRouting returns policy metadata only. It never resolves provider availability and cannot affect verify/evidence completion authority.

type RunSpan added in v0.4.0

type RunSpan struct {
	SpanID       string   `json:"span_id"`
	ParentSpanID string   `json:"parent_span_id,omitempty"`
	RunID        string   `json:"run_id,omitempty"`
	SpecID       string   `json:"spec_id"`
	TaskID       string   `json:"task_id,omitempty"`
	Attempt      int      `json:"attempt,omitempty"`
	Kind         SpanKind `json:"kind"`
	StartedAt    string   `json:"started_at,omitempty"`
	GitHead      string   `json:"git_head,omitempty"`
	Actor        string   `json:"actor,omitempty"`
	Status       string   `json:"status,omitempty"`
	Reference    string   `json:"reference,omitempty"`

	// SourceRank and Seq are the deterministic tie-break keys (R6.2), never
	// serialized — identical role and semantics as HistoryEvent's.
	SourceRank int `json:"-"`
	Seq        int `json:"-"`
}

RunSpan is one metadata-only node in a run's trajectory (spec 07 R6). It reuses the W2 run/attempt identity (RunID) and W3 accounting rather than inventing new keys, and carries no payload content. StartedAt is informational — shown "where recorded" — and no gate derives an outcome from wall-clock order (R6.3). Ordering across equal or missing timestamps is resolved by the (SourceRank, Seq) tie-break, exactly like HistoryEvent, so a trace export is byte-stable (R6.2).

func (RunSpan) Validate added in v0.4.0

func (s RunSpan) Validate() error

Validate enforces the span invariants: a resolvable kind, a span id, and a git_head on any span that claims code effects or completion (spec 07 R6.1,R6.3).

type RunV1 added in v0.4.0

type RunV1 struct {
	EnvelopeVersion string `json:"envelope_version"`
	RunID           string `json:"run_id"`
	SpecID          string `json:"spec_id"`
	TaskID          string `json:"task_id"`
	Attempt         int    `json:"attempt"`
	StartedAt       string `json:"started_at"`
	GitHead         string `json:"git_head,omitempty"`
	Actor           string `json:"actor,omitempty"`
	WorkerID        string `json:"worker_id,omitempty"`
	TelemetrySource string `json:"telemetry_source,omitempty"`
}

RunV1 is one attempt in a task's run chain (spec 07 R2.1). run_id is a deterministic function of spec/task/baseline — never a provider trace ID — and is stable across the whole retry/recovery chain: two failures and a pass on one task share one run_id and carry attempts 1, 2, 3 (R2.2). The ledger (runs.jsonl) is append-only and additive: completion authority stays verify/eval, so the evidence gate passes or fails identically whether the ledger is present or absent (R2.3).

func AllocateRun added in v0.4.0

func AllocateRun(root, slug, taskID, gitHead, actor, workerID, source string) (RunV1, error)

AllocateRun allocates and durably appends the next run/attempt identity for a task under the spec lock (spec 07 R2.1). Manual verify and Brain runs call this one allocator, so a task's attempts accrue on a single run chain regardless of who drove them (R2.2). The read-derive-append happens under WithSpecLock, so racing writers cannot duplicate an attempt (R2.4). gitHead doubles as the chain baseline for a fresh chain. An empty actor resolves to the host actor.

func ReadRuns added in v0.4.0

func ReadRuns(path string) ([]RunV1, error)

ReadRuns loads the run ledger. A torn *trailing* line — the signature of a crash mid-append (AppendRun writes the record and its newline in one fsynced write) — is dropped, so a crash yields the prior complete records rather than a decode failure (spec 07 R2.4). Corruption anywhere but the final line is a real error. A missing ledger is not an error: the ledger is additive (R2.3).

type ScorerKind added in v0.4.0

type ScorerKind string
const (
	ScorerCode      ScorerKind = "code"
	ScorerHuman     ScorerKind = "human"
	ScorerHeuristic ScorerKind = "heuristic"
	ScorerLM        ScorerKind = "lm"
)

type ScorerMetadata added in v0.4.0

type ScorerMetadata struct {
	Kind         ScorerKind `json:"kind"`
	Provider     string     `json:"provider,omitempty"`
	Model        string     `json:"model,omitempty"`
	PromptDigest string     `json:"prompt_digest,omitempty"`
	Sampling     string     `json:"sampling,omitempty"`
}

type SecurityConfig added in v0.3.0

type SecurityConfig struct {
	Profile       string
	Secrets       string
	Injection     string
	Slopsquat     string
	CleanWorktree string
	Sandbox       string
}

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.

func (SecurityConfig) RequiresVerifySandbox added in v0.4.0

func (c SecurityConfig) RequiresVerifySandbox() bool

RequiresVerifySandbox reports whether policy makes isolation mandatory. Keeping profile resolution in core prevents CLI flag behavior from becoming an independent, potentially weaker policy interpretation.

type SharedOutcome added in v0.4.0

type SharedOutcome struct {
	ID          string              `json:"id"`
	Status      SharedOutcomeStatus `json:"status"`
	EvidenceRef string              `json:"evidence_ref,omitempty"`
}

type SharedOutcomeStatus added in v0.4.0

type SharedOutcomeStatus string
const (
	OutcomeUnknown SharedOutcomeStatus = "unknown"
	OutcomePending SharedOutcomeStatus = "pending"
	OutcomePassed  SharedOutcomeStatus = "passed"
	OutcomeFailed  SharedOutcomeStatus = "failed"
)

type SpanKind added in v0.4.0

type SpanKind string

SpanKind is the versioned closed enum of run-span activity types (spec 07 R6.1). A trace span records only metadata about one activity in a run — never the prompt, response, chain-of-thought, file contents, or raw output that produced it. Unknown kinds fail ParseSpanKind unless namespaced as an extension ("x-<name>"), so a critical kind is never silently dropped.

const (
	SpanContext  SpanKind = "context"
	SpanModel    SpanKind = "model"
	SpanTool     SpanKind = "tool"
	SpanEdit     SpanKind = "edit"
	SpanVerify   SpanKind = "verify"
	SpanEval     SpanKind = "eval"
	SpanApproval SpanKind = "approval"
	SpanDispatch SpanKind = "dispatch"
)

func ParseSpanKind added in v0.4.0

func ParseSpanKind(s string) (SpanKind, error)

ParseSpanKind validates a span kind string. A member of the closed enum, or a non-empty extension kind ("x-…"), parses; anything else fails so an unknown critical kind cannot silently disappear from a trace (spec 07 R6.1).

func (SpanKind) ClaimsCodeEffect added in v0.4.0

func (k SpanKind) ClaimsCodeEffect() bool

ClaimsCodeEffect reports whether a span asserts a change to, or verification/ evaluation of, tracked code — edit, verify, and eval spans. Such a span must carry a git_head anchoring the claim to a real artifact (spec 07 R6.3).

type SpecEconomics added in v0.4.0

type SpecEconomics struct {
	SpecID       string           `json:"spec_id"`
	Telemetry    *TelemetryReport `json:"telemetry,omitempty"`
	SourceRefs   []string         `json:"source_refs,omitempty"`
	PreviousCost string           `json:"previous_cost,omitempty"`
}

type SpecResolution added in v0.4.0

type SpecResolution struct {
	Slug   string `json:"slug"`
	Source string `json:"source"`
}

func ResolveSpec added in v0.4.0

func ResolveSpec(root, explicit, pinned string) (SpecResolution, error)

type SpecResolutionError added in v0.4.0

type SpecResolutionError struct{ Code, Message, RecoveryAction string }

func (SpecResolutionError) Error added in v0.4.0

func (e SpecResolutionError) Error() string

type Spike added in v0.4.0

type Spike struct {
	Question  string `json:"question"`
	Scope     string `json:"scope"`
	Expiry    string `json:"expiry"`
	OutputRef string `json:"output_ref,omitempty"`
	Timestamp string `json:"timestamp"`
	GitHead   string `json:"git_head"`
	Actor     string `json:"actor"`
}

Spike is a bounded exploratory-learning record (spec 01 R7.3). It captures what a prototype learned WITHOUT authorizing anything: a spike never completes a task and never approves architecture. Those transitions demand a passing verify record (CompleteTask) and a human design approval respectively, and a spike is a distinct record kind that neither path reads — so it cannot be a bypass. The bound (Question + Scope + a future Expiry) is what keeps a spike from silently becoming an open-ended parallel track that substitutes for real intent: an unbounded "spike" is just unreviewed work.

func StampSpike added in v0.4.0

func StampSpike(s Spike, gitHead string) Spike

StampSpike fills the provenance triple, mirroring StampRecord/StampAmendment.

func (Spike) Expired added in v0.4.0

func (s Spike) Expired(now time.Time) bool

Expired reports whether the spike's exploration window has closed as of now. A malformed expiry is treated as expired (fail-closed): a spike whose bound cannot be read cannot be trusted as live. Reports use this to surface stale spikes; it never invalidates the stored record.

func (Spike) Validate added in v0.4.0

func (s Spike) Validate() error

Validate enforces the R7.3 bound: question, scope, and a parseable expiry are all required, and the expiry must fall strictly after the record's own timestamp so the exploration window is finite. It deliberately does NOT compare against wall-clock now — an already-elapsed spike is expired, not invalid, and must still decode so history stays replayable (see Expired).

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 InitialState(slug string) State

func LoadState

func LoadState(path string) (State, error)

func MigrateState added in v0.3.0

func MigrateState(state State) (State, error)

func (State) Amendments added in v0.4.0

func (s State) Amendments() ([]Amendment, error)

func (*State) AppendAmendment added in v0.4.0

func (s *State) AppendAmendment(a Amendment) error

func (*State) AppendSpike added in v0.4.0

func (s *State) AppendSpike(spike Spike) error

AppendSpike stores a validated spike under a never-reused sequential key, mirroring AppendAmendment. It touches no lifecycle status, task status, or approval record — recording a spike authorizes nothing.

func (State) Spikes added in v0.4.0

func (s State) Spikes() ([]Spike, error)

Spikes returns the recorded spikes in stable key order.

func (State) StateFreshness added in v0.4.0

func (s State) StateFreshness() (FreshnessReport, error)

func (State) Validate added in v0.3.0

func (s State) Validate() error

type Status added in v0.3.0

type Status string
const (
	StatusRequirements Status = "requirements"
	StatusDesign       Status = "design"
	StatusTasks        Status = "tasks"
	StatusExecuting    Status = "executing"
	StatusVerifying    Status = "verifying"
	StatusComplete     Status = "complete"
	StatusBlocked      Status = "blocked"
)

func NextStatus added in v0.4.0

func NextStatus(status Status) Status

NextStatus returns the status immediately after status in the lifecycle order, or "" when status is already final. It names the gate an actor must clear next (spec 01 R6.1 driving guidance).

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

type SubmitConfig struct {
	Command     string
	TimeoutSecs int
}

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

type TaskDAG struct {
	Tasks []TaskRow
	ByID  map[string]TaskRow
}

func NewTaskDAG added in v0.3.0

func NewTaskDAG(tasks []TaskRow) (TaskDAG, error)

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

func (dag TaskDAG) TopologicalWaves() ([][]string, error)

type TaskRow added in v0.3.0

type TaskRow struct {
	ID     string
	Marker string
	Role   string
	Files  string
	// DeclaredFiles is the canonical, sorted, de-duplicated projection of Files.
	// Files remains untouched so tasks.md round-trips byte-for-byte.
	DeclaredFiles []string
	DependsOn     []string
	Verify        string
	Acceptance    string
	// Trace/risk planning metadata (spec 01 R3.1). Parsed from optional named
	// columns; absent columns yield zero values so legacy 6-column tasks.md
	// files parse unchanged (backward compatible). The task-trace gate requires
	// them only under the production planning profile.
	Refs         []string // requirement/design references this task implements
	Kind         string   // work kind (e.g. feature, fix, refactor, docs)
	Risk         string   // risk tier
	Complexity   string   // operator-declared routing complexity
	Capabilities []string // required provider-neutral capability ids
	Context      string   // required context declaration
	Evidence     string   // evidence classes planned
	Checks       string   // negative/edge checks planned
}

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"`
	InputTokens  int           `json:"input_tokens"`
	OutputTokens int           `json:"output_tokens"`
	CachedTokens int           `json:"cached_tokens"`
	Cost         string        `json:"cost"`
	// Source is the telemetry provenance surfaced so a report renders the values
	// as reported, never as independently measured (spec 07 R1.3). A legacy
	// attempt carries no explicit source and is reported as worker-reported.
	Source       string `json:"telemetry_source,omitempty"`
	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 TaskTraceFinding added in v0.4.0

type TaskTraceFinding struct {
	TaskID  string
	Message string
}

TaskTraceFinding is an addressable task-planning defect (spec 01 R3.1). TaskID names the offending task.

func ValidateTaskTrace added in v0.4.0

func ValidateTaskTrace(tasks []TaskRow, knownReqIDs map[string]bool, requireTrace bool) []TaskTraceFinding

ValidateTaskTrace reports task trace/risk defects. A declared requirement reference (R<n>/R<n>.<m>) that does not resolve, and an unrecognized risk tier, are always refused (safety). When requireTrace is set — the production planning profile (spec 01 R7.2) — every task must additionally declare its references, work kind, risk tier, required context, evidence classes, and negative/edge checks (R3.1); under the default profile these are optional so legacy tasks.md files keep planning (R7.1). Design-component references (ids that are not R<n> shaped) are accepted here; resolving them against a design component registry is deferred to a later wave. Pure: no disk, no clock.

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

func ParseTasksMd(raw []byte) (TasksMd, error)

type TelemetryReport added in v0.3.0

type TelemetryReport struct {
	Tokens       int             `json:"tokens"`
	InputTokens  int             `json:"input_tokens"`
	OutputTokens int             `json:"output_tokens"`
	CachedTokens int             `json:"cached_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 ToolAuthority added in v0.4.0

type ToolAuthority struct {
	ID             string   `json:"id"`
	ArgConstraints []string `json:"arg_constraints,omitempty"`
}

type ToolContract added in v0.4.0

type ToolContract struct {
	Name       string     `json:"name"`
	Route      string     `json:"route"`
	Phases     []Phase    `json:"phases"`
	Capability string     `json:"capability"`
	Mutable    bool       `json:"mutable"`
	HumanOnly  bool       `json:"human_only"`
	ExitCodes  []ExitCode `json:"exit_codes"`
}

func ManifestToolContracts added in v0.4.0

func ManifestToolContracts() []ToolContract

ManifestToolContracts derives driver routes from canonical Commands.

type ToolPolicy added in v0.3.0

type ToolPolicy struct {
	Optional map[string]bool
}

func LoadToolPolicy added in v0.3.0

func LoadToolPolicy(path string) ToolPolicy

type TrajectoryPolicy added in v0.4.0

type TrajectoryPolicy struct {
	Required  []string
	Forbidden []string
}

TrajectoryPolicy is the deterministic contract a trajectory must satisfy: a set of tool/action identities that must appear, and a set that must not (spec 04 R4.2). It is declarative and offline — no scorer, model, or network.

type TrajectoryResult added in v0.4.0

type TrajectoryResult struct {
	Verdict        EvalVerdict
	Missing        []string
	Forbidden      []string
	DigestMismatch bool
	Malformed      bool
}

TrajectoryResult reports how a normalized trace measured against a policy. Missing lists required tools absent from the trace; Forbidden lists forbidden tools present; DigestMismatch is true when the trace does not match the expected pinned digest. Verdict is pass only when all three are clean.

func EvaluateTrajectory added in v0.4.0

func EvaluateTrajectory(normalized []byte, policy TrajectoryPolicy, expectedDigest string) TrajectoryResult

EvaluateTrajectory checks a normalized trace (JSONL, one observable event per line) against a policy and an expected trace digest. It lives in core and is intentionally decoupled from the orchestration trace producer — it re-reads only the tool identity from each line, so completion gates never depend on the orchestration package. Passing an expectedDigest of "" skips the digest check (the caller did not pin one). No hidden reasoning is consulted: only observable tool identities drive the verdict (spec 04 R4.1/R4.2).

func (TrajectoryResult) Err added in v0.4.0

func (r TrajectoryResult) Err() error

Err returns a stable ordered failure describing a non-passing result, or nil.

type VerifyConfig added in v0.4.0

type VerifyConfig struct {
	TimeoutSecs int
	// Trivial lists verify commands that do no real checking (spec 01 R4.2). A
	// write task (role craftsman) using one of these is rejected — it must
	// verify its own change — while a read-only task (scout/validator/auditor)
	// may legitimately retain a trivial verify. Configurable to avoid false
	// positives (design 01: role/profile allowlists, exact finding, no opaque ban).
	Trivial []string
}

VerifyConfig bounds a single task verify command (gap 4.2 / W6-T4). TimeoutSecs caps wall-clock for one verify exec; a timeout is recorded as a FAILING evidence record (exit 124), never a crash or a silent hang. Zero means unbounded, which preserves prior behavior — operators opt into a bound.

type Wave added in v0.3.0

type Wave struct {
	Index int      `json:"index"`
	Tasks []string `json:"tasks"`
}

func ProjectWaves added in v0.3.0

func ProjectWaves(tasks []TaskRow) ([]Wave, error)

Directories

Path Synopsis
security
Package security implements the opt-in deterministic security gate (spec 05).
Package security implements the opt-in deterministic security gate (spec 05).

Jump to

Keyboard shortcuts

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