Files
AILang/docs/journals/2026-05-14-iter-cli-diag-human.md
T
Brummel f08ba2bb36 iter cli-diag-human: route WorkspaceLoadError through diagnostic in non-JSON path
Closes P2 todo "CLI human-mode diagnostic surface for
WorkspaceLoadError" surfaced by ct.1.8 tester (2026-05-11).
Pre-iter, non-JSON `ail check` (+8 sibling subcommands) propagated
loader errors via anyhow's Display, producing
`Error: <message>` without the bracketed `[code]` prefix the JSON
path emits.

Fix: new private helper `load_workspace_human(path)` in
crates/ail/src/main.rs that wraps ailang_surface::load_workspace,
threads any WorkspaceLoadError through workspace_error_to_diagnostic,
formats the resulting Diagnostic into a single stderr line
`error: [<code>] <def>: <message>`, and exits non-zero. Pure I/O
errors still propagate as anyhow errors.

Nine call sites swapped to the helper (check non-JSON arm, build,
run, emit-ir, prose, describe, deps, diff, manifest). The JSON arm
of `ail check` keeps its explicit `match` — different output
contract (structured stdout array).

The BareCrossModuleTypeRef Diagnostic message gained the existing
migration-command hint ("Run `ail migrate-canonical-types` to fix
legacy fixtures.") so the ct.1.8 actionable-hint test stays green.
The hint previously rode on WorkspaceLoadError's thiserror Display;
making workspace_error_to_diagnostic the single source for both
JSON and human paths required moving it into the Diagnostic body.

RED test crates/ail/tests/cli_diag_human_workspace_load_error.rs
pins the bracketed-code surface on a missing-import workspace
(tempdir-based fixture; no committed corpus addition).

cargo test --workspace: 565/0/3. clippy + doc: zero warnings.
Roadmap entry struck.
2026-05-14 02:26:46 +02:00

2.9 KiB

iter cli-diag-human — non-JSON CLI surfaces WorkspaceLoadError with bracketed [code]

Date: 2026-05-14 Started from: 6755060 (post-rpe.1.tidy) Status: DONE

Summary

Closes the P2 todo "CLI human-mode diagnostic surface for WorkspaceLoadError" surfaced by the ct.1.8 tester (2026-05-11). Pre-iter, the non-JSON path of every CLI subcommand that called ailang_surface::load_workspace(&path)? propagated the error via anyhow's Display — producing Error: <thiserror-formatted-message> on stderr — while the JSON path of ail check --json correctly routed through workspace_error_to_diagnostic and emitted the bracketed [code] prefix. The asymmetry made the human-mode output harder to triage and less consistent across the toolchain.

Fix: new private helper load_workspace_human(path) -> Result<Workspace> in crates/ail/src/main.rs that wraps ailang_surface::load_workspace, threads any WorkspaceLoadError through the existing workspace_error_to_diagnostic, formats the resulting Diagnostic into a single stderr line of shape error: [<code>] <def>: <message>, and exits non-zero. Pure I/O errors (where workspace_error_to_diagnostic returns None per the loader's own contract) still propagate as anyhow errors so the caller's ?-flow stays well-behaved.

Nine call sites in main.rs swapped from ailang_surface::load_workspace(<expr>)? to load_workspace_human(<expr>)?: the ail check (non-JSON arm), build, run, emit-ir, prose, describe, deps, diff, manifest paths. The JSON arm of ail check (line 596) kept its explicit match shape — it builds a structured diagnostics array on stdout, which is a different output contract.

The BareCrossModuleTypeRef arm of workspace_error_to_diagnostic gained the existing migration-command hint ("Run ail migrate-canonical-types to fix legacy fixtures.") so that the ct.1.8 actionable-hint test (check_human_mode_emits_actionable_message_to_stderr) stays green. The hint was previously carried by WorkspaceLoadError's thiserror Display impl; making workspace_error_to_diagnostic the single source for both JSON and human paths required moving it into the Diagnostic message body.

Files touched

  • crates/ail/src/main.rs — new load_workspace_human helper (~25 lines, including doc comment); 9 call-site swaps; one Diagnostic message gained the migration-hint suffix.
  • crates/ail/tests/cli_diag_human_workspace_load_error.rs — new RED-pin test (tempdir-based fixture asserting [module-not-found] in stderr on a missing-import workspace).
  • docs/roadmap.md — entry struck through.

Verification

  • RED test check_non_json_emits_bracketed_module_not_found flipped from RED to GREEN.
  • cargo test --workspace → 565 / 0 / 3 (was 564 pre-iter; +1 from this iter's RED pin).
  • cargo clippy --workspace --all-targets → 0 warnings.
  • cargo doc --workspace --no-deps → 0 warnings.

Concerns

  • (none)

Known debt

  • (none)