@@ -55,7 +55,7 @@ above speaks generic logits-processor vocabulary.
5555 ▼
5656 stream / executor / scheduler ── NO
5757 GenerateStream (gates on prepare()), NormalExecutor / MtpExecutor
58- (call batch_logits_processor ::*), FIFOScheduler (generic readiness skip),
58+ (call stream_logits_processor ::*), FIFOScheduler (generic readiness skip),
5959 BatchDecodeScheduler (only the generic hasStructuredOutputRequest() predicate)
6060 │ wired once at startup by
6161 ▼
@@ -71,11 +71,11 @@ Two seams cross these layers without leaking concrete types:
7171 generic factory, breaking the otherwise-cyclic build dependency
7272 (` models:logits_processor ` → xgrammar → ` engine_base/stream ` →
7373 ` models:logits_processor ` ).
74- 2 . ** Batch -dispatch seam** — ` batch_logits_processor ::*` + ` SpecLogitsVerifyRunner `
75- let executors drive whole-batch masks (verify / draft / decode). The dispatch
76- is the only code that walks ` StreamGroups ` ; it hands the runner a flat list of
77- ` SpecLogitsProcessor ` participants, so the model layer and executors never see
78- ` StreamGroups ` or a concrete backend.
74+ 2 . ** Stream -dispatch seam** — ` stream_logits_processor ::*` + ` SpecLogitsVerifyRunner `
75+ lets stream/executor preparation code drive whole-batch masks (verify / draft /
76+ decode). The dispatch is the only code that walks ` StreamGroups ` ; it hands the
77+ runner a flat list of ` SpecLogitsProcessor ` participants, so the model layer and
78+ concrete executors never see a constraint backend.
7979
8080Data (not behavior) does cross the boundary in two benign forms: the request
8181config fields on ` GenerateConfig ` (` json_schema ` / ` regex ` / ` ebnf ` /
@@ -116,10 +116,10 @@ configuration contracts, not engine-type coupling.
116116 that exposes only per-stream primitives (` tryAcceptAndFillBitmask ` for verify,
117117 ` fillDecodeBitmask ` / ` fillDraftBitmask ` for decode/draft, plus a generic
118118 ` applyBitmask ` ). For all three batch passes (verify, draft, decode),
119- ` BatchLogitsProcessorDispatch ` collects the active processors from
119+ ` StreamLogitsProcessorDispatch ` collects the active processors from
120120 ` StreamGroups ` into a flat list and ` SpecLogitsVerifyRunner ` owns the batch
121121 assembly (allocate, per-stream fill, merge, apply). The model layer never sees
122- ` StreamGroups ` ; callers name only the generic ` batch_logits_processor `
122+ ` StreamGroups ` ; callers name only the generic ` stream_logits_processor `
123123 namespace.
124124
1251255 . Fail closed rather than silently generating unconstrained output.
@@ -251,7 +251,7 @@ calls `notifyCommit`.
251251### Normal Decode Batch Mask
252252
253253` NormalExecutor ` calls
254- ` batch_logits_processor::batchApplyDecodeMaskFromStreams ` immediately before
254+ ` stream_logits_processor::applyDecodeMaskFromStreams ` immediately before
255255sampling, which collects participants and runs ` SpecLogitsVerifyRunner::runDecode `
256256(one row per stream). This path collapses per-stream mask launches into one batch
257257apply. If the batch mask ran, ` SamplerInputs::is_decode_mask_batched ` is set so the
@@ -268,19 +268,21 @@ model layer):
268268
269269- draft-side masking (` runDraft ` + ` fillDraftBitmask ` ) keeps proposed tokens in
270270 the legal set when possible: each processor DFS-walks its proposed chain, fills
271- its single row, then rolls back so observable state is unchanged;
271+ its single row, then rolls back so observable state is unchanged. MTP exposes
272+ this through ` MtpDraftMaskState ` , so the executor does not manage CPU draft-chain
273+ row alignment itself;
272274- verify-side masking (` run ` + ` tryAcceptAndFillBitmask ` ) fills each stream's
273275 ` [propose_step + 1, words] ` row block, merges processors for the same stream by
274276 bitwise AND, and applies the merged bitmask through the generic ` applyBitmask() `
275- hook.
277+ hook. This is applied while ` MtpBatchStreamProcessor ` prepares the target
278+ sampler input.
276279
277280The actual matcher state remains unchanged during those batch passes. After the
278281speculative sampler decides the accepted suffix, the normal stream commit path
279282updates every attached logits processor exactly once.
280283
281- ` MtpExecutor ` and ` MtpBatchStreamProcessor ` therefore know only about
282- ` batch_logits_processor ` , ` SpecLogitsVerifyRunner ` , and ` SpecLogitsProcessor ` ,
283- not ` GrammarLogitsProcessor ` .
284+ ` MtpExecutor ` and ` MtpBatchStreamProcessor ` therefore know only about the
285+ ` stream_logits_processor ` seam, not ` GrammarLogitsProcessor ` .
284286
285287### PD Separation
286288
@@ -340,7 +342,7 @@ resolve the hook's definition). This keeps the composition root explicit (no
340342
341343` NormalExecutor ` , ` MtpExecutor ` , and ` MtpBatchStreamProcessor ` should not know
342344about grammar. The current design satisfies that by routing all batch mask work
343- (verify, draft, decode) through ` batch_logits_processor ` : the stream dispatch
345+ (verify, draft, decode) through ` stream_logits_processor ` : the stream dispatch
344346collects ` SpecLogitsProcessor ` participants into a flat list and delegates the
345347actual assembly to ` SpecLogitsVerifyRunner ` , so no concrete processor owns the
346348whole batch and the model layer never sees ` StreamGroups ` . The names are
0 commit comments