MCP-inside-rlm + return-shape cache (Blacksmith muscle memory, not V8) - #623
Conversation
After load_tool_schemas unfolds a tool, rlm scripts may call that MCP name via exec_mod (unloaded names refused; GRAFF_RLM_MCP=0 restores structured- only). Infer field names + broad types from results, persist under .graff/mcp-shapes.json, and splice them onto the next load_tool_schemas result — never the always-on prefix. each(arr, tool, field) maps a JSON array so the Linear-shaped bench can run as one script.
Live grok-4.6 one-rep: warm D is -36% tok_in vs --old; cold C loses wall; B (structured-only) is the old gap. How to rerun is in the record.
Second-round A/B for ADR 0029: F/G never print() fat MCP arrays; H/I drop the each() recipe so we can see whether shapes alone steer the script. --only filters the runner.
Second SuperGrok rep: A wall is stable (~36s). D token win did not hold (159k / 61s). Quiet-print (F/G) burned 21–29 calls on Python. No-hint H/I never used rlm and beat --old (28–31s, 7 calls).
|
Follow-up SuperGrok A/B (same day, ADR 0029):
The |
each() without a slim print made grok invent for/len (ADR 0029). len(x) and project(x, field) stay data helpers. eval-mcp-pareto.py keeps the undominated set on wall / tok_in / calls.
|
Pareto front on wall / tok_in / calls (minimize all three, pass-only). Added
This session: A No point wins wall and tokens. Rerun: |
len/project recipe (J) is the token vertex at 84k / 47s. H remains the wall vertex at 28s / 7 calls. Nothing wins both.
After remember() of the fat payload, takeSlim / print() keep identity keys and fold comments to n+latest_author. Two stored shapes add a # muscle: line on the load result (never the catalog prefix). L–Q sweep those paths against the existing Linear fixture.
The len/project advertise pushed the discovery note over the byte check (em-dash + signatures). Shorter wording; the catalog desc still has the full each/len/project signatures.
|
Learnt slim landed on this branch (
Next: live SuperGrok L–Q sweep on the same Linear fixture (warm/cold × no-hint / each-hint / quiet / reduce) and a Pareto recompute. Will comment numbers here; not rewriting this PR body. |
|
Follow-up in the agent queue, so the live L–Q SuperGrok sweep is deferred (ReleaseSafe binary is built). Unit suite is the gate for this revision. L–Q are wired in |
Lean skipped MCP connect and hid load_tool_schemas even when a workspace server was present, so every MCP one-shot needed --no-lean. Default -p (lean+yolo) now connects and folds: names on the meta tool, full schemas a load away. Empty -p still hides the meta tool.
|
Out-of-the-box gap was lean itself, not another hint:
Next: live variant R = |
|
R live (SuperGrok grok-4.6, ReleaseSafe, one rep): 16.3s / 14,113 in / 4 calls / pass. That is the default binary ( Out of the box was: connect + fold + slim on the default one-shot. Not another recipe. |
Live SuperGrok grok-4.6: graff-dev + linear-nohint passed and dominates the prior --no-lean H/I/J front.
Lean shrinks the prefix (workflow/webfetch/full MCP listing off). R's 16s/14k/4 is not an A/B against H/J. Front stays graff-dev-nolean; next live points are N/L/P (slim on the full harness).
|
Full harness (
L and N are the |
graff-dev-nolean SuperGrok: L 14.8s/31k/5 (warm), N 20.8s/30k/5 (cold). Both dominate H/I/J. P 48s/66k/9 does not. R stays off the front (lean catalog).
|
L/slim is on |
Verdict
Muscle memory is a real token win vs
--old. MCP-inside-rlm is real (each()ran). It is not a wall win this rep.Warm D: 107k tok_in vs A 168k (−36%), same 10 API calls. Cold C lost wall (56.7s vs A 36.7s) — fat
print()+import/for/lenretries, same story as Blacksmith cold code mode. B (rlm, MCP structured-only) is the old gap: the model wroteeach(...)and was refused. Do not hide bash/edit/read_file. Do not add V8/IPython/QuickJS. Do not makerlmthe only catalog tool.SuperGrok
[usage]is$0.0000flat-rate; the 60k input cut on D is the metered-key spend win.Evidence: ADR 0029.
Live A/B (2026-08-25)
SuperGrok OAuth, grok-4.6, one rep, ReleaseSafe. Same prompt: 8 fat fixture issues + comments + counts + latest authors. No live Linear.
tok_inis ordinary+cache_read+cache_write.--oldstructured MCPeach()refused; thenimporteach()worked; 3 rlm failslenretryRetries were missing language (
len/for/import), not wrong MCP field names. Shapes splice onto theload_tool_schemasresult, never the always-on prefix (ADR 0011).What this is
Blacksmith [code]smith mapped onto graff, not a JS/TS/V8 sandbox:
load_tool_schemasunfolds a tool and consent already allows it,rlmscripts may call that MCP name (src/rlm_mcp.zig,exec_mod). Unloaded names refused. Deferral can only subtract.GRAFF_RLM_MCP=0restores B..graff/mcp-shapes.json; splice on the next load/search result (src/mcp_shapes.zig).each(arr, tool, field)maps a JSON array — smallest control flow forfor issue in list_issues(): list_comments(id). Not a general language.Fixture:
scripts/linear_fixture_mcp.py(stdio MCP, 8 fat issues ISS-1..8, fat comments). Held-out check:graff-evals/hidden/check_linear_report.py.How to rerun
Suite
mcpis opt-in; defaultallstays core+rlm+swe.Tests
Unit: rlm dispatches a loaded MCP name; unloaded refused; shape inference strips values; warm
load_tool_schemasincludes merged shapes; lean/consent unchanged. New modules imported fromexec.zigtest {}(main.zig is already at the 600 LOC ceiling). Suite 1646 pass / 1 skip / 1647 total (baseline 1600, slack 25).