| name | update-package-locks |
| description | Use when refreshing package-lock.json files in ng-mocks, resolving lockfile conflicts in an existing dependency PR, or ensuring a lockfile PR is conflict-free after creation. |
Update Package Locks
Use this skill for a fresh lockfile refresh or to regenerate a lockfile while resolving an existing dependency PR conflict, without permanently changing the repo's normal install flow.
This workflow is intentionally narrow. Follow the sequence exactly. Do not manually add tests, lint, rebases, or unrelated cleanup unless the user explicitly asks for them. All execution must follow AGENTS.md's Docker-only rule.
Task List
Create a plain Markdown checklist that any AI agent can follow:
- [ ] Identify whether this is a fresh refresh or an existing dependency PR conflict
- [ ] Create an isolated worktree from `upstream/main` or the existing PR branch
- [ ] For a PR conflict, merge `upstream/main` and keep the dependency PR's lockfile side as the regeneration base
- [ ] Temporarily change the relevant `compose.yml` service command line(s) from `npm install` to `npm update`
- [ ] Run the update wrapper pass with wrapper targets in batches of 2-4
- [ ] Restore `compose.yml` back to `npm install`
- [ ] Run the install wrapper pass with wrapper targets in batches of 2-4
- [ ] Commit the refreshed lockfiles with only the dependency or merge changes already in scope
- [ ] Push a fresh branch and create a PR, or push the existing PR branch
- [ ] Check the remote PR mergeability after every push
- [ ] If conflicts exist, merge current `upstream/main`, preserve both sides' intended changes, regenerate affected lockfiles, push, and recheck
- [ ] Summarize the two wrapper passes and any npm warnings
Workflow
- Work in an isolated worktree:
- For a fresh refresh, fetch the current base and create a new branch from
upstream/main.
- For an existing dependency PR conflict, fetch that PR branch into an isolated worktree, merge
upstream/main without rewriting history, and keep the dependency PR's lockfile side as the regeneration base.
- In that new worktree, inspect
compose.yml.
- Temporarily change only the affected
compose.yml service command line(s) from npm install to npm update.
- For a repo-wide refresh, derive the current wrapper targets from
compose.sh and compose.yml, then run them in batches of 2-4 concurrent commands. If the user explicitly named one target, run only that target.
- Restore the same service command line(s) back to
npm install.
- Run the same target set again in batches of 2-4 so the resulting lockfiles match the normal CI install flow.
- Commit the refreshed
package-lock.json files with only the dependency or merge changes already in scope, plus .agents/skills/update-package-locks/SKILL.md if this skill was intentionally edited.
- For a fresh refresh, push the branch to a writable remote and create a PR against
upstream/main. For an existing dependency PR, push back to that PR branch.
- After creating the PR or pushing its branch, query the hosting provider for the PR's current mergeability. If the result is indeterminate, wait and query again. Do not treat pending or failed CI checks as merge conflicts.
- If the provider reports conflicts:
- Fetch current
upstream/main and merge it into the PR branch in the same isolated worktree without rebasing or rewriting history.
- Inspect every conflicted file. Resolve non-lockfile conflicts semantically so both sides' intended changes remain; never choose an entire side without checking what it would discard.
- When merging
upstream/main into the PR branch, keep the PR side of each conflicted package-lock.json only as the regeneration base, then run the update and install wrapper passes for every affected target against the combined manifests. Never hand-merge lockfile conflict blocks.
- Verify there are no unmerged paths, restore every affected
compose.yml command to npm install, commit with normal hooks, push, and query remote mergeability again.
- Repeat the check if the base advances. Finish only when the provider returns a definitive conflict-free state.
Do not use the current active worktree. A fresh refresh needs a new branch; an existing dependency PR conflict stays on its PR branch in an isolated worktree. Do not manually run sh test.sh, root tests, lint, or TypeScript checks as part of this workflow unless the user explicitly asks for them. Never use local runtimes or ad-hoc dependency commands.
For a repo-wide refresh, the affected command lines are all service command entries in compose.yml that currently read - install. Change only those entries to - update, run the wrapper, then change those same entries back to - install. Do not edit package.json, shell scripts, or lockfiles by hand.
For repo-wide refreshes, derive targets from the current compose.sh and compose.yml; do not hardcode target names or rely on bare sh compose.sh. Run each target once per pass in batches of 2-4, with a unique COMPOSE_PROJECT_NAME per concurrent command. Clean each batch with docker compose down -v before starting the next one.
If a wrapper target fails, including Docker address-pool or Puppeteer cache errors, report the command, error, and remaining work to the user and discuss the solution before cleanup, retries, or other recovery steps. Do not switch to local runtimes or create a workaround.
If several worktrees or agent sessions are active, use a unique compose namespace for every wrapper command:
COMPOSE_PROJECT_NAME=ngmocks_<unique> sh compose.sh <target>
Commands
git fetch upstream main
git worktree add -b codex/<lockfile-branch> ../<lockfile-worktree> upstream/main
git fetch upstream main <pr-branch>
git worktree add ../<pr-worktree> <pr-branch>
git merge --no-edit upstream/main
git checkout --ours path/to/package-lock.json
COMPOSE_PROJECT_NAME=ngmocks_<unique> sh compose.sh <target>
COMPOSE_PROJECT_NAME=ngmocks_<unique> sh compose.sh <target>
git add package-lock.json docs/package-lock.json tests-e2e/package-lock.json e2e/*/package-lock.json
git add .agents/skills/update-package-locks/SKILL.md
git commit -m "chore: refresh package lockfiles"
git remote -v
git push -u origin codex/<lockfile-branch>
git fetch upstream main
git merge --no-edit upstream/main
git diff --name-only --diff-filter=U
git checkout --ours path/to/package-lock.json
git diff --check
git commit --no-edit
git push
Validation
- The required validation for this skill is a successful wrapper-based update pass followed by a successful wrapper-based install pass.
- For a single target, run
sh compose.sh <target> once while the service command is temporarily npm update, then run sh compose.sh <target> again after restoring npm install.
- For a repo-wide lock refresh, run every relevant wrapper target once with all relevant service commands temporarily set to
npm update, then run every same target again after restoring all service commands to npm install.
- Repo-wide target runs may be concurrent in batches of 2-4. A batch is successful only when every target command exits successfully.
- After the final push, the hosting provider must report a definitive conflict-free PR state. A local clean merge is not sufficient, and CI status is a separate signal.
- Do not run
sh test.sh, npm test, lint, or TypeScript checks as part of this skill's default validation.
Guardrails
- Always use an isolated worktree: a new branch from current
upstream/main for fresh work, or the existing PR branch for conflict resolution.
- Never delete lockfiles.
- Never hand-merge lockfile conflict blocks or rewrite dependency PR history.
- Never discard either side of a non-lockfile conflict without inspecting and preserving its intended behavior.
- Never leave
compose.yml in an npm update state after finishing.
- Use only the documented wrapper flow and repo images. Never use local runtimes or custom install, build, test, or
check scripts, including inside Docker.
- If multiple worktrees, agent sessions, or concurrent wrapper targets are active, set a unique
COMPOSE_PROJECT_NAME for each wrapper command.
- Clean up temporary compose projects with
docker compose down -v after successful batches. Discuss failed setup
runs with the user before recovery steps.
- When committing or pushing, let the repository's normal git hooks run. Do not bypass hooks unless the user explicitly asks.
- Do not manually invoke extra validation beyond this skill. If a hook requires local runtime execution or fails,
report it and discuss the solution; do not bypass it or use local tooling to make it pass.
- Push to a configured writable remote; never assume
upstream accepts contributor branches.
- Never declare the PR conflict-free from local Git state alone; query its remote mergeability after the final push.