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,81 +0,0 @@
|
||||
---
|
||||
topic: branches
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
---
|
||||
|
||||
# Branch operations
|
||||
|
||||
Call signatures below were verified live against the deployed `gitea-mcp` server via `ToolSearch`
|
||||
at authoring time, not copied from research docs — this is deliberate: research docs are generated
|
||||
from source code at a point in time and can drift from the server actually deployed. Re-verify
|
||||
against the live schema if these tools appear to behave differently than documented here.
|
||||
|
||||
## `list_branches`
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `page` (number, optional, default: `1`)
|
||||
- `per_page` (number, optional, default: `30`)
|
||||
|
||||
**Call:**
|
||||
```
|
||||
list_branches owner: <owner> repo: <repo>
|
||||
```
|
||||
|
||||
**Response:** one object per branch: `name`, `protected` (bool), `commit_sha` (present when the
|
||||
underlying commit data is available).
|
||||
|
||||
Paginate if you need the full list (see Gotchas in SKILL.md) — iterate `page` until the returned
|
||||
count is less than `per_page`.
|
||||
|
||||
## `create_branch`
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `branch` (string, required) — new branch name
|
||||
- `old_branch` (string, optional) — source branch; if omitted, defaults to the repo's default
|
||||
branch server-side (not necessarily your current local checkout)
|
||||
|
||||
**Call:**
|
||||
```
|
||||
create_branch owner: <owner> repo: <repo> branch: <new-name> old_branch: <source-branch>
|
||||
```
|
||||
|
||||
Default dispatch: if the user gives a base ("branch off of X", "from X"), pass it as `old_branch`.
|
||||
If they don't specify a base and you're mid-task on a local branch, pass your current branch
|
||||
(`git branch --show-current`) as `old_branch` so the new branch forks from where you're actually
|
||||
working, rather than silently falling back to the repo default. If neither applies (e.g. a fresh
|
||||
top-level request with no working branch context), omit `old_branch` and let it default server-side.
|
||||
|
||||
A branch name collision returns `409 Conflict`.
|
||||
|
||||
## `delete_branch`
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `branch` (string, required)
|
||||
|
||||
**Call:**
|
||||
```
|
||||
delete_branch owner: <owner> repo: <repo> branch: <name>
|
||||
```
|
||||
|
||||
Before calling this, see the hard-refusal Gotcha in SKILL.md. If the target branch's name isn't
|
||||
obviously a scratch/feature branch, call `list_branches` first and check `protected` on the
|
||||
matching entry — name-matching `main`/`master` alone isn't authoritative, since a repo can protect
|
||||
a differently-named default branch. Confirm explicitly with the user before deleting anything
|
||||
protected, every time, regardless of how the request is phrased.
|
||||
|
||||
## Token scope
|
||||
|
||||
All three — `list_branches`, `create_branch`, `delete_branch` — require `write:repository`. Gitea
|
||||
gates reads behind write scope for repo-scoped operations, so `list_branches` needs the same scope
|
||||
as the write operations, not `write:issue` alone. An earlier version of this doc claimed
|
||||
`write:issue` alone was sufficient for `list_branches`, based on empirical testing under a token
|
||||
that held both `write:issue` and `write:repository` simultaneously — that test didn't isolate the
|
||||
variable, so it couldn't actually establish `write:issue` alone as sufficient.
|
||||
@@ -1,73 +0,0 @@
|
||||
---
|
||||
topic: commits
|
||||
source_keys:
|
||||
- gitea-mcp-repo
|
||||
- gitea-mcp-slim-go
|
||||
---
|
||||
|
||||
# Commit operations
|
||||
|
||||
Read-only commit history, scoped to a repo (optionally to one branch or one path). Call signatures
|
||||
below were verified live against the deployed `gitea-mcp` server via `ToolSearch` at authoring time,
|
||||
not copied from research docs, for the same drift-avoidance reason noted in `references/branches.md`.
|
||||
|
||||
This domain has no prior skill precedent — it's new coverage added alongside branches because commit
|
||||
history is naturally scoped to a branch (a "what happened on this branch" question), not because it
|
||||
shares any tool family with branch create/delete.
|
||||
|
||||
## `list_commits`
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `sha` (string, optional) — starting SHA or branch name; if omitted, gitea-mcp uses the repo's
|
||||
default branch
|
||||
- `path` (string, optional) — restrict results to commits that touched this file/path
|
||||
- `page` (number, optional, default: `1`, minimum: `1`)
|
||||
- `per_page` (number, optional, default: `30`, minimum: `1`)
|
||||
|
||||
**Call:**
|
||||
```
|
||||
list_commits owner: <owner> repo: <repo> sha: <branch-or-sha> path: <optional-path>
|
||||
```
|
||||
|
||||
Dispatch defaults:
|
||||
- "commits on `<branch>`" → pass `<branch>` as `sha`.
|
||||
- "commits touching `<path>`" (no branch mentioned) → pass `path` alone, `sha` omitted (defaults to
|
||||
the repo's default branch).
|
||||
- Both given → pass both; the result is history for that path, walked from that branch/SHA.
|
||||
- Neither given → omit both; this returns default-branch history, which is a reasonable default for
|
||||
an open-ended "what's the recent history here" question.
|
||||
|
||||
**Response:** one object per commit: `sha`, `html_url`, `created`, `message` (when available),
|
||||
`author` (`{name, email, date}`, when available).
|
||||
|
||||
Paginate per the manual-pagination Gotcha in SKILL.md if you need more than one page of history.
|
||||
|
||||
## `get_commit`
|
||||
|
||||
**Parameters:**
|
||||
- `owner` (string, required)
|
||||
- `repo` (string, required)
|
||||
- `sha` (string, required)
|
||||
|
||||
**Call:**
|
||||
```
|
||||
get_commit owner: <owner> repo: <repo> sha: <commit-sha>
|
||||
```
|
||||
|
||||
**Response:** same shape as a `list_commits` entry, but always fully populated (`message` and
|
||||
`author` are guaranteed present, not conditional). Use this when the user asks about one specific
|
||||
commit by SHA rather than browsing history — `list_commits` entries may omit `message`/`author` in
|
||||
edge cases, `get_commit` will not.
|
||||
|
||||
## Token scope
|
||||
|
||||
Both tools are believed to require `write:repository`, even though they're read-only — inferred by
|
||||
analogy with the scope-gating principle in `overview.md` (Gitea gates reads behind write scope for
|
||||
repo-scoped operations), not a claim `overview.md` makes for commits by name: its explicit
|
||||
`write:repository` enumeration lists PR, branch, file, release, and tag operations, but doesn't
|
||||
mention commits. An earlier version of this doc claimed `write:issue` alone worked, based on
|
||||
empirical testing under a token that held both `write:issue` and `write:repository`
|
||||
simultaneously — that test didn't isolate the variable either. Treat this as unverified until
|
||||
tested under a token scoped to `write:issue` only (no `write:repository`).
|
||||
@@ -1,41 +0,0 @@
|
||||
# Sources
|
||||
|
||||
**Note on call signatures:** per `docs/adr/0011-gitea-skill-deep-modules.md`, the tool parameter
|
||||
signatures in `references/branches.md` and `references/commits.md` were re-verified live via
|
||||
`ToolSearch` against the deployed `gitea-mcp` server at authoring time — they are not copied
|
||||
verbatim from `api-reference.md` below. This resolves issue #6 comment #849's root-cause finding
|
||||
that a prior skill was authored from API docs that had drifted from the actual MCP tool schema.
|
||||
The research docs cited here informed gotchas, response shapes, and workflow context, not the
|
||||
parameter lists themselves.
|
||||
|
||||
## gitea-mcp-repo
|
||||
|
||||
- **URL:** https://gitea.com/gitea/gitea-mcp
|
||||
- **Description:** Official gitea-mcp repository (v1.3.0); operation/*.go source files documenting all 55 MCP tools, their parameters, and CLI flags. Informed the dispatch table and pagination / 404-may-mean-403 gotchas in SKILL.md, and the list/create/delete branch and list/get commit mechanics (including 409 conflict and default-branch fallback behavior) in references/branches.md and references/commits.md.
|
||||
- **Research doc:** plugins/gitea/docs/research/docs/gitea/sources.md
|
||||
- **Contributing files:** SKILL.md, references/branches.md, references/commits.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## gitea-mcp-slim-go
|
||||
|
||||
- **URL:** https://gitea.com/gitea/gitea-mcp/raw/branch/main/operation/repo/slim.go
|
||||
- **Description:** Slim response shape structs from gitea-mcp source; defines exactly which fields the MCP server returns for branches (name, protected, commit_sha) and commits (sha, html_url, created, message, author), and informed get_commit's always-populated guarantee vs. list_commits' conditional fields.
|
||||
- **Research doc:** plugins/gitea/docs/research/docs/gitea/sources.md
|
||||
- **Contributing files:** references/branches.md, references/commits.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## context7-websites-gitea
|
||||
|
||||
- **URL:** context7:/websites/gitea
|
||||
- **Description:** Official Gitea docs mirror on Context7 — informed the protected-branch gotcha in SKILL.md (protected branches can block server-side operations regardless of client-side checks; admins aren't exempt by default).
|
||||
- **Research doc:** plugins/gitea/docs/research/docs/gitea/sources.md
|
||||
- **Contributing files:** SKILL.md
|
||||
- **Status:** `extracted`
|
||||
|
||||
## context7-gitea-tea-cli
|
||||
|
||||
- **URL:** context7:/git_gitea_com/gitea_tea
|
||||
- **Description:** Official `tea` CLI docs on Context7 — practitioner conventions for issues, PRs, and releases (semver tags, draft/prerelease flags). Consulted as part of the shared research pass but its content is scoped to releases/tags, out of scope for branches/commits — no content from it was used in this skill.
|
||||
- **Research doc:** plugins/gitea/docs/research/docs/gitea/sources.md
|
||||
- **Contributing files:** (none)
|
||||
- **Status:** `extracted`
|
||||
Reference in New Issue
Block a user