agentleFS
kevinlinkevinlin/skills/spec-compact/SKILL.md

spec-compact

Skill5 starsChanged 4 months agoMITView on GitHub

Compact a spec plan (or design doc) markdown file after the implementation has shipped: strip the transient how — code snippets, step-by-step walkthroughs, file-by-file diffs — that the codebase now owns, keep the why — design decisions, key file references, changelog. Use when the user wants to compact, shrink, or trim a plan/spec file post-implementation, says the plan is bloated or too long now that the feature shipped, or invokes `/spec-compact`. Renaming files, fixing dead links, and index updates belong to `spec-lint`.

The file

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 4 are distinctive, and 5 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈4

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 5

    Very specific

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

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

    Read README.md and CLAUDE.md (root + .claude/CLAUDE.md) for an explicit pointer ("design docs in docs/specs/").

    line 31
  2. Very specific:

    If <SPECS_ROOT>/meta/convention.md exists, read it — the per-project source of truth for artifact classes (requirements, design, plan, plus …

    line 34
  3. Very specific:

    If <SPECS_ROOT>/index.md exists, read it to find the sibling design_<topic>.md for the input plan, the closest requirements_<topic>.md (and …

    line 35
  4. Distinctive:

    Read the file fully. Note lines + bytes for the before/after summary.

    line 51
  5. Distinctive:

    If all five are silent, stop here before Step 3.

    line 59
  6. Very specific:

    Use the actual current date.

    line 113
  7. Distinctive:

    Wait for the answer:

    line 147
  8. Very specific:

    Write the file in place. Preserve any frontmatter block and the H1 (# Plan: …) untouched.

    line 158
  9. Distinctive:

    Leave the diff uncommitted — the user reviews it in their VCS tool and decides when to commit.

    line 175

≈ “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

spec-compact: Post-Implementation Spec File Compaction

After a feature lands, the plan that guided it is usually 3–10× larger than future readers need. Code blocks, per-step walkthroughs, and Verify: command lists earned their keep during implementation but now duplicate what the codebase and git history carry. The rule that governs every decision below: the codebase owns the how; the plan keeps the why — plus pointers to where the how now lives.

Scope guard: naming, dead links, index drift, and reverse coverage belong to spec-lint. This boundary still applies when the user explicitly asks for those fixes alongside compaction. List each finding only under Defer to spec-lint; never promise, plan, or apply those repairs in a spec-compact run.

Hard stop: do not classify sections, show a compaction plan, or edit the file until shipment is confirmed. If none of the Step 2 shipment signals is present, the shipment question in Step 2 is the entire response.


Step 1: Resolve the Specs Root and Read Local Meta

Build a small map of the spec tree first, so the compaction can keep links to the sibling specs that own the long-term knowledge instead of restating them.

  1. Identify the specs root, stopping at the first hit:
    • Read README.md and CLAUDE.md (root + .claude/CLAUDE.md) for an explicit pointer ("design docs in docs/specs/").
    • Probe in order: docs/specs/, openspec/specs/, specs/, docs/spec/, spec/.
    • Still none → ask the user where the specs live.
  2. If <SPECS_ROOT>/meta/convention.md exists, read it — the per-project source of truth for artifact classes (requirements, design, plan, plus project extensions like runbook or adr). Compaction applies to plan and (when explicitly requested) design files only.
  3. If <SPECS_ROOT>/index.md exists, read it to find the sibling design_<topic>.md for the input plan, the closest requirements_<topic>.md (and root requirements.md), and other plans in the same module folder.

Step 1 is done when you have recorded three values: the sibling design path, the closest requirements path, and sibling plan paths (each may be "none found"). If meta/convention.md or index.md are missing, proceed on filename and location alone and note the degraded context in the final report.


Step 2: Validate the Input and Read the File

The user passes one spec file path. Verify before touching it:

  1. The path resolves to a file inside SPECS_ROOT. If it points outside the spec tree, ask the user to confirm before proceeding.
  2. The file's class is plan or design (per the convention). Refuse requirements, index, meta, or other files by emitting this line verbatim — it names the override the user needs, so paraphrasing it, or replacing it with a general explanation of why the file looks fine, is a failure:

    "spec-compact only operates on plan_*.md and design_*.md files — <file> is a <class> file, which has different content lifetime semantics. Re-invoke with --force to override."

    On --force, proceed and apply the plan rules.

  3. Compacting a design_*.md is allowed but more conservative: design docs are the long-term home for decisions and components, so the bar for removing content is higher than for plans.
  4. Read the file fully. Note lines + bytes for the before/after summary.
  5. Confirm the implementation has shipped. Any one heuristic suffices:

    • Files in the plan's Critical Files table exist on disk in the working tree.
    • UPDATE_LOG.md (or equivalent) mentions the feature.
    • The plan has a ## Changelog / ## Status section noting completion.
    • The user's prompt says it has shipped.
    • git log --oneline -- <referenced-files> returns commits.

    If all five are silent, stop here before Step 3. Do not inspect or classify sections for compaction, do not estimate the rewrite, do not print a compaction plan, and do not edit any file. Output this question verbatim as the whole reply, then wait:

    I can't tell whether this plan has shipped — compaction removes detail from the spec for good (only git preserves it). Confirm the implementation is complete?

    "Confirm the implementation is complete?" is part of the question. Paraphrases ("has this shipped?", "is this plan still active?", "I need your go-ahead") do not satisfy this gate. Resume at Step 3 only after an explicit yes.


Step 3: Classify Every Section

Walk the file and put every ## and ### heading into exactly one bucket: keep, thin, remove, hoist, or defer. Step 3 is done when every heading in the file appears in the Step 4 report. Bias toward keep: a slightly-bloated plan costs little; a deleted irreplaceable rationale costs a lot.

Two principles govern the buckets:

  • Preserve the heading skeleton. The bloat lives in section bodies — code blocks, exact diffs, per-step worklist prose — not in the structure. A reader looking for "Implementation Plan" should still find a section by that name; it is just a thin worklist now. Delete a whole section only when folding it into a sibling spec.
  • Hoist before folding. When a section body is replaced by a link to a sibling spec (typically a plan that embeds a verbatim draft of its own design_<topic>.md), first lift the plan-specific subsections — cleanup lists, file-deletion tables, breaking-change notes — out to top-level ## sections. They don't belong in the design and must not vanish with the wrapper.

Classification rules

ContentAction
## Context / ## Goal (current state / why change / target state)Keep verbatim — the most-read block in the file. Tense-shift to past post-shipping counts as tightening.
## Design Decisions / ## Approach / ## Confirmed Design ChoicesKeep verbatim — the most expensive content to recreate. Exception: mirrored verbatim in the sibling design → keep it there, link from the plan.
Error-handling tables, decision matrices, taxonomy lists, IPC command tablesKeep verbatim — reference material, not implementation steps.
Architecture diagrams, ASCII layouts, Mermaid blocksKeep verbatim — high signal per line.
Cross-doc links to design_*.md, requirements.md#X.Y, sibling plansKeep — future readers should be one click from the canonical home of decisions and acceptance criteria.
Top-of-file requirement linkage ("Plan: X (Requirement 6 + 4.3.3)")Keep — feeds spec-lint's reverse coverage check.
Live TODOs naming follow-up work not yet doneKeep, under a ## Outstanding follow-ups heading.
## Changelog / ## Status / ## HistoryKeep; prepend the new compaction entry (see below).
## Implementation Plan / ## TasksThin: keep the section heading and every ### Task N — <title> heading; replace each task body with 1–3 sentences of past-tense intent (what was done and why). Lift interwoven design rationale into ## Design Decisions (or the intent sentence itself) — rationale is never deleted.
## Cleanup of the Old Implementation / ## Removed / ## Deprecations / ## Breaking ChangesThin to a compact path | change table: one row per deleted file or removed surface, 1-phrase reason. These are the breadcrumbs that tell a future reader "this used to exist".
## Critical Files — Summary tableThin: one-line note per row; drop rows with no forward value (one-time config edits, files tweaked in passing, this plan's own doc rewrites). Collapse any separate Files modified worklist table into it.
Long code block defining a public type or data model (design artefact)Thin to a 2–4 line schema sketch (field names + types) plus a link to the canonical file.
Repeated cross-references ("as described in Step 3 above")Thin: resolve once and link, or drop if the target no longer exists post-compaction.
All other fenced code blocks (ts, rust, sql, bash, …)Remove — the compiled, versioned code is the source of truth; snippets rot and mislead.
Steps: bodies that are file-by-file diffs ("Replace X with Y", "Add field Z to TaskConfig")Remove — the diffs are in git; the task heading + intent line carry the meaning.
Per-task Files: preambles (Modify X / Modify Y / Modify Z)Remove — consolidate paths into the Critical Files table.
Verify: lines — project commands (pnpm typecheck, cargo check) and per-task test commandsRemove — project commands belong in CLAUDE.md / AGENTS.md; tests live in the repo.
Per-task test case-name lists ("tests: does X, does Y")Remove — the test file is the record. If a name is the only trace of a behavioural intent, lift a one-line summary into the task intent first.
TODO / TBD / FIXME markers about work that was doneRemove — stale.
[path](path) link wrappers in prose that are broken or redundantRemove the wrapper, keep the code-quoted path.
Section duplicating the sibling design_<topic>.md verbatimHoist plan-specific subsections, then replace the body with one line: "See design_<topic>.md for the canonical design."
Naming violations, dead links/anchors, index drift, missing requirement IDs or coverage columns, empty headings, reverse-coverage gapsDefer to spec-lint — list in the final report only.

Changelog entry

Plan a changelog entry near the bottom of the file:

## Changelog

- YYYY-MM-DD — **Compacted post-implementation.** Removed step-by-step tasks, file-by-file diffs, code snippets, and verification commands now that the feature has shipped. Preserved Goal, Design Decisions, Critical Files summary, and follow-ups. Original plan recoverable via git history.

Use the actual current date. Prepend to an existing ## Changelog, keeping all old entries. If the plan uses ## Status or ## History instead, keep that section name and add the entry there in the same style.


Step 4: Show the Compaction Plan and Confirm

Compaction is irreversible without git, so an explicit go-ahead is required even when the invocation sounds decisive ("compact this plan now"). This gate is separate from the Step 2 ship gate: if the ship gate fired, that question was already answered before you got here — never merge the two into one question. Show this report in chat before writing anything:

## Compaction plan for `<file>`

- Current size: N lines / M bytes
- Estimated post-compaction: ~P lines / Q bytes (~L% line, ~B% byte reduction)
- Sibling design (kept as link): `<path or "none found">`
- Closest requirements (kept as link): `<path or "none found">`

### Remove in full (folded into a sibling spec)
- `## <Heading>` — <reason; name the sibling target>

### Thin in place (heading kept, body replaced)
- `## <Heading>` — <what stays vs what goes>

### Keep verbatim
- `## <Heading>` — <one-line reason>

### Hoist (lift out of a removed wrapper)
- `### <Subheading>` (under `## <Wrapper>`) → top-level `## <Subheading>` — <why it is plan-specific>

### Defer to spec-lint
- <one line per finding, or "None observed">

Proceed? (yes / preview-file / preview-diff / abort)

Wait for the answer:

  • yes → apply in place (Step 5).
  • preview-file → write the compacted result to <original>.compacted-preview.md, report the path, and stop; the original stays untouched. Useful the first time on a contentious file.
  • preview-diff → show the rewritten file body in chat, then ask again.
  • abort → stop; confirm nothing was written.

Step 5: Apply and Report

  1. Write the file in place. Preserve any frontmatter block and the H1 (# Plan: …) untouched.
  2. Lint the output: every code fence closed and link bracket matched; the changelog entry present; no duplicated ## Goal / ## Context / ## Design Decisions headings from consolidation.
  3. Print:
## Compacted `<file>`

- Before: N lines / M bytes → After: P lines / Q bytes (L% line, B% byte reduction)
- Removed: <count> code blocks, <count> step-list sections, <count> file tables
- Kept: Goal/Context, Design Decisions, Critical Files, <other named sections>
- Changelog entry added: YYYY-MM-DD

### Suggested next steps
- Run `spec-lint` to refresh reverse-consistency coverage and handle any naming / index drift this run deferred.
- If you maintain `UPDATE_LOG.md`, the implementation entry there is now the authoritative narrative for the feature.
  1. Leave the diff uncommitted — the user reviews it in their VCS tool and decides when to commit.

Operating Posture

  • Single-file mutation. The only write is to the file passed in (or its .compacted-preview.md sibling). Everything else — meta/convention.md, index.md, sibling design/requirements, UPDATE_LOG.md, release notes — is read-only context. Deleting or moving an obsolete plan is the user's call.
  • One invocation, one file. For several plans, run once per file so each diff stays small and reviewable.
  • Idempotent. A second run on the same file is (almost) a no-op; if a compaction changelog entry already exists, skip writing a duplicate.
  • Composable with spec-lint. Typical flow: implement → ship → spec-compact the plan → spec-lint the tree to refresh coverage and surface anything the compaction made newly visible.

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.

Reviews can't be read right now.

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.