Architecture
aiscope is a 6-layer deterministic pipeline. This page maps the layers to the actual source modules.
┌─────────┐ ┌─────────────┐ ┌──────────┐ ┌───────┐ ┌─────────┐ ┌────────┐ ┌────────┐
│ scanner │→ │ frontmatter │→ │ md-parse │→ │ canon │→ │ extract │→ │ reason │→ │ render │
└─────────┘ └─────────────┘ └──────────┘ └───────┘ └─────────┘ └────────┘ └────────┘
Module layout
src/
├── main.rs # entry, CLI dispatch
├── cli.rs # clap arg model
├── lib.rs # public API, ContextBundle
├── types.rs # Source, Statement, Assertion, Conflict, Scope
├── scanner/
│ ├── mod.rs # discover() entry point
│ ├── common.rs # walkdir helpers, gitignore filter
│ ├── copilot.rs # .github/* + AGENTS.md
│ ├── cursor.rs # .cursor/* + .cursorrules
│ └── claude.rs # CLAUDE.md + .claude/* + --user
├── frontmatter/
│ └── mod.rs # YAML/TOML parser → Scope
├── parse.rs # markdown → Statement[]
├── canon.rs # NFKC + light stemming
├── extract/
│ ├── mod.rs
│ └── pattern.rs # regex assertion extractors
├── reason/
│ ├── mod.rs
│ ├── matrix.rs # Specific-mode subsystem table
│ ├── overlap.rs # globset-based scope overlap
│ └── tools.rs # AgentToolMismatch detector
└── render/
├── tui.rs # ratatui interactive
├── text.rs # plain text
├── diag.rs # miette
├── json.rs # serde_json
└── card.rs # tiny-skia + cosmic-text PNG
Key types
#![allow(unused)] fn main() { pub struct ContextBundle { pub root: PathBuf, pub sources: Vec<Source>, pub statements: Vec<Statement>, pub assertions: Vec<Assertion>, pub conflicts: Vec<Conflict>, pub total_tokens: usize, pub stale_tokens: usize, } }
Every renderer takes &ContextBundle. Adding a new output format means one
new module — nothing else changes.
Determinism
walkdirresults are sorted before consumption.HashMapis never iterated for output — we useBTreeMapor sort first.- No threads, no async runtime, no clock reads in the hot path.
Same input → byte-identical JSON, byte-identical card PNG, identical
diagnostic line order. This is what makes aiscope check safe to wire into
CI.
Test suite
42 tests across:
- per-module unit tests (frontmatter, canon, extract, overlap, matrix)
- end-to-end fixtures (
tests/fixtures/) with golden snapshots - copilot-only fixture proving single-tool repos work
- privacy-guard tests asserting
~/.claude/projects/is never read
Run cargo test to see.