Stop the Line on Instruction Drift
Your layers start clean. The agent profiles are short. The skill procedures are complete. Six weeks later one profile has grown a procedure, and a generated jobs block disagrees with the manifest it came from. An agent begins to make a mistake nobody can attribute. Review caught none of it, because a reviewer reads a diff and does not read a budget.
Jidoka builds the checking into the process. The
jidoka command family is the andon cord. It halts the
moment a layer breaches its budget, a jobs block goes stale, or one
of your own invariants breaks. The fix then happens where the defect
appeared. The defect never reaches every downstream agent run.
This guide wires the checks into a repository you own. It covers what each command catches, how to read a finding, and how to route it to the owning fix.
Prerequisites
-
Adopt Jidoka in Your Repository
is complete. Your root
CLAUDE.md,CONTRIBUTING.md, andJTBD.mdexist, and.jidoka/invariants/holds at least one rule module. - Node.js 22 or later, with
npxon your path. - 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. Attribution depends on that separation. A length breach is a different problem from a stale jobs block, and each one routes to 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/
|
whatever rule your repository declared for itself |
Every command accepts --json for machine-readable
findings. Run
npx @forwardimpact/jidoka <command> --help before
you script against it.
What jidoka instructions enforces
A line cap and a word cap gate every layer. Either breach fails. Put Your Instructions on One Layered Architecture carries the layer table. The word cap is the one that surprises people, because it catches padded prose that still fits inside a passing line count.
These behaviours decide which files the check budgets.
- 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 carries bothnameanddescriptionfront matter. Without them it counts as an agent reference, which has a far larger budget. The agent loader applies the same test. So a long reference that gainsnameanddescriptionflips to the tight profile budget and fails. -
The walk skips non-instruction trees. It ignores
version-control, dependency, build, cache, temporary, and worktree
directories, and a
wiki/checkout, so agent memory never competes with instruction budgets. -
Checklist blocks come from
CONTRIBUTING.mdand from eachSKILL.md. The check never gates a checklist you paste into an agent profile. Put universal gates inCONTRIBUTING.md. Put domain gates in the procedure that owns the pause point.
What jidoka jtbd enforces
This command reports two unrelated kinds of trouble. The first is
schema. Each jobs entry must name a persona from the
accepted set, and the finding prints that set for you. Each entry
needs a goal, a trigger, a competitor list, a Big Hire, and a Little
Hire. Each hire sentence ends with a period. No two entries with
different goals may claim the same hire sentence.
The second is freshness. Your job entries generate marker-delimited blocks in the prose files that publish them. The check compares the generated text against the manifest. It reports a mismatch as stale.
npx @forwardimpact/jidoka jtbd # report schema and stale blocks
npx @forwardimpact/jidoka jtbd --fix # regenerate the stale blocks in place
Order matters. A schema finding stops regeneration for the catalog
that holds it. So 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 forever.
One silent pass is worth planning for. 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. So never read
a green jtbd as proof that your entries are good. That
proof comes from
Write Jobs To Be Done Entries.
What jidoka invariants enforces
Nothing, until you write a rule. The command ships the engine. Your
repository owns the policies. The loader discovers every
*.rules.mjs module under
.jidoka/invariants/. It searches upward from the
working directory, so the command behaves the same from any
subdirectory.
A missing rules directory is an error:
jidoka: error: rules directory not found: /srv/my-repo/.jidoka/invariants
That error is deliberate. A half-copied repository fails loudly instead of reporting success over an empty policy set. To author a module, see Enforce Your Repository's Own Invariants.
Read a finding
Every check emits one finding format. Here is a run against a repository whose 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 group under the file that owns them. Each finding names the measured value, the cap it broke, the layer the check assigned, and the rule that fired. The arrow line is the hint. It names the direction of the fix and never the edit.
Two facts about the gate matter when you script it.
-
Any finding fails the run. A rule may declare
warnseverity, and the output labels it a warning. The exit code stays non-zero. Severity documents intent and does not soften 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. Read--jsonwhen a bot needs the structured fields.
Run every check in one step
The bare command is the shortest thing to type, and it has one trap. It runs the instruction check and the jobs check. 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
So a single bare call leaves the rules you wrote yourself
unenforced, and .jidoka/invariants/ looks green because
nothing ran it. Wire two calls everywhere you wire one:
npx @forwardimpact/jidoka
npx @forwardimpact/jidoka invariants
Keep them as separate calls rather than one combined script line. The log then names which class of defect stopped the line, and a contributor reaches 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 resolves the bare
jidoka name from the local install, with no global
state.
{
"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 concrete command in CONTRIBUTING.md, beside
the repository's other quality commands. Contributors and agents
both read that file to learn how to verify their work.
Never wire a form that only resolves on a machine somebody already
provisioned. A jidoka binary sitting on your own
PATH hides an invocation that a clean runner cannot
resolve. 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 on the pull request. Use the identical commands in both places, so 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
These decisions come up when teams wire this for the first time.
- One job, separate steps. A single job keeps the setup cost down. Separate steps keep the failure attributable 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. Fix it on its own branch, then make the job required. A required check that fails on day one teaches the team to ignore it.
A published composite action also exists. It takes an optional
command input, and it assumes a pinned
jidoka binary is already on PATH. The
action carries no npx fallback, so adopt it only when
the platform bootstrap
runs ahead of 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 |
Fix the cause. Do not fix the symptom.
- 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 signals that content sits 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 the rule objects to. Never widen an allow-list to silence a finding. Never delete the rule because it is inconvenient this week.
Re-run the suite after each fix, because one fix can expose the next. When you trim a profile, a checklist can move into a file that gates checklist blocks. The check then measures that block for the first time. A clean run is the bar.
Grandfather only during a real migration
Sometimes a new invariant lands on a codebase that already violates it. Then the rule module carries 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 @forwardimpact/jidoka invariants --seed <module-name>
Treat the list as monotone. Each migration commit removes entries. No commit ever adds one. A grandfather list that grows is an allow-list wearing a disguise, and it retires the invariant without anyone deciding to.
Record what recurs
The check names which layer broke. It does not name why the same layer keeps breaking. Keep a short note of the finding classes that return.
When one class returns again and again, the layer that should prevent it is incomplete. Do not blame the contributor who tripped the gate. Strengthen the procedure, the reference, or the invariant that should have made the mistake impossible. A check that fires every week trains people to ignore every check.
Migrate from the Co-Aligned era
This standard shipped previously under the name Co-Aligned. A repository still on 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. -
Swap the CLI. The old
coalignedcommand becomesjidoka. Update the check script, the CI workflow, and the command recorded inCONTRIBUTING.md.
An unmigrated repository fails loudly. The loader stops with a
rules directory not found error that names the location
it expected.
Verify
-
npx @forwardimpact/jidokaandnpx @forwardimpact/jidoka invariantsboth report a clean pass from a fresh clone and a fresh install. -
npm run checkruns both commands, andCONTRIBUTING.mdrecords that command. - The andon cord works. Paste a paragraph into an agent profile until it goes over its cap. Run the check, and confirm the finding names that file. Then revert the paste.
-
The invariant leg 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 deliberate defect fails the CI job, and the run summary names the step that stopped.
What's next
Enforce Your Repository's Own Invariants
Write a declarative rule module so 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. 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, so a bad agent run points at exactly one file instead of at a pile of prose.
Author or Repair One Instruction Layer
Write or fix one layer at a time. Name 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 binary check. Tag both gates so one search finds every gate in your repository.
Write Jobs To Be Done Entries
Write a job entry that traces 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, and the four forces. It also covers the Fired When clause and the tag that makes every job searchable.
Adopt Jidoka in Your Repository
Install the Jidoka skill pack, lay out the root instruction layers, wire the checks into your check command and CI, then watch the line stop on a deliberate breach.