ADR-0006: RepoRuntime Isolation Architecture¶
Status: Superseded Date: 2026-02-28
Context¶
HydraFlow is fundamentally single-repo per process. Each HydraFlowOrchestrator
owns one IssueStore (deque-based queues), one StateTracker (JSON file), one
EventBus, and 11 async loop tasks. The supervisor (supervisor_service.py)
uses a module-global RUNNERS dict of RepoProcess structs and
subprocess.Popen to spawn per-repo workers. State isolation is implicit via
the filesystem: each repo has its own .hydraflow/ directory.
SessionLog.repo is the only explicit repo-namespaced field.
This implicit isolation model has several drawbacks:
- No formal lifecycle boundary between repos running in the same process.
- Adding in-process multi-repo support requires threading repo identity through every component manually.
- Shared global state (e.g., background loop registries) creates coupling between repos that should be independent.
Decision¶
Introduce a RepoRuntime abstraction that wraps Orchestrator + StateTracker +
EventBus + IssueStore as a formal isolation boundary. Each repo slug gets one
RepoRuntime instance that owns its full mutable runtime state.
Key elements:
RepoRuntimeclass bundles per-repo orchestrator, state tracker, event bus, issue store, and worker pools into a single lifecycle unit.RepoRuntimeRegistrymanages runtime creation, lookup by slug, and graceful shutdown ordering.- CLI entry point (
cli.py) constructs aRepoRuntimeinstead of manually assembling individual services. - Supervisor integration uses
RepoRuntimeas the unit of start/stop rather than rawsubprocess.Popen.
Consequences¶
Positive:
- Explicit lifecycle boundary makes multi-repo support tractable.
- Per-repo state is fully encapsulated — no shared globals between repos.
- Graceful shutdown can drain one repo without affecting others.
- Testing becomes simpler: instantiate a RepoRuntime with test config.
Trade-offs:
- One additional abstraction layer between CLI and orchestrator.
- Existing single-repo users see no behavior change but get a new code path.
- Migration requires refactoring cli.py and supervisor service.
Alternatives considered¶
- Keep implicit isolation via subprocess boundaries. Rejected: limits in-process multi-repo support and makes shared dashboard proxying complex.
- Thread repo slug through all components without a wrapper. Rejected: high coupling, error-prone, and every component needs repo awareness.
Related¶
- Superseded by: ADR-0009 (Multi-Repo Process-Per-Repo Model)
- Source memory: #1615
- Implementation: #1467
src/orchestrator.py,src/state.py,src/issue_store.py,src/events.pysrc/hf_cli/supervisor_service.py