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
142
143
144
//! Convert-time chat-template auto-inject (ADR-012 follow-up, 2026-04-30).
//!
//! # Why this module exists
//!
//! `tokenizer.chat_template` is a GGUF metadata key consulted by
//! [`crate::serve::render_chat_template`] (priority 3, between `--chat-template`
//! CLI overrides and the hardcoded Gemma4 fallback). When the source HF model
//! ships no `chat_template` field — e.g. all 4 abliterated Qwen3.6
//! variants on disk as of 2026-04-30 — the convert path at
//! [`crate::backends::gguf::load_tokenizer_metadata`] used to silently skip
//! the emit, leaving the runtime to fall through to the Gemma4 hardcoded
//! string. Qwen3 was never trained on Gemma4 control tokens, so the
//! resulting chat session produced gibberish and contaminated ADR-013's
//! sourdough byte-parity gate.
//!
//! This module owns the *vendor-shipped* per-architecture default
//! templates. Each fixture under `chat_templates/*.jinja` is copied
//! verbatim from a known vendor release of a model in that architecture
//! family (see `[VENDOR PROVENANCE]` annotations on each constant). We
//! never invent a template; if no vendor reference exists for an arch,
//! we return `None` and the caller logs a structured WARN.
//!
//! # Priority chain (mirrored in `gguf.rs::load_tokenizer_metadata`)
//!
//! 1. `chat_template.jinja` file alongside the HF tokenizer
//! 2. `tokenizer_config.json[chat_template]`
//! 3. **arch-default from this module** (NEW)
//! 4. Graceful skip + WARN (operator-visible)
//!
//! [VENDOR PROVENANCE — qwen3-chatml.jinja]
//! Source file: `/opt/hf2q/models/qwen3.6-27b-dwq46/tokenizer_config.json`
//! Field: `chat_template`
//! Length: exactly 7764 bytes (asserted in [`QWEN3_CHATML_LEN`] +
//! in tests via [`vendor_chat_template_lengths_match_fixtures`]).
//! Captured: 2026-04-30 by ADR-012 chat-template-auto-inject CFA session.
/// Vendor-shipped Qwen3 ChatML chat template, served verbatim from
/// `qwen3.6-27b-dwq46/tokenizer_config.json`.
///
/// Used by `qwen35` and `qwen35moe` when the source HF dir omits a
/// chat_template (e.g. all Qwen3.6 abliterated variants).
pub const QWEN3_CHATML: &str = include_str!;
/// DeepSeek-V4-Flash-0731 GGUF interoperability template.
///
/// The hf2q runtime uses [`crate::core::deepseek_v4_encoding`] for its
/// stateful, pure-Rust encoding path. This Jinja fixture is emitted into GGUF
/// metadata so external readers such as the pinned llama.cpp reference can
/// apply the same public chat contract. Provenance: llama.cpp template
/// `models/templates/deepseek-ai-DeepSeek-V4-Flash-0731.jinja`, commit
/// `6ea215d17`, which ports DeepSeek's published `encoding_dsv4.py`.
pub const DEEPSEEK_V4_FLASH_0731: &str =
include_str!;
/// Compile-time-known length of [`QWEN3_CHATML`]. The fixture's length
/// must match the vendor's exactly — drift means someone trimmed or
/// re-encoded the template, and the byte-identical guarantee fails.
pub const QWEN3_CHATML_LEN: usize = 7764;
pub const DEEPSEEK_V4_FLASH_0731_LEN: usize = 7646;
/// Look up the vendor-shipped chat template for `arch`.
///
/// Returns `None` for arches where we have no vendor-shipped reference
/// to embed. The convert path then logs a structured WARN and skips
/// emit (graceful degradation — the runtime falls through to the
/// hardcoded Gemma4 fallback as before, and the operator sees a
/// log line rather than silent gibberish at chat time).
///
/// # Arch coverage (2026-04-30)
///
/// | arch | source | status |
/// |------------|------------------------|------------|
/// | qwen35 | qwen3.6-27b-dwq46 | EMBEDDED |
/// | qwen35moe | qwen3.6-27b-dwq46 | EMBEDDED |
/// | qwen2 | (no vendor ref yet) | WARN-only |
/// | qwen3 | (no vendor ref yet) | WARN-only |
/// | gemma3 | (no vendor ref yet) | WARN-only |
/// | gemma4 | (no vendor ref yet) | WARN-only |
/// | llama | (no vendor ref yet) | WARN-only |
/// | mistral | (no vendor ref yet) | WARN-only |
/// | phi | (no vendor ref yet) | WARN-only |
///
/// New arch entries MUST be sourced from a published vendor model's
/// `tokenizer_config.json` and copied verbatim — never synthesized.