teqo-backup/.agents/skills/code-simplification/SKILL.md
Francisco Solla 0822cca82c chore: reduce token overhead in agent workflow
- Drop model-selection skill (dead, pool is dormant)
- Drop PNG rendering from UI planning (HTML-only, no pnpm ui-draft:render)
- Trim code-simplification: 331→~150 lines, Python/React examples moved to reference/
- Compress engineering-brief.md: remove redundant 'Pinhos do repo' (alwaysApply rules)
- Deduplicate capture-review-debts: reference decision-quality.md instead of re-explaining
- Create concise-output skill (35 lines) to enforce terse agent output
- Trim all 99 skill descriptions to ≤1 sentence
- Split AGENTS.md into layers: core (73 lines, always) + campaign/public/infra (on-demand)
- Decompose plan-issue: exploration sub-agent + parallel plan-writers + register sub-agent
- Decompose work-issue: exploration sub-agent + plan-writer + 2 parallel reviewers + debt sub-agent
- Update agent-work-issue to match sub-agent pattern
2026-08-21 20:38:56 -03:00

6.6 KiB

name description
code-simplification Simplify code for clarity without changing behavior.

Code Simplification

Simplify code by reducing complexity while preserving exact behavior. The goal is not fewer lines — it's code that is easier to read, understand, modify, and debug. Every simplification must pass: "Would a new team member understand this faster than the original?"

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 consolidating related logic scattered across files

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

The Five Principles

1. Preserve Behavior Exactly

Don't change what the code does — only how it expresses it. All inputs, outputs, side effects, error behavior, and edge cases must remain identical.

ASK BEFORE EVERY CHANGE:
→ Does this produce the same output for every input?
→ Does this maintain the same error behavior?
→ Do all existing tests still pass without modification?

2. Follow Project Conventions

Simplification means making code more consistent with the codebase, not imposing external preferences. Match the project's style for imports, naming, error handling, and type annotations. Simplification that breaks project consistency is not simplification — it's churn.

3. Prefer Clarity Over Cleverness

Explicit code is better than compact code when the compact version requires a mental pause to parse. Dense ternaries, chained reduces with inline logic, and single-letter variables obscure intent — replace with readable equivalents.

4. Maintain Balance

Simplification has a failure mode: over-simplification. Don't inline so aggressively you remove a helper that gave a concept a name. Don't combine two simple functions into one complex one. Don't remove abstractions that exist for extensibility or testability. Fewer lines is not the goal; easier comprehension is.

5. Scope to What Changed

Default to simplifying recently modified code. Avoid drive-by refactors of unrelated code unless explicitly asked to broaden scope. Unscoped simplification creates noise in diffs and risks unintended regressions.

The Simplification Process

Step 1: Understand Before Touching (Chesterton's Fence)

Before changing or removing anything, understand why it exists. If you see a fence across a road and don't understand why it's there, don't tear it down.

BEFORE SIMPLIFYING, ANSWER:
- What is this code's responsibility?
- What calls it? What does it call?
- What are the edge cases and error paths?
- Why might it have been written this way?
- Check git blame: what was the original context?

If you can't answer these, you're not ready to simplify. Read more context first.

Step 2: Identify Simplification Opportunities

Scan for these patterns — each one is a concrete signal, not a vague smell:

Pattern Signal Simplification
Deep nesting (3+ levels) Hard to follow control flow Extract 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 or lookup objects
Boolean parameter flags doThing(true, false, true) Replace with options objects or separate functions
Generic names data, result, temp, val Rename to describe content: userProfile, errors
Comments explaining "what" // increment counter above count++ Delete — the code is clear enough
Comments explaining "why" // Retry because the API is flaky Keep — they carry intent the code can't express
Duplicated logic Same 5+ lines in multiple places Extract to a shared function
Dead code Unreachable branches, unused variables Remove after confirming it's truly dead
Redundant type assertions Casting to an already-inferred type Remove the assertion

Step 3: Apply Changes Incrementally

Make one simplification at a time. Run tests after each change. Submit refactoring changes separately from feature or bug fix changes.

FOR EACH SIMPLIFICATION:
1. Make the change
2. Run the test suite
3. If tests pass → commit (or continue to next simplification)
4. If tests fail → revert and reconsider

The Rule of 500: If a refactoring would touch more than 500 lines, invest in automation (codemods, AST transforms) rather than making the changes by hand.

Step 4: Verify the Result

COMPARE BEFORE AND AFTER:
- Is the simplified version genuinely easier to understand?
- Did you introduce 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.

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.
"Fewer lines is always simpler" A 1-line nested ternary is not simpler than a 5-line if/else.
"I'll just quickly simplify this unrelated code too" Unscoped simplification creates noisy diffs and risks regressions.
"The types make it self-documenting" Types document structure, not intent. A well-named function explains why.
"This abstraction might be useful later" Don't preserve speculative abstractions. Remove it and re-add when needed.

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

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
  • No error handling was removed or weakened
  • No dead code was left behind (unused imports, unreachable branches)