docs: five INVARIANTS entries and three security comments describe code that does not exist - #466
Merged
Merged
Conversation
…ery mirror ships the wrong ts-rs `.ai/RULES.md` is fanned out to six mirrors. #431 corrected five of them. `CLAUDE.md` — the file Claude Code actually loads every session — got none of it, so the one mirror with the most readers was the one still wrong. Three drifts, each verified against the code before rewriting the doc: - **Design tokens were unusable as written.** `CLAUDE.md` listed `--bg-primary`, `--text-primary`, `--accent-gold`. The real names carry a `--color-` prefix (`src/App.css:8-26`, inside the Tailwind `@theme` block). Anyone following `CLAUDE.md` verbatim produced CSS that silently resolved to nothing. The other five mirrors already had this right; their wording is copied over, light-theme caveat included. - **The 60-line Rust function rule claimed an enforcement that does not exist.** `CLAUDE.md` said "max 60 lines (warning only)". There is no warning — `src-tauri/Cargo.toml:252` sets `too_many_lines = "allow"`, so clippy is silent. It is a convention, and now says so. - **`ts-rs` v10 was wrong in all seven files.** `src-tauri/Cargo.toml:27` pins `ts-rs = { version = "12", features = ["serde-compat"] }`. The version has been wrong in the source of truth and every mirror simultaneously, which is how a fanned-out fact rots without anyone noticing. Also corrects the source-adapter count. Six files said "20+ content source adapters" while listing 20 names; `build_all_sources()` in `src-tauri/src/sources/mod.rs` registers **22** `Box::new` entries — Mastodon and Lemmy were missing from every list. The count is now stated exactly (22) with the roster beside it, so the number checks itself against its own list. `CVE/OSV` is split into `CVE, OSV`: they are two separate adapters, and writing them as one is what made 22 look like 20. `site/src/docs/sources.md` had the same defect on a public page — "20+ source adapters" over a table naming exactly 20. Now 22, with Lemmy under Community and Mastodon under Social & video. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ot exist in the codebase
`.ai/INVARIANTS.md` sits at the top of the authority stack — above WISDOM,
DECISIONS and CLAUDE.md. Seven of its entries were checked against the code
they describe. Five were false and two had drifted. Every one of the false
ones names a constant, enum or threshold with **zero occurrences** in any
`.rs` file, because they were transcribed from `specs/ACE-STONE-TABLET.md`
as if the spec were an implementation report.
- **INV-001** demanded ">85% precision or an alert". No 85% / 0.85 threshold
exists. The floors that actually fail a build are in
`scoring/simulation/reality.rs`: aggregate precision >= 0.70, aggregate
F1 >= 0.40, per-persona noise rejection >= 80%. Entry now states those,
plus the real runtime surface (`calibration_monitor`, composite health
< 0.7, cold-start-silent).
- **INV-023** carried `STATIC_LAYER_WEIGHT` / `ACTIVE_LAYER_WEIGHT` /
`LEARNED_LAYER_WEIGHT` as a CANONICAL code pattern. Zero `.rs` hits. This
is why AD-029's amendment set a constant that never existed to 0.0 — the
behavior it describes shipped correctly in the pipeline, but the invariant
was documenting a mechanism rather than an outcome. Now documents the
outcome, and the real per-item provenance weights `scoring::context`
actually uses.
- **INV-060** declared Soft/Hard/Absolute exclusion tiers at 50%/90%/100%
and called the percentages CANONICAL. `ExclusionStrength` has zero `.rs`
hits. Exclusion is binary: `check_exclusions` matches, `pipeline_v2`
zeroes the score before any scoring work runs. The tiered model is not
merely unbuilt — its selector derived strength from dismissal counts,
which AD-029 retired.
- **INV-041** said "ALL persistent state MUST live in SQLite. No state split
across multiple storage mechanisms." Four subsystems contradict it, one of
which (`settings/manager.rs:74`) calls itself "the authoritative source"
in its own comment. Also the keychain, `data/calibrations/`, and
`data/signal_terminal_token.txt`. Rewritten to scope the rule to corpus
and derived state, enumerate the four exceptions with their reasons, and
state the rule that actually matters: out-of-DB state must be bound to the
data it was derived from. `FAILURE_MODES.md` documented the 2026-08-11
poisoned-calibration incident — the exact consequence of that split —
without ever naming the invariant it violated; the cross-reference now
runs both ways.
- **INV-071** said ">=5 exposures" over a Rust `if total_exposures < 5`
pattern. The gates are SQL and there are three of them, disagreeing:
compute >= 3 (`tracking.rs:37`), read >= 5 (`queries.rs:11`), display > 3
(`interactions.rs:429`). And the explicit-rejection arm sits *ahead* of
all of them with no exposure floor at all, so one explicit dismissal
produces a negative affinity from a single exposure. All four recorded.
- **INV-090** listed warn thresholds TS 350 / RS 600. `check-file-sizes.cjs`
uses ts 300 / tsx 350 / rs 700 — the doc matched neither.
- **INV-032** ("works completely offline") gets a divergence note rather than
a rewrite, because the honest fix is a code change and is not made here:
the use-time SSRF re-validation in `llm.rs:495`/`llm.rs:706` exempts the
literal provider string `"ollama"` and nothing else, so the three other
local servers the app itself probes for and offers in setup — LM Studio
:1234, llama.cpp :8080, Jan :1337 — are rejected as internal addresses.
The detector advertises three configurations that cannot complete a
request.
`specs/ACE-STONE-TABLET.md` is left intact as the historical design record,
with three not-built notes at the exact code blocks the false invariants were
copied from (§1 precision target, §5 ExclusionStrength, §6.1
compute_final_weight) so the next transcription stops at the source.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… does not have Comments are read as specification. These three each promise a guarantee that is not implemented, and all three are in the class where a reader would reasonably stop checking. Behavior is unchanged — only the claims are corrected. **`settings/types.rs` — `cloud_llm_disclosure_accepted`** was documented as "Must be true before cloud providers (Anthropic/OpenAI) can be used." No call site reads it as a precondition; `settings/manager.rs:302` sets it to true at configure-time and nothing consults it afterwards. This is not a regression — INV-031 records the deliberate decision that cloud-LLM consent is informed-disclosure rather than an enforced gate, on the reasoning that it is the user's own key and data with no third-party recipient. But a field comment saying "must be true before X" invites the next author to assume the enforcement exists and to build on it. **`src-tauri/Cargo.toml` — `victauri-plugin`** was described as "a debug-only dependency (stripped from release builds)", so "updates only affect the local dev loop". It is in `[dependencies]`, under no `cfg(debug_assertions)` target table, and `lib.rs:811` registers `VictauriBuilder` unconditionally — five lines below `tauri_plugin_updater`, which *is* `#[cfg(not(debug_assertions))]` gated, showing the pattern was available and not used. The crate ships in the release binary. Any inertness comes from Victauri's own internal gating, which this manifest cannot assert. The practical cost of the old wording: a Victauri advisory would have been triaged as dev-only when it is not. **`osv/sync.rs`** claimed the OSV sync "never sends the user's dependency set anywhere." True of the ZIP-mirror path it sits in — that downloads the whole ecosystem archive and matches locally — but false as a property of OSV sync, which is how the sentence reads in context. `sync_ecosystem` POSTs package names to `OSV_BATCH_URL` in chunks of up to 1000 and is attempted FIRST on every cycle; arriving at the ZIP fallback means the dependency set has already gone to api.osv.dev. For a privacy-first product this is the most consequential of the three: it is the sentence someone would cite when answering "does 4DA tell anyone what I depend on?" Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…nd what I verified Self-correction on the entry I just rewrote, applying the same standard the rewrite was for. "That was false on the day it was written" asserts the state of the code at a commit I never opened. Replaced with what is checkable now: three of the four out-of-DB stores document their own reasoning in the module that implements them, which is the actual evidence that nobody intended the absolute rule. "poisoned scoring for weeks" was a vague duration standing in for dates that `FAILURE_MODES.md` already records precisely — curve fit 2026-06-19, database reset 07-31 removed its training samples, undetected until 08-11. Stated. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
runyourempire
added a commit
that referenced
this pull request
Aug 16, 2026
…nt main, replaces #419) (#469) ## AD-030: retire the "gets sharper every day" promise — rebuilt onto current main Replaces **#419**, which was CONFLICTING, 31 commits behind, with CI dead since 08-11 (self-hosted runner timeouts). Rather than rebase a 46k-line diff dominated by whole-file locale churn, this PR **merges #419's branch onto current `main`** and resolves every conflict in favour of main's newer facts. Net diff: **62 files, +848/−677** (vs #419's +23,646/−22,838). Operator decision on record (2026-08-14): the promise is completely retired, on every surface. Decision record: `.ai/DECISIONS.md` **AD-030** (in this PR). ### What this ships - **New canonical line** on every copy surface: *"4DA reads the internet for developers — privately, locally. Your codebase decides what's relevant."* — README, site (title/meta/OG/JSON-LD/hero/FAQ), docs, scan page, streets module, writing footers, installer metadata (`tauri.conf.json`), mcp README, RELEASE-NOTES. - **"Yesterday's noise becomes tomorrow's signal" KEPT** — re-attributed to corpus re-judging (verdict epochs), never to engagement. - **13 locales, surgically**: #419's translations ported **per-leaf** onto main's current files — 312 rewordings + 130 deletions of dead affinity-surface keys. Its 752 key *additions* were dropped: they belong to surfaces #421 already deleted from `en` (momentum, wisdom, comparison, toolkit…), and porting them would have resurrected orphans. `validate-translations`: 0 errors, warnings identical to main. - **v19.1 hotfix**: auto-detected `anti_topics` removed from both `build_negative_stack` call sites — the last structurally-live behavioral scoring path. No `PIPELINE_VERSION` bump; justification (live probe: `anti_topics` = 0 rows → byte-identical priors) recorded at the constant. - **Enforcement gate**: `scripts/check-retired-claims.cjs` + 9 tests. Violations on main measured before: **57 across 24 files**; after this PR: **2, both in CLAUDE.md** (see residuals). - **Public handling**: `site/src/writing/retiring-a-claim-we-could-not-measure.njk` — the engineering record, now linked from /writing and the sitemap. Site builds clean (11ty, 127 files). ### Conflict-resolution calls worth reviewing - Kept main's newer copy where it was already promise-free and more current: the 93%/98.9%/245-item benchmark (#460), Precision Ledger references, BYOK never-paywalled rationale. - **Fixed 3 fact regressions #419 would have reintroduced**: stale 92%/98%/215 benchmark figures (2 files) and a RELEASE-NOTES tier table listing Developer DNA / Signal Chains / Score Autopsy as paid (they are free per AD-025/026). - `apply-translations.cjs`, `missing-keys.json`, `BadgeRow.tsx` stay deleted (deleted on main since #419's base). ### Residuals (tracked in `.claude/plans/PENDING-DECISION.md`) 1. **`CLAUDE.md` tagline + `package.json` gate wiring** — both files are claimed by live peer lanes (#466; agent-a875). A follow-up commit on this branch lands the moment the claims release. Until then the gate exists but is not yet wired into `validate`, so CI on this PR does not self-fail on CLAUDE.md. 2. **npm README** — `@4da/mcp-server` live README still serves the old table; needs a republish (different terminal, tag `mcp-v5.0.0`). 3. **Live 4da.ai** — CF Pages is direct-upload; needs `wrangler pages deploy --branch main` after merge. 4. **Close #419** after this merges. ### Verification - Frontend: **1249/1249** pass, `tsc --noEmit` clean, ESLint clean, i18n types regenerate in sync. - Rust: `cargo check --lib` clean; targeted tests (negative_stack / context / blind_spots) green. - Gate self-test: 9/9; full-tree scan = only the 2 deferred CLAUDE.md hits. - Site: eleventy build clean, post renders. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
runyourempire
added a commit
that referenced
this pull request
Aug 16, 2026
…ne (#472) The last 2 retired-claim violations in the repo, deferred from #469 because CLAUDE.md was claimed by the #466 lane (now merged, worktree reaped). With this, `node scripts/check-retired-claims.cjs` reports **zero violations repo-wide**. Remaining enforcement residual: wiring the gate into `validate`/`test:scripts` waits on the live lane holding `package.json`. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
runyourempire
added a commit
that referenced
this pull request
Aug 16, 2026
runyourempire
added a commit
that referenced
this pull request
Aug 16, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes the documentation-truth findings from the forensic audit that were verified still open at
f26da1ea. Every change makes a document match the code; where the code is the problem, this PR records the divergence rather than pretending it away.CLAUDE.mdnever received #431's drift correction#431 corrected five of the six agent-instruction mirrors.
CLAUDE.md— the propagation root — got none of it, so the file every session loads first has been the wrong one.CLAUDE.mdlisted--bg-primary,--text-primary,--accent-gold. The real names are--color--prefixed (src/App.css:8-26). An agent following the doc verbatim produced CSS that silently did nothing. Verified independently:--color-bg-primaryatApp.css:8, and a light theme at:49+overrides the same token names, so the added "never hard-code a hex" note is load-bearing rather than decorative.src-tauri/Cargo.toml:252explicitly setstoo_many_lines = "allow". Now stated as a convention.ts-rswas wrong in all seven files, not justCLAUDE.md— every one said v10;src-tauri/Cargo.toml:27pins"12".build_all_sources()registers 22 (counted: 22Box::newentries). Mastodon and Lemmy were missing from every list, andCVE/OSVwas written as one entry when it is two — which is exactly how 22 came to read as 20.Five INVARIANTS entries describe mechanisms that do not exist
Verified by repo-wide grep. Each is now either corrected to what the code does or retired with its reason.
scoring/simulation/reality.rs)STATIC_/ACTIVE_/LEARNED_LAYER_WEIGHT.rshits. Also still stale inspecs/ACE-STONE-TABLET.mdsettings.json, the OS keychain,data/calibrations/,data/signal_terminal_token.txtExclusionStrengthenum, "percentages are CANONICAL".rshits.ai/FAILURE_MODES.mddocumented the 2026-08-11 poisoned-curve incident as caused by state living outside SQLite without naming the invariant that forbids it. That cross-reference is now there.INV-071 turned out to be three disagreeing gates, not one wrong number: compute uses
>= 3(ace/behavior/tracking.rs:37), read defaults to>= 5(ace/behavior/queries.rs:11-12), display uses> 3(ace_commands/interactions.rs:429) — and the explicit-rejection arm sits ahead of all three with no exposure floor at all, so a single dismissal of a never-engaged topic yields a negative affinity from one exposure. All four are recorded. The code is unchanged; this needs a decision, not a doc edit.Three in-code comments assert security properties the code does not have
Comments only — zero behaviour change. False security comments are worse than none, because they stop the next reader from checking.
settings/types.rs— "Must be true before cloud providers can be used." No call site gates oncloud_llm_disclosure_accepted. INV-031 now says explicitly that consent is informed-disclosure, not an enforced gate; the comment now agrees.src-tauri/Cargo.toml— "debug-only dependency, stripped from release builds" aboutvictauri-plugin, which sits in[dependencies], not[dev-dependencies], under nocfg(debug_assertions)table. True only via the crate's own internal gating, which is now what it says.src-tauri/src/osv/sync.rs— "it never sends the user's dependency set anywhere." True of the ZIP-mirror fallback only.sync_ecosystemPOSTs the user's package names toOSV_BATCH_URL(up to 1000/request) and is attempted first on every cycle, so reaching that branch means disclosure already happened.Two things this PR deliberately does not do
AD-030 is out of scope. PR #419 already contains the AD-030 entry,
scripts/check-retired-claims.cjs, and the promise removal across 67 files. This PR touches none of it —CLAUDE.mdedits here are confined to lines 46+ and do not go near the tagline. A trial merge against #419 is conflict-free.specs/ACE-STONE-TABLET.mdgets not-built notes at the three blocks the false invariants were transcribed from, but is otherwise left intact as the historical design record rather than rewritten.Something that needs settling
.ai/RULES.md's own header says it is "Generated fromCLAUDE.md— the maintained source of truth", and explainssync-ai-rules.shwas deleted because it ran the other way and would clobberCLAUDE.md. That is the opposite of how the mirror set is usually described. All seven files are now consistent either way, so nothing is blocked — but one of those two statements is wrong and someone should decide which.Still open, for #419
src/locales/en/ui.jsonfirstRun.scanningDescriptionstill says "20 sources", as do all 12 other locales. Left alone because #419 owns the locale pass; fold 20→22 into it.🤖 Generated with Claude Code
https://claude.ai/code/session_01Fq96xWyPQjx2bCCzWtsnC9