Skip to content

fix: publish a working install command and stop the version drifting - #35

Merged
elkaix merged 1 commit into
mainfrom
fix/install-command-and-version-drift
Sep 12, 2026
Merged

elkaix merged 1 commit into
mainfrom
fix/install-command-and-version-drift

Conversation

@elkaix

@elkaix elkaix commented Sep 12, 2026 •

Copy link
Copy Markdown
Contributor

Four standardization fixes on top of v3.0.0. The first one blocks anyone from installing the skills at all.

The install command in v3.0.0 does not run

npx @pymodel/claude-agy-mcp-install-skills reads as a package name to npx, so it 404s for every user. The form in the script header, npx @pymodel/claude-agy-mcp install-skills, starts the stdio server with a stray argument and hangs.

The bin is a package selection, not a subcommand, so the working form names both:

npx --package @pymodel/claude-agy-mcp claude-agy-mcp-install-skills

Fixed in the README and the script header. The v3.0.0 release notes need the same correction.

The version was restated, not derived

VERSION was a constant copied from package.json, guarded by a test. That guard fired in CI one commit after the last bump. It now reads package.json at module init: ../package.json resolves to the package root from both src/ and the bundled dist/, and npm ships package.json regardless of the files array.

Verified against the real tarball rather than the source tree. Installing pymodel-claude-agy-mcp-3.0.1.tgz into a temp project and driving an initialize over stdio returns "version":"3.0.1" from the bundled entry.

The test keeps the equality assertion and adds the constraint that actually carries the risk now: the bin entry stays one directory below the package root, since that is what the relative read depends on.

The installer would clobber a symlink

It replaced the destination outright. Someone who points a skill at a checkout they edit would have had that link silently swapped for a frozen copy on the next install, which is the same silent-clobber class this project's own release notes warn about. It now skips a symlinked destination and says so, with --force to replace deliberately. Two tests drive the real script against temp directories.

The concurrency test was timing-dependent

It drained its semaphore on a single macrotask tick. Under load the gate is still empty, the shift is a no-op, and the assertion measures an empty semaphore rather than a full one. It surfaced as a flake once the new subprocess tests started competing for the machine. It now waits for each admitted run to reach the spawn.

Verification

288 tests pass, 1 skipped. Typecheck, build and format clean. Three consecutive full runs green after the concurrency fix. Tarball contents confirmed: both skill trees, the installer at mode 755, and --list, --dir and the symlink guard all exercised from an installed copy rather than the repo.

Summary by CodeRabbit

  • New Features

    • Added a --force option to replace symlinked skills during installation.
    • Installations now report installed and skipped skills, including preserved symlinks.
    • The installer can be run through the documented npx --package command.
  • Bug Fixes

    • Prevented linked skill checkouts from being overwritten by default.
    • Package version reporting now stays synchronized with the published package version.
  • Documentation

    • Updated installation instructions with the new command format and --force option.

The command shipped in 3.0.0 does not run. `npx
@pymodel/claude-agy-mcp-install-skills` reads as a package name to npx and
404s for everyone, and the form in the script header, `npx
@pymodel/claude-agy-mcp install-skills`, starts the stdio server with a
stray argument and hangs. The bin is a package selection, so the working
form names the package and the bin separately.

The handshake version was a constant restated from package.json, guarded
only by a test. That guard fired in CI one commit after the last bump,
which is the whole class working as designed and also a standing tax. It
is now read from package.json at module init. `../package.json` resolves
to the package root from both src/ and the bundled dist/, verified by
installing the tarball and reading the version back out of the running
server, and npm ships package.json regardless of the files array. The
test keeps the assertion and adds the constraint that actually matters
now: the bin entry stays one directory below the package root.

The installer replaced a skill directory outright, including a symlink.
Anyone pointing a skill at a checkout they edit would have had that link
silently swapped for a frozen copy on the next install. It now skips a
symlinked destination and says so, and --force replaces it deliberately.

The concurrency test drained its semaphore on a single macrotask tick,
which is not enough under load: the gate would still be empty, the shift
would be a no-op, and the assertion would measure an empty semaphore
rather than a full one. It now waits for each admitted run to reach the
spawn.
@coderabbitai

coderabbitai Bot commented Sep 12, 2026 •

Copy link
Copy Markdown

Review Change StackReview Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: a07f2360-b7fc-40f0-95d3-3666dab95769

📥 Commits

Reviewing files that changed from the base of the PR and between 3f049c2 and a555a86.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (7)
  • README.md
  • package.json
  • scripts/install-skills.mjs
  • src/server.ts
  • test/delegation.test.ts
  • test/server.test.ts
  • test/skills.test.ts

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 3 reviews per hour.


📝 Walkthrough

Walkthrough

The package release updates skill installation through npx --package, protects destination symlinks by default, supports forced replacement, loads the server version from package.json, and adds integration and concurrency test coverage.

Changes

Package maintenance

Layer / File(s) Summary
Installer symlink handling
README.md, scripts/install-skills.mjs, test/skills.test.ts
The installer documents --force, skips symlink destinations by default, replaces them when forced, reports skipped results, and tests installation behavior.
Runtime package version
package.json, src/server.ts, test/server.test.ts
The package version is 3.0.1. VERSION loads from package metadata. Tests validate semantic-version syntax and binary path layout.
Delegation test synchronization
test/delegation.test.ts
The concurrency test waits for an admitted run before checking limits and releasing its gate.

Priority: ⬇️ Low

Estimated code review effort: 3 (Moderate) | ~20 minutes

Change: Bug fix

Merge Risk: ⚪ Minimal · up to a555a

The updated installer behavior, version reporting, and concurrency test synchronization are covered without an actionable regression. The change is ready to merge.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 5 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies two primary changes: fixing the install command and preventing version drift. It is concise and relevant to the pull request objectives.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 5 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/install-command-and-version-drift

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

@elkaix
elkaix merged commit 01547b8 into main Sep 12, 2026
3 checks passed
@elkaix
elkaix deleted the fix/install-command-and-version-drift branch September 12, 2026 17:43
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