Skip to content

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 an ApplicationRun, seeds step labels from WorkdayAutomationEngine.StepLabels (:48), logs "Run started", returns. It never opens a browser or calls OpenApplicationAsync/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/ CodexPageAdvisor exist but are never wired; StubCodexAdvisorTransport.SendAsync throws NotImplementedException (Automation/Advisor/CodexPageAdvisor.cs:65). No engine references the advisor.
  • AtsKind is detected but never routes. No switch (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/.
  • AtsKind enum is missing families with engines: Oracle, Dayforce, SuccessFactors, Paycor, Microsoft (JobPosting.cs:94). AtsDetector detects 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/AnswerResolver registered (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.E2Eempty 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

  1. Queue resync 409-conflict handling (real branching, zero tests).
  2. Connections connect flows — Google/GitHub/LinkedIn all untested (mock even hides the LinkedIn 2-arg contract).
  3. Applied .ics download/email + Google-Calendar button — wired in the component, zero tests.
  4. Data & Backup Tier-0 folder mirror — untested.
  5. Onboarding structured address + Drive opt-in — untested (spec only checks step arithmetic).
  6. 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 UnconfiguredGoogleTokenProvider as the DI-registered provider "today" — it's GoogleOAuthService now (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)

  1. 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 shared IApplyAutomationEngine contract + promote engines behind it. c. Extend AtsKind (Oracle/Dayforce/SuccessFactors/Paycor/Microsoft) + AtsDetector. d. Add an AtsKind → engine router; make ApplicationRunService actually drive the selected engine. e. Register the IPageAdvisor/IAdvisorTransport seam and call it at the judgement pause. f. Integration-test the whole vertical against the fake sites (fields filled, submit located-not-clicked).
  2. Fill the ABSENT backend tests (GoogleOAuth/GitHubOAuth/ClaudeCli) and the THIN ones.
  3. Fill the frontend gaps (queue 409, connect flows, applied .ics/gcal, folder mirror, onboarding, vault lock).
  4. Make the Electron E2E real (reference the API; exercise boot→connections→queue→onboarding).
  5. Confirm Stryker scope covers the new auth/vault/scraper code; raise thresholds.
  6. Bring the making-of journal + connection/SSO diagrams current.
  7. Decide on the 8 unreachable endpoints: wire UI or remove.