-
-
Notifications
You must be signed in to change notification settings - Fork 26
fix: exempt AMRAP leases from rep freshness gate (#700) #701
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -154,6 +154,103 @@ class RepNotificationFreshnessGateTest { | |
| ) | ||
| } | ||
|
|
||
| // --- Issue #698: Just Lift target mismatch exemption --- | ||
|
|
||
| @Test | ||
| fun `just lift lease accepts repsSetTotal 252 despite finite UI target`() { | ||
| val gate = RepNotificationFreshnessGate() | ||
| val lease = activeLease(target = 10, cutover = 1_000L).copy(isJustLift = true) | ||
|
|
||
| // First packet establishes baseline and arms | ||
| assertEquals(RepFreshnessDecision.BaselineOnly, gate.evaluate(lease, modernPacket(timestamp = 1_001L))) | ||
| assertEquals(RepFreshnessState.Armed, gate.stateFor(lease)) | ||
|
|
||
| // repsSetTotal=252 (unlimited) should NOT be dropped as TARGET_MISMATCH | ||
| assertEquals( | ||
| RepFreshnessDecision.Process, | ||
| gate.evaluate(lease, modernPacket(repsSetCount = 1, repsSetTotal = 252, timestamp = 1_002L)), | ||
| ) | ||
| } | ||
|
|
||
| @Test | ||
| fun `just lift lease does not treat repsSetCount as terminal`() { | ||
| val gate = RepNotificationFreshnessGate() | ||
| val lease = activeLease(target = 3, cutover = 1_000L).copy(isJustLift = true) | ||
|
|
||
| // repsSetCount=3 >= workingRepTarget=3 would be terminal for finite, | ||
| // but Just Lift should process it normally after baseline | ||
| assertEquals(RepFreshnessDecision.BaselineOnly, gate.evaluate(lease, modernPacket(timestamp = 1_001L))) | ||
| assertEquals( | ||
| RepFreshnessDecision.Process, | ||
| gate.evaluate(lease, modernPacket(repsSetCount = 3, repsSetTotal = 252, timestamp = 1_002L)), | ||
| ) | ||
| } | ||
|
|
||
| @Test | ||
| fun `finite lease still rejects mismatched repsSetTotal after fix`() { | ||
| val gate = RepNotificationFreshnessGate() | ||
| val lease = activeLease(target = 3, cutover = 1_000L) // isJustLift = false | ||
|
|
||
| assertEquals( | ||
| RepFreshnessDecision.Drop(RepDropReason.TARGET_MISMATCH), | ||
| gate.evaluate(lease, modernPacket(repsSetCount = 1, repsSetTotal = 252, timestamp = 1_001L)), | ||
| ) | ||
| } | ||
|
|
||
| // --- Issue #700: AMRAP target mismatch exemption (mirrors #698 Just Lift tests) --- | ||
|
|
||
| @Test | ||
| fun `amrap lease accepts repsSetTotal 252 despite finite UI target`() { | ||
| val gate = RepNotificationFreshnessGate() | ||
| val lease = activeLease(target = 0, cutover = 1_000L).copy(isAmrap = true) | ||
|
|
||
| // First packet establishes baseline and arms | ||
| assertEquals(RepFreshnessDecision.BaselineOnly, gate.evaluate(lease, modernPacket(timestamp = 1_001L))) | ||
| assertEquals(RepFreshnessState.Armed, gate.stateFor(lease)) | ||
|
|
||
| // repsSetTotal=252 (unlimited) should NOT be dropped as TARGET_MISMATCH for AMRAP | ||
| assertEquals( | ||
| RepFreshnessDecision.Process, | ||
| gate.evaluate(lease, modernPacket(repsSetCount = 1, repsSetTotal = 252, timestamp = 1_002L)), | ||
| ) | ||
| } | ||
|
|
||
| @Test | ||
| fun `amrap lease does not treat repsSetCount as terminal`() { | ||
| val gate = RepNotificationFreshnessGate() | ||
| val lease = activeLease(target = 0, cutover = 1_000L).copy(isAmrap = true) | ||
|
|
||
| // AMRAP should never treat repsSetCount as terminal, same as Just Lift | ||
| assertEquals(RepFreshnessDecision.BaselineOnly, gate.evaluate(lease, modernPacket(timestamp = 1_001L))) | ||
| assertEquals( | ||
| RepFreshnessDecision.Process, | ||
| gate.evaluate(lease, modernPacket(repsSetCount = 5, repsSetTotal = 252, timestamp = 1_002L)), | ||
| ) | ||
| } | ||
|
|
||
| @Test | ||
| fun `finite amrap lease still rejects mismatched repsSetTotal`() { | ||
| val gate = RepNotificationFreshnessGate() | ||
| val lease = activeLease(target = 3, cutover = 1_000L).copy(isAmrap = true) | ||
|
|
||
| // Even with isAmrap=true, a mismatched finite repsSetTotal should be rejected | ||
| assertEquals( | ||
| RepFreshnessDecision.Drop(RepDropReason.TARGET_MISMATCH), | ||
| gate.evaluate(lease, modernPacket(repsSetCount = 1, repsSetTotal = 4, timestamp = 1_001L)), | ||
| ) | ||
| } | ||
|
|
||
| @Test | ||
| fun `pre-cutover amrap packet is still rejected`() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🔥 The Roast: This test exists in a quantum superposition — it both adds coverage and adds nothing. The pre-cutover drop at lines 51–54 of the gate runs before any 🩹 The Fix: Delete this test. Pre-cutover behavior is already covered by 📏 Severity: suggestion Reply with |
||
| val gate = RepNotificationFreshnessGate() | ||
| val lease = activeLease(target = 0, cutover = 1_000L).copy(isAmrap = true) | ||
|
|
||
| assertEquals( | ||
| RepFreshnessDecision.Drop(RepDropReason.PRE_CUTOVER_TIMESTAMP), | ||
| gate.evaluate(lease, modernPacket(repsSetCount = 1, repsSetTotal = 252, timestamp = 999L)), | ||
| ) | ||
| } | ||
|
|
||
| private fun activeLease(target: Int, cutover: Long) = ExecutionLease( | ||
| executionId = 1L, | ||
| sessionId = "session-a", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🔥 The Roast: This assertion is going to fail in CI with the confidence of someone who shipped without running tests. You wrote
copy(isAmrap = true)on line 234, then expect the gate to drop forTARGET_MISMATCH. But line 62 of the gate short-circuits target matching wheneverisAmrapis true —targetMatchesis unconditionallytrue, so we skip the drop and fall through. Thenterminalis forcedfalseby the AMRAP exemption (line 70),allZeroisfalse(repsSetCount=1),hasNonTerminalProgressistrue, and the gate returnsProcess. The "even with isAmrap=true, mismatched finite repsSetTotal should be rejected" comment is right about the intent and wrong about the implementation — AMRAP gets a blanket exemption, no finite-target validation whenisAmrap=true. The PR description bragged "Local Java runtime unavailable; tests will be validated by CI" — yep, CI is going to validate straight into a red ❌.🩹 The Fix: Mirror the JustLift version at line 190 — drop
copy(isAmrap = true)from line 234 so it actually exercises the non-exempt path. Or delete this test outright sincefinite lease still rejects mismatched repsSetTotal after fixalready covers the non-exempt case.📏 Severity: critical
Reply with
@kilocode-bot fix itto have Kilo Code address this issue.