Documentation
¶
Overview ¶
CANARY: REQ=CP-268; FEATURE="MermaidRefs"; ASPECT=Engine; STATUS=TESTED; TEST=TestCANARY_CBIN_202_ExtractDiagramRefs; UPDATED=2026-08-28
CANARY: REQ=CP-274; FEATURE="MigrateNotes"; ASPECT=Engine; STATUS=TESTED; TEST=TestCANARY_CBIN_301_ExtractMigrateNotes; UPDATED=2026-08-29
CANARY: REQ=CP-277; FEATURE="StalenessConfig"; ASPECT=Engine; STATUS=TESTED; TEST=TestCANARY_CBIN_304_StaleDaysFromConfig,TestCANARY_CBIN_304_UpdateStaleV2IDs,TestCANARY_CBIN_304_UpdateStaleAddsMissingUpdated,TestCANARY_CBIN_304_RunReportsActualRewriteCount; UPDATED=2026-08-29
Index ¶
- Constants
- func AnnotateSources(rep *Report, reg *sources.Registry)
- func DefaultSkipRegex() *regexp.Regexp
- func LoadCanaryIgnore(root string) (*ignore.GitIgnore, error)
- func MarshalSortedMap(m map[string]int) ([]byte, error)
- func RefTimeFromEnv() time.Time
- func Run(cfg Config, stdout, stderr io.Writer) (exitCode int)
- func RunFromArgs(root, out, csv, verifyPath, skipExpr string, ...) int
- func ScanSummaryLine(rep Report) string
- func Stale(rep Report, maxAge time.Duration, refTime time.Time) []string
- func UpdateStaleTokens(root string, skip *regexp.Regexp, staleDiags []string, ...) (updatedFiles map[string]bool, tokenCount int, err error)
- func VerifyClaims(rep Report, gapPath string, reg *sources.Registry) []string
- func WriteCSV(path string, rep Report) error
- func WriteJSON(path string, rep Report) error
- type Config
- type DiagramRef
- type Feature
- type MigrateNote
- type ProjectConfig
- type Report
- type Requirement
- type Summary
Constants ¶
const DefaultStaleDays = 30
DefaultStaleDays is the fallback staleness window (in days) when neither Config.StaleDays nor .canary/project.yaml's verification.staleness_days is set.
Variables ¶
This section is empty.
Functions ¶
func AnnotateSources ¶
AnnotateSources stamps each requirement with its source name and ticket URL.
func DefaultSkipRegex ¶
DefaultSkipRegex returns the default skip path regex.
func LoadCanaryIgnore ¶
LoadCanaryIgnore loads .canaryignore from root. Returns nil if file missing.
func MarshalSortedMap ¶
MarshalSortedMap ensures deterministic JSON object key order for map[string]int.
func RefTimeFromEnv ¶
RefTimeFromEnv returns time from CANARY_TEST_TIMESTAMP (RFC3339) for tests; zero if unset or invalid.
func Run ¶
Run runs the full scan pipeline: load config, scan, optional update-stale, write outputs, verify, strict. It writes to stdout/stderr via the given writers (use os.Stdout, os.Stderr from CLI). Returns exit code: 0 success, 2 verify/staleness failure, 3 parse/IO error.
func RunFromArgs ¶
func RunFromArgs(root, out, csv, verifyPath, skipExpr string, strict, updateStale, projectOnly bool, staleDays int) int
RunFromArgs is a convenience that builds Config from flag-like args and runs with os.Stdout/os.Stderr. Used by tools/canary main. skipExpr is the regex string; if empty, default is used. staleDays overrides the staleness window in days; 0 means "use config/default".
func ScanSummaryLine ¶
ScanSummaryLine returns a single parseable line for rep so agents get metrics without reading status.json.
func Stale ¶
Stale returns diagnostics for TESTED/BENCHED tokens older than maxAge. If refTime is zero, time.Now().UTC() is used.
func UpdateStaleTokens ¶
func UpdateStaleTokens(root string, skip *regexp.Regexp, staleDiags []string, ignorePatterns *ignore.GitIgnore) (updatedFiles map[string]bool, tokenCount int, err error)
UpdateStaleTokens rewrites UPDATED in source files for tokens matching staleDiags REQ IDs. Only updates TESTED/BENCHED tokens. Existing UPDATED=YYYY-MM-DD values are rewritten to today; a token line missing UPDATED= entirely gains one. Returns the set of files that were modified and the number of individual token lines actually rewritten (which may differ from len(staleDiags): several diags can share one REQ, or a REQ can span multiple physical token lines/files).
ignorePatterns (from LoadCanaryIgnore) is honored the same way Scan honors it: relative path matched first, dirs skipped via SkipDir; nil means no .canaryignore patterns apply. This keeps the rewrite walk in sync with the read walk that produced staleDiags in the first place — without it, a file excluded from scanning by .canaryignore could still be silently mutated by --update-stale.
func VerifyClaims ¶
VerifyClaims reads the GAP file and returns diagnostics for claimed-but-not- TESTED/BENCHED requirements. Claims are lines like "✅ <ID>" where <ID> matches any configured source key; a nil registry means the default (CBIN). CANARY: REQ=CP-267; FEATURE="TicketSources"; ASPECT=Engine; STATUS=IMPL; TEST=TestCANARY_CBIN_201_VerifyClaimsTicketSource; UPDATED=2026-08-28
Types ¶
type Config ¶
type Config struct {
Root string
Out string
CSV string
VerifyPath string
Strict bool
SkipRegex *regexp.Regexp
UpdateStale bool
ProjectOnly bool
// StaleDays overrides the staleness window (in days) used by --strict and
// --update-stale. When <= 0, the effective threshold falls back to
// .canary/project.yaml's verification.staleness_days, then to 30 days.
StaleDays int
}
Config holds scanner run options. Used by both the standalone tools/canary binary and the canary scan CLI subcommand so scan works from any CWD.
type DiagramRef ¶
DiagramRef records one requirement-ID mention inside a mermaid diagram.
func ExtractDiagramRefs ¶
func ExtractDiagramRefs(relPath, content string, reg *sources.Registry) []DiagramRef
ExtractDiagramRefs finds requirement IDs inside ```mermaid fenced blocks. relPath ending in .mmd is treated as a whole-file mermaid diagram (no fences required). IDs are normalized through reg (flatfile padding); reg nil means sources.Default() (the legacy CBIN series).
func ScanDiagramRefs ¶
func ScanDiagramRefs(root string, skip *regexp.Regexp, reg *sources.Registry, ignorePatterns *ignore.GitIgnore) ([]DiagramRef, error)
ScanDiagramRefs walks root for .md/.markdown/.mmd files and extracts all requirement-ID mentions inside mermaid diagrams. Paths in the result are root-relative with forward slashes. ignorePatterns (from LoadCanaryIgnore) is honored the same way Scan honors it: relative path matched first, dirs skipped via SkipDir; nil means no .canaryignore patterns apply.
type Feature ¶
type Feature struct {
Feature string `json:"feature"`
Aspect string `json:"aspect"`
Status string `json:"status"`
Files []string `json:"files"`
Tests []string `json:"tests"`
Benches []string `json:"benches"`
Owner string `json:"owner,omitempty"`
Updated string `json:"updated"`
}
Feature is one feature/aspect/status aggregation.
type MigrateNote ¶ added in v0.3.0
type MigrateNote struct {
File string `json:"file"`
Line int `json:"line"` // 1-based
Text string `json:"text"`
ReqIDs []string `json:"req_ids,omitempty"` // registry-pattern matches inside Text, normalized
}
MigrateNote is one CANARY:MIGRATE guidance comment.
func ExtractMigrateNotes ¶ added in v0.3.0
func ExtractMigrateNotes(relPath, content string, reg *sources.Registry) []MigrateNote
ExtractMigrateNotes finds CANARY:MIGRATE guidance comments in content. relPath is recorded verbatim on each note. reg nil means sources.Default() (the legacy CBIN series). A MIGRATE line is free text, not a KV token, and is never fed to parseKV — this is what keeps a MIGRATE line from ever aborting a scan.
func ScanMigrateNotes ¶ added in v0.3.0
func ScanMigrateNotes(root string, skip *regexp.Regexp, ignorePatterns *ignore.GitIgnore, reg *sources.Registry) ([]MigrateNote, error)
ScanMigrateNotes walks root and extracts CANARY:MIGRATE guidance notes from every non-binary file the scanner would otherwise read. Paths in the result are root-relative with forward slashes. ignorePatterns (from LoadCanaryIgnore) is honored the same way Scan honors it: relative path matched first, dirs skipped via SkipDir; nil means no .canaryignore patterns apply. Files larger than 1MB are skipped.
type ProjectConfig ¶
type ProjectConfig struct {
Project struct {
Name string `yaml:"name"`
Description string `yaml:"description"`
} `yaml:"project"`
Requirements struct {
IDPattern string `yaml:"id_pattern"`
} `yaml:"requirements"`
Scanner struct {
ExcludePaths []string `yaml:"exclude_paths"`
} `yaml:"scanner"`
Verification struct {
StalenessDays int `yaml:"staleness_days"`
} `yaml:"verification"`
}
ProjectConfig is the .canary/project.yaml shape.
func LoadProjectConfig ¶
func LoadProjectConfig(root string) (*ProjectConfig, error)
LoadProjectConfig loads .canary/project.yaml from root. Returns nil if file missing.
type Report ¶
type Report struct {
GeneratedAt string `json:"generated_at"`
Requirements []Requirement `json:"requirements"`
Summary Summary `json:"summary"`
MigrationNotes []MigrateNote `json:"migration_notes,omitempty"`
}
Report is the scan output (JSON/CSV shape).
type Requirement ¶
type Requirement struct {
ID string `json:"id"`
Source string `json:"source,omitempty"`
TicketURL string `json:"ticket_url,omitempty"`
Diagrams []string `json:"diagrams,omitempty"` // filled by Task 4
Features []Feature `json:"features"`
}
Requirement groups features by requirement ID.