The dispatch row "Create tracking a remote branch" prescribed
`git worktree add <path> <remote>/<branch>`. Per git-worktree(1) the
tracking DWIM fires only when <commit-ish> is a bare branch name that is
NOT found locally, no -b/-B/--detach is given, and exactly one remote has
a matching name; only then is it equivalent to
`git worktree add --track -b <branch> <path> <remote>/<branch>`.
An explicit <remote>/<branch> is found, so that precondition fails and no
branch is created: the result is a detached HEAD with no upstream. Commits
made in it become unreachable once the worktree is removed or HEAD moves,
and push needs an explicit refspec. Only the -d row was flagged detached.
The table now names --track -b as the always-correct form, keeps the bare
name shortcut with its precondition stated, and adds a Never row for the
<remote>/<branch> spelling. The single-remote and checkout.defaultRemote
preconditions move into the body, since a reader who trusts the table
never follows the reference pointer.
Also corrects `git worktree repair`: the no-argument form is the only
cwd-dependent one, and `repair <path>...` runs from any worktree. The
claim that running it from the wrong directory "reports nothing and fixes
nothing" has no basis in the manual and is removed.
Found by an independent review of this branch.
Refs #99
An independent audit of the ADR-0020 retrofit (issue #99) found that
git-submodules, git-worktrees, and gitea-files each collapsed their
description length correctly during retrofit but left the capability
clause as a verb enumeration (e.g. "Create, list, lock, move, remove,
prune, or repair") instead of ADR-0020's required single clause. The
deterministic char-count gate can't catch this — it's a qualitative
rubric violation the retrofit commits' own messages never claimed to
address, only measurable length/word-count fixes.
Validated clean via skill-audit and skill-size-check after the fix;
boundary clauses and routing targets left untouched.
Refs #99
Description 475 -> 213 chars, body 680 -> 212 words. Create and modify
become self-contained flow files behind a dispatch table, since the two are
mutually exclusive on whether the config already exists.
Passed its clean-context audit with no must-fix findings.
Description 477 -> 211 chars, body 736 -> 367 words. Install, autoupdate,
and clean become flow files behind the Route table.
The audit found no route for 'hooks aren't running': the only pointer to
failure-patterns.md sat inside the failure path, but when hooks never fire
the manual run succeeds, so the request fell to the ambiguity default and
was masked. Restores the disclosure that install -f is not reversible by
uninstall.
Description 450 -> 266 chars, body 1044 -> 462 words. The bisect procedure
moves to references/bisect.md.
The boundary clause read 'not writing or rewriting commits', which
disclaimed the cherry-pick and revert this skill's own Step 3 executes; it
now excludes authoring and rebasing only. Adds 'backport' so cherry-pick is
reachable by natural language at all, accepting 266 chars against a 250
soft target and a 400 ceiling.
Description 480 -> 248 chars, body 1011 -> 347 words. The single
submodules.md splits into setup-and-update, urls-and-config, and removal.
Restores three regressions the first pass introduced: 'repointing' as the
trigger for the URL branch, which had none while the boundary clause
steered those queries to git-remotes; clone and absorbgitdirs in the output
enum, which dispatch still routed to; and status --cached, the flag that
makes the pre-commit pointer gate verifiable.
Description 566 -> 249 chars, body 644 -> 398 words, Gotchas 12 -> 2. The
eight organisational hard rules move to references/hard-rules.md.
Its load trigger enumerates operations rather than rule topics: the first
draft keyed on 'commit message form', which left the atomicity and
working-state rules unreachable when a caller supplied a conventional
message. Also promotes the destructive-op confirmation ahead of the
orchestrator invocation, which it previously followed.
Description 582 -> 237 chars, body 1217 -> 290 words. The single remotes.md
splits into config, fetch, push, and pull flow files.
Restores the confirm: true token to the force-push gate -- it is the git
plugin's cross-skill contract, gated on by git-orchestrate and git-branches.
Moves push.md's worked example off main, which the skill's own Step 1
refuses, and restores the never-bare---force directive.
Description 592 -> 248 chars, body 756 -> 515 words, Gotchas 8 -> 4.
The audit found the dispatch table had no row for a worktree on an
existing local branch, so that request fell to the adjacent -B row, which
resets the branch to HEAD and discards its commits. Non-destructive create
is now the first row and -B names its own destructiveness. Adds the missing
lock/unlock row and repair's run-from constraint.
Description 612 -> 273 chars, body 1124 -> 457 words. Branch patterns,
operations, merging, comparison, and the orchestrator contract move to
references/.
Corrects rebase routing in four places: this skill sent rebase to
git-history, which carries no rebase content and disclaims it. Rebase is
git-commits'; cherry-pick and revert stay git-history's. Drops a Step 3
gate on a rebase flow this skill does not have.
Description 724 -> 214 chars, body 1102 -> 343 words, Gotchas 12 -> 3.
Create, rewrite, and cherry-pick flows move to self-contained references/
files behind a dispatch table.
The audit caught that moving the secret scan into the create flow left the
amend/squash path with no check in its loaded context; it is now a gate
common to every flow. Also re-homes the interactive-rebase reflog warning
git-history dropped, since this skill owns rebase.
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