Skip to content

feat(cadence): wire p3_velocity into Stop + UPS dispatchers (#876 PR 3/5) - #886

Merged
github-actions[bot] merged 2 commits into
mainfrom
feat/issue-876-p3-velocity-wire
May 21, 2026
Merged

github-actions[bot] merged 2 commits into
mainfrom
feat/issue-876-p3-velocity-wire

Conversation

@robotrocketscience

Copy link
Copy Markdown
Owner

Part of #876. PR 3 of 5 in the stack. Builds on #884 (PR 1) + #885 (PR 2).

Summary

Wires p3_velocity into both Stop and UPS cadence dispatchers. After this PR, an operator can opt into bytes-per-turn-density cadence by setting [cadence] enabled = true + [cadence] policy = "p3_velocity" in .aelfrice.toml.

New in this PR

Session-ring slot

Added fire_idx_at_last_fire to the ring schema. The velocity predicate needs both bytes_at_last_fire AND a fire_idx anchor to compute turns_since_last_fire = next_fire_idx - fire_idx_at_last_fire. Backward-compat handled in _normalize_for_session — pre-PR-3 rings default the field to 0.

Atomic combined updater

update_p3_velocity_state(session_id, *, transcript_bytes, fire_idx) writes both p3_velocity state slots atomically under the existing advisory lock. Keeps the two inputs in sync so the next predicate evaluation sees a consistent (bytes, fire_idx) snapshot. update_bytes_at_last_fire is kept as a thin wrapper for backward-compat with PR 2 callers.

Dispatch wiring

POLICY_P3_VELOCITY branch in _maybe_fire_cadence_checkpoint (Stop) and _maybe_run_ups_cadence_checkpoint (UPS). Both branches:

  1. Read ring state — extract next_fire_idx, bytes_at_last_fire, fire_idx_at_last_fire.
  2. Resolve p3_velocity_threshold + estimate transcript bytes via the existing P2 helper.
  3. Compute turns_since_last_fire; bail if non-positive.
  4. Call should_fire_p3_velocity with the three state inputs.
  5. On fire: run the rebuilder, write resume cache (Stop only), call update_p3_velocity_state to advance both state slots atomically.
  6. Emit stderr observability line with computed density + threshold.

Counter-sharing post-#874 pattern preserved: UPS reads ring state before this turn's _ring_append_ids, sees same next_fire_idx Stop saw at end of prior turn. Both fire on the same boundary; second updater is a benign overwrite.

Determinism (#605)

Predicate inputs are filesystem state + config. Same inputs reproduce same fire decisions across replays.

Tests

10 new wiring tests across two files:

tests/test_hook_stop_cadence_p3_velocity.py — 6 tests: above-threshold fires, below skips, turns_since_last_fire == 0 short-circuit, default-OFF respected, env override, missing session state skips cleanly.

tests/test_hook_ups_cadence_p3_velocity.py — 4 tests: UPS fires returns body, UPS below skips, atomic state update on UPS fire, empty session_id short-circuit.

All 277 cadence + session_ring tests pass locally. Full suite pass pending in CI.

Discretion

Diff clean against the pre-push deny-list.

What's left in the stack

PR 3 of 5 in the #876 stack. Builds on:
  - PR 1 (#884, 647953b): POLICY_P3_VELOCITY enum + resolver +
    pure should_fire_p3_velocity predicate.
  - PR 2 (#885, f1f9d7b): session_ring P3 state slots
    (bytes_at_last_fire, classifications) + writer helpers.

Adds in this PR:

1. New session_ring slot: fire_idx_at_last_fire. The velocity
   predicate needs both bytes_at_last_fire AND a fire_idx anchor
   to compute turns_since_last_fire (= next_fire_idx -
   fire_idx_at_last_fire). Backward-compat handled in
   _normalize_for_session — pre-PR-3 rings default the field to 0.

2. update_p3_velocity_state(session_id, *, transcript_bytes, fire_idx) —
   new combined updater that writes both p3_velocity state slots
   atomically under the existing advisory lock. Keeps the two
   inputs in sync so the next predicate evaluation sees a consistent
   (bytes, fire_idx) snapshot. update_bytes_at_last_fire is kept
   as a thin wrapper for backward-compat with PR 2 callers.

3. POLICY_P3_VELOCITY dispatch branch in _maybe_fire_cadence_checkpoint
   (Stop) and _maybe_run_ups_cadence_checkpoint (UPS). Both branches:
     a. Read ring state — extract next_fire_idx, bytes_at_last_fire,
        fire_idx_at_last_fire (type-check each).
     b. Resolve p3_velocity_threshold + estimate transcript bytes
        via the existing P2 helper.
     c. Compute turns_since_last_fire; bail if non-positive (no
        valid window yet, e.g. first fire of a new session).
     d. Call should_fire_p3_velocity with the three state inputs.
     e. On fire: run the rebuilder, write resume cache (Stop only),
        call update_p3_velocity_state to advance both state slots
        atomically to the current (transcript_bytes, next_fire_idx).
     f. Emit stderr observability line with the computed density
        and configured threshold for operator visibility.

Counter-sharing with Stop (post-#874 pattern): UPS reads ring state
before this turn's _ring_append_ids, so it sees the same
next_fire_idx Stop saw at end of the prior turn. Both fire on the
same boundary by construction; the second updater is a benign
overwrite with identical values.

Tests:

  - tests/test_hook_stop_cadence_p3_velocity.py (6 tests): above-
    threshold fires, below skips, turns_since_last_fire == 0 short-
    circuit, default-OFF respected, env override, missing session
    state skips cleanly.
  - tests/test_hook_ups_cadence_p3_velocity.py (4 tests): UPS fires
    return body, UPS below skips, atomic state update on UPS fire,
    empty session_id skips.

All cadence + session_ring suites pass: 277 / 277 (267 prior + 10
new). Full pytest pass pending in PR CI.

What's left in the stack:
  - PR 4: wire p3_substantive into Stop + UPS + #881 shadow-mode
    companions for the two new policies.
  - PR 5: CHANGELOG + CONFIG.md + design-doc updates.

@sourcery-ai sourcery-ai 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.

Sorry @robotrocketscience, you have reached your weekly rate limit of 500000 diff characters.

Please try again later or upgrade to continue using Sourcery

@coderabbitai

coderabbitai Bot commented May 21, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@robotrocketscience has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 1 minute and 20 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 773a66b3-bd81-4480-8b53-c55bfe998ea6

📥 Commits

Reviewing files that changed from the base of the PR and between 38834e2 and af0306e.

📒 Files selected for processing (4)
  • src/aelfrice/hook.py
  • src/aelfrice/session_ring.py
  • tests/test_hook_stop_cadence_p3_velocity.py
  • tests/test_hook_ups_cadence_p3_velocity.py
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-876-p3-velocity-wire

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 and usage tips.

@robotrocketscience robotrocketscience added attn:review Needs review (PR open, awaiting reviewer) author-garsecg PR coordination mutex ready-to-merge Trigger merge-train: FF main to this PR's head labels May 21, 2026
@github-actions

github-actions Bot commented May 21, 2026

Copy link
Copy Markdown

PR-size soft cap

This PR is over the advisory size threshold:

  • 699 changed lines (limit: 200)
  • 4 changed files (limit: 3)

Bigger PRs collide with more open work, which under the parallel-session workflow tends to produce repeated attn:merge-conflict cycles (see #602). When practical, split into smaller PRs that each touch a focused surface.

This is advisory only — nothing is blocked. If the size is intentional (large refactor, module removal, generated code), apply the size:override label and this comment will be removed on the next push.

Comment thread tests/test_hook_stop_cadence_p3_velocity.py Fixed
@github-actions

Copy link
Copy Markdown

merge-train: blocked

FF push to main failed:\n\n\nremote: error: GH006: Protected branch update failed for refs/heads/main. remote: remote: - All comments must be resolved. To https://github.com/robotrocketscience/aelfrice ! [remote rejected] e7bf040fbfea6b7e1febab8f230c54ded539dfcc -> main (protected branch hook declined) error: failed to push some refs to 'https://github.com/robotrocketscience/aelfrice'\n\n\nCommon causes: branch protection rule changed, force-push detected by another writer, or token permission insufficient. Re-add the label after investigating.

The ready-to-merge label has been removed. Address the issue above and re-add the label when you're ready for another attempt.

@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label May 21, 2026
CodeQL caught the unused symbol — the test exercises the policy via
TOML config strings, not by referencing the constant directly.

merge-train catch on PR #886.
@robotrocketscience robotrocketscience added the ready-to-merge Trigger merge-train: FF main to this PR's head label May 21, 2026
@github-actions
github-actions Bot merged commit af0306e into main May 21, 2026
27 of 28 checks passed
@github-actions github-actions Bot removed the ready-to-merge Trigger merge-train: FF main to this PR's head label May 21, 2026
@github-actions

Copy link
Copy Markdown

merge-train: merged af0306emain via FF push.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

attn:review Needs review (PR open, awaiting reviewer) author-garsecg PR coordination mutex

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants