Skip to content

feat(router): add per-session beta routing toggle - #1006

Open
Symbiomancer wants to merge 2 commits into
mainfrom
codex/hmm-beta-toggle-20260824
Open

feat(router): add per-session beta routing toggle#1006
Symbiomancer wants to merge 2 commits into
mainfrom
codex/hmm-beta-toggle-20260824

Conversation

@Symbiomancer

Copy link
Copy Markdown
Contributor

Summary

  • add a bare /beta command for Claude Code and Pi sessions
  • persist the session selection server-side and route it through an independently configured beta HMM policy
  • keep beta unavailable through headers, installation defaults, deployment defaults, and the policy catalog
  • bind all session pin state to the effective strategy while retaining stable compatibility with legacy pins
  • fail beta closed without changing stable routing when its optional sidecar is unavailable

Validation

  • go test ./... -count=1
  • make test-install
  • bash install/pi-router/test/e2e.sh
  • SQLC v1.30 regeneration
  • git diff --check

No model artifact, deployment pin, or infrastructure configuration is included in this public repository PR.

@claude

claude Bot commented Aug 24, 2026

Copy link
Copy Markdown

Claude finished @Symbiomancer's task —— View job


Posted advisory comment-length review with 7 inline suggestions.

@workweave-bot workweave-bot left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Advisory only — comment-length nits. Won't block merge.

Comment thread cmd/router/main.go Outdated
Comment thread cmd/router/main.go Outdated
Comment thread internal/proxy/pin_strategy.go Outdated
Comment thread internal/proxy/beta.go Outdated
Comment thread internal/proxy/service.go Outdated
Comment thread internal/proxy/service.go Outdated
Comment thread internal/server/middleware/router_strategy_override.go Outdated

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using default effort and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit 97307fc. Configure here.

Comment thread internal/proxy/beta.go
@greptile-apps

greptile-apps Bot commented Aug 24, 2026

Copy link
Copy Markdown

T-Rex T-Rex Logs

What T-Rex did

  • T-Rex produced a proof for a posted P1 finding and attached artifacts showing a focused Go harness that overlaps two beta toggles after the same preference read.
  • A second P1 finding proof comment was posted to document another related finding.
  • The overlapping-beta-toggles contract validation was executed: go test -race ./internal/proxy -run TestTReXOverlappingBetaTogglesCollapse -count=1 -v, then -count=20; both runs exited with code 0 and no race-detector findings, and gets=2, sets=2, clears=0, finalEnabled=true on every overlap, with HTTP responses acknowledging beta enabled.
  • The temporary in-package test was removed after execution; its exact source was kept as an artifact for review.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (1)

  1. General comment

    P1 Concurrent /beta toggles lose one toggle and send inconsistent acknowledgements

    • Bug
      • Two same-session /beta requests can both read a missing preference, both execute Set, and both return “Beta enabled.” The final stored state is enabled even though two serialized toggles from disabled should leave it disabled, with the second acknowledgement saying beta was disabled.
    • Cause
      • handleBetaCommand performs an unguarded Get at line 69, makes its toggle decision from that snapshot at lines 80-88, and performs an independent Clear or Set at lines 83-95. The sessionstrategy.Store contract supplies no atomic toggle/compare-and-swap operation, transaction, or per-session lock.
    • Fix
      • Serialize the read-modify-write per (installationID, sessionKey), preferably with a repository-level atomic toggle transaction (for example, row/advisory locking plus read and mutation) that returns the resulting enabled state for the acknowledgement. A process-local keyed mutex alone would not protect multiple router instances.

    T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "feat(router): add session beta routing t..." | Re-trigger Greptile

Comment thread internal/proxy/beta.go
Comment on lines +69 to +95
preference, enabled, err := s.sessionStrategyStore.Get(ctx, installationID, sessionKey)
if err != nil {
return fmt.Errorf("read beta routing preference: %w", err)
}
if enabled && preference.Strategy != router.StrategyHMMBeta {
return fmt.Errorf("unsupported persisted session routing strategy %q", preference.Strategy)
}
if !enabled && !s.PolicyStrategyAvailable(router.StrategyHMMBeta) {
return writeBetaCommandResponse(w, env, betaUnavailable, inputTokens)
}

message := betaEnabledMessage
previousStrategy := router.StrategyFromContext(ctx)
if enabled {
if err := s.sessionStrategyStore.Clear(context.Background(), installationID, sessionKey); err != nil {
return fmt.Errorf("disable beta routing: %w", err)
}
previousStrategy = router.StrategyHMMBeta
message = betaDisabledMessage
} else {
if err := s.sessionStrategyStore.Set(context.Background(), sessionstrategy.Preference{
InstallationID: installationID,
SessionKey: sessionKey,
Strategy: router.StrategyHMMBeta,
}); err != nil {
return fmt.Errorf("enable beta routing: %w", err)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Concurrent beta toggles lose state

Two overlapping /beta requests for the same session can both read a missing preference, both call Set, and both return “Beta enabled.” Two serialized toggles from disabled should instead enable and then disable beta, leaving it disabled and returning an enabled acknowledgement followed by a disabled one. Make the per-session read-modify-write atomic—preferably in the persistence layer with a transaction or lock that returns the resulting state—so it remains correct across multiple router instances.

Artifacts

Focused Go harness that overlaps two beta toggles after the same preference read

  • The in-package test source installs a barrier after both Get calls snapshot the disabled state and then invokes the real beta handler twice, with the takeaway that the exact concurrent path is exercised.

Race-enabled first concurrent beta-toggle reproduction

  • The first race-enabled execution records two Gets, two Sets, zero Clears, final enabled state, and two enabled acknowledgements, with the takeaway that the collapse occurs in an executed handler path.

Race-enabled repeated concurrent beta-toggle reproduction

  • Twenty race-enabled executions repeat the same two-Set, zero-Clear result without a race-detector report, with the takeaway that the lost-toggle interleaving is deterministic under the controlled overlap.

Sequential beta toggle comparison and concurrent reproduction

  • The comparison run shows the harness collapsing concurrent toggles while the existing sequential test logs enabled then disabled, with the takeaway that only the non-serialized concurrent path violates toggle semantics.

View artifacts

T-Rex Ran code and verified through T-Rex

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.

2 participants