specs

package
v0.2.5 Latest Latest
Warning

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

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

Documentation

Overview

CANARY: REQ=CBIN-134; FEATURE="ExactIDLookup"; ASPECT=Engine; STATUS=IMPL; UPDATED=2025-10-16

CANARY: REQ=CBIN-134; FEATURE="SectionLoader"; ASPECT=Engine; STATUS=IMPL; UPDATED=2025-10-16

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FindSpecByID

func FindSpecByID(reqID string) (string, error)

FindSpecByID locates spec.md file by exact requirement ID Uses glob pattern: .canary/specs/CBIN-XXX-*/spec.md

func FindSpecBySearch

func FindSpecBySearch(query string, limit int) ([]matcher.Match, error)

FindSpecBySearch performs fuzzy search across spec directories Reuses CBIN-133 fuzzy matcher for scoring and ranking

func FindSpecInDB

func FindSpecInDB(db *storage.DB, reqID string) (string, error)

FindSpecInDB queries database for fast spec lookup (optional fallback) If database is unavailable, returns error and caller should use FindSpecByID

func ListSections

func ListSections(content string) ([]string, error)

ListSections returns all section headers from markdown content Extracts all ## level headers

func ParseSections

func ParseSections(content string, sections []string) (string, error)

ParseSections extracts specific sections from markdown content If sections is empty, returns full content Preserves metadata at top (lines before first ##) Section names are case-insensitive

Types

type Dependency

type Dependency struct {
	// Source is the requirement ID that has the dependency (e.g., "CBIN-147")
	Source string

	// Target is the requirement ID being depended upon (e.g., "CBIN-146")
	Target string

	// Type indicates whether this is a full, partial feature, or aspect dependency
	Type DependencyType

	// RequiredFeatures lists specific features needed for PartialFeatures dependencies.
	// Only populated when Type is DependencyTypePartialFeatures.
	RequiredFeatures []string

	// RequiredAspect specifies the aspect needed for PartialAspect dependencies.
	// Only populated when Type is DependencyTypePartialAspect.
	RequiredAspect string

	// Description provides human-readable context about why this dependency exists.
	// This is optional and used for documentation purposes.
	Description string
}

Dependency represents a dependency relationship between two requirements. It captures the source requirement, target requirement, type of dependency, and any specific features or aspects that must be satisfied.

func ParseDependencies

func ParseDependencies(sourceReqID string, reader io.Reader) ([]Dependency, error)

ParseDependencies parses dependency declarations from a spec.md file reader. It looks for the "## Dependencies" section and extracts all dependency declarations.

Supported formats: - Full: "- CBIN-123 (Description)" - Partial Features: "- CBIN-123:Feature1,Feature2 (Description)" - Partial Aspect: "- CBIN-123:AspectName (Description)"

Returns a slice of Dependency objects. Returns empty slice if no dependencies found.

func ParseDependenciesFromFile

func ParseDependenciesFromFile(sourceReqID, specPath string) ([]Dependency, error)

ParseDependenciesFromFile reads a spec.md file and extracts all dependencies. Returns a slice of Dependency objects or an error if the file cannot be read.

type DependencyGraph

type DependencyGraph struct {
	// Nodes maps requirement IDs to their list of outgoing dependencies.
	// Key: Source requirement ID (e.g., "CBIN-147")
	// Value: List of dependencies where this requirement is the source
	Nodes map[string][]Dependency
}

DependencyGraph represents the complete dependency graph for all requirements. It provides methods for querying, traversal, and cycle detection.

func NewDependencyGraph

func NewDependencyGraph() *DependencyGraph

NewDependencyGraph creates a new empty DependencyGraph.

func (*DependencyGraph) AddDependency

func (dg *DependencyGraph) AddDependency(dep Dependency)

AddDependency adds a dependency to the graph. If the source node doesn't exist, it creates it.

func (*DependencyGraph) GetAllRequirements

func (dg *DependencyGraph) GetAllRequirements() []string

GetAllRequirements returns all unique requirement IDs in the graph (both sources and targets).

func (*DependencyGraph) GetDependencies

func (dg *DependencyGraph) GetDependencies(reqID string) []Dependency

GetDependencies returns all dependencies for a given requirement ID. Returns an empty slice if the requirement has no dependencies.

func (*DependencyGraph) GetReverseDependencies

func (dg *DependencyGraph) GetReverseDependencies(reqID string) []Dependency

GetReverseDependencies returns all requirements that depend on the given requirement ID. This answers the question: "What would be blocked if this requirement changes?"

type DependencyStatus

type DependencyStatus struct {
	// Dependency is the dependency being evaluated
	Dependency Dependency

	// IsSatisfied indicates whether the dependency requirements are met.
	// For Full: All features of target are TESTED or BENCHED
	// For PartialFeatures: All RequiredFeatures are TESTED or BENCHED
	// For PartialAspect: All features of RequiredAspect are TESTED or BENCHED
	IsSatisfied bool

	// Blocking indicates whether this unsatisfied dependency blocks implementation.
	// Set to true when IsSatisfied is false.
	Blocking bool

	// Message provides human-readable explanation of the status.
	// Examples:
	// - "All required features are TESTED"
	// - "Waiting for CBIN-146:ProjectRegistry to reach TESTED status (currently IMPL)"
	// - "Target requirement CBIN-999 does not exist"
	Message string

	// MissingFeatures lists features that are not yet in TESTED/BENCHED status.
	// Only populated for PartialFeatures dependencies when IsSatisfied is false.
	MissingFeatures []string

	// CurrentStatus describes the current status of the target requirement or features.
	// Used for debugging and reporting.
	CurrentStatus string
}

DependencyStatus represents the current satisfaction status of a dependency. It indicates whether the dependency is satisfied and provides contextual information.

type DependencyType

type DependencyType int

DependencyType represents the type of dependency relationship between requirements.

const (
	// DependencyTypeFull indicates the entire target requirement must be complete
	// (all features must be in TESTED or BENCHED status).
	DependencyTypeFull DependencyType = iota

	// DependencyTypePartialFeatures indicates only specific features of the target
	// requirement must be complete.
	DependencyTypePartialFeatures

	// DependencyTypePartialAspect indicates all features of a specific aspect
	// of the target requirement must be complete.
	DependencyTypePartialAspect
)

func (DependencyType) String

func (dt DependencyType) String() string

String returns a human-readable string representation of the DependencyType.

type DependencyValidator

type DependencyValidator struct {
	// contains filtered or unexported fields
}

DependencyValidator validates dependency graphs for cycles and missing requirements.

func NewDependencyValidator

func NewDependencyValidator(graph *DependencyGraph) *DependencyValidator

NewDependencyValidator creates a new dependency validator for the given graph.

func (*DependencyValidator) SetSpecFinder

func (dv *DependencyValidator) SetSpecFinder(finder SpecFinder)

SetSpecFinder configures the validator to check for missing requirements.

func (*DependencyValidator) Validate

func (dv *DependencyValidator) Validate() ValidationResult

Validate performs comprehensive validation of the dependency graph. It checks for: 1. Circular dependencies (using DFS with recursion stack) 2. Missing requirements (if SpecFinder is configured)

type GraphGenerator

type GraphGenerator struct {
	// contains filtered or unexported fields
}

GraphGenerator builds and visualizes dependency graphs.

func NewGraphGenerator

func NewGraphGenerator(loader SpecLoader) *GraphGenerator

NewGraphGenerator creates a new graph generator.

func (*GraphGenerator) BuildGraph

func (gg *GraphGenerator) BuildGraph(reqIDs []string) (*DependencyGraph, error)

BuildGraph builds a complete dependency graph from a list of requirement IDs. It loads dependencies for each requirement and constructs the full graph.

func (*GraphGenerator) FormatASCIITree

func (gg *GraphGenerator) FormatASCIITree(graph *DependencyGraph, rootReqID string) string

FormatASCIITree generates an ASCII tree visualization of the dependency graph. Shows the structure with Unicode box-drawing characters and optional status indicators.

Example output: CBIN-147 (Specification Dependencies) ├── CBIN-146 (Multi-Project Support) ✅ │ └── CBIN-129 (Migrations) ❌ └── CBIN-145 (Legacy Migration) ✅

func (*GraphGenerator) FormatCompactList

func (gg *GraphGenerator) FormatCompactList(graph *DependencyGraph, reqID string) string

FormatCompactList formats dependencies as a compact comma-separated list. Example: "CBIN-146, CBIN-145, CBIN-129"

func (*GraphGenerator) FormatDependencyChain

func (gg *GraphGenerator) FormatDependencyChain(reqIDs []string) string

FormatDependencyChain formats a list of requirement IDs as a chain. Example: "CBIN-147 → CBIN-146 → CBIN-129"

func (*GraphGenerator) FormatDependencySummary

func (gg *GraphGenerator) FormatDependencySummary(graph *DependencyGraph, reqID string) string

FormatDependencySummary generates a multi-line summary of dependencies. Includes direct dependencies, transitive count, and depth.

func (*GraphGenerator) FormatMermaid

func (gg *GraphGenerator) FormatMermaid(graph *DependencyGraph, rootReqID string, urlFor func(string) string) string

FormatMermaid renders the dependency graph rooted at rootReqID as a mermaid flowchart (flowchart TD). Node identifiers are sanitized via mermaidNodeID; node labels are the raw requirement IDs. Edges are deduped and traversal is cycle-safe (each edge is only ever emitted once, so a cycle cannot cause unbounded recursion). urlFor is optional; when it returns a non-empty URL for a requirement ID, a mermaid `click` directive is emitted for that node so viewers can jump straight to the ticket/doc. Click lines are emitted in sorted (deterministic) order.

func (*GraphGenerator) GetDependencyDepth

func (gg *GraphGenerator) GetDependencyDepth(graph *DependencyGraph, reqID string) int

GetDependencyDepth returns the maximum depth of the dependency tree. Depth is the longest path from the root to any leaf node.

func (*GraphGenerator) GetTransitiveDependencies

func (gg *GraphGenerator) GetTransitiveDependencies(graph *DependencyGraph, reqID string) []string

GetTransitiveDependencies returns all transitive dependencies of a requirement. Uses BFS to traverse the dependency graph and collect all reachable requirements.

func (*GraphGenerator) SetStatusChecker

func (gg *GraphGenerator) SetStatusChecker(checker StatusCheckerInterface)

SetStatusChecker configures the generator to show dependency status in visualizations.

type SpecFinder

type SpecFinder interface {
	// SpecExists checks if a specification exists for the given requirement ID
	SpecExists(reqID string) bool

	// FindSpecPath returns the path to the spec.md file for a requirement
	FindSpecPath(reqID string) (string, error)
}

SpecFinder is an interface for finding and checking specification existence. This allows validation against the actual filesystem or a mock for testing.

type SpecLoader

type SpecLoader interface {
	// LoadDependencies loads all dependencies for a given requirement ID
	LoadDependencies(reqID string) ([]Dependency, error)
}

SpecLoader is an interface for loading dependencies from spec files.

type StatusChecker

type StatusChecker struct {
	// contains filtered or unexported fields
}

StatusChecker checks whether dependencies are satisfied based on CANARY token status.

func NewStatusChecker

func NewStatusChecker(provider TokenProvider) *StatusChecker

NewStatusChecker creates a new status checker with the given token provider.

func (*StatusChecker) CheckAllDependencies

func (sc *StatusChecker) CheckAllDependencies(deps []Dependency) []DependencyStatus

CheckAllDependencies checks all dependencies and returns their statuses.

func (*StatusChecker) CheckDependency

func (sc *StatusChecker) CheckDependency(dep Dependency) DependencyStatus

CheckDependency checks whether a single dependency is satisfied. Satisfaction rules: - Full: All features of target requirement must be TESTED or BENCHED - PartialFeatures: All RequiredFeatures must be TESTED or BENCHED - PartialAspect: All features of RequiredAspect must be TESTED or BENCHED

IMPL status is NOT sufficient - dependencies require tests.

func (*StatusChecker) FormatBlockingReport

func (sc *StatusChecker) FormatBlockingReport(deps []Dependency) string

FormatBlockingReport generates a human-readable report of blocking dependencies.

func (*StatusChecker) GetBlockingDependencies

func (sc *StatusChecker) GetBlockingDependencies(deps []Dependency) []DependencyStatus

GetBlockingDependencies returns only the dependencies that are blocking (not satisfied).

type StatusCheckerInterface

type StatusCheckerInterface interface {
	// IsDependencySatisfied checks if a dependency is satisfied
	IsDependencySatisfied(dep Dependency) bool
}

StatusChecker interface for checking dependency satisfaction

type TokenInfo

type TokenInfo struct {
	ReqID   string
	Feature string
	Aspect  string
	Status  string
}

TokenInfo represents a CANARY token from storage. This is used by StatusChecker to query token status.

type TokenProvider

type TokenProvider interface {
	// GetTokensByReqID returns all CANARY tokens for a given requirement ID
	GetTokensByReqID(reqID string) []TokenInfo
}

TokenProvider is an interface for retrieving CANARY tokens from storage. This allows the status checker to query token status without tight coupling to storage.

type ValidationResult

type ValidationResult struct {
	// IsValid is true if the dependency graph is valid (no cycles, all requirements exist)
	IsValid bool

	// Cycles contains all detected circular dependencies.
	// Each cycle is represented as a slice of requirement IDs forming the cycle.
	// Example: ["CBIN-100", "CBIN-101", "CBIN-102", "CBIN-100"]
	Cycles [][]string

	// MissingRequirements lists requirement IDs that are referenced but don't exist
	MissingRequirements []string

	// Errors contains human-readable error messages
	Errors []string
}

ValidationResult contains the results of dependency validation.

func (*ValidationResult) FormatErrors

func (vr *ValidationResult) FormatErrors() string

FormatErrors returns a formatted string containing all validation errors.

Jump to

Keyboard shortcuts

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