Skip to content

docs: four checks that make doc drift a build error, and the ~60 claims they found - #119

Merged
sebyx07 merged 2 commits into
mainfrom
docs/drift-and-doc-gates
Aug 17, 2026
Merged

sebyx07 merged 2 commits into
mainfrom
docs/drift-and-doc-gates

Conversation

@sebyx07

@sebyx07 sebyx07 commented Aug 17, 2026 •

Copy link
Copy Markdown
Contributor

Slice 13 — the last one. Four agents on disjoint directories in one checkout.

The corrections are not the deliverable; the four checks are. The slice document says so in its
own words — "that enforcement gap is the slice's real deliverable" — because this repo has
corrected these same pages before and they drifted again. Twelve new X_* codes, four new gate
rules, and the ~60 stale claims they found on the way in.

The old rule judged the command name and nothing below it

checkErrorFixes resolved a cited x <command> against the registry — and stopped there. So every
one of these passed the gate:

Cited Where What is actually wrong
x test summarize a shipped fix: line summarize is not a TestType
x env check --fix wiki/Installation.md no such flag — it dies at the parser with X_CLI_BAD_FLAG
x jobs retry --from two docs/architecture/ pages the flag is --from-step, and packages/cli/README.md already spelled it right
x db query, x entity explain wiki/Error-Codes.md wrong subcommand; wrong command (x entities describe)
x i18n add <key> docs/architecture/10-cross-cutting.md the subcommand exists and takes a locale

The resolver now works four levels down — command → planned → subcommand/positional → flag.
CommandSpec.positionalChoices is declarative and x test reads it from TEST_TYPES, the same
constant the runtime validates against, so the two cannot drift.

The flag half ships enforcing, with a number: 386 flag citations across wiki/ and docs/, 23
flagged, 0 false positives after skipping planned commands. A sibling agent measured a similar
rule at 21 flagged / 20 false positives earlier in this audit and correctly refused to ship it —
this one met the bar.

Four checks

Check Scope State
doc-fixes every Fix cell of wiki/Error-Codes.md 403 cells, enforcing
doc-commands every `x …` in prose across wiki/ and docs/ 95 pages, enforcing
readme-fences every ts/tsx fence in a package README 170 fences, 155 pinned on a ratchet
version-stamps one page states the version; 29 workspaces must agree enforcing

readme-fences ships pinned deliberately. The slice framed it as catching three READMEs; it is 28
of 29 READMEs and ~170 fences, most of them illustrative fragments. A ratchet that only lowers means
a new broken example fails from day one while the existing 155 retire over time — a real edge,
honest about what it does not yet cover.

Two things it had to get right, both measured rather than assumed:

  • tsc reports no semantic diagnostics at all once a program holds one syntax error. Verified
    directly: a fixture with const a: number = 'x' beside one unparseable fence reports the fence
    and says nothing about the assignment. A single-pass check would have gone silently green across
    all 27 packages the first time a README gained an elided …. Hence two passes.
  • The base tsconfig's exclude: ["node_modules"] silences the whole fixture if inherited
    (TS18003: No inputs were found) — the exact fail-open a reviewer caught in three of four checks
    built earlier this month. A tsc that refuses to run is X_README_EXAMPLE_UNSCANNED, never a pass.

Every one of the four fails on a missing or unreadable input, and each has a test that proves it.

23 stamps became one

23 wiki pages carried v1.1.0 \As of 2026-08`while the tree was at 1.2.0. **Not find-and-replaced to 1.2.0** —[Unreleased]carries **30BREAKING —` entries**, so the next cut is a major and all
23 would have been wrong again in one release. 23 hand-copies of one fact is what axioms 1 and 2
forbid.

_Footer.md renders on every wiki page, so it is the one page that states the version; the other 22
keep their date. The check enforces the sentence the footer now makes, and asserts the lockstep
itself — a documented rule (CHANGELOG.md, root CLAUDE.md) that nothing verified, and a repo that
has already once cut nine tags with no version bump at all.

Versioning is lockstep; publication is not — @ultimat3/flags has never been published. The
check asserts the version invariant only; the registry needs a network call and the gate runs offline.

Premises falsified

  • packages/action/README.md was right and the code is wrong. One action is reachable under
    publishPost on the wire (packages/mcp/src/from-action.ts:74 — the only name tools/call
    accepts) while openapi.json and x.manifest.json both publish publish_post. The
    published contract advertises a name nothing serves.
    Not unified here: it is BREAKING, changes
    both tracked apps' committed openapi.json, and re-pins nine test files. Recorded as a dated
    known defect at the README so no agent copies it as design, and filed for its own PR.
  • packages/ai/src/eval-errors.ts does not cite x test summarize — it reads
    x test eval --filter … with a comment explaining why. The convention was being held by
    memory
    ; positionalChoices makes it a build error. Only the README still printed the bad form.
  • createPgLeader exists (driver-pg.ts:383), contrary to the report that it does not. The
    defect was that scheduler.ts:42 recommended it — the session-scoped one whose grant dies with
    the pooled connection — instead of createPgLeaseLeader. Eleven files described scheduler
    leader election as an advisory lock, one with a SELECT pg_try_advisory_lock(...) block.
  • Most of the slice's High table was already fixed in-flight by the eighteen PRs that merged
    since it was written — x db status, x live explain, x db drift, x jobs run,
    x build --helm, x cache purge and more. Each verified and dropped. The checks would have
    caught every one.
  • The scaffold count is 115 / 91, measured — not the 99/76 the wiki said and not the 112/88 the
    slice document claimed
    . Both derivations now sit next to the number.
  • docker/README.md's two rows were already correct — the healthz claim was fixed and the
    dependency stage really is lockfile-only now (a manifests stage strips the rest). Dropped.
  • x env check was documented as planned and ships — a working diagnostic every X_ENV_MISSING
    fix points at, documented as unavailable.

The escape hatches were fiction

docs/architecture/02-boundaries.md documented two boundary escape hatches — boundaries.allow and
a // boundary-allow: comment with a 90-day expiry — with zero implementation anywhere. Deleted,
pointing at guards/, which is the real, discovered, tested mechanism an app writes its own rules
with. A second escape hatch would be axiom 1 broken. The same page named schema → core as the
sideways exception; SIDEWAYS_ALLOW has no such entry and packages/schema/src/errors.ts says
outright that schema may not import core.

Conventions documented as rules that nothing enforced

Each is now labelled rather than asserted, per axiom 3: hardcoded-string, raw-hex,
date-no-tz, money-as-number (no Biome rule, no gate step), cached-query tagging, idempotency-key
determinism, og.image and broken-link checks, SW checksum and strategy coherence, the 50-char
description minimum (DESCRIPTION_MIN_LENGTH is exported and read by nothing). Eighteen phantom
X_* codes across the docs were replaced with the codes that really throw.

Also fixed

packages/admin/src/dev/server.ts:185 shipped fix: x dev --panel <key>, and x dev declares
port, role and once. It was failing error-contract.test.ts at the moment this branch
opened
— found by a check in this PR, in a package no agent in the wave owned.

Gate

bun run verify — 14 of 17, 3 skipped. bun run scripts/reference-app-gate.ts — every pin holds,
examples/dummy 11/17, dummy/social-media-clone 15/17. Manifest at 417 codes.


View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

…ms they found

The last slice of the audit. Its stated deliverable was never the corrections —
it was the enforcement, because a corrected doc drifts again.

Four new gate rules, 12 new X_* codes:

- doc-fixes    every Fix cell of wiki/Error-Codes.md must be runnable (403 cells)
- doc-commands every `x …` in wiki/ and docs/ must resolve — command, subcommand,
               positional AND flag (95 pages, 386 flag citations, 0 false positives)
- readme-fences every ts/tsx fence in a package README must compile (170 fences,
               155 pinned on a ratchet that only lowers)
- version-stamps one page states the version, and the 29 workspaces must agree

The flag half is what matters: the old resolver judged only the command name, so
`x env check --fix`, `x jobs retry --from` and `x test summarize` all passed while
none of them runs. `x test summarize` was a shipped fix: line.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBwWKBJkiogA4mDaJiJf3D
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Caution

Review failed

An error occurred during the review process. Please try again later.


Comment @coderabbitai help to get the list of available commands.

…issues filed

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBwWKBJkiogA4mDaJiJf3D
@sebyx07

sebyx07 commented Aug 17, 2026

Copy link
Copy Markdown
Contributor Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Aug 17, 2026 •

Copy link
Copy Markdown
❌ Action failed

Review failed.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@sebyx07
sebyx07 merged commit f100d3e into main Aug 17, 2026
4 checks passed
@sebyx07
sebyx07 deleted the docs/drift-and-doc-gates branch August 17, 2026 16:02
sebyx07 added a commit that referenced this pull request Aug 17, 2026
…he wrong thing (#131)

* fix(cli,money)!: two shipped fix: lines that resolved and still did the wrong thing

Both passed #119's new doc checks, because the checks verify an invocation PARSES,
not that it does what its sentence says. That gap is the whole of this change.

`x branch` is planned, and its fix: line read `x db branch ls --json`. But `cmd-db.ts`
fell through — any unrecognised subcommand became a branch NAME — so an agent following
the fix verbatim CREATED a database called `<source>_branch_ls` instead of listing one.
`x db branch` now takes a verb from a closed set: `ls | create <name> | drop <name>`.
Verb-first is the only shape where a name cannot be read as a subcommand, and every one
of those three verbs is itself a legal branch name.

The repo already documented that surface and contradicted itself about it: four shipped
`fix:` lines in `@ultimat3/db`'s own registry, its README and a test all spelled
`x db branch create|drop <name>` for commands that did not exist, while the wiki said in
so many words that no such subcommands existed.

External create no longer shells out to `psql`. Forced by `ls`: branches are found by the
`comment on database` marker `createBranch` writes, and the psql path wrote the database
and no comment — so `x db branch ls` would have reported "no branches" over branches the
CLI itself made.

The `money` fix: line named a seam that did not exist — "add yours in `app.config.ts`",
where there is no currency field and no registration function. `@ultimat3/money` now
exports `registerCurrency()`. The decisive argument was not that a closed table is
unfriendly; it is that THREE layers already treated the set as open — `moneySchema`'s
`^[A-Z]{3}$`, entity's Postgres CHECK, and the PUBLISHED OpenAPI `pattern`. An app could
already accept `GHS` over HTTP, validate it, store it and read it back, and only money's
arithmetic refused it. That is one package disagreeing with the boundary, the storage
layer and the contract.

Consolidating that bound turned up five copies of `^[A-Z]{3}$`, not the two we knew about
— including the hardcoded one in the published contract. It is now one tier-0 declaration
(`CURRENCY_CODE_PATTERN` + `isCurrencyCode`), with the Postgres CHECK interpolating the
same constant. A live test applies the emitted CHECK to a real Postgres and asserts it
accepts exactly what the predicate accepts, SQLSTATE 23514, so a DDL typo that refuses
everything cannot read as agreement. Two copies remain by necessity: core is tier 0
alongside schema and may not import it, so it keeps a documented duplicate with its own
corpus test, plus a cross-package pin in `cli`, which may import both.

Three further defects found on the way, each the same class:

- `production` was hardcoded `false` in the only producer of a `DatabaseTarget`, so
  `assertBranchDatabase`'s "production is never migratable from MCP" arm was DEAD for
  every database the CLI makes. A production `DATABASE_URL` ending `/shop_branch_hotfix`
  read as a branch and was migratable through an MCP tool call. It now reads core's env
  exactly as `x doctor` does, and fails CLOSED on a malformed `ULTIMATE_ENV`.
- `scanFixes` only ever saw a `fix:` PROPERTY, so a fix passed positionally into a local
  helper was invisible to the gate — 22 such helpers across 8 packages, 13 files declaring
  codes and yielding zero readable fixes. That is why the two stale mcp lines survived.
  Now read under four measured rules: 16 files gained fixes, 0 new findings.
- `MissingSubcommandError`'s own fix: was `x db --help`, which throws
  `MissingSubcommandError` again — a fix line that reproduced its own failure forever.

BREAKING: `x db branch <name>` is gone; use `create`. `branchSql` is removed from
`@ultimat3/cli`.

Fixes #122

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBwWKBJkiogA4mDaJiJf3D

* fix(http): an unregistered currency over HTTP answered 500 and paged the on-call

Found by the gate, not by reading: adding `registerCurrency`'s two refusals made the
`errors` step demand a status for them, and checking whether they could reach a request
turned up a third code that already could.

`X_CURRENCY_UNKNOWN` had no row in `packages/http/src/error-map.ts`, so it took
DEFAULT_STATUS — and `stages.ts` reports every `status >= 500` to the error monitor. It
is 400 now, beside `X_LOCALE_UNSUPPORTED`.

It was never theoretical, and this branch is what makes it undeniable: every surface
between the wire and the throw accepts any `^[A-Z]{3}$` — schema's `CURRENCY_CODE_PATTERN`,
the OpenAPI `pattern` emitted from it, and entity's `char(3)` CHECK. So `{"minor":100,
"currency":"ZWL"}` parsed, validated, reached `assertCurrency`, and the caller was told the
server had broken over a code the framework's own schema had just accepted.

Deleting the row fails 3 of the 4 new tests — including the one that asserts the monitor
records nothing, which comes back with 37 lines where `[]` was expected.

The two NEW codes go to the backlog instead, with the argument written down rather than
implied: `registerCurrency` is their only thrower, it is a boot-time module-scope registry
like `registerRoute`, and its `REGISTERED` map is per process while the chart runs three
web replicas — so a request-driven registration is broken on the second replica before a
status could describe it. Every comparable registry refusal in the repo is pinned the same
way, and the one counter-precedent applies to all 228 pins equally, so it does not
distinguish these.

Also: both `packages/money/README.md` fences were missing their import line and did not
compile. Fixing the pre-existing one as well let the ratchet FALL — money leaves
`readme-fences-backlog.ts` entirely, so any future breakage there is a build error.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBwWKBJkiogA4mDaJiJf3D

* fix: review findings — a drop that could delete a database we never created

CodeRabbit raised 17 on this PR. Six were Major; several were real, two were wrong,
and one was right about the severity while wrong about the mechanism.

The worst: `x db branch drop <name>` could `DROP DATABASE` one that carries no marker at
all — a database this framework never made. `listBranches()` filters on the marker and the
marker records a timestamp, never the source, so on a server hosting two Ultimate apps
`analytics_branch_feat` reduced to `feat` for a session on `postly` and SATISFIED THE
GUARD. The reviewer read that as dropping the other app's database; it is not — the target
is always derived from the connected source — but the foreign row authorised a drop of an
unmarked `postly_branch_feat` belonging to someone else. Fixture reproduces it: before the
fix the command returned success having dropped it. `ls` and `drop` now require the
marker AND this source's prefix, and the check moved inside the deleting function on the
same connection, one statement before the DROP.

Seven `fix:` lines in @ultimat3/money emitted UNPARSABLE JavaScript for legal input — a
currency named `O'Reilly` produced `fromDecimal('1.5', 'O'Reilly')`. `error-render` passed
them because the values are typed `string`, not `unknown` (issue #97's exact gap). There
was a second route with no quote involved: `fromDecimal` trims before parsing but hands the
untrimmed value to the error, so a trailing newline broke the line and the 3-line render.
Where the value has a known shape it is now GATED, not escaped — escaping alone yields a
parsable `assertCurrency("O'Reilly")` that throws the same error when pasted, and this file
already said an instruction that raises the error it answers is not an instruction.

`bodyOf` in ts-scan took the next `{` anywhere after an expression-bodied arrow, so a later
object with a `code:` key could classify a non-error helper as an error builder and reject
valid source. Latent, not firing — measured 857 fix sites before and after, none lost.

Two rejections, both with evidence. "Put the retry guidance in a separate field" — there is
no fourth field on UltimateError, and inventing one is a convention with no build error
behind it; the real defect was the joiner, since `ARGUMENT_END` makes `#` terminate the
scan and 64 shipped lines use it against 9 comma-joined. "`<name>` is wrong" — the
placeholder rule matches the third slot only, where a closed verb set makes substitution
impossible; a branch name is caller-chosen and `packages/db` ships `<branch>` there.

And the reviewer had the advisory-lock finding backwards: Error-Codes.md was RIGHT and six
other pages were wrong. `X_MIGRATE_CONCURRENT` is thrown — one `pg_try_advisory_lock` per
500ms against a 60s budget. "Reserved, never thrown" was true of 1.2.0 and became false
when #98 merged, which `git merge-base --is-ancestor` confirms is not an ancestor of the
tag. Ten pages now say one thing.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01RBwWKBJkiogA4mDaJiJf3D

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant