Reconcile stale entries when regenerating skills-lock.json - #70
Draft
warp-agent-staging[bot] wants to merge 2 commits into
Draft
Reconcile stale entries when regenerating skills-lock.json#70warp-agent-staging[bot] wants to merge 2 commits into
warp-agent-staging[bot] wants to merge 2 commits into
Conversation
update_common_skills_lock seeded its temp dir from the existing downstream lock and ran `skills add`, which merges into whatever lock it finds but never removes an entry for a skill that no longer exists in the source. A rename or deletion in warpdotdev/common-skills left a ghost entry behind pointing at a skillPath that no longer exists. Reconcile the candidate lock before comparing/copying it back: drop any entry whose source is warpdotdev/common-skills unless this run's `--copy` actually materialized its skillPath under the temp directory. Entries from any other source, including hand-added ones, are left untouched. This reuses the copy `skills add` already produced instead of making a second fetch. Fixes DEVX-8492. Co-Authored-By: Warp Agent <agent@warp.dev>
Contributor
Author
|
This PR was generated with Warp. |
Review of the previous revision found that pruning by checking whether a copied path existed under the temp dir failed open: if skills add exited 0 without actually copying anything (e.g. a broken CLI run), every warpdotdev/common-skills entry looked stale and got deleted, while the one entry from another source survived. That result is worse than the original bug and would auto-merge into warp and warp-server. Restructure the fix: regenerate the warpdotdev/common-skills portion of the lock from scratch in a clean, unseeded temp directory instead of seeding it with the existing lock and pruning what didn't reappear. skills add can then only ever emit entries for skills it actually finds, so nothing stale can survive the merge in the first place. Entries from any other source are carried over from the existing lock unmodified. As a backstop, fail closed with a non-zero exit and leave the existing lock untouched if regenerating produces no warpdotdev/common-skills entries at all while the existing lock has some - that is a sign the run didn't discover or copy anything, not that every skill vanished upstream. Add scripts/tests/update_common_skills_lock_test.sh, a self-contained regression suite that runs the real script against a fake npx (scripts/tests/fake-bin/npx) modeling `skills add ... --copy` deterministically from a local fixture directory, with no network access. Covers a rename, a plain deletion, foreign-source preservation, idempotence, and the fail-closed guard. Wire it into a new CI workflow that runs on push to main and on every pull request. Co-Authored-By: Warp Agent <agent@warp.dev>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
scripts/update_common_skills_lockregenerated a downstreamskills-lock.jsonadditively: it seeded a temp dir from the existing lock and ranskills add, which merges into whatever lock it finds and never removes an entry for a skill that's no longer in the source. A rename or deletion inwarpdotdev/common-skillsleft a ghost entry behind, pointing at askillPaththat no longer exists. Since.github/workflows/update-downstream-skill-locks.ymlruns this on every push tomainand opens the downstream PRs with squash auto-merge enabled, a corrupted lock could land unreviewed.Fixes DEVX-8492.
Changes
scripts/update_common_skills_lock: regenerates thewarpdotdev/common-skillsportion of the lock from scratch in a clean, unseeded temp directory (instead of seeding it with the existing lock), then merges in any entries from other sources unmodified. Since nothing is seeded,skills addcan only ever emit entries for skills it actually finds in the current source — there is nothing stale for it to merge forward, so the bug's root cause is removed structurally rather than patched after the fact.warpdotdev/common-skillsentries while the existing lock has some, the script aborts with a non-zero exit and leavesskills-lock.jsoncompletely untouched, instead of writing a lock that dropped every locked skill. See "Revision" below for why this was added.scripts/tests/update_common_skills_lock_test.sh, a self-contained regression suite, plusscripts/tests/fake-bin/npx, a fakenpxthat deterministically modelsskills add ... --copyfrom a local fixture directory (no network access). Wired into a new.github/workflows/test-scripts.yml, run on every push tomainand every pull request.scripts/README.md: documented the clean-regeneration behavior, the fail-closed guard, and the new test suite.Revision (addressing review findings)
An adversarial review of the first version of this PR found two issues, both fixed in this revision:
skillPathwasn't found copied under the temp dir. Ifskills addexited 0 without actually copying anything (e.g. a broken CLI run), everywarpdotdev/common-skillsentry looked "not found" and got pruned — deleting all of them — while the lone different-source entry survived untouched. That result is worse than the bug this PR fixes, and would have auto-merged intowarpandwarp-server. Fixed by restructuring the regeneration to not seed the temp dir at all (so nothing stale can survive the merge in the first place), plus an explicit fail-closed guard for the case where regeneration produces nothing.Verification
Regression suite (
scripts/tests/update_common_skills_lock_test.sh, runs in CI): 5 tests, all passing —npxwrites a technically-valid but empty lock (no copies)npxproduces no candidate lock at allI confirmed these tests are not vacuous by running them against the original (pre-fix) script and against the first, since-replaced version of this fix — both fail multiple tests in the suite, including (for the first fix) the two fail-closed tests, reproducing the exact regression the review found.
Manual validation, using a local git fixture repo as a stand-in for
warpdotdev/common-skills(via afile://source, so theskillsCLI takes the identical clone+copy code path as the real GitHub source) and the fakenpx:npxthat writes an empty lock, and one that writes nothing at all — both abort with a non-zero exit and leave the existing lock byte-identical to before.warpdotdev/common-skillssource, real network) against copies of the realwarpdotdev/warpandwarpdotdev/warp-serverskills-lock.jsonfiles. Output was identical to the original (unfixed) script on the same inputs — onlycomputedHashbumps for skills whose content changed upstream since those locks were generated; no entries added or removed.bash -npasses on all three shell scripts (scripts/update_common_skills_lock,scripts/tests/update_common_skills_lock_test.sh,scripts/tests/fake-bin/npx).Out of scope
COMMON_SKILLS_SOURCEfor ad hoc/manual testing; the fix itself doesn't need one, and the shipped regression suite covers this via the fakenpxinstead.skills additself reports — only the zero-materialization case is guarded against, per the review's explicit "at minimum" scope for finding 1.