Skip to content

test(#754): pin the missing no-holder-fallback regression + comment cleanup - #819

Merged
Weegy merged 2 commits into
mainfrom
feat/754-role-holder-resolver
Aug 21, 2026
Merged

test(#754): pin the missing no-holder-fallback regression + comment cleanup#819
Weegy merged 2 commits into
mainfrom
feat/754-role-holder-resolver

Conversation

@Weegy

@Weegy Weegy commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Summary

Closes #754. The scope was almost entirely already delivered by #333 Phase 3 (PR #726) — this PR
finds and fills the one gap: the second mandatory regression test the issue calls out, plus a
stale comment.

What #726 already shipped (verified, not re-designed)

  • middleware/packages/harness-channel-sdk/src/roleHolderSource.tsRoleHolderSource,
    RoleHolderRegistry, AggregateHolderLookup with the resolved | unavailable + partial
    discipline the issue requires (never a bare string[]).
  • middleware/src/conductor/roleHolderResolver.ts — wires ConductorRoleStore in as the
    'conductor-local' source, buildRoleHolderRegistry(), and holdersOnly() for the
    call sites that may legitimately degrade (operator inbox, reminder nudger).
  • middleware/src/conductor/index.ts — already builds the registry
    (buildRoleHolderRegistry(roleStore, deps.roleHolderSources ?? [])) and threads it into both
    RunExecutor (resolveRoleHolders) and the await worker (holdersOnly(...)).
  • middleware/src/conductor/runExecutor.ts:
    • resolveAwait's quorum='all' completeness check already refuses to close on a partial
      holder list, even if every currently-known holder responded.
    • openHumanAwait's "role has no holder → take the fallback" already only fires on a
      resolved-empty lookup; a partial-empty lookup parks instead (the run reaches the same
      fallback later via its deadline, but only after the real holders had a chance to answer).

I verified this by reading roleHolderResolver.ts/runExecutor.ts end to end before touching
anything — the "check whether wiring is the entire remaining scope" the issue asks for. It is.

What was missing

Of the issue's two mandatory regression tests:

  1. quorum='all' non-completion on partial/unavailablealready existed
    (conductorQuorumAndTimeout.test.ts:127, from feat(#333): role sources + pluggable role→holder resolution (phases 2 and 3) #726), with a same-inputs partial:false
    control right below it.
  2. "no holder → fallback" firing only on resolved-empty, never on unavailablehad no
    test
    . openHumanAwait's fail-closed branch was implemented but unexercised.

Added the missing pair in middleware/test/conductorQuorumAndTimeout.test.ts (new describe
block, same minimal-fake-harness pattern as the existing quorum tests, driven through the public
ConductorRunExecutor.startRun):

  • a RESOLVED empty holder list takes the fallback path — records the step 'failed' with
    actor: { kind: 'human', noHolder: true }, opens zero awaits.
  • an UNAVAILABLE (partial) holder lookup does not take the fallback — it parks (opens an
    await, calls runStore.park) exactly as if a real, not-yet-answered holder existed.

Also updated the roleStore.ts:22 comment (issue requirement #5): it still described the
external-resolver seam as future work after #726 had already filled it.

Blast radius

  • middleware/src/conductor/roleStore.ts — comment-only change (no behavior change).
  • middleware/test/conductorQuorumAndTimeout.test.ts — additive; no existing test modified.
  • No production code paths changed. No migration needed — no schema change.
  • Untouched (per scope guardrails): credentials/ namespaces, src/index.ts.

Test + mutation evidence

  • npx tsx --test test/conductorQuorumAndTimeout.test.ts — 9/9 pass (4 suites).
  • npx tsx --test test/conductor*.ts (full conductor suite) — 229/229 pass (58 suites).
  • npx tsx --test test/roleHolderSource.test.ts test/roleSource.test.ts test/conductorCancelAndStrictApproval.test.ts test/conductorReminders.test.ts test/conductorRunExecutorNotifyRunEnded.test.ts — 59/59 pass.
  • npm run build — clean.
  • npm run typecheck:test — ratchet unchanged (371 known errors, baseline 371, no regressions).
  • Mutation check: reverted each fail-closed guard in runExecutor.ts one at a time against a
    clean rebuild —

Open questions

None — the scope really was "wiring is already the entire remaining work," confirmed before
writing anything new, per the issue's own instruction.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Weegy added 2 commits August 21, 2026 09:44
…r resolver must never reintroduce

#333 Phase 3 (#726) already delivered the full seam this issue describes: RoleHolderSource /
RoleHolderRegistry (harness-channel-sdk/src/roleHolderSource.ts), the conductor-local wiring
(src/conductor/roleHolderResolver.ts), and index.ts building the registry and threading it
into both the executor (resolveRoleHolders) and the await worker (holdersOnly). RunExecutor
already refuses quorum='all' completion on a partial holder list and already withholds the
no-holder fallback on a partial-empty lookup (runExecutor.ts resolveAwait / openHumanAwait).

What was still missing was the issue's second mandatory regression test:

- quorum='all' partial/unavailable non-completion already had a test
  (conductorQuorumAndTimeout.test.ts:127, from #726).
- 'role has no holder -> fallback' firing ONLY on a resolved-empty lookup, never on
  unavailable, had no test at all — openHumanAwait's fail-closed branch was unexercised.

Added that missing pair via ConductorRunExecutor.startRun with a minimal in-memory
workflow/run/await-store harness (same pattern as the existing quorum tests):
- a RESOLVED empty holder list takes the fallback path (records the step 'failed' with
  actor.noHolder=true) and never opens an await.
- an UNAVAILABLE (partial) holder lookup does NOT take the fallback -- it parks (opens an
  await, calls runStore.park) exactly as if a real holder existed but had not answered yet.

Mutation-verified: reverting either fail-closed guard in runExecutor.ts (the partial branch
in openHumanAwait, or the !holdersPartial conjunct in the quorum='all' completeness check)
turns the corresponding test red; both were confirmed against a clean tsc rebuild before and
after.

Also updated the roleStore.ts:22 comment (issue requirement #5) -- it still described the
external-resolver seam as future work after #726 had already filled it.
@Weegy
Weegy merged commit 25f247c into main Aug 21, 2026
8 checks passed
@Weegy
Weegy deleted the feat/754-role-holder-resolver branch August 21, 2026 08:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Conductor: external role-holder resolver ahead of roleStore (roleStore.ts:22 seam)

1 participant