Skip to content

Make IsMachineOutput honor an explicit --styled/--md - #670

Merged
jeremy merged 1 commit into
mainfrom
machine-output-honors-style-flags
Aug 31, 2026
Merged

Make IsMachineOutput honor an explicit --styled/--md#670
jeremy merged 1 commit into
mainfrom
machine-output-honors-style-flags

Conversation

@jeremy

@jeremy jeremy commented Aug 31, 2026

Copy link
Copy Markdown
Member

Follow-through on the one declined thread from #654: IsMachineOutput read flags and config but never Flags.Styled/Flags.MD, while ApplyFlags lets those flags overwrite a configured json/quiet writer. The same invocation was human to the renderer and machine to every gate, and humanFormatOverride in chat.go is this exact rule written once at one call site because the predicate couldn't say it.

Change

One clause in IsMachineOutput, between the machine-flag block and the config switch — machine flags must stay above it, since --json --styled resolves JSON-first in ApplyFlags and the predicate mirrors that ordering.

Deliberately not delegated to EffectiveFormat(). That would also pull in FormatAuto-on-a-pipe (EffectiveFormat()==FormatJSON where IsMachineOutput() is false today), flipping upgrade stdout→stderr, attachment progress, the skill-update nudge, and quickstart/skill/wizard gating for every basecamp foo | grep. It would also be order-sensitive: the existing TestIsMachineOutput* tables never call ApplyFlags, so every row would read the writer's JSON default and pass vacuously.

Callers whose behavior changes

Only when an explicit --styled/--md overrides a configured json/quiet — all flip toward "treat as human", which is what the flag asked for:

  • shouldIncludeStatsInError / shouldPrintStatsToStderr (context.go)
  • root post-run notices (root.go:207,221)
  • attachment progress (attachments.go)
  • quickstart.go routing, skill.go dump→picker (still TTY-gated), upgrade.go
  • the setup/wizard gate (wizardCanRun, setupCanRun after Streamline first-time setup with recommended defaults #660)

humanFormatOverride in chat.go stays — the breadcrumb must still carry the flag for the future invocation it suggests.

Tests

  • New table in context_test.go: --styled over config json and --md over config quiet → not machine; config json alone and --json --styled → machine. Existing rows unchanged.
  • TestMachinePredicatesAgree in internal/commands: the regression net for "these must not drift again" — every flag×config combination asserts app.IsMachineOutput() == machineReadsThisOutput(cmd), with all three stdio streams pinned to pipes and the precondition asserted. The one deliberate divergence (FormatAuto on a pipe) is asserted as a divergence rather than skipped, so a change to either side of it shows up.
  • Mutation-checked: deleting the clause fails exactly the six new rows and nothing else; TestChatDeleteConfirmationMatrix passes with and without.

Note: #660 also touches wizard.go (renames the gate to setupCanRun and moves its doc comment). The comment amendment here will need a trivial rebase whichever lands second.

bin/ci green.


Summary by cubic

Makes IsMachineOutput honor explicit --styled/--md flags, so an invocation that overrides a configured json/quiet format is treated as human by all gates instead of being routed as machine while rendering human.

Behavior changes

  • All callers that consulted IsMachineOutput now flip to human for --styled/--md over machine config, covering error stats, post-run notices, attachment progress, quickstart/skill/upgrade routing, and wizard gating.
  • Machine flags (--json, --quiet, etc.) still win over style flags, matching ApplyFlags ordering.

Testing

  • Adds a table test covering the override behavior and a TestMachinePredicatesAgree regression net that asserts the full flag×config matrix against the renderer, with the one deliberate FormatAuto-on-pipe divergence enforced explicitly.

Written for commit 1f415ec. Summary will update on new commits.

Review in cubic

ApplyFlags lets --styled and --md rebuild the writer over a configured
json/quiet format, but IsMachineOutput never read those flags — so
`basecamp --styled <cmd>` on a format=json machine was human to the
renderer and machine to every gate. That split surfaced as the declined
review thread on #654: chat delete demanded --force for an invocation
whose confirmation a person could see and answer, and chat.go grew
humanFormatOverride to state the rule at one call site because the
predicate couldn't.

The clause sits between the machine-flag block and the config switch,
mirroring ApplyFlags' ordering: --json --styled resolves JSON-first
there, so machine flags still win here.

Deliberately not delegated to EffectiveFormat(): that would also pull in
FormatAuto-on-a-pipe, flipping upgrade's stdout, attachment progress,
the skill-update nudge, and quickstart/wizard gating for every
`basecamp foo | grep`. TestMachinePredicatesAgree pins the whole
flag/config matrix against machineReadsThisOutput, asserting that one
divergence explicitly instead of skipping it.
Copilot AI balanced review requested due to automatic review settings August 31, 2026 09:26
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 31, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-31T09:29:20.795563Z 1f415ec PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions github-actions Bot added commands CLI command implementations tests Tests (unit and e2e) labels Aug 31, 2026

Copilot AI 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.

Pull request overview

Aligns machine-output detection with explicit human-format flags and renderer precedence.

Changes:

  • Treats --styled/--md as overriding configured JSON/quiet output.
  • Adds unit and predicate-consistency coverage.
  • Updates wizard test documentation.

Tip

If you aren't ready for review, convert to a draft PR.
Click "Convert to draft" or run gh pr ready --undo.
Click "Ready for review" or run gh pr ready to reengage.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated no comments.

Show a summary per file
File Description
internal/appctx/context.go Adds human-format override handling.
internal/appctx/context_test.go Tests format precedence.
internal/commands/helpers_test.go Adds predicate consistency matrix.
internal/commands/wizard.go Clarifies gate documentation.
internal/commands/wizard_test.go Clarifies test documentation.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@jeremy
jeremy merged commit e68ce1d into main Aug 31, 2026
26 checks passed
@jeremy
jeremy deleted the machine-output-honors-style-flags branch August 31, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

commands CLI command implementations tests Tests (unit and e2e)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants