Skip to content

feat(upgrade) add vlurp upgrade command with catalog diffing#14

Merged
indexzero merged 1 commit into
mainfrom
catalog
Mar 19, 2026
Merged

feat(upgrade) add vlurp upgrade command with catalog diffing#14
indexzero merged 1 commit into
mainfrom
catalog

Conversation

@indexzero

@indexzero indexzero commented Mar 17, 2026

Copy link
Copy Markdown
Owner

What

Adds vlurp upgrade [source] as a first-class command that combines outdated detection, selective re-fetching, .vlurpfile rewriting, and structured catalog diffing into a single atomic operation. Also adds vlurp catalog-diff [old] [new] for standalone catalog comparison with both human-readable and --json output.

The implementation spans four phases: a structure-preserving vlurpfile writer (updateRef(), updateRefs() in src/vlurpfile.js), the upgrade command itself (src/commands/upgrade.js), pure catalog diff logic (src/catalog-diff.js with diffCatalogs() and formatCatalogDiff()), and catalog integration into the upgrade output — snapshots before/after, diffs them inline, and rotates catalog.jsoncatalog.prev.json. The catalog-building logic was extracted from the CatalogCommand Ink component into a reusable buildCatalog() function in src/catalog.js.

The version field is now extracted from SKILL.md YAML frontmatter and included in the catalog schema, enabling version-aware diffing that reports skill additions, removals, version bumps, and tool/command/file surface area deltas.

Why

The skill pack ecosystem has two distribution models: git-clone-as-package-manager (gstack's approach: git reset --hard origin/main && ./setup) and tarball-fetch-with-filtering (vlurp's approach). vlurp had better security properties — lineage tracking, integrity verification, content scanning — but no upgrade story. Users had to manually run vlurp outdated + vlurp pin + vlurp batch --force as separate steps, with no structured view of what changed.

The gstack model's problem

gstack's upgrade runs ./setup after every pull — a shell script that compiles a Bun binary and creates symlinks. This is an npm postinstall script by another name. The upstream repo author decides what code runs on the consumer's machine. The same supply chain attack vector that made npm install dangerous. gstack also uses CHANGELOG.md summarized by an LLM to show "what's new" — optional, lossy, and not machine-readable.

How this fixes it

vlurp upgrade treats upgrading as fetching with better UX. No lifecycle hooks. No code execution. The catalog is derived from content on disk by vlurp's own trusted code. The catalog diff is deterministic and exact — a new tool in tool_surface shows up as +Bash, a removed skill shows up as (removed). No LLM summarization, no author discipline required, and --json output is directly consumable by CI pipelines.

The vlurpfile writer preserves the human-authored structure (comments, blank lines, argument ordering) while updating --ref values in-place, making .vlurpfile function as a lockfile that's both human-readable and machine-updatable.

Risk Assessment

Low risk. All changes are additive — two new commands (upgrade, catalog-diff), two new modules (src/catalog.js, src/catalog-diff.js), and extensions to existing modules. The CatalogCommand refactor extracts logic into buildCatalog() without changing behavior. The vlurpfile writer operates on string content and does not touch the filesystem directly. Existing commands are unchanged.

Future Work

  • vlurp upgrade --dry-run could fetch to a temp directory and show a catalog diff preview (currently only shows outdated/current status)
  • Catalog diff could detect description changes (currently only compares version, tools, commands, files)
  • The upgrade command could integrate with vlurp scan to highlight new security findings in upgraded content

Implement SPEC.4: Upgrade and Catalog Versioning. Adds `vlurp upgrade`
as a first-class command that combines outdated detection, selective
re-fetching, vlurpfile rewriting, and structured catalog diffing into
a single atomic operation. No lifecycle hooks, no code execution — the
catalog is derived from content on disk by vlurp's own code.

Phase 1 — Vlurpfile writer: `updateRef()` and `updateRefs()` perform
structure-preserving edits to .vlurpfile content, updating or inserting
`--ref` values while preserving comments, blank lines, and argument
ordering.

Phase 2 — Upgrade command: `vlurp upgrade [source]` resolves upstream
HEAD for each source, re-fetches outdated entries, writes lineage, and
rewrites the .vlurpfile with new refs. Supports `--dry-run` and
`--vlurpfile` flags.

Phase 3 — Catalog diff: `vlurp catalog-diff [old] [new]` computes a
structured comparison of two catalog snapshots, reporting new, removed,
changed, and unchanged skills with tool/command/file surface deltas.
Supports `--json` for machine-readable output.

Phase 4 — Catalog in upgrade output: `vlurp upgrade` snapshots catalogs
before and after fetching, diffs them, and renders the structured
changelog inline. Saves `catalog.prev.json` for subsequent diffing.
Extracts `buildCatalog()` from the catalog command into a reusable
module.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@indexzero
indexzero merged commit 2742321 into main Mar 19, 2026
2 checks passed
@indexzero
indexzero deleted the catalog branch April 1, 2026 06:50
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