Stop the Line on Instruction Drift
Your layers start clean, with short agent profiles and complete skill procedures. Six weeks later, one profile has grown a procedure, and a generated jobs block disagrees with the manifest it came from. An agent starts to make a mistake that no one can trace to a file. Review catches none of it, because a reviewer reads a diff and does not check a budget.
Jidoka builds the checking into the process. The
jidoka command family stops the line when a layer
breaks its budget, a jobs block goes stale, or one of your own
invariants breaks. The fix then happens where the defect appeared,
and the defect never reaches the agent runs that come after it.
This guide adds the checks to a repository you own. It covers what each command catches, how to read a finding, and how to route the finding to the fix that owns it.
Prerequisites
-
Adopt Jidoka in Your Repository
is complete. Your root
CLAUDE.md,CONTRIBUTING.md, andJTBD.mdexist, and.jidoka/invariants/contains at least one rule module. - Node.js 22 or later, with
npxon your path. -
@forwardimpact/jidokainstalled as a development dependency, so thatnpx jidokaruns from the local install. - Write access to the repository's check script and its CI workflow.
One command per class of defect
Each command owns one class of defect. You can trace a finding to a fix because of that separation. A length breach is a different problem from a stale jobs block, and each one has a different fix.
| Command | What it reads | What it catches |
|---|---|---|
jidoka instructions |
every instruction layer in the tree | a layer over its line cap or its word cap, a checklist block with too many items, a checklist item that explains |
jidoka jtbd |
every package.json that declares
jobs, and the generated blocks those jobs feed
|
a job entry that breaks the schema, and a generated block that no longer matches its source |
jidoka invariants |
every *.rules.mjs module under
.jidoka/invariants/
|
the rules your repository declared for itself |
Every command accepts --json for machine-readable
findings. Run npx jidoka <command> --help before
you script against it.
What jidoka instructions enforces
Every layer has a line cap and a word cap, and the check fails on either breach. Put Your Instructions on One Layered Architecture has the layer table. The word cap catches padded prose that still fits inside the line cap, so it can fail a file that the line cap passes.
These rules decide which files the check applies a budget to.
- Front matter is exempt. The check strips a leading YAML block before it counts. A published copy of a skill therefore counts the same as its source in your repository.
-
Location and front matter set the layer. A file
in
.claude/agents/counts as an agent profile when it has bothnameanddescriptionfront matter. Without them it counts as an agent reference, which has a much larger budget. The agent loader applies the same test. A long reference that gainsnameanddescriptiontherefore moves to the small profile budget and fails. -
The check skips directories that hold no instructions.
It ignores version-control, dependency, build, cache, temporary,
and worktree directories, and a
wiki/checkout, so agent memory never counts against an instruction budget. -
Checklist blocks come from
CONTRIBUTING.mdand from eachSKILL.md. The check never measures a checklist that you paste into an agent profile. Put universal gates inCONTRIBUTING.md, and put domain gates in the procedure that owns the pause point.
What jidoka jtbd enforces
This command reports two unrelated kinds of problem. The first is a
schema problem. Each jobs entry must use a persona from
the accepted set, and the finding prints that set for you. An entry
also needs a goal, a trigger, a competitor list, a Big Hire, and a
Little Hire. Every hire sentence ends with a period, and two entries
with different goals must not use the same hire sentence.
The second is a stale block. Your job entries generate marker-delimited blocks in the prose files that publish them. The check compares the generated text with the manifest and reports a mismatch as stale.
npx jidoka jtbd # report schema and stale blocks
npx jidoka jtbd --fix # regenerate the stale blocks in place
The order matters. A schema finding stops regeneration for the
catalog that contains it. Fix every schema finding first, then run
--fix, then commit the regenerated files. Never
hand-edit text between the generated markers. The next
--fix overwrites your edit, and the check reports the
same file as stale every time.
Be aware of one case where the check passes without checking
anything. The command reads job declarations from the package
directories that the
Monorepo structure standard
defines. A repository that keeps one hand-written
JTBD.md and declares no package manifests gets a
passing jtbd run that validated nothing. Do not treat a
green jtbd run as proof that your entries are good.
That proof comes from
Write Jobs To Be Done Entries.
What jidoka invariants enforces
It enforces nothing until you write a rule. The command ships the
engine, and your repository owns the policies. The loader finds
every *.rules.mjs module under
.jidoka/invariants/. It searches upward from the
working directory, so the command works the same from any
subdirectory.
A missing rules directory is an error:
jidoka: error: rules directory not found: /srv/my-repo/.jidoka/invariants
The error is intended. A half-copied repository fails with a clear message instead of reporting success over an empty policy set. To write a module, see Enforce Your Repository's Own Invariants.
Read a finding
Every check uses the same finding format. Here is a run against a repository where the identity file and one agent profile both grew past their caps.
CLAUDE.md
error 201 lines (max 192, root CLAUDE.md) instructions.line-budget
→ trim prose to fit the layer cap, and see JIDOKA.md for the layered-instruction model
error 1202 words (max 896, root CLAUDE.md) instructions.word-budget
→ trim prose to fit the layer cap, and see JIDOKA.md for the layered-instruction model
.claude/agents/demo.md
error 92 lines (max 72, agent profile) instructions.line-budget
→ trim prose to fit the layer cap, and see JIDOKA.md for the layered-instruction model
✖ 3 problems (3 errors, 0 warnings)
Findings are grouped under the file that owns them. Each finding shows the measured value, the cap it broke, the layer the check assigned, and the rule the file broke. The arrow line is the hint. It gives the direction of the fix and not the exact edit.
Note two points when you script against the gate.
-
Any finding fails the run. A rule can declare
warnseverity, and the output then labels the finding a warning, but the exit code stays non-zero. Severity records the intent of the rule and does not change the gate. -
Exit codes are stable. A clean run exits
0. A run with findings or stale blocks exits1. An unknown command exits2. Gate on the exit code, and read--jsonwhen a bot needs the structured fields.
Run every check in one step
The bare command is the shortest command to type, and it has one trap. It runs the instruction check and the jobs check, but it does not run your invariant modules.
jidoka # instruction caps and jobs, together
jidoka instructions # layer length and checklist caps only
jidoka jtbd --fix # regenerate the stale generated blocks
jidoka invariants # your repository's own rule modules
A single bare call therefore leaves the rules you wrote yourself
unenforced, and .jidoka/invariants/ looks green because
nothing ran it. Add two calls everywhere you add one:
npx jidoka
npx jidoka invariants
Keep them as separate calls instead of one combined script line. The log then shows which class of defect stopped the line, and a contributor can find the right fix without reading the whole output.
Wire it into your check script
Add the CLI as a development dependency of the repository. An
npm script then finds the bare jidoka name
in the local install, with no global state.
npm install --save-dev @forwardimpact/jidoka
The manifest then contains the dependency and the scripts that call it:
{
"devDependencies": {
"@forwardimpact/jidoka": "^0.2.0"
},
"scripts": {
"check:instructions": "jidoka",
"check:invariants": "jidoka invariants",
"check": "npm run check:instructions && npm run check:invariants"
}
}
Record the exact command in CONTRIBUTING.md, next to
the repository's other quality commands. Contributors and agents
both read that file to learn how to verify their work.
Never use a form of the command that only works on a machine that
someone already set up. A jidoka binary on your own
PATH hides a command that a clean runner cannot find.
The check then passes for you and fails for everyone else. Test the
wiring the way CI runs it, from a fresh checkout.
Wire it into CI
The same two calls belong in the pull request checks. Use the same commands in both places, so that a contributor can reproduce a CI failure with one local run.
name: jidoka
on: [pull_request]
jobs:
instructions:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm run check:instructions
- run: npm run check:invariants
graph LR
A["contributor edits a layer"] --> B["npm run check
local gate"]
B --> C["pull request"] --> D["jidoka job
CI gate"] --> E["merge"]
B & D -.->|finding| F["fix the owning layer"]
F --> B
Teams face these decisions the first time they set this up.
- Use one job with separate steps. A single job keeps the setup cost down. Separate steps show which check failed in the run summary.
-
Never run
--fixin CI on a protected branch. The flag writes files. Regeneration belongs in a contributor's commit, where a human reviews the generated diff. - Turn the gate on after the repository is clean. A first run usually reports a backlog of findings. Fix them on their own branch, then make the job required. If a required check fails from the first day, the team learns to ignore it.
A published composite action also exists. It takes an optional
command input, and it assumes that a pinned
jidoka binary is already on PATH. The
action has no npx fallback, so use it only when
the platform bootstrap
runs before it in the same job.
- uses: forwardimpact/jidoka@v1
with:
command: invariants
Triage each finding to the fix that owns it
Group the findings by command before you change anything. Then route each group.
| Finding from | What it means | Route to |
|---|---|---|
instructions (budget) |
a layer exceeds its line cap or word cap | Author or Repair One Instruction Layer |
instructions (checklist) |
a block holds too many items, or an item explains | Write a Checklist That Verifies Instead of Teaches |
jtbd (schema) |
an entry breaks the jobs structure | Write Jobs To Be Done Entries |
jtbd (stale block) |
a generated block is out of date | jidoka jtbd --fix, then commit the result |
invariants |
one of your rule modules flagged code | the hint that rule prints, then Enforce Your Repository's Own Invariants |
Each finding shows a symptom. Fix the cause behind it:
- A budget breach is a placement problem. Do not cut words until the layer fits. Move the content to the layer that owns it. A template or a lookup table belongs in a skill reference. A procedure belongs in a skill procedure and never in an agent profile. The budget shows that content is one layer too high.
- A stale block is a source problem. Edit the manifest, then regenerate.
- An invariant violation is a code problem. Fix the code that the rule rejects. Do not widen an allow-list to silence a finding, and do not delete the rule because it is inconvenient this week.
Run the suite again after each fix, because one fix can expose the next. When you trim a profile, a checklist can move into a file that the check measures, and the check then measures that block for the first time. Stop when the run is clean.
Grandfather only during a real migration
Sometimes a new invariant arrives in a codebase that already violates it. For that case, the rule module can have an optional seed path. The seed prints a deny-list of the known violations, and the module reads that list back, so the existing cases pass and new ones fail.
npx jidoka invariants --seed <module-name>
The list must only shrink. Each migration commit removes entries, and no commit adds one. A list that grows works as an allow-list, and it retires the invariant without a decision from anyone.
Record what recurs
The check shows which layer broke. It does not show why the same layer keeps breaking. Keep a short note of the finding classes that come back.
When one class comes back again and again, the layer that should prevent it is incomplete. Do not blame the contributor who tripped the gate. Improve the procedure, the reference, or the invariant that should have made the mistake impossible. If a check fails every week, people learn to ignore every check.
Migrate from the Co-Aligned era
This standard was previously published under the name Co-Aligned. A repository that still uses the old tools moves across in three steps.
-
Rename the rules directory with
git mv .coaligned .jidoka. -
Reinstall the skill pack with
apm install forwardimpact/jidoka-skills. -
Replace the CLI. The old
coalignedcommand becomesjidoka. Update the check script, the CI workflow, and the command recorded inCONTRIBUTING.md.
A repository that has not migrated fails with a clear message. The
loader stops with a rules directory not found error
that shows the location it expected.
Verify
-
npx jidokaandnpx jidoka invariantsboth report a clean pass from a fresh clone and a fresh install. -
npm run checkruns both commands, andCONTRIBUTING.mdrecords that command. - The budget check works. Paste a paragraph into an agent profile until it goes over its cap. Run the check, and confirm that the finding shows that file. Then revert the paste.
-
The invariant check works. Confirm that
jidoka invariantsreports an error when.jidoka/invariants/is absent, and a pass when your module is in place. - A pull request with a planted defect fails the CI job, and the run summary shows the step that stopped.
What's next
Enforce Your Repository's Own Invariants
Write a declarative rule module so that the check fails on a forbidden import, a value that disagrees across two files, or a broken directory shape. The engine ships with the CLI, and the policy stays in your repository.
Put Your Instructions on One Layered Architecture
Give every instruction file one owning question, one load moment, and one budget. A bad agent run then points at exactly one file.
Author or Repair One Instruction Layer
Write or fix one layer at a time. Find the layer that owns a piece of text, move misplaced text, and bring an over-budget layer back under its cap without a loss of meaning.
Write a Checklist That Verifies Instead of Teaches
Place a READ-DO entry gate and a DO-CONFIRM exit gate at real pause points. Keep every item to one yes-or-no check. Tag both gates so that one search finds every gate in your repository.
Write Jobs To Be Done Entries
Write a job entry that links an instruction layer to the progress a persona seeks in a real moment. The page covers the entry structure, the Big Hire and Little Hire split, the four forces, the Fired When clause, and the tag that makes every job searchable.
Adopt Jidoka in Your Repository
Install the Jidoka skill pack, create the root instruction layers, add the checks to your check command and CI, then watch the line stop on a planted defect.