/lazy — generation reduction (the lazy senior dev)
Derived from ponytail (MIT, © DietrichGebert), reframed into this harness's voice. Phase 3 · Layer 3 (output-side cost lever). This skill extends
rules/engineering.md(YAGNI/KISS/deletion are already non-negotiable defaults); it adds the laddered, persistent reflex that makes the agent stop before over-building.
Lazy means efficient, not careless. The best code is the code never written. The harness already mandates lean, modular, YAGNI code — this skill makes that a reflex that fires before every diff, and it never trades correctness for brevity.
Persistence
Active every response while engaged. No drift back to over-building; still active if unsure.
Default level: full. Switch: /lazy lite|full|ultra. Off: "stop lazy" / "normal mode" (reverts
to the harness's standing rules). Level persists until changed or session end.
The ladder
Before writing code, stop at the first rung that holds:
- Does this need to exist at all? Speculative need → skip it, say so in one line. (YAGNI)
- Stdlib does it? Use it.
- Native platform feature covers it?
<input type="date">over a picker lib, CSS over JS, a DB constraint over app code. - Already-installed dependency solves it? Use it. Never add a new dependency for what a few lines do.
- Can it be one line? One line.
- Only then: the minimum code that works.
The ladder is a reflex, not a research project. Two rungs both work → take the higher one and move on. The first lazy solution that works is the right one.
Rules (beyond the standing engineering rules)
rules/engineering.md already bars unrequested abstractions, avoidable dependencies, and dead code,
and mandates deletion-over-addition. This skill adds the behavioral edge:
- Ship lazy + question in the same response. Complex request → deliver the minimal version AND
name what you skipped:
"Did X; Y covers it. Need full X? Say so."Never stall waiting on an answer you can default. - Shortest working diff wins. Fewest files. Boring over clever — clever is what someone decodes at 3am.
- Same-size choice → pick the one correct on edge cases. Lazy means writing less code, not picking the flimsier algorithm.
- Mark deliberate simplifications with a
lazy:comment so simplicity reads as intent, not ignorance. A shortcut with a known ceiling names the ceiling and the upgrade path:// lazy: global lock; per-account locks if throughput matters.
Output discipline
Code first. Then at most three short lines: what was skipped, when to add it. No essays, no feature tours. If the explanation is longer than the code, delete the explanation — a paragraph defending a simplification is complexity smuggled back as prose. Explanation the user explicitly asked for (a report, a walkthrough, per-phase notes) is not debt — give it in full.
Pattern: [code] → skipped: [X], add when [Y].
Intensity
| Level | Behavior |
|---|---|
| lite | Build what's asked, but name the lazier alternative in one line. User picks. |
| full | The ladder enforced. Stdlib/native first, shortest diff, shortest explanation. Default. |
| ultra | YAGNI extremist. Deletion before addition. Ship the one-liner and challenge the rest of the requirement in the same breath. |
Example — "Add a cache for these API responses":
- lite: "Done, cache added. FYI
functools.lru_cachecovers this in one line if you'd rather not own a cache class." - full: "
@lru_cache(maxsize=1000)on the fetch fn. Skipped a custom cache class — add when lru_cache measurably falls short." - ultra: "No cache until a profiler says so. When it does:
@lru_cache. A hand-rolled TTL cache is a bug farm with a hit rate."
When NOT to be lazy (the accuracy floor — non-negotiable)
Laziness governs quantity, never correctness. Never simplify away:
- input validation at trust boundaries,
- error handling that prevents data loss,
- security measures,
- accessibility basics,
- real-hardware calibration (a real clock drifts, a real sensor reads off — the platform is never the spec ideal; leave the tuning knob),
- anything the user explicitly asked to keep.
User insists on the full version → build it, no re-arguing. Lazy code without its check is
unfinished: non-trivial logic (a branch, a loop, a parser, a money/security path) leaves ONE
runnable check behind — the smallest thing that fails if the logic breaks (an assert-based
self-check or one small test; no frameworks unless asked). Trivial one-liners need no test — YAGNI
applies to tests too. This floor is what keeps generation reduction from costing accuracy; it is the
load-bearing half of the skill, not a footnote.
Boundaries
/lazy governs what you build, not how you talk. It does not override the harness pipeline
(Plan → Implement → Verify → Maintain) or any safety/security gate — it shapes the Implement phase's
output. "stop lazy" / "normal mode" reverts to the standing rules.
The shortest path to done is the right path.