phase 1: Go foundation — module, migrations, domain, seed ingest

Core deliverables:
- Go module github.com/dtoro/oikos (Go 1.26.3)
- cmd/oikos: single binary with role subcommands (migrate, seed, export)
- 6 SQL migrations: ontology meta-schema, entity instances (UUID+slug,
  blast_radius recursive function), operations (signals/checks/approvals),
  cognition (classifications/executions/feedback/patterns/skills), policy,
  observability (TimescaleDB hypertables + CAGGs + retention)
- Domain layer: entity, signal, execution, classification, pattern, skill,
  approval, check types + 11 sentinel errors + lifecycle state machines
- DB layer: pgx pool, SQL splitter (handles 94436 and -- comments), migration
  runner, seed ingest (ontology+inventory+policy) with content-hash dedup
- Config: env-based with defaults, secrets redaction
- Observability: slog JSON logger with debug mode
- Infrastructure: Makefile, docker-compose.yml, multi-stage Dockerfile
  (distroless, CGO_ENABLED=0)

Verified end-to-end against timescale/timescaledb:2.17.2-pg16:
- 6 migrations applied (65 SQL statements)
- Seeds ingested: 6 lifecycles, 59 entity types, 46 relationship types,
  111 entities, 144 relationships, 4 risk classes, 27 approval rules,
  9 autonomy settings
- Idempotent: second seed run is a no-op (content hash matches)

Bugs fixed during implementation:
- TimescaleDB CAGGs can't run in a transaction -> splitSQL() executes
  statements individually
- Semicolons in -- comments treated as separators -> comment handling
- YAML keys source/target didn't match code's source_type/target_type
- yaml.Marshal produced YAML for JSONB columns -> json.Marshal
This commit is contained in:
2026-07-07 01:07:26 +02:00
parent 55710bd254
commit aa2ca0ae6f
23 changed files with 1964 additions and 0 deletions

70
docker-compose.yml Normal file
View File

@@ -0,0 +1,70 @@
# Docker Compose for Oikos development
# Usage: docker compose up -d postgres (just the DB)
# make dev (full dev stack)
services:
postgres:
image: timescale/timescaledb:2.17.2-pg16
environment:
POSTGRES_DB: oikos
POSTGRES_USER: oikos
POSTGRES_PASSWORD: oikos_dev
ports:
- "5432:5432"
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD", "pg_isready", "-U", "oikos"]
interval: 5s
timeout: 5s
retries: 5
# One-shot: run migrations then exit
migrate:
build:
context: .
dockerfile: compose/oikos/Dockerfile
depends_on:
postgres:
condition: service_healthy
environment:
OIKOS_DATABASE_URL: postgres://oikos:***@postgres:5432/oikos?sslmode=disable
command: ["migrate"]
restart: "no"
# One-shot: ingest seeds then exit
seed:
build:
context: .
dockerfile: compose/oikos/Dockerfile
depends_on:
migrate:
condition: service_completed_successfully
environment:
OIKOS_DATABASE_URL: postgres://oikos:***@postgres:5432/oikos?sslmode=disable
OIKOS_SEEDS_DIR: /app/seeds
command: ["seed"]
restart: "no"
# API server (Phase 2)
api:
build:
context: .
dockerfile: compose/oikos/Dockerfile
profiles: ["dev", "full"]
depends_on:
seed:
condition: service_completed_successfully
environment:
OIKOS_DATABASE_URL: postgres://oikos:***@postgres:5432/oikos?sslmode=disable
OIKOS_API_LISTEN: ":8090"
OIKOS_ENV: dev
OIKOS_DEBUG: "true"
ports:
- "8090:8090"
command: ["api"]
stop_signal: SIGTERM
stop_grace_period: 30s
volumes:
pg-data: