Skip to content

fix: close post-merge test gaps in hooks + Phase-2 history - #140

Merged
saucam merged 2 commits into
mainfrom
test/hooks-history-gaps
Jul 10, 2026
Merged

fix: close post-merge test gaps in hooks + Phase-2 history#140
saucam merged 2 commits into
mainfrom
test/hooks-history-gaps

Conversation

@saucam

@saucam saucam commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator

What

Post-merge testing audit of #137 (hook bus) and #138 (Phase-2 history). The merged combination passes the full suite (1233 tests) and the new files measure 99–100% line coverage, but four behaviors were untested. This PR covers them — tests only, no product code changes.

New coverage

canonical-sdk-compat.test.ts — pins the riskiest converter integration points to the actual installed SDKs instead of code comments:

  • toGeminiContent output is fed through the real @google/generative-ai startChat(), whose constructor runs validateChatHistory synchronously (offline, zero network). A negative control (functionResponse on a user turn — the design doc's original sketch) proves the validator actually fires, so the role-"function" decision can't silently regress on an SDK bump.
  • toOpenAIMessages output is assigned to ChatCompletionMessageParam[] without a cast, so bun run typecheck enforces structural compatibility — the provider call site uses a cast, which would hide drift.

session-hooks.test.ts H8–H11:

  • H8 — hook input mutation composed with manual approval (previous coverage was autonomous-mode only): the approval UI delta shows the hook-rewritten input, and the approved merge base is the mutated input, not the model's original.
  • H9/H10/H11 — the provider_switched, rotated, and session_end observe emits, none of which were exercised before (only session_start/after_turn were).

Test-harness fix

The observe-hook assertions now wait for parseable JSON, not file existence — cat > file creates the file before the payload bytes land, which made H9/H11 flaky. H8 also waits for the mutation broadcast rather than waiting_approval (the tool_start handler flips that status from its side-effect-free peek before the hook gate runs, so status alone races the hook).

bun run test (1233 pass), typecheck, lint green.

🤖 Generated with Claude Code

Post-merge audit of #137/#138 found four untested behaviors; all now
covered, no product code changes:

- canonical-sdk-compat.test.ts: toGeminiContent output validated by the
  REAL @google/generative-ai validateChatHistory (startChat constructor,
  offline) with a negative control proving the validator fires — pins
  the role:"function" decision to the SDK, not to a code comment.
  toOpenAIMessages output assigned to ChatCompletionMessageParam[]
  WITHOUT a cast so typecheck enforces shape compatibility (the provider
  call site casts, which would hide drift).
- session-hooks H8: hook input mutation composed with MANUAL approval —
  the approval UI delta shows the hook-rewritten input and the approved
  merge base is the mutated input, not the model's original.
- session-hooks H9/H10/H11: provider_switched, rotated, and session_end
  observe emits (previously only session_start/after_turn were covered).

Also hardens the observe-hook file waits: wait for parseable JSON, not
file existence — 'cat > file' creates the file before the payload lands.
@codecov

codecov Bot commented Jul 10, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 82.07%. Comparing base (8e9e86a) to head (d04cead).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@           Coverage Diff           @@
##             main     #140   +/-   ##
=======================================
  Coverage   82.07%   82.07%           
=======================================
  Files          97       97           
  Lines       16867    16867           
=======================================
  Hits        13843    13843           
  Misses       3024     3024           
Flag Coverage Δ
daemon 82.07% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

provider-gemini.test.ts installs a process-global
mock.module("@google/generative-ai"), so whether an in-process import
sees the real SDK depends on test-file execution order — passed locally,
failed in CI (startChat returned the mock's {sendMessageStream} stub and
the negative control stopped throwing). Move the validation into a
spawned fixture (fake-pi pattern): a fresh process is mock-proof and
order-independent.
@saucam

saucam commented Jul 10, 2026

Copy link
Copy Markdown
Collaborator Author

/gemini-review

@saucam
saucam merged commit 3108619 into main Jul 10, 2026
4 checks passed
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