Skip to content

WW-99 Result — HonestyGuard trust anchor

Tailored-resume choke point

The job-specific path is:

IDocumentService.GenerateAsync / RegenerateAsync → DocumentService.GenerateAsync → IClaudeDrafter.DraftDocumentsAsync → ClaudeDrafter.TryDraftWithLlmAsync → ILlmHarness.GenerateAsync.

The point of no return is ClaudeDrafter.TryDraftWithLlmAsync, immediately before BuildProfileBlock assembles the profile and the resulting prompt is sent to the selected ILlmHarness. The generation path calls HonestyGuard.FilterMaterialSkills(intake.SkillRecords) once and gives those Prove-derived names absolute precedence.

SkillRecord had no production consumer before this ticket; the existing tailoring prompt read only legacy IntakeProfile.TopSkills strings. The council bridge now routes those strings around the Prove-only filter through a separate UnverifiedLegacy prompt channel while typed Prove records use ProvenMaterial. The two channels never blend: any Prove material wins outright and legacy strings are ignored.

The UnverifiedLegacy block labels its values as legacy free text that is not Prove-validated and instructs the model to use only the exact strings, never invent supporting evidence, never upgrade confidence, and omit rather than embellish a weak match.

Filter

HonestyGuard.FilterMaterialSkills keeps a record only when at least one ProveItem has a nonblank RefId. Claim-only, Aspire-only, hollow Prove items, and in-progress-study-plan-claim-only records are removed unconditionally. Missing, null, or malformed Prove data fails closed. The WW-97 compile-time [Obsolete(error: true)] lock is removed now that the implementation and production call site are real.

Legacy TopSkills are never passed to that method or converted into SkillRecord.

The top-level drafting flag drafting.skillsProveOnlyStrict (FeatureFlags.SkillsProveOnlyStrict) defaults OFF. OFF enables only the explicitly unverified legacy bridge when no Prove records exist. ON omits legacy skills; if nonblank legacy skills were present, GeneratedDocuments.Warnings carries: “Skills omitted: none have Prove evidence yet. Add verified skills in Skills & Growth, or leave strict mode off until then.” A genuinely empty profile produces neither a skills block nor a warning.

The review-fix round closes four additional silent-failure paths:

  • the documents UI renders every generated warning as a warning banner;
  • a feature-flag read failure fails closed to strict mode and adds the distinct warning “Could not read drafting settings; skills section may be incomplete.”;
  • hollow Prove items no longer count as evidence, and a null skill list returns empty;
  • Prove-backed records with blank names fall through to the legacy/strict selection path instead of suppressing all visible skill content.

Honest education language

The same tailored prompt assembly now renders every EducationEntry.InProgress credential with the centralized approved phrase DegreeAdvisorCopy.DegreeInProgress ("Degree in progress"), so it cannot imply completion.

No study-plan skill prompt template exists beyond the new SkillRecord seam. The explicit in-progress study-plan test proves such a Claim-only record never reaches the prompt; a future consumer must use the same Prove-only gate and may describe unproved work only as studying or working toward it, never as present competency.

Degree-advisor copy gate

DegreeAdvisorCopy establishes a centralized, extensible approved-strings catalog with evidence-calibrated education-screen, requirement-progress, and degree-in-progress wording. DegreeAdvisorCopyTests scans every approved string against an extensible banned-phrase data set: unlocks, guarantees, and qualifies you for the job, using case-insensitive substring checks.

API shape

The new IntakeProfile.SkillRecords seam preserves SkillRecord's three distinct typed axes: Claim, Prove, and Aspire. No aggregate, composite, rating, or score type was introduced.

Verification

  • dotnet build WorkWingman.slnx -c Debug: exit 0; 0 errors; 22 pre-existing warnings.
  • dotnet test tests/WorkWingman.Tests/WorkWingman.Tests.csproj --filter "FullyQualifiedName~HonestyGuard|FullyQualifiedName~ClaudeDrafter|FullyQualifiedName~DegreeAdvisor": exit 0; 133 passed, 0 failed, 0 skipped.
  • frontend: npx tsc -p tsconfig.json --noEmit: exit 0; no diagnostics.
  • frontend: npm test: exit 0; 67 files passed, 1049 tests passed, 0 failed.