# =============================================================================
# config/hermes.yaml
# -----------------------------------------------------------------------------
# Run configuration for the ALWAYS-ON Hermes runner (hermes.py at the repo root).
# Hermes is "a program you keep ON that scouts, finds skills, improves, and
# reports on a loop" -- a thin, human-gated orchestrator over the deterministic
# vault scripts. Each loop TICK runs ONE cycle, then sleeps interval_minutes.
#
# WHAT HERMES DOES EACH CYCLE (every step is toggled below, runs in order, and
# is wrapped so one failure does NOT kill the loop):
#   a) scout_scaffold : py -3 scripts/scout.py  (scaffold/refresh the day's
#                       report + registry diff; it SKIPS an existing report
#                       unless --force, so a filled report is never clobbered).
#   b) llm_fill       : if a headless agent CLI is available AND llm.enabled AND
#                       not --scaffold-only, invoke it with the FIXED Hermes
#                       prompt (docs/HERMES.md "Fixed operating prompt") to do
#                       the find-skills / summarize / improve brain-work. This
#                       step can NEVER approve / install / publish.
#   c) lint           : py -3 scripts/lint_vault.py (record pass/fail; a FAIL
#                       skips the commit step and flags for a human).
#   d) commit         : DEFAULT OFF. Only if auto_commit AND lint passed AND not
#                       --dry-run: git add -A && git commit with a [hermes] msg.
#                       NEVER git push unless allow_push AND --allow-push.
#   e) report         : write _private/hermes/status.json + append hermes.log.
#                       _private is gitignored, so logs never get committed.
#
# GLOBAL POLICY REMINDER (mirrors CLAUDE.md / README / docs/HERMES.md -- the SAFE
# posture is baked into hermes.py as hard guardrails, not just these defaults):
#   default private; NEVER auto-publish; NEVER auto-promote a skill to approved
#   (candidate/watch_only only); NEVER auto-install plugins/MCP/packages; NEVER
#   move private -> public; NEVER git push without the explicit double-gate.
#   Anything trust-sensitive HALTS and waits for a human.
#
# YAML SUBSET: 2-space indent, block maps/seqs, plain/quoted scalars, empty
# collections only as inline [] / {}. No anchors/flow maps/folding.
# =============================================================================

version: 1
updated: 2026-06-23

# --- Loop cadence ------------------------------------------------------------
# interval_minutes : sleep between cycles in the 'run' loop. Default 1440 = once
#                    per day, matching the daily Scout cron in docs/HERMES.md.
# max_cycles       : 0 = run forever (until SIGINT / Ctrl-C / a 'stop' sentinel).
#                    Any positive N = stop cleanly after N cycles (handy for
#                    testing, e.g. `py -3 hermes.py run --once-config ...`).
interval_minutes: 1440
max_cycles: 0

# --- Cycle steps -------------------------------------------------------------
# Toggle each pipeline step on/off. Order is fixed in code (a -> e); these flags
# only decide whether a step runs. 'commit' is OFF by default: Hermes writes and
# reports, but does NOT mutate git history unless you opt in (see auto_commit).
steps:
  scout_scaffold: true    # a) refresh today's report + registry diff (safe, idempotent)
  llm_fill: true          # b) headless agent brain-step (skipped if no CLI / disabled / --scaffold-only)
  lint: true              # c) validate the vault; gate the commit on a clean lint
  commit: false           # d) OFF by default -- see auto_commit below
  report: true            # e) always write status.json + append hermes.log

# --- Commit / push (TRUST-SENSITIVE -- both OFF by default) -------------------
# auto_commit : when true AND lint passed AND not --dry-run, Hermes runs
#               `git add -A && git commit -m '[hermes] ...'` locally. Even ON, a
#               failed lint or --dry-run suppresses the commit. Leave OFF unless
#               you explicitly want autonomous local commits.
# allow_push  : NEVER pushed unless this is true AND the operator also passes
#               --allow-push on the command line (double-gate). Default false so
#               nothing ever leaves the machine automatically. Hermes never
#               touches a public channel regardless of this flag.
auto_commit: false
allow_push: false

# --- LLM / agent step (the "find skills / improve" brain) --------------------
# Hermes detects a headless agent CLI via shutil.which(<the program in
# command_template>). If found AND enabled AND not --scaffold-only, it runs the
# CLI as a subprocess, passing the EXACT fixed operating prompt from
# docs/HERMES.md (Hermes does NOT paraphrase it). The CLI's stdout/stderr is
# captured into hermes.log. This step is sandboxed by policy: it may collect raw,
# summarize, and register candidate/watch_only skills, but it can NEVER approve a
# skill, install tooling, or publish -- those halt for a human.
#
# command_template : how to invoke the agent headless. '{prompt}' is replaced
#                    with the fixed Hermes prompt at run time (shell-quoted by
#                    hermes.py). Example shapes:
#                      'claude -p {prompt}'
#                      'claude --print --permission-mode plan -p {prompt}'
#                    Keep it READ-MOSTLY / planning-oriented; the guardrails in
#                    hermes.py are the real backstop, not this string.
# timeout_seconds  : hard cap on the agent subprocess so a hung CLI cannot stall
#                    the loop. On timeout the step is logged as failed and the
#                    loop continues to lint/report.
llm:
  enabled: true
  command_template: 'claude -p {prompt}'
  timeout_seconds: 900

# --- State + logs (under _private, which is gitignored) ----------------------
# status_file : machine-readable last-run record (cycle count, timestamps,
#               per-step results, lint pass/fail). `py -3 hermes.py status`
#               prints this. Created on first run (mkdir parents, exist_ok).
# log_file    : human-readable append-only line log. Also gitignored (*.log).
status_file: _private/hermes/status.json
log_file: _private/hermes/hermes.log

# --- Notifications -----------------------------------------------------------
# Discord digest after a cycle (counts, notable signals, pending candidates,
# anything awaiting human approval). We store ONLY the ENV VAR NAME that holds
# the webhook URL -- never the secret itself. hermes.py reads os.environ[name]
# and posts only if it is set; the digest links file paths and publishes nothing.
discord_webhook_env: KARNEL_DISCORD_WEBHOOK
