feat(flows): persistence + default graph (NF-4) #353

Closed
code-lead wants to merge 1 commit from boss/325 into main
Collaborator

Three new SQLite tables (flows, flow_runs, flow_node_runs) in a dedicated flows.db; a baked default-graph.json bundle with 18 entries reproducing every current dispatch; first-boot seeder, 30-day retention swept via the existing sweeper, and the four spec-mandated read endpoints.

Test plan

  • default-graph.test.ts — every baked flow compiles against defaultRegistry(); trigger-catalog coverage assertion
  • flow-store.test.ts — schema bootstrap, seeding (first boot, no-op replay, version-bump reseed, operator-row pass-through), CRUD reads, flow_runs + flow_node_runs round-trip, 30-day retention with custom TTL
  • sweeper.test.ts — new Phase-4 block calls runFlowRetention with the configured TTL, defaults to 30 days, swallows retention errors
  • just qa clean — typecheck across 4 packages, Biome check + format, 1612 server tests pass (2 pre-existing failures on main unrelated to NF-4)
  • Route registration: GET /flows/runs is registered before GET /flows/:id so the literal segment isn't swallowed
  • Seeder respects the spec: never touches source='operator' rows; reseeds defaults when DEFAULT_GRAPH_VERSION bumps

Closes #325

Three new SQLite tables (`flows`, `flow_runs`, `flow_node_runs`) in a dedicated `flows.db`; a baked `default-graph.json` bundle with 18 entries reproducing every current dispatch; first-boot seeder, 30-day retention swept via the existing sweeper, and the four spec-mandated read endpoints. ## Test plan - [x] `default-graph.test.ts` — every baked flow compiles against `defaultRegistry()`; trigger-catalog coverage assertion - [x] `flow-store.test.ts` — schema bootstrap, seeding (first boot, no-op replay, version-bump reseed, operator-row pass-through), CRUD reads, `flow_runs` + `flow_node_runs` round-trip, 30-day retention with custom TTL - [x] `sweeper.test.ts` — new Phase-4 block calls `runFlowRetention` with the configured TTL, defaults to 30 days, swallows retention errors - [x] `just qa` clean — typecheck across 4 packages, Biome check + format, 1612 server tests pass (2 pre-existing failures on `main` unrelated to NF-4) - [x] Route registration: `GET /flows/runs` is registered before `GET /flows/:id` so the literal segment isn't swallowed - [x] Seeder respects the spec: never touches `source='operator'` rows; reseeds defaults when `DEFAULT_GRAPH_VERSION` bumps Closes #325
feat(flows): persistence + default graph (NF-4)
All checks were successful
qa / qa (pull_request) Successful in 4m32s
qa / dockerfile (pull_request) Successful in 9s
43126d33c7
Three new SQLite tables in `flows.db` — `flows`, `flow_runs`,
`flow_node_runs` — live alongside the existing `agents.db` / `tasks.db`
under the same state root so `CLAUDE_HOOKS_STATE_DIR` keeps tests
isolated. A baked `default-graph.json` bundle ships 18 default flows
covering every current dispatch entry point (issue.assigned,
issue.labeled, issue.closed, issue_comment.slash_command,
pull_request.*, pull_request_review.*, check_suite.completed, plus
cron / task.* / manual placeholders). Every entry compiles against
`defaultRegistry()` at test time.

Seeder (`seedDefaultFlows`) upserts on first boot and reseeds any
`source='default'` row whose `version` falls below
`DEFAULT_GRAPH_VERSION`; operator-authored rows are never touched.
The sweeper gains a Phase-4 retention pass that drops `flow_runs` +
`flow_node_runs` older than 30 days, swept every pass via an injectable
`runFlowRetention` so sweeper tests stay isolated from the real
`flows.db`.

Four read-only endpoints: `GET /flows`, `GET /flows/:id`,
`GET /flows/runs`, `GET /flows/runs/:id`. Mutations are deferred to
NF-7. Route order registers `/flows/runs` ahead of `/flows/:id` so the
literal segment doesn't get swallowed by the `:id` param.

Closes #325

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Author
Collaborator

Rebase aborted — design invalidated by main.

eb74a47 feat(flows): SQLite persistence + default graph + read endpoints (NF-4) (#352) already merged NF-4 with a different layout (flows-routes.ts, flows-db.test.ts, db.ts-hosted store) than this PR (http/handlers/flows.ts, flow-store.ts). Conflicts in default-graph.{ts,json,test.ts}, sweeper.ts, main.ts are duplicate-implementation collisions, not mechanical merges — picking either side would silently regress behaviour.

Closing recommended; #325 is already resolved on main via #352.

Rebase aborted — design invalidated by `main`. `eb74a47 feat(flows): SQLite persistence + default graph + read endpoints (NF-4) (#352)` already merged NF-4 with a different layout (`flows-routes.ts`, `flows-db.test.ts`, `db.ts`-hosted store) than this PR (`http/handlers/flows.ts`, `flow-store.ts`). Conflicts in `default-graph.{ts,json,test.ts}`, `sweeper.ts`, `main.ts` are duplicate-implementation collisions, not mechanical merges — picking either side would silently regress behaviour. Closing recommended; #325 is already resolved on `main` via #352.
Author
Collaborator

Closing as superseded by #352 which landed NF-4 first and is already on main. Thanks for the parallel attempt — the ticket is closed and the implementation that merged is the canonical one. Closing this branch to keep the PR list clean.

Closing as superseded by #352 which landed NF-4 first and is already on main. Thanks for the parallel attempt — the ticket is closed and the implementation that merged is the canonical one. Closing this branch to keep the PR list clean.
code-lead closed this pull request 2026-04-24 14:08:50 +00:00
All checks were successful
qa / qa (pull_request) Successful in 4m32s
Required
Details
qa / dockerfile (pull_request) Successful in 9s

Pull request closed

Sign in to join this conversation.
No reviewers
No milestone
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!353
No description provided.