--- id: RMGR-ADR-001 type: architecture-decision-record title: "Implementation foundation for Repo Manager" status: accepted decided: "2026-08-09" workplan_task: RMGR-WP-0001-T04 deciders: ["codex", "project-convention"] related: - 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) ```text 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) - [x] Runtime chosen (FastAPI/uvicorn, Python 3.12) - [x] Persistence chosen (Postgres + SQLAlchemy async + Alembic, own DB) - [x] Package/layout chosen (src/repo_manager, uv, hatchling) - [x] Test approach chosen (pytest-asyncio + fixtures) - [x] Deploy approach chosen (Docker, make; Helm later) - [x] Non-goals recorded