feat(flows): NF-6 Phase 4B — pr-approved-merge baked-in flow #381
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
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks!381
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "feat/flows-pr-approved-merge"
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
Ports
webhook-handlers.ts::handleApproved(rebase precheck + boss merge dispatch) into a baked-in node-flow graph. Shipspr-approved-mergeas the third seeded flow on thepull_request_review.submittedtrigger.Both branches dispatch on
branch=pr.headRefso the worktree lands on the actual PR head (not the derived<branch_prefix>/<issue>).DSL extensions (small, surgical)
agent.resolve_by_login/resolve_by_typegain agateinput — mirrorsagent.render_skill.gate. Handler ignores the value; FILTER_DROP propagation does the gating work.forge.*nodes gain an optionaltokeninput port (in addition toargs.token).inputs.tokenwins, letting flows thread per-run tokens out of upstreamagent.resolve_by_*envelopes instead of baking them into the JSON.Documented deviation
When the PR author can't be resolved (rare external author), the entire pipeline drops. Legacy fires merge to boss anyway, which the merge skill's
mergeableprecondition then refuses — net behaviour matches (no merge happens), and the flow path avoids the noisy boss task.Force-merge path (
opts.force=true, MAX_ROUNDS escape hatch) is OUT OF SCOPE here — that lives ondispatchMerge(…, { force: true })from the changes-requested round-cap, ported in Phase 4E.Cutover
Set
node_flows.suppress_legacy: ["pull_request_review.submitted"]once the new flow soaks clean onGET /flows/divergence/summary.Test plan
bun test apps/server/src/domain/flows/pr-approved-merge-graph.test.ts— 16 tests, all passbun test apps/server/src/domain/flows/— 263 tests, all pass (no regressions)bun test apps/server/src/http/flows-routes.test.ts— 63 tests pass (BAKED_IN_FLOWS seeding intact)mode: "live"against a real approval, confirm flow + legacy emit identical dispatches viaGET /flows/divergence/summarysuppress_legacy: ["pull_request_review.submitted"]after a clean soak window🤖 Generated with Claude Code
Ports `webhook-handlers.ts::handleApproved` (rebase precheck + boss merge dispatch) into a baked-in node-flow graph. Ships a third seeded flow (`pr-approved-merge`) on the `pull_request_review.submitted` trigger: src → router.filter (review.state==="approved") → agent.resolve_by_login (PR author) → forge.get_pull_request (using author token) → router.switch on `mergeable` • not_mergeable → render `rebase` + dispatch to author • default → resolve_by_type("boss") + render `merge` + dispatch to boss Both branches dispatch on `branch=pr.headRef` so the worktree lands on the actual PR head (not the derived `<branch_prefix>/<issue>`). Two small DSL extensions were needed: - `agent.resolve_by_login` / `resolve_by_type` gain a `gate` input (mirrors `agent.render_skill.gate`). The handler ignores the value; FILTER_DROP propagation does the gating work. - `forge.*` nodes gain an optional `token` input port (in addition to the existing `args.token`). `inputs.token` wins, letting flows thread per-run tokens out of upstream `agent.resolve_by_*` envelopes instead of baking them into the JSON. Documented deviation: when the PR author can't be resolved (rare external author), the entire pipeline drops. Legacy fires merge to boss anyway, which the merge skill's `mergeable` precondition then refuses — net behaviour matches (no merge happens), and the flow path avoids the noisy boss task. Cutover gate: `node_flows.suppress_legacy: ["pull_request_review.submitted"]` skips the legacy `webhook.ts:310-316` switch arm once the new flow soaks clean on `GET /flows/divergence/summary`. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>