Skip to content

fix(ad-030): retire the promise from the six agent-instruction mirrors - #431

Merged
runyourempire merged 1 commit into
mainfrom
fix/ad030-agent-mirrors
Aug 14, 2026
Merged

fix(ad-030): retire the promise from the six agent-instruction mirrors#431
runyourempire merged 1 commit into
mainfrom
fix/ad030-agent-mirrors

Conversation

@runyourempire

Copy link
Copy Markdown
Collaborator

Completes AD-030 on the surfaces #419 does not reach. Blocks a failure in #419 itself.

Why this is needed

#419 ships scripts/check-retired-claims.cjs, wired into test:scripts and validate, which bans gets sharper every day, learns from how you engage, compound intelligence, behavioural learning and friends.

I extracted that gate from #419 and ran its real logic against main: 61 violations, four of them in files #419 does not touch.

File Line Violation
.ai/RULES.md 15 canonical one-liner
AGENTS.md 5, 7 one-liner + the engagement beat
CONVENTIONS.md 9 canonical one-liner
CHANGELOG.md 14 "Behavioral learning demoted…"

Left alone, #419 fails its own gate the moment it rebases onto main.

These are my regression: they were absent at #419's merge-base, and #421 rewrote all six mirrors, syncing them to CLAUDE.md's then-current line — which was the retired promise.

What changed

The six agent-instruction mirrors of CLAUDE.md.ai/RULES.md, AGENTS.md, CONVENTIONS.md, .clinerules, .windsurfrules, .cursor/rules/project.mdc — now carry the new line copied verbatim from #419's CLAUDE.md, so they cannot drift from the source of truth. They feed Cline, Windsurf, Cursor, Codex and Aider; stale copies re-teach the retired claim to every other agent working this repo.

.clinerules, .windsurfrules and .cursor/rules/project.mdc are not scanned by the gate (no matching file extension), so they are not CI-blocking — fixed anyway, because the point is the claim, not the gate.

CHANGELOG.md gets the retired-ok: escape hatch instead of a reword. That entry is release history naming the mechanism that was demoted; rewriting it would falsify the record. The hatch exists for exactly this.

"Yesterday's noise becomes tomorrow's signal" is deliberately kept. #419 retains it in the new reserved beat, re-attributed to engine updates re-judging the corpus rather than to user engagement, and explicitly exempts it from the banned patterns. It is not a leftover.

Verification

Note for #419

The gate will also want a look at src/types/i18n-resources.d.ts — except it does not, because that file is gitignored and untracked. Confirmed, no action needed. Nothing else outside your file set violates.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WJ6BP3GX5HYrnjW1nGtrvC

AD-030 retires "gets sharper every day" and "it learns from how you engage
with what it shows you" on every surface, enforced by #419's new
scripts/check-retired-claims.cjs. #419 updates CLAUDE.md but not its six
mirrors — and #421 (mine) rewrote all six, reintroducing the retired line
into main after it was absent at #419's merge-base.

Running #419's gate logic against main: 61 violations, four of them in
files #419 does not touch — .ai/RULES.md, AGENTS.md, CONVENTIONS.md and
CHANGELOG.md. Left alone, #419 fails its own gate the moment it rebases.

Wording is copied verbatim from #419's CLAUDE.md so the mirrors cannot
drift: relevance is attributed to the user's codebase, and improvement to
engine updates re-judging the corpus. "Yesterday's noise becomes tomorrow's
signal" is deliberately retained — it is true of corpus re-judging and is
explicitly not a banned pattern.

CHANGELOG.md gets the gate's `retired-ok:` escape hatch rather than a
reword: the entry is release history naming the demoted mechanism, and
rewriting it would falsify the record.

.clinerules, .windsurfrules and .cursor/rules/project.mdc are not scanned
by the gate (no matching extension) but are fixed anyway — they teach the
retired claim to Cline, Windsurf and Cursor.

Verified: my four scanned files drop to zero violations, and every
remaining violation on the tree lies inside #419's file set, so the two
PRs together take the gate to zero.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WJ6BP3GX5HYrnjW1nGtrvC
@runyourempire
runyourempire merged commit 9180d19 into main Aug 14, 2026
8 checks passed
@runyourempire
runyourempire deleted the fix/ad030-agent-mirrors branch August 14, 2026 14:28
runyourempire added a commit that referenced this pull request Aug 15, 2026
…pply-chain blind spot (#433)

## The premise, verified first

An audit lane claimed the quick-xml suppression in `deny.toml:96-112` /
`.cargo/audit.toml:15-29` had gone stale. It rested on this
justification:

> "NO consumer in our tree has a released version against >=0.41 yet"

**Confirmed false.** Read straight out of the registry index
(`rust_version` and `deps` per published version):

| consumer | we had | latest | quick-xml req | zip req |
|---|---|---|---|---|
| `calamine` | **0.25.0** | 0.36.1 | `^0.31` → **`^0.41`** | `^1.0` →
`^8.6` |
| `docx-rs` | **0.4.20** | 0.4.22 | `^0.36` → **`^0.41`** (since 0.4.21)
| `^0.6.3` → `^8.6` |
| `plist` | **1.9.0** | 1.10.0 | `^0.39.2` → **`^0.41`** | — |

All three shipped support. The ignores were suppressing a live, fixable
advisory pair on a parser that reads **user-supplied `.xlsx` /
`.docx`**.

## What changed

**quick-xml (RUSTSEC-2026-0194 / -0195) — resolved, not re-justified.**
Bumping the three consumers collapses `quick-xml` **0.31.0 + 0.36.2 +
0.39.4 → a single 0.41.0**. Both advisories stop firing on their own, so
both ignores are **deleted** from `deny.toml` *and* `.cargo/audit.toml`
(they had diverged; both were checked). `RUSTSEC-2023-0071` (`rsa`) left
alone as instructed.

**`office.rs` needed no edit** — and that is a verified claim, not an
absence of errors:
- `sheet_names()` and `worksheet_range()` have byte-identical signatures
in 0.25 and 0.36.
- `Data` still has exactly the same nine variants with the same
payloads. `cell_to_string` matches it **exhaustively with no wildcard
arm**, so an added variant could not have compiled.
- `ExcelDateTime`'s `Display` impl is byte-identical (`write!(f, "{}",
self.value)`), so `DateTime` cells format the same.
- Same for `docx-rs`: `TableChild` / `TableRowChild` are destructured
irrefutably, so a new variant there could not have compiled either.

The documented decompression-bomb weakness (the 100 MB cap is on the
**compressed** size) is untouched — separate work, not regressed.

**zip — partial.** `zip 1.1.4` retired as hoped. **`zip 0.6.6` did not**
— it is our own direct `zip = "0.6"`, so retiring it is an 8-major API
migration across `osv/cache.rs`, `extractors/archive.rs` and
`embeddings_providers/fastembed.rs`. No advisory attaches to it, so it
is staleness, not exposure. Left as follow-up rather than smuggled into
a security PR. Tree is now `zip` 0.6.6 (ours) + 4.6.1
(tauri-plugin-updater) + 8.6.0 (calamine/docx-rs).

**`relay/` — 5 vulnerabilities → 0.** A TLS-terminating server with no
Dependabot entry, no cargo-audit, no CI.

| crate | change | advisory |
|---|---|---|
| `rustls-webpki` | 0.103.9 → **0.103.14** | RUSTSEC-2026-0049 / -0098 /
-0099 / -0104 (cert validation) |
| `spin` | 0.9.8 → **0.9.9** | 0.9.8 was **yanked** |
| `anyhow` | 1.0.102 → 1.0.104 | RUSTSEC-2026-0190 |
| `event-listener` | 5.4.1 → 5.4.2 | RUSTSEC-2026-0221 |
| `rand` | 0.8.5 → 0.8.7 | RUSTSEC-2026-0097 |

`rsa 0.9.10` remains with no fix available, and is recorded in a new
`relay/.cargo/audit.toml` with evidence that it is **not in the build
graph**: it reaches `Cargo.lock` only via sqlx's optional `mysql`
backend, which relay never enables — `cargo tree -i rsa` and `cargo tree
-i sqlx-mysql` both report *nothing to print*.

**Coverage, so it stops recurring.** `dependabot.yml` gains a `cargo`
entry for `/relay` (not a `src-tauri` workspace member, so the existing
entry never saw it), and `nightly-audit.yml`'s cargo-audit step now
loops every `Cargo.lock` in the repo. **Workflow footprint is
deliberately limited to those two files** — `validate.yml` is being
reshaped by peer PRs and is untouched here.

**`relay/Dockerfile`.** `cargo build --release --locked 2>/dev/null ||
cargo build --release` silently dropped lockfile enforcement and
swallowed the reason. Fallback removed. Its base image also had to move
**1.82 → 1.95**: the lockfile already required 1.88 via `time 0.3.47`
(`jsonwebtoken` → `simple_asn1`), so that image could not have built
this crate at all — the fallback was hiding a hard failure, not
surviving a soft one.

## Two things found on the way

**1. `main` was un-committable — independently confirmed, now fixed by
#430.** `scripts/check-file-sizes.cjs` exits 1 on
`src-tauri/src/analysis_rerank.rs` (**1032 lines against a 1000 hard
limit**, arrived with #423). The gate scans the whole repo rather than
staged paths, so `.husky/pre-commit` failed for *every* terminal on
*every* commit — including this one. I hit it, diagnosed it, and fixed
it the same way a peer did in **#430** (lift the test module into a
sibling `analysis_rerank_tests.rs` via `#[path]`, 1032 → 866). #430
landed first, so **that commit has been dropped from this branch by
rebase** — this PR now contains only the dependency work. Recording it
here as an independent second confirmation of both the diagnosis and the
chosen fix.

**2. `cargo clippy --all-targets -- -D warnings` does not pass on
`main`** (255 pre-existing errors at my branch point, ~all
`unwrap_used`/`expect_used` in test code). This is **not** the gate — CI
runs `cargo clippy ${{ matrix.cargo-features }} -- -D warnings`
*without* `--all-targets`, so the numbers below are from the
CI-equivalent invocation. Reported as an observation, not touched.

## Verification

| check | result |
|---|---|
| `src-tauri` `cargo audit` | **exit 0** — zero vulnerabilities, zero
warnings |
| `src-tauri` `cargo deny check` | **exit 0** — `advisories ok, bans ok,
licenses ok, sources ok` |
| `relay` `cargo audit` | **exit 0** (was 5 vulns + 4 warnings + 1
yanked) |
| `relay` `cargo check --locked --all-targets` | clean |
| `cargo clippy -- -D warnings` (CI-equivalent, default) | **exit 0** |
| `cargo clippy --features experimental -- -D warnings` | **exit 0** |
| `cargo fmt --check` | **exit 0** |
| `cargo test --lib` | **4300 passed, 0 failed, 10 ignored** |

All re-run after rebasing onto `c1fd348c` (#425, #426, #427, #429, #430,
#431 all landed mid-flight).

`--features team-sync` and `--features enterprise` fail to compile —
**pre-existing rot on `main`** (`chacha20poly1305::aead::OsRng`
unresolved, then cascading `__cmd__*` macro failures), which is what
#424 exists to repair. My lockfile diff touches no crypto crate. #424 is
still open as of this push, and the CI clippy matrix on `main` still
carries only the `default` and `experimental` legs — so the two legs
verified above are exactly the gate.

### The extractor tests were `#[ignore]`d and had never run

There are no `.xlsx`/`.docx` fixtures anywhere in the repo, so
`test_real_docx_extraction` / `test_real_xlsx_extraction` were no-ops
that returned early. To gain real confidence in an 11-minor-version
parser bump I generated **real OOXML documents** — shared strings, an
inline string, numeric and boolean cells, paragraphs and a table —
confirmed both `#[ignore]`d tests pass against them, and separately
asserted the extracted text matches the pre-bump formatting contract
exactly:

```
=== Sheet: Budget ===        Hello from 4DA
Item | Cost                  Second paragraph
Widget | 42                  A1 | B1
Gadget | 3.50 | TRUE
```

That exercises every arm of `cell_to_string` that a document can reach
(shared/inline string, integral float → `42`, fractional float → `3.50`,
bool → `TRUE`) plus the docx paragraph and table paths. The scratch
harness was deleted; **no test-file changes ship in this PR**.

## Deliberately left

- **`zip 0.6.6`** — direct dep, 8-major API migration, no advisory.
Follow-up.
- **`office.rs` decompression bomb** — the 100 MB cap is on the
compressed size. Out of scope, not regressed.
- **`--all-targets` clippy backlog** — pre-existing, not the CI gate.
- **`validate.yml`** — peer-owned right now, untouched on purpose.
- **`--features team-sync` / `enterprise`** — pre-existing rot, #424's
job.

---------

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
runyourempire added a commit that referenced this pull request Aug 16, 2026
…de that does not exist (#466)

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.md` never 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.

- **Design tokens.** `CLAUDE.md` listed `--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-primary` at `App.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.
- **The 60-line Rust function rule** was presented as enforced. It is
not implemented anywhere, and `src-tauri/Cargo.toml:252` explicitly sets
`too_many_lines = "allow"`. Now stated as a convention.
- **`ts-rs` was wrong in all seven files**, not just `CLAUDE.md` — every
one said v10; `src-tauri/Cargo.toml:27` pins `"12"`.
- **Source count.** Every mirror said "20+". `build_all_sources()`
registers **22** (counted: 22 `Box::new` entries). Mastodon and Lemmy
were missing from every list, and `CVE/OSV` was 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.

| | Claimed | Actual |
|---|---|---|
| INV-001 | "precision MUST be >85%" | No 85% threshold exists. Real
enforced floors: aggregate precision >= 0.70, F1 >= 0.40, per-persona
noise rejection >= 80% (`scoring/simulation/reality.rs`) |
| INV-023 | `STATIC_/ACTIVE_/LEARNED_LAYER_WEIGHT` | **Zero `.rs`
hits.** Also still stale in `specs/ACE-STONE-TABLET.md` |
| INV-041 | "ALL persistent state MUST live in SQLite" | Contradicted by
four subsystems — `settings.json`, the OS keychain,
`data/calibrations/`, `data/signal_terminal_token.txt` |
| INV-060 | `ExclusionStrength` enum, "percentages are CANONICAL" |
**Zero `.rs` hits** |
| INV-071 | ">=5 exposures" | See below — it is worse than "3 not 5" |
| INV-090 | warn at TS 350 / RS 600 | Gate uses ts 300 / tsx 350 / rs
700 |

`.ai/FAILURE_MODES.md` documented 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 on `cloud_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"* about `victauri-plugin`, which sits in
`[dependencies]`, not `[dev-dependencies]`, under no
`cfg(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_ecosystem`
POSTs the user's package names to `OSV_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.md` edits 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.md` gets 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 from `CLAUDE.md` —
the maintained source of truth"*, and explains `sync-ai-rules.sh` was
deleted because it ran the other way and would clobber `CLAUDE.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.json` `firstRun.scanningDescription` still 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.com/claude-code)

https://claude.ai/code/session_01Fq96xWyPQjx2bCCzWtsnC9

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
runyourempire added a commit that referenced this pull request Aug 17, 2026
…d but never ran (#477)

## The residual this closes

`scripts/check-retired-claims.cjs` + its 9 tests merged in #469 as the
AD-030 enforcement gate — but nothing ever invoked them. Not
`test:scripts`, not the `validate` chain, so the gate never ran in CI.
Meanwhile `.ai/RULES.md` / `AGENTS.md` (via #431) already assert this
enforcement exists. This was the priority residual of the AD-030
retirement arc (tracked in `.claude/plans/PENDING-DECISION.md` item 1);
it was blocked on #470's lane holding `package.json` and is unblocked
now that #470 merged.

## Change (3 lines, package.json only)

- `validate:retired-claims` script → `node
scripts/check-retired-claims.cjs`
- `scripts/check-retired-claims.test.cjs` added to `test:scripts`
- Gate inserted at the front of the `validate` chain, right after the
size check — it is sub-second, so it fails fast before the heavy steps

## Verification

- `node scripts/check-retired-claims.cjs` — OK repo-wide (0 violations)
- `node --test scripts/check-retired-claims.test.cjs` — 9 pass / 0 fail
- Pre-push gate (typecheck + suite) passed locally

🤖 Generated with [Claude Code](https://claude.com/claude-code)

https://claude.ai/code/session_01LBY5q2MskiKMkTm6NmB49L

Co-authored-by: Claude Fable 5 <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