Files
ironclaw/.coderabbit.yaml
Benjamin Kurrek 173f078bba Gate & ratchet audit: full-inventory report, five fail-opens armed, dead gates deleted (#7373)
* test(architecture): drop the dead ironclaw_storage row and arm the substrate list

Gate-audit finding (open-and-shut): SUBSTRATE_CRATES in
reborn_composition_boundaries.rs carried three rows of rot, all invisible
because the loop's `let Some(..) else { continue }` silently skipped any
entry that resolves to no workspace package:

- "ironclaw_storage": no such package exists (verified against
  `cargo metadata --no-deps`; the only MISSING name of the 29 listed).
- "ironclaw_approvals" and "ironclaw_assistant" were each listed twice.

The silent skip is replaced with a panic naming the stale entry, so the
list can no longer rot invisibly. Verified by sabotage: adding a bogus
"ironclaw_zzz_probe" row now fails the test with
"is listed in SUBSTRATE_CRATES but is not a workspace package"; the
clean list passes (23/23).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(architecture): prune the dead sanctioned path from the specificity gate

Gate-audit finding (open-and-shut): SANCTIONED_PATHS in
reborn_extension_specificity.rs still exempted
`extension_host/extension_installation_store.rs` — a file deleted by
#6430. No scanned path matches the fragment (verified with rg across
crates/), so the entry exempted nothing; it is also the one exclusion
surface in this gate with no staleness check, which is how it outlived
its file. Full specificity suite green after removal (8/8).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(architecture): drop the v1 ironclaw_gateway/static exclusions from the telegram gates

Gate-audit finding (open-and-shut): both cross-tree scans in
telegram_extension_gates.rs still carved out `ironclaw_gateway/static`
— the v1 monolith's embedded UI, whose crate was deleted with the src/
monolith (no crates/*/ironclaw_gateway directory exists). The exclusions
matched nothing; scans now cover the whole tree with no dead carve-outs.
Suite green after removal (12/12).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(architecture): make the dto-collapse gate's header describe the gate that exists

Gate-audit finding (open-and-shut doc rot): the module doc still
described the pre-#6447 freeze design — a dangling doc-link to
FROZEN_COLLAPSE_DTOS (renamed RETIRED_COLLAPSE_DTOS in #6447), a
promised delete-without-trimming failure and an empty-allowlist
assertion that do not exist in the file, and a named owner for a
collapse that completed. The mechanism itself is armed and untouched;
the header now describes the permanent zero-gate it became, and records
the two originally-frozen names that deliberately left governance
(CapabilityOutcome via #6299 deletion, CapabilityDispatchRequest blessed
as the canonical port type). Suite green (2/2).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(architecture): repoint the manifest-reparse allowlist note at the colocated asset

Gate-audit finding (open-and-shut doc rot): the BundledAsset allowlist
entry's justification still cited include_str! of
assets/memory_native/manifest.toml — a path retired when WS2 (#7037)
colocated packages; the live include in memory_native_extension.rs
reaches crates/extensions/packages/memory-native/manifest.toml. Comment
only; the gate's mechanism and counts are untouched. Suite green (2/2).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(architecture): give the memory-vocabulary gate the partial-tree floor its twin has

Gate-audit finding: reborn_memory_retired_vocabulary.rs had no
MIN_SCANNED_FILES floor, unlike its explicit twin
reborn_retired_taxonomy.rs — so a partially-moved tree (the CHECKLIST
WS0 / #6963 'green while measuring nothing' shape) would scan a
fraction of the files and still report the vocabulary clean. The gate
was in fact born with an already-dead sanctioned path (its own header
records this), so the rot class is not hypothetical for this file.

Adds the same 500-file floor (real count ~4000), asserts it in the main
gate, and pins the premise on a fixture: a 10-file partial tree scans
clean and is rejected by the floor. Suite green (4/4); clippy clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(architecture): close the transport gate's nested-use-group fail-open

Gate-audit finding (sabotage-verified): product_symbols_in's braced-group
branch closed at the FIRST '}' (group.find('}')), so a nested group —
use ironclaw_assistant::{m::{X}}; — truncated mid-element and recorded
zero symbols. Probed live before the fix: appending
use ironclaw_assistant::{zzz_audit::{ZzzProbe}}; to webui's lib.rs left
transports_name_only_the_frozen_residue_of_product_symbols GREEN, while
the plain-path spelling of the same import correctly failed. The same
truncation dropped qualified elements inside flat groups
({qualified_module::X} recorded nothing).

The group branch now does a balanced-brace walk, splits elements at
depth-0 commas only, and records a qualified/nested element's leading
path segment — the same key the single-path branch records for
ironclaw_assistant::module::X. Flat-element semantics are byte-for-byte
unchanged, so the frozen 100-row webui inventory is untouched (suite
green 6/6 on the live tree). Regression fixtures added to
import_scanner_reads_symbols_out_of_real_use_shapes; the original
sabotage now fails with the gate's own message (re-verified).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: delete check-e2e-matrix-files.sh — a gate for a workflow that no longer exists

Gate-audit finding (provably inert): the script's default target is
.github/workflows/e2e.yml, deleted when the v1 e2e suites were retired
(git log --diff-filter=D shows the removing commit); no workflow, script,
hook, doc, or guidance file references check-e2e-matrix-files.sh
(verified with rg across the repo including .github and .githooks).
A checker nothing runs, pointed at a file nothing provides, is dead
weight that reads as coverage.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci: delete the measured-broken check-boundaries.sh and its guidance references

Gate-audit finding (provably inert, previously measured): crates/AGENTS.md
recorded on 2026-08-05 that the script fails on a clean tree (check 5
false-positives on live test files) and that checks 1/2/3/6 target the
deleted v1 src/ tree, passing vacuously. No workflow or hook runs it; its
only callers were guidance files, two of which claimed it 'enforces'
root-tests feature gating — an enforcement claim the skill-maintainer
rules forbid for a check nothing executes.

Removed the script and every live reference: the crates/AGENTS.md warning
row becomes a tombstone note; the testing skill + exemplar reference drop
the false enforcement parenthetical; the architecture-review skill's
Verify line drops the dead command; deslop-reborn's allowed-tools drops
the permission; .coderabbit.yaml's driver-leak instruction now points at
the live enforcement (reborn_persistence_driver_boundary). Two dated
docs/internal/ plan snapshots keep their historical mentions.

Verified: python3 scripts/ci/check-guidance.py OK (2084 path references)
and its self-test OK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(product): stop hardcoding charter sub-owner counts in the family map

Gate-audit finding (stale prose): crates/product/AGENTS.md said
'19-sub-owner reborn_services charter map' — the enforced map has had 20
sub-owners since #7235 added the inspector row (counted from the live
table). Rather than chase the number, drop both inline counts: the
owning maps and their gates are authoritative, and the re-verify
commands are already inline (skill-maintainer rule: no counts without a
regeneration recipe). check-guidance.py OK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(architecture): correct the scanner-fixture file's name-filter claim

Gate-audit finding (doc rot with a false coverage claim): the header
said naming the FILE reborn_* makes code_style.yml's
'cargo test -p ironclaw_architecture_tests reborn' see it — but that
argument is a test-NAME filter (the measurement is documented in
reborn_contracts_vendor_census.rs), and none of this file's test fns
contains the substring, so that smoke lane runs 0 of them (11 collected
by the full plan). Comment-only; the note now records the real semantics
so file names are not trusted for lane coverage. Suite green (11/11).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(internal): gate & ratchet audit report + proposed preflight gauntlet

The audit the owner asked for after PR #7157 went red six times across
four gates: every architecture-test gate, module charter, CI script, and
committed baseline inventoried with a verdict and evidence; the handful
worth acting on ranked by friction x weakness; the CI-ergonomics analysis
(why failures surface one per ~1h round-trip: no --no-fail-fast anywhere
in CI, cancel-in-progress on push, sequential fast-checks steps —
measured: two broken gates report 1 failure in 18s under the CI shape vs
both in 211s with --no-fail-fast); and the sabotage log for every probe.

scripts/preflight-gates.sh is the concrete pre-push proposal: the
deterministic-gate classes only (script gates ~10s + architecture suite
--no-fail-fast + changed-crate charter tests), covering all four #7157
gate classes locally in one command. Unwired — nothing invokes it.
Validated end-to-end on this branch: exit 0, 'every deterministic gate
green', 402.8s including gate-binary recompiles.

Placement verified: python3 scripts/ci/docs_publication_boundary.py OK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci(planner): classify preflight-gates.sh and the deleted check-boundaries.sh

The gate audit's own PR hit the planner's fail-closed arm — 'unmapped
test or CI path: scripts/check-boundaries.sh' — exactly the class the
arm exists to force a decision on (and the audit's report documents).
Per the PR_STATIC_CONTROL_PATHS membership rule (no Reborn test lane
exercises either file):

- scripts/preflight-gates.sh — the audit's proposed local pre-push
  gauntlet; referenced by no workflow.
- scripts/check-boundaries.sh — deleted by the audit; the entry lets the
  deletion diff (and any revert) classify instead of failing every
  downstream Reborn lane.

Verified: the planner now produces mode=selected with the
architecture-misc bucket for this branch's diff, and
python3 scripts/ci/test_reborn_pr_test_plan.py is OK.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(internal): add the fold-tripped asymmetric-tolerance exhibit to the audit

The strongest single exhibit for shortlist item 2, contributed by the
#7157 branch steward after this audit's cutoff and verified against the
gate's code: TOLERANCE = 400 is consulted in exactly one direction (the
banked-slack check, ceiling.saturating_sub(lines) > TOLERANCE); the
growth check is a bare lines > ceiling. With the in-file 'set to
current, not padded' instruction, every ceiling is a hard cap at the
observed count — so one line landing on main in any contracts crate
reds every open branch at its next fold until someone re-captures.

Measured recurrence on #7157: loop_contracts re-captured four times,
~once per fold (14,479 -> 13,850 -> 13,949 -> 13,115 -> 13,181), the
last tripped by main's #7361/#7363 adding 66 lines to
instruction_bundle.rs — nothing the branch wrote. All four deltas were
<= 105 lines: either repair shape in §3.2 (one-line upward tolerance
using the existing constant, or mid-window pinning) would have absorbed
every one with zero red builds. This audit's own sabotage already
proved the jaws (+1 line host_api red / -1 line common red); the fold
history shows the operational cost. The repair stays a recommendation —
adding growth headroom to a ratchet is the owner's call, not this PR's.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(architecture): give the contracts size ceiling upward working slack

Owner-directed repair of the audit's sharpest finding (report §3.2): the
gate's TOLERANCE = 400 was consulted in exactly one direction — the
banked-slack check — while the growth check was a bare lines > ceiling.
Combined with 'set to current, not padded' pins, every ceiling was a hard
cap at the exact observed count, so one line landing on main in any
contracts crate redded every open branch at its next fold until someone
re-captured. Measured on #7157: four loop_contracts re-captures, roughly
once per fold, every delta <= 105 lines — the gate generating its own
busywork.

The growth check now allows GROWTH_TOLERANCE = 150 of working slack
above each pin (sized to composition-budget precedent; the reviewed
raises this gate has caught were +1,069 and +1,214 lines, far above it),
and all six ceilings are re-pinned to the counts the test itself
reported with every ceiling at 0 — which also removes the +400 seed
padding on common/loop_contracts/prompt_envelope that contradicted the
capture rule and put those crates one deleted line from the banked jaw.

Sabotage-verified both ways: +1 line in host_api and -1 line in common —
both red before this change — now pass; a +151-line probe still fails
with the effective-ceiling arithmetic in the message. Full
reborn_dependency_boundaries binary green (41/41); clippy clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci(budget): re-equalize composition pins to observed — restore the working window

Owner-directed companion to the contracts-ceiling repair (same annoying
class, other mass gate): merged main-side growth since the 2026-08-05
equalization had drifted +101 LOC and +5 Arc<dyn> sites through the
tolerance windows, leaving 49 LOC / 10 sites of live headroom — the next
routine composition PR would have gone red on wiring alone (the gate
audit measured this the same day it was pinned).

Per the TOML's own maintenance instructions: loc_ceiling/loc_observed
40423 -> 40524 and arc_dyn 814 -> 819, measured with the gate's --print,
set to current not padded, dated notes appended (not overwritten), and
the arch-test record (COMPOSITION_ABSOLUTE_SRC_LOC) moved in the same
commit as its file requires. ceiling_bp stays 658 — the WS0 floor is
deliberately not re-set.

Verified: check-composition-budget.sh OK; its 76-case self-test green;
reborn_restructure_baselines green; probe +100 LOC now passes (was red
at 49 headroom), probe +160 LOC still fails.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(internal): record the landed zero-slack repairs in the audit report

The §3.2 repair moved from recommendation to landed at owner direction;
the report's answer, inventory rows, and §7 ledger now say so, with the
counting-rule fix promoted to the top remaining recommendation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* gates: pin the ceiling-window arithmetic; fail preflight discovery closed

Two review-round hardenings (the open CodeRabbit Majors):

- reborn_dependency_boundaries.rs: extract the size-ceiling comparison into
  contracts_ceiling_verdict() and pin its four window edges with a committed
  regression test (contracts_size_ceiling_window_edges_hold) — accept at
  ceiling+GROWTH_TOLERANCE, reject one line past, accept at
  ceiling-TOLERANCE, reject one banked line further, and a zero-measure scan
  reads Banked, never a silent pass. The pre-repair asymmetry (tolerance
  consulted only downward) can no longer return silently. Live-gate behavior
  re-probed unchanged after the rewiring: +1 line to host_api passes, +151
  fails with the same effective-ceiling message.
- preflight-gates.sh: setup and changed-file discovery now fail closed — a
  missing repo root exits 2, and a failed merge-base/diff widens the charter
  run to all five crates instead of silently skipping them (the same
  fallback the missing-base branch already used). A broken setup may cost
  compile time, never a silent skip.

Full boundary binary 42/42 green; clippy clean; preflight-gates.sh
end-to-end green on this tree.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-12 15:04:35 +00:00

267 lines
15 KiB
YAML

# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
#
# CodeRabbit configuration for nearai/ironclaw.
#
# Context: CodeRabbit is being trialed as the primary AI reviewer, a candidate
# replacement for Gemini Code Assist, the ruleset-enforced Copilot review, Codex,
# and the on-demand `@claude review` workflow. During the trial all reviewers run
# side by side for comparison.
#
# Deterministic CI remains authoritative for everything it gates (cargo fmt,
# clippy -D warnings, cargo-deny, scripts/check_no_panics.py,
# scripts/check_gateway_boundaries.py, regression-test-check) — CodeRabbit is
# configured NOT to repeat those findings.
#
# On-demand deep review: comment `@coderabbitai full review` (replaces
# `@claude review`). Other commands: `@coderabbitai review` (incremental),
# `pause` / `resume`, and `@coderabbitai ignore` in the PR description to opt out.
#
# NOTE: this file is inert until the CodeRabbit GitHub App is installed on the
# nearai org and authorized for this repository (dashboard action, not code).
language: en-US
tone_instructions: "Terse, evidence-first senior Rust review. Cite the repo invariant violated (CLAUDE.md/AGENTS.md/.claude/rules). Skip what clippy, rustfmt, cargo-deny and check_no_panics already gate. Sandbox, trust, secrets, egress and migration issues first."
reviews:
profile: assertive # full strength for the head-to-head trial against the other AI reviewers
request_changes_workflow: false # advisory only; merge gating stays with the ruleset's required checks
high_level_summary_in_walkthrough: true # keep PR descriptions owner-authored; put generated summaries in the walkthrough comment
# Review everything except generated / vendored / fixture / binary content.
path_filters:
- "!**/Cargo.lock"
- "!CHANGELOG.md" # maintained by release-plz
- "!ironclaw.bash" # clap_complete-generated completions
- "!ironclaw.fish"
- "!ironclaw.zsh"
- "!README.ja.md" # translations; review the English source
- "!README.ko.md"
- "!README.ru.md"
- "!README.zh-CN.md"
- "!docs/zh/**"
- "!docs/images/**"
- "!docs/internal/architecture-video/package-lock.json"
- "!tests/test-pages/**" # saved web pages (linguist-generated)
- "!tests/fixtures/**" # recorded LLM/gateway traces
- "!tests/snapshots/**" # insta snapshots — the replay gate owns these
- "!src/cli/snapshots/**"
- "!tests/e2e/ironclaw_e2e.egg-info/**"
- "!tests/e2e/**/*.png"
- "!fuzz/corpus/**"
- "!crates/substrates/ironclaw_safety/fuzz/corpus/**"
- "!**/*.wasm" # compiled artifacts; new binaries surface via registry/ and manifest review
- "!crates/ironclaw_webui_v2_static/static/assets/**" # binary icons; static/js IS hand-written and reviewed
- "!wix/**" # cargo-dist/WiX installer boilerplate
- "!ironclaw.png"
path_instructions:
- path: "**/*.rs"
instructions: |
Review against the repo's named invariants and cite them:
- "Everything Goes Through Tools": gateway handlers, CLI commands, routine engine,
WASM channels and other non-agent callers route actions through
ToolDispatcher::dispatch(), never directly via state.store / workspace /
extension_manager / skill_registry / session_manager (exceptions need
"// dispatch-exempt: <reason>").
- Trusted-ingress seal: product adapters, product workflow, first-party capabilities
and host-runtime handlers consume untrusted inbound requests; they must not mint
TrustedInboundTurnRequest or call trusted trigger-submitter factories; never add a
second agent loop.
- Fail loud: flag silent-failure patterns — .unwrap_or_default() on a Result, .ok()?
dropping errors, let-else returning None to swallow failures, warn-and-continue that
poisons state. Errors propagate with ? into thiserror types with context.
- "LLM data is never deleted": no stripping/truncating/deleting LLM output, context,
reasoning or tool calls from the database; cleanup means cache eviction, never row
deletion.
- Prompt templates live in files (crates/ironclaw_engine/prompts/*.md via
include_str!), never inline Rust string constants.
- REPL/TUI logging: info!/warn! corrupt the terminal UI — internal diagnostics use
debug!; background tasks never use info!.
- Test through the caller: when a helper gates a side effect, require a test driving
the real call site (handler/factory/manager), not only the helper.
- Imports: crate:: for cross-module paths (super:: only in tests); no pub use
re-exports unless for downstream consumers; import extracted-crate types from
ironclaw_safety / ironclaw_skills / ironclaw_llm directly, not via crate:: shims.
- Module specs win ties (root CLAUDE.md "Module Specs" table) — flag diffs that
contradict their module spec without updating it.
- New `unsafe` outside #[cfg(test)] env-var manipulation is exceptional and needs a
SAFETY comment; many reborn/product crates declare #![forbid(unsafe_code)].
Do NOT flag: .unwrap()/.expect()/assert! in production (scripts/check_no_panics.py is
a blocking CI gate), rustfmt/clippy-level style, dependency licenses/advisories
(cargo-deny), or pre-existing issues the PR does not touch.
- path: "migrations/**"
instructions: |
Refinery PostgreSQL migrations. Released migrations are IMMUTABLE: any edit to an
existing V*.sql or to a pinned hash in migrations/checksums.lock is a hard error (the
released_migrations_are_immutable test enforces SipHasher13 checksums). New
migrations: next sequential V{n}__snake_case.sql, up-only, PostgreSQL dialect.
Dual-backend mandate: schema changes generally need a matching hand-translated update
in src/db/libsql_migrations.rs (UUID→TEXT, TIMESTAMPTZ→ISO-8601 TEXT, JSONB→TEXT,
BYTEA→BLOB, VECTOR→F32_BLOB) — flag a new V*.sql without a libSQL twin change unless
justified. Ported schema must include indexes and seed data, with semantic
differences documented. Destructive DDL is review track C: 2 approvals + documented
rollback plan (CONTRIBUTING.md).
- path: "src/db/**"
instructions: |
Dual-backend persistence: every new persistence feature supports BOTH PostgreSQL and
libSQL — extend the shared Database trait first, then both backends (Reborn stores
keep ironclaw_hooks_postgres / ironclaw_hooks_libsql in parity via hooks_parity).
Multi-step DB operations must be wrapped in a transaction. Driver types
(tokio_postgres::, libsql::) must not leak outside the allowed modules
(enforced by reborn_persistence_driver_boundary in
crates/app/ironclaw_architecture_tests).
- path: "**/*.wit"
instructions: |
Hand-written WIT contracts define the trusted/untrusted WASM ABI. Interface changes
must stay in sync with the host bindgen sites (src/tools/wasm/wrapper.rs,
src/channels/wasm/wrapper.rs, crates/ironclaw_wasm/src/bindings.rs,
crates/ironclaw_wasm_product_adapters/src/bindings.rs) and the ~20 guest crates under
tools-src/ and channels-src/. WIT or extension-source changes require version bumps
(scripts/check-version-bumps.sh; escape token [skip-version-check]). Host capability
functions are security-gated: secrets must never cross into WASM guests; guest
outputs are scanned for leaks — flag anything that widens host capabilities or
bypasses capability checks.
- path: "**/*.capabilities.json"
instructions: |
Capability manifests grant authority to sandboxed WASM guests. Every new or broadened
grant (network hosts, workspace paths, secrets, tool-invoke) is a security decision:
require justification, prefer the narrowest scope, flag wildcard or broad-domain
grants.
- path: "registry/**"
instructions: |
Registry manifests are embedded into the binary and drive extension installation.
Verify URLs point at expected upstreams, artifact references carry checksums, and no
un-audited prebuilt WASM is introduced (root build.rs documents committed WASM as a
supply-chain risk).
- path: "{src/sandbox/**,src/secrets/**,src/safety/**,src/gate/**,src/pairing/**,src/auth/**,crates/substrates/ironclaw_safety/**,crates/substrates/ironclaw_secrets/**,crates/substrates/ironclaw_network/**,crates/kernel/ironclaw_trust/**,crates/kernel/ironclaw_authorization/**,crates/kernel/ironclaw_capabilities/**,crates/ironclaw_process_sandbox/**,crates/contracts/ironclaw_prompt_envelope/**,crates/product/ironclaw_webui/**}"
instructions: |
Kernel/safety boundary — review track C (2 approvals + rollback plan). Hold the line
on: no weakening of bearer/webhook auth, CORS/origin checks, body/rate limits or
egress allowlists; egress goes through host-mediated policy with private-IP /
DNS-rebinding rejection (ironclaw_network policy/resolver); never expose raw secret
material via metadata, errors, debug output, audit records, events or dispatch
results (ironclaw_secrets); privileged EffectiveTrustClass variants (FirstParty,
System) are constructible only inside ironclaw_trust; sandbox lanes accept typed
plans only (SandboxProcessPlan) — no raw Docker flags, raw host paths or blanket env
inheritance; events/audit records are redacted by contract. Treat containers and
external services as untrusted.
- path: ".github/workflows/**"
instructions: |
GitHub Actions hygiene. Privileged triggers exist (pull_request_target in
pr-label-*.yml; issue_comment dispatchers in claude-review.yml and nearai-bench.yml):
flag privileged workflows that check out or execute PR-controlled code,
`permissions:` expansions, unpinned third-party actions (pin full SHAs), and
interpolation of untrusted ${{ github.event.* }} strings into run: scripts. The
roll-up job names "Run Tests" and "Code Style (fmt + clippy)" are required checks in
the main ruleset — renaming them silently un-gates merges.
- path: "{scripts/**,.github/scripts/**}"
instructions: |
CI and dev tooling. Expect set -euo pipefail and quoted expansions; these scripts
gate merges (check_no_panics.py, check_gateway_boundaries.py, pr-labeler.sh), so
behavior changes need matching workflow updates.
- path: "tests/e2e/**"
instructions: |
Python/Playwright e2e harness (see tests/e2e/CLAUDE.md). Scenarios use the mock LLM /
fake APIs, never live providers; credentials come from env, never hardcoded.
- path: "{Dockerfile*,docker/**,deploy/**,infra/**,crates/Dockerfile.sandbox}"
instructions: |
Sandbox and deployment images are security boundaries running untrusted workloads.
Flag privilege escalation (root user, added capabilities, docker.sock mounts),
weakened entrypoint isolation, secrets baked into layers, and unpinned base images.
- path: "{crates/ironclaw_gateway/static/**,crates/ironclaw_webui_v2_static/static/js/**,src/channels/web/static/**}"
instructions: |
Hand-written no-build frontends embedded into the binary. Watch XSS sinks
(innerHTML / htm interpolation), CSP-nonce handling
(ironclaw_webui_v2_static/src/router.rs), origin/CSRF checks, and token handling in
client JS.
auto_review:
enabled: true
drafts: false # matches the Copilot ruleset behavior; review starts at ready-for-review
auto_pause_after_reviewed_commits: 0 # never silently pause mid-PR during the trial
base_branches: # main is always reviewed; these are the long-lived extras
- "staging"
- "reborn-integration"
suggested_labels: false # label suggestions are owned by .github/scripts/pr-labeler.sh + actions/labeler
auto_apply_labels: false # labels are owned by .github/scripts/pr-labeler.sh + actions/labeler
tools:
clippy:
enabled: false # CI gates `cargo clippy --all-features -- -D warnings`; re-reporting is noise
github-checks:
enabled: true
timeout_ms: 300000 # required roll-ups aggregate ~15 conditional jobs; default 90s is too short
gitleaks:
enabled: true # no secret scanning in CI — unique fill
trufflehog:
enabled: true
actionlint:
enabled: true # 21 workflows incl. privileged triggers, unlinted today
zizmor:
enabled: true
shellcheck:
enabled: true # scripts/** has no shell linting in CI
hadolint:
enabled: true # 6 hand-written Dockerfiles, unlinted
sqlfluff:
enabled: true # 31 refinery migrations, unlinted
osvScanner:
enabled: false # cargo-deny (PR-time) + Dependabot own dependency advisories
trivy:
enabled: false
markdownlint:
enabled: false # docs are Mintlify-managed; no repo markdownlint config — style nags only
yamllint:
enabled: false # no repo yamllint config; actionlint covers workflow correctness
languagetool:
enabled: false # prose grammar comments are noise here
pre_merge_checks: # advisory (warning) — request_changes_workflow stays false
docstrings:
mode: "off" # quoted deliberately: bare `off` is YAML boolean false
title:
mode: warning
requirements: "Prefer Conventional Commits style (type(scope): summary) — squash-merge makes the PR title the permanent main-branch subject."
description:
mode: warning
issue_assessment:
mode: warning # CONTRIBUTING.md requires an approved issue for new features
# custom_checks are Pro+ — uncomment after confirming the plan tier in the dashboard:
# custom_checks:
# - name: "FEATURE_PARITY same-branch update"
# mode: warning
# instructions: "If the PR changes the implementation status of any capability tracked in FEATURE_PARITY.md (❌/🚧/✅, notes, priorities), FEATURE_PARITY.md must be updated in this same PR (AGENTS.md / CONTRIBUTING.md 'Feature Parity Requirement')."
# - name: "Released migrations are immutable"
# mode: warning
# instructions: "Fail if the PR edits an existing migrations/V*.sql or rewrites a pinned hash in migrations/checksums.lock; released refinery migrations must never be modified."
finishing_touches:
docstrings:
enabled: false
unit_tests:
enabled: false # Pro+; regression-test-check.yml + the codecov patch target own test pressure
simplify:
enabled: false
knowledge_base:
web_search:
enabled: true
learnings:
scope: local # public repo — keep learnings repo-scoped
code_guidelines:
enabled: true
# Defaults already ingest **/AGENTS.md and **/CLAUDE.md (root + the nested crate files).
# Add the review-shaped docs the defaults miss:
filePatterns:
- ".claude/rules/*.md" # error-handling, review-discipline, testing, safety-and-sandbox — the most review-shaped rules in the repo
- "CONTRIBUTING.md" # review tracks A/B/C, issue-first policy, FEATURE_PARITY requirement
- files: "src/tools/README.md" # declared module specs (root CLAUDE.md table) hidden from the defaults by README naming
applyTo: "src/tools/**"
- files: "src/setup/README.md"
applyTo: "src/setup/**"
- files: "src/workspace/README.md"
applyTo: "src/workspace/**"
chat:
auto_reply: true