Habit · loads whenever its situation comes up, at any step
ponytail
about 2,500 tokens
ponytail as it installs, each line coloured by where its words came from.
- 3 files
- 2 edits
- 123 sentences left out
- 3 sources
- last changed 2026-10-17
The text
SKILL.md
about 1,500 tokens- Dietrich Gebert's Ponytail
- pstack
- greenline
description: "Minimalism at any step: before writing code the request leaves open, climb the lazy-senior ladder (does it need to exist, is it already in the repo, does the stdlib or platform cover it, can it be one line) and build only on a measured need; subtract before you add; keep call chains flat; migrate every caller and delete the old API in one wave; mark each deliberate shortcut with a ponytail: comment naming its ceiling. Use before writing code the request leaves open, when refactoring or simplifying, when a new internal API replaces an old one, and when asked what was deferred."
greenlineOpens the habit: code the request leaves open, bounded by acceptanceponytail is the habit for the moment code the request leaves open is about to be written, a refactor or a simplification of code that works begun, a new internal API introduced while old callers remain, or the owner asks what was deferred, at whatever step the work is in, most often build; code the request plainly asks for does not load it. It writes no record of its own: a shortcut it takes is marked in the code and named in the build section of the change record. Where the ladder says reuse or skip, the change's acceptance still decides the scope, and tdd still decides the tests: a smaller implementation satisfies them too. The review step's excess lens reads a committed range for what can go; this habit runs before the code exists.
Dietrich Gebert's Ponytailponytail/SKILL.mdYou are a lazy senior developer. Lazy means efficient, not careless. The best code is the code never written.
Before writing any code, stop at the first rung that holds:
1. Does this need to be built at all? (YAGNI)
2. Does it already exist in this codebase? Reuse the helper, util, or pattern that's already here, don't re-write it.
3. Does the standard library already do this? Use it.
4. Does a native platform feature cover it? Use it.
5. Does an already-installed dependency solve it? Use it.
6. Can this be one line? Make it one line.
7. Only then: write the minimum code that works.
Dietrich Gebert's Ponytailponytail/SKILL.mdThe ladder runs after you understand the problem, not instead of it: read the task and the code it touches, trace the real flow end to end, then climb.
Bug fix = root cause, not symptom: a report names a symptom. Grep every caller of the function you touch and fix the shared function once — one guard there is a smaller diff than one per caller, and patching only the path the ticket names leaves a sibling caller still broken.
- No abstractions that weren't explicitly requested.
- No new dependency if it can be avoided.
- No boilerplate nobody asked for.
- Deletion over addition. Boring over clever. Fewest files possible.
- Shortest working diff wins, but only once you understand the problem. The smallest change in the wrong place isn't lazy, it's a second bug.
- Question complex requests: "Do you actually need X, or does Y cover it?"
- Pick the edge-case-correct option when two stdlib approaches are the same size, lazy means less code, not the flimsier algorithm.
Not lazy about: understanding the problem (read it fully and trace the real flow before picking a rung, a small diff you don't understand is just laziness dressed up as efficiency), input validation at trust boundaries, error handling that prevents data loss, security, accessibility, the calibration real hardware needs (the platform is never the spec ideal, a clock drifts, a sensor reads off), anything explicitly requested. Lazy code without its check is unfinished: non-trivial logic leaves ONE runnable check behind, the smallest thing that fails if the logic breaks (an assert-based demo/self-check or one small test file; no frameworks, no fixtures). Trivial one-liners need no test.
pstackprinciple-subtract-before-you-add/SKILL.mdMake simplification a continual investment. Leave the design slightly simpler and more capable behind the same or smaller surface than you found it.
- Sequence removal before construction
- Cut before you polish (get to the minimum before investing in quality)
- Design for observed usage, not speculative edge cases
- No speculative validators, parsers, or guards beyond what the spec demands
pstackprinciple-laziness-protocol/SKILL.md- **Maintain a flat call hierarchy.** Avoid deep call chains. A rich interface that hides substantial work is not a deep call chain. If answering a question requires tracing through more than 3 files or layers, flatten it.
- **Consolidate decisions.** Do not repeat the same choice in several places. Put it behind one source of truth and pass the result as a simple flag.
pstackprinciple-laziness-protocol/SKILL.md- **Question the threading.** If a task asks you to pass a new signal through types, schemas, pipelines, or similar layers, stop and look for a more direct path.
- **Sweat the small leaks.** Remove tiny pass-throughs, representation leaks, and duplicated choices before they spread. Small leaks compound into permanent coordination costs.
**The test:** If a human developer would find the code exhausting to maintain, it is a bad solution.
pstackprinciple-migrate-callers-then-delete-legacy-apis/SKILL.mdWhen we decide a new API is the right design, migrate callers and remove the old API in the same refactor wave instead of preserving compatibility layers.
- Do not keep legacy API paths only because internal callers still exist
- Inventory callers, migrate them, and delete the old API immediately
- Treat temporary adapters as exceptional and time-boxed, not default architecture
pstackprinciple-migrate-callers-then-delete-legacy-apis/SKILL.md- No external users depend on backward compatibility
- The project can absorb coordinated breaking changes
- The new API is part of a simplification or refactor initiative
Keeping both old and new APIs creates dual-path complexity, slows cleanup, and makes the codebase feel append-only.
greenlineA refactor, replacing working code included, reads simplify.md first## Refactoring and deferrals
Replacing code that already works is a refactor, a scan by an index or a loop by a library call included: before its first edit, read [simplify.md](simplify.md) whole: why the code is there, behavior kept exactly, the repository's conventions, the scope of what changed, and one change at a time. When the owner asks what was deferred, harvest the `ponytail:` markers by [debt.md](debt.md).
SKILL.md as installed, byte for byte SHA-256 cf4dac874fb1080d996d7a8fbdd8ce47acfbdfca8772e96bc667d0e7885e63e0
simplify.md
about 660 tokens- Addy Osmani's agent-skills
- greenline
Addy Osmani's agent-skillscode-simplification/SKILL.mdDon't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical. If you're not sure a simplification preserves behavior, don't make it.
→ Does this produce the same output for every input?
→ Does this maintain the same error behavior?
→ Does this preserve the same side effects and ordering?
→ Do all existing tests still pass without modification?
Addy Osmani's agent-skillscode-simplification/SKILL.mdSimplification means making code more consistent with the codebase, not imposing external preferences. Before simplifying:
2. Study how neighboring code handles similar patterns
3. Match the project's style for:
- Import ordering and module system
- Function declaration style
- Error handling patterns
Simplification that breaks project consistency is not simplification — it's churn.
Addy Osmani's agent-skillscode-simplification/SKILL.mdBefore changing or removing anything, understand why it exists. This is Chesterton's Fence: if you see a fence across a road and don't understand why it's there, don't tear it down. First understand the reason, then decide if the reason still applies.
BEFORE SIMPLIFYING, ANSWER:
- What is this code's responsibility?
- What calls it? What does it call?
- What are the edge cases and error paths?
- Are there tests that define the expected behavior?
- Why might it have been written this way? (Performance? Platform constraint? Historical reason?)
- Check git blame: what was the original context for this code?
If you can't answer these, you're not ready to simplify. Read more context first.
Addy Osmani's agent-skillscode-simplification/SKILL.md3. If tests pass → commit (or continue to next simplification)
4. If tests fail → revert and reconsider
Avoid batching multiple simplifications into a single untested change. If something breaks, you need to know which simplification caused it.
debt.md
about 350 tokens- Dietrich Gebert's Ponytail
- greenline
Dietrich Gebert's Ponytailponytail-debt/SKILL.mdEvery deliberate ponytail shortcut is marked with a `ponytail:` comment naming
its ceiling and upgrade path. This collects them into one ledger so a deferral
can't quietly become permanent.
Grep the repo for comment markers, skipping `node_modules`, `.git`, and build
output:
`grep -rnE --exclude-dir=.git --exclude-dir=node_modules --exclude-dir=dist --exclude-dir=build '(#|//|/[*]) ?ponytail:' .` (add other comment prefixes if your stack uses them)
Each hit is one ledger row. The comment prefix keeps prose that merely mentions
the convention out of the ledger.
One row per marker, grouped by file:
`<file>:<line>, <what was simplified>. ceiling: <the limit named>. upgrade: <the trigger to revisit>.`
The convention is `ponytail: <ceiling>, <upgrade path>`, so pull the ceiling
and the trigger straight from the comment. Want an owner per row too? add
`git blame -L<line>,<line>`.
Flag the rot risk: any `ponytail:` comment that names no upgrade path or
trigger gets a `no-trigger` tag, those are the ones that silently rot.
End with `<N> markers, <M> with no trigger.` Nothing found: `No ponytail: debt. Clean ledger.`
The edits
Red is upstream's text; green is what greenline shipped in its place.
What the edit kinds mean
- method
- changes what the method does, under a recorded ruling
- correction
- fixes an error
- scope
- fits the text to this skill
- pointer
- re-points a reference
- smaller edits
- rename, relocate or adjust tool details
2 smaller edits
Renames, locations and tool details, each with its reason.
-
Upstream: Mark deliberate simplifications that cut a real corner with a known ceiling (global lock, O(n²) scan, naive heuristic) with a `ponytail:` comment naming the ceiling and upgrade path.
Shipped: Mark deliberate simplifications that cut a real corner with a known ceiling (global lock, O(n²) scan, naive heuristic) with a `ponytail:` comment naming the ceiling and upgrade path, and name it in the build section of the change record.
A deliberate shortcut is named in the build section, so it survives
Full reason
A deliberate shortcut's deferral is named in the change record's build section, which records each deviation and what was left alone, so it survives the session.
-
Upstream: 1. Read CLAUDE.md / project conventions
Shipped: 1. Read the agent instructions file, AGENTS.md or CLAUDE.md, and the repository's conventions
Reads the agent instructions file, AGENTS.md or CLAUDE.md, not only CLAUDE.md
Full reason
Read CLAUDE.md names one harness's instructions file; the agent instructions file, AGENTS.md or CLAUDE.md, and the repository's conventions hold in any harness (R21).
What greenline wrote
The full reason for every passage greenline wrote, in the order of the text.
SKILL.md:8 method
One opening paragraph in the habit's own voice: the situations the block's rows key it by, code the request leaves open and not code it plainly asks for, since QA runs loaded it ahead of its situation (J-60, the fourth family); that it writes no record of its own and the build section names a shortcut, that acceptance and tdd still bound a smaller implementation, and where the review step's excess lens stands beside it. R1
SKILL.md:22 method
The first rung builds only on a measured need, and a choice the owner leaves to the agent takes a measurement's answer of none, since a QA run built an index after measuring no need (J-60, the fifth family). R1
SKILL.md:41 scope
principle-subtract-before-you-add's title becomes a section of the habit.
SKILL.md:55 scope
principle-laziness-protocol's title becomes a section of the habit, named for what its taken bullets keep flat: the call chain, the decisions and the threading.
SKILL.md:64 scope
principle-migrate-callers-then-delete-legacy-apis' title becomes a section of the habit.
SKILL.md:80 method
code-simplification's selected passages and ponytail-debt's harvest live on simplify.md and debt.md, read only on their branch, so the body names each page and what it holds; replacing working code is a refactor that reads simplify.md whole first, since a QA run replaced a working scan with an index and left it unread (J-60, the fifth family). R1
simplify.md:1 scope
code-simplification's selected passages make one page, read before a refactor or a simplification of code that already works; its title named the upstream skill.
simplify.md:3 scope
The first principle's heading, its number dropped with the principles not taken.
simplify.md:15 scope
The second principle's heading, its number dropped with the principles not taken.
simplify.md:32 scope
The fifth principle's heading, its number dropped with the principles not taken.
simplify.md:36 scope
The process's first step takes a heading of its own, Chesterton's fence named in its text.
simplify.md:52 scope
The process's third step takes a heading of its own.
simplify.md:54 scope
A PR is a forge's and an outward act the line does not run; the split the line runs is one commit per logical change, the build step's first rule.
Credits: Addy Osmani's agent-skills
debt.md:1 scope
ponytail-debt opens with no title of its own; the page takes one naming what it does.
debt.md:34 relocate
ponytail-debt's ledger file becomes the reply, or the step's section of the change record when a change asked for the harvest, greenline's homes for what the agent reports.
Credits: Dietrich Gebert's Ponytail
What it left out
Dietrich Gebert's Ponytail
Dietrich Gebert's Ponytail, ponytail/SKILL.md: all 36 sentences taken
Dietrich Gebert's Ponytail, ponytail-debt/SKILL.md: 2 of 20 sentences left out
- To persist it, ask and it writes the
ledger to a file (e.g. `PONYTAIL-DEBT.md`). left out: The ledger file becomes the reply or the change record's section. replaced by line 34 of debt.md
- 1 sentence taken
- "stop ponytail-debt" or
"normal mode" to revert. left out: The plugin's commands to leave its mode have no meaning here: the harvest is one reply.
pstack
pstack, principle-subtract-before-you-add/SKILL.md: 5 of 14 sentences left out
- # Subtract Before You Add left out: The title becomes a section of the habit. replaced by line 41 of SKILL.md
- 1 sentence taken
- **Why:** Adding to a complex system compounds complexity.
- Removing first leaves less code, reveals the essential structure, and usually makes the next design obvious. 2 sentences left out: The why restates the ladder's deletion over addition.
- 8 sentences taken
- Simplify prompts (remove redundant instructions, excessive templates)
- When a reference has no novel content, delete it rather than leaving a stub 2 sentences left out: Simplifying prompts and deleting a reference stub concern agent instructions, handed to the workshop craft craft-writing-for-agents.
pstack, principle-laziness-protocol/SKILL.md: 7 of 20 sentences left out
- # Laziness Protocol left out: The title becomes a section of the habit. replaced by line 55 of SKILL.md
- Aim for the most result with the least code and complexity. left out: The aim restates the ladder's opening.
- **Prefer deletion.**
- When asked to refactor or improve, look for removals before additions. 2 sentences left out: Prefer deletion restates the rule Deletion over addition. replaced by line 10 of SKILL.md
- 7 sentences taken
- **Minimize the diff.**
- Make the smallest change that solves the problem.
- Fewer lines beat "elegant" boilerplate. 3 sentences left out: Minimize the diff restates the rule Shortest working diff wins. replaced by line 10 of SKILL.md
pstack, principle-migrate-callers-then-delete-legacy-apis/SKILL.md: 2 of 12 sentences left out
- # Migrate Callers Then Delete Legacy APIs left out: The title becomes a section of the habit. replaced by line 64 of SKILL.md
- 5 sentences taken
- Update tests to assert the new contract, and delete tests that only protect pre-refactor implementation details left out: Deleting tests that protect pre-refactor details is not taken: a test is removed only through sweep-tests and its mutation proof (contradiction 23). R2
Addy Osmani's agent-skills
Addy Osmani's agent-skills, code-simplification/SKILL.md: 107 of 130 sentences left out
- # Code Simplification
- Inspired by the [Claude Code Simplifier plugin](https://github.com/anthropics/claude-plugins-official/blob/main/plugins/code-simplifier/agents/code-simplifier.md).
- Adapted here as a model-agnostic, process-driven skill for any AI coding agent. 3 sentences left out: The title and the credit to a Claude Code plugin give way to the page's own title (R21). replaced by line 1 of simplify.md
- ## Overview
- Simplify code by reducing complexity while preserving exact behavior. 2 sentences left out: The overview restates behavior preserved exactly, taken below.
- The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. left out: The goal is not fewer lines gives way to the ladder's one line where it reads without a pause (contradiction 24). R2
- Every simplification must pass a simple test: "Would a new team member understand this faster than the original?" left out: The new team member's test restates Boring over clever.
- ## When to Use
- After a feature is working and tests pass, but the implementation feels heavier than it needs to be
- During code review when readability or complexity issues are flagged
- When you encounter deeply nested logic, long functions, or unclear names
- When refactoring code written under time pressure
- When consolidating related logic scattered across files
- After merging changes that introduced duplication or inconsistency
- **When NOT to use:**
- Code is already clean and readable — don't simplify for the sake of it
- You don't understand what the code does yet — comprehend before you simplify
- The code is performance-critical and the "simpler" version would be measurably slower
- You're about to rewrite the module entirely — simplifying throwaway code wastes effort 12 sentences left out: When to use is the habit's opening and the block's row.
- ## The Five Principles left out: The five principles' heading gives way to the page's own headings.
- ### 1. Preserve Behavior Exactly left out: The first principle's heading drops its number. replaced by line 3 of simplify.md
- 4 sentences taken
- ### 2. Follow Project Conventions left out: The second principle's heading drops its number. replaced by line 15 of simplify.md
- 4 sentences taken
- ### 3. Prefer Clarity Over Cleverness
- Explicit code is better than compact code when the compact version requires a mental pause to parse.
- ```typescript
// UNCLEAR: Dense ternary chain
const label = isNew ? 'New' : isUpdated ? 'Updated' : isArchived ? 'Archived' : 'Active';
// CLEAR: Readable mapping
function getStatusLabel(item: Item): string {
if (item.isNew) return 'New';
if (item.isUpdated) return 'Updated';
if (item.isArchived) return 'Archived';
return 'Active';
}
```
- ```typescript
// UNCLEAR: Chained reduces with inline logic
const result = items.reduce((acc, item) => ({
...acc,
[item.id]: { ...acc[item.id], count: (acc[item.id]?.count ?? 0) + 1 }
}), {});
// CLEAR: Named intermediate step
const countById = new Map<string, number>();
for (const item of items) {
countById.set(item.id, (countById.get(item.id) ?? 0) + 1);
}
``` 4 sentences left out: Clarity over cleverness restates Boring over clever.
- ### 4. Maintain Balance
- Simplification has a failure mode: over-simplification.
- Watch for these traps:
- **Inlining too aggressively** — removing a helper that gave a concept a name makes the call site harder to read
- **Combining unrelated logic** — two simple functions merged into one complex function is not simpler 5 sentences left out: The traps of over-simplification restate the ladder's understanding first and Boring over clever.
- **Removing "unnecessary" abstraction** — some abstractions exist for extensibility or testability, not complexity left out: An abstraction kept for extensibility loses to No abstractions that weren't explicitly requested (contradiction 25). R2
- **Optimizing for line count** — fewer lines is not the goal; easier comprehension is left out: Fewer lines is not the goal gives way to the ladder's one line (contradiction 24). R2
- ### 5. Scope to What Changed left out: The fifth principle's heading drops its number. replaced by line 32 of simplify.md
- 3 sentences taken
- ## The Simplification Process left out: The process's heading gives way to the page's own headings.
- ### Step 1: Understand Before Touching (Chesterton's Fence) left out: The first step's heading becomes the page's. replaced by line 36 of simplify.md
- 6 sentences taken
- ### Step 2: Identify Simplification Opportunities
- Scan for these patterns — each one is a concrete signal, not a vague smell:
- **Structural complexity:**
- | Pattern | Signal | Simplification |
- |---------|--------|----------------|
- | Deep nesting (3+ levels) | Hard to follow control flow | Extract conditions into guard clauses or helper functions |
- | Long functions (50+ lines) | Multiple responsibilities | Split into focused functions with descriptive names |
- | Nested ternaries | Requires mental stack to parse | Replace with if/else chains, switch, or lookup objects |
- | Boolean parameter flags | `doThing(true, false, true)` | Replace with options objects or separate functions |
- | Repeated conditionals | Same `if` check in multiple places | Extract to a well-named predicate function |
- **Naming and readability:**
- | Pattern | Signal | Simplification |
- |---------|--------|----------------|
- | Generic names | `data`, `result`, `temp`, `val`, `item` | Rename to describe the content: `userProfile`, `validationErrors` |
- | Abbreviated names | `usr`, `cfg`, `btn`, `evt` | Use full words unless the abbreviation is universal (`id`, `url`, `api`) |
- | Misleading names | Function named `get` that also mutates state | Rename to reflect actual behavior |
- | Comments explaining "what" | `// increment counter` above `count++` | Delete the comment — the code is clear enough |
- | Comments explaining "why" | `// Retry because the API is flaky under load` | Keep these — they carry intent the code can't express |
- **Redundancy:**
- | Pattern | Signal | Simplification |
- |---------|--------|----------------|
- | Duplicated logic | Same 5+ lines in multiple places | Extract to a shared function |
- | Dead code | Unreachable branches, unused variables, commented-out blocks | Remove (after confirming it's truly dead) |
- | Unnecessary abstractions | Wrapper that adds no value | Inline the wrapper, call the underlying function directly |
- | Over-engineered patterns | Factory-for-a-factory, strategy-with-one-strategy | Replace with the simple direct approach |
- | Redundant type assertions | Casting to a type that's already inferred | Remove the assertion | 26 sentences left out: The opportunity tables restate the ladder, the rules and the review step's excess lens.
- ### Step 3: Apply Changes Incrementally left out: The third step's heading becomes the page's. replaced by line 52 of simplify.md
- 3 sentences taken
- A PR that refactors and adds a feature is two PRs — split them. left out: Two PRs become two commits, the split the line runs. replaced by line 54 of simplify.md
- 3 sentences taken
- **The Rule of 500:** If a refactoring would touch more than 500 lines, invest in automation (codemods, sed scripts, AST transforms) rather than making the changes by hand.
- Manual edits at that scale are error-prone and exhausting to review. 2 sentences left out: The rule of 500 loses to the bar of triviality, not repetition (contradiction 26). R2
- ### Step 4: Verify the Result
- After all simplifications, step back and evaluate the whole:
- ```
COMPARE BEFORE AND AFTER:
- Is the simplified version genuinely easier to understand?
- Did you introduce any new patterns inconsistent with the codebase?
- Is the diff clean and reviewable?
- Would a teammate approve this change?
```
- If the "simplified" version is harder to understand or review, revert.
- Not every simplification attempt succeeds. 5 sentences left out: Verifying the result restates the review step that follows the build.
- ## Language-Specific Guidance
- ### TypeScript / JavaScript
- ```typescript
// SIMPLIFY: Unnecessary async wrapper
// Before
async function getUser(id: string): Promise<User> {
return await userService.findById(id);
}
// After
function getUser(id: string): Promise<User> {
return userService.findById(id);
}
// SIMPLIFY: Verbose conditional assignment
// Before
let displayName: string;
if (user.nickname) {
displayName = user.nickname;
} else {
displayName = user.fullName;
}
// After
const displayName = user.nickname || user.fullName;
// SIMPLIFY: Manual array building
// Before
const activeUsers: User[] = [];
for (const user of users) {
if (user.isActive) {
activeUsers.push(user);
}
}
// After
const activeUsers = users.filter((user) => user.isActive);
// SIMPLIFY: Redundant boolean return
// Before
function isValid(input: string): boolean {
if (input.length > 0 && input.length < 100) {
return true;
}
return false;
}
// After
function isValid(input: string): boolean {
return input.length > 0 && input.length < 100;
}
```
- ### Python
- ```python
# SIMPLIFY: Verbose dictionary building
# Before
result = {}
for item in items:
result[item.id] = item.name
# After
result = {item.id: item.name for item in items}
# SIMPLIFY: Nested conditionals with early return
# Before
def process(data):
if data is not None:
if data.is_valid():
if data.has_permission():
return do_work(data)
else:
raise PermissionError("No permission")
else:
raise ValueError("Invalid data")
else:
raise TypeError("Data is None")
# After
def process(data):
if data is None:
raise TypeError("Data is None")
if not data.is_valid():
raise ValueError("Invalid data")
if not data.has_permission():
raise PermissionError("No permission")
return do_work(data)
```
- ### React / JSX
- ```tsx
// SIMPLIFY: Verbose conditional rendering
// Before
function UserBadge({ user }: Props) {
if (user.isAdmin) {
return <Badge variant="admin">Admin</Badge>;
} else {
return <Badge variant="default">User</Badge>;
}
}
// After
function UserBadge({ user }: Props) {
const variant = user.isAdmin ? 'admin' : 'default';
const label = user.isAdmin ? 'Admin' : 'User';
return <Badge variant={variant}>{label}</Badge>;
}
// SIMPLIFY: Prop drilling through intermediate components
// Before — consider whether context or composition solves this better.
// This is a judgment call — flag it, don't auto-refactor.
``` 7 sentences left out: The TypeScript, Python and React guidance is knowledge consulted for an engineering choice, handed to garden's maintainer. R2
- ## Common Rationalizations
- | Rationalization | Reality |
- |---|---|
- | "It's working, no need to touch it" | Working code that's hard to read will be hard to fix when it breaks. Simplifying now saves time on every future change. |
- | "Fewer lines is always simpler" | A 1-line nested ternary is not simpler than a 5-line if/else. Simplicity is about comprehension speed, not line count. |
- | "I'll just quickly simplify this unrelated code too" | Unscoped simplification creates noisy diffs and risks regressions in code you didn't intend to change. Stay focused. |
- | "The types make it self-documenting" | Types document structure, not intent. A well-named function explains *why* better than a type signature explains *what*. |
- | "This abstraction might be useful later" | Don't preserve speculative abstractions. If it's not used now, it's complexity without value. Remove it and re-add when needed. |
- | "The original author must have had a reason" | Maybe. Check git blame — apply Chesterton's Fence. But accumulated complexity often has no reason; it's just the residue of iteration under pressure. |
- | "I'll refactor while adding this feature" | Separate refactoring from feature work. Mixed changes are harder to review, revert, and understand in history. |
- ## Red Flags
- Simplification that requires modifying tests to pass (you likely changed behavior)
- "Simplified" code that is longer and harder to follow than the original
- Renaming things to match your preferences rather than project conventions
- Removing error handling because "it makes the code cleaner"
- Simplifying code you don't fully understand
- Batching many simplifications into one large, hard-to-review commit
- Refactoring code outside the scope of the current task without being asked 18 sentences left out: The rationalizations and red flags restate the principles as their violations.
- ## Verification
- After completing a simplification pass:
- [ ] All existing tests pass without modification
- [ ] Build succeeds with no new warnings
- [ ] Linter/formatter passes (no style regressions)
- [ ] Each simplification is a reviewable, incremental change
- [ ] The diff is clean — no unrelated changes mixed in
- [ ] Simplified code follows project conventions (checked against CLAUDE.md or equivalent)
- [ ] No error handling was removed or weakened
- [ ] No dead code was left behind (unused imports, unreachable branches)
- [ ] A teammate or review agent would approve the change as a net improvement 11 sentences left out: The checklist restates the principles and the review step; its CLAUDE.md is the harness's (R21).
The ledger entry
greenline's ledger logs how each skill was made and changed, with a reason for each entry.
2026-10-17 2026-10-17-ponytail-measured-need-and-simplify-first
Builds only on a measured need; reads simplify.md before a refactor
The habit loads for code the request leaves open, builds only on a measured need and reads simplify.md before replacing working code, since QA runs loaded it ahead of its situation and built after measuring no need.
- Authorised by
- 2026-10-17 The operator's card of 2026-10-15 on the QA series, "One fix job after the fifth family", with the delegation of 2026-10-16 whose words finalise the fix job's slices: a start or a habit loads only in the situation its row names, architecture-survey at an orientation and never as one where a change record exists, secrets only with a secret in reach and ponytail before code the request leaves open; a start is named in the record only when it ran; the survey never opens its report; a session with nothing to resume says so and asks for the request; diagnose ranks its hypotheses before the first probe and keeps them ranked; and ponytail builds only on a measured need and reads simplify.md before a refactor
Rulings, R1 to R6
- The operator's card of 2026-10-15 on the QA series, "One fix job after the fifth family", with the delegation of 2026-10-16 whose words finalise the fix job's slices: a start or a habit loads only in the situation its row names, architecture-survey at an orientation and never as one where a change record exists, secrets only with a secret in reach and ponytail before code the request leaves open; a start is named in the record only when it ran; the survey never opens its report; a session with nothing to resume says so and asks for the request; diagnose ranks its hypotheses before the first probe and keeps them ranked; and ponytail builds only on a measured need and reads simplify.md before a refactor
- the operator's rulings of 2026-10-08 on the intake R3 ("everything is good", and "yes go ahead" on the portable forms of R21), the verdicts standing and every contradiction ruled as recommended: one line where it reads without a pause, which "Boring over clever" already bounds (contradiction 24), no abstraction kept for an extensibility nobody requested (25), the bar for automation triviality and not a line count (26), and a test removed only through sweep-tests and its mutation proof (23); the language section of code-simplification garden's, and its "Read CLAUDE.md" the agent instructions file and the repository's conventions under R21
- The method items carry the operator's rulings of 2026-10-08 on the intake R3 ("everything is good", and "yes go ahead" on the portable forms of R21), the verdicts standing and every contradiction ruled as recommended: one line where it reads without a pause, which "Boring over clever" already bounds (contradiction 24), no abstraction kept for an extensibility nobody requested (25), the bar for automation triviality and not a line count (26), and a test removed only through sweep-tests and its mutation proof (23); the language section of code-simplification garden's, and its "Read CLAUDE.md" the agent instructions file and the repository's conventions under R21
- the operator's rulings of 2026-10-04, "cool then lock everything in": every change has one record its steps write, and a habit writes none of its own
- R16 of 2026-10-07, a habit loaded when its situation arises at any step ("update the agents md created by greenline product to mention the kind with the skill table and also prose about when to use what kind skill")
- J-59, on the operator's words of 2026-10-09 ('okay then implement all of this'): a gist of at most twelve words on every account whose reason is stated; no text, measure or method changes
4 earlier entries
2026-10-09 2026-10-09-ponytail-gists
Every account gets a short gist for the website
2026-10-08 2026-10-08-ponytail-recut
Re-cut as a habit on its own spine, five sources grafted
Pages it touched: SKILL.md, debt.md, simplify.md
2026-10-07 2026-10-07-ponytail-refresh
Upstream unchanged; the recipe re-anchors as it stands
2026-10-05 2026-10-05-ponytail-recipe
Moves to its recipe byte for byte, nothing changed