feature

package
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: Apr 1, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

pkg/feature

Feature discovery, traversal, metadata, dependency resolution, and scaffolding. Pure library functions — no cobra, no fmt.Print, no os.Exit.

Outstanding Questions

None at this time.

Documentation

Overview

Package feature provides feature discovery, traversal, metadata, dependency resolution, and scaffolding. Pure library functions — no cobra, no fmt.Print, no os.Exit.

Index

Constants

View Source
const (
	DefaultSpecDir = "spec"
	FeaturesSubDir = "features"
)

Default directory layout constants.

Variables

View Source
var ValidFields = map[string]bool{
	"status":    true,
	"oq":        true,
	"deps":      true,
	"refs":      true,
	"children":  true,
	"plans":     true,
	"proposals": true,
}

ValidFields lists all recognized metadata field names.

View Source
var ValidStatuses = []string{"draft", "approved", "implemented"}

ValidStatuses lists the allowed feature lifecycle statuses.

Functions

func BoolPtr

func BoolPtr(b bool) *bool

BoolPtr returns a pointer to a bool value.

func CountOutstandingQuestions

func CountOutstandingQuestions(readmePath string) (int, error)

CountOutstandingQuestions counts list items in the ## Outstanding Questions section.

func DepsResolver

func DepsResolver(featuresDir, featureID string) ([]string, error)

DepsResolver returns the direct dependencies for a feature.

func EnrichTransitiveNodes

func EnrichTransitiveNodes(featuresDir string, nodes []*EnrichedFeature, fields []string)

EnrichTransitiveNodes adds field metadata to a transitive tree.

func Exists

func Exists(featuresDir, featureID string) bool

Exists checks if a feature ID corresponds to a valid feature directory with README.md.

func ExtractFeatureID

func ExtractFeatureID(item string) string

ExtractFeatureID extracts a feature ID from a dependency list item.

func FeatureIDFromRelativePath

func FeatureIDFromRelativePath(relPath string) string

FeatureIDFromRelativePath converts a relative path like "../cli/README.md" to a feature ID like "cli".

func FeatureIDs

func FeatureIDs(features []Feature) []string

FeatureIDs is a convenience helper that extracts just the ID strings from a slice of Feature values.

func FilterFocusedFeatures

func FilterFocusedFeatures(allFeatures []string, targetID, direction string) []string

FilterFocusedFeatures returns features relevant to a focused tree view.

func FindFeatureRefs

func FindFeatureRefs(featuresDir, featureID string) ([]string, error)

FindFeatureRefs finds all features that reference the given featureID as a dependency.

func FindLinkedPlans

func FindLinkedPlans(repoRoot, featureID string) ([]string, error)

FindLinkedPlans scans spec/plans/*/README.md for plans that reference the given feature.

func FindSpecRepoRoot

func FindSpecRepoRoot(startDir string) (string, error)

FindSpecRepoRoot walks up from startDir looking for synchestra-spec-repo.yaml. As a fallback it checks for a spec/features/ directory. Returns the directory that serves as the spec repo root.

func GenerateReadme

func GenerateReadme(title, status, description string, deps []string) string

GenerateReadme produces the full README.md content for a new feature. If description is empty, a TODO placeholder is used. The Dependencies section is only included when deps is non-empty.

func GenerateSlug

func GenerateSlug(title string) string

GenerateSlug converts a human-readable title to a URL-safe directory name.

It lowercases the title, replaces spaces and underscores with hyphens, removes non-alphanumeric/non-hyphen characters, collapses consecutive hyphens, and trims leading/trailing hyphens.

func IsValidStatus

func IsValidStatus(status string) bool

IsValidStatus reports whether status matches one of the ValidStatuses (case-insensitive).

func MarkFocus

func MarkFocus(nodes []*FeatureNode, targetID string)

MarkFocus sets the focus flag on the target node in the tree.

func ParseContentsTable

func ParseContentsTable(readmePath string) (map[string]bool, error)

ParseContentsTable reads a README and extracts entries from the ## Contents section. Returns a map of directory names found in the table.

func ParseDependencies

func ParseDependencies(readmePath string) ([]string, error)

ParseDependencies reads a feature's README.md and extracts the ## Dependencies section. Returns a sorted list of feature IDs listed as bullet items.

Supports two formats:

  • bare ID: "- claim-and-push"
  • markdown link: "- [Name](../path/README.md) -- optional description"

func ParseFeatureStatus

func ParseFeatureStatus(readmePath string) (string, error)

ParseFeatureStatus extracts the status from a feature README. Looks for patterns like "**Status:** Conceptual" or "Status: Implemented".

func ParseFieldNames

func ParseFieldNames(fieldsStr string) ([]string, error)

ParseFieldNames validates and returns field names from a comma-separated string.

func PrintTransitiveText

func PrintTransitiveText(sb *strings.Builder, nodes []*EnrichedFeature, depth int)

PrintTransitiveText writes transitive results as indented text.

func PrintTree

func PrintTree(w *strings.Builder, nodes []*FeatureNode, depth int)

PrintTree writes the tree to a strings.Builder with tab indentation. Nodes with Focus set are prefixed with "* ".

func ReadmePath

func ReadmePath(featuresDir, featureID string) string

ReadmePath returns the absolute path to a feature's README.md.

func RefsResolver

func RefsResolver(featuresDir, featureID string) ([]string, error)

RefsResolver returns features that depend on the given feature.

func UpdateFeatureIndex

func UpdateFeatureIndex(indexPath, featureID, description string) (bool, error)

UpdateFeatureIndex adds a new row to the feature index at spec/features/README.md. Returns true if the file was modified.

func UpdateParentContents

func UpdateParentContents(parentReadmePath, childSlug, description string) (bool, error)

UpdateParentContents adds or updates the ## Contents section in the parent's README. Returns true if the file was modified.

func ValidateFormat

func ValidateFormat(format string) error

ValidateFormat checks the format flag value is valid.

func ValidateSlug

func ValidateSlug(slug string) error

ValidateSlug checks that slug is a valid feature slug.

A valid slug is non-empty, lowercase, contains only alphanumeric chars, hyphens, and forward slashes (for nested paths). Consecutive hyphens are not allowed. Each segment (split by "/") must not have leading or trailing hyphens.

Types

type ChildInfo

type ChildInfo struct {
	Path     string `yaml:"path" json:"path"`
	InReadme bool   `yaml:"in_readme" json:"in_readme"`
}

ChildInfo represents a child sub-feature.

func DiscoverChildFeatures

func DiscoverChildFeatures(featuresDir, featureID, readmePath string) ([]ChildInfo, error)

DiscoverChildFeatures finds immediate child sub-feature directories and checks whether each is listed in the parent's ## Contents table.

type EnrichedFeature

type EnrichedFeature struct {
	Path       string             `yaml:"path" json:"path"`
	Focus      *bool              `yaml:"focus,omitempty" json:"focus,omitempty"`
	Cycle      *bool              `yaml:"cycle,omitempty" json:"cycle,omitempty"`
	Status     string             `yaml:"status,omitempty" json:"status,omitempty"`
	OQ         *int               `yaml:"oq,omitempty" json:"oq,omitempty"`
	Deps       []string           `yaml:"deps,omitempty" json:"deps,omitempty"`
	Refs       []string           `yaml:"refs,omitempty" json:"refs,omitempty"`
	Plans      []string           `yaml:"plans,omitempty" json:"plans,omitempty"`
	Proposals  []string           `yaml:"proposals,omitempty" json:"proposals,omitempty"`
	ChildPaths []string           `yaml:"children,omitempty" json:"children,omitempty"`
	ChildNodes []*EnrichedFeature `yaml:"child_nodes,omitempty" json:"child_nodes,omitempty"`
}

EnrichedFeature holds a feature ID with optional metadata fields. ChildPaths holds child IDs for flat output; ChildNodes holds enriched children for tree representations.

func BuildEnrichedTree

func BuildEnrichedTree(featuresDir string, featureIDs []string, fields []string, focusID string) []*EnrichedFeature

BuildEnrichedTree builds a tree of EnrichedFeature nodes with resolved fields.

func ResolveFields

func ResolveFields(featuresDir, featureID string, fields []string) (*EnrichedFeature, error)

ResolveFields computes the requested metadata fields for a feature. Returns partial results alongside any errors encountered.

func TransitiveDeps

func TransitiveDeps(featuresDir, startID string) []*EnrichedFeature

TransitiveDeps follows dependency chains recursively with cycle detection.

func TransitiveRefs

func TransitiveRefs(featuresDir, startID string) []*EnrichedFeature

TransitiveRefs follows reference chains recursively with cycle detection.

type Feature

type Feature struct {
	// ID is the slash-separated path relative to the features directory
	// (e.g. "cli/task/claim").
	ID string
}

Feature holds a discovered feature's identity.

func Discover

func Discover(featuresDir string) ([]Feature, error)

Discover walks featuresDir and returns all features sorted alphabetically. A feature is any directory containing a README.md. Directories prefixed with _ are skipped (reserved for tooling).

type FeatureNode

type FeatureNode struct {
	Name     string
	ID       string // full feature ID
	Focus    bool   // marked as target in focused tree
	Children []*FeatureNode
}

FeatureNode represents a feature in a tree structure.

func BuildTree

func BuildTree(featureIDs []string) []*FeatureNode

BuildTree builds a tree from a sorted list of feature IDs.

type Info

type Info struct {
	Path     string        `yaml:"path" json:"path"`
	Status   string        `yaml:"status" json:"status"`
	Deps     []string      `yaml:"deps" json:"deps"`
	Refs     []string      `yaml:"refs" json:"refs"`
	Children []ChildInfo   `yaml:"children,omitempty" json:"children,omitempty"`
	Plans    []string      `yaml:"plans,omitempty" json:"plans,omitempty"`
	Sections []SectionInfo `yaml:"sections" json:"sections"`
}

Info is the top-level metadata structure for a single feature.

func GetInfo

func GetInfo(featuresDir, featureID string) (*Info, error)

GetInfo builds and returns the full Info for a feature.

type NewOptions

type NewOptions struct {
	Title       string   // Human-readable feature title (required).
	Slug        string   // Feature slug (directory name); auto-generated from Title if empty.
	Parent      string   // Parent feature ID for creating a sub-feature.
	Status      string   // Initial feature status (default "draft").
	Description string   // Short description for the Summary section.
	DependsOn   []string // Feature IDs this feature depends on.
}

NewOptions holds the parameters for creating a new feature.

type NewResult

type NewResult struct {
	FeatureID    string   // The created feature's full ID.
	FeatureDir   string   // Absolute path to the created feature directory.
	ReadmePath   string   // Absolute path to the created README.md.
	ChangedFiles []string // All files that were created or modified.
	Info         Info     // Metadata for the newly created feature.
}

NewResult describes the outcome of creating a new feature.

func New

func New(featuresDir string, opts NewOptions) (*NewResult, error)

New scaffolds a new feature directory with a README template. It does NOT perform any git operations — those belong in the CLI layer.

type RelationResolver

type RelationResolver func(featuresDir, featureID string) ([]string, error)

RelationResolver is a function that returns related feature IDs for a given feature.

type SectionInfo

type SectionInfo struct {
	Title    string        `yaml:"title" json:"title"`
	Lines    string        `yaml:"lines" json:"lines"`
	Items    int           `yaml:"items,omitempty" json:"items,omitempty"`
	Children []SectionInfo `yaml:"children,omitempty" json:"children,omitempty"`
}

SectionInfo represents a heading section in the README.

func ParseSections

func ParseSections(readmePath string) ([]SectionInfo, error)

ParseSections reads a README and builds a section TOC from markdown headings. Supports h2 and h3 nesting. Counts list items (lines starting with "- ") within each section.

Jump to

Keyboard shortcuts

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