plugins/claude-code-hermit/skills/reflect-scheduled-checks/SKILL.md
Standalone routine skill for interval-triggered scheduled checks. Runs one due check, gates findings through reflection-judge + proposal-triage, applies state, and logs. Run as a daily routine — not called by reflect.
npx skillsauth add gtapps/claude-code-hermit reflect-scheduled-checksInstall 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.
Standalone routine skill. Runs at most one due interval-triggered scheduled check per invocation, gates any findings through the normal proposal pipeline, applies state, and appends a Progress Log entry. Invoked by the scheduled-checks routine (daily, offset from reflect).
Any skill registered in config.scheduled_checks that satisfies this contract:
scheduled_checks.interval_days.Read config.json → scheduled_checks (filter to enabled: true, trigger: "interval").
Read state/reflection-state.json → scheduled_checks (per-check state: last_run, last_unavailable_at, last_error_at, consecutive_empty).
From the enabled interval entries, keep those where:
last_run is null or older than interval_days days, ANDlast_unavailable_at is null or older than 4 hours (transient cooldown — skill may have been briefly unavailable), ANDlast_error_at is null or older than interval_days days (persistent back-off for true errors)Select the entry with the oldest last_run (null sorts first). If none are due, skip to the Progress Log (§ 7) with outcome skipped.
Invoke the skill command string as-is, using the Skill tool. Do not "verify installation" first — the harness's loaded-skills list (shown in system-reminders) is authoritative. In particular, never grep ~/.claude/plugins/cache/ or any plugin directory to check whether a plugin is installed — the cache layout is cache/<marketplace>/<plugin>/, not cache/<plugin>/, and assumption-based path checks have produced false-negative unavailable outcomes.
Classify the result:
Skill tool rejects it as unknown → outcome: unavailableoutcome: erroroutcome: actionable, summarize findingoutcome: contextual, summarize finding; apply directly if trivialoutcome: emptyactionable / contextual:
Pass through the Evidence Validation gate:
Candidate: <title derived from finding>
Tier: 1
Evidence Source: scheduled-check/<id>
Evidence: <one-paragraph summary>
Sessions: none
Delegate to claude-code-hermit:reflection-judge. On ACCEPT (scheduled-check) or DOWNGRADE, proceed to claude-code-hermit:proposal-triage with:
Title: <title>
Evidence Source: scheduled-check/<id>
Evidence: <summary>
Parse line 1 as the verdict. 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.
After receiving the verdict, append one event to state/proposal-metrics.jsonl:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/append-metrics.ts \
.claude-code-hermit/state/proposal-metrics.jsonl \
'{"ts":"<now ISO>","type":"triage-verdict","verdict":"<CREATE|SUPPRESS|DUPLICATE>","caller":"scheduled-checks"}'
CREATE → classify tier. Tier 1/2: queue micro-approval (§ Micro-approval queuing). Tier 3: call /claude-code-hermit:proposal-create directly.SUPPRESS or DUPLICATE → drop silently; note in SHELL.md Progress Log.bun ${CLAUDE_PLUGIN_ROOT}/scripts/append-metrics.ts \
.claude-code-hermit/state/proposal-metrics.jsonl \
'{"ts":"<now ISO>","type":"gate-failed","agent":"proposal-triage","title":"<title>"}'
Note gate-failed: proposal-triage — <title> in the SHELL.md Progress Log. The candidate re-surfaces on the next scheduled-checks run.On SUPPRESS from reflection-judge → drop silently. On unrecognized verdict from reflection-judge (malformed/empty output): fail closed — treat as SUPPRESS. Append:
bun ${CLAUDE_PLUGIN_ROOT}/scripts/append-metrics.ts \
.claude-code-hermit/state/proposal-metrics.jsonl \
'{"ts":"<now ISO>","type":"gate-failed","agent":"reflection-judge","title":"<title>"}'
Note gate-failed: reflection-judge — <title> in the SHELL.md Progress Log. The candidate re-surfaces on the next scheduled-checks run.
empty:
No proposal candidate. Increment consecutive_empty counter in state (§ State update). Check interval-adjustment logic (§ Interval adjustment proposals).
unavailable:
Note in SHELL.md ## Findings: Scheduled check skipped: <id> — skill unavailable (cooldown 4h). No candidate.
error:
Note in SHELL.md ## Findings: Scheduled check error: <id> — retrying after interval_days. No candidate.
skipped: No action except Progress Log.
Every micro-proposal question must include: [observed pattern + duration] + [consequence] + [exact proposed change] + "Yes / No"
Queuing procedure:
MP-YYYYMMDD-N where N increments within the same day (0, 1, 2). Check existing micro-queued events in proposal-metrics.jsonl for today to determine N.micro-queued event to proposal-metrics.jsonl first (so a partial failure leaves a recoverable orphaned event, not a silent ghost entry):
bun ${CLAUDE_PLUGIN_ROOT}/scripts/append-metrics.ts .claude-code-hermit/state/proposal-metrics.jsonl <<'HERMIT_METRICS_JSON'
{"ts":"<now ISO>","type":"micro-queued","micro_id":"MP-YYYYMMDD-N","tier":1,"question":"<full question text>"}
HERMIT_METRICS_JSON
state/micro-proposals.json. Append a new entry to pending with id: "MP-YYYYMMDD-N", tier: <1|2>, status: "pending", follow_up_count: 0, ts: "<now ISO>", question: "<full question text>". Write the file.Using the current consecutive_empty value (after update in § State update):
Reset rules:
empty outcome → consecutive_empty += 1actionable / contextual outcome → consecutive_empty = 0Proposals (standard Three-Condition Rule, not tagged scheduled-check):
interval_days (e.g., 7 → 14). Three occurrences = repeated pattern; high interval_days means the check never fires usefully = meaningful consequence; operator approves the config change = actionable. Pass through claude-code-hermit:proposal-triage before creating.Adjustments always go through PROP-NNN — this skill never auto-adjusts.
Write the state delta directly to state/reflection-state.json → scheduled_checks.<id>:
bun -e "
const fs=require('fs');
const f='.claude-code-hermit/state/reflection-state.json';
try {
const s=JSON.parse(fs.readFileSync(f,'utf-8'));
if(!s.scheduled_checks) s.scheduled_checks={};
const id='<check-id>';
if(!s.scheduled_checks[id]) s.scheduled_checks[id]={};
const c=s.scheduled_checks[id];
// Set fields according to outcome — only set fields that should change
// outcome=unavailable: c.last_unavailable_at='<ISO>'; (leave last_run unchanged)
// outcome=error: c.last_error_at='<ISO>'; (leave last_run unchanged)
// outcome=empty: c.last_run='<ISO>'; c.consecutive_empty=<prior+1>;
// outcome=actionable|contextual: c.last_run='<ISO>'; c.consecutive_empty=0;
fs.writeFileSync(f, JSON.stringify(s,null,2)+'\n','utf-8');
} catch(e){ process.stderr.write('scheduled-checks state: '+e.message+'\n'); }
"
Substitute the actual id, ISO timestamp, and field assignments for the current outcome before running. Always exits cleanly — a failed write is logged to stderr only.
Append one line to .claude-code-hermit/sessions/SHELL.md under ## Progress Log:
[HH:MM] scheduled-checks — <id>: <outcome>; verdicts: accept=A downgrade=D suppress=S; outcome: <none|micro-queued|proposal-created|interval-proposal>
Use skipped for the id field and skipped for outcome when no check was due.
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.