You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up from the #127 segmentation spike (docs/segmentation-spike.md), under epic #109. PR 1 of the sequence — the provably-inert proof.
Goal
Promote the section structure the cascade already computes (PdfSection[] in buildHeuristicResult, openresume.ts:166) into a typed SectionedResume field on CascadeResult, and use it to retire the skillsSectionText side-channel end to end.
Why
The scorer can't answer "is this line a skill?" so the cascade hands it a hand-serialized slice (skillsSectionLines → skillsSectionText → buildSkillsExclusion). That slice is a fragment of the section structure the cascade already had and threw away. Promote the structure; delete the side-channel. This is the smallest end-to-end proof that the model works (spike §3).
Scope (Option A, minimal slice — see spike §3)
Add SectionedResume type ({ byName: ReadonlyMap<SectionName|"profile", string[]>, accomplishmentSections, source }) + a toSectionedResume(sections, source) builder.
buildHeuristicResult returns sections on HeuristicResult; cascade carries it onto both CascadeResult builders (cascade.ts:198, :408).
computeAnonymousAtsScore derives the skills-exclusion set from input.sections.byName.get("skills") instead of skillsSectionText.
DeleteCascadeResult.skillsSectionText (types.ts:189), AnonymousAtsScoreInput.skillsSectionText (score.ts:532), HeuristicResult.skillsSectionLines build (openresume.ts:294), and the two cascade spreads.
skillsSectionText no longer exists in the codebase.
Corpus goldens (24 .expected.json) are UNCHANGED — this is behavior-preserving. Regenerating goldens would mask a regression; a clean diff is the pass condition.
Follow-up from the #127 segmentation spike (
docs/segmentation-spike.md), under epic #109. PR 1 of the sequence — the provably-inert proof.Goal
Promote the section structure the cascade already computes (
PdfSection[]inbuildHeuristicResult,openresume.ts:166) into a typedSectionedResumefield onCascadeResult, and use it to retire theskillsSectionTextside-channel end to end.Why
The scorer can't answer "is this line a skill?" so the cascade hands it a hand-serialized slice (
skillsSectionLines→skillsSectionText→buildSkillsExclusion). That slice is a fragment of the section structure the cascade already had and threw away. Promote the structure; delete the side-channel. This is the smallest end-to-end proof that the model works (spike §3).Scope (Option A, minimal slice — see spike §3)
SectionedResumetype ({ byName: ReadonlyMap<SectionName|"profile", string[]>, accomplishmentSections, source }) + atoSectionedResume(sections, source)builder.buildHeuristicResultreturnssectionsonHeuristicResult; cascade carries it onto bothCascadeResultbuilders (cascade.ts:198,:408).computeAnonymousAtsScorederives the skills-exclusion set frominput.sections.byName.get("skills")instead ofskillsSectionText.CascadeResult.skillsSectionText(types.ts:189),AnonymousAtsScoreInput.skillsSectionText(score.ts:532),HeuristicResult.skillsSectionLinesbuild (openresume.ts:294), and the two cascade spreads.App.tsx:52,useResumeAnalysis.ts:99,corpus.test.ts:108; reshapescore.test.tsSkills section scored with experience-bullet rules (action verb / metric / length) #30 tests (:503-:520,:542).Acceptance
skillsSectionTextno longer exists in the codebase..expected.json) are UNCHANGED — this is behavior-preserving. Regenerating goldens would mask a regression; a clean diff is the pass condition.Notes
Refs #127, #109.