repo-manager/docs/adr-001-implementation-foundation.md

183 lines
6.5 KiB
Markdown
Raw Permalink Normal View History

---
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
P0P5, 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 P0P2 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