Lint the tree on every Ren turn — the named Hatsu process for the declared `lint` verb. Breath proves it on the fresh tip, rasengan may run it as authoring feedback, kokusen must run it over the finished tree before it commits, and aka runs it before squash and again after catch-up if the tree moved. It never measures coverage and never runs tests.
Install
npx skillscat add zheref/hatsu/gyo Install via the SkillsCat registry.
Shared policy location: docs/DISCOVERY.md, docs/WORKFLOW.md,docs/LAUNCH-MIGRATION.md, docs/STANDALONE-ENTRY.md, docs/PROCESS.md and docs/SURFACES.md belong to the resolved Hatsu plugin
root, not the consuming repository. On an installed surface, use the absolute root printed byten to read those files (re-resolve through that skill if unavailable). Relative links
below identify source locations; a missing consumer docs/ copy is not a missing policy and must not
trigger a duplicate filing. Never copy or invent a second policy in the target repository.
Gyo — the lint, every turn
Nature: Transmuter. Gyo runs the declared lint machinery and reports what it said. Fixing what
lint named is the surrounding phase's work in that phase's own nature.
Lint this tree. Do not let a red lint commit, and do not skip the check because the last run
was green.
Gyo is the linting process. The Nen verb is still lint — there is no nen shu gyo. What
changed on 2026-09-14 is the name: the check breath, rasengan, kokusen and aka already
ran as iteration.checks → lint is this skill. Coverage measurement and capture belong to
`hatsu:byakugan`, at mukai. Tests belong to
`hatsu:tsukuyomi` (focused) and
`hatsu:kotoamatsukami` (impacted project-wide unit, UI and
integration).
It runs on every Ren turn. `hatsu:rasengan` may run it as inner-loop
feedback while the work is in front of the author. `hatsu:kokusen` must
run it over the finished tree and refuses to commit on red. That is the same cadence the lint
iteration check already had; this file is the name of that cadence.
It is also invocable alone as a diagnostic.
0. Standalone entry — already total
Gyo needs nothing from a caller. The lane comes from its own on <lane> clause or fromnen/workflow.json → iteration.lane, and linting reads the tree in front of it rather than a delta,
so there is no turn boundary to inherit. `docs/STANDALONE-ENTRY.md` § 4 lists it as already total, and the whole of that
contract that applies here is P1: run `hatsu:ten gyo` (ten § 6 catches up the prerequisites) first when
no composite did, because nen shu lint is a nen call.
Being typed by hand changes nothing else. Gyo still never measures coverage and never runs tests —
`hatsu:byakugan` and `hatsu:kotoamatsukami` own
those — and a green lint is never reported as anything more than a green lint.
Hand-back. Next in the wired run: whatever asked for the lint — hatsu:kokusen's commit gate,hatsu:aka's pre-squash gate, or the author's own loop. A green lint is not a test result and not a
coverage number.
1. Invocation
hatsu:gyo [on <lane>]nen parse gyo --grammar "on [<lane>]" --line "<the invocation, minus the hatsu:gyo prefix>"The clause is anchored behind a literal for the reason `hatsu:spiritual-message` § 1
records. With no clause the lane is nen/workflow.json → iteration.lane, defaulting toproject.defaultLane. A bare invocation is not parsed — there is nothing in it to parse — and
the resolved lane is named out loud either way.
The grammar used to be
against [<base>]. That clause belonged to gyo-as-coverage and is
retired. Historical transcripts indocs/ab/gyo.mdstill record it. Coverage's base now lives
on `hatsu:byakugan`.
2. The parameters, and where they come from
| Value | File → key | Default when absent |
|---|---|---|
| Which lane the lint row runs in | nen/workflow.json → iteration.lane |
project.defaultLane |
| Whether this run is due as an iteration check | nen/workflow.json → iteration.checks contains lint |
Hatsu's own list is ["lint"]; a repository that omits lint still gets a named gyo run when a caller invokes this skill, and a seat is quoted |
| What lint actually runs | nen/contract.json → project.verbs.<lane>.lint |
none — an absent row is exit 2, the trigger to ask and set it up; a seat is exit 4 |
A missing argument or configuration item is asked for and set up inline (missing-argument,missing-configuration; `WORKFLOW.md` § 4 Ask, set up, continue); a
missing lint row or lane is set up through nen scaffold init.
When nen/workflow.json is absent, say so in the turn's report, in these words — "no
workflow.json: using the built-in defaults from docs/WORKFLOW.md" — and use iteration.lane =project.defaultLane.
The verb stays lint. Callers that loop iteration.checks still spawn nen shu lint when
that entry is in the list. This skill is the name of that entry, not a second command.
3. When this run is due
| Caller | When | What red does |
|---|---|---|
| `hatsu:breath` | the fresh tip, first turn of an effort, when lint is in iteration.checks |
G5 — a base that does not lint is not this effort's to repair |
| `hatsu:rasengan` | inner-loop feedback, as often as the work wants it | the loop working — fix, run again, never hand a red tree to kokusen |
| `hatsu:kokusen` | the finished tree, every Ren turn, before staging | the commit ends and the tree returns to rasengan (nen/decisions.json row red-lint); never a G5 |
| `hatsu:aka` | before squash, and again after catch-up unless catch-up was a complete no-op | the push ends |
Mukai does not call this skill for coverage. Catch-up inside mukai still hits lint through
murasaki's iteration checks, which is this same process.
4. The dry run, once
On a repository whose lint row you have not yet seen this session:
nen shu lint --repo <path> --lane <lane> --dry-runIt prints the exact argv, the cwd, the env names and the declared artifacts, and spawns
nothing. After that, run it bare.
5. The run
nen shu lint --repo <path> --lane <lane>Never the linter's own command line typed from memory. The exit table is
`hatsu:rasengan` § 6's — the same seven rows, read the same way — and it
differs in exactly one place, which is whose the 1 is:
| Caller | Exit 1 |
|---|---|
| rasengan | fix and re-run; do not hand over |
| kokusen, aka, breath | the surrounding phase ends the commit / push / effort; quote the failing check |
A seat (exit 4) is not red. Quote the declaration's own reason and move on. Hatsu's plugin
lane has a real lint row (claude plugin validate . --strict) and seats build; gyo is that
lint row, not a substitute build.
Exit 0 is the green lint. It writes no .nen/proof/<lane>.json — that file is nen shu build's. A commit that rests on lint rests on this run's own exit 0, named in the report.
6. Report
One line: the lane, the argv the dry-run printed (or that it was already known), the exit code,
and which caller asked. A seat is quoted. A red run quotes the tool's own output and the step.
Residue
- The grammar change —
against [<base>]was gyo-as-coverage's parse. Lint has no base.docs/ab/gyo.mdkeeps the old transcripts. - Shared shu machinery — containment, preconditions, hosts, stall guards, and the no-declaration
case are `hatsu:rasengan` §§ 5a–9. This skill does not restate them.
Authority
- Permitted: run the declared
lintrow; probe the host throughnen shu tools; read the
working copy. Callers decide whether a1is a loop or a stop. - Not permitted: push, commit, PR, label, merge, deploy; editing a declaration on the fly; running
tests or coverage; inventing a linter command the row did not declare. - Carries no delegation. Being invoked inside rasengan, kokusen, aka or breath does not lend it
one.
Hard limits
- Never skips a due lint because an earlier run in the session was green. The tree moves.
- Never treats a seat as red, or a red as a seat.
- Never runs coverage or tests. Coverage is byakugan's; tests are kotoamatsukami's and tsukuyomi's.
- Never types a linter command from memory in a repository that declares
lint. - Never lowers a lint bar — not by narrowing the check, not by deleting a rule, not by declaring
a seat where a real row failed. - Never presents by-hand lint as a verb's output — the argv is
nen shu lint's.