Skip to content

Phase 3 — const/macro examples, domain starters, quality signals, AI aids (completes the roadmap) - #20

Merged
rwilliamspbg-ops merged 7 commits into
mainfrom
feat/phase-3-breadth
Oct 14, 2026
Merged

rwilliamspbg-ops merged 7 commits into
mainfrom
feat/phase-3-breadth

Conversation

@rwilliamspbg-ops

Copy link
Copy Markdown
Owner

Phases 3a–3d of docs/roadmap-production-ready.md — the final phase. With this, the roadmap is complete.

What's in it

3a — const/macro testing examples. crates/core-tests/examples/const_eval_walkthrough.rs: const fns plus const _: () = assert!(...) static assertions — a broken const fn fails the build (verified: E0080: evaluation panicked: assertion failed), checked by every --all-targets build including CI's clippy. syntax-tests gains parse_cases!, a macro_rules! case-table expander with a fallback arm emitting a helpful compile_error!, plus a trybuild fixture whose expected diagnostic is our own message text — stable across rustc versions.

3b — Domain starter examples. examples/parser-starter/ (arithmetic evaluator: unit tests per construct, proptest panic-freedom/round-trips, total error enum), examples/async-service-starter/ (tokio key-value store: paused-time expiry tests, concurrent inserts, background sweeper with graceful shutdown), and examples/cli-starter/ (wc-style CLI: pure logic in the lib, thin main, integration tests spawning the real binary, --json output) — each a detached standalone workspace, documented in docs/domain-starters.md.

3c — Quality signals (opt-in, informational). just bloat / bloat-json (cargo-bloat, JSON included in the machine-readable outputs), just size (binary-size tracking), just timings (cargo's built-in compile-time report). Local recipes only — no CI gates.

3d — Docs. docs/ai-test-generation.md: the checklist every generated test must satisfy plus fill-in templates (signature→property derivation, trybuild, snapshot, golden tables, placement rules) — aimed at LLM-assisted test generation. docs/adoption.md gains a "Minimal adoption" section; docs/adding-tests.md gains "When to promote a template test into the real library's tests".

Notes

  • Final state, all verified: fmt clean; clippy -D warnings clean across all features; 64 tests pass in the full suite; compile-fail green; all three starters 0 failures.
  • Real bugs caught pre-commit: Option::is_none_or is Rust 1.82 against the declared MSRV 1.75; a paused-time ordering bug in the sweeper test (the task must register its timer before time advances); Copy derived on a struct holding a String; two byte-count miscalculations in golden expectations.

Context

Phases 1 and 2 are already merged (#17, #19), so this PR's diff is Phase 3 only — the final phase of the roadmap. The branch is stacked on the merged work, so there are no conflicts.

Phase 3 const/macro items from docs/roadmap-production-ready.md.

- crates/core-tests/examples/const_eval_walkthrough.rs (new): const fns
  (factorial, fibonacci), the const-testing primitive
  'const _: () = assert!(...)' — a broken const fn fails the BUILD
  (E0080), checked by every --all-targets build including CI's clippy —
  the same values consumed in a const context (a table whose length IS
  a const fn's output), and runtime #[test]s pinning them.
- syntax-tests gains parse_cases!: a macro_rules! case-table expander
  (one #[test] per row) with a fallback arm emitting a helpful
  compile_error! instead of the classic "no rules expected" wall, plus
  four macro-generated cases and a ui/fail/macro_case_missing_arrow.rs
  trybuild fixture — its expected diagnostic is OUR message text, stable
  across rustc versions, unlike the rendered errors the existing
  type-mismatch fixtures assert on. No new CI job: the compile-fail
  job's glob picks the fixture up.
- docs/adding-tests.md gains a "Compile-time and macro-powered checks"
  section; examples/README.md lists the new walkthrough.

Verified against real execution: the example runs and its 3 runtime
tests pass; a deliberately wrong static assertion was confirmed to fail
the build with 'E0080: evaluation panicked: assertion failed:
factorial(5) == 121' (scratch crate); the trybuild fixture passes with
the committed .stderr (7 unit tests, 1 compile-fail); fmt/clippy clean,
64 tests pass across the full feature set. One compile error caught
pre-commit: a 'use crate::parse_cases;' inside lib.rs is redundant
(unused-import) — #[macro_export] macros are in textual scope after
their definition; only external crates need the import.
Phase 3 domain-starter items from docs/roadmap-production-ready.md:
three self-contained example crates showing the template's test shapes
in real domains, each detached with an empty [workspace] table (the
fuzz/ pattern) so the default 'cargo test --workspace' stays fast and
dependency-light.

- examples/parser-starter/: arithmetic-expression evaluator — unit
  tests per construct (precedence, parens, unary minus, every error
  variant), proptest property tests (arbitrary strings never panic;
  generated operand pairs round-trip through format→parse→eval), and a
  total EvalError enum (no panics anywhere).
- examples/async-service-starter/: tokio key-value store —
  #[tokio::test(start_paused = true)] for deterministic expiry tests,
  concurrent inserts through a shared Arc<Mutex> store, and a
  background sweeper task with graceful shutdown.
- examples/cli-starter/: wc-style counting CLI — pure logic in the lib
  (unit-tested), thin main (I/O wiring only), integration tests
  spawning the real binary via env!("CARGO_BIN_EXE_tally") asserting
  stdout/stderr/exit codes, and --json machine-readable output.
- docs/domain-starters.md (new): the containment pattern, what each
  starter demonstrates, and how to copy one out. examples/README.md
  lists them.

Verified against real execution: parser 8 unit + 3 property + 1
doc-test; async-service 5 tests; cli 7 unit + 7 integration + a live
binary run — all green. Main workspace unaffected (45 tests, default
features). Three bugs caught pre-commit: Option::is_none_or is Rust
1.82 (the starters declare MSRV 1.75 — replaced with a match), a
paused-time ordering bug in the sweeper test (the task must register
its timer before time advances), and Copy derived on a struct holding
a String.
Phase 3 quality-signal items from docs/roadmap-production-ready.md —
local recipes only, no CI gates, consistent with the template's
informational stance for everything beyond correctness.

- just bloat / just bloat-json (cargo-bloat): code-size analysis per
  function/crate, table or JSON (bloat.json joins the Phase 1.3
  machine-readable outputs). Both variadic so callers pass --bin/
  --release/etc.
- just size: release-builds the template's example binary (the
  workspace itself is lib-only) and reports sizes; documents comparing
  your own target/release/<bin> across commits in an adopted workspace.
- just timings: cargo's built-in compile-time report — verified it
  writes target/cargo-timings/cargo-timing-*.html.
- README 'Coverage, Reporting, and Debugging' gains an 'Optional
  quality signals' bullet; docs/machine-readable-outputs.md lists
  bloat-json; .gitignore covers bloat.json.

Verified against real execution: cargo bloat --bin tally
--message-format json emits valid JSON (file/text-section sizes plus
per-function breakdown); the timings report is generated by
cargo build --release --workspace --timings.
…Phase 3d)

Phase 3 doc items from docs/roadmap-production-ready.md — the last
Phase 3 items, completing the exit criteria.

- docs/ai-test-generation.md (new): the checklist every generated test
  must satisfy (right category, right shape, no new default deps,
  MSRV 1.75, docs, determinism — mirroring the CONTRIBUTING process),
  plus fill-in templates for the common generation targets:
  signature→property derivation (totality, round-trip, invariance,
  boundary — in priority order), trybuild compile-fail (prefer
  compile_error! text over rendered rustc diagnostics),
  assert_debug_snapshot, golden-case tables, and mechanical
  category/fixture placement rules. Points at the evaluation harness
  for reviewing generated implementations, and the differential helpers
  for proving equivalence against a reference.
- docs/adoption.md: new 'Minimal adoption' section — the smallest
  useful signal (Cargo.toml with the inheritance tables + core-tests +
  syntax-tests, default features, zero heavy deps), growing one
  dependency-pulling category at a time, and the one thing never to
  trim (the workspace.package/lints tables).
- docs/adding-tests.md: new 'When to promote a template test into the
  real library's tests' — promote by moving not copying, keep feature
  flags honest; plus an intro pointer to ai-test-generation.md.

Final Phase 3 verification (all green): fmt clean; clippy -D warnings
clean across all features; 64 tests pass in the full suite;
compile-fail job green; all three starters 0 failures.
…MSRV doc-test

Two failures PR #20's CI run caught, both from Phase 2/3 additions and
both invisible to local verification on modern stable:

- 'cargo generate' aborted with 'Substitution skipped, found invalid
  syntax' on examples/cli-starter/src/lib.rs — its JSON renderer's
  format!("{{{}}}...") is valid Rust but invalid liquid (a {{ tag
  with no name), breaking the adoption job. Added to
  cargo-generate.toml's [template] exclude, together with target/** and
  examples/*/target/**: cargo-generate skips CACHEDIR.TAG dirs but not
  .gitignore, so a dirty working tree fed binary
  target/debug/.fingerprint/* files through the same parser (local
  'just adopt-test' hit this; CI's clean checkout didn't).
- The parse_cases! doc example failed the msrv job under Rust 1.75
  (E0601: no main function): 1.75's rustdoc decides whether to wrap a
  doctest in fn main() by textually scanning for one, and the
  example's "fn main() {}" string literals made it skip the wrapper.
  Newer rustdoc parses properly, so stable passed. The example now
  carries an explicit fn main wrapper, with a comment on why.

Verified locally against the exact CI conditions: 'cargo +1.75 test
--workspace --exclude performance-tests' (the msrv job's command,
lockfile deleted first per that job's procedure) exits 0 with
doc-tests green; './scripts/adoption-check.sh' passes end-to-end
including the generated tree's doc-tests; fmt clean, 64 tests pass,
compile-fail green.
The previous fix commit's own changelog entry reintroduced the exact bug
it documented: quoting format!("{{{}}}...") in prose is a {{{...}}} run
— invalid liquid — which aborted cargo generate on CHANGELOG.md in CI's
adoption job (the file my own entry had just taught readers about).

Changelogs are documentation and are never templated, so exclude the
whole file: this project's history legitimately discusses {{...}}
syntax repeatedly (the justfile's {{target}}, GitHub's
${{ ... }} expressions), and while *valid* liquid passes through
unchanged (verified: the generated docs keep ${{ github.base_ref }}
intact), any future entry quoting doubled braces would abort generation
the same way.

Verified: cargo generate exits 0 and copies CHANGELOG.md verbatim;
the full adoption script (both legs + eval harness) passes end-to-end.
The Unreleased section (Phases 2 and 3 — evaluation harness,
differential helpers, mutation polish, const/macro examples, domain
starters, quality signals, AI aids, plus the CI fixes) becomes
[1.1.0] - 2026-10-14, with a fresh empty Unreleased above it. Cutting
it here so the release tag lands with the changelog already complete.
@rwilliamspbg-ops
rwilliamspbg-ops merged commit b0447b8 into main Oct 14, 2026
22 checks passed
@rwilliamspbg-ops
rwilliamspbg-ops deleted the feat/phase-3-breadth branch October 14, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant