feat(kyberforge): execute plugin-to-apm marketplace conversion
Why: ADR-0015 established that Microsoft APM (apm.yml + .apm/) should replace this repo's hand-authored plugin.json/marketplace.json model, with those files becoming compiled output of `apm pack` instead of files edited by hand via the (now-retired) plugin-author/marketplace-author skills. Issue #90 was the deferred execution of that decision, gated on #88 (apm tooling) and #89 (apm-native agent-author/skill-author routing). Implementation notes: - All six plugins (bin, core, git, gitea, kyberforge, lint) now carry apm.yml + .apm/{skills,agents,hooks} as their authoring source. Skills moved with a plain git mv (content-identical across targets). Agents were re-authored, not moved: per ADR-0016, .apm/agents/*.agent.md compiles verbatim to both Claude and Copilot, so plugin-scope agents now carry only name/description/model/source_keys -- no tools: field, no Claude-only knobs (isolation, maxTurns, effort, memory, permissionMode). - Root apm.yml registers all 7 marketplace packages (6 local plus mattpocock-skills as a remote entry) under versioning: per_package, matching this repo's existing independent-plugin-versioning practice. - .claude-plugin/marketplace.json and every plugin's plugin.json are now apm-pack-compiled output, verified against the prior hand-maintained content: same names/descriptions/versions/licenses/authors, only cosmetic serialization differences (JSON key order, owner email vs. url, Unicode escaping). - plugin-author and marketplace-author are retired now that apm-based authoring fully replaces their job; kyberforge bumped 1.3.1 -> 1.4.0 for that removal, and the root marketplace catalog bumped 0.3.1 -> 0.3.2 to match, per the version-bump convention now documented in apm-workflow's reference docs instead of a dedicated script (apm has no native version-bump automation). - Fixed hardcoded pre-.apm/ path assumptions across .pre-commit-config.yaml, .pre-commit-hooks.yaml, scripts/check-scope-walkup-sync.sh, scripts/sync-vale-styles.sh, scripts/check-vale-style-sync.sh, six plugins' root plugin.json (stale skills/hooks/agents pointer fields that check-manifests.sh validates), and several tests/*.bats and tests/*.sh fixtures -- including a bats REPO_ROOT relative-path depth bug (10 files, one extra .apm/ directory level to walk up) and a vale probe-path isolation regression introduced mid-fix. - Corrected empirically-wrong assumptions surfaced this session in apm-workflow/apm-install's own reference docs: `apm marketplace package add` does not accept local paths (only owner/repo remote shorthand -- local packages are registered by editing apm.yml's marketplace.packages[] directly); `apm compile` is a consumer-side AGENTS.md/CLAUDE.md generator, not the plugin.json producer, and hard-fails on skill/agent-only packages without --clean; `apm plugin init <name>` nests a stray subdirectory when run with a positional name arg from inside a same-named directory; no native Copilot marketplace output profile exists; .mcp.json is merged into the compiled plugin.json content-aware and target-scoped, with no dependencies.mcp entry needed for simple passthrough; pipx is the correct pip fallback on externally-managed Python environments. - Renamed agent-author's copilot.agent.md template asset to copilot.agent.md.template so apm compile's recursive *.agent.md glob stops misparsing the placeholder template as a real agent primitive. Impact: plugin.json and marketplace.json are compiled artifacts from here on -- editing them by hand is no longer the workflow; edit apm.yml/.apm/ and run apm pack. CONTEXT.md's Plugin/Plugin marketplace glossary entries reflect this. ADR-0001 is marked superseded, ADR-0006 moot, and ADR-0010 updated for the new .apm/agents/ path (project/user scope unaffected, per ADR-0016). Full local verification: claude plugin validate --strict on all 6 plugins, apm audit --ci, apm marketplace check, check-manifests.sh, and the full test suite (165/165 bats, 13/13 shell scripts) all pass clean. Fixes: #90 Refs: #88, #89 ADR: 0015 ADR: 0016 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Ub96PyaSRD9BHPktotj1pC
This commit is contained in:
@@ -1,112 +0,0 @@
|
||||
---
|
||||
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.
|
||||
Reference in New Issue
Block a user