feat(flows): NF-6 Phase 5B + 5C — cutover to flows, simplify webhook dispatcher #388
No reviewers
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!388
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/flows-cutover-delete-legacy"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Switches the production dispatch path from the hard-coded webhook switch to the node-flow runner. After 7 baked-in flows shipped in Phase 4 + 1 in Phase 5A, every trigger kind now has flow coverage — the legacy switch arms are redundant.
Stacks on PR #387 (Phase 5A —
slash-commands-other). Merge order matters; this PR depends on the slash-commands-other flow existing for theissue_comment.slash_commandsuppression to be safe.Phase 5B — rewire
onAssignedReadycallbackpropagateDependencyClosure.onAssignedReadypreviously re-fired the legacyhandleIssueAssignedhelper on each unblocked dependent. After cutover that helper is no longer the canonical entry point; swapped to a syntheticForgeEvent+dispatchToFlowsre-entry so dep-triggered re-dispatches go through the same flow-runner +flow_runsobservability. Lazy import breaks theflow-dispatch.ts → webhook-handlers.tsload cycle.Phase 5C — flip cutover + simplify dispatcher
config/agents.json:node_flows.mode = "live"+suppress_legacycovers all 7 trigger kinds shipped (issue.assigned, issue.labeled, issue.closed, pull_request_review.review_requested, pull_request_review.submitted, issue_comment.slash_command, check_suite.completed).webhook.ts: ripped out the legacy switch (~150 lines) + per-trigger bypass gate plumbing. Forgejo webhook now does only:handlePullRequestOpened/handlePullRequestClosedinline (no flow yet covers these — Phase 6)dispatchToFlows(forgeEvent)(canonical path)Deleted
webhook-suppress-legacy.test.ts(gate is gone).Removed two test cases asserting "legacy switch fires
cleanupIssueonissues.closed" — equivalent coverage inissue-closed-deps-graph.test.ts.What's NOT deleted
Legacy handler functions in
webhook-handlers.ts(handleIssueAssigned,handleIssueLabeled,handleApproved,handleChangesRequested,handleReviewRequested,handleIssueComment,handleStatusEvent,handleActionRunEvent) are dead code in production but kept in the file. Their direct unit tests still verify them. Phase 6 rips them out + their tests in one cleanup pass.handleIssueClosed,handleSlashCommandOther,handleCheckSuiteCompleted,handlePullRequestOpened,handlePullRequestClosed,handlePostMergeRebaseSTAY — flow injections (or surviving inline calls in webhook.ts) still need them.Test plan
flow_runsfor flow-only failures; drop tomode = "off"inconfig/agents.jsonif needed (trivial rollback)🤖 Generated with Claude Code
Switches the production dispatch path from the hard-coded webhook switch to the node-flow runner. After 7 baked-in flows shipped in Phase 4 + 1 in Phase 5A, every trigger kind now has flow coverage — the legacy switch arms are redundant. ## Phase 5B — rewire onAssignedReady callback `propagateDependencyClosure.onAssignedReady` previously re-fired the legacy `handleIssueAssigned` helper on each unblocked dependent. After the cutover that helper is no longer the canonical entry point; swapped to a synthetic `ForgeEvent` + `dispatchToFlows` re-entry so dep-triggered re-dispatches go through the same flow-runner + `flow_runs` observability as everything else. Lazy import breaks the `flow-dispatch.ts → webhook-handlers.ts` load cycle. ## Phase 5C — flip cutover + simplify webhook dispatcher 1. `config/agents.json`: `node_flows.mode = "live"` + `suppress_legacy` covers all 7 trigger kinds shipped in Phase 4 + 5A. 2. `webhook.ts`: ripped out the legacy switch (~150 lines) + per-trigger bypass gate plumbing. The Forgejo webhook now does only: - signature verify - parse + multi-repo gate - normalise payload to ForgeEvent - run `handlePullRequestOpened` / `handlePullRequestClosed` inline (no flow yet covers these — Phase 6 will add them) - `dispatchToFlows(forgeEvent)` (canonical path) 3. Deleted `webhook-suppress-legacy.test.ts` (gate is gone). 4. Removed the two test cases in `webhook.test.ts` + `webhook-handlers.test.ts` that asserted "legacy switch fires `cleanupIssue` on `issues.closed`" — the equivalent coverage lives in `issue-closed-deps-graph.test.ts`. ## What's NOT deleted The legacy handler functions in `webhook-handlers.ts` (`handleIssueAssigned`, `handleIssueLabeled`, `handleApproved`, `handleChangesRequested`, `handleReviewRequested`, `handleIssueComment`, `handleStatusEvent`, `handleActionRunEvent`) are dead code in production now (webhook.ts no longer calls them) but kept in the file. Their direct unit tests in `webhook-handlers.test.ts`, `webhook-assign-dedup.test.ts`, and `force-merge.integration.test.ts` still verify them — and the flow-side tests duplicate the coverage by injection. Phase 6 will rip them out + their tests in one cleanup pass. `handleIssueClosed`, `handleSlashCommandOther`, `handleCheckSuiteCompleted`, `handlePullRequestOpened`, `handlePullRequestClosed`, `handlePostMergeRebase` STAY — flow injections (or the surviving inline calls in webhook.ts) still need them. ## Test plan - [x] Server typecheck clean - [x] Test suite: 1968 pass / 5 fail (all pre-existing — session-pruning + foreman CRUD, unrelated to this PR) - [ ] Soak in production: watch `flow_runs` for any flow-only failures; drop into `mode = "off"` if needed (flips trivially) Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>