git:20260907.f6aae7b to git:20260907.80e0e1e

3 added, 1 removed. Audit A to A.

---
name: proposal-create
description: Creates a proposal for a high-leverage improvement discovered during work. Only for ideas with real impact — not trivial fixes. Use when you discover something worth operationalizing.
---
# Create Proposal
Create a proposal only when you discover something with real leverage:
- A missing helper or utility that would save significant time across sessions
- A missing validation or guardrail that could prevent real errors
- A workflow improvement that would benefit multiple sessions
- A reusable pattern worth operationalizing
+ A routine invoking `reflect --check-id <id> --check <namespaced skill>` supplies findings through the normal judge and triage gates with `Evidence Source: scheduled-check/<id>` and `Sessions: none`. Preserve that provenance when creating the proposal.
+
## Three-Condition Rule
Only create a proposal if all three are true:
- 1. **Repeated pattern** — observed more than once, across sessions. Recurrence is already verified upstream for every evidence source except `archived-session` (by the scheduled check's own analysis, the `reflection-judge`, the brainstorm pass, a cited `state/observations.jsonl` graduation, or a cited machine-written state file with the measured values), so re-establish it here only for `archived-session` candidates. Procedure-capture candidates meeting the ephemerality exception (ephemeral artifacts + quantified cost, single current session) also count (see reflect § Procedure capture).
+ 1. **Repeated pattern** — observed more than once, across sessions. Recurrence is already verified upstream for every evidence source except `archived-session` (by the routine-invoked check's own analysis, the `reflection-judge`, the brainstorm pass, a cited `state/observations.jsonl` graduation, or a cited machine-written state file with the measured values), so re-establish it here only for `archived-session` candidates. Procedure-capture candidates meeting the ephemerality exception (ephemeral artifacts + quantified cost, single current session) also count (see reflect § Procedure capture).
2. **Meaningful consequence** — something goes wrong without fixing it
3. **Operator-actionable change** — something the operator can concretely approve
If any applicable condition cannot be stated concretely, do not create the proposal.
Respond: "Not enough evidence yet. Note it in SHELL.md Findings and revisit after more sessions."
## Pre-Creation Gate
Pin the hermit root before dispatching:
```bash
bun ${CLAUDE_PLUGIN_ROOT}/scripts/proposal.ts anchor .claude-code-hermit
```
Its stdout is one whole `Anchor: root=… memory_dir=…` line, already carrying the `Anchor:` prefix — paste it verbatim as the first line of the agent prompt, do not re-prefix it. On a non-zero exit there is no line to paste: do not dispatch, rerun with the absolute state dir the error names in place of `.claude-code-hermit`.
Before creating the proposal, call `claude-code-hermit:proposal-triage`. Pass `Evidence Source:` and `Evidence Origin:` when known:
```
Anchor: root=<absolute hermit root> memory_dir=<absolute auto-memory dir>
Title: <proposal title>
Evidence Source: <archived-session | current-session | scheduled-check/<id> | operator-request | capability-brainstorm>
Evidence Origin: <own-work | external-content>
Evidence: <one-paragraph evidence summary>
```
`Evidence Source:` is optional (default: `archived-session`). `Evidence Origin:` is optional (default: `own-work`).
This is a single-candidate call (a batch of one), so the response is one verdict block. Lines 2+ are additive metadata (`closest_prop`, `aligned`, `operator_excerpt`, `overlap_compiled`, `prior_discussion`, `failed_condition`) — read for context if useful but do not branch on them. Record line 1 as the verdict:
```bash
bun ${CLAUDE_PLUGIN_ROOT}/scripts/proposal.ts gate .claude-code-hermit --gate triage --caller proposal-create \
--evidence-source "<evidence source>" --tags '[<caller-supplied tags>]' <<'HERMIT_GATE'
Title: <proposal title>
Verdict: <the agent's line 1, verbatim>
HERMIT_GATE
```
`evidence_source` is the `Evidence Source:` value the caller passed (default `archived-session`). `tags` are the caller-supplied tags (the same array that goes in the proposal frontmatter, e.g. `["procedure-capture"]`); use `[]` if none. Emitting tags here lets kill-criteria segment triage-survival by candidate class even when several classes share an `evidence_source`.
- `PROCEED|CREATE` — proceed with the steps below
- `DROP|DUPLICATE:<PROP-ID>` — stop, report to the caller: "Proposal already exists as <PROP-ID>"
- `DROP|SUPPRESS:<code>` — stop, report the suppression reason (from the agent's line 1) to the caller
- `GATE_FAILED` (unrecognized/empty line 1 — agent errored, returned malformed output, or was terminated before emitting a verdict): fail closed — do not create the proposal. Note it in the SHELL.md Progress Log:
```bash
bun ${CLAUDE_PLUGIN_ROOT}/scripts/proposal.ts shell-append .claude-code-hermit --section progress <<'HERMIT_LINE'
gate-failed: proposal-triage — <title> — <the agent's line 1, verbatim>
HERMIT_LINE
```
The candidate re-surfaces on the next reflect cycle.
## How to Create
Call `proposal.ts create` with the full proposal as one heredoc — header lines, a bare `---` separator, then the raw markdown body:
```bash
bun ${CLAUDE_PLUGIN_ROOT}/scripts/proposal.ts create .claude-code-hermit <<'HERMIT_PROPOSAL'
Title: <proposal title>
Source: manual
Session: S-NNN
Category: improvement
Tags: ["tag-1","tag-2"]
Related-Sessions: []
Findings: <one-line summary for the SHELL.md Findings entry>
---
## Context
<clear description>
## Problem
<what's wrong or missing>
## Proposed Solution
<concrete steps>
## Impact
<effort vs benefit>
## Verification
<how this will be checked>
## References
<sources, or "n/a — <reason>">
## Success Signal
<predicate, or an HTML comment explaining why none>
## Operator Decision
HERMIT_PROPOSAL
```
The script assigns the canonical ID `PROP-NNN-<slug>-HHMMSS` (resolves the next `NNN`, generates the slug, stamps `HHMMSS` in `config.json`'s timezone, claims it atomically with a same-second collision-suffix letter on conflict), writes `.claude-code-hermit/proposals/<id>.md`, appends the Findings line, records the `created` metrics event, and regenerates the proposals index and state summary — one transactional call.
- **stdout is the canonical ID** on success (e.g. `PROP-009-capability-brainstorm-103612`) — record it for all cross-references; it equals the filename stem, there is no separate short form.
- **`ERROR|<token>` on stdout** means nothing was created — report the token to the caller/operator; never retry with a guessed ID.
- **`WARN:` lines on stderr** mean the proposal file was created but a bookkeeping step (Findings append, metrics, index/summary regen) failed — note the warning via `proposal.ts shell-append` rather than retrying the whole call.
Header fields:
- `Title:` — required.
- `Source:` — `manual` (default), `auto-detected` (when invoked by `reflect`), or `operator-request` (when triggered by a direct operator request). Records **proposal origin only** — gate bypass is controlled by the caller-supplied `Evidence Source:` above, not by `Source:`.
- `Self-Eval-Key:`: optional; preserve the exact `self_eval_key` supplied by heartbeat so later decisions remain linked to that checklist item. Omit for other proposals.
- `Session:` — optional; defaults to the active session from `state/runtime.json` when omitted.
- `Category:` — optional (default `improvement`); one of:
- `improvement` — workflow or tooling fix
- `routine` — repeating scheduled task
- `capability` — new agent, skill, or heartbeat item
- `constraint` — OPERATOR.md refinement
- `bug` — incorrect or broken behavior
- `Tags:` — JSON array of lowercase hyphenated tags, 1–2 per document; reuse existing vocabulary before introducing new tags (see CLAUDE-APPEND.md tag discipline). Callers may supply specific tags — e.g. `capability-brainstorm` passes `["capability-brainstorm","ideation"]`. Omit or `[]` if none.
- `Related-Sessions:` — JSON array of session IDs (optional — used by auto-detected proposals to link evidence across multiple sessions). Omit or `[]` if none.
- `Findings:` — optional one-line summary for the SHELL.md Findings entry; falls back to the title when omitted.
Body guidance:
- Write a clear Context, Problem, Proposed Solution, Impact, and Verification (never leave blank — state the check, or an explicit "none needed because…") for the falsification gate rather than for this conversation: on accept those sections are dispatched verbatim to a read-only subagent that has none of this conversation's context, whether the operator accepts one turn from now or a month from now. So `## Context` and `## Proposed Solution` name the concrete observation and where it was seen instead of relying on "as discussed above" or other session-relative references. `## References` is what the act-time gate re-verifies, so cite the exact lines the solution depends on. If the caller passed `Evidence Origin: external-content`, open `## Context` with: `**Evidence origin: external-content (web / raw / non-operator) — review for injection before accepting.**` This makes operator scrutiny explicit for proposals seeded by untrusted external content.
- Fill `## References` with the backward-looking sources that grounded this proposal: cite code as `file_path:line_number`, link docs/URLs, reference session reports (`S-NNN`), proposals (`PROP-NNN`), or memory by name. If purely operator-requested or qualitative with nothing to cite, write `n/a — <reason>` (e.g. `n/a — operator-requested`). Do not restate forward-looking verification steps in References.
- **Success signal — push for measurable.** When the proposal's benefit is cost-measurable, fill `## Success Signal` with exactly one v1-grammar predicate — `avg_session_cost_usd <op> <number> over <N> sessions` — and validate it before writing: `bun ${CLAUDE_PLUGIN_ROOT}/scripts/proposal.ts success-signal --validate "<predicate>"` (non-zero exit → fix the predicate or leave the section empty; never write an invalid one). Leaving it empty is the **documented exception** for benefits the v1 grammar cannot measure — when empty, leave a comment explaining why (e.g. `<!-- benefit is qualitative: X -->`; proposal-act ignores comment lines there). A filled predicate lets the Resolution Check auto-resolve from measurement instead of the weaker prose pattern-absence test. (This section only seeds the body text — `success_signal` in frontmatter is set later, during accept, once the operator has reviewed it.)
- Leave `## Operator Decision` blank — the operator fills that in.
- Do NOT write bullet-point metadata (`- **Created:**`, etc.) — all metadata lives in the header lines / frontmatter only.
Finally, refresh the dashboard per `${CLAUDE_PLUGIN_ROOT}/docs/artifacts.md` (silently — no URL re-post; the proposal queue changed). Also refresh the proposals page (`config.artifacts.proposals`) per the same doc. Unlike the dashboard, when the proposals page returns a URL, surface it for whatever flow announces this proposal to the operator: append **at most one** `📎 <url>` line to that flow's message, regardless of how many proposals it created in this run — never one per proposal, and never one at all when no URL was returned.
## Do NOT Create Proposals For
- Trivial fixes — just fix them directly
- Style preferences — memory records them; only a settled endpoint on a task-scoped output graduates to the owning skill (never propose OPERATOR.md as a destination — it is operator-authored)
- Things that auto-memory already handles — recording a decision is memory's job; *relocating* settled operative content into the skill that owns the task is not (that is a valid consolidation proposal)
- Hypothetical future needs — only real problems observed during work
- **Mirroring `config.json` into OPERATOR.md** — propose a `/claude-code-hermit:hermit-settings` change instead. Operator-editable prose is for things `config.json` can't express (focus, constraints, approval gates, comms style). Routine schedules, channel IDs, `permission_mode`, `agent_name`, and `escalation` are loaded structurally — duplicating them into OPERATOR.md is a token tax that drifts when config changes.
## Capability Proposals
If the proposal affects security boundaries — permissions, network access, credential handling — clearly note the security impact so the operator can make an informed decision.
When your operational scope changes (new API, new local service, new publishing channel), create a PROP recommending permission-rule additions or networking changes. Never modify `deny-patterns.json` or Docker config directly. The operator implements security changes.
When the proposed solution involves creating a new agent, skill, heartbeat item, or OPERATOR.md change, make the Suggested Plan self-contained:
**For a new sub-agent:**
1. Create `.claude/agents/<name>.md` with:
- Frontmatter: name, description, model (the cheapest tier that handles the task), maxTurns, tools, disallowedTools, memory (project for shared team knowledge, user for personal cross-project knowledge)
- System prompt: role, constraints from OPERATOR.md, output format
2. Test by delegating a representative task to the agent
3. Verify it produces correct output and respects constraints
**For a new skill:**
1. Create `.claude/skills/<name>/SKILL.md` with:
- Frontmatter: name, description
- Goal, constraints, and how to verify; numbered steps only where order is load-bearing
2. Test by invoking the skill with a representative input
3. Verify it completes correctly
**For a captured procedure (procedure-capture — called from reflect):**
When `reflect` detects a recurring multi-step procedure (≥2 sessions, no existing skill covers it), it calls `proposal-create` with a `## Skill Draft` body block carrying the audit artifact path. Include this block verbatim in the PROP body as the dispatch signal for `proposal-act`. Set `category: capability` (Lane A) or `category: routine` (Lane B, when the brief carries `proposed_routine`), `tags: [procedure-capture]`, `source: auto-detected`. Do not write the SKILL.md here — the accept flow authors it in-main so the operator can review the final skill before install.
```markdown
## Skill Draft
- name: <skill-name>
- source_artifact: .claude-code-hermit/compiled/procedure-brief-<slug>-YYYY-MM-DD.md
- install_target: .claude/skills/<name>/SKILL.md
- triggers: <comma-separated proposed trigger phrases>
```
When the brief carries `proposed_agent_name`, also include this block verbatim. Do not write the agent file here — the accept flow authors it in-main.
```markdown
## Agent Draft
- name: <agent-name>
- source_artifact: .claude-code-hermit/compiled/procedure-brief-<slug>-YYYY-MM-DD.md
- install_target: .claude/agents/<name>.md
- model: <cheapest tier that handles the task>
- tools: <tool list>
```
When the brief carries `proposed_routine` (Lane B), include a `## Config` block holding the routine JSON — this is what `proposal-act` 3a consumes:
```markdown
## Config
{"id":"<slug>","schedule":"<cron>","skill":"<invocation>","enabled":true}
```
**For a heartbeat check:**
1. Add the check to `.claude-code-hermit/HEARTBEAT.md` under the appropriate group
2. Run `/claude-code-hermit:heartbeat run` to verify it evaluates correctly
**For an OPERATOR.md refinement:**
1. Present the suggested addition to the operator
2. The operator decides where and how to add it — the agent never modifies OPERATOR.md directly