11.03 — Explicit refusals#

Synthesis of refusals scattered across the Holy Book.

Summary table#

RefusalReasonReference
async/awaitSelenium synchronous, Requests synchronous; readability; no point introducing an event-loopHoly Book
pytest pluginIndependence, ISTQB fidelityOcarina README
Text DSL (Robot, Gherkin)No translation layerHoly Book
Reactive programmingStatic scenarios, in-memory cache sufficesHoly Book
Tricks and hacksTeach the pattern, not the symptomCLAUDE.md ai-example
Stylish” contributionsIt’s my carHoly Book
Active security testsFunctional and static only, never attacksCLAUDE.md ai-example

1. Refusal of async/await#

Central quote:

Ocarina doesn’t support async/await and never will.

ArgumentResponse
It’s fasterNot for Selenium (synchronous by nature)
Everyone does itEveryone often does it badly
For HTTP APIsrequests (synchronous) works just fine
For locksthreading.Lock + redis.lock are enough
For parallelizationThreadPoolExecutor (see ../02-ocarina/05-orchestration/04-test-suite.md)

2. Refusal to be a pytest plugin#

Ocarina’s README:

Ships its own test runner: Ocarina is NOT a pytest plugin.

With pytest pluginStandalone runner
pytest vocabulary (function, fixture, parametrize)ISTQB vocabulary (test, suite, campaign, cycle)
Lifecycle depends on pytestOwn controllable lifecycle
Compatibility with other pytest pluginsNo API surface to maintain
Discoverable via pytest --collectDirect python -u src/main.py

See ../01-philosophy/02-istqb-vs-pytest.md

3. Refusal of text DSLs#

No .robot, .feature, .spec.yml files. Everything is Python.

Quote (Holy Book what-is-it):

Robot Framework tried to dodge that with a DSL (…) their own format and their own plugin ecosystem. So RF de-facto imposes its own standards: that’s the immediate cost of its promise.

Text DSLEmbedded Python DSL
Translation layer (parser, alternative runtime)None: it’s just Python
Hard refactoring (search in .robot)Trivial refactoring (Python IDE)
Impossible / partial type checkingFull type checking (mypy strict)
Proprietary tooling (PyCharm RF plugin, RIDE, etc.)Any Python editor

See ../01-philosophy/01-flip-the-problem.md

4. Refusal of reactive programming#

Holy Book (chapter “First jutsus”, “Reactive programming: NO” section):

Ocarina test scenarios are intentionally static. Yet a web application is dynamic, and sometimes capturing a value on the fly to pass it to a later step is perfectly legitimate.

Ocarina doesn’t answer that. It doesn’t need to.

Answer: in-memory cache + reserved keys (see ../07-ocarina-example/08-caches-locks.md)

With reactivityWithout (cache)
Scenarios full of streams and subscriptionsReadable declarative scenarios
Hard debugging (event flow)Trivial debugging (sequential calls)
Subtle concurrency hazardsSimple threading.Lock
Dependencies on RxPY or similarNo reactive dep

5. Refusal of “geek tricks#

CLAUDE.md ocarina-with-ai-example:

No tricks or hacks. JS-clicks to skip hit-testing, # noqa to silence a rule, time.sleep to mask a race, driver.implicitly_wait to patch a timing bug. If a hack is genuinely the only option, document why no clean fix exists and mark it so a reader doesn’t copy the pattern. The JS-click-for-logout incident is the canonical anti-example: ElementClickInterceptedException had a clean polling fix; the JS click hid the problem.

HackWhy it’s NO
driver.execute_script("...click()") to bypass hit-testingHides a real UI defect; a human user couldn’t have clicked
# noqa without justificationHides a real style/security violation
time.sleep(N) to mask a race conditionMysterious timing” nonsense
driver.implicitly_wait(N) patched outside the frameworkDecouples from the CLI --wait-timeout config
delete_all_cookies() to “reset stateA user doesn’t do this; hides a real session bug
driver.refresh() to bypass cacheA user doesn’t do this; hides a real bug
Query-string cache busters (?_=<ts>)Same

If a hack is really necessary: document why.

6. Refusal of “stylish” contributions#

Holy Book (chapter “First feedbacks”, “Incorruptibles” section):

Handing over Ocarina means handing over a car I’ve maintained entirely myself, for myself, hence very carefully. That said, it is and will remain handed over as-is. It’s my car.

And:

Contributing to an open-source project because it’s “stylish” is a totally immature view, and tolerance for this phenomenon causes havoc.

Contribution acceptance criterion: alignment with the direction. Not “does it work” but “does it respect the project’s philosophy?”.

The author quotes DHH:

My response will be supplemented with a David Heinemeier Hansson (DHH) quote: “Fuck You”.

Fuck you

7. Refusal of active/offensive security tests#

CLAUDE.md ocarina-with-ai-example:

This is a functional test suite. (…) Inside that scope:

  • Static analysis is welcome and encouraged.
  • Functional tests that exercise security-relevant behaviour through the normal UI/HTTP path (…) are fine.

Forbidden, no exceptions:

  • Crafted attack payloads of any kind: SQL injection strings, XSS / HTML / JS payloads, command injection, header/parameter pollution, path traversal, deserialisation payloads.
  • Token tampering, signature stripping, cookie forgery, session-fixation attempts, forced-browsing fuzzers.
  • Cross-origin POSTs constructed outside the suite, scripted directory enumeration, DOS, rate-floods — anything that escalates from “use the app like a user” to “attack the app like an adversary”.

Strict limit: use the app like a user, don’t attack it like an adversary.

Active testing is a different project (Burp, ZAP, sqlmap, a separate contract and dedicated scope).

Why#

Every refusal recenters the project:

RefusalSimplification
No asyncReadable synchronous code
No pytest pluginNo incomprehensible pytest API to learn
No text DSLNo parser to maintain
No reactivitySimple cache suffices
No hacksExpressive code
No “stylish” contributionsCoherent direction
No active security testsRespect for the functional perimeter

Saying no is also design. Cf. Steve Jobs: “Innovation is saying no to 1,000 things.

Refusal of growth without benefit#

None of these refusals is dogmatic. Each is justified by an explicit trade-off:

Hypothetical benefit: X
Operational cost: Y
Verdict: not worth it

If a new use case justifies reconsidering a refusal, the author will. But the burden of proof is on the proposer.

That’s the practical embodiment of sovereignty.