Projects · agent methodology

Which promises are enforced: Zetetic Agents, traced through its source

The claim on the tin is unusually testable: not a prompt library, a methodology with commit-time enforcement.1 A claim like that can be checked, and this dossier checks it, one guarantee at a time. The criterion is simple: a guarantee is enforced when a hook, a script or a test can return a non-zero exit that actually stops the action, and it is requested when it exists only as prose addressed to a model. Four are enforced and fail closed. Four more are enforced until someone changes a setting. One — the method the product is named after — is report-only until you opt in. And ninety-seven documented refusals are instruction, which the project states itself, twice.23

Catalogue97 reasoning patterns and 23 team agents, 81 skills, 27 commands, 57 tools57
Three ways inthe host dispatches a team agent, a shell script assembles a genius, and one script actually launches a process69
Hard stopno delegation contract, no launch — and the contract must name an external acceptance oracle1022
Measureda pre-registered paired benchmark: spawning cost more on every run, and was slower where the difference was significant2829
Published ceilingrouting agreement between two annotators is 39.0 %, and every routing score is reported against it30
Outside the hostnothing applies. Terminal commits, CI and other editors bypass every gate24
Exhibit 01 · the catalogue

A hundred and twenty agents, and three different ways in

The roster is not meant to be browsed. You name the shape of your problem and the shape selects the pattern,3 and what ships for each one is a method rather than a persona: the citations, the canonical moves, the documented blind spots, and the conditions under which it must refuse.4 The distinguishing claim is narrower and more interesting than it sounds — that an agent here can say it does not know.2

Three paths reach that catalogue and they do not overlap. The host dispatches the twenty-three team agents by matching their description.5 A shell script assembles the ninety-seven reasoning patterns, and it is worth knowing exactly what it does: it prints the agent file. No model is called.6 Only the spawn script launches a process, and it is the one place where a guarantee has teeth.9

WHAT IS SHIPPED, COUNTED 97 genius agents 23 team agents 81 skills, 15 problem-shaped 27 commands · 57 tools 23 hook registrations counted from the tree, not read from the documentation PATH A · THE HOST DISPATCHES 23 team agents selected by matching the description field PATH B · A SHELL SCRIPT ASSEMBLES 97 genius agents genius-invoker.sh — invoke, list, route it prints the agent file. No model is called. PATH C · THE ONLY ONE THAT LAUNCHES spawn-agent.sh a genius is spawnable here, unlike path A claude --permission-mode bypassPermissions with the agent body as system prompt BEFORE ANY MUTATION a contract, or nothing runs no python3 on the machine is a refusal Isolated worktree <repo>/.claude/ worktrees/<agent> identity comes from the spawn site WHAT THE CATALOGUE IS FOR “You don't browse a roster of 97 historical figures. You name the shape of your problem.” Each pattern ships with its citations, its canonical moves, its documented blind spots, and the conditions under which it must refuse. Those refusal conditions are prose addressed to a model. The project says so itself, three times over. One script on disk is registered nowhere: a context hook removed on 2026-09-04 after it fired twice per crossing alongside another plugin's copy.
A counted catalogue, not a quoted one. The figures above were counted from the tree rather than read from the documentation, which matters here more than usual: the last exhibit shows what happens where that discipline stops. One script on disk is registered nowhere at all, and the manifest says why — it fired twice per crossing alongside another plugin's copy of the same hook, wasting tens of thousands of tokens per spurious spawn, and was removed on 2026-09-04.33
Exhibit 02 · enforcement

What actually blocks, and under what condition

Four guarantees hold without a way around them. A delegation cannot start without a validated contract.9 A definition with a live caller cannot be deleted, and the gate fails closed on “cannot determine” rather than open.21 A call that would surface secrets exits with a blocking code.20 And an acceptance gate passes only if its command exits zero, with an empty gate set counting as a rejection.22

Four more are enforced until someone changes a setting, and one of those is stated wrongly in the README. It says unsourced absolutes are blocked at any profile;17 under the permissive profile the checker counts the errors, prints them, and exits zero.16 The rule names themselves cannot be switched off — that attempt exits 2 — but the severity can.18 Then comes the one that matters most: the zetetic spine, the four-step method the product is named after, is report-only by default and blocks only if you opt in, and its detection is a heuristic that a single web search satisfies.19

ENFORCED, FAIL-CLOSED a delegation contract, or no spawn deleting a definition with a live caller, including “cannot determine” reading dotenv files, keys, tokens an acceptance gate that passes only if its command exits zero an empty gate set is a rejection, never an automatic accept ENFORCED, BUT TUNABLE OFF unsourced absolutes at commit time three-decimal constants with no source, in strict only a TODO with no reference, likewise file-size and shape thresholds, each settable to block, advise or off the rule names themselves cannot be disabled: that check exits 2 REPORT-ONLY BY DEFAULT the zetetic spine recall, evidence, adversarial verification, remember warns once per session; blocks only if a file at the repo root says so, or an environment variable does and the detection is heuristic: one web search satisfies it INSTRUCTION ONLY the refusal conditions of all 97 reasoning patterns the judgment rules: single responsibility, rule of three “Refusal conditions are intent statements, not enforced contracts” “An agent can name a blind spot in its own description and exhibit it” THE ONE THAT MATTERS MOST IS REPRODUCIBLE A two-line file holding one absolute word and one bare constant was run through the checker under each profile: standard fails with one blocking violation, strict with two, and permissive prints “Errors: 1 (blocking)” and then exits zero. The README states both things. AND NONE OF IT APPLIES OUTSIDE THE HOST “Hooks fire only inside Claude Code's invocation path. Direct terminal commits, CI scripts, and other editors bypass the gates.” Without a working Python 3 the nine Python hooks fail open by design: they warn on stderr and exit zero.
The honest part is that the project says most of this itself. Refusal conditions are named as intent statements rather than contracts.23 Hooks are documented as firing only inside the host, so a terminal commit bypasses every gate.24 And without a working Python 3 the nine Python hooks fail open by design.25 What the documentation does not say is the permissive-profile exception, and that one is reproducible in two lines.16
Exhibit 03 · delegation

The contract is the only thing standing before a mutation

When an agent is launched into a repository with permissions bypassed, the question is what stands between the launch and the working tree. The answer here is one file, validated before anything is touched: no contract, no contract file, or no Python interpreter each refuse the launch outright.9 The schema requires owned paths, excluded paths, a push authority with no default, handback artefacts, and an acceptance oracle it defines as the external signal that decides completion, never a self-report.10

Two details raise this above a checklist. The lock re-runs the whole validation at registration time, explicitly to cover the race between the first check and the launch,12 and two delegations whose paths overlap are denied rather than queued, which the schema states plainly and admits is not serialisation.11 The agent's identity is set by the spawn site, on the stated grounds that a subagent cannot be allowed to forge its own.13

STEP 0 · BEFORE MUTATION Contract required no contract, no file, or no python3 → the launch is refused The validator 12 named rejection reasons owned paths, push authority, handback artefacts, an oracle Cross-check the contract must name the agent that was requested, or the spawn is refused The lock re-validates to cover the race between step 0 and this point; an overlapping scope is denied Worktree <repo>/.claude/worktrees/ inside the repository, where the cleanup sweep looks Launch identity comes from the spawn site: “the subagent cannot forge its own id” THE ACCEPTANCE ORACLE, REQUIRED BY THE SCHEMA “The EXTERNAL signal that decides completion… never a self-report.” A gate passes if and only if its command exits zero, and an empty or unreadable gate set is a rejection rather than an automatic accept. WHY THE WORKTREE LOCATION IS A RULE AND NOT A PREFERENCE Owner correction, 2026-09-08: a campaign had left 43 detached worktrees and 33 branch worktrees under a temporary directory, outside the repository and invisible to the cleanup sweep, taking space nothing would reclaim. Every line of guidance naming an outside location was retired that day. The schema carries the same discipline: a rule the validator does not enforce is documentation, not a contract.
The worktree rule is an incident report turned into a constraint. On 2026-09-08 a campaign left forty-three detached worktrees and thirty-three branch worktrees outside the repository, where the cleanup sweep could not see them and nothing would reclaim the space; every line of guidance naming an outside location was retired the same day.1514 The project also states the limit of the whole approach: worktrees isolate files, not runtime.36 And one claim about this loop has no artefact behind it — that it converged end-to-end on an external repository, with no log, date or verdict in the tree.35
Exhibit 04 · the numbers

What is measured, and what drifted past the gate

The measurement work here is real and unusually disciplined. A paired benchmark compares an inline skill against a spawned subagent with the protocol frozen before any run existed, five repetitions, randomised order, two blind graders, raw and scored data committed.28 Its result is not the flattering one: spawning cost more on every run, and was slower where the difference reached significance.29 The routing scorecard goes further and publishes a ceiling: two annotators agree on the shape only 39 % of the time, so every routing score is reported against 39 rather than against 100.3031 A structural auditor passes over all 120 agent files, and a count check verifies thirty-seven documented claims against the tree.327

Then there is the sentence every user reads. The session banner prints four numbers, and three are wrong at this revision: 63 skills where there are 81, 14 hooks where there are 23 registrations, 17 tools where there are 57.26 The command index claims seventeen commands where the tree holds twenty-seven.27 The counting document contradicts itself four paragraphs apart, and disagrees with its own prescribed command about the number of tools.8 None of those files is in the registry the drift check reads.7 The gate works; it was simply given a list of five files, and the most visible sentence in the product is not on it.

MEASURED, WITH A PROTOCOL FROZEN BEFORE THE RUN Inline skill against spawned subagent n = 5 repetitions, randomised order, two blind graders, raw and scored data committed. Quality 9.60 against 9.90 on one task, 10.00 against 8.50 on another. Spawning cost more every time: $0.59 against $0.85. Wall clock 47.7 s against 88.4 s, significant. Routing agreement has a ceiling, and it is published Two annotators agree on the shape 39.0 % of the time. The rule that follows: “Every shape-routing score is reported against this ceiling, never against 100%.” Cohen kappa 0.554 on 351 real conversation turns. DRIFTED, AND OUTSIDE THE GATE THAT WOULD CATCH IT The banner every session prints 97 reasoning patterns · 63 skills · 14 hooks · 17 tools Measured at this revision: 81 skills, 23 hook registrations, 57 tools. Three of the four numbers are wrong, in the one sentence every user reads. The command index says 17 commands. There are 27. The counting document gives 23 registrations in its table and 19 in its prose, four paragraphs apart, and 56 tools where its own command returns 57. The trigger count appears as 650+, 400+ and 400+ in the same README. THE GATE THAT DOES WORK A count check verifies 37 claim instances against the tree and passes. A structural auditor runs 18 checks over 120 agent files: no blockers, no warnings. Both were re-run for this dossier and reproduced. Test counts are stated as suites, never as assertions, on purpose. AND WHY IT MISSES THE REST Its registry names five files. The session banner is not one of them. Neither is the command index, nor the trigger counts, nor the two lines of the counting document that disagree with each other. A gate is only as wide as the list it is given.
A gate is only as wide as the list it is given. That is the finding worth keeping from this exhibit, and it generalises well beyond this repository: the anti-drift check here is genuine, reproducible and passing, and it never looks at the one line every single session prints.726

Why this is the right thing to publish

A project whose first rule is “no source, say I don't know” invites exactly this treatment, and mostly survives it. The enforcement that matters — contract, deletion, secrets, acceptance — holds and fails closed. The benchmark reports against its own product's interest. The routing score is published against a measured ceiling instead of a round number. What does not hold is narrower and fixable: one README line that contradicts the checker,17 a documented context budget resting on a hook that was deliberately removed,34 and four self-descriptions that drifted because nobody added them to a list.26278 Naming them is not a reservation about the tool. It is the tool's own standard, applied to the tool.

1README.md:17:17 — “Not a prompt library. A methodology with commit-time enforcement.”
2README.md:47:47 — “Zetetic Agents are different in one specific way: they can say ‘I don't know.’
3README.md:55:55 — “You don't browse a roster of 97 historical figures. You name the *shape* of your problem.”
4README.md:196:196 — “Most AI agent libraries ship ‘pretend to be Einstein.’ This ships Einstein's method… Reasoning procedures, not personas.”
5.claude-plugin/plugin.json:25:25-49 — the twenty-three team agents the host is told about
6tools/genius-invoker.sh:5:5-8 — four verbs: invoke, list, route, compose. Invoke prints the agent file; no model is called anywhere in the script
7tools/doc-count-check.sh:36:36-74 — the registry of documented counts the drift check verifies. It names five files
8docs/COUNTING.md:35:35-36 gives 23 hook registrations and 24 scripts; :68-69 says 19 and 20, four paragraphs later. :38 gives 56 tools where its own prescribed command returns 57
9scripts/spawn-agent.sh:74:74-92 — step 0 runs before any mutation: no contract, no contract file, or no python3 each refuse the launch
10schemas/delegation-contract.schema.yaml:28:28-40 — the required fields, including an acceptance oracle described as “The EXTERNAL signal that decides completion… never a self-report”; :47-58 lists twelve rejection reasons
11schemas/delegation-contract.schema.yaml:65:65-70 — “This validator's policy is DENY (not queue-and-serialize)… Serialization (queueing) is not implemented”
12scripts/spawn-agent.sh:165:165-176 — the lock re-runs the validation, explicitly to cover the race between step 0 and the launch
13scripts/spawn-agent.sh:202:202-203 — “Identity MUST come from the spawn site, not the subagent: the subagent cannot forge its own id.”
14rules/agent-reference/worktree-protocol.md:10:10-13 — the worktree lives inside the repository, under .claude/worktrees/, because that is the only place the cleanup sweep knows about
15rules/agent-reference/worktree-protocol.md:19:19-22 — owner correction of 2026-09-08: 43 detached worktrees and 33 branch worktrees left outside the repository, invisible to the sweep. Every line of guidance naming an outside location was retired that day
16tools/zetetic-checker.sh:301:301-304 — under the permissive profile the checker exits 0 unconditionally, errors counted and printed. Reproduced on a two-line file: standard fails with one blocking violation, strict with two, permissive prints “Errors: 1 (blocking)” and exits 0
17README.md:188:188 — “blocks commits with UNSOURCED keywords… at any profile”. :333 documents permissive as “everything informational; never blocks”. The two cannot both hold
18tools/zetetic-checker.sh:59:59-65 — an attempt to disable a rule by configuration exits 2: “Rules themselves (UNSOURCED, MAGICNUMBER, TODONO_REF) cannot be disabled.”
19hooks/stop-zetetic-spine.py:13:13-21 — report-only by default, once per session; it blocks only on an explicit opt-in file or environment variable. :112-119 shows the detection is heuristic, and a single web search satisfies it
20hooks/pre-tool-secret-shield.py:7:7-9 — “Exits with code 2 (blocking)” when a call would surface secrets; :26-31 records its own limit, that writing such a file is flagged rather than blocked
21hooks/pre-tool-deletion-gate.py:27:27-31 — “FAIL-CLOSED ON ‘CANNOT DETERMINE’, not fail-open”, with the branch-protection check that motivated it dated and quoted
22tools/acceptance_gate.py:29:29-31 — a gate passes if and only if its command exits 0, and an empty or unreadable gate set is a rejection rather than an automatic accept
23README.md:186:186 — “Refusal conditions are intent statements, not enforced contracts”; :288 adds that an agent “can name a blind spot in its own description and exhibit it anyway”
24README.md:287:287 — “Hooks fire only inside Claude Code's invocation path. Direct terminal commits, CI scripts, and other editors bypass the gates.”
25hooks/run-python.sh:32:32-38 — with no working Python 3 the hooks “Fail open: warn on stderr but do not block the session (exit 0)”, which turns nine of them into no-ops
26hooks/session-start.sh:60:60 — the line printed at every session start: “97 reasoning patterns · 63 skills · 14 hooks · 17 tools”. Measured at this revision: 81 skills, 23 hook registrations, 57 tools
27commands/_index.md:3:3 — “17 commands across 6 categories”. The tree holds 27 commands across 8 directories, and the names listed do not match the paths they are invoked by
28tools/bench-agent-cost/README.md:332:332-335 and :340-354 — the paired benchmark, pre-registered, n = 5, randomised order, two blind graders, raw and scored data committed
29tools/bench-agent-cost/README.md:451:451-466 — quality 9.60 against 9.90, cost $0.59 against $0.85 and wall clock 47.7 s against 88.4 s, the last two significant
30docs/GOA-SCORECARD.md:36:36-41 — two annotators agree on the shape 39.0 % of the time, and the rule that follows: “Every shape-routing score is reported against this ceiling, never against 100%.”
31docs/GOA-SCORECARD.md:23:23-27 — Cohen kappa 0.554 over 351 real conversation turns, 64 disagreements, seven arbitrated by a human on 2026-08-05
32README.md:399:399 — all 120 agent files pass the structural auditor. Re-run for this dossier: 18 checks, no blockers, no warnings
33hooks/hooks.json:2:2 — the removal note: the context hook “was registered here AND by context-guard@session-optimizer-marketplace simultaneously — confirmed live double-firing… ~55-66K tokens wasted per spurious memory-writer spawn”, 2026-09-04
34README.md:321:321-323 — the README still describes that hook as registered and wired out of the box. It appears in neither manifest
35README.md:251:251 — “the loop has converged end-to-end on an external repository with the result independently re-gated”. No log, date, repository name or verdict for that run is in the tree
36README.md:253:253 — “Honest limit: git worktrees isolate *files*, not *runtime*… the file-writing build step is mitigated… but not fully enforced by git alone.”