Maintenance Prompts
Maintenance work fails when agents "improve" while fixing. Freeze behavior unless the bug fix is the behavior change — and say which. Technique: Maintenance Prompts, Production Debugging, Legacy Refactor.
Debugging
Systematic diagnosis before any fix attempt.
Inputs: <symptom>, <repro steps>, <environment>, <recent changes>, <logs or traces>
Debug only — do not fix yet.
Symptom: <symptom>
Repro: <repro steps>
Environment: <environment>
Recent changes: <recent changes>
Evidence: <logs or traces>
Process:
1. Restate the bug as an expected vs actual assertion.
2. Form 3 hypotheses ranked by likelihood.
3. Design the cheapest check for each (log, bisect, bisect commit,
minimal repro).
4. Run checks; eliminate hypotheses with evidence (cite file:line /
log lines).
5. Name the root cause in one paragraph.
6. Propose a minimal fix plan — wait for approval.
Do not spray speculative fixes. Do not refactor while debugging.Expected output: expected/actual, hypothesis log, root cause, fix plan pending approval.
Evaluate: Root cause is evidenced, not guessed. Fix plan is minimal. No drive-by edits landed.
Variations:
- Production-only: read-only access, propose instrumentation first.
- Add "time box: N minutes then report."
Bug fixing
Implement a minimal fix after root cause is known.
Inputs: <root cause summary>, <failing test or repro>, <affected paths>, <regression risks>
Fix this bug with minimal change.
Root cause: <root cause summary>
Repro / failing test: <failing test or repro>
Likely files: <affected paths>
Regression risks: <regression risks>
Rules:
- Add or adjust a failing test that captures the bug BEFORE fixing
(red → green).
- Change only what the root cause requires.
- Do not clean up adjacent code.
- Call out if the "bug" is actually undefined behavior that needs a
product decision.
Deliver: test, fix, brief risk notes, commands you ran.Expected output: red-then-green test, minimal fix, risk notes.
Evaluate: Test failed on old behavior. Diff is small. No unrelated formatting.
Variations:
- Hotfix branch: fix only; tests in follow-up PR (exception — say so).
- Require changelog entry.
Legacy understanding
Map a legacy area into durable notes before changing it.
Inputs: <entry paths>, <questions to answer>, <output doc path>
Explain this legacy area; do not modify production code.
Entry points: <entry paths>
Questions:
<questions to answer>
Write findings to: <output doc path>
Include:
1. Responsibility of the area (what it's for).
2. Call graph / data flow (mermaid, keep small).
3. Implicit invariants (things the code assumes but doesn't enforce).
4. Sharp edges / historical hacks (with file:line).
5. Safe vs unsafe change zones.
6. Suggested characterization tests before any refactor.
Ask me if a question can't be answered from the code alone.Expected output: committed-quality understanding doc with diagram and sharp edges.
Evaluate: Invariants and hacks are concrete. Safe/unsafe zones would change how you'd prompt a refactor.
Variations:
- Limit to auth/payments path only.
- Output as annotated tour for onboarding.
Technical debt cleanup
Scoped debt removal with an explicit non-goal of feature work.
Inputs: <debt item>, <success metric>, <allowlist>, <do not touch>
Clean up this debt only: <debt item>
Success metric: <success metric>
May touch: <allowlist>
Do not touch: <do not touch>
Rules:
- No feature behavior changes — if behavior must change, STOP.
- Prefer deleting code to abstracting it.
- Keep PRs/slices small; stop when <success metric> is met.
- Update docs/comments that would otherwise lie.
Provide before/after evidence for the success metric.Expected output: debt reduced to metric; evidence; no feature deltas.
Evaluate: Metric moved. Behavior tests still pass. Scope didn't expand into "while I'm here."
Variations:
- Delete dead code only (prove unused).
- Dependency upgrade with compatibility shims removed.
Refactor (behavior frozen)
Restructure with characterization tests as the contract.
Inputs: <refactor goal>, <paths>, <characterization suite>, <forbidden changes>
Refactor with FROZEN behavior.
Goal: <refactor goal>
Paths: <paths>
Characterization suite: <characterization suite>
Forbidden: <forbidden changes>
Process:
1. Ensure characterization suite is green on HEAD.
2. Refactor in small steps; suite must stay green after each step.
3. No assertion changes except imports/renames required by moves.
4. No feature flags, no API shape changes, no perf "improvements"
unless they are the stated goal and covered by tests.
End with a summary of structural before/after and residual risks.Expected output: structural change, green characterization suite, risk summary.
Evaluate: Assertions stable. Public behavior identical. Goal actually achieved (not just files moved). See Legacy Refactor.
Variations:
- Strangler: new path beside old, then switch.
- Extract module only (Behavior-preserving extract).
Characterization test generation
Pin current behavior before you dare change it.
Inputs: <legacy module>, <behaviors to pin>, <test location>, <mock policy>
Generate characterization tests for <legacy module>.
Pin these behaviors (current behavior, even if ugly):
<behaviors to pin>
Write tests under: <test location>
Mock policy: <mock policy>
Rules:
- Tests document what IS, not what SHOULD be.
- Name tests with `characterizes_` or equivalent convention.
- Where behavior is ambiguous, pick one observation, assert it, and
comment `QUESTIONABLE: ...`.
- Do not refactor production code.
Output the suite + a list of questionable behaviors for human triage.Expected output: pinning tests + questionable list.
Evaluate: Suite fails if behavior drifts. Questionable items aren't silently "fixed."
Variations:
- Golden-file / snapshot for complex outputs.
- Record HTTP fixtures for legacy integrations.
Migration planning
Plan a data/system migration without executing it yet.
Inputs: <from → to>, <data volume>, <downtime budget>, <rollback requirement>
Plan migration: <from → to>
Data volume: <data volume>
Downtime budget: <downtime budget>
Rollback: <rollback requirement>
Deliver a migration plan:
1. Expand/contract (or big-bang) strategy with phases.
2. Data backfill approach, batching, and idempotency.
3. Dual-write / dual-read needs.
4. Verification queries/checksums per phase.
5. Rollback steps that actually work within the budget.
6. Monitoring signals that say "abort."
7. Owner checklist for the cutover window.
Do not run destructive commands. Do not "start the migration."
Flag decisions that need an ADR.Expected output: phased plan with verification, rollback, abort signals.
Evaluate: Rollback is real. Verification isn't "looks fine in UI." Downtime budget respected. See Migration.
Variations:
- Online schema change only.
- Multi-service cutover with feature flags.
Dependency upgrade
Upgrade a dependency with compatibility proof, not hope.
Inputs: <package and target version>, <changelog constraints>, <test command>, <rollback>
Upgrade <package and target version>.
Read changelog/breaking changes: <changelog constraints>
Verify with: <test command>
Rollback: <rollback>
Process:
1. Summarize breaking changes that apply to OUR usage (cite our call sites).
2. Apply upgrade + required code adaptations only.
3. Run tests; fix breakages minimally.
4. Note any deprecated APIs we still use and a follow-up task.
Do not upgrade unrelated packages. Do not refactor call sites for style.Expected output: upgrade commit, adapted call sites, test proof, follow-ups.
Evaluate: Only relevant breakages handled. Lockfile intentional. Rollback path clear.
Variations:
- Major version: require codemod or compatibility package first.
- Security patch only — smallest bump that fixes CVE.
Related
- Maintenance Prompts — pattern rationale
- Production Debugging — debug playbook
- Legacy Refactor — frozen-behavior refactors
- Migration — migration playbook
- Architecture Erosion — what debt cleanup is fighting
- Recovery — when maintenance sessions thrash