Skip to content

[WS2] Add CP-aware Attention contract and dispatch metadata - #236

Open
Bsgg1 wants to merge 12 commits into
RL-Align:testfrom
Bsgg1:feat/issue-235-attention-cp-contract
Open

[WS2] Add CP-aware Attention contract and dispatch metadata #236
Bsgg1 wants to merge 12 commits into
RL-Align:testfrom
Bsgg1:feat/issue-235-attention-cp-contract

Conversation

@Bsgg1

@Bsgg1 Bsgg1 commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements PR1 of #235: the typed WS2 Attention contract and strict dispatch metadata used by the later CP reference, runtime binding, decode, backward, and H100 validation PRs.

Contract

Area Enforced behavior
TP/CP ownership Validates Qwen3-style TP-local GQA heads, CP sequence ownership, and stable global block indices
Reduction Declares FP32 online-softmax (Out, LSE) merge and final-write downcast
Split-KV Records the requested policy and complete executed batch x TP x CP x owner plan provenance; missing/mismatched evidence fails closed
RoPE / position Records Q/K/cache RoPE state, theta/scaling, rotary dimension, position offsets, cast point, dtype, and fused/unfused boundary
KV cache Binds cache positions, sequence lengths, logical token positions, page ownership, and shared-prefix identity
Dispatch Rejects undeclared capabilities, fallback, or incompatible backend provenance
Shared core Defines rlkernel.attention.deterministic_core.v1 as the strict production core identity

Validation

Check Result
Focused contract and dispatch suite 45 passed
Full reviewed contract/dispatch/operator-input set 67 passed
Formatting and static checks Black, isort, flake8, and pre-commit passed
Base branch test

Boundary

Included here Intentionally not claimed
Contract construction, validation, capability gating, and provenance CP collective execution, deterministic kernel arithmetic, fused RoPE+Attention, distributed drift, or H100 execution

Multi-rank execution evidence is owned by #279 and accepted by #285. Related: #235, #108, #207.

@coderabbitai

coderabbitai Bot commented Jul 19, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR adds a typed WS2 CP-aware attention contract, validates attention metadata, adds capability-aware registry dispatch with provenance, and documents and tests strict backend rejection behavior.

Changes

WS2 attention contract and dispatch

Layer / File(s) Summary
Contract model and attention metadata
docs/design/ws2-cp-attention-contract.md, rl_engine/kernels/attention_contract.py
Defines TP/CP sharding, deterministic FP32 reduction, KV-cache, RoPE, batching, validation, serialization, and public contract types.
Capability-aware registry dispatch
rl_engine/kernels/registry.py, docs/design/ws2-cp-attention-contract.md
Adds get_attention_op(contract), registers backend capabilities, filters incompatible candidates, rejects undeclared fallbacks, and records provenance.
Contract and dispatch validation
tests/test_attention_contract.py
Tests contract construction, sharding, reduction, RoPE, KV-cache, packed layouts, capability matching, rejection behavior, and provenance.
Dispatch documentation and CI coverage
docs/design/runtime-dispatch.md, docs/operators/attention.md, .github/workflows/ci.yml
Documents WS2 dispatch rules, explicit rejection, unchanged legacy dispatch, and CI execution of the contract tests.

Estimated code review effort: 4 (Complex) | ~45 minutes

Possibly related PRs

Suggested reviewers: flink-ddd, kjldefeated, zhangj1an

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the pull request's main WS2 CP-aware attention contract and dispatch metadata changes.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

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

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 `@rl_engine/kernels/attention_contract.py`:
- Around line 403-420: Rename the loop-bound active_blocks variables in the
sequence consistency loop and the exclusive_page_owners loop to distinct names,
updating their references within each loop. Preserve the existing list-based
active_blocks binding and all validation and ownership logic.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: bb3bdb48-0e1e-4f2b-9707-bebdb8e47072

📥 Commits

Reviewing files that changed from the base of the PR and between 6df029a and b7ba64b.

📒 Files selected for processing (6)
  • docs/design/runtime-dispatch.md
  • docs/design/ws2-cp-attention-contract.md
  • docs/operators/attention.md
  • rl_engine/kernels/attention_contract.py
  • rl_engine/kernels/registry.py
  • tests/test_attention_contract.py

Comment thread rl_engine/kernels/attention_contract.py Outdated
@Bsgg1
Bsgg1 requested a review from bitborne as a code owner July 19, 2026 15:59
Comment thread rl_engine/kernels/attention_contract.py Outdated
object.__setattr__(self, "mode", _enum_value(AttentionMode, self.mode, "mode"))
object.__setattr__(self, "dtype", _enum_value(AttentionDType, self.dtype, "dtype"))
batch_size = _positive_int(self.batch_size, "batch_size")
_positive_int(self.query_sequence_length, "query_sequence_length")

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.

Small contract gap: for prefill, should we reject cases where query_sequence_length doesn’t match sharding.local_sequence_length? Right now an inconsistent contract like query_sequence_length=2048 with local_sequence_length=1024 can still be constructed.

global_token_positions = _integer_tuple(
self.global_token_positions, "global_token_positions"
)
if not cache_positions or any(position < 0 for position in cache_positions):

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.

Another small gap: cache_positions is only checked for shape/non-negativity, but not against global_token_positions. For decode identity, we probably want to reject cases like cache_positions=(999,) when the declared tokens are only 0..16.

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

🧹 Nitpick comments (2)
tests/test_attention_contract.py (2)

458-466: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Exercise registry rejection for packed-layout incompatibility.

This test only calls AttentionBackendCapability.incompatibilities(...); it never proves that KernelRegistry.get_attention_op() rejects an otherwise declared backend. Register the capability and assert the dispatch error includes the packed-varlen incompatibility, preventing registry regressions from bypassing this check.

🤖 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/test_attention_contract.py` around lines 458 - 466, Extend
test_packed_layout_requires_declared_backend_support to register the capability
with KernelRegistry and invoke get_attention_op() for the packed-varlen
contract. Assert that dispatch is rejected and the resulting error includes
“packed varlen layout is unsupported,” while retaining the direct
incompatibilities assertion.

100-101: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Cover the stated TP=4/CP=4 target, not only TP=2/CP=2.

The representability test and its declared backend only exercise TP2/CP2, while the PR objective explicitly calls out a Qwen3-8B TP4/CP4 BF16 contract. Add a TP4/CP4 case with matching local sequence/block metadata and capability support so four-way head ownership and CP validation are covered.

Also applies to: 110-116

🤖 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/test_attention_contract.py` around lines 100 - 101, Extend the
representability test’s world-size parameters to include the stated TP=4/CP=4
scenario, and add matching local sequence/block metadata plus backend capability
support for that case. Update the relevant test setup around the
representability test and its declared backend so four-way tensor-parallel head
ownership and context-parallel validation are exercised while preserving the
existing TP2/CP2 coverage.
🤖 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.

Nitpick comments:
In `@tests/test_attention_contract.py`:
- Around line 458-466: Extend
test_packed_layout_requires_declared_backend_support to register the capability
with KernelRegistry and invoke get_attention_op() for the packed-varlen
contract. Assert that dispatch is rejected and the resulting error includes
“packed varlen layout is unsupported,” while retaining the direct
incompatibilities assertion.
- Around line 100-101: Extend the representability test’s world-size parameters
to include the stated TP=4/CP=4 scenario, and add matching local sequence/block
metadata plus backend capability support for that case. Update the relevant test
setup around the representability test and its declared backend so four-way
tensor-parallel head ownership and context-parallel validation are exercised
while preserving the existing TP2/CP2 coverage.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 19a56bfb-94c2-40c6-b17b-1422b2d0c29f

📥 Commits

Reviewing files that changed from the base of the PR and between 6d826df and 8a4f9eb.

📒 Files selected for processing (2)
  • docs/design/ws2-cp-attention-contract.md
  • tests/test_attention_contract.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • docs/design/ws2-cp-attention-contract.md

Signed-off-by: inaniloquentee <3051000145@qq.com>

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

Actionable comments posted: 2

🤖 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 `@rl_engine/kernels/attention_contract.py`:
- Around line 606-618: The RoPE validation around position_ids and
query_position_offsets/key_position_offsets currently checks only lengths and
must enforce CP token ownership. Require position metadata for RoPE-aware
requests, validate dense position_ids against global_block_token_starts and
local_block_offsets, and reject offset-only metadata when ownership is
non-contiguous; add regression coverage for blocks with non-contiguous global
starts such as (0, 3072).
- Around line 495-500: Update theta validation in the attention contract around
self.theta to reject non-finite values after converting to float. Require
math.isfinite(theta) alongside the existing positive-value check before
object.__setattr__ stores the normalized value, while preserving the current
error behavior and message.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: b24f9885-0127-42d0-bd01-c402cfe94026

📥 Commits

Reviewing files that changed from the base of the PR and between 8a4f9eb and d39f0a5.

📒 Files selected for processing (3)
  • docs/design/ws2-cp-attention-contract.md
  • rl_engine/kernels/attention_contract.py
  • tests/test_attention_contract.py

Comment on lines +495 to +500
if isinstance(self.theta, bool) or not isinstance(self.theta, (float, int)):
raise AttentionContractError(f"theta must be a positive number; got {self.theta!r}")
theta = float(self.theta)
if theta <= 0.0:
raise AttentionContractError(f"theta must be a positive number; got {self.theta!r}")
object.__setattr__(self, "theta", theta)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Reject non-finite theta values.

float("nan") and float("inf") pass theta <= 0.0. They can produce invalid RoPE semantics and non-standard JSON values in provenance. Require math.isfinite(theta) before storing the value.

Proposed fix
-        if theta <= 0.0:
+        if not math.isfinite(theta) or theta <= 0.0:
             raise AttentionContractError(f"theta must be a positive number; got {self.theta!r}")
📝 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
if isinstance(self.theta, bool) or not isinstance(self.theta, (float, int)):
raise AttentionContractError(f"theta must be a positive number; got {self.theta!r}")
theta = float(self.theta)
if theta <= 0.0:
raise AttentionContractError(f"theta must be a positive number; got {self.theta!r}")
object.__setattr__(self, "theta", theta)
if isinstance(self.theta, bool) or not isinstance(self.theta, (float, int)):
raise AttentionContractError(f"theta must be a positive number; got {self.theta!r}")
theta = float(self.theta)
if not math.isfinite(theta) or theta <= 0.0:
raise AttentionContractError(f"theta must be a positive number; got {self.theta!r}")
object.__setattr__(self, "theta", theta)
🤖 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 `@rl_engine/kernels/attention_contract.py` around lines 495 - 500, Update theta
validation in the attention contract around self.theta to reject non-finite
values after converting to float. Require math.isfinite(theta) alongside the
existing positive-value check before object.__setattr__ stores the normalized
value, while preserving the current error behavior and message.

Comment thread rl_engine/kernels/attention_contract.py Outdated
Comment on lines +606 to +618
if self.rope.position_ids is not None and len(self.rope.position_ids) not in {
query_sequence_length,
self.sharding.local_sequence_length,
}:
raise AttentionContractError(
"position_ids must describe the local query sequence or full local "
"sequence length"
)
for field in ("query_position_offsets", "key_position_offsets"):
offsets = getattr(self.rope, field)
if offsets is not None and len(offsets) != batch_size:
raise AttentionContractError(
f"{field} must contain one entry per logical batch entry"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Bind RoPE positions to CP token ownership.

The current checks only validate lengths. They accept absent position metadata and accept position_ids=range(local_sequence_length) for non-contiguous CP blocks. For example, blocks with global starts (0, 3072) would assign the second local block positions starting at 1024, not 3072. This changes the RoPE phase and can produce incorrect attention results.

Require position identity for RoPE-aware requests. Validate dense IDs against global_block_token_starts and local_block_offsets. Reject an offset-only representation when it cannot represent non-contiguous ownership. Add regression coverage for this case.

🤖 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 `@rl_engine/kernels/attention_contract.py` around lines 606 - 618, The RoPE
validation around position_ids and query_position_offsets/key_position_offsets
currently checks only lengths and must enforce CP token ownership. Require
position metadata for RoPE-aware requests, validate dense position_ids against
global_block_token_starts and local_block_offsets, and reject offset-only
metadata when ownership is non-contiguous; add regression coverage for blocks
with non-contiguous global starts such as (0, 3072).

@inaniloquentee
inaniloquentee changed the base branch from main to test August 12, 2026 16:13
# Conflicts:
#	docs/operators/attention.md
#	rl_engine/kernels/gtest/operator_specs.py
#	rl_engine/kernels/ops/cuda/attention/__init__.py
#	rl_engine/kernels/registry.py
Signed-off-by: lamentropetion <3051000145@qq.com>
Signed-off-by: lamentropetion <3051000145@qq.com>
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