coding.sgit.ai / what is not enforced

What is not enforced

A coding-standards site that publishes only the numbers that flatter it is not reporting, it is advertising. This page is the other list: what is broken, what is undocumented, what is claimed but unverified, and what this site itself cannot currently do.

1. Nothing is enforced by tooling

No linter. No formatter. No type-checker. No mypy, ruff, flake8, black, isort or tox configuration anywhere in the estate. No pre-commit hook.

Compliance with the documented rules is nonetheless high — 100% on banners, 989/992 = 99.7% on docstrings, 299/302 = 99% on empty __init__.py — and it is achieved entirely by discipline. That is genuinely impressive and it is exactly as fragile as it sounds: it holds while the people and the agents writing the code all happen to know the rules, and it degrades silently the first time one of them does not. The configs that would fix it →

2. One guard has never worked

The four tests/ci/ structural guards are the entire automated enforcement surface. A fifth exists and has never matched anything.

test_no_legacy_imports.py is supposed to fail the build if the new tree ever imports the legacy one. Its regex is sgraph_ai_service_playwright[^_] — and [^_] requires a non-underscore character after the stem, while the real package is sgraph_ai_service_playwright__cli, with two.

# verified by the survey
GUARD regex  : 0 files   -> test PASSES (vacuously)
REAL imports : 69 files, 228 import lines
FIXED regex  : 69 files  -> test FAILS, as intended
             (the fix is deleting four characters)
A guard that passes because it cannot match what it guards against is worse than no guard, because it produces a green tick.

It is the strongest possible argument for the enforcement page, and it is worth being precise about the failure mode: nothing was wrong with the rule. Somebody wrote the rule, wrote the test, watched it go green and moved on. The only defence against that is a test that has been seen to fail. F1, four characters →

3. Two more guards are claimed and not listed

Rule 10 (evaluate is allowlist-gated) is described as having a CI guard behind it. Rule 16 (Step__Executor is the ONLY class that calls page.*) is described as having a CI guard that fails the build if a raw browser.new_context( appears outside Page__Factory. Neither appears in the source's own table of CI guards, which lists five and describes tests/ci/ as the entire enforcement surface.

Either the table is not the whole surface, or two guards are claimed that do not exist. This site cannot resolve it — it does not contain the code — so it publishes the discrepancy and marks both rules ❓ guard claimed, unlisted on the rules page rather than counting them as enforced. Given the guard in section 2, the benefit of the doubt is not free.

4. Four of the five languages have no rules at all

All 31 documented rules are about Python and process. JavaScript, CSS, HTML and Bash have consistent, discoverable conventions and zero written rules, which means they are currently maintained by whoever last read the neighbouring file. Reconstructing them by counting is most of what this site's source documents did. The fourteen conventions that are not rules →

And the rules that do exist live in .claude/CLAUDE.md — an agent instruction file. It is read by every agent session and by no human who has not gone looking for it. There is no human-readable style guide anywhere. That gap is the reason this site exists, which is a slightly uncomfortable thing for this site to be the first to say.

5. The bad numbers

WhatMeasuredStatus
Rule 9 — no _ prefix for private methods895/992 = 91% (97 violations), and universal violation in JavaScript⚠️ documented, violated
Import alignment39%321 of 817 files❌ not a rule at all
One class per file90%187 of 208 sampled⚠️ documented, violated
set -e in shell scripts2 of 5, in three different forms❌ no rule covers it
Semicolons in JavaScript531 statement lines without, 401 with. Two trees disagree❌ no rule covers it
The sp-cli: event namespace23 files carrying legacy namingAn uncounted rename surface, now counted
Design token prefixesThree families for one systemUnresolved — Q3
The em-dash rule“all documents are em-dash-free”248 em-dashes across the 11 markdown documents that state the rule. Not one file has zero⚠️ documented, contradicted by its own source

The last row is the one worth sitting with. It is the cheapest rule on this page to enforce — one grep, one line of CI — it is stated in absolute terms, and it is broken in every single file that states it. A rule nobody enforces does not stay at 99%; it decays to whatever people were going to do anyway, and this is what the bottom of that curve looks like. The count, per file →

6. What this site itself cannot do

The house rule this site was commissioned under is explicit:

Every code example and every count is extracted from the repo at build time, with a path and a commit reference.

This site does not do that, and it is worth saying plainly why and what it does instead. This repository contains the website, not the 217,000 lines it describes. There is no build-time access to the code, so there is nothing to extract from and no commit to reference.

What is in place is the next-strongest thing available:

The gap that remains is freshness, and it is real: these counts will drift from the code, and this site will not know. Closing it means giving the build read access to the estate and re-running the survey as a build step. That is tracked as request R2, and until it is done, every count on this site carries its survey date rather than a claim to be current.

7. The honest tensions

Six of them are set out in full, with the seven open questions that go with them, on the open questions page. The short version: