Repository navigation
Decision log
The major design decisions behind anti-hall: what was decided, why, and when. Each row cites a committed source. The engine's full record, with every decision numbered D1 onwards and a dated revision log, is ah-engine/DECISIONS.md on the engine-proto branch; "D17" below means decision 17 there and "rev 1.94" means its revision-log entry 1.94.
To add a decision, use Template: Decision. Rows are never deleted; a decision that replaces an earlier one says so in its own row.
About the dates. Commit history on dev before 2026-10-03 was squashed, and early CHANGELOG sections carry no date. Those rows say "before 2026-08-04", the first dated release section (0.70.1).
| Date | Decision | Why | Source |
|---|---|---|---|
| 2026-10-04 | Build a resident Rust engine (ah-engine) to answer hooks, instead of starting Node processes for every hook |
Measured on 0.201.0: each Bash call started 9 Node hooks before the tool and 6 after, peaking around 409 MB; Node start-up was 65–100% of each hook's cost. The Rust prototype client used 2.0 MB against 44 MB and took 2.9 ms against 19.7 ms per call | D1, D2 |
| 2026-10-04 | One engine per user, resident and single-instance; idle exit off by default | It replaces several per-feature daemons and cron ticks; staying up keeps the scheduler and mailbox running | D3, D7 |
| 2026-10-04 | Fallback, never a silent allow: a bad, late or busy engine reply runs the Node guard | The engine must never be weaker than Node; what it cannot decide goes to Node | D11; rev 1.102 (2026-10-08) |
| 2026-10-04 | Exact parity with Node, proven check by check through parity tests, a shadow period and review | Users must not see a behaviour change when a check moves to the engine | D31, D57 |
| 2026-10-04 | Monorepo now, a separate repository later, never a submodule | One place to review and release while the engine and plugin change together | D69 |
| 2026-10-04 | Some tools stay in Node: doctor, update, state migration, DevSwarm recovery |
They must work while the engine is down | D60 |
| 2026-10-04 | Users never build: prebuilt binaries per Unix target, sha256-pinned in ah-engine.lock, built by a two-step prepare/publish release, and rebuilt only when the engine changed |
Supply-chain integrity, and no toolchain on user machines | D64, D67, D68; ah-engine/RELEASING.md |
| 2026-10-05 | Latest stable Rust and latest dependencies, kept current automatically; an old pin needs a written reason | Avoid accumulating security and upgrade debt | D84 |
| 2026-10-06 | One thin trigger per hook event (ah-hook.sh <Event>), with hooks.json generated from the dispatch table |
One dispatcher call per event; the Node hooks run whenever the engine is missing, times out, crashes or defers | rev 1.75 (D87, D58) |
| 2026-10-07 | Zero new Node code: new capability goes into the engine; Node gets bug fixes only, and the Node parity runners became Rust tests | Node is the reference the engine is compared against, not a second place to grow features | rev 1.101 (D80) |
| Date | Decision | Why | Source |
|---|---|---|---|
| 2026-10-04 | No hardcoding, enforced by tests: every tunable, table, message and limit lives in shipped defaults that user config overrides | Behaviour must be tunable and reviewable without code changes | D17; commit c9a9f52e (ratchet, 2026-10-08) |
| 2026-10-07 | Nothing is compiled into the binary: all engine config lives in plugin files, read at start-up, on plugin update and on file change | Tuning a rule means editing plugin files, never rebuilding the engine; this replaced the earlier compile-time embedding | D17 amendment, rev 1.94 |
| 2026-10 | Layered config failover: edited defaults, then last-known-good, then defaults.pristine, then Node |
A broken edit heals itself instead of breaking hooks; every fallback is logged |
engine-proto CHANGELOG, Unreleased; ah-engine/src/defaults/load.rs
|
| 2026-10-08 to 2026-10-09 | Check decisions live in editable plugin JavaScript on an embedded QuickJS; compiled decision logic driven to zero | Behaviour is data; each script must reproduce its check's golden corpus byte for byte | D88; rev 1.110; commit f33647e0
|
| 2026-10-09 | A check's own failure never blocks the agent | A script hitting its CPU limit had blocked a stop event in live use | rev 1.120 |
| Date | Decision | Why | Source |
|---|---|---|---|
| before 2026-10 | Hooks fail open: a parse, read or state error exits 0, and a guard blocks only on a positive match | A hook must never wedge a turn | CONTRIBUTING.md |
| 2026-10-05 | Stop hooks never block forever: they fail open on stop_hook_active or after a cap |
Avoid wedged sessions | rev 1.62 |
| before 2026-08-04 (0.60.0) | Each injecting hook stays under about 10,000 characters, and over-cap hooks are split, not truncated | The host spills over-cap context to a file rather than truncating it, so the orchestration rules had been reaching no session inline | CHANGELOG 0.60.0 |
| before 2026-10 | No deletion of data without explicit confirmation; automated jobs detect and report only | Data safety; deletion is a human decision |
AGENTS.md; tests/hygiene/devswarm-lifecycle-no-auto-delete.test.js
|
| 2026-10-04 | Engine pruning is limited to its own expired, derived files; user and agent content is archived, never deleted | Keeps automated cleanup consistent with the no-delete rule | D59 |
| 2026-10-09 | Doctor repairs move stores aside instead of deleting them, and preview before --apply
|
Same rule, applied to repairs | commit ae862ccf
|
| before 2026-10 | No AI credit lines in commits, pull requests or releases; git-guard enforces it |
Project policy | CONTRIBUTING.md |
| Date | Decision | Why | Source |
|---|---|---|---|
| 2026-10-10 | Repo automation is rules-first; a model only adds research, wording or an escalation, and nothing closes or deletes | Predictable, cheap, and consistent with the no-delete rule |
.github/moderation/config.json; Repo automation
|
| 2026-10-10 | Model chain: Claude primary, Claude secondary, Copilot, then rules only; models set per job by alias | Survives a token limit or outage without pinning a version | .github/workflows/ai-model.yml |
| 2026-10-10 | The Copilot CLI is pinned through a lockfile | Supply-chain integrity for a tool that runs in CI | commit 1980e0af
|
| 2026-10-10 | Pull-request CI is lean (Node 24); the full matrix runs on tags, main and weekly; parity and benchmark suites run nightly |
Faster PRs, flaky timing tests kept out of the PR gate, macOS runner cap respected |
.github/workflows/test.yml, nightly.yml
|
| 2026-10-10 | The roadmap manager marks issues named by PRs merged into dev as Done, and opens one issue per security alert |
The board stays truthful without manual moves; alerts get an owner | commits b6dd7746, 1980e0af
|
| 2026-10-10 | Docs site: dark-first slate theme with one accent, no JavaScript, no extra dependencies; contributor detail lives in this wiki | Tasteful and fast; the user site stays user-focused | docs PR for issue #90 |
| Date | Decision | Why | Source |
|---|---|---|---|
| before 2026-08-04 (0.58.1) | Minimum Node.js 22 (was 18) | Node 18 and 20 are past end of life, and Claude Code's own npm package requires 22+ | CHANGELOG 0.58.1 |
| before 2026-08-04 (0.69.0); 2026-10-04 | Windows dropped from CI and support claims; macOS and Linux (including WSL) supported | It was not being tested; the pure-Node code is unchanged. Native Windows support was later put on the roadmap (commit 86fb198d, 2026-10-07) |
CHANGELOG 0.69.0; commit 9f581bd0
|
| before 2026-10 | Dual-platform parity: every change covers the Claude plugin and the Codex port, and both orchestration layers (OMC and OMX) | A one-sided change makes the ports drift; a test checks hook parity | AGENTS.md, "Dual-platform parity" |
| before 2026-08-04 (0.67.0) | Model routing is version-agnostic: route by tier alias, never a pinned model version | The host resolves each alias to the newest model; pinned versions go stale | CHANGELOG 0.67.0 |
| Date | Decision | Why | Source |
|---|---|---|---|
| 2026-10-03 | The plugin options screen shows only 10 headline switches and 4 sensitive keys; every other setting is reached through /anti-hall:settings
|
Usability and manifest size; every feature still has a setting | commit 0e1f29dd; CHANGELOG 0.200.0 |
| 2026-10-04 | The Jev classifier is optional: it may add a block but never remove one, it is never the only gate, and deterministic rules never go to it | With Jev off, behaviour equals the non-Jev path | D34, D35, D36 |
| 2026-10-04 | No claimed Jev gains until benchmarks measure them | Published text uses only measured numbers | D37 (rev 1.4) |
| Date | Decision | Why | Source |
|---|---|---|---|
| 2026-10-03 | Work happens on dev; main changes only through a pull request from dev, with dev-only and tests-passed required |
main is what users install, so every merge to it is a release-quality event |
commit c5e5963c; RELEASING.md
|
| before 2026-10 | Release tags are never moved or deleted; a bad release is fixed with a new version | Users and the updater rely on tags being stable | CONTRIBUTING.md |
| before 2026-10 |
plugins/anti-hall/.claude-plugin/plugin.json is the only version authority; the Codex manifest and package.json track it; the marketplace entry carries no version |
Avoids the trap where two version fields silently disagree | CHANGELOG preamble; tests/hygiene/manifest-drift.test.js
|
| 2026-10-04 | The engine reaches dev by pull request from engine-proto once a phase is done and tested |
The engine lands in reviewed, tested steps | D55 |
anti-hall by Mohammed Talas (@talas9) · Repository · Docs site · Discussions · Contributor wiki: the repository is the source of truth; fix this wiki when they disagree.
🗺️ How it works
- 🏗️ Architecture
- ⚙️ Engine internals
- 🌐 DevSwarm
- 🤖 Repo automation
🛠️ How we work
📄 Templates
🔗 Elsewhere