1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
// SPDX-License-Identifier: MIT OR Apache-2.0
//! 2026-09-25: Helpers: BF16 conversion, sampling defaults, loop-detection
//! constants (the detectors are in `helpers/detectors.rs`), env parsers,
//! and the pure predicates behind the length limits (the limits travel on
//! `SchedCtx`; see `scheduler::limits`).
//!
//! Owner: scheduler.
//! Invariants: none beyond the types.
/// 2026-09-25: Convert two little-endian BF16 bytes to f32.
/// 2026-09-25: Would the next decode step reach the served context
/// ceiling? `position` is `SequenceState::seq_len`. `max_seq_len == 0`
/// means no ceiling, and this is then always false.
/// 2026-09-25: Has this sequence hit a hard ceiling: completion budget
/// exhausted (`remaining == 0`) or [`seqlen_force_stop`]?
// 2026-09-25: sampling defaults for the `SamplingParams` the scheduler
// builds.
pub const DEFAULT_LZ_PENALTY: f32 = 0.0;
pub const DEFAULT_DRY_MULTIPLIER: f32 = 0.0;
pub const DEFAULT_DRY_BASE: f32 = 1.75;
pub const DEFAULT_DRY_ALLOWED_LENGTH: u32 = 3;
/// 2026-09-25: Thinking-loop watchdog parameters. When the model's
/// `WatchdogParams::enable_think_loop_watchdog` is set, `decode_logits_step`
/// checks every `THINK_LOOP_CHECK_STRIDE` thinking tokens once
/// `THINK_LOOP_MIN_TOKENS` have been spent inside `<think>`: if the output
/// ends in a pattern of `THINK_LOOP_PERIOD_MIN..=THINK_LOOP_PERIOD_MAX`
/// tokens repeated back to back `WatchdogParams::think_loop_min_repeats`
/// times (3 when MODEL.toml leaves it unset), unless the request overrides
/// these, it sets `force_end_thinking`.
pub const THINK_LOOP_MIN_TOKENS: u32 = 48;
pub const THINK_LOOP_CHECK_STRIDE: u32 = 8;
pub const THINK_LOOP_PERIOD_MIN: usize = 4;
pub const THINK_LOOP_PERIOD_MAX: usize = 20;
pub const THINK_LOOP_MIN_REPEATS: usize = 3;
/// 2026-09-25: Carried as `WatchdogParams::think_loop_scan_window`, but
/// `detect_token_loop` does not read it (`_scan_window`).
pub const THINK_LOOP_SCAN_WINDOW: usize = 160;
/// 2026-09-25: Content-loop watchdog parameters. Outside a tool body, every
/// `CONTENT_LOOP_CHECK_STRIDE` content tokens once `CONTENT_LOOP_MIN_TOKENS`
/// have been emitted, the content-phase handlers (`decode_logits_content.rs`,
/// `emit_step/token.rs`) check whether the output ends in a pattern of
/// `CONTENT_LOOP_PERIOD_MIN..=CONTENT_LOOP_PERIOD_MAX` tokens repeated
/// `CONTENT_LOOP_MIN_REPEATS` times back to back, unless the request or
/// operator overrides these; a hit rolls back or ends the response.
///
/// Armed by `SchedLevers::loop_watchdog()`, which serve sets from
/// `--content-loop-watchdog`, then `METRALE_CONTENT_LOOP_WATCHDOG`, then
/// MODEL.toml `[behavior].enable_loop_watchdog` (false when unset); the
/// dashboard's `/watchdog` command can change it mid-run.
pub const CONTENT_LOOP_MIN_TOKENS: u32 = 48;
pub const CONTENT_LOOP_CHECK_STRIDE: u32 = 16;
pub const CONTENT_LOOP_PERIOD_MIN: usize = 2;
pub const CONTENT_LOOP_PERIOD_MAX: usize = 64;
pub const CONTENT_LOOP_MIN_REPEATS: usize = 3;
pub const CONTENT_LOOP_SCAN_WINDOW: usize = 280;
/// 2026-09-25: Repeat threshold of the digit-normalized content-loop
/// detector when the request sets none. It is one more than
/// `CONTENT_LOOP_MIN_REPEATS`, so a three-item numbered list, whose lines
/// normalize to the same pattern, does not fire.
pub const CONTENT_LOOP_NORM_MIN_REPEATS: usize = 4;
/// 2026-09-25: Stands in for each run of numeric tokens in the normalized
/// tail (`detect_content_token_loop_normalized_with`). It must not be a
/// real token id.
pub const NUMERIC_SENTINEL: u32 = u32MAX;
/// 2026-09-25: Parse of `METRALE_DISABLE_WATCHDOGS`: true for `1` or `true`
/// (trimmed, case-insensitive), false otherwise. `SchedLevers` resolves
/// `disable_watchdogs` with it.
pub
/// 2026-09-25: Parse of `METRALE_DISABLE_FORCED_TOKEN` into "forced-token
/// fast path enabled": unset → true; `1` or `true` (trimmed,
/// case-insensitive) → false; anything else → true.
///
/// `SchedLevers::forced_token_fastpath` holds the result, and
/// `ForcedTokenFastPath` (`logit_processors/forced_token.rs`) reads it:
/// when the grammar admits exactly one next token, that token is emitted
/// without sampling.
pub
/// 2026-09-25: The default-on rule: unset → true; `0` or `false` (trimmed,
/// case-insensitive) → false; anything else → true. `SchedLevers` resolves
/// `tool_response_stop`, `tool_eos_escape` and `grammar_budget_close` with
/// it.
pub
pub use *;
pub use *;