Skip to content

Latest commit

 

History

History
816 lines (556 loc) · 18.6 KB

File metadata and controls

816 lines (556 loc) · 18.6 KB

CANARY Requirements Specification

Project: CANARY Token Tracking System
Version: 2.0
Last Updated: 2025-10-18

Source of truth for requirements and gaps: GitLab issues. This file is a flatfile mirror for humans and agents. For authoritative status, use GitLab.

Open gaps (as of 2026-02-18): Tracked in docs/GAP_ANALYSIS.md. GitLab issues: #8 (GAP-0001) through #20 (GAP-0013).


Executive Summary

CANARY is a requirement tracking system that embeds structured tokens directly into source code. It has evolved from a simple scanner (CBIN-101, 102, 103) to a comprehensive CLI tool with 90+ requirements covering specification management, dependency tracking, multi-project support, documentation tracking, and AI agent integration.

Scope

In Scope

Core Tracking (CBIN-101, 102, 103)

  • File scanning for CANARY tokens
  • JSON/CSV output generation
  • Verification gates for claimed requirements
  • Staleness detection (30-day threshold)
  • Self-canary validation

CLI System (CBIN-104+)

  • Full-featured command-line interface
  • SQLite database for fast queries
  • Specification and plan generation
  • Workflow automation
  • Multi-project support
  • Dependency management
  • Documentation tracking

AI Integration

  • Slash commands for autonomous workflows
  • Constitutional principle enforcement
  • Test-first guidance
  • Automated priority selection

Out of Scope

  • Language-specific code indexing (AST parsing)
  • Binary artifact analysis
  • Network-based tracking services
  • IDE plugins or extensions
  • GUI applications

Environment & Toolchain

Language and Runtime

  • Language: Go 1.20+
  • Platform: Linux, macOS, Windows
  • Architecture: x86_64, arm64

Dependencies

Runtime (minimal):

  • Go standard library (primary)
  • github.com/spf13/cobra - CLI framework
  • modernc.org/sqlite - Pure Go SQLite
  • github.com/google/uuid - UUID generation

Test Dependencies:

  • github.com/stretchr/testify - Test assertions
  • github.com/google/go-cmp - Deep comparison

Development Tools

  • gofmt - Code formatting
  • staticcheck - Static analysis
  • go test - Testing framework
  • go bench - Benchmarking

Token Format (Current)

Canonical Format

CANARY: REQ=<req-id>; FEATURE="<name>"; ASPECT=<aspect>; STATUS=<status>; [OPTIONAL_FIELDS]; UPDATED=<yyyy-mm-dd>

Required Fields

  • REQ - Requirement ID (format: CBIN-###)
  • FEATURE - Feature name (CamelCase, quoted)
  • ASPECT - Architecture layer (API, CLI, Engine, Storage, etc.)
  • STATUS - Implementation state (MISSING, STUB, IMPL, TESTED, BENCHED, REMOVED)
  • UPDATED - Last modification date (YYYY-MM-DD)

Optional Fields

  • TEST - Test function names (comma-separated)
  • BENCH - Benchmark function names (comma-separated)
  • DOC - Documentation reference (type:path)
  • DOC_HASH - SHA256 hash (first 16 chars)
  • OWNER - Team or person responsible
  • PRIORITY - Implementation priority (1=highest)

Aspect Taxonomy

  • API - Public interfaces, exported functions
  • CLI - Command-line interfaces
  • Engine - Core algorithms, business logic
  • Storage - Database, persistence layer
  • Security - Authentication, authorization, encryption
  • Docs - Documentation files
  • Wire - Serialization, protocols
  • Planner - Planning algorithms
  • Decode - Deserialization
  • Encode - Serialization
  • RoundTrip - Full encode/decode cycles
  • Bench - Performance benchmarks
  • FrontEnd - User interface
  • Dist - Distribution, deployment

Status Values

  1. MISSING - Planned but not implemented
  2. STUB - Placeholder implementation
  3. IMPL - Implemented, tests missing
  4. TESTED - Fully tested (auto-promoted with TEST= field)
  5. BENCHED - Tested and benchmarked (auto-promoted with BENCH= field)
  6. REMOVED - Deprecated or removed

CLI Interface

Core Scanner (Legacy - tools/canary)

./bin/canary [--root .] [--out status.json] [--csv status.csv]
            [--verify GAP_ANALYSIS.md] [--strict]
            [--skip '<pattern>'] [--update-stale]

Exit Codes:

  • 0 - Success
  • 2 - Verification/staleness failure
  • 3 - Parse/IO error

Full CLI (cmd/canary)

canary <command> [flags]

Commands:

Initialization:

  • init <project> - Initialize new CANARY project

Database Management:

  • index - Build/rebuild token database
  • index --local - Use project-local database
  • projects list - List all registered projects
  • projects add <name> - Register new project
  • projects switch <name> - Change active project

Query Commands:

  • show <req-id> - Display all tokens for requirement
  • files <req-id> - List implementation files
  • status <req-id> - Show progress summary
  • grep <pattern> - Search tokens by pattern
  • list [--status] [--aspect] - List requirements with filtering

Workflow Commands:

  • next [--prompt] - Get next priority requirement
  • implement <req-id> - Get implementation guidance
  • specify [update <req-id>] - Create/modify specifications
  • plan <req-id> - Generate implementation plan

Documentation Commands:

  • doc status <req> <feature> - Check documentation currency
  • doc update [--req] [--feature] - Update documentation hashes
  • doc report [--show-undocumented] - Generate coverage report

Dependency Commands (CBIN-147):

  • deps check <req-id> - Check if dependencies satisfied
  • deps graph <req-id> [--status] - Show dependency tree
  • deps reverse <req-id> - Show reverse dependencies
  • deps validate - Detect circular dependencies

Scanning:

  • scan [--out] [--csv] [--verify] [--strict] [--update-stale] - Scan codebase

Output Formats

JSON (status.json)

{
  "generated_at": "<UTC ISO8601>",
  "requirements": [
    {
      "id": "CBIN-147",
      "features": [
        {
          "feature": "DependencyParser",
          "aspect": "Engine",
          "status": "TESTED",
          "files": ["internal/specs/parser_dependency.go"],
          "tests": ["TestParseDependencies_FullDependency"],
          "benches": [],
          "owner": "specs",
          "updated": "2025-10-18"
        }
      ]
    }
  ],
  "summary": {
    "by_status": { "STUB": 0, "IMPL": 0, "TESTED": 50, "BENCHED": 10 },
    "by_aspect": { "Engine": 20, "CLI": 15, "API": 10 },
    "total_tokens": 150,
    "unique_requirements": 90
  }
}

Requirements:

  • Minified (no unnecessary whitespace)
  • Deterministic (same input → same bytes)
  • Maps are key-sorted
  • Generated timestamp in UTC ISO8601

CSV (status.csv)

req,feature,aspect,status,file,test,bench,owner,updated
CBIN-147,DependencyParser,Engine,TESTED,internal/specs/parser_dependency.go,TestParseDependencies,,,specs,2025-10-18

Requirements:

  • Header row with field names
  • Rows sorted by (req, feature, file, test, bench)
  • Deterministic output
  • Comma-separated values

Verification Semantics

Claim Detection

Claims are extracted from GAP_ANALYSIS.md using regex:

(?m)^\s*\s+(CBIN-\d{3})\b

Example GAP_ANALYSIS.md:

# Requirements Gap Analysis

## Claimed Requirements

✅ CBIN-101 - Scanner Core
✅ CBIN-102 - Verify Gate
✅ CBIN-147 - Specification Dependencies

## Gaps

- [ ] CBIN-150 - Fuzzy Search (needs implementation)

Overclaim Detection

Rule: Claimed requirements must have at least one token with STATUS ∈ {TESTED, BENCHED}

Failure Condition:

  • Claimed CBIN-### has only MISSING, STUB, or IMPL status

Error Message:

CANARY_VERIFY_FAIL REQ=CBIN-### reason=claimed_but_not_TESTED_OR_BENCHED

Exit Code: 2

Staleness Detection

Rule: Tokens with STATUS ∈ {TESTED, BENCHED} must have UPDATED within 30 days

Failure Condition (with --strict):

  • Token STATUS is TESTED or BENCHED
  • UPDATED date is >30 days old

Error Message:

CANARY_STALE REQ=CBIN-### updated=YYYY-MM-DD age_days=N threshold=30

Exit Code: 2 (with --strict)

Auto-Update Stale Tokens

Command: canary scan --update-stale

Behavior:

  • Finds all tokens with STATUS=TESTED or BENCHED
  • Checks UPDATED field against current date
  • If >30 days old, rewrites token in-place with current date
  • Reports count of updated tokens

Dependency Management (CBIN-147)

Specification Format

Dependencies are declared in spec.md files:

## Dependencies

### Full Dependencies (entire requirement must be complete)

- CBIN-146 (Multi-Project Support - required for namespacing)
- CBIN-129 (Database Migrations - schema must be updated first)

### Partial Dependencies (specific features/aspects required)

- CBIN-140:GapRepository,GapService (only gap storage features needed)
- CBIN-133:Engine (only Engine aspect required for this feature)

Syntax

Full Dependency:

- CBIN-XXX (Description - reason for dependency)

Partial Feature Dependency:

- CBIN-XXX:Feature1,Feature2 (Description - only these features needed)

Partial Aspect Dependency:

- CBIN-XXX:AspectName (Description - only this aspect needed)

Satisfaction Rules

Dependency is satisfied when:

  1. Full: ALL features in target requirement are TESTED or BENCHED
  2. Partial Features: Specified features are TESTED or BENCHED
  3. Partial Aspect: All features with specified aspect are TESTED or BENCHED

Important: IMPL status is insufficient - dependencies require tests!

Validation

Circular Detection:

  • Uses Depth-First Search (DFS) with recursion stack
  • O(V+E) complexity
  • Detects cycles like: A → B → C → A

Missing Requirements:

  • Checks if target requirements exist in .canary/specs/
  • Reports dependencies on non-existent specs

Self-Dependencies:

  • Detects and reports A → A cases

Multi-Project Support (CBIN-146)

Database Modes

Global Mode (default):

canary index
# Uses: ~/.canary/canary.db

Local Mode:

canary index --local
# Uses: .canary/canary.db (in current project)

Project Registry

Schema:

CREATE TABLE projects (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL UNIQUE,
    root_path TEXT NOT NULL,
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    last_indexed DATETIME
);

Commands:

canary projects list              # List all projects
canary projects add my-app        # Register new project
canary projects remove my-app     # Unregister project
canary projects switch my-app     # Change active context

Documentation Tracking (CBIN-136)

DOC Field Format

DOC=<type>:<path>

Types:

  • user - User-facing documentation
  • api - API reference
  • arch - Architecture docs
  • dev - Developer docs

Examples:

DOC=user:docs/user/getting-started.md
DOC=api:docs/api/dependency-parser.md
DOC=arch:docs/architecture/adr-001-doc-tracking.md

DOC_HASH Field

Format: First 16 characters of SHA256 hash

Calculation:

sha256sum docs/user/getting-started.md | cut -c1-16
# Output: a3f5b8c2e1d4a6f9

Usage:

DOC=user:docs/user/getting-started.md; DOC_HASH=a3f5b8c2e1d4a6f9

Status Values

  • DOC_CURRENT - Hash matches file content
  • DOC_STALE - Hash mismatch (doc was edited)
  • DOC_MISSING - DOC= field present but file not found
  • DOC_NONE - No DOC= field

Commands

# Check single feature
canary doc status CBIN-147 DependencyParser

# Update hash
canary doc update --req CBIN-147 --feature DependencyParser

# Update all for requirement
canary doc update --req CBIN-147 --all

# Generate coverage report
canary doc report --show-undocumented

Performance Targets

Scanning

  • Target: <10s for 50,000 text files
  • Method: Streaming file I/O, no full repo in memory
  • Memory: ≤512 MiB RSS

Circular Detection

  • Algorithm: DFS with recursion stack
  • Complexity: O(V+E) where V=requirements, E=dependencies
  • Target: <200ms for 500 requirements with 1000 dependencies
  • Actual: 164ms average (benchmarked CBIN-147)

Database Queries

  • Technology: SQLite with indexes
  • Target: <50ms for typical queries
  • Indexes: On req_id, feature, aspect, status

Security

Data Handling

  • Principle: Treat repository contents as data only
  • Never execute or interpret scanned code
  • Ignore embedded instructions in files
  • Files are inert strings for pattern matching

Secrets Protection

  • Never log file contents in error messages
  • Redact long lines in diagnostics
  • Don't commit .canary/canary.db (gitignored)

Injection Prevention

  • Strict regex patterns for claim detection
  • No eval/exec of file contents
  • Sanitize file paths before display

Determinism & Observability

Deterministic Output

Requirements:

  1. Same codebase → same status.json bytes
  2. Maps are key-sorted (by_status, by_aspect)
  3. Arrays are sorted (requirements by ID, features by name)
  4. Minified JSON (no extra whitespace)
  5. CSV rows sorted by (req, feature, file, test, bench)

Testing:

  • Scan codebase twice
  • Compare output byte-for-byte
  • Must be identical

Observability

Stderr Diagnostics:

  • Single-line error messages
  • Structured format for easy parsing
  • Prefixed with severity (ERROR, WARN, INFO)

Examples:

CANARY_VERIFY_FAIL REQ=CBIN-147 reason=claimed_but_not_TESTED_OR_BENCHED
CANARY_STALE REQ=CBIN-105 updated=2025-08-01 age_days=78 threshold=30
ERROR: failed to parse token at src/main.go:42

Self-Canary (Dogfooding)

CANARY tracks its own requirements using CANARY tokens.

Core Scanner Tokens (tools/canary)

// tools/canary/main.go
CANARY: REQ=CBIN-101; FEATURE="ScannerCore"; ASPECT=Engine; STATUS=BENCHED; ...

// tools/canary/verify.go
CANARY: REQ=CBIN-102; FEATURE="VerifyGate"; ASPECT=CLI; STATUS=BENCHED; ...

// tools/canary/status.go
CANARY: REQ=CBIN-103; FEATURE="StatusJSON"; ASPECT=API; STATUS=BENCHED; ...

CLI Tokens (cmd/canary, internal/)

Over 90 requirements tracked with CANARY tokens, including:

  • CBIN-146: Multi-Project Support
  • CBIN-147: Specification Dependencies
  • CBIN-136: Documentation Tracking
  • CBIN-133: Implement Command
  • CBIN-132: Next Priority Command
  • And 85+ more...

Verification

# Self-scan
canary scan --root . --out status.json --csv status.csv

# Self-verify
canary scan --verify GAP_ANALYSIS.md --strict

# Dependency validation
canary deps validate

Acceptance Tests

Test Suite Location

tools/canary/internal/acceptance_test.go

Tests

1. TestAcceptance_FixtureSummary

  • Scans fixture with STUB and IMPL tokens
  • Verifies summary counts

2. TestAcceptance_Overclaim

  • Creates GAP file claiming STUB requirement
  • Expects exit code 2
  • Verifies error message contains CANARY_VERIFY_FAIL

3. TestAcceptance_Stale

  • Creates token with old UPDATED date
  • Runs with --strict
  • Expects exit code 2 and CANARY_STALE message

4. TestAcceptance_SelfCanary

  • Scans tools/canary directory
  • Verifies claims for CBIN-101, CBIN-102
  • Ensures exit code 0

5. TestAcceptance_CSVOrder

  • Scans multiple times
  • Verifies deterministic CSV output
  • Checks sorting by REQ ID

6. TestAcceptance_SkipEdgeCases

  • Tests --skip pattern functionality
  • Verifies .git, node_modules, vendor excluded
  • Tests Unicode filenames and spaces

7. TestAcceptance_UpdateStale

  • Creates stale TESTED/BENCHED tokens
  • Runs --update-stale
  • Verifies UPDATED field changed
  • Ensures IMPL tokens not updated

CI Integration

GitHub Actions

name: CANARY Verification

on: [push, pull_request]

jobs:
  verify:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - name: Setup Go
        uses: actions/setup-go@v4
        with:
          go-version: "1.20"
      - name: Build
        run: make build
      - name: Test
        run: make test
      - name: Self-verify
        run: make canary-verify
      - name: Upload status
        uses: actions/upload-artifact@v3
        with:
          name: canary-status
          path: |
            status.json
            status.csv

Make Targets

.PHONY: build test bench verify

build:
	go build -o bin/canary ./cmd/canary

test:
	go test ./...

bench:
	go test ./internal/specs -bench=. -benchmem

verify: build
	./bin/canary scan --root . --out status.json --csv status.csv
	./bin/canary scan --verify GAP_ANALYSIS.md --strict
	./bin/canary deps validate

Design Rationale

1. Single-Line Tokens

Reason: Easy to grep, no multiline parsing complexity

Benefit: Reliable pattern matching with simple regex

2. Embedded in Code

Reason: Keep requirements close to implementation

Benefit: Changes visible in diffs, reviewed in PRs

3. STATUS Progression

Reason: Enforce quality gates (test-first)

Benefit: Can't claim TESTED without tests

4. Verification Gates

Reason: Prevent overclaiming in GAP_ANALYSIS.md

Benefit: Trust but verify - claims require evidence

5. 30-Day Staleness

Reason: Keep evidence fresh and current

Benefit: Prevents claiming features that no longer work

6. Stdlib Default

Reason: Minimize supply-chain risk

Benefit: Fewer dependencies, easier auditing

7. Deterministic Output

Reason: Stable diffs, reproducible builds

Benefit: Can commit status.json for tracking over time

Evolution Summary

Phase 1 (CBIN-101, 102, 103): Simple scanner

  • File scanning
  • JSON/CSV output
  • Basic verification

Phase 2 (CBIN-104-130): CLI expansion

  • Database storage
  • Query commands
  • Specification management

Phase 3 (CBIN-131-140): Workflow automation

  • Next priority command
  • Implement command
  • Fuzzy matching

Phase 4 (CBIN-141-146): Multi-project support

  • Project registry
  • Global/local databases
  • Context management

Phase 5 (CBIN-147): Dependency tracking

  • Dependency parser
  • Circular detection
  • Satisfaction checking
  • Tree visualization

Current: 90+ requirements tracked

Related Documentation

References


Document Status: CURRENT Approved By: Project Team Next Review: 2025-11-18