Documentation
¶
Overview ¶
Package plan parses single-file Plan artifacts at spec/plans/<slug>.md per the SpecStudio plan-Feature contract (https://github.com/specscore/specstudio-skills/blob/main/spec/features/skills/plan/README.md).
The directory-form plans at spec/plans/<slug>/README.md historically used by specscore-cli are out of scope for this package — they are parsed by the existing plan-hierarchy / plan-roi-metadata lint checkers.
Package plan — Reconcile is the out-of-band correction path for when a Plan's recorded **Status:** (and its embedded tasks' **Status:** lines) fell behind reality: work landed outside the tracked `change-status` flow, and the ONLY supported way to make the record true was, until now, a hand edit — the exact anti-pattern SpecScore's change-status verbs exist to eliminate.
Reconcile is deliberately NOT `change-status`: it does not walk the plan through the legal-transition matrix one arc at a time (that would require silently re-enacting a history that never happened), and it does not touch the state machine in pkg/lifecycle at all. It performs one direct rewrite — every reconciled task's **Status:** to complete, and the plan's own **Status:** to the execution band that rollup then derives (Implemented, today's only supported outcome — see DeriveExecutionBand) — and it makes that jump impossible to mistake for a normal transition: a **Reconciled:** header marker plus a dated, clearly-labeled `## Resolution` paragraph are written every time, and a caller-supplied --note justification is mandatory. There is no silent-bypass path: every field this function requires is enforced before any byte is written. A task recorded as failed or aborted is never swept into "every task" by default either — --tasks=complete refuses to touch it unless the caller names its number via ForceTasks, and every such override is itemized (not just aggregated) in the record.
Cross-references:
- Verb spec: spec/features/cli/plan/reconcile/README.md
- Sibling verb: spec/features/cli/plan/change-status/README.md
- Canonical lifecycle: spec/features/plan/README.md#req-status-rollup
Package plan — lifecycle transition orchestration for the Plan kind.
This file hosts ChangeStatus, the kind-specific orchestrator invoked by `specscore plan change-status`. It composes pkg/lifecycle/ primitives (state-machine validation and one atomic artifact transaction) and adds the Plan-specific structured `**Superseded By:**` successor reference.
`plan change-status` owns ONLY the human-authored arcs: the prep band (Draft/In Review/Approved) plus the dispositions (Rejected/Withdrawn/ Superseded/Deprecated). The execution band (Executing/Blocked/Implemented/ Failed) is LINT-DERIVED from the task-status rollup (rule P-007) and MUST NOT be settable here — the lifecycle KindPlan matrix encodes that by omitting every execution-band-entering arc. Plans are flat single files (or the optional directory form); change-status NEVER relocates a file.
LINT INVOCATION lives in the cobra adapter (internal/cli/plan.go), NOT here, to avoid an import cycle: pkg/lint imports pkg/plan for the plan-* lint rules, so pkg/plan cannot depend back on pkg/lint. The adapter passes a PostMutationHook callback into ChangeStatus. It runs after the Plan lock is released; failure retains the committed Plan and reports recovery required.
Cross-references:
- Verb spec: spec/features/cli/plan/change-status/README.md
- Meta contract: spec/features/cli/lifecycle-transitions/README.md
- Canonical lifecycle: spec/features/plan/README.md#req-status-transitions
Index ¶
- Constants
- func IndexContent(plansDir string, content []byte) ([]byte, bool, error)
- func IsExecutionBandStatus(s lifecycle.Status) bool
- func IsLegalChangeStatusTarget(s lifecycle.Status) bool
- func IsSingleFilePlanPath(plansDir, filePath string) bool
- func LegalChangeStatusTargetNames() []string
- func LegalTransitionMatrix() string
- func Scaffold(opts ScaffoldOptions) ([]byte, error)
- func SyncIndex(plansDir string) (bool, error)
- func ValidateSlug(slug string) error
- type ChangeStatusOptions
- type ChangeStatusResult
- type DeferredAC
- type EvidenceEntry
- type Mode
- type Plan
- type PostMutationHook
- type PrerequisiteReadiness
- type ReconcileOptions
- type ReconcileResult
- type Rollup
- type ScaffoldOptions
- type SnapshotValidator
- type Task
- type TaskOverride
- type TaskStatus
- type UnmetPrerequisite
Constants ¶
const FormatURL = "https://specscore.md/plan-specification"
FormatURL is the canonical spec URL for the Plan document type. It is carried verbatim in both the frontmatter `format:` field and the adherence-footer line, per the artifact-frontmatter-convention.
const PlaceholderBodyToken = "<!-- implement: pending -->"
PlaceholderBodyToken is the byte-exact marker the parser recognizes as a placeholder task body in `**Mode:** stub` Plans. The MVP working decision (see Open Questions in the plan-rules Feature) is an HTML comment so the marker is invisible in rendered markdown.
Variables ¶
This section is empty.
Functions ¶
func IndexContent ¶ added in v0.24.1
IndexContent returns the canonical plans-index content formed by replacing the Plan rows in content with rows derived from the flat Plan files in plansDir. It preserves every non-table byte, including Recently Closed and Open Questions sections. The returned changed flag reports whether writing the result would mutate the index.
func IsExecutionBandStatus ¶ added in v0.13.0
IsExecutionBandStatus reports whether s is one of the lint-derived execution-band statuses. The cobra adapter rejects these as --to values with a dedicated message that points the user at `spec lint --fix`.
func IsLegalChangeStatusTarget ¶ added in v0.13.0
IsLegalChangeStatusTarget reports whether status is one of the human- settable --to values for `specscore plan change-status`. This is the union of every To column in the KindPlan matrix MINUS the execution-band values (which appear in the matrix only as disposition From-states, never as a human-settable target). The cobra adapter uses this for the exit-2 early flag check BEFORE the state-machine check.
func IsSingleFilePlanPath ¶
IsSingleFilePlanPath reports whether path looks like a single-file Plan candidate location — i.e., directly under spec/plans/, has a `.md` extension, and is not named README.md (which is the index file).
It does NOT read the file; callers still must validate the title prefix via Parse() before treating it as a Plan.
func LegalChangeStatusTargetNames ¶ added in v0.13.0
func LegalChangeStatusTargetNames() []string
LegalChangeStatusTargetNames returns the canonical-titled names of the legal --to values, for stderr rendering and help text.
func LegalTransitionMatrix ¶ added in v0.13.0
func LegalTransitionMatrix() string
LegalTransitionMatrix returns a human-readable, ANSI-free rendering of the Plan legal-transition matrix, suitable for cobra `Long` help text. Built from lifecycle.LegalTargets so the help stays current as the matrix grows.
func Scaffold ¶ added in v0.7.0
func Scaffold(opts ScaffoldOptions) ([]byte, error)
Scaffold returns a lint-clean flat Plan file body: the artifact-frontmatter-convention frontmatter (`format:` + `status:` mirroring the body `**Status:** Draft`), the `# Plan:` title, the body-metadata header, the four required sections with HTML-comment prompts, and the adherence footer whose URL agrees with `format:`.
func SyncIndex ¶ added in v0.24.1
SyncIndex rewrites plansDir/README.md only when its derived Plan rows have drifted. It is safe to call after every Plan mutation and idempotent.
func ValidateSlug ¶ added in v0.7.0
ValidateSlug returns nil when slug is a lowercase, hyphen-separated, URL-safe identifier with no `/` (cli/plan/new#req:slug-format).
Types ¶
type ChangeStatusOptions ¶ added in v0.13.0
type ChangeStatusOptions struct {
// SpecRoot is the project root that contains the `spec/` subtree
// (NOT the `spec/` directory itself). The Plan is resolved at
// SpecRoot/spec/plans/<slug>.md (flat) or .../spec/plans/<slug>/README.md
// (the optional directory form).
SpecRoot string
// Slug is the Plan slug, e.g. "user-auth". Caller is expected to have
// validated it via plan.ValidateSlug.
Slug string
// To is the canonical (title-case) target status. The cobra adapter parses
// the raw --to value via lifecycle.ParseStatus and rejects execution-band /
// unrecognized values BEFORE reaching this function.
To lifecycle.Status
// Note is the optional free-form markdown transition note. When non-empty
// it is written as a `## Resolution` section, atomically with the status
// rewrite. REQUIRED (enforced by the cobra adapter) for the Withdrawn and
// Superseded dispositions.
Note string
// Successor is the slug of the plan that supersedes this one. REQUIRED
// (enforced by the cobra adapter) for --to=Superseded, rejected otherwise.
// It is written as a `**Superseded By:** <slug>` header line.
Successor string
// ValidateSnapshot runs under the Plan artifact lock before lifecycle
// validation and transformation. CLI coordination-branch enforcement is
// supplied here so it cannot authorize one snapshot and mutate another.
ValidateSnapshot SnapshotValidator
// PostMutation is the post-rewrite hook (typically a spec-lint pass).
// Required; ChangeStatus returns exit 10 if nil.
PostMutation PostMutationHook
// contains filtered or unexported fields
}
ChangeStatusOptions packages the inputs to ChangeStatus.
type ChangeStatusResult ¶ added in v0.13.0
ChangeStatusResult is the success payload returned on exit 0. The cobra adapter formats it as the `<slug>: <from> → <to>` success line.
func ChangeStatus ¶ added in v0.13.0
func ChangeStatus(opts ChangeStatusOptions) (ChangeStatusResult, error)
ChangeStatus performs a Plan-kind lifecycle transition end-to-end.
Flow:
- Resolve <slug> to an existing Plan file (flat or directory form). A missing file returns exit 3.
- Under the Plan artifact lock, read the exact bytes, validate against the KindPlan matrix, and compose Status, successor, and Resolution in memory.
- Commit those bytes with one atomic durable replacement and release.
- Invoke PostMutation. Failure retains the committed Plan and returns a typed recovery-required error.
type DeferredAC ¶
type DeferredAC struct {
ACID string // `<feature-slug>#ac:<ac-slug>`
Line int // 1-based line of the entry
Reason string // text after the em-dash; opaque to lint
}
DeferredAC is a single `- <feature-slug>#ac:<ac-slug> — <reason>` line.
type EvidenceEntry ¶ added in v0.15.0
type EvidenceEntry struct {
Task int `yaml:"task" json:"task"` // task number carrying the ref
Id string `yaml:"id,omitempty" json:"id,omitempty"` // task **Id:** when present
Ref string `yaml:"ref" json:"ref"` // the `**Implemented-by:**` value
}
EvidenceEntry is one task's implementation-commit reference, surfaced as a distinct record from any plan-level Snapshots Git Hash.
type Plan ¶
type Plan struct {
Path string // absolute path on disk
Slug string // filename without `.md`
HasPlanTitle bool // first H1 line was `# Plan: <title>`
TitleLine int // 1-based line number of the title (0 when absent)
Title string // the `<title>` portion after `# Plan: `
SourceFeature string // value of `**Source Feature:**` (empty when missing)
SourceFeatureLine int // 1-based line of the field; 0 when absent
SourceIdea string // Idea slug from `**Source:** idea:<slug>` (empty when not idea-sourced)
SourceNone bool // true when the source line is `**Source:** none` (source-less plan)
SourceRaw string // raw value of a `**Source:**` line as written (empty when absent)
SourceLine int // 1-based line of the `**Source:**` field; 0 when absent
Status string // value of `**Status:**` (empty when missing)
StatusLine int // 1-based line of the field; 0 when absent
StatusCount int // number of Plan-header **Status:** fields
Date string // value of `**Date:**` (empty when missing)
DateLine int // 1-based line of the field; 0 when absent
Owner string // value of `**Owner:**` (empty when missing)
OwnerLine int // 1-based line of the field; 0 when absent
Parent string // value of `**Parent:**` (empty when missing) — master/sub-plan composition
ParentLine int // 1-based line of the field; 0 when absent
Coordination string // value of `**Coordination:**` (empty when missing) — <owner>/<repo>@<branch> mutation-authority reference
CoordinationLine int // 1-based line of the field; 0 when absent
PrerequisitePlans []string // same-repo predecessor plan slugs from `**Prerequisite Plans:**`
PrerequisiteLine int // 1-based line of the first field; 0 when absent
PrerequisiteLines []int // every field occurrence, so duplicate headers cannot overwrite the first edge
PrerequisiteRaw string // first raw field value, retained so lint can distinguish malformed input
Mode Mode // `full` (default) or `stub`
ModeLine int // 1-based line of `**Mode:**`; 0 when absent
ModeRaw string // raw value as written (used by P-004 to report invalid tokens)
ModeRawPresent bool // true when the field was present at all
ModeValueValid bool // true when ModeRaw parsed cleanly into Mode
Tasks []Task // task blocks in source order
DeferredACs []DeferredAC // entries under `## Deferred AC Coverage`
DeferredACsLine int // 1-based line of the H2 heading; 0 when absent
}
Plan is a parsed single-file Plan artifact.
func Discover ¶ added in v0.7.0
Discover walks the direct children of plansDir and returns the parsed single-file Plans found there, sorted alphabetically by Slug.
It selects candidates via IsSingleFilePlanPath (which excludes README.md and anything not directly under plansDir), Parses each, and keeps only files whose first H1 was `# Plan: <title>` (HasPlanTitle == true). Directory-form plans at spec/plans/<slug>/README.md are out of scope and skipped.
An absent plansDir is not an error: Discover returns an empty slice and nil.
func Parse ¶
Parse reads a candidate Plan file. It returns a populated Plan even when the file is not actually a Plan (HasPlanTitle == false in that case) so callers can distinguish "not a Plan" from "malformed Plan".
func ParseBytes ¶ added in v0.35.0
ParseBytes parses an exact in-memory Plan snapshot. Artifact transactions use this entry point so identity resolution, singleton validation, and line-number calculation all describe the same bytes that will be transformed and committed. Path supplies only diagnostic and slug context; it is never read.
func (*Plan) DeriveExecutionBand ¶ added in v0.13.0
DeriveExecutionBand computes the plan's execution-band status from the rollup of its task statuses, per the canonical plan#req:status-rollup precedence (Failed > Executing > Blocked > Implemented). It returns ("", false) when the rollup is INDETERMINATE — there are no tasks, or at least one task is still pre-execution (planning/queued) so the set cannot resolve to a single band. The returned string, when ok, is the canonical Title-Case Plan status ("Failed"/"Executing"/"Blocked"/ "Implemented"). This reads task status only; it never writes it.
func (*Plan) ImplementationEvidence ¶ added in v0.15.0
func (p *Plan) ImplementationEvidence() []EvidenceEntry
ImplementationEvidence derives the deduplicated SET of implementation-commit refs carried by p's tasks (via each task's `**Implemented-by:**` field), in a stable order by task number. It is query-only: it reads task provenance and never reads or writes any plan-body/frontmatter "evidence" field, nor the `## Snapshots` Git Hash (which records spec-document state, a distinct axis). Tasks without provenance — or with an empty ref — contribute nothing, so a plan with no provenance yields an empty slice.
func (*Plan) PrerequisiteReadiness ¶ added in v0.37.0
func (p *Plan) PrerequisiteReadiness(plansDir string) (PrerequisiteReadiness, error)
PrerequisiteReadiness evaluates p's declared prerequisites using plansDir (the project's spec/plans directory). The result keeps every unmet prerequisite in declaration order, so callers can give an actionable diagnostic rather than stopping at the first one. Missing or malformed references are not treated as ready; P-009 remains responsible for naming their authoring errors during lint.
Directory-form prerequisites are resolved with the same flat-first lookup used by plan lifecycle commands, so a valid legacy directory-form Plan can satisfy a prerequisite while it remains supported by those commands.
func (*Plan) TaskRollup ¶ added in v0.7.0
TaskRollup tallies p.Tasks by status. Total is len(p.Tasks); each per-status count is 0 when no task holds that status.
type PostMutationHook ¶ added in v0.13.0
type PostMutationHook func() error
PostMutationHook is the callback the cobra adapter wires to `specscore spec lint --fix` (plus a verify pass). It MUST return nil on success; a non-nil return is wrapped as a committed/recovery-required error.
type PrerequisiteReadiness ¶ added in v0.37.0
type PrerequisiteReadiness struct {
Ready bool
Unmet []UnmetPrerequisite
}
PrerequisiteReadiness describes whether a Plan may begin execution with respect to its declared same-repository prerequisite Plans. It deliberately does not inspect the Plan's own tasks: callers decide what operation counts as beginning execution. A prerequisite is met only when its task rollup derives the Implemented execution band; a hand-authored **Status:** line is never sufficient on its own.
func PlanReadiness ¶ added in v0.37.0
func PlanReadiness(specRoot, slug string) (PrerequisiteReadiness, error)
PlanReadiness resolves slug in specRoot and evaluates its prerequisites. It is the command-facing convenience wrapper around PrerequisiteReadiness.
func (PrerequisiteReadiness) UnmetMessage ¶ added in v0.37.0
func (r PrerequisiteReadiness) UnmetMessage() string
UnmetMessage renders the stable, actionable part of an execution-readiness refusal. It names every unmet slug with both the recorded Plan status and the task-rollup-derived status that is authoritative for this gate.
type ReconcileOptions ¶ added in v0.23.0
type ReconcileOptions struct {
// SpecRoot is the project root that contains the `spec/` subtree (NOT the
// `spec/` directory itself). The Plan is resolved at
// SpecRoot/spec/plans/<slug>.md; the optional directory form
// (.../spec/plans/<slug>/README.md) is NOT supported — embedded-task
// reconciliation requires the single-file parser (pkg/plan.Parse).
SpecRoot string
// Slug is the Plan slug, e.g. "user-auth". Caller is expected to have
// validated it via plan.ValidateSlug.
Slug string
// Note is the mandatory justification for the reconciliation: what was
// actually delivered, and why the tracked change-status flow was
// skipped. Required — Reconcile refuses (exit 2) when empty or
// whitespace-only. Written verbatim into the `## Resolution` section
// alongside the fixed reconciliation preamble.
Note string
// Evidence is an optional list of commit SHAs, PR URLs, or file paths
// backing the claim that the work is actually done. When non-empty it is
// recorded as a trailing "Evidence: ..." line in the same Resolution
// paragraph as Note.
Evidence []string
// ForceTasks is the caller's explicit, per-task-number acknowledgement
// that a task recorded as failed or aborted should be overridden to
// complete anyway. --tasks=complete never silently force-completes a
// failed/aborted task: a task in either terminal state whose number does
// NOT appear here blocks the whole reconciliation (exit 4), naming the
// offending task numbers and their current statuses. Tasks named here
// that are NOT actually failed/aborted are harmless no-ops. Every task
// number that IS overridden this way is recorded — by number and prior
// status — in the `## Resolution` paragraph, never folded silently into
// the aggregate "N task(s) marked complete" count.
ForceTasks []int
// ReopenTasks is an explicit list of falsely-completed embedded tasks to
// correct to blocked. It is deliberately narrow: only complete tasks may
// be reopened, and no unlisted task is touched. This is the inverse audit
// path for an over-stated prior reconciliation, not a general bypass of
// the task lifecycle.
ReopenTasks []int
// ValidateSnapshot runs under the Plan artifact lock before reconciliation
// validation/transformation. It must not mutate the artifact.
ValidateSnapshot SnapshotValidator
// PostMutation is the post-rewrite hook (typically a spec-lint pass that
// syncs the plans index). The lifecycle write itself keeps the frontmatter
// `status:` mirror in lockstep with the canonical Plan body status.
// Required; Reconcile returns exit 10 if nil.
PostMutation PostMutationHook
// contains filtered or unexported fields
}
ReconcileOptions packages the inputs to Reconcile.
type ReconcileResult ¶ added in v0.23.0
type ReconcileResult struct {
Slug string
// From is the plan's **Status:** value before reconciliation.
From lifecycle.Status
// To is the derived execution-band status the plan is reconciled to.
// Today this is always lifecycle.PlanImplemented — the only supported
// --tasks value ("complete") forces every task to StatusComplete, and
// DeriveExecutionBand's complete-rollup case always yields Implemented.
To lifecycle.Status
// TasksReconciled is the count of embedded tasks whose **Status:** line
// was actually rewritten (tasks already at the target status are left
// byte-untouched and do not count). This INCLUDES any tasks named in
// Overrides — they are both counted here and itemized there.
TasksReconciled int
// Overrides lists every task whose failed/aborted status was overridden
// via --force-tasks, by number and prior status. Empty when no task was
// in a terminal failure state (the common case).
Overrides []TaskOverride
// Target is the status written to every reconciled task. Complete is the
// normal all-task delivery reconciliation; Blocked is used only by the
// explicit ReopenTasks correction path.
Target TaskStatus
}
ReconcileResult is the success payload returned on exit 0.
func PreviewReconcile ¶ added in v0.37.0
func PreviewReconcile(opts ReconcileOptions) (ReconcileResult, error)
PreviewReconcile runs the complete read-only reconciliation validation and composition against the current Plan bytes. It is used by whole-tree transactions to reject an invalid command before creating recovery state; it never acquires a write lock, writes the Plan, or invokes PostMutation.
func Reconcile ¶ added in v0.23.0
func Reconcile(opts ReconcileOptions) (ReconcileResult, error)
Reconcile performs a Plan-kind out-of-band status correction end-to-end.
Flow:
- Resolve <slug> to an existing flat-form Plan file. A missing file returns exit 3; a directory-form-only plan returns exit 4 (unsupported shape for this verb).
- Parse the plan and reject artifact shapes reconcile cannot handle: a terminal disposition status (Rejected/Withdrawn/Superseded/Deprecated — no resurrection via this verb), zero embedded tasks, or any task missing an explicit **Status:** line. Each exits 4. A task recorded as failed or aborted is ALSO refused unless its number appears in ForceTasks — --tasks=complete never silently force-completes a recorded failure (exit 4, naming the offending tasks and statuses).
- Compute the hypothetical all-complete task rollup and its derived execution band. If nothing would actually change — every task is already complete AND the plan is already at the derived band — exit 4 (not idempotent; re-running a completed reconciliation is a no-op refusal, mirroring lifecycle-transitions#req:not-idempotent).
- Under one fail-fast per-artifact lock, read the exact bytes, resolve and validate every target against that snapshot, then compose every task status, the Plan status, the first-reconciliation marker, and the `## Resolution` audit into one atomic durable replacement.
- Release the lock, then invoke PostMutation (spec lint --fix + verify). Callback failure reports a typed committed/recovery-required error; the already-visible canonical bytes are deliberately never rolled back.
type Rollup ¶ added in v0.7.0
type Rollup struct {
Total int `yaml:"total" json:"total"`
Complete int `yaml:"complete" json:"complete"`
InProgress int `yaml:"in_progress" json:"in_progress"`
Planning int `yaml:"planning" json:"planning"`
Queued int `yaml:"queued" json:"queued"`
Blocked int `yaml:"blocked" json:"blocked"`
}
Rollup counts a plan's tasks by their parsed task **Status:** value.
type ScaffoldOptions ¶ added in v0.7.0
type ScaffoldOptions struct {
Slug string
Title string // defaults to a title-cased slug
Owner string // defaults to "unknown"
Date string // ISO-8601 (YYYY-MM-DD); defaults to today's UTC date
// At most one of SourceFeature / SourceIdea may be set: a plan decomposes
// one Feature, one Idea, or no source at all (source-less, emitted as
// `**Source:** none`) (cli/plan/new#req:source-optional).
SourceFeature string
SourceIdea string
// Parent, when non-empty, records the master plan this plan is a sub-plan of
// (cli/plan/new#req:parent-ref-optional). It is emitted verbatim as a
// `**Parent:** <value>` header line after `**Supersedes:**`; resolution is
// deferred to lint (P-005). A same-repo slug or a cross-repo
// `<repo-slug>:<plan-slug>` soft reference.
Parent string
}
ScaffoldOptions controls the flat Plan file Scaffold emits.
type SnapshotValidator ¶ added in v0.35.0
SnapshotValidator checks caller-specific preconditions against the exact bytes read under the Plan artifact lock. It must not mutate the artifact.
type Task ¶
type Task struct {
Number int // parsed N from `### Task N:`
Name string // text after `Task N: `
HeadingLine int // 1-based line of the `### Task N:` heading
BodyLines []string // lines after the heading, up to the next task / H2 / EOF (verbatim)
BodyStart int // 1-based line where the body begins (one past the heading)
Verifies []string // AC IDs from `**Verifies:**`, in source order
VerifiesLine int // 1-based line of `**Verifies:**`; 0 when absent
VerifiesPresent bool // true when the field was present
Id string // stable task identifier from `**Id:**`; empty when absent
IdLine int // 1-based line of `**Id:**`; 0 when absent
IdPresent bool // true when the field was present
IdCount int // number of **Id:** fields; values above one are ambiguous
Status TaskStatus
StatusLine int // 1-based line of `**Status:**`; 0 when absent
StatusRaw string // raw value as written
StatusPresent bool // true when the field was present
StatusValueValid bool // true when StatusRaw parsed cleanly into TaskStatus
StatusCount int // number of **Status:** fields in this task block
DependsOn []int // predecessor task numbers, empty when none
DependsOnLine int // 1-based line of `**Depends-On:**`; 0 when absent
DependsOnRaw string // raw value as written
DependsOnPresent bool
DependsOnValid bool // true when raw value parsed cleanly (em-dash or list of ints)
HasPlaceholder bool // true when the body contains the placeholder token on its own line
PlaceholderLine int // 1-based line of the placeholder; 0 when absent
// Implementation-commit provenance, written by `task change-status` as an
// `**Implemented-by:** <ref>` field adjacent to the task's **Status:**.
ImplementationCommit string // raw value of `**Implemented-by:**`; empty when absent or empty
ImplementedByLine int // 1-based line of `**Implemented-by:**`; 0 when absent
ImplementedByPresent bool // true when the field was present (even with an empty value)
ImplementedByCount int // number of singleton provenance fields
// Note is a free-text annotation written by `task change-status --note=`,
// adjacent to the task's **Status:** (and any **Implemented-by:**). Distinct
// from ImplementationCommit: Note carries qualitative context (e.g. "verified
// live"), not a code reference.
Note string // raw value of `**Note:**`; empty when absent or empty
NoteLine int // 1-based line of `**Note:**`; 0 when absent
NotePresent bool // true when the field was present (even with an empty value)
NoteCount int // number of singleton Note fields
// Evidence is a list of supporting references written by
// `task change-status --evidence=`, adjacent to the task's **Status:**.
// Unlike ImplementationCommit (a syntactically validated code reference —
// P-008), Evidence is unstructured: commit SHAs, PR URLs, file paths,
// deploy/monitoring links, or anything else backing the claim.
Evidence []string // parsed comma-separated refs from `**Evidence:**`, in source order
EvidenceRaw string // raw value as written
EvidenceLine int // 1-based line of `**Evidence:**`; 0 when absent
EvidencePresent bool // true when the field was present (even with an empty value)
EvidenceCount int // number of singleton Evidence fields
}
Task captures a `### Task N: <name>` block.
type TaskOverride ¶ added in v0.23.0
type TaskOverride struct {
Number int
From TaskStatus
}
TaskOverride names an embedded task whose recorded terminal failure state (failed or aborted) was overridden to complete via --force-tasks, and what it was before. Reconcile never invents these silently — a TaskOverride only exists because the caller named that exact task number.
type TaskStatus ¶
type TaskStatus string
TaskStatus enumerates valid `**Status:**` task body-field values.
const ( StatusPlanning TaskStatus = "planning" StatusQueued TaskStatus = "queued" StatusInProgress TaskStatus = "in_progress" StatusBlocked TaskStatus = "blocked" StatusComplete TaskStatus = "complete" StatusFailed TaskStatus = "failed" StatusAborted TaskStatus = "aborted" )
type UnmetPrerequisite ¶ added in v0.37.0
type UnmetPrerequisite struct {
Slug string `yaml:"slug" json:"slug"`
Status string `yaml:"status" json:"status"`
DerivedStatus string `yaml:"derived_status,omitempty" json:"derived_status,omitempty"`
// Reason is set only for invalid prerequisite graphs or declarations. It
// keeps derived_status reserved for a determinate task-rollup result.
Reason string `yaml:"reason,omitempty" json:"reason,omitempty"`
}
UnmetPrerequisite records the declared and derived state of one prerequisite that prevents execution. Status is the prerequisite's recorded **Status:** value (or "missing" when its Plan cannot be resolved); DerivedStatus is the task-rollup result, or empty when the rollup is indeterminate.