Skip to content

fix(skill-creator): audit_skill_regression compare can't survive a rename - #293

Merged
daymade merged 2 commits into
mainfrom
fix/skill-creator-rename-identity-check
Aug 15, 2026
Merged

fix(skill-creator): audit_skill_regression compare can't survive a rename#293
daymade merged 2 commits into
mainfrom
fix/skill-creator-rename-identity-check

Conversation

@daymade

@daymade daymade commented Aug 15, 2026

Copy link
Copy Markdown
Owner

What broke

The existing-skill migration gate's compare command verifies identity between
--before (the pre-edit snapshot) and --after (the edited skill) before
producing a regression review. For --baseline-origin pre-edit-snapshot, it
hashes --after's absolute path and compares it against the path recorded
when snapshot --source was run. For --baseline-origin git-ref:<ref>, it
looks up --after's relative path inside the historical git tree.

Both checks assume the skill's path is unchanged between snapshot-time and
compare-time. That assumption breaks for the one operation this exact tool's
own SKILL.md documents extensively elsewhere: renaming a skill. Any
legitimate rename hits a hard pre-edit snapshot source identity does not match the edited skill (or an equivalent git-ref lookup failure), with no
documented way to proceed short of hand-editing the provenance manifest —
which the tool's own docs explicitly warn against (.skill-regression-*
markers are described as things you should never hand-edit).

The fix

Add an explicit --renamed-from <old-path> flag to compare. When given, the
identity check verifies that declared path instead of --after's current
path/relative-path — for both baseline-origin modes. The content/tree-hash
checks (tree_hash(before) vs the manifest, and before's tree vs the
historical git ref) are untouched, so an undeclared path change, or a
--renamed-from pointing at the wrong old path, still fails exactly as
before. Same design as the existing --allow-identical-baseline flag: a
narrow, explicit, opt-in override for one named legitimate scenario, not a
general relaxation.

The provenance recorded in the report now includes renamed_from when the
flag is used, so a reviewer can see a rename was declared and what the old
path was.

Also documented the flag in SKILL.md's migration-gate walkthrough, right next
to the existing compare example, so the next rename doesn't rediscover this
the same way.

How this was found

Renaming a skill (transcript-research-brieffact-check-pro) in a
private sibling skill repo today, following this exact skill's own
"existing-skill migration gate" procedure. snapshot succeeded; compare
failed with the identity error above. Read the source
(_resolve_baseline_provenance, lines ~218–256 before this change) and
confirmed the root cause is the absolute-path hash. Verified via git diff
that the rename itself preserved 100% of content (git's rename detection
made this exact and complete) and used that as the regression check for that
specific rename, since this tool structurally couldn't run.

Testing

  • All 35 existing tests in tests/test_audit_skill_regression.py still pass
    unchanged (ran before and after the fix).
  • 3 new tests added, covering both baseline-origin modes:
    • test_pre_edit_snapshot_rejects_undeclared_rename — confirms the
      default (no flag) behavior is unchanged: an undeclared rename still
      fails with the same error as before.
    • test_pre_edit_snapshot_accepts_declared_rename — confirms a declared
      rename succeeds, the report records renamed_from, and a
      --renamed-from pointing at the wrong old path still fails (the
      override doesn't degrade into "skip identity checking").
    • test_git_ref_baseline_accepts_declared_rename — same shape for the
      git-ref: baseline-origin mode, including an undeclared-rename negative
      case.
    • 38/38 green in a fully isolated fresh clone (not just the working copy
      the fix was written in).
  • End-to-end CLI smoke test (not just the Python API): snapshot → rename the
    directory → compare without the flag (reproduces the original failure,
    now with an improved error message pointing at --renamed-from) →
    compare with the flag (succeeds, report.json provenance shows
    renamed_from).

Scope

Touches only daymade-skill/skill-creator/{SKILL.md, scripts/audit_skill_regression.py, tests/test_audit_skill_regression.py}. No other files. No new dependencies, no new capability beyond making an already-documented, already-supported operation (skill rename) actually work with the migration-gate tooling.

🤖 Generated with Claude Code

https://claude.ai/code/session_01DcR3tHN3tKMy9WnYRJJZKk

daymade and others added 2 commits August 15, 2026 11:37
…name

The migration-gate identity check hashed --after's absolute path against
the path recorded at snapshot time (or, for git-ref origin, looked up
--after's relative path inside the historical ref). Both are the same
path by construction only when the skill wasn't renamed or moved — so
any legitimate skill rename hit a hard identity-mismatch error, with no
way to proceed short of hand-editing the provenance manifest (which the
tool's own docs explicitly warn against elsewhere).

Add an explicit --renamed-from <old-path> flag to `compare`. When given,
the identity check verifies that declared path instead of --after, for
both baseline-origin modes; the content/tree-hash checks are untouched,
so an undeclared mismatch (or a renamed-from pointing at the wrong old
path) still fails exactly as before. Same shape as the existing
--allow-identical-baseline escape hatch: narrow, explicit, opt-in.

Found while renaming transcript-research-brief -> fact-check-pro in a
private sibling skill repo today; git-diff verification stood in as the
regression check for that rename since this tool structurally couldn't
run. Documented the flag in the migration-gate section of SKILL.md so
the next rename doesn't rediscover this the same way.

Tests: 3 new cases (pre-edit-snapshot positive/negative, git-ref
positive) alongside the existing 35, all green; plus an end-to-end CLI
smoke test reproducing the original failure and confirming the fix.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcR3tHN3tKMy9WnYRJJZKk
…-from

An independent, fresh-context read-only reviewer (general-purpose subagent,
not a fork — per CLAUDE.md's "自审不算数" discipline for compounding skill
edits) was given the reader spec "another agent about to run the migration
gate for a skill rename, working only from SKILL.md" and told to actually
exercise the previous commit's changes against real corpus (today's real
transcript-research-brief -> fact-check-pro rename), not synthetic fixtures.
It surfaced two real, reproduced defects and two documentation gaps:

1. --renamed-from's docs said "old relative path" without saying relative to
   what. It's resolved via Path.resolve() against the process's CWD — same
   as --before/--after — but unlike those two, a wrong renamed_from has no
   existence check to catch a bad resolution, so it fails deep and
   confusingly instead. This bites skill-creator's own edits specifically:
   the migration-gate walkthrough's own `cd <skill-creator-path>` convention
   puts CWD in skill-creator's own repo, which is normally a *different*
   repo than the skill being edited — reproduced live, exact repro in the
   independent-review artifact.

2. The git-ref branch's single broad except block reported "requires the
   edited skill to be inside a Git worktree and the ref to resolve" for
   THREE distinguishable failures: --after genuinely not in a worktree,
   renamed_from/after resolving outside that worktree (the actual failure
   in defect 1), and the ref not resolving. Split into three narrower
   try/except blocks, each with an accurate, specific message; the
   renamed_from-outside-repo case now names both paths and states the CWD-
   relative-resolution cause directly.

3. The pre-edit-snapshot hint only fired when renamed_from was omitted
   entirely; a *wrong* renamed_from value produced the same bare error as no
   flag at all, giving no way to tell the two apart. Hint now always shows
   the resolved path when renamed_from was given.

4. SKILL.md's migration-gate walkthrough said "materialize the directory
   from the chosen ref" with no command — the only place git archive |
   tar -x -C actually appears is under an unrelated heading ("Concurrent
   sessions on the same skill repo"), several hundred lines away. Its
   "Extract into a fresh, non-existent directory" phrasing, read literally,
   contradicts `tar -x -C` requiring the target to already exist (reproduced
   on this machine's bsdtar: "could not chdir"). And git archive's output
   directory structure is one level deeper than snapshot's, which no text
   stated — a --before value copied from the snapshot recipe by pattern-
   match points at the wrong depth. Inlined the actual command, clarified
   the extraction-target wording, and stated the depth difference and its
   --before consequence explicitly.

All fixes verified against the same live corpus that surfaced them (the real
fact-check-pro rename, git-archive-reconstructed from its actual pre-rename
commit) plus new regression tests: 39/39 passing (up from 38), including 2
new cases locking in the specific error messages so they can't silently
regress back to the generic ones. Full independent-review record — reviewer
prompt verbatim, every finding with disposition and reason, what wasn't
verified (the pre-edit-snapshot branch's equivalent CWD-mismatch case was
read but not exercised against real corpus, since the real snapshot this
session took earlier had already been cleaned from scratch space by the
time of review) — committed separately to the private skill-reviews archive,
not this public repo.

Existing-skill migration gate re-run against the same immutable pre-edit ref
(b8556f2) after this round's edits: 3
candidates (1 SKILL.md paragraph, the 2 files from the first round),
all preserved_or_moved with verified reasons, 0 unclassified, verify passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DcR3tHN3tKMy9WnYRJJZKk
@daymade
daymade merged commit 2d7bda1 into main Aug 15, 2026
4 checks passed
@daymade
daymade deleted the fix/skill-creator-rename-identity-check branch August 15, 2026 04:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant