chore(flows): default graph refs don't match TriggerEventIssueAssigned shape #361

Closed
opened 2026-04-24 15:39:01 +00:00 by code-lead · 0 comments
Collaborator

NF-6 dry-run smoke test exposed a shape mismatch between the baked default graph (NF-4) and the actual TriggerEventIssueAssigned payload emitted by the NF-1 converter.

Symptom

Running dispatchToFlows against a synthetic issues.assigned event produces:

run flow=default status=error
  error=agent.dispatch: type: expected non-empty string, got undefined
  node=src                      ok
  node=log_trigger              ok
  node=type_switch              ok
  node=dispatch_by_assignee     error
  node=dispatch_designer        skipped
  node=dispatch_design_reviewer skipped

Root cause

Default graph at apps/server/src/domain/flows/default-graph.json reads:

  • src.out.routedType (for router.switch)
  • src.out.repo, src.out.issueNumber, src.out.labels

The real trigger shape (from packages/shared/src/trigger-event.ts):

TriggerEventIssueAssigned {
  kind: "issue.assigned",
  repo: string,
  firedAt: string,
  issue: { number, title, labels: string[], assignees: string[] },
  assignee: string,
}

No routedType, no flat issueNumber, no flat labels.

Fix (preferred)

Rewrite the default graph's input refs to match the real trigger shape. Keep routing logic inside the graph (operator-composable), not pre-computed on the trigger (would pollute the shared contract).

  • src.out.repo -> src.repo
  • src.out.issueNumber -> src.issue.number
  • src.out.labels -> src.issue.labels
  • Replace the src.out.routedType-driven router.switch with routing composed from existing primitives against the actual payload fields. Deferring a new util.route_agent_type registry node until a second consumer needs it (YAGNI).

Acceptance

  • Default graph compiles against defaultRegistry() (default-graph.test.ts still passes).
  • Synthetic issues.assigned dispatch produces status=ok in dry-run (no unresolved-path errors).
  • Dry-run mode records agent.dispatch intent for the routed type rather than short-circuiting on undefined input.
  • flow-dispatch.test.ts extended with a smoke check that the default graph completes in dry-run against the real trigger shape.

Out of scope

  • Adding util.route_agent_type registry node — defer.
  • Expanding default-graph coverage to PR review / CI / slash-command paths — NF-6 follow-up work.

References

  • Spec: specs/node-flows.md § Default flow.
  • NF-6 PR #360.
  • NF-1 trigger union landed in #341.
NF-6 dry-run smoke test exposed a shape mismatch between the baked default graph (NF-4) and the actual `TriggerEventIssueAssigned` payload emitted by the NF-1 converter. ## Symptom Running `dispatchToFlows` against a synthetic `issues.assigned` event produces: ``` run flow=default status=error error=agent.dispatch: type: expected non-empty string, got undefined node=src ok node=log_trigger ok node=type_switch ok node=dispatch_by_assignee error node=dispatch_designer skipped node=dispatch_design_reviewer skipped ``` ## Root cause Default graph at `apps/server/src/domain/flows/default-graph.json` reads: - `src.out.routedType` (for `router.switch`) - `src.out.repo`, `src.out.issueNumber`, `src.out.labels` The real trigger shape (from `packages/shared/src/trigger-event.ts`): ``` TriggerEventIssueAssigned { kind: "issue.assigned", repo: string, firedAt: string, issue: { number, title, labels: string[], assignees: string[] }, assignee: string, } ``` No `routedType`, no flat `issueNumber`, no flat `labels`. ## Fix (preferred) Rewrite the default graph's input refs to match the real trigger shape. Keep routing logic inside the graph (operator-composable), not pre-computed on the trigger (would pollute the shared contract). - `src.out.repo` -> `src.repo` - `src.out.issueNumber` -> `src.issue.number` - `src.out.labels` -> `src.issue.labels` - Replace the `src.out.routedType`-driven `router.switch` with routing composed from existing primitives against the actual payload fields. Deferring a new `util.route_agent_type` registry node until a second consumer needs it (YAGNI). ## Acceptance - [ ] Default graph compiles against `defaultRegistry()` (`default-graph.test.ts` still passes). - [ ] Synthetic `issues.assigned` dispatch produces `status=ok` in dry-run (no unresolved-path errors). - [ ] Dry-run mode records `agent.dispatch` intent for the routed type rather than short-circuiting on undefined input. - [ ] `flow-dispatch.test.ts` extended with a smoke check that the default graph completes in dry-run against the real trigger shape. ## Out of scope - Adding `util.route_agent_type` registry node — defer. - Expanding default-graph coverage to PR review / CI / slash-command paths — NF-6 follow-up work. ## References - Spec: `specs/node-flows.md` § Default flow. - NF-6 PR #360. - NF-1 trigger union landed in #341.
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
charles/claude-hooks#361
No description provided.