Skip to content

fix(update): keep re-checking a formerly-frozen capability until its files land - #217

Merged
PrzemekGalarowicz merged 1 commit into
mainfrom
claude/optimistic-heisenberg-8rw8ke
Sep 24, 2026
Merged

PrzemekGalarowicz merged 1 commit into
mainfrom
claude/optimistic-heisenberg-8rw8ke

Conversation

@PrzemekGalarowicz

Copy link
Copy Markdown
Contributor

What this changes

PHARN-13 (#207) made update re-open its same-version gate while frozenCapabilities is non-empty. A frozen capability is one pharn can't parse upstream, so update keeps it and leaves its files alone.

The bug: the run that can parse such a capability again removed it from the list unconditionally. The version bump had already happened on the run that froze it (that run left the capability's files out of its plan). So if one of its files was skipped on the re-check run (a user edit, or an unrecorded file), withholding the bump held back nothing. Every later update then printed "Already up to date" without fetching. The review reproduced this: the file stayed at the old version even after the user reverted their edit, and only --force recovered it.

  • src/commands/update.ts:
    • A key from the previous frozenCapabilities now stays listed while any file under that capability's directory was skipped this run. The check uses the same <subtree>/<name>/ prefix that recordsUnderCapabilities uses.
    • Keys are drawn from the merged capability list, so an entry the merge drops can't linger.
    • pendingSkillsVersion is no longer written when it would equal the withheld skillsVersion. That happened on a same-version re-check and told add nothing new.
  • src/types.ts: the frozenCapabilities comment now describes both reasons a key is listed, and that a re-run init writes it too (fix(init): a re-run init keeps what update would keep, and re-checks the config under its lock #216). Comment only.
  • Docs: docs/commands/update.md and docs/reference/pharn-config.md state when the field clears. CHANGELOG [Unreleased] → Fixed.

Third of the four fixes from the 18-commit review (#213, #216).

Type of change

  • feat — new stack option, wizard step, or command capability
  • fix — bug fix
  • docs — docs-only change
  • chore / refactor — tooling or internal restructure, no behavior change

Area(s) touched

commands/update | types (comment) | docs

Checklist

  • Read the existing file(s) before editing; followed the ESM .js-extension import convention.
  • Updated the matching tests/*.test.ts. The three-run case (skip → fetch again → revert → upgrade and clear) fails against the base update.ts; I checked by stashing it.
  • Updated the relevant docs/ pages.
  • Security invariants untouched. frozenCapabilities is still validated at ingest, and only keys that match a merged config entry are written back.

Quality gates

  • npm run check passes locally (format:check + lint + typecheck + test): 1498 tests.
  • npm run build succeeds.
  • npm run test:coverage passes (coverage thresholds met).

Floor workflow tests: 754/754 passed. validate.mjs: GREEN. Pharn-dev verdicts: regress no-regressions, verify PASS, review GREEN (2 minor advisory findings). I ran all gates with the same CI-equivalent setup as #213.

Notes for the reviewer

  • A skip under a path outside the formerly-frozen capability doesn't keep the key. On a re-check run those files are already at the recorded version, so the normal same-version behavior applies. A test pins this.
  • If you deliberately keep an edit in such a file, every update fetches again until you resolve the edit or pass --force. The non-frozen path already behaves this way (a user edit withholds the bump), and update.md now says so.
  • Still open, and older than the 18 commits: a new upstream capability that pharn can't parse never enters frozenCapabilities, so it installs only on the next SKILLS_VERSION bump.

🤖 Generated with Claude Code

https://claude.ai/code/session_0199owRmYfskqYQVQrVP679o


Generated by Claude Code

…files land

When `update` keeps a capability it cannot parse upstream ("frozen"), it
leaves that capability's files out of the plan and moves `skillsVersion`
on. The next run that can parse it again removed it from
`frozenCapabilities` unconditionally. If one of its files was skipped on
that run (a user edit, or an unrecorded file), withholding the bump held
back nothing, because the bump had already happened. Every later
`update` then early-returned "Already up to date", and the file stayed at
the old version even after the user reverted the edit as advised.

A key from the previous `frozenCapabilities` now stays listed while any
file under that capability's directory was skipped this run. Keys are
drawn from the merged capabilities, so an entry the merge drops cannot
linger. `update` also no longer writes a `pendingSkillsVersion` equal to
the withheld `skillsVersion`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0199owRmYfskqYQVQrVP679o
@coderabbitai

coderabbitai Bot commented Sep 24, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: c849ca49-ef0b-4873-b0c1-47124558929e


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@PrzemekGalarowicz
PrzemekGalarowicz merged commit 431f02b into main Sep 24, 2026
12 checks passed
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.

2 participants