fix(init): the skill it writes ignores itself, as a generated directory

A repository that ignores .claude wholesale, as Crafter.Build does,
never sees in git the prepush skill init writes, and the question was
whether it should: it should not. The skill is generated
from the shipped text with init's marker and refreshed by every init, a
tracked copy lags the installed binary whenever the shipped skill
changes, and every refresh would be a diff in the consumer's own ranges.
Jorijn's ruling: every consumer leaves it untracked, one init per
checkout.

When init owns the skill - wrote or refreshed it - it writes a
.gitignore of `*` beside it, as Python's venv and pytest's cache do for
theirs: the directory ignores itself, that file included, on every
checkout that runs init, whatever the repository's own rules or one
machine's say, and nothing of the repository's is edited for it. A copy
init wrote that the repository tracks gets the step that untracks it, in
the output and in the README's migration. A skill the repository wrote
itself is kept and not ignored - the ignore file an earlier init wrote
beside it goes - and an ignore file init did not write is kept unless
--force; a link there, dangling or not, is refused like the skill's
other links unless --force, which replaces it (the old setup's exemption
- a link that resolves into the review-gates submodule at the toplevel,
not one that merely names it - is the skill directory's and SKILL.md's
alone), and nothing is written through it: the links go before anything
is written, and one init cannot remove refuses. The procedure's log
records the ruling.
This commit is contained in:
Jorijn van der Graaf 2026-11-01 17:24:03 +01:00
commit ddf32a8c02
Signed by: jorijnvdgraaf
GPG key ID: 2937E59CDCC1BCFB
4 changed files with 185 additions and 20 deletions

View file

@ -45,10 +45,10 @@ crafter-review config # edit .review-gates/config.json until it prints no
`init` does four things:
- it writes `.review-gates/config.json` from the template when there is none - the three artifact kinds as modes with every lens of their kind: trim each to what this repository runs;
- it adds `.review-gates/push/` and `.review-gates/trees/` to `.gitignore`;
- it writes the `/prepush` skill to `.claude/skills/prepush/SKILL.md`, which a later `init` refreshes (the line after its frontmatter marks it as init's);
- it writes the `/prepush` skill to `.claude/skills/prepush/SKILL.md`, which a later `init` refreshes (the line after its frontmatter marks it as init's), with a `.gitignore` of `*` beside it: the skill is generated from the shipped text, so it stays out of git and every checkout runs `init` once (a tracked copy would lag the installed binary); a skill the repository wrote itself, without that line, is left alone and not ignored, unless `--force`;
- it prints the next steps.
It writes nothing in a subdirectory, in your home directory (`--force` when that is the repository) or over a `SKILL.md` it did not write.
It writes nothing in a subdirectory, in your home directory or over a `SKILL.md`, a `.gitignore` beside it or a link there that it did not make (the old link into the review-gates submodule aside, which it removes); `--force` allows all but the first.
`.review-gates/config.json` is committed. It says what the pipeline must know about the repository:
- who may author its commits, and which branch a range is measured against;
@ -66,6 +66,7 @@ It writes nothing in a subdirectory, in your home directory (`--force` when that
1. Re-freeze every review in flight with crafter-review. The Flatpak's git may be another version than the one that froze it, and a different git version gives a different hash. The old `run-line.txt` also points into the submodule.
2. `git submodule deinit -f review-gates && git rm review-gates`
3. `crafter-review init`. If `.claude/skills/prepush` is the old link into `review-gates/`, it removes the link, never writing through it, and makes a real directory with the skill.
4. If a copy of the skill that an earlier `init` wrote is tracked, `git rm --cached .claude/skills/prepush/SKILL.md` (init says so when it sees one): the skill is generated, and the `.gitignore` init writes beside it keeps it out of git from then on.
An existing `config.json` needs one change since 2026-11-01: `lenses.<name>.run` is retired, so list the lenses in `modes.commits.lenses` (`config` names what is missing, and `freeze`, `run` and `slots` refuse until it is there). The reuse keys keep working: a range reviewed before the move is reused, not bought again.