Stabilization Phase 4 -- Operator truth and parity¶
Problem statement¶
Operators cannot trust CLI output, config writes, or docs to reflect effective runtime state. Standalone daemon mode diverges from REST-embedded mode for budget and profiles. Dead config keys and MCP trust boundaries are undocumented.
Exact files and functions¶
| Finding | Location | Label |
|---|---|---|
| Budget CLI requires REST | src/hive/cli/main.py budget/status commands |
Verified defect |
| Standalone start enforces budget | src/hive/daemon/loop.py, budget.py |
Correct; CLI view missing |
| Config writes hide reload metadata | cli/main.py config set; server/routes/system.py PATCH |
Verified defect |
| Effective vs persisted vs live conflated | Phase G partial; CLI still unclear | Verified defect |
| Profile path mismatch | cli/main.py Path.cwd() / "profiles" vs agents/profile.py default_profiles_dir() |
Verified defect |
| Heartbeat CLI override overwritten | heartbeat.py disk reload on first tick |
Verified defect |
Dead keys event_poll_interval, watch_refresh_rate |
src/hive/config.py |
Verified defect (dead config) |
logs_dir unused at runtime |
Config vs hardcoded log paths in daemon | Verified defect |
| MCP smaller control surface | mcp/server.py vs REST routes |
By design; docs wrong |
| Doctor missing diagnostics | cli/main.py doctor command |
Verified defect |
| Config reload security | Phase G restart-required matrix | Not a bug -- improve visibility only |
Scope¶
- Standalone budget status/reset without REST.
- Unified profile directory resolution (CLI, daemon, REST, MCP).
- CLI + REST expose effective / persisted / live config and reload status.
- Heartbeat override semantics documented; fix or explicit "ignored after reload" warning.
- Wire or remove dead config keys; wire
logs_diror mark deprecated. - MCP trusted-host documentation; doctor extensions for stale PID, budget, plugins.
Non-goals¶
- Hot-rebuilding guardrails/tools on config PATCH (restart-required stays correct).
- Full REST == daemon toolkit parity (Phase 5 secure-minimal factory).
- MCP feature parity with REST.
- Rewriting all operator docs (targeted updates only).
Implementation slices¶
Slice 4.1 -- Standalone budget commands¶
hive budget statusreadsBudgetTrackerfrom running standalone daemon state file or hive dir persist JSON.hive budget resetwrites persist file + optional running daemon notify hook.- Parity tests: standalone vs REST embedded same numbers after spend.
Slice 4.2 -- Profile directory unification¶
- Single resolver:
default_profiles_dir()withHIVE_PROFILES_DIR/ config override. - Replace
Path.cwd() / "profiles"incli/main.pystart/spawn. - Test: spawn from non-cwd hive root finds profiles.
Slice 4.3 -- Config truth surfaces¶
hive config show --effective|--persisted|--live(or subcommands).- REST
GET /configreturns{ persisted, live, restart_required_fields[] }. - PATCH response includes
applied: hot|restart_requiredper key (extend Phase G). - CLI prints warning when changed keys require restart.
Slice 4.4 -- Heartbeat override semantics¶
- Document: constructor/
hive start --heartbeatapplies until firstget_config()disk reload. - Option A: persist heartbeat to config on CLI start.
- Option B: warn on mismatch after reload.
- Pick one; test documented behavior.
Slice 4.5 -- Dead config keys and logs_dir¶
- Grep consumers for
event_poll_interval,watch_refresh_rate; remove or wire to wake loop. - Wire
logs_dirinHiveDaemon/RunLogWriteror deprecate with migration note. - Update config tables in
docs/getting-started/cli-quickstart.md.
Slice 4.6 -- MCP trust documentation¶
- Add section to
docs/guide/daemon-mode.mdor new MCP page: stdio == trusted local operator, not network auth. - Fix architecture diagrams implying MCP == full control plane.
Slice 4.7 -- Doctor diagnostics¶
- Extend
hive doctor: stale PID file, duplicate daemon hint, budget persist readable, plugin load errors, profile dir exists. - Non-zero exit when critical issues found.
Acceptance criteria¶
uv run pytest tests/cli/test_cli.py tests/test_config.py -v
uv run pytest tests/test_daemon_setup.py -v
uv run mkdocs build --strict
- [x]
hive budget statusworks with standalone daemon (no REST). - [x] CLI and REST spawn same profile from package
profiles/. - [ ] Config PATCH shows restart-required for guardrails/budget keys.
- [ ] Doctor detects stale PID and reports budget state path.
- [ ] Dead keys removed or wired; docs match.
Status: BLOCKERS CLEARED (B1–B3, 2026-07-25) — profile resolver unified, budget CLI/REST ledger parity, daemon status ledger fallback. Remaining slices (4.3–4.7) open.
Re-verification (2026-07-25): VERIFIED — 127 targeted tests, 1857 full, 243 adversarial; B1 resolve_profiles_dir unified, B2 budget 503 ledger fallback + REST/ledger parity, B3 optional logs_dir wiring.
Regression matrix (Hardening A--G)¶
| Phase | Check |
|---|---|
| G | Reload contract extended, not contradicted |
| D | Budget persist path unchanged except CLI read access |
| F | Secure profile template still valid |
Rollback / compatibility¶
- Profile path change may affect users with cwd-relative
./profilesonly -- documentprofiles_dirconfig. - New CLI flags additive only.
Dependencies¶
- Phase 0 -- baseline green.
- Phase 2 -- budget persist path stable for standalone budget commands.
Risks and YAGNI cuts¶
| Risk | Mitigation |
|---|---|
| Reading budget from file while daemon running | Document read-only snapshot; optional IPC later |
YAGNI: Full config UI; hot plugin reload; MCP auth layer.
Finding labels¶
| Finding | Label |
|---|---|
| Budget CLI REST-only | Verified defect |
| Profile path split | Verified defect |
| Config reload drops security silently | Not a bug (restart-required correct) |
| MCP network auth expected | Risk / hypothesis (docs gap) |
| Dead config keys | Verified defect |