# ADR-106: Multi-Signal Gate+Rerank Activation for Neo4j

**Date:** 2026-03-15 | **Status:** ACCEPTED

## Context

CypherActivation uses a single signal (vector search cosine similarity) for node selection.
This means:
- High-PageRank hub nodes with poor semantic relevance can't be properly deprioritized
- Historically useful nodes get no preference boost
- Graph topology (link prediction) is computed but never used for activation
- An additive weighted-sum formula would let irrelevant hub nodes sneak past the semantic gate

We have 5 patent-protected innovations (EP26162901.8) available but not wired into activation:
Innovation #10 (Cross-query learning), #14 (Neo4j vector+graph search).

## Decision

Implement **Gate + Rerank** architecture in `MultiSignalActivation`:

**Phase 1 — GATE:** Vector search on chunk embeddings. Nodes below `min_score=0.15` are
discarded regardless of any other signal. Semantic similarity is the mandatory entry requirement.

**Phase 2 — RERANK:** Multiply (not add) the semantic score by bonus signals:
```
final = semantic × (1 + authority + memory + link + freshness)
```

Where:
- `authority` ∈ [0, 0.15]: Normalized PageRank (70%) + degree centrality (30%)
- `memory` ∈ [0, 0.15]: Activation memory usefulness × keyword overlap
- `link` ∈ [0, 0.10]: Adamic-Adar proximity to seed nodes (top-3 semantic hits)
- `freshness` ∈ [0, 0.05]: Exponential decay based on days since modification

**Key invariant:** Maximum amplification is 1.45×. A node with 0.1 semantic score can reach
at most 0.145 — still below the 0.15 gate. **Irrelevant nodes cannot be rescued by topology.**

**Why multiplicative, not additive:**
- Additive: `0.4×0.2 + 0.2×0.9 = 0.26` — a 0.2-semantic node passes due to high PageRank
- Multiplicative: `0.2 × 1.135 = 0.227` — same node stays low, semantic dominates

## Implementation

- `graqle/activation/multi_signal.py`: Gate + Rerank engine
- Single Cypher query fetches PageRank + degree + freshness for all candidates
- Second Cypher query computes Adamic-Adar to seed nodes
- Activation memory boosts from `.graqle/activation_memory.json`
- Falls back to CypherActivation if any Neo4j query fails

## Consequences

**Positive:**
- Semantic relevance always dominates — no "popular but irrelevant" activation
- Bonus signals break ties between equally-relevant nodes in favor of authoritative, recently-modified, historically-useful ones
- Uses existing patent-protected innovations (#10, #14) from EP26162901.8
- All bonus signal fetches are pre-computed or single Cypher queries (<50ms total)
- Transparent: `last_signals` dict exposes per-node score breakdown for debugging

**Negative:**
- Requires Neo4j with pre-computed PageRank (run `graq upgrade neo4j` or use traversal engine)
- Falls back to CypherActivation (single-signal) if topology data unavailable
- Adds ~20ms latency for bonus signal fetch (acceptable given 2000ms+ reasoning phase)

**Trade-offs:**
- Bonus caps are conservative (max 1.45× amplification) — could be tuned per-project
- Link prediction uses Adamic-Adar only (not Common Neighbors or PA) for speed
