Documentation
¶
Overview ¶
Package plan parses single-file Plan artifacts at spec/plans/<slug>.md per the SpecStudio plan-Feature contract (https://github.com/synchestra-io/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.
Index ¶
Constants ¶
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 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.
Types ¶
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 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
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.
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
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
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
}
Task captures a `### Task N: <name>` block.
type TaskStatus ¶
type TaskStatus string
TaskStatus enumerates valid `**Status:**` task body-field values.
const ( StatusPending TaskStatus = "pending" StatusInProgress TaskStatus = "in-progress" StatusDone TaskStatus = "done" StatusBlocked TaskStatus = "blocked" )