refactor(skills): retrofit the corpus to the ADR-0020 context contract (#129)
Retrofits all 39 skills to ADR-0020's description/body context contract, then fixes what six rounds of independent review found in that retrofit — including four ways the hot gate itself failed open. Closes #99, #107, #108, #110, #111, #114, #115, #120. ## The retrofit (waves 1-5) | | Start | Now | |---|---|---| | Description FAILs (>400 chars) | 26 | **0** | | Body FAILs (>900 words, body-only) | 9 | **0** | | Dangling routing targets | 2 | **0** | | `Kyberforge.CompositionNote` | 10 | **0** | | Preload tax | 21,005 chars | **~10,500** | Under the 12,000-char success criterion. Per-wave detail is on #99. ## The review fixes **The gate failed open four ways, three of them found after the retrofit shipped.** An unrecognised follower token made a dangling target vanish. A skill directory with no `SKILL.md` resolved as a valid target, so a commit could be green locally and red in a fresh clone — three existing fixtures were relying on that, one of which made the install-leak A/B pass vacuously. Then the free-standing `/name` sweep turned out to be gated on the sentence carrying a boundary marker, so route notation in any other sentence was invisible — not an ERROR, not a SUGGESTION, not an INFO — which left the documented "`/name` always blocks" promise false from a second direction. All four fixed and pinned. **Two checks were silently not running.** `validate-provenance.sh` checks 7-8 were dead across nine skills. Waking them exposed a deeper problem: they assume `Research doc:` names a source index, but 30 of 121 entries point at topic content documents, so every new check-7 INFO was a false positive and check 8 was saved from a false-FAIL flood only by an *unannounced* skip. Checks 7/8 are now scoped to source indexes and every skip announces itself (#121). **The retrofit's own anti-goal, four times.** ADR-0020 warns that a blunt gate gets satisfied by deleting content rather than relocating it. `diagnose` and `skill-audit` relocated prose and then read it unconditionally; `prototype` and `vale-config` deleted rules outright that survived nowhere. All four addressed. ## Verification - `bash tests/run-tests.sh --strict` — 24 suites, 0 skipped, 0 failed - `bash tests/run-bats.sh` — 325 tests, 0 failures - `pre-commit run --all-files` — 17/17 - `pre-commit run --hook-stage pre-push --all-files` — 16/16, with `apm marketplace check` and `apm pack --check-clean` run against the remote, not skipped - `scripts/skill-size-check.sh` over all 39 skills — rc 0, 0 ERROR/FAIL, SUGGESTION-only - Preload tax measured at **10,498 chars**, max description 390 — both inside budget - Every new test proven non-vacuous by a deliberate mutation of the behaviour it covers **Per-commit sync, stated accurately:** the ten commits from the latest review round each pass `check-plugin-content-sync` in isolation, verified by checking each out in a detached worktree with a clean between. The earlier gitea window (`dfacf05..bedbd1d`, nine commits) does **not** — its mirror was regenerated in one batch at `bbc7300`. An earlier revision of this description claimed the property held for every commit; it does not, and a bisect through that window lands on a red commit. **Squash-merge** to collapse it, or accept that this range is not bisectable. ## Version bump Six plugins and the catalog take a **patch**, not a minor. The branch is **89 commits — 40 `fix` / 30 `refactor` / 12 `docs` / 5 `chore` / 2 `test` — zero `feat`, zero `!`, zero `BREAKING CHANGE`** — and adds no skill, agent, command or hook. (Two earlier revisions of this section cited a stale histogram, most recently 78 commits; the figures above are measured at HEAD.) Both rules this repo ships (`forge/references/version-bump.md`, landing in this PR, and `git-commits/references/conventional-commits-spec.md`) make that a patch, and the catalog set is unchanged at 7 entries. Not settled by that: four published files were removed from the installed tree, three moved, and `caveman` gained `disable-model-invocation`, retiring its old triggers. Under a strict reading those are major-class and currently ship under `refactor:` with no marker. Whether the deployed skill surface is a public contract is written down nowhere — worth deciding, but it outlives this PR. ## Deliberately not in scope #112 (cherry-pick ownership, now resolved in favour of `git-commits`), #113 (`rtk git` normalisation), #116 (research fan-out), #101 (audit-skill merge), #122 (non-spec skill-root files), #123 (no PRD producer) stay open. #117 is the one worth reading: the contract's remedy is to move prose into `references/`, which is exactly where neither the size gate nor Vale looks — and the blind spot is wider than #117 currently records, since there is no root `.vale.ini` at all, so every ADR, `CONTEXT.md` and `README.md` is unlinted too. That blind spot let this branch carry two `level: error` `Kyberforge.SentenceOpenerThereIs` violations into `references/` files it created — `provider-adapter-author/references/provider-matrix.md:31` and `agent-audit/references/finding-criteria.md:95`. Both are reworded in `afadaae`, confirmed by routing each file through the audit's own `vale-wrap.sh` (1 error each before, 0 after). Five further occurrences sit in `references/` files already on `main`; those are the pre-existing corpus and stay with #117, which is the real fix. Also unfixed and not this PR's: `apm install` appends a duplicate `SessionStart` entry to `.claude/settings.json`, so a fresh clone cannot get pre-push green without an edit AGENTS.md warns against. Reproduces identically on `main`. Co-authored-by: Defame1297 <gitea@rkdr.net> Reviewed-on: https://git.dev.rkdr.net/Defame1297/holocron/pulls/129 Co-authored-by: Claude Code AI - Gitea MCP <claude@noreply.git.dev.rkdr.net> Co-committed-by: Claude Code AI - Gitea MCP <claude@noreply.git.dev.rkdr.net>
This commit was merged in pull request #129.
This commit is contained in:
@@ -2,11 +2,10 @@
|
||||
name: git-worktrees
|
||||
|
||||
description: >
|
||||
Manage Git worktrees to enable multi-branch parallel development across isolated directories.
|
||||
Use when the user needs to work on multiple branches simultaneously without stashing, switch between feature/hotfix/experimental work, or coordinate code reviews alongside ongoing development.
|
||||
Handles creation, listing, locking, moving, removal, pruning, and repair of worktrees.
|
||||
Provides structured results (paths, branches, lock status) for agent composition in git orchestration workflows.
|
||||
Do not use when only inspecting a single branch or when the user needs standard checkout/stash workflows.
|
||||
Use when working on several branches at once without stashing —
|
||||
manages the full lifecycle of a git worktree.
|
||||
Not ordinary branch switching or checkout -> `git-branches`.
|
||||
Not interactive multi-step git guidance -> `git-workflow`.
|
||||
|
||||
metadata:
|
||||
category: git
|
||||
@@ -14,101 +13,45 @@ metadata:
|
||||
- git-scm-worktree-docs
|
||||
---
|
||||
|
||||
## Concept
|
||||
|
||||
A worktree lets you check out multiple branches simultaneously from one repository, each in its own directory. All worktrees share the same objects, config, and most refs (`refs/`). Each worktree has its own `HEAD`, index, and per-worktree metadata (`ORIG_HEAD`, `MERGE_HEAD`, `refs/bisect/`, `refs/worktree/`, `refs/rewritten/`) stored at `$GIT_DIR/worktrees/<name>/`. The **main worktree** (from `git init`/`git clone`) is exactly one per repo and cannot be removed; **linked worktrees** are the additional ones created via `git worktree add`.
|
||||
|
||||
## Gotchas
|
||||
|
||||
- **A branch can only be checked out in one worktree at a time.** Attempting `git worktree add` for an already-checked-out branch fails unless you pass `--force`. Use `--force` only when intentional.
|
||||
- **Submodules are unsupported and block operations.** Repos with submodules have incomplete worktree support. Worktrees containing submodules cannot be moved and require `--force` to remove.
|
||||
- **Never manually `rm -rf` a worktree directory.** This leaves stale metadata in `$GIT_DIR/worktrees/`. Always use `git worktree remove`. If already deleted, run `git worktree prune` to clean up.
|
||||
- **Manual moves break bidirectional pointers.** If a worktree directory is moved outside of `git worktree move`, run `git worktree repair` to fix connections.
|
||||
- **Force-flag escalation with locks.** Removing or moving a locked worktree requires `-ff` (two flags), not just `-f`.
|
||||
- **Worktree identification is by full path, unique basename, or unique partial path.** Ambiguous names error. Use `git worktree list` to see available identifiers.
|
||||
- **`--lock` on `add` is atomic; create-then-lock has a race window.** Use `--lock` directly on `git worktree add` when consistency matters.
|
||||
- **`extensions.worktreeConfig = true` is a one-way door.** It enables per-worktree config (`git config --worktree ...`) but makes the repo refuse to open in older Git versions. Once set, `core.bare`/`core.worktree` must live in `config.worktree`, not `config`. Don't enable it unless per-worktree config is actually needed.
|
||||
- **A branch can be checked out in only one worktree at a time.** `git worktree add` on an already-checked-out branch fails; `--force` is the only override, so use it only deliberately.
|
||||
- **Never `rm -rf` a worktree directory.** That strands metadata in `$GIT_DIR/worktrees/`. Use `git worktree remove`, or `git worktree prune` afterwards.
|
||||
- **Submodules break worktree support.** A worktree containing submodules cannot be moved at all, and needs `--force` to remove.
|
||||
- **`extensions.worktreeConfig = true` is a one-way door.** Without it, `git config --worktree` errors; with it, that flag writes to the worktree's own `config.worktree` file, and `core.bare`/`core.worktree` are forced there too. It also breaks older Git. Leave it off unless per-worktree config is needed.
|
||||
|
||||
## Common Operations
|
||||
## Step 1 — Dispatch
|
||||
|
||||
**Create and switch to a new worktree** — default approach:
|
||||
```bash
|
||||
git worktree add -b <new-branch> <path>
|
||||
cd <path>
|
||||
```
|
||||
This creates a new branch and checks it out in a new directory. Other branches cannot be checked out elsewhere simultaneously.
|
||||
| Operation | Run |
|
||||
|---|---|
|
||||
| Create on a branch that already exists locally | `git worktree add <path> <branch>` |
|
||||
| Create on a new branch | `git worktree add -b <branch> <path>` |
|
||||
| Create on the branch named after the path basename | `git worktree add <path>` — checks that branch out if it exists, else creates it from HEAD |
|
||||
| Create and reset an existing branch to HEAD — discards its commits | `git worktree add -B <branch> <path>` |
|
||||
| Create a local branch tracking a remote one | `git worktree add --track -b <branch> <path> <remote>/<branch>` — always correct. `git worktree add <path> <branch>` expands to exactly this, but **only** under the conditions in `references/worktrees.md` |
|
||||
| Throwaway experiment, no branch | `git worktree add -d <path>` — detached HEAD |
|
||||
| **Never** `git worktree add <path> <remote>/<branch>` | That ref resolves, so the shortcut never fires and you get **a detached HEAD, no branch, no upstream**. Commits there go unreachable once HEAD moves, and `git push` needs an explicit refspec. Use the tracking row above |
|
||||
| List | `git worktree list -v`, or `--porcelain -z` to parse |
|
||||
| Lock or unlock | `git worktree lock [--reason <str>] <path>` / `git worktree unlock <path>` |
|
||||
| Move | `git worktree move <from> <to>` |
|
||||
| Remove | `git worktree remove <path>` |
|
||||
| Prune stale metadata | `git worktree prune --dry-run`, then without the flag |
|
||||
| Repair after a manual move | `git worktree repair` — in the main worktree if *it* moved, or inside a linked worktree that moved. `git worktree repair <path>...` — from any worktree, naming each moved linked worktree's new path |
|
||||
|
||||
**Create-or-reset a branch**: `git worktree add -B <branch> <path>` — like `-b` but resets the branch to HEAD if it already exists.
|
||||
If the operation needs anything the table does not carry — the full `add` flag
|
||||
table, orphan branches, sparse-checkout, locking for removable media, remote
|
||||
disambiguation across several remotes, how to name a worktree unambiguously,
|
||||
worktree config keys, or the worked emergency-fix and PR-review patterns — read
|
||||
`references/worktrees.md`.
|
||||
|
||||
**Create a worktree for an existing remote branch**:
|
||||
```bash
|
||||
git worktree add <path> <remote>/<branch>
|
||||
```
|
||||
For ambiguous names across remotes, disambiguate via `checkout.defaultRemote` config or `--guess-remote`. Full flag table and detail: `references/worktrees.md`.
|
||||
Gates:
|
||||
|
||||
**Throwaway experiment in detached HEAD**:
|
||||
```bash
|
||||
git worktree add -d ../experiment # or --detach
|
||||
# experiment freely, no branch created
|
||||
git worktree remove ../experiment
|
||||
```
|
||||
- **`move`, `remove` — the main worktree cannot be moved or removed.** Only linked worktrees, the ones `git worktree add` created, are candidates.
|
||||
- **`add`, `move`, `remove` — escalate force flags one step at a time.** `-f` overrides a safeguard such as an unclean tree; `move` and `remove` need `-ff` on top of that when the worktree is locked. Confirm with the user before either — both discard state.
|
||||
- **`add` — lock at creation, not after.** `git worktree add --lock` is atomic, where add-then-`lock` leaves a window in which the worktree is unprotected.
|
||||
|
||||
**List all worktrees with state**:
|
||||
```bash
|
||||
git worktree list -v # human-readable with lock/prune reasons
|
||||
git worktree list --porcelain -z # machine-readable, NUL-terminated
|
||||
```
|
||||
## Step 2 — Report
|
||||
|
||||
**Move a worktree to a new path**:
|
||||
```bash
|
||||
git worktree move <current-path> <new-path>
|
||||
# Cannot move: main worktree, worktrees with submodules
|
||||
# To override safeguards: -f; to override locked state too: -ff
|
||||
```
|
||||
|
||||
**Remove a worktree**:
|
||||
```bash
|
||||
git worktree remove <path> # only if clean
|
||||
git worktree remove -f <path> # force-remove unclean
|
||||
git worktree remove -ff <path> # force-remove even if locked
|
||||
```
|
||||
|
||||
**Prune stale metadata**:
|
||||
```bash
|
||||
git worktree prune --dry-run # preview what would be removed
|
||||
git worktree prune # clean up orphaned metadata
|
||||
```
|
||||
Also triggered by `git gc`, controlled by `gc.worktreePruneExpire` config.
|
||||
|
||||
**Repair broken connections** (after a manual move):
|
||||
```bash
|
||||
git worktree repair # from main worktree or after it was moved
|
||||
git worktree repair <path> # reconnect a specific linked worktree
|
||||
```
|
||||
|
||||
Sparse-checkout worktrees, locking for removable media, the full `add` flag table, and the config key reference: `references/worktrees.md`.
|
||||
|
||||
## Worked Examples
|
||||
|
||||
**Emergency fix without disrupting current work** — no stashing needed, ongoing work in the main worktree is untouched:
|
||||
```bash
|
||||
git worktree add -b emergency-fix ../temp main
|
||||
cd ../temp
|
||||
# fix, commit
|
||||
git commit -a -m "fix: critical production bug"
|
||||
cd -
|
||||
git worktree remove ../temp
|
||||
```
|
||||
|
||||
**Review a PR branch alongside your current work** — no context switch, both branches stay checked out:
|
||||
```bash
|
||||
git worktree add ../review-pr-123 origin/feature-xyz
|
||||
# open ../review-pr-123 in a second editor window or terminal
|
||||
```
|
||||
|
||||
## Return Format for Agents
|
||||
|
||||
When invoking worktree operations, return structured results:
|
||||
```yaml
|
||||
worktrees:
|
||||
- path: <directory-path>
|
||||
@@ -116,10 +59,8 @@ worktrees:
|
||||
commit: <short-hash>
|
||||
locked: <true/false>
|
||||
lock_reason: <reason or empty>
|
||||
- ...
|
||||
```
|
||||
Derive these fields from `git worktree list --porcelain -z` — its `worktree`/`branch`/`HEAD`/`locked` lines map directly to `path`/`branch`/`commit`/`locked`+`lock_reason`.
|
||||
|
||||
For single operations, include the operation result (e.g., `created: true`, `removed: true`, `moved: true`).
|
||||
|
||||
For multi-step flows spanning branch strategy plus worktree setup, compose with the `git-workflow` skill — it handles the broader orchestration, this skill handles the worktree mechanics.
|
||||
Derive those fields from `git worktree list --porcelain -z`. For a single
|
||||
operation, report its outcome instead — `created: true`, `moved: true`,
|
||||
`removed: true`.
|
||||
|
||||
Reference in New Issue
Block a user