feat(adaptive): recipe authoring — steps in, lowered graphs out - #60
Merged
Merged
Conversation
Nine field runs against a live host established why full-graph authoring fails at small model tiers: the author must emit exact tokens across three foreign syntaxes at once — the graph dialect, the host's tools, and whatever CLI its scripts drive — blind, with feedback one round away. One wrong token anywhere is a dead graph, and the defects surface serially (observed: an invented tool arg, an invented gh field, a split_out on unparsed stdout, a binding embedded in prose — one per round, never converging). So the model no longer writes graphs. It writes a recipe — steps that either `run` a script or `ask` an agent, with `reads` naming which earlier steps' output an agent needs — and `intake::recipe::lower` compiles that into a valid WorkflowGraph deterministically. Every expression, envelope path and edge is machine-generated by code that knows the engine's shapes exactly; the prose-binding failure class is impossible by construction. The lowered graph still walks every downstream gate, and the author feedback rounds now carry the lowering's refusals, each of which states the fix. Because every generated prompt is now an expression, reuse::baked_in learned to scan the QUOTED LITERALS of expressions (paths stay exempt): ="review acme/thing" is a paste however it is spelled, and the old skip-expressions rule would have blinded the keep gate entirely. The node catalogue leaves the authoring prompt — the model never writes node syntax, so teaching it was pure token cost. Test fixtures across author/driver/intake speak the recipe dialect. Verified end to end on a live host: the cheapest model tier authored a working multi-tool research workflow in two attempts, 9m37s wall clock, where six full-graph runs had produced nothing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
How this change flows5 changed behaviours across 13 relationships. 6 surrounding behaviours are shown (60 graph nodes walked). 38 further behaviours left out to keep the diagram readable. flowchart LR
n0["author<br/>changed"]:::changed
n1["fingerprint<br/>changed"]:::changed
n2["gated<br/>changed"]:::changed
n3["...red_and_worked_becomes_a_stored_procedure<br/>changed"]:::changed
n4["...ves_to_a_stand_down_and_consolidates_once<br/>changed"]:::changed
n5["unknown"]:::impacted
n6["caps_with"]:::impacted
n7["new"]:::impacted
n8["...lt_of_different_kinds_drive_the_same_loop"]:::impacted
n9["prompts"]:::impacted
n10["...s_the_refusal_back_and_binds_on_the_retry"]:::impacted
n0 -->|calls| n2
n2 -->|calls| n1
n3 -->|calls| n5
n3 -->|tests| n5
n4 -->|calls| n5
n4 -->|tests| n5
n8 -->|calls| n5
n8 -->|tests| n5
n10 -->|calls| n5
n10 -->|tests| n5
n10 -->|calls| n6
n10 -->|calls| n7
n10 -->|calls| n9
classDef changed fill:#0d4429,stroke:#238636,color:#e6edf3
classDef impacted fill:#161b22,stroke:#6e7681,color:#c9d1d9
classDef flagged fill:#5a1e02,stroke:#d93f0b,color:#ffffff
classDef blocking fill:#67060c,stroke:#f85149,color:#ffffff
Green: changed behaviour. Grey: surrounding behaviour. Arrows name the call, use, implementation, or test relationship. Orange: has findings. Red: has a finding that blocks the merge. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See the commit message for the full rationale: nine field runs showed full-graph authoring fails at small model tiers (exact tokens across three foreign syntaxes, blind, serial defects — an invented tool arg, an invented
ghfield, asplit_outon unparsed stdout, a binding embedded in prose). The model now writes a recipe — steps thatruna script oraskan agent, withreadslinks and an optionalworker— andintake::recipe::lowercompiles it deterministically: every expression, envelope path and edge machine-generated (stdout for script upstreams, text for agent upstreams), the prose-binding class impossible by construction, lowered graphs still walking every downstream gate, and lowering refusals feeding the existing author retry rounds.Carried in the same change:
reuse::baked_inscans expressions' quoted literals (paths stay exempt) — all generated prompts are expressions now, so the old skip-expressions rule would have blinded the keep gate. The node catalogue leaves the authoring prompt. All author/driver/intake fixtures speak the recipe dialect; newrecipe_tests.rscovers lowering, envelope-path selection, jq quoting, worker→agent_ref, id sanitisation, and every-problem-at-once refusals.Verified live: the cheapest model tier (deepseek-v4-flash on every loop tier) authored a working multi-tool research workflow in 2 attempts / 9m37s wall clock — the same goal six full-graph runs had failed — with the judge refusing attempt 1's shallow result and attempt 2 delivering a 13.7KB evidence-backed report.
🤖 Generated with Claude Code