Hooks and guards
Everything on this page is off until you turn it on — and most of it advises rather than denies.
What it is#
Guards are checks you can run by hand, from a git hook, or from an IDE hook:
| Command | What it denies |
|---|---|
orch guard dup <file> |
A file duplicating a shared symbol; also reports copied function bodies |
orch guard code-lang [root] |
Identifiers and user-visible strings that do not match workspace.code_lang |
orch guard lang [root] |
Docs that do not match workspace.locale |
orch guard ddl [files...] |
A migration or CREATE TABLE change with no seeder or repository companion |
orch guard tracker [path] |
A TRACKER state table that breaks T1–T4: bad status, SPEC with no .md, VERIFIED with no evidence, narrative dump |
There are more: comment, lock, add-all, shared-brand, control-bytes, artifacts, encoding.
Hooks are two entry points into your harness, each gated by its own consent key in orch.yaml:
| Key | Fires on | What it does |
|---|---|---|
context.hooks.post_tool |
Claude Code PostToolUse, OpenCode tool.execute.after |
Shrinks a tool result before it lands in the context window |
context.hooks.pre_compact |
Claude Code PreCompact |
Runs the orch memory condense condenser on workshop memory before the harness compacts |
Both default to false. Copilot CLI and Cursor expose the same capability but orch has no wiring path for either yet, so neither is installed; Codex CLI cannot replace tool output at all.
Wiring:
orch guard wire # from guard.profile, or --git / --claude / --cursor
orch guard unwire # add --git to remove the git hooks too
orch guard hooks install # git pre-commit + pre-push, orch-marked
orch guard hooks status
orch guard profile # show, or set: lite | shared | strict | bring | none
Advisory or block#
The distinction is per guard.
- Advisory — the clone scan, by default.
guard.dup.mode: advisoryreports what it found and injects it as context; the write proceeds. Setblockand the same finding fails the call withclone guard denied N duplicated block(s); setoffand it does not look. - Block — every other guard. A finding prints to stderr and the command exits non-zero, so a pre-commit hook stops the commit.
- Soft-skip — outside a bound workshop, or when the relevant setting is unset.
orch guard langwith noworkspace.localeskips rather than guessing.
Why it exists#
Field lessons, each cheap to state and expensive to learn. git add -A on a shared layer steals another session's work in progress. Chatting with a model in one language quietly puts that language into identifiers and error strings. A migration without a seeder passes review and fails in production. None of these need a policy engine — they need one check at the moment the mistake is made.
They are opt-in because the workshop is yours: orch init calls the starter kit recommendations, not mandates.
How it relates to the rest#
- The same guardrail suite runs twice: from the pre-commit hook you installed, and again when a session closes, over exactly the files that session touched. That second run is the observed half of the verification report.
orch harness scanreports which AI tools and doctrine surfaces it can see, before you decide what to wire.- Guard profiles control what
orch initwires:liteseeds docs and skills with no hooks,noneskips the doctrine seeds entirely.
Nothing to run here#
Nothing here runs unless you wire it. Run the guards by hand if that is all you want; orch guard wire is the switch that enforces them.