ID

R720

Status

Backlog

Bucket

cleanup

Priority

4

Theme

routine

Created

2026-08-18

Updated

2026-08-18

Three routine read-surface residues: prose naming the directive, a non-discriminating order pin, and a misfiled rejection

Three small residues from the @routine read-surface work, filed together because they are one mistake told three ways: a claim about the binding written as a claim about the directive that used to be the only way to state it. None is a defect a build catches, and none was worth holding that item’s Done gate.

Prose naming the directive where the code holds the binding. A routine’s result now binds its return type, so a chain’s landing is table-bound whether or not the author wrote @table. Four places still say @table: QueryField.java’s `QueryTableField javadoc ("terminates on the field’s @table return type"), the terminus-invariant comment above the same record’s compact constructor, that invariant’s own throw message ("the field’s @table type is bound to …​"), and RoutineResolution.java’s interface javadoc ("the chain’s terminus is the field’s `@table type"). The record component is ReturnTypeRef.TableBoundReturnType in every case, which is the binding. An author who took the directive removal up and then hits the terminus invariant reads a message about a directive their schema does not carry. This is the same sweep that repointed isDirectivelessNestingTarget, the producing-edge registration and GraphitronSchemaBuilder.unsupportedFacetCarrierReason, run over the prose the code left behind.

A rejection message forked on the wrong question. RoutineDirectiveResolver.bindReturn picks its message by hasAppliedDirective(DIR_REFERENCE), and tells anything carrying @reference that "the chain lands on a catalog table and the return type must name it". A hops-then-routine chain carries @reference and lands on the routine’s own result, which is exactly the shape the return grounding covers, so on the narrow path where that chain’s return is unbindable anyway (a scalar, an interface, a union) the author is told the wrong thing about where their chain lands. The fork wants to ask where the chain ends, which is whether the last application is the @routine, the same question RecordBindingResolver.groundRoutineReturnType asks one layer up.

An execution-tier order assertion that passes either way. RoutineFieldExecutionTest.routineTerminusListOrdersByItsAuthoredDefaultOrder is the test named for the reported bug, and it does not discriminate against it. The fixture function returns (184, 'admin'), (185, 'user') from a literal VALUES set in init.sql, and the field’s @defaultOrder is ascending over those same two columns, so the asserted row order is the order the function body produces and a dropped ORDER BY passes. The behaviour is genuinely pinned elsewhere, by the DESC arm of orderByArgumentSortsTheRoutineResultBothWays and by the executed ORDER BY in `RootLauncherSqlBaselineTest’s routine baselines, so this is a weak test rather than a coverage hole. Give the fixture an order the function’s own row order contradicts, so the assertion fails when the clause goes missing.