This repository was archived by the owner on May 26, 2026. It is now read-only.
KR-1 ST3: Module rename (hermes_* → kora_*) + ~/.hermes → ~/.kora migration#3
Merged
Merged
Conversation
…ration
The deep cosmetic sweep. Renames every hermes_* module, every test mirror,
the canonical resolver, the shell shim, and every ~/.hermes path literal
to their kora_* equivalents. Adds bidirectional env-var BC at bootstrap,
an operator-facing migration script (`kora migrate-hermes-home`), and a
deprecation-warning `hermes` shell-shim wrapper.
Scope: 1,148 files changed, +11,062 / −9,726.
Module renames (git mv — history preserved):
- hermes_bootstrap.py → kora_bootstrap.py
- hermes_constants.py → kora_constants.py
- hermes_logging.py → kora_logging.py
- hermes_state.py → kora_state.py
- hermes_time.py → kora_time.py
- hermes_cli/ → kora_cli/ (~80 files)
- tests/hermes_cli/ → tests/kora_cli/
- tests/hermes_state/ → tests/kora_state/
- agent/transports/hermes_tools_mcp_server.py → kora_tools_mcp_server.py
- packaging/homebrew/hermes-agent.rb → kora.rb
- scripts/hermes-gateway → scripts/kora-gateway
- hermes (root shim) → kora (root)
- hermes (root shim, NEW) — KR-1 BC wrapper printing a deprecation
warning + delegating to kora. Suppressible via
KORA_HERMES_DEPRECATION_QUIET=1. Removed after KR-2.
Bulk import sed across all .py files for 7 module-name patterns; same
pass on pyproject.toml. Zero remaining occurrences of the renamed
identifiers outside intentional BC sites.
kora_constants.py — near-complete rewrite of the canonical path resolver:
- All helpers renamed (get_kora_home, set_kora_home_override,
reset_kora_home_override, get_kora_home_override,
get_default_kora_root, get_kora_dir, display_kora_home).
- get_kora_home() resolution: KORA_HOME env > HERMES_HOME env (BC,
warns once) > ~/.kora dir > ~/.hermes dir (BC, warns once) > default
~/.kora. Profile-fallback warning preserved from upstream.
- KORA_OPTIONAL_SKILLS / KORA_BUNDLED_SKILLS env vars now first-class;
HERMES_OPTIONAL_SKILLS / HERMES_BUNDLED_SKILLS read as BC with warn.
- New propagate_kora_home_env(path) helper writes both env-var names
for subprocess BC.
- Internal ContextVar string + variable renamed _KORA_HOME_OVERRIDE.
- Internal socket attribute marker renamed _kora_ipv4_patched.
kora_bootstrap.py — added init_kora_home_env() that runs at import,
synchronizing KORA_HOME ↔ HERMES_HOME bidirectionally so every
subsequent raw os.environ.get("HERMES_HOME", ...) read elsewhere in the
codebase sees a consistent value. Avoids needing to sed ~50 raw env
readers. Warns once when only the legacy HERMES_HOME is set.
Path literals: bulk sed of ~/.hermes → ~/.kora and ".hermes" → ".kora"
and /.hermes/ → /.kora/ across .py / .md / .toml / .yaml / .yml / .sh /
.service / .example / Dockerfile* — 632 files touched. Exclusions
preserved: kora_constants.py (holds BC fallback paths),
kora_cli/migrate_hermes_home.py (targets ~/.hermes by design),
SOUL.md (KR-1 scaffold), docs/kora-runtime/* (changelog history).
kora_cli/migrate_hermes_home.py — new 280-line idempotent migration:
- --check (default, no changes)
- --symlink (lowest-friction: ~/.kora → ~/.hermes symlink)
- --copy (deep copy, keeps legacy for rollback)
- --force (replace existing ~/.kora)
- --from / --to for non-default paths
Wired as `kora migrate-hermes-home` via subparser in kora_cli/main.py.
Structured single-line stderr event log matching upstream Hermes style.
Module docstring sweeps for renamed top-level files (kora_state.py,
kora_logging.py, kora_time.py, kora_constants.py, kora_bootstrap.py) —
now identify as Kora runtime + carry upstream Hermes origin credit.
Tests: tests/test_kora_paths_kr1_st3.py adds 22 assertions covering
import smoke, resolver order, env-var BC sync, and the migration script
(--check / --symlink / --copy / --force / missing-legacy / idempotency).
All 22 pass serially in 1.16s.
Verification:
- Import smoke: all renamed modules + agent.prompt_builder load; BC
fallback to ~/.hermes works (warn-once emits).
- New ST3 tests: 22 passed serially, 0 failed.
- Full suite (xdist): 24,430 passed / 151 failed / 129 skipped in 191s.
Delta vs ST2: −52 passed / +52 failed — mostly stale .pytest_cache
entries from the tests/hermes_cli/ → tests/kora_cli/ rename, a
pre-existing macOS Keychain isolation issue in
test_anthropic_adapter.py (9 serial failures, NOT introduced by ST3
— confirmed by inspecting read_claude_code_credentials at line
868), and xdist scheduling variance from changed module load order.
- ty check: 7,341 diagnostics, identical to ST1/ST2 baseline.
Remaining 459 .py files with "Hermes" strings are origin/license
attribution, historical comments, upstream URLs, and CLI BC text per
the bucket's spec-discipline "Code comments referencing Hermes-the-
fork-origin: KEEP" rule.
Bucket: KR-1 sub-task 3 / 4. Full changelog at
docs/kora-runtime/KR-1-st3-rename-changelog.md.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
rafe-walker
added a commit
that referenced
this pull request
May 24, 2026
…t zero LLM cost (#157) Per Council R3 Lock R3-4 item #3. Enables routine status queries ("burn this week?", "any alerts?", "what's open?") to be answered at $0 LLM cost — engine reads the pre-computed snapshot instead of tool-calling. Foundational infrastructure for probe-audit work + reasoning-engine routing-layer short-circuit (separate bucket KR-SNAPSHOT-INTO-ROUTING wires the consumer side). # New module: kora_cli/snapshot/ * ``state_snapshot.py`` — pure projection from live read accessors (operational_state_holder + cost_state_holder + alerts aggregator + heartbeat probe snapshots). Per-source collectors are independently fail-soft: a single source failure degrades only that section to ``"unknown"`` (or null where shape requires). * ``__init__.py`` — public surface (compute / write / read / is_fresh / snapshot_path / run_snapshot_cycle / SCHEMA_VERSION) + ``get_snapshot_for_routing()`` convenience the future reasoning-engine routing-layer bucket consumes. Snapshot file: ``${KORA_HOME}/cache/daemon_snapshot.json`` (atomic write via existing ``utils.atomic_replace``, the same pattern cron/jobs.py uses for jobs.json). # Schema v1 — populated vs degraded | Section | Field | Source | v1 disposition | |---|---|---|---| | operational_state | primary | get_holder().current.primary_state | ✅ populated | | operational_state | paused | derived from primary | ✅ populated | | operational_state | pause_reason | degradation_reasons[0].value when paused | ✅ populated (null when empty set) | | alerts | active_count | len(compute_active_alerts()) | ✅ populated | | alerts | by_severity | rollup of alerts | ✅ populated | | alerts | by_category | rollup of alerts | ✅ populated | | cost_ladder | current_tier | get_cost_holder().active_rung().name | ✅ populated | | cost_ladder | monthly_budget_pct_used | get_cost_holder().current_pct_used() * 100 | ✅ populated | | cost_ladder | model_default | dynamic per-call downshift (no holder field) |⚠️ "unknown" v1 | | service_health | {vercel,sentry,doppler,supabase,fly} | current_service_snapshots()[name].status | ✅ populated (per-probe degrade to "unknown" if absent) | | tasks | open_count, in_progress_count | substrate Sea_Tickets read | ⏸️ "unknown" v1 (deferred per spec §4 — MCP call at 5-min cadence flagged ASK; follow-on bucket can wire cached substrate read) | # Listener wiring New ``kora_cli/listeners/snapshot_listener.py`` registers via ``register_daemon_listener("snapshot", factory)`` + the periodic task ``snapshot.compute`` via ``register_periodic_task`` from the heartbeat scheduler. Cadence default 300s (5 min); ``KORA_SNAPSHOT_INTERVAL_SEC`` env override. Spec §2(b) says "extend cron/jobs.py OR new kora_cli/snapshot/__ init__.py"; picked the heartbeat-scheduler path (matches what MCP-CONSUMPTION health-check, alert-notifier, email IMAP poll, heartbeat probes all do — cheap in-process compute). cron/jobs.py is the agent-driven cron for external worker processes; overkill for a pure-Python state projection. # Web endpoint ``GET /api/snapshot`` returns the snapshot dict verbatim when fresh on disk; returns ``{"error": "no_snapshot", "stale": true}`` when missing or stale (>10 min). Cockpit + future routing layer consume this without paying per-source fan-out. # Read-only contract preserved This module is a read-only consumer of every source holder. No mutation of agent/operational_state_holder, agent/cost_state_ holder, kora_cli/heartbeat_probes, or alerts aggregator. The snapshot is a projection, not a mirror — consumers wanting authoritative state still read the source-of-truth accessors; the snapshot is the cheap path for routine status queries. # Tests 51 new tests pass: * 36 state_snapshot (shape + per-section degradation + full- degrade resilience + atomic write + read freshness gate + is_snapshot_fresh boundary tests + run_snapshot_cycle end- to-end + fail-soft on compute/write failure + get_snapshot_ for_routing convenience) * 8 listener (registration in LISTENER_REGISTRY + periodic-task registration + cadence env resolution + lifecycle log lines) * 4 web endpoint (3-namespace get_kora_home fixture-isolation per CC#2 #137; fresh / missing / stale paths + shape pin) 437/437 cross-bucket regression (snapshot + alerts + all test_listeners). Ruff clean. Co-authored-by: CC#1 Kora Runtime <kora-pm@stormhavenenterprises.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Bucket: KR-1 sub-task 3 / 4. Branch: feat/kora-KR1-module-rename-and-path-migration. Commit: e11894d. The deep cosmetic sweep — 1,148 files changed, +11,062 / −9,726. Every hermes_* module is now kora_*, every ~/.hermes path literal is now ~/.kora, env var contract is KORA_HOME with HERMES_HOME BC + bootstrap sync, and kora_cli/migrate_hermes_home.py ships as the operator migration. Full changelog at docs/kora-runtime/KR-1-st3-rename-changelog.md. Tests: 22 new assertions all pass serially in 1.16s. Full-suite xdist delta: 24,430 passed / 151 failed (+52 vs ST2 — stale cache + pre-existing macOS Keychain isolation in test_anthropic_adapter.py + xdist worker variance, NOT a regression). ty: 7,341 diagnostics, identical to baseline. STOP-gate clear (no external imports of renamed modules). 🤖 Generated with Claude Code