canaryscan

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: 13 Imported by: 0

Documentation

Overview

CANARY: REQ=CBIN-202; FEATURE="MermaidRefs"; ASPECT=Engine; STATUS=TESTED; TEST=TestCANARY_CBIN_202_ExtractDiagramRefs; UPDATED=2026-08-28

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AnnotateSources

func AnnotateSources(rep *Report, reg *sources.Registry)

AnnotateSources stamps each requirement with its source name and ticket URL.

func DefaultSkipRegex

func DefaultSkipRegex() *regexp.Regexp

DefaultSkipRegex returns the default skip path regex.

func LoadCanaryIgnore

func LoadCanaryIgnore(root string) (*ignore.GitIgnore, error)

LoadCanaryIgnore loads .canaryignore from root. Returns nil if file missing.

func MarshalSortedMap

func MarshalSortedMap(m map[string]int) ([]byte, error)

MarshalSortedMap ensures deterministic JSON object key order for map[string]int.

func RefTimeFromEnv

func RefTimeFromEnv() time.Time

RefTimeFromEnv returns time from CANARY_TEST_TIMESTAMP (RFC3339) for tests; zero if unset or invalid.

func Run

func Run(cfg Config, stdout, stderr io.Writer) (exitCode int)

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

func ScanSummaryLine

func ScanSummaryLine(rep Report) string

ScanSummaryLine returns a single parseable line for rep so agents get metrics without reading status.json.

func Stale

func Stale(rep Report, maxAge time.Duration, refTime time.Time) []string

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) (map[string]bool, error)

UpdateStaleTokens rewrites UPDATED in source files for tokens matching staleDiags REQ IDs. Only updates TESTED/BENCHED tokens. Returns files that were modified.

func VerifyClaims

func VerifyClaims(rep Report, gapPath string, reg *sources.Registry) []string

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=CBIN-201; FEATURE="TicketSources"; ASPECT=Engine; STATUS=IMPL; TEST=TestCANARY_CBIN_201_VerifyClaimsTicketSource; UPDATED=2026-08-28

func WriteCSV

func WriteCSV(path string, rep Report) error

WriteCSV writes rep to path as CSV.

func WriteJSON

func WriteJSON(path string, rep Report) error

WriteJSON writes rep to path as JSON.

Types

type Config

type Config struct {
	Root        string
	Out         string
	CSV         string
	VerifyPath  string
	Strict      bool
	SkipRegex   *regexp.Regexp
	UpdateStale bool
	ProjectOnly bool
}

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

type DiagramRef struct {
	ReqID string
	File  string
	Line  int // 1-based
}

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 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"`
}

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"`
}

Report is the scan output (JSON/CSV shape).

func Scan

func Scan(root string, skip *regexp.Regexp, projectFilter *regexp.Regexp, ignorePatterns *ignore.GitIgnore) (Report, error)

Scan walks root and returns a Report. skip, projectFilter, and ignorePatterns may be nil.

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.

type Summary

type Summary struct {
	ByStatus           map[string]int `json:"by_status"`
	ByAspect           map[string]int `json:"by_aspect"`
	TotalTokens        int            `json:"total_tokens"`
	UniqueRequirements int            `json:"unique_requirements"`
}

Summary holds aggregate counts.

Jump to

Keyboard shortcuts

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