agentleFS
gtappsgtapps/claude-code-hermit/.agents/skills/stale-proposals/SKILL.md

stale-proposals

Skill84 starsChanged 7 days agoMITView on GitHub

Audit this repository's local proposal queue for stale entries: proposals still open as a proposal task (awaiting consent or approved) even though the work already shipped, plus old proposals whose subject has become inert. Reconcile proposals against plugin changelogs and first-parent Git history, automatically resolve only unambiguous shipped matches, and ask before any weak-match, aged, or dismissal decision. Use when the user asks to check, reconcile, clean up, prune, or find stale proposals; asks whether proposal work already shipped; is confused why an old PROP remains open; or wants to stop heartbeat from repeatedly surfacing obsolete proposal-pending items. Supports a report-only no-apply mode.

1 other project uses a version of this.

Adopted by

Most recently taken up by

The file

We split this skill into the rules it gives an agent

6 rules. About 0 are common, 5 are distinctive, and 1 is very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈5

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 1

    Very specific

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

  • Common
  • Distinctive
  • Very specific
  1. Distinctive:

    Do not read the evidence bundle in the main session.

    line 34
  2. Distinctive:

    Use this contract verbatim, substituting the real path:

    line 40
  3. Very specific:

    Only a proposal still awaiting consent (status: proposed in the bundle) is auto-resolved: closing an approved one needs a named user …

    line 69
  4. Distinctive:

    Stop and wait for the response.

    line 89
  5. Distinctive:

    Treat only family-wide dismissal preferences as durable feedback.

    line 97
  6. Distinctive:

    Use this compact shape:

    line 101

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

Stale Proposals

Reconcile the open proposal queue against what actually shipped.

Trust shipping evidence more than age. An unambiguous shipped match can close automatically because the evidence is inspectable and the decision is reversible. Age or silence alone requires the user's judgment.

Invocation

  • $stale-proposals — audit the queue, auto-resolve strong shipped matches, and ask about everything else.
  • $stale-proposals with no apply or report only — write nothing and report all verdicts.

Step 1 — Collect bounded evidence

From the repository root, run:

bun .agents/skills/stale-proposals/scripts/collect-evidence.ts [--hermit-dir <hermit-dir>]

<hermit-dir> is the state folder that holds tasks/; a proposal is a task record with kind: proposal (see plugins/hermitd/docs/task-records.md), and migrated ones keep their PROP-NNN id as dedupe key proposal:PROP-NNN. It defaults to <repo>/.hermit, which is only right in the resident's own checkout. In a checkout whose .hermit is a projection (a core checkout under a resident workspace, a worktree), pass the resident's absolute .hermit path. Use that same path in Steps 3 and 4.

The script prints one of:

  • OK|<bundle-path>|<open>|<bullets>|<commits>|<cutoff>|<tasks>
  • NONE|no-open-proposals

For NONE|no-open-proposals, report Queue is clean — no open proposals. and stop. A non-zero exit means a wrong path or an unmigrated state folder: report the stderr message and stop, never treat it as a clean queue. Unmigrated means proposals/*.md still exist; the user runs proposal.ts migrate <hermit-dir> once, this skill does not. The bundle also lists closed task records that name a PROP id.

Do not read the evidence bundle in the main session. It can be tens of thousands of tokens and exists specifically to keep that corpus isolated.

Step 2 — Match in one isolated worker

Spawn one worker agent with a fresh context (fork_turns: "none" when supported). Give it only the repository root, evidence-bundle path, and the contract below. Wait for its result before continuing. If agent spawning is unavailable, stop and explain that this audit requires one isolated worker; do not load the bundle into the main session as a fallback.

Use this contract verbatim, substituting the real path:

Read the evidence bundle at <path>. It lists open proposals (each headed by its PROP-NNN or T- id), then CHANGELOG bullets, closed task records, then first-parent commits.

For each open proposal, decide whether the thing it asked for has already shipped. Emit exactly one line per proposal, and nothing else:

  • SHIPPED-STRONG|<ID>|<plugin> <version> / <commit or "changelog">|<one sentence: what the evidence says, in the changelog's own words>
  • SHIPPED-WEAK|<ID>|<evidence ref>|<one sentence: what matches and what you could not confirm>
  • AGED|<ID>|<age in days>|<one sentence: why nothing has moved on this>
  • OPEN|<ID>

STRONG requires all three: the evidence names the same component the proposal targets; it describes the same behavior change the proposal asked for; and no distinct part of the proposal's ask is left unaddressed. A proposal asking for three things where the changelog delivers two is WEAK, not strong — partial delivery is the single most likely way this audit closes live work by mistake, so when you notice yourself arguing for why a gap "probably doesn't matter," that is WEAK.

Ignore date order at your peril: evidence dated before a proposal was created cannot be that proposal shipping. It is usually the prior art the proposal was written against. Changelog dates have day granularity while proposals carry a timestamp, so same-day changelog or commit evidence cannot be ordered at all — treat it as at most SHIPPED-WEAK and say so.

Closed task records (the bundle's task section) are stronger evidence. A record whose title or closed_reason names the proposal, closed done, with a closed_reason saying its PR or PRs all merged, counts as SHIPPED-STRONG evidence even when it is the only evidence and even on the same day as the proposal: the record was opened and closed after the proposal existed. It must still cover the whole ask; a record for one of several parts is SHIPPED-WEAK. A cancelled record, or one that only records a helper report or investigation, is not shipping evidence.

A proposal can ship under a different name than it asked for. Match on substance — the component, the behavior, the problem being closed — not on the proposal's chosen identifier.

Use AGED only when there is no shipping evidence at all AND no commit in the history touches the proposal's subject area since it was created — an untouched subject is what "inert" actually means. Age alone is not staleness; a good idea nobody got to yet is OPEN.

Be conservative. OPEN is the correct answer for most proposals and costs nothing; a wrong SHIPPED-STRONG silently closes live work.

Reject malformed lines or missing proposal IDs instead of guessing.

Step 3 — Apply strong matches

Skip this step in report-only mode.

Only a proposal still awaiting consent (status: proposed in the bundle) is auto-resolved: closing an approved one needs a named user identity, so a SHIPPED-STRONG on an accepted proposal joins the Step 4 list.

The bundle's task: line gives the task id. Record the evidence, then decline consent through the local answer path, which is how task.ts closes a pending proposal from the terminal (plugins/hermitd/docs/task-records.md § Proposals and durable questions):

bun plugins/hermitd/scripts/task.ts note <hermit-dir> <task-id> --decision <<'HERMIT_NOTE'
Resolved @now: shipped in <plugin> <version>. <evidence sentence>
HERMIT_NOTE

bun plugins/hermitd/scripts/task.ts answer <hermit-dir> <task-id> --local --reply no

Replace @now with the current date. The note makes the automatic resolution auditable. A shipped proposal closes as cancelled (the record's closed reason reads "Consent declined"), because a pending proposal has no resolved outcome; the Decisions note says why. The answer needs the harness permission prompt and is refused under bypass mode, so a refusal means leave it for Step 4 and say so.

answer prints {"status":"match",...} on success. Any other status (none, refused, ambiguous, stale), or {"error":...}, means nothing was closed: report it, move that proposal to Step 4, and continue. A note already written stays as a harmless record.

Step 4 — Ask about the rest

Present SHIPPED-WEAK first, then AGED, then any accepted SHIPPED-STRONG. Ask the user in one concise round whether to resolve, dismiss, or leave each item open. Separate items when one group clearly needs different decisions.

Stop and wait for the response. Do not interpret the original audit request as approval for these mutations.

Apply confirmed choices with task.ts against the same <hermit-dir> as Step 1. Both resolve and dismiss close the record as cancelled; the Decision note carries the difference:

  • Awaiting consent: note --decision with the user's choice and reason (for resolve, as Step 3), then answer <task-id> --local --reply no.
  • Accepted: cancel <task-id> --actor <source>:<user-id> --chat <chat-key> --user <user-id> --reason-stdin with the reason on stdin, using the user's own identity from this conversation. A terminal-only session has none: report the task id and leave it open.
  • Leave open: make no changes.

Treat only family-wide dismissal preferences as durable feedback; proposal-specific reasons are not standing policy.

Step 5 — Report the delta

Use this compact shape:

Proposal queue: <N> open → <M> open

Resolved automatically (<n>)
  PROP-056 — shipped in hermitd [Unreleased]: <evidence>

Confirmed with you (<n>)
  PROP-006 — dismissed

Still open (<n>)

Report what changed and any failed mutations. Do not re-list the whole remaining queue.

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.