test(reset): let a personalized profile carry its own ## sections (#676)

* test(reset): let a personalized profile carry its own ## sections

test_full_file_skeletons_keep_the_shipped_headings compares /reset's
skeleton with the ## headings of 01-candidate-profile.md and
02-behavioral-profile.md exactly. On a fork those files are the user's
populated profile, so adding one section of their own (Certifications,
say) fails the suite on the fork's CI and in local runs, though /reset
is fine.

Off upstream (is_upstream_checkout(), as the placeholder and
template-token guards already use) the check now requires every skeleton
heading to appear in the file in order, so a renamed, dropped or
reordered template heading still fails. Upstream keeps the exact
comparison. A new test pins the in-order helper, since the fork branch
never runs in upstream CI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* changelog: place the #676 entry under [Unreleased]

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Mads Lorentzen <madslorentzen_17@hotmail.com>
This commit is contained in:
authored and GitHub committed 2026-10-19 20:06:16 +02:00
1 parent 93f37dde0b
commit a59535083f
2 files changed
+37 -1

No files matched your search

+7
View File
@@ -165,6 +165,13 @@ per-file diff commands.
path now counts as removed when its nearest ancestor directory exists at the base but not path now counts as removed when its nearest ancestor directory exists at the base but not
in HEAD; a new file or subdirectory under a directory the fork kept is still worth reviewing. in HEAD; a new file or subdirectory under a directory the fork kept is still worth reviewing.
- **The `/reset` skeleton test lets a fork's profile carry its own `##` sections** (#676,
`tests/test_reset_command.py`) - it compared `/reset`'s `##` headings with
`01-candidate-profile.md` and `02-behavioral-profile.md` exactly, so a fork that added a section
to its own profile failed its CI and local runs although `/reset` worked. Off upstream it now
requires every shipped heading to appear in order, so an added section passes and a renamed,
dropped or reordered one still fails; upstream keeps the exact comparison.
## [1.7.3] - 2026-10-19 ## [1.7.3] - 2026-10-19
### Added ### Added
+30 -1
View File
@@ -34,6 +34,11 @@ import unittest
from pathlib import Path from pathlib import Path
from tempfile import TemporaryDirectory from tempfile import TemporaryDirectory
try:
from tests._upstream import is_upstream_checkout
except ImportError: # `python -m unittest discover -s tests` imports test modules top-level
from _upstream import is_upstream_checkout
REPO = Path(__file__).resolve().parent.parent REPO = Path(__file__).resolve().parent.parent
RESET = REPO / ".claude" / "commands" / "reset.md" RESET = REPO / ".claude" / "commands" / "reset.md"
SETUP = REPO / ".claude" / "commands" / "setup.md" SETUP = REPO / ".claude" / "commands" / "setup.md"
@@ -205,6 +210,12 @@ def h2_headings(text):
return [line.strip() for line in text.splitlines() if line.startswith("## ")] return [line.strip() for line in text.splitlines() if line.startswith("## ")]
def appear_in_order(needles, haystack):
"""Whether every needle occurs in haystack, in the same relative order."""
remaining = iter(haystack)
return all(needle in remaining for needle in needles)
class TestResetTargetsTheHeadingsTheShippedFilesHave(unittest.TestCase): class TestResetTargetsTheHeadingsTheShippedFilesHave(unittest.TestCase):
"""Step 3's skeletons and anchors must name sections that exist. """Step 3's skeletons and anchors must name sections that exist.
@@ -230,13 +241,31 @@ class TestResetTargetsTheHeadingsTheShippedFilesHave(unittest.TestCase):
for filename in ("01-candidate-profile.md", "02-behavioral-profile.md"): for filename in ("01-candidate-profile.md", "02-behavioral-profile.md"):
with self.subTest(file=filename): with self.subTest(file=filename):
shipped = (SKILL_DIR / filename).read_text(encoding="utf-8") shipped = (SKILL_DIR / filename).read_text(encoding="utf-8")
skeleton = h2_headings(skeleton_block(self.reset, filename))
if not is_upstream_checkout():
# On a fork this file is the user's personalized profile, which
# may carry ## sections of its own; a rename or a drop still fails.
self.assertTrue(
appear_in_order(skeleton, h2_headings(shipped)),
f"/reset's skeleton headings for {filename} must all appear, in "
f"order, in the personalized file: {skeleton}",
)
continue
self.assertEqual( self.assertEqual(
h2_headings(skeleton_block(self.reset, filename)), skeleton,
h2_headings(shipped), h2_headings(shipped),
f"/reset's skeleton for {filename} must carry exactly the shipped " f"/reset's skeleton for {filename} must carry exactly the shipped "
"## headings, in order - a reset must not rename or drop sections", "## headings, in order - a reset must not rename or drop sections",
) )
def test_fork_heading_check_rejects_a_renamed_dropped_or_reordered_heading(self):
# The fork branch above never runs in upstream CI, so pin its strictness here.
skeleton = ["## Identity", "## Education", "## Awards"]
self.assertTrue(appear_in_order(skeleton, ["## Identity", "## Education", "## Certifications", "## Awards"]))
self.assertFalse(appear_in_order(skeleton, ["## Identity", "## Schooling", "## Awards"]))
self.assertFalse(appear_in_order(skeleton, ["## Identity", "## Awards"]))
self.assertFalse(appear_in_order(skeleton, ["## Education", "## Identity", "## Awards"]))
def test_full_file_skeletons_keep_the_framework_version_frontmatter(self): def test_full_file_skeletons_keep_the_framework_version_frontmatter(self):
# The shipped files open with a `framework_version` marker that # The shipped files open with a `framework_version` marker that
# check_framework_version.py requires and check_upstream_updates.py # check_framework_version.py requires and check_upstream_updates.py