# Audit a written rule before you enforce it

[Journal](/journal/)

August 7, 2026 · [guides](/journal/#guides)



A read-only lint audit separated enforceable Mobile rules from false positives and checks that still need review.

![Six abstract rule cards pass through a selector gate into three accepted routes, one narrowed route, and a two-card review tray.](/_astro/audit-a-written-rule-before-you-enforce-it.D_6Tacqz_Xg950.avif)

A written rule is only a hypothesis about enforceable syntax. Our Muniment Mobile audit tested six candidates before CI could turn misunderstandings into blockers.

## Written policy left 28 rules with reviewers

One React Native repository kept 34 written house rules. CI enforced six through ESLint and three copy and structure scripts. Review carried the other 28.

We translated six candidate rules into esquery selectors. Each selector ran through `no-restricted-syntax` as a read-only audit, so no result blocked a change.

That dry run tested both sides of each rule. A zero count needed scrutiny, and every hit needed context.

| Candidate rule | Audit result | Decision |
| --- | --- | --- |
| `FlatList` sets three rendering controls | Seven components, zero hits | Adopt as written |
| A disabled control exposes its accessibility state | One hit, false positive | Narrow the scope |
| A labeled `View` sets `accessible` | Four reviewed exemptions | Leave to review |
| `Modal` sets `onRequestClose` | Zero hits | Adopt as written |
| `TextInput` has an accessibility label | Zero hits | Adopt as written |
| `ScrollView` sets `keyboardShouldPersistTaps` | Fifteen components | Leave to review |

## A hit can indict the selector

All seven `FlatList` components set `initialNumToRender`, `maxToRenderPerBatch`, and `windowSize`. Their selector returned zero hits.

One control set `disabled` without `accessibilityState`. That hit was a false positive.

The code passed `disabled` to a repository component. That component set the accessibility flag on the native control.

Scoping the selector to native control names returned zero hits. One written rule survived, but its first selector did not.

Four `View` components set `accessibilityLabel` without `accessible`. Every hit matched a reviewed exemption because each view holds a control.

Syntax alone cannot distinguish that composition safely. Review keeps the context that the selector lacks.

## Context decides what CI can own

The `Modal` selector found zero components missing `onRequestClose`. Its `TextInput` counterpart found zero components missing `accessibilityLabel`.

Fifteen `ScrollView` components lacked `keyboardShouldPersistTaps`. That rule applies only when a scroll view sits above a keyboard.

The audit made three rules adoptable as written. One needed a narrower scope, and two stayed review checks.

## The audit has three limits

A zero count does not prove that the selector matches the written rule. It may prove only that the selector found nothing.

A hit is not automatically a defect. It can expose an exemption, an abstraction boundary, or a selector that reaches too far.

Syntax cannot supply runtime context. Component behavior, composition, and screen state can decide whether a pattern violates the rule.

Visitors cannot exercise Muniment Mobile through a public install or authentication surface yet.

This evidence comes from our Muniment Mobile note pinned to commit `b5d1a0bdfd5fc6460bbb1f374372f2c35fdd1920`.

Run a candidate rule in read-only mode first. Inspect every hit and several expected non-hits before that selector gets authority over CI.
