Polish construction error/bind ergonomics — by-identifier finalize, prose bind-mismatch, discoverable bind form #162
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
The cycle-0088 fieldtest (
fieldtests/cycle-0088-construction-op-script/FINDINGS.md) confirmed the construction op-script surface (#157) authors cleanly by-identifier, but three error/bind presentation defects break that register at the edges. All three are message-quality only -- the faults are correctly detected and exit non-zero.1. The holistic
finalizeerror speaks raw machine indicesaura graph build < c0088_2_partial.jsonprints:The sibling
introspect --unwiredreports the same open slot by-identifier assub.rhs:F64, so the identifier mapping demonstrably exists at finalize time. The build finalize path drops to the rawnode/slotindex Debug form, forcing the author to count nodes (0=fast, 1=slow, 2=sub) to decode it. Route finalize faults through the same by-identifier formatter--unwiredalready uses.2. Bind-kind-mismatch leaks the
#[derive(Debug)]structaura graph build < c0088_3g_bad_bind_kind.jsonprints:The parallel connect-mismatch is hand-phrased prose (
producer Bool, consumer F64). Two kind-mismatch errors, two registers -- phrase the bind mismatch like the connect one.3. The typed-Scalar bind form is not discoverable
introspect --node SMAshowsparam length:I64but never that a bind value is wrapped{"I64": 2}. The natural first guess"bind":{"length":2}fails with a generic serde error (invalid type: integer 2, expected string or map) carrying no domain hint about the{"I64": <v>}shape. Show the bind-value form inintrospect --node(e.g.param length:I64 (bind {"I64": <v>})) or hint it in the serde error. (Capitalizedkindis already discoverable, both fromintrospect --nodeand the self-documenting lowercase-kind error.)Source: cycle-0088 fieldtest. Low-urgency polish on a shipped surface; the happy path and eager per-op diagnostics already read well.
Design decisions (boss run — spec production for this issue)
Two derived forks, recorded before the spec is written.
Fork: where to translate the raw node/slot/role index into the by-identifier form for a finalize fault. → Derived: in
GraphSession::finish()(crates/aura-engine/src/construction.rs), not in the CLI presenter. Rationale: the construction layer owns the id↔name map (ids,schemas, the composite'sinput_roles()); the engineOpErroralready carries by-identifier data for every other variant and the CLI'sformat_op_erroris a thin presenter over that data — doing the translation infinish()keeps that split intact, whereas threading the name map into the CLI would invert it. The holistic gates (validate_wiring,check_param_namespace_injective,check_root_roles_bound) stay byte-for-byte unchanged; onlyfinish()'s wrapping of theirCompileErrorchanges.Fork: which finalize faults to map by-identifier. → Derived: the three index-carrying holistic faults reachable on a well-formed-but-incomplete authored op-list —
UnconnectedPort { node, slot }(the observedsub.rhstotality case),RoleKindMismatch { role }(reachable —feeddoes not eager-check the fanned-in slot kinds, construction.rs feed() only resolves + coverage-checks), andUnboundRootRole { role }(anInputrole left unbound at the root). Each becomes a new by-identifierOpErrorvariant carryingStringids. The remainingCompileErrorcases stayOpError::Incomplete:DoubleWiredPortis caught eagerly bycover()/feed(SlotAlreadyWired), so it is unreachable at finish;DuplicateParamPathalready carries a by-identifier path string;BadInteriorIndex/OutputPortOutOfRange/Bootstrapare construction-internal inconsistencies a validly-replayed op-list does not produce (and carry no per-node identifier). Net validity-floor statement: after this change, every finalize fault a hand-author can actually trigger reads by-identifier.Items 2 (bind-mismatch prose) and 3 (discoverable bind form) are CLI-presenter-only changes in
graph_construct.rswith no fork.