hiroro-work/claude-plugins

verify-bundle-sync

Verify the dev-workflow-bundle canonical and bundle copy directories are in sync. Workaround for upstream symlink bug; delete this skill and its callers when symlinks are restored.

First seen May 19, 2026

Installation

$ npx skills add hiroro-work/claude-plugins --skill verify-bundle-sync

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from hiroro-work/claude-plugins · top by installs.

npx skills add hiroro-work/claude-plugins

Browse all from hiroro-work/claude-plugins

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Repository health

Stars 47
Default branch main
Open issues 0
Status Active

Skill metadata

Parsed from SKILL.md frontmatter.

Allowed toolsBash(jq *), Bash(diff *), Bash(test *)
Declared agents claude-code

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 6,127 B
  • docs SUMMARY.md 206 B

History

  1. First seen on skills.sh
  2. First recorded snapshot · 7 installs

SKILL.md

Verify Bundle Sync

This skill exists solely to work around an upstream Claude Code symlink bug (anthropics/claude-code#53948) that requires plugins/dev-workflow-bundle/skills/<name>/ to be a real directory copy of skills/<name>/ rather than a symlink. It is a project-local skill (lives under .claude/skills/verify-bundle-sync/, not registered in .claude-plugin/marketplace.json). When the bug is fixed and the bundle layout returns to symlinks, delete this skill directory, the .claude/dev-workflow.md test_commands entry, the dev-workflow-triage (d4) sub-step, and the .claude/rules/project.rules.md bullet that document this workaround.

The skill compares each bundle member's canonical directory against its bundle copy and reports drift. It is detect-only — it never modifies any files.

Process

Accepts an optional --base-commit <sha> argument (ignored — the scope is structural, not changeset-dependent). Running with no arguments behaves identically.

Run the following directly in the main thread (no subagent dispatch is needed — the check is lightweight: one jq invocation plus one diff -rq per bundle member).

  1. Load the bundle membership list from .claude-plugin/marketplace.json:

``bash bundleskills=$(jq -r '(.plugins[] | select(.name == "dev-workflow-bundle") | .skills[]) // empty' .claude-plugin/marketplace.json 2>/dev/null) # If $bundleskills is empty after this guard, halt and emit the Return contract response # (Layer 1 prose Status: EXECUTION_ERROR + Layer 2 fenced JSON with status: "error", # reason: "marketplace.json missing, malformed, or dev-workflow-bundle plugin entry absent") # immediately — see § Return contract. ``

The // empty is the array-enumeration null-fallback idiom: when the entry / array is absent, it yields a zero-length stream (no literal null\n leaking to stdout). This is a different concern from the canonical scalar // "unknown" pattern documented in .claude/rules/project.rules.local.md § jq の null 文字列フォールバック, which targets scalar values. The post-pipeline [ -z "$output" ] guard catches array absence, jq non-zero exit, and file-not-found uniformly.

  1. For each bundle member entry ./skills/<name>:

- Resolve canonical=skills/<name>/ - Resolve bundlecopy=plugins/dev-workflow-bundle/skills/<name>/ - Verify both directories exist with test -d "$canonical" && test -d "$bundlecopy". If either is missing, exit immediately with EXECUTIONERROR and report which path was missing. - Run diff -rq "$canonical" "$bundlecopy". Capture stdout. If exit code is non-zero AND stdout is empty, treat as EXECUTIONERROR (tool failure). If stdout is non-empty, treat every output line as a drift entry — each line is one of: - Files <canonical-path> and <bundle-copy-path> differ → type: "differ" - Only in <canonical-dir>: <file> → type: "onlyincanonical" - Only in <bundle-copy-dir>: <file> → type: "onlyin_copy"

  1. Aggregate the result:

- All entries drift-free → SUCCESS (e.g. 6 bundle skills verified, 0 drift) - Any entry has drift → TESTFAILED. Include the per-entry drift list and a remediation hint of the form cp -R skills/<name>/. plugins/dev-workflow-bundle/skills/<name>/ for each affected member - jq failed / diff missing / marketplace.json unreadable / per-entry path missing → EXECUTIONERROR

EXECUTIONERROR is deterministic within a run: marketplace.json absence, missing tooling (jq / diff), and missing path entries do not become resolved during the same run, so retrying the same invocation will not change the outcome. Callers that retry on EXECUTIONERROR (such as dev-workflow Phase 9's retry handler) will simply burn through their retry budget producing the same error each time — that wastes a few extra invocations but is harmless.

Return contract

The skill emits its result in two layers in a single response so that both prose-reading callers (such as dev-workflow Phase 9) and JSON-parsing callers (such as dev-workflow-triage (d4)) can extract the verdict mechanically.

Layer 1 — Prose summary (first, at the top of the response):

Status: SUCCESS | TEST_FAILED | EXECUTION_ERROR

<one-paragraph human-readable summary>
<if TEST_FAILED: per-entry drift list with remediation hint lines>
<if EXECUTION_ERROR: reason and which step failed>

Layer 2 — Fenced JSON verdict (last, at the end of the response):

````

{
  "status": "ok" | "drift" | "error",
  "checked_count": <int>,
  "drift_files": [{"skill": "<name>", "path": "<relative-path>", "type": "differ|only_in_canonical|only_in_copy"}],
  "reason": "<optional, required when status=error>"
}

````

Mapping between the prose status token and the JSON status field:

Prose Status: JSON status
SUCCESS ok
TEST_FAILED drift
EXECUTION_ERROR error
  • checkedcount: number of bundle member entries actually inspected (8 at the time of writing — ask-peer, dev-workflow, extract-rules, rules-review, tidy, prose-polish, mobpro, kabeuchi). If the list could not be loaded (EXECUTIONERROR from Step 1), set this to 0.
  • drift_files[]: drift / one-sided-presence entries, populated only for status: "drift". Empty array for ok and error. The path value preserves the raw line as it appeared in diff -rq output so that downstream rendering does not need to re-derive it.
  • reason: required on status: "error". Short, ≤ 80 characters. Examples: marketplace.json missing, dev-workflow-bundle plugin entry absent, jq not in PATH, canonical missing: skills/ask-peer.