fix(reset): target the headings the shipped skill files actually have (#519)

* fix(reset): target the headings the shipped skill files actually have

Two of /reset profile's Step 3 targets had drifted from the files they
rewrite.

The 05-cv-templates.md step anchored on a section beginning
"**Profile statement templates", a line the guide has never contained
(its heading is "**Create 2-3 profile statement templates for your main
role types:**"), so the wipe found nothing: the user's role-tailored
profile statements, and any *[Used for: ...]* statements /setup Path A
extracted from archived applications, survived a reset that reported
success.

The 02-behavioral-profile.md skeleton used headings the shipped file
does not have ("Strongest Behavioral Traits", "How I Work Best", a
truncated "Growth Areas") and dropped "## Core Behavioral Drives" - the
assessment table /setup collects and /interview reads - so one reset
left the file's headings permanently different from every other fork's.

Anchor on the real heading and re-emit it in the replacement; carry the
shipped headings in order in the skeleton. 01-candidate-profile.md and
07-interview-prep.md were already correct. Two new tests derive both
checks from the shipped files, so a renamed heading fails until /reset
follows it; both fail on master.

* test(reset): place the heading guards above the __main__ guard so a direct run sees them

python tests/test_reset_command.py ran only the five old tests; unittest
discover imports the module and saw all seven, which is why CI was green.
Also drop the CHANGELOG's claim that /setup and /interview name the Core
Behavioral Drives table - neither does.
This commit is contained in:
Ayobami Adegoke authored and GitHub committed 2026-10-08 21:23:59 +02:00
1 parent 8dbc941642
commit a011214d60
3 files changed
+102 -6

No files matched your search

+8 -6
View File
@@ -171,11 +171,13 @@ Wait for the user's response.
## Overview
## Strongest Behavioral Traits
## Core Behavioral Drives
## How I Work Best
## Strongest Behaviors
## Growth Areas
## How You Work Best
## Growth Areas (frame positively in applications)
## Mapping to Job Posting Language
@@ -205,12 +207,12 @@ Also remove any `## Calibration from Past Applications` section, which `/setup`
Leave the rest of `04-job-evaluation.md` intact: the five scoring dimensions and their score bands, the weighting, the Language Gate, the red-flag guidance, the Company Research Checklist and cache schema, and the salary benchmark section. If `/setup` Step 3.4 ever personalizes a value not in the table above, add it here too.
**For `05-cv-templates.md`**, locate the section that begins with `**Profile statement templates` and extends through the role-specific template blocks. Replace only that section with:
**For `05-cv-templates.md`**, locate the section that begins with the line `**Create 2-3 profile statement templates for your main role types:**` and extends through the role-specific template blocks, including any statements labeled *[Used for: <company>_<role>]* that `/setup` Path A extracted from archived applications. Stop before the paragraph that begins "Statements labeled" - that is framework guidance, not candidate data. Replace only that section with:
```markdown
**Profile statement templates:**
**Create 2-3 profile statement templates for your main role types:**
<!-- Run /setup to populate role-specific profile statements -->
<!-- SETUP: These are populated based on your background -->
```
Then restore the contact block inside the file's LaTeX template to its placeholder tokens: `\name{[FIRST_NAME]}{[LAST_NAME]}`, `\address{[YOUR_ADDRESS]}{}{}`, `\phone[mobile]{[YOUR_PHONE]}`, `\email{[YOUR_EMAIL]}`, the `\extrainfo{...}` line's `[YOUR_LINKEDIN_URL]` and `[YOUR_GITHUB_URL]`, and `[YOUR_NAME]` in the `pdftitle`. Leave all other content in `05-cv-templates.md` intact.
+17
View File
@@ -15,6 +15,23 @@ per-file diff commands.
### Fixed
- **`/reset profile` now targets the headings the shipped skill files actually have**
(`.claude/commands/reset.md` Step 3, `tests/test_reset_command.py`) - two of its Step 3
targets had drifted. The `05-cv-templates.md` step anchored on a section beginning
`**Profile statement templates`, a line the guide has never contained (its heading is
`**Create 2-3 profile statement templates for your main role types:**`), so the wipe found
nothing: the user's role-tailored profile statements, and any `*[Used for: ...]*`
statements `/setup` Path A extracted from archived applications, survived a reset that
reported success. The `02-behavioral-profile.md` skeleton used headings the shipped file
does not have (`Strongest Behavioral Traits`, `How I Work Best`, a truncated `Growth Areas`)
and dropped `## Core Behavioral Drives` - the assessment table the shipped file carries - so
one reset left the file's headings permanently different
from every other fork's, with nothing to recreate the table. The anchor now names the real
heading and the replacement re-emits it; the skeleton carries the shipped headings in order.
`01-candidate-profile.md` and `07-interview-prep.md` were already correct. Two new tests
derive both checks from the shipped files, so a renamed heading fails until `/reset`
follows it; both fail on master.
- **The `/apply` host-check test derives its installed-portal hosts from the skills tree
instead of a hand-copied set** (#497, `tests/test_apply_host_check.py`) - `SHIPPED_PORTAL_HOSTS`
was six names typed into the test and nothing tied it to anything: a portal added by
+77
View File
@@ -163,6 +163,83 @@ class TestResetCoversEveryPersonalizedSkillFile(unittest.TestCase):
f"{mislabeled}",
)
SKILL_DIR = REPO / ".claude" / "skills" / "job-application-assistant"
def skeleton_block(reset_text, filename):
"""The fenced markdown /reset writes over `filename` in Step 3."""
marker = f"**For `{filename}`**, replace the file content with:"
start = reset_text.index(marker)
fence_open = reset_text.index("```markdown", start) + len("```markdown")
fence_close = reset_text.index("```", fence_open)
return reset_text[fence_open:fence_close]
def h2_headings(text):
return [line.strip() for line in text.splitlines() if line.startswith("## ")]
class TestResetTargetsTheHeadingsTheShippedFilesHave(unittest.TestCase):
"""Step 3's skeletons and anchors must name sections that exist.
Two of them drifted from the files they rewrite. The behavioral-profile
skeleton used "Strongest Behavioral Traits" / "How I Work Best" / "Growth
Areas" where the shipped file has "Strongest Behaviors" / "How You Work
Best" / "Growth Areas (frame positively in applications)", and dropped
"Core Behavioral Drives" - the structured assessment table /setup collects
and /interview reads - so one reset left the file's headings permanently
different from every other fork's. The CV-guide step anchored on a line
beginning "**Profile statement templates", which the guide has never
contained (its heading is "**Create 2-3 profile statement templates for
your main role types:**"), so the wipe found nothing and the user's
role-tailored statements survived a reset that reported success. Both are
derived here from the shipped files, so a renamed heading fails this test
until /reset follows it.
"""
def setUp(self):
self.reset = RESET.read_text(encoding="utf-8")
def test_full_file_skeletons_keep_the_shipped_headings(self):
for filename in ("01-candidate-profile.md", "02-behavioral-profile.md"):
with self.subTest(file=filename):
shipped = (SKILL_DIR / filename).read_text(encoding="utf-8")
self.assertEqual(
h2_headings(skeleton_block(self.reset, filename)),
h2_headings(shipped),
f"/reset's skeleton for {filename} must carry exactly the shipped "
"## headings, in order - a reset must not rename or drop sections",
)
def test_partial_anchors_exist_in_the_files_they_target(self):
# (reset.md anchor phrase, file, heading the replacement must re-emit)
cases = (
(
r"locate the section that begins with the line `([^`]+)`",
"05-cv-templates.md",
),
(
r"The entire `([^`]+)` section",
"07-interview-prep.md",
),
)
for pattern, filename in cases:
with self.subTest(file=filename):
match = re.search(pattern, self.reset)
self.assertIsNotNone(match, f"reset.md no longer states its anchor for {filename}")
anchor = match.group(1)
shipped = (SKILL_DIR / filename).read_text(encoding="utf-8")
self.assertIn(
anchor,
shipped,
f"/reset anchors {filename} on {anchor!r}, which the shipped file does not contain - "
"the wipe would silently find nothing",
)
# The replacement block re-emits the anchor line so the heading survives the wipe.
step = self.reset[match.start():]
block_start = step.index("```markdown") + len("```markdown")
block = step[block_start: step.index("```", block_start)]
self.assertIn(anchor, block, f"the replacement for {filename} must keep the heading {anchor!r}")
if __name__ == "__main__":
unittest.main()