Skip to content

CLI consistency sweep: exit-code classes, silent check --json, build defaults and target list, patch no-op and read-only writes, wording #40

Closed

Description

@wsdt

Summary

Command-surface inconsistencies found by a QA sweep of every command across 12 example projects, 11 operand spellings, and the error-handling matrix on semaprax 0.3.0 (main 5c6e7a4b). Each item is small and independent; together they make the CLI unpredictable for scripts and agents. Data-loss items, the path-component rejection, the patch argument laxity and context on while are filed separately.

Exit codes and diagnostics

  1. test <nonexistent> exits 2 (usage) with test requires a Project v1 semaprax.toml manifest, while check/run/lock on the same operand exit 1 with SPX-I001/SPX-J102. A missing path is not a grammar error. src/cli/execution.rs ~96-104.
  2. check --json prints nothing on success (human form prints verified …). Automation cannot distinguish success from silence; emit {"status":"verified","revision":…} or the same line as the human form. Same for project check --json.
  3. lock and resolve usage errors print the hint: line twice: the usage() helpers in src/cli/project_lock.rs ~241 and src/cli/resolve.rs ~345 embed a hint and help::finish appends the generic one.
  4. fmt rejects flag-first order: fmt --check semaprax.toml → unknown fmt option --check, while check --json semaprax.toml is accepted; bare fmt --check reports the missing operand as an unknown option. src/cli/fmt.rs ~30-40.
  5. --max-steps bounds are three different error classes: 0 → exit 2 usage, 100000001 → SPX-F101 exit 1, -1 → "requires a value". Pick one.
  6. native-callable -o <bare-name> fails with SPX-I107: cannot canonicalize native-callable output parent : No such file or directory (empty parent), while -o ./bare works: Path::new("bare").parent() is Some(""), so the unwrap_or_else(|| Path::new(".")) fallback never fires. src/codegen/native_callable_bundle.rs ~288.
  7. Missing-main diagnostic always says "entry module" (even for the test module), carries "path":null, and SPX-G172 is reused for cycles, unknown identities, duplicate @id, missing module, missing main, permit mismatches and profile exclusions. Split the code or at least make each message name its cause; the permit-list mismatch currently reads "module is outside the pure scalar linker profile".
  8. Project test counts are inconsistent: failure says 1 of 4 in <module> (counts main), success says passed (3 named cases).
  9. fmt --check names no line for a drifting file (… is not canonically formatted), while the manifest checker prints the first differing line; and fmt joins a five-line match into one 230-character line (canonical, but worth a documented rule).
  10. Wording: patch <file> with a missing patch operand says missing file path; help all extra → unknown command help; resolve --target bogus is never validated (reports SPX-J126 about [dependencies] instead); new . → "final component is not UTF-8" (it is UTF-8; the name simply cannot be derived).

Build command

  1. build --target bogus on a project lists rust (then refused as unavailable in the standalone package) and omits native-callable, contradicting help build; derive the list from the catalog for the capability class. src/cli/build.rs ~409-414.
  2. --target wasm is byte-identical to --target web and both print built … web package; -o dist/app.wasm therefore creates a directory named app.wasm. Either document the alias or make wasm emit only app.wasm.
  3. build without --target silently builds web; without -o it writes <name>-web/<name>-out/<name>-npm into the project root, or <stem>.out beside a single source file. No help or doc mentions the defaults. Document [-o path] (default …) or require -o.
  4. --output is an undocumented alias of -o (src/cli/build.rs ~323).
  5. Profile projects report SPX-W120 cannot create fresh npm package destination for --target web; parametrise message and code by target (src/project/npm).
  6. build --json is rejected (exit 2) although check --json and test --json exist.
  7. Two concurrent project native builds into the same -o both exit 0 (last writer wins) while web/npm close the window with SPX-I307/SPX-W120; documented as a non-claim, but the asymmetry is surprising.

Patch, run, context

  1. patch applies a no-op rename (rename math.add to add when it is already add) with exit 0 on the single-file route, contradicting docs/SEMANTIC-PATCH-V2.md (SPX-G106 covers no-op edits); the workspace route rejects with SPX-G153. Apply the check from src/patch.rs (~1320 / ~2823) on the single-file route.
  2. patch rewrites a 0444 read-only source via stage+rename and keeps the mode; fmt on the same file correctly refuses. Probe writability first and report an SPX-I205-class error.
  3. run <file> --json is rejected ("legacy single-file run accepts exactly semaprax run <file>") while check <file> --json works.
  4. run on a command-profile project runs main, not the command, and prints nothing about it; print a note naming the command function and the adapters that exercise it.
  5. context --max-bytes admits 1024 but every value below ~1300 fails SPX-G004 … cannot contain the canonical envelope; the admitted range message should start at the smallest value that can succeed, or the envelope should truncate.
  6. fmt accepts symlinked sources, manifests and project directories that every other project command rejects (SPX-J102) and writes through the link. Documented, but fmt . rewrites what check . refuses to read.

Verification

Each item has a one-command reproducer above. Add regression cases in the harness that owns each command (tests/cli_help_surface_v1.rs tree for grammar, tests/project.rs tree for project commands) and update docs/CLI-GUIDE.md, docs/CLI-HELP-V4.md (if the grammar text changes) and CHANGELOG.md.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions