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.
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user