chore: scaffold M0 — repo structure, ADRs, dev environment, pre-merge checklist

This commit is contained in:
2026-08-02 10:26:49 +02:00
commit 581191e93a
20 changed files with 781 additions and 0 deletions
+16
View File
@@ -0,0 +1,16 @@
# ADR-NNN: <Short decision title>
**Status:** Proposed | Accepted | Superseded by ADR-XXX
**Date:** YYYY-MM-DD
## Context
What problem are we solving? What forces are at play (constraints, requirements, tradeoffs)?
## Decision
What did we decide, stated as a plain sentence.
## Consequences
What becomes easier or harder because of this. What we're explicitly giving up. What we'd need to revisit this decision.
@@ -0,0 +1,23 @@
# ADR-001: Backend language and framework
**Status:** Accepted
**Date:** 2026-08-02
## Context
The Backend API (see founding strategy, Section 3) is the single source of domain logic for the whole platform: it orchestrates the Knowledge Agent, the Execution Guard, and every integration connector. It needs to be comfortable talking to Qdrant, Postgres, Redis, and local/cloud LLM providers, and needs to be maintainable by a single developer over a period of years.
The existing AI stack (Ollama, Qdrant tooling, most LLM/RAG libraries) is Python-centric. Alternatives considered: Go (excellent for infra tooling, but a weaker ecosystem for RAG/embedding work and a steeper day-to-day lift for solo AI-focused development), TypeScript/Node (strong for the n8n/webhook side of things, but would mean maintaining two primary languages across backend and glue layers).
## Decision
The Backend API is built in **Python**, using **FastAPI**.
FastAPI gives us API-first development for free (automatic OpenAPI schema generation, which keeps `docs/api/` honest), async support for talking to multiple I/O-bound systems (Qdrant, Postgres, Docker/Proxmox APIs) without extra ceremony, and direct access to the Python AI/RAG ecosystem the rest of the stack already lives in.
## Consequences
- One primary language across backend, agents, and integrations — reduces context-switching for a solo developer.
- n8n workflows remain thin glue (per founding strategy, Section 1.2) calling this API; language choice here doesn't constrain n8n.
- We accept Python's weaker raw performance vs. Go for CPU-bound work — acceptable, since this platform is I/O-bound (API calls, DB queries, LLM calls), not compute-bound.
- Revisit only if a specific component (e.g. a high-throughput execution guard under heavy load) demonstrably needs a different runtime — not a whole-platform decision to reopen lightly.
@@ -0,0 +1,26 @@
# ADR-002: Docs → Qdrant sync strategy
**Status:** Accepted (default recommendation — flag in review if you want polling instead)
**Date:** 2026-08-02
## Context
The Knowledge Ingestion Service (founding strategy, Section 3) needs to keep Qdrant's embeddings in sync with source documents (Docker Compose files, Markdown docs, configs) living in Gitea. Two options:
- **Polling:** the Ingestion Service periodically checks Gitea for changes and re-syncs.
- **Webhook:** Gitea pushes a notification to the Ingestion Service on every relevant commit, triggering an immediate re-sync.
Polling is simpler to build first (no inbound endpoint, no webhook secret to manage) but introduces staleness by design — the exact problem flagged in the founding strategy, Section 1.5 ("knowledge freshness" as a first-class requirement). Webhook-based sync is barely more work at this scale (Gitea supports repository webhooks natively) and directly serves the freshness requirement.
## Decision
Use a **Gitea webhook** on relevant repositories, calling a Backend API endpoint that triggers re-ingestion of the changed files. Every ingested chunk stores a `last_synced_at` timestamp sourced from the commit, surfaced in every Knowledge Agent answer (per Section 1.5).
A lightweight periodic reconciliation job (e.g. once daily) remains as a safety net in case a webhook delivery is missed — this is not the primary mechanism, just a backstop.
## Consequences
- Requires a webhook secret to be configured and kept out of version control (`.env`, never committed).
- Ingestion Service needs an inbound endpoint reachable from Gitea — trivial on the same homelab network, worth remembering if Gitea and the platform ever live on separate networks.
- Freshness timestamps become a real, enforceable product feature from day one rather than an afterthought.
- If webhook reliability becomes a problem in practice, the daily reconciliation job already covers the failure mode — no redesign needed, just tune its frequency.
@@ -0,0 +1,25 @@
# ADR-003: Deployment strategy
**Status:** Accepted
**Date:** 2026-08-02
## Context
We need a way to get merged code running on real infrastructure. Options considered: a Gitea Actions CI/CD pipeline, a fully manual deploy process, or a dedicated deployment platform. The project owner already runs (or intends to run) **Coolify** in the homelab, and wants it as the long-term deployment mechanism: Coolify connects to Gitea via webhook, and automatically pulls, builds, and deploys on merge to the appropriate branch.
Building a full CI pipeline (lint, test, build, deploy stages) now, before there is any application code to test, would be effort spent on tooling with nothing yet to validate — directly against the founding strategy's core principle of avoiding infinite runway to real value (Section 1.1).
## Decision
- **Gitea remains the Git source of truth.** All code, config, and IaC live there.
- **Coolify handles build and deployment**, triggered by a webhook on merge to `main`.
- **CI is intentionally deferred.** For M0 and M1, a **manual pre-merge checklist** (`docs/architecture/pre-merge-checklist.md`) substitutes for automated checks. This is a conscious tradeoff, not an oversight — revisit once there's a real test suite worth automating.
- **No staging branch/environment yet.** Given the MVP is read-only (Section 1.5), the blast radius of a bad production deploy is low. Revisit at v0.5, when the Execution Guard starts allowing real write actions against homelab infrastructure (founding strategy, Section 7).
- The repository is structured to be Coolify-ready from day one (separate `docker-compose.prod.yml`, `docs/deployment/`) even though the actual Coolify connection is not made in M0 — there's nothing deployable yet.
## Consequences
- Merges to `main` will, once Coolify is connected, deploy directly to production with no automated gate in between — raises the real stakes of the manual pre-merge checklist; it needs to be used honestly, not treated as a formality.
- We save the time cost of building and maintaining a CI pipeline before there's anything meaningful to run through it.
- We accept slower feedback on regressions until CI is eventually introduced (tracked as a backlog item once a real test suite exists — see roadmap).
- The Coolify connection itself (webhook setup, environment variables) is deliberately out of scope for M0 — it becomes real at the end of M1, once `main` contains a working service worth deploying.