Skip to content

v0.0.277

Choose a tag to compare

@github-actions github-actions released this 26 Aug 03:54
· 42 commits to main since this release

v0.0.277 (2026-08-26)

MCP-inside-rlm + learnt slim is now on the full harness, and the licensed
one-read-surface / turn pulse / Smolify opt-in that was already on
release/v0.0.277 is in the cut. graff still writes a code REPL
(ADR 0022); this release is what that loop does with MCP, with X, and
with a licensed codedb-pro seat.

The short version: fat MCP results slim themselves, grok-4.6 can search X
without a scrape, small turns do not pay for rlm, and a licensed
codedb-pro install is one read surface and one edit surface — no default
16-call cap, no Smolify unless you ask.

MCP-inside-rlm and learnt slim

Loaded MCP names are rlm host functions (src/rlm_mcp.zig). After
load_tool_schemas unfolds a tool, a script may call that name;
unloaded names are refused, and deferral can only subtract.
GRAFF_RLM_MCP=0 restores the structured-only gap.

After each MCP result, graff infers a value-free return shape (keys +
broad types, never values), persists .graff/mcp-shapes.json, and splices
it onto the next load_tool_schemas result. Never the always-on
prefix (ADR 0011).

The learnt part is applied in Zig, not as another prompt hint:

  • Fat JSON arrays auto-slim after remember(): identity keys on
    issue-like rows; comment arrays fold to {n, latest_author}.
  • Two stored shapes add a one-line # muscle: playbook on the load
    result. No new GRAFF_ knob.
  • each / len / project exist so a script can print a slim summary.
    They are not advertised as the recipe — an each() hint is a footgun
    on grok-4.6 (it invents for/len/import or dumps the fat bind).

A later run in the same repo is L: shapes already on disk, muscle on
the load result. N is the same slim on a cold cache. Both dominate
the pre-slim H/I/J front. This is not Blacksmith's V8 sandbox and not an
rlm-only catalog — those already failed (ADR 0023 / 0024).

See ADR 0029.

Performance

All MCP numbers are live grok-4.6 SuperGrok OAuth, one rep, ReleaseSafe,
--no-lean (graff-dev-nolean). SuperGrok is flat-rate ($0.0000 both
ways). Token/call cuts are the spend win on a metered XAI_API_KEY.
Rerun: python3 scripts/eval-mcp-shapes.py / eval-mcp-pareto.py.

Learnt slim vs pre-slim (Linear fixture, no each() hint)

wall in calls
L warm + slim 14.8s 31k 5
N cold + slim 20.8s 30k 5
H (pre-slim, same harness) 28.0s 112k 7
I (pre-slim, warm shapes unused) 31.1s 107k 7

L is N after muscle memory has been written. Both dominate H/I/J (J was
47s / 84k / 9). Variant P (reduce recipe + slim, 48s / 66k / 9) is
dominated by L/N. Lean default -p (variant R, 16.3s / 14k / 4) is a
different catalog and is not on this front — the MCP bench stays
--no-lean.

What did not ship as the default path

The first A/B (2026-08-25) showed MCP-inside-rlm + shape cache can cut
tokens when the model stays in each() (D vs --old: 167k → 107k in).
A same-day rerun did not hold (D-r2 159k / 61s), and an explicit each()
hint plus "never print fat arrays" blew out to 220s / 462k / 29 calls.
No-hint structured MCP (H/I) was the stable cheap path until slim; slim
then made L/N the front. Do not copy the each() recipe onto the prefix.

Default -p connects MCP

Lean used to skip MCP connect and hide load_tool_schemas even
when a workspace .mcp.json was present. That forced --no-lean for
every MCP one-shot (ADR 0024 leftover).

Default -p still implies lean + yolo, but it now connects a
workspace .mcp.json and folds (names + one-liners, full schemas a
load away). Empty -p (no deferred MCP) still hides the meta tool.
Consent is unchanged. --no-lean is the eager-schema opt-out, not the
MCP on-switch.

Licensed codedb-pro: one read surface, one edit surface

When codedb-pro is licensed, the catalog is one read/search surface and
one edit surface (#626,
#627):

  • Native read_file and legacy codedb are hidden. codedb-pro
    read / faster_search / meta_search stay.
  • Companion write tools (mcp__codedbpro__ / mcp__muonry__
    edit/patch/create/replace/byte_delta) are omitted — they
    bypass /rewind. The exec gate still refuses them if they leak through.
  • Native edit_file / write_file stay. subagent stays. webfetch is
    not hidden here.
  • bash whose first token is a search (grep/rg/find/cat/head/
    tail/sed/awk/…) is refused; use the licensed search tools.
  • Workers inherit the same catalog. A subagent gets codedb-pro reads,
    not native read_file, and never the companion writes. Hiding subagent
    from the REPL was the other half of #627 and is not done.

Without a license the native tools stay. The hide is catalog + exec, not
a prompt essay.

Long turns pulse; no 16-call cap

A local trajectory corpus (129 real turns) had p50 = 5 model calls. A
default cap of 16 would have paused 174 successful turns. So the inner
loop is unlimited (max_turn_model_calls = 0).

What you get instead (#624,
#625, ADR 0020 chrome):

  • From the second model call of a turn: · turn still going · model call 3 · 11 tools
  • On transport flakes: · retry 3/6 · HungRequest (also UnknownHostName)
  • JSON mode and subagent turns stay quiet (chrome is not output).

GRAFF_MAX_TURN_MODEL_CALLS=16 is the opt-in cap, with a denominator on
the pulse (model call 3/16). It is not the default.

Optional MCP stays off until asked

Smolify, DeepWiki, and Mobbin were the high-fail unauthenticated servers
in the same corpus. They stay out of the default catalog
(#628):

want set
Smolify GRAFF_SMOLIFY=1 (or GRAFF_SMOLIFY_ACCESS=public / full)
never Smolify GRAFF_NO_SMOLIFY=1
DeepWiki GRAFF_DEEPWIKI=1
Mobbin GRAFF_MOBBIN=1
either/both GRAFF_MCP_OPTIONAL=deepwiki,mobbin

A workspace .mcp.json you actually configured still connects (folded on
-p). The skip is the bundled unauthenticated extras.

Hosted x_search (xAI Responses)

grok-4.6 already runs {"type":"x_search"} server-side. This cut splices
that hosted tool onto xAI Responses tools turns
(ADR 0031).
It is not a catalog function, not on the prefix, and not dispatched by
graff — x_search_call / custom_tool_call names x_search,
x_keyword_search, x_semantic_search, x_user_search, x_thread_fetch
are already done. Tools-off turns stay tools-off. Chat completions
(GRAFF_XAI_WIRE=chat) and Codex never get it.

GRAFF_XAI_X_SEARCH=0 (or off/false/no) opts out.

Same SuperGrok prompt (“what are people saying about xAI on X?”):

scrape (GRAFF_XAI_X_SEARCH=0) hosted x_search
wall 101s 37s
calls 7 1
input tokens 64k 28k

Citation annotations ride the message; v1 does not pretty-print them.
Revisit the splice if the extra hosted object shows up as cache noise on
a coding eval.

Late + context showcase

Small turns hide rlm (and sPTC). L/N never call rlm; advertising the
spec on every turn still costs prefix bytes and invites the each()
dialect. Zhang / Li / Khattab argue RLM's job is length generalization,
not replacing structured tools on short in-distribution turns.

Showcase (markLoaded, schema on the tools tail, never the head) when
(ADR 0030):

  • --rlm / GRAFF_RLM=1 — immediate;
  • a structured batch of ≥4 native host tools (read_file / codedb /
    bash / webfetch) — the scatter-gather that sPTC overlaps;
  • effectiveContextTokens() ≥ 50% of provider.compactAt() — the existing
    overflow meter, not a second counter;
  • explicit load_tool_schemas tools=["rlm"].

MCP-only fan-out and first slim do not showcase. /new / /clear
hide a session-discovered showcase; --rlm sticks. --old resets
discovery. Auto-load on a confident rlm call still works (gateExec).

GRAFF_RLM_CONTEXT overrides the size gate: unset = 50% of compactAt;
0/off disables; 1100 or 50% is a percent; 32k / 32768 is
an absolute floor (Zhang's RL curriculum, opt-in — not the default).

The hide is the token win on short work. Showcase itself costs ~200
input tokens (schema on the tail) until the model actually scripts.

Flags

knob default what it does
--no-lean off on -p eager MCP schemas; not the MCP on-switch
--rlm / GRAFF_RLM=1 late showcase force rlm on now
--old / --no-rlm off structured-only catalog
GRAFF_RLM_MCP=0 on MCP names are not rlm host functions
GRAFF_RLM_CONTEXT 50% of compactAt size gate for late showcase
GRAFF_XAI_X_SEARCH=0 on (xAI Responses) no hosted x_search splice
GRAFF_MAX_TURN_MODEL_CALLS 0 (unlimited) inner-loop pause cap
GRAFF_SMOLIFY / _ACCESS off connect Smolify
GRAFF_NO_SMOLIFY never connect Smolify
GRAFF_DEEPWIKI / GRAFF_MOBBIN off bundled extras
GRAFF_MCP_OPTIONAL empty comma list of those extras

Last CLI flag still wins over env for --old / --rlm (ADR 0022).

What we did not take

  • No V8 Code Mode / IPython / QuickJS. rlm is already the analog
    (ADR 0023). MCP-inside-rlm is host functions + shapes, not a sandbox.
  • No rlm-only catalog. File/shell tools stay; hiding them tanks pass
    rate (ADR 0024).
  • No each() recipe on the prefix. It is a grok-4.6 footgun.
  • No default 16-call turn cap. Pulse instead (#624).
  • No hiding subagent. Workers keep codedb-pro reads (#627).
  • No Smolify / DeepWiki / Mobbin in the default catalog (#628).
  • No x_search catalog tool. Hosted splice only (ADR 0031).
  • No showcasing rlm on MCP fan-out or first slim (ADR 0030).
  • Experiment worktree pool / default fan-out is #629 and is not in this cut.

Also in this cut

  • ADR 0029 MCP-inside-rlm + return shapes + learnt slim.
  • ADR 0030 hide rlm on small turns; showcase later.
  • ADR 0031 xAI Responses hosts x_search.
  • #624#628 out-of-the-box surface (pulse, retry chrome, licensed reads, subagent catalog, optional MCP).
  • Test ratchet: unit suite 1677 (floor 1664).

Downloads

All six CLI archives, the curl installer, and checksums:

File Platform
graff-aarch64-linux.tar.gz Linux arm64
graff-aarch64-macos.tar.gz macOS Apple Silicon — Developer ID signed, Apple notarized
graff-aarch64-windows.tar.gz Windows arm64
graff-x86_64-linux.tar.gz Linux x86_64
graff-x86_64-macos.tar.gz macOS Intel — Developer ID signed, Apple notarized
graff-x86_64-windows.tar.gz Windows x86_64
install.sh curl installer
SHA256SUMS checksums for the six archives
curl -fsSL https://github.com/justrach/codegraff/releases/download/v0.0.277/install.sh | bash

Both macOS binaries are Developer ID Application signed (hardened runtime,
timestamped) and Apple notarized (notary-local, Accepted). Stapling is
skipped on the bare CLI (stapler error 73); Gatekeeper checks the ticket
online at first launch. GitHub also attaches the usual source zip/tarball
for the tag.