Skip to content

chore(v20a): delete the structurally-dead learned-affinity surfaces (AD-029/AD-030 arc) - #474

Merged
runyourempire merged 1 commit into
mainfrom
worktree-agent-a2dd3b8c178ec2bcb
Aug 16, 2026
Merged

chore(v20a): delete the structurally-dead learned-affinity surfaces (AD-029/AD-030 arc)#474
runyourempire merged 1 commit into
mainfrom
worktree-agent-a2dd3b8c178ec2bcb

Conversation

@runyourempire

Copy link
Copy Markdown
Collaborator

Implements the v20a-1 dead-code removal for the AD-029/AD-030 arc: deletes every learned-affinity surface that is STRUCTURALLY DEAD (provably unreachable or provably no-op), and nothing that is live. −1,620 lines, +107.

Proof classes (what made each removal behavior-neutral)

  • Pinned inputs — pipeline_v2 pins affinity_mult=1.0 / anti_penalty=0.0, so these could never produce output: the learned-axis strength branch in compute_signal_strength_bonus (both conditions structurally unreachable), the _anti_mult dead binding, the LearnedPreference explanation factor (learned_weight = max(0.0, 1.0−1.0), never fires — variant removed from FactorKind in Rust + the FE mirror), and probes_engine's ax_learned condition (probe report now lists only the four axes that can actually fire).
  • Empty-map reads — the AD-029 quarantined loader returns an empty topic_affinities map, so these always saw nothing: compute_affinity_multiplier + compute_anti_penalty (whole scoring/affinity.rs deleted), the channel_render multiplier + always-"Not yet learned" affinity_summary prompt line, the explanation-confidence affinity contribution, the two dead semantic/embeddings.rs loops, and the frontend learnedAffinities/antiTopics/lastLearnedTopic store state with its 500 ms refresh round-trip feeding nothing. ctx.feedback_boosts was a hardcoded empty map → the feedback_boost computation always yielded 0.0; the then-unread field was deleted with its writers.
  • Phantom schema — two PRE-EXISTING bugs, now deleted rather than shipped broken: weekly_digest::collect_topics queried a nonexistent ace_topic_affinities table (real table: topic_affinities) — top_topics empty since the day it was written; developer_dna::get_blind_spots filtered on a phantom weight column (real: affinity_score) — prepare failed, blind_spots always []. (The real Blind Spots feature in blind_spots.rs is untouched.)
  • Unreachable / zero callers — gate's learned axis never confirms (learned_confirmed = false); dead commands ace_get_single_affinity + get_learning_stats (handler + registration + CommandMap types + victauri allowlist entry + ghost-backlog entry); the persona-posterior READ side (get_dominant_persona, get_persona_topic_boosts, drift detection + posterior_snapshots); stability_detector's three unused query fns (+ their orphaned private helper); the monitoring FROZEN threshold auto-tune "would have done" log block; simulation affinity-injection arms (persona_data*, enrichment, feedback_sim, enriched_lifecycle, ace_validation).

Deliberately KEPT

  • Capture/writers: ace/behavior/tracking.rs, decay, engagement telemetry, interactions, persona-posterior WRITE side (update_posterior, seed_from_taste_test).
  • The AD-029 quarantined loader + its guard test (ace_context_quarantines_topic_affinities) — the quarantine itself.
  • Learned Preferences panel, preference_commands.rs, stability-detector core, EngagementPulse, get_engagement_summary, tech_radar overlay_affinities, standing_queries_suggestions, get_top_engaged_topics, data_export, mcp-4da-server.
  • affinity_mult / anti_penalty / feedback_boost FIELDS in ScoreBreakdown, still pinned 1.0/0.0/0.0 — stored score_breakdown JSON in user databases carries them; the serialized struct is unchanged.
  • ace_get_topic_affinities / ace_get_anti_topics commands (live readers of real rows): their only FE caller was the dead store refresh, so they are now backlogged in ghost-command-backlog.json with reviewed reasons rather than deleted.
  • anomaly.rs / sovereign profile / contradiction & skill-gap boosts — v20a-2 (INV-023) territory, untouched.

DSL

Removed only the two verified orphans: semantic_boost.affinity_clamp and engagement_weights.affinity_w (generated constants with zero src references; DSL validation is per-param, no required-key checks, and scoring_dsl.rs tests use their own inline SAMPLE_DSL — no test churn). The remaining affinity/feedback constants (AFFINITY_THRESHOLD, FEEDBACK_SCALE, FEEDBACK_CAP_RANGE, SIGNAL_NORMALIZATION_AFFINITY_RANGE, SIGNAL_NORMALIZATION_FEEDBACK_STRENGTH, AFFINITY_MULT_RANGE, AFFINITY_EFFECT, ANTI_PENALTY_MAX) stay in the DSL: they generate into scoring_config under its existing module-wide #![allow(dead_code)], and removing them would cascade beyond the two verified orphans.

NO PIPELINE_VERSION bump

Every removed path was provably emitting nothing (pinned 1.0/0.0 inputs or empty-map reads), so stored scores cannot differ and a corpus re-stamp would be a no-op. Simulation/version-comparison suites confirm: all asserted precision numbers unchanged.

Skipped (fleet coordination)

src-tauri/src/commands.rs (inventory item 3: score-autopsy learned_affinities build+emit, the pinned "Learned Affinity" / "Anti-Topic Penalty" components, and score_tuning_snapshot's mislabeled feedback_interaction_count field) — the file is claimed by worktree-agent-a01f9610ade32c536, so per protocol its changes were skipped. Verified compile-safe: commands.rs references only the kept pinned breakdown fields and the kept quarantined map, none of the deleted symbols. The FE side of the autopsy (render block, interface field, autopsy.learnedPreferences en-only locale key) IS removed — the backend's extra JSON field is simply ignored.

Observation (not fixed here)

context_engine.rs carries a duplicate topic_affinities CREATE TABLE schema alongside the canonical one in ace/db.rs — a schema-drift hazard of exactly the class that produced the two phantom-schema bugs deleted above.

Verification

  • cargo fmt clean; cargo test --lib 4372 passed / 0 failed / 8 ignored; cargo clippy --lib -- -D warnings clean
  • pnpm install --frozen-lockfile; pnpm run i18n:types (no diff); pnpm run typecheck clean; pnpm run test 1242 passed / 0 failed (111 files)
  • npx eslint clean on all touched TS files
  • node scripts/check-file-sizes.cjs — no errors (48 pre-existing warnings)
  • node scripts/check-retired-claims.cjs — OK
  • node scripts/ghost-commands.cjs — 0 new ghosts, 0 unregistered, 0 stale backlog
  • node scripts/validate-commands.cjs — 383/383/383 consistent
  • No new #[allow(dead_code)]
  • Rebased onto origin/main (690ced1) before push; no file overlap with fix(tier-truth): sell only reachable Signal features — Blind Spots + Knowledge Gaps #473

🤖 Generated with Claude Code

https://claude.ai/code/session_01MMarGhXjbKyNJzsm3JG1jw

…AD-029/AD-030 arc)

Removes every learned-affinity surface that is STRUCTURALLY DEAD — provably
unreachable or provably no-op — and nothing that is live. Four proof classes:

- Pinned inputs: pipeline_v2 pins affinity_mult=1.0 / anti_penalty=0.0, so the
  learned-axis strength branch, the _anti_mult binding, the LearnedPreference
  explanation factor (weight = max(0.0, 1.0-1.0), never fires), and the probe
  engine's ax_learned condition could never produce output.
- Empty-map reads: the AD-029 quarantined loader returns an empty
  topic_affinities map, so compute_affinity_multiplier / compute_anti_penalty
  (and their channel_render call + affinity_summary prompt line), the
  explanation confidence contribution, the two semantic-embeddings pre-warm /
  assembly loops, and the frontend learnedAffinities/antiTopics store state
  (+ its 500ms refresh round-trip) always saw nothing. ctx.feedback_boosts was
  a hardcoded empty map, so the feedback_boost computation always yielded 0.0;
  the now-unread field was deleted with it.
- Phantom schema (pre-existing bugs, now deleted rather than shipped broken):
  weekly_digest::collect_topics queried a nonexistent ace_topic_affinities
  table (real table: topic_affinities) — empty top_topics since the day it was
  written; developer_dna::get_blind_spots filtered on a phantom weight column
  (real column: affinity_score) — prepare failed, blind_spots always [].
- Unreachable branches / zero callers: gate's learned axis never confirms
  (learned_confirmed = false), dead commands ace_get_single_affinity +
  get_learning_stats (handler, registration, CommandMap types, victauri
  allowlist entry), the persona-posterior READ side (dominant persona, persona
  boosts, drift detection + posterior_snapshots), stability_detector's three
  unused query fns, and the simulation affinity-injection arms.

KEPT: capture/writer paths (tracking, decay, telemetry, persona-posterior
write side), the Learned Preferences panel + preference_commands, the AD-029
quarantined loader + its guard test, ace_get_topic_affinities /
ace_get_anti_topics (live readers of real rows — backlogged as ghosts after
their dead frontend caller was removed), and the affinity_mult / anti_penalty /
feedback_boost FIELDS in ScoreBreakdown, still pinned 1.0/0.0/0.0 — stored
score_breakdown JSON in user databases carries them.

DSL: removed the two orphaned generated constants (semantic_boost.affinity_clamp,
engagement_weights.affinity_w — zero src references). The other affinity/feedback
constants stay in the DSL: they generate into scoring_config under its existing
module-wide dead-code allowance and removing them would cascade beyond the two
verified orphans.

NO PIPELINE_VERSION bump: every removed path was provably emitting nothing
(pinned 1.0/0.0 inputs or empty-map reads), so stored scores cannot differ and
a corpus re-stamp would be a no-op.

Observation (not fixed here): context_engine.rs carries a duplicate
topic_affinities CREATE TABLE schema alongside ace/db.rs — a drift hazard of
the same phantom-schema class as the two bugs above.

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:19
@runyourempire
runyourempire merged commit a15bcc7 into main Aug 16, 2026
15 checks passed
@runyourempire
runyourempire deleted the worktree-agent-a2dd3b8c178ec2bcb branch August 16, 2026 15:38
runyourempire added a commit that referenced this pull request Aug 16, 2026
…uarantine — PIPELINE_VERSION 20 (#476)

## 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.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 17, 2026
…commands.rs, stale affinity docs (#479)

## The residual this closes

The half of #474 that was skipped because `src-tauri/src/commands.rs`
was claimed by the #471 lane (now merged). Inventory item 3 of the v20a
dead-surface sweep, tracked in `.claude/plans/PENDING-DECISION.md` item
2.

## Removed from `commands.rs` (all structurally dead, same proof classes
as #474)

- **`mcp_score_autopsy` "Learned Affinity" component** —
`bd.affinity_mult` is pinned `1.0_f32` (`pipeline_v2.rs:614`), so
`(bd.affinity_mult - 1.0).abs() > 0.01` could never fire. Pinned-input
class.
- **`mcp_score_autopsy` "Anti-Topic Penalty" component** —
`bd.anti_penalty` is pinned `0.0_f32` (`pipeline_v2.rs:615`), so `>
0.01` could never fire. Pinned-input class.
- **`matching_affinities` build + `"learned_affinities"` emit** — reads
`ace_ctx.topic_affinities`, which the AD-029 quarantined loader returns
empty; always `[]`. Empty-map-read class. The FE render side was already
removed in #474; the autopsy type has no `learned_affinities` field.
- **`score_tuning_snapshot`'s `feedback_interaction_count`** —
mislabeled: its value was `ace_ctx.topic_affinities.len()` (always 0 via
the quarantined loader), not a feedback-interaction count. The real
`feedback_interaction_count` concept (scoring-context bootstrap
detection, taste-test seeding) is untouched.

`commands.rs` now has zero `topic_affinities` references. The capture
side (`run_background_behavior_decay` → `apply_behavior_decay`) is
deliberately untouched — that is v20b operator territory.

## Also cleaned

- `src/components/ScoreAutopsy.test.tsx` — stale `learned_affinities`
fixture line (the interface field was removed in #474; the fixture
carried dead data).
- **Two docs still described the retired scoring path as live**
(discovered while verifying consumers):
- `docs/GETTING_STARTED.md` told users scores come from "Topic Affinity:
Learned preferences from your interactions" and an affinity/anti-penalty
formula. Replaced with the actual scoring inputs (context similarity,
interests, stack/deps, freshness/quality).
- `docs/ARCHITECTURE-DETAILED.md` — the PASIFA formula's Steps 5–6
(affinity multiplier, anti-topic penalty), the pipeline flow's "Apply
affinity multiplier (learned behavior)" step, and the Relevance Judge
diagram entry. Replaced with the v20 reality + a pointer to the PASIFA
V2 DSL. Capture-side descriptions (tables, interaction writers, decay)
are left as-is — they are still true and pending the operator's v20b
call.

## NO PIPELINE_VERSION bump

Nothing here touches scoring — only presentation surfaces (autopsy JSON,
dev-time tuning snapshot) that provably emitted nothing, plus docs.
Stored scores cannot differ.

## Verification

- `cargo fmt` clean; `cargo test --lib commands::` targeted pass; clippy
via pre-push gate
- `npx vitest run src/components/ScoreAutopsy.test.tsx` — 5/5
- `npx tsc --noEmit` clean; `npx eslint` clean on touched TS
- `node scripts/check-file-sizes.cjs` — no new errors (commands.rs
shrank 40 lines)
- `grep topic_affinities src-tauri/src/commands.rs` — zero hits

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

https://claude.ai/code/session_01LBY5q2MskiKMkTm6NmB49L

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
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