feat(examples): self-improvement flow v1 — read runs, propose prompt+structure edits, open PR
What
examples/self-improvement/ is v1 of the self-improvement agent flow. It is meant to run on a schedule (flows schedule, or flows run from cron or CI). Each pass:
- Observe (deterministic):
listCloudRunsscans the newest runs, filters them to the target flow's name and to terminal status (completed/failed), and takes the last N.getCloudRunStepsis then called for each run. It authenticates with the workspaceworkflowtoken (FLOWS_CLOUD_TOKEN).digest.mjsranks steps by leverage across four signals: failing ×2.0, weak ×1.0, cost share ×0.5 and latency share ×0.4. - Analyse (agent, readonly): picks the highest-leverage step and writes
proposal.json, which holds a diagnosis, evidence from cited runs, prompt edits, structure edits, and a hypothesis (before / after / metric / expected / falsified_if). - Edit (agent,
cwd= target checkout): applies the proposal to the target.flow.yaml. - Gate (deterministic, one repair pass each): the proposal must name real steps and cite only collected runs. The edit must change exactly the flow file and pass
flows check. The compiled canonical spec, diffed before vs after, must show at least one prompt change and at least one structural change. - PR: one open
self-improve/<flow>/…PR per flow, with no stacking. The flow pushes usingGH_TOKEN(the App token on Cloud) and runsgh pr create. The PR body carries the before/after hypothesis and the evidence table.
It uses only primitives that exist today. It does not replay, evaluate, merge or deploy, and the README lists the gaps that keep it stopped at the PR.
Verified
npm --prefix examples/self-improvement test: 7/7 pass. Covers ranking, filtering of terminal runs and other flows, fail-closed behaviour with no runs, prompt-vs-structure classification in the spec diff, and both check-proposal stages.- Typecheck: running
tsc -p examples/tsconfig.jsonshows no errors inself-improvement/. The other errors are pre-existing missing deps in a bare worktree. - End to end, locally, with real agents:
flows run examples/self-improvement/self-improvement.flow.ts --local-agent --input examples/self-improvement/example/input.jsoncompleted 11 steps withcompletionReason: success. Against the fixture runs it pickedclassify(failing in 2 of 6 runs). It rewrote the instruction to a closed label enum with an exact final-line contract. It also addedmaxIterations: 2and tightened the gate toregex_match, giving 1 prompt edit and 4 structural edits in the compiled spec. - Not exercised: the live Cloud read and the real
gh pr createpath. That needs a workspace token, plus a target repo I was not authorised to open PRs against.
Found along the way (not fixed here)
flows build refuses any YAML flow that has a named gate (regex_match, …), reporting gate_command_missing: command "node" does not resolve. The cause: build's probes defer commands by throwing, and probeNamedGate (packages/sdk/src/preflight.ts) treats the throw as a missing command. This flow therefore compiles with the SDK's compileYamlToCanonicalJson instead (see compile-spec.mjs). The SDK bug deserves its own fix.
Not in scope (documented gaps)
There is no replay-as-gate and no headless deploy auth. Memory writes are also missing, since f.memory.learn throws. Cloud has no first-class way to inject a workspace read token into a hosted run, so for now this flow runs wherever FLOWS_CLOUD_TOKEN is available.
Do not merge without human review.
🤖 Generated with Claude Code
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.
[!NOTE]
Medium Risk
Example-only, but agents can use inherited GH/Cloud credentials and push PR branches; misconfiguration or weak repo scoping could publish unwanted changes despite the deterministic gates.
Overview
Adds examples/self-improvement/, a new scheduled-style example that improves a target YAML flow from Cloud run history and stops at an opened PR (no replay, merge, or deploy).
The main self-improvement.flow.ts pipeline clones or copies the target, compiles a before spec, collects terminal runs (Cloud or fixture), ranks steps by leverage, then runs analyst and editor agents. Deterministic .mjs helpers (collect, digest, compile-spec, spec-diff, check-proposal, seal) are base64-embedded via bundle.mjs so hosted runs stay self-contained and gates are re-materialized before each check.
Safety and publication: evidence is sha256-sealed; edits must match proposal.json against the compiled spec (prompt text exact, structure by step/field); git commit/push/PR steps are idempotent on branch self-improve/<flow>. Includes an offline issue-triage fixture, README, node:test suite, and ignores scratch dir /improve/. examples/tsconfig.json includes the new flow for typecheck.
Reviewed by Cursor Bugbot for commit 80e0a039d48cd165f823b36039667c9a09b4d804. Bugbot is set up for automated code reviews on this repo. Configure here.
Summary by cubic
Adds examples/self-improvement/, a scheduled agent flow that reads a target YAML flow's terminal runs, ranks steps by leverage, proposes both prompt and structure edits with a falsifiable hypothesis, gates the edits deterministically, and opens one PR per flow. It stops at the PR: no replay, eval, merge, or deploy.
- Helper scripts are embedded in the flow source (
bundle.mjs --write; the test fails on drift) because Cloud replays one self-contained source, and they are re-materialized before every check so agents can't edit the gates that judge them. - Evidence (runs, digest, before spec, before authored ids,
proposal.json) is sha256-sealed and verified from journaled command text; the target checkout must stay at its base commit, and the published blob is byte-compared against the sealed file.compile-specruns beforeflows checkin both checks so a symlink escaping the checkout is refused before check reads through it. - The edit gate requires the compiled-spec diff to be exactly the proposal: prompt edits carry the exact new text, structure edits are matched by compiled-spec (step, field) both ways, and a newly added agent/llm step counts as a prompt change. A step is compiler-generated only if neither the before nor the after YAML declares its id, so a re-authored step under a previously lowered gate's id is never exempt; only lowered gates absent from both declared-id sets and bound to a restructured producer's output are covered.
- Runs from same-named flows are dropped when their executed steps are mostly not the target's; publication is an idempotent commit/push/PR-reuse sequence on one fixed branch
self-improve/<flow>, so a concurrent run's non-force push fails closed. An orphaned branch is taken over with--force-with-leaseonly when its tip is older than an hour and no PR exists, re-checked right before the push and failing closed if the PR listing errors. A flowName that breaks git ref rules is refused. - Scheduling is cron/CI, not
flows schedule— a hosted fire can't read other runs — and the README documents that agent steps inherit GH/Cloud credentials.
Not exercised
- The live Cloud read path and real
gh pr createweren't run; they need a workspace token and a repo authorized for PRs. - A local end-to-end run with real agents against the fixture data succeeded, and the deterministic helpers have 7 passing tests.
Found along the way
flows buildrejects YAML flows with named gates likeregex_matchbecause the named-gate probe misreads a deferred command as missing; the flow compiles with the SDK'scompileYamlToCanonicalJsoninstead, and the bug warrants its own fix.
Agent Relay sessions