Skip to content

gh-#401 PR-1: OrchestratorBuilder front door, root NoOp resolution, frozen characterisation replay (STORY-451/452) - #805

Merged
genwave-radio merged 7 commits into
mainfrom
test/orchestrator-front-door-451
Sep 17, 2026
Merged

genwave-radio merged 7 commits into
mainfrom
test/orchestrator-front-door-451

Conversation

@genwave-radio

@genwave-radio genwave-radio commented Sep 17, 2026 •

Copy link
Copy Markdown
Collaborator

🚪 gh-#401 PR-1 — the front door (STORY-451, STORY-452)

Part of #401 (Orchestrator split) and #772. Zero behaviour change; this PR builds the proof harness the later seam PRs are measured against.

What

  • 🧰 tests/GenWave.TestSupport — OrchestratorBuilder + the 15 harness fakes, one With<Seam> per constructor parameter. Every Orchestration.Tests and Host.Tests site now constructs the Orchestrator through it; duplicate fakes deleted.
  • 🏭 AddGenWaveOrchestration registers INextItemProvider through a resolve-time factory: optional seams are read once at first resolve, so the Program.cs overrides that run after it still win. The five seams with a NoOp type coalesce to it; the other ten pass null through unchanged.
  • 📌 Story451_ConstructionPins pins the only two new Orchestrator( sites (the builder and the factory).
  • 🧊 Story452_BreakCharacterisationReplay + Story452_PinnedTables — one fixed script (SPEC F185.1) served through the unsplit Orchestrator; buffer order by media id, DjName stamps, event kinds and WARN lines pinned as literals. Frozen for the rest of the epic; only PR-3 (T522) may touch the file, and only to un-skip the trace fact.
  • 🔴 The red specs for STORY-451–460 ride this PR (fc7bf63); every remaining skip starts pending: T<n>.

Proof

  • Full solution green (Category!=Integration): Orchestration 462 / 100 skipped (epic pendings only), Architecture 172 / 12, Host 3075 / 15, all other suites unchanged.
  • Dev station cycled on this branch's image and on v5.9.0 (main) for one hour each; station.booth_log kind histograms:
kind main hour branch hour
track-started 42 39
patter-aired 29 27
↳ BackAnnounce / LeadIn / StationId 13 / 13 / 3 12 / 12 / 3

Same kind set on both; the count gap is one track boundary (about one track per 85 s). Windows: main 21:30–22:30Z on v5.9.0 (3678269), branch 20:20–21:20Z on 6861b34; the station is back on the branch image.

Not in this PR

No plan/render/deliver split yet (PR-2 onward). No #772 speaker snapshot yet.

Fourteen pending spec files for the Orchestrator split (F184–F193) and the
speaker snapshot (gh-#772, F189): Orchestration.Tests 451–459, Tts.Tests 456,
Host.Tests 456, Architecture.Tests 451/456/460. Every new fact is
[Fact(Skip = "pending: T<n> …")] with a loud body; /build-loop turns them
green one task at a time. STORY-461 (landing) is manual and carries no spec.
A support classlib (IsTestProject=false, no test SDK) that will hold
OrchestratorBuilder and the fakes it needs (SPEC F184.1). Referenced by
Orchestration.Tests, Host.Tests and Architecture.Tests; the STORY-451 AC8
fact now reflects the assembly and pins that it carries no [Fact].
…tSupport (gh-#401)

One With<Seam>(...) per Orchestrator constructor parameter; Build() returns
OrchestratorChain (Orchestrator, deferral queue, time provider, tts, event
sink, logger, catalog, patter estimator) with slots typed to the seam so any
valid override compiles and builds. Defaults mirror ProductionChainHarness
parameter-for-parameter, so nothing shifts behaviourally; the harness stays
in place for T512. The 15 fakes the harness uses move to
GenWave.TestSupport.Fakes as public types; Orchestration.Tests picks them up
through global usings, Host.Tests does not until T513 removes its duplicates.
Story451 AC1/AC2 go green; remaining skips are retagged to T512/T514.
…tratorBuilder (gh-#401)

ProductionChainHarness.BuildProductionChain keeps its signature and record
but is now a builder call, and the 32 inline `new Orchestrator(` sites in 27
spec files (including the four local harness copies in Story241/243/307/309)
pass the same arguments through the matching With* seams. No assertion,
arrange value, or test name changes; seams a site never passed keep the
builder default only where that default is provably inert against the
Orchestrator's reads. Story451 AC3 pins the harness unit order; AC9 pins the
reflected fact count (556 methods, 562 runner cases) and that every skip is
an epic pending. `new Orchestrator(` no longer appears in this project.
… fakes deleted (gh-#401)

The four `new Orchestrator(` sites in Story012, Story102 (two) and Story139
pass the same arguments through the builder's With* seams; the instances
each fact later mutates or observes (scope provider, render budget, tts,
clock) are the ones the Orchestrator holds. Host.Tests' own
FakeRenderBudgetProvider and FakeBoundaryBiasProvider were shape-identical
to the TestSupport copies and are removed; Story139 now resolves the
TestSupport one through a per-file using (no global using, so Host.Tests'
other same-named fakes keep winning by enclosing namespace). Story451 AC5
pins the TestSupport reference and the two files' absence.
…al seams once (gh-#401)

INextItemProvider is now a factory registration: every Orchestrator
seam is read inside the lambda at first resolve, so the Program.cs
overrides that run after AddGenWaveOrchestration (persona pick,
request fulfillment, event sink, context settings, ad vend) still win.
The five seams with a NoOp type coalesce to it; the other ten pass a
null through to the Orchestrator's existing null handling.

Story451 AC4 pins the two `new Orchestrator(` sites by text scan
(OrchestratorBuilder + this factory); AC6/AC7 resolve the provider
through a real ServiceCollection with and without a registered vend.
Orchestration.Tests gains Microsoft.Extensions.DependencyInjection
for BuildServiceProvider. Story460's comment reworded so the scan
does not hit it.
…t the unsplit Orchestrator (gh-#401)

One fixed script (SPEC F185.1) served unit by unit through
OrchestratorBuilder: announcements, vended crosstalk, ad, station id,
context segment, an over-budget sign-off, a straddling show boundary
with held sign-on, a null render, time/date on-time/late/expired, and
a ceremony-only finale. Buffer order by media id, DjName stamps, event
kinds and WARN lines are pinned as literals in Story452_PinnedTables.

The assertions are frozen for the rest of the epic; only PR-3 (T522)
may touch the file, and only to un-skip the trace fact.

Story451 AC9 no longer pins a skip count that every epic task moves;
it asserts zero skips outside the STORY-451..459 pendings.
@genwave-radio
genwave-radio merged commit 0ee3c32 into main Sep 17, 2026
11 checks passed
@genwave-radio
genwave-radio deleted the test/orchestrator-front-door-451 branch September 17, 2026 23:50
@github-actions github-actions Bot locked and limited conversation to collaborators Sep 17, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant