Skip to content

fix(cli): merge an intent's presets into a request body piped on stdin - #89

Merged
2ynn merged 3 commits into
mainfrom
fix/cli/intent-stdin-body-presets
Oct 7, 2026
Merged

2ynn merged 3 commits into
mainfrom
fix/cli/intent-stdin-body-presets

Conversation

@2ynn

@2ynn 2ynn commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Why

A declared intent command treats a whole request body supplied up front, whether through its JSON body flag or piped on stdin, as a partial body that the command completes: inputs given alongside it are merged in, and the intent's presets fill the gaps while a body naming another request variant is refused (CLI_VALIDATION, naming the escape command).

For single-route intents the preset merge ran only on a body flag the caller set. A body piped on stdin without a flag skipped it, so the request went out with the operation's defaults instead of the values the command pins, and a body naming another variant was sent instead of refused (request bodies abridged, primary CLI fixture):

$ echo '{"input":"cat"}' | cli render --dry-run
  "input": "cat", "model": "text-1"            # preset model and output_modalities missing

$ echo '{"input":"cat"}' | cli render --body @- --dry-run
  "input": "cat", "model": "render-1", "output_modalities": ["image"]

$ echo '{"agent":"helper","input":"cat"}' | cli render --dry-run    # sent; with --body it is refused

Route-dispatch intents already merge the selected route's preset into a stdin body (dispatchBody), and --body @- with the same bytes was merged, so only the implicit stdin path of single-route intents differed.

What changed

  • Runtime (flagutil/flags.go): MergePresetStdinBody reads the body AttachStdinBody re-attached from stdin, merges the preset with MergePresetBody (same fill, same variant guard, non-object bodies passed through), and re-attaches the result. Stdin is still read once; TTY, empty-pipe and agent-mode deadline behaviour is unchanged.
  • Template (intentcmd.go.stmpl): in the non-dispatch branch, a supplied body that did not come from a body flag gets MergePresetStdinBody after the existing body-flag merge.
  • Docs: CLI template README states that piped stdin gets the same preset merge as the body flag.
  • Review SDK: zSDKs/sdk-cli regenerated (internal/flagutil/flags.go, the five intent run functions, gen.lock).
  • Changeset: fix, cli.

Behaviour change: piping a partial body into an intent now sends the command's pinned values (model, variant, and other preset keys), and a piped body naming another variant is a CLI_VALIDATION error. Callers who need the operation's own defaults keep using the generated operation command.

Overlaps #82 on the README preset-merge bullet and the review SDK gen.lock (internal/flagutil/flags.go checksum); whichever lands second needs a rebase and a review SDK regeneration. With #82 and #83 merged, a piped body also gets the nested preset fill, and a nested flag works with a piped body.

Testing

  • TARGET=primary make test-cli: 1655 tests, 0 failures. New TestIntentPipedBodyKeepsPresets: a piped partial body gets the presets, --body @- gives the same result, the piped body's own keys win, a positional prompt is merged into a piped body, and a piped body naming another variant is refused as a typed CLI_VALIDATION conflict (usage exit code, escape command named) with no request reaching the server. It fails without the template change (model is text-1, the foreign-variant body is sent).
  • TARGET=review make test-cli: 609 tests, 2 skipped, 0 failures.
  • make lint, make check-template-cli: pass.

Public-safety check

  • This change contains no credentials, customer documents, private repository URLs, private filesystem paths, or unredacted private logs.
  • Title, body, comments, and commit messages name no customers or customer-derived identifiers, private paths or trackers, or workflow provenance, and are understandable without private context (.claude/skills/public-repo-communication/SKILL.md).
  • Generated fixtures and review SDK changes are public-safe.
  • I reviewed git diff --check.

Summary by cubic

Fixed an intent command's preset merge so a request body piped on stdin gets the same treatment as a body passed via --body: a piped partial body now keeps the command's pinned model and variant, and a piped body naming another variant is refused instead of being sent.

Bug Fixes

  • MergePresetStdinBody applies the same merge as the body-flag path: caller keys win, presets fill gaps, and foreign-variant bodies error as CLI_VALIDATION.
  • The merge runs only when the body did not come from a body flag; stdin is still read once, and TTY, empty-pipe, and agent-mode deadline behavior are unchanged.
  • Template README updated and the review sdk-cli regenerated; new tests cover piped bodies, --body @-, positional merging, and variant refusal that sends no request.

Written for commit 2d0e0c8. Summary will update on new commits.

View guided diff Turn on auto-fix

2ynn added 2 commits October 7, 2026 12:00
A whole body piped on stdin took request control like --body, but the
preset merge ran only on a body flag the caller set, so a piped body skipped
the presets and the variant guard: `echo '{"input":"cat"}' | cli render`
sent the operation's default model instead of the preset one, and a piped
body naming another variant was sent instead of refused. --body @- with the
same bytes was merged.

The non-dispatch intent run function now merges the preset into a body
attached from stdin (flagutil.MergePresetStdinBody), as route-dispatch
intents already do.
@2ynn
2ynn requested a review from a team as a code owner October 7, 2026 16:07
@2ynn
2ynn requested a review from mfbx9da4 October 7, 2026 16:07

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 12 files

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Shadow auto-approve: would auto-approve. Fixes CLI intent commands so request bodies piped on stdin get the same preset merge and variant validation as --body, with new tests, docs, changeset, and regenerated SDK. The correction is focused, consistent with existing intent semantics, and clearly beneficial.

View guided diff | Turn on auto-fix | Re-trigger cubic

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0 issues found across 1 file (changes from recent commits).

Confidence score: 5/5

  • Automated review surfaced no issues in the provided summaries.
  • No files require special attention.

Shadow auto-approve: would auto-approve. Focused fix making piped stdin bodies in intent commands get the same preset merge and variant validation as --body, with tests, docs, changeset, and regenerated SDK. Clearly beneficial and consistent with documented intent semantics.

View guided diff | Turn on auto-fix | Re-trigger cubic

@ThomasRooney ThomasRooney left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm.

@2ynn
2ynn added this pull request to the merge queue Oct 7, 2026
Merged via the queue into main with commit f984647 Oct 7, 2026
167 checks passed
@2ynn
2ynn deleted the fix/cli/intent-stdin-body-presets branch October 7, 2026 17:23
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 7, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants