Skip to content

test: reproduce HANDOFF finding 29 (handler-scoped session mutation races the reply snapshot) - #532

Draft
JarbasAl wants to merge 1 commit into
devfrom
fix/flush-context-before-snapshot
Draft

test: reproduce HANDOFF finding 29 (handler-scoped session mutation races the reply snapshot)#532
JarbasAl wants to merge 1 commit into
devfrom
fix/flush-context-before-snapshot

Conversation

@JarbasAl

Copy link
Copy Markdown
Member

🤖 Auto-generated by Claude Fable 5 (claude-fable-5) via Claude Code — NOT human-reviewed. Verify before acting.

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-workshop alone;
see "Design constraint" below.

What was found

Two write paths were probed with a real OVOSSkill + FakeBus +
add_event dispatch (no mocked peers), inspecting the actual
mycroft.skill.handler.complete message:

  • "raw" path — a handler calling
    SessionManager.get(message).set_intent_context(...) directly. This is
    already synchronous, in-process, and already correctly flushed into the
    handler-complete snapshot via ovos-bus-client's existing
    Message.forwardSessionManager.sync_message_session re-stamp
    (documented in ovos_spec_tools.session.SessionManager's class
    docstring). Green, no fix needed.
    (test_raw_session_write_is_flushed)

  • "wrapper" path — a handler calling skill.set_context() (the
    developer-facing adapt-context helper, ovos_workshop/skills/ovos.py:2498
    ovos_workshop/intents.py:_AdaptIntentApi.set_context). This only
    emits an async add_context bus message for ovos-core (a separate
    process 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_context
write onto SessionManager.get(msg).set_intent_context(...) synchronously,
before forwarding the add_context message (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 intent
one 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_context the same way a second, workshop-local write into
that map does - or desyncs from whatever ovos-core's own add_context
handler does with it. That handler lives outside ovos-workshop, so a safe
fix needs core-side visibility/cooperation (or a fix verified against a
real ovos-core intent-matching path), not a workshop-only patch built
blind to what add_context actually does on the other end.

Test evidence

  • test_raw_session_write_is_flushed: green before and after (already
    correct upstream via ovos-bus-client).
  • test_wrapper_set_context_is_flushed: red before, confirmed still open;
    marked xfail with the full investigation writeup in its docstring
    rather than silently skipped.
  • Full dev baseline: 567 passed, 0 failed (before this PR).
  • With this PR: 568 passed, 1 xfailed (permits merging without masking the
    open contract or claiming a fix that isn't safely verified).
  • test_intent_layers_e2e.py (the regression trap for the abandoned local
    fix): 2 passed, confirming this PR does not reintroduce that regression
    (it ships no behavior change, tests only).

Test plan

  • pytest test/unittests full suite green (568 passed, 1 xfailed)
  • Reproducer isolates raw-path (green) vs wrapper-path (red) mechanics
  • Attempted fix built, verified, and reverted after confirming its
    regression against test_intent_layers_e2e.py
  • Needs an ovos-core-side investigation of what its add_context
    handler / 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

…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>
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 72b46184-adc2-41c8-a510-46499ca5d0ae

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Tada! The results of the latest automation run are here. 🎉

I've aggregated the results of the automated checks for this PR below.

📋 Repo Health

Keeping the project in tip-top shape! 🏃

✅ All required files present.

Latest Version: 9.3.11a2

ovos_workshop/version.py — Version file
README.md — README
LICENSE — License file
pyproject.toml — pyproject.toml
⚠️ setup.py — setup.py
CHANGELOG.md — Changelog
ovos_workshop/version.py has valid version block markers

🔍 Lint

Evaluating 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 Tests

Running the forge to see if the code tempers correctly. 🔥

✅ All versions pass

Python Build Install Tests
3.10
3.11
3.12
3.13
3.14

Signed, sealed, and delivered by the OVOS bot. 📧

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant