Handoff: fixed supervisor + full findings/state so work can resume
Browse files- HANDOFF.md +104 -0
HANDOFF.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# SecureCoder β handoff state (2026-10-04)
|
| 2 |
+
|
| 3 |
+
Everything needed to pick this up later. All code lives in this repo and in
|
| 4 |
+
`C:\Users\Taimwe\.cline\data\workspaces\chat\securecoder-pipeline`.
|
| 5 |
+
|
| 6 |
+
## The bug we found and fixed
|
| 7 |
+
|
| 8 |
+
**v1 and v2 both emit literal `\n` (backslash-n) instead of real newlines**, so their
|
| 9 |
+
Python output does not parse. Measured with the same harness on the same prompts:
|
| 10 |
+
|
| 11 |
+
| Model | literal `\n` | valid Python |
|
| 12 |
+
|---|---:|---:|
|
| 13 |
+
| base `unsloth/Qwen3-Coder-30B-A3B-Instruct` | β | **93.3%** |
|
| 14 |
+
| `securecoder-30b-pro` (v1) | 14/15 | ~6.7% |
|
| 15 |
+
| `securecoder-30b-pro-v2` | 15/15 | **0.0%** |
|
| 16 |
+
|
| 17 |
+
**Root cause: parts of the training data mix store message text JSON-escaped.**
|
| 18 |
+
`_unescape_if_needed()` in `train_securecoder.py` now repairs them. Confirmed by
|
| 19 |
+
`--validate-only` against 40 rows/source:
|
| 20 |
+
|
| 21 |
+
| Source | repaired/40 |
|
| 22 |
+
|---|---:|
|
| 23 |
+
| `Trendyol/Cybersecurity-Instruction-Tuning` | 40 (100%) |
|
| 24 |
+
| `AlicanKiraz0/Cybersecurity-Dataset-Fenrir-v2.1` | 40 (100%) |
|
| 25 |
+
| `Humanlearning/CyberSecurity_OWASP-sft-dataset` | 40 (100%) |
|
| 26 |
+
| `ukcli/Cybersecurity-Dataset-Heimdall-v1.1` | 40 (100%) |
|
| 27 |
+
| `MrClipperz134/CTF-Instruct` | 23 (58%) |
|
| 28 |
+
| hermes-fc, xlam, Magicoder, threat-intel, ctf-solver, FineTome | 0 |
|
| 29 |
+
|
| 30 |
+
Every escaped source is a cybersecurity dataset. That is why tool-calling still scored
|
| 31 |
+
100% (clean sources dominate it) while code scored 0% (escaped sources dominate it).
|
| 32 |
+
|
| 33 |
+
## Files in this repo
|
| 34 |
+
|
| 35 |
+
| File | What changed |
|
| 36 |
+
|---|---|
|
| 37 |
+
| `train_securecoder.py` | **fixed** β `_unescape_if_needed()`, `repaired=` counter, BOM stripped so uv PEP 723 deps install |
|
| 38 |
+
| `eval_securecoder.py` | **fixed** β honours `--max-new-tokens` (was hardcoded 384), excludes truncation from the syntax score, falls back across dataset splits |
|
| 39 |
+
| `pipeline.py` | supervisor: `RESULT` seeded up front (fixes the `UnboundLocalError` that killed every supervised run), retries, `ADAPTER_REPO`/`GGUF_REPO` env overrides |
|
| 40 |
+
| `debug_v2_code.py` | dumps full replies β found the escaped newlines |
|
| 41 |
+
| `bisect_adapter.py` | proved base+adapter (no merge) is also affected β the adapter, not the merge |
|
| 42 |
+
|
| 43 |
+
## Two bugs worth remembering
|
| 44 |
+
|
| 45 |
+
1. **UTF-8 BOM before `# /// script`** β uv never saw the PEP 723 metadata block, so
|
| 46 |
+
`torch` was never installed and every job died in 3β6s with `No module named 'torch'`.
|
| 47 |
+
This is almost certainly what the old `patch-deps` jobs were fighting.
|
| 48 |
+
2. **`eval_securecoder.py` scored truncation as invalid syntax.** With `max_new_tokens=384`
|
| 49 |
+
correct code was cut mid-statement and counted as a failure. Now truncated replies are
|
| 50 |
+
tracked separately (`truncated`, `n_truncated`, `truncated_rate`).
|
| 51 |
+
|
| 52 |
+
## Repo state
|
| 53 |
+
|
| 54 |
+
- **Deleted** (intentionally, both shipped broken code): `securecoder-30b-pro-merged`,
|
| 55 |
+
`securecoder-30b-pro-GGUF`, `securecoder-30b-pro-v2-merged`, `securecoder-30b-pro-v2-GGUF`.
|
| 56 |
+
- **Kept**: both adapters (`securecoder-30b-pro`, `securecoder-30b-pro-v2`) β re-mergeable.
|
| 57 |
+
- **Eval reports**: `Taimwe/securecoder-eval-v2`, `Taimwe/securecoder-eval-base`.
|
| 58 |
+
|
| 59 |
+
## How to resume
|
| 60 |
+
|
| 61 |
+
```powershell
|
| 62 |
+
# 1. retrain with the fixed data (a100-large, ~2.4h, ~$6)
|
| 63 |
+
hf jobs run ghcr.io/astral-sh/uv:python3.12-bookworm `
|
| 64 |
+
uv run --with torch --with transformers --with datasets --with huggingface_hub `
|
| 65 |
+
--with bitsandbytes --with accelerate --with unsloth --with trl --with peft `
|
| 66 |
+
https://huggingface.co/Taimwe/securecoder-scripts/resolve/main/train_securecoder.py `
|
| 67 |
+
--base-model unsloth/Qwen3-Coder-30B-A3B-Instruct `
|
| 68 |
+
--output-repo Taimwe/securecoder-30b-pro-v3 `
|
| 69 |
+
--mix-scale 0.25 --max-steps 480 --max-seq-length 2048 --learning-rate 1e-4 `
|
| 70 |
+
--save-steps 200 --eval-samples 100 --report-to none `
|
| 71 |
+
--flavor a100-large --timeout 10800 --secrets HF_TOKEN --detach
|
| 72 |
+
|
| 73 |
+
# 2. then merge + quantise + eval
|
| 74 |
+
```
|
| 75 |
+
|
| 76 |
+
**Sizing matters:** the full mix is 83,781 rows; at seq 4096 that is 983 steps at
|
| 77 |
+
43.5 s/it β **11.8h / $29.50**. With `--mix-scale 0.25 --max-seq-length 2048` it is
|
| 78 |
+
480 steps at 17.7 s/it β **2.4h / $6**. Do not omit those two flags.
|
| 79 |
+
|
| 80 |
+
Also set `--timeout` generously but below the credit budget you intend to spend.
|
| 81 |
+
|
| 82 |
+
## Still to do (publishing, free)
|
| 83 |
+
|
| 84 |
+
- Fill the `_pending_` eval table on the model cards with the eval-14 numbers.
|
| 85 |
+
- The corrected harness is ready: `python publish_cards.py` or three `hf upload` calls.
|
| 86 |
+
|
| 87 |
+
## Money spent this session (~$13 of 20)
|
| 88 |
+
|
| 89 |
+
| Item | ~$ |
|
| 90 |
+
|---|---:|
|
| 91 |
+
| two evals (v2 + base, A/B) | 2.30 |
|
| 92 |
+
| adapter-vs-merge bisect | 0.11 |
|
| 93 |
+
| two `--validate-only` diagnostics | 0.06 |
|
| 94 |
+
| cancelled run A (bad scoping: full mix @4096) | 7.45 |
|
| 95 |
+
| cancelled run B (this one, stopped in error) | 2.50 |
|
| 96 |
+
|
| 97 |
+
The `$7.45` was avoidable β v2's original job command showed `--mix-scale 0.25` and
|
| 98 |
+
`--max-seq-length 2048`, and I should have read it before launching instead of guessing.
|
| 99 |
+
|
| 100 |
+
## Unrelated scaffold
|
| 101 |
+
|
| 102 |
+
`C:\Users\Taimwe\.cline\data\workspaces\chat\flux2-lora` β LoRA fine-tune + FastAPI
|
| 103 |
+
serving for `FLUX.2-klein-4B` (Apache-2.0). Not runnable here: HF large-file downloads
|
| 104 |
+
transfer at **0 MB/min** from this machine, and there is no GPU.
|