Skip to content

fix(timing): carry has_forks onto continuation turns#1123

Draft
ajcasagrande wants to merge 1 commit into
mainfrom
ajc/continuation-has-forks-fix
Draft

fix(timing): carry has_forks onto continuation turns#1123
ajcasagrande wants to merge 1 commit into
mainfrom
ajc/continuation-has-forks-fix

Conversation

@ajcasagrande

@ajcasagrande ajcasagrande commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Problem

TurnToSend.from_previous_credit has a two-argument form (src/aiperf/credit/structs.py) that accepts the next turn's TurnMetadata and derives has_forks from it. The fixed-schedule and user-centric timing strategies called it without next_meta, so every continuation turn (turn index >= 1) was issued with has_forks=False regardless of what the dataset declared.

Under dag_jsonl FORK datasets, has_forks is what tells the sticky router (#891) to defer parent-entry eviction until the DAG children drain (src/aiperf/credit/issuer.py, src/aiperf/workers/worker.py). With the flag dropped, a parent whose later turn declares FORK branches is treated as fork-free: its sticky-router entry is evicted the moment its terminal turn returns, prematurely tearing down the pin that FORK children need to land on the parent's worker.

Notably, fixed_schedule.py already computed next_meta on the line above the call — it just never passed it.

Fix

  • src/aiperf/timing/strategies/fixed_schedule.py: pass the already-computed next_meta to from_previous_credit.
  • src/aiperf/timing/strategies/user_centric_rate.py: look up the next turn's metadata via ConversationSource.get_next_turn_metadata and pass it.

Intended behavior change: continuation turns now carry the dataset-declared has_forks flag, so the sticky router keeps fork-bearing parents pinned until their children drain. First turns were already correct (SampledSession.build_first_turn reads turn-0 metadata).

Tests (revert-verified pins)

  • tests/unit/timing/strategies/test_fixed_schedule.py::TestFixedScheduleCreditReturn::test_continuation_turn_carries_has_forks
  • tests/unit/timing/strategies/test_user_centric_rate.py::TestUserCentricCreditReturn::test_continuation_turn_carries_has_forks (new — the user-centric path had no pin)

Each source hunk was independently reverted (git apply -R) and its test confirmed to fail, then re-applied:

  • revert fixed_schedule hunk -> test_fixed_schedule.py::test_continuation_turn_carries_has_forks FAILED (1 failed, 49 passed)
  • revert user_centric hunk -> test_user_centric_rate.py::test_continuation_turn_carries_has_forks FAILED (1 failed, 49 passed)

Evidence

  • uv run pytest -n auto tests/unit/timing/strategies/ -> 147 passed
  • ruff format --check / ruff check on all four touched files: clean
  • Ratchets: ruff-baselined: OK (118 total, 118 baselined, 0 new), ergonomics: OK (58 total, 58 baselined, 0 new)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Continuation turns now retain the next-turn metadata when credits are returned, improving scheduling behavior for ongoing conversations.
    • Fixed continuation handling so fork-related timing information is preserved consistently across supported timing strategies.
  • Tests

    • Added regression coverage to verify continuation credits keep fork metadata during scheduling.

…e and user-centric strategies

TurnToSend.from_previous_credit accepts next_meta and derives has_forks
from it, but the fixed-schedule and user-centric strategies called it
without next_meta, so every continuation turn was issued with
has_forks=False. Under dag_jsonl FORK datasets this prematurely evicts
fork-bearing parent entries from the sticky router instead of deferring
eviction until the DAG children drain.

Pass the already-computed next_meta in fixed_schedule and look up the
next turn's metadata in user_centric_rate, and pin both paths with
regression tests.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Signed-off-by: Anthony Casagrande <acasagrande@nvidia.com>
@ajcasagrande ajcasagrande added the AgentX Feature for AgentX label Jul 7, 2026
@github-actions

github-actions Bot commented Jul 7, 2026

Copy link
Copy Markdown

Try out this PR

Quick install:

pip install --upgrade --force-reinstall git+https://github.com/ai-dynamo/aiperf.git@60b3245a00f85cf50527982ce3f840f15c977ff3

Recommended with virtual environment (using uv):

uv venv --python 3.12 && source .venv/bin/activate
uv pip install --upgrade --force-reinstall git+https://github.com/ai-dynamo/aiperf.git@60b3245a00f85cf50527982ce3f840f15c977ff3

Last updated for commit: 60b3245Browse code

@github-actions github-actions Bot added the fix label Jul 7, 2026
@coderabbitai

coderabbitai Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Both FixedScheduleStrategy.handle_credit_return and UserCentricStrategy.handle_credit_return now construct continuation TurnToSend objects with next-turn metadata included, preserving fork/sticky-router eviction behavior. Corresponding regression tests were added to verify has_forks metadata is carried through continuation credits.

Changes

Continuation metadata fix

Layer / File(s) Summary
FixedScheduleStrategy metadata propagation and test
src/aiperf/timing/strategies/fixed_schedule.py, tests/unit/timing/strategies/test_fixed_schedule.py
handle_credit_return now builds the continuation turn via TurnToSend.from_previous_credit(credit, next_meta), with a new test verifying has_forks is preserved on the issued credit.
UserCentricStrategy metadata propagation and test harness
src/aiperf/timing/strategies/user_centric_rate.py, tests/unit/timing/strategies/test_user_centric_rate.py
handle_credit_return fetches next-turn metadata from conversation_source and passes it into TurnToSend.from_previous_credit; new make_strategy helper and test validate has_forks propagation.

Estimated code review effort: 2 (Simple) | ~12 minutes

Poem

A credit hops forward, metadata in tow,
No fork left behind as the next turn we go,
Sticky routers rejoice, the eviction stays true,
Tests confirm it works, a rabbit's cheer for you! 🐰
Hop, hop, hooray — the turns carry through!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and accurately summarizes the main change: propagating has_forks to continuation turns in timing strategies.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/unit/timing/strategies/test_fixed_schedule.py`:
- Line 235: The test setup in make_strategy unpacks scheduler but never uses it,
which triggers the static analysis warning. Update the assignment in the test to
avoid binding the unused scheduler value, or otherwise remove that unpacked
variable while keeping the existing strategy and placeholder return from
make_strategy intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: c0a33633-bb3c-4bc3-981f-98a31e78fd81

📥 Commits

Reviewing files that changed from the base of the PR and between 0314074 and 60b3245.

📒 Files selected for processing (4)
  • src/aiperf/timing/strategies/fixed_schedule.py
  • src/aiperf/timing/strategies/user_centric_rate.py
  • tests/unit/timing/strategies/test_fixed_schedule.py
  • tests/unit/timing/strategies/test_user_centric_rate.py

continuation turn (the sticky router defers parent-entry eviction until
DAG children drain). Regression: from_previous_credit(credit) was called
without next_meta, so every continuation turn got has_forks=False."""
strategy, scheduler, _ = make_strategy([(0, "c1"), (100, "c1")])

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Unused scheduler unpacked variable.

Static analysis flags scheduler as unused in this test.

🧹 Proposed fix
-        strategy, scheduler, _ = make_strategy([(0, "c1"), (100, "c1")])
+        strategy, _scheduler, _ = make_strategy([(0, "c1"), (100, "c1")])
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
strategy, scheduler, _ = make_strategy([(0, "c1"), (100, "c1")])
strategy, _scheduler, _ = make_strategy([(0, "c1"), (100, "c1")])
🧰 Tools
🪛 Ruff (0.15.20)

[warning] 235-235: Unpacked variable scheduler is never used

Prefix it with an underscore or any other dummy variable pattern

(RUF059)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/timing/strategies/test_fixed_schedule.py` at line 235, The test
setup in make_strategy unpacks scheduler but never uses it, which triggers the
static analysis warning. Update the assignment in the test to avoid binding the
unused scheduler value, or otherwise remove that unpacked variable while keeping
the existing strategy and placeholder return from make_strategy intact.

Source: Linters/SAST tools

@codecov

codecov Bot commented Jul 7, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@datadog-official

Copy link
Copy Markdown

Pipelines

⚠️ Warnings

🚦 1 Pipeline job failed

Run Integration Tests | integration-tests (ubuntu-latest, 3.13)   View in Datadog   GitHub Actions

This comment will be updated automatically if new data arrives.
🔗 Commit SHA: 60b3245 | Docs | Give us feedback!

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

Labels

AgentX Feature for AgentX fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant