Snapshot of the programme as of 8 September 2026, 18:25 AEST, reconciled against the programme record on 9 September. The live record lives in the model-ops repo (mrichardsJBOIT/model-ops, private).

Update — 9 September. The open question this page ended on (“why the survey doesn't finish”) was answered that evening and confirmed overnight:
  • The blank plans were never blank. Every killed survey already held the full, correct plan in its transcript — phase A doesn't fail to converge, it fails to stop. A 40-call cap plus forced emission turned 6-of-8 blanks into 3 of 4 graded passes (the fe queue, including the cutover run FE1).
  • The sheet mechanism is confirmed, not just observed. Placebo control (same-size sheet, decisive facts removed): 0 of 2. Generality: sup-log-to-terminal — 0 of 4 locally, 0 of 3 for cloud frontier upstream — passed 2 of 2 with one verified paragraph on the broadcast logger.
  • Overnight step 4 — ten tasks upstream ≥ 88%: 2 of 10 passed (ac-throttle-search, sup-legacy-conversions again with the oracle diff), zero blank plans in ten, and six of the eight misses were each one verified fact away.
  • Now running: knowledge keyed by Rails topic, not task — a blind topic-indexed sheet (knowledge/rails8_topics.md, 8 sections, every entry verified with bin/rails runner), the survey names the topics, the harness injects those sections. Eight held-out tasks run overnight 9–10 Sep, with a cloud calibration lane (deepseek-v4-flash, capped at US$10) in parallel.
Details: docs/SCOREBOARD.md §2i, §2j, §2k.

Apple Silicon · 25 August – 8 September 2026

A 4-bit model on a laptop passed a real Rails task three times. Four lines of prompt did it. The next task showed exactly where it stops.

Fifteen days of measuring local coding agents against the 21-task rails/ai-evals corpus. The retrieval layer the programme was built to test turned out not to be the constraint. A stopping rule was. Then a boundary. Then a 1.6 KB sheet of verified upgrade notes.

What the programme was

One person, two MacBook Pros, a fixed corpus, and an agent that ran the experiments overnight.

The Model-Ops Evaluation Programme set out to test one thesis: local models can do accurate, timely Rails work if a RAG layer injects the right docs at dispatch. It measured that against the 21-task rails/ai-evals corpus (Writebook on Rails 8.2.0.alpha), first through the upstream lemans/miniswen harness, then through pi with a hand-built grader. The host was a 14-inch MacBook Pro M1 Max with 64 GB, serving Qwen3.8-27B-4bit via oMLX; a second M1 Max was commissioned mid-programme.

The thesis did not survive contact. Real retrieval reached ~56% recall against the oracle's 100%, and a matched pair on Opus showed RAG making no difference at all. What produced the first local pass was a four-line stopping rule; what produced the second was a two-phase survey-then-execute pipeline handed a 1.6 KB sheet of empirically verified Rails upgrade notes.

What did not move: multi-locus tasks without that sheet. And the survey phase's 8-blank-plans-in-10 stretch turned out to be a missing stopping rule, not a missing plan — capped and asked to emit, the same surveys produced first-attempt passes that evening.

Prompt structure beat model choice. Harness beat retrieval. A small verified sheet beat general RAG. And the survey phase was never failing to think — it was failing to stop. Forced emission fixed it in an afternoon.

21tasks in rails/ai-evals, against 1,170 published upstream trials
22.0 sper step, local 4-bit via openai/ adapter, vs 37.7 s cloud
3 / 3ac-throttle-search passes with the stopping rule, a different implementation each time
0 / 6multi-locus passes with the stopping rule alone, across two tasks
1.6 KBverified upgrade notes into Phase A: first sup-legacy-conversions pass, diff byte-identical to the oracle
8 / 10Phase A attempts on Sep 8 that produced no work order — fixed that evening by a call cap + forced emission (3 of 4 graded passes)

Read the denominator carefully. Per graded run, the pipeline looks good — when Phase A produces a work order, the rest works and the answer is exactly right. Per attempt, Phase A fails to produce a work order more often than it succeeds: KBrep1 needed 3 attempts for its 1 pass; two produced no plan and cost ~45 minutes each. Until 2026-09-08 the retry logic recorded only the successful attempt, so the flattering rate was the only one visible. Every attempt is now written to the results table. For comparison against the published leaderboard, per-attempt is the honest figure — upstream runs do not get retries.

Architecture and design

A senior→junior split with the same local model in both seats, a harness-level loop guard, and a retrieval layer that ended up replaced by a curated sheet. Source: docs/PHASED_RUN_DESIGN.md, docs/AGENT_EXECUTOR_PAIR_PROMPT_MODEL.md.

Phased run pipeline Task body plus knowledge sheet feed Phase A survey, which is read-only and emits a work order. Phase B execute receives the work order verbatim and applies it with full tools. Phase C verify runs the suite. A harness-level loop guard and stall detector watch phases A and B. Every attempt is recorded, including blank plans. Input Task body + 1.6 KB knowledge sheet Phase A · senior Survey (read-only) read, grep, find, ls · emits work order Phase B · junior Execute full tools · "the search is finished" Phase C · verify bin/rails test → grade C1 has run for real exactly once loop guard: duplicate tool call in last N → interrupt · stall detector: 480 s silence → terminate Per-attempt record: calls, uniq, dup %, edits, SURVEY_EXIT, bytes, grade
The design is A + B + C + guard. What actually produced the passes is narrower: task → knowledge sheet → A → B → grading. Phase C1 has been exercised once and wrote no script; the loop guard has fired in real runs (KBrep2__a2 at 20.0%, FE2's diffuse trip, FE4's tight trip) — and since 8 Sep evening a trip ends in a forced plan rather than a blank. C1 remains the one designed component still unproven.

The work order Phase A is asked to write

You are in phase 1 of 2: SURVEY. You have read-only tools.
You cannot edit anything, and you will not be asked to.

Your only job is to produce the plan the next phase will execute.

1. Find every site that must change. Do not stop at the one
   described above — the same defect may appear in several
   places, and may appear in more than one form.
2. If a search returns nothing, accept that and move on.
   Do not repeat a search you have already run.
3. Write the plan incrementally. Emit each site as you
   confirm it. A partial plan is useful; a plan you never
   finish is not.

Then output ONLY this, and nothing else:

SITES: <n>
- <path>:<line> — <exact current code> → <exact replacement>
- ...
RISKS: <anything that looks similar but must NOT be changed,
        or "none">
Point 1 is the definition of done. Point 2 is the dead-end rule. Point 3 was added on Sep 8 after two surveys timed out with zero bytes. RISKS exists because the task contains a trap: a ternary where only one branch may change.

The one that passed — Bprobe, 28 calls, 0% duplication

All six sites confirmed across the whole tree.

Findings:
- 5 sites use `to_s(:format)` — renamed, now `to_fs`.
- 1 site uses the removed `to_default_s` in the nightly
  archive job — that's last night's crash.
- One near-miss: `report_card.rb:28` has a bare `value.to_s`
  in the else branch — must stay.

SITES: 6
- app/controllers/books/reports_controller.rb:16 —
  `updated_at.to_s(:number)` → `updated_at.to_fs(:number)`
- app/helpers/books/reports_helper.rb:3 —
  `time.to_date.to_s(:long)` → `time.to_date.to_fs(:long)`
- app/views/report_digest_mailer/weekly.text.erb:6 —
  `to_date.to_s(:short)` → `to_date.to_fs(:short)`
- app/models/book/reportable.rb:5 —
  `length.to_s(:delimited)` → `length.to_fs(:delimited)`
- lib/publishing/report_card.rb:24 —
  `to_a.to_s(:db)` → `to_a.to_fs(:db)`
- app/jobs/report_archive_job.rb:12 —
  `last_edited_at&.to_default_s` → `last_edited_at&.to_s`
RISKS: report_card.rb:28 `format ? value.to_s(format) :
  value.to_s` — else-branch no-arg `to_s` must NOT change.
Scope slightly wrong, remedy right. It listed 6 of 7 sites and misfiled the ternary as do-not-touch; Phase B changed it correctly anyway. The same task without the sheet (Bphase3) got all 7 sites and prescribed strftime hand-rolls with 5 of 7 formats wrong. Scope right, remedy wrong. That diff is the whole story of Sep 8.

The loop guard, and what it can't see

Prompts failed four times to stop a local model repeating itself — 38× bin/rails runner 'puts Book.count' in one run, one grep 47 times in another. So the guard is harness-level: it watches the session JSONL and interrupts on a duplicate tool call in the last N. Removing tools moved the metric where prompts hadn't: the read-only survey ran at 5% duplication where the bash-equipped arm ran at 42%.

Then the Sep 8 queue showed the guard's blind spot. Of eight blank plans, only one was a loop. Four had duplication at or below 3.1%, three at exactly 0.0%. Phase A doesn't loop; it reads honestly and never converges on a plan. A duplication guard cannot see that, which is why a 480-second stall detector was added the same afternoon, threshold set above the longest legitimate gap observed (349 s).

The retrieval layer, and what replaced it

Hybrid dense + lexical retrieval with RRF fusion and LLM query expansion over Rails 8.2.0.alpha at the pinned SHA, turbo-rails, and the app's own source. It reached ~56% recall at five, and on the one task where it changed an outcome it cost 52% more steps on a task the model already passed. What actually closed the last gap was a hand-curated sheet of Rails upgrade notes, every entry verified with bin/rails runner, handed to Phase A. Knowledge was the constraint; untargeted retrieval was the wrong delivery mechanism.

Hardware and harness stack

  • Eval hostMBP-14, M1 Max, 64 GB. oMLX 0.6.4, ceiling 64.4 GB
  • Second hostMBP-16, M1 Max, 64 GB. oMLX 0.6.3rc1, ceiling 55.7 GB — not interchangeable for controlled comparisons
  • Modelmlx-community/Qwen3.8-27B-4bit, ~15 GB resident, v22.4 chat template. Also run: Gemma 12B (agentic fine-tune, MLX 8-bit), IQuest 40B
  • Local harnesspi v0.84.4 in lemans-writebook-pi:v1, graded by factory_harness.sh
  • Upstream harnesslemans / miniswen (bash-only), used for cloud controls via OpenRouter
  • Frontier controlClaude Opus 5 via Claude Code harness
  • Corpusrails/ai-evals, 21 api-knowledge tasks, Writebook on Rails 8.2.0.alpha at 3a4961048ad2
  • Prehistoryexo cluster over the same Macs, pre-oMLX; August OpenRouter spend $101.48 USD; see docs/exo/

Two M1 Max machines at $2,400 each sitting idle was the prehistory's stated concern. The programme is the answer to "can they do anything useful once running."

Key findings

Six results, each with the number that supports it. Sources: docs/SCOREBOARD.md, docs/RAG_EFFICACY_EXPERIMENT.md, docs/LOCAL_MODEL_BENCHMARK_RECONCILIATION.md, RESULTS_TABLE.md.

1

Prompt beat model beat retrieval

Experiment 1 gave the local model a full editing harness — pi with read/edit/write — and it never called an edit tool in an hour. 84 of 87 calls were bash; one grep ran 47 times. Experiment 1b changed nothing but the prompt: four lines telling it when to stop investigating. It passed in 21 minutes and stopped voluntarily — the first local run ever to judge itself finished. The "10 tool calls" in the rule never bound anything; both passes first edited at call 25. The working ingredient is the transition imperative.

Exp 1, no rule
87 calls, 0 edits, FAIL, killed at 60 m
Exp 1b, + rule
28 calls, 3 edits, PASS, 21.3 m, PI_EXIT=0
Replication
3/3, three different implementations
2

Static scores did not predict agentic completion

On Aug 25's single-turn rubric, IQuest 40B 8-bit scored 95/100 and local Qwen 88/100. In the agentic harness, Qwen became the primary executor for tool-schema adherence and IQuest hallucinated another vendor's tool names. Then the sharper version: the same Qwen family passes 76.2% of upstream trials from the cloud and passed 0 of 7 locally in miniswen. 100% of our failures never reached the verifier; only 12.5% of upstream failures fail that way. We were not failing at Rails. We were failing before Rails became relevant.

Static winner
IQuest 40B, 95/100
Agentic executor
Qwen 3.8 27B 4-bit
Cloud vs local, same family
76.2% vs 0/7 (miniswen era)
Never submitted
100% ours vs 12.5% upstream
3

Local inference is not slow. The adapter was.

Same weights, same server, same task: 41–48 s/step via the ollama/ provider path, 22.0 s/step via openai/. That is faster than the cloud model that passed (37.7 s via OpenRouter). It also exposed a fairness bug: the bench sets 100 steps and 60 minutes, cloud runs exhaust steps, and the slow local runs exhausted the clock at 70–88 steps. The 0-for-7 versus 76.2% comparison was never made under the same budget.

Local, ollama/
41–48 s/step
Local, openai/
22.0 s/step (104 requests, 2292 s)
Cloud, OpenRouter
37.7 s/step (40 steps, 1507 s)
Token shape
~1.70 M prompt : 14.4 K completion
4

RAG efficacy is narrow, and general RAG was the wrong delivery

Real retrieval reached ~56% R@5. On cloud Qwen it converted sup-legacy-conversions from 0/3 upstream to 1/3 — and on the guardrail task it already passed, injection cost 52% more steps for the same outcome. The properly controlled pair on Opus was a clean null: plain and RAG arms produced byte-identical diffs and failed the same hidden test. Both saw the second bug and reasoned themselves out of fixing it — a judgement failure, not a knowledge gap. What worked was the opposite of general retrieval: 1.6 KB of curated, empirically verified notes into Phase A.

Retrieval recall
~56% R@5 vs oracle 100%
sup-legacy, cloud Qwen
0/3 → 1/3 with RAG (61 steps, 44 m)
Guardrail cost
40 → 61 steps (+52%), same pass
Opus matched pair
both FAIL, identical diff
Knowledge sheet, local
PASS, diff = solution.patch
5

The multi-locus boundary

The stopping rule is 3-for-3 on ac-throttle-search (rated easy, one locus of change) and 0-for-6 on two tasks that need edits in several places. Opus passed the harder task with no docs in 27 calls. The local model, once phasing gave it correct scope, still failed on remedy: it never found to_fs, declared the removed API had no replacement, and hand-rolled formats that missed 5 of 7. Whether thin Rails 8 knowledge is fatal depends on the verifier: behavioural assertions forgive a hand-rolled fix, exact-output assertions do not.

Single-locus
3/3 local
Multi-locus, rule only
0/6 local
Opus, no docs
PASS, 27 calls, 6.6 m
Local remedy errors
5 of 7 formats wrong
6

Duplication as the discriminator — and its limit

In the single-phase arms, every failure ran 20–82% duplicate tool calls and the pass ran 0%. It is cheap to compute, and it became the loop guard's trigger. But the Sep 8 queue qualified it: of eight blank Phase A plans, only one looped. The survey mostly fails by reading exhaustively and never emitting — 104 calls, 72 reads, 30 ls, 0% duplication. Timing separates outcomes better than duplication does: every plan ever produced arrived by 19.7 minutes; every blank ran past 24.

Single-phase fails
20–82% dup
Single-phase pass
0% dup
Phase A blanks that looped
1 of 8
Plans arrived by
10.8, 12.9, 19.7 min
Blanks ran to
24.1, 37.9, 42.5, 44.9 min
After forced emission
3 of 4 graded passes (fe); 0 blanks in 10 (step 4)

Before and after

Where the three repos meet: a task from rails/ai-evals, seeded into basecamp/writebook, graded by the rails/lemans verifier. Three worked examples from the evidence directory. Sources: docs/PROGRAMME_MAP.html §3, docs/SCOREBOARD.md §2b/§2e/§2g, benchmarks/…/<run>.diff.

Suite22 ai-evals tasks against Writebook. 21 are api-knowledge; hello-world proves the pipeline. 4 touched, 18 untouched.
TaskFour files: instruction.md (frontmatter carries rails_anchor, stripped), environment.patch (seeded defect), solution.patch (oracle), verification_test.rb (hidden).
ArmOne run = task × one intervention. The only variable. Named Bphase4, Bprobe, KBrep1__a3
PipelineA ▸ B ▸ C, guard watching. The thing being built. Everything above and below this row is upstream's.
Gradinglemans' verifier, mirrored by factory_harness.sh: preverify app suite ▸ restore test/ bin/ config/environments/test.rb ▸ run hidden test. Exit status is the reward.

sup-legacy-conversions — same seven lines, three outcomes

7 sites · 6 files · 1 trap · local Qwen 27B 4-bit both columns

The seeded defect is a Rails 7.0 rename left unapplied: to_s(:format) became to_fs(:format) and to_default_s was removed. The task describes it the way a bug report would — the nightly archive job crashed — and never names the API. Both runs below had a correct work order and made their edits in 13 calls at 0% duplication. One had been handed 1.6 KB of verified upgrade notes in Phase A. The other had not.

Writebook fileSeeded (before)Bphase4, no sheetBprobe, with sheet = oracle
books/reports_controller.rb:16updated_at.to_s(:number) strftime("%Y%m%d%H%M%S") updated_at.to_fs(:number)
books/reports_helper.rb:3to_date.to_s(:long) strftime("%B %d, %Y") to_date.to_fs(:long)
report_digest_mailer/weekly.text.erb:6to_date.to_s(:short) %b %d — verifier wants %d %b to_date.to_fs(:short)
book/reportable.rb:5length.to_s(:delimited) number_with_delimiter — a view helper, errors in a model length.to_fs(:delimited)
publishing/report_card.rb:24to_a.to_s(:db) map(&:title).join(", ") — wants ids to_a.to_fs(:db)
publishing/report_card.rb:28format ? value.to_s(format) : value.to_s strftime without the time component value.to_fs(format), else-branch untouched
report_archive_job.rb:12last_edited_at&.to_default_s strftime("… %z") — wants %Z last_edited_at&.to_s
Hidden verifier4 failures + 2 errors · FAIL0 failures, 0 errors · PASS · diff byte-identical to solution.patch

Bprobe diff, app/jobs/report_archive_job.rb

   private
     def header(book)
-      "# archived #{book.last_edited_at&.to_default_s}"
+      "# archived #{book.last_edited_at&.to_s}"
     end
 end

Verified runtime output, probe against real records, rolled back

report_stamp   : September 07, 2026
filename       : shelf-report-20260907072256.txt
report card    : Updated: 07 Sep 07:22
                 Covers: 1,2,3
archive header : # archived 2026-09-07 07:22:56 UTC
digest line    : * Probe Book, last edited 07 Sep

Scope was never the problem in the left column: Bphase4 found all seven sites. It believed to_default_s had no Rails 8.2 replacement and hand-rolled formats; five of seven missed the verifier's exact strings. The right column's survey found only six sites and misfiled the ternary as do-not-touch; Phase B changed it correctly anyway. One fact — renamed, not removed — is the entire difference.

as-purge-embedded-images — one line, and the line it didn't write

Opus via Claude Code · matched pair · plain vs +11,704 chars of RAG · both FAIL

The controlled RAG test. Two fresh Opus runs, identical harness, only the instruction varied: one plain, one with the retriever's top chunks appended, purge_later at rank 0. Both arms produced the same one-line change in app/models/page.rb:

-  dependent: :destroy
+  dependent: :purge_later

Both failed the same hidden test — a page revised after its image went in frees the revision's image too. Both runs saw the second leak. Both wrote it up under uncertainties and declined to fix it:

"I judged this a pre-existing upstream design quirk rather than the injected bug… Flagging it in case the hidden tests exercise the edit-then-destroy path."

The contaminated run — the one that received rails_anchor: purge_later because the frontmatter had not been stripped — found both bugs and passed. Being handed part one appears to have freed it to look further. That is a scoping judgement, not a knowledge gap, and it is why eleven kilobytes of correct documentation changed nothing. The result is the cleanest null in the programme and the reason the RAG line was closed.

ac-throttle-search — pass by hand-rolling

local Qwen 27B 4-bit · 3 of 3 with the stopping rule · Rails API recall: 0 of 3 · the verifier rewards behaviour

The task turns on Rails 8's built-in rate_limit. No local run ever found it — and the run you're about to see didn't either. It passed anyway, which is the point. Run C left this on disk:

  • Mapp/controllers/books/searches_controller.rb
  • ??app/controllers/concerns/rate_limited.rb
  • ??lib/rate_limiter.rb

A concern and a library class where the oracle adds one macro to the controller. The behavioural verifier accepted it, as lemans' methodology says it should: the checks test behaviour, not implementation, and API recall is scored separately from passing. It is the mirror image of example 1 — there, a behavioural verifier would have forgiven the strftime hand-rolls too; an exact-output verifier did not. Whether thin Rails 8 knowledge is fatal depends on what the test asserts.

Timeline of breakthroughs

From static rubrics to a measured boundary. Sources: docs/LOCAL_MODEL_BENCHMARK_RECONCILIATION.md, docs/JOURNEY.md, docs/plans/2026-09-08_PLAN.md.

  1. Static benchmarks

    Single-turn prompts scored 0–100 on Rails 8 omakase, inverted maths, locking. IQuest 40B 8-bit wins at 95/100. Bottleneck named as architectural knowledge.

  2. The paradigm shift

    Evaluation moves to live multi-turn tool execution. Static scores stop predicting anything; Qwen 3.8 27B 4-bit becomes the primary local executor on tool-schema adherence and clean exits. The pi coding agent is adopted as the harness. Bottleneck renamed: tool dialect and loop termination.

  3. The retrieval layer, and the A/B that measured nothing

    Hybrid retriever built and measured at ~56% R@5. Six agentic trials, zero solved, every one killed by the wall clock. One run received the correct answer at step 17 and re-ran the identical probe 61 more times.

  4. The cloud control, and the throughput finding

    Cloud Qwen passes ac-throttle-search in 40 steps through our exact harness: infrastructure sound, fault isolated to the local stack. Local via openai/ measured at 22.0 s/step, faster than the cloud. RAG converts sup-legacy 0/3 → 1/3 on cloud Qwen; the Opus matched pair is a clean null.

  5. First local pass

    Experiment 1b. Same harness as the hour-long failure, plus four lines of stopping rule. 28 calls, three edits, 21 minutes, voluntary stop. It never found Rails 8's rate_limit and hand-rolled a rate limiter instead; the verifier checks behaviour, so it passed.

  6. The boundary

    Seven runs while Mark slept. ac-throttle-search passes a third time with a different implementation. Everything multi-locus fails: 0-for-6. A definition of done makes it worse. The two-phase arm times out at 25 minutes with 0 bytes — recorded INVALID, not FAIL.

  7. Phase A works. Phase B still loops. Then it doesn't.

    Bphase3: give the survey a session directory and ask for incremental emission, and it finishes in the budget that twice produced nothing — all 7 sites, 0% duplication. Execute then loops on a correct plan, hunting a timestamp format that is not in the repo. Bphase4, byte-identical plan, guard on: 13 calls, 6 files edited, guard never fired. Phase B's variance is too large for single-run comparisons.

  8. The knowledge sheet

    Bprobe: one variable against Bphase4, a 1.6 KB sheet of verified upgrade notes into Phase A. First local pass on sup-legacy-conversions, 6 runs, 21 assertions, 0 failures, diff byte-identical to the oracle. 0-for-6 becomes 1-for-7.

  9. Forced emission — the blank plans were never blank

    The replication queue's failures (8 blanks in 10) got the forensic they needed: every killed survey, resumed with no tools and asked for its plan, produced it in minutes — the three sup-legacy ones with the oracle's exact remedy. Phase A wasn't failing to converge; it was failing to stop. The harness gained a 40-call cap and a forced plan; the fe queue passed 3 of 4 graded runs the same night, including the cutover run FE1 from the new repo.

  10. Boundary confirmed from the other side

    Replication queue: 10 attempts, 2 graded, 1 pass, 8 blank plans. Only one blank was a loop. The revised diagnosis — phase A fails to stop, not to think — was written down that evening and confirmed by experiment hours later. The programme's next question was answered before it was asked.

  11. The sheet holds — placebo, generality, and a 10-task sweep

    Placebo control: same-size sheet without the decisive facts, 0 of 2 — the mechanism is the specific facts. Generality: sup-log-to-terminal, 0 of 4 locally and 0 of 3 for cloud models, passes 2 of 2 with one verified paragraph. Step 4: ten tasks, 2 of 10 passed, zero blank plans, six of eight misses each one verified fact away.

  12. Topic-keyed knowledge, and the hosts at full capacity

    The sheet is now keyed by Rails topic, not task — eight sections, every entry verified with bin/rails runner, and the survey names the topics it needs. MBP-16's hidden blocker (the ANE prefill setting) was found and disabled, making it the faster host; eight held-out tasks and a cloud calibration lane (deepseek-v4-flash, capped at US$10) run overnight 9–10 Sep.

Roadmap

The goals as written in docs/plans/2026-09-08_PLAN.md, with their status, and the gates that follow from §2h of the scoreboard.

G1 · done 8 Sep

Finish the two-phase run

Phase A produces a complete, correct work order in 25 minutes. Both prerequisites — a transcript and recoverable partial output — turned out to be one change: --session-dir instead of --no-session.

G1b, the diagnosis it revealed: "the junior loops for want of scope" is dead. It had the scope. The constraint moved to Rails 8 API knowledge.

G4 · PASS 8 Sep · G5 · failed

Targeted knowledge, then replication

G4: a small curated verified delta sheet closes the knowledge gap. Cheap, static, derivable from release notes for upgrade-shaped work.

G5's replication queue failed 8-of-10 on blanks — but the blanks turned out to be plans waiting to be asked for. The mechanism itself held up under placebo (0 of 2 without the decisive facts) and generalised (2 of 2 on sup-log-to-terminal, a task five frontier models score 0 on).

Answer — forced emission · the open question is closed

Why the survey doesn't finish: it never knows it's done

  • Forced emission (8 Sep evening). Every killed survey, resumed with no tools and asked for its plan, produced it in minutes — the three sup-legacy ones with the oracle's exact remedy. Phase A was failing to stop, not to converge.
  • Harness fix. Survey capped at 40 calls; any survey that ends without a plan is asked for one with the tools removed. Result: 3 of 4 graded passes on the same arm that was 2-of-8 the day before, and 0 blank plans in ten runs overnight.
  • Sep 9. The sheet is keyed by Rails topic, not task; eight held-out tasks and a cloud calibration lane run overnight 9–10 Sep. Results land in the scoreboard §2k.

Deferred, and still open

  • Generality across the suite — the eight held-out tasks through topic-selected sheet sections ran overnight 9–10 Sep; the result is the next number on the board (scoreboard §2k).
  • Greenfield A/B/C — local Qwen vs cloud Flash vs cloud SOTA with pair prompting, when a real set of customer requirements exists. Kickoff drafted, not run.
  • Quantisation ladder — IQuest 40B 4-bit vs 8-bit, sequentially on one box. Staged, not run.
  • Fine-tuning a Rails-specialist model — only once enough platforms have shipped to make a concrete cost, latency, or privacy case. Two-of-eight is a reason to fix the loop, not to train a model.
  • Phase C1 has run for real once and wrote no script — the one designed component still unproven. The sweet-spot experiment (how much context is enough) is queued behind SPEC-1 Part C.

Trials and tribulations

Five failures, each of which paid for itself in what it revealed. None of them was a model failure.

The bash tool-casing bug

Gemma 12B emitted Bash; the lemans harness expected bash. Six trials failed at the harness before the model's competence was ever tested, and they sat in the scored count until the forensic pass separated harness failures from model results. Fixed since.

What it taught: tool-schema conformance is a harness/format interaction, not a knowledge gap, and no amount of retrieval addresses it. The programme's first lesson in not scoring its own bugs as model results.

The definition-of-done backfire

Bdod added "fix every site this defect can occur at" to the stopping rule. It was the only arm that made the model act — 8 edits where every other sup-legacy arm made 0. It then wrote lib/rails_ext/active_support_formatting.rb, monkey-patching the removed Rails API back into existence globally, and broke the app's own test suite before the hidden tests ran.

What it taught: instructing for completeness without constraining method converts inaction into sweeping wrong action. The remedy went into the work-order format, not the prompt: exact current code → exact replacement, per site.

The wall-clock trap

The bench sets step_limit: 100 and timeout: 60m. Cloud models burn 100 steps in minutes. Local runs via ollama/ at 41–48 s/step hit the clock at 70–88 steps and never received their budget. A three-hour, 231-step run produced exactly what the one-hour runs produced, so more time was not the answer either.

What it taught: set the clock so the step limit binds, or the result measures throughput rather than capability. At 22 s/step that means at least 40 minutes; at 45 s/step, 80. Every earlier upstream-vs-local comparison was retracted as not like-for-like.

The blank plan epidemic

Two surveys timed out with 0 bytes at 25 and 45 minutes because pi -p prints only on completion. Two later blanks were retried silently before the stepper recorded them, so a run reported a clean PASS while concealing a 1-in-3 denominator; one transcript was overwritten and is unrecoverable. Then the replication queue: 8 blanks in 10 attempts, every one with zero assistant text.

What it taught: a blank is a result and must be recorded as one — and the follow-through matters: session directories made timeouts recoverable, a stall detector caught the 33-minute silences, and the forced-emission experiment that evening proved the plans were in the transcripts all along. Phase A was failing to stop, not to think. The survey is no longer the open question.

The host-down silent failure

oMLX on MBP-16 exited cleanly mid-run (Finished server process, empty crash log). The container issued 5 tool calls into a dead endpoint, then sat silent for 14 minutes, and was graded as a blank plan. Three gaps let it run that long: the health gate only runs at launch, the stall detector had not landed in that container, and the KeepAlive LaunchAgent had been removed that morning to make the GUI sole supervisor.

What it taught: excluded from the denominator by Mark's call — counting a dead host as a model failure would overstate the blank-plan rate, exactly the drift per-attempt accounting exists to prevent. The control arm it belonged to therefore answers nothing, and is still owed a run.

Harness, prompt, budget, instrumentation, operations. The leverage is in the loop, and so are the bugs. The scoreboard is harsher than it was a week ago because the accounting got better, not because the model got worse.

The One-Person Software Factory

The blueprint this programme exists to serve — and which, until the Sep 8 migration, no model-ops document cross-referenced. Source: docs/architecture/ONE_PERSON_FACTORY.md, docs/LOCAL_MODEL_BENCHMARK_RECONCILIATION.md §3.

The vision

One person ships and supports multiple platforms without a team. A hub-and-spoke orchestrator holds only routing, the credential vault, and escalation; everything else is delegated to sub-agents for spec, code, infra, marketing and support. Every action report carries exactly three fields — status, data, next — so the orchestrator reads state, not prose. The constraint the blueprint names is curation fatigue, not token cost.

The evaluation programme is the first hard measurement of the implementer seat. Its result is a routing rule with numbers behind it: well-specified single-locus work can go local today (ac-throttle-search, 3/3, plus the overnight wins); multi-locus work goes local only with a curated knowledge sheet and a survey phase that is made to finish by the harness; everything else goes to the frontier.

Why local models matter

Three reasons, in the order the prehistory ranks them. Cost: August's OpenRouter bill was $101.48 USD, and two M1 Max machines bought at $2,400 each were the "idle" concern that started the exo work. A local loop at 22 s/step costs electricity. Privacy: client repositories never leave the machine. Sovereignty: the loop keeps running when an upstream API changes terms or availability.

The standing constraint of the eval sessions followed from this: everything stays local, both phases, no frontier model as architect or fallback. A pipeline that only works with a frontier planner tells the factory nothing new — Opus already passes most of the corpus unaided.

The orchestrator pattern

Ralph Loop: one agent, one goal per loop. The tiering from the reconciliation doc puts cloud models on design and decomposition into bounded "one feature, one verification" slices, and local executors on the slices. The programme's contribution is what a slice has to contain for a local executor to finish it.

  • Tier 1Cloud orchestrator and design strategist. Decomposes features into bounded slices with acceptance criteria.
  • Tier 2Local executors on Apple Silicon via oMLX. Qwen 3.8 27B 4-bit primary: logic, tests, ActiveRecord, bug fixes.
  • Phase AThe same local model as senior: read-only survey, emits the work order.
  • Phase BThe same local model as junior: "the search is finished," apply the work order, leave a change on disk.
  • AgentsDuncan Claw authored the reconciliation and the blueprint; the Sandi agent drove the Sep 6–8 evaluation runs; the programme record now lives in the mrichardsJBOIT/model-ops repo.
intent ──▶ Tier 1: spec, bounded slice, acceptance criteria
                 │
        slice shape?
                 ├─ single-locus ─────────────▶ local, stopping rule       (3/3)
                 ├─ multi-locus + upgrade-shaped ▶ local, A→B + verified sheet (2/8, Phase A gated)
                 └─ multi-locus, no sheet ─────▶ frontier                  (Opus: 27 calls)
                                                       │
                                 per-attempt record ◀──┘  pass, fail, blank, host-down
The routing rule the programme validated. The parenthesised figures are the evidence behind each branch.