The plan,
by slice.
Each phase ships a thin strip through the whole system — extraction, IR, rule, output, cache, docs. We do not build the entire extractor and then the entire rule catalogue. We build one rule working end-to-end, then another, then another.
00 · Foundations (shipped)
01 · Markdown pack (shipped)
02 · Capability planner (in flight)
03 · Grammar & spelling (planned)
04 · CI & packaging (planned)
05 · Editor & LSP (planned)
Skeleton & walking spine
The goal of this slice
The Rust extractor emits a minimal Document IR. The Python runtime loads one rule, receives regions, and prints diagnostics. PyO3 wheels build on three platforms. CI runs green. The product exists in outline.
Deliverables
- PyO3 bindings with a narrow JSON-over-FFI boundary
- Document IR v0 — regions, ranges, content_hash
- One working rule: MD201 heading depth
- Text formatter with stable ordering
- stilyagi check reads paths and stdin
- CI green on Linux, macOS, Windows
Markdown policy pack
The goal of this slice
Heading hygiene, list consistency, link policy, inline code usage, punctuation within prose. Suppression comments arrive at line and block scope. SARIF output lands. Early adopters can replace Vale for most of their configuration.
Deliverables
- MD rule pack — 22 rules across headings, links, lists, code fences
- Suppressions: disable-line, disable-next-line, disable-block
- SARIF output, stable across invocations
- Safe-fix class with dry-run and --diff
- Cache v1 keyed by (content_hash, ruleset_id, capability_set)
- stilyagi rule list / show / describe
Capability planner & docstrings
The goal of this slice
Extend Stilyagi's reach into source-embedded prose. Introduce the capability planner so linguistic providers are loaded on demand only, and ship docstring extraction for Python and Rust. The planner is what makes the rest affordable: it lets grammar and spelling join the catalogue without taxing every lint run.
Deliverables
- Capability planner with explicit provider declarations
- Python AST extractor for Module, Class, Function docstrings
- Rust syn extractor for /// doc comments
- PYDOC rule pack — 14 rules
- RSDOC rule pack — 9 rules
- stilyagi dump-ir with --include annotations
- Owner metadata surfaced in diagnostics
Grammar & spelling providers
The goal of this slice
Add the linguistic providers behind the capability planner without compromising the offline base install. Grammar ships as stilyagi[grammar]; spelling as stilyagi[spell]. Neither is required to use Stilyagi's core value — but when enabled, they unlock the GRAM, SPELL, and TERM families.
Deliverables
- spaCy provider with model pinning and cache
- symspell spellchecker with a bundled dictionary
- GRAM rule pack — passive voice, sentence length, modal verbs
- SPELL rule pack — common words, allowlists, per-region scoping
- TERM rule pack — canonical term enforcement
- Documented optional-extras install story
CI, SARIF polish, packaging
The goal of this slice
Make Stilyagi trivial to adopt in CI pipelines, editors, and agentic workflows. Polish every surface a machine will read and every surface a developer will first encounter. Cached runs should be indistinguishable from clean runs modulo timestamp.
Deliverables
- Pre-commit hook with a config template
- GitHub Action with matrix-friendly defaults
- Reviewdog format parity
- SARIF v2.1.0 full schema conformance
- stilyagi config print / validate / explain KEY / locate
- Auto-discovery of stilyagi.toml and pyproject.toml
Editor integration & LSP
The goal of this slice
Land the editor story. A language server that speaks textDocument/diagnostic, supports codeAction for safe fixes, and respects the capability planner's cost model under interactive load. Incremental analysis keyed by content_hash and line_index. The 1.0 mark — Stilyagi is someone's daily driver.
Deliverables
- stilyagi-lsp process with workspace symbols
- Incremental re-analysis keyed by line_index
- codeAction handlers for safe and unsafe fixes
- Suppressions surfaced in hover & relatedInformation
- VS Code extension (thin)
- Neovim and Zed recipes
- 1.0.0 release with semver guarantees
What we will not do along the way
We will not ship a rule whose diagnostic we cannot justify in one sentence. We will not add a capability to the planner without naming who asked for it. We will not accept a dependency into the base install that pushes the wheel past thirty megabytes.
We will not invent a configuration key to paper over an ambiguous rule. If two users read a rule's description and expect different outcomes, that rule is not ready. It sits in the draft column until it is.
We will not write a linter that calls itself opinionated as a substitute for writing down the opinions. Each rule ships with a rationale paragraph and — where the rationale is contestable — a citation.