agentleFS
ingoclaroingoclaro/claude-skills/skills/defer-issues/SKILL.md

defer-issues

Skill0 starsChanged 18 days agoMITView on GitHub

Use when a problem is being deferred rather than fixed — a bug, refactor, or cleanup the user sets aside, or one you notice outside your current task's scope — and record it against the affected code so it resurfaces the next time someone works there. Do that unprompted, including for work dropped at the end of a task. Also use at the other end, when a deferred item resurfaces — including a "TODO [issue-…]" marker or a "Pending:" rule showing up in code you are reading — and you are deciding whether to act on it now (the resolution protocol lives here), when several have piled up on one module, and to list, audit, or prune what is still open. Not for the current task's own to-do list, for problems being fixed right now, or for committing (use git-commit).

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Write the record — issues_dir/issue-<id>.md, always — then anchor it:

    line 41
  2. Distinctive:

    Comment mechanism: place the one-line TODO marker at each affected spot.

    line 42
  3. Very specific:

    Rule mechanism: write .claude/rules/issue-<id>.md — the tl;dr a marker would have carried, plus a Full record: line pointing at the record …

    line 43
  4. Distinctive:

    2. Gate the opportunistic fix: All must hold, otherwise mention the issue as pending in your report and move on:

    line 57
  5. Distinctive:

    3. Fix in a separate commit: Never mix the opportunistic fix into the main task's commit — reviewers must be able to see and revert each …

    line 63
  6. Very specific:

    Start from the record files in issues_dir — they are the population, and markers and rules are anchors into it.

    line 76

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Defer issues

Deferred work dies in conversation logs. This skill anchors each deferred issue to the code it affects so it resurfaces exactly when someone is already there — the moment a fix is cheapest. Two mechanisms, chosen by scope:

  • File-specific (specific lines or functions in files you can name) → a one-line TODO comment at the affected lines, pointing at the record. This is the default: it costs zero context until someone actually opens that file, and its writes are ordinary (no protected paths).
  • Broad (a whole package, module, or component — or any future file matching a pattern) → a rule file in .claude/rules with paths: frontmatter, auto-injected whenever a matching file is read. Injection carries more weight than a comment, and a broad issue has no single line to anchor a comment to. Reserve rules for this case: every rule is paid for in context on every matching read, so a rule that a comment could have covered is pure overhead.

The tiebreak: could you list the affected spots exhaustively right now? Yes → comment each spot. No (it's about the module as a whole, or about files not yet written) → rule.

The record is always a file in issues_dir. One issues_dir/issue-<id>.md holds the issue itself, whichever mechanism you picked; the anchor — marker or rule — is only a tl;dr plus a pointer to that record. A rule never holds the issue body: it is injected on every matching read, so what it costs must stay near a comment's cost. A GitHub issue holds the full discussion when the repo has one, and ISSUES.md (repo root) indexes every open issue one line each — never auto-loaded, for humans and audits. Record files are the source of truth, and the index is generated from them by scripts/check_todo_markers.py --index: never hand-edit the list, edit the record and regenerate. (The script keeps whatever prose sits above the generated-section sentinel, so the file can still carry a human preamble.)

Formats, naming, and templates: read references/record-template.md before writing the record — it is the same file for both mechanisms — then the one anchor file you need, references/comment-template.md for markers or references/rule-template.md for rules. Never both anchor files.

Shared conventions. Both mechanisms share one id space and one index, so these hold whichever you pick:

  • Ids. issue-<number> when paired with a GitHub issue, else issue-local-<n> with n the next free number across issues_dir and ISSUES.md.
  • Index line. - [<id>](<record path>) <short summary>, plus ([gh](<url>)) when GitHub-paired — all of it derived by --index from the record's filename, its # Pending: <id> — <title> heading, and the first GitHub issue URL in its body. Never typed by hand.
  • Protected paths. Writes and deletes under .claude/ are permission-gated. If a write is blocked, put the intended file content in your report so it isn't lost and suggest allowlisting Write(.claude/rules/issue-*.md); delete with git rm, which runs under ordinary git permissions where a direct delete would stall a non-interactive run.
  • One commit. An issue's record file, its anchors (markers, rule), and its index line are created — and removed — together with the change they belong to.

Escalation. A comment is passive — a hurried reader can edit right past it. When a marker keeps being ignored, promote the issue to a rule so it gains injection weight on the next edit: scripts/check_todo_markers.py (designed as a CI step) detects markers in files that were edited without the issue being touched or mentioned, and with --escalate writes the rule for you, in the same pointer format as any other rule. The comment stays put; both anchors then point at the one record. A file that documents the marker format, or a fixture that embeds one, is indistinguishable from a real marker — list those paths as globs in .defer-issues-ignore at the repo root so editing them doesn't report a phantom.

Record

Record without being asked whenever deferred work surfaces: you notice a minor bug or refactor opportunity outside the current task's scope, you defer something at task end, or a proposed rewrite gets declined. Recording is additive and cheap to undo — it needs no permission ceremony. Offer instead of acting only when you genuinely doubt the observation deserves an issue. An unrecorded issue is lost; that loss is what this skill exists to prevent.

  1. Decide the scope (file-specific → comment; broad → rule), then read references/record-template.md and the reference file for that one anchor.
  2. Detect the issue home: if gh repo view succeeds (remote exists, gh authenticated) → GitHub; else local-only. GitHub: gh issue create --title "<title>" --body "<full description>" (add issue_label if set) and capture the number and URL — the full write-up lives there. Local-only: the record file is the whole record; keep it short but sufficient to act on.
  3. Write the record — issues_dir/issue-<id>.md, always — then anchor it:
    • Comment mechanism: place the one-line TODO marker at each affected spot. Recording must be the only change — never alter code while recording.
    • Rule mechanism: write .claude/rules/issue-<id>.md — the tl;dr a marker would have carried, plus a Full record: line pointing at the record file, with paths: globs scoped to the package/module actually implicated. The description stays in the record; the rule does not repeat it.
  4. Regenerate the index: python3 scripts/check_todo_markers.py --index (creates ISSUES.md if absent). The one-line entry comes from the record's # Pending: <id> — <title> heading, so that heading is what a human sees in the index — write it as the summary.
  5. Report: record path, marker locations or rule globs chosen, and the issue URL if GitHub.

Resolve

Entered when a Pending: rule or a TODO [issue-…] marker surfaced while you were doing other work, or on an explicit request ("fix pending issue 142").

0. Accumulation check. List the distinct pending issues covering the file/module at hand — rules in context plus grep -rn "TODO \[issue-" <module>, deduped — and read their titles together. The question is not how many there are but whether they share a root cause: would one redesign retire most of them? If yes, do not fix piecemeal — the module, not the issues, is the problem. Complete the task you were actually asked to do first, then present the cluster in your final report as a rewrite/redesign candidate listing the issues it would retire — the proposal is report material, never a reason to pause the requested work. If the rewrite is deferred — the user declines, or there is no user to ask — record the rewrite itself as a new issue (via Record, rule mechanism: it's module-scoped by definition), referencing the issues it would retire.

Three issues that are all the same missing abstraction qualify; a dozen unrelated nits that merely share an address do not — fix the one at hand and move on. rewrite_threshold is the prompt to make that judgment, not the verdict: at that many issues on one module, stop and assess before fixing anything; below it, assess anyway whenever the titles rhyme.

1. Read the whole issue first — the GitHub issue body, or the record file if local. The rule summary or marker line is a teaser, not the spec: the issue may span files your current task never touches (grep the id repo-wide to see every marker), and both the gate below and the close-out depend on knowing its full extent.

2. Gate the opportunistic fix. All must hold, otherwise mention the issue as pending in your report and move on:

  • Localized: confined to files you're already touching or their immediate neighbors.
  • Low-risk: no behavior change beyond the issue's stated intent, no API/schema changes.
  • Proportionate: doesn't balloon the current task.

3. Fix in a separate commit. Never mix the opportunistic fix into the main task's commit — reviewers must be able to see and revert each independently.

4. Verify full resolution before closing. Enumerate everything the issue covers (grep the id for markers; read the record's affected list) and check each part is addressed:

  • Fully resolved → remove every artifact in the fix commit: all TODO [issue-<id>] markers, the rule file if there is one, and the record file; then python3 scripts/check_todo_markers.py --index to drop its index line; gh issue close <id> if GitHub-paired.
  • Partially resolved (the headline case: a multi-file issue where you only fixed the file at hand) → do not delete the record or close the issue. Remove only the fixed spots' markers (or narrow the rule's paths: to the remaining scope), note the progress (a gh issue comment, or a line in the record body), and report what remains.

5. Don't stall. In non-interactive runs or when judgment is pre-delegated, apply the gate and the accumulation rule autonomously and flag every such judgment call prominently in your report — a documented judgment is recoverable; a stalled run is not.

Audit

On "what's pending?", "prune stale issues", or before a milestone:

  1. Start from the record files in issues_dir — they are the population, and markers and rules are anchors into it. python3 scripts/check_todo_markers.py --index rebuilds ISSUES.md from them, so orphaned index lines and missing ones both disappear by construction; --index --check reports the drift without writing, for CI.
  2. Where a GitHub issue is linked, check its state: closed → delete the record file and its markers, then regenerate the index.
  3. Cross-check anchors, both directions: a record with no surviving anchor — no TODO [issue-<id>] marker anywhere, or a rule whose globs no longer match any file — is stale; re-anchor it or retire the issue. An anchor pointing at a missing record file, marker or rule alike, is dangling — remove it or reconstruct the record.
  4. Summarize as a table: id, mechanism, title, scope, age/state, and any inconsistency repaired.

Plain ls, grep, and gh cover the rest — scripts/check_todo_markers.py (no flags) also reports ignored markers if you want the escalation view.

Report

Whichever workflow ran, end with what changed: issues recorded (id, mechanism, scope), issues fixed (commit hash), issues surfaced but deferred and why, escalations, and any rewrite proposal made. The report is what keeps opportunistic work reviewable.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.