Correct the governing documents where this session disproved them
Both documents are the first thing a new reader trusts, and several of their
claims were wrong — some wrong from the start, some overtaken by work this
week. A governing document that misdescribes the system is worse than none,
because it is believed.
CLAUDE.md §10 specified Python 3.11, FastAPI, SQLAlchemy and Alembic. The code
is Go and has never been anything else. That is corrected rather than quietly
deleted, so the next person understands the document drifted rather than
wondering which half to trust.
Also in CLAUDE.md: the tool count was 17 with one write and is 19 with two;
delegation now exists and §11's Orchestration row says what it guarantees; the
embedder deviation described a Voyage-or-stand-in choice that has since become
EMBED_PROVIDER with three options, of which production sets none.
The handover claimed three things that this session disproved by running them:
- "definition_versions is empty ... nothing has gone through it". It was not
empty in production; activity-agent had a v1 that the shipped file
contradicted, which is how a real drift was found. It now holds every
agent and skill.
- "Skills are still stored in user_preferences". They are rows in
skill_definitions, and are now versioned.
- "make eval-live ... has never been run". It has, it passes 3/3, and what
it established is recorded — including that the handbook corpus carries a
planted prompt injection which the agent refused and reported. That is I7
holding against a real model, which is worth more than the pass count.
The endpoint counts were one high throughout (55/57, not 56/58) — the delta of
two was always right, so the signal worked and the absolute numbers did not.
Added, because they cost time this week and would cost it again:
- the app reaches its database through pgbouncer, not PostgreSQL directly.
Enabling TLS on PostgreSQL does nothing for the application hop; pgbouncer
terminates 5432 and needs its own client_tls_sslmode.
- the seeded UserActivity is NOT anchored to today the way ShiftRecord is,
so it ages out of every window the activity tools offer. Twenty-three days
old as of writing: zero events in the last 7 days, 6 of 15 in the last 30.
The agent answers truthfully and the demo looks dead.
- the whole stack runs on Docker alone. Dockerfile.api builds every command
plus the migrate CLI, so a new machine needs neither Go nor psql — which
is how this one was set up, having no Homebrew.
- Ollama runs on the HOST, so a container reaches it at
host.docker.internal, not localhost. The old .env said localhost and would
have failed with nothing obviously wrong.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PJvibeSc1JYXjatankqM1g
This commit is contained in:
21
CLAUDE.md
21
CLAUDE.md
@@ -188,12 +188,16 @@ Each eval case:
|
||||
|
||||
## 10. Conventions
|
||||
|
||||
- Python 3.11+, FastAPI, async throughout. SQLAlchemy 2.0 style.
|
||||
- Type hints on every public function. `mypy --strict` on `src/registry/` and `src/runtime/`.
|
||||
- **Go** (see `go-api/go.mod`), standard library HTTP with `net/http` routing
|
||||
patterns, `pgx` for PostgreSQL. NOT Python: this document specified
|
||||
Python 3.11 / FastAPI / SQLAlchemy / Alembic and the code has never been any
|
||||
of those. Corrected here rather than left to mislead the next reader, which
|
||||
it did.
|
||||
- Exported functions carry doc comments. `go vet ./...` clean; `gofmt -w`.
|
||||
- Errors: structured exception types with a `code`, never bare strings. User-facing text is derived at the surface layer, not raised from the core.
|
||||
- Logging: structured JSON, always include `run_id`, `tenant_id`, `agent_key`, `agent_version`. Never log message content or retrieved chunks at INFO — that is a data leak into your log store. DEBUG only, behind a per-tenant flag.
|
||||
- Config via environment, validated once at startup into a frozen settings object. No `os.getenv` at call sites.
|
||||
- Migrations: Alembic, one per PR, reversible.
|
||||
- Migrations: golang-migrate, one per PR, reversible (`.up.sql` and `.down.sql`).
|
||||
|
||||
---
|
||||
|
||||
@@ -216,9 +220,9 @@ depends on the curated-versus-self-serve decision and is not settled.
|
||||
| Layer | State |
|
||||
|---|---|
|
||||
| Surfaces | `POST /api/v1/agents/{id}/runs` (streams over SSE on `Accept: text/event-stream`), `GET /api/v1/runs/{id}`; the chat panel is the only answering path — the browser simulator is deleted |
|
||||
| Orchestration | spec-driven loop, four bounds claimed before dispatch, six terminations, trajectories in `agent_runs` |
|
||||
| Orchestration | spec-driven loop, four bounds claimed before dispatch, six terminations, trajectories in `agent_runs`; delegation per §6 — a subagent is a tool call, runs as the caller, shares the parent budget, capped at depth 2, and writes its own trajectory linked by `parent_run_id` |
|
||||
| Registry | 9 agents + 23 skills as rows; published versions immutable (append-only, trigger-enforced); runs pin the version they started with |
|
||||
| Tools | 17, one of which writes, behind a bound single-use confirmation |
|
||||
| Tools | 19, two of which write (`move_application`, `assign_worker`), behind a bound single-use confirmation |
|
||||
| Knowledge | ACL-tagged ingest, hybrid dense + BM25 fused with RRF, pre-filtered |
|
||||
| Gateway | tier → model + effort, token accounting, refusal as an outcome |
|
||||
|
||||
@@ -233,8 +237,11 @@ depends on the curated-versus-self-serve decision and is not settled.
|
||||
- Vectors are `real[]` with a dot-product function rather than pgvector, which
|
||||
is not installed. Exact search, no ANN index, bounded by the ACL pre-filter.
|
||||
The upgrade is a column type change and no logic change.
|
||||
- Dense retrieval runs on a deterministic stand-in embedder until a Voyage key
|
||||
exists. It is **not semantic** and refuses to run in production.
|
||||
- Dense retrieval takes its embedder from `EMBED_PROVIDER`: `ollama` (local,
|
||||
real semantics, no credential), `voyage` (hosted), or `lexical` — a
|
||||
deterministic stand-in that is **not semantic** and that config validation
|
||||
refuses in production. Unset means keyword-only, which is what production
|
||||
runs today.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user