musememory 2.3.0 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/.agents/artifacts/2026-10-20-lifeos-memory-distillation-plan.md +865 -0
  2. package/.agents/artifacts/HANDOFF.md +22 -0
  3. package/.agents/artifacts/audit-and-realigned-roadmap-20261015.md +152 -0
  4. package/.agents/artifacts/bench-graph-baseline.json +519 -0
  5. package/.agents/artifacts/bench-graph-baseline.md +139 -0
  6. package/.agents/artifacts/brief-dayos-inspired-site-redo.md +89 -0
  7. package/.agents/artifacts/handoff-20261015-143202.md +109 -0
  8. package/.agents/artifacts/plan-competitor-adaptation-dashboard-graph.md +99 -0
  9. package/.agents/artifacts/session-report-2026-10-01-memory-gaps-and-website.md +94 -0
  10. package/.agents/artifacts/wave-3-sdd-ledger.md +18 -0
  11. package/.agents/artifacts/wave-4-sdd-ledger.md +18 -0
  12. package/.agents/context/architecture.md +1 -0
  13. package/.agents/context/current.md +166 -3
  14. package/.agents/context/decisions.md +4 -0
  15. package/.agents/context/deep-research-agentic-memory-evolution.md +261 -0
  16. package/.agents/context/deep-research-memory-adaptation-2026-10.md +107 -0
  17. package/.agents/context/deep-research-memory-improvement-2026-10.md +420 -0
  18. package/.agents/context/deep-research-memory-mechanisms-2026-09.md +334 -0
  19. package/.agents/context/index.md +5 -0
  20. package/.agents/context/roadmap.md +361 -7
  21. package/.agents/context/ticket-plan.md +553 -0
  22. package/.agents/plans/2026-10-20-wave-22-failure-attribution-negative-mining-design.md +198 -0
  23. package/.agents/plans/2026-10-20-wave-22-failure-attribution-negative-mining-plan.md +274 -0
  24. package/.agents/plans/EVOLUTION_PLAN.md +351 -0
  25. package/.agents/plans/local-embeddings-llama-cpp.md +37 -0
  26. package/.agents/plans/recall-eval-harness.md +31 -0
  27. package/.agents/research/ecosystem-teardown-2026-10.md +289 -0
  28. package/.agents/research/research-brief-walrus-memory-architecture.md +189 -0
  29. package/.agents/research/retirement-audit-2026-10.md +45 -0
  30. package/.agents/standards/git-workflow.md +5 -0
  31. package/.agents/standards/workflows.md +13 -0
  32. package/README.md +137 -56
  33. package/dist/index.js +20579 -9092
  34. package/package.json +20 -10
  35. package/schema.json +39 -2
@@ -0,0 +1,198 @@
1
+ # 🏛️ Wave 22 Design Specification: Failure Attribution & Negative Memory Mining
2
+
3
+ > **Version Target**: `v2.11.0`
4
+ > **Status**: APPROVED SPECIFICATION
5
+ > **Date**: 2026-10-20
6
+ > **Author**: Muse (Chief Agency Orchestrator) & Nexus (Quality Gate)
7
+ > **Tracked Tickets**: `T-313`, `T-144`, `T-314`, `T-315`
8
+ > **Related Epics**: R17b (Ecosystem Teardown), v2 Gap Audit, LangMem Frequency Modeling
9
+
10
+ ---
11
+
12
+ ## 1. Executive Summary & Goals
13
+
14
+ Wave 22 hardens Muse Memory's cognitive learning and retrieval quality loops across four foundational axes:
15
+
16
+ 1. **Scoped Failure Attribution (`T-313`)**: Scopes command and test regressions (`isRegression = exitCode !== 0`) strictly to memories with matching code anchors, affected paths, or specific symbols. Replaces the naive 3-strike immediate demotion with session-deduplicated strikes and a dual-decay counter (2 clean runs or 30 days), protecting innocent architectural guidelines and preferences from false-positive disputes.
17
+ 2. **Trajectory Fix-Pair Mining (`T-144`)**: Detects sequential trajectories of `Error ➔ Remediation ➔ No Recurrence` across session observations. Distills them into candidate negative memories (`AVOID: ...`) with sanitized error reasons, verified alternatives, and template-safe reproduction commands.
18
+ 3. **Source-Tagged Recall Hits & HOT.md (`T-314`)**: Connects the compiled `.memory/HOT.md` working cache directly into the retrieval engine, tagging candidate hits with origin channels (`hot`, `fts`, `vector`, `tree`, `distilled`) and applying relevance-gated provenance bonuses.
19
+ 4. **LangMem Frequency Rank Axis (`T-315`)**: Upgrades linear access counters to a mathematically bounded logarithmic frequency curve, blending retrieval frequency with verified application success.
20
+
21
+ ---
22
+
23
+ ## 2. Invariants & Guardrails
24
+
25
+ - **Zero External Daemons**: All attribution, distillation, and scoring executes in-process via Bun and SQLite (`memory.db`).
26
+ - **Constitutional Protection Gate**: Memories marked with `type: "constraint"`, `temporal_mode: "timeless"`, or `salience >= 0.95` can never be auto-disputed by automated test evaluations.
27
+ - **Vibeguard Secret Defense**: All mined error snippets, terminal commands, and failure logs are scrubbed via `scanSecrets` before candidate creation or audit logging.
28
+ - **Template-Safe Test Commands (`T-001`)**: Reproduction commands must strictly conform to allowed safe templates (`bun test <relative-file>`, `bunx tsc --noEmit`, `node --check <file>`); arbitrary shell commands are kept strictly in documentation text.
29
+ - **Zero-Migration Compatibility**: New utility metrics live safely within the existing `data` JSON blob and lazily backfill on access without altering SQLite table structures.
30
+
31
+ ---
32
+
33
+ ## 3. Detailed Component Architecture
34
+
35
+ ### Section 1: Scoped Failure Attribution & Decaying Strike Engine (`T-313`)
36
+
37
+ #### 1.1 Relevance Detection (`isMemoryRelevantToFailure`)
38
+ In `src/learning/feedback.ts`:
39
+ ```typescript
40
+ export interface FailureRelevanceContext {
41
+ command?: string;
42
+ logs?: string;
43
+ exitCode: number;
44
+ project: string;
45
+ }
46
+
47
+ export function isMemoryRelevantToFailure(
48
+ entry: MemoryEntry,
49
+ context: FailureRelevanceContext,
50
+ ): boolean;
51
+ ```
52
+ A memory is relevant to a failure if and only if:
53
+ 1. **Code Anchors**: Any anchor file or symbol in `entry.anchors` matches the failure context using word boundaries:
54
+ - File match: `matchesWordBoundary(context.command + " " + context.logs, anchor.file)` or exact basename match.
55
+ - Symbol match: Symbol has `calculateSymbolSpecificity(anchor.symbol) > 0.3` and `matchesWordBoundary(context.logs, anchor.symbol)`.
56
+ 2. **Affected Paths**: Any path in `entry.graph?.affected_paths` matches paths referenced in `context.command` or `context.logs`.
57
+ 3. **Reproduction Command**: `entry.test_command` or `entry.negative?.reproduction_command` matches `context.command`.
58
+
59
+ Memories without anchor or symbol affinity are classified as **bystanders** and are exempt from regression strikes.
60
+
61
+ #### 1.2 Data Structures & Strike State
62
+ In `src/types.ts`:
63
+ ```typescript
64
+ export interface MemoryUtility {
65
+ retrieval_count: number;
66
+ application_count: number;
67
+ successful_applications: number;
68
+ failed_applications: number;
69
+ regressions: number;
70
+ contradictions: number;
71
+ reuse_success_rate: number;
72
+ last_applied_at?: string;
73
+ // Wave 22 Additions (T-313)
74
+ regression_strikes?: number; // Active un-decayed corroborated strikes (0-3)
75
+ last_regression_at?: string; // ISO timestamp of latest attributed failure
76
+ last_regression_session?: string; // Session ID to deduplicate retry loops
77
+ clean_runs_since_regression?: number; // Count of clean runs since last strike
78
+ }
79
+ ```
80
+
81
+ #### 1.3 Strike Accumulation, Deduplication & Decay Dynamics
82
+ In `src/quality/utility.ts`:
83
+ - **Session Deduplication**: At most **1 regression strike** is added per session (or 10-minute window) per memory, regardless of how many times a test is retried in that turn.
84
+ - **Dual Decay Ladder**:
85
+ - **Usage Decay**: Each consecutive successful application increments `clean_runs_since_regression`. Every **2 clean runs**, `regression_strikes = Math.max(0, regression_strikes - 1)`.
86
+ - **Time Decay**: If `now - last_regression_at > 30 days`, active strikes decay by 1.
87
+ - **Demotion Threshold**:
88
+ - `entry.status` flips from `"confirmed"` to `"disputed"` **only if**:
89
+ $$\text{regression\_strikes} \ge 3 \quad \text{AND} \quad \text{entry.type} \ne \text{"constraint"} \quad \text{AND} \quad \text{entry.salience} < 0.95$$
90
+ - When auto-disputed, an audit event `dispute_triggered` is logged with the full strike history.
91
+
92
+ ---
93
+
94
+ ### Section 2: Trajectory Fix-Pair Mining (`T-144`)
95
+
96
+ #### 2.1 The Trajectory Pattern
97
+ Session observations in `.memory/observations.jsonl` are inspected for pairs:
98
+ $$\text{Observation } A \text{ (Failure)} \xrightarrow{\le 5 \text{ turns}} \text{Observation } B \text{ (Success)}$$
99
+
100
+ #### 2.2 Target & Command Affinity Matching
101
+ To prevent pairing unrelated commands (e.g. `git push` network failure paired with `ls -la`), Event $B$ is validated against Event $A$:
102
+ 1. **Exclude Informational Commands**: Event $B$ cannot be a read/informational command (`ls`, `cat`, `git status`, `pwd`, `echo`, `find`).
103
+ 2. **Affinity Rules**: Event $B$ must satisfy at least one condition:
104
+ - Same command or file target as Event $A$ (verifying the error was cleared).
105
+ - Toolchain remedy verb (e.g. `bun add <pkg>`, `bun install`, package update) following a missing module/dependency error.
106
+ - Same test suite or script with green exit code (`exitCode === 0`).
107
+
108
+ #### 2.3 Error Signature Normalization & Deduplication
109
+ - Error messages are normalized:
110
+ - Strip dynamic line/column numbers (`:\d+:\d+`).
111
+ - Strip memory addresses, timestamps, and thread IDs.
112
+ - Collapse consecutive attempts of the same normalized signature into a single failure block.
113
+ - Deduplication Hash:
114
+ $$\text{dedupHash} = \text{sha256}(\text{normalizedApproach} + "::" + \text{normalizedErrorSignature})$$
115
+
116
+ #### 2.4 Candidate Proposal
117
+ Via `recordNegativeLesson(store, ...)` in `src/learning/negative.ts`:
118
+ - `title`: `AVOID: <concise summary of failed approach>`
119
+ - `status`: `"candidate"` (never auto-promoted)
120
+ - `salience`: 0.75
121
+ - `temporal_mode`: `"timeless"`
122
+ - `failed_approach`: Event $A$ command/input
123
+ - `failure_reason`: Sanitized error text (Vibeguard-scrubbed)
124
+ - `alternative_recommended`: Event $B$ successful remediation command
125
+ - `source_ids`: `[eventA.id, eventB.id]`
126
+ - `tags`: `["fix-pair", "mined-trajectory", "anti-pattern"]`
127
+ - **Volume Cap**: Maximum **3 candidates** proposed per harvest pass.
128
+
129
+ ---
130
+
131
+ ### Section 3: Scoring Model & Retrieval Pipeline (`T-314` & `T-315`)
132
+
133
+ #### 3.1 Retrieval Source Channels (`T-314`)
134
+ ```typescript
135
+ export type RetrievalSourceChannel = "hot" | "fts" | "vector" | "tree" | "distilled";
136
+ ```
137
+
138
+ #### 3.2 In-Memory HOT.md Cache
139
+ In `src/compounding/temporal.ts`:
140
+ - Maintain an in-memory `hotCacheState: { mtime: number; ids: Set<string> }`.
141
+ - Check file `mtime` before reading `.memory/HOT.md`. If unchanged, return memoized `ids` in $<1\mu\text{s}$.
142
+
143
+ #### 3.3 Relevance-Gated Source Bonus
144
+ In `src/retrieval.ts`:
145
+ - Base source weights:
146
+ - `hot`: $+0.20$
147
+ - `fts`: $+0.15$
148
+ - `vector`: $+0.15$
149
+ - `tree`: $+0.10$
150
+ - `distilled`: $+0.08$
151
+ - **Relevance Gate**:
152
+ `sourceBonus` is applied **only if**:
153
+ $$\text{baseApplicability} > 0 \lor \text{bm25Match} > 0 \lor \text{exactSymbolMatch} > 0 \lor \text{semanticMatch} > 0$$
154
+ This prevents hot memory "zombie distraction" on totally unrelated queries.
155
+ - Multi-channel cap: $\text{sourceBonus} \le +0.25$.
156
+
157
+ #### 3.4 Logarithmic LangMem Frequency Axis (`T-315`)
158
+ In `computeFactors` (`src/retrieval.ts`):
159
+ - Effective Count:
160
+ $$\text{effectiveCount} = \text{access\_count} + 2 \times (\text{utility.successful\_applications} \mathbin{??} 0)$$
161
+ - Frequency Curve:
162
+ $$\text{frequencyScore} = 0.25 \times \frac{\ln(1 + \text{effectiveCount})}{\ln(1 + 50)}$$
163
+ - Recency Modulation:
164
+ - If `daysSince(last_accessed_at) <= 7`: $+0.05$ boost.
165
+ - If `daysSince(last_accessed_at) > 60`: frequency bonus decayed by $0.7\times$.
166
+ - Expose `frequencyScore` and `source_channels` in `ScoreFactors` and `deriveWhyRetrieved`.
167
+
168
+ ---
169
+
170
+ ## 4. Error Handling & Audit Telemetry
171
+
172
+ ### 4.1 Defensive Try/Catch Wrappers
173
+ - All failure evaluation and fix-pair mining calls run wrapped in try/catch blocks; errors emit `console.warn` and return neutral results without failing agent turns.
174
+ - Timestamp injection (`now?: number`) is supported on all utility and evaluation methods to guarantee 100% deterministic testing.
175
+
176
+ ### 4.2 Structured Audit Events
177
+ Log four distinct operations to `.memory/audit.jsonl`:
178
+ 1. `regression_strike`: Memory ID, matched anchor, failing command, strike count.
179
+ 2. `strike_decay`: Memory ID, decay reason (`clean_runs` or `time`), remaining strikes.
180
+ 3. `dispute_triggered`: Memory ID, total regressions, corroborating strike history.
181
+ 4. `fix_pair_mined`: Candidate ID, failed approach, successful remedy.
182
+
183
+ ---
184
+
185
+ ## 5. Verification & Test Plan
186
+
187
+ | Test File | Target Ticket | Key Assertions |
188
+ |---|---|---|
189
+ | `test/failure_attribution.test.ts` | `T-313` | - Anchor/symbol match increments strike<br>- Bystander memory ignored on exit != 0<br>- 1 strike max per session retry loop<br>- 2 clean runs decay strike<br>- 30 days decay strike<br>- Constraints cannot be auto-disputed |
190
+ | `test/fix_pair_mining.test.ts` | `T-144` | - Error + success pairs into candidate negative memory<br>- Informational commands (`ls`, `pwd`) rejected as remedies<br>- Normalized error deduplication<br>- Vibeguard secret scrubbing<br>- Session volume capped at 3 |
191
+ | `test/source_tagging_frequency.test.ts` | `T-314`, `T-315` | - Memoized `HOT.md` candidate lookup<br>- Irrelevant hot entries receive zero bonus<br>- Logarithmic frequency curve ($0 \to 0, 5 \to \approx 0.11, \ge 50 \to 0.25$)<br>- `deriveWhyRetrieved` outputs `source:*` and `freq:*` tokens |
192
+
193
+ ### Gate Verification Commands
194
+ 1. `bun test test/failure_attribution.test.ts test/fix_pair_mining.test.ts test/source_tagging_frequency.test.ts`
195
+ 2. `bun test` (full suite, 527+ tests green)
196
+ 3. `bunx tsc --noEmit` (clean, 0 type errors)
197
+ 4. `bun run build` (build completes without warnings)
198
+ 5. `bun ~/.config/LIFEOS/runtime/TOOLS/SecretScan.ts .` (0 secret leaks)
@@ -0,0 +1,274 @@
1
+ # Wave 22: Failure Attribution & Negative Memory Mining Implementation Plan
2
+
3
+ > **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:executing-plans or superpowers:subagent-driven-development to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
4
+
5
+ **Goal:** Implement scoped failure attribution with decaying strikes (T-313), trajectory fix-pair mining into candidate negative memories (T-144), source-tagged recall hits with HOT.md cache (T-314), and LangMem logarithmic frequency ranking (T-315).
6
+
7
+ **Architecture:** Extend existing feedback, utility, distillation, and retrieval scoring engines in-process with zero external daemons. Keep schema backward-compatible, enforce template-gated test reproduction, and maintain sub-2ms retrieval performance.
8
+
9
+ **Tech Stack:** TypeScript, Bun, SQLite (via `bun:sqlite`), FTS5, Vitest/Bun test runner.
10
+
11
+ ## Global Constraints
12
+ - Pinned to Bun runtime (`bun test`, `bun run build`, `tsc --noEmit`).
13
+ - Zero resident external daemons; all logic executes in-process.
14
+ - Zero secret exposure: Vibeguard SecretScan on all mined error snippets and terminal commands.
15
+ - Constitutional protection gate: `type: "constraint"`, `temporal_mode: "timeless"`, or `salience >= 0.95` can never be auto-disputed.
16
+ - Template-gated reproduction commands: only allowlisted templates (`bun test <relative-file>`, `bunx tsc --noEmit`, `node --check <file>`) allowed as `test_command`.
17
+
18
+ ---
19
+
20
+ ### Task 1: Scoped Failure Attribution (`T-313`)
21
+
22
+ **Files:**
23
+ - Modify: `src/learning/feedback.ts`
24
+ - Test: `test/failure_attribution.test.ts`
25
+
26
+ **Interfaces:**
27
+ - Produces: `isMemoryRelevantToFailure(entry: MemoryEntry, context: FailureRelevanceContext): boolean`
28
+ - Updates: `evaluateSessionOutcomes(store: Store, options: SessionOutcomeEvaluationOptions): SessionOutcomeResult`
29
+
30
+ - [ ] **Step 1: Write failing tests for failure relevance detection**
31
+ Create `test/failure_attribution.test.ts` asserting:
32
+ 1. An entry with an anchor matching the failure file/symbol receives `regression: true`.
33
+ 2. An entry whose anchor does not match the failure context is classified as a bystander and does NOT receive `regression: true`.
34
+ 3. Low-specificity symbols (e.g. `id`, `get`) do not trigger false attribution.
35
+
36
+ - [ ] **Step 2: Run test to verify it fails**
37
+ Run: `bun test test/failure_attribution.test.ts`
38
+ Expected: FAIL (cannot find `isMemoryRelevantToFailure` or bystander memory gets regression).
39
+
40
+ - [ ] **Step 3: Implement `isMemoryRelevantToFailure` in `src/learning/feedback.ts`**
41
+ Add relevance matching:
42
+ 1. Anchor file basename and symbol match via `matchesWordBoundary` with specificity $> 0.3$.
43
+ 2. Affected path match in `entry.graph?.affected_paths`.
44
+ 3. Test command match in `entry.test_command`.
45
+ Only mark `regression = isRegression && isRelevant` in `evaluateSessionOutcomes`.
46
+
47
+ - [ ] **Step 4: Run test to verify it passes**
48
+ Run: `bun test test/failure_attribution.test.ts`
49
+ Expected: PASS.
50
+
51
+ - [ ] **Step 5: Commit**
52
+ ```bash
53
+ git add src/learning/feedback.ts test/failure_attribution.test.ts
54
+ git commit -m "feat(learning): scope failure attribution to anchor-relevant memories (closes T-313 part 1)"
55
+ ```
56
+
57
+ ---
58
+
59
+ ### Task 2: Decaying Strike Engine & Constitutional Gate (`T-313`)
60
+
61
+ **Files:**
62
+ - Modify: `src/types.ts`
63
+ - Modify: `src/quality/utility.ts`
64
+ - Test: `test/failure_attribution.test.ts`
65
+
66
+ **Interfaces:**
67
+ - Extends: `MemoryUtility` with `regression_strikes`, `last_regression_at`, `clean_runs_since_regression`, `last_regression_session`.
68
+ - Updates: `recordApplicationOutcome(store: Store, options: ApplicationOutcomeOptions): MemoryEntry`
69
+
70
+ - [ ] **Step 1: Write failing tests for strike decay, session dedup, and constitutional gate**
71
+ In `test/failure_attribution.test.ts`, add test cases:
72
+ 1. Re-running the failing command 3 times within the same session ID adds at most 1 strike.
73
+ 2. 2 consecutive clean applications decay active strikes by 1.
74
+ 3. Simulating 30 days passing via `now?: number` parameter decays strikes by 1.
75
+ 4. Auto-dispute triggers only when `regression_strikes >= 3`.
76
+ 5. `type: "constraint"` or `salience >= 0.95` memories are immune to auto-dispute.
77
+
78
+ - [ ] **Step 2: Run test to verify it fails**
79
+ Run: `bun test test/failure_attribution.test.ts`
80
+ Expected: FAIL.
81
+
82
+ - [ ] **Step 3: Implement decaying strikes and constitutional gate in `src/quality/utility.ts`**
83
+ 1. Add `now?: number` and `sessionId?: string` to `ApplicationOutcomeOptions`.
84
+ 2. Update `ensureUtility` with default zero fields.
85
+ 3. In `recordApplicationOutcome`:
86
+ - If `options.regression`: check if `last_regression_session === options.sessionId`. If not, increment `regression_strikes`. Reset `clean_runs_since_regression = 0`.
87
+ - If `options.success`: increment `clean_runs_since_regression`. If $\ge 2$, decay 1 strike and reset count. Also check if `now - last_regression_at > 30 days`.
88
+ - Auto-dispute only if `regression_strikes >= 3` AND not constraint/salience $\ge 0.95$.
89
+ - Log audit events `regression_strike`, `strike_decay`, and `dispute_triggered`.
90
+
91
+ - [ ] **Step 4: Run test to verify it passes**
92
+ Run: `bun test test/failure_attribution.test.ts`
93
+ Expected: PASS.
94
+
95
+ - [ ] **Step 5: Commit**
96
+ ```bash
97
+ git add src/types.ts src/quality/utility.ts test/failure_attribution.test.ts
98
+ git commit -m "feat(quality): add decaying strike counter and constitutional immunity (closes T-313 part 2)"
99
+ ```
100
+
101
+ ---
102
+
103
+ ### Task 3: Trajectory Fix-Pair Mining (`T-144`)
104
+
105
+ **Files:**
106
+ - Modify: `src/learning/distill.ts`
107
+ - Modify: `src/compaction/harvester.ts`
108
+ - Test: `test/fix_pair_mining.test.ts`
109
+
110
+ **Interfaces:**
111
+ - Produces: `mineFixPairsFromObservations(observations: ObservationEvent[], options?: FixPairMiningOptions): FixPairCandidate[]`
112
+ - Integrates: `distillSessionObservations` & `harvestSessionMemories` to emit candidate negative memories.
113
+
114
+ - [ ] **Step 1: Write failing tests for fix-pair mining**
115
+ Create `test/fix_pair_mining.test.ts` asserting:
116
+ 1. A failing test command followed by a green test run produces a candidate negative memory (`AVOID: ...`).
117
+ 2. Read-only commands (`ls`, `cat`, `git status`) are rejected from remedy pairing.
118
+ 3. Error signature normalization collapses repetitive compiler line-number shifts.
119
+ 4. Secret tokens in error logs are scrubbed via Vibeguard before candidate creation.
120
+ 5. Volume cap limits candidates to at most 3 per session.
121
+
122
+ - [ ] **Step 2: Run test to verify it fails**
123
+ Run: `bun test test/fix_pair_mining.test.ts`
124
+ Expected: FAIL.
125
+
126
+ - [ ] **Step 3: Implement `mineFixPairsFromObservations` in `src/learning/distill.ts`**
127
+ 1. Traverse observations window, match failure $\to$ success within $\le 5$ events.
128
+ 2. Check target affinity and exclude informational commands.
129
+ 3. Normalize error text by stripping line/column coordinates and memory addresses.
130
+ 4. Pass through `scanSecrets`.
131
+ 5. Call `recordNegativeLesson(store, { confirmed: false, ... })` with volume cap of 3.
132
+ 6. Connect into `distillSessionObservations` and `harvestSessionMemories`.
133
+
134
+ - [ ] **Step 4: Run test to verify it passes**
135
+ Run: `bun test test/fix_pair_mining.test.ts`
136
+ Expected: PASS.
137
+
138
+ - [ ] **Step 5: Commit**
139
+ ```bash
140
+ git add src/learning/distill.ts src/compaction/harvester.ts test/fix_pair_mining.test.ts
141
+ git commit -m "feat(learning): add trajectory fix-pair mining into negative memories (closes T-144)"
142
+ ```
143
+
144
+ ---
145
+
146
+ ### Task 4: Source-Tagged Recall Hits & HOT.md (`T-314`)
147
+
148
+ **Files:**
149
+ - Modify: `src/compounding/temporal.ts`
150
+ - Modify: `src/retrieval.ts`
151
+ - Modify: `src/retrieval/ranking.ts`
152
+ - Test: `test/source_tagging_frequency.test.ts`
153
+
154
+ **Interfaces:**
155
+ - Produces: `getHotCandidateIds(store: Store, memoryDir: string): Set<string>`
156
+ - Extends: `ScoreFactors` with `source_channels?: RetrievalSourceChannel[]` and `sourceBonus: number`
157
+ - Updates: `computeFactors` and `rankAndRetrieveMemories`
158
+
159
+ - [ ] **Step 1: Write failing tests for HOT.md source tagging**
160
+ Create `test/source_tagging_frequency.test.ts` asserting:
161
+ 1. Entries in `.memory/HOT.md` are tagged with channel `"hot"`.
162
+ 2. Candidates with channel `"hot"` receive $+0.20$ bonus when applicable to the query.
163
+ 3. Completely irrelevant hot entries receive $+0$ bonus (relevance gate prevents zombie distraction).
164
+ 4. `deriveWhyRetrieved` outputs `source:hot` and `source:fts`.
165
+
166
+ - [ ] **Step 2: Run test to verify it fails**
167
+ Run: `bun test test/source_tagging_frequency.test.ts`
168
+ Expected: FAIL.
169
+
170
+ - [ ] **Step 3: Implement memoized `HOT.md` lookup and source tagging**
171
+ 1. In `src/compounding/temporal.ts`: add `getHotCandidateIds` with file `mtime` memoization.
172
+ 2. In `src/retrieval/ranking.ts`: ingest `HOT.md` candidate IDs and track `candidateSources: Map<string, Set<RetrievalSourceChannel>>`.
173
+ 3. In `src/retrieval.ts`: add `sourceBonus` to `ScoreFactors` in `computeFactors`, gated on non-zero applicability.
174
+ 4. Update `deriveWhyRetrieved` with `source:*` reason tokens.
175
+
176
+ - [ ] **Step 4: Run test to verify it passes**
177
+ Run: `bun test test/source_tagging_frequency.test.ts`
178
+ Expected: PASS.
179
+
180
+ - [ ] **Step 5: Commit**
181
+ ```bash
182
+ git add src/compounding/temporal.ts src/retrieval.ts src/retrieval/ranking.ts test/source_tagging_frequency.test.ts
183
+ git commit -m "feat(retrieval): wire HOT.md candidate source tagging into ranking (closes T-314)"
184
+ ```
185
+
186
+ ---
187
+
188
+ ### Task 5: LangMem Frequency Rank Axis (`T-315`)
189
+
190
+ **Files:**
191
+ - Modify: `src/retrieval.ts`
192
+ - Modify: `src/retrieval/ranking.ts`
193
+ - Test: `test/source_tagging_frequency.test.ts`
194
+
195
+ **Interfaces:**
196
+ - Extends: `ScoreFactors` with `frequencyScore: number`.
197
+ - Updates: `computeFactors` with logarithmic LangMem formula.
198
+
199
+ - [ ] **Step 1: Write failing tests for logarithmic frequency curve**
200
+ In `test/source_tagging_frequency.test.ts`, assert:
201
+ 1. `access_count = 0` produces `frequencyScore = 0`.
202
+ 2. `access_count = 5` produces `frequencyScore ≈ 0.11`.
203
+ 3. `access_count >= 50` smoothly caps at `0.25`.
204
+ 4. Successful applications boost effective count $2\times$ faster than passive retrieval.
205
+ 5. Recency boost adds $+0.05$ if accessed within 7 days.
206
+
207
+ - [ ] **Step 2: Run test to verify it fails**
208
+ Run: `bun test test/source_tagging_frequency.test.ts`
209
+ Expected: FAIL.
210
+
211
+ - [ ] **Step 3: Implement LangMem frequency curve in `src/retrieval.ts`**
212
+ Replace linear `access_count * 0.02` with:
213
+ $$\text{effectiveCount} = \text{access\_count} + 2 \times (\text{utility.successful\_applications} \mathbin{??} 0)$$
214
+ $$\text{frequencyScore} = 0.25 \times \frac{\ln(1 + \text{effectiveCount})}{\ln(1 + 50)}$$
215
+ Incorporate 7-day recency bonus and 60-day decay. Expose in `ScoreFactors` and `deriveWhyRetrieved` (`freq:high`, `freq:moderate`).
216
+
217
+ - [ ] **Step 4: Run test to verify it passes**
218
+ Run: `bun test test/source_tagging_frequency.test.ts`
219
+ Expected: PASS.
220
+
221
+ - [ ] **Step 5: Commit**
222
+ ```bash
223
+ git add src/retrieval.ts src/retrieval/ranking.ts test/source_tagging_frequency.test.ts
224
+ git commit -m "feat(retrieval): implement LangMem logarithmic frequency rank axis (closes T-315)"
225
+ ```
226
+
227
+ ---
228
+
229
+ ### Task 6: Full Verification Gate & Clean Build
230
+
231
+ **Files:**
232
+ - Entire codebase
233
+
234
+ - [ ] **Step 1: Run full test suite**
235
+ Run: `bun test`
236
+ Expected: All 85+ test files pass, 0 failures.
237
+
238
+ - [ ] **Step 2: Run type check**
239
+ Run: `bunx tsc --noEmit`
240
+ Expected: 0 errors.
241
+
242
+ - [ ] **Step 3: Run build**
243
+ Run: `bun run build`
244
+ Expected: Clean build, 0 warnings.
245
+
246
+ - [ ] **Step 4: Run pre-ship SecretScan**
247
+ Run: `bun ~/.config/LIFEOS/runtime/TOOLS/SecretScan.ts .`
248
+ Expected: 0 secrets detected.
249
+
250
+ ---
251
+
252
+ ### Task 7: Documentation & Agent Memory Synchronization (`/updatedocs` & `/updateagents`)
253
+
254
+ **Files:**
255
+ - Modify: `docs/failure-attribution-and-negative-mining.md` (new)
256
+ - Modify: `CHANGELOG.md`
257
+ - Modify: `README.md`
258
+ - Modify: `.agents/context/ticket-plan.md`
259
+ - Modify: `.agents/context/current.md`
260
+ - Modify: `.memory/CURRENT.md`
261
+
262
+ - [ ] **Step 1: Write detailed documentation**
263
+ Document scoped failure attribution, fix-pair mining, HOT.md source tagging, and LangMem frequency curves.
264
+
265
+ - [ ] **Step 2: Update CHANGELOG & README**
266
+ Record Wave 22 features, tickets `T-313`, `T-144`, `T-314`, `T-315`.
267
+
268
+ - [ ] **Step 3: Mark tickets landed in ticket-plan.md & update current.md**
269
+ Update tickets `T-313`, `T-144`, `T-314`, `T-315` from `[ ]` to `[x]`, advance shipped capabilities, and update working constraints.
270
+
271
+ - [ ] **Step 4: Commit documentation & agent context pass**
272
+ ```bash
273
+ git commit -m "docs(wave-22): document failure attribution, fix-pair mining, and frequency ranking"
274
+ ```