Skip to content

release/v0.0.281 — learn skip + flash effort + Pareto product (#688) - #670

Merged
justrach merged 83 commits into
mainfrom
release/v0.0.281
Aug 31, 2026
Merged

release/v0.0.281 — learn skip + flash effort + Pareto product (#688)#670
justrach merged 83 commits into
mainfrom
release/v0.0.281

Conversation

@justrach

@justrach justrach commented Aug 29, 2026

Copy link
Copy Markdown
Owner

Next cut after tagged v0.0.280. One-shots skip the 38s learn pin; flash SWE is now faster than Pi. #664, #665, #687, and #688 (Pareto product) are on this branch too.

Do not tag until asked. Download / notarization ids land after the build. Do not merge to main until asked.

Headline (ADR 0044 / #668)

startBackgroundLearning is a no-op on -p / --json. Interactive REPL/TUI/ACP still auto-init after 5 model calls.

Confirm (run-20260829-031139.jsonl, SuperGrok grok-4.6): 4/6 in 456s → 5/6 in 205s.

Pareto product (#688)

Named-file Responses nudge (input_text + Chat→typed coerce on resend), catalog rebuild after a 4-wide native showcase (tools:, empty-array bug), -p TTFT mark, SSE hold until the data payload, and the chrome / MCP handshake / symlink fixture. Hardlink pin, detached learn init, x_search on, and the oneshot learn skip stay.

In-house (run-20260830-122731): graff-dev 6/6 in 164.7s / 0.7s first / 26 calls vs grok 530.9s and OpenCode 168.4s.
Spine (run-20260830-124315): 3/3 in 19.9s / 0.6s first.

Product commits: e4e2a2a 8b2f401 5124323 e0ea59d 350b03c 0e7480c f72ca6d bed8e4f.

Also on this branch

#666#669 / #671 / #664 / #665 / #687 / #688 are folded here. 280 leftover duplicates (#655#663) stay off this cut.

Test floor 1804 (slack 25). Suite 1804. No tag. No merge to main until asked.

Tip: e1acd389e0bfac40744aabd16c81aa835d18d54f

cursoragent and others added 30 commits August 26, 2026 05:13
Add apps/native: copy-paste Beautiful UI primitives and tokens, drop
posthog/cuelume/dialkit/paid Central icons, and wire the harness chrome
to graff serve NDJSON (thinking, stream, tools, ask_user, todos).

The merjs contribution is the WKWebView window pattern (macOS); Linux
opens the Next.js app in a browser. The existing Tauri gui/ is unchanged.
Smolify is no longer a reserved core server. Startup does not inject
schemas, GRAFF_SMOLIFY is ignored, and a workspace or plugin entry
named smolify connects like any other remote MCP.

CI no longer runs the boundary E2E (it asserted default tools while
GRAFF_NO_SMOLIFY=1). The local secret-egress gate stays if someone
adds mcp__smolify__*. smolify-tools.json remains a schema-gate fixture.

Ratchet floor 1683: the offline connectSmolify registration test left
with the server.
The evaluators wait up to 120s for all four primary-start markers
(#467). invoke() killed graff at 60s, so a loaded PR runner reported
TimeoutExpired while the same commit's push job finished in 3s.
graff acp now translates --json events into ACP session/update
notifications (thought, text, tool_call / tool_call_update) while a
prompt is live, so a client can render tools from the first call.
The native Beautiful UI harness speaks ACP via /api/acp instead of
graff serve (ADR 0032).
Node's test runner needs the .ts specifier, and a tool_call_update
without a kind was dropping the edit chip before a diff could land.
After the plugins receipt, interactive --yolo still handshook
codedb-pro on the main thread (registry empty under defer_join)
and probed with timeout 0. Print mcp/companion receipts, queue
the companion like deferred MCP, cap the probe, and skip inline
io.async when concurrent fails.
The previous check rejected any '256, 256, 0' substring, including
the comment that explained the old unbounded runCapped.
plugins:/mcp:/companion: are the same dim session_notice as the
existing plugins line. connectCompanion with a PATH stub emits
the companion receipt and does not addServer. TUI first paint
stays the welcome composer — those lines print before alt-screen.
Stalls still reconnect; the ⚠ and "model call N" lines were harness
bus (ADR 0021). A turn that dies still says so. Ending-turn notices stay.
FORCE_STALL_ALWAYS reconnects silently, then ends the turn. The e2e
script now checks the ending-turn notice, not a mid-turn reconnect line.
…notes

A ~40s gateway blip on glm-5.3-flash (2026-08-29, dhi triage session
6deff1df) surfaced as 3 transport timeouts followed by a 4xx "Body must
be valid JSON" on the SAME unchanged request body. The envelope path
hard-failed and killed the turn even though the identical (larger)
payload succeeded two minutes later: body bytes do not change between
attempts, so a parse rejection arriving right after a timeout run
indicts the gateway, not the request.

Classify body-parse rejection phrasings and retry them bounded (2 tries,
1-2s backoff) when THIS request already logged >=2 error.Timeout hits;
without that timeout history the 400 stays fail-fast exactly as before.
Wired into all four envelope-fatal paths (codex .failure, streamed SSE,
plain JSON type=="error", openai-style error envelope).

Also attribute retry trace notes with the agent label: the same session
drew three 5xx retries inside two parallel subagents (each recovered on
the same payload) and none of the anonymous "retry" events said who —
attribution took ms-arithmetic across api spans. REPL output unchanged.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
The Zig boot phases are ~12ms; the delay is staring at the leftover
shell until tui.run writes the alt-screen. Claim that screen at
runSubcommand for `tui`/`repl` so keys/MCP/prompt happen inside the
pager, and restore via atexit if we never reach run.

Live TUI tail and zigzag repl pending used sanitize/strip only, so
- lists and **bold** stayed raw until the turn settled. Render them
the same way a settled assistant row does; keep raw bash plain.
The pager paints through layout_cache, not scrollback.render, so the
live stream was still sanitize-only. Share liveTail. Skip a second
enable_seq after an early claim — kitty keyboard is a stack, and the
extra push failed PTY mode-balance.
Early claim pushed kitty/mouse before boot, then skipped the loop's
enable write. Hover never tinted and a second push unbalanced kitty.
Claim is now ?1049h/?25l plus a wipe; run re-asserts raw and writes
the full enable string exactly once.
Add a pi-xai harness that maps graff login xai into XAI_API_KEY so
`--suite swe --harness graff-dev,pi-xai --model grok-4.6` is the same
seat A/B ADR 0024 used for grok-build. Stock Pi xai is an API-key
provider; oauth type is ignored.
Same-login A/B (run-20260828-164346): Pi 5/6 in 276s / 166M vs graff
4/6 in 456s / 91M. Extra pass is json-stream whitespace-only json-seq
(already named in ADR 0024). Do not steal Pi's catalog or heap.
Pi's SWE wall win was not a shorter catalog. Every graff-dev task made
5 API calls — the bootstrap floor — then copied 132M graff-pinned and
generated suites (~38s CPU). Interactive REPL/TUI/ACP still auto-init.
After the skip, graff-dev is 5/6 in 205s / 6.5s CPU (was 4/6, 456s,
230s CPU). json-stream passed this rep; label-sort still fails.
Same key, same model, graff-dev vs pi-codegraff. Pi 5/6 in 758s;
graff 3/6 — three tasks hit the 300s cap before an edit landed.
Headline is ADR 0044: one-shots no longer copy 132M graff-pinned.
SuperGrok SWE 5/6 in 205s / 6.5s CPU. Also lands TUI alt-screen claim
(0042), pi-xai (0043), and the glm-5.3-flash record (0045). No tag
until asked.
Tier 1 counted 1758 on this cut (was 1745). Bump the ratchet at the
release cut so a dropped module is visible again.
Pi's glm-5.3-flash SWE first/wall win was no thinking, not four tools.
Codegraff takes_effort sent default medium on every flash request —
seconds of silent TTFT and 3–7k thinking tokens (ADR 0045 timeouts).

Same Gemini skip, now any *flash* name. Lean -p shortens tool prose
only. Catalog glm-5.3-flash. Do not shrink the keep-list (ADR 0024).
Eval first=6.7s was turn chrome on stdout at model call 2, not boot
(boot is 7ms; gateway TTFT is ~6s). Drop the pulse when unattended
so stdout stays the answer, and print `calling <model>` on stderr
at oneshot start — same class of signal as Pi's session JSON.
justrach/codegraff is repository 84216 on trendshift.io.
justrach/codegraff is repository 84216 on trendshift.io.
json-stream and cookie-store SIGKILL'd at 300s because -p gated live
transport on out!=null. A hung/5xx second call sat in postWatched until
the deadline, then retried, then the eval cap killed the process.

Root one-shots now postLive so the 30s head-stall fires. Paint stays
off (out=null / stream_quiet). graff-dev also caps postWatched at 90s
for subagents.
json-stream passed (280s). cookie-store / label-sort still hit the
300s cap on live streams, not the old 5-minute watched POST.
Codegraff glm-5.3-flash bills reasoning_tokens when reasoning_effort
is absent (27 on a pong; SWE streamed 1.9MB reasoning_content).
thinking.disabled still thinks. low bills 0. none is a 400.

That is the wall gap with Pi, not Zig vs JS. /effort high still
sends high. Do not shrink the keep-list.
Beats Pi's 758s on the same model. Same miss (label-sort). Out tokens
29k → 4.7k — the wall was thinking novels, not Zig vs JS.
…notes

A ~40s gateway blip on glm-5.3-flash (2026-08-29, dhi triage session
6deff1df) surfaced as 3 transport timeouts followed by a 4xx "Body must
be valid JSON" on the SAME unchanged request body. The envelope path
hard-failed and killed the turn even though the identical (larger)
payload succeeded two minutes later: body bytes do not change between
attempts, so a parse rejection arriving right after a timeout run
indicts the gateway, not the request.

Classify body-parse rejection phrasings and retry them bounded (2 tries,
1-2s backoff) when THIS request already logged >=2 error.Timeout hits;
without that timeout history the 400 stays fail-fast exactly as before.
Wired into all four envelope-fatal paths (codex .failure, streamed SSE,
plain JSON type=="error", openai-style error envelope) via the one
afterServerErrorOrParseReject gate that runs the shared transient-overload
retry first, unchanged.

Also attribute retry trace notes with the agent label: the same session
drew three 5xx retries inside two parallel subagents (each recovered on
the same payload) and none of the anonymous "retry" events said who —
attribution took ms-arithmetic across api spans. REPL output unchanged.

Both touched files sat at the 600-line ceiling, so the new logic lives in
src/agent_gateway_retry.zig (state, classifier, gate, attributed notes)
with re-exports on agent_request_policy.zig; the #402 source pin now
asserts the delegation chain arm -> gate -> shared transient retry.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Lands cursor/eval-frontier-4ffc on the 281 cut: OpenCode --dir / dsh
harnesses, in-house fixtures, frontier SVGs, list-price plot, hardlink
graff-pinned + detached learn init, scripted-REPL usage footer, and the
#685 atomic credential write already on main. Conflicts in
graff-evals/README.md and harnesses.json kept both Pi-on-SuperGrok and
the new in-house / OpenCode / dsh entries.

Do not tag. Do not merge to main from this commit.
Tier 1 warned the ratchet sat 33 ahead of 1758 (slack 25) after folding
#687. Bump the floor on this cut so a dropped module would still trip
the hook. Notes mention the eval-frontier land.
Lean -p no longer handshakes imported MCP when the sandbox has no
.mcp.json (ADR 0029 is the project file). Turn-pulse chrome stays off
oneshot stdout. -p streams answer tokens so first_out is TTFT. The
atomic-symlink-write prompt now requires editing atomic_write.py, and
lean work notes say to edit named files before answering.
@justrach justrach changed the title release/v0.0.281 — learn skip + flash effort=low + TUI boot/stall release/v0.0.281 — learn skip + flash effort + eval frontier (#687) Aug 30, 2026
`event: response.completed` arrives one line before the `data:`
object that carries usage. Treating the event name as terminal
dropped tokens/$ to zero on the live -p path.
Tool-first -p turns stayed silent until the final answer, so file-ops
first_out ≈ wall. One dim › on stderr at the first model SSE event
makes eval first_out true TTFT without putting chrome on stdout.

In-house remasure closed atomic-symlink-write but cache-gitroot and
stall-warn one-shotted ("I'll read SPEC.md") with zero tools. One
bounded nudge, shared by -p and the REPL, asks the model to edit the
named path. Strengthen those two fixture prompts the same way as
atomic-symlink-write. Do not loosen the verifier.
Same-session grok-4.6 A/B after the SSE usage fix. Spine wall/$/RSS
beat both rivals; first-token still loses on file-ops. In-house is
4/6 (atomic-symlink-write now passes; cache-gitroot and stall-warn
one-shot). Not Pareto.
role=user / content-string lookup missed xAI Responses items
(input_text blocks), so atomic-symlink-write and stall-warn still
one-shotted. Walk every string in the conversation instead. Strengthen
the empty-catalog fixture prompt so showcase rebuilds NATIVE+extra.
Responses history after the first step is not a role=user string.
Snapshot the user prompt at -p / runTurn start and nudge from that
copy when tools_used is still empty.
Graff wins wall / first / tokens / $ / RSS on run-20260830-113706.
Calls 8 > grok 7. In-house nudge still misses some 1-call turns.
A Chat `{role, content: string}` after output_text / function_call
items is dropped or 400s on the follow-up request, so atomic-symlink
and stall-warn stayed 1-call misses. Append a real `input_text`
message, close the WS chain so the next call re-anchors, and force a
tool on that one extra request. Shared by -p and the REPL.
The input_text nudge itself was valid, but -p still appended the
original user turn as {role, content: string}. Mixed with output_text
that full resend 400s (graff exit 1, one counted call). Promote Chat
strings to typed message items at send, and append the -p prompt as
input_text on the Responses wire.

stall-warn was the remaining in-house 1-call miss after atomic-symlink
started passing.
noticeWideNative invalidated tools_responses and never called
ensureRootTools. The next request serialized `"tools":,` and xAI
400'd — graff exit 1, one counted call, four tools already run.
That is stall-warn's remaining miss (and the empty-catalog fixture
in product form). load_tool_schemas / noticeContext already rebuild;
match them.
…Code

Same-session grok-4.6 A/B after the 4-wide showcase catalog rebuild.
Graff is ≤ both rivals on pass/wall/first/calls/tokens/list$/RSS and
strictly better on at least one in each table. Sampler RSS is not a
heap steal — child HWM stays ~20M.
Named-file Responses nudge, Chat-to-typed coerce, catalog rebuild after
4-wide showcase, TTFT mark, SSE hold, and -p chrome/MCP handshake/symlink
fixture. Eval tables from #688 come along.

Conflicts: keep 281 usesLiveTransport (every agent streams) and MCP
receipts/timing; take Pareto deferMcpJoin + oneshotSkipsImportedMcp.
Learn skip and x_search-on stay as on 281.
#688 landed 13 reachable tests (named-file nudge, catalog rebuild, MCP
handshake). Record the Pareto product on the cut notes. No tag.
@justrach justrach changed the title release/v0.0.281 — learn skip + flash effort + eval frontier (#687) release/v0.0.281 — learn skip + flash effort + Pareto product (#688) Aug 30, 2026
cursoragent and others added 6 commits August 30, 2026 13:40
Double --suite inhouse with distilled verifiers from merged CodeGraff
PRs: hardlink pin (#687), hosted x_search splice (#632), first-turn MCP
skip (ADR 0035/0029), rlm showcase gate (#633), codedb five-shot menu
(#597), peer-channel resume (#584). Same pattern as the first six —
buggy starter + SPEC + visible tests + hidden/ check. Not the live repo.
Same-session grok-4.6 vs grok-build and OpenCode on the doubled PR suite
(run-20260830-141658). Graff 192s / 52 calls / $0.350 vs OpenCode 236s /
74 / $0.792 and grok 462s / 63 / $1.115. First-token 0.02s is stderr ›
at boot — not scored as TTFT.
Visible README is ~200 lines (was ~1700). Same-model in-house 12/12 table
replaces the retracted oneshot-learn-skip blurb. CLI / slash / providers
stay in one <details>. Broken section links in embedding, ACP registry,
and benchmarks/README follow the new headings.
Shipped-PR fixtures (hardlink pin, x_search splice, MCP first-turn, rlm
showcase gate, codedb menu, peer resume), the same-session 12/12 A/B, and
a ~200-line README with the frontier table.
Tip is hardlink + detached init, not the retracted oneshot skip. Point
at the 12-task in-house table (#690).
…ap settle

CI was red on the release tip for two independent reasons.

pinExecutable used File.hardLink, whose Io.Threaded fileHardLink is
implemented for linux only — every macOS pin silently degraded to the
full byte copy the feature exists to avoid, and the hardlink unit test
failed here. Dir.hardLink's dirHardLink path linkat()s by name and works
on macOS; an absolute source path ignores the old dir handle.

The learn bootstrap probe still asserted the pre-detach world: it
checked refs/active.json the moment the session exited (the store now
lands seconds later, detached), expected the old "learning on for this
workspace" line (now "learning setup started in the background"), and
expected the bootstrapping session itself to sit at sessions_since_trial
1 (the cadence now starts with the next session that finds the store).
Poll for the store, match the current wording, and count the next
short session instead.

Co-Authored-By: Codegraff <blackfloofie@codegraff.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants