Skeleton First
The working method for this morning, as a fixed sequence.
The morning’s project block is 2 hours 25 minutes, split around the break. The phases:
| Phase | Budget |
|---|---|
| Phase 1: skeleton workshop | 45 minutes |
| Phase 2: cross-review | 15 minutes |
| Phase 3: generation under contract | 1 hour 25 minutes |
Phase 1: Skeleton workshop (45 minutes, no agent)
Forty-five minutes is enough because typing a skeleton is cheap. Deciding it’s the work, and the deciding is what this phase practices.
Write by hand, in src/lib.rs and modules:
- Every public type, with fields, or a comment explaining why the fields are private and what they will be.
- Every public function and method signature, with
todo!()bodies. - The error enums, one per module, implementing
std::error::Error. - Doc comments carrying the contracts: ordering, threading, blocking behavior, and failure semantics.
cargo check must pass. A skeleton that doesn’t compile isn’t
finished.
Unlike Project A’s M0, the design interview stays closed here: run its questions on yourselves. By Day 2 the questions should be yours.
As you write, apply yesterday’s tables to your own work: receivers,
parameter ownership, fallibility shapes, and any lifetime that appears in
anything pub. For each, ask the question from the lifetime page: who
decided this, and where is the decision written down?
Phase 2: Cross-review (15 minutes)
Swap skeletons with another pair. Each side files at least three findings in the other pair’s review log. Only signature-level findings are possible at this point. A finding made now saves someone from having to make it later against two thousand generated lines.
Phase 3: Generation under contract
Freeze the skeleton. The agent fills in bodies without changing public signatures; state that constraint in every prompt. Any signature change that turns out to be needed is a design change: it goes through the pair, gets a row in the log, and amends the skeleton before regeneration. Keep the diff between the frozen skeleton and the final one; it’s a debrief artifact.
Two guardrails belong to this phase (see Build Your Own Guardrails):
- Freeze by lint, not by vigilance. Ask the agent for the Clippy
configuration that enforces what your review decided (the banned
calls in
clippy.toml’sdisallowed-methods, the lint levels at the crate root), and requirecargo clippy -- --deny warningsgreen before any fill is accepted. - If any
unsafeappears in a fill, it needs two things before acceptance: acargo +nightly miri testrun and a written justification in the log. The usual outcome is a safe rewrite. Miri tells you whether the unsafe block is sound instead of leaving you to guess. If time permits, runmutest-rson the contract tests and look at what survives. A suite that no mutant can kill isn’t testing anything.