repo-manager/docs/adr-001-implementation-foundation.md
tegwick e02f5a258a docs(RMGR-WP-0001): complete T04 implementation foundation
Accept ADR-001: Python 3.12, FastAPI, Postgres/SQLAlchemy async, src layout,
uv/hatchling, pytest. Scaffold package, rmgr CLI stub, and version tests.
2026-08-09 22:41:26 +02:00

182 lines
6.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
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