Merge audit + full assessment (2026-07-05)¶
Systematic read-only audit (4 parallel agents) of the codebase after ~60 feature branches merged into master, checking what got half-connected, plus test/doc coverage depth. This is the ground truth the remediation plan works from.
Headline: the apply-automation vertical is scaffolded but never connected¶
The single most severe pattern. The "apply to a job" flow is a status simulation, not real automation:
- No engine ever drives a run.
ApplicationRunService.StartRunAsync(src/WorkWingman.Infrastructure/Services/ApplicationRunService.cs:35) builds anApplicationRun, seeds step labels fromWorkdayAutomationEngine.StepLabels(:48), logs "Run started", returns. It never opens a browser or callsOpenApplicationAsync/SignInAsync/FillContactAsync/…(WorkdayAutomationEngine.cs:44,78,159…). The engine's real methods are invoked nowhere in src/ — only in the offline lab loops under tools/. - The advisor seam is fully orphaned.
IPageAdvisor+IAdvisorTransport(Core/Interfaces) are registered nowhere and consumed by nothing.ClaudePageAdvisor/CodexPageAdvisorexist but are never wired;StubCodexAdvisorTransport.SendAsyncthrowsNotImplementedException(Automation/Advisor/CodexPageAdvisor.cs:65). No engine references the advisor. AtsKindis detected but never routes. Noswitch (job.Ats.Kind)anywhere; every run hardcodes Workday step labels regardless of the job's ATS.- iCIMS & Microsoft production selectors are dead — present in src/…/Automation, consumed only by lab engines in tools/.
AtsKindenum is missing families with engines: Oracle, Dayforce, SuccessFactors, Paycor, Microsoft (JobPosting.cs:94).AtsDetectordetects only 7.- All 24 tools/WorkWingman.ScraperLab.* projects are stranded from
WorkWingman.slnx— not in the solution, not referenced by any src project, so outside the CI build graph.
ATS engine wiring gap¶
| ATS | prod selectors | prod engine | lab engine | detected | AtsKind member |
|---|---|---|---|---|---|
| Workday | ✅ | ✅ (never invoked) | — | ✅ | ✅ |
| iCIMS | ✅ (dead) | ❌ | ✅ | ✅ | ✅ |
| Microsoft | ✅ (dead) | ❌ | ✅ | ❌ | ❌ |
| Greenhouse / Lever / ADP / Paycom / UKG | ❌ | ❌ | ✅ | ✅ | ✅ |
| Oracle / Dayforce / SuccessFactors / Paycor | ❌ | ❌ | ✅ | ❌ | ❌ |
Other orphaned/half-connected seams¶
IAnswerResolver/AnswerResolverregistered (Program.cs:264) but consumed by nothing (dead — it's the deterministic sibling of the advisor, meant for the run driver that doesn't exist).IPasswordManagerHandoff/KeePassXcHandoff— live stub (always "not connected"); only referenced by the never-run Workday engine.UnconfiguredGoogleTokenProvider— not registered, but its exception type is still caught as the "Google not connected" signal in DataPortabilityService/YouTubeStudyService (brittle marker).tests/WorkWingman.E2E— empty shell: Playwright+xunit packages, no ProjectReference to the API.
Contract & type integrity (the good news)¶
- No broken frontend→backend calls; no DTO type drift across intake/connection/vault/job/studyplan.
- 8 backend endpoints are unreachable from the UI: entire FinancesController (cost-of-living, tax-estimate, compare), documents/regenerate, applications/{id}/status, applications/sync-interviews, study/enroll, interview-coaching/we-focus. Several are token-gated build-ahead surfaces, not dead.
Test coverage depth¶
Backend (xUnit)¶
- DETAILED: IcsBuilder, MsLearnCatalogSource, MediumRssSource, AppEnvironment, SandboxConfigScrubber, LinkedInJobLdParser, DataPortabilityService (Excel round-trip), KeePassVaultService (core).
- THIN: InterviewCalendarService (Gmail send path untested), LinkedInSessionConnection, DevController (IOException path comment-only), JobQueueService (enrichment pipeline untested), DataPortabilityService folder-mirror + AES-256-GCM encryption paths.
- ABSENT: GoogleOAuthService (zero PKCE/scope/HasScope/refresh tests), GitHubOAuthService (zero device-flow/poll/back-off tests), ClaudeCliConnection (zero .claude.json/CLI-state tests).
Frontend (vitest) — highest-value gaps¶
- Queue resync 409-conflict handling (real branching, zero tests).
- Connections connect flows — Google/GitHub/LinkedIn all untested (mock even hides the LinkedIn 2-arg contract).
- Applied .ics download/email + Google-Calendar button — wired in the component, zero tests.
- Data & Backup Tier-0 folder mirror — untested.
- Onboarding structured address + Drive opt-in — untested (spec only checks step arithmetic).
- Vault lock + automation-settings save — untested. Well-covered: vault create/unlock, Drive-sync confirm, study deep links. No stale specs.
Electron / E2E — smoke-only¶
tests/electron-e2e: 3 assertions (app boots, Angular loads, API reachable).tests/WorkWingman.E2E(dotnet): 6 JourneyTests against a fully stubbed API — proves routing/DTOs, not real behavior. And the project has no reference to the real API (empty shell).- No E2E exercises the real apply/connections/onboarding/vault flows.
Stryker¶
- Configs exist for WorkWingman.Tests, ScraperLab.Microsoft.Tests, and 3 lab tools + frontend.
- Recent files (GoogleOAuthService, KeePassVaultService, MsLearnCatalogSource, LinkedInJobLdParser) need confirming inside the mutation scope; likely under-covered given the ABSENT unit tests above.
Docs¶
- Dangling references (must-fix):
- Vault path wrong in 5 docs (connections-and-sso.md:11,155; architecture.md:202; overview.md:156;
plain/connections-and-sso.md:5) — they say
%USERPROFILE%\Wingman\vault.kdbx; real path is%USERPROFILE%\Desktop\WorkWingman-vault.kdbx. - 5 docs (connections-and-sso.md:18,73,105; architecture.md:199; data-backup.md:236; overview.md:155;
study-media.md:95,123) describe
UnconfiguredGoogleTokenProvideras the DI-registered provider "today" — it'sGoogleOAuthServicenow (Program.cs:206-208); the Unconfigured class survives only as an exception marker. - api-reference.md omits the 3 account-wall endpoints (
/account/check|credential|acknowledge) that exist in RunsController and are documented in ats-accounts.md. - The making-of journal is stale — current only through the YouTube/podcast section (~July 4). Missing the last week: real .kdbx vault, Google OAuth loopback, real/sandbox environments, Medium RSS, MS Learn Catalog API + study deep links, LinkedIn JSON-LD scraper rebuild, data-backup folder mirror, GitHub device flow. The design tables mention the features but not the real "how".
Remediation plan (ordered)¶
- Stand up the apply vertical against the LAB FAKE-SITES first (user-directed, safe/offline):
a. Add the ScraperLab projects to
WorkWingman.slnx(into CI build graph). b. Define a sharedIApplyAutomationEnginecontract + promote engines behind it. c. ExtendAtsKind(Oracle/Dayforce/SuccessFactors/Paycor/Microsoft) +AtsDetector. d. Add anAtsKind → enginerouter; makeApplicationRunServiceactually drive the selected engine. e. Register theIPageAdvisor/IAdvisorTransportseam and call it at the judgement pause. f. Integration-test the whole vertical against the fake sites (fields filled, submit located-not-clicked). - Fill the ABSENT backend tests (GoogleOAuth/GitHubOAuth/ClaudeCli) and the THIN ones.
- Fill the frontend gaps (queue 409, connect flows, applied .ics/gcal, folder mirror, onboarding, vault lock).
- Make the Electron E2E real (reference the API; exercise boot→connections→queue→onboarding).
- Confirm Stryker scope covers the new auth/vault/scraper code; raise thresholds.
- Bring the making-of journal + connection/SSO diagrams current.
- Decide on the 8 unreachable endpoints: wire UI or remove.