Background
aegis-daemon ships a Phase 2 shadow-read drift gauge (aegis#564) that writes rows into shadow_read_drift as readers (router / dashboard / decision-docs / overworld / mcp) exercise getProcedureWithDerivedStats / getAllProceduresWithDerivedStats. The diagnostic endpoint GET /api/shadow-read-drift is how the Phase 3 readiness gate is measured (p95 drift + per-pair readiness). An adjacent endpoint GET /api/entropy also lives only on the daemon side.
During v2.1.4 deploy we hit the project_daemon_kernel_shadow pattern: the daemon's web/src/routes/observability.ts is a superset of core's but was never imported by the daemon's src/index.ts, so both endpoints 404'd. v2.1.5 thin-mounted the daemon router via createAegisApp extension routes (relying on core winning first-match for colliding paths). That unblocks the rollout but leaves the two endpoints permanently shadow-forked.
Ask
Port the two endpoints into aegis-oss/web/src/routes/observability.ts:
-
GET /api/shadow-read-drift — p50/p95/p99 absolute drift per reader (nearest-rank — D1 lacks percentile_cont), readiness gauge partitioned by (reader, task_pattern), top-15 drifters. Uses the shadow_read_drift table (migration 0030_shadow_read_drift.sql lives in the daemon; the table needs to exist in any downstream variant that turns the gauge on). Source of truth is currently aegis-daemon/web/src/routes/observability.ts:82-181.
-
GET /api/entropy — wraps detectEntropy(env) from kernel/scheduled/entropy.js. Source: aegis-daemon/web/src/routes/observability.ts:75-80.
Coordination
- The Phase 2 shadow-read infrastructure (migration, bulk aggregator, drift-log codepath, scheduled prune) currently lives in the daemon's local
kernel/memory/procedural.ts + kernel/scheduled/shadow-read-prune.ts. These may also be shadow forks — if they are, porting just the route alone won't be enough (the table and writer need to live upstream too). Worth one grep pass before deciding scope.
- After the port ships in a new
@stackbilt/aegis-core release and the daemon bumps the dep, remove the daemon-side thin mount (src/index.ts additionalRoutes entry and the observability import).
Context
- Daemon PR that added the endpoints: Stackbilt-dev/aegis#569
- Daemon fix that thin-mounted: commit b8573fb (v2.1.5)
- Project memory:
project_daemon_kernel_shadow.md
Background
aegis-daemon ships a Phase 2 shadow-read drift gauge (aegis#564) that writes rows into
shadow_read_driftas readers (router / dashboard / decision-docs / overworld / mcp) exercisegetProcedureWithDerivedStats/getAllProceduresWithDerivedStats. The diagnostic endpointGET /api/shadow-read-driftis how the Phase 3 readiness gate is measured (p95 drift + per-pair readiness). An adjacent endpointGET /api/entropyalso lives only on the daemon side.During v2.1.4 deploy we hit the
project_daemon_kernel_shadowpattern: the daemon'sweb/src/routes/observability.tsis a superset of core's but was never imported by the daemon'ssrc/index.ts, so both endpoints 404'd. v2.1.5 thin-mounted the daemon router viacreateAegisAppextension routes (relying on core winning first-match for colliding paths). That unblocks the rollout but leaves the two endpoints permanently shadow-forked.Ask
Port the two endpoints into
aegis-oss/web/src/routes/observability.ts:GET /api/shadow-read-drift— p50/p95/p99 absolute drift per reader (nearest-rank — D1 lackspercentile_cont), readiness gauge partitioned by(reader, task_pattern), top-15 drifters. Uses theshadow_read_drifttable (migration0030_shadow_read_drift.sqllives in the daemon; the table needs to exist in any downstream variant that turns the gauge on). Source of truth is currentlyaegis-daemon/web/src/routes/observability.ts:82-181.GET /api/entropy— wrapsdetectEntropy(env)fromkernel/scheduled/entropy.js. Source:aegis-daemon/web/src/routes/observability.ts:75-80.Coordination
kernel/memory/procedural.ts+kernel/scheduled/shadow-read-prune.ts. These may also be shadow forks — if they are, porting just the route alone won't be enough (the table and writer need to live upstream too). Worth one grep pass before deciding scope.@stackbilt/aegis-corerelease and the daemon bumps the dep, remove the daemon-side thin mount (src/index.tsadditionalRoutes entry and theobservabilityimport).Context
project_daemon_kernel_shadow.md