Skip to content

test(backend): cover clarification lifecycle clock behavior#42

Open
devcool20 wants to merge 3 commits into
inthhq:mainfrom
devcool20:fix/16-clarification-lifecycle-e2e
Open

test(backend): cover clarification lifecycle clock behavior#42
devcool20 wants to merge 3 commits into
inthhq:mainfrom
devcool20:fix/16-clarification-lifecycle-e2e

Conversation

@devcool20

Copy link
Copy Markdown

Closes #16

Summary

Adds backend e2e coverage for the clarification lifecycle over the real HTTP runtime.

The new test exercises:

  • request capture
  • verification request/approval
  • clarification request
  • clarification receive
  • fulfilment
  • timeline retrieval
  • legal clock explanation

It also verifies policy-driven clock behavior:

  • EU clarification pauses the clock and shifts the final deadline by the clarification pause duration
  • US clarification is recorded but does not shift the final deadline

Note: the issue mentions UK as the no-stop comparison, but the current UK policy pack uses the shared stop_clock clarification default. The existing no-stop clarification policy is covered with the US pack instead.

Validation

  • bun x ultracite check packages/backend/test/e2e/full-flow.api.e2e.test.ts
  • bun --cwd packages/backend vitest run test/e2e/full-flow.api.e2e.test.ts
  • cd packages/backend && bun run test:e2e

Notes

cd packages/backend && bun run typecheck currently fails in unrelated persistence crypto code involving Node Buffer type compatibility in packages/internals/persistence/src/services/persistence/webhook-secret-encryption.ts.

@coderabbitai

coderabbitai Bot commented May 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@KayleeWilliams, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 59 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 4c39e2c5-5684-4460-9a87-a2de2c3f2494

📥 Commits

Reviewing files that changed from the base of the PR and between cf72a7d and 39b2872.

📒 Files selected for processing (1)
  • packages/backend/test/e2e/full-flow.api.e2e.test.ts
📝 Walkthrough

Walkthrough

This PR extends the e2e full-flow test suite to validate clarification round-trip behavior with clock pause semantics. The changes introduce test infrastructure for capturing request/clarification lifecycle interactions, asserting clock segment pause windows and deadline shifts, and comparing policy-driven behavior divergence between EU and US jurisdictions.

Changes

Clarification Round-Trip E2E Test

Layer / File(s) Summary
Test setup, constants, and type definitions
packages/backend/test/e2e/full-flow.api.e2e.test.ts (1–61)
Imports delay utility for async timing control and adjusts test harness imports. Defines CLARIFICATION_RECEIPT_DELAY_MS constant and introduces local type shapes for clock segments, policy info, pause reasons, and clarification round-trip result aggregation.
Clarification round-trip helpers and utilities
packages/backend/test/e2e/full-flow.api.e2e.test.ts (91–239)
Implements helper functions to compute closed clock segment durations, select clock segments by reason and duration match, and execute the full clarification lifecycle round-trip (capture → verification → clarification request/receive with delay → fulfillment → clock/timeline fetch) with intermediate HTTP status assertions.
Clarification lifecycle e2e test
packages/backend/test/e2e/full-flow.api.e2e.test.ts (690–761)
Test case that runs the clarification round-trip for both EU and US policies, asserts timeline event sequences and pause reasons, validates clock segment inclusion and computed duration matching, and verifies policy pack/version and due-at invariants across jurisdictions.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A clarification pauses time, the clock must rest,
From EU rules to US west, we test each quest—
Capture, verify, receive, and round they go,
Timeline events and segments dance, the deadlines know! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding e2e test coverage for clarification lifecycle clock behavior.
Description check ✅ Passed The description clearly relates to the changeset, explaining the test coverage added and the policy-driven clock behavior being validated.
Linked Issues check ✅ Passed The PR meets all coding requirements from issue #16: exercises the full clarification round-trip, asserts clock segments with countsTowardDeadline validation, verifies deadline shifts, checks timeline events, and tests policy-driven divergence with EU and US packs.
Out of Scope Changes check ✅ Passed All changes are scoped to the e2e test file and directly support the clarification lifecycle test requirements with no out-of-scope modifications.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/backend/test/e2e/full-flow.api.e2e.test.ts`:
- Line 18: The test uses a too-small CLARIFICATION_RECEIPT_DELAY_MS (currently
10) causing flaky deadline-shift assertions where euDeadlineShiftMs may be 0;
increase CLARIFICATION_RECEIPT_DELAY_MS to a larger value (e.g. 50–200ms
depending on CI/storage resolution) wherever it's defined/used in this file
(symbol: CLARIFICATION_RECEIPT_DELAY_MS) and re-run tests, ensuring assertions
that compute euDeadlineShiftMs are stable; update all occurrences of that
constant in full-flow.api.e2e.test.ts so the clarification receipt delay is
consistently increased.
- Around line 189-203: Add explicit HTTP status assertions for the timeline and
clock explain requests: after sending the GET for
`/requests/${requestId}/timeline` (variables timeline and timelineBody) assert
the response status is the expected success code (e.g., 200) before calling
asEnvelope; do the same for the `/requests/${requestId}/clock/explain` response
(variables clock and clockBody). This ensures the flow test validates the HTTP
contract for the timeline and clock explain endpoints (and replicate the same
assertions for the subsequent similar block around lines 205-231).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 27ab34be-2696-4c1b-9429-4455a80fd3c5

📥 Commits

Reviewing files that changed from the base of the PR and between e0c300b and cf72a7d.

📒 Files selected for processing (1)
  • packages/backend/test/e2e/full-flow.api.e2e.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (3)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Use explicit types for function parameters and return values when they enhance clarity
Prefer unknown over any when the type is genuinely unknown
Use const assertions (as const) for immutable values and literal types
Leverage TypeScript's type narrowing instead of type assertions

Files:

  • packages/backend/test/e2e/full-flow.api.e2e.test.ts
**/*.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{js,jsx,ts,tsx}: Use meaningful variable names instead of magic numbers - extract constants with descriptive names
Use arrow functions for callbacks and short functions
Prefer for...of loops over .forEach() and indexed for loops
Use optional chaining (?.) and nullish coalescing (??) for safer property access
Prefer template literals over string concatenation
Use destructuring for object and array assignments
Use const by default, let only when reassignment is needed, never var
Always await promises in async functions - don't forget to use the return value
Use async/await syntax instead of promise chains for better readability
Handle errors appropriately in async code with try-catch blocks
Don't use async functions as Promise executors
Remove console.log, debugger, and alert statements from production code
Throw Error objects with descriptive messages, not strings or other values
Use try-catch blocks meaningfully - don't catch errors just to rethrow them
Prefer early returns over nested conditionals for error cases
Extract complex conditions into well-named boolean variables
Use early returns to reduce nesting
Prefer simple conditionals over nested ternary operators
Don't use eval() or assign directly to document.cookie
Avoid spread syntax in accumulators within loops
Use top-level regex literals instead of creating them in loops
Prefer specific imports over namespace imports
Use descriptive names for functions, variables, and types instead of relying on Oxlint + Oxfmt to catch naming issues
Add comments for complex logic, but prefer self-documenting code

Files:

  • packages/backend/test/e2e/full-flow.api.e2e.test.ts
**/*.{test,spec}.{js,jsx,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{test,spec}.{js,jsx,ts,tsx}: Write assertions inside it() or test() blocks
Avoid done callbacks in async tests - use async/await instead
Don't use .only or .skip in committed code
Keep test suites reasonably flat - avoid excessive describe nesting

Files:

  • packages/backend/test/e2e/full-flow.api.e2e.test.ts

Comment thread packages/backend/test/e2e/full-flow.api.e2e.test.ts Outdated
Comment thread packages/backend/test/e2e/full-flow.api.e2e.test.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR — Adds an e2e test that drives the clarification round-trip over the real HTTP runtime and asserts policy-driven clock behavior for EU (deadline shifts) vs US (deadline holds). The coverage is well-scoped and deterministic; a few small clarity polish suggestions inline.

Key changes

  • Add runClarificationRoundTrip helper — drives capture → verify → clarify request/receive → fulfil → timeline → clock/explain and returns the clock summary, request id, and timeline event types.
  • Cover EU clarification clock pause — asserts clarification segment has countsTowardDeadline: false, pauses includes clarification, and finalDueAt > baseDeadline.
  • Cover US clarification no-shift — asserts segments contain only base, pause is still recorded, and finalDueAt === baseDeadline.
  • Cross-jurisdiction timeline parity — both EU and US emit the same ordered event types.

Summary | 1 file | 1 commit | base: mainfix/16-clarification-lifecycle-e2e


Jurisdiction substitution vs issue #16

Before: Issue #16 asked for UK as the no-stop comparison.
After: Test uses US, because UK's policy pack currently inherits the shared stop_clock clarification default.

The PR body calls this out — worth a maintainer eyeball to confirm the substitution is intended rather than papering over a UK policy-pack gap that should itself be fixed.

packages/backend/test/e2e/full-flow.api.e2e.test.ts


Clock-segment duration coupling

Before: No e2e assertion on the relationship between clarification segment duration and deadline shift.
After: requireClockSegment(..., euDeadlineShiftMs) requires the EU clarification segment's to - from to equal finalDueAt - baseDeadline.

Both quantities derive from the same server-side timestamps, so this is effectively an identity check on the policy implementation — flakiness from the delay(10ms) is bounded by the > 0 assertion rather than absolute timing.

packages/backend/test/e2e/full-flow.api.e2e.test.ts

Pullfrog  | Fix all ➔Fix 👍s ➔View workflow run | Using Claude Opus𝕏

Comment thread packages/backend/test/e2e/full-flow.api.e2e.test.ts Outdated
Comment thread packages/backend/test/e2e/full-flow.api.e2e.test.ts

@pullfrog pullfrog Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No new issues. Reviewed the following changes:

  • Bumped CLARIFICATION_RECEIPT_DELAY_MS from 10ms to 200ms to harden the receipt-delay window against CI timestamp resolution.
  • Added HTTP status assertions for the /timeline and /clock/explain calls inside runClarificationRoundTrip, so the helper now covers the full happy-path status sequence.
  • Replaced the [eu.requestId, us.requestId].every(Boolean) truthiness check with expect(eu.requestId).not.toBe(us.requestId), which actually proves the two round-trips produced distinct requests.
  • Collapsed the self-equal array assertion for the US clock into a direct expect(us.clock.finalDueAt).toBe(us.clock.baseDeadline), making the no-shift contract explicit.

Pullfrog  | View workflow run | Using Claude Opus𝕏

@KayleeWilliams

Copy link
Copy Markdown
Collaborator

Thanks for contributing will check out this PR either later this week or next week, a bit busy traveling currently!

@KayleeWilliams

Copy link
Copy Markdown
Collaborator

Maintainer review: verified the UK-vs-US substitution — the UK pack inherits the shared stop_clock clarification default (packages/internals/policy-packs/src/packs/shared.ts), so the issue's premise about UK being no-stop was wrong and launch-us (no_stop_clock) is the correct divergence comparator. The 200ms wall-clock delay is justified since lifecycle timestamps come from nowIso() with no injection point, and the assertions compare persisted timestamps to each other, so the exact-duration checks are deterministic. Full issue #16 scope is covered (round-trip, pause segment with countsTowardDeadline: false, deadline shift equals pause duration, timeline, policy divergence). Pushed a merge of latest main; test-only change so no changeset needed. Verified locally: e2e suite passes. Fully closes #16.

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.

[backend] Clarification round-trip lifecycle test

2 participants