diff --git a/.agents/skills/merge-and-release/SKILL.md b/.agents/skills/merge-and-release/SKILL.md index dcf4e34d..3eb31c30 100644 --- a/.agents/skills/merge-and-release/SKILL.md +++ b/.agents/skills/merge-and-release/SKILL.md @@ -103,11 +103,17 @@ skill covers all of it, scoped down by what the maintainer actually asks for. retried. 7. In the hub, when the chosen scope includes a release, bring this checkout to the merged content without discarding or mixing in anything local. First assert `git status --porcelain - --untracked-files=all --ignored` is empty, and stop and report rather than proceeding over any - uncommitted content, tracked, untracked, or gitignored, since `skills_install.py` installs - each skill directory with `shutil.copytree()`, which copies a gitignored stray file the same - as any other, so the plain porcelain form (silent on ignored paths) would pass this preflight - while one still rides along into the install. Then `git fetch origin main`, `git checkout main` + --untracked-files=all --ignored -- .agents/skills/ .claude-plugin/` is empty, and stop and + report rather than proceeding over any uncommitted content there, tracked, untracked, or + gitignored, since `skills_install.py` reads both paths: `shutil.copytree()` installs each + `.agents/skills/` skill directory for Codex/opencode, and `claude plugin marketplace add` + installs from `.claude-plugin/` for Claude Code, so a gitignored stray file under either rides + along the same as any other, and the plain porcelain form (silent on ignored paths) would pass + this preflight while one still rides into an install. Scoped to those two paths rather than + the whole tree, matching `skills_install.py`'s own `source_ref()` dirty check (`watched = + [SKILLS_SRC, CLAUDE_PLUGIN_DIR]`), since an ignored file elsewhere in the checkout (a build + cache, a lockfile) is not this preflight's concern and should not block the refresh on it. + Then `git fetch origin main`, `git checkout main` (or `git checkout -b main origin/main` the first time this checkout carries no local `main` at all, `checkout` rather than `switch` since the fleet's own `git` floor is undeclared and `checkout` needs no minimum version for this), and `git merge --ff-only origin/main`. diff --git a/.claude-plugin/fleet-skills/.source-digest b/.claude-plugin/fleet-skills/.source-digest index 93518134..db22d6f2 100644 --- a/.claude-plugin/fleet-skills/.source-digest +++ b/.claude-plugin/fleet-skills/.source-digest @@ -1 +1 @@ -332c16d2c066383b +86607328dc15eded diff --git a/.claude-plugin/fleet-skills/skills/merge-and-release/SKILL.md b/.claude-plugin/fleet-skills/skills/merge-and-release/SKILL.md index dcf4e34d..3eb31c30 100644 --- a/.claude-plugin/fleet-skills/skills/merge-and-release/SKILL.md +++ b/.claude-plugin/fleet-skills/skills/merge-and-release/SKILL.md @@ -103,11 +103,17 @@ skill covers all of it, scoped down by what the maintainer actually asks for. retried. 7. In the hub, when the chosen scope includes a release, bring this checkout to the merged content without discarding or mixing in anything local. First assert `git status --porcelain - --untracked-files=all --ignored` is empty, and stop and report rather than proceeding over any - uncommitted content, tracked, untracked, or gitignored, since `skills_install.py` installs - each skill directory with `shutil.copytree()`, which copies a gitignored stray file the same - as any other, so the plain porcelain form (silent on ignored paths) would pass this preflight - while one still rides along into the install. Then `git fetch origin main`, `git checkout main` + --untracked-files=all --ignored -- .agents/skills/ .claude-plugin/` is empty, and stop and + report rather than proceeding over any uncommitted content there, tracked, untracked, or + gitignored, since `skills_install.py` reads both paths: `shutil.copytree()` installs each + `.agents/skills/` skill directory for Codex/opencode, and `claude plugin marketplace add` + installs from `.claude-plugin/` for Claude Code, so a gitignored stray file under either rides + along the same as any other, and the plain porcelain form (silent on ignored paths) would pass + this preflight while one still rides into an install. Scoped to those two paths rather than + the whole tree, matching `skills_install.py`'s own `source_ref()` dirty check (`watched = + [SKILLS_SRC, CLAUDE_PLUGIN_DIR]`), since an ignored file elsewhere in the checkout (a build + cache, a lockfile) is not this preflight's concern and should not block the refresh on it. + Then `git fetch origin main`, `git checkout main` (or `git checkout -b main origin/main` the first time this checkout carries no local `main` at all, `checkout` rather than `switch` since the fleet's own `git` floor is undeclared and `checkout` needs no minimum version for this), and `git merge --ff-only origin/main`. diff --git a/.github/skills/merge-and-release/SKILL.md b/.github/skills/merge-and-release/SKILL.md index dcf4e34d..3eb31c30 100644 --- a/.github/skills/merge-and-release/SKILL.md +++ b/.github/skills/merge-and-release/SKILL.md @@ -103,11 +103,17 @@ skill covers all of it, scoped down by what the maintainer actually asks for. retried. 7. In the hub, when the chosen scope includes a release, bring this checkout to the merged content without discarding or mixing in anything local. First assert `git status --porcelain - --untracked-files=all --ignored` is empty, and stop and report rather than proceeding over any - uncommitted content, tracked, untracked, or gitignored, since `skills_install.py` installs - each skill directory with `shutil.copytree()`, which copies a gitignored stray file the same - as any other, so the plain porcelain form (silent on ignored paths) would pass this preflight - while one still rides along into the install. Then `git fetch origin main`, `git checkout main` + --untracked-files=all --ignored -- .agents/skills/ .claude-plugin/` is empty, and stop and + report rather than proceeding over any uncommitted content there, tracked, untracked, or + gitignored, since `skills_install.py` reads both paths: `shutil.copytree()` installs each + `.agents/skills/` skill directory for Codex/opencode, and `claude plugin marketplace add` + installs from `.claude-plugin/` for Claude Code, so a gitignored stray file under either rides + along the same as any other, and the plain porcelain form (silent on ignored paths) would pass + this preflight while one still rides into an install. Scoped to those two paths rather than + the whole tree, matching `skills_install.py`'s own `source_ref()` dirty check (`watched = + [SKILLS_SRC, CLAUDE_PLUGIN_DIR]`), since an ignored file elsewhere in the checkout (a build + cache, a lockfile) is not this preflight's concern and should not block the refresh on it. + Then `git fetch origin main`, `git checkout main` (or `git checkout -b main origin/main` the first time this checkout carries no local `main` at all, `checkout` rather than `switch` since the fleet's own `git` floor is undeclared and `checkout` needs no minimum version for this), and `git merge --ff-only origin/main`. diff --git a/scripts/skills_install.py b/scripts/skills_install.py index 1b521648..4e9b254c 100755 --- a/scripts/skills_install.py +++ b/scripts/skills_install.py @@ -282,9 +282,11 @@ def main(): stamp_path.write_text( json.dumps(build_stamp(claude_registered), indent=2) + "\n", encoding="utf-8" ) - print( - f"Installed to {home / 'skills'}. Claude Code marketplace registered: {claude_registered}." - ) + # Materializing skills and registering the marketplace are independent operations. + # Each can succeed or be skipped on its own (`claude` missing skips only the second). + # Separate lines keep that distinction once a third target (Codex/opencode) joins them. + print(f"Skills materialized to {home / 'skills'}.") + print(f"Claude Code marketplace registered: {claude_registered}.") # `claude` missing is a partial-but-expected install (a Codex/opencode-only machine). # `claude` present but registration failing is a real failure.