Use this when changing account selection, quota behavior, retry/failover logic, runtime rotation proxy behavior, or forecast/report reasoning. Companion short version: RUNBOOK_CHANGE_ROUTING_POLICY.md.
Change policy without breaking request flow, account safety, or diagnostics.
index.ts— optional plugin-host runtime orchestrationlib/runtime-rotation-proxy.ts— wrapper/app runtime Responses routing and account rotationlib/runtime/rotation-account-selection.ts—chooseAccounttiers: soft pin → priority → hard pin → sequential → affinity → hybrid → scanlib/policy/runtime-policy.ts,lib/policy/runtime-policy-cache.ts— composed per-request decision + its caches (invalidate via fingerprint, not by mutating cached objects)lib/accounts.ts— account selection inputs, health state, cooldown readiness datalib/rotation.ts— hybrid account selection (health*2 + tokens*5 + hoursSinceUsed*2 + capabilityBoost)lib/forecast.ts— readiness/risk forecastinglib/request/failure-policy.ts— retry/failover decision tablelib/request/rate-limit-backoff.ts— cooldown/backoff behaviorlib/quota-probe.ts/lib/quota-cache.ts/lib/preemptive-quota-scheduler.ts— quota-derived decision inputs and deferraltest/accounts.test.ts,test/rotation.test.ts,test/rotation-account-selection.test.ts,test/runtime-rotation-proxy.test.ts,test/forecast.test.ts,test/failure-policy.test.ts,test/rate-limit-backoff.test.ts,test/codex-manager-cli.test.ts— policy coverage
- Isolate the policy change from pure code motion.
- Locate the decision point before editing: selection tier,
evaluateRuntimePolicygate, failure-policy table row, backoff/cooldown constant, or quota-deferral rule. Prefer changing one. - Update the reasoning-producing surfaces (
forecast,report --explain,why-selected,rotation status) if their output semantics change — operators read those to explain selection. - Add or update focused tests before widening scope.
- Prefer one policy change per PR.
- Do not break existing JSON contract shapes unless the contract is explicitly being revised.
- Do not expose account emails/tokens or stale decoded upstream encoding headers from the runtime proxy.
- Keep runtime rotation default-on and loopback-only unless the release plan explicitly changes those invariants.
- Keep request invariants (
stream: true,store: false,reasoning.encrypted_content) unless the change explicitly targets them. - If recommendation or routing reasoning changes, update the explain/report output tests too.
- Keep live-probe behavior and storage mutations covered by tests.
- Changes to per-request policy state must respect the
runtime-policy-cache.tscontract: callers getstructuredCloned values; never mutate cache-held objects.
npm run typecheck
npm run lint -- index.ts lib/rotation.ts lib/forecast.ts lib/policy/runtime-policy.ts lib/request/failure-policy.ts lib/request/rate-limit-backoff.ts lib/runtime-rotation-proxy.ts
npm test -- test/rotation.test.ts test/rotation-account-selection.test.ts test/forecast.test.ts test/failure-policy.test.ts test/rate-limit-backoff.test.ts test/runtime-rotation-proxy.test.ts test/codex-manager-cli.test.ts
npm run buildExecute at least one real CLI/manual QA path that demonstrates the changed reasoning or routing behavior (for example codex-multi-auth why-selected --last --json or a report --explain run).
- policy delta stated in one sentence; only one decision point changed
why-selected/report/rotation statusoutput still explains selections truthfully- request invariants and proxy safety boundaries unchanged (or explicitly targeted)
- exhaustion exits still carry reason +
retry_after_ms+account_skip_reasons - targeted regression tests added; no storage/CLI refactor mixed in
- cached-policy objects never mutated by callers