Getting started (technical)¶
Setup, running, testing, and client regeneration for fleet-mission-control.
See ARCHITECTURE.md for how the pieces fit together and
contributing.md for the branch/review workflow.
Prerequisites¶
| Tool | Version | Used for |
|---|---|---|
| .NET SDK | 10.0.x | src/FleetMissionControl.Api, tests/ |
| Node.js | 24.x | frontend/, extensions/vscode/ |
| npm | bundled with Node | package management, NSwag client generation |
| D2 | 0.7.x (optional) | regenerating docs/diagrams/*.svg |
The API reads live fleet state from a shared OneDrive-backed directory tree
(FleetPaths) and ~/.claude/usage-governor/state.json — those are
optional for local dev; every reader degrades gracefully to
empty/UNKNOWN when its source file is absent (see
ARCHITECTURE.md for the exact fallback behavior of each
reader).
Run it¶
# backend (terminal 1)
dotnet run --project src/FleetMissionControl.Api # http://localhost:5170
# frontend (terminal 2)
cd frontend && npm ci && npx ng serve --proxy-config proxy.conf.json # http://localhost:4200
The dev proxy (frontend/proxy.conf.json) forwards /api, /hubs
(websocket), and /openapi to :5170 — open http://localhost:4200, not
:5170, during frontend development.
Kestrel binds localhost plus any Tailscale (100.64.0.0/10) interface —
see ARCHITECTURE.md §1. No
LAN/public interface is ever bound.
Test¶
dotnet test # backend: xUnit, reader/parser/gate suites against temp dirs
cd frontend && npx ng test # Angular/Karma-style runner
cd frontend && npm run test:vitest # standalone vitest config — kept passing in lockstep with `ng test`;
# this is the config the Stryker mutation job drives directly
Both frontend test stacks must stay green together — CI runs both independently precisely so they can't silently drift apart.
Client regeneration (do this after any backend contract change)¶
dotnet build src/FleetMissionControl.Api # refreshes openapi/FleetMissionControl.Api.json
cd frontend && npm run generate:client # rewrites src/app/api/fleet-api.generated.ts
Commit both regenerated files. CI runs two independent drift checks — a
backend job diffs openapi/ after a clean build, and a frontend job runs
npm run check:drift (regenerate + diff) — either one fails the build if you
forget.
CI locally¶
Run the same checks the home-ci runners run before pushing:
dotnet build FleetMissionControl.slnx --no-restore -warnaserror
dotnet test FleetMissionControl.slnx --no-build
cd frontend
npx ng lint
npx ng build
npx ng test
npm run test:vitest
npm audit --omit=dev --audit-level=high
Mutation testing (dotnet tool run dotnet-stryker -- --config-file
stryker-config.json backend, npm run test:mutation frontend) and the
5×-repeat flake gate are slow — CI runs them on every push/PR, but they're
optional for a local inner loop. See
ARCHITECTURE.md §13 for the full gate list.
Diagram regeneration¶
Mermaid diagrams live inline in the markdown under docs/technical/ and
docs/plain/, with their sources mirrored under docs/diagrams/*.mmd for
independent editing — GitHub renders Mermaid natively, no build step needed.
The two C4 diagrams are rendered to committed SVG via D2:
d2 docs/diagrams/c4-context.d2 docs/diagrams/c4-context.svg
d2 docs/diagrams/c4-container.d2 docs/diagrams/c4-container.svg
Regenerate both after any change to the system's external dependencies or its container boundaries.
IDE extensions¶
extensions/vscode/ and extensions/vs2026/ each embed the built cockpit
bundle in a webview/WebView2 host and inject
window.__FLEET_CONFIG__.apiBaseUrl to point it at a live API instance —
see ARCHITECTURE.md §10.
Building the frontend bundle first is a prerequisite for both:
cd frontend && npm ci && npm run build
cd extensions/vscode && npm ci && npm run package # vsce package
extensions/vs2026/ builds via its own .csproj
(FleetMissionControl.Vs2026.csproj) with dotnet build, not the main
solution.