Skip to content
Back to skills

Proposal List

ASecurity

Lists all proposals with their status, source, and age. Shows auto-detected proposals prominently. Activates on messages like "what have you noticed", "any improvements", "any proposals", "show proposals".

  • 74 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 27, 2026
data-aigofrontend

Works with

  • terminal

Security analysis

A100/100

Scanned September 20, 2026

npx -y skills add gtapps/claude-code-hermit --skill proposal-list --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Proposal List?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Proposal List
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/gtapps-proposal-list/badge)](https://www.skillsdirectory.com/skills/gtapps-proposal-list)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: proposal-list
description: Lists all proposals with their status, source, and age. Shows auto-detected proposals prominently. Activates on messages like "what have you noticed", "any improvements", "any proposals", "show proposals".
---
# Proposal List

Lists all proposals with status, source, and age. Auto-detected proposals (from the learning loop) are listed first.

## Step 0 — Channel reply

If this skill was invoked from a channel-arrived message (the inbound prompt contains a `<channel source="...">` tag), reply via that channel's reply tool and render as **Suggestion cards** (§4a) instead of the table (§4). Otherwise emit the table to conversation as usual.

## Plan

### 1. Read the proposals index

Rebuild the index:
```
bun ${CLAUDE_PLUGIN_ROOT}/scripts/proposal.ts index .claude-code-hermit
```
Then read `.claude-code-hermit/state/proposals-index.json` — a derived cache of every proposal's frontmatter (`id`, `status`, `source`, `category`, `title`, `created`, `session`, `responded`, plus an `unparseable` flag), refreshed on every proposal write by the `generate-summary` PostToolUse hook. **(fresh read — re-read the file now; do not reuse a value cached in context from before compaction.)**

The rebuild reads frontmatter off disk — idempotent, no LLM/token cost — so run it unconditionally: it also catches out-of-band proposal writes and **deletions** that the `generate-summary` hook (which fires only on `Edit`/`Write` tool payloads) never sees. The script prints `SKIP|no proposals dir` when there are no proposals — in that case respond "No proposals found." and stop. If the index's `count` is 0, also respond "No proposals found." and stop.

**Do not read proposal bodies.** Every field the table needs is in the index row; this is the whole point of the index (reading a dozen full bodies costs ~22K tokens for a table that needs only frontmatter). Read a specific body only if the operator asks to see one proposal's detail.

### 2. (metadata is already parsed)

The index rows are the parsed metadata — use them directly. A file whose frontmatter can't be read (unreadable, or no `---` block) appears with `unparseable: true` and every field null, counting as status `unknown` — the lifecycle can't act on it, since proposal.ts only writes frontmatter.

### 3. Calculate age

Calculate age in days since the proposal's `created` timestamp. Display as "N days ago".

### 4. Display as table (terminal path)

```
| ID                                       | Status   | Source        | Category    | Age          | Summary                          |
|------------------------------------------|----------|---------------|-------------|--------------|----------------------------------|
| PROP-020-tag-correlation-103612          | proposed | auto-detected | improvement | 1 session    | [tag-correlation] Frontend blocked |
| PROP-019-test-env-recurring-091455       | proposed | auto-detected | routine     | 3 sessions   | [blocker] Test env recurring     |
| PROP-015-refactor-auth-module-142233     | proposed | manual        | improvement | 12 sessions  | ⚠ Refactor auth module           |
| PROP-012                                 | accepted | manual        | capability  | 20 sessions  | Add retry logic (legacy ID)      |
```

Ordering:
1. Auto-detected proposals first (Source: auto-detected), then manual
2. Within each group: open (proposed) first, then accepted, then deferred
3. Within each status: newest first

Stale proposals (open for 10+ sessions) get a ⚠ prefix on the summary line.

### 4a. Suggestion cards (channel path)

Never surface `PROP-NNN`, the slug/timestamp, `category`, or tier in channel text — the operator sees a plain suggestion number and a summary. Derive `#N` by stripping leading zeros from the proposal's `PROP-(\d+)` integer (e.g. `PROP-014-tag-correlation-103612` → `#14`); this is a deterministic reverse-lookup (`proposal-act`'s resolution algorithm already accepts an unpadded `PROP-N`), not a separate stored counter.

For each `status: proposed` proposal (same ordering as §4), render one card:

```
Suggestion #14 — Frontend blocked on tag correlation.
Reply YES to go ahead, LATER to hold, NO to drop it.
```

Derive the summary from the title with any `[category]`/`[blocker]` bracket prefix stripped. Drop the stale-⚠ marker; if a card is stale, fold it into the summary in plain words instead ("been waiting a while").

Non-open proposals (`accepted`/`deferred`, plus `dismissed`/`resolved` when "show all" was asked — §5) that the operator explicitly asked to see render as one plain line each, no reply prompt, stating the status in plain words:

```
Suggestion #12 — Add retry logic (already accepted).
```

If more than one Suggestion card is shown, add one footer line: "Reply with the number if you mean a specific one, e.g. 'YES #14'." Omit the footer when only one card is shown — a bare YES/LATER/NO is unambiguous.

### 5. Default filtering

By default, **hide** proposals with status `dismissed` or `resolved`.

If the operator asks to "show all", "include dismissed", "show everything", or similar: include all proposals regardless of status. Dismissed and resolved proposals appear at the bottom of the table with their status visible.

### 6. Offer actions (terminal path only)

After displaying the table, offer:

```
Actions: /proposal-act accept [ID] | /proposal-act defer [ID] | /proposal-act dismiss [ID]
```

If there are stale proposals, add: "⚠ N proposal(s) have been open for 10+ sessions. Consider reviewing or dismissing."

On the channel path (§4a), the card's own YES/LATER/NO prompt is the action offer — no slash-command footer.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.