Iter 13f: rustdoc polish for ailang-codegen + ail CLI

Third docwriter mission (combined). Pure rustdoc additions, no
API or behaviour change.

ailang-codegen (113 LOC of doc):
- Crate root: intra-doc links (emit_ir, lower_workspace,
  CodegenError::MissingEntryMain) + precondition note (both
  entry points assume type-checked input).
- /// on CodegenError + every variant, naming AST trigger.
- /// on emit_ir and lower_workspace (single vs multi-module
  split, cross-linked).

ail CLI (49 LOC of doc):
- Module-level //! expanded from 5 lines to full subcommand
  list with one-liners (11 subcommands verified against Cmd
  enum), clang-on-PATH note, design-intent paragraph.

Verification: cargo doc --no-deps zero warnings (also under
RUSTDOCFLAGS='-D rustdoc::broken_intra_doc_links'); build green;
tests 64/64 + 3 ignored doctests green. Diff is 100% doc lines
(verified by filtering).

Findings (not fixed; orchestrator-deferred):
- CodegenError::Internal is one catch-all variant for ~30
  invariant-violation sites; splitting would help test
  ergonomics but is out of doc scope.
- emit_ir synthesises a Workspace with root_dir="."; harmless
  today, surfaces if codegen ever reads root_dir.

Process note: my brief said the CLI had 9 subcommands; agent
found and documented 11. Useful counter-pressure on orchestrator
sloppiness — recorded in JOURNAL.

Workspace-wide rustdoc invariant (DESIGN.md item 6) now
load-bearing across all four crates. Docwriter shifts from
sweep to maintenance mode going forward.

Next: 14a (polymorphic list_map using Iter-13a parameterised
ADTs) is unblocked.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-07 15:20:17 +02:00
parent d8727d5bdb
commit 1918fbee7f
3 changed files with 243 additions and 14 deletions
+95
View File
@@ -1312,3 +1312,98 @@ CLI) is the natural next polish iter; 14a (`List a` rewrite of
`list_map`) remains the next-feature default. Auto-mode is on,
so I'll continue into 13f directly unless context budget
pressures a switch.
## Iter 13f — rustdoc polish for `ailang-codegen` + `ail` CLI
Combined docwriter mission. Codegen has a small public
surface (only 3 top-level `pub` items: `CodegenError` enum +
7 variants, `emit_ir`, `lower_workspace`); the CLI is a
binary with zero `pub` items, so the only useful rustdoc is
the module header. One agent run, both files.
What landed (148 LOC of doc additions, no non-doc lines
changed, verified by filtering the diff):
- `ailang-codegen` crate root got intra-doc-link upgrades
(`[`emit_ir`]`, `[`lower_workspace`]`,
`[`CodegenError::MissingEntryMain`]`) and a precondition
sentence — both entry points assume their input has already
passed the typechecker; codegen does not call the checker
itself.
- Every `CodegenError` variant got a `///` string naming the
AST term/condition that triggers it. Same shape as
`CheckError` post-13e, so the two error enums now read
similarly and a reader can grep across them. `Internal` is
flagged in its doc as a catch-all that covers ~30
invariant-violation sites.
- `emit_ir` and `lower_workspace` now make the
single-vs-multi-module split explicit and cross-link to
each other.
- `ail/main.rs` module header expanded from a 5-line stub to
a full subcommand list with one-liners (`manifest`,
`render`, `describe`, `deps`, `check`, `emit-ir`, `build`,
`run`, `builtins`, `diff`, `workspace`), the `clang`-on-PATH
prerequisite for `build`/`run`, the design-intent paragraph
about each subcommand being narrowly scoped for LLM
consumption (already partly there), and an explicit "no
`pub` items, `--help` text comes from clap" note for anyone
who lands here from rustdoc.
**Findings reported** (judgement deferred to me):
- `CodegenError::Internal(String)` is a single opaque catch-all
for ~30 distinct invariant-violation sites (mono-queue
desync, ctor-index miss, lambda-env shape, ...). Tests can
only substring-match on it. **Not fixing**: splitting is a
test-ergonomics decision, not a doc one. Worth raising the
next time codegen tests get a serious rewrite.
- `emit_ir` synthesises an internal `Workspace` with
`root_dir = "."`. No codegen path reads `root_dir` today, so
this is harmless; if a future feature reaches `root_dir`
from codegen, the assumption surfaces. **Not fixing**: the
agent flagged it correctly as "would change behaviour, out
of scope".
**Process note: brief drift caught by the agent.** I told the
docwriter the CLI had nine subcommands; it found eleven
(`Deps` and `Diff` were missing from my brief, which was
written off a `head -40` of the source). Agent silently
corrected and flagged the drift in its findings. Useful
counter-pressure to the orchestrator pattern: my survey was
sloppy and the agent did not propagate the sloppiness into
the doc. This is one of the things sub-agents are good at and
why I keep delegating even on small jobs.
**Tests:** 64/64 unit + e2e (unchanged), 3 ignored doctests
(unchanged). `cargo doc --no-deps`: 0 warnings. Also verified
under `RUSTDOCFLAGS='-D rustdoc::broken_intra_doc_links'` per
agent report. `cargo build --workspace` green. `cargo test
--workspace` green.
**Workspace-wide rustdoc invariant achieved.** All four
crates (`ailang-core`, `ailang-check`, `ailang-codegen`,
`ail`) now have:
- crate-root `//!` that names ownership, position in
pipeline, and entry points;
- module-root `//!` on every file with non-trivial content;
- `///` on every public item (struct, enum, variant, fn,
field, const) that names the contract, not just the type;
- intra-doc links wherever prose previously referred to
another item by name.
DESIGN.md item 6 ("rustdoc cleanliness") is now load-bearing
across the whole workspace, not just `core`. The
`ailang-docwriter` agent's job from here is **maintenance**:
run after any iter that adds public surface, not full sweeps.
**Next.** 14a is now unblocked: write a polymorphic `list_map`
that uses `List a` (Iter-13a parameterised ADTs) and `Maybe a`,
then extend an existing demo program (`hello_print` or one of
the dogfood sources) to call it end-to-end. That exercises
the parameterised-ADT pipeline through type-check, codegen,
and runtime — the missing piece in 13a/b/c was that the
feature shipped but no real program used it. If context
budget at the start of 14a is tight, alternative is 14b
(GC/arena scaffolding) or 14c (poly fn as value); both have
real design questions that need an orchestrator design pass
first, so 14a stays the default.