FORGED Session
CORE Build Engine — Zentraler Build-Agent fuer XXBILLION. Orchestriert den kompl...
DEEP
SCOPE EINGEFROREN
R1
R2
R3
Gap
R4
Scope
Tech-Spec
Naechster Schritt
Der Scope und die technische Spezifikation sind eingefroren. Jetzt geht es weiter mit dem Build — lade den Scope herunter und starte den Build-Prozess.
Technische Spezifikation
xxbillion-core-build-engine
Port 5600
{'language': 'Python 3.10', 'framework': 'Flask 3.x', 'server': 'gunicorn', 'database': 'SQLite 3 (WAL)', 'templating': 'Jinja2', 'frontend': 'Vanilla HTML + minimal CSS, no SPA', 'realtime': 'Server-Sent Events (SSE)', 'http_client': 'requests', 'git': 'git CLI required on host', 'crypto': 'hmac + hashlib (HMAC-SHA256)', 'schema_validation': 'jsonschema', 'logging': 'python logging JSON lines', 'migrations': 'SQLite DDL on startup (idempotent) + schema_version table'}
Datenbank
[
{
"constraints": [
"PRIMARY KEY(version)"
],
"fields": [
{
"name": "version",
"type": "INTEGER NOT NULL"
},
{
"name": "applied_at",
"type": "TEXT NOT NULL"
}
],
"indices": [],
"table": "schema_version"
},
{
"constraints": [
"CHECK(status IN (\u0027new\u0027,\u0027running\u0027,\u0027paused\u0027,\u0027completed\u0027,\u0027failed\u0027,\u0027canceled\u0027,\u0027budget_paused\u0027))",
"CHECK(current_phase BETWEEN 1 AND 14)",
"CHECK(jury_status IN (\u0027none\u0027,\u0027requested\u0027,\u0027running\u0027,\u0027completed_pass\u0027,\u0027completed_fail\u0027,\u0027timeout\u0027))",
"UNIQUE(project_id, spec_version_number)"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "project_id",
"type": "TEXT NOT NULL"
},
{
"name": "created_at",
"type": "TEXT NOT NULL"
},
{
"name": "updated_at",
"type": "TEXT NOT NULL"
},
{
"name": "status",
"type": "TEXT NOT NULL"
},
{
"name": "current_phase",
"type": "INTEGER NOT NULL"
},
{
"name": "active_run_id",
"type": "TEXT NOT NULL"
},
{
"name": "scope_text",
"type": "TEXT NOT NULL"
},
{
"name": "tech_spec_json",
"type": "TEXT NULL"
},
{
"name": "spec_version_number",
"type": "INTEGER NOT NULL DEFAULT 1"
},
{
"name": "forged_idempotency_key",
"type": "TEXT NULL"
},
{
"name": "forged_spec_hash",
"type": "TEXT NULL"
},
{
"name": "budget_hard_limit_cents",
"type": "INTEGER NOT NULL DEFAULT 500"
},
{
"name": "budget_added_cents_total",
"type": "INTEGER NOT NULL DEFAULT 0"
},
{
"name": "budget_spent_cents",
"type": "INTEGER NOT NULL DEFAULT 0"
},
{
"name": "budget_reserved_cents",
"type": "INTEGER NOT NULL DEFAULT 0"
},
{
"name": "last_error_code",
"type": "TEXT NULL"
},
{
"name": "last_error_message",
"type": "TEXT NULL"
},
{
"name": "pause_reason",
"type": "TEXT NULL"
},
{
"name": "service_repo_path",
"type": "TEXT NULL"
},
{
"name": "service_name",
"type": "TEXT NULL"
},
{
"name": "service_port",
"type": "INTEGER NULL"
},
{
"name": "service_health_url",
"type": "TEXT NULL"
},
{
"name": "jury_status",
"type": "TEXT NOT NULL DEFAULT \u0027none\u0027"
},
{
"name": "jury_session_id",
"type": "TEXT NULL"
},
{
"name": "jury_last_completed_at",
"type": "TEXT NULL"
}
],
"indices": [
"idx_sessions_project ON sessions(project_id)",
"idx_sessions_status ON sessions(status)",
"idx_sessions_updated ON sessions(updated_at)"
],
"table": "sessions"
},
{
"constraints": [
"FOREIGN KEY(session_id) REFERENCES sessions(id) ON DELETE RESTRICT",
"CHECK(phase_number BETWEEN 1 AND 14)",
"CHECK(status IN (\u0027queued\u0027,\u0027running\u0027,\u0027paused\u0027,\u0027completed\u0027,\u0027failed\u0027))",
"CHECK(progress_percent BETWEEN 0 AND 100)",
"UNIQUE(session_id, phase_number, run_number)"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "session_id",
"type": "TEXT NOT NULL"
},
{
"name": "phase_number",
"type": "INTEGER NOT NULL"
},
{
"name": "run_number",
"type": "INTEGER NOT NULL"
},
{
"name": "status",
"type": "TEXT NOT NULL"
},
{
"name": "substatus",
"type": "TEXT NULL"
},
{
"name": "started_at",
"type": "TEXT NULL"
},
{
"name": "ended_at",
"type": "TEXT NULL"
},
{
"name": "progress_percent",
"type": "INTEGER NOT NULL DEFAULT 0"
},
{
"name": "required_artifacts_json",
"type": "TEXT NOT NULL"
},
{
"name": "artifact_index_json",
"type": "TEXT NOT NULL DEFAULT \u0027[]\u0027"
},
{
"name": "error_code",
"type": "TEXT NULL"
},
{
"name": "error_message",
"type": "TEXT NULL"
}
],
"indices": [
"idx_phase_runs_session_phase ON phase_runs(session_id, phase_number)",
"idx_phase_runs_status ON phase_runs(status)"
],
"table": "phase_runs"
},
{
"constraints": [
"FOREIGN KEY(session_id) REFERENCES sessions(id) ON DELETE RESTRICT",
"FOREIGN KEY(phase_run_id) REFERENCES phase_runs(id) ON DELETE SET NULL",
"CHECK(level IN (\u0027debug\u0027,\u0027info\u0027,\u0027warn\u0027,\u0027error\u0027,\u0027critical\u0027))"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "session_id",
"type": "TEXT NOT NULL"
},
{
"name": "phase_run_id",
"type": "TEXT NULL"
},
{
"name": "created_at",
"type": "TEXT NOT NULL"
},
{
"name": "level",
"type": "TEXT NOT NULL"
},
{
"name": "event_type",
"type": "TEXT NOT NULL"
},
{
"name": "message",
"type": "TEXT NOT NULL"
},
{
"name": "data_json",
"type": "TEXT NOT NULL DEFAULT \u0027{}\u0027"
}
],
"indices": [
"idx_timeline_session_time ON timeline_events(session_id, created_at DESC)",
"idx_timeline_type ON timeline_events(event_type)"
],
"table": "timeline_events"
},
{
"constraints": [
"CHECK(actor_type IN (\u0027forged\u0027,\u0027mkb\u0027,\u0027jury\u0027,\u0027genesis\u0027,\u0027admin\u0027,\u0027system\u0027))"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "created_at",
"type": "TEXT NOT NULL"
},
{
"name": "actor_type",
"type": "TEXT NOT NULL"
},
{
"name": "actor_id",
"type": "TEXT NULL"
},
{
"name": "action",
"type": "TEXT NOT NULL"
},
{
"name": "session_id",
"type": "TEXT NULL"
},
{
"name": "phase_run_id",
"type": "TEXT NULL"
},
{
"name": "request_id",
"type": "TEXT NULL"
},
{
"name": "ip",
"type": "TEXT NULL"
},
{
"name": "user_agent",
"type": "TEXT NULL"
},
{
"name": "data_json",
"type": "TEXT NOT NULL DEFAULT \u0027{}\u0027"
}
],
"indices": [
"idx_audit_time ON audit_events(created_at DESC)",
"idx_audit_session ON audit_events(session_id)"
],
"table": "audit_events"
},
{
"constraints": [
"CHECK(source IN (\u0027forged\u0027,\u0027mkb\u0027,\u0027jury\u0027,\u0027genesis\u0027))"
],
"fields": [
{
"name": "nonce",
"type": "TEXT PRIMARY KEY"
},
{
"name": "source",
"type": "TEXT NOT NULL"
},
{
"name": "timestamp",
"type": "INTEGER NOT NULL"
},
{
"name": "received_at",
"type": "TEXT NOT NULL"
}
],
"indices": [
"idx_nonces_time ON webhook_nonces(timestamp)"
],
"table": "webhook_nonces"
},
{
"constraints": [
"CHECK(source IN (\u0027forged\u0027,\u0027ui_upload\u0027))",
"CHECK(status IN (\u0027queued\u0027,\u0027processed\u0027,\u0027rejected\u0027))",
"UNIQUE(source, idempotency_key)"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "received_at",
"type": "TEXT NOT NULL"
},
{
"name": "source",
"type": "TEXT NOT NULL"
},
{
"name": "idempotency_key",
"type": "TEXT NOT NULL"
},
{
"name": "project_id",
"type": "TEXT NOT NULL"
},
{
"name": "session_id",
"type": "TEXT NOT NULL"
},
{
"name": "version_number",
"type": "INTEGER NOT NULL"
},
{
"name": "spec_hash",
"type": "TEXT NOT NULL"
},
{
"name": "payload_json",
"type": "TEXT NOT NULL"
},
{
"name": "status",
"type": "TEXT NOT NULL"
},
{
"name": "error_json",
"type": "TEXT NOT NULL DEFAULT \u0027[]\u0027"
}
],
"indices": [
"idx_inbound_specs_project_ver ON inbound_specs(project_id, version_number DESC)",
"idx_inbound_specs_status ON inbound_specs(status)"
],
"table": "inbound_specs"
},
{
"constraints": [
"FOREIGN KEY(session_id) REFERENCES sessions(id) ON DELETE RESTRICT",
"CHECK(phase_number IN (4,6,10,13))",
"CHECK(source IN (\u0027mkb\u0027,\u0027system\u0027,\u0027jury_feedback\u0027))",
"CHECK(status IN (\u0027open\u0027,\u0027completed\u0027))",
"UNIQUE(session_id, phase_number, round_number)"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "session_id",
"type": "TEXT NOT NULL"
},
{
"name": "phase_number",
"type": "INTEGER NOT NULL"
},
{
"name": "round_number",
"type": "INTEGER NOT NULL"
},
{
"name": "created_at",
"type": "TEXT NOT NULL"
},
{
"name": "source",
"type": "TEXT NOT NULL"
},
{
"name": "status",
"type": "TEXT NOT NULL"
},
{
"name": "columns_json",
"type": "TEXT NOT NULL"
},
{
"name": "summary_json",
"type": "TEXT NOT NULL DEFAULT \u0027{}\u0027"
}
],
"indices": [
"idx_checklists_session_phase ON checklists(session_id, phase_number)",
"idx_checklists_status ON checklists(status)"
],
"table": "checklists"
},
{
"constraints": [
"FOREIGN KEY(checklist_id) REFERENCES checklists(id) ON DELETE CASCADE",
"CHECK(anchor_type IN (\u0027symbol\u0027,\u0027file_context\u0027))",
"CHECK(gatekeeper_status IN (\u0027not_run\u0027,\u0027pass\u0027,\u0027fail\u0027))",
"UNIQUE(checklist_id, row_number)"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "checklist_id",
"type": "TEXT NOT NULL"
},
{
"name": "row_number",
"type": "INTEGER NOT NULL"
},
{
"name": "requirement_text",
"type": "TEXT NOT NULL"
},
{
"name": "source_ref",
"type": "TEXT NOT NULL"
},
{
"name": "locked_green",
"type": "INTEGER NOT NULL DEFAULT 0"
},
{
"name": "file_path",
"type": "TEXT NULL"
},
{
"name": "symbol_ref",
"type": "TEXT NULL"
},
{
"name": "anchor_type",
"type": "TEXT NOT NULL DEFAULT \u0027symbol\u0027"
},
{
"name": "anchor_body_hash_before",
"type": "TEXT NULL"
},
{
"name": "anchor_body_hash_after",
"type": "TEXT NULL"
},
{
"name": "commit_before",
"type": "TEXT NULL"
},
{
"name": "commit_after",
"type": "TEXT NULL"
},
{
"name": "formatting_only",
"type": "INTEGER NOT NULL DEFAULT 0"
},
{
"name": "controller_results_json",
"type": "TEXT NOT NULL DEFAULT \u0027{}\u0027"
},
{
"name": "mkb_notes",
"type": "TEXT NULL"
},
{
"name": "gatekeeper_status",
"type": "TEXT NOT NULL DEFAULT \u0027not_run\u0027"
},
{
"name": "gatekeeper_attempts",
"type": "INTEGER NOT NULL DEFAULT 0"
},
{
"name": "gatekeeper_last_error",
"type": "TEXT NULL"
}
],
"indices": [
"idx_items_checklist ON checklist_items(checklist_id, row_number)",
"idx_items_gatekeeper ON checklist_items(gatekeeper_status)"
],
"table": "checklist_items"
},
{
"constraints": [
"FOREIGN KEY(session_id) REFERENCES sessions(id) ON DELETE RESTRICT",
"FOREIGN KEY(checklist_item_id) REFERENCES checklist_items(id) ON DELETE RESTRICT",
"CHECK(status IN (\u0027pass\u0027,\u0027fail\u0027))",
"UNIQUE(checklist_item_id, attempt_number)"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "session_id",
"type": "TEXT NOT NULL"
},
{
"name": "phase_number",
"type": "INTEGER NOT NULL"
},
{
"name": "checklist_item_id",
"type": "TEXT NOT NULL"
},
{
"name": "attempt_number",
"type": "INTEGER NOT NULL"
},
{
"name": "created_at",
"type": "TEXT NOT NULL"
},
{
"name": "repo_path",
"type": "TEXT NOT NULL"
},
{
"name": "commit_before",
"type": "TEXT NOT NULL"
},
{
"name": "commit_after",
"type": "TEXT NOT NULL"
},
{
"name": "file_path",
"type": "TEXT NOT NULL"
},
{
"name": "symbol_ref",
"type": "TEXT NOT NULL"
},
{
"name": "anchor_hash_before",
"type": "TEXT NULL"
},
{
"name": "anchor_hash_after",
"type": "TEXT NULL"
},
{
"name": "diff_text",
"type": "TEXT NOT NULL"
},
{
"name": "ast_changed",
"type": "INTEGER NOT NULL"
},
{
"name": "formatting_only",
"type": "INTEGER NOT NULL"
},
{
"name": "status",
"type": "TEXT NOT NULL"
},
{
"name": "reason",
"type": "TEXT NOT NULL"
}
],
"indices": [
"idx_gatekeeper_session_phase ON gatekeeper_results(session_id, phase_number)",
"idx_gatekeeper_item ON gatekeeper_results(checklist_item_id)"
],
"table": "gatekeeper_results"
},
{
"constraints": [
"FOREIGN KEY(session_id) REFERENCES sessions(id) ON DELETE RESTRICT",
"CHECK(phase_number BETWEEN 1 AND 14)",
"UNIQUE(session_id, phase_number, doc_type, COALESCE(round_number, -1), path)"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "session_id",
"type": "TEXT NOT NULL"
},
{
"name": "phase_number",
"type": "INTEGER NOT NULL"
},
{
"name": "doc_type",
"type": "TEXT NOT NULL"
},
{
"name": "round_number",
"type": "INTEGER NULL"
},
{
"name": "created_at",
"type": "TEXT NOT NULL"
},
{
"name": "path",
"type": "TEXT NOT NULL"
},
{
"name": "sha256",
"type": "TEXT NOT NULL"
},
{
"name": "size_bytes",
"type": "INTEGER NOT NULL"
},
{
"name": "mime_type",
"type": "TEXT NOT NULL"
},
{
"name": "title",
"type": "TEXT NOT NULL"
},
{
"name": "tags_json",
"type": "TEXT NOT NULL DEFAULT \u0027[]\u0027"
}
],
"indices": [
"idx_docs_session_phase ON documents(session_id, phase_number)",
"idx_docs_type ON documents(doc_type)"
],
"table": "documents"
},
{
"constraints": [
"FOREIGN KEY(session_id) REFERENCES sessions(id) ON DELETE RESTRICT",
"CHECK(kind IN (\u0027reserve\u0027,\u0027commit\u0027,\u0027release\u0027,\u0027manual_add\u0027))"
],
"fields": [
{
"name": "id",
"type": "TEXT PRIMARY KEY"
},
{
"name": "session_id",
"type": "TEXT NOT NULL"
},
{
"name": "created_at",
"type": "TEXT NOT NULL"
},
{
"name": "kind",
"type": "TEXT NOT NULL"
},
{
"name": "phase_run_id",
"type": "TEXT NULL"
},
{
"name": "external_call_id",
"type": "TEXT NULL"
},
{
"name": "amount_cents",
"type": "INTEGER NOT NULL"
},
{
"name": "note",
"type": "TEXT NOT NULL"
},
{
"name": "data_json",
"type": "TEXT NOT NULL DEFAULT \u0027{}\u0027"
}
],
"indices": [
"idx_budget_session_time ON budget_ledger(session_id, created_at DESC)"
],
"table": "budget_ledger"
},
{
"constraints": [],
"fields": [
{
"name": "name",
"type": "TEXT PRIMARY KEY"
},
{
"name": "holder",
"type": "TEXT NOT NULL"
},
{
"name": "acquired_at",
"type": "TEXT NOT NULL"
},
{
"name": "expires_at",
"type": "TEXT NOT NULL"
}
],
"indices": [
"idx_locks_expires ON locks(expires_at)"
],
"table": "locks"
}
]
API Endpoints
[
{
"auth_required": false,
"description": "Healthcheck for reverse proxy and deploy validation. Must not require auth.",
"method": "GET",
"path": "/health",
"request_body": null,
"response": {
"db": "string(\u0027ok\u0027|\u0027error\u0027)",
"status": "string(\u0027ok\u0027)",
"time_utc": "string(ISO8601)",
"version": "string",
"worker": "string(\u0027ok\u0027|\u0027stopped\u0027)"
},
"status_codes": [
200,
500
]
},
{
"auth_required": false,
"description": "Optional Prometheus-like plaintext metrics. If disabled, return 404.",
"method": "GET",
"path": "/metrics",
"request_body": null,
"response": {
"text/plain": "string"
},
"status_codes": [
200,
404
]
},
{
"auth_required": false,
"description": "Receives build instruction/spec from FORGED. Validates schema, HMAC signature, replay protection, idempotency, version monotonicity per project_id, persists inbound_specs, starts/continues session workflow within \u003c5s by enqueueing phase 3 if allowed.",
"idempotency_rules": [
"Idempotency-Key header required; same key returns same response body as first successful processing (200) or first rejection (4xx) with stored error_json",
"If same Idempotency-Key but different payload hash -\u003e 409 error_code=\u0027IDEMPOTENCY_KEY_REUSE_DIFFERENT_BODY\u0027"
],
"method": "POST",
"path": "/api/core/receive-spec",
"request_body": {
"project_id": "string(min=3,max=64,pattern=^[a-zA-Z0-9_-]+$)",
"scope": "string(min=1,max=20000)",
"session_id": "string(min=3,max=64,pattern=^[a-zA-Z0-9_-]+$)",
"tech_spec": "object|null",
"version_number": "integer(min=1)"
},
"request_schema_rules": [
"Required fields: session_id, project_id, scope, version_number",
"tech_spec is optional; if present must be JSON object and \u003c= 500KB serialized",
"Reject if Content-Type not application/json",
"Reject if body \u003e 600KB"
],
"response": {
"accepted": "boolean",
"current_phase": "integer",
"errors": "array\u003cobject\u003e{path:string,code:string,message:string}",
"inbound_spec_id": "string",
"project_id": "string",
"session_id": "string",
"session_status": "string",
"version_number": "integer"
},
"status_codes": [
200,
202,
400,
401,
403,
409
],
"versioning_rules": [
"For each project_id, version_number must be strictly increasing compared to sessions.spec_version_number for latest session row with that project_id",
"If version_number == current stored for project_id and spec_hash identical -\u003e treated as duplicate; return 200 accepted=true without starting new run",
"If version_number \u003c= stored and spec_hash differs -\u003e 409 error_code=\u0027SPEC_VERSION_NOT_MONOTONIC\u0027"
]
},
{
"auth_required": true,
"description": "Manual upload of a spec (fallback). Same validation as FORGED but authenticated and without HMAC/IP checks.",
"method": "POST",
"path": "/api/admin/spec-upload",
"request_body": {
"project_id": "string",
"scope": "string",
"session_id": "string",
"tech_spec": "object|null",
"version_number": "integer"
},
"response": {
"accepted": "boolean",
"current_phase": "integer",
"errors": "array",
"inbound_spec_id": "string",
"session_id": "string"
},
"status_codes": [
200,
400,
409
]
},
{
"auth_required": true,
"description": "List sessions for dashboard.",
"method": "GET",
"path": "/api/sessions",
"request_body": null,
"response": {
"sessions": "array\u003cobject\u003e{id:string,project_id:string,status:string,current_phase:int,updated_at:string,ampel:string,last_event:string,budget_spent_cents:int,budget_hard_limit_cents:int}"
},
"status_codes": [
200
]
},
{
"auth_required": true,
"description": "Get full session details including phase runs, last 10 events, budget, jury, and links.",
"method": "GET",
"path": "/api/sessions/{session_id}",
"request_body": null,
"response": {
"budget": "object{spent:int,reserved:int,hard_limit:int,added_total:int}",
"checklist_overview": "array\u003cobject\u003e{phase_number:int,latest_round:int,total_rows:int,green_rows:int,percent:int}",
"links": "object{ui_session:string,documents:string}",
"phase_runs": "array\u003cobject\u003e",
"session": "object",
"timeline_last_10": "array\u003cobject\u003e"
},
"status_codes": [
200,
404
]
},
{
"auth_required": true,
"description": "Pause session; sets session.status=paused (or budget_paused stays budget_paused), and current running phase_run.status=paused. Must be idempotent.",
"method": "POST",
"path": "/api/sessions/{session_id}/pause",
"request_body": {
"reason": "string(max=5000)"
},
"response": {
"current_phase": "integer",
"ok": "boolean",
"status": "string"
},
"status_codes": [
200,
404,
409
]
},
{
"auth_required": true,
"description": "Resume session from paused/budget_paused. If budget_paused, requires budget to be under limit. Starts worker processing within \u003c5s.",
"method": "POST",
"path": "/api/sessions/{session_id}/resume",
"request_body": null,
"response": {
"current_phase": "integer",
"ok": "boolean",
"status": "string"
},
"status_codes": [
200,
404,
409
]
},
{
"auth_required": true,
"description": "Atomically adds +500 cents to hard limit. Only admin. Must be atomic and idempotent per request_id header.",
"idempotency_rules": [
"Requires header X-Request-Id; unique per action; stored in audit_events.request_id; duplicates return same response"
],
"method": "POST",
"path": "/api/budget/{session_id}/add",
"request_body": {
"amount_cents": "integer(enum=[500])"
},
"response": {
"added_total_cents": "integer",
"new_hard_limit_cents": "integer",
"ok": "boolean"
},
"status_codes": [
200,
404,
409
]
},
{
"auth_required": true,
"description": "Returns latest checklist round for phase 4/6/10/13 including column model and rows. Used by UI for horizontal scrolling table.",
"method": "GET",
"path": "/api/checklists/{session_id}/{phase_number}",
"request_body": null,
"response": {
"checklist": "object{id:string,phase_number:int,round_number:int,status:string,columns:array\u003cobject\u003e,rows:array\u003cobject\u003e}"
},
"status_codes": [
200,
404,
409
]
},
{
"auth_required": false,
"description": "Webhook receiver for MKB Bridge results. Must validate replay-protection headers (X-MKB-Timestamp, X-MKB-Nonce) and HMAC header X-MKB-Signature using CORE_MKB_BRIDGE_TOKEN as secret. Updates checklist round results and locks green rows.",
"method": "POST",
"path": "/api/mkb/webhook",
"request_body": {
"columns": "array\u003cobject\u003e",
"phase_number": "integer(enum=[4,6,10,13])",
"round_number": "integer(min=1)",
"rows": "array\u003cobject\u003e{row_number:int,requirement_text:string,controller_results:object,notes:string|null,file_path:string|null,symbol_ref:string|null,commit_before:string|null,commit_after:string|null,anchor_body_hash_before:string|null,anchor_body_hash_after:string|null}",
"session_id": "string"
},
"response": {
"ok": "boolean"
},
"status_codes": [
200,
400,
401,
403,
404,
409
]
},
{
"auth_required": false,
"description": "Webhook receiver for JURY completion. Validates replay-protection + HMAC (X-JURY-Signature, X-JURY-Timestamp, X-JURY-Nonce). Writes findings as documents and potentially as new checklist rows for phase 10 or 6 based on mapping.",
"method": "POST",
"path": "/api/jury/webhook",
"request_body": {
"completed_at": "string(ISO8601)",
"findings": "array\u003cobject\u003e{severity:string(enum=[\u0027critical\u0027,\u0027major\u0027,\u0027minor\u0027,\u0027info\u0027]),title:string,description:string,is_jury_bug:boolean,is_false_positive:boolean,affected_url:string|null,suggested_fix:string|null,source_locator:string|null}",
"jury_session_id": "string",
"session_id": "string",
"status": "string(enum=[\u0027completed_pass\u0027,\u0027completed_fail\u0027,\u0027timeout\u0027])"
},
"response": {
"ok": "boolean"
},
"status_codes": [
200,
400,
401,
403,
404,
409
]
},
{
"auth_required": true,
"description": "SSE stream for live dashboard/session updates. Emits JSON per event with session_id correlation. Auth required.",
"method": "GET",
"path": "/api/events/stream",
"request_body": null,
"response": {
"event_stream": "text/event-stream; data: {type:string,session_id:string,phase:int,level:string,message:string,created_at:string}"
},
"status_codes": [
200,
401
]
},
{
"auth_required": true,
"description": "List documents with filters query params: phase_number, doc_type, q (substring in title), tag.",
"method": "GET",
"path": "/api/documents/{session_id}",
"request_body": null,
"response": {
"documents": "array\u003cobject\u003e{id:string,phase_number:int,doc_type:string,round_number:int|null,created_at:string,title:string,path:string,size_bytes:int,tags:array\u003cstring\u003e}"
},
"status_codes": [
200,
404
]
}
]
UI Seiten
[
{
"elements": [
"Top bar: Service name + current time (UTC) + global health indicator (green if /health db=ok and worker=ok)",
"Table \u0027Sessions\u0027 with columns: Project, Session, Phase (1-14), Status, Ampel, Last Event (single line), Updated, Budget (spent/hard), Actions",
"Actions per row: Open, Pause (if running), Resume (if paused/budget_paused)"
],
"interactions": [
"Open -\u003e navigates to /sessions/{session_id}",
"Pause -\u003e POST /api/sessions/{id}/pause then refresh row",
"Resume -\u003e POST /api/sessions/{id}/resume then refresh row",
"Page opens SSE /api/events/stream and updates Last Event + Status live"
],
"layout": "Single column; table full width; no modals; actions are inline buttons.",
"path": "/",
"title": "CORE Dashboard"
},
{
"elements": [
"Header: Project ID, Session ID, Status badge, Current Phase, Ampel",
"Buttons: Pause, Resume, +500ct Budget",
"Budget bar: percent=spent/hard, labels at 80% (yellow) and 95% (red), values spent/reserved/hard",
"Panel \u0027Timeline (last 10)\u0027 list with timestamp, level, event_type, message; link \u0027all events\u0027 anchors to /sessions/{id}#events",
"Panel \u0027Phases\u0027 vertical list 1..14 with each latest run status (queued/running/paused/completed/failed), runtime (ended-started), progress%",
"Panel \u0027Checklists\u0027 with links for phases 4/6/10/13 to open latest checklist view",
"Panel \u0027Gatekeeper\u0027 with counters: items pass/fail/not_run and list of failing items with reason and link to checklist row",
"Panel \u0027Documents\u0027 list latest 10 docs with filters: phase dropdown, type dropdown, search input; opens file path via download endpoint (served as static file)"
],
"interactions": [
"+500ct -\u003e POST /api/budget/{id}/add amount=500, then refresh budget bar",
"Checklist link -\u003e navigates to /sessions/{id}/checklists/{phase_number}",
"Failing gatekeeper item click -\u003e scrolls checklist table to that row and highlights it"
],
"layout": "Two columns on desktop: left=timeline+phases, right=budget+checklists+gatekeeper+documents; collapses to single column under 900px.",
"path": "/sessions/{session_id}",
"title": "Session Detail"
},
{
"elements": [
"Header: Phase number, latest round number, percent complete, counts green/total",
"Controls row: Filter (All / Only open / Only failing / Only green), Compact toggle (compact shows only: row_number, requirement, status, failing controller names), Search input (substring over requirement_text)",
"Checklist table with frozen first 2 columns (Row#, Requirement) and horizontally scrollable remaining columns",
"Columns must be rendered in exact order as checklists.columns_json; never re-ordered by UI",
"Each row shows: requirement_text, file_path, symbol_ref, commit_before, commit_after, gatekeeper_status, then controller columns (DEV-1, DEV-5, DEV-6, DEV-9, DEV-3, DEV-15) and any additional MKB columns as provided",
"Row coloring: green only if 6/6 controllers = 100% AND gatekeeper_status=pass (if file_path/symbol_ref present); red otherwise; gray if no controller results"
],
"interactions": [
"Filter changes update table client-side only (no API call)",
"Compact toggle hides all non-essential columns but keeps controller pass/fail summary",
"If a row is red, UI must show a \u0027Why blocked\u0027 expandable area with: failing controllers + gatekeeper reason (if fail) + latest mkb_notes"
],
"layout": "Full-width; table header sticky; horizontal scroll with visible scrollbar.",
"path": "/sessions/{session_id}/checklists/{phase_number}",
"title": "Checklist Viewer"
},
{
"elements": [
"Form fields: session_id, project_id, version_number, scope textarea, tech_spec JSON textarea (optional)",
"Submit button",
"Result area showing accepted/rejected and errors list"
],
"interactions": [
"Submit -\u003e POST /api/admin/spec-upload; on 400 show error list exactly as returned"
],
"path": "/admin/spec-upload",
"title": "Manual Spec Upload"
}
]
Business Logic
[
{
"details": "Session upsert: Wenn sessions.id existiert -\u003e update scope_text, tech_spec_json, spec_version_number=version_number, updated_at=now. Wenn nicht existiert -\u003e insert mit status=\u0027new\u0027, current_phase=1, active_run_id=uuid. Danach enqueue_work(session_id) setzt sessions.status=\u0027running\u0027 falls nicht paused/budget_paused.",
"rule": "Wenn /api/core/receive-spec valide ist, dann wird inbound_specs.status=\u0027queued\u0027 gespeichert und eine Session angelegt/aktualisiert, und innerhalb von \u003c5s ein Phase-Run f\u00fcr Phase 3 queued."
},
{
"details": "Beim Startup: Transaktion: UPDATE sessions SET status=\u0027paused\u0027, pause_reason=\u0027restart_reconciliation\u0027, updated_at=now WHERE status=\u0027running\u0027; UPDATE phase_runs SET status=\u0027paused\u0027, substatus=\u0027reconciled_from_running\u0027, ended_at=now WHERE status=\u0027running\u0027. Timeline + Audit event erzeugen.",
"rule": "Wenn CORE neu startet, dann werden alle Sessions mit status=\u0027running\u0027 deterministisch auf status=\u0027paused\u0027 gesetzt und die aktuell laufende phase_runs.status=\u0027paused\u0027 gesetzt."
},
{
"details": "Worker w\u00e4hlt n\u00e4chsten startbaren Phase-Run: kleinste phase_number mit nicht completed. Start ist verboten wenn vorherige Phase nicht completed. Wiederholung: Wenn eine Phase failed oder Review/JURY neue Items erzeugt, wird ein neuer run_number f\u00fcr die betroffene Phase erstellt und erneut ausgef\u00fchrt; previous completed run bleibt unver\u00e4ndert.",
"rule": "Es gibt kein Skip: Phase N darf nur starten, wenn Phase N-1 in irgendeinem Run status=\u0027completed\u0027 hat (progress_percent=100) und validate_phase_completion(session_id,N-1) true ist."
},
{
"details": "F\u00fcr jedes Artefakt: write tmp file, fsync, validate (exists, size\u003e0, parseable if JSON), atomic rename to artifacts_root/session_id/phase_{n}/run_{r}/...; erst danach BEGIN; update phase_runs.status=\u0027completed\u0027, progress_percent=100, artifact_index_json includes final paths; COMMIT.",
"rule": "Phase-Completion ist atomar: Artefakte werden zuerst in tmp geschrieben, validiert, nach Ziel verschoben, dann DB in einer Transaktion auf completed gesetzt."
},
{
"details": "controller_results_json muss Keys enthalten: DEV-1,DEV-5,DEV-6,DEV-9,DEV-3,DEV-15. Gr\u00fcn wenn alle Werte genau String \u0027100%\u0027. Jede andere Zeichenkette ist ein Fehlertext. 100% f\u00fcr Phase = alle Zeilen gr\u00fcn. Locked-green: Wenn eine Zeile in einer fr\u00fcheren Runde 6/6 gr\u00fcn war, wird locked_green=1 und muss in sp\u00e4teren Runden nicht erneut angefragt werden; bleibt gr\u00fcn.",
"rule": "MKB Review 100%: Eine Checklisten-Zeile ist nur gr\u00fcn wenn alle 6 Controller exakt \u0027100%\u0027 melden; 5/6 reicht nicht."
},
{
"details": "Neue Runde = checklists.round_number +1, neue Spalten werden nur angeh\u00e4ngt: columns_json der neuen Runde ist columns_json der alten Runde + new_columns; niemals Spalten entfernen/\u00fcberschreiben. checklist_items in neuer Runde \u00fcbernehmen requirement_text+source_ref; locked_green rows werden kopiert mit locked_green=1 und controller_results_json unver\u00e4ndert.",
"rule": "Rundenmodell: Nur die letzte Runde z\u00e4hlt f\u00fcr nicht-locked Zeilen; fr\u00fchere Runden bleiben als Historie unver\u00e4ndert."
},
{
"details": "Gatekeeper wird bei Abschluss von Phase 5 und bei jeder Review-Runde von Phase 6 automatisch f\u00fcr alle nicht-locked Items ausgef\u00fchrt. Kein Override. gatekeeper_attempts++ pro Run. Nach 5 fails f\u00fcr dasselbe checklist_item_id: Session wird pausiert und es wird ein critical Timeline+Audit Event \u0027gatekeeper_escalation\u0027 erstellt.",
"rule": "Gatekeeper: F\u00fcr jedes Checklist-Item mit file_path+symbol_ref+commit_before+commit_after muss Gatekeeper pass liefern, sonst blockiert es Phase-Advance."
},
{
"details": "Python-Dateien: parse AST f\u00fcr symbol_ref; compute body hash from AST dump. ast_changed = (hash_before != hash_after). Wenn diff vorhanden aber ast_changed=false -\u003e formatting_only=1, status pass. Nicht-Python-Dateien: ast_changed wird 1 wenn diff nicht leer ist.",
"rule": "Gatekeeper semantische Pr\u00fcfung: Wenn AST unver\u00e4ndert, ist es formatting_only=1; wird akzeptiert (gatekeeper pass), z\u00e4hlt aber nicht als Fix-Indikator."
},
{
"details": "Phase 7 flow: (1) Acquire deploy lock \u0027deploy:{service_name}\u0027. (2) Create snapshot dir artifacts_root/session_id/deploy_snapshots/{ts}/code/ by rsync --exclude .env and --exclude artifacts; copy SQLite db files from service_repo_path to snapshot dir with suffix .pre-deploy. (3) Apply code changes already present in repo_path. (4) systemctl restart {service_systemd_unit}. (5) Healthcheck GET service_health_url, 3 tries, 2s delay, timeout 2s. If fail -\u003e restore code from snapshot to repo_path, restore sqlite from .pre-deploy, systemctl restart, re-check health. If still fail -\u003e phase_run failed with error_code=\u0027DEPLOY_ROLLBACK_FAILED\u0027. Always write timeline event for snapshot, restart, health result, rollback.",
"rule": "Deploy ist atomar: Pre-Deploy Snapshot von Code-Verzeichnis und SQLite Snapshot; Healthcheck entscheidet \u00fcber Rollback."
},
{
"details": "reserve_cents = estimated_max_output_tokens * price_per_token + fixed_overhead_cents. Wenn budget_spent_cents + budget_reserved_cents + reserve_cents \u003e budget_hard_limit_cents -\u003e set sessions.status=\u0027budget_paused\u0027, pause_reason=\u0027budget_hard_limit\u0027, create timeline+audit, do not start call. Nach Call: replace reservation with committed actual cost from usage; update ledger entries reserve-\u003ecommit/release.",
"rule": "Budget Circuit Breaker: Vor jedem externen Call muss reserviert werden; bei \u00dcberschreitung wird Session budget_paused."
},
{
"details": "On Phase 10 completion: verify checklist pass criteria. Then: update sessions.jury_status=\u0027requested\u0027; POST CORE_JURY_BASE_URL + \u0027/api/jury/start\u0027 with body {session_id,project_id,url:service_public_url}. On 200: store jury_session_id, set jury_status=\u0027running\u0027. Poll every 60s until completed_* or timeout at 1800s. Timeout sets jury_status=\u0027timeout\u0027 and creates retry event; worker retries start after 300s by re-requesting /api/jury/status then /api/jury/retry if supported; if not supported, re-run /api/jury/start with new jury_session_id and keep history as document.",
"rule": "JURY Trigger: Nur wenn Phase 10 Review Live 100% ist, dann set jury_status requested und starte JURY."
},
{
"details": "Finding mapping: if is_jury_bug=true OR is_false_positive=true -\u003e document only; else -\u003e create new checklist item in phase 10 checklist (if UI/UX issue) or phase 6 checklist (if code defect) with requirement_text prefixed \u0027JURY:\u0027 and source_ref=\u0027jury:{jury_session_id}\u0027. Freigabe-Check z\u00e4hlt nur echte Fehler: 4x0 bedeutet count(findings where is_jury_bug=false and is_false_positive=false and severity in critical/major/minor/info)==0.",
"rule": "JURY Findings R\u00fcckf\u00fchrung: echte Fehler erzeugen neue Checklisten-Zeilen; JURY_BUG und KEIN_FEHLER erzeugen nur Dokumentation und blockieren 4x0 nicht."
},
{
"details": "Gates: Phase4=100%, Phase6=100%, Phase10=100%, Phase11 jury_status=completed_pass with 4x0 echte Fehler, Phase13=100%. Dann set sessions.status=\u0027completed\u0027, current_phase=14, create documents: release_note.md, and POST to CORE_GENESIS_WEBHOOK_URL with HMAC using CORE_GENESIS_WEBHOOK_SECRET.",
"rule": "Freigabe (Phase 14) wird automatisch gesetzt und an Genesis gemeldet, wenn alle Gates erf\u00fcllt sind."
}
]
Dateistruktur
[
{
"file": "app.py",
"purpose": "Flask app factory, route registration, error handlers, middleware (auth header, rate limit), SSE endpoint."
},
{
"file": "core/config.py",
"purpose": "Load env vars, defaults, validation on startup; fail-fast if missing required env."
},
{
"file": "core/db.py",
"purpose": "SQLite connection (WAL), migrations/DDL, transaction helpers, row dict helpers."
},
{
"file": "core/models.py",
"purpose": "Typed constants/enums for statuses, phase definitions, validation helpers."
},
{
"file": "core/security.py",
"purpose": "HMAC verification, replay protection, IP allowlist parsing, CSP header."
},
{
"file": "core/spec_schema.py",
"purpose": "JSONSchema for receive-spec payload, validation and error normalization."
},
{
"file": "core/worker.py",
"purpose": "Background worker loop, queue selection, phase execution orchestration, reconciliation job."
},
{
"file": "core/phases/phase03_planning.py",
"purpose": "Claude call for build plan, validation against tech_spec, artifact writes."
},
{
"file": "core/phases/phase05_build.py",
"purpose": "Repo writes + git commit + gatekeeper run stub invocation."
},
{
"file": "core/phases/phase07_deploy.py",
"purpose": "Snapshot, systemd restart, healthcheck, rollback logic."
},
{
"file": "core/phases/phase08_tests.py",
"purpose": "pytest execution, report capture, artifact registration."
},
{
"file": "core/phases/phase09_5isct.py",
"purpose": "5ISCT Claude prompts, retries, warn handling, JSON report."
},
{
"file": "core/phases/phase11_jury.py",
"purpose": "JURY start/poll/timeout, webhook handler helpers."
},
{
"file": "core/phases/phase12_docs.py",
"purpose": "Genesis folder writes, required docs generation, indexing in documents table."
},
{
"file": "core/mkb_bridge.py",
"purpose": "Outgoing calls to MKB bridge to request reviews, polling (if used), webhook processing."
},
{
"file": "core/gatekeeper.py",
"purpose": "Diff + AST verification, anchor extraction, ignore patterns."
},
{
"file": "core/git_tools.py",
"purpose": "git diff, commit sha retrieval, follow renames, safe command execution."
},
{
"file": "core/budget.py",
"purpose": "Reservation/commit/release ledger logic, hard limit enforcement."
},
{
"file": "core/genesis.py",
"purpose": "Genesis webhook client + document path conventions + HMAC signing."
},
{
"file": "templates/dashboard.html",
"purpose": "Dashboard page server-rendered."
},
{
"file": "templates/session_detail.html",
"purpose": "Session detail page server-rendered."
},
{
"file": "templates/checklist_view.html",
"purpose": "Checklist viewer with horizontal scroll table."
},
{
"file": "templates/spec_upload.html",
"purpose": "Manual spec upload page."
},
{
"file": "static/core.css",
"purpose": "Minimal CSS for table scrolling, sticky headers, color states."
},
{
"file": "static/core.js",
"purpose": "SSE client, table filtering, compact toggle, row highlight."
}
]
Akzeptanz-Checks
[
{
"check": "Minimaler Bauauftrag wird akzeptiert und startet Phase-Queue in \u003c5s.",
"how_to_verify": "curl -X POST https://core.xxbillion.ai/api/core/receive-spec mit g\u00fcltiger HMAC+Headers und body {session_id,project_id,scope,version_number}. Zeit messen bis sessions.status=\u0027running\u0027 und phase_runs f\u00fcr phase=3 status=\u0027queued\u0027 via GET /api/sessions/{id} sichtbar ist; muss \u003c5s sein."
},
{
"check": "Ung\u00fcltiges JSON Schema liefert 400 mit maschinenlesbarer Fehlerliste.",
"how_to_verify": "POST ohne project_id; Response 400 JSON enth\u00e4lt errors[0].path == \u0027/project_id\u0027 und code == \u0027REQUIRED\u0027."
},
{
"check": "Webhook Security: falsche HMAC Signatur -\u003e 401 und Audit-Event.",
"how_to_verify": "POST mit falschem X-FORGED-Signature; Response 401; audit_events latest action=\u0027forged_webhook_rejected\u0027 data_json.error_code=\u0027FORGED_SIGNATURE_INVALID\u0027."
},
{
"check": "Replay Protection: gleicher Nonce erneut -\u003e 403.",
"how_to_verify": "Sende identischen Request zweimal mit gleichem X-FORGED-Nonce; zweiter Response 403 error_code=\u0027FORGED_REPLAY_DETECTED\u0027."
},
{
"check": "Keine Skip-Regel: Phase 4 kann nicht starten ohne completed Phase 3.",
"how_to_verify": "Manipulationsversuch durch POST /api/sessions/{id}/resume oder internes Triggern; System muss 409 error_code=\u0027PHASE_PREREQUISITE_NOT_MET\u0027 und Phase 4 bleibt queued/running=false."
},
{
"check": "Restart-Reconciliation: running -\u003e paused deterministisch.",
"how_to_verify": "Session auf running setzen (Phase 5 running), Service neu starten, dann GET /api/sessions/{id} zeigt status=\u0027paused\u0027 und phase_runs.status=\u0027paused\u0027 mit substatus=\u0027reconciled_from_running\u0027."
},
{
"check": "MKB 6/6-Logik: 5/6 ist nicht gr\u00fcn.",
"how_to_verify": "Sende MKB webhook mit einer Zeile wo ein Controller !=\u0027100%\u0027; UI zeigt rot; Phase bleibt blockiert."
},
{
"check": "Gatekeeper: Item bindet an commit_before/after und best\u00e4tigt AST-\u00c4nderung oder formatting-only korrekt.",
"how_to_verify": "Erzeuge Commit A-\u003eB mit nur Black formatting in function; Gatekeeper status pass und formatting_only=1. Erzeuge Commit C-\u003eD mit semantischer \u00c4nderung; Gatekeeper status pass und ast_changed=1."
},
{
"check": "Gatekeeper Eskalation nach 5 Fehlversuchen pausiert Session und erzeugt critical Event.",
"how_to_verify": "F\u00fchre 5 mal Gatekeeper fail f\u00fcr gleiche checklist_item_id aus; session.status wird \u0027paused\u0027 oder \u0027budget_paused\u0027 bleibt, und timeline_events enth\u00e4lt event_type=\u0027gatekeeper_escalation\u0027 level=\u0027critical\u0027."
},
{
"check": "Deploy atomar mit Rollback bei Health-Fail.",
"how_to_verify": "Simuliere Deploy mit absichtlich kaputter app import; Healthcheck fail -\u003e Rollback; danach /health der Ziel-App liefert 200 und timeline enth\u00e4lt deploy_rollback event."
},
{
"check": "Phase 8 Tests ausf\u00fchrbar und Report als Artefakt gespeichert.",
"how_to_verify": "Vorhandene tests/ ausf\u00fchren; artifacts Pfad enth\u00e4lt pytest_report.json; Dashboard zeigt 1-zeilige Zusammenfassung \u0027pytest: pass\u0027 oder \u0027pytest: fail\u0027 in Last Event."
},
{
"check": "5ISCT l\u00e4uft immer, 3 Retries bei Flakes, danach WARN, nicht Blocker.",
"how_to_verify": "Simuliere 5ISCT Antwort mit flaky Marker 3x; Phase 9 completed mit warn in timeline_events, nicht failed."
},
{
"check": "JURY Trigger nur nach Review Live 100%.",
"how_to_verify": "Solange Phase 10 nicht 100% ist, darf sessions.jury_status nicht \u0027requested\u0027 werden. Nach 100% muss automatisch \u0027requested\u0027-\u003e\u0027running\u0027 erscheinen."
},
{
"check": "Freigabe setzt Status completed und sendet Genesis Webhook.",
"how_to_verify": "Erf\u00fclle alle Gates; CORE erstellt audit_event action=\u0027release_sent\u0027 und sessions.status=\u0027completed\u0027, current_phase=14; Genesis webhook request im audit log gespeichert (ohne Secret)."
},
{
"check": "Budget Hard-Limit pausiert Session automatisch; +500ct Button setzt neue Grenze ohne Session-Verlust.",
"how_to_verify": "Setze budget_spent nahe hard_limit und starte externen Call; CORE setzt budget_paused. Danach POST /api/budget/{id}/add amount=500; Resume m\u00f6glich und Session bleibt konsistent."
}
]
Scope
Was gebaut wird
CORE Build Engine als zentraler Build-Agent auf core.xxbillion.ai (Port 5600) mit Web-UI + API. Empfang von FORGED-Bauanleitungen per HTTP POST /api/core/receive-spec inkl. Schema-Validierung, Versionierung (monoton steigende version_number), Idempotenz-Key und HMAC-SHA256 (X-FORGED-Signature). Orchestrierung eines verbindlichen 14-Phasen-Prozesses (1–14) mit harter Regel: kein Skip, Pause/Resume erlaubt, Wiederholung einzelner Phasen erlaubt, Vorwärts nur bei 100%. Persistenter State in SQLite (WAL) inkl. Sessions/Phasen/Checklisten/Items/Gatekeeper-Resultaten/Dokument-Metadaten, crash-sicheres Resume (running -> paused bei Restart) und Reconciliation für „stuck running“. MKB-Review-Integration (Bridge API) mit wachsenden Spalten, 6/6-Controller-Logik für 100%, Rundenmodell (nur letzte Runde zählt, vorherige grüne Zeilen bleiben locked), UI für horizontales Spalten-Scrolling, Filter und Kompaktansicht für Johannes. Python-Gatekeeper als Gatekeeper für Checklisten-zu-Code-Verifikation: diff- und AST-basierte Prüfung mit refactor-stabilen Ankern (file + symbol_ref + body-hash), bindet jedes Checklist-Item an commit_before/commit_after; keine Overrides, Eskalation nach 5 Fehlversuchen an Johannes. Build/Deploy/Test-Pipeline: Build (Phase 5) führt Code-Änderungen im Service-Verzeichnis aus, Deploy (Phase 7) auf Hetzner Ubuntu 22.04 via systemd restart, Caddy Reverse Proxy bleibt vorgelagert, atomarer Deploy mit Pre-Deploy Backup (Code-Verzeichnis + SQLite Snapshot), Post-Deploy Healthcheck /health, automatischer Rollback auf letzte funktionierende Version (git tag/Backup) inkl. Timeline-Event. Testausführung gemäß Bauplan (Phase 8) + verpflichtender 5ISCT (Phase 9) mit Retries/Flake-WARN, Reports als Artefakte. Review Live (Phase 10) triggert automatisch JURY (Phase 11) bei 6/6 = 100% auf allen Zeilen, JURY-Statusmaschine (requested/running/completed_pass/completed_fail/timeout) mit Webhook/Polling, Findings werden als neue Checklisten-Zeilen zurückgeführt; JURY_BUG/KEIN_FEHLER werden dokumentiert, echte Fehler müssen zu 4x0 führen. Dokumentation (Phase 12) in Genesis-Ordnerstruktur inkl. Pflichtdokumente, Metadaten-Index in SQLite, Suche/Filter in Web-UI. Freigabe (Phase 14) automatisch bei: Review Plan 100%, Review Code 100%, Review Live 100%, JURY 4x0 (nur echte Fehler), Review Doku 100%; Status-Webhook an Genesis und grünes Signal im Dashboard. Budget-Management (pro Phase soft, pro Session hard 500ct, pro Projekt monitoring), Echtzeit-Kostentracking (Reservation vor Call, Buchung nach Call), UI-Budgetbalken + atomarer +500ct-Button für Johannes, Circuit-Breaker pausiert bei Hard-Limit. Observability: Live-Timeline (letzte 10 Events), Gatekeeper-Status, Checklistenstatus, Laufzeiten pro Phase, Kosten-Counter, strukturierte Logs mit Correlation (session_id/phase), Health-Endpoint und optional /metrics; Notification-Regeln (kritisch vs. Info) mit „rote Lampe“ im Genesis Dashboard und später WhatsApp.
Akzeptanzkriterien
['CORE akzeptiert minimalen Bauauftrag (session_id, project_id, scope) und validiert tech_spec optional; invalide Payload -> HTTP 400 mit maschinenlesbarer Fehlerliste; gültige -> <5s bis Phase-Start', 'Webhook-Security: HMAC-SHA256 Signaturprüfung mit Replay-Protection (timestamp+nonce) und IP-Allowlist für FORGED; fehlerhafte Signatur -> 401/403 und Audit-Event', '14-Phasen-State-Machine ist implementiert und erzwingt: kein Skip; Phase startet nur wenn vorherige Phase 100% completed; Pause/Resume funktioniert nach Neustart ohne Datenverlust', 'SQLite-Datenmodell besitzt Constraints (Unique/Foreign Keys) für sessions/phases/checklists/items; WAL aktiv; Reconciliation-Job setzt „stuck running“ nach Restart deterministisch auf paused mit Hinweis', 'MKB-Review: Checkliste unterstützt wachsende Spalten, jede Runde hängt Spalten an (nie überschreiben); 100% ist strikt 6/6 pro Zeile; UI kann in <30s den Gesamtstatus erfassbar machen (Kompaktansicht)', 'Gatekeeper: jedes Checklist-Item enthält file_path + symbol_ref + commit_before/commit_after; Gatekeeper bestätigt Änderungen per git diff + AST/body-hash; reine Formatierung wird erkannt (AST unverändert) und nicht als Fix gezählt, blockiert aber nicht', 'Gatekeeper-Block: UI markiert rote Zeile mit Begründung; kein Override; nach 5 Fehlversuchen wird Johannes benachrichtigt und ein Audit-Record existiert', 'Deploy ist atomar: Pre-Deploy Snapshot (Code-Verzeichnis + SQLite .pre-deploy) wird erstellt; bei Healthcheck-Fail erfolgt automatischer Rollback und Service läuft wieder grün; Rollback-Event ist in Timeline sichtbar', 'Phase 8 Tests sind ausführbar und deterministisch genug für Alltag: Start/Stop der App im Test definiert, Seeds/Fixtures geregelt, Retries für Flakes; Ergebnis-Report als Artefakt gespeichert und im Dashboard 1-zeilig zusammengefasst', '5ISCT läuft immer, 3 Retries bei Flakes, danach WARN (nicht Blocker), JSON-Report pro Identität gespeichert', 'JURY-Trigger erfolgt ausschließlich nach Review Live = 100% (6/6 auf allen Zeilen); JURY-Statusmaschine verhindert falsches Weiterlaufen; Timeout (30min) führt zu retry-state statt „grün“', 'Freigabe wird automatisch gesetzt und an Genesis per Webhook gemeldet, sobald alle Freigabekriterien erfüllt sind; Johannes sieht im Dashboard sofort „freigegeben“ inkl. Links zu Bauplan/Checklisten/Reports', 'Budget: Session pausiert automatisch bei Hard-Limit 500ct; Johannes kann im UI +500ct freischalten ohne Session-Verlust; Kosten pro Phase/Session werden nachvollziehbar geloggt', 'Web-UI deckt Johannes’ Daily ab: Dashboard (alle Sessions, Phase, Ampel), Session-Detail (Timeline, Checklisten, Logs, Gatekeeper, Kosten) ohne SSH-Notwendigkeit']
Nicht-Ziele
Kein CLI für Johannes (nur Web-UI + API). Kein Docker/Kubernetes/Blue-Green/Canary; Deploy ist systemctl restart mit Healthcheck. Kein Multi-User-RBAC v1 (nur Admin Johannes; Read-Only später). Keine automatische Secret-Rotation/Vault-Integration (nur .env + manuelle Rotation). Keine vollständige Cross-Service-Kollisionsprüfung beim Spec-Eingang (Caddy-Konflikte werden beim Deploy sichtbar). Kein Live-Monitoring-getriggerter JURY-Run; JURY nur automatisch nach Review Live 100%. Keine Lösch-/Retention-Policy außer „alles behalten“ (keine Dedupe/Kompression v1). Keine MKB-interne Parallelisierungs-/Kostensteuerung (nur Bridge-Aufruf und Cost-Tracking in CORE). Kein Mehrheitsentscheid bei Controllern und kein Override von 6/6-Regeln.
Erfolgsbild
Johannes öffnet morgens das Dashboard und erkennt sofort pro Projekt/Session: aktuelle Phase, Ampelstatus, aktive Aufgabe, letzte Events, Kostenstand. CORE arbeitet autonom durch die Pipeline und fragt Johannes nur bei Eskalationen (z.B. Gatekeeper nach 5 Fehlversuchen, Service-Down, Budget-Pause). Standardprojekte deployen innerhalb von 30 Minuten, Tests laufen unter 15 Minuten. Der Service ist 24/7 erreichbar (Auto-Restart, Healthchecks), Ausfälle werden sichtbar gemeldet. Jeder Schritt ist nachvollziehbar: Bauplan, Checklisten (alle Runden), Gatekeeper-Reports, Test-/5ISCT-Reports, JURY-Protokolle und Changelog liegen strukturiert im Genesis-Ordner und sind über die UI such-/filterbar. Freigaben passieren nur bei echten 100%-Gates (Reviews + JURY 4x0 echte Fehler), und Johannes muss keine manuelle Koordination zwischen Tools mehr leisten.
Risikostellen
Source of Truth & Reproduzierbarkeit: aktuelles „alles auf main auf VPS“ ist fragil; Gatekeeper braucht verlässliche commit_before/after und deterministische Replays/Rollbacks. Build/Test-Umgebung: ohne venv/Python-Pinning und klaren Test-Framework/DoD drohen Drift, nicht reproduzierbare Fehler und lange Debug-Zeiten. Phase-8-Teststrategie: muss konkret werden (Arten, Framework, deterministische Daten, Start/Stop, Mindestkriterien), sonst bleibt Phase 8 nicht automatisierbar. Deploy-Transaktionalität: Code+DB+Config müssen sauber gekapselt sein; Partial-Deploy-Erkennung, Rollback-Konsistenz und „resume“ dürfen keine alten Artefakte als neu interpretieren. Security Hardening: Webhook-Replay-Protection, CSRF/CSP, Least-Privilege (root vermeiden), Audit-Log-Unveränderlichkeit sind nötig für langlebigen Betrieb. State-Machine/DB-Constraints: ohne harte Enumerations/Transitions, Dead-letter/Poison-Handling und Reconciliation entstehen „hängende“ Sessions. Concurrency/Queue: Latest-Wins vs. Historie, Idempotenz, Cancel-Semantik und Fairness müssen sauber definiert sein bevor MAX_CONCURRENT_BUILDS>1 genutzt wird. Scope/Change-Control: klare Regel, was „Scope-Erweiterung“ ist vs. legitime Fixes aus MKB/JURY, sonst Endlosschleifen oder schleichende Feature-Expansion.
Gap-Analyse
5 Kritisch
7 Wichtig
R4 erforderlich
KRITISCH
Source of Truth / Git-Workflow: Unklar, welches Repo/Branching-Modell CORE als verbindlich nutzt (pro Session Branch, pro Projekt Repo, Monorepo vs. Multi-Repo), wie Commits/Tags erzeugt werden, und wie der Gatekeeper eindeutig Checklist-Items an Commit-SHAs bindet. Ohne sauberes Git-Truth-Model sind Diff-/AST-Verifikation, Rollback und Deploy-Reproduzierbarkeit nicht belastbar.
KRITISCH
Build/Runtime Isolation auf VPS: Es fehlt die verbindliche Ausführungsumgebung pro Projekt (venv/pyenv, Python-Version-Pinning, Abhängigkeitsinstallation, Caching, Artefakt-Reuse) sowie die genaue Strategie, wie CORE Builds ausführt (lokal auf VPS vs. separater Runner). Ohne das ist 'Build' (Phase 5) nicht reproduzierbar und kann bei Parallelität/Drift brechen.
KRITISCH
Deploy-Target Definition & Service Lifecycle: systemctl restart + Caddy ist erwähnt, aber nicht präzisiert: Unit-Names/Service-Templates, WorkingDirectory, User/Permissions, Logs, Environment-Files, Port-Binding, Healthcheck-URL pro Service, Rollback-Mechanik für Code+Config gemeinsam. Ohne klare Service-Definition ist Phase 7 nicht zuverlässig automatisierbar.
KRITISCH
Teststrategie (Phase 8) – konkrete Umsetzung: Phase 8 ist nur abstrakt beschrieben. Es fehlen: Testarten (unit/integration/e2e), Frameworks (pytest/playwright?), Testdatenstrategie, Start/Stop der App im Test, deterministische Seed-Regeln, Coverage-/Mindestkriterien und 'Definition of Done' für Phase 8. Ohne das ist 'Test gemäß Bauplan' nicht ausführbar.
KRITISCH
Failure Containment / Safe Writes: Atomare Phase-Transitions sind beschrieben, aber es fehlen harte Regeln, welche Pfade/Artefakte überschrieben werden dürfen (immutable artefacts pro Run vs. latest), wie Partial-Deploys erkannt werden, und wie 'resume' verhindert, dass alte Artefakte als neu gelten. Ohne das drohen inkonsistente Zustände nach Crash/Retry.
WICHTIG
API Contracts / Versioning zwischen Services: Für FORGED/MKB/JURY/Genesis sind Endpoints angedeutet, aber es fehlen vollständige API-Verträge: Payload-Schemas, Response-Schemas, Fehlercodes, Versioning/Compat-Strategie (v1/v2), Timeout-Regeln, Signatur-Header für alle Integrationen (nicht nur FORGED).
WICHTIG
State Machine / Datenmodell-Details: Es gibt Tabellen-Namen, aber keine verbindlichen Zustände pro Phase, keine Enumerations/Transitions pro Substatus, keine Constraints (Unique Keys, FK), und keine Regeln für 'Latest-Wins' vs. historische Versionen (Bauplan/Checkliste). Das erhöht Bug-Risiko und erschwert Recovery.
WICHTIG
Security Hardening (Production): Auth ist grob, aber es fehlen: CSRF-Strategie, Session-Handling, Content-Security-Policy, IP-Allowlisting für Webhooks, Replay-Protection für HMAC (timestamp/nonce), Secret-Rotation-Prozess, Least-Privilege auf VPS (kein root), sowie Audit-Log Unveränderlichkeit.
WICHTIG
Observability / Debuggability: Health/Metrics sind erwähnt, aber es fehlen: strukturierte Logs (JSON), Correlation IDs (session_id, phase_id), Log-Retention/Rotation-Policy, Trace von externen Calls (Claude/MKB/JURY), sowie eine klare '2-Minuten-Diagnose'-Ansicht (Top Failure Signature, Next Action).
WICHTIG
Concurrency & Queue Semantics: Es gibt Inbox-Queue und MAX_CONCURRENT_BUILDS, aber es fehlen: Fairness/Priorität, starvation avoidance, Cancel-Semantik (was ist wirklich cancelbar), Dead-letter-Queue/Poison-Message-Handling, und Reconciliation-Job nach Neustart (stuck running).
WICHTIG
Scope/Change-Control Regeln: Es heißt 'Scope darf nie erweitert werden', aber es fehlen Kriterien, was als Scope-Erweiterung gilt (z.B. Security-Fixes, Observability, Performance), und wie CORE damit umgeht, wenn MKB/JURY neue Anforderungen erzeugen, die nicht in tech_spec standen.
NICE_TO_HAVE
UX Details (Johannes-Flow): UI ist grob beschrieben, aber es fehlen konkrete Interaktionsflows: 'rote Lampe' Details, One-click Resume/Rollback, Diff-Viewer in Checklistenzeile, 'Why blocked' Erklärungen, sowie mobile/responsive Breakpoints.
NICE_TO_HAVE
Plugin-/Extension-Modell: Keine Klärung, wie neue Phasen/Checks/Agenten später ergänzt werden (Plugin-Schnittstellen, Phase-Registry, Konfig-DSL). Das beeinflusst Wartbarkeit, ist aber nicht build-blocking für v1.
NICE_TO_HAVE
Data Retention & Storage Growth: Retention=unbegrenzt ist gesetzt, aber es fehlen Größenlimits, Kompression, Artefakt-Dedupe, sowie Strategie für große Logs/Testartefakte. Langfristig wichtig, kurzfristig nicht blockierend.
Runden-Verlauf
Runde 1
37 Fragen (714 raw)
100 Agents
Runde 2
19 Fragen (23 raw)
5 Agents
Runde 3
7 Fragen (9 raw)
3 Agents
Runde 4
5 Fragen (9 raw)
3 Agents