test: reproduce HANDOFF finding 29 (handler-scoped session mutation races the reply snapshot) - #532
test: reproduce HANDOFF finding 29 (handler-scoped session mutation races the reply snapshot)#532JarbasAl wants to merge 1 commit into
Conversation
…s snapshot race) Adds a red/xfail reproducer for the "handler-scoped session mutations must be flushed before the handler's session snapshot finalizes" contract (ovos-core HANDOFF.md finding 29), using a real OVOSSkill + FakeBus + add_event dispatch (no mocked peers). Findings: - the "raw" write path (a handler calling SessionManager.get(message).set_intent_context(...) directly) is already synchronous in-process and already correctly flushed into the mycroft.skill.handler.complete snapshot, via ovos-bus-client's existing Message.forward -> SessionManager.sync_message_session re-stamp. Green, no fix needed (test_raw_session_write_is_flushed). - the "wrapper" write path (skill.set_context(), the developer-facing adapt-context helper) only emits an async `add_context` bus message for ovos-core to apply; it never touches this process's own session singleton, so the re-stamp is a no-op and the handler-complete snapshot never carries the mutation. Confirmed red (test_wrapper_set_context_is_flushed, xfail). A workshop-local fix (mirroring the write onto SessionManager.get(msg).set_intent_context(...) before forwarding) was built and closes the gap in isolation, but regresses test_intent_layers_e2e.py::test_layers_advance_in_sequence_and_gate_intents (matches the PREVIOUS layer's intent one step late) - real ovos-core intent-matching apparently does not consult Session.intent_context the same way a second, workshop-local write into that map does, or desyncs from ovos-core's own `add_context` handling. That handler lives outside this repo, so a safe fix needs core-side cooperation, not a workshop-only patch. See the xfail test docstring for the full account. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Tada! The results of the latest automation run are here. 🎉I've aggregated the results of the automated checks for this PR below. 📋 Repo HealthKeeping the project in tip-top shape! 🏃 ✅ All required files present. Latest Version: ✅ 🔍 LintEvaluating the overall quality of your PR. ✨ ❌ ruff: issues found — see job log 🔒 Security (pip-audit)I've scanned the dependencies for any hidden surprises. 🔍 ✅ No known vulnerabilities found (74 packages scanned). 🔨 Build TestsRunning the forge to see if the code tempers correctly. 🔥 ✅ All versions pass
Signed, sealed, and delivered by the OVOS bot. 📧 |
Summary
Investigates and reproduces ovos-core HANDOFF.md finding 29: "handler-scoped
session mutations must be flushed before the handler's session snapshot
finalizes" (live A/B probe measured ~40% loss window on TEXT-query paths;
voice-wake is listener-side and unaffected per the severity correction in
the same HANDOFF entry).
This PR adds a reproducer only - it does not ship the fix. The
investigation found the fix does not safely live in
ovos-workshopalone;see "Design constraint" below.
What was found
Two write paths were probed with a real
OVOSSkill+FakeBus+add_eventdispatch (no mocked peers), inspecting the actualmycroft.skill.handler.completemessage:"raw" path — a handler calling
SessionManager.get(message).set_intent_context(...)directly. This isalready synchronous, in-process, and already correctly flushed into the
handler-complete snapshot via
ovos-bus-client's existingMessage.forward→SessionManager.sync_message_sessionre-stamp(documented in
ovos_spec_tools.session.SessionManager's classdocstring). Green, no fix needed.
(
test_raw_session_write_is_flushed)"wrapper" path — a handler calling
skill.set_context()(thedeveloper-facing adapt-context helper,
ovos_workshop/skills/ovos.py:2498→
ovos_workshop/intents.py:_AdaptIntentApi.set_context). This onlyemits an async
add_contextbus message for ovos-core (a separateprocess in production) to apply; it never touches this process's own
session singleton, so the re-stamp is a no-op and the reply snapshot
never carries the mutation. Confirmed red.
(
test_wrapper_set_context_is_flushed,@unittest.expectedFailure)Design constraint (why no fix is shipped here)
A workshop-local fix was built: mirror the
set_context/remove_contextwrite onto
SessionManager.get(msg).set_intent_context(...)synchronously,before forwarding the
add_contextmessage (so the forwarded snapshot -and the handler-complete snapshot - already carry it).
In isolation this closed the gap (both reproducer tests green). But it
regressed
test/unittests/skills/test_intent_layers_e2e.py::test_layers_advance_in_sequence_and_gate_intents(2/2 passing on
dev→ consistently matching the previous layer's intentone step late, with the fix in place). That e2e test exercises the real
ovos-core intent-matching path (ovos-adapt's context-gated matching).
Reverting the workshop-local mirror restores it to green.
This means real ovos-core intent matching does not consult
Session.intent_contextthe same way a second, workshop-local write intothat map does - or desyncs from whatever ovos-core's own
add_contexthandler does with it. That handler lives outside
ovos-workshop, so a safefix needs core-side visibility/cooperation (or a fix verified against a
real
ovos-coreintent-matching path), not a workshop-only patch builtblind to what
add_contextactually does on the other end.Test evidence
test_raw_session_write_is_flushed: green before and after (alreadycorrect upstream via
ovos-bus-client).test_wrapper_set_context_is_flushed: red before, confirmed still open;marked
xfailwith the full investigation writeup in its docstringrather than silently skipped.
devbaseline: 567 passed, 0 failed (before this PR).open contract or claiming a fix that isn't safely verified).
test_intent_layers_e2e.py(the regression trap for the abandoned localfix): 2 passed, confirming this PR does not reintroduce that regression
(it ships no behavior change, tests only).
Test plan
pytest test/unittestsfull suite green (568 passed, 1 xfailed)regression against
test_intent_layers_e2e.pyovos-core-side investigation of what itsadd_contexthandler / adapt engine context-gating actually consults, to design a
fix that doesn't desync from it
Related: adapt#66 probe findings (~40% window); naptime two-turn goldens
parked on this; ovos-skill-alerts#150 wake-arbitration.
🤖 Generated with Claude Code