mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-11-02 13:12:50 +00:00
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:
1 parent
8dbc941642
commit
a011214d60
3 files changed
+102
-6
No files matched your search
@@ -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()
|
||||
Reference in new issue
Block a user