- name
- day0-release
- description
- Deterministic end-to-end driver for day-0 quantized-checkpoint releases — chains PTQ → evaluation → comparison with enforced gates between stages (the evaluation stage deploys the checkpoint itself), and returns a publish decision (ACCEPT / REGRESSION / ANOMALOUS / INFEASIBLE). Use when the user asks to "release a model at day-0", "quantize and validate model X is within N% of baseline and tell me if it's publishable", or "run the full day-0 workflow". Do NOT use for single-stage requests — quantizing only (use ptq), serving only (use deployment), evaluating only (use evaluation), or comparing two existing runs (use compare-results).
- license
- Apache-2.0
# Day-0 Release
Drive a model from a pretrained checkpoint to a publish decision for a quantized
checkpoint, in a fixed sequence with a gate after every stage. This skill is a
**conductor**: it sequences the existing domain skills and enforces the gates —
it does not re-implement quantization, serving, evaluation, or comparison.
**Goal (the default day-0 criterion):** a quantized checkpoint smaller than the
source, with accuracy drop within the threshold (default <1%) on the standard
benchmark set versus the matching baseline, plus a publish recommendation.
## When to use
Use only for the full goal-driven release. For a single stage, route to the
domain skill directly: quantize → **ptq**, serve → **deployment**, evaluate →
**evaluation**, compare two existing runs → **compare-results**.
## Inputs
Resolve these before starting (ask the user for anything missing):
- **Model** — HF handle or checkpoint path.
- **Recipe / qformat** — e.g. `nvfp4`, `fp8`, or a recipe path. One candidate for v1.
- **Cluster / launcher** — from `clusters.yaml` (see the common skill's
`environment-setup.md`).
- **Eval set** — defaults to the evaluation skill's AA suite
(`recipes/tasks/aa/`).
- **Threshold** — max accuracy drop; default `0.01` (1%).
## The chain
```text
setup ─▶ PTQ ─▶ canary ─▶ baseline-eval ─▶ quantized-eval ─▶ compare ─▶ verbosity ─▶ closeout
│ │ │ │ │ │
gate_ptq /health gate_run gate_run gate_compare gate_verbosity
+ 1 gen
```
The **evaluation** skill deploys the model it evaluates (it stands up its own
endpoint per run), so there is no separate deploy *stage* — a serving failure
during evaluation surfaces through the eval gate (`DEPLOYMENT_HEALTH_FAILED`) and
triages to the **deployment** skill (see Step 4). The Step 2b **canary** is not
that: it runs *before* any evaluation precisely so an unservable checkpoint is
caught in ~15 min rather than after a multi-hour eval.
Accuracy (Step 5) and verbosity (Step 5b) are **independent gates**; closeout
requires both.
Run each stage by invoking the domain skill, then run its gate before
proceeding. **Do not advance past a failed gate.** Copy this checklist and track
progress:
```text
- [ ] Step 0: Resolve inputs; confirm threshold and eval set
- [ ] Step 1: Setup gate — creds present, cluster reachable
- [ ] Step 2: PTQ (ptq skill) → gate_ptq.py
- [ ] Step 2b: Serving canary — /health + one generation (deployment skill)
- [ ] Step 3: Baseline eval (evaluation skill, deploys source) → gate_run.py
- [ ] Step 4: Quantized eval (evaluation skill, deploys candidate) → gate_run.py
- [ ] Step 5: Compare (compare-results skill) → external sanity → gate_compare.py → decision
- [ ] Step 5b: Verbosity gate → gate_verbosity.py
- [ ] Step 6: Closeout — report + publish recommendation
```
### Step 1 — Setup gate
Use the common skill's `credentials.md` and `remote-execution.md` to confirm
credentials and cluster reachability. If either fails, stop with
`SYSTEMIC` — do not start PTQ.
### Step 2 — PTQ
Invoke the **ptq** skill to produce the quantized checkpoint. Then gate:
```bash
# The ptq skill's post-PTQ validation produces a validation-summary JSON (size
# ratio + layer-precision counts + metadata diffs; see the ptq skill's
# references/checkpoint-validation.md). v1 gates on that summary:
python "$SKILL_DIR/scripts/gate_ptq.py" --summary <validation-summary.json>
# add `--recipe <qformat>` to override the recipe recorded in the summary
```
`gate_ptq.py` returns JSON `{pass, failure_class, detail}`. On `pass: false`,
branch on `failure_class` (see **Triage** below). Do not evaluate an
unvalidated checkpoint.
#### Step 2b — serving canary (MANDATORY before Step 3)
The canary itself is **already specified** by the ptq skill: see
`ptq/references/checkpoint-validation.md` (required gate, canary query and the
`Serving canary` row of its report table) and `ptq/SKILL.md`. Run it there rather
than re-deriving it here — `gate_ptq.py` checks size, coverage and metadata, not
whether the checkpoint *loads*, and skipping the canary has cost a full baseline
eval against a checkpoint the serving stack could never load.
On failure use `failure_class: CHECKPOINT_NOT_SERVABLE` and drop to the
**deployment** skill; do not proceed to Step 3.
**What that spec does not cover: writing a canary that cannot lie.** Both of these
produced a wrong verdict on a large MoE, in opposite directions:
- **Poll ceiling > load time**, with headroom. A 50 min poll against a 51 min load
reported failure for a checkpoint that serves fine. Large MoE loads are
CPU-bound fp8 dequant (~50 min); 0% GPU during *load* is normal.
- **Print an explicit `RESULT:` on every path** and exit non-zero on failure. A
poll loop that falls through to the generation test exits 0 and reads as PASS.
- Server log on shared storage, not node-local `/tmp`.
- Canary the **as-exported** artifact, not a copy you modified to make it work.
### Step 3 — Baseline eval
The baseline is the **source** (pre-quantization) model on the same task set and
sampling params. Always run a fresh baseline via the **evaluation** skill,
which deploys the source model itself. Gate with `gate_run.py`.
### Step 4 — Quantized eval
Invoke the **evaluation** skill on the quantized checkpoint, matching the
baseline's task set and sampling params. The evaluation skill stands up the
serving endpoint itself (it builds the `deployment.command`, e.g. a
`vllm serve …`), so a serving failure surfaces here as a failed `gate_run.py`
with `DEPLOYMENT_HEALTH_FAILED`. When that happens, **drop to the deployment
skill** to reproduce and debug serving in isolation (serve the checkpoint
standalone, confirm `/health` + one generation, iterate on flags / TP / image /
env vars) rather than burning full eval cycles on a broken endpoint — then carry
the working command back into NEL's `deployment.command` and resume the eval. If
the checkpoint genuinely can't serve, `POINT_INFEASIBLE`.
**Before submitting: assert baseline/candidate config parity.** The candidate
config must differ from the baseline's in nothing but checkpoint path and served
model name. Diff mechanically — an eyeball pass misses this:
```bash
diff <(grep -vE 'checkpoint_path|served_model_name' baseline.yaml) \
<(grep -vE 'checkpoint_path|served_model_name' candidate.yaml)
```
Any other difference biases the comparison and invalidates the gate: a mismatched
`parallelism` between the two sides was worth ~2 pp, enough to invert the sign of
the delta. If the model card splits sampling params per scenario, apply the same
split to both sides. Never set an unbounded `request_timeout` (`1e9`) — it turns a
transient stall into a job that holds its GPUs until the wall clock kills it.
Gate:
```bash
python "$SKILL_DIR/scripts/gate_run.py" --run <run-summary.json>
```
A `pass: false` here means the run is incomplete or invalid (judge/parse error,
dropped samples) — do **not** compare scores from it.
### Step 5 — Compare
Invoke the **compare-results** skill. It must perform the shared external
baseline sanity check before the candidate-delta gate. A failed check is
`ANOMALOUS` with failure class `EXTERNAL_BASELINE_MISMATCH`: investigate and
rerun the baseline. If no credible comparable external score exists, record the
baseline as externally unverified and continue using the validated measured
baseline.
#### Statistical power — check BEFORE trusting any per-task verdict
A task whose measurement noise rivals the threshold cannot decide a gate. Confirm
each task's repeat count gives a standard error below the threshold; otherwise
mark it `INDETERMINATE` rather than reporting a pass/fail.
For example, on a 1 % gate on DeepSeek-V4-Pro, both tasks that originally failed passed once measured properly:
| task | runs pooled | drop | verdict |
| --- | --- | --- | --- |
| SciCode | 1 | 2.96 pp | REGRESSION |
| SciCode | 8 | **-0.96 pp** | PASS |
| IFBench | 5 | 2.73 pp | REGRESSION |
| IFBench | 16 | **0.63 pp** | PASS |
Add precision by submitting the benchmark **more times**, not by raising
`num_repeats` within a run. SciCode's floor is **8 runs per side**, pooled as a
mean — `recipes/tasks/aa/scicode.md`.
**Re-running does not guarantee fresh samples.** With a warm NEL response cache a "re-run" can
replay cached responses — two runs came back bit-identical to 16 digits. But an equal score is a
signal to check provenance (invocation id, output dir, response artifacts), **not** proof of replay:
discrete-scored tasks tie legitimately. Confirm replay before discarding a run as a duplicate.
After recording the external status, produce per-task deltas and run:
```bash
python "$SKILL_DIR/scripts/gate_compare.py" \
--baseline <baseline_scores.json> --candidate <candidate_scores.json> \
--threshold 0.01
```
The threshold is a fraction of each task's score scale. Most AA tasks report
0-100, but some (e.g. `tau2_bench_telecom` `Result`) report 0-1; the gate infers
each task's scale (0-1 if both scores are within [0, 1], else 0-100) and
normalizes the drop accordingly, so `--threshold 0.01` means "≤1 pt on a 0-100
task / ≤0.01 on a 0-1 task" uniformly. Pass `--scales '{"task": max}'` to
override inference if a task's scores happen to fall in an ambiguous range.
`gate_compare.py` checks only the candidate delta; it cannot override a failed
external baseline check. Combined decision:
- **ACCEPT (accuracy only)** — no external check failed and every task is within
the candidate threshold → continue to **Step 5b**. This verdict covers accuracy
alone; advance to Step 6 only once the verbosity gate also passes. A missing
comparable external score is not a failure; report it as externally unverified.
- **REGRESSION** — one or more tasks exceed threshold. **v1 stops here and
reports** which tasks regressed by how much. (Picking the next recipe and
re-running is deferred — see Scope.)
- **ANOMALOUS** — external baseline sanity failed, or scores are otherwise
implausible (e.g. baseline lower than candidate by a large margin, or a task
score is outside its valid range) → correct the baseline or surface it.
#### Step 5b — Verbosity gate (MANDATORY; independent of accuracy)
`gate_compare.py` does not measure verbosity, so stopping after Step 5 leaves a
hard gate unmeasured. Step 5's ACCEPT is accuracy-only — Step 6 requires both.
```bash
python "$SKILL_DIR/scripts/gate_verbosity.py" \
--baseline <baseline_eval_root> --candidate <candidate_eval_root> \
--glob 'eval_*' --exclude _high --threshold 0.05
```
Exit codes follow the other gates: `0` pass, `1` the gate failed, `2` it could not read its input.
A `2` means fix the invocation, not the checkpoint — check `--baseline`/`--candidate`, `--glob`
(`no_files_matched` names the pattern that missed), and `--exclude`. If the detail names
`collapsed_keys`, the artifact tree gave several tasks one name: point the gate at a tree whose
task dirs are `<harness>.<task>` rather than `<invocation_id>.<job_index>`, or re-sync so each
`artifacts/` carries its own `config.yml`.
Read `response_stats.avg_completion_tokens` from each task's
`artifacts/eval_factory_metrics.json`. Do **not** use the `reasoning.*` fields:
`reasoning.*_tokens` are always `0` (only the reasoning/content split is missing)
and the `*_words` siblings are a proxy that can disagree with the gate — one task
read +6.10% FAIL in words and +1.32% PASS in tokens.
The gate is two-sided; a large drop in output length is also a change.
Two filters are mandatory: same reasoning effort (pass `--exclude` explicitly — it is empty by
default, since which tier is canonical is run-specific) and complete runs only —
runs within 1% of the largest `successful_count` that **both** sides can match (exact equality
would make one dropped sample unmeasurable). A task with no such count on both sides is
`not_comparable`. When the matched count is below a run
one side has, the task carries `truncated_comparison`.
Tasks sharing no sample count are `not_comparable`, not a delta. Means under
~1000 tokens carry a `short_output_warning` — read absolute counts there.
### Step 6 — Closeout
Report the decision with: source vs output size + ratio, per-task baseline /
candidate / delta / within-threshold, **the verbosity verdict from Step 5b**,
external source and sanity status, MLflow run IDs, and a publish recommendation
(publish / do-not-publish). Archive artifacts to the workspace.
**Publish exactly what was evaluated.** Verify mechanically, not by path
convention: inode-compare a shard in the evaluated directory against the one being
published. A day-0 run leaves near-identical sibling exports
that differ by one calibration suffix — prefix rejected ones `REJECTED-` so the
artifact cannot be picked by autocomplete, and re-run the Step 2b canary against
the final path after any move.
## Triage (gate failure → decision)
For completed evaluations, apply
[evaluation run validation](../evaluation/references/run-validation.md) before
triage; its policy overrides retry actions below. Warn but do not retry solely
for failures below tolerance. For runs that fail tolerance or an independent
validation check, return findings and a recommendation to the parent/user for
review; do not automatically resubmit.
Map a gate's `failure_class` to the next action:
| `failure_class` | Action |
| --- | --- |
| `INFRA_TRANSIENT` | Retry the stage once; if it recurs, `SYSTEMIC`. |
| `MODEL_UNSUPPORTED` | PATCH: fix the recipe pattern / add model support (ptq skill owns the patch loop), then retry. If unpatchable, `POINT_INFEASIBLE`. |
| `QUANT_COVERAGE_FAILURE` | PATCH: fix the recipe wildcard so intended layers are covered; re-run PTQ. |
| `SIZE_NOT_REDUCED` | The output is not smaller than the source. If the recipe cannot shrink the source (e.g. mxfp4 under nvfp4, or fp8 under fp8), record `source_precision` in the validation summary and re-run the gate — that states *why* the growth is expected. Otherwise treat it as a real compression failure: check that the recipe matched the intended parameter mass and that the exporter did not retain the original tensors. `accept_size_growth: true` waives it unconditionally (no growth bound) and is a last resort, not the fix — it records no reason, so prefer `source_precision` where the claim is checkable. |
| `CHECKPOINT_NOT_SERVABLE` | The Step 2b canary could not load/generate. Usually a tensor-naming or config-schema mismatch between the exporter and the serving stack, or missing/dangling auxiliary files (tokenizer). Fix the export; do not evaluate. |
| `VERBOSITY_EXCEEDED` | Re-check run hygiene first (mixed reasoning effort, partial runs, unequal sample counts) — that has explained every false positive so far. If the delta survives matched, complete runs, it is a real behavioural change; do not publish on accuracy alone. |
| `DEPLOYMENT_HEALTH_FAILED` | Drop to the **deployment** skill: reproduce serving standalone (`/health` + one generation), debug flags / image / TP / env, then carry the working command into NEL's `deployment.command` and retry the eval. If it can't serve, `POINT_INFEASIBLE`. |
| `EVAL_JUDGE_FAILED` | For completed runs, apply evaluation run validation above; return tolerance failures to the parent/user without automatic retry. Otherwise investigate auth/rate limits before retrying. |
| `SAMPLE_ACCOUNTING_FAILED` | Investigate dropped/failed samples before trusting scores. |
| `EXTERNAL_BASELINE_MISMATCH` | Investigate baseline configuration, correct it, rerun the baseline, and repeat external sanity before comparison. |
| `USER_CONFIG_ERROR` | Correct it from the request, workspace, or model/config metadata and retry; if irrecoverable, return `ANOMALOUS` with evidence. |
| `UNKNOWN` | Investigate with the owning domain skill; if unresolved, return `ANOMALOUS` with the evidence and next automated retry or patch action. |
`gate_ptq.py` also emits non-blocking `notes` (present on every result). Size growth is
**blocking by default**, waived to a note only when the validation summary's `source_precision`
is already at or below the recipe's target bits and the growth is within what that explains. Recording
`source_precision` is part of the ptq skill's validation table, so the waiver is reachable from the
normal pipeline. A BF16 source that failed to compress still fails, which is the case this check
exists for.
`SYSTEMIC` (cluster down, dataset unavailable) aborts the whole run.
`POINT_INFEASIBLE` means this (model, recipe) can't work as configured.
## Output
Return a decision, not a raw artifact:
- `ACCEPT` + report + publish recommendation
- `REGRESSION` + which tasks failed the threshold and by how much
- `ANOMALOUS` / `INFEASIBLE` + reason and next automated action
- Always: workspace path + MLflow run IDs for traceability
## Scope (v1)
In v1: the linear chain + gates + report. On `REGRESSION`, v1 reports and stops.
Deferred to a follow-up: the evaluator-optimizer recipe loop (compare → pick the
next recipe → re-run PTQ), which needs the bigpareto integration and a shared
config/result schema.
Ver no GitHub