v0.1.5 — subagent model override · observability · debug-mcp
What's new
feat(task) — per-spawn model override for subagents
The Task tool now accepts an optional model field, so the parent can
spawn a subagent on a different model from itself in the same run:
{
"tasks": ["summarize crates/forge_app"],
"agent_id": "muse",
"model": "gpt-5.5-medium"
}The override is validated against the agent's already-authenticated
provider — pass a model that isn't on the parent agent's authenticated
provider list and you get a clean error listing what is, instead of a
silent cross-provider switch or a confused 401 deep inside the request
path. The subagent banner surfaces the override
(MUSE [Agent · gpt-5.5-medium]) so the parent/child story stays
legible in the trace.
Plumbed end-to-end: TaskInput.model → ChatRequest.model_override →
validated in ForgeApp::chat → agent.model(override) → recorded in
the trajectory as a requested-vs-resolved diagnostic round-trip.
feat(observability) — agent_run + agent_run_end trajectory events
Two new TrajectoryPayload variants make per-spawn behaviour
inspectable:
agent_runcaptures the spawn diagnostic:agent_id,
parent_agent_id,requested_model,resolved_model, plus a
agent_versionSHA-256 prefix of the agent's system prompt template.
Two edits toforge.mdare still bothforgebut produce different
hashes — so a rollup query can group runs by behaviourally distinct
variants rather than byagent_idalone.agent_run_endcarries the per-spawn fitness vector: turns,
prompt/completion tokens, total tool calls, tool errors, wall-clock
ms, and aninterrupt_reasonif the run terminated abnormally. Sums
what's already computed turn-by-turn so the bottom ofrun()writes
the full picture without re-walking events.
/trace renders both, including the requested-vs-resolved diff when
they differ. This is the substrate for an empirical archive of agent
variants — no mutation logic yet, just observation.
feat(debug) — graff debug last-mcp-call
A new top-level subcommand that prints recent MCP request/response
pairs as JSONL, no log-spelunking required:
graff debug last-mcp-call -n 5 --server codedb --tool codedb_bundle --prettyforge_infra::mcp_debug writes a ring buffer at
<base>/debug/mcp-recent.jsonl capturing the literal arguments that
hit rmcp::call_tool, the round-trip duration, and the outcome
(returned vs failed + error). When an MCP server complains "arguments
arrived empty," this pins the loss to the wire vs upstream of the
client.
fix(tools) — rewrite oneOf → anyOf for OpenAI Responses
OpenAI's tool-schema validator (including
chatgpt.com/codex/responses) rejects oneOf outright with
'oneOf' is not permitted', regardless of strict mode. anyOf is
accepted by both OpenAI and Anthropic, and for discriminated unions
whose branches pin a property to different const values (like
codedb_bundle's ops schema) the two are functionally equivalent —
no input matches more than one branch anyway.
A new forge_app::utils::rewrite_one_of_to_any_of recursively
rewrites every oneOf to anyOf before strict-mode normalization
runs, in both the legacy chat-completions and Responses-API paths.
Bundled codedb is now started with CODEDB_DISCRIMINATED_SCHEMA=1
so its discriminated branches actually flow through the rewrite (vs
arriving as a bare {type: "object"} and triggering missing-path /
missing-pattern runtime errors). Regression test in
forge_repo covers the codedb_bundle shape end-to-end.
feat(ui) — banner logs path, softer status icons, reasoning hidden by default
- The interactive banner now shows the log directory under
Logs:so
agents debugging graff can find it without spelunking through
forge_tracker. - Status icons softened:
✓for completion,✗for error, dimmer
info dot, brighter timestamps. Reads less like a syslog and more
like a chat trace. - Reasoning summaries (
Evaluating ...,Exploring ...) are hidden
unless--verbose. They're available in the trajectory if you want
them; the live REPL stays signal-rich. - Tracing:
FORGE_LOGfalls back toRUST_LOGso anyone with Rust
muscle memory just works. Default filter is module-segment-agnostic
(debugnotforge=debug) so events fromforge_infra,
forge_domain,forge_main, etc. actually land in the log file.
Parallel tool calls — visible header
When the model emits ≥2 tool calls in a single assistant turn, an
⇉ N parallel tool calls (breakdown) header lands above them — the
batch is now visible as a group rather than dissolving into a stream
of unrelated icons.
Release pipeline
The CI release workflow is removed in this version. The previous
generator pushed to antinomyhq/npm-code-forge,
antinomyhq/npm-forgecode, and antinomyhq/homebrew-code-forge —
upstream-fork repos this codegraff fork doesn't own. Releases are
manual from 0.1.5 onwards: build locally, gh release upload. We'll
re-add CI builds once we have target distribution channels under our
own org.
Binaries
This release ships macOS arm64 only (codesigned with Developer ID,
notarized by Apple). Other platforms can be built from source:
cargo build --release --bin graff --bin codegraffNotes
- Workspace version bumped to
0.1.5. - Tag:
v0.1.5.
🤖 Generated with Claude Code