fix(kyberforge): bridge apm content to Claude Code's flat plugin discovery
Claude Code's (and Copilot's) native plugin installer has zero awareness of .apm/ nesting -- it convention-scans only flat skills/, agents/, commands/, hooks.json at each plugin's root. Confirmed via strings on the installed claude binary and live installs of git@holocron/gitea@holocron/kyberforge@ holocron, all reporting Skills(0) Agents(0) Hooks(0) post ADR-0015's apm conversion. Root cause (apm_cli/core/plugin_manifest.py): apm's plugin.json compiler deliberately strips skills/agents/commands keys, assuming the host already auto-discovers those convention directories -- it has no model of .apm/ being host-visible at all. Separately, apm's own bundle exporter (apm_cli/bundle/plugin_exporter.py, behind `apm pack --format plugin`) implements the correct .apm/ -> flat mapping, but only ever targeted build/<name>-<version>/, a path nothing in marketplace.json's source: points at. scripts/sync-plugin-content.sh wraps that bundle exporter and copies its agents/, skills/, commands/, instructions/, extensions/, and merged hooks.json back into each plugin's own root as a second tracked compiled-output category -- same governance status as .claude-plugin/plugin.json: generated from .apm/, never hand-edited. tests/ subdirectories are excluded from the mirror (dev fixtures, not host-visible runtime content; several hardcode a relative repo-root walk-up sized for the .apm/-nested depth, which breaks when duplicated one level shallower). Applied for real across all 6 plugins and verified two ways: `claude plugin validate --strict` passes on every real plugin directory, and a live `claude --plugin-dir <path> -p "list skills/agents"` behavioral test confirms content is now actually discovered. Also, from the same issue #90 review round: - scripts/check-manifests.sh pointed at each plugin's root-level plugin.json (checking skills/hooks/mcpServers/agents pointer fields) -- that file was a stale near-duplicate of .claude-plugin/plugin.json nothing else read or wrote, now deleted across all 6 plugins. check-manifests.sh is rewritten to validate .claude-plugin/plugin.json instead, and drops the pointer-field checks entirely (nothing to check -- those fields are correctly absent by design). Content-presence drift is now check-plugin-content-sync's job, a new pre-push hook wired in .pre-commit-config.yaml. docs/adr/0017 records the root cause and decision in full, including two rejected alternatives (patching plugin.json's path fields directly -- apm's compiler strips them on every run; pointing marketplace.json at apm pack's build/ output -- a version-suffixed non-source directory nothing can install from without an extra build step). ADR-0015 and CONTEXT.md are updated to point at it. Refs: #90
This commit is contained in:
22
plugins/git/skills/git-branches/README.md
Normal file
22
plugins/git/skills/git-branches/README.md
Normal file
@@ -0,0 +1,22 @@
|
||||
# git-branches
|
||||
|
||||
Manage the full lifecycle of git branches — create, switch, delete, rename, and track feature/hotfix/release branches under GitHub Flow or Gitflow.
|
||||
|
||||
## What it does
|
||||
|
||||
This skill handles branch operations within the git workflow suite. It creates branches following GitHub Flow or Gitflow conventions (configurable), switches and tracks branches, handles safe deletion with unmerged-work checks, and retrieves branch intent metadata for use by other skills (e.g., commit message context). It returns structured results suitable for agent composition.
|
||||
|
||||
## Usage
|
||||
|
||||
```
|
||||
/git-branches
|
||||
```
|
||||
|
||||
Describe your branch task: create a feature/hotfix/release branch, switch, delete, rename, or track. The skill will determine the branching pattern (GitHub Flow or Gitflow) from config or repo state and handle safety checks for destructive operations.
|
||||
|
||||
## Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `SKILL.md` | Skill instructions for agents |
|
||||
| `references/sources.md` | Research sources backing the branching/gitflow guidance |
|
||||
112
plugins/git/skills/git-branches/SKILL.md
Normal file
112
plugins/git/skills/git-branches/SKILL.md
Normal file
@@ -0,0 +1,112 @@
|
||||
---
|
||||
name: git-branches
|
||||
|
||||
description: >
|
||||
Use when managing the full lifecycle of git branches: create feature/hotfix/release branches
|
||||
(gitflow, GitHub Flow, or custom patterns from config), switch, delete, rename, and track branches,
|
||||
or retrieve branch intent metadata. Handles branch protection safety checks and returns structured
|
||||
results for agent composition. Use even if the user doesn't explicitly mention branch names — they
|
||||
may be asking about "fixing something" or "shipping a feature", which implicitly requires branch
|
||||
management. Do not use when the user needs only commit operations (use git-commits) or history
|
||||
inspection (use git-history).
|
||||
|
||||
metadata:
|
||||
category: git
|
||||
source_keys:
|
||||
- context7-git-htmldocs
|
||||
- nvie-gitflow-post
|
||||
- atlassian-gitflow-tutorial
|
||||
- gitflow-cheatsheet
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Branches are cheap; deletion is cheap but risky.** Deleting one requires checking if commits on it are reachable elsewhere; always confirm before deleting, as it may lose unmerged work.
|
||||
- **Uncommitted changes can block branch switches.** `git switch` aborts if local modifications conflict with the target branch. Offer to stash changes before switching when this happens, don't force a checkout.
|
||||
- **Tracking relationships matter for coordination.** Agents pushing on behalf of users should always set tracking (`-u origin <branch>`) so later pushes/pulls know the target. Without it, commands fail or target the wrong remote branch.
|
||||
- **Gitflow vs. GitHub Flow are not compatible.** Gitflow requires `develop` and `release/*` branches with `--no-ff` merges; GitHub Flow uses only `main` and feature branches with fast-forward. Read the repo's config or ask the orchestrator which pattern to use — don't guess.
|
||||
- **Naming collisions with tags.** A branch and tag can have the same name. Prefer `git switch` over `git checkout` for branch operations — verify which ref you're targeting with `git branch --list <name>` / `git tag --list <name>` if the name could be ambiguous, and disambiguate explicitly with `refs/heads/<name>` (branch) or `refs/tags/<name>` (tag) where a command accepts either.
|
||||
- **Never force-push `main` or `master`.** This is a hard refusal, not a confirmation gate — it applies even if the caller passes `confirm: true`. Deleting or renaming `main`/`master` in a way that would require a force-push to reconcile the remote (e.g. force-deleting and recreating it, or renaming it out from under in-flight work) must be rejected outright; explain why and suggest a non-destructive alternative (e.g. a new branch) instead of proceeding.
|
||||
|
||||
## Branch Patterns
|
||||
|
||||
Default to **GitHub Flow** (simpler, modern, CI/CD-friendly). Fall back to **Gitflow** only if the repo's config specifies it or the branch structure shows it in use (presence of `develop` or release branches).
|
||||
|
||||
**GitHub Flow:**
|
||||
- Base: `main`
|
||||
- Feature branches: `feature/<feature-name>` or `fix/<bug-name>`
|
||||
- Merge: fast-forward when possible (preserves linear history)
|
||||
- Delete after merge
|
||||
|
||||
**Gitflow:**
|
||||
- Base: `main` (production) + `develop` (integration)
|
||||
- Feature branches: `feature/<feature-name>` (from `develop`)
|
||||
- Release branches: `release/X.Y.Z` (from `develop`, merged to `main` + `develop`)
|
||||
- Hotfix branches: `hotfix/X.Y.Z` (from `main`, merged to `main` + `develop`)
|
||||
- Merge: always use `--no-ff` to preserve branch structure
|
||||
|
||||
## Workflow
|
||||
|
||||
- [ ] **Determine pattern:** Check git plugin config (`.claude/plugins/git/config.json`, if present — see `config.example.json` in the plugin root for the expected shape) for `branching_pattern` (default: `github-flow`). If not set, inspect repo for `develop` branch or `release/*` branches; if present, assume Gitflow.
|
||||
- [ ] **Create branch:** Use `git switch -c <branch> <base>`. Base defaults to config's `base_branch` (usually `main` or `develop`). Include intent metadata in branch name or return as structured result (e.g., `{ "branch": "feature/x", "intent": "implement feature X" }`).
|
||||
- [ ] **Track remote:** If pushing, always use `git push -u origin <branch>` to establish tracking.
|
||||
- [ ] **Safety checks before destructive ops:** Before delete/force-push/rebase with history loss, check: (1) Is this branch tracking a remote? Warn if yes. (2) Are there unpushed commits? Warn if yes. (3) Does the orchestrator call include `confirm: true`? Fail if not. For humans, prompt interactively.
|
||||
- [ ] **Return structured results:** Always return branch operations as JSON or structured text: `{ "action": "create", "branch": "feature/x", "base": "main", "tracking": "origin/feature/x", "intent": "implement feature X" }`. Agents need to parse this for subsequent operations.
|
||||
- [ ] **Retrieve intent (`get-intent`):** Git has no native field for free-text branch metadata — this skill doesn't persist it. On `create`, the `intent` value is only ever returned in the structured result; the caller (orchestrator or agent) is responsible for storing it if it needs to be looked up later. On `get-intent`, either parse it back out of the branch name convention (`feature/<intent-slug>`) or return `{ "intent": null }` if the caller never persisted the original create-time value — don't fabricate an intent.
|
||||
|
||||
### Command mapping for each action
|
||||
|
||||
- **delete:** `git branch -d <branch>` refuses if the branch has unmerged commits — prefer this by default. `git branch -D <branch>` forces deletion and discards unmerged work; only use it after the safety checks above pass and `confirm: true` is set. For a remote branch: `git push origin --delete <branch>`.
|
||||
- **rename:** `git branch -m <old> <new>`.
|
||||
- **list:** `git branch` (local only), `git branch -a` (all local + remote-tracking), `git branch -r` (remote-tracking only), `git branch --merged`/`--no-merged` (filter by merge status into current branch).
|
||||
- **get-intent:** No git command — see Workflow step "Retrieve intent" for how this is resolved.
|
||||
- **track (existing branch):** `git branch --set-upstream-to=origin/<branch>` sets tracking without a push; `git branch -vv` shows tracking state for all local branches.
|
||||
- **switch (existing branch):** `git switch <branch>` — switches to an existing local branch (aborts on conflicting local changes, see Gotchas). `git switch -` switches back to the previously checked-out branch.
|
||||
|
||||
## Merging
|
||||
|
||||
Scope: fast-forward/merge-commit mechanics and conflict resolution only. Rebase, cherry-pick, and revert belong to `git-history`.
|
||||
|
||||
- **Fast-forward:** `git merge <branch>` — advances the pointer with no merge commit if the target hasn't diverged.
|
||||
- **True merge:** `git merge --no-ff <branch>` — forces a merge commit even when fast-forward is possible; required by Gitflow on all supporting-branch merges.
|
||||
- **Squash merge:** `git merge --squash <branch>` stages the combined diff without committing; follow with a manual `git commit`.
|
||||
- **Octopus merge:** `git merge branch-a branch-b branch-c` merges more than two branches at once; fails outright on any conflict, so use sequential two-way merges if conflicts are expected.
|
||||
|
||||
**Conflict resolution:** when Git can't auto-merge, it inserts conflict markers and stops. Run `git status` to find conflicted files, edit them to resolve the markers, then `git add <file>` and `git merge --continue`. `git merge --abort` reverts to the pre-merge state. `git mergetool` opens the configured merge tool; `git diff --diff-filter=U` shows only conflicted files.
|
||||
|
||||
## Comparing Branches
|
||||
|
||||
- `git log main..feature` — commits in `feature` not in `main`.
|
||||
- `git log feature..main` — commits in `main` not in `feature` (reverse direction).
|
||||
- `git log --left-right main...feature` — both diverging sets (symmetric diff).
|
||||
- `git diff main...feature` — diff from the common ancestor to `feature`'s tip.
|
||||
- `git merge-base main feature` — print the common ancestor commit.
|
||||
|
||||
## Integration with Orchestrator
|
||||
|
||||
When invoked by `git-orchestrate`, accept requests in the form:
|
||||
```json
|
||||
{
|
||||
"action": "create|switch|delete|rename|track|list|get-intent",
|
||||
"branch": "<branch-name>",
|
||||
"base": "<base-branch (optional, defaults to config)>",
|
||||
"intent": "<human-readable intent (optional)>",
|
||||
"confirm": "<true for destructive ops, omit for read ops>"
|
||||
}
|
||||
```
|
||||
|
||||
Return results as:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"action": "create|switch|...",
|
||||
"branch": "<name>",
|
||||
"message": "descriptive message",
|
||||
"intent": "<intent if tracked>",
|
||||
"tracking": "origin/<branch (if set)>",
|
||||
"error": "<error message if success=false>",
|
||||
"suggestion": "<recovery suggestion if applicable>"
|
||||
}
|
||||
```
|
||||
|
||||
If error is due to uncommitted changes, include `{ "suggestion": "stash changes and retry" }` so the orchestrator can offer automatic recovery.
|
||||
48
plugins/git/skills/git-branches/references/sources.md
Normal file
48
plugins/git/skills/git-branches/references/sources.md
Normal file
@@ -0,0 +1,48 @@
|
||||
---
|
||||
# Research sources referenced by this skill
|
||||
# Each entry documents where the skill's guidance came from.
|
||||
---
|
||||
|
||||
## nvie-gitflow-post
|
||||
|
||||
**Description:** Original 2010 post by Vincent Driessen introducing the Gitflow branching model, including a 2020 reflection note recommending GitHub Flow for continuous delivery teams.
|
||||
|
||||
**Source:** https://nvie.com/posts/a-successful-git-branching-model/
|
||||
|
||||
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
|
||||
|
||||
**Contributing files:**
|
||||
- SKILL.md (Branch Patterns — Gitflow vs. GitHub Flow structure and defaults)
|
||||
|
||||
## atlassian-gitflow-tutorial
|
||||
|
||||
**Description:** Atlassian's comprehensive Gitflow tutorial covering all five branch types, lifecycle steps, and CLI usage.
|
||||
|
||||
**Source:** https://www.atlassian.com/git/tutorials/comparing-workflows/gitflow-workflow
|
||||
|
||||
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
|
||||
|
||||
**Contributing files:**
|
||||
- SKILL.md (Branch Patterns — Gitflow branch types, base/merge targets, `--no-ff` requirement)
|
||||
|
||||
## gitflow-cheatsheet
|
||||
|
||||
**Description:** Visual cheatsheet for the git-flow CLI commands (git-flow-avh fork), covering all subcommands for feature, release, and hotfix branches.
|
||||
|
||||
**Source:** https://danielkummer.github.io/git-flow-cheatsheet/
|
||||
|
||||
- **Research doc:** plugins/git/docs/research/docs/git/gitflow.md (whole-document reference)
|
||||
|
||||
**Contributing files:**
|
||||
- SKILL.md (Branch Patterns — feature/release/hotfix naming conventions)
|
||||
|
||||
## context7-git-htmldocs
|
||||
|
||||
**Description:** Official Git HTML documentation from the git/htmldocs repository — covers all commands, concepts, and internals.
|
||||
|
||||
**Source:** context7:/git/htmldocs
|
||||
|
||||
- **Research doc:** plugins/git/docs/research/docs/git/branching-merging.md (whole-document reference)
|
||||
|
||||
**Contributing files:**
|
||||
- SKILL.md (Command mapping, Merging, Comparing Branches — `git switch`/`git branch`/`git merge`/`git log`/`git diff`/`git merge-base` command vocabulary and flags)
|
||||
Reference in New Issue
Block a user