Skip to content

Making Of — Fleet Mission Control

LIVING DOCUMENT. A journal of how this repo actually got built, including the parts that didn't go cleanly the first time. Newest entries at the bottom; update this file, don't replace it, when more lands. Companion: ../plain/making-of.md — the same story without jargon.

Ground rule for this file: every claim about "what happened" is checked against git log / git show / the repo's own BUILD-REPORT-*.md files before it goes in. If something can't be confirmed against the actual commit history or diff, it's marked as such rather than smoothed over.


2026-07-15 — FLT-14: responsive postures, a real bug, and a lint backlog

The three commits, in the order they actually landed

Verified via git log --oneline on master at c75883a:

  1. 774261efeat(frontend): add iPhone safe-area and Fold spanned postures
  2. 0b8d416fix(frontend): clear 12 pre-existing ESLint errors surfaced by first CI run
  3. 236a73ffix(frontend): fix dead Fold two-pane layout + safe-area overflow in status-wall
  4. c75883afeat(FLT-14): make cockpit backend origin configurable at runtime

One correction to make up front: the FLT-14 ticket that spawned this documentation pass described 236a73f as covering "postures + 12 pre-existing lint errors cleared by the repo's first-ever CI run" in one breath. Having actually opened git show on both commits, that's two separate commits with two separate causes — 0b8d416 is the lint cleanup, 236a73f is the posture fix, and they landed 24 minutes apart. Recording it correctly here rather than perpetuating the conflation, per the whole point of this file.

774261e — the feature ships, with an honest gap in its own commit message

This commit added two device postures to status-wall.component.ts: safe-area insets for notch/Dynamic-Island-class phones, and a @media (horizontal-viewport-segments: 2) block meant to handle a foldable phone spanning its hinge. Worth noting: the commit's own message already flagged the risk. Its final paragraph reads (verbatim from git show 774261e):

Verified in-browser: 3-pane desktop, 2-pane mid, and phone card-stack layouts render correctly at 1280px/900px/440px/360px widths (screenshots). NOT verified: safe-area inset and viewport-segment behavior, which no desktop browser emulator can produce — those need real hardware.

So this was not a case of a developer claiming full coverage they didn't have — the commit was honest about what a desktop browser can and can't prove. The gap was structural: nothing in the toolchain available at the time could emulate Device Posture or CSS viewport segments, so the segment-specific code path shipped un-exercised by anything except code review.

236a73f — the gap became a real, shipped defect

An independent review (the commit message credits "an independent Codex review," corroborated against the CSS Device Posture spec and Chrome's own implementation notes) caught something the screenshots in 774261e could never have caught: the segments media query doesn't fire for the case it was written to handle.

The mechanics, read directly out of git show 236a73f's message and the resulting doc comment in status-wall.component.ts: @media (horizontal-viewport-segments: 2) only matches when the OS reports Device Posture folded — the phone physically bent into a book/tent/laptop angle. An unfolded, flat foldable (a Pixel Fold opened out flat, used like a small tablet) reports posture continuous and exactly one segment. The query never matches for that device in that state. Before the fix, the code fell through to the container-query breakpoint for a phone-sized card stack — so an unfolded Fold, which has a tablet-sized screen, got the cramped single-column phone layout. That's the exact scenario the segments block was written to prevent, landing anyway, because the block was scoped to the wrong posture.

The fix itself didn't touch the segments block's logic — it left that block in place, correctly scoped to genuinely folded/spanned devices, and instead fixed the width-based breakpoint that should have been carrying the unfolded case all along: the dual-pane floor moved from 699px down to 599px, anchored to Google's published large-screen width classes (compact <600dp, medium 600–840dp, expanded ≥840dp) instead of a guessed device-specific pixel number. The commit message is explicit that the Fold's actual unfolded CSS viewport width in px was still unconfirmed at fix time, and deliberately avoids hardcoding it.

The part worth sitting with: by the numbers, this shipped clean. The 774261e commit message reports screenshots at four widths and states in-browser verification. The 236a73f fix commit reports 95/95 tests passing across 11 files and ng lint clean, on top of new screenshots at 440px/620px/700px/1280px specifically confirming the 620px case moved from card-stack to dual-pane. Every automatable signal was green at every step. None of it could exercise Device Posture or viewport segmentation, because the available tooling (browser test runners, desktop screenshot tooling) has no way to emulate either — that's stated directly in both commit messages, not an excuse constructed after the fact. The defect was invisible to every gate this repo had, and was only caught because a second reviewer checked the segments block's logic against the actual CSS spec instead of trusting that green tests + screenshots meant the feature worked on the hardware it was built for.

The lesson this repo is trying to hold onto: a green CI run and a screenshot are evidence the code didn't crash and rendered something at the widths you could test — they are not evidence a capability-gated code path fires under the actual capability it's gated on. When a feature depends on a signal your test environment structurally cannot produce (Device Posture, real GPS, actual push notification delivery, etc.), the commit message should say so plainly — as 774261e's did — and that gap should get flagged for a second pair of eyes before it's treated as done, not after a device in the field turns out to be broken.

0b8d416 — 12 lint errors, and why they surfaced now

Between the two posture commits, 0b8d416 cleared 12 ESLint errors. Per its commit message: this repo had just gotten its first remote, so npx ng lint ran in CI for the first time — and surfaced 12 errors that, per the commit message, were confirmed pre-existing on master (checked via stash + re-lint against the base commit, independent of the branch's own changes), not newly introduced. The fixes were mechanical: an unused import, an Array<T>T[] style fix, and replacing nine any casts in fleet-live.service.spec.ts with real or unknown types. Not part of the posture story, but worth recording as its own fact: a repo's first CI run is often the first time lint has ever actually gated it, and a backlog like this is a normal, boring consequence of that — not a regression.

c75883a — runtime backend origin

The last commit before the first documentation pass. Added frontend/src/app/core/runtime-config.ts so a host embedding the cockpit (VS Code webview, Antigravity, VS 2026 WebView2) can inject window.__FLEET_CONFIG__.apiBaseUrl before the bundle boots, and wired that value into the existing NSwag-generated FLEET_API_BASE_URL token (app.config.ts) plus the hand-built SignalR hub URL in fleet-live.service.ts — the one URL in the frontend that wasn't already flowing through the generated client. See ARCHITECTURE.md §10 for the file:line detail. Default (no host config set) behavior is byte-for- byte unchanged: apiBaseUrl resolves to '', same-origin, matching the pre-existing dev-proxy setup.

The FLT-14 documentation pass

Written in worktree fleet-mission-control-wt0026f on branch wt/WT-0026/FLT-14-docs, cut from master at c75883a. Every architectural claim was checked against source actually opened in that session — Program.cs, FleetHub.cs, FleetPollingService.cs, ApiModels.cs, status-wall.component.ts, fleet-live.service.ts, fleet-store.service.ts, runtime-config.ts, app.config.ts, app.ts, index.html, ngsw-config.json, manifest.webmanifest, nswag.json, and .github/workflows/ci.yml — not inferred from file names or directory structure. The three Mermaid diagrams written then were syntax-checked with mermaid.parse() before being committed.


2026-07-18 — FLT-120 / FLT-122 / FLT-125 / FLT-130-131: four features in one day, three sequential worktrees

Verified via git log --oneline on master at b5930a9: five commits landed on 2026-07-18, in this actual chronological order (oldest first — git log prints newest-first, so this is the reverse of what git log --oneline shows):

  1. dd3d2e3FLT-125: ARTIFACT RUN - add pptx/docx/xlsx/html/pdf artifact-run types
  2. c072839FLT-120: repo registry + pick-by-name dispatch
  3. 4395c09FLT-122: card as first-class object + session-tree queue
  4. 19d1f91FLT-125 followup: fix stale run-stream view-chip test assertion
  5. b5930a9FLT-131: unavailable-mode placement-skip + host status UX

Each of the four ticket commits has a companion BUILD-REPORT-FLT<n>.md at the repo root — this section is written directly from those reports plus the diffs they describe, the same discipline the FLT-14 entry above used.

dd3d2e3 — FLT-125: DESIGN RUN becomes ARTIFACT RUN

Built in worktree fmc-FLT125 off base 5c415e6. This extended the existing FLT-19 design-run capability/routing/dispatch/artifact pipeline (landed the day before, 2026-07-17 — 60bb555 through 1272dcf in the log above) to cover document/presentation generation, and renamed the user-facing concept from "DESIGN RUN" to "ARTIFACT RUN". The report is explicit about what stayed frozen on purpose: CapabilityRouter.LaneName, AgentRunDispatcher.SendDesign, and the DesignRunRequest/DesignJobPayload wire contract were kept unchanged — only the label and the capability set grew — specifically so no fleet-dispatch listener needed to change for this ticket to ship (BUILD-REPORT-FLT125.md).

One deliberate, disclosed shortcut: the frontend's generated API client was hand-edited, not regenerated via nswag run, because the worktree had no frontend/node_modules and the ticket's stated build/test gate was dotnet build -warnaserror + dotnet test only. The report flags this explicitly as something a follow-up should re-verify by running the real generator — worth noting here because it's the kind of gap that's easy to paper over silently and this repo's convention is not to.

Test delta: backend went from 322 to 361 tests (39 new, across CapabilityRouterTests, DesignJobPayloadTests, ArtifactStoreTests, DesignRunRegistryTests). Frontend tests were not executed in this pass (same no-node_modules reason) — also explicitly flagged, not hidden.

c072839 — FLT-120: repo registry + pick-by-name dispatch

Built in worktree fmc-FLT120, council-approved shape from a 2026-07-18 unanimous build-first decision: registry only, no live filesystem browser — a browse-any-path endpoint on the write surface was explicitly rejected as attack surface (BUILD-REPORT-FLT120.md). This is the ticket that removed the dispatch form's free-text absolute-path box; see ARCHITECTURE.md §7 for the mechanics.

Explicitly out of scope, by design: the scanner that actually populates the registry. Nothing in fleet-dispatch or fleet-harness writes repo-inventory/{PC}.json yet, so as of this commit GET /api/repos always returns an empty, unpopulated registry on every real PC — the frozen contract for that scanner lives in ../repo-registry-contract.md specifically so it can ship independently later without renegotiating the shape. Test delta: 322 → 332 backend tests (10 new, RepoRegistryReaderTests).

4395c09 — FLT-122: card as first-class object + session-tree queue

Built in worktree off origin/master, which by this point already carried FLT-120 and FLT-125 — the report opens by naming both and stating neither was touched or duplicated, the scope-discipline habit this repo's contributing.md calls out as a pattern worth following.

The interesting design call here: Card is explicitly a projection, not a new store — CardRegistry.Project builds it from the same QueuedJob/ RunSummary data /api/workers and /api/runs already expose, and BuildTree groups it server-side rather than shipping a flat list for the frontend to group — a judgment call recorded in the report as keeping parent/child logic in one well-tested (xUnit) place instead of duplicating it in TypeScript.

One test failure surfaced and was investigated rather than silently ignored: run-stream.component.spec.ts's "renders both view and download chips" test failed (192/193) — but the report verified, on a throwaway clean origin/master checkout, that the same test failed there too (pre-existing, caused by FLT-125's chip-text change landing the day before, unrelated to FLT-122's own diff) — and left it unfixed rather than silently absorbing an out-of-scope fix, flagging it for the next ticket instead. That flag is exactly what 19d1f91 (below) picked up.

Manual verification is recorded honestly too: the report describes standing up the worktree's API on an alternate port specifically so the real production instance on 5170 was never touched, loading the cockpit against ~52 live in-flight/finished cards, and confirming the Queue column rendered correctly with per-card chips and no console errors — then confirms the verification-only processes were stopped and the real instance was left running. Test delta: 361 → 394 backend tests (CardRegistryTests, 20 new).

19d1f91 — FLT-125 followup: the flagged test gets fixed

A one-line pickup of the gap 4395c09's report flagged: the run-stream spec asserted literal text 'view artifact', but FLT-125's chip now renders "view {filename}". Small, but worth recording as the mechanism working as intended — a build report named a known gap instead of quietly leaving a red (or falsely-passing) test, and the very next commit closed it.

b5930a9 — FLT-130/131: unavailable-PC mode

Built in worktree off 19d1f91 (so it already had FLT-120/122/125). Two tickets landed together because they're two halves of one feature — placement-skip (FLT-130, the gate) and the host-status UI + manual toggle (FLT-131) — see ARCHITECTURE.md §9 for the mechanics.

The report records an honest, load-bearing bug caught by its own test suite before it shipped: adding availability/ as a reserved subdirectory under DispatchRoot made FleetDispatchReader.ListTargets() — which enumerates every subdirectory as a "PC" — start reporting availability itself as a phantom worker. Fixed by excluding the literal directory name from that enumeration, with a regression test (Snapshot_CarriesAvailabilityOntoTheMatchingWorker) pinning the fix. This is exactly the class of bug this file's FLT-14 entry (above) warns about — a structural gap in what the code was written to handle — except this time a unit test caught it before merge, not a second reviewer after.

A genuine mid-task contract change is recorded plainly rather than smoothed into "and also": fleet-dispatch bumped its wire protocol (DispatchJob.SchemaVersion 1→2, JobClass appended to the signed canonical string) while this ticket was in flight, and the report describes updating this repo's signer mirror to match exactly, coordinated rather than discovered after the fact — the one exception in this repo's history to the "contracts are additive, not renamed" convention documented in contributing.md, because it required both sides to move together.

The report is also explicit about what's a genuine wire fact versus a client-side guess: HostAvailability carries no expiry field for auto-detected (gaming/streaming) states — there's no way it could, a game's end time is unknowable in advance — so the "available in MM:SS" countdown the UI shows is stated plainly as a client-side heuristic (a per-reason grace constant added to since), not a promise from the backend, with a note to tune or replace it if the real listener ever publishes an explicit debounce window. Test delta: 394 → 429 backend tests, 206/206 frontend (vitest stack).


This documentation pass (fmc-docs, WT-6022)

Written in worktree fmc-docs on branch wt/WT-6022/fmc-docs, cut from origin/master at b5930a9 — the tip after FLT-131. Restructured the existing single-track docs/architecture.md / docs/architecture-plain.md / docs/making-of.md into the two-track mirror tree (docs/technical/ + docs/plain/) and extended every page to cover the four 2026-07-18 features (repo registry, session-tree cards, artifact run, unavailable-mode) that landed after the FLT-14 docs pass. Every new claim in ARCHITECTURE.md was checked against source opened in this session: Program.cs, every file under Services/, Endpoints/, Security/, Contracts/, Hubs/FleetHub.cs, the relevant frontend/src/app/**/*.ts files (fleet-store.service.ts, fleet-live.service.ts, command.service.ts, command-panel.component.ts, worker-list.component.ts, session-tree-row.component.ts, design-panel.component.ts, run-stream.component.ts, status-wall.component.ts), .github/workflows/ci.yml, and all four BUILD-REPORT-FLT*.md files — not inferred from file or directory names. The new Mermaid sources under docs/diagrams/*.mmd and the two D2 C4 diagrams under docs/diagrams/c4-*.d2 (rendered to .svg with the d2 binary available in this environment) were kept as separate files precisely so a future pass can regenerate them without re-deriving the content from this markdown.