mirror of
https://github.com/MadsLorentzen/ai-job-search.git
synced 2026-11-08 07:57:40 +00:00
fix(reset): keep the framework_version frontmatter on the two files /reset profile rewrites (#532)
The full-file skeletons for 01-candidate-profile.md and
02-behavioral-profile.md started at the "#" title, while the shipped
files open with a "---" block carrying framework_version. Applied as
written, one /reset profile left both files failing
tools/check_framework_version.py ("missing 'framework_version' in
frontmatter") and invisible to tools/check_upstream_updates.py, which
records a configuration error for a file with no local version - the
fork update path every fork is sent through.
Say to keep the frontmatter block and replace only what follows, with a
note under "Profile reset" that the marker is framework data, never
candidate data. The version is not hardcoded into the skeleton, where it
would go stale on the next bump. A derived test applies each skeleton
the way the step says and asserts the shipped file's version still
parses out unchanged; it fails on master for both files.
This commit is contained in:
1 parent
a011214d60
commit
eaa73e55ab
3 files changed
+64
-7
No files matched your search
@@ -138,7 +138,9 @@ Wait for the user's response.
|
|||||||
|
|
||||||
### Profile reset
|
### Profile reset
|
||||||
|
|
||||||
**For `01-candidate-profile.md`**, replace the file content with:
|
Every skill file under `.claude/skills/job-application-assistant/` opens with a `---` frontmatter block carrying its `framework_version` marker. That marker is framework data, not candidate data: `tools/check_framework_version.py` fails a file without it, and `tools/check_upstream_updates.py` cannot compare the file against upstream. Never remove or rewrite it - the two full-file replacements below keep it and replace only what follows.
|
||||||
|
|
||||||
|
**For `01-candidate-profile.md`**, keep the file's `---` frontmatter block exactly as it is and replace everything below it with:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# Candidate Profile
|
# Candidate Profile
|
||||||
@@ -162,7 +164,7 @@ Wait for the user's response.
|
|||||||
## References
|
## References
|
||||||
```
|
```
|
||||||
|
|
||||||
**For `02-behavioral-profile.md`**, replace the file content with:
|
**For `02-behavioral-profile.md`**, keep the file's `---` frontmatter block exactly as it is and replace everything below it with:
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# Behavioral Profile
|
# Behavioral Profile
|
||||||
|
|||||||
@@ -15,6 +15,20 @@ per-file diff commands.
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- **`/reset profile` keeps the `framework_version` frontmatter on the two files it rewrites**
|
||||||
|
(`.claude/commands/reset.md` Step 3, `tests/test_reset_command.py`) - the full-file skeletons
|
||||||
|
for `01-candidate-profile.md` and `02-behavioral-profile.md` started at the `#` title, while
|
||||||
|
the shipped files open with a `---` block carrying `framework_version`. Applied as written,
|
||||||
|
one `/reset profile` left both files failing `tools/check_framework_version.py` ("missing
|
||||||
|
'framework_version' in frontmatter") and invisible to `tools/check_upstream_updates.py`,
|
||||||
|
which records a configuration error for a file with no local version to compare - the fork
|
||||||
|
update path the README sends every fork through. The step now says to keep the frontmatter
|
||||||
|
block and replace only what follows, with a note under "Profile reset" that the marker is
|
||||||
|
framework data, never candidate data; the version is not hardcoded into the skeleton, where
|
||||||
|
it would go stale on the next bump. A derived test applies each skeleton the way the step
|
||||||
|
says and asserts the shipped file's version still parses out unchanged; it fails on master.
|
||||||
|
Found while re-checking #519's class of drift.
|
||||||
|
|
||||||
- **`/reset profile` now targets the headings the shipped skill files actually have**
|
- **`/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
|
(`.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
|
targets had drifted. The `05-cv-templates.md` step anchored on a section beginning
|
||||||
|
|||||||
@@ -166,13 +166,26 @@ class TestResetCoversEveryPersonalizedSkillFile(unittest.TestCase):
|
|||||||
SKILL_DIR = REPO / ".claude" / "skills" / "job-application-assistant"
|
SKILL_DIR = REPO / ".claude" / "skills" / "job-application-assistant"
|
||||||
|
|
||||||
|
|
||||||
|
def skeleton_step(reset_text, filename):
|
||||||
|
"""(instruction sentence, fenced markdown) /reset uses to rewrite `filename` in Step 3."""
|
||||||
|
marker = f"**For `{filename}`**"
|
||||||
|
start = reset_text.index(marker)
|
||||||
|
fence_open = reset_text.index("```markdown", start)
|
||||||
|
fence_close = reset_text.index("```", fence_open + len("```markdown"))
|
||||||
|
return reset_text[start:fence_open], reset_text[fence_open + len("```markdown"):fence_close]
|
||||||
|
|
||||||
|
|
||||||
def skeleton_block(reset_text, filename):
|
def skeleton_block(reset_text, filename):
|
||||||
"""The fenced markdown /reset writes over `filename` in Step 3."""
|
"""The fenced markdown /reset writes over `filename` in Step 3."""
|
||||||
marker = f"**For `{filename}`**, replace the file content with:"
|
return skeleton_step(reset_text, filename)[1]
|
||||||
start = reset_text.index(marker)
|
|
||||||
fence_open = reset_text.index("```markdown", start) + len("```markdown")
|
|
||||||
fence_close = reset_text.index("```", fence_open)
|
def frontmatter(text):
|
||||||
return reset_text[fence_open:fence_close]
|
"""The leading `---` block of a skill file, or '' when it has none."""
|
||||||
|
if not text.startswith("---\n"):
|
||||||
|
return ""
|
||||||
|
end = text.index("\n---", 4)
|
||||||
|
return text[: end + len("\n---") + 1]
|
||||||
|
|
||||||
|
|
||||||
def h2_headings(text):
|
def h2_headings(text):
|
||||||
@@ -211,6 +224,34 @@ class TestResetTargetsTheHeadingsTheShippedFilesHave(unittest.TestCase):
|
|||||||
"## headings, in order - a reset must not rename or drop sections",
|
"## headings, in order - a reset must not rename or drop sections",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def test_full_file_skeletons_keep_the_framework_version_frontmatter(self):
|
||||||
|
# The shipped files open with a `framework_version` marker that
|
||||||
|
# check_framework_version.py requires and check_upstream_updates.py
|
||||||
|
# reads. The skeletons started at the `#` title, so one /reset profile
|
||||||
|
# left both files failing the version gate ("missing 'framework_version'
|
||||||
|
# in frontmatter") and invisible to the fork update checker. The
|
||||||
|
# instruction must say to keep the block, and the block must not be
|
||||||
|
# hardcoded into the skeleton, where it would go stale on the next bump.
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, str(REPO / "tools"))
|
||||||
|
from check_upstream_updates import get_framework_version_from_text
|
||||||
|
|
||||||
|
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")
|
||||||
|
head = frontmatter(shipped)
|
||||||
|
self.assertTrue(head, f"{filename} must ship with a frontmatter block")
|
||||||
|
instruction, block = skeleton_step(self.reset, filename)
|
||||||
|
self.assertIn("frontmatter", instruction, f"the {filename} step must say to keep the frontmatter")
|
||||||
|
self.assertNotIn("framework_version", block, "the skeleton must not hardcode a version")
|
||||||
|
# What the file looks like after the reset, applied as written.
|
||||||
|
after = head + block.lstrip("\n")
|
||||||
|
self.assertEqual(
|
||||||
|
get_framework_version_from_text(after),
|
||||||
|
get_framework_version_from_text(shipped),
|
||||||
|
f"a reset must leave {filename}'s framework_version readable and unchanged",
|
||||||
|
)
|
||||||
|
|
||||||
def test_partial_anchors_exist_in_the_files_they_target(self):
|
def test_partial_anchors_exist_in_the_files_they_target(self):
|
||||||
# (reset.md anchor phrase, file, heading the replacement must re-emit)
|
# (reset.md anchor phrase, file, heading the replacement must re-emit)
|
||||||
cases = (
|
cases = (
|
||||||
|
|||||||
Reference in new issue
Block a user