| name | refine-deck |
| description | Deck hygiene pass — retag stale cards, prune 90-day unverified parks, surface defunct references, orphaned dependencies, and jargon titles. AUTO-INVOKE on "tidy up the deck", "hygiene pass", "clean up the queue", or /refine-deck. The board itself gets refactored each iteration. |
When to invoke
Invoke when the user says "tidy up the deck", "check for stale cards", "hygiene pass", "clean up the queue", "archive old", "audit the deck", or invokes /refine-deck. Covers retagging stale cards, pruning 90-day unverified parks, surfacing defunct file:line references, surfacing orphaned dependencies (epics with no children, meta-fix families not wired, log.md migration TODOs), surfacing engineer-jargon titles for retitling, and proposing new canonical tags (XP refactor mercilessly + Kanban continuous improvement).
Preflight
If any ! block below shows goc: command not found, Permission for this action has been denied, or no such file or directory: .game-of-cards/deck/, stop and invoke Skill(kickoff) first. Kickoff detects which setup step is missing (CLI not installed, Bash allowance not granted, project state not scaffolded) and walks the user through it. Re-invoke this skill only after kickoff completes.
Context (project-local extension)
!cat .game-of-cards/hooks/refine-deck.md 2>/dev/null || true
Refine the deck
Every iteration the BOARD gets better, not just the code on it: this
skill is the recurring hygiene tax that keeps the deck's read-pattern
guarantee alive as filing slows down and rot accumulates. The hook
above may extend the flow with project-specific categories or
thresholds (scope rules in reference.md § Rationale).
Surface rot and act on it before commit. Two action paths depending
on the finding's nature:
- Hygiene findings (mechanical: stale
unverified parks, defunct
file:line cites, missing summaries, orphaned-edge mechanical wires)
— apply the edit directly; a non-firing tag row is the one
exception, reported and never edited.
- Structural findings (epic-shaped clusters, missing
canonical-reference families, contribution-recall proposals,
meta-decision umbrellas, newly-emergent tag candidates surfaced
by a project hook's pattern-discovery pass) — file via
Skill(create-card), disprove via
Skill(advance-card) <title> disproved, or park
--tag unverified per Step 4.5. "Surfaced and discussed in chat"
is not a disposition.
Long-form material lives in reference.md — a sibling file in
this skill's directory. Read the named section only when the
situation actually applies:
| Situation | reference.md section |
|---|
| Why this pass exists; hook scope rules | Rationale |
| Running the four orphaned-dependency sub-checks | Orphaned-dependency sub-check scripts |
| Anchoring cites; what the recipe declines | Citation anchor check |
goc quality-pass --llm | Quality-pass --llm flag |
| What the Step 4 report should look like | Example Step 4 output |
| Which findings Step 4.5 covers, escape valve | Step 4.5 scope notes |
Step 1 — sanity floor
!b=.claude/skills/_goc-bootstrap.sh; if [ -f $b ]; then sh $b validate; else goc validate; fi 2>&1 || echo "[refine-deck] validate found rot; the skill body below will route you through fixing it"
If validate fails with half-edge errors, run goc repair-edges to
preview the missing reverse-edge writes, then goc repair-edges --apply and re-run goc validate. If repair reports a structural
cycle, park that card for human review instead of guessing which edge
is wrong. Fix unknown tags / missing required fields FIRST too.
Hygiene runs on a valid deck. The precondition above is intentionally
soft-gated so a failing validator surfaces its output into this
skill rather than blocking the skill load.
Step 2 — survey by category
Stale unverified parks
!b=.claude/skills/_goc-bootstrap.sh; if [ -f $b ]; then sh $b --tag unverified -v; else goc --tag unverified -v; fi 2>&1 || true
For each entry: check created against today's date. Cards parked
90 days that nobody has reproduced or refuted are decay
candidates. Options:
- Retry the falsifying recipe. If the body's
"what-evidence-would-falsify-it" recipe is now feasible (infra
exists, sweep budget available), run it. On evidence: drop the
unverified tag (promote) or flip to disproved.
- Demote to disproved. If three independent rounds have failed
to reproduce, the lead is dead.
Skill(advance-card) <title> disproved with a one-line "Three rounds attempted; no
reproduction" rebuttal.
- Keep parked. Add a one-line note in
log.md explaining why
this round didn't have the budget; the 90-day clock resets.
Stale-open cards (no log activity)
!b=.claude/skills/_goc-bootstrap.sh; if [ -f $b ]; then sh $b --status open --json; else goc --status open --json; fi 2>&1 | head -100
Cards with status: open whose log.md has no entries in 60+
days are at risk of being forgotten. For each: read the body,
decide if the lead is still real, and either:
- Re-prioritize via
Skill(next-card) (recommend it on the next
loop iteration).
- Escalate the gate from
none to decision if blocking on a
framing question.
- Flip to
disproved if the original evidence has rotted away.
Defunct file:line citations
Check each open card's cites against current code with an ANCHOR
test, not a bounds test. An in-range line number is no evidence the
cite is current: a file that grew keeps every old number valid while
the code that was there moved down, so line ≤ EOF can only fire on
a file that SHRANK. Compare what is AT the cited line now against
what the card says is there. Per cite (long form: reference.md
§ Citation anchor check):
- Resolve the path — cards write
engine.py:N for goc/engine.py:N;
prefer a non-mirror match. Ranges map both endpoints.
- Anchor = that line's text at the commit that last WROTE the number:
walk
git log --follow --format=%H -- <card>/README.md oldest →
newest and take the newest commit where the cite token turns from
absent to present — the filing commit for a virgin cite, the repair
commit for one an earlier pass rewrote. Anchoring a repaired number
at the filing commit reads unrelated code and moves the cite onto it.
- Anchor ≠ the line in HEAD → the cite is defunct.
- Relocate the anchor text in HEAD and rewrite the number only on
a unique match of a non-trivial line (>~12 chars, not a blank or a
bare brace). Never guess.
Cites step 4 declines — anchor gone, ambiguous, or trivial — are
REPORTED for a human to read, never silently skipped. Anchor text that
exists nowhere usually means the cited code was refactored away:
re-read the card and, if the refactor also fixed the defect, close via
Skill(finish-card) with a note "fixed incidentally by ".
Missing summaries
Pre-2026-05-01 cards may have empty or absent summary: fields.
Surface these:
goc --status all --json | \
jq '.[] | select(.summary == "" or .summary == null) | .title'
For each surfaced card: read the body, write a ≤3-sentence
summary into the frontmatter. Mechanical doc edit; no status
change.
Tags without firing predicates
Per Skill(card-schema), a tag must satisfy its own row, not a
fixed text window; the row's check column says whether that is
scorable or a judgment (reference.md § Tag sweeps). Survey 5–10
random cards per round. Report, never strip — a non-firing row
costs a line of output, not curated grouping.
Orphaned dependencies
Relational rot the validator cannot see: it enforces edge SYMMETRY
at commit time but not edge ABSENCE — epics with zero linked
children; meta-fix cards whose body lists a family roster but carry
zero edges; open cards with legacy **Depends on:** / **Next:** / **Part of:** body markers but empty schema arrays; unactioned
log.md migration TODOs (formerly parent: X / formerly spawned_from: X). Run the four sub-checks in reference.md
§ Orphaned-dependency sub-check scripts, judge each surfaced card's
edge direction, and wire it via goc advance X --by Y
(symmetric-by-construction, so the validator stays happy). A card
whose family members are code sites has nothing to wire — leave it.
Card metadata quality pass
Title antipatterns + missing-summary scan via:
goc quality-pass --status all
What it surfaces:
- Title antipatterns — same regex predicates
goc new uses to
reject filings (engineer-jargon: r88, path-2, phase-3,
bug-140, _md_/_py_ infixes, camelCase tokens, math symbols).
Catches legacy cards filed before the antipattern guard was wired.
For each surfaced title: rename via goc move <old> <new> so
cross-references rewrite atomically.
- Missing summaries — pre-2026-05-01 cards may lack the
summary: frontmatter field that triage views (goc -v)
depend on. For each: read the body, write a ≤3-sentence summary
into the YAML.
Step 3 — file new canonical tag candidates
When a coherent body of work emerges that isn't covered by an
existing tag (e.g., a sprint of 6 cards all about a specific
research front), file via Skill(create-card) a card whose DoD is
the SCHEMA.md PR adding the new tag + its predicate. Adding the
tag itself remains a SCHEMA.md PR per the schema's "Adding new
tags" rule; the filing that schedules that PR is imperative. Like
every other structural finding, the candidate either becomes a
card here, gets disproved (the proposed predicate doesn't fire on
a sufficient set), or parks --tag unverified per Step 4.5 — not
a chat-only proposal.
Step 4 — surface and act
For each surfaced issue, output one line documenting the action
taken (hygiene) or the card filed / disprove flip / park
(structural):
<title>: <issue> → <action>
Sample lines in reference.md § Example Step 4 output.
Step 4.5 — Park-or-disprove unfollowed structural candidates (mandatory)
Project hooks may extend Step 2 with a pattern-discovery pass that
surfaces more structural candidates than this round can verify and
file. Structural candidates that didn't get applied this round
MUST go somewhere durable before commit:
- Filed as a new card via
Skill(create-card).
- Disproved via
Skill(advance-card) <title> disproved — when
you re-read the cited code and the candidate is wrong on its
face.
- Unverified via
Skill(create-card) ... --tag unverified —
when the candidate has substance but no verification budget
this round. Body must include: the candidate's hypothesis with
file:line (verbatim quote), why deferred, falsification recipe,
the category (Step 2 sub-section) that surfaced it.
Scope, minimum-vs-maximum bound, and the noise escape valve:
reference.md § Step 4.5 scope notes.
Cross-references
Skill(advance-card) — for status flips (disproved / re-open
/ unblock).
Skill(card-schema) — tag application predicates and the schema
PR contract for new tags.
Skill(create-card) — when a hygiene issue surfaces a NEW
defect (e.g., the defunct citation reveals a real bug, not just
rot), file via create-card.
- Project commit workflow — to land the hygiene edits as a
chore(deck): hygiene pass — <date> commit.