Skip to content

core: route procedural reads through a derived-stats compat helper (supports daemon aegis#564 Phase 2) #30

@stackbilt-admin

Description

@stackbilt-admin

Context

AEGIS daemon's aegis#564 Phase 2 shipped a compat helper (`getProcedureWithDerivedStats` / `getAllProceduresWithDerivedStats`) that logs cached-vs-derived drift into `shadow_read_drift` so the Phase 3 cached-column drop on `procedural_memory` can be data-driven.

The gap

The public routes that actually exercise procedural reads — `GET /procedures` and `GET /dashboard` — are owned by `@stackbilt/aegis-core`:

  • `src/routes/observability.ts:58` — `/procedures` calls bare `getAllProcedures`.
  • `src/dashboard.ts:4,118` (via `src/routes/pages.ts:36`) — `/dashboard` calls bare `getAllProcedures`.

First-match-wins in Hono mounting (core mounts before extensions in `src/core.ts:210-211`), so the daemon's instrumented duplicates are dead code. Net effect: the Phase 2 drift gauge stayed empty even under normal daemon traffic, because the router hot path (sample 0.1) is the only non-shadowed reader and episodic volume is low.

Daemon shipped a synthetic hourly `drift-probe` cron in v2.1.6 to unblock Phase 3 readiness, but that's a tactical patch — the correct long-term fix lives here.

Proposal

Move the compat helper down to aegis-core and swap both readers:

  1. Add `getProcedureWithDerivedStats` / `getAllProceduresWithDerivedStats` + `DriftLogOpts` to core's `kernel/memory/procedural.ts` (structure-identical port from daemon's `web/src/kernel/memory/procedural.ts`).
  2. Swap `src/dashboard.ts:getDashboardData` → `getAllProceduresWithDerivedStats(db, { reader: 'dashboard' })`.
  3. Swap `src/routes/observability.ts:/procedures` → `getAllProceduresWithDerivedStats(c.env.DB, { reader: 'observability' })`.
  4. Keep the compat layer gated on the `shadow_read_drift` table's existence (core shouldn't require a daemon-owned migration). Either check via `sqlite_master` on first call or no-op cleanly if the table isn't present.

Once published and pulled, daemon removes the `drift-probe` cron and the local `dashboard.ts` shadow.

Why now

Part of the `project_daemon_kernel_shadow.md` epic (daemon-side memory in `memory/project_daemon_kernel_shadow.md`). This is exactly the class of drift the collapse is meant to close: daemon ships instrumentation for a shared primitive, core doesn't know about it, the instrumentation silently no-ops.

References

cc: @stackbilt-admin

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions