factory.toml
One file per repository, written by /factory:setup. Every key has a default, so a short file is a correct file.
Schema
[factory]
spec_dir = "docs/specs" # <spec_dir>/<slug>/{spec.md,plan.md,issues/}
base = "origin/main" # root of every stack; a planned slice measures against its Parent
[tracker]
kind = "github" # github | gitlab | jira | local
jira_site = "" # mysite.atlassian.net (jira only)
jira_project = "" # project key such as ENG (jira only)
jira_type = "Task" # work item type for slices (jira only)
[verify]
crap_threshold = 5 # poly-crap --threshold
coverage = "" # lcov path when auto-detection fails
llm = false # judge lawbook prose standards on a green tree; fail-level ones gate
max_requests = 50 # cap on model requests per verify run (one per rule per file)
max_iterations = 5 # cap for the implement <-> verify loop
exclude = [] # globs left out of every stage and passed to poly-crap, e.g. ["upstream/*"]
[verify.commands] # each key overrides the stack default; "" keeps it
typecheck = ""
lint = ""
format = ""
test = "" # must write the lcov file named in [verify].coverage
factory.toml lives at the repository root. Every skill reads it first
and falls back to detection when a key is missing or the file is absent.
Omit keys that match the defaults.
Stack defaults
The verify script detects the stack from marker files. First match wins.
| Marker | Stack | typecheck | lint | format | test (writes lcov) |
|---|---|---|---|---|---|
pnpm-lock.yaml, package.json |
node | <pm> exec tsc --noEmit (if tsconfig), else node --check |
<pm> exec eslint <files> (if config) |
<pm> exec prettier --check <files> (if config) |
<pm> test; lcov at coverage/lcov.info or lcov.info |
pyproject.toml, uv.lock |
python | uv run python -m compileall -q <files> |
uvx ruff check <files> |
uvx ruff format --check <files> |
uv run pytest --cov --cov-report=lcov:.verify/lcov.info |
Cargo.toml |
rust | cargo check |
cargo clippy -- -D warnings |
cargo fmt --check |
cargo llvm-cov --lcov --output-path .verify/lcov.info |
go.mod |
go | go vet ./... |
golangci-lint run (if present) |
gofmt -l <files> |
go test -coverprofile=.verify/coverage.out ./... |
For node, <pm> follows the lockfile: pnpm with pnpm-lock.yaml,
yarn with yarn.lock, otherwise npm. A repo with none of these
markers needs [verify.commands] filled in, or the verify script exits 2.
A command that is not installed also exits 2.
[verify].exclude filters the files verify sends to every stage and is
passed to poly-crap as --exclude. lawbook keeps its own ignore list in
lawbook.yaml, because it also runs outside verify.
Tracker kinds
local: one file per slice at<spec_dir>/<slug>/issues/NN-<task>.md.github:gh issue createper slice plus one tracking issue.gitlab:glab issue createper slice plus one tracking issue.jira:acli jira workitem createper slice under a parent work item.
/factory:plan publishes only after the user approves the breakdown. The
exact commands live in the plan skill’s references/trackers.md.