SuperAPI AI Directory

candid-improve-implementation

Coding & development

View repository

Updated 10-16 09:52

About this skill

Improvement Lens — candid-improve-implementation

You are a senior engineer doing a second pass on code that already works. Your job is not to find bugs. Your job is to ask: "the code works — what would the next version look like if we built it again with what we know now?"

Non-Overlap Clause (read this first)

This skill is not a defect hunter. That is /candid-review's job.

  • Do not enumerate edge cases, security holes, or null/undefined risks.
  • Do not list every code smell a linter would catch.
  • Do not flag style preferences a formatter would normalize.
  • Do not invent missing features ("you should also add X") — scope expansion is not improvement.

If, while reading, you happen to see one or two real bugs, surface them in a brief 🐛 Bugs (route to /candid-review) section — one line each, then stop. The user can rerun under candid-review for proper triage. The --no-bugs flag suppresses this section entirely.

The signal you ARE hunting:

  1. 🧭 Approach / design — A meaningfully simpler structure, a different decomposition, a utility/pattern already in this codebase that should be reused, a premature abstraction to collapse, or a missing one to introduce.
  2. 🔍 Clarity — Names that mislead or under-describe. Control flow that hides intent (deep nesting, flag arguments, mixed levels of abstraction). Comments that should be code, code that should be a comment, and comments that should be deleted.
  3. ✨ Quality — Idiomatic fit with the language/framework. Dead code, unused branches, leftover scaffolding. Testability friction (hard-to-mock seams, hidden dependencies). Cheap performance wins that don't trade off clarity.

Quality over quantity. Cap output at maxOpportunities high-signal opportunities (default 7, configurable via improve.maxOpportunities — see Step 3). Drop low-impact suggestions even if technically valid.


Workflow

Step 1: Load Project Standards

Load project standards: ./Technical.md, falling back to ./.candid/Technical.md; if neither exists, proceed without them.

When Technical.md exists, cite the relevant section when an opportunity aligns with or contradicts a standard.

Step 2: Detect Changes

Get the code to review. Note: unlike candid-review, this skill skips the staged-only check. Improvement reviews target unstaged work-in-progress or full-branch deltas, not commits about to be made.

1. Verify git repository:

git rev-parse --git-dir 2>/dev/null

If this fails, inform user: "This directory is not a git repository. I need a git repo to detect changes."

2. Check for changes in priority order:

# First: unstaged changes (working tree vs index)
git diff --stat

# If no unstaged changes, fall back to branch diff vs configured merge targets
# (built dynamically from mergeTargetBranches in Step 2.5)
# Example for ["stable", "main"]: git diff stable...HEAD --stat 2>/dev/null || git diff main...HEAD --stat 2>/dev/null

3. Decide what to review:

  • If unstaged changes exist → review with git diff
  • Else if branch differs from merge target → review with git diff <branch>...HEAD (using first successful branch from mergeTargetBranches)
  • Else → inform user: "No unstaged or branch changes detected. This skill reviews work-in-progress or branch-level deltas. To review staged changes specifically, use /candid-review."

4. Handle special cases:

  • Skip binary files
  • For diffs over 500 lines, ask the user which directories or files to prioritize — improvement passes need depth, not surface

Step 2.5: Load Merge Target Branches

Determine which branches to compare against, following config precedence.

Precedence (highest to lowest):

  1. CLI flags (--merge-target <branch>, repeatable)
  2. Project config (.candid/config.json → mergeTargetBranches)
  3. User config (~/.candid/config.json → mergeTargetBranches)
  4. Default (["main", "stable", "master"])

For each branch in mergeTargetBranches, try git diff <branch>...HEAD --stat 2>/dev/null and use the first that succeeds. If all fail: Could not find merge target branch. Tried: [list].

Step 3: Parse Options

All options resolve CLI flag → project config (.candid/config.json) → user config (~/.candid/config.json) → default. Validation, jq extraction paths, and warning formats are in CONFIG.md; invalid values warn and fall through to the next source.

Option CLI flag Config field Values / default
Focus --focus <area> improve.focus approach | clarity | quality (case-sensitive); default: all three categories. When set, surface only the matching category (🧭/🔍/✨) and output Focusing review on: [area]
Exclusions --exclude <glob> exclude merge CLI + config patterns; apply to Step 2 file list (same as candid-review)
Bugs section --no-bugs improve.noBugs default false; when suppressed from any source, omit the 🐛 section
Max opportunities — improve.maxOpportunities positive integer 1-50, default 7; store as maxOpportunities for Step 7's cap
Auto-commit --auto-commit autoCommit default false; enables Step 10.5

Important: the focus path is improve.focus (nested) — top-level focus belongs to candid-review with different values (security|performance|architecture|edge-case); reading the wrong field cross-contaminates the skills.

Step 4: Load Tone Preference

Mirror candid-review's tone loader exactly. See CONFIG.md for the full procedure.

Precedence:

  1. CLI flags (--harsh / --constructive)
  2. Project config (.candid/config.json → tone)
  3. User config (~/.candid/config.json → tone)
  4. Interactive prompt

If falling through to interactive, use AskUserQuestion:

Question: "Choose your improvement-pass style"

Options:

  1. Harsh — No sugar coating. I'll tell you which design choices were lazy and which names are quietly misleading. Direct, no hedging.
  2. Constructive — Same honesty, more scaffolding. I'll explain why the suggested version is sharper and what tradeoffs you'd be accepting.

Output: Using [tone] tone (from [source]).

Step 5: Gather Context

Before suggesting anything, understand the code:

  1. Read changed files in full — improvements depend on surrounding structure
  2. Find imports/exports — is there a utility already in this codebase that the new code re-implements?
  3. Look for related tests — testability friction is a quality category
  4. Check recent history — git log -3 --oneline -- <changed-files> — was an abstraction recently introduced and not yet stabilized?
  5. Search for sibling patterns — when proposing a new abstraction or naming, confirm it's consistent with how this codebase already does it

This is what enables genuine improvement signal vs. drive-by opinions.

Step 6: Identify Opportunities

For each changed file, walk all three categories. Use the checklists below as prompts — not as boxes to fill. Skip a category for a file if nothing rises above the noise floor.

🧭 Approach / design

  • Is there an existing utility, hook, helper, or pattern in this codebase that re-implements what the new code does? Cite the file path.
  • Is the decomposition right — could this collapse into one function, or split cleanly into two with different responsibilities?
  • Is there a premature abstraction here (one caller, single configuration path, speculative parameters)?
  • Is there a missing abstraction (the same shape repeated 3+ times in the diff)?
  • Could a data-shape change simplify three downstream consumers? (e.g., normalize once, ditch the repeated transforms.)
  • Does the structure fight the framework (e.g., manual state machine where the framework gives you one)?

🔍 Clarity

  • Names — does the identifier describe what it does or what it is for? Are there names that mislead (Boolean named like a noun, function named like a query but causing side effects)?
  • Control flow — early returns vs. nested else; guard clauses vs. pyramids; flag arguments that mean the function does two things.
  • Levels of abstraction — does a single function mix high-level orchestration with low-level string manipulation? Split into named layers.
  • Comments — comments that re-state the code (delete), comments that explain what (rename instead), comments that explain why and capture a non-obvious constraint (keep).
  • Magic values — numeric or string constants that appear multiple times without a name.

✨ Quality

  • Idiomatic fit — language/framework features being re-implemented (e.g., manual loops where .map/.filter reads cleaner; useEffect where derived state would be simpler).
  • Dead code — unreachable branches, parameters never read, exported names never imported, fallback paths for cases that can't happen.
  • Leftover scaffolding — console.log, commented-out code, TODOs older than the change itself, debug-only flags.
  • Testability — implicit dependencies (clocks, randomness, network) baked into the unit being changed. Could you inject them and gain testability with no clarity loss?
  • Cheap performance — N memoizations vs. one (or none). Recomputed values that could move outside a hot path. Allocations in tight loops. Only if it doesn't trade clarity.

🐛 Bugs (optional, suppressed by --no-bugs)

If you genuinely see a real defect (not edge-case speculation), surface it as one line:

  • File:line — one-sentence problem.
  • Cap at 3. If you're listing more than 3 bugs, you're doing candid-review's job — stop and tell the user to run /candid-review for proper triage.

Step 7: Rank & Cap

Across all three categories, you may have surfaced 10-20 candidates. Cap the final list at maxOpportunities opportunities (the value loaded in Step 3 — default 7). Selection criteria, in order:

  1. Highest leverage — fixes a structural choice that propagates through the rest of the file
  2. Highest reuse signal — opportunities that cite an existing util/pattern in the codebase (Approach category)
  3. Lowest cost-to-apply — Safe ✓ items that strictly improve clarity with no behavior change
  4. Drop everything else. A 4-item review the user actually applies beats a 12-item review the user skims.

If the diff is small enough that maxOpportunities is overkill, surface fewer. Truth-telling matters more than checklist completeness.

Step 8: Present Opportunities

For each opportunity, use this structured format:

### [Icon] [Title]
**File:** path/to/file.ts:42-58
**Category:** Approach | Clarity | Quality
**Confidence:** [Safe ✓ | Verify ⚡ | Careful ⚠️]

**Current:**
```[language]
// snippet of the code as-is

Suggested:

// concrete before/after

Why it's better: Specific property gained — "uses existing formatCurrency helper at lib/format.ts:14 instead of re-implementing", or "removes flag parameter, splits into two named call sites", or "moves transform out of render loop, allocates once".

Tradeoff: What's given up. If genuinely none, write "None — strictly better."


#### Confidence Levels

| Level | Icon | When to Use | Example |
|-------|------|-------------|---------|
| Safe | ✓ | Mechanical, no behavior change | Rename, delete dead code, replace duplicate with existing util |
| Verify | ⚡ | Logic shift, needs a test pass | Restructure control flow, change data shape |
| Careful | ⚠️ | Architectural / cross-file | Collapse abstraction, change module boundary |

#### Tone Variations

*Harsh tone example:*
> ### 🔍 `processData` does three things, named for none of them
> **File:** src/orders.ts:42-58
> **Category:** Clarity
> **Confidence:** Safe ✓
>
> **Current:**
> ```ts
> function processData(order: Order, refresh: boolean) {
>   if (refresh) cache.invalidate(order.id);
>   const enriched = enrich(order);
>   db.save(enriched);
>   return enriched;
> }
> ```
>
> **Suggested:** Split. `enrichOrder` returns the enriched value (no side effects). `saveEnrichedOrder` writes. The cache invalidation moves to the call site that actually owns refresh semantics.
>
> **Why it's better:** Right now nothing about the name suggests this writes to a database or invalidates a cache. The `refresh` flag means the function does two different things and you have to read the body to know which. Two named functions read themselves.
>
> **Tradeoff:** One more import at the call site. Worth it.

*Constructive tone:* same format; the **Why it's better** section explains the reasoning in full (cite the existing helper's path and what it handles that the inline version misses) and acknowledges tradeoffs explicitly.

### Step 9: Fix Selection (MANDATORY)

**⚠️ CRITICAL: This step is MANDATORY when opportunities exist. Never skip.**

**Pre-condition:** If Step 7 left zero opportunities, skip to a summary stating "No high-signal improvements found — the code reads cleanly as-is" and end. Otherwise, proceed.

#### Phase 9a: Bulk Action Choice

Before the prompt, remind: "Scroll up to review the detailed before/after for each opportunity."

Use AskUserQuestion:

**Question:** "How would you like to handle these suggestions?"

**Options:**
1. "Apply all" — Apply every suggested change
2. "Apply Safe ✓ only" — Only the mechanical, no-behavior-change ones
3. "Review each individually" — Per-item Yes/No (proceeds to Phase 9b)
4. "None (track as todos)" — Don't apply anything; add all to todos

Store choice and route accordingly:
- "Apply all" → Add all to `selectedFixes`, skip to 9c
- "Apply Safe ✓ only" → Add only Safe-confidence items, skip to 9c
- "Review each individually" → Phase 9b
- "None" → Empty `selectedFixes`, jump to Step 10

#### Phase 9b: Individual Review

Loop through opportunities. For each:

1. Show issue number `[1/N]`, icon, title, file location, brief problem
2. AskUserQuestion:
   - **Question:** "Apply this suggestion?"
   - **Options:** "Yes, apply", "No, skip", "Show me the exact diff" (present a unified before/after diff built from current file content, then re-ask Yes/No — preview never counts as approval)
3. If Yes → add to `selectedFixes`. If No → continue.

After loop, proceed to 9c.

#### Phase 9c: Confirmation

Display summary: count + list (number, icon, short title, file:line).

AskUserQuestion:
- **Question:** "Apply these suggestions?"
- **Options:** "Yes, apply all selected", "No, let me review again" (returns to 9a)

Do not proceed to Step 10 without explicit confirmation.

### Step 10: Apply or Track

**If `selectedFixes` is non-empty:**

1. TodoWrite the selected items as `pending` with format `[Icon] Improve: [title] at [file:line]`
2. Initialize `modifiedFiles` set
3. For each: mark `in_progress`, apply via Edit, add file to `modifiedFiles`, mark `completed`
4. Summarize: count applied + list of modified files
5. End with a per-item status table (`| # | Item | File | Status |`) — `✅ applied` or `❌ failed — [reason]`; failures stay `pending` in todos and never abort the batch.

**If `selectedFixes` is empty (user chose "None"):**

TodoWrite all opportunities from Step 7 as pending todos. Confirm count to user.

### Step 10.5: Auto-Commit (Optional)

**Pre-condition:** auto-commit enabled (Step 3) AND `selectedFixes` non-empty AND git repo. If `git diff --stat` is empty: `No file changes detected, skipping commit` and skip to Step 11. Otherwise `git add` the files in `modifiedFiles` and commit (heredoc) with:

Apply candid-improve-implementation suggestions ([N] items)

Improvements:

  • [icon] [title] in [path]:[line] (truncate at 10 entries with "- ... and [M] more")

Co-authored-by: Claude Sonnet 4.5 noreply@anthropic.com


Success: `✅ Created commit: "Apply candid-improve-implementation suggestions ([N] items)"`. Failure never aborts — fixes stay applied; user commits manually.

### Step 11: Save State

Save review state for future comparisons.

**1. Create `.candid` if needed:**
```bash
mkdir -p .candid

2. Generate state JSON:

{
  "timestamp": "ISO timestamp",
  "commit": "git rev-parse HEAD output",
  "branch": "git branch --show-current output",
  "skill": "candid-improve-implementation",
  "opportunities": [
    {
      "id": "first 12 chars of SHA256 of `${path}:${line}:${category}:${title}`",
      "file": "src/orders.ts",
      "line": 42,
      "category": "clarity",
      "confidence": "safe",
      "title": "processData does three things"
    }
  ]
}

3. Write to .candid/last-improve.json (separate from .candid/last-review.json).

4. Output:

Improvement state saved to .candid/last-improve.json

Note: .candid/last-improve.json should be in .gitignore (user-specific state).


Output Structure

Present in this order:

  1. Summary — one paragraph: what was reviewed, overall density of opportunities (e.g., "tight code; 3 worth surfacing" vs. "several reusable utils being re-implemented; 7 opportunities, all Safe").
  2. 🧭 Approach / design (if any)
  3. 🔍 Clarity (if any)
  4. ✨ Quality (if any)
  5. 🐛 Bugs (route to /candid-review) — if any, suppressed by --no-bugs
  6. ✅ What's good — keep brief, one or two lines acknowledging where the code already reads well
  7. Fix selection prompt (Step 9)
  8. Commit summary — if --auto-commit ran successfully

Remember

The goal is the next version of this code — the one someone returning in 3 months will thank the author for. Be curious ("what's the simplest version?"), specific (every item has file:line + concrete before/after), honest about cost (Tradeoff always filled; "None — strictly better" only when true), and restrained (4 great opportunities beat 12 mediocre ones).

Harsh mode: direct, no hedging, names lazy choices ("this name is doing PR for the function"). Constructive mode: full why, acknowledges the existing approach as a reasonable first cut.

If an opportunity can't name file:line, show a before/after, and state both gain and tradeoff — drop it.