plan

package
v0.2.0 Latest Latest
Warning

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

Go to latest
Published: May 22, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

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

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

func IsSingleFilePlanPath(plansDir, filePath string) bool

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 Mode

type Mode string

Mode enumerates valid `**Mode:**` body-metadata values.

const (
	ModeFull Mode = "full"
	ModeStub Mode = "stub"
)

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.

func Parse

func Parse(path string) (*Plan, error)

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".

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"
)

Jump to

Keyboard shortcuts

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