= SRC TODO list
// SPDX-FileCopyrightText: Copyright Eric S. Raymond <esr@thyrsus.com>
// SPDX-License-Identifier: CC-BY-4.0

* Eliminate 'L' status, turning it to '=' and automatically checking
  out the file when required.

ChatGPT-5.2 suggested these UI changes:

1. Introduce a --dry-run and --yes pattern For anything that mutates
   history, a default preview would build trust. --yes keeps scripts
   fast.

2. More actionable errors.  Wrap backend tool failures with a short
   explanation and what to try next. Example: “SCCS rmdel failed:
   likely locked or not tip; run src checkout first.”

3. Safer revision‑spec parsing. When a token ambiguously looks like a
   file, offer a hint: “If this is a file, use --.” You already do
   this in some places; make it universal.

4. Improve default output consistency. Ensure all commands emit
   consistent prefixes/headers so piping to tools is easier and users
   can recognize patterns quickly.

It further extracts these design rules, which could be followed more strictly:

Here is a compact design rule set that matches the direction src already seems to be taking.

  Core Rules

  1. src is file-oriented by default.
     Commands operate on explicitly named files unless the command is inherently repository/report
     scoped.
  2. Reporting commands may infer scope.
     Commands like status, list, log, ls, help, version may default to current file set, branch, or
     repository scope.
  3. Mutating commands must require explicit targets.
     If a command changes history, working copy state, names, tags, branches, or file placement, it
     must require explicit file arguments unless it is explicitly repo-wide by design.
  4. stdout is for payload, stderr is for commentary.
     Human-readable reports and machine-readable data go to stdout. Notices, selections, warnings,
     and errors go to stderr.
  5. Every command should have one stable mental model.
     A command should be clearly one of:

  - report
  - content emitter
  - mutator
  - admin/meta

  If a command straddles categories, the UI should make that explicit with options rather than
  implicit defaults.

  Scope Rules

  1. Empty file arguments mean “all files” only for report commands.
     Never for destructive or state-changing commands.
  2. Revision specs may default; file specs may not for mutators.
     It is fine for checkout foo to imply “tip of foo”.
     It is not fine for checkout to imply “tip of everything”.
  3. Repo-wide actions should be explicit in the command design.
     If you ever want a mutator to work repo-wide, that should be a dedicated option like --all, not
     silent defaulting.

  Output Rules

  1. Human output should be readable without decoration-dependent parsing.
     Avoid width-sensitive banners except where they add real value.
  2. Machine output should be a first-class interface.
     -P should mean:

  - no color
  - no padding
  - no banners
  - stable field order
  - escaped separators/newlines
  - one record per line unless documented otherwise

  3. Similar commands should emit similar shapes.
     If list -P and log -P are both record streams, their first fields should line up where
     practical:

  - file
  - revision
  - date
  - mode-specific fields

  4. Notices should never contaminate pipelines.
     Anything like src: .src is selected. belongs on stderr.

  Argument Rules

  1. Short options should preserve established Unix meaning where possible.
     Avoid reclaiming common options once published.
  2. Shared verbs should share shared options.
     If -l means limit in one history-report command, it should mean limit in the adjacent ones too.
  3. Hidden parser cleverness should be minimized.
     Convenient syntax is fine, but only if users can predict it from help text.

  Error Message Rules

  1. Errors should say what was missing, not just what was invalid.
     Good: checkout requires at least one file argument
     Less good: bad arguments
  2. Errors should preserve the command noun.
     tag deletion requires at least one file argument is better than a generic parser complaint.
  3. Errors should suggest recovery when there is an obvious next step.
     You already do this well in some places; keep that pattern.

  A Simple Test
  For any command, a user should be able to answer these questions without reading code:

  1. Does it read, emit, or mutate?
  2. If I omit files, what happens?
  3. If I pipe it, will I get only payload?
  4. Is there a stable machine-readable mode?
  5. Does its behavior match neighboring commands?

  If you apply these rules consistently, the UI will feel much more intentional and the remaining
  TODO items will likely collapse into smaller, local fixes rather
  than policy debates.

Here’s the highest-value change list, ordered roughly by impact.

  Output Contract

  - Move announce() to stderr so pipelines only receive payload.
  - Audit all non-error chatter and route it through one stderr-only notice path.
  - Add a tiny shared output layer for human headers and porcelain records instead of open-coded
    sys.stdout.write() patterns.
  - Normalize multi-file human report headers across list, log, tag list, and branch list.

  Scope Policy

  - Add an explicit default_files=False policy to every mutating command, not just the ones fixed so
    far.
  - Review release, rename, tag create, and branch create/delete against the “mutators require
    explicit file args” rule.
  - If any mutator should support repo-wide behavior, require --all rather than empty args.

  Porcelain

  - Extend -P to other structured-report commands, especially status, tag list, and branch list.
  - Define and document a stable field order for every porcelain command.
  - Keep first fields aligned where possible: file, revision, date, then command-specific fields.
  - Ensure all porcelain output is single-record-per-line with escaping rules centralized in one
    helper.

  Parser Simplification

  - Split CommandContext policy from parsing.
    Right now it parses revspecs, infers files, and applies safety policy. That should become:
      - syntax parsing
      - default-scope expansion
      - command policy
  - Replace hidden defaults with explicit flags like default_files, allow_empty_files,
    default_revision.
  - Add a small command classification table: report, content, mutator, admin. Use it to drive
    defaults consistently.

  CLI Consistency

  - Audit option meanings across neighboring commands and normalize them.
  - Preserve -p/-u/-c semantics for patch/diff commands, keep -P reserved for porcelain everywhere.
  - Make sure -l always means limit where a record stream is produced.
  - Avoid command-specific special parsing unless it is documented in help text and manpage.

  Error Messages

  - Standardize missing-target errors:
      - X requires at least one file argument
      - X requires explicit source and target file arguments
      - X deletion requires at least one file argument
  - Prefer action-oriented recovery hints where obvious:
      - checkout tip first
      - use --all if you really mean every file if you add that mode
  - Make parser errors preserve command intent instead of surfacing generic context errors.

  Docs

  - Add a short “Interface Conventions” section to src.adoc:
      - report vs mutator commands
      - stdout vs stderr contract
      - -P porcelain contract
      - empty-file-argument policy
  - Update per-command help to explicitly say whether omitted file args are allowed.
  - Document porcelain formats in one place rather than only inside command blurbs.

  Tests

  - Add regression tests for every mutator's empty-file rejection.
  - Add golden tests proving notices do not appear on stdout.
  - Add porcelain tests for every supported command and ensure they are color-free and banner-free.
  - Add tests for stderr/stdout separation on mixed-behavior commands.

  Small Cleanup

  - Replace remaining ad hoc sys.stdout.write() formatting blocks with helpers.
  - Reduce width-dependent formatting in human output where it doesn’t add much.
  - Consider making decorative banners optional or limited to human report mode only.
