Skip to content

Reorganize xorl.ops: vendored quarantine, objectives split, ops/exact, ops/families (#78 phases 1-5) - #81

Draft
qywu wants to merge 14 commits into
reorg/phase0-vendored-markersfrom
reorg/phases-1-5
Draft

Reorganize xorl.ops: vendored quarantine, objectives split, ops/exact, ops/families (#78 phases 1-5)#81
qywu wants to merge 14 commits into
reorg/phase0-vendored-markersfrom
reorg/phases-1-5

Conversation

@qywu

@qywu qywu commented Aug 21, 2026

Copy link
Copy Markdown
Member

Phases 1–5 of #78, one commit per phase, stacked on the phase-0 PR #80 (base branch reorg/phase0-vendored-markers; retarget to main after #80 lands). Every move leaves a compat stub or lazy re-export at the old import path for one deprecation cycle, and every in-repo import was codemodded to the new canonical path in the same commit.

Phase 1 — vendored quarantine

ops/quackops/_vendored/quack, ops/linear_attention/flashqlaops/_vendored/flashqla (~30k lines out of the first-party namespace). Old paths are sys.modules alias stubs (deep submodule imports through them create a duplicate module instance — noted in the stub docstrings). Lint/format/codespell excludes collapse to the single _vendored/ prefix.

Phase 2 — objectives out of ops/loss

New xorl.objectives package: policy_loss, grpo_loss, cispo_loss, importance_sampling_loss, opd_loss, opd_streaming_kl, causallm_loss, reducers, loss_output, and the loss registry. ops/loss keeps only the CE/selected-logprob kernel stack. The old package paths re-export the objective API lazily (PEP 562) — eager re-export is an import cycle, since the objectives import the kernels.

Phase 3 — the exact-contract family under ops/exact (+ ops/sglang, per review)

Physically moved: rope_class_b, canonical_moe_leaf, canonical_moe_cast, kernel_config_pin, bi_gemm_configs, block_fp8_native, fused_silu_and_mul, and (after review feedback, commit cc8f635) exact_sampling_transforms.pyops/exact/sampling_transforms.py.

Per @kiddyboots216's suggestion on #78, the literal serving-engine twins get their own ops/sglang/ package: bi_families_v2.py (moved byte-identical — same git blob as main; the sha256 gate hashes content, not paths) and batch_invariant_ops.py (vendored-adapted from sglang/srt/batch_invariant_ops). One deviation from the issue sketch stands: batch_invariant_ops.py is not split — it must remain a single file diffable against the serving twin. The taxonomy is three-way: _vendored/ (untouchable snapshots), sglang/ (parity twins, paired-edit policy), first-party everything else.

Phase 4 — one home per family; layers out of ops

ops/glm5_kernelsops/families/glm5, ops/dsv4ops/families/dsv4. Deviation from the issue sketch: they stay under ops/ rather than moving into models/transformers/<family>/ because those packages have import side effects (DSV4 mutates the HF Auto registries on import) and kernels must be importable without them. The GatedDeltaNet and Mamba2Mixer layer classes move to xorl.models.layers; the kernel-adjacent contract modules (linear_attention/modules, ssm/modules) stay in ops by design.

Phase 5 — dead code

ops/ep_kernels had zero importers for any of its seven exports — deleted rather than merged into moe/ as sketched.

Verification

  • pre-commit run --all-files (the lint CI command) green after every phase.
  • Full CPU matrix run locally: tests/ops (90 passed), catch-all tests minus server/distributed/ops (501 passed), tests/server -m cpu (green), tests/distributed -m cpu (153 passed; 1 failure — test_native_fp8_meta_materialization_preserves_fsdp2_dtensors — fails identically on unmodified main).
  • GPU spot checks on moved paths: MoE backends, BI golden gates, fused linear-logprob (quack), gated-delta-rule.
  • Pre-existing failures on this box, identical on unmodified main, unrelated to this PR: 14 tilelang-compile failures (dsv4 indexer/sparse-MLA + flashqla contract pins; nvcc/CUDA-13 header mismatch), 2 model-snapshot tests, 1 native-FP8 FSDP2 materialization test, and 2 pytest_asyncio-missing collection errors in tests/server/orchestrator.
  • One real codemod bug was caught by the sweep and fixed in the last commit: the vendored-path rewrite matched …flashqla as a prefix of the first-party flashqla_cp module.

Closes nothing by itself; tracks #78 (phases 1–5). The deprecation-stub deletion sweep is the future final phase.

qywu added 6 commits August 21, 2026 03:30
git-mv ops/quack -> ops/_vendored/quack and
ops/linear_attention/flashqla -> ops/_vendored/flashqla.  In-repo imports are
rewritten to the new paths; the old paths remain as alias stubs (sys.modules
aliasing) for one deprecation cycle.  The lint/format/codespell excludes and
the pyproject vendoring note collapse to the single _vendored/ prefix, and
the ops/README.md map is updated.
The RL and supervised objective functions (policy_loss, grpo_loss,
cispo_loss, importance_sampling_loss, opd_loss, opd_streaming_kl,
causallm_loss, reducers, loss_output) and the loss registry move out of
xorl.ops.loss into a new xorl.objectives package; ops/loss keeps only the
cross-entropy/selected-logprob kernel stack.  In-repo imports are rewritten;
the old module paths remain as compat stubs, and xorl.ops.loss /
xorl.ops re-export the objective API lazily (PEP 562) for one deprecation
cycle — lazily because the objectives import the kernels, so an eager
re-export is an import cycle.
Physically moves the seven first-party contract modules (rope_class_b,
canonical_moe_leaf, canonical_moe_cast, kernel_config_pin, bi_gemm_configs,
block_fp8_native, fused_silu_and_mul) into xorl.ops.exact, rewriting in-repo
imports and leaving compat stubs at the old paths.

Three members are aliased in place rather than moved, deviating deliberately
from the original #78 sketch:
- bi_families_v2.py is sha256-gated byte-identical against the serving copy;
- batch_invariant_ops.py turned out to be vendored-adapted from SGLang's
  srt/batch_invariant_ops — splitting or moving it would destroy side-by-side
  diffability with the serving twin, so the planned 4-way split is dropped;
- exact_sampling_transforms.py is under active rewrite in #74; the canonical
  direction flips to ops/exact/sampling_transforms.py after #74 lands.
- ops/glm5_kernels -> ops/families/glm5 and ops/dsv4 -> ops/families/dsv4.
  Deliberate deviation from the #78 sketch: the kernels stay under ops/
  rather than moving into models/transformers/<family>/ because those
  packages have import side effects (DSV4 mutates the HF Auto registries on
  import) and kernels must be importable without them.  Old paths are
  sys.modules alias stubs.
- The GatedDeltaNet and Mamba2Mixer nn.Module layer classes move from
  ops/linear_attention/layers and ops/ssm/layers to xorl.models.layers;
  ops keeps only kernels.  The old package paths re-export the classes
  lazily (PEP 562) for one deprecation cycle.
- In-repo imports rewritten; the kernel-adjacent contract modules
  (linear_attention/modules, ssm/modules) stay in ops by design.
Every export (build_sorted_indices, group_tokens_by_expert{,_v2},
DeepEPScatter, DeepEPWeightedGather, deepep_scatter, deepep_weighted_gather)
has zero importers in src/, tests/, benchmarks/, or certification/ — the
DeepEP dispatch paths in ops/moe grew their own implementations.  The #78
plan said 'merge into moe/'; deleting dead code beats moving it.
The vendored-path rewrite matched 'xorl.ops.linear_attention.flashqla' as a
prefix of the first-party module 'flashqla_cp', mispointing backend.py and
the CP equivalence test at a nonexistent _vendored.flashqla_cp.
@broly-code-security-scanner

broly-code-security-scanner Bot commented Aug 21, 2026

Copy link
Copy Markdown

Broly Security Scan

Note

Clean scan
No vulnerabilities detected in this PR.

Note

Re-scan this PR anytime with /broly scan — useful after /broly undismiss, or to refresh findings without a new push.

Broly — SAST (zai-org/GLM-5.2) · Secrets · SCA · IaC · GH Actions · Base Images · Supply Chain Threats · Exploit Chains · Adversarial Verification

We're continuously improving Broly's accuracy and finding quality — your feedback is valuable. False positives, missed findings, bugs, and feature requests all welcome.

Ask in #security-engineering   Powered by Together AI

@kiddyboots216

Copy link
Copy Markdown
Contributor

Three members are aliased in place rather than moved, deviating deliberately from the issue sketch:

don't think this is good

Per kiddyboots216 on #78/#81: the three 'aliased in place' modules are now
physically moved.

- New ops/sglang/ package for the literal serving-engine twins:
  bi_families_v2.py (moved byte-identical — same git blob as main; the
  sha256 gate hashes content, not paths) and batch_invariant_ops.py
  (vendored-adapted from sglang/srt/batch_invariant_ops; kept a single
  diffable file).  The package docstring states the paired-edit policy;
  the format/rewrite excludes follow the new path.
- exact_sampling_transforms.py -> ops/exact/sampling_transforms.py, making
  the replay contract physically canonical under ops/exact.
- Old module paths are sys.modules alias stubs (full-fidelity, including
  underscore names) for one deprecation cycle; in-repo imports codemodded.
@qywu

qywu commented Aug 21, 2026

Copy link
Copy Markdown
Member Author

Done in cc8f635 — no aliases left. You were right that the constraint was narrower than I stated: the sha256 gate hashes content, not paths, so moving the file is safe (the moved bi_families_v2.py is the same git blob as on main — byte-identical).

Per your #78 suggestion there's now an ops/sglang/ package for the literal serving-engine twins: bi_families_v2.py (byte-gated, format carve-out follows the new path) and batch_invariant_ops.py (vendored-adapted from sglang/srt/batch_invariant_ops; kept a single file so it stays diffable against the serving copy — the originally-sketched 4-way split is the one thing I'd still push back on, for that reason). exact_sampling_transforms.py is now physically ops/exact/sampling_transforms.py. Old paths are full-fidelity alias stubs for one deprecation cycle; all in-repo imports rewritten. #74 will need a rebase over the rename — I'll handle it.

@kiddyboots216

Copy link
Copy Markdown
Contributor

a lot of the file names etc. are kind of artifact-y, like the "rope class b" is just nomenclature from the blog post, i think we should feel free to take a high-level look at the kernels / ops breakdown and see how we can name things to not be so inscrutable / opaque. there's too much scar tissue in the names.

Decoder ring for the historical jargon (bi_, K3, Class-B, canonical MoE
reduce, one-round SwiGLU, families v1/v2, GKN, exact) pending the rename
pass discussed on #78 — several terms are user-facing config fields or
vocabulary shared with the serving engine and need coordinated renames.
@qywu

qywu commented Aug 21, 2026

Copy link
Copy Markdown
Member Author

Agreed on the scar tissue. Two-part response:

Done now (abed122): a name glossary in ops/README.md decoding bi_, K3, Class-A/B RoPE, canonical MoE reduce, one-round SwiGLU, families v1/v2, GKN, "exact" — so nothing is inscrutable while we rename.

Needs your sign-off before executing — most of these names are load-bearing beyond file names, so renames have blast radii:

current proposed blast radius
rope_class_b (module + fns) rope_fp32_single_round also a YAML config field rope_class_b: — needs a deprecated alias
bi_ prefix (fns, bi_gemm_configs, tests) spell out batch_invariant_ ce_mode: bi_fused is user config; bi_families_v2 is the serving twin — renaming it means renaming in SGLang too
canonical_moe_* moe_fixed_order_reduce_* CANONICAL_MOE_REDUCE_VERSION is a cross-engine contract key (string can stay; module/fn names can change)
exact_ fn prefix drop it — the ops/exact/ package now carries the meaning pure churn, best done in the stub-deletion sweep
fused_silu_and_mul's exact_fp32_silu_and_mul one_round_swiglu config stamp _exact_one_round_swiglu already uses this vocabulary
K3 (docs/k3, "zero-K3") keep — it's the k3 KL estimator, a real term
families_v2 / head_v2 keep — version names are genuine

Say which rows you want and I'll execute them as one rename commit here (module renames with alias stubs) plus a follow-up for the config-field deprecations.

qywu added 5 commits August 21, 2026 16:26
'Class-B' was blog-post nomenclature; the descriptive name says what it is:
one fp32 chain with a single final round.  Module, functions, internal
config stamps, and the YAML field are renamed; 'rope_class_b:' remains
accepted as a deprecated alias in both entry points (DeprecationWarning),
and XORL_ROPE_CLASS_B stays an env alias.  The ops module docstring keeps
the Class-A/Class-B mapping as historical context.
#81 review, row 3)

Module and Python-level function names spell out what 'canonical' meant: the
pinned fixed-order expert-contribution reduction.  The cross-engine contract
key CANONICAL_MOE_REDUCE_VERSION and the registered torch.library op names
(xorl_k3::_canonical_moe_*) are pinned identifiers and keep their strings.
Matches the existing _exact_one_round_swiglu resolution stamp vocabulary; a
deprecated module-level alias keeps the old callable importable.
…review, row 2)

- ce_mode canonical value is now 'batch_invariant'; 'bi_fused' remains an
  accepted deprecated alias normalized (with a DeprecationWarning) in both
  argument entry points, and the CrossEntropyMode Literal accepts both.
- ops/loss/bi_fused_lm_head.py -> batch_invariant_lm_head.py;
  bi_fused_per_token_ce / bi_fused_vocab_parallel_per_token_ce /
  resolve_bi_fused_lm_head_tp_groups spell out batch_invariant_*.
- ops/exact/bi_gemm_configs.py -> batch_invariant_gemm_configs.py.
- Prose, error messages, examples, and docs updated; test files renamed
  (incl. the tests/distributed shard claim).
- The bi_ prefix survives only inside the serving twins
  (bi_families_v2, batch_invariant_ops' bi_* kernels, bi_fused_gdn_gating)
  whose symbol names must match the engine.
- Alias regression tests cover rope_class_b and ce_mode='bi_fused'.
@qywu

qywu commented Aug 21, 2026

Copy link
Copy Markdown
Member Author

All table rows executed (4 commits, abed122..c28f8cb):

  • rope_class_brope_fp32_single_round — module, functions, internal stamps, and the YAML field. rope_class_b: and XORL_ROPE_CLASS_B remain deprecated aliases (DeprecationWarning). Test files renamed incl. the distributed shard claim.
  • bi_ spelled out — canonical ce_mode value is now batch_invariant (bi_fused accepted + warned in both entry points); bi_fused_lm_head.pybatch_invariant_lm_head.py with its functions; bi_gemm_configsbatch_invariant_gemm_configs; prose/messages/examples/docs updated. The bi_ prefix survives only inside the serving twins (bi_families_v2, the bi_* kernels in batch_invariant_ops, bi_fused_gdn_gating) whose symbols must match the engine.
  • canonical_moe_*moe_fixed_order_reduce_* — modules + Python names; the cross-engine contract key CANONICAL_MOE_REDUCE_VERSION and the registered xorl_k3::_canonical_moe_* torch.library op names keep their strings (pinned identifiers).
  • exact_fp32_silu_and_mulone_round_swiglu with a deprecated alias.
  • Rows marked keep/defer stayed as proposed (K3, families_v2/head_v2; the exact_ fn-prefix drop lands with the stub-deletion sweep).

Glossary updated to lead with the new names (old terms noted as "formerly"). Alias regression tests added for both config deprecations. Verified: full pre-commit, arguments suites, the batch-invariant head + golden-gate + rmsnorm-family + exact-head + trainers surfaces all green locally.

Comment thread src/xorl/ops/exact/kernel_config_pin.py Fixed
…rity-bot finding)

The sentinel alone is not sufficient authorization: whoever controls
XORL_EXACT_KERNEL_CONFIG_DIR could pre-place it anywhere.  Deletion now also
requires the resolved target to live strictly inside the (resolved) pin
directory and refuses symlinked targets, bounding any rmtree to the pin tree.
Pre-existing behavior surfaced by the phase-3 file move.
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.

3 participants