Qwen3.5-4B Sketch Coverage Shift Probe
The one idea you need
Picture a fill-in-the-blank code template, its gaps filled with pieces from a fixed toolbox; every combination runs and anything that passes the tests is kept. If a task needs a tool the toolbox lacks and the template never asks for it, the right program is never assembled.
The question
When a coding task suddenly needs an operation the template-based program builder has never seen, does the correct program still turn up among the candidates it generates?
What we found
Only when the template explicitly names the new operation. On tasks needing a brand-new operation, hand-written templates that named and typed it kept the correct program every single time; auto-generated templates kept it just 17% of the time, and stripped-down templates never. And no amount of extra candidates per blank or follow-up test questions could recover a program the builder never proposed.
Why it matters
Before investing in a smarter candidate-picker or more test queries, make sure your template actually proposes the operations new tasks demand. No selector can rescue a correct program the generation step never produced.
On this page
Results at a glance 4
How to read
Bars grouped by task type: a familiar task, the same task with a renamed operation, and a task needing a brand-new operation. Within each group, three bars for auto-generated, hand-written, and stripped templates. Bar height is the share of tasks where the correct program stayed a candidate; taller is better.
Takeaway → Hand-written bars stay at full height across all three task types, while the auto-generated bar collapses to a sliver and the stripped bar to zero once the task needs a brand-new operation.
Data table
| task shift type | auto sketch | manual sketch | erased sketch |
|---|---|---|---|
| control (in bank) | 100% | 100% | 33.3% |
| name shift | 100% | 100% | 0% |
| primitive shift | 16.7% | 100% | 0% |
Numbers from experiments/qwen35_4b_sketch_coverage_shift_probe/reports/coverage_by_shift.csv
Technical framing
Does the correct program stay in the candidate set when the task shifts? — Coverage survives shift only when the sketch names and types the shifted operator; auto sketches collapse to 17% on primitive shift.
How to read
On brand-new-operation tasks, the horizontal axis is how many fill-in options each blank may try (8, 16, then 28); the vertical axis is the share of tasks keeping the correct program. Three lines: hand-written, auto-generated, stripped templates. Higher is better.
Takeaway → Only the hand-written line rises to full coverage; the auto line stays flat near one in six and the stripped line at zero, because more options cannot propose an operation the template never names.
Data table
| hole options per typed hole (cap) | manual sketch | auto sketch | erased sketch |
|---|---|---|---|
| 8 | 83.3% | 16.7% | 0% |
| 16 | 100% | 16.7% | 0% |
| 28 | 100% | 16.7% | 0% |
Numbers from experiments/qwen35_4b_sketch_coverage_shift_probe/reports/coverage_by_shift.csv
Technical framing
Raising the hole-option cap does not rescue auto sketches on primitive shift — More candidates per hole only helps manual sketches; auto and erased sketches stay flat because the shifted operator is never proposed.
How to read
The horizontal axis is how many follow-up test questions are allowed (zero to three); the vertical axis is the share where the finally chosen program passes hidden tests. Two lines had the correct program available, one did not. Higher is better.
Takeaway → The two lines with the correct program present climb to full correctness within two or three questions, while the line missing it stays flat no matter how many questions are asked.
Data table
| oracle-elimination query budget | name shift, auto sketch | primitive shift, manual sketch | primitive shift, auto sketch |
|---|---|---|---|
| 0 | 50% | 91.7% | 16.7% |
| 1 | 83.3% | 97.9% | 16.7% |
| 2 | 100% | 100% | 16.7% |
| 3 | 100% | 100% | 16.7% |
Numbers from experiments/qwen35_4b_sketch_coverage_shift_probe/reports/active_by_shift.csv
Technical framing
Active queries disambiguate candidates but cannot create missing coverage — With coverage, 2-3 oracle queries reach 100%; without coverage (primitive shift, auto sketch) extra queries change nothing.
How to read
A grid: each row is one of twelve task families (familiar, renamed, and brand-new-operation groups); each column is a template style (auto-generated, hand-written, stripped). Cell shade is the share of that family's tasks keeping the correct program; brighter is higher.
Takeaway → The hand-written column is fully lit down every row, the auto column goes dark across most brand-new-operation families (one still keeps the program), and the stripped column is dark almost everywhere — the template, not the family, decides survival.
Data table
| auto | manual | erased | |
|---|---|---|---|
| control_length_contains | 100% | 100% | 0% |
| control_sum_mod | 100% | 100% | 0% |
| control_tuple_mod_gate | 100% | 100% | 100% |
| alias_length_contains | 100% | 100% | 0% |
| alias_sum_mod | 100% | 100% | 0% |
| alias_tuple_mod_gate | 100% | 100% | 0% |
| primitive_abs_min_delta | 0% | 100% | 0% |
| primitive_max_gate | 0% | 100% | 0% |
| primitive_max_mod | 0% | 100% | 0% |
| primitive_mul_sum | 100% | 100% | 0% |
| primitive_prefix_gate | 0% | 100% | 0% |
| primitive_prod_mod | 0% | 100% | 0% |
Numbers from reports/coverage_by_family.csv
Technical framing
Does the correct program survive each task family and sketch mode? (cap 28) — Share of tasks where the correct program stayed in the candidate set. Manual sketches keep it everywhere; auto sketches lose it on the primitive families; erasing the sketch loses it almost everywhere.
In the author’s words from the Report · “Summary”
This standalone experiment tests whether typed-sketch verified completion keeps the correct executable program in its bounded candidate set when the task substrate shifts. No new adapter is trained. The executor can score shifted primitives, while the completion bank is held fixed for the falsification pass. Each record is evaluated under three sketch conditions: auto: generated by the typed target-sketch function. manual: hand-typed sketch with the intended operator shape and typed holes. erased: low-information sketch that preserves only output format or branch labels.
Overview
Standalone falsification experiment for typed-sketch verified completion under task shift.
The experiment does not train a new adapter. It tests the load-bearing coverage assumption behind typed-sketch synthesis: when the task substrate changes, does the correct executable completion still appear in the bounded candidate set?
Large artifacts, if any are produced later, belong outside this directory:
/workspace/large_artifacts/qwen35_4b_sketch_coverage_shift_probe
Layout
configs/: experiment configuration.data/: generated shifted task records and dataset manifest.logs/: chronological experiment log.reports/: metrics, CSVs, figures, and final writeup.run_logs/: captured command output.scripts/: dataset, evaluation, and reporting entry points.src/: standalone executor, typed-sketch completer, and shifted task definitions.
Main Commands
python scripts/build_dataset.py
python scripts/run_coverage_probe.py --data data/shifted_coverage_eval.jsonl --output reports/coverage_probe.json
python scripts/make_report.pyReport
Rendered from reports/qwen35_4b_sketch_coverage_shift_probe_report.md
Summary
This standalone experiment tests whether typed-sketch verified completion keeps the correct executable program in its bounded candidate set when the task substrate shifts. No new adapter is trained. The executor can score shifted primitives, while the completion bank is held fixed for the falsification pass.
Each record is evaluated under three sketch conditions:
auto: generated by the typed target-sketch function.manual: hand-typed sketch with the intended operator shape and typed holes.erased: low-information sketch that preserves only output format or branch labels.
Key Findings
- Control target coverage at cap 28 with
autosketches was100.0%. - Primitive-shift target coverage at cap 28 was
16.7%forauto,100.0%formanual, and0.0%forerased. - Name-shift target coverage at cap 28 was
100.0%formanual, but only0.0%forerased. - The decisive failure mode is operator support in the sketch: if the sketch explicitly names and types the shifted operator, completion often works; if the operator must be discovered by the bank, coverage collapses.
- Active querying helps only after coverage exists. It cannot recover a target program that was never synthesized.
Coverage Tables
Primary cap-28 shift summary:
| shift_type | sketch_mode | records | target_coverage_pct | oracle_hidden_all_pct | selected_hidden_all_pct | avg_program_count |
|---|---|---|---|---|---|---|
| control_in_bank | auto | 24 | 100.0 | 100.0 | 66.7 | 493.2 |
| control_in_bank | erased | 24 | 33.3 | 33.3 | 33.3 | 28.0 |
| control_in_bank | manual | 24 | 100.0 | 100.0 | 66.7 | 493.2 |
| name_shift | auto | 24 | 100.0 | 100.0 | 50.0 | 501.3 |
| name_shift | erased | 24 | 0.0 | 4.2 | 4.2 | 28.0 |
| name_shift | manual | 24 | 100.0 | 100.0 | 50.0 | 501.3 |
| primitive_shift | auto | 48 | 16.7 | 16.7 | 16.7 | 698.7 |
| primitive_shift | erased | 48 | 0.0 | 0.0 | 0.0 | 28.0 |
| primitive_shift | manual | 48 | 100.0 | 100.0 | 91.7 | 117.2 |





Active Query Diagnostic
Active selection is reported at hole option cap 28. These rows test disambiguation among synthesized candidates; they are not a substitute for coverage.
| shift_type | sketch_mode | policy | budget | records | selected_hidden_all_pct |
|---|---|---|---|---|---|
| control_in_bank | auto | active_max_split | 0 | 24 | 66.7 |
| control_in_bank | auto | active_max_split | 1 | 24 | 70.8 |
| control_in_bank | auto | active_max_split | 2 | 24 | 75.0 |
| control_in_bank | auto | active_max_split | 3 | 24 | 87.5 |
| control_in_bank | auto | oracle_elimination | 0 | 24 | 66.7 |
| control_in_bank | auto | oracle_elimination | 1 | 24 | 91.7 |
| control_in_bank | auto | oracle_elimination | 2 | 24 | 95.8 |
| control_in_bank | auto | oracle_elimination | 3 | 24 | 100.0 |
| control_in_bank | manual | active_max_split | 0 | 24 | 66.7 |
| control_in_bank | manual | active_max_split | 1 | 24 | 70.8 |
| control_in_bank | manual | active_max_split | 2 | 24 | 75.0 |
| control_in_bank | manual | active_max_split | 3 | 24 | 87.5 |
| control_in_bank | manual | oracle_elimination | 0 | 24 | 66.7 |
| control_in_bank | manual | oracle_elimination | 1 | 24 | 91.7 |
| control_in_bank | manual | oracle_elimination | 2 | 24 | 95.8 |
| control_in_bank | manual | oracle_elimination | 3 | 24 | 100.0 |
| name_shift | auto | active_max_split | 0 | 24 | 50.0 |
| name_shift | auto | active_max_split | 1 | 24 | 62.5 |
| name_shift | auto | active_max_split | 2 | 24 | 75.0 |
| name_shift | auto | active_max_split | 3 | 24 | 91.7 |
| name_shift | auto | oracle_elimination | 0 | 24 | 50.0 |
| name_shift | auto | oracle_elimination | 1 | 24 | 83.3 |
| name_shift | auto | oracle_elimination | 2 | 24 | 100.0 |
| name_shift | auto | oracle_elimination | 3 | 24 | 100.0 |
| name_shift | manual | active_max_split | 0 | 24 | 50.0 |
| name_shift | manual | active_max_split | 1 | 24 | 62.5 |
| name_shift | manual | active_max_split | 2 | 24 | 75.0 |
| name_shift | manual | active_max_split | 3 | 24 | 91.7 |
| name_shift | manual | oracle_elimination | 0 | 24 | 50.0 |
| name_shift | manual | oracle_elimination | 1 | 24 | 83.3 |
| name_shift | manual | oracle_elimination | 2 | 24 | 100.0 |
| name_shift | manual | oracle_elimination | 3 | 24 | 100.0 |
| primitive_shift | auto | active_max_split | 0 | 48 | 16.7 |
| primitive_shift | auto | active_max_split | 1 | 48 | 16.7 |
| primitive_shift | auto | active_max_split | 2 | 48 | 16.7 |
| primitive_shift | auto | active_max_split | 3 | 48 | 16.7 |
| primitive_shift | auto | oracle_elimination | 0 | 48 | 16.7 |
| primitive_shift | auto | oracle_elimination | 1 | 48 | 16.7 |
| primitive_shift | auto | oracle_elimination | 2 | 48 | 16.7 |
| primitive_shift | auto | oracle_elimination | 3 | 48 | 16.7 |
| primitive_shift | manual | active_max_split | 0 | 48 | 91.7 |
| primitive_shift | manual | active_max_split | 1 | 48 | 93.8 |
| primitive_shift | manual | active_max_split | 2 | 48 | 95.8 |
| primitive_shift | manual | active_max_split | 3 | 48 | 95.8 |
| primitive_shift | manual | oracle_elimination | 0 | 48 | 91.7 |
| primitive_shift | manual | oracle_elimination | 1 | 48 | 97.9 |
| primitive_shift | manual | oracle_elimination | 2 | 48 | 100.0 |
| primitive_shift | manual | oracle_elimination | 3 | 48 | 100.0 |

Artifacts
- Dataset:
data/shifted_coverage_eval.jsonl - Dataset manifest:
data/dataset_manifest.json - Full result JSON:
reports/coverage_probe.json - Coverage CSVs:
reports/coverage_by_shift.csv,reports/coverage_by_family.csv - Active CSV:
reports/active_by_shift.csv - Large artifacts:
/workspace/large_artifacts/qwen35_4b_sketch_coverage_shift_probe
Conclusion
The coverage assumption does not survive all task shifts. The strongest result is conditional: typed completion can still work on shifted primitives when the sketch names the shifted operator and uses correctly typed holes. The weak result is equally important: erased sketches and automatically mistyped sketches often lose the target completely. The next scaling step should therefore widen and train sketch/operator coverage before investing in a stronger selector.
Experiment log 7
Show the running log (7 entries, 2026-06-24)
2026-06-24 08:20 UTC
Initialized a standalone coverage-shift probe.
Design commitments:
- Use a local executable substrate with typed sketches and verified completion.
- Do not train a new Qwen adapter for the first pass.
- Keep the completion bank intentionally unchanged while extending only the executor to score shifted primitives.
Compare three sketch conditions:
auto: the existing target-sketch generator.manual: a hand-typed sketch with the intended operator shape and typed holes.erased: a low-information sketch that preserves only output format or branch labels.
Compare three task regimes:
control_in_bank: operations and names the completion bank is tuned for.name_shift: same operations but renamed variables and constants.primitive_shift: executor-visible primitives that the completion bank was not tuned to propose.
- Evaluate candidate coverage first; only interpret active-query selection where coverage exists.
Initial implementation:
- Created standalone experiment directory.
- Copied local executor and sketch completion mechanics into
src/. - Extended the executor with
mul,abs,max,min,prod, andstartswith. - Added shifted task definitions with visible, hidden, and query-pool cases.
- Added dataset builder, README, config, and large-artifact manifest.
Validation:
python -m py_compile scripts/build_dataset.py src/*.py- Result: passed.
2026-06-24 08:31 UTC
Built the first shifted dataset with 12 records per family.
Command:
python scripts/build_dataset.py > run_logs/dataset_build_console.log 2>&1Observed:
- Total records:
144. control_in_bank:36.name_shift:36.primitive_shift:72.- Visible cases per record:
6. - Hidden cases per record:
18. - Query-pool cases per record:
48.
Sketch inspection showed the intended contrast:
- Control and name-shift
autosketches were typed correctly. - Shifted primitives such as
max,min,prod, andstartswithwere mistyped byautosketches in most families. manualsketches preserved the shifted operator shape and typed holes.erasedsketches preserved only output format or branch labels.
2026-06-24 08:38 UTC
Ran evaluator smoke test.
Command:
python scripts/run_coverage_probe.py --data data/shifted_coverage_eval.jsonl --output reports/_smoke_coverage_probe.json --max-records 3 --hole-options 8,16 --active-hole-options 16 --max-programs-per-sketch 500 > run_logs/coverage_smoke_console.log 2>&1Observed:
- Smoke completed successfully.
- Control target coverage was present.
- Primitive
auto/erasedfailures appeared in the smoke slice. - Primitive
manualsketches recovered targets in the smoke slice. - Active-query rows were emitted for both max-split and oracle-elimination policies.
Decision:
- Proceed to the full grid, but watch runtime because high-arity sketches can enumerate many completions.
2026-06-24 08:44 UTC
Started a full grid with a 4000-program completion cap, then stopped it after the first minute because high-arity rows were too slow for the information gain.
Stopped command:
python scripts/run_coverage_probe.py --data data/shifted_coverage_eval.jsonl --output reports/coverage_probe.json --hole-options 8,16,28 --active-hole-options 28 --max-programs-per-sketch 4000 > run_logs/coverage_full_console.log 2>&1Reason:
- Early tuple-style rows were taking tens of seconds each.
- The smoke run had already recovered the relevant high-arity targets within 500 completions.
- The falsification question is coverage under shift, not exhaustive enumeration at a very large cap.
Adjustment:
- Rebuilt the dataset at 8 records per family to preserve family balance while reducing runtime.
- Used
1000completions per sketch for the full run.
Command:
python scripts/build_dataset.py --records-per-family 8 > run_logs/dataset_build_records8_console.log 2>&1Observed:
- Total records:
96. control_in_bank:24.name_shift:24.primitive_shift:48.
2026-06-24 08:55 UTC
Completed the full coverage and active-query grid.
Command:
python scripts/run_coverage_probe.py --data data/shifted_coverage_eval.jsonl --output reports/coverage_probe.json --hole-options 8,16,28 --active-hole-options 28 --max-programs-per-sketch 1000 > run_logs/coverage_full_cap1000_console.log 2>&1Runtime:
864coverage jobs completed in9:35.
Primary cap-28 coverage results:
control_in_bank,auto: target coverage24/24, candidate oracle24/24, visible-selected hidden all-pass16/24.control_in_bank,manual: target coverage24/24, candidate oracle24/24, visible-selected hidden all-pass16/24.control_in_bank,erased: target coverage8/24, candidate oracle8/24, visible-selected hidden all-pass8/24.name_shift,auto: target coverage24/24, candidate oracle24/24, visible-selected hidden all-pass12/24.name_shift,manual: target coverage24/24, candidate oracle24/24, visible-selected hidden all-pass12/24.name_shift,erased: target coverage0/24, candidate oracle1/24, visible-selected hidden all-pass1/24.primitive_shift,auto: target coverage8/48, candidate oracle8/48, visible-selected hidden all-pass8/48.primitive_shift,manual: target coverage48/48, candidate oracle48/48, visible-selected hidden all-pass44/48.primitive_shift,erased: target coverage0/48, candidate oracle0/48, visible-selected hidden all-pass0/48.
Family-level primitive-shift cap-28 target coverage:
primitive_mul_sum:auto 8/8,manual 8/8,erased 0/8.primitive_abs_min_delta:auto 0/8,manual 8/8,erased 0/8.primitive_max_gate:auto 0/8,manual 8/8,erased 0/8.primitive_max_mod:auto 0/8,manual 8/8,erased 0/8.primitive_prefix_gate:auto 0/8,manual 8/8,erased 0/8.primitive_prod_mod:auto 0/8,manual 8/8,erased 0/8.
Active-query cap-28 diagnostic:
- Control
auto/manual: visible-selected16/24; active max-split reached21/24at budget 3; oracle elimination reached24/24. - Name-shift
auto/manual: visible-selected12/24; active max-split reached22/24at budget 3; oracle elimination reached24/24by budget 2. - Primitive-shift
manual: visible-selected44/48; active max-split reached46/48at budget 3; oracle elimination reached48/48by budget 2. - Primitive-shift
auto: stayed at8/48for every active budget because coverage was absent for five of six families. - Primitive-shift
erased: stayed at0/48.
Interpretation:
- Completion coverage survives name shift when the sketch carries the correct structure.
- Completion coverage does not survive primitive shift when the sketcher mistypes or omits the shifted operator.
- If the shifted operator is explicitly present in a correctly typed sketch, the completion bank can usually fill the arguments and recover target coverage.
- Active querying is useful for disambiguating survivors after coverage exists, but it cannot recover absent programs.
2026-06-24 09:08 UTC
Generated report, CSVs, and figures.
Command:
python scripts/make_report.py > run_logs/report_generation_v2_console.log 2>&1Artifacts:
- Final report:
reports/qwen35_4b_sketch_coverage_shift_probe_report.md. - Full result JSON:
reports/coverage_probe.json. CSVs:
reports/coverage_by_shift.csvreports/coverage_by_family.csvreports/active_by_shift.csv
Figures:
2026-06-24 09:14 UTC
Final packaging and audit completed.
Checks:
python -m py_compile scripts/*.py src/*.pypassed before cache cleanup.- Removed generated
__pycache__directories. - Verified no stale package-name references in the standalone experiment tree.
- Verified no file larger than
50Munder/workspace/experiments/qwen35_4b_sketch_coverage_shift_probe. - Verified experiment package size:
4.1M. - Verified large artifact directory size:
0. - Verified all 6 generated PNG figures are readable and non-empty.
Final locations:
- Downloadable experiment package:
/workspace/experiments/qwen35_4b_sketch_coverage_shift_probe. - Large artifact root:
/workspace/large_artifacts/qwen35_4b_sketch_coverage_shift_probe. - Final report:
reports/qwen35_4b_sketch_coverage_shift_probe_report.md.
Figures 6
Reproduce
Run steps are documented inside the experiment folder (README and scripts).