feat(flows-yaml): shadow mode + cutover CLI + legacy + UI deletion (closes #1078) #1083

Merged
charles merged 5 commits from flows-yaml/cutover into main 2026-05-10 21:28:55 +00:00
Collaborator

Closes #1078. Final phase of the Flows YAML milestone (#40). Builds on #1075 (engine), #1076 (defaults + REST), #1077 (UI).

This PR is destructive. The legacy JSON node engine, React Flow canvas, and /api/flows-yaml URL prefix are gone. The YAML engine becomes the sole dispatch path. Operator post-merge checklist below.

Commits

  1. feat(flows-yaml): live capabilities + shadow mode + diff reporter — wires real service deps, adds shadow tables + diff reporter (no behavior change at default mode: "off").
  2. feat(flows-yaml): per-flow cutover CLI + 24h shadow gate — operator-driven per-flow promotion. Settings learn per_flow overrides + cutover_history.
  3. feat(flows-yaml): delete legacy engine + cut UI over + rename audit columns — destructive cleanup.

What landed

Phase 1 — live + shadow

  • buildLiveCapabilitiesDeps() in main.ts composes thin closures over the existing service surface (workers, dedup, agent-resolver, forge, breakdown, review-guard, pr-flow). assertCapabilitiesSatisfyOps() refuses to start the dispatcher on missing deps.
  • shadow-capabilities.ts wraps mutating ops as no-op recorders; read-only ops pass through.
  • shadow-hooks-impl.ts persists to flow_runs_yaml + flow_node_runs_yaml.
  • flows-yaml-diff-reporter.ts (6h cron) pairs flow_runs vs flow_runs_yaml ±60s window; emits legacy_only / yaml_only / flow_name_diverged / op_sequence_diverged mismatch types. Surfaced via GET /api/flows/diff-report.
  • Drizzle migration 0014_flow_runs_yaml_shadow_table.sql adds the shadow tables with the post-cutover column names (flow_name, step_id, uses).

Phase 2 — per-flow cutover

  • FlowsYamlSettings extended with per_flow: Record<name, mode> + cutover_history.
  • per-flow-router.ts returns the right capability bag per flow at execution time; settings flips take effect on the next event.
  • cutover-gate.ts enforces "→ live" promotion (must be in shadow, ≥24h shadow data, zero recent diff mismatches naming this flow). --force overrides + records.
  • POST /api/flows/:name/mode — operator-callable mode change. Auth-gated. Same gate as the CLI.
  • CLIs: apps/server/scripts/flows-yaml-cutover.ts + flows-yaml-mode-status.ts plus just flows-yaml-cutover NAME MODE *EXTRA and just flows-yaml-mode-status recipes.

Phase 3 — legacy deletion + UI cutover + renames

Server deletions (54 files):

  • apps/server/src/domain/flows/ entire directory — JSON node-graph engine: executor, registry, validation, flow-dispatch, agent/forge/mcp-nodes, every *-graph.{ts,json,test.ts}, types, seed-status, rate-limit
  • apps/server/src/http/{flows-divergence,divergence-summary,flow-assistant-routes} — dead consumers of the deleted engine
  • apps/server/src/infrastructure/database/{flows,flow-audit}.ts + schema modules — paired with the dropped tables

Server rewrites:

  • webhook.ts — drop dispatchToFlows + the three imperative handlers at lines 296–341. The YAML dispatcher is the sole path.
  • main.ts — drop 13 legacy imports + 11 /api/flows/* legacy handler stubs + seedDefaultFlowAtBoot(). Wire setEventHandlersTriggerBus (closes a latent unwired-bus bug).
  • event-handlers.ts — replace flow-dispatch lazy-import in propagateDependencyClosure with a YAML trigger-bus publish.
  • dispatcher.ts — drop the legacy single-bag constructor; router-only.

Drizzle migration 0015_drop_legacy_flows_and_rename_audit.sql:

  • DROP TABLE flows + flow_audit
  • flow_runs.flow_idflow_name
  • flow_runs.flow_version dropped
  • flow_node_runs.node_idstep_id; uses TEXT added (matches shadow table shape)
  • Idempotent guard in migrate.ts. New migrate-0015-rename.test.ts covers pre/post column shape + idempotence.

Web deletions + cutover:

  • apps/web/src/features/flows/* canvas + palette + inspector + assistant panel deleted (the #1075-era React Flow canvas)
  • apps/web/src/routes/flows.{index,$flowId,$flowId.v.$version,$flowId.versions,new,test}.tsx legacy routes deleted
  • features/flows-yaml/features/flows/; routes/flows-yaml.*routes/flows.*; lib/flows-yaml-api.tslib/flows-api.ts
  • /api/flows-yaml/*/api/flows/*; /flows-yaml/*/flows/*
  • testid prefix flows-yaml-flows-
  • nav-sections.tsx collapsed to a single canonical Flows entry pointing at /flows
  • apps/web/package.json drops @xyflow/react + @types/dagre + dagre

Spec retirement:

  • specs/node-flows.md + specs/node-flows-ui.md get a RETIRED banner; files kept as archive

What stays:

  • Shadow tables (flow_runs_yaml / flow_node_runs_yaml / flows_yaml_diff_report) — operator may want post-merge shadow data
  • workflow/event-handlers.tshandleIssueClosed, handleCheckSuiteCompleted, handlePullRequestClosed, handlePullRequestOpened, handleSlashCommandOther, detectOutstandingChangeRequest, latestVerdict, isTrustedUser, dispatchIssueForAgent all still support live capabilities

Stats

  • 162 files changed, +2304 / -34710
  • Server suite: 3207 / 0 (485 legacy tests retired with their subjects)
  • Web tsc: clean
  • Server tsc: clean

Operator post-merge checklist

  1. Backup DB before deploy — migration 0015 is destructive (DROP TABLE flows + column renames).
  2. Flip flows_yaml_settings.mode to live (or per-flow live) BEFORE the deploy lands, otherwise no dispatch fires (the legacy fallback is gone). The phase-2 cutover CLI is the gate.
  3. /api/flows-yaml/* is removed — bookmarks and external scripts need to flip to /api/flows/*.
  4. routeTree.gen.ts auto-regenerates on next vite build.
  5. Validate shadow data before merge — if shadow data isn't yet collected, plan the rollout sequence: deploy phase 1 + 2, validate via the diff reporter for ≥24h, then deploy phase 3.

🤖 Generated with Claude Code

Closes #1078. Final phase of the Flows YAML milestone (#40). Builds on #1075 (engine), #1076 (defaults + REST), #1077 (UI). **This PR is destructive.** The legacy JSON node engine, React Flow canvas, and `/api/flows-yaml` URL prefix are gone. The YAML engine becomes the sole dispatch path. Operator post-merge checklist below. ## Commits 1. `feat(flows-yaml): live capabilities + shadow mode + diff reporter` — wires real service deps, adds shadow tables + diff reporter (no behavior change at default `mode: "off"`). 2. `feat(flows-yaml): per-flow cutover CLI + 24h shadow gate` — operator-driven per-flow promotion. Settings learn `per_flow` overrides + `cutover_history`. 3. `feat(flows-yaml): delete legacy engine + cut UI over + rename audit columns` — destructive cleanup. ## What landed ### Phase 1 — live + shadow - `buildLiveCapabilitiesDeps()` in `main.ts` composes thin closures over the existing service surface (workers, dedup, agent-resolver, forge, breakdown, review-guard, pr-flow). `assertCapabilitiesSatisfyOps()` refuses to start the dispatcher on missing deps. - `shadow-capabilities.ts` wraps mutating ops as no-op recorders; read-only ops pass through. - `shadow-hooks-impl.ts` persists to `flow_runs_yaml` + `flow_node_runs_yaml`. - `flows-yaml-diff-reporter.ts` (6h cron) pairs `flow_runs` vs `flow_runs_yaml` ±60s window; emits `legacy_only` / `yaml_only` / `flow_name_diverged` / `op_sequence_diverged` mismatch types. Surfaced via `GET /api/flows/diff-report`. - Drizzle migration `0014_flow_runs_yaml_shadow_table.sql` adds the shadow tables with the post-cutover column names (`flow_name`, `step_id`, `uses`). ### Phase 2 — per-flow cutover - `FlowsYamlSettings` extended with `per_flow: Record<name, mode>` + `cutover_history`. - `per-flow-router.ts` returns the right capability bag per flow at execution time; settings flips take effect on the next event. - `cutover-gate.ts` enforces "→ live" promotion (must be in shadow, ≥24h shadow data, zero recent diff mismatches naming this flow). `--force` overrides + records. - `POST /api/flows/:name/mode` — operator-callable mode change. Auth-gated. Same gate as the CLI. - CLIs: `apps/server/scripts/flows-yaml-cutover.ts` + `flows-yaml-mode-status.ts` plus `just flows-yaml-cutover NAME MODE *EXTRA` and `just flows-yaml-mode-status` recipes. ### Phase 3 — legacy deletion + UI cutover + renames **Server deletions** (54 files): - `apps/server/src/domain/flows/` entire directory — JSON node-graph engine: executor, registry, validation, flow-dispatch, agent/forge/mcp-nodes, every `*-graph.{ts,json,test.ts}`, types, seed-status, rate-limit - `apps/server/src/http/{flows-divergence,divergence-summary,flow-assistant-routes}` — dead consumers of the deleted engine - `apps/server/src/infrastructure/database/{flows,flow-audit}.ts` + schema modules — paired with the dropped tables **Server rewrites**: - `webhook.ts` — drop `dispatchToFlows` + the three imperative handlers at lines 296–341. The YAML dispatcher is the sole path. - `main.ts` — drop 13 legacy imports + 11 `/api/flows/*` legacy handler stubs + `seedDefaultFlowAtBoot()`. Wire `setEventHandlersTriggerBus` (closes a latent unwired-bus bug). - `event-handlers.ts` — replace `flow-dispatch` lazy-import in `propagateDependencyClosure` with a YAML trigger-bus publish. - `dispatcher.ts` — drop the legacy single-bag constructor; router-only. **Drizzle migration `0015_drop_legacy_flows_and_rename_audit.sql`**: - DROP TABLE `flows` + `flow_audit` - `flow_runs.flow_id` → `flow_name` - `flow_runs.flow_version` dropped - `flow_node_runs.node_id` → `step_id`; `uses TEXT` added (matches shadow table shape) - Idempotent guard in `migrate.ts`. New `migrate-0015-rename.test.ts` covers pre/post column shape + idempotence. **Web deletions + cutover**: - `apps/web/src/features/flows/*` canvas + palette + inspector + assistant panel deleted (the `#1075`-era React Flow canvas) - `apps/web/src/routes/flows.{index,$flowId,$flowId.v.$version,$flowId.versions,new,test}.tsx` legacy routes deleted - `features/flows-yaml/` → `features/flows/`; `routes/flows-yaml.*` → `routes/flows.*`; `lib/flows-yaml-api.ts` → `lib/flows-api.ts` - `/api/flows-yaml/*` → `/api/flows/*`; `/flows-yaml/*` → `/flows/*` - testid prefix `flows-yaml-` → `flows-` - `nav-sections.tsx` collapsed to a single canonical Flows entry pointing at `/flows` - `apps/web/package.json` drops `@xyflow/react` + `@types/dagre` + `dagre` **Spec retirement**: - `specs/node-flows.md` + `specs/node-flows-ui.md` get a RETIRED banner; files kept as archive **What stays**: - Shadow tables (`flow_runs_yaml` / `flow_node_runs_yaml` / `flows_yaml_diff_report`) — operator may want post-merge shadow data - `workflow/event-handlers.ts` — `handleIssueClosed`, `handleCheckSuiteCompleted`, `handlePullRequestClosed`, `handlePullRequestOpened`, `handleSlashCommandOther`, `detectOutstandingChangeRequest`, `latestVerdict`, `isTrustedUser`, `dispatchIssueForAgent` all still support live capabilities ## Stats - **162 files changed, +2304 / -34710** - Server suite: **3207 / 0** (485 legacy tests retired with their subjects) - Web tsc: clean - Server tsc: clean ## Operator post-merge checklist 1. **Backup DB before deploy** — migration 0015 is destructive (DROP TABLE flows + column renames). 2. **Flip `flows_yaml_settings.mode` to `live` (or per-flow `live`) BEFORE the deploy lands**, otherwise no dispatch fires (the legacy fallback is gone). The phase-2 cutover CLI is the gate. 3. **`/api/flows-yaml/*` is removed** — bookmarks and external scripts need to flip to `/api/flows/*`. 4. **`routeTree.gen.ts` auto-regenerates** on next `vite build`. 5. **Validate shadow data before merge** — if shadow data isn't yet collected, plan the rollout sequence: deploy phase 1 + 2, validate via the diff reporter for ≥24h, then deploy phase 3. 🤖 Generated with [Claude Code](https://claude.com/claude-code)
#1078 phase 1/3 — wire real service deps into the YAML engine and
turn on shadow-mode dual-running. No production behavior change yet
(`flows_yaml_settings.mode` defaults to `off`); operator flips per-
flow via the cutover CLI in phase 2.

Live capabilities (`apps/server/src/main.ts`):
- buildLiveCapabilitiesDeps() composes thin closures over
  dispatchByType + worker registry cancel surface, assign-dedup
  (scope-keyed `<repo>#<issue>:<type>`), webhook-config agent
  resolvers, createForgeAdapterForRepo + probe-token, slash-commands
  (parse + dispatch breakdown), review-loop guards + change-request
  detection (latestVerdict-based), and the three legacy PR/issue
  handlers (handlePrDependencyMarkers, handleStackedRebaseCascade,
  handleIssueClosed) wrapped behind the prFlow capability.
- bootstrapFlowsYamlEngine() refuses to start the dispatcher when
  any OpDepKey is unsatisfied (assertCapabilitiesSatisfyOps);
  selects buildLiveCapabilities or buildShadowCapabilities based on
  service_settings.flows_yaml.mode.

Shadow mode (apps/server/src/domain/flows-yaml/):
- shadow-capabilities.ts wraps every mutating op as a no-op recorder
  that returns a plausible output shape; read-only ops
  (resolve_agent, dedup.isDup, forge.listLabels, reviewGuard.*,
  breakdown.isTrusted) pass through to live deps so downstream
  routing keeps walking.
- shadow-hooks-impl.ts persists to flow_runs_yaml +
  flow_node_runs_yaml; intent JSON drained per step.
- webhook handlers (forgejo + github + gitlab) fan out to the YAML
  dispatcher alongside the legacy `dispatchToFlows`. Legacy path
  unchanged in shadow mode.

Drizzle migration 0014_flow_runs_yaml_shadow_table.sql adds
flow_runs_yaml + flow_node_runs_yaml + flows_yaml_diff_report
tables. Idempotent guard registered in migrate.ts. Schema columns
adopt the post-cutover names (flow_name, step_id, uses) so phase 3
ports cleanly.

Diff reporter (apps/server/src/background/flows-yaml-diff-reporter.ts):
- Pairs flow_runs vs flow_runs_yaml by (trigger_kind, subtype) ±60s
  window; emits legacy_only / yaml_only / flow_name_diverged /
  op_sequence_diverged mismatch types.
- 6h cron mirrors divergence-summary.ts pattern; surfaces totals via
  GET /api/flows-yaml/diff-report.

15 new tests in 4 files; full server suite 3707/3707 green; tsc clean.

Refs: #1078

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#1078 phase 2/3 — operator-driven per-flow promotion from shadow to
live. Settings learn a `per_flow` override map; the dispatcher picks
the right capability bag per flow at execution time.

apps/server/src/infrastructure/database/service-config-store.ts:
- FlowsYamlSettings extended with `per_flow` (Record<name, mode>) and
  `cutover_history` (array of {flow_name, from, to, ts, force,
  reason}) entries. Robust normalisers preserve self-healing posture.
- New helpers: setFlowsYamlPerFlowMode,
  clearFlowsYamlPerFlowOverride, effectiveFlowMode.

apps/server/src/domain/flows-yaml/per-flow-router.ts:
- createPerFlowRouter({live, shadow, getSettings}) returns an
  { effectiveMode, route } pair. route() re-reads settings on every
  call so flips take effect on the next event with no restart.

apps/server/src/domain/flows-yaml/cutover-gate.ts:
- Single source of truth for "→ live" promotion: must be in shadow,
  ≥24h shadow data exists, recent flows_yaml_diff_report has zero
  mismatches naming this flow. --force skips the gate but is still
  recorded in cutover_history.

apps/server/src/domain/flows-yaml/dispatcher.ts:
- Optional router parameter. When present, picks the per-flow
  capability bag in the matched-flows loop; bag === null skips with
  a log. Legacy single-bag path kept so the existing
  dispatcher.test.ts and direct-bag callers don't have to change.

apps/server/src/main.ts:
- bootstrapFlowsYamlEngine now builds both live + shadow bags and
  hands the router to the dispatcher. Boot gate flips on
  `mode !== "off" || any per_flow !== "off"` so a flow can be live
  while the global default stays off. assertCapabilitiesSatisfyOps
  runs against both bags.

HTTP: POST /api/flows-yaml/:name/mode (apps/server/src/http/flows-yaml-routes.ts):
- Body { mode, force?, reason? }. Auth-gated. Runs the same
  evaluateCutover the CLI does, appends to cutover_history,
  audit-logs, broadcasts `flows_yaml.settings_changed` SSE.
- GET /api/flows-yaml/settings returns the full settings shape so
  CLI + UI can render mode status.

Operator surfaces:
- apps/server/scripts/flows-yaml-cutover.ts CLI: POSTs the mode
  endpoint. Exit codes 0 / 1 (not found) / 2 (gate refused) / 3
  (server error). CLAUDE_HOOKS_BASE_URL override for non-default
  hosts.
- apps/server/scripts/flows-yaml-mode-status.ts CLI: prints a
  per-flow effective-mode table.
- justfile recipes: `flows-yaml-cutover NAME MODE *EXTRA` and
  `flows-yaml-mode-status`.

27 new tests across 3 files (per-flow-router, cutover-gate, mode-
endpoint). Full server suite 3734/3734 green; tsc clean.

Refs: #1078

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
feat(flows-yaml): delete legacy engine + cut UI over + rename audit columns
Some checks failed
qa / sql-layer-check (pull_request) Successful in 8s
qa / db-schema (pull_request) Failing after 8s
qa / dockerfile (pull_request) Successful in 10s
qa / i18n-string-check (pull_request) Successful in 11s
qa / qa-1 (pull_request) Failing after 41s
qa / qa (pull_request) Failing after 0s
9d70409e55
#1078 phase 3/3 — destructive cleanup. The JSON node engine, React
Flow canvas, and legacy CRUD endpoints are gone. The YAML engine is
now the sole dispatch path. Operator must validate via shadow mode +
flip flows to live (or per-flow) before this lands; the cutover CLI
from phase 2 is the gate.

Server deletions:
- apps/server/src/domain/flows/ — entire JSON node-graph engine:
  executor, registry, validation, flow-dispatch, agent/forge/mcp-
  nodes, every *-graph.{ts,json,test.ts}, types, seed-status,
  rate-limit (49 files).
- apps/server/src/http/flows-routes.ts (legacy) — replaced by the
  renamed YAML routes; flows-divergence + divergence-summary +
  flow-assistant-routes deleted as dead consumers.
- apps/server/src/infrastructure/database/{flows.ts,flow-audit.ts}
  + corresponding schema modules — paired with the dropped flows
  table.

Server rewrites:
- webhook.ts — drop `dispatchToFlows` + the three imperative
  handlers at lines 296–341. The YAML dispatcher is the sole path;
  cancel_tasks / pr_dependency_markers / propagate_dependencies ops
  cover the old behavior.
- main.ts — drop 13 legacy imports + 11 `/api/flows/*` legacy
  handler stubs + seedDefaultFlowAtBoot(). Wire
  setEventHandlersTriggerBus (closes a latent unwired-bus bug); the
  YAML pr.merged trigger now routes through the dispatcher.
- event-handlers.ts — replace flow-dispatch lazy-import in
  propagateDependencyClosure with a YAML trigger-bus publish.
- dispatcher.ts — drop the legacy single-bag constructor; router-
  only.

Drizzle migration 0015_drop_legacy_flows_and_rename_audit.sql:
- DROP TABLE flows + flow_audit
- flow_runs.flow_id → flow_name (TEXT)
- flow_runs.flow_version dropped (YAML mtime is the version axis;
  shadow audit rows had been writing 1 as a placeholder)
- flow_node_runs.node_id → step_id; uses TEXT added (matches the
  shadow table shape introduced in phase 1).
- Idempotent guard in migrate.ts (dropLegacyFlowsAndRenameAudit)
  mirrors the existing pattern.
- New migrate-0015-rename.test.ts covers pre/post column shape +
  legacy-table drops + idempotence.

Web deletions:
- apps/web/src/features/flows/* canvas + palette + inspector +
  FlowAssistantPanel + InputRefPicker + ModeBanner + RunsDrawer +
  TestFireModal + widgets + nodeRegistry + flowsApi + useFlowAuth
  (the canvas UI from #1075 era).
- apps/web/src/routes/flows.{index,$flowId,$flowId.v.$version,
  $flowId.versions,new,test}.tsx — legacy routes gone.

Web renames + cutover:
- features/flows-yaml/* → features/flows/*
- routes/flows-yaml.* → routes/flows.*
- lib/flows-yaml-api.ts → lib/flows-api.ts
- /api/flows-yaml/* server routes → /api/flows/*
- /flows-yaml/* UI routes → /flows/*
- testid prefix flows-yaml- → flows-
- Identifier renames: FlowsYaml* → Flows*, flowsYamlApi → flowsApi
- nav-sections.tsx — collapsed the duplicate Flows / Flows (YAML)
  entries into a single canonical Flows entry pointing at /flows
- apps/web/package.json — drop @xyflow/react + @types/dagre + dagre
  (the React Flow canvas no longer ships)

Spec retirement:
- specs/node-flows.md + specs/node-flows-ui.md — RETIRED banner
  prepended; files kept for archival reference.

What stays:
- flow_runs_yaml + flow_node_runs_yaml + flows_yaml_diff_report
  shadow tables (the operator may still want post-merge shadow data)
- workflow/event-handlers.ts (handleIssueClosed,
  handleCheckSuiteCompleted, handlePullRequestClosed,
  handlePullRequestOpened, handleSlashCommandOther,
  detectOutstandingChangeRequest, latestVerdict, isTrustedUser,
  dispatchIssueForAgent — all still support live capabilities)

Stats: 162 files changed, +2304 / -34710. Server suite 3207/0
(485 legacy tests retired with their subjects). tsc clean (server +
web).

Operator post-merge checklist:
1. Backup DB before deploy — migration 0015 is destructive.
2. Flip flows_yaml_settings.mode to live (or per-flow live) BEFORE
   the deploy lands; otherwise no dispatch fires (the legacy
   fallback is gone). The phase-2 cutover CLI is the gate.
3. /api/flows-yaml/* is removed; bookmarks and external scripts
   need to flip to /api/flows/*.
4. routeTree.gen.ts auto-regenerates on next vite build.

Refs: #1078

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
chore: refresh bun.lock for #1078 cutover (drop dagre/xyflow deps)
All checks were successful
qa / sql-layer-check (pull_request) Successful in 8s
qa / i18n-string-check (pull_request) Successful in 13s
qa / dockerfile (pull_request) Successful in 13s
qa / db-schema (pull_request) Successful in 15s
qa / qa-1 (pull_request) Successful in 3m57s
qa / qa (pull_request) Successful in 0s
fe5588fd03
CI hit `lockfile had changes, but lockfile is frozen` because the
phase-3 commit removed @xyflow/react + dagre + @types/dagre from
apps/web/package.json without re-running bun install. Refresh the
lockfile so the frozen-install gate passes.

Refs: #1078

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
fix(flows-yaml/cutover): restore handlePullRequestClosed + wire pr_dependency_markers + fix CLI URLs
All checks were successful
qa / i18n-string-check (pull_request) Successful in 12s
qa / dockerfile (pull_request) Successful in 12s
qa / sql-layer-check (pull_request) Successful in 12s
qa / db-schema (pull_request) Successful in 14s
qa / qa-1 (pull_request) Successful in 3m6s
qa / qa (pull_request) Successful in 0s
6e4b7bf66e
PR #1083 review surfaced three real regressions from the phase-3
deletion. Fix all three.

1. BLOCKER — handlePullRequestClosed was unreachable.
   Phase-3 deleted the imperative handler call from webhook.ts but no
   YAML op replaces its non-flow side effects: cleanupBranch (worktree
   teardown), handlePostMergeRebase fan-out, dropping outgoing
   pr_dependencies rows, AND publishing the pr.merged internal trigger.
   Result: pr-merged.yml never fired; the rebase cascade silently
   stopped working. Restore the call from the Forgejo webhook handler
   alongside the YAML dispatch — the function is host-only logic that
   doesn't fit the op model yet (forge adapter still doesn't expose
   worktree cleanup).

2. BLOCKER — pr_dependency_markers op was unwired.
   The op exists at apps/server/src/domain/flows-yaml/ops/
   pr_dependency_markers.ts and registers in the default registry, but
   no default flow under flows/defaults/ called `uses:
   pr_dependency_markers`. PR-body `Depends on #N` markers no longer
   drove label / dep-row sync. Add a new
   flows/defaults/pr-dependency-markers.yml on
   `pull_request: [opened, edited, synchronize]` (no top-level if: gate
   — dependency tracking applies to every PR, not just area:agents
   ones).

3. SERIOUS — cutover CLIs hit non-existent URLs.
   Phase-3 renamed all server routes to /api/flows/* but
   apps/server/scripts/flows-yaml-{cutover,mode-status}.ts still POST
   /GET /api/flows-yaml/*. Both CLIs would 404 on every run, breaking
   the operator surface phase-2 was built to provide. sed-replace the
   four URL references + the two JSDoc lines.

Server suite 3207/0 still green; tsc clean.

Refs: #1078

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
charles deleted branch flows-yaml/cutover 2026-05-10 21:28:56 +00:00
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
2 participants
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!1083
No description provided.