The reaper's content judgment of one idle bead: is its premise still real against the repo at HEAD? Emits a structured fresh | already-done | obsolete verdict. Called by `reaper --judge` (headless `claude -p`, cmd/reaper/judge.go) and by the in-session /reaper skill (Step 3); a dead verdict is what lets the reaper close the bead. Read-only; it never closes anything itself.
Installs into .claude/skills of the current project.
Are you the author of Freshness Triage?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/kurofune-freshness-triage)
---
# Generated by djinn-gen-adapters from theme=djinn. DO NOT EDIT — regenerate via djinn-gen-adapters.
# djinn-compat: 1
name: freshness-triage
description: "The reaper's content judgment of one idle bead: is its premise still real against the repo at HEAD? Emits a structured fresh | already-done | obsolete verdict. Called by `reaper --judge` (headless `claude -p`, cmd/reaper/judge.go) and by the in-session /reaper skill (Step 3); a dead verdict is what lets the reaper close the bead. Read-only; it never closes anything itself."
---
<!-- djinn-compat-check: begin -->
**Before anything else:** run `djinn skills check --here` in the repo you are working in. If it exits non-zero, stop: relay its output to the user verbatim — it names the fix — and run no other step of this skill. On exit 0, continue.
<!-- djinn-compat-check: end -->
# Freshness Triage
## Overview
This skill judges one idle bead and answers one question:
> "Is this bead's premise still real against the current codebase — should this bead exist at all?"
Idle backlogs accumulate beads whose work landed through another bead or commit, or whose premise was redesigned away. Idle age alone never closes a bead; this judgment against HEAD is the content evidence that can.
Two callers, both the reaper:
| Caller | Surface | Acts on the verdict |
|---|---|---|
| `cmd/reaper/judge.go` | `reaper --judge`, headless `claude -p` driver; `parseFreshnessVerdict` decodes the sidecar | `fresh` → keep; `already-done` / `obsolete` → close, high confidence, `reason` as the close reason |
| `core/skills/reaper/SKILL.body.md` | in-session `/reaper`, Step 3 | same mapping; closes only on operator confirmation |
Both callers reject a dead verdict with an empty `reason` and a sidecar whose `bead` names a different id — either leaves the candidate untouched.
This is a **single-pass** judgement — one agent, one pass, one verdict. It does not iterate, dedupe, or fan out.
## Scope boundary — what this judgment does and does NOT do
It answers ONLY "should this bead exist at all?" It does **NOT**:
- **Refresh stale file paths.** Design `file:line` references are hints, not contracts; whoever implements the bead re-grounds them. A real premise with moved breadcrumbs is `fresh`. Do NOT emit `obsolete` merely because a cited path moved.
- **Judge acceptance-criteria quality.** That is `ac-quality-review`, run by `/create-bead` at filing time. A bead with a real premise and vague criteria is still `fresh` here.
- **Re-plan the work.** Whether this is the *right* work is `/plan-to-beads`'s job. This judgment only asks whether the premise the bead already states is still true.
## Inputs
The invoker must provide:
1. **`bead_id`** — e.g. `phoenix-abcd`. The skill reads `bd show <bead_id> --json` to fetch `description`, `acceptance_criteria`, `design`, and `notes`.
If `bead_id` is missing, stop and ask.
## Process
### Step 1. Read the bead
```bash
bd show <bead_id> --json | jq -r '.[0] | {type, description, acceptance_criteria, design, notes}'
```
Identify the bead's **claimed deliverable**: the concrete capability, symbol, file, endpoint, or behavior the bead says it will produce. This is what you check against HEAD.
### Step 2. Check the deliverable against the repo at HEAD
You are running in the reaper's checkout at HEAD. Use read-only commands to test whether the deliverable already exists:
```bash
# Does the named symbol / file / endpoint already exist?
git grep -n "<named symbol or string>" -- '<likely path glob>'
ls <cited deliverable path>
# Does the cited test already exist and pass?
go test ./<cited package> -run '<CitedTest>' # or the project's test command
```
Read-only only. Do NOT edit, build artifacts, or mutate the tree.
### Step 3. Decide the verdict
Apply this decision order:
1. **Is the deliverable already present and satisfied at HEAD?** If the named symbol/file/endpoint exists and the cited acceptance is already met (e.g. the cited test exists and passes), the work landed via another path → verdict `already-done`. The `reason` names the concrete evidence (which symbol/test you found).
2. **Is the premise still real?** Re-read the bead's `description` — the thing it wants to change. Does that thing still exist to be changed? Was the subsystem removed, the feature redesigned away, or the approach explicitly ruled out (e.g. by a parent epic's non-goals)? If the premise no longer exists, no implementation can satisfy the bead → verdict `obsolete`. The `reason` names what was removed/redesigned and (where possible) the bead/commit/decision that removed it.
3. **Otherwise → `fresh`.** The premise holds and the work is real and unstarted (or only partially done — a partially-done bead with real remaining work is `fresh`, not `already-done`; `already-done` means the acceptance is FULLY satisfied at HEAD). The `reason` names why the premise still holds (e.g. "the named handler does not yet exist; the design file it references is still present").
**Bias toward `fresh` under uncertainty.** Closing a live bead as stale costs more than keeping a dead one another reaper pass. Emit `already-done` or `obsolete` only when the evidence is concrete — a found symbol, a passing cited test, a removed subsystem, an explicit non-goal. Vague suspicion is `fresh`.
### Step 4. Emit the structured sidecar
Emit a fenced ```json``` block (and at most ~300 words of prose above it). The reaper parses ONLY the fenced JSON.
```json
{
"verdict": "fresh",
"bead": "<bead_id>",
"reason": "<one or two sentences naming the concrete evidence for the verdict>"
}
```
`verdict` MUST be exactly one of `fresh`, `already-done`, or `obsolete` (lowercase canonical; the reaper normalizes casing but emit lowercase). `bead` MUST equal `bead_id`. `reason` MUST be non-empty — it becomes the `bd close` reason for a stale verdict, and the reaper refuses to close on an empty one.
The schema is `checks.FreshnessSidecar` (`internal/djinn/formula/checks/freshness_verdict.go`); the implement step's already-done exit (`internal/djinn/session/implement_verdict.go`) writes the same shape without running this skill. Change the keys or tokens only together with both readers.
## Verdict reference
| Verdict | Meaning | Reaper disposition |
|---|---|---|
| `fresh` | Premise still holds; work is real and unstarted/partial | keep |
| `already-done` | Acceptance is FULLY satisfied at HEAD (work landed elsewhere) | close, high confidence |
| `obsolete` | Premise no longer exists (subsystem removed / redesigned away / explicit non-goal) | close, high confidence |
## Worked examples
### Example 1 — `fresh`
Bead asks to add a `djinn.bead_claim_v2` handler. `git grep djinn.bead_claim_v2` returns nothing; the design file it cites still exists.
```json
{
"verdict": "fresh",
"bead": "djinn-abcd",
"reason": "The named handler djinn.bead_claim_v2 does not exist at HEAD and the design file it references is still present; the work is real and unstarted."
}
```
### Example 2 — `already-done`
Bead asks for a capability that a sibling bead already shipped. `git grep` finds the symbol; the cited acceptance test passes.
```json
{
"verdict": "already-done",
"bead": "djinn-abcd",
"reason": "The deliverable landed via sibling bead djinn-wxyz (commit 7ab9c28); the cited test TestFoo exists and passes at HEAD, so the acceptance is already satisfied."
}
```
### Example 3 — `obsolete`
Bead asks to modify a subsystem the parent epic's non-goals explicitly removed.
```json
{
"verdict": "obsolete",
"bead": "djinn-abcd",
"reason": "This bead modifies the summoner triage path, but parent epic djinn-aaqu's non-goals decision explicitly removed triage logic from the summoner; the premise no longer exists to be changed."
}
```
## Failure-mode handling
- **Bead not found.** `bd show <bead_id>` exits non-zero. Emit verdict `fresh` with a reason naming the lookup failure — do NOT close a bead you could not read.
- **Probe commands unavailable** (`git`/`go` absent). Default to `fresh` — never close a bead on a toolchain failure. Inconclusive evidence is `fresh`.
## Universal constraints
- **Verify against the repo at HEAD.** Read the actual checked-out code, not your memory of it. A claim about a symbol's presence names the `git grep` you ran.
- **Read-only.** The skill never edits the bead or the tree. Closing a stale bead is the reaper's job; this skill emits the verdict only.
- **Bias toward `fresh`.** Closing a live bead costs more than keeping a dead one. Emit a stale verdict only on concrete evidence.
- **Cap output at ~300 words of prose + the JSON sidecar.** Tokens go to the HEAD check, not narration.