| id |
type |
title |
status |
decided |
workplan_task |
deciders |
related |
| RMGR-ADR-001 |
architecture-decision-record |
Implementation foundation for Repo Manager |
accepted |
2026-08-09 |
RMGR-WP-0001-T04 |
|
| docs/repository-representation_v0.1.md |
| docs/observation-command-contracts_v0.1.md |
| docs/state-hub-extraction-inventory_v0.1.md |
| INTENT.md |
|
ADR-001: Implementation foundation for Repo Manager
Status
Accepted (2026-08-09).
Context
RMGR-WP-0001 requires a runtime, persistence, packaging, migration, test, and
deployment shape before substantial extraction from State Hub (T03 phases
P0–P5, T05 E2E). Choices must match ordinary HelixForge services so dual-run,
operators, and agents do not face a one-off stack.
Reference platforms:
| Repo |
Role |
Stack |
state-hub |
Current repo index + consistency (extract source) |
Python 3.12, FastAPI, SQLAlchemy async, asyncpg, Alembic, uv, FastMCP |
hub-core |
Shared library |
Python 3.12, FastAPI/SQLAlchemy primitives, hatchling |
core-hub |
Production hub runtime |
Same + Docker/k8s |
activity-core |
Schedulers/executors |
Python, FastAPI, SQLAlchemy async, Alembic, Temporal (domain-specific) |
Repo Manager is a functional component (not a domain hub): service + CLI,
own data plane for projections, Git as file authority.
Decision
1. Language and packaging
| Choice |
Decision |
| Language |
Python 3.12+ |
| Layout |
src/repo_manager/ (src-layout, hatchling) |
| Distribution |
Installable package repo-manager / import repo_manager |
| Tooling |
uv + Makefile (fleet norm) |
| Lint (phase 2) |
ruff (align with core-hub when CI lands) |
2. Runtime surface
| Choice |
Decision |
| HTTP API |
FastAPI (async) implementing helixforge.repo-manager 0.1 |
| ASGI server |
uvicorn |
| Settings |
pydantic-settings |
| DTOs |
Pydantic v2 only at API boundary (no ORM leakage) |
| CLI |
Entry point rmgr (repo_manager.cli) — reconcile, register, later command |
| MCP |
Not day-1 — agents keep State Hub / hub-core MCP until dual-run; optional FastMCP adapter in a later WP |
| Schedulers |
None in-process — activity-core calls reconcile HTTP/CLI |
3. Persistence
| Choice |
Decision |
| Database |
PostgreSQL 16 (CNPG/fleet); dedicated DB/schema repo_manager |
| ORM |
SQLAlchemy 2.x asyncio + asyncpg |
| Migrations |
Alembic under src/repo_manager/migrations/ or repo-root migrations/ |
| Metadata |
Own Base — never mix with hub-core or state-hub metadata (isolation) |
| SQLite |
Dev/test only optional via aiosqlite; production is Postgres |
Rationale: Separate DB from State Hub so cutover does not share write
contention or schema ownership. Files remain authority for work records;
Postgres holds registry, index, findings, command/idempotency logs.
4. Git and files
| Choice |
Decision |
| Git operations |
subprocess git (parity with consistency_check extract) |
| Parsing |
Port/adapt SH parsers → repo_manager.parse |
| Writeback |
Same commit evidence rules as contracts (git_sha required) |
Avoid new Git bindings (GitPython) until a concrete need; subprocess matches
extract source and SSH/forge setups already in production images.
5. Events and integration
| Choice |
Decision |
| hub-core dependency |
Optional path/editable for utils only (slug/pagination) if useful; no shared tables |
| NATS |
Optional later — emit HTTP hooks or in-process event bus first; nats-py when hub-core event bus is standard |
| Authz |
Call hub-core policy port when available; dev allowlist scopes for local |
6. Testing
| Choice |
Decision |
| Runner |
pytest + pytest-asyncio (asyncio_mode = auto) |
| Unit |
parsers, transition matrix, DTOs |
| Integration |
Postgres test DB or ephemeral container; git fixtures in tests/fixtures/repos/ |
| Compat |
Suites T-PARSE…T-DUAL-RUN from extraction inventory |
7. Deployment
| Choice |
Decision |
| Container |
Dockerfile (python:3.12-slim + git + openssh-client + uv) modeled on state-hub |
| Local |
make db migrate api / make test |
| Cluster |
Later Helm under railiance (not blocking T05); single replica first |
| Secrets |
DATABASE_URL / policy tokens via env or platform custody — never in repo |
8. Initial package modules (target)
src/repo_manager/
__init__.py
config.py
db.py # engine, session, Base
models/ # private ORM
schemas/ # public Pydantic DTOs
api/ # FastAPI routers
parse/ # workplan/work-record parsers
consistency/ # C-rules engine (extract)
commands/ # command handlers
gitops/ # subprocess git helpers
cli.py
migrations/
tests/
pyproject.toml
Makefile
Dockerfile # with first deployable slice
9. Explicit non-choices
| Rejected |
Why |
| Haskell / IHP |
Retired path; fleet is Python for this class of service |
| Sharing State Hub database long-term |
Confuses authority and cutover |
| Embedding Temporal |
activity-core owns schedules |
| Day-1 full MCP surface |
Dual-run via existing SH tools first |
| Calling Repo Manager a hub |
Taxonomy: functional component |
Consequences
Positive
- Operators and extract PRs stay on known stack.
- Clear dual-run: SH and RM side by side with same Git authority.
- CLI
rmgr reconcile can replace statehub fix-consistency gradually.
Negative / cost
- Another Postgres database and migration chain to operate.
- Temporary dual registration until SH registry is strangler-cut.
Follow-ons
- T05: E2E on
repo-manager itself (or a fixture repo) using P0/P1 slices.
- STATE-WP-0079: point fix-consistency / MCP writebacks at RM adapters.
- Optional: publish OpenAPI for
helixforge.repo-manager 0.1 from FastAPI.
Compliance with prior docs
| Doc |
How this ADR satisfies it |
| REP-0001 |
ORM private; snapshots are DTOs |
| CMD-0001 |
FastAPI + CLI implement observation/commands |
| EXTRACT-0001 |
Phases P0–P2 map to modules above |
Acceptance (T04)