This is a live-tracking working document, changes will be updated at least per-task if not annotated further. The end is a rolling commentary of abstract thought related to the project.
This roadmap reflects the current state: Phases 0–8 complete. v1.0 freeze readiness is the next milestone.
The goal is to establish a functional, minimal reference substrate before adding any sophistication.
Objective: Make the repo legible and structurally real.
schemas/
examples/
docs/
migrations/
cmd/control-plane/
internal/
agents/
dashboard/static/
storage/
schemas/canonical_object.schema.json
schemas/agent_reference.schema.json
schemas/policy.schema.json
docs/architecture.md
docs/governance-model.md
Makefile
docker-compose.yml (empty or stub)
Exit condition:
Status: Complete. Docs written. Schemas and examples in place.
Objective: Lock the data model before writing behavior.
Finalize JSON schemas:
Add schema version field:
"schema_version": "0.1.0"
examples/canonical_object_example.json
examples/agent_reference_example.json
Exit condition:
/schemas folder is understandable without reading code.Status: Complete. make validate passes. Policy schema included beyond original scope.
Objective: Establish durable, queryable history.
Create initial migration:
migrations/001_initial.sql
Tables:
Add docker service:
Exit condition:
Status: Complete. make migrate is idempotent for a fresh database. All four tables with correct indices.
Objective: Create the smallest possible governance layer.
GET /status
POST /stop
POST /resume
POST /canonical
POST /reference
Exit condition:
Status: Complete. All five endpoints live. Full hash verification, size verification, and storage-path verification on every POST /canonical. Referential integrity enforced on POST /reference.
Known debt:
internal/pg is a temporary stdlib-only PostgreSQL wire-protocol driver. Written because pgx/v5 requires Go 1.25, which was unavailable in the offline build environment. Migration path documented in internal/pg/pg.go. When Go 1.25 + network are available: go get github.com/jackc/pgx/v5@latest, rewrite internal/db, delete internal/pg, remove POSTGRES_HOST_AUTH_METHOD=md5, bump Dockerfile to golang:1.25-alpine.Objective: Establish immutable payload storage.
canonical/{object_type}/{yyyy}/{mm}/{dd}/{hash}.json
Exit condition:
Status: Complete. Implemented against MinIO (S3-compatible). Switch to Cloudflare R2 or any S3-compatible store by setting STORAGE_ENDPOINT, STORAGE_ACCESS_KEY_ID, STORAGE_SECRET_ACCESS_KEY, STORAGE_REGION. No code change required. SigV4 signing implemented from scratch; no SDK dependency.
Known debt:
PutObject, an orphaned object remains in storage. The subsequent attempt returns 409 (storage duplicate check catches it). A reconciliation process to re-drive the DB insert from storage is deferred to Phase 7.make smoke verifies the full round-trip including duplicate rejection (409).Objective: Prove multi-actor interaction.
Create minimal agent:
/statusImplement signing stub (even if local key).
Exit condition:
Status: Complete. agents/observer/ is a production-quality async Python agent (httpx, cryptography, structlog).
Observation dispatch (OBSERVE_TARGET env var):
https?://... — fetch URL, record status/headers/bodyEd25519 key loaded from AGENT_PRIVATE_KEY env (base64 raw seed) or generated ephemerally with public key logged at startup. Signatures verified by the control plane since Phase 7 (TOFU key registry; unsigned references rejected with 422).
Agent checks /status before each cycle and skips writes when STOPPED. Resumes automatically.
Objective: Human-readable state inspection.
Read-only views:
Exit condition:
Status: Complete. TypeScript source in dashboard/src/. Compiled output committed to dashboard/static/. Served by the control plane at http://localhost:8080/.
Three new read endpoints added to the control plane:
GET /canonicals?limit=N&offset=MGET /references?limit=N&offset=MGET /audit?limit=NDashboard shows: system mode (live status indicator), canonical objects table, agent references table, audit log. Auto-refreshes every 30 seconds. Rebuild with make dashboard (requires tsc). No Node required at runtime.
Objective: Prevent silent corruption.
Enforce:
Add:
Exit condition:
Status: Complete.
Signature verification — Ed25519 TOFU key registry (agent_keys table, migration 002). POST /reference requires signature and public_key. First submission from an agent_id registers the key; subsequent submissions verify against the stored key. Key mismatch or missing fields returns 422 with an actionable hint. Unsigned references rejected.
Object export — scripts/export_canonicals.sh paginates GET /canonicals and writes NDJSON to backups/canonicals_<ts>.ndjson. Run via make export.
Postgres backup — scripts/backup_pg.sh wraps pg_dump via docker compose exec. Writes backups/cognition_<ts>.sql.gz. Restore command documented in script header and printed after each run. Run via make backup.
Storage/DB orphan reconciliation — GET /reconcile endpoint on the control plane iterates all ledger entries, HEAD-checks each in MinIO, and returns a JSON summary with any missing paths. scripts/reconcile_storage.sh is the shell wrapper; exits 1 if anything is missing. Run via make reconcile.
Objective: Make the substrate understandable without you.
Write:
docs/trust-model.md ✓docs/lifecycle.md ✓docs/threat-model.md ✓Add:
docs/architecture-diagram.md)docs/data-flow-diagram.md)Plus (alignment pass):
d0e92df): read
endpoints (GET /canonicals, /references, /audit, /reconcile),
dashboard serving at /, observer service in docker-compose.yml,
AuditEntry model, DB list methods, make dashboard target..env.example rewritten to match the STORAGE_* env vars the control
plane actually reads.make up echo corrected (compose starts the control plane;
only make migrate is needed afterwards).docs/.Exit condition:
/docs + /schemas. ✓Objective: Close the last gaps between the roadmap’s claims and a system someone else can deploy without your help.
See docs/v1-readiness.md for the full checklist.
Short list:
pgx driver migration (retires the stdlib internal/pg driver and the
MD5-auth workaround).make install / one-shot deployable binary; reproducible Docker image.up → migrate → smoke → reconcile.Exit condition:
git clone && make up && make migrate && make smoke
from a cold cache and reach a signed green result without reading
issue tracker history.make reconcile passes on a populated system.Do not add yet:
These do not improve the substrate.
The project is functionally real when someone can:
make up
At that point, the substrate exists.
Everything beyond that is expansion, not foundation.
Current state: All six steps work today. The observer agent runs steps 2–3 automatically. The dashboard shows steps 4–6 without a terminal. Signatures are verified on every reference write since Phase 7.
| Item | Phase introduced | Blocking | Resolution |
|---|---|---|---|
Temporary stdlib Postgres driver (internal/pg) |
3 | No | Replace with pgx when Go 1.25 + network available. 5-step migration documented in internal/pg/pg.go. |
| MD5 auth only (no SCRAM-SHA-256) | 3 | No | Removed when pgx replaces internal/pg. |
| Storage-first write ordering (orphan risk) | 4 | No | GET /reconcile + make reconcile detects orphaned storage objects. Resolved Phase 7. |
CONTROL_API_KEY declared but not enforced by the router |
3 | Yes for v1.0 | Add auth middleware to write endpoints (and optionally read endpoints) before the v1.0 tag. |
| Audit log is append-only by convention, not cryptographically chained | 2 | No | Hash-chaining or external log shipping deferred to Phase 9 / post-v1.0. |
Signatures cover identity fields only (id:coid:agent_id:created_at) |
7 | No | Extend to full-payload signing in a later schema bump. |
Merge d0e92df silently dropped Phase 6/7 work (restored in Phase 8) |
8 | No | Restored from 8f09a7b; guard against recurrence via end-to-end CI in Phase 9. |
Boring systems survive.
The control plane is the invariant. Everything else — agents, dashboards, policies — is pluggable. The invariant is: a canonical object, once written, is never changed. That’s the only promise that has to hold.
The stdlib Postgres driver was a deliberate tradeoff. Staying offline and dependency-free during early phases meant the system could be built and verified without a network, without module mirrors, without version negotiation. The cost is MD5 auth and no prepared statements. Both are acceptable for a substrate that hasn’t reached production yet. When the build environment has Go 1.25 and a network, the replacement is straightforward.
The observer agent does more than the spec required — URL fetch, file read, and environment snapshot. That’s because “observe whatever it’s pointed at” is the right abstraction. A more constrained agent would need rewriting the moment the use case changed.
The dashboard is served by the control plane intentionally. One fewer moving part. One fewer port to configure. The operator opens a browser to the same address they already use for the API.
The TOFU key model is the right tradeoff for a substrate. Agents don’t need an out-of-band registration step — they just sign and submit. The first signed submission locks the key. This makes onboarding frictionless while still preventing impersonation after the first contact. The operator can rotate a key by editing the agent_keys table directly; that’s an intentional sharp edge that keeps the control plane simple.
The reconciliation endpoint lives in the control plane rather than as a standalone tool because it needs authenticated MinIO access (SigV4). Putting the HTTP surface in Go and the user-facing interface in a shell script keeps the separation clean: Go owns the credentials, bash owns the UX.