Latest Results
Wire layered memory (org/agent/project) into the working loop on a durable substrate (#2615)
## What this does
Makes three-layer memory (org / agent / project) actually reach a
working agent's context, durably and safely. The audit found the gap was
deeper than the issue diagnosed: the shared backend in the default
container was an ephemeral in-process dict with a substring matcher, and
the real factory + embedder resolver had no caller anywhere in `src/`.
So project-brain, the knowledge/RAG substrate and living-docs were all
doing substring matching over a dict that emptied on every restart,
while the settings page declared a Mem0 backend that boot silently
ignored.
## The shape
```
AgentEngine._prepare_context
-> MemoryInjectionStrategy (proactive, all three layers, one shared budget)
-> RRF(dense, sparse) -> rerank -> MMR -> calibrated floor -> top-5
-> MemoryBackend protocol (unchanged)
-> PgVectorBackend (Postgres: pgvector + tsvector/pg_trgm)
-> SqliteVecBackend (SQLite: sqlite-vec + FTS5)
```
Everything above the protocol already existed and was merely unreached.
Only the storage leaf is new. Mem0 + qdrant-client are removed.
### Substrate
- `PgVectorBackend` + `SqliteVecBackend` behind the existing
`MemoryBackend` protocol, inside the persistence boundary, with
dual-backend conformance tests. Postgres image swapped to the hardened
`dhi.io/pgvector` variant (no security regression).
### Boot
- `memory_backend_wiring.py` resolves the embedder, builds the backend
and wires it **before** runtime services read it. **Fails loud** when no
embedder resolves (no silent keyword fallback); the ephemeral store is
an explicit, confirm-gated, degraded opt-in only.
### Retrieval
- `MemoryRecallRequest` composes the query from task + objective + role
+ department + project; cross-layer unified ranking; tuned defaults (RRF
+ rerank + MMR); a **calibrated** relevance floor (not a bare cosine
cutoff) with a first-class inject-nothing branch.
### Write path
- Agent self-edits through the MemGPT-style tools; a **deterministic**
gate dedups and supersedes at write time (no LLM, no per-task cost).
Success + procedural capture, distillation, and the consolidation
service are wired to a scheduler so `memory.consolidation_enabled` and
its knobs become real.
### Proof
- Golden recall eval harness scoring the tuned config against the naive
baseline on precision@k / recall@k / pollution, including abstention
cases, run in CI.
## Review hardening (two `/pre-pr-review` rounds)
- **Project isolation** (top security finding, was inert by default):
every write now lands in its project namespace (derived from the ambient
execution identity, or the source group for consolidation), and every
read â CONTEXT, TOOL_BASED, SELF_EDITING, the write-gate dedup, offload
rehydrate â is scoped to the project's namespace union. Proven
end-to-end across all three strategies.
- **Collaborator wiring** (was a latent boot crash): enabling rerank /
hierarchical retrieval / query-reformulation now constructs each
collaborator from the engine's explicit provider on its pinned model,
instead of raising in the strategy constructor.
- **Persistence**: HNSW index built `CONCURRENTLY` behind a session
advisory lock; filtered dense search under `SET LOCAL
hnsw.iterative_scan`; oldest-first cap eviction; connection-state leaks
closed.
- **Redaction**: credentials and emails masked before storage, with the
finding report proven never to quote the secret it removed.
- Plus a surfaced pre-existing perf bug: unseeded auto-name generation
built a 57-locale Faker (~6s) to draw one name; now samples one locale
(sub-100ms).
## Verification
All pre-push gates green: consolidated Python gates, mypy, the affected
unit suite, dual-backend parity, module size, magic numbers, licence
compatibility, provider auto-pick, architecture drift, and runtime-stats
freshness.
Closes #2608 Make a greenlit initiative one connected, status-rolling graph (#2610)
Closes #2607
A greenlit objective now becomes an owned, planned, verified initiative
you can supervise: the project knows its plan, plan items know their
tasks, and status rolls up from the work.
## The model
**Scalar keys up, collections derived.** `Project.plan_id`,
`Task.plan_id`, `Task.plan_item_id` are new; `Project.task_ids` is
deleted outright. It was write-orphaned (declared, persisted, never
populated) and is the cautionary case: a collection embedded in a row
cannot stay correct under concurrent writes, which is why the dashboard
showed a task count of zero next to a full task list. Reverse lookups
are indexed queries instead.
**Real state machines.** `Plan` and `Project` both gain a transition
table on the shared `core/state_machine.py`, as `Task` already had.
`PlanStatus` gains `EXECUTING` and `COMPLETED`; `APPROVED` stops being
terminal because it dispatches. There is deliberately **no failed
project status**: nothing can honestly derive that an initiative is dead
(an oracle `REJECT` routes a task back to rework, and a `FAILED` task
stays reassignable), so a derived failure would flap. Ending an
initiative stays a human act; failed and blocked work surfaces as
derived counts.
**Verification-derived rollup.** `ProjectRollupService` registers as a
`TaskEngine` observer and, on each event, re-queries every task for the
plan and recomputes from scratch. Two properties are load-bearing:
recompute is idempotent, so a dropped best-effort event heals on the
next one without a reconciler; and it reads *persisted* `Task.status`,
never `DispatchResult` outcomes. The coordination-level parent rollup
does the latter and so counts an `IN_REVIEW` task as done â the
initiative rollup cannot, which is what stops a project completing on
unverified work.
**Re-planning.** A plan under review is edited in place. Once dispatched
its items are already building, so `POST /plans/{id}/replan` retires the
current revision, cancels the work it started, opens a successor under
review, and repoints the project. The ordering protects one invariant: a
project never has two live plans.
**Operator surface.** `GET /projects/{id}/progress` serves per-item
status, derived counts, and the critical path through the plan's item
DAG, computed server-side so it is reachable by any API client rather
than only the browser. The project page renders it; the dashboard
persists nothing.
## Notes for review
- `CREATE INDEX CONCURRENTLY` on `tasks` runs outside a transaction, so
each change is expressed as one `ALTER TABLE` â the `plans` CHECK is
swapped in a single statement rather than dropped and re-added, so there
is never a window without a status constraint.
- The claim that the review gate is the *only* path to `COMPLETED` is
stated as a property of which writers are wired, not a structural
guarantee: the lifecycle-only baseline execution service and the
coordination parent rollup both reach it without the oracle chain.
- `generate_endpoint_table.py` could not run at all (7 tags missing from
`TAG_TO_SECTION`), which is why `docs/openapi/index.md` had drifted as
far as Providers 20 vs 34. Fixed, and the `--check` hook its docstring
already claimed now exists.
## Verification
37678 unit; 2310 dual-backend conformance; 3933 web plus tsc and ESLint;
mypy strict over 6368 files; both schema-drift arms; full pre-push gate
set.
The full integration tier could not be driven green locally: running
~3600 tests at `-n 8` against a single Postgres container saturates the
machine and the 30s per-test timeout kills workers at the same ~82%
mark. Root-caused rather than assumed â the abort point is identical
with and without the migration change, every aborting test is a Postgres
infra test untouched by this diff, and `tests/integration/persistence`
passes 89/89 at full parallelism. That tier gets its real verdict from
CI. Latest Branches
0%
release-please--branches--main--components--synthorg 0%
feat/layered-memory-wiring 0%
feat/project-plan-task-linkage ÂĐ 2026 CodSpeed Technology