# fieldtest — canonical-type-names

**Date:** 2026-05-11
**Branch:** main (orchestrator-direct dispatch; the or.1 branch-per-iter rule lands on the *next* implement run)
**Status:** DONE_WITH_CONCERNS
**Examples:** 5 of 5 authored + committed
**Findings:** 9 (4 working, 4 friction, 1 spec_gap, 0 bugs)

## Summary

Standard skill-pipeline step after audit cleanly closed
canonical-type-names. The fieldtester wrote five `.ailx` examples
that exercise the milestone surface — one happy-path exhibit and
four diagnostic-triggers, one per new diagnostic plus a second
branch of the merged BadCrossModuleTypeRef case. Spec at
`docs/specs/2026-05-11-fieldtest-canonical-type-names.md`; fixtures
under `examples/ct_*`.

All four milestone-scoped findings landed as **working**: the new
diagnostics fire on the LLM-natural authoring mistakes, the
diagnostics carry actionable recipes (BareCrossModuleTypeRef lists
import candidates + names the migration tool), and Form-A
round-tripping stays byte-stable across cross-module type refs.

One milestone-internal friction: `BadCrossModuleTypeRef` collapses
two distinguishable cases (unknown owner vs. known owner / unknown
type name) into one diagnostic shape. A future tidy iter can split
these and, in the known-owner branch, list the available type names
the way `bare-cross-module-type-ref` lists candidates from imports.

Three orthogonal friction items surfaced as pre-existing UX gaps
that every fieldtest invocation will keep tripping on:

- Workspace search confined to the entry module's directory — no
  way to organise fieldtest fixtures under
  `examples/fieldtest/` while still importing prelude or std.
- `ail check foo.ailx` returns a misleading JSON-parse error
  instead of either auto-parsing `.ailx` or pointing to `ail parse`.
- `(import prelude)` is rejected with a clear diagnostic but no
  corpus example warns the author that prelude is auto-injected.

One spec_gap: the canonical happy-path exhibit shipped with this
milestone (`examples/compare_primitives_smoke.ail.json`) exists
only as JSON. Decision 6 makes Surface the LLM-author surface; the
milestone should ship a `.ailx` counterpart (or retire the JSON
fixture in favour of `ct_1_ordering_signum.{ailx,ail.json}`).

## Routing

| Finding | Class | Action |
|---|---|---|
| BareCrossModuleTypeRef recipe + JSON ctx | working | carry-on |
| BadCrossModuleTypeRef catches Surface | working | carry-on |
| QualifiedClassName fires on `(class prelude.Eq)` | working | carry-on |
| Form-A round-trip byte-stable | working | carry-on |
| BadCrossModuleTypeRef merges two cases | friction | roadmap P2 |
| Workspace search confined to entry dir | friction | roadmap P2 |
| `ail check` on `.ailx` misleading | friction | roadmap P2 |
| `(import prelude)` corpus doc gap | friction | carry-on (one-line DESIGN.md hint sufficient) |
| No `.ailx` for `compare_primitives_smoke.ail.json` | spec_gap | roadmap P3 |

No bug findings, so no debug dispatch. The five `.ailx` fixtures
stay in the corpus as live exhibits.

## Lesson — orthogonal UX gaps surface together

Three of four friction items are orthogonal to canonical-type-names
proper. They predate the milestone. None would have surfaced in a
brainstorm or planner pass because none touches the milestone's
substance. Fieldtest's role IS to surface this kind of cross-cutting
UX debt — DESIGN.md does not mention `.ailx` extension handling,
workspace-root flags, or the prelude doc-gap, but every downstream
LLM author trips on them within ten minutes of writing their first
program. The roadmap entries below are the persistent backlog this
fieldtest produced.
