Metis (condensed)
Write code that favors plain data, pure logic, clear call sites, and
early architectural thinking. Strong defaults, not laws: follow the
codebase, framework, and language when they clearly matter more.
Design
- Start from the call site by wishful thinking: write the caller you
wish existed, then make helpers match. Awkward calling code means
wrong abstractions — found before building anything.
- Plain data + focused functions/modules over behavior-heavy objects.
Boundaries around what systems DO, not what entities ARE.
- Simplest state model that matches reality: discriminated unions for
mutually exclusive states, composable data for orthogonal features,
a flat record when neither pressure exists.
- Mutation and I/O at the edges; orchestration decides, leaves do
narrow work; push ifs up, fors down.
- Assert at boundaries both ways (entering and leaving): parsing,
persistence, APIs, state transitions. Check what must be true AND
what must not be.
- Design for the hardest real requirement first, then simplify down.
When batch elements can invalidate each other, classify the whole
batch before applying any element.
- Trace invariants before adding defensive checks: if an upstream
parser/type/boundary already guarantees it, do not re-check.
Working
- Prefer pure functions and data transformations; adapters around
awkward external APIs; invariants next to the operations that need
them (do not validate early and trust it later if data can drift).
- Self-explaining names; comments only for a non-obvious WHY, one line.
- SOLID as a checklist without ceremony: one reason to change; extend
via a focused function/variant/adapter, never pre-built extension
points; variants honor the contract; narrow interfaces; policy
depends on stable abstractions, not I/O details.
Tests
Decide expected behavior BEFORE implementing; prefer a failing behavior
check first (red-green) when practical. Prefer integration/contract
tests over implementation-mirroring unit tests. One visible behavior
per test; no loops/branches hiding the harness. Never move goalposts to
make broken code look right. Delete scaffolding tests before done.
Review (diff/PR)
Passes, one question each: 1) correctness/contracts + failure paths;
2) data/state (plain data, unions, mutation at edges); 3) control flow
and API shape (call sites, ifs-up-fors-down, no speculation); 4) tests
and slop (narrating comments, duplicate checks, dead scaffolding).
Verify each finding against the code before reporting; report as
file:line, severity, one sentence. Quality findings are not padding.
Before claiming done
Re-read the request; run the relevant checks and READ the output; review
the diff for slop (narrating comments, duplicated guards, speculative
abstractions, doc/test spam); keep only tests that earn their place.
When implementing or fixing (agentic work)
- For every requirement, write the failing behavior check FIRST when a
test harness exists; watch it fail, fix, watch it pass. Commit the
check with the fix — a fix without a guarding test is half done.
- Fix causes, not sites: when two symptoms share a root, restructure
the root; when a defect class exists once, look for its siblings
before finishing (the same stale-check or missing-boundary usually
appears more than once).
- Optimize for the NEXT change: after the fix works, ask what the next
feature in this area costs; if your structure makes it expensive
(touching many branches/classes), restructure to data + one system
now, while context is loaded.
- Long task lists do not suspend quality: the last requirement gets the
same test, assertion, and naming discipline as the first. Do not drop
the quality pass because the functional list is long.
- Leave the campsite cleaner: delete dead code and scaffolding you
find mid-task if it is inside the code you already changed.
1---2name: p8-agentic3description: Metis (condensed)4---5# Metis (condensed)67Write code that favors plain data, pure logic, clear call sites, and8early architectural thinking. Strong defaults, not laws: follow the9codebase, framework, and language when they clearly matter more.1011## Design12131. Start from the call site by wishful thinking: write the caller you14 wish existed, then make helpers match. Awkward calling code means15 wrong abstractions — found before building anything.162. Plain data + focused functions/modules over behavior-heavy objects.17 Boundaries around what systems DO, not what entities ARE.183. Simplest state model that matches reality: discriminated unions for19 mutually exclusive states, composable data for orthogonal features,20 a flat record when neither pressure exists.214. Mutation and I/O at the edges; orchestration decides, leaves do22 narrow work; push ifs up, fors down.235. Assert at boundaries both ways (entering and leaving): parsing,24 persistence, APIs, state transitions. Check what must be true AND25 what must not be.266. Design for the hardest real requirement first, then simplify down.27 When batch elements can invalidate each other, classify the whole28 batch before applying any element.297. Trace invariants before adding defensive checks: if an upstream30 parser/type/boundary already guarantees it, do not re-check.3132## Working3334- Prefer pure functions and data transformations; adapters around35 awkward external APIs; invariants next to the operations that need36 them (do not validate early and trust it later if data can drift).37- Self-explaining names; comments only for a non-obvious WHY, one line.38- SOLID as a checklist without ceremony: one reason to change; extend39 via a focused function/variant/adapter, never pre-built extension40 points; variants honor the contract; narrow interfaces; policy41 depends on stable abstractions, not I/O details.4243## Tests4445Decide expected behavior BEFORE implementing; prefer a failing behavior46check first (red-green) when practical. Prefer integration/contract47tests over implementation-mirroring unit tests. One visible behavior48per test; no loops/branches hiding the harness. Never move goalposts to49make broken code look right. Delete scaffolding tests before done.5051## Review (diff/PR)5253Passes, one question each: 1) correctness/contracts + failure paths;542) data/state (plain data, unions, mutation at edges); 3) control flow55and API shape (call sites, ifs-up-fors-down, no speculation); 4) tests56and slop (narrating comments, duplicate checks, dead scaffolding).57Verify each finding against the code before reporting; report as58file:line, severity, one sentence. Quality findings are not padding.5960## Before claiming done6162Re-read the request; run the relevant checks and READ the output; review63the diff for slop (narrating comments, duplicated guards, speculative64abstractions, doc/test spam); keep only tests that earn their place.6566## When implementing or fixing (agentic work)67681. For every requirement, write the failing behavior check FIRST when a69 test harness exists; watch it fail, fix, watch it pass. Commit the70 check with the fix — a fix without a guarding test is half done.712. Fix causes, not sites: when two symptoms share a root, restructure72 the root; when a defect class exists once, look for its siblings73 before finishing (the same stale-check or missing-boundary usually74 appears more than once).753. Optimize for the NEXT change: after the fix works, ask what the next76 feature in this area costs; if your structure makes it expensive77 (touching many branches/classes), restructure to data + one system78 now, while context is loaded.794. Long task lists do not suspend quality: the last requirement gets the80 same test, assertion, and naming discipline as the first. Do not drop81 the quality pass because the functional list is long.825. Leave the campsite cleaner: delete dead code and scaffolding you83 find mid-task if it is inside the code you already changed.