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:
115
plugins/git/skills/git-commits/SKILL.md
Normal file
115
plugins/git/skills/git-commits/SKILL.md
Normal file
@@ -0,0 +1,115 @@
|
||||
---
|
||||
name: git-commits
|
||||
|
||||
description: >
|
||||
Use when creating, amending, squashing, or cherry-picking commits.
|
||||
Generates well-formatted commit messages following Conventional Commits spec (type, scope, description, body, footers).
|
||||
Validates against commitlint config-conventional constraints (header max 100 chars, lowercase subject, no trailing periods, type must be one of 11 standard types).
|
||||
Communicates SemVer impact (MAJOR for breaking changes, MINOR for features, PATCH for fixes).
|
||||
Handles confirmation gates for history-altering operations (amend, rebase, squash).
|
||||
Provides interactive guidance for humans, structured JSON output for agents.
|
||||
Do not use for: inspecting git history, branch management, or repository state inspection — those are separate skills.
|
||||
|
||||
metadata:
|
||||
version: "0.1.2"
|
||||
category: git
|
||||
source_keys:
|
||||
- conventional-commits-spec
|
||||
- commitlint-config-conventional
|
||||
- org-commit-conventions
|
||||
- context7-git-htmldocs
|
||||
|
||||
allowed-tools: Bash
|
||||
---
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **Type must be one of 11 standard types** — `feat`, `fix`, `perf`, `revert`, `docs`, `style`, `refactor`, `test`, `build`, `ci`, `chore`. Non-standard types will fail commitlint validation. Note: the Conventional Commits spec itself only mandates `feat`/`fix` — the 11-type set is a commitlint/Angular convention this skill validates against, not a spec requirement.
|
||||
- **Scope is optional but should be used** — helps identify which part of the system changed. Examples: `api`, `db`, `cli`, `config`.
|
||||
- **Header max 100 characters** — type + scope + colon + description must fit. If longer, move detail to body.
|
||||
- **BREAKING CHANGE notation** — use `!` before the colon (`feat!: drop Node 6`) for visibility in `git log --oneline`. Footer notation (`BREAKING CHANGE: ...`) is machine-readable but hidden in log.
|
||||
- **SemVer mapping is not optional** — agents must communicate: `feat` → MINOR bump, `fix`/`perf`/`revert` → PATCH, any with breaking change → MAJOR.
|
||||
- **Confirmation gates are mandatory for destructive operations** — amend, rebase, squash require explicit user/agent approval before execution.
|
||||
- **Never skip hooks with `--no-verify`** — hooks are the automated QA gate; bypassing them breaks the pipeline. Do not add this flag to any commit command unless the user explicitly demands it, and warn them if they do.
|
||||
- **Never force-push `main`/`master`** — even after an amend or interactive rebase, refuse to force-push a protected branch (`main`, `master`) and explain why; force-push is only safe on branches no one else has based work on.
|
||||
- **Command examples use the `rtk git` wrapper** — this org's convention routes all git invocations through `rtk git <subcommand>` instead of bare `git <subcommand>`. Follow this prefix in any command you actually run.
|
||||
- **Never commit secrets, credentials, or environment-specific config** — if staged changes contain what looks like an API key, token, password, or connection string, stop and flag it before committing rather than committing it.
|
||||
- **Commits must be atomic and leave the repo working** — each commit should be one logical, independently reviewable and reversible change, and should leave the repository in a buildable/testable state. If staged changes bundle unrelated work, suggest splitting before committing.
|
||||
- **Commit messages explain why, not what** — the diff already shows what changed; the message's job is to capture context the diff can't (motivation, root cause, tradeoffs). See `references/commit-template.md` for the structure this maps to.
|
||||
|
||||
## Workflow
|
||||
|
||||
### For creating a new commit:
|
||||
|
||||
1. **Gather context** — what changed and why? (from staged changes, PR description, issue context). Verify the staged diff is one logical, atomic change and that the repo would still build/test at this commit — if not, suggest splitting before proceeding.
|
||||
2. **Check for secrets** — scan the staged diff for anything that looks like a credential, API key, token, or environment-specific config. Stop and flag it rather than committing.
|
||||
3. **Determine type** — is this a feature (`feat`), bug fix (`fix`), or other? Default: check the change itself.
|
||||
4. **Determine scope** — which system/module? Use scope from plugin config if set, otherwise infer from files changed.
|
||||
5. **Write description** — imperative mood, no period. Neither source spec sets a length target below the 100-char header max, but convention favors keeping it to ~50 characters where possible for `git log --oneline` readability. Examples: "add user authentication", "fix race condition in cache".
|
||||
6. **Add body if needed** — explain why (not what). Blank line before body, wrap at 100 chars. For non-trivial changes, follow the Why / Implementation Notes / Impact structure in `references/commit-template.md`.
|
||||
7. **Add footers if needed** — `Fixes: #123`, `Refs: #123`, `ADR: 0012`, `RFC: 0003`, `Design: <link>`, `Reviewed-by: Name`, `Co-authored-by: Name <email>`, `Signed-off-by: Name <email>`, `BREAKING CHANGE: description`. See `references/commit-template.md` for the full trailer list.
|
||||
8. **Validate** — check header length, type correctness, no trailing periods, lowercase.
|
||||
9. **Confirm and execute** — for agents, require explicit approval; for humans, show preview and ask. Never add `--no-verify` to skip hooks.
|
||||
|
||||
### For amending a commit:
|
||||
|
||||
1. **Stage new changes** (or changes to undo)
|
||||
2. **Run amend operation** — executes `rtk git commit --amend [--no-edit]` based on user intent
|
||||
3. **Offer message edit** — if user wants to change commit message, show current message and prompt for new one
|
||||
4. **Confirm before force-push** — amending is only safe on non-shared branches; if the current branch is `main`/`master`, refuse to force-push and explain why rather than warning and proceeding
|
||||
|
||||
### For squashing commits (interactive rebase):
|
||||
|
||||
1. **Identify commits to squash** — typically the last N commits on current branch
|
||||
2. **Confirm operation** — squashing rewrites history; get explicit approval
|
||||
3. **Execute rebase** — `rtk git rebase -i HEAD~N`, mark older commits as `squash` or `fixup`
|
||||
4. **Handle merge conflicts** — if rebase halts, offer conflict resolution options or abort; do not resolve automatically without confirmation
|
||||
5. **Offer message composition** — if squashing interactive, allow message editing
|
||||
|
||||
### For squashing commits (autosquash — preferred when tagging at commit time):
|
||||
|
||||
Prefer this over manual interactive rebase when a commit is written to be folded into an earlier one, since it removes the manual "mark as squash/fixup" step and the risk of reordering the wrong line:
|
||||
|
||||
1. **Create the fixup/squash commit** — `rtk git commit --fixup=<commit>` (keeps target's message) or `rtk git commit --squash=<commit>` (lets you edit the combined message later). Both prefix the message with `fixup!`/`squash!` and target `<commit>`.
|
||||
2. **Confirm operation** — rewriting history still requires explicit approval before the rebase runs.
|
||||
3. **Execute** — `rtk git rebase --autosquash HEAD~N` (or `-i --autosquash` to review the plan first); git reorders and marks the `fixup!`/`squash!` commits against their targets automatically.
|
||||
4. **Handle merge conflicts** — same as manual rebase: offer resolution or abort, never resolve automatically without confirmation.
|
||||
|
||||
### For cherry-picking:
|
||||
|
||||
1. **Identify source commit(s)** — hash or branch reference
|
||||
2. **Confirm destination branch** — cherry-pick will replay commits on current branch
|
||||
3. **Execute cherry-pick** — `rtk git cherry-pick <commit-hash>`
|
||||
4. **Handle conflicts** — offer conflict resolution or abort
|
||||
5. **Report outcome** — successful replays, conflicts, or rejected commits
|
||||
|
||||
## Output format (for agent consumption)
|
||||
|
||||
Return structured JSON:
|
||||
|
||||
```json
|
||||
{
|
||||
"operation": "create|amend|squash|cherry-pick",
|
||||
"status": "success|conflict|rejected",
|
||||
"message": "Commit message or error description",
|
||||
"commit_hash": "abc1234",
|
||||
"semver_impact": "MAJOR|MINOR|PATCH|none",
|
||||
"breaking_change": true|false,
|
||||
"confirmation_required": true|false,
|
||||
"details": {
|
||||
"type": "feat",
|
||||
"scope": "api",
|
||||
"description": "add user authentication",
|
||||
"body": "optional body text",
|
||||
"footers": ["Fixes: #123", "Refs: #456", "ADR: 0012", "Reviewed-by: Alice", "Co-authored-by: Bob <bob@example.com>", "Signed-off-by: Alice <alice@example.com>"]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
For interactive human use, format as readable prose with clear prompts and previews.
|
||||
|
||||
## Reference
|
||||
|
||||
If a footer or type/scope edge case isn't covered above, read `references/conventional-commits-spec.md` for the full specification.
|
||||
|
||||
For the Why / Implementation Notes / Impact body structure and the full trailer list, read `references/commit-template.md`.
|
||||
Reference in New Issue
Block a user