Skip to content

fix(nyxid-chat): make needs-you resolutions resume the authoritative task #3154

Description

@eanz17

Context

The source contract added by #3131 is reachable from feature/integrate at commit 09a9bb4b8d0183416ffdc4b0b2d1094a85a12bfb, but the consumer path in eanz17/nyxid-chat#9 cannot be completed without guessing runtime semantics.

Source audit found three gaps:

  1. NyxIdChatInputRequestCommand has an actor handler and tests, but no non-test production publisher/producer. git grep outside tests finds only the handler, decision helper, and proto declaration.
  2. HandleInputResolveAsync and HandleApprovalResolveAsync only persist their resolution event. The decision helpers clear the pending fact, record a digest/latest result, and increment progress. They do not apply the input answer to the waiting input step, dispatch or resume the next operation, or bridge the approval decision to the underlying tool approval continuation. The active task/step can therefore remain waiting with no pending control.
  3. pendingInput.multiSelect is public, while input.resolve.answer is one opaque string. The contract does not define how multiple selected option identities/labels are encoded. Browser consumers must not invent comma/newline/JSON conventions.

The checked-in v1 fixture set covers one nyxid.input.request plus its matching current-state and conversation summary. It does not freeze nyxid.input.changed, nyxid.approval.request, nyxid.approval.changed, pending approval current-state, latest resolutions, or approval attention summary shapes.

Scope

  • Add a real production path that authors NyxIdChatInputRequestCommand for an exact active input step.
  • Make an accepted input resolution apply the exact answer to that step and deterministically resume/advance the actor-owned task.
  • Make an accepted approval resolution drive the exact underlying approval continuation and deterministically resume/terminalize the task.
  • Keep stale-version rejection, exact replay idempotency, first-decision-wins, passivation safety, and secret-free committed state.
  • Replace the ambiguous multi-select string convention with a typed, documented answer shape, or explicitly remove multiSelect until a typed shape exists.
  • Check in versioned live/current-state/conversation-summary fixtures for input request/change and approval request/change, including latest resolution readback.

Acceptance

  • A production integration test creates pending input without directly sending the internal command from the test.
  • Resolving that input advances the exact waiting step and the answer reaches the intended continuation without entering durable/log/presentation state in raw form.
  • Approve and deny each advance/terminalize the exact approval-waiting step through the real tool approval path.
  • Duplicate identical decisions are idempotent; stale/conflicting decisions do not advance state.
  • Multi-select serialization is typed and covered with at least two selected options.
  • Live and current-state fixtures converge for all four request/change frames.
  • Reload/passivation tests prove no pending fact is lost and no resolved step remains orphaned.

Non-scope

No browser heuristics, no second Chat API, no query-time replay, no raw answer/reason persistence, and no nyxid-chat frontend implementation.

Related: #3131, eanz17/nyxid-chat#6, eanz17/nyxid-chat#9.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions