Skip to content

Execute recipes through a typed boundary - #2477

Merged
chubes4 merged 1 commit into
mainfrom
refactor/2431-typed-recipe-execution
Sep 3, 2026
Merged

Execute recipes through a typed boundary#2477
chubes4 merged 1 commit into
mainfrom
refactor/2431-typed-recipe-execution

Conversation

@chubes4

@chubes4 chubes4 commented Sep 3, 2026

Copy link
Copy Markdown
Collaborator

Part of #2431. This is a bounded first slice, not the full canonical request/result contract.

Problem

Internal callers reached Codebox execution by building CLI argument arrays, capturing Codebox's own stdout, and reparsing that JSON back into a result they had just produced in process. agent-task-run.ts and three paths in wordpress-runtime.ts did this, each with its own parseRecipeRunOutput() and its own temporary recipe file.

Change

Add a typed in-process execution seam and make recipe-run a thin CLI adapter over it.

  • executeRecipeRun(options, interruption?) dispatches dry-run vs. real run and applies interruption metadata.
  • createRecipeRunOptions(input) supplies the same defaults the CLI parser produces, so callers stop synthesizing flags.
  • RecipeRunOptions accepts an optional in-memory recipe and recipeDirectory. Generated recipes no longer need temporary files, while recipePath remains the provenance and replay identity.
  • agent-task-run.ts drops captureOutput(), parseRecipeRunOutput(), and its temporary recipe directory.
  • wordpress-runtime.ts routes its three round trips through one executeGeneratedRecipe() helper and drops its local parser and temporary files.

runRecipeRunCommand() keeps every CLI-only concern: argument parsing, host-heap replay, preview-lease child handling, heartbeats, stdout capture, human/JSON rendering, output files, and exit codes. adversarial.ts stays a thin CLI forwarder because its behavior is argument-level.

Two regressions caught in self-review and fixed

  • recipeRunMetadata() derived site-seed provenance from dirname(recipePath), which resolves to the wrong directory for in-memory recipes. It now takes the resolved recipe directory.
  • The generated agent-task recipe was briefly written before execution, which would newly sweep it into the artifact manifest. Restored to post-run ordering so artifact contents match previous behavior.

Verification

  • npm run build passes.
  • npm run check passes: 310 commands, re-run after both fixes.
  • New tests/recipe-execution-boundary.test.ts proves the typed path with no recipe file on disk returns output deep-equal to the CLI's JSON for the same failure, and that typed defaults match CLI defaults.

Not run locally: the heavier integration and browser lanes. CI covers them.

Residual risks for reviewers

  • agent-task-run now passes process.cwd() as the recipe directory instead of the previous empty temp directory. buildAgentTaskRecipe emits absolute paths, so no relative source resolved before; this widens rather than breaks resolution.
  • Agent-task failure evidence now takes stdout/stderr from execution records and the serialized error instead of captured process output. Contract and canonical-evidence tests pass, but this is the most behavior-visible edge.

Follow-ups

Sequence stays #2431 execution boundary, then #2432 artifact kernel, #2433 generated adapters, #2434 optional workload extraction.

AI assistance

  • Model: Claude Sonnet 4.5
  • Tool: OpenCode
  • Used for: Traced the stdout round trips, implemented the typed seam, migrated callers, wrote the parity test, and ran build/check under Chris Huber's direction. A delegated second-opinion review failed on a usage limit, so the review noted above was performed in the same session rather than independently.

Internal callers built CLI argument arrays, captured Codebox's own stdout,
and reparsed the JSON to recover a result they already produced in process.

Add executeRecipeRun() and createRecipeRunOptions() so agent-task and the
WordPress workload/fuzz paths consume typed results directly. Accept an
in-memory recipe so generated recipes no longer need temporary files, while
recipePath remains the provenance and replay identity.

runRecipeRunCommand() keeps every CLI-only concern: argument parsing, host
heap replay, preview-lease children, heartbeats, stdout capture, rendering,
output files, and exit codes.
@chubes4
chubes4 marked this pull request as ready for review September 3, 2026 19:14
@chubes4
chubes4 merged commit aa4788f into main Sep 3, 2026
5 checks passed
@chubes4
chubes4 deleted the refactor/2431-typed-recipe-execution branch September 3, 2026 19:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant