plugins/claude-code-hermit/skills/reflect/SKILL.md
Reflect on recent work and propose improvements if patterns are noticed.
npx skillsauth add gtapps/claude-code-hermit reflectInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Pause and think about your recent work.
Silent by default. Only notify the operator (per CLAUDE.md § Operator Notification) if reflect produces an outcome: a proposal candidate, a micro-approval, a resolved proposal, a graduated observation, or a cost spike.
Rare-branch procedures live in ${CLAUDE_PLUGIN_ROOT}/skills/reflect/branches.md. "Read branches.md § X" means: read that section now and follow it exactly — it is normative.
If $ARGUMENTS contains --quick:
--precheck-verdict '<verdict>': the reflect_after routine already ran the hash-gate precheck; <verdict> is always RUN|<hash> (the routine stops on EMPTY without loading this skill). Parse <hash>; do not re-run the precheck. Otherwise (manual invocation) run it in force mode (no gate to skip once this skill is loaded — always returns RUN|<hash>):
bun ${CLAUDE_PLUGIN_ROOT}/scripts/reflect-precheck.ts .claude-code-hermit ${CLAUDE_PLUGIN_ROOT} --quick --force
$PHASE = adult. Only the live SHELL.md scan + judge + outcomes path runs.## Findings and ## Blockers for actionable patterns. Only Tier-1 + Evidence Source: current-session candidates are eligible. Candidates needing archived-session evidence or Tier 2/3 defer to the next scheduled reflect — append one ledger row each so the signal survives archival and can graduate:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/observations.ts observe .claude-code-hermit quick-deferral <<'HERMIT_OBSERVATION'
<candidate-title-slug>
HERMIT_OBSERVATION
Exception: a current-session candidate with Evidence Origin: external-content is not deferred — send it to the judge; Tier-3 escalation routes it to proposal-create.claude-code-hermit:proposal-triage batch call, judge the CREATE survivors in one claude-code-hermit:reflection-judge call, route ACCEPT/DOWNGRADE through branches.md § Outcomes; unrecognized gate output fails closed per branches.md § Gate failure handling. Track whether anything hit the gate-failed/SUPPRESS path — it gates the cursor write.[HH:MM] reflect (quick, post-routine) — N candidates; verdicts: accept=A downgrade=D suppress=S; outcomes: <list or "none">; when suppress>0 add the ; suppressed: suffix (§ Progress Log Entry) so quick-run suppressions reach the weekly digest.last_quick_hash makes the next reflect_after fire re-read the same Findings/Blockers (the "re-surfaces next cycle" contract; deferred candidates are already durable in the ledger):
bun ${CLAUDE_PLUGIN_ROOT}/scripts/update-reflection-state.ts .claude-code-hermit/state/reflection-state.json --quick-hash '<hash>'
update-reflection-state.ts <path> '<json-payload>' form here — quick runs are event-driven; mutating last_run_at would suppress the next scheduled reflect (--quick-hash is an isolated write).If $ARGUMENTS contains --scheduled-checks (the scheduled-checks routine — daily, offset from the main reflect): run at most one due interval-triggered scheduled check — an idempotent, short-running, read-mostly skill from config.scheduled_checks whose cadence is owned by scheduled_checks.interval_days — route any finding through reflect's normal gates, persist per-check state, append a Progress Log line, then stop (no precheck, no numbered steps below). Read branches.md § Scheduled checks now and follow its steps 1–8 exactly.
--precheck-verdict '<verdict>': the reflect routine already ran the precheck in bash — use <verdict> directly, do not re-run it (always RUN|<phases-json>; the routine stops on EMPTY without loading this skill). Otherwise run it yourself and read the first line:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/reflect-precheck.ts .claude-code-hermit ${CLAUDE_PLUGIN_ROOT}
EMPTY → nothing due; the precheck already updated reflection-state.json and appended the Progress Log line. Emit reflect: no candidates and stop.RUN|<phases-json> → continue. The JSON lists due phases (cost_spike, behavior, resolution_check, compute, digest, newborn, observations_fresh); skip sections for phases not listed. observations_fresh means the ledger has rows newer than last_run_at — run step 3b even if compute is absent.cost_spike is listed: the precheck already detected the spike and wrote the row (cost-spike:<YYYY-MM-DD>, carrying today_total and median_7d as fields), so there is nothing to read or record here — it graduates via step 3b like any other observation. Do not re-read cost-log.jsonl to restate a number the precheck already computed.3a. Behavioral digest — if behavior is listed: run bun ${CLAUDE_PLUGIN_ROOT}/scripts/transcript-digest.ts .claude-code-hermit --record-observation (bounded ~20-line JSON of ground-truth counters — tool failures, tool_rejections by kind, wakes vs productive_wakes, compaction_events, subagent_dispatches; never Read a transcript directly). Two uses of the counters:
--record-observation makes the script write the defer-loop row itself when its own counters cross the threshold, citing the observed window.from→to span. Nothing to record here. (The flag is opt-in so an ad-hoc digest run stays a pure read.)tool_rejections.automode-blocked > 0; any single tool with tool_failures[tool] ≥ 5; compaction_events ≥ 3. A hit is a question for the gates (triage → judge), never a verdict — a quiet week with mostly unproductive wakes is legitimate, so the gates own false-positive pruning.3b. Observations ledger — prune, then graduate recurring patterns.
bun ${CLAUDE_PLUGIN_ROOT}/scripts/prune-observations.ts .claude-code-hermit (fail-open).state/observations.jsonl (skip if absent/empty; per-line try { JSON.parse(line) } catch {}); group by pattern.graduation_min_sessions distinct session_ids (config reflection.graduation_min_sessions, default 1) is mechanically promoted to a candidate. Origin aggregation: Evidence Origin: external-content if any grouped row has origin: "external-content", else own-work (old rows lacking the field are own-work). Build with Evidence Source: archived-session, Sessions: <the distinct session_ids>, Artifact: state/observations.jsonl — pattern "<label>" in N sessions; route via § Candidate processing. Below-threshold patterns stay untouched.skill-correction:<name>: Read branches.md § skill-correction:* routing and follow it (brief resolution → Tier 2 Skill Improvement candidate).Compute phase — read counters.since from state/reflection-state.json (missing/unparseable → $PHASE = adult, never block). age_days = whole days since it: newborn < 3, juvenile 3–13, adult ≥ 14. $PHASE gates sub-threshold surfacing and the Progress Log annotation.
Delegate the proposal scan to the built-in Explore subagent. Prompt: List all .claude-code-hermit/proposals/PROP-*.md files. For each, extract id, status, title, source, created, accepted_date, related_sessions from YAML frontmatter. Skip any file with no frontmatter block. Return a compact JSON array — metadata only, no file bodies. Also tail the last 100 lines of state/proposal-metrics.jsonl (inline, single read): count responded and micro-resolved events by action, triage-verdict events by verdict — feeds the operator-value and Component Health checks.
Dispatch the eval runner. Dispatch claude-code-hermit:skill-eval-runner pointed at ${CLAUDE_PLUGIN_ROOT}/skills/reflect/reference.md. The dispatch prompt carries: plugin_root (resolved absolute path — ${CLAUDE_PLUGIN_ROOT} is not substituted in reference.md), the precheck phases-json, the last_resolution_check cursor (from state/reflection-state.json), and session_state (from state/runtime.json; controls the routine check).
Failure policy: null/malformed runner JSON → fail open: skip the apply steps, carry forward empty candidate lists, do not advance the cursor, append [HH:MM] reflect — analysis-runner failed; introspection-only to the Progress Log, continue.
Eval runner return schema — byte-identical in reference.md (producer) and here; contract-tested.
{
"resolution_actions": [ { "proposal_id": "PROP-NNN", "action": "auto-resolve|nudge|skip",
"frontmatter_patch": {"status":"resolved","resolved_date":"<ISO>"}|null,
"shell_findings_line": "<pre-rendered finding text>"|null } ],
"routine_candidates": [ { "routine_id": "<id>", "action": "disable|retime|diagnostic",
"tier": 1, "schedule": "<new-cron>"|null,
"evidence": "<text>", "sessions": ["<S-NNN>"],
"shell_findings_line": "<pre-rendered>"|null } ],
"procedure_candidates": [ { "slug": "<slug>", "title": "<title>", "tier": 3,
"evidence_source": "archived-session", "evidence_origin": "own-work",
"evidence": "<text>", "sessions": ["<S-NNN>"]|"none",
"artifact": "<file — value>"|null } ],
"last_resolution_check": "PROP-NNN|null",
"last_sparse_nudge": { "PROP-NNN": "<ISO>" }
}
<!-- reflect-eval-schema:end -->
Apply resolution_actions (housekeeping; exempt from the evidence integrity rule): pipe the runner's resolution_actions via a quoted heredoc (model-authored JSON may contain apostrophes) to the transactional apply script — it validates the whole batch before any write (a malformed batch writes nothing), then performs the frontmatter patches, state/proposal-metrics.jsonl appends, and SHELL.md ## Findings appends itself (nudge debounce handled in the runner):
bun ${CLAUDE_PLUGIN_ROOT}/scripts/apply-reflection-actions.ts .claude-code-hermit <<'HERMIT_REFLECT_ACTIONS'
{"resolution_actions": <the runner's resolution_actions array>}
HERMIT_REFLECT_ACTIONS
Parse its single JSON line: ok === false or empty stdout → treat as the step-6 failure policy (skip apply, append [HH:MM] reflect — apply-reflection-actions failed; introspection-only to the Progress Log, continue). Carry the other four return fields to Candidate processing and State Update.
Now reflect — think hard — using inherited context only (SHELL.md from step 2, cost shape from step 3, behavior digest from step 3a, metrics summary from step 5; the runner handled cross-session file analysis — do not re-read session reports or proposal bodies). Signals: anything recurring or worked around instead of fixed? Spending proportional to the work — could a cheaper subagent (Haiku) have handled it; was context bloat avoidable? Something done manually that a skill covers, or a repeating subtask within the session a subagent could have handled? Value the operator actually uses — high dismiss/rejected rates from step 5 signal noise (Tier 1 micro-proposal to pare back); a high expired rate means poor question timing, not unwanted questions. The same multi-step procedure in ≥2 sessions with no covering skill (procedure-capture candidate)? If runtime.json session_state is idle, think broader: a recurring check for HEARTBEAT.md, a missing OPERATOR.md preference, a skill/subagent to formalize repeating work, a manual request repeating on a schedule (routine-type candidate; branches.md § Candidate processing has the Type: routine Config-block format).
Is any skill, agent, or hook underperforming? Skills: output consistently corrected after use (answered from the skill-correction:* ledger graduation in step 3b, not re-derived from prose)? Avoided for manual steps? Missed something it should catch? Disproportionate tokens for its value? Agents: flag reflection-judge when judge_suppress > 2× judge_accept (reflection-state counters, ≥5 verdicts since since); flag proposal-triage when step 5's SUPPRESS > 2× CREATE (≥5 verdicts) — the gate may be over-strict. Hooks: out of scope (no telemetry) — do not infer from side-effects; note as a known gap if suspected. Findings become candidates (signal ladder + ## Skill Improvement format: branches.md § Candidate processing).
Collect all candidates first — think-hard observations, step-3b graduations, routine_candidates and procedure_candidates from the runner, Component Health findings. None → skip to State Update. Any → follow branches.md § Candidate processing exactly (it is normative; this summary is orientation) — read the file now only if step 3b's skill-correction:* branch didn't already load it earlier this run:
current-session needs 1 session; Tier-1 archived and Tier 2/3 need 2+ distinct archived sessions; artifact-cited efficiency/cost candidates cite a machine-written state file (Artifact: line, Sessions: none); procedure capture has an ephemerality exception. Failing candidates go sub-threshold to the ledger.claude-code-hermit:reflection-judge batch (dedup by title-slug first), then one batched claude-code-hermit:proposal-triage call before any queue/create; unrecognized gate output fails closed (gate-failed metric + Progress Log note; re-surfaces next cycle). Tier 1/2 → micro-approval queue (state/micro-proposals.json); Tier 3 → /claude-code-hermit:proposal-create; Evidence Origin: external-content is always Tier 3 (quarantine). Runner routine_candidates are Tier 1 (pre-rendered diagnostic shell_findings_line entries go straight to Findings, no gates); procedure_candidates route through branches.md § Procedure capture (dedup guard, brief, ## Skill Draft, kill criteria).pattern label, "source":"reflect-noticed", "origin":"own-work" — or "origin":"external-content" when the finding carries an [origin: external] marker (copy, never infer). Reuse exact labels; grouping is string equality. Phase surfacing: newborn logs Noticed: lines, juvenile emits a weekly digest (sets last_digest_at), adult is silent.After each reflection run:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/update-reflection-state.ts \
.claude-code-hermit/state/reflection-state.json \
'{"last_resolution_check":"<last-PROP-NNN-or-null>","ran_with_candidates":<true|false>,"judge_accept":<N>,"judge_downgrade":<N>,"judge_suppress":<N>,"judge_suppress_by_code":{"no-evidence":<N>,"no-sessions":<N>,"covered-by-memory":<N>},"proposals_created":<N>,"micro_proposals_queued":<N>}'
judge_suppress_by_code counts judge SUPPRESS verdicts by canonical code; omit zero-count codes, omit the key when judge_suppress is 0. Add "last_digest_at":"<now ISO>" only when a juvenile digest fired. Add "last_behavior_digest_at":"<now ISO>" whenever the behavior phase fired (step 3a) — this advances its weekly cursor; omit it otherwise. Add "last_sparse_nudge":{"<PROP-NNN>":"<now ISO>"} when the runner returned a non-empty last_sparse_nudge map (the script merges it). The script handles counters, timestamps, since preservation, and atomic write; always exits 0. Counters are diagnostic, not audit-grade.
On every run reaching this point (not an EMPTY verdict — the precheck logs those), append to SHELL.md ## Progress Log:
[HH:MM] reflect (<phase>) — N candidates; verdicts: accept=A downgrade=D suppress=S; outcomes: <list or "none">
When suppress>0, append ; suppressed: [<slug>: <code>, ...] — canonical codes from the judge/triage verdicts (no-evidence, no-sessions, weak-recurrence, weak-consequence, not-actionable), capped at 3 with +N more. <phase> is newborn/juvenile/adult (step 4; missing-since fallback annotates adult silently). This is the audit trail — the silent-by-default rule governs operator pings only; the log line always goes in.
tools
Composes and delivers the daily fitness brief — a forward-looking morning read (readiness + today's plan) or a backward-looking evening read (today's training, or an earned-rest note, + tomorrow's setup) — in the operator's configured voice. Invoke with /claude-code-fitness-hermit:fitness-brief --morning|--evening|--slot <name>. Becomes the plugin's two daily beats — the morning Strava connectivity check and the evening activity sync, RPE binding, and Run deep-dive.
development
Renew the hermit's long-lived Claude login token over the channel, before it expires. Relays a one-time sign-in link to the operator, takes the code back, installs the new token, and restarts. Activates on messages like 'relogin', 'renew my login', 'reauth', 'the login is expiring', or when doctor's credential-expiry check flags setup-token.
development
Synthesizes the past 7 days of archived briefs into a weekly digest — top stories, emerging vs faded themes, category activity, and per-source performance built from archive frontmatter. Delivers to the operator's configured channel and archives a weekly note. Designed as a weekly routine. Invoke with /feed-hermit:weekly-digest.
development
Manage developing story arcs tracked across briefs — add, resolve, and list active arcs in compiled/story-arcs-*.md. Arc Watch keywords drive the feed-brief arc-tagging enrichment. Invoke with /feed-hermit:story-arcs add|resolve|list.