Skip to content

refactor(core,cli): unified watch coordinator behind one seam, two adapters - #212

Merged
tonyketcham merged 2 commits into
mainfrom
stack/tonyketcham/feat/unified-watch-effort-graph/unified-watch-coordinator-behind-one-seam-two--92f7ac79
Jul 18, 2026
Merged

tonyketcham merged 2 commits into
mainfrom
stack/tonyketcham/feat/unified-watch-effort-graph/unified-watch-coordinator-behind-one-seam-two--92f7ac79

Conversation

@tonyketcham

Copy link
Copy Markdown
Collaborator

Watch policy existed twice: liveServer.ts fused the Apollo
generation-swap with a watch coordinator (parcel subscription,
picomatch matchers, 150ms coalescing over closed-over mutable state,
config reload, codegen refresh) testable only through a real
filesystem watcher; codegen's watchAndGenerate ran a second legacy
loop (chokidar, a regenerating mutex that silently DROPPED events
arriving mid-regeneration, its own config reload, full schema
rebuild).

New packages/core/src/watch/coordinator.ts owns the policy — interface:
file events in → committed/rejected generations out. It handles
classification (config globs → classifyPath → document globs),
debounced coalescing with delete-wins semantics, single in-flight
build with mid-build events QUEUED (fixes the legacy drop), config
replacement with matcher recompilation, reindex calls, codegen
scheduling, and per-phase rejection isolation (build errors never kill
the loop). Subscribers get monotonic WatchCoordinatorResult events —
the seam the effort-graph committed-generation bridge wires into next.

Home is core by dependency direction: flatbread depends on codegen,
so neither could host a module both consume; core has zero @flatbread
deps and owns classifyPath. Codegen scheduling stays an injected hook,
so core imports nothing new.

Both former loops are now thin adapters (two adapters = the seam is
real): startGraphqlServer keeps parcel plumbing + the Apollo swap —
swap mechanics byte-untouched, all 7 liveServer AVA tests green
unmodified — and watchAndGenerate keeps chokidar + kleur output but
delegates all policy. docs/local-dev-loop.md now documents the single
flatbread start --watch loop instead of two terminals.

Test plan: 12 new coordinator AVA unit tests driven entirely by
synthetic events via an injectable scheduler (classification routing,
coalescing, config-change rebuild, queueing during in-flight builds,
rejected-generation recovery, codegen scheduling, idle-flush
regression); liveServer suite unchanged; watch-patterns vitest suite
green. Full suite: pnpm verify (271 AVA + 52 vitest).

Co-authored-by: Cursor cursoragent@cursor.com

Depends-On: #211

…apters

Watch policy existed twice: liveServer.ts fused the Apollo
generation-swap with a watch coordinator (parcel subscription,
picomatch matchers, 150ms coalescing over closed-over mutable state,
config reload, codegen refresh) testable only through a real
filesystem watcher; codegen's watchAndGenerate ran a second legacy
loop (chokidar, a `regenerating` mutex that silently DROPPED events
arriving mid-regeneration, its own config reload, full schema
rebuild).

New packages/core/src/watch/coordinator.ts owns the policy — interface:
file events in → committed/rejected generations out. It handles
classification (config globs → classifyPath → document globs),
debounced coalescing with delete-wins semantics, single in-flight
build with mid-build events QUEUED (fixes the legacy drop), config
replacement with matcher recompilation, reindex calls, codegen
scheduling, and per-phase rejection isolation (build errors never kill
the loop). Subscribers get monotonic WatchCoordinatorResult events —
the seam the effort-graph committed-generation bridge wires into next.

Home is core by dependency direction: flatbread depends on codegen,
so neither could host a module both consume; core has zero @flatbread
deps and owns classifyPath. Codegen scheduling stays an injected hook,
so core imports nothing new.

Both former loops are now thin adapters (two adapters = the seam is
real): startGraphqlServer keeps parcel plumbing + the Apollo swap —
swap mechanics byte-untouched, all 7 liveServer AVA tests green
unmodified — and watchAndGenerate keeps chokidar + kleur output but
delegates all policy. docs/local-dev-loop.md now documents the single
`flatbread start --watch` loop instead of two terminals.

Test plan: 12 new coordinator AVA unit tests driven entirely by
synthetic events via an injectable scheduler (classification routing,
coalescing, config-change rebuild, queueing during in-flight builds,
rejected-generation recovery, codegen scheduling, idle-flush
regression); liveServer suite unchanged; watch-patterns vitest suite
green. Full suite: pnpm verify (271 AVA + 52 vitest).

Co-authored-by: Cursor <cursoragent@cursor.com>
Change-Id: I92f7ac7914952a0d5c42952f192ee7e0f187f004
@tonyketcham

tonyketcham commented Jul 17, 2026 •

Copy link
Copy Markdown
Collaborator Author

This pull request is part of a Mergify stack:

# Pull Request Link
1 docs(effort-graph): add Effort Graph glossary and ADRs 0001-0007 #205
2 feat(core,cli): unified watch with incremental reindex and live schema swap #206
3 feat(effort-graph): journaled semantic writer for the Effort Graph #207
4 refactor(config): loadConfig returns an initialized LoadedFlatbreadConfig #208
5 refactor(core): single Record-production module owns file→Record and path classification #209
6 refactor(effort-graph): per-mutate snapshot + Decision lifecycle module #210
7 refactor(core): collection query executor owns filter/sort/paging with copy-on-output #211
8 refactor(core,cli): unified watch coordinator behind one seam, two adapters #212 👈
9 refactor(core): per-build schema composer; delete the config-keyed schema cache #213
10 feat(effort-graph,flatbread): committed-generation bridge completes the ADR-0003/0004 contract #214
11 chore(core): drop unused graphql-compose-json and lru-cache dependencies #215
12 test: raise AVA concurrency now that the global-composer pin is obsolete #216
13 docs(agents): define orchestrator-executor operating model #217

@tonyketcham

Copy link
Copy Markdown
Collaborator Author

@Mergifyio queue

@mergify

mergify Bot commented Jul 18, 2026 •

Copy link
Copy Markdown
Contributor

Merge Queue Status

  • ✅ Entered queue — 2026-07-18 08:36 UTC · Rule: owner-bypass · triggered by @tonyketcham with the @mergifyio queue command
  • ✅ Checks passed · in-place
  • ✅ Merged — 2026-07-18 09:10 UTC · at 3f8efdd8adcd08cf63eb93f734484ecad7f33ec0

This pull request spent 34 minutes 7 seconds in the queue, including 4 minutes 1 second running CI.

Required conditions to merge
  • author = tonyketcham
  • check-success = build (20.x, ubuntu-latest)
  • check-success = build (22.x, ubuntu-latest)
  • check-success = integration-nextjs (20.x, macos-latest)
  • check-success = integration-nextjs (20.x, ubuntu-latest)
  • check-success = integration-nextjs (20.x, windows-latest)
  • check-success = integration-nextjs (22.x, macos-latest)
  • check-success = integration-nextjs (22.x, ubuntu-latest)
  • check-success = integration-nextjs (22.x, windows-latest)
  • check-success = integration-sveltekit (20.x, macos-latest)
  • check-success = integration-sveltekit (20.x, ubuntu-latest)
  • check-success = integration-sveltekit (20.x, windows-latest)
  • check-success = integration-sveltekit (22.x, macos-latest)
  • check-success = integration-sveltekit (22.x, ubuntu-latest)
  • check-success = integration-sveltekit (22.x, windows-latest)
  • check-success = lint (20.x, ubuntu-latest)
  • check-success = lint (22.x, ubuntu-latest)
  • check-success = test (20.x, ubuntu-latest)
  • check-success = test (22.x, ubuntu-latest)
  • depends-on = FlatbreadLabs/flatbread#211 [⛓️ refactor(core): collection query executor owns filter/sort/paging with copy-on-output #211]

@mergify mergify Bot added the queued label Jul 18, 2026
Base automatically changed from stack/tonyketcham/feat/unified-watch-effort-graph/collection-query-executor-owns-filter-sort-paging--f0e0928c to main July 18, 2026 09:05
…graph/unified-watch-coordinator-behind-one-seam-two--92f7ac79
@tonyketcham
tonyketcham merged commit 60e706c into main Jul 18, 2026
19 checks passed
@tonyketcham
tonyketcham deleted the stack/tonyketcham/feat/unified-watch-effort-graph/unified-watch-coordinator-behind-one-seam-two--92f7ac79 branch July 18, 2026 09:10
@mergify mergify Bot removed the queued label Jul 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant