Files
msd-core/tests
Tom Boucher 6214039358 refactor(#1644): Hub extension — exitReason? field on InvalidArgs + adapter honestification (#1645)
Phase 1 of parent #1641. Implements the contract documented in the
Phase 0 ADR-0174 §5 amendment (#1642 / #1643).

src/command-routing-hub.cts
  * InvalidArgsResult interface gains optional exitReason?: string
    (carries an ERROR_REASON enum value, separate from reason which is
    the explanation text).
  * makeInvalidArgs(arg, reason, exitReason?) factory conditionally adds
    the field only when the third arg is truthy — preserves the strict-
    keys invariant tested at command-routing-hub.test.cjs:444.
  * _VARIANT_SCHEMA.InvalidArgs.allowed Set extended to include
    'exitReason' so the runtime validator does not coerce well-formed
    extended Results to HandlerFailure.

src/cjs-command-router-adapter.cts
  * Honestified the wrapper comment: the runtime check ('ok' in result)
    already passes any {ok:*} object through, so the historical
    {ok:true, data} return type was a lie for err Results. The lying
    cast is preserved because the Hub's export = syntax doesn't expose
    HubResult for import; the Hub's _validateErrResult runtime-validates
    the actual shape.
  * Result→error() translation branched: when InvalidArgs carries
    exitReason, the adapter calls error(result.reason, result.exitReason)
    so the JSON-error envelope (GSD_JSON_ERRORS=1) preserves the typed
    ERROR_REASON value. When exitReason is absent, error(msg) is called
    with exactly one arg — byte-identical with prior behavior.
  * RouteCjsCommandFamilyOptions.error and RouteHubCommandFamilyOptions
    .error callback types widened from (message) to (message, reason?)
    to match io.cts's actual error() signature.

CONTEXT.md
  * Command Routing Hub predicate updated to document the new field,
    factory signature, and dispatcher translation contract.

Tests (TDD red→green)
  * tests/command-routing-hub.test.cjs: 8 new tests covering 2-arg
    (strict-keys), 3-arg (key present), undefined, empty string, frozen
    result, hub.dispatch propagation, and validator acceptance.
  * tests/cjs-command-router-adapter.test.cjs: 2 new tests covering
    exitReason passed as second arg + byte-identical prior behavior when
    absent.

Verification
  * npm run test:unit: 2448 tests, 0 fail (no regressions)
  * gsd-test-summary on docker: outcome=passed, 0 failures
    (RULESET.PR-FLOW.docker-before-push)

Memtrace blast radius: LOW (get_impact makeInvalidArgs → 3 nodes; the
optional field is non-breaking for the 1 existing caller routePhaseCommand).
2026-06-23 22:47:57 -04:00
..