4.4 KiB
AI-003 Strategy Snapshot durable operation
Updated: 2026-08-09
Status: IMPLEMENTED — NOT VERIFIED. Repository implementation and automated tests pass; browser, selected local model, MariaDB, restart canary and production rollout are not verified.
Revalidated execution path and root cause
The Overview button in JobDetailsDialog.tsx called candidate fit and GET /api/jobapplications/{id}/focus-plan concurrently. Opening the Focus Plan tab or pressing Regenerate called the same GET. JobApplicationsController.GetFocusPlan loaded owner-filtered job/profile/attachments, then performed four sequential model requests and wrote one AiWorkspaceNote before returning. Authorization and owner filters were present, but the browser request owned the complete workload: proxy/transport timeout or application restart lost the request, there was no stable operation ID, and refresh/double-click/cancel/retry had no durable contract. Live reproduction remains blocked; this is a confirmed code execution path, not a claimed browser reproduction.
Implemented contract
GET /api/jobapplications/{jobId}/focus-planis read-only and returns only the stable cached result or404 strategy_not_generated.POST /api/jobapplications/{jobId}/focus-plan/operationsvalidates the owner-scoped job, profile and up to four selected attachments, applies centralized Pro/privacy/capacity admission and returns202with the existing safe operation DTO/status URL.GET .../focus-plan/operationresumes the latest operation for the exact job/attachment context after navigation or refresh.- Task
strategy.snapshotstores onlyjobId|attachmentIds; job text, CV, notes, attachment text and prompts are rehydrated in the worker's owner scope and never copied intoUserOperations. - An active operation is reused. The next successful regeneration key includes the current cached-result timestamp; failed/cancelled work uses the existing safe retry API. A crash/retry overwrites the same unique
AiWorkspaceNote, not a second output row. - The handler makes one bounded structured generation request, validates the entire JSON shape before publishing, passes worker cancellation, records actual provider/model/route metadata and rejects embedded source instructions. Job text, profile text, structured profile and extracted attachment context have explicit ceilings.
- UI states cover queued, local processing, retry wait, approved-fallback wait, completed, failed, cancelled and cancellation requested, with cancel/retry actions. A request-version guard prevents a stale resume lookup from erasing a newly queued operation.
- The existing generic terminal notification is produced transactionally by the operation store. No email is sent.
strategy.snapshot is not in the external fallback allowlist, so it remains local-only even when a user has external consent. The worker switch remains off by default pending the production canary.
Automated evidence
- Focused backend Strategy/cache/queue/policy tests: 34/34.
- Strategy UI focused suite: 6/6.
- Full backend: 592/592.
- Full frontend: 47/47 suites, 160/160 tests.
- Frontend production build and
git diff --check: pass; line-ending notices only. - Tests use SQLite and fake model output. They cover 202/idempotent duplicate click, typed handler success/provenance, one stable result, malformed response/retry state/no partial output, owner isolation, queued/cancelled/failed/retry UI states and cached-result refresh.
Remaining gates
- Browser refresh, navigation, back/forward, mobile, light/dark and keyboard checks are blocked by localhost browser policy.
- No Ollama model, external provider, private CV, production service or paid API was called.
- Worker/model restart and lease recovery are proven generically by AI-001 tests but not run with a real Strategy model.
- MariaDB execution, production queue telemetry, selected-model timeout/quality benchmarks, notification navigation and deployment rollback remain unverified.
- Cross-feature monthly token/cost accounting remains incomplete; the durable operation row prevents duplicate work and records execution provenance, but is not a billing ledger.
Rollback
Keep Workers:AiOperationsEnabled=false, revert commit a621226, and retain the additive operation/note tables. No dependency, schema or migration changed. Any already queued strategy.snapshot rows should be cancelled or drained before removing the handler.