- Use nextest:
cargo nextest runfor tests,cargo test --docfor doctests - Product spelling: always write the product name as
acdc, lowercase. Preserve other casing only in exact external quotations or case-sensitive identifiers and test inputs. - Worktree ownership: inspect
git status --shortbefore editing. Preserve unrelated and staged work, and do not stage or commit unless the user explicitly asks. - Feature coverage: use
--all-featuresfor standard test/build/clippy commands. When a task changes supported feature-off behavior, also run the applicable documented--no-default-featuresconfiguration. - Clippy pedantic:
cargo clippy --all-targets --all-features -- --deny clippy::pedantic --deny clippy::todo - Format before committing:
cargo fmt --all - Compact imports: merge imports from the same crate/module into one
usewith braces, e.g.use std::{borrow::Cow, io::Write};— not separateuse std::borrow::Cow;/use std::io::Write;lines - Update changelogs: each crate has its own
CHANGELOG.md; update[Unreleased]for affected crates. Entries describe what a user sees or is affected by — the new behavior, the attribute/option to reach it, and any divergence fromasciidoctor. Never regurgitate internal mechanics (function/field names, struct changes, control flow); those belong in code/commits, not the changelog. - Surface converter warnings structurally: user-relevant converter warnings should use
Warning/Diagnostics, nottracing::warn! - Never use CLI for fixtures: use the examples directly (CLI adds
last_updatedtimestamps) - asciidoctor is reference: compare one source using the built
acdcCLI and the matching asciidoctor backend first. Compare observable behavior, not byte-identical output, and avoid temporary Rust harnesses. Use thecompare-asciidoc-outputagent only after a direct comparison confirms a divergence or deeper research is needed. For PDF comparisons, keep clearly named*-acdc.pdfand*-asciidoctor.pdfoutputs; do not create raster previews unless the user asks.
Workspace crates and key source directories are listed below.
Check the root Cargo.toml for workspace membership and read any directory-specific AGENTS.md before editing that area.
acdc/
├── acdc-cli/ # Command-line interface
│ └── src/main.rs # CLI entry point
├── acdc-editor-wasm/ # WASM live editor with syntax highlighting and preview
├── acdc-execute/ # Discover and run AsciiDoc command blocks
├── acdc-lint/ # Recommended-practice lint checks
├── acdc-lsp/ # Language Server Protocol server
│ └── src/
│ ├── capabilities/ # Diagnostics, hover, completion, rename, references, semantic tokens
│ └── state/ # Document and workspace state, cross-file anchor index
├── acdc-parser/ # Core parser and AST
│ ├── src/
│ │ ├── grammar/ # PEG grammar definitions
│ │ ├── model/ # AST data structures
│ │ ├── preprocessor/ # Include and conditional handling
│ │ └── proptests/ # Property-based tests
│ └── fixtures/ # Parser test fixtures
└── converters/ # Output converters
├── core/ # Shared converter traits and utilities
├── dev/ # Development and testing utilities
├── html/ # HTML5 converter
├── manpage/ # Native roff/troff manpage output
├── markdown/ # CommonMark and GitHub Flavored Markdown output
├── pdf/ # PDF output backed by the Rust Typst engine
│ └── crates/
│ ├── images/ # Local, remote, and data URI image resolution
│ ├── render/ # Typst compilation to PDF
│ ├── theme/ # YAML themes, bundled fonts, and syntax theme
│ └── typst/ # Shared Typst writing utilities
└── terminal/ # Rich terminal output
-
Never run Cargo commands concurrently against the same target directory.
-
During implementation, run the smallest relevant package, test, or stable nextest expression, such as
-E 'test(/name/)'rather than a generated fixture number. -
Use
--all-featuresfor standard validation. When changing feature-off behavior, also run the applicable documented--no-default-featureschecks. -
At a cross-crate, public-API, checklist, or commit boundary, run:
cargo fmt --all -- --check cargo nextest run --workspace --all-features cargo test --doc --workspace --all-features cargo clippy --all-targets --all-features -- --deny clippy::pedantic --deny clippy::todo git diff --check
-
Report whether a broad command failed during compilation or after tests began.
-
Do not rerun Rust checks after a documentation-only wording change when the relevant code checks have already passed.
pre-spec-subs, setext, and network are declared in acdc-parser and forwarded by every crate that consumes them, so a workspace --no-default-features build turns them off consistently. The rest are converter-local.
| Feature | Default | Crate | Notes |
|---|---|---|---|
pre-spec-subs |
on | parser (+ all converters and lint) | acdc-parser/AGENTS.md (parser contract) + converters/AGENTS.md (converter plumbing & fixtures) |
setext |
on | parser | Setext (two-line underlined) headers |
network |
off | parser | Remote include::https://...[] (pulls in ureq) |
highlighting |
off | html, terminal | syntect source highlighting |
terminal |
off | html | Renders terminal previews into HTML; the cli exposes it as html-terminal |
emulator |
off | terminal | Runs terminal output through a libghostty-vt terminal emulator and captures the rendered screen grid (static previews + session replays); the cli exposes it as terminal-emulator |
images |
off | terminal | Inline terminal image rendering (viuer) |
New code that gates parsing or rendering on a specific substitution belongs behind pre-spec-subs, not an ad-hoc cfg.
When tests fail, identify the category and follow the appropriate path:
- Fixture mismatches → run the
regen-fixturesskill (ask first). If the skill is unavailable, ask before using the documented scoped generator. - Parser / grammar / preprocessor failures →
acdc-parser/AGENTS.md - Converter failures →
converters/AGENTS.md
acdc-parser has two Criterion benches. parser_bench (string-parse hot paths) runs
under a bare cargo bench. f1_include_bench (include / partial-include parsing) is
disabled by default (bench/test = false) so CI and cargo bench/cargo test
skip it — it writes temp fixtures and takes minutes. Run it on demand when touching the
include/preprocessor/remap paths: cargo bench --bench f1_include_bench.
Beware machine drift: a single before/after run on this hardware shows a uniform few-percent shift (confirmed via a before-vs-before run) that swamps small real deltas. For trustworthy numbers use a paired/alternating run (alternate the old and new binaries back-to-back several times and compare adjacent pairs), with an untouched benchmark as a codegen-bias control.
All crates have independent versions — bump only crates that changed.
- Published to crates.io:
acdc-parser - Not published:
acdc-cli,acdc-lint,acdc-lsp,acdc-converters-core,acdc-converters-html,acdc-converters-manpage,acdc-converters-markdown,acdc-converters-terminal,acdc-converters-dev,acdc-editor-wasm
acdc-cli and acdc-lsp are distributed as binaries but we haven't built a pipeline to produce these as GitHub releases yet; acdc-editor-wasm ships via GitHub Release; the converters and acdc-converters-dev are internal workspace members only.
Released via GitHub Actions. Bump version in Cargo.toml, update changelog, commit, tag acdc-editor-wasm-vX.Y.Z, push.