Skip to content

fix(scoring): close the two behavioral inputs that survived the v19 quarantine — PIPELINE_VERSION 20 - #476

Merged
runyourempire merged 11 commits into
mainfrom
worktree-ad030-promise-retirement-v2
Aug 16, 2026
Merged

fix(scoring): close the two behavioral inputs that survived the v19 quarantine — PIPELINE_VERSION 20#476
runyourempire merged 11 commits into
mainfrom
worktree-ad030-promise-retirement-v2

Conversation

@runyourempire

Copy link
Copy Markdown
Collaborator

fix(scoring): close the two behavioral inputs that survived the v19 quarantine — PIPELINE_VERSION 20

The v20a inventory (behind #474) found that AD-029's loader quarantine did not fully hold: topic_affinities still reached live scoring through two doors. Both are now closed, with live-DB probes grounding every decision.

Door 1 — contradiction_boost (removed end-to-end)

anomaly::get_contradicted_topics joined topic_affinities against anti_topics and fed the necessity path (0.45 + boost×0.25, capped 0.70). Removed: the anomaly query, the ScoringContext.contradicted_topics field, the pipeline computation, NecessityInputs.contradiction_boost, try_contradiction_path, and its four tests. Live probe: anti_topics = 0 rows → the JOIN was empty → this removal is byte-identical on the live corpus.

Door 2 — skill_gap_boost's engaged-set (re-sourced + cold-start floor)

detect_skill_gaps excluded "engaged" dependencies using the behavioral top_affinities. Live probes: the engaged-set was 15 topics built entirely from scroll noise — interactions holds only 328 scroll + 303 ignore rows (zero explicit actions, ever) and feedback has 0 rows; the affinity table includes java .466 and ruby .092 on a Rust/TS codebase.

Now: the exclusion is sourced from explicit engagement only (click/save/share/briefing_click/engagement_complete/save_with_context in interactions), and with zero explicit engagement recorded no gap is assertable — "you never engaged with X" is vacuously true for every dependency, so the detector emits nothing until explicit data exists (cold-start doctrine). SkillsDimension.top_affinities stays for the profile's display/export. New tests: cold-start floor + an INV-023 regression guard (a behavioral affinity can never close a gap).

PIPELINE_VERSION 19 → 20

Gap sets — and skill_gap_boost (+0.15/0.20) — change on the live corpus, so this is a real score change. Unregistered (full-drain) bump: affected items aren't expressible as a stored-column predicate (breakdowns are computed on demand), and the ~15.6k corpus converges in minutes on the recency-first parallel drain (#372#374). Verdict reconciliation (F2) demotes any stale curated verdicts. Full justification recorded at the constant.

Verification

cargo test --lib 4391/0 · clippy --lib -- -D warnings clean · fmt clean · merged over #474 cleanly, targeted suites re-green on the combined tree.

Activation note

The bump goes live when the root-tree debug binaries (fourda.exe + fourda-engine.exe) are next rebuilt — until then the running engine keeps stamping v19.

🤖 Generated with Claude Code

https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw

runyourempire and others added 11 commits August 12, 2026 03:46
…stack

The last behavioral scoring path left after the v19 demotion (AD-029),
found by the post-merge verification sweep: build_negative_stack injected
0.30 Bayesian suppression priors from auto-detected anti_topics rows whose
confidence is pure dismissal count (rejection_count/10) — five dismissals
could auto-ban a topic to x0.30 composite authority via
negative_stack_prior. Inert on the live corpus (anti_topics has 0 rows,
priors byte-identical, hence NO PIPELINE_VERSION bump — precedent and
probe documented in scoring/mod.rs), but structurally live.

The negative stack now builds from competing-tech inference over the
actual dependency graph only. Explicit topic suppression remains
user-authored exclusions, which hard-filter upstream. blind_spots'
duplicate anti-topic feed removed with it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016puYGGmj3oHxmcKBbJ5vXq
The promise described a mechanism AD-029 removed, was never measurable
("all risk, no demonstrated lift" — 7 explicit feedback signals against a
200k-item corpus), and post-v19 left ~100 instances of self-contradicting
copy, several asserting dead mechanisms inside Score Autopsy — live
INV-023 violations. Pre-launch (public, unadvertised) is the only cheap
moment; after launch this is a retraction.

New canonical (propagated from CLAUDE.md through every surface):
"4DA reads the internet for developers — privately, locally. Your
codebase decides what''s relevant." "Yesterday''s noise becomes tomorrow''s
signal" SURVIVES, re-attributed to corpus re-judging (verdict epochs +
re-examination) — it is true and implemented. The 92%/98% benchmark stays
as body copy with methodology. "Compound knowledge" survives only in the
framework''s dev-process sense.

- Governance first: AD-030 (with re-claim criteria: a /calibrate-measured
  lift, published) + amendments to AD-017/025/026/028 — all four decisions
  survive, only rationales rewrite (AD-028''s lifetime honesty now rests on
  the cost structure: zero marginal cost + offline 2099 key)
- P0: in-app strings that asserted dead mechanisms rewritten or deleted
  ("will be penalized in relevance scoring", "Boosted because you''ve shown
  interest", "scoring corrections applied", the "Learned" badge, learned
  factor rows + affinity chips — the anti factor also had inverted
  magnitude/multiplier semantics and rendered a false penalty on every item)
- "Compound Intelligence" tab renamed "Personal, Not Aggregate" — its
  content (per-user, inspectable, local-only) was always a privacy story
- 13 locales: 45 stale keys purged per locale, regenerated from corrected
  English via i18n:fill; generator scripts purged first so nothing
  re-injects (apply-translations.cjs carried 12 hardcoded copies)
- Ship-locked surfaces: installer shortDescription/longDescription,
  homepage JSON-LD (incl. the Offer), npm MCP README (lands on next
  publish)
- Site + docs: 22 files rewritten under the house rule (present-tense
  verifiable statements; improvement attributed to engine updates and the
  user''s codebase, never engagement); signal.njk''s 16 compounding claims
  reframed on the analysis layer; the refund-adjacent trial claim deleted;
  framework §7 kept as a dev-process thesis with scoring-accuracy claims
  stripped across all three mirrored copies
- New public post: site/src/writing/retiring-a-claim-we-could-not-measure
  — the incident record as an engineering story, ending on the re-claim bar
- Enforcement: scripts/check-retired-claims.cjs (+9 tests) wired into
  test:scripts and validate; historical-record files allowlisted;
  retired-ok escape hatch for quoting the claim as history

Verified: guard clean repo-wide; translation parity 0 errors across 13
languages; tsc clean; frontend suite green; Rust 4,419 green; fmt clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_016puYGGmj3oHxmcKBbJ5vXq
…uilt onto current main)

Merges origin/worktree-promise-retirement-ad030 (PR #419) with conflicts
resolved in favour of current main's newer facts:
- locale ui.json files: main's structure kept; #419's 312 reworded values
  and 130 deleted affinity-surface keys ported per-leaf (its 752 key
  additions dropped — those surfaces were deleted from en by #421)
- README/index.njk/signal.njk/SETUP-GUIDE/LICENSE-ACTIVATION: main's newer
  copy (93% figure, Precision Ledger, BYOK rationale) kept, retired
  phrases replaced with the canonical line
- Developer DNA kept OUT of paid-feature lists (AD-025/026 tier truth)
- apply-translations.cjs / missing-keys.json / BadgeRow.tsx stay deleted
  (deleted on main since #419's base)
- CLAUDE.md + package.json deliberately untouched: claimed by live peer
  lanes (#466, agent-a875) — gate wiring + tagline follow in-branch once
  those claims release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw
- 92% -> 93% / 98% -> 98.9% / 215 -> 245-item corpus (the current
  measured benchmark, #460) in COMPARISON.md and the retirement post
- RELEASE-NOTES-v1.0.0 tier table + closing line matched to AD-025/026
  tier truth (DNA, Signal Chains, Score Autopsy are free; the paid set
  is Blind Spots, Knowledge Gaps, Standing Queries, Semantic Shifts,
  cross-project intelligence)
- retirement post added to /writing index (retired-ok teaser quote) and
  sitemap
- two Rust doc comments un-mangled; engagement_telemetry header no
  longer claims facets influence scoring (INV-023)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw
The last 2 retired-claim violations in the repo. The tagline mandate now
teaches the canonical description and points at the enforcement gate
instead of restating the retired phrases. Deferred from #469 because this
file was claimed by the #466 lane; that lane is merged and its worktree
reaped.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw
…Knowledge Gaps

Verified against the live code: of the features sold on /signal, README,
LICENSE-ACTIVATION, SETUP-GUIDE, RELEASE-NOTES and the Terms, only Blind
Spots (with AI assessment) and Knowledge Gaps have a reachable UI.
Removed from every sales surface: Standing Queries (backend exists, no
creation UI — only a Brief listener that can never fire), Semantic
Shifts / cross-project intelligence / Project Health comparison
(commands registered, zero frontend callers), Attention Report + the
attention dashboard (backend command deleted as a ghost in #421; the
settings.attention locale keys are orphans), Decision Health, Trust
Ledger analytics, and the Precision Ledger (unbuilt in both layers).

Also corrects tier misattribution the same surfaces carried: Score
Autopsy, Developer DNA and Signal chain analysis are FREE (AD-025/026)
and now sit in the Free column/card, not the Signal one. The Terms'
Signal-tier list (site/src/terms.njk + docs/legal/TERMS-OF-SERVICE.md)
was internally inconsistent — §3.2 sold channels/DNA as paid while §4.5
said they stay free; both now state the true paid set. Legal wording
otherwise untouched — flag for counsel review.

Backend + gating for the unreachable features are KEPT; each returns to
the sales surfaces when its UI ships. Site builds clean; retired-claims
gate green.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw
…uarantine — PIPELINE_VERSION 20

The AD-029 quarantine neutered the affinity loader, but topic_affinities
still reached live scoring through two doors:

1. contradiction_boost — anomaly::get_contradicted_topics joined
   topic_affinities against anti_topics and fed the necessity path
   (0.45 + boost*0.25). Removed end-to-end: the anomaly query, the
   ScoringContext field, the pipeline computation, the necessity path
   and its tests. Live-corpus probe: anti_topics has 0 rows, so the
   join was empty and this removal is byte-identical there.

2. skill_gap_boost — detect_skill_gaps excluded 'engaged' deps using
   the behavioral top_affinities. On the live box that engaged-set was
   15 topics built ENTIRELY from scroll/ignore noise (the interactions
   table holds zero explicit actions; the feedback table is empty).
   The exclusion is now sourced from EXPLICIT engagement only
   (click/save/share/briefing_click/engagement_complete), and with
   zero explicit engagement recorded no gap is assertable — the
   detector emits nothing until explicit data exists (cold-start
   doctrine). New INV-023 regression guard: a behavioral affinity can
   never close a gap.

Gap sets — and skill_gap_boost (+0.15/0.20) — change on the live
corpus, so PIPELINE_VERSION bumps to 20. Unregistered (full-drain)
bump: affected items are not expressible as a stored-column predicate
and the 15.6k corpus converges in minutes on the recency-first
parallel drain. Justification recorded at the constant.

cargo test --lib 4391/0 - clippy -D warnings clean - fmt clean

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw
@runyourempire
runyourempire enabled auto-merge (squash) August 16, 2026 15:49
@runyourempire
runyourempire merged commit 45d02c3 into main Aug 16, 2026
14 checks passed
@runyourempire
runyourempire deleted the worktree-ad030-promise-retirement-v2 branch August 16, 2026 16:04
runyourempire added a commit that referenced this pull request Aug 18, 2026
… explicit engagement stays

AD-031 (operator decision 2026-08-17): delete the implicit behavioral-capture
layer end-to-end; explicit engagement capture stays; scoring is byte-identical
(NO PIPELINE_VERSION bump — stays at 21).

Removed (proof class: implicit capture — AD-029 demoted it from scoring in
v19, v20a deleted its last honest UI surfaces, leaving a write-only pipeline):
- FE emitters: use-view-tracking.ts (sole scroll/ignore emitter) + its wiring
  in ResultItem/ResultsView (itemIndex kept — it drives auto-summary)
- BehaviorAction::Scroll/Ignore variants, their strength arms and IPC match
  arms; engagement_telemetry::on_implicit_skip (+3 tests)
- Derived-profile writers in ace/behavior/tracking.rs: update_topic_affinities,
  update_anti_topics, update_source_preference, update_activity_patterns,
  RECOMPUTE_AFFINITY_SQL (a frozen copy is inlined into db/migrations.rs so
  historical Phase 89/90 behave identically for pre-89 databases), and
  taste_test/continuous.rs (persona-posterior write side; the EXPLICIT taste
  seeding via add_interest + generate_synthetic_feedback survives untouched)
- Readers of the dropped tables: ace/behavior/queries.rs (whole file),
  ace_get_topic_affinities / ace_get_anti_topics commands (registry 383->381,
  ghost backlog entries cleared in the same commit), the three affinity
  anomaly detectors (context drift / contradiction / confidence mismatch —
  detect_abnormal_volume and stale-data KEPT; AnomalyType variants KEPT so
  historical stored anomaly rows still deserialize), the tech-radar affinity
  overlay + its always-0 engagement score term, the learned_behavior export
  section (+ i18n key removed from en + 12 locales), apply_behavior_decay
  (detected-tech decay + frozen tuner survive), the AD-029 quarantine loader
  and the anti_topics / anti_topic_confidence / topic_affinities fields on
  ACEContext, and the simulation enrichment arms + persona anti-topic fixtures
- Zero-reader proof class (justified separately, not implicit): autophagy
  decision_outcomes.rs — its "results feed back into scoring" doc claim was
  false; no reader of the decision_outcome digest_type ever existed

Re-sourced to explicit engagement (the #476 six-type predicate over
`interactions`, mirroring detect_skill_gaps): standing-query suggestions and
Developer DNA get_top_engaged_topics — return shapes preserved, counts honest.

Kept per rulings:
- A1: Dismiss / MarkIrrelevant / BriefingDismiss still write interactions rows
  and feed the stability_detector and record_item_feedback
- A2(a): SkillsDimension.top_affinities + AffinityEntry + the INV-023 guard
  test behavioral_affinities_do_not_exclude_gaps KEPT; only the source query
  deleted (field permanently empty — serialized-shape stability, the pinned
  ScoreBreakdown doctrine). The v20 explicit skill-gap query directly below it
  is untouched; all four skill-gap tests pass.
- A5: the bootstrap-mode term in scoring/context.rs is UNTOUCHED and there is
  NO DELETE on interactions. Live probe (2026-08-17, post-#482): 713
  interactions total, 296 with |signal_strength| >= 0.3, ALL 296 implicit =>
  effective_feedback_count = 98 => bootstrap OFF, held off entirely by
  implicit rows. Rows kept => count unchanged => scoring byte-identical.
  Open v20c question recorded in AD-031: should bootstrap-exit require
  EXPLICIT signal (a scoring change needing a PIPELINE_VERSION bump)?
- A7: the snooze bug is untouched (out of scope).

Migration Phase 105 (TARGET_VERSION 104->105): DROP TABLE IF EXISTS
topic_affinities, anti_topics, activity_patterns, source_preferences,
persona_posterior, posterior_snapshots (orphaned by #474); DELETE FROM
digested_intelligence WHERE digest_type='decision_outcome'. NO deletions on
interactions. ACTIVATION: rebuild BOTH fourda and fourda-engine before
anything runs (the old-binary/newer-db incident class).

FE honesty (required): feedback toasts rewritten as plain confirmations
("Saved." / "Marked irrelevant." / "Dismissed.") — the affinity-boost /
anti-topics / auto-filter promises had been false since v19 and named
dropped tables.

Docs: INV-071 marked RETIRED with its body preserved as history (its
display-gate bullet was already stale — the cited counter died in v20a);
AD-029 amended to record the partial adoption of its rejected "full removal"
option; AD-031 added; historical banners added to specs/ACE-STONE-TABLET.md
and specs/CONTEXT-ENGINE.md; API_REFERENCE + ghost-command backlog updated.

Calibration-window drift (report item): autophagy calibration analyzers read
interactions over rolling windows; v20b stops NEW implicit rows, so those
windows drift gradually as legacy rows age out — forward-looking data-mix
drift, not a change to any current computation (day-0 output identical).

Also while here: removed three dead-mechanism simulation tests that had
passed vacuously since v19 (ace_anti_topic_excludes_matching_content,
breakdown_anti_penalty_range, penalties_asymmetrically_stronger_than_boosts —
the ACE anti-topic scoring mechanism they asserted left in AD-029); removed a
duplicated `use super::*;` in llm_stream_tests.rs (the battery's only
warning, pre-existing); added two `retired-ok` history markers in
mcp-4da-server/CHANGELOG.md so check-retired-claims passes via its own
documented escape hatch (lint markers only — the mcp-4da-server code/db
cleanup stays deferred to v20c per A4).

Verification: cargo test --lib 4380 passed / 0 failed / 8 ignored; clippy
--lib -D warnings clean; cargo fmt applied to touched files; no new
allow(dead_code); golden/simulation assertions untouched (zero baseline
edits); FE 1242/1242 green; tsc clean; i18n:types regenerated;
validate-commands consistent at 381; ghost-commands 0 new / 0 stale;
check-file-sizes 0 errors; check-retired-claims OK; migration test
test_phase_105_drops_implicit_capture_tables added per the existing idiom.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LBY5q2MskiKMkTm6NmB49L
runyourempire added a commit that referenced this pull request Aug 18, 2026
… explicit engagement stays (#488)

v20b: removal of the IMPLICIT behavioral-capture layer, per the
completed read-only inventory and the seven operator rulings
(2026-08-17). Companion to #474 (v20a). **Implicit capture goes,
explicit engagement stays, scoring is byte-identical — NO
PIPELINE_VERSION bump (stays at 21). New decision record: AD-031; AD-029
amended; INV-071 retired.**

## Rulings A1–A7 as implemented

- **A1 — Dismiss / MarkIrrelevant / BriefingDismiss STAY.** They still
write `interactions` rows and feed the kept
`stability_detector::record_evidence` loops and `record_item_feedback`.
Only their dead affinity/anti-topic consumers were removed.
- **A2(a) — `SkillsDimension.top_affinities` + `AffinityEntry` + INV-023
guard test KEPT.** Only the source query in
`sovereign_developer_profile.rs::assemble_skills` was deleted; the field
is permanently empty (serialized-shape stability, same doctrine as the
pinned ScoreBreakdown fields). The v20 explicit skill-gap query directly
below it is untouched; all four skill-gap tests pass, including
`behavioral_affinities_do_not_exclude_gaps` and
`no_explicit_engagement_means_no_gaps`.
- **A3 — the three affinity/anti-topic anomaly detectors removed**
(`detect_context_drift`, `detect_contradictions`,
`detect_confidence_mismatch` + their tests/fixtures).
`detect_abnormal_volume` and `detect_stale_data` KEPT. The `AnomalyType`
enum variants were deliberately KEPT so historical stored anomaly rows
still deserialize and render — this kept the Anomalies UI coupling
trivial (no STOP needed).
- **A4 — `mcp-4da-server` DEFERRED to v20c.** No code/db changes in it.
Its reads degrade gracefully on the dropped tables; note that its
`db.ts` `CREATE TABLE IF NOT EXISTS` may resurrect empty
`topic_affinities`/`anti_topics` tables in 4da.db — cosmetic, cleaned in
v20c. (One exception, disclosed: two `retired-ok` HISTORY MARKERS added
to `mcp-4da-server/CHANGELOG.md` — the check-retired-claims gate fails
on the base because the 5.0.2 changelog entry quotes the retired claims
as history without the gate's documented marker. Lint markers only, zero
behavior.)
- **A5 — bootstrap term UNTOUCHED, rows KEPT.** Live probe (2026-08-17,
post-#482): **713 interactions total, 296 with |signal_strength| ≥ 0.3,
ALL 296 implicit ⇒ effective_feedback_count = 98 ⇒ bootstrap OFF**, held
off entirely by implicit rows. v20b performs NO DELETE/UPDATE on
`interactions`, so the count — and therefore scoring — is unchanged.
Open v20c question (recorded in AD-031): should bootstrap-exit require
EXPLICIT signal? That is a scoring change and needs a PIPELINE_VERSION
bump.
- **A6 — docs:** INV-071 marked RETIRED with a reason, body preserved as
history (its display-gate bullet was already stale — the cited counter
at `ace_commands/interactions.rs:429` died in v20a; the file now ends at
~400 lines). AD-029 amended to record the 2026-08-17 partial adoption of
its previously-rejected "full removal" option (implicit removed,
explicit kept — the "destroys honest surfaces" objection dissolved when
v20a removed those surfaces). AD-031 added following the file's format.
`specs/`: historical-status banners added to ACE-STONE-TABLET.md and
CONTEXT-ENGINE.md (matching the existing 2026-08-16 banner idiom);
history sections not rewritten.
- **A7 — snooze untouched.** No snooze arm added, FE call not removed.

## STOP facts honored

1. `record_interaction` / `store_interaction` / `ace_record_interaction`
all survive — only the Scroll/Ignore arms and the implicit-skip block
were excised inside them. `ace_record_interaction` stays registered
everywhere (lib.rs, CommandMap, Victauri allowlist). The implicit-skip
excision was scoped to the if-block inside the same `if let Ok(conn)` as
the KEPT stability loops.
2. ACE DB = main DB honored throughout (Phase 105 runs on the shared
4da.db).
3. Scoring touched at exactly the two reported points and nowhere else:
the A5 bootstrap term (untouched) and the calibration-window note below.
**Zero golden/simulation baseline edits; no asserted number changed.**

## Scoring-inertness proof

- PIPELINE_VERSION untouched at 21.
- A5 numbers above; `interactions` rows kept, so
`effective_feedback_count` is bit-identical.
- The deleted `ACEContext.anti_topics` / `topic_affinities` fields had
NO reader in the scoring pipeline (v19 removed them; the quarantine
loader returned an empty map by construction) — their only remaining
readers were two LLM-prompt injections: `analysis_rerank.rs` (block
never fired — live table 0 rows) and the digest prompt, which is now
unconditionally the same "None specified" string it always produced,
keeping the prompt byte-identical.
- Full suite green with zero baseline adjustments: the scoring
simulation + validation suites (inside `cargo test --lib`) all pass
unmodified.
- Three simulation tests were REMOVED, not adjusted — they asserted the
ACE anti-topic scoring mechanism deleted in v19 (AD-029) and had passed
**vacuously** ever since: `ace_anti_topic_excludes_matching_content` (a
pure-Rust persona scores python items <0.05 regardless),
`breakdown_anti_penalty_range` (plain range check),
`penalties_asymmetrically_stronger_than_boosts` (its two contexts became
literally identical). Removing a vacuous test changes no asserted
number.
- **Calibration-window drift (forward-looking note, not a change):** the
autophagy calibration analyzers read `interactions` over rolling
windows. v20b stops NEW implicit rows, so those windows gradually shift
toward explicit-only as legacy rows age out. Day-0 output is identical;
the drift is organic data-mix change, not a computation change.

## Migration Phase 105 (TARGET_VERSION 104 → 105)

```sql
DROP TABLE IF EXISTS topic_affinities;
DROP TABLE IF EXISTS anti_topics;
DROP TABLE IF EXISTS activity_patterns;
DROP TABLE IF EXISTS source_preferences;
DROP TABLE IF EXISTS persona_posterior;
DROP TABLE IF EXISTS posterior_snapshots;   -- orphaned by #474
DELETE FROM digested_intelligence WHERE digest_type = 'decision_outcome';
```

**NO DELETE/UPDATE on `interactions`** (A5). Historical Phase 89/90 keep
byte-identical behavior via a frozen inline copy of the recompute SQL
(the live const was deleted with tracking.rs's learning layer). New
migration test `test_phase_105_drops_implicit_capture_tables` follows
the existing wind-back idiom (seeds legacy tables + a decision_outcome
digest + an implicit interaction row at v104, re-migrates, asserts
dropped/purged/KEPT).

**ACTIVATION REQUIREMENT: rebuild BOTH `fourda` and `fourda-engine`
before anything runs after merge.** An old binary opening the schema-105
database is the exact incident class that quarantined the live corpus on
2026-08-16 (old-binary/newer-db → corrupt-db fallback). Migrate and
rebuild together.

## Zero-reader proof class (separate justification)

`autophagy/decision_outcomes.rs` was deleted not as implicit capture but
as a **zero-reader**: it wrote `decision_outcome` digests that no code
ever read back (its module doc claimed "results feed back into scoring"
— false). Unwound through `AutophagyCycleResult` (ts-rs binding
regenerated by the suite, not hand-edited), digest.rs,
autophagy_commands.rs.

## Re-sourced consumers (kept features made honest)

- `standing_queries_suggestions.rs`: suggestions now come from 3+
explicit positive-engagement interactions (the #476 six-type predicate
over `interactions`, mirroring `detect_skill_gaps`); 4 tests
re-fixtured, incl. an explicit guard that legacy `scroll` rows never
count.
- `developer_dna.rs::get_top_engaged_topics`: same predicate; return
shape preserved; `interactions` is now an honest count (previously
`affinity_score as u32`, i.e. almost always 0).

## Inventory deviations found and handled

- `commands.rs` (not `ace/behavior/commands.rs`) held the decay call —
as inventoried by content, path corrected.
- `personas.rs` persona `anti_topics` feed the KEPT `exclusions` scoring
input — left fully untouched (deleting them would have changed
validation numbers).
- The i18n key existed in 13 locale files total (en + 12), not en + 13.
- `differential.rs` / `ace_validation.rs` contained three anti-topic
fixture sites the inventory's "~8 simulation files" bucket did not
enumerate — handled as above.
- `source_items.view_count` is now write-only (its only reader was the
deleted return-visit strength boost). The write was KEPT (not in the
inventory's removal scope); flagged as a v20c candidate.
- Stacks `source_preferences` name-trap honored: zero changes under
`stacks/`.

## Verification (all required gates)

| Check | Result |
|---|---|
| `cargo test --lib` (full, incl. scoring simulation + validation +
migration tests) | **4380 passed / 0 failed / 8 ignored** |
| `cargo clippy --lib -- -D warnings` | clean |
| `cargo fmt` (targeted, all touched files) | applied |
| New `#[allow(dead_code)]` | none |
| Golden / simulation baselines | **zero edits** |
| `pnpm run test` (FE) | **1242/1242 passed** (111 files) |
| `pnpm run typecheck` | clean |
| `pnpm run i18n:types` | regenerated (diff committed) |
| `npx eslint` (touched TS) | 0 errors (3 pre-existing warnings in
untouched DataExportPanel lines) |
| `check-file-sizes.cjs` | exit 0, no new errors |
| `check-retired-claims.cjs` | OK (after the two disclosed history
markers) |
| `ghost-commands.cjs` | 0 new / 0 stale (both cleared backlog entries
removed with their commands) |
| `validate-commands.cjs` | consistent at **381** (was 383) |
| Sacred tests | all four skill-gap tests,
`anti_topics_no_longer_feed_the_negative_stack`,
`detected_tech_decay_runs_and_does_not_compound`,
`test_engagement_summary_shape` — all pass |

Known-external on this base (per orchestrator): the NOTICE attribution
delta from #450 (fix merging as #486) — not regenerated here to avoid
conflicting; resolved by rebase at landing.

**DO NOT run the migration or touch data/4da.db until both binaries are
rebuilt.**

🤖 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