Skip to content

Self-update release UX (#27–#29) + semantic-index publish fix + SkillOps landscape brief#33

Open
stuffbucket wants to merge 8 commits into
mainfrom
claude/skillops-repo-exploration-hl630h
Open

Self-update release UX (#27–#29) + semantic-index publish fix + SkillOps landscape brief#33
stuffbucket wants to merge 8 commits into
mainfrom
claude/skillops-repo-exploration-hl630h

Conversation

@stuffbucket

@stuffbucket stuffbucket commented Jul 15, 2026

Copy link
Copy Markdown
Owner

What does this PR do?

Completes the skill-router self-update epic (#30: #27#28#29), fixes several release-pipeline bugs, hardens the frontmatter parsers so the invalid-YAML class of bug can't recur, and adds a researched SkillOps industry-landscape brief.

Self-update epic (#30)

Release-pipeline fixes

  • Semantic index never shipped. The router ships semantic-index.json, but its only builder lived in site/ and never ran in the publish path — published packages silently fell back to keyword-only search. publish.yml now builds it (best-effort, continue-on-error) before npm publish, via a new root build:semantic script. Corrected CLAUDE.md (the index files are gitignored, built at publish time — not "committed and shipped").
  • 11 skills with invalid YAML frontmatter (5 pages-*-vite, 6 tauri-*): unquoted colons in description that the lenient line-parser tolerated but strict YAML rejected — already red on main, blocking validate/check:llms for every PR. Fixed by removing the colon-space.
  • Parser hardening (root cause). build-index.js and generate_llms_txt.py used hand-rolled line parsers that accepted invalid YAML the validator rejects — the exact lenient/strict divergence that let those 11 skills ship. Both now parse with a real YAML library (js-yaml / PyYAML) and fall back to the line parser only when it's absent (mirroring quick_validate.py). This also fixed a latent bug it surfaced: 9 skills with double-quoted descriptions were leaking literal quote characters into index.json/llms.txt (degrading router search) — real YAML strips them. New test-build-index.js locks in the behavior (unquoted colon rejected; quoted/block-scalar colons accepted; never throws).

Docs

  • docs/skillops-landscape.md — how agent skills evolved across Anthropic, OpenAI, Vercel, and GitHub Copilot; the SKILL.md/agentskills.io open-standard convergence; where this repo's skills-over-MCP router sits; and an improvement backlog. (ARD claims calibrated to "nascent, watch-only" after review.)

Type of change

  • Skill update (update-skills + 11 frontmatter fixes)
  • Tooling / CI (release workflow, MCP server, build tooling, tests)
  • Documentation (CLAUDE.md, landscape brief)
  • Bug fix (update detection, semantic-index publish, invalid YAML, quote-leak in index)

Checklist

  • SKILL.md has valid YAML frontmatter (name, description)
  • Directory name is kebab-case and matches frontmatter name
  • Content is under 500 lines
  • npm run validate passes locally
  • npm test passes locally — 35 MCP smoke + 27 version-check + 10 build-index parser + 140 structure + 6 launch
  • npm run ci passes locally (lint + validate + check:versions + test + check:llms + check:readme) — green end to end

Follow-ups (surfaced, not in this PR)

  • site/scripts/sync-skills.js has the same lenient parser; hardening it needs the site's heavy ML deps (@huggingface/transformersonnxruntime-node, which won't install in this sandbox). Low stakes (the site already emits quoted descriptions and isn't in npm run ci), but worth converging for consistency.
  • agentskills.io conformance pass; optional always-on AGENTS.md tier; cross-host install verification (.github/skills / Vercel skills CLI / Codex).

🤖 Generated with Claude Code

https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs

claude added 8 commits July 15, 2026 07:50
Research synthesis on how agent skills evolved across Anthropic, OpenAI,
Vercel, and GitHub Copilot (2025-2026), the convergence on the SKILL.md
open standard (agentskills.io) and progressive disclosure, and where this
repo's skills-over-MCP router sits. Includes an improvement backlog
(notably: the semantic index is not built in the publish path, so the
shipped package falls back to keyword-only search).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs
The update detector ran 'git ls-remote --tags --refs origin' against the
package install root. The primary distribution is the npm package launched
via 'npx -p @stuffbucket/skills', which has no .git/origin remote, so the
check errored, checkFreshness() returned null, and npx users got no update
signal at all. It also compared against git tags rather than the npm
dist-tag that actually defines 'latest' for the npm channel.

Adopt a distribution-correct source, modeled on stuffbucket/maximal's
notify-only detector:

- Source of truth is the npm registry dist-tags document fetched over plain
  HTTPS (no git, no auth). Works for every install type (npm, npx, git,
  plugin) with zero extra infra.
- Total / never-throws getUpdateStatus() returning the maximal-style shape
  { current, latest, update_available, checked_at, last_error, enabled };
  offline/non-200/timeout/malformed all resolve to a coherent idle status
  preserving last-known. In-process TTL cache (6h), 15s fetch timeout, UA
  header, hand-rolled semver compare, zero deps. Background fetch is unref'd
  so it never keeps the process alive.
- Local version is read from the real package.json, never a git tag.
- Reconcile the two duplicated version-check.js copies: skill-router holds
  the single detector; update-skills/scripts/version-check.js delegates to
  it (one source of truth) and keeps its one-shot CLI.
- Notify-only: guidance routes the user to the update-skills skill (which
  owns the apply step, #29) instead of a bare 'git checkout' that breaks on
  npm installs. Dropped the advertised '--update' no-op from the CLI hint.

serverInfo.version and the explicit check_updates MCP tool are #28; the
real in-place apply is #29. Adds a network-free unit test (27 cases) wired
into npm test.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs
ARD is a ~June 2026 draft spec with a large roster of announced backers but
a small active org and essentially one shipping harness (Copilot Agent
Finder). Distinguish it from the broadly-adopted SKILL.md/agentskills.io
standard, which the original brief conflated it with. Downgrade the ARD
interop item to low-priority watch-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs
- serverInfo.version now reports the real package version (read from
  package.json) instead of the hardcoded '1.0.0'.
- New check_updates MCP tool returns the maximal-style status shape
  { current, latest, update_available, checked_at, last_error, enabled }
  so a client can check without a list_skills side effect. Notify-only —
  never installs; routes users to the update-skills skill to apply.
- Driven by the same detector as the list_skills banner (one source of
  truth). handleRequest is now async to await a fresh registry check.
- REPL gains a 'check' command. Smoke tests updated (3 tools, real
  version, check_updates status shape).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs
The advertised 'npx ... --update' was a no-op. Replace it with a real,
notify-only upgrade flow: the user invokes the update-skills skill, which
detects the install type and runs the correct upgrade per type.

- Add detect-install.js (git / npm-global / npx).
- Rewrite SKILL.md: check -> detect -> apply (npx cache clear, npm -g
  @latest, or git fetch/checkout) -> restart -> verify. No bare 'git
  checkout' advertised to npm installs; no dangling --update flag.
- Notify-only: nothing auto-installs; the detector only surfaces status
  and the user drives the apply. Bump skill version to 2.0.0.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs
…UDE.md

The router ships semantic-index.json for embedding-based search, but the
only builder lived in site/ and never ran in the publish path (prepublishOnly
builds only the keyword index.json; the publish job ran npm publish directly).
npm silently skips the missing file, so published packages fell back to
keyword-only search.

- Add root 'build:semantic' script that runs the site's sync + semantic build.
- publish.yml builds the semantic index before npm publish, best-effort
  (continue-on-error) so a model-download blip never blocks a release.
- Correct CLAUDE.md: the index files are gitignored (not committed), built
  at publish time; semantic-index.json comes from the site builder / CI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs
…riptions

npm run validate (and check:llms) were red on main: 11 skills had a
colon-space inside their unquoted description, which the router's lenient
line-parser tolerates but strict YAML (quick_validate) rejects with
'mapping values are not allowed here'.

- pages-*-vite (5): 'USE FOR:' → 'USE FOR —'.
- tauri-* (6): drop the space after in-value colons in code-like fragments
  (decorations:false, transparent:true, sidecar:true, pattern:{ use:"…" },
  capabilities:[…], invoke:Invoke), preserving the leading 'description:' key.

The repo's line-parser can't handle quoted or block scalars, so the fix
removes the colon-space rather than quoting. Regenerated README.md and
llms.txt. npm run ci is now green end to end.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs
…arsers

The lenient hand-rolled parsers in build-index.js and generate_llms_txt.py
accepted invalid YAML that the validator (quick_validate.py / PyYAML)
rejects — the divergence that let 11 skills ship unquoted colons in their
descriptions. Converge both on a real YAML parse so they accept/reject
exactly what the validator does.

- build-index.js: parse via js-yaml (new devDep) when available, falling
  back to the line parser only if it's absent (mirrors quick_validate's
  try/except-yaml). Invalid YAML → null → skill skipped and flagged by
  validate, never mis-parsed into a corrupt index entry. Export
  parseFrontmatter and guard the auto-run with require.main.
- generate_llms_txt.py: parse via PyYAML with the same fallback.
- Fixes a latent bug this surfaced: 9 skills with double-quoted descriptions
  were leaking literal quote characters into index.json/llms.txt (degrading
  router search); real YAML strips them. Regenerated llms.txt.
- Add test-build-index.js: unquoted colon-space is rejected; quoted values
  and block scalars may contain colons; nested metadata survives; never
  throws. Wired into npm test.

Note: site/scripts/sync-skills.js has the same lenient parser; hardening it
needs the site's heavy deps (blocked here) — left as a follow-up.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01C8RykrdHzASymQEQTDbJTs
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