Summary
`ouroboros_query_events` returns 0 events for auto sessions even when the interview loop demonstrably ran and emitted structlog events. This is the F2 follow-up from #1170 R2-diag (companion to PR-β #1252 substrate fix and PR-γ #1253 harness fix).
Diagnostic evidence
R2-diag (cli-todo canonical, auto_8afc447d551f, interview_c4dd59b4f57b43f7) showed:
mcp__ouroboros__ouroboros_query_events(auto_session_id) → 0 events.
mcp__ouroboros__ouroboros_session_status(interview_session_id) → "Session not found".
- Yet the interview loop demonstrably ran 12 rounds (visible in the BLOCKED envelope's blocker text and stop-reason).
Same regression observed in #1170 R2 (20260526-1636) and reproduced under R2-1709.
Root cause (confirmed by grep)
src/ouroboros/auto/interview_driver.py:41 uses structlog.get_logger(__name__) only. Every log.info(\"auto.interview.*\", ...) call goes to structlog's configured sink (stderr / stdout / file handler depending on env), not to EventStore.
EventStore is wired into the auto pipeline only via Ralph's job_event_store (see src/ouroboros/auto/pipeline.py:1350-1356 and adjacent). The interview phase has no parallel append path.
mcp__ouroboros__ouroboros_query_events reads from EventStore, so it never sees the interview events. There is no architectural bug — the two systems are genuinely separate.
Why this matters
The L0 acceptance gate (#1170) relies on post-hoc evidence inspection. With structlog as the only sink for interview events, query_events is misleading (returns 0 even when the interview ran), and the interview session detachment from session_status makes resume diagnostics opaque.
The user-visible promise of ooo auto (per SSOT #1157 Closure Policy, 2026-05-27) is "produce a verifiable artifact then refine via evolutionary loop." Verification depends on inspectable evidence; right now the interview phase produces none that query_events can surface.
Design questions (needs-design)
Two viable approaches; pick one as the design contract:
Option A — Wire interview events to EventStore
Make interview_driver append a typed auto.interview.* event family to EventStore alongside its structlog emission. New event family entries (per #946 substrate vocabulary):
auto.interview.opened / auto.interview.round_answered / auto.interview.ledger_only_closure / auto.interview.safe_default.{entered,closed,partial_unsafe_gaps} / auto.interview.blocked.
Pros: query_events becomes the SSOT for interview evidence. Resume diagnostics work. L0 evidence files can pull from one queryable surface.
Cons: new substrate (event family registration, schema migration if any). Coupling between interview_driver and EventStore wiring (currently interview_driver is store-agnostic).
Option B — Clarify the contract; expand inspectability via interview_session_id
Keep structlog as interview-event sink; expose a separate mcp__ouroboros__ouroboros_interview_status(interview_session_id) (or extend session_status to resolve nested interview ids). Document that query_events is for EventStore-stream events only (Ralph job lifecycle, watchdog, etc.).
Pros: minimal substrate addition. Honors existing separation.
Cons: dual surfaces for evidence retrieval. Acceptance reporter (#1170) must consult both. Doesn't fix the "Session not found" detachment by itself — interview events still aren't in a queryable store.
Recommendation
Option A aligns better with SSOT #1157's "every terminal carries one typed reason_code, no silent abandonment" invariant (Success Conditions #5/#7). A single queryable EventStore surface for the interview phase makes the canonical acceptance contract (#1170) verifiable without out-of-band log scraping. The substrate addition is bounded — one event family, additive to projection v1.
Acceptance criteria
Companion work
References
Summary
`ouroboros_query_events` returns 0 events for auto sessions even when the interview loop demonstrably ran and emitted structlog events. This is the F2 follow-up from #1170 R2-diag (companion to PR-β #1252 substrate fix and PR-γ #1253 harness fix).
Diagnostic evidence
R2-diag (cli-todo canonical,
auto_8afc447d551f,interview_c4dd59b4f57b43f7) showed:mcp__ouroboros__ouroboros_query_events(auto_session_id)→ 0 events.mcp__ouroboros__ouroboros_session_status(interview_session_id)→ "Session not found".Same regression observed in #1170 R2 (20260526-1636) and reproduced under R2-1709.
Root cause (confirmed by grep)
src/ouroboros/auto/interview_driver.py:41usesstructlog.get_logger(__name__)only. Everylog.info(\"auto.interview.*\", ...)call goes to structlog's configured sink (stderr / stdout / file handler depending on env), not toEventStore.EventStoreis wired into the auto pipeline only via Ralph'sjob_event_store(seesrc/ouroboros/auto/pipeline.py:1350-1356and adjacent). The interview phase has no parallel append path.mcp__ouroboros__ouroboros_query_eventsreads from EventStore, so it never sees the interview events. There is no architectural bug — the two systems are genuinely separate.Why this matters
The L0 acceptance gate (#1170) relies on post-hoc evidence inspection. With structlog as the only sink for interview events,
query_eventsis misleading (returns 0 even when the interview ran), and the interview session detachment fromsession_statusmakes resume diagnostics opaque.The user-visible promise of
ooo auto(per SSOT #1157 Closure Policy, 2026-05-27) is "produce a verifiable artifact then refine via evolutionary loop." Verification depends on inspectable evidence; right now the interview phase produces none thatquery_eventscan surface.Design questions (needs-design)
Two viable approaches; pick one as the design contract:
Option A — Wire interview events to EventStore
Make
interview_driverappend a typedauto.interview.*event family toEventStorealongside its structlog emission. New event family entries (per #946 substrate vocabulary):auto.interview.opened/auto.interview.round_answered/auto.interview.ledger_only_closure/auto.interview.safe_default.{entered,closed,partial_unsafe_gaps}/auto.interview.blocked.Pros:
query_eventsbecomes the SSOT for interview evidence. Resume diagnostics work. L0 evidence files can pull from one queryable surface.Cons: new substrate (event family registration, schema migration if any). Coupling between interview_driver and EventStore wiring (currently interview_driver is store-agnostic).
Option B — Clarify the contract; expand inspectability via interview_session_id
Keep structlog as interview-event sink; expose a separate
mcp__ouroboros__ouroboros_interview_status(interview_session_id)(or extendsession_statusto resolve nested interview ids). Document thatquery_eventsis for EventStore-stream events only (Ralph job lifecycle, watchdog, etc.).Pros: minimal substrate addition. Honors existing separation.
Cons: dual surfaces for evidence retrieval. Acceptance reporter (#1170) must consult both. Doesn't fix the "Session not found" detachment by itself — interview events still aren't in a queryable store.
Recommendation
Option A aligns better with SSOT #1157's "every terminal carries one typed reason_code, no silent abandonment" invariant (Success Conditions #5/#7). A single queryable EventStore surface for the interview phase makes the canonical acceptance contract (#1170) verifiable without out-of-band log scraping. The substrate addition is bounded — one event family, additive to projection v1.
Acceptance criteria
log.info(\"auto.interview.safe_default.entered\", ...)and the other interview structured events also callEventStore.append_event(...)(or equivalent) with the same payload shape.mcp__ouroboros__ouroboros_query_events(auto_session_id)returns the interview event stream when re-running the Meta SSOT slice: L0 — Canonical Test Harness for ooo auto acceptance #1170 R2-diag scenario.mcp__ouroboros__ouroboros_session_status(interview_session_id)resolves the nested interview session id (no "Session not found").Companion work
References