Skip to content

Commit 2067d9e

Browse files
authored
Merge pull request #23 from anombyte93/reconcile/atlas-catchup
Atlas /atlas full catch-up — gates + settled tournament + first-run UX (868 tests green)
2 parents dc66a44 + 96f45cb commit 2067d9e

142 files changed

Lines changed: 31197 additions & 1902 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.atlas-dogfood/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# transient worker/gate logs from bench runs
2+
*.log
3+
worker_*.log
4+
gate_*.log

.atlas-dogfood/RESULTS.md

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,202 @@
1+
# Dogfood: goose-gemini vs codex on hardening /atlas
2+
3+
**Goal:** loop until a cheap goose+Gemini-2.5-Flash worker reaches results
4+
comparable to codex on real /atlas hardening tasks — decomposing into smaller
5+
subtasks as needed to compensate for the cheaper model.
6+
7+
**Method (A/B, unfakable):** for each real task I (the orchestrator) write a
8+
pytest acceptance gate the worker may NOT edit. `.atlas-dogfood/bench/run_trial.sh`
9+
runs a worker (codex | gemini) autonomously, runs the external gate (pytest +
10+
ruff), records verdict/wall/diff, then resets the source file to baseline so the
11+
next worker gets a clean tree. Worker self-report is never trusted — the gate is
12+
truth. Codex (`codex exec`, gpt via OPENAI_API_KEY) is the bar; gemini is goose
13+
(`GOOSE_PROVIDER=google GOOSE_MODEL=gemini-2.5-flash`).
14+
15+
## Results
16+
17+
| Iter | Task | Granularity | codex | gemini | Note |
18+
|------|------|-------------|-------|--------|------|
19+
| 1 | T2 `_parse_version` fixed 3-tuple (real cmp bug) | coarse (1 instr) | PASS 358s | PASS 38s | gemini matches codex; ~9x faster, far cheaper. Small task → no discrimination. |
20+
| 2 | T3 google/gemini credential-gating in `_provider_usable` + `validate_setup` wiring | coarse, **cross-file (2 files)** | PASS 362s | PASS 41s | gemini matches codex on a cross-file task with **no decomposition**; tighter diff (4 vs 6 ins). ~9x faster, far cheaper. |
21+
22+
## Emerging insight (after 2 iterations)
23+
The discriminator is NOT task size or cross-file-ness — goose-gemini-2.5-flash matches
24+
codex on both, at ~1/9th the wall time and far lower cost, when the task is
25+
**precisely specified** (exact contract in the instruction). The decomposition
26+
hypothesis most likely bites on **under-specified / autonomous** tasks (e.g. "these
27+
5 tests fail, find and fix the root cause") where the model must infer the spec
28+
itself. Reframe for the orchestrator: the lever for cheap models is **specification
29+
precision** — atomizing a task into small, precisely-specified subtasks IS the
30+
decomposition that lets a cheap model match a strong one. Iter 3 will test an
31+
UNDER-specified task to find gemini's failure point, then show decomposition
32+
(adding spec/structure) closing the gap.
33+
34+
## Iteration 3 — the decomposition test (under-specified vs precise) ★
35+
Real task: a chunk of the suite was **non-hermetic**`resolve_provider` reads real
36+
API keys (os.environ + bound `discover_key`), so results flipped on the shell:
37+
native_backend needed a key present (5 fail without); test_cli/test_engine_preflight
38+
"no-key" tests needed keys absent (fail with one). NO env was fully green.
39+
40+
Two-phase experiment (operator planned the fix in a SEALED file first):
41+
- **Under-specified** ("5 tests fail, find root cause & fix"): goose-gemini ran with
42+
ambient keys → failures were masked → it made **ZERO changes**, got confused, and
43+
asked for clarification. It did NOT find the root cause autonomously. **gemini < codex/operator.**
44+
- **Decomposed/precise** (operator handed gemini the exact recipe: patch
45+
`backend.resolve_provider` in native tests; clear key env in no-key tests): gemini
46+
produced a diff **matching the operator's sealed plan exactly** — test-side only, no
47+
production change, no weakened assertions. Verified 36/36 green **with AND without**
48+
ambient keys. Committed (fbac5f1). **gemini == operator/codex.**
49+
50+
## VERDICT
51+
goose-gemini-2.5-flash is **comparable to codex** on /atlas hardening — and ~9x
52+
faster / far cheaper — **whenever the task is precisely specified**, including
53+
cross-file changes. It falls short only on **autonomous diagnosis of under-specified**
54+
problems. The user's hypothesis is confirmed and operationalized: **decomposition =
55+
specification precision is the lever** that lets the cheap model match the strong one.
56+
Orchestrator implication: spend the strong/expensive model on *decomposition &
57+
diagnosis*; fan the *precisely-specified subtasks* out to cheap goose-gemini workers.
58+
59+
Real hardening landed this run: google provider (f994018) + hermetic test suite (fbac5f1).
60+
61+
## Iteration 4 — full model spectrum: DECOMPOSITION vs EXECUTION ★★
62+
Question: how far are cheap/local models from codex at BOTH (a) decomposing a PRD into
63+
tasks and (b) actually completing the generated tasks? Harnesses:
64+
`.atlas-dogfood/bench/decomp_bench.py` (decomposition, scored by the engine's own
65+
`run_validate_tasks`) and goose+ollama on the T2 coding gate (execution).
66+
67+
### (a) Decomposition — PRD → tasks (one-shot JSON, gate = run_validate_tasks)
68+
| Model | Gate | Note |
69+
|---|---|---|
70+
| openai gpt-4.1-mini (strong API) | PASS | clean 5 tasks |
71+
| **gemini-2.5-flash** | **PASS** | **matches the strong API** |
72+
| qwen3 ~8B (local) | FAIL | no JSON extracted — reasoning-model `<think>` wrapper defeats _extract_json |
73+
| llama3.2:3B (local) | FAIL | 14 problems: status "in progress" (not "in-progress"), missing fields |
74+
| qwen2.5:1.5B (local) | FAIL | only 3 problems — produced 6 tasks, 3 lacked a 2nd subtask |
75+
Local failures are FIXABLE format/discipline issues, not reasoning failures. The gap
76+
to codex on decomposition is SHORT.
77+
78+
### (b) Execution — complete the T2 coding task (agentic, gate = pytest+ruff)
79+
| Worker | Gate | Note |
80+
|---|---|---|
81+
| codex | PASS | (iter 1) |
82+
| gemini-2.5-flash via goose | PASS | (iter 1) == codex, ~9x faster |
83+
| llama3.2:3B via goose | FAIL | 4s, emitted a malformed tool call (`edit` missing `path`), then rambled; ZERO edits |
84+
| qwen3 ~8B via goose | FAIL | 219s wandering files, confused, ZERO edits |
85+
Local ≤8B models CANNOT drive an agentic tool-using harness. The gap to codex on
86+
execution is LONG — a model-capability wall (tool-calling), not a prompt issue.
87+
88+
## What prd-taskmaster should ADJUST (to bring goose + any/local model in line)
89+
DECOMPOSITION (cheap wins, likely gets local models passing the gate):
90+
1. Validation-aware REPAIR loop: when run_validate_tasks fails, feed the specific
91+
`problems` back for ONE repair pass. Today generate_json only retries on JSON-parse
92+
failure, not on validation problems — so weak models never get to self-correct
93+
"missing 2nd subtask" / "invalid status".
94+
2. Reasoning-model JSON extraction: strip `<think>...</think>` (and similar) before
95+
_extract_json. qwen3/deepseek-r1 failed ONLY on this.
96+
3. Status/field normalization: map "in progress"->"in-progress", coerce obvious
97+
variants before validating (kills avoidable llama failures).
98+
4. Few-shot: embed one COMPLETE valid example task in the prompt for weak models.
99+
100+
EXECUTION (the hard wall — needs an architectural path, not prompt tweaks):
101+
5. A constrained STRUCTURED-EDIT execution path for models that can't drive freeform
102+
tool-calling: the model returns a structured patch/full-file JSON; the HARNESS
103+
applies it + runs the gate. This is the original "raw API + harness applies"
104+
design — it lets cheap/local models contribute to execution without agentic tool-use.
105+
6. Capability-tiered routing: goose agentic path only for models proven to drive tools
106+
(gemini+); structured-edit path for weak/local; codex/claude for the hardest tasks.
107+
The orchestrator decomposes with a strong model, then routes each subtask to the
108+
cheapest worker whose capability clears the bar.
109+
110+
### Bottom line for the user's question
111+
- Decomposition: gemini is ALREADY at codex level; local models are CLOSE and reachable
112+
with adjustments #1-#4.
113+
- Execution: gemini is at codex level; local models are FAR — only adjustments #5-#6
114+
(a non-agentic structured-edit path) can bring them in, and even then only for simple
115+
tasks. The strong model stays essential for decomposition/diagnosis and hard execution.
116+
117+
## Engine debt found (not yet fixed)
118+
5 tests in `tests/core/test_native_backend.py` (parse_prd / expand / rate) fail on
119+
`main`: they mock the OLD seam `llm_client.discover_key`, but backend.py now routes
120+
via `resolve_provider("main")` (backend.py:344) which returns `kind="plan"` in a
121+
keyless env → handoff path → `ok:False`. Stale tests from the resolver refactor.
122+
Fix = update those tests to mock `resolve_provider` (or add a discover_key API
123+
fallback in backend). Deferred: fixing requires editing tests, which conflicts with
124+
the worker-gate methodology; will handle as a direct maintenance task.
125+
126+
### Iteration 1 detail (T2)
127+
Real bug: variable-length version tuples mis-compare ((1,2) < (1,2,0) is True →
128+
"1.2" wrongly older than "1.2.0"). Gate: `tests/core/test_parse_version_tuple.py`
129+
(11 cases incl. the equality regression). Both workers normalized to a 3-tuple
130+
and passed the external gate; both diffs clean; source reset verified; gate test
131+
untampered. **Verdict: comparable on small, well-specified tasks — gemini wins on
132+
cost/latency.**
133+
134+
## Next
135+
T2 did not discriminate (too small). Escalate to a harder, multi-branch real task
136+
— hero candidate: **credential-aware `validate_setup`** (audit P0-2, the v5.2.0
137+
relaunch blocker: the readiness gate green-lights a keyless paid config). Expect
138+
codex to one-shot it and gemini-coarse to struggle → then demonstrate the
139+
decomposition hypothesis (split into smaller subtasks until gemini matches codex).
140+
141+
## Iteration 5 — quantifying the decomposition gap-closing ★★★
142+
Enhanced decomp_bench.py to measure raw → +normalize → +repair (max_tokens 8192).
143+
- **Variance is the headline for raw local runs:** qwen2.5:1.5b went 3-problems → 0-tasks
144+
across runs; qwen3 went clean-JSON → no-json. Small local models are UNRELIABLE
145+
run-to-run, and a validation-aware repair pass did NOT rescue them (llama3.2:3b could
146+
not self-correct even when handed the exact problems). Normalization/repair help only
147+
capable models that slip; they do not lift sub-floor (<=3B) models.
148+
- **DECISIVE FIX for local reasoning models — disable thinking:** qwen3:8b with `/no_think`
149+
passed the gate **3/3, clean (5 tasks, 2 subtasks each)**. Thinking-mode was the entire
150+
source of its strict-JSON instability. With it off, a LOCAL 8B model == codex/gemini on
151+
decomposition.
152+
153+
### QUANTIFIED answer — "how far to bring local in line with codex"
154+
DECOMPOSITION: hosted-cheap gemini-flash already == codex (distance 0); local 8B reasoning
155+
(qwen3) + thinking-disabled == codex, 3/3 (distance ≈ ONE config flag); local <=3B not
156+
reliable (distance = a bigger model). EXECUTION: unchanged — local can't drive the agentic
157+
harness; needs the structured-edit path (distance = an architectural change, not a model swap).
158+
159+
### Refined prd-taskmaster adjustments (priority order)
160+
1. ★ Reasoning-model handling: detect reasoning models and DISABLE thinking for
161+
structured-gen (ollama think:false / `/no_think`; strip `<think>` before JSON extract).
162+
Decisive: qwen3 0%→100% reliable on decomposition.
163+
2. Raise structured-gen max_tokens (4096→8192+) to avoid truncating multi-task JSON.
164+
3. Validation-aware repair loop (feed run_validate_tasks problems back, 1 pass) — helps
165+
capable models on hard PRDs; will NOT rescue sub-floor models.
166+
4. Status/priority normalization before validation — kills avoidable format fails.
167+
EXECUTION: structured-edit path + capability-tiered routing (from iter4) remain the levers.
168+
169+
## Iteration 6 — structured-edit EXECUTION POC (does adjustment #5 work?) ★★★
170+
POC: model never touches the FS; it returns JSON {find, replace}; a deterministic
171+
harness applies it (str.replace) + runs gate_t2.sh. (.atlas-dogfood/bench/structured_edit_poc.py)
172+
| Model | Result | Meaning |
173+
|---|---|---|
174+
| gemini-2.5-flash (control) | edit applied, near-pass | viable; failed only an over-specified edge ("1.two.3"→(0,0,0) vs its (1,0,3) per-part leniency) |
175+
| qwen3:8b (/no_think) | applicable edit, wrong fix | **path lowers the bar: 0 edits in agentic mode → an APPLICABLE edit here** |
176+
| llama3.2:3b | NO-EDIT | below protocol floor — can't emit valid {find,replace} JSON |
177+
| qwen2.5:1.5b | NO-EDIT | below protocol floor |
178+
179+
CONCLUSION: the structured-edit path REMOVES the tool-calling wall (an 8B local model
180+
that made zero edits via agentic goose can now produce an applicable edit), but it does
181+
NOT remove the CAPABILITY requirement — the edit must still be correct, and that still
182+
tracks model strength. Tiny (<=3B) models can't even follow the JSON edit protocol.
183+
184+
## ===== FINAL SYNTHESIS: how far to bring goose+local in line with codex =====
185+
DECOMPOSITION (PRD→tasks):
186+
- gemini-flash (hosted cheap): == codex. distance 0.
187+
- local 8B reasoning + thinking-disabled: == codex (3/3). distance ≈ one config flag.
188+
- local <=3B: unreliable; below floor. distance = a bigger model.
189+
EXECUTION (complete tasks):
190+
- gemini via goose: == codex (~9x cheaper/faster).
191+
- local via AGENTIC goose: fails entirely (tool-calling wall).
192+
- local via STRUCTURED-EDIT: 8B can participate (applicable edits) but not yet reliably
193+
correct; <=3B can't follow the protocol. distance = architectural path (built here) +
194+
a stronger local model for correctness.
195+
NET: a cheap HOSTED model (gemini-flash) already matches codex for BOTH decomposition and
196+
execution at a fraction of the cost — that is the immediate win. LOCAL models reach codex
197+
on decomposition (8B + no-think) but remain short on execution correctness; the
198+
structured-edit path is the right architecture to let them contribute as they improve.
199+
Highest-value prd-taskmaster changes: (1) reasoning-model thinking-disable for structured
200+
gen, (2) max_tokens bump, (3) validation-aware repair loop, (4) a structured-edit execution
201+
backend + capability-tiered routing (strong model decomposes/diagnoses; cheapest capable
202+
worker executes each precisely-specified subtask, gated externally).

0 commit comments

Comments
 (0)