Skip to content

fix: content-anchored fixture matching + relaxed-turnIndex divergence warn/opt-out#276

Open
jpr5 wants to merge 4 commits into
mainfrom
fix/fixture-content-anchored-match
Open

fix: content-anchored fixture matching + relaxed-turnIndex divergence warn/opt-out#276
jpr5 wants to merge 4 commits into
mainfrom
fix/fixture-content-anchored-match

Conversation

@jpr5

@jpr5 jpr5 commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Makes aimock's fixture replay matching content-anchored: a fixture's recorded content/shape is the primary match key, and turnIndex is no longer a hard reject gate. This kills a class of false-misses where a multi-bubble / multi-turn run that drifts past its scripted turnIndex was spuriously rejected (empty assistant response), even though the content matched. The record path is unchanged — strict per-turn capture is preserved via MatchOptions.strictTurnIndex.

⚠️ Public replay-semantics change — please confirm intended

A fixture that previously force-missed on turnIndex will now match if its content predicates match. Empirically measured by replaying the real fixture corpora (showcase d6 + aimock examples) through the old vs new matcher — 786 fixture sets / 9769 requests:

  • 3213 MISS→MATCH (the intended false-miss fixes), 0 MATCH→MISS, 0 wrong-fixture selections (the 69 MATCH→DIFF are all same-content twins / forward-progress).
  • 0 changes at the canonical position (assistantCount == turnIndex) — divergence happens only when a conversation runs off-by-N from its scripted turn.

So this is a strict improvement on real corpora; it's a minor bump. (Content gating stays strict; multiple content matches → closest scripted turnIndex; all-ahead → unpositioned fallback.)

Not surprising anyone (detection + reversible opt-out)

For the divergence to be discoverable + reversible by the ~500k-downloads/wk user base:

  • AIMOCK_STRICT_TURN_INDEX=1 — process opt-out that restores the legacy strict-turnIndex hard gate for replay (default = new content-anchored behavior). This reversible escape hatch is what keeps the change a minor bump.
  • Surgical divergence warn — a once-per-fixture, logger-gated warn fires only when a served fixture's turnIndex was relaxed (i.e. the strict gate would have rejected it). Silent in programmatic use (logger default), so it never spams a test suite; for the typical record→replay user (who sits at the canonical position) divergence is rare, so the warn is a genuine, useful signal.
  • Diagnostic fields turnIndexRelaxed / matchedBy on the match diagnostic for inspection.

Review

Converged via two full cr-loop passes (content-anchored matching, then the warn package) — 7 unbiased agents/round + confirmation rounds + Procedure-3 audits (0 promotions). Notable fixes caught in review: WeakSet-identity throttle (predicate/RegExp fixtures no longer collide), accurate matchedBy attribution, and the divergence-direction wording.

Test plan

  • pnpm test4041 passed / 0 failed; tsc --noEmit clean; lint 0/0; build ok
  • Confirm the intended replay semantics (above) before merge

Known follow-ups (pre-existing, not this PR)

  • getSystemText/getTextContent present-but-empty "" stray-newline edge under useExactMatch.
  • Handler input-validation: unguarded parts/content derefs (gemini/cohere/responses/bedrock/bedrock-converse) → TypeError on malformed JSON.

Not auto-merging — flagging the replay-semantics change for review.

@pkg-pr-new

pkg-pr-new Bot commented Jun 23, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@copilotkit/aimock@276

commit: 74d4ffc

jpr5 added 4 commits June 23, 2026 16:19
…ivergence detection in router

Anchor fixture matcher selection on request content rather than positional
turnIndex, and add relaxed-turnIndex divergence detection: warn when a match
is found by content but diverges from the recorded turnIndex, with an
AIMOCK_STRICT_TURN_INDEX opt-out, per-fixture-identity throttle, and accurate
matchedBy reporting for predicate/regex fixtures.
Pass recordMatchOptions and the logger through the server record path into
each provider handler (messages, responses, gemini, bedrock, bedrock-converse,
cohere, ollama) so recorded fixtures carry the content-anchored match metadata.
Cover content-anchored fixture matching, record-path wiring, and relaxed
turnIndex detect/warn/opt-out behavior (red-green).
Document content-anchored relaxed-turnIndex replay matching, the divergence
warning direction, and the AIMOCK_STRICT_TURN_INDEX opt-out.
@jpr5 jpr5 force-pushed the fix/fixture-content-anchored-match branch from f571084 to 74d4ffc Compare June 23, 2026 23:23
@jpr5 jpr5 changed the title fix: content-anchored fixture matching (turnIndex no longer hard-rejects) fix: content-anchored fixture matching + relaxed-turnIndex divergence warn/opt-out Jun 23, 2026
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