Skip to content

The no-direct-stdout walk misses writers that are stdout by another name: cmd.OutOrStdout() #794

Closed

Description

@David-Noble-at-work

Feature: #832 — The shared root: one root, the common set, and its enforcement

NoDirectStdout (cmd/internal/cli/invariants.go, #776) reports fmt.Print*, fmt.Fprint* aimed at
os.Stdout, os.Stdout.Write*, the print builtins, and any handoff of os.Stdout. It never considered
cmd.OutOrStdout(), which is stdout by another name, so fmt.Fprintf(cmd.OutOrStdout(), ...) passes the
walk and bypasses the pipeline just the same. Seen 2026-09-04 on a Windows test machine:

PS> writ repo list
base     -> C:\Users\david-noble\.local\share\devlore\writ\repos\base

Hand-shaped text where the convention says a json result. Four sites in scope reach stdout this way:
cmd/writ/writ/repo_cmd.go at 153, 299 and 312 (repo add, repo remove, repo list), and the shared
cmd/internal/cli/version.go:61. cmd/writ/writ/migrate/format.go:139 writes to a writer whose origin the
walk should trace too.

The rule that closes it: cmd.OutOrStdout() is called in cli.Emit and nowhere else. Every result
reaches stdout through the pipeline, and the pipeline is the one caller that needs the writer. The walk
reports any other call, and a fixture shows it red.

Acceptance

Found on a Windows test of writ repo list. Its own worktree.

Metadata

Metadata

Labels

Area:CLICommand-line interfaceEpic:CommandLineOne output convention across every CLI in the suitebugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions