Use when starting a Rust feature, module, or rewrite skeleton-first — design the types and signatures, land a compiling skeleton whose bodies are todo!() as its own commit, then fill the holes in a separate later pass; never mix the two.
Instal·la
npx skillscat add platypeeps/sd-ai-command-pack/sd-typed-holes Instal·la des del registre de SkillsCat.
sd-typed-holes
Split Rust work into two passes that never mix. First lay the complete type
surface — real signatures, real types, todo!() bodies — and prove it
composes under check and lint before any behavior exists. Then fill the
holes one at a time against that fixed surface. The compiler reviews the
design in the first pass; the second pass cannot silently change it.
When to use
Use when starting a Rust feature, module, or rewrite where the type surface
deserves review before behavior exists, when splitting Rust work into
independently deliverable units, or when delegating implementation to
executors that must not redesign the surface they fill.
Do not use for one-line fixes or edits inside an existing surface, and do
not use it to model the types themselves — sd-rust-design owns the
modeling rules the skeleton must satisfy.
Arguments
None.
This skill takes no key=value arguments.
Unknown argument names are an error — stop and report them before starting.
Workflow
- Design the type surface with
sd-rust-design: states as enums,
transitions as consuming methods, constrained constructors returningResultwith their error enums fully written. Record, per public
type, the one business rule it enforces and the illegal state it
forbids. - Lay the skeleton — the full surface and nothing else:
- real signatures, derives, conversion impls, and leaf types; no
placeholderStringstanding in for a type not yet written; todo!()only in bodies with real behavior — parsing, rendering,
assembly, anything with a decision in it;- trivial accessors implemented, not held open: a field read left as
todo!()hides surface from the compiler instead of exposing it.
- real signatures, derives, conversion impls, and leaf types; no
- Mark the holes so they ask to be removed:
- each
todo!()function with parameters carries#[expect(unused_variables, reason = "hole; filled by <unit>")]—
once the lint stops firing the marker warns; leave a hole unmarked
wherever the lint could not fire in the first place and the
expectation would go unfulfilled the moment it was written — a
zero-parameter hole, a receiver-only one (unused_variablesnever
fires onself), and one whose parameters are all
underscore-prefixed, which is the same suppression by another name; - the module enters with
#![allow(dead_code)], removed slice by
slice as the surface goes live; - both markers get explicit removal steps in the fill plan — a filled
body that still ignores a parameter keeps its marker silent, so
each fill sweeps by hand.
- each
- Gate the skeleton alone: workspace check and clippy with warnings
denied, plus a format check, all green with every behavioral body
stilltodo!()— the trivial accessors step 2 asks you to implement
stay implemented. Then propose the skeleton as its own commit, so the
reviewed design is a retrievable git object rather than a
conversation, and let the user make it. Committing is theirs to
authorize; this workflow reaching step 4 is not that authorization. - Track the holes deterministically —
todo!()is a diverging panic the
compiler happily accepts, so nothing tracks it for you. Prefer the
clippy lint fortodo!(): warn during the fill phase, deny as the
completion gate. Agrep -rn 'todo!('baseline is the fallback, and
it is a lower bound rather than a census — it misses a hole writtentodo! ()or produced by a macro, and counts occurrences in comments
and string literals. Take the baseline at the skeleton commit, account
for every changed line per fill, and let the lint, never the grep,
decide that the holes are closed. - Review the skeleton before any body lands: apply the
sd-rust-reviewprobe lens to the skeleton diff and route the change
through thesd-reviewlane, which owns the verdict. Design repairs
land as skeleton amendments, before filling starts. - Fill the holes in a later pass, one body at a time: run the check
after each fill to narrow the next hole's types, sweep the filled
function's marker, account for its inventory lines, and hold each
body tosd-rust-quality. A fill that needs a signature, derive, or
type change has found a skeleton defect — stop, amend the skeleton as
its own reviewed change, then resume filling. Never let a fill mutate
the surface in passing. - Close out: remove the remaining dead-code allowance, flip the hole
lint to deny or show the grep returning nothing, and confirm the
surface carries no marker whose reason is stale.
Safety rules
- Never mix the passes: a change that both alters the type surface and
implements behavior defeats the point and must be split before it
lands. - Never let a fill silently change a signature, derive, visibility, or
error variant; surface changes are skeleton amendments with their own
review. - Do not over-claim what the green skeleton proves: it shows the design
composes, not that behavior is correct — derives and runtime semantics
still need inspection and tests. - Keep the hole inventory honest: no fill unit closes while a hole it
owns survives, and no marker outlives the truth of its reason. - Review verdicts on either pass belong to the
sd-reviewlane; this
workflow schedules reviews, it does not decide them.
Final report
- Surface summary — the public types with their business rules and
forbidden states, per the design record; - Skeleton commit — the commit that carries the surface and its
green check, lint, and format evidence; - Hole inventory — holes opened, holes filled, holes remaining, and
the tracking mechanism (lint level or grep baseline); - Marker status — expect-markers and dead-code allowances still
standing and the units that will remove them; - Fill progress — bodies filled this pass and the per-fill check
results; and - Handoffs — reviews routed to the
sd-reviewlane.
Lineage
Re-authored from the typed-holes skill ingithub.com/Shearerbeard/claude-skills (plugins/rust/skills/typed-holes/,
revision c79fe3a). That repository ships no licence file — LICENSE,LICENSE.md, LICENSE.txt and COPYING are all absent as of that revision —
so its terms are unstated rather than permissive. Nothing here is copied
verbatim: the ideas were rewritten in this pack's conventions, which is what
the absence of stated terms permits and is why this section says so plainly
instead of naming a licence it cannot cite.
It reached this pack by two hops. It was written as se-typed-holes inplatypeeps/se-ai-command-pack commit 9de85c3 (2026-08-27), one of the
thirteen se-* skills of that pack's Engineer family, and folded here assd-typed-holes in 56ba92eb (2026-08-31, #640) alongside sixty-three
siblings.
What was left upstream, and why it matters here. Upstream is a two-layer
practice. Layer 1 is the type-checked skeleton this skill kept. Layer 2 —
whole-frame golden tests written from the spec so that they fail on arrival —
was not carried over. Layer 2 is test-first under another name, so dropping it
is worth knowing: what reads as a skill opposing test-first is a skill missing
the half that supplied it, not a practice that rejected it.
How this skill relates to sd-tdd is not settled here. The obvious answer —
that the type surface and the todo!() bodies are exempt from test-first while
the bodies that get filled are not — does not survive contact with step 2,
which also lands derives, From/Into impls, and trivial accessors
implemented rather than held open. Each of those has a real body and real
runtime semantics, and a getter returning the wrong same-typed field compiles
and passes clippy. This skill's safety rules already say a green skeleton shows
the design composes and not that behavior is correct. Writing the boundary
precisely enough to be followed was tried and failed review three times, so it
is named as an open question rather than stated wrongly a fourth.
Four of the rules above look arbitrary and are each a corrected error, from the
review rounds that followed the original: 419f9131, 10b32167, 78f3dc2b
and 037d6137. They fixed a skeleton gate that demanded every body still be a
hole while also demanding trivial accessors be implemented; two cases where#[expect(unused_variables)] is unfulfillable the moment it is written,
because the lint fires on neither a receiver nor an underscore-prefixed
parameter; and the standing of grep -rn 'todo!(', which is a lower bound
rather than a census and sits behind the clippy lint for that reason.