Skip to content

fix(cli): stamp the installed skill's metadata.version with the build that wrote it - #448

Merged
theCodeDrift merged 2 commits into
mainfrom
worktree-447-needs-resolution-found
Oct 6, 2026
Merged

theCodeDrift merged 2 commits into
mainfrom
worktree-447-needs-resolution-found

Conversation

@theCodeDrift

Copy link
Copy Markdown
Member

A nightly init rewrote the body of .taskless/skills/taskless/SKILL.md to pin itself, but left metadata.version in the frontmatter at the last release (0.11.2). info --json then reported installedVersion and currentVersion both as 0.11.2 with current: true.

Cause

The skill source carries the committed package version, which the build asserts. A nightly's __VERSION__ is its own version, but nothing restamped the frontmatter. checkStaleness also read both sides from that same embedded skill, the installed file it had just written and its own embedded copy, so the comparison could never come back stale.

Fix

  • stampSkillVersion rewrites only the version: line inside the frontmatter's metadata: block. Prose and the body are untouched.
  • getEmbeddedSkills stamps each skill with the running build's version. Every install writes skills from it and checkStaleness reads "current" from it, so both sides now report the running build.
  • For a release build the stamp equals what the source already says, so prod output is unchanged.

Tests

  • test/nightly/skill-version-stamp.test.ts (nightly vitest project): an install writes the nightly's version, checkStaleness reports it on both sides, and a skill a release left at 0.11.2 now reports stale. All three fail with the fix reverted.
  • test/stamp-skill-version.test.ts: only the frontmatter is rewritten; content without frontmatter or without metadata.version is left alone.

Typecheck, lint, and the full CLI suite pass.

Fixes #447

… that wrote it

A nightly rewrote the canonical skill body to pin itself but left metadata.version at the committed package version, and checkStaleness compared that stamp against the same embedded value, so info reported the skill current either way. getEmbeddedSkills now stamps each skill with the running build's version, so an install writes it and the staleness check reads it.

Fixes #447
@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@claude

claude Bot commented Oct 6, 2026 •

Copy link
Copy Markdown

Claude finished @theCodeDrift's task in 2m 52s —— View job


Review mode: incremental — read 0 prior review thread(s) before reviewing.

.prior-review.json contained no reviews, review threads, or prior comments beyond the trigger itself, so this is the first review pass on this PR. Nothing to carry forward as already-addressed or still-open.

  • Read prior review data (none found)
  • Fetch PR diff and metadata (gh pr diff, gh pr view --json)
  • Review changed files (install.ts, both new test files, changeset)
  • Post findings

Assessment

The fix is well-targeted and the regex/stamping logic checks out against the actual skill source and build infrastructure:

  • stampSkillVersion operates only on the sliced frontmatter block (/^---\n[\s\S]*?\n---\n/), so it can't touch version:-looking text in the body — verified against the real skills/taskless/SKILL.md, which has metadata: as a top-level, unindented key followed by indented author:/version:/commandName: lines, matching METADATA_VERSION's shape exactly.
  • The lazy (?:[ \t]+.*\n)*? skip-group correctly finds version: regardless of which other metadata.* keys precede it, and the stamp-skill-version.test.ts case with description: | prose containing version: 1.0.0 confirms the anchor on metadata:\n keeps that from being a false match.
  • The CLI_VERSION === "unknown" guard in getEmbeddedSkills correctly preserves the committed package.json version for plain vitest runs (where __VERSION__ is undefined), so this change doesn't perturb any of the existing non-nightly tests that assert metadata.version === "0.11.2".
  • The nightly vitest project (vite.config.ts NIGHTLY_TEST_ENVIRONMENT/NIGHTLY_TEST_VERSION) really does define __VERSION__ as "0.0.0-nightly.test" via the same resolveCliVersion the real nightly build uses, so test/nightly/skill-version-stamp.test.ts's expect(CLI_VERSION).toBe("0.0.0-nightly.test") is asserting against real build-target wiring, not a hardcoded string that merely resembles it.
  • assertSkillVersions in vite.config.ts only asserts the source skills/**/SKILL.md matches pkg.version at build start — it never sees the runtime-stamped content — so this change can't trip that build-time guard.
  • Reference/stub targets stay version-free (writeSkill's reference branch builds StubFrontmatter with only name/description), consistent with checkStaleness's existing comment that stubs carry no version, so the stamp is correctly scoped to the canonical store only.

[New] Minor test-coverage gap (non-blocking): stamp-skill-version.test.ts covers "no frontmatter" and "frontmatter with no metadata: key at all," but not "frontmatter has a metadata: block without a nested version: key." That case silently no-ops today (String.replace returns the input unchanged when the pattern doesn't match), which is the right behavior, but it's currently only exercised implicitly rather than asserted.

No correctness, security, or performance issues found. Test coverage for the actual bug (both sides of checkStaleness reading from the same stamped source, and a release-era 0.11.2 skill reporting stale) is solid and directly maps to the regression described in #447.

@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @claude — "Minor test-coverage gap (non-blocking): stamp-skill-version.test.ts covers "no frontmatter" and "frontmatter with no metadata: key at all"…"
#448 (comment)

Added in 9603cb9: a frontmatter metadata: block with no version: is now asserted unchanged, with a metadata:/version: pair in the body to confirm the match cannot reach past the frontmatter to find one.

— AI Coding Agent

@theCodeDrift
theCodeDrift merged commit 5a3e359 into main Oct 6, 2026
4 checks passed
@theCodeDrift
theCodeDrift deleted the worktree-447-needs-resolution-found branch October 6, 2026 03:02
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.

init rewrites the skill body but leaves metadata.version at the previous CLI

1 participant