Skip to content

fix: exempt AMRAP leases from rep freshness gate (#700) - #701

Merged
9thLevelSoftware merged 3 commits into
mainfrom
fix/issue-700-amrap-rom-reps
Aug 16, 2026
Merged

fix: exempt AMRAP leases from rep freshness gate (#700)#701
9thLevelSoftware merged 3 commits into
mainfrom
fix/issue-700-amrap-rom-reps

Conversation

@9thLevelSoftware

Copy link
Copy Markdown
Owner

Summary

Extends PR #699's Just Lift exemption to also cover AMRAP leases in RepNotificationFreshnessGate.evaluate().

Root cause (from GPT-5.6 Terra RCA): RepNotificationFreshnessGate.evaluate() lines 59-61 deterministically drops every rep notification for AMRAP/JustLift sets because the Vitruvian machine sends repsSetTotal=252 (UNLIMITED_REPS, 0xFF on the wire) which never matches lease.workingRepTarget. PR #699 already exempts isJustLift but misses isAmrap; routine AMRAP sets hit the same gate with no exemption.

Changes

RepNotificationFreshnessGate.kt

  • targetMatches check (line 62): Add lease.isAmrap alongside lease.isJustLift so repsSetTotal=252 is accepted for AMRAP sets
  • terminal check (line 70): Add lease.isAmrap to the exemption so repsSetCount is never treated as terminal for AMRAP leases

RepNotificationFreshnessGateTest.kt

Four new mirror test cases for isAmrap=true:

  1. AMRAP accepts repsSetTotal=252 despite finite UI target
  2. AMRAP does not treat repsSetCount as terminal
  3. Finite AMRAP mismatch still rejected (repsSetTotal != target)
  4. Pre-cutover AMRAP packet still rejected

Acceptance Criteria

  • Post-cutover modern packets with repsSetTotal=252 accepted for both isJustLift=true and isAmrap=true
  • repsSetCount never treated as terminal for isJustLift=true or isAmrap=true
  • Finite-target leases still reject nonzero mismatched repsSetTotal
  • Pre-cutover packets still rejected
  • PR fix: exempt Just Lift from rep freshness gate target mismatch (#698) #699's existing JustLift test cases unchanged
  • ./gradlew :shared:testAndroidHostTest --tests '*RepNotificationFreshnessGateTest*' (CI)
  • ./gradlew :shared:testAndroidHostTest --tests '*DWSMWorkoutLifecycleTest*' (CI)
  • No changes to BlePacketFactory, WorkoutExecutionGuard, ExecutionSeed, or any other consumer

Note: Local Java runtime unavailable; tests will be validated by CI.

Fixes #700

Devil added 2 commits August 16, 2026 00:21
… in RepNotificationFreshnessGate

Issue #698: Echo Just Lift commands use unlimited target semantics (0xFF/252),
but the modern rep freshness gate required the device-reported repsSetTotal to
equal the finite UI lease workingRepTarget. This caused every valid Just Lift
packet to be dropped as TARGET_MISMATCH before rep counting, warmup, audio
feedback, or auto-stop could fire.

Fix: gate the target-equality and finite-terminal checks on !lease.isJustLift
using the existing isJustLift field on ExecutionLease.

Acceptance criteria:
- Just Lift modern packets with repsSetTotal=252 pass the freshness gate
- Just Lift repsSetCount is not treated as terminal
- Finite-target executions still reject nonzero mismatched targets
- Pre-cutover, invalidated, and non-current packets remain rejected

Fixes #698
Extend PR #699's Just Lift exemption to also cover AMRAP leases in
RepNotificationFreshnessGate.evaluate():

- targetMatches: add lease.isAmrap alongside lease.isJustLift so
  repsSetTotal=252 (UNLIMITED_REPS) is accepted for AMRAP sets
- terminal check: add lease.isAmrap to the exemption so repsSetCount
  is never treated as terminal for AMRAP leases

Add four mirror test cases for isAmrap=true:
- AMRAP accepts repsSetTotal 252 despite finite UI target
- AMRAP does not treat repsSetCount as terminal
- Finite AMRAP mismatch still rejected (repsSetTotal != target)
- Pre-cutover AMRAP packet still rejected

Fixes #700
Copilot AI lite review requested due to automatic review settings August 16, 2026 12:07
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, add credits to your account and enable them for code reviews in your settings.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.


// Even with isAmrap=true, a mismatched finite repsSetTotal should be rejected
assertEquals(
RepFreshnessDecision.Drop(RepDropReason.TARGET_MISMATCH),

Copy link
Copy Markdown
Contributor

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 for TARGET_MISMATCH. But line 62 of the gate short-circuits target matching whenever isAmrap is true — targetMatches is unconditionally true, so we skip the drop and fall through. Then terminal is forced false by the AMRAP exemption (line 70), allZero is false (repsSetCount=1), hasNonTerminalProgress is true, and the gate returns Process. 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 when isAmrap=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 since finite lease still rejects mismatched repsSetTotal after fix already covers the non-exempt case.

📏 Severity: critical


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

}

@Test
fun `pre-cutover amrap packet is still rejected`() {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The 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 isAmrap is consulted, so this assertion holds for any lease regardless of isAmrap. The JustLift mirror set has no equivalent for exactly this reason. You wrote it anyway. Like backup paperwork for a backup.

🩹 The Fix: Delete this test. Pre-cutover behavior is already covered by pre-cutover packet drop prevents stale notification processing at line 11 and is independent of isAmrap.

📏 Severity: suggestion


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

// Issue #698/#700: Just Lift and AMRAP use unlimited target semantics
// (0xFF/252), so the device-reported repsSetTotal will never match the
// finite UI lease target. Exempt both from target equality check.
val targetMatches = lease.isJustLift || lease.isAmrap ||

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔥 The Roast: lease.isJustLift || lease.isAmrap lives here at line 62 and again inverted at line 70. Two places to keep in sync the day someone inevitably adds isEcho or isCluster. The kind of micro-duplication that won't bite today but absolutely will haunt whoever maintains this gate next quarter.

🩹 The Fix: Hoist to a single local at the top of the block: val isUnlimitedRepSet = lease.isJustLift || lease.isAmrap. Then targetMatches = isUnlimitedRepSet || ... and terminal = !isUnlimitedRepSet && .... Optional but cheap.

📏 Severity: nitpick


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

Code Review Roast 🔥

Verdict: Approve | Recommendation: Merge — the critical test-vs-implementation mismatch from the prior pass is fixed.

Overview

Severity Count
🚨 critical 0
⚠️ warning 0
💡 suggestion 1
🤏 nitpick 0
Issue Details (click to expand)
File Line Status Roast
shared/.../RepNotificationFreshnessGateTest.kt 238 ✅ Resolved by 4989b06 Now correct — (isAmrap && target==0) makes the finite AMRAP mismatch actually drop.
shared/.../RepNotificationFreshnessGateTest.kt 244 ⚠️ Still open (optional) Pre-cutover AMRAP test still duplicates the line-11 coverage; pre-cutover check runs before any isAmrap lookup. Existing suggestion comment covers it.
shared/.../RepNotificationFreshnessGate.kt 73 ⚠️ Asymmetry (unchanged line) Target check exempts AMRAP only when target==0; terminal check still blanket-exempts AMRAP. Not introduced by this diff, so not a blocker.

🏆 Best part: The new commit 4989b06f is a tight, surgical fix — four lines, one branch tightened, zero new abstractions, and it actually makes the test that previously asserted the wrong thing pass for the right reason. Whoever wrote repsSetTotal != target as a finite-AMRAP invariant deserves a coffee.

💀 Worst part: The pre-cutover AMRAP test at line 244 is still alive — a quantum-superposition test that passes regardless of isAmrap because the pre-cutover guard runs first. It's not blocking, but it's the kind of "coverage theatre" that survives because CI is green.

📊 Overall: Like the second pancake — same batter, slightly better shape, ready to serve. The fix landed cleanly, the only leftovers are optional cleanup.

Files Reviewed (1 changed file in incremental diff)
  • shared/src/commonMain/kotlin/com/devil/phoenixproject/presentation/manager/RepNotificationFreshnessGate.kt — 0 issues on changed lines
  • shared/src/commonTest/kotlin/com/devil/phoenixproject/presentation/manager/RepNotificationFreshnessGateTest.kt — unchanged in this diff

Reviewed by minimax-m3 · Input: 53.6K · Output: 19.5K · Cached: 624.3K

Review guidance: REVIEW.md from base branch main

Previous Review Summary (commit f288cef)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit f288cef)

Verdict: Request changes | Recommendation: One test asserts behavior the implementation does not deliver; will fail in CI.

Overview

Severity Count
🚨 critical 1
⚠️ warning 0
💡 suggestion 1
🤏 nitpick 1
Issue Details (click to expand)
File Line Roast
shared/.../RepNotificationFreshnessGateTest.kt 238 Mirror test asserts Drop(TARGET_MISMATCH) but the AMRAP exemption at line 62 makes the gate return Process — CI will validate this straight into a red ❌
shared/.../RepNotificationFreshnessGateTest.kt 244 Pre-cutover AMRAP test duplicates existing line-11 coverage; pre-cutover check runs before any isAmrap lookup
shared/.../RepNotificationFreshnessGate.kt 62 lease.isJustLift || lease.isAmrap is duplicated (also at line 70) — hoist to one local

🏆 Best part: The fix structure itself — adding isAmrap alongside isJustLift in the same two predicates — is exactly the right surgical change. Tiny, scoped, no new abstractions, mirrored tests. Whoever designed the ExecutionLease flags made this a one-line fork.

💀 Worst part: A test that was never run because "Local Java runtime unavailable" — and asserts the opposite of what the code does. The gate gives AMRAP a blanket exemption (line 62 short-circuits target matching), but the test asserts that AMRAP with a finite target still validates repsSetTotal. CI is going to teach that lesson so the author doesn't have to.

📊 Overall: The fix is sound, the tests just shipped a self-own. Remove the copy(isAmrap = true) from line 234 (mirror the JustLift version), delete the redundant pre-cutover test, and this PR is ready to merge.

Files Reviewed (2 files)
  • shared/src/commonMain/kotlin/com/devil/phoenixproject/presentation/manager/RepNotificationFreshnessGate.kt — 0 critical, 1 nitpick
  • shared/src/commonTest/kotlin/com/devil/phoenixproject/presentation/manager/RepNotificationFreshnessGateTest.kt — 1 critical, 1 suggestion

Fix these issues in Kilo Cloud


Reviewed by minimax-m3 · Input: 42.5K · Output: 9.9K · Cached: 268.4K

Review guidance: REVIEW.md from base branch main

The blanket isAmrap exemption in targetMatches allowed ANY AMRAP lease
to bypass target equality, even when the lease has a finite target
(e.g., target=3). This caused mismatched repsSetTotal to be accepted
instead of dropped as TARGET_MISMATCH.

Fix: only exempt AMRAP from target matching when workingRepTarget == 0
(unlimited). AMRAP with a finite target must still match.

Fixes test: finite amrap lease still rejects mismatched repsSetTotal
@9thLevelSoftware
9thLevelSoftware merged commit 57d47d4 into main Aug 16, 2026
10 checks passed
@9thLevelSoftware
9thLevelSoftware deleted the fix/issue-700-amrap-rom-reps branch August 16, 2026 18:47
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.

AMRAP ROM reps not registering in JustLift mode

2 participants