diff --git a/CHANGELOG.md b/CHANGELOG.md index 827ee3bf6..f97a79d88 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,17 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [0.22.3] - 2026-07-22 ### Fixed +- `specs/004-memory`: `004-16-memory-type-aware-retrieval.md` and `004-16-shadow-memory-safety.md` + both claimed the `004-16` slot (issue #6636, found during the spec audit in #6629). Renamed + shadow-memory-safety to `004-19` and synced all 26 rustdoc citation sites across `crates/` + (MAGE/`TrajectoryRiskAccumulator`/shadow-memory citations moved to `004-19`; MemGuard/ + type-aware-retrieval citations stay at `004-16`), plus the Obsidian wikilinks in + `004-memory/spec.md` and the cross-directory reference in + `083-memory-write-consent-gate/spec.md`. Also added an authoritative statement in + `specs/004-memory/spec.md` resolving which of three coexisting edge-strengthening mechanisms + (A-MEM `retrieval_count` boost, Benna-Fusi dual-rate `confidence_fast`/`confidence_slow`, + HeLa-Mem Hebbian `weight`) governs real graph traversal today, grounded in file:line + citations against `crates/zeph-memory/src/graph/` (issue #6635). - `.github/workflows/ci-non-linux.yml`: the sharded macOS/Windows `Test` jobs intermittently crashed with `fatal runtime error: stack overflow, aborting` on `serve::agent_factory::tests::build_agent_factory_gates_trust_state_independently_per_session` diff --git a/crates/zeph-common/src/audit.rs b/crates/zeph-common/src/audit.rs index 55c25c421..042708568 100644 --- a/crates/zeph-common/src/audit.rs +++ b/crates/zeph-common/src/audit.rs @@ -9,7 +9,7 @@ /// Signal type emitted by a sanitizer subsystem. /// -/// Variants correspond to the four signal classes defined in spec 004-16, FR-007. +/// Variants correspond to the four signal classes defined in spec 004-19, FR-007. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] #[non_exhaustive] pub enum AuditSignalType { diff --git a/crates/zeph-config/src/memory/persona.rs b/crates/zeph-config/src/memory/persona.rs index 91785ee3d..4ffd4a63d 100644 --- a/crates/zeph-config/src/memory/persona.rs +++ b/crates/zeph-config/src/memory/persona.rs @@ -204,7 +204,7 @@ impl Default for TreeConfig { } } -// ── TrajectoryRiskAccumulator config (spec 004-16) ───────────────────────────── +// ── TrajectoryRiskAccumulator config (spec 004-19) ───────────────────────────── fn validate_tra_nonneg_weight<'de, D>(deserializer: D) -> Result where @@ -337,7 +337,7 @@ impl Default for TrajectorySeverityMultipliers { } } -/// Configuration for the MAGE trajectory risk accumulator (spec 004-16). +/// Configuration for the MAGE trajectory risk accumulator (spec 004-19). /// /// Controls how per-turn safety signals accumulate into a session-level risk score /// and when tool execution is blocked or escalated. @@ -410,7 +410,7 @@ impl TrajectoryRiskAccumulatorConfig { /// `[escalation_threshold, risk_threshold)` band becomes empty) — the hard block /// (`is_blocked`) still works, so this is a degraded-but-safe misconfiguration, not a /// security gap; validation exists to surface it instead of leaving it silent (critic - /// finding F4, spec 004-16). + /// finding F4, spec 004-19). /// /// # Errors /// diff --git a/crates/zeph-config/src/memory/root.rs b/crates/zeph-config/src/memory/root.rs index 1b0838d6c..ffa336490 100644 --- a/crates/zeph-config/src/memory/root.rs +++ b/crates/zeph-config/src/memory/root.rs @@ -482,7 +482,7 @@ pub struct MemoryConfig { /// key facts, and promotes them to the semantic tier in `zeph_key_facts`. #[serde(default)] pub episodic_consolidation: EpisodicConsolidationConfig, - /// MAGE shadow memory trajectory risk accumulator (spec 004-16). + /// MAGE shadow memory trajectory risk accumulator (spec 004-19). /// /// Maintains a per-session rolling risk score fed by sanitizer audit signals. /// When `shadow_memory.enabled = true`, tool execution is gated if cumulative diff --git a/crates/zeph-core/src/agent/mod.rs b/crates/zeph-core/src/agent/mod.rs index 8671fc321..84c8d2bf5 100644 --- a/crates/zeph-core/src/agent/mod.rs +++ b/crates/zeph-core/src/agent/mod.rs @@ -1031,7 +1031,7 @@ impl Agent { self.runtime.lifecycle.turn_tool_calls = 0; // Spec 050 §2: drain pending risk signals from executor layers before advancing. - // Also advance MAGE accumulator (spec 004-16 FR-009) and ingest mapped signals. + // Also advance MAGE accumulator (spec 004-19 FR-009) and ingest mapped signals. { use crate::agent::trajectory::{RiskSignal, VigilRiskLevel}; use zeph_memory::shadow::{AuditSignalType as MageSignal, Severity as MageSev}; @@ -1043,14 +1043,14 @@ impl Agent { for code in pending { let signal = RiskSignal::from_code(code); self.services.security.trajectory.record(signal); - // Map RiskSignal to MAGE AuditSignalType + Severity (spec 004-16 FR-002, FR-007). + // Map RiskSignal to MAGE AuditSignalType + Severity (spec 004-19 FR-002, FR-007). // Matching on the already-decoded `RiskSignal` (rather than the raw `code`) // keeps this in sync with `RiskSignal::from_code`, the single source of truth - // for the code-to-meaning table. Only the four spec-004-16 signal classes have a + // for the code-to-meaning table. Only the four spec-004-19 signal classes have a // MAGE equivalent; the remaining RiskSignal variants (OutOfScope, PiiRedaction, // ToolFailure, HighCallRate, UnusualReadVolume, ToolPairTransition, // ExfilReadThenSend, CredThenEgress, and VigilFlagged(Low)) are trajectory-only - // and intentionally not surfaced to MAGE (spec 004-16's four classes are a fixed + // and intentionally not surfaced to MAGE (spec 004-19's four classes are a fixed // set; widening MAGE's mapping is a separate, spec-governed change, not part of // #6561/F2's scope, which only fixes these two signals' TrajectorySentinel // weight). diff --git a/crates/zeph-core/src/agent/state/mod.rs b/crates/zeph-core/src/agent/state/mod.rs index b95b0fea4..393eefa73 100644 --- a/crates/zeph-core/src/agent/state/mod.rs +++ b/crates/zeph-core/src/agent/state/mod.rs @@ -461,7 +461,7 @@ pub(crate) struct SecurityState { /// `None` by default. When `Some`, `begin_turn()` calls `reset()` to clear per-turn state. /// The same `Arc` must be passed to `ShellExecutor::with_risk_chain` at build time. pub(crate) risk_chain_accumulator: Option>, - /// MAGE trajectory risk accumulator (spec 004-16). + /// MAGE trajectory risk accumulator (spec 004-19). /// /// Per-session in-memory accumulator that ingests sanitizer audit signals with exponential /// temporal decay and gates tool execution when cumulative risk exceeds `risk_threshold`. diff --git a/crates/zeph-core/src/agent/tests/mage_signal_mapping_tests.rs b/crates/zeph-core/src/agent/tests/mage_signal_mapping_tests.rs index 85c11cf50..2f743caa8 100644 --- a/crates/zeph-core/src/agent/tests/mage_signal_mapping_tests.rs +++ b/crates/zeph-core/src/agent/tests/mage_signal_mapping_tests.rs @@ -4,7 +4,7 @@ //! Tests for #6272: `Agent::begin_turn` maps drained `RiskSignal`s to MAGE //! `(AuditSignalType, Severity)` pairs by matching on the already-decoded `RiskSignal` enum //! rather than re-deriving the mapping from the raw `u8` signal code. These tests pin the -//! resulting mapping table (spec 004-16 FR-002/FR-007) so a future refactor of either +//! resulting mapping table (spec 004-19 FR-002/FR-007) so a future refactor of either //! `RiskSignal::from_code` or the MAGE match arm cannot silently desync the two. use zeph_config::TrajectoryRiskAccumulatorConfig; @@ -45,7 +45,7 @@ fn drain_one_code(agent: &mut Agent, code: u8) { /// Codes 1, 2, 6, 7 (`PolicyDeny`, `ExfiltrationRedaction`, `VigilFlagged(Medium)`, /// `VigilFlagged(High)`) are the only `RiskSignal` variants with a MAGE equivalent -/// (spec 004-16 FR-002). Each must ingest into `mage_accumulator` with the exact +/// (spec 004-19 FR-002). Each must ingest into `mage_accumulator` with the exact /// `AuditSignalType`/`Severity` pair documented at the match site in `begin_turn`. #[test] fn begin_turn_maps_known_risk_codes_to_mage_signals() { @@ -88,7 +88,7 @@ fn begin_turn_maps_known_risk_codes_to_mage_signals() { #[test] fn begin_turn_no_mage_signal_for_trajectory_only_codes() { // 10/11 (ExfilReadThenSend/CredThenEgress, #6561/F2) are trajectory-only too — MAGE's - // mapping stays at the fixed spec 004-16 four-class set; widening it is out of scope. + // mapping stays at the fixed spec 004-19 four-class set; widening it is out of scope. for code in [3u8, 4, 5, 10, 11, 99] { let mut agent = make_agent_with_mage(); drain_one_code(&mut agent, code); diff --git a/crates/zeph-core/src/agent/tool_execution/confirmation.rs b/crates/zeph-core/src/agent/tool_execution/confirmation.rs index 3f4e546f4..310eeee32 100644 --- a/crates/zeph-core/src/agent/tool_execution/confirmation.rs +++ b/crates/zeph-core/src/agent/tool_execution/confirmation.rs @@ -4,7 +4,7 @@ //! MAGE trajectory-risk confirmation and escalation gates. //! //! Covers the human-in-the-loop confirmation phase (`ConfirmationRequired` tool errors) and -//! the MAGE trajectory risk hard-block/soft-escalation gates (spec 004-16 FR-004–FR-006). +//! the MAGE trajectory risk hard-block/soft-escalation gates (spec 004-19 FR-004–FR-006). //! Split out of `tier_loop.rs` — see that module for the orchestration entry point that calls //! into these gates. @@ -14,7 +14,7 @@ use crate::agent::Agent; use crate::channel::Channel; impl Agent { - /// Single batch-level human confirmation for the MAGE soft-escalation tier (spec 004-16 + /// Single batch-level human confirmation for the MAGE soft-escalation tier (spec 004-19 /// FR-006). /// /// Returns `Ok(true)` if the user declined — the tombstone and `[Cancelled]` notice are @@ -112,7 +112,7 @@ impl Agent { Ok(false) } - /// Check MAGE trajectory risk gate (spec 004-16 FR-004, FR-005). + /// Check MAGE trajectory risk gate (spec 004-19 FR-004, FR-005). /// /// Returns `Some((score, top_signals))` when the accumulator is blocked. Emits a security /// event, increments `pre_execution_blocks`, and calls `record_block()` on the accumulator. @@ -144,7 +144,7 @@ impl Agent { Some((score, top)) } - /// Check MAGE trajectory risk soft-escalation gate (spec 004-16 FR-006). + /// Check MAGE trajectory risk soft-escalation gate (spec 004-19 FR-006). /// /// Returns `true` when the accumulator's risk is in `[escalation_threshold, /// risk_threshold)`. Emits a security event, increments `pre_execution_warnings`, and diff --git a/crates/zeph-core/src/agent/tool_execution/mod.rs b/crates/zeph-core/src/agent/tool_execution/mod.rs index 174d4f6b7..77912a76c 100644 --- a/crates/zeph-core/src/agent/tool_execution/mod.rs +++ b/crates/zeph-core/src/agent/tool_execution/mod.rs @@ -64,12 +64,12 @@ struct ToolDispatchContext { /// (`is_cacheable`) and the cache-store gate later in `apply_tier_results`, so the tier /// loop never re-scans the registry per call or per tier (#5733 follow-up, M1). mcp_tool_ids: std::collections::HashSet, - /// MAGE trajectory risk gate (spec 004-16 FR-005). + /// MAGE trajectory risk gate (spec 004-19 FR-005). /// /// When `Some((score, top_signals))`, all tool calls in this batch are blocked with /// `ToolError::TrajectoryRiskExceeded`. Set when `mage_accumulator.is_blocked()` at dispatch time. mage_blocked: Option<(f64, Vec)>, - /// MAGE trajectory risk soft-escalation gate (spec 004-16 FR-006). + /// MAGE trajectory risk soft-escalation gate (spec 004-19 FR-006). /// /// When `true`, the batch requires a single up-front human confirmation /// (`Agent::confirm_mage_escalation`) before the normal tier execution loop runs — approval diff --git a/crates/zeph-core/src/agent/tool_execution/tests/mage_escalation_tests.rs b/crates/zeph-core/src/agent/tool_execution/tests/mage_escalation_tests.rs index d6a9a9f58..8a426ce23 100644 --- a/crates/zeph-core/src/agent/tool_execution/tests/mage_escalation_tests.rs +++ b/crates/zeph-core/src/agent/tool_execution/tests/mage_escalation_tests.rs @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2026 Andrei G // SPDX-License-Identifier: MIT OR Apache-2.0 -//! Tests for the MAGE trajectory-risk soft-escalation gate (spec 004-16 FR-006, #5956). +//! Tests for the MAGE trajectory-risk soft-escalation gate (spec 004-19 FR-006, #5956). //! //! `TrajectoryRiskAccumulator::should_escalate()`/`record_escalation()` existed but were never //! queried by the agent loop before this fix. These tests exercise the wiring added to diff --git a/crates/zeph-core/src/agent/tool_execution/tier_loop.rs b/crates/zeph-core/src/agent/tool_execution/tier_loop.rs index 456dd5f15..42c51b908 100644 --- a/crates/zeph-core/src/agent/tool_execution/tier_loop.rs +++ b/crates/zeph-core/src/agent/tool_execution/tier_loop.rs @@ -21,9 +21,9 @@ use crate::channel::{Channel, StopHint, ToolStartEvent}; /// /// Returns `Some(TierLoopData)` synthesizing `ToolError::TrajectoryRiskExceeded` for every /// call in the batch — bypassing `run_tier_execution_loop` entirely — when the hard-block -/// tier (`mage_blocked`, spec 004-16 FR-005) fired. Returns `None` when it did not, so the +/// tier (`mage_blocked`, spec 004-19 FR-005) fired. Returns `None` when it did not, so the /// caller runs the normal tier execution loop (this also covers the soft-escalation tier, -/// spec 004-16 FR-006, which gates on a single batch-level confirmation but then falls +/// spec 004-19 FR-006, which gates on a single batch-level confirmation but then falls /// through to the normal tier loop — see `Agent::confirm_mage_escalation` — so that /// `check_trust`/`PermissionPolicy`/shadow-probe still apply per call; critic finding F1 /// caught an earlier version of this function that bypassed those gates for escalation too). @@ -734,10 +734,10 @@ impl Agent { // Inject active skill secrets before tool execution. self.inject_active_skill_env(); - // MAGE trajectory risk gate (spec 004-16 FR-004, FR-005). + // MAGE trajectory risk gate (spec 004-19 FR-004, FR-005). // Extracted to keep prepare_tool_dispatch under the line limit. let mage_blocked = self.check_mage_block(); - // Soft-escalation tier (spec 004-16 FR-006): only meaningful when the hard block + // Soft-escalation tier (spec 004-19 FR-006): only meaningful when the hard block // above did not already fire — the two threshold ranges never overlap, but the // guard keeps this call site independent of that invariant. let mage_escalate = mage_blocked.is_none() && self.check_mage_escalation(); diff --git a/crates/zeph-memory/src/shadow/mod.rs b/crates/zeph-memory/src/shadow/mod.rs index aa82bafb7..38b997c7a 100644 --- a/crates/zeph-memory/src/shadow/mod.rs +++ b/crates/zeph-memory/src/shadow/mod.rs @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2026 Andrei G // SPDX-License-Identifier: MIT OR Apache-2.0 -//! MAGE shadow memory stream — trajectory-level risk accumulation (spec 004-16). +//! MAGE shadow memory stream — trajectory-level risk accumulation (spec 004-19). //! //! [`TrajectoryRiskAccumulator`] maintains a per-session rolling risk score by ingesting //! [`AuditSignalType`] events from `zeph-sanitizer`. The score decays exponentially between @@ -60,7 +60,7 @@ pub struct SignalEvent { pub raw_score: f64, } -/// Per-session trajectory risk accumulator (MAGE spec 004-16). +/// Per-session trajectory risk accumulator (MAGE spec 004-19). /// /// Maintains a rolling `trajectory_risk` score in `[0.0, 1.0]` that accumulates safety /// signals with exponential temporal decay. Designed to detect multi-turn attacks that diff --git a/crates/zeph-tools/src/executor.rs b/crates/zeph-tools/src/executor.rs index de2c854ee..adc238f06 100644 --- a/crates/zeph-tools/src/executor.rs +++ b/crates/zeph-tools/src/executor.rs @@ -529,7 +529,7 @@ pub enum ToolError { reason: String, }, - /// Tool call blocked by the MAGE `TrajectoryRiskAccumulator` (spec 004-16). + /// Tool call blocked by the MAGE `TrajectoryRiskAccumulator` (spec 004-19). /// /// Cumulative session risk exceeded `risk_threshold`. The agent loop receives the /// score and the top contributing signals so it can explain the denial to the user. diff --git a/specs/004-memory/004-16-shadow-memory-safety.md b/specs/004-memory/004-19-shadow-memory-safety.md similarity index 99% rename from specs/004-memory/004-16-shadow-memory-safety.md rename to specs/004-memory/004-19-shadow-memory-safety.md index 26bd90f0c..f00656387 100644 --- a/specs/004-memory/004-16-shadow-memory-safety.md +++ b/specs/004-memory/004-19-shadow-memory-safety.md @@ -333,7 +333,7 @@ AND no tool call is blocked by shadow memory > The bullet below previously claimed `TrajectoryRiskAccumulator` was renamed to `ShadowSentinel` > during implementation. This is incorrect: both structs exist and coexist as **separate** > components. `TrajectoryRiskAccumulator` (`crates/zeph-memory/src/shadow/mod.rs`, doc comment -> literally reads "Per-session trajectory risk accumulator (MAGE spec 004-16)") is this spec's +> literally reads "Per-session trajectory risk accumulator (MAGE spec 004-19)") is this spec's > actual, unrenamed implementation — wired into `zeph-core` via `agent/builder.rs` and > `agent/state/security.rs`. `ShadowSentinel` (`crates/zeph-core/src/agent/shadow_sentinel.rs`) is > a distinct, additional defense-in-depth feature (an LLM pre-execution safety probe) that belongs diff --git a/specs/004-memory/spec.md b/specs/004-memory/spec.md index 600a1746c..869f35104 100644 --- a/specs/004-memory/spec.md +++ b/specs/004-memory/spec.md @@ -16,7 +16,7 @@ related: - "[[001-system-invariants/spec#6. Memory Pipeline Contract]]" - "[[002-agent-loop/spec]]" - "[[004-6-graph-memory]]" - - "[[004-16-shadow-memory-safety]]" + - "[[004-19-shadow-memory-safety]]" - "[[004-17-implicit-conflict-detection]]" - "[[004-18-five-signal-retrieval]]" - "[[012-graph-memory/spec]]" @@ -54,7 +54,7 @@ specific areas, refer to the child specs below. See also §"Sub-Specifications" below for [[004-10-memory-memmachine-retrieval]], [[004-11-memory-hela-mem]], [[004-12-memory-reasoning-bank]], [[004-14-memory-tiering-rfc-decision]], -[[004-15-memory-skill-coevolution-rfc-decision]], [[004-16-shadow-memory-safety]], +[[004-15-memory-skill-coevolution-rfc-decision]], [[004-19-shadow-memory-safety]], [[004-17-implicit-conflict-detection]], and [[004-18-five-signal-retrieval]]. --- @@ -243,7 +243,7 @@ When disabled, the prior `recall_semantic` path is used unchanged. | [[004-12-memory-reasoning-bank]] | ReasoningBank distilled strategy memory, self-judge pipeline | | [[004-14-memory-tiering-rfc-decision]] | RFC #4217 decision: memory tiering architecture analysis | | [[004-15-memory-skill-coevolution-rfc-decision]] | RFC #4218 decision: memory–skill coevolution analysis | -| [[004-16-shadow-memory-safety]] | Shadow Memory Safety — trajectory-level attack defense (MAGE, issue #3695) | +| [[004-19-shadow-memory-safety]] | Shadow Memory Safety — trajectory-level attack defense (MAGE, issue #3695) | | [[004-17-implicit-conflict-detection]] | Implicit Conflict Detection — STALE/CUPMem fuzzy predicate matching and propagation-aware SYNAPSE recall (issue #3702) | | [[004-18-five-signal-retrieval]] | Five-Signal Retrieval — access frequency, causal distance, novelty signals + async consolidation daemon (MemTier, issue #3703) | @@ -389,6 +389,66 @@ is a concern. --- +## Edge-Strengthening Mechanisms: Authoritative Statement + +Three independent but coexisting mechanisms strengthen edges on repeated access: + +### 1. A-MEM's `retrieval_count` Boost (PRIMARY, UNIVERSAL) + +**Authority**: This is the fundamental edge-strength evolution mechanism governing graph recall in all traversal paths (main BFS, SYNAPSE spreading activation, and HL-F5). + +**Implementation** (`crates/zeph-memory/src/graph/types.rs`): +- Each edge tracks an integer `retrieval_count` (line 139) incremented on every recall traversal +- The `evolved_weight()` function (lines 399–406) applies: `confidence * min(1.0, 1.0 + 0.2 * ln(1 + retrieval_count))` +- On `count=0`: returns raw confidence (identity) +- On `count=10`: ~1.48x boost +- This formula is documented in [[004-6-graph-memory|spec 004-6]], §1 ("A-MEM link weights"), lines 88–92 + +**Used in**: +- Main `graph_recall()` path: `composite_score()` (lines 432–434) calls `evolved_weight(edge.retrieval_count, edge.confidence)` (`crates/zeph-memory/src/graph/types.rs`) +- SYNAPSE `graph_recall_activated()` path: spreads activation using a blended confidence passed to `evolved_weight()` (`crates/zeph-memory/src/graph/activation.rs`, line 617) + +**Increment mechanism**: `apply_hebbian_increment()` in the graph store fire-and-forget loop after each recall (`crates/zeph-memory/src/graph/retrieval.rs`, lines 152 and 467). + +### 2. Benna-Fusi Dual-Timescale Model (SECONDARY, LAYERED) + +**Authority**: This is a secondary confidence-blending mechanism used *only* in SYNAPSE spreading activation. It does **not** replace A-MEM; instead, it provides the base confidence value that A-MEM then boosts. + +**Implementation** (`crates/zeph-memory/src/graph/types.rs`, lines 157–166): +- Each edge tracks two synaptic variables: `confidence_fast` (high plasticity) and `confidence_slow` (high retention) +- Both update on every reassertion: `fast' = fast + η_f * (c - fast)` and `slow' = slow + η_s * (fast' - slow)` +- Documented in this spec's "Benna-Fusi Multi-Timescale SYNAPSE Edges" section and [[004-6-graph-memory]], §2 ("SYNAPSE two-timescale learning") + +**Used in**: +- SYNAPSE spreading activation *only*: `graph_recall_activated()` blends the two variables (`crates/zeph-memory/src/graph/activation.rs`, lines 615–616): `blended = α * confidence_fast + (1 − α) * confidence_slow` +- This blended value is immediately passed to `evolved_weight(edge.retrieval_count, blended)`, so A-MEM boost is applied to the Benna-Fusi blend, not the raw edge confidence +- **NOT used in the main `graph_recall()` BFS path**, which uses `edge.confidence` directly + +### 3. HeLa-Mem Hebbian `weight` Field (SEPARATE, HL-F5 ONLY) + +**Authority**: This is a **separate mechanism** for HL-F5 spreading activation only. It does **not** influence main graph recall or SYNAPSE spreading activation scoring. + +**Implementation** (`crates/zeph-memory/src/graph/types.rs`, lines 151–156): +- Each edge tracks a Hebbian reinforcement weight: `weight` (starts at 1.0) +- Incremented by `apply_hebbian_increment()` on every HL-F5 traversal (marked as "HL-F1" in [[004-11-memory-hela-mem]], #3344) + +**Used in**: +- HL-F5 BFS path-weight propagation *only*: `path_weight = parent_pw * edge.weight` (`crates/zeph-memory/src/graph/activation.rs`, line 317) +- The path weight is then multiplied by entity embedding cosine similarity to produce the HL-F5 fact score: `score = path_weight × max(cosine(query, entity), 0.0)` (activation.rs, HL-F5 section) +- **NOT used** in A-MEM or SYNAPSE mechanisms; does not influence main `composite_score()` or SYNAPSE activation propagation + +### Summary + +| Mechanism | Field | Used in | Boost Formula | Authority | +|-----------|-------|---------|---------------|-----------| +| A-MEM | `retrieval_count` + `confidence` | Main BFS, SYNAPSE | `c * min(1.0, 1.0 + 0.2*ln(1+count))` | **Primary, universal** | +| Benna-Fusi | `confidence_fast` / `confidence_slow` | SYNAPSE only | Blended as `α*fast + (1-α)*slow`, then passed to A-MEM | Secondary, layered | +| HeLa-Mem | `weight` | HL-F5 spreading only | Multiplicative path propagation | Separate, HL-F5 isolated | + +**Key Invariant**: A-MEM is the only edge-strengthening mechanism that operates universally across all graph recall strategies. Benna-Fusi and HeLa-Mem are add-ons specialized to their respective recall strategies (SYNAPSE and HL-F5). + +--- + ## JoinSet and CancellationToken Fixes - `spawn_graph_extraction` now receives a `CancellationToken` from `LifecycleState` for clean shutdown (commit #4635) diff --git a/specs/083-memory-write-consent-gate/spec.md b/specs/083-memory-write-consent-gate/spec.md index a80b3ec9e..a1b1fc8c3 100644 --- a/specs/083-memory-write-consent-gate/spec.md +++ b/specs/083-memory-write-consent-gate/spec.md @@ -245,7 +245,7 @@ Wired through `AgentSessionConfig` (all four agent entry points: CLI/TUI, ACP, A - [[constitution]] — project principles - [[004-memory/spec]] — memory system parent index - [[004-9-memory-write-gate]] — MemReader write quality gate (orthogonal, noise-control) -- [[004-16-shadow-memory-safety]] — MAGE shadow memory (orthogonal, trajectory-level attack defense) +- [[004-19-shadow-memory-safety]] — MAGE shadow memory (orthogonal, trajectory-level attack defense) - [[039-background-task-supervisor/spec]] — non-blocking contract this gate's background path follows - [[001-system-invariants/spec]] — system-wide non-negotiable rules - [[MOC-specs]] — all specifications diff --git a/specs/MOC-specs.md b/specs/MOC-specs.md index c26f002e6..750b74fca 100644 --- a/specs/MOC-specs.md +++ b/specs/MOC-specs.md @@ -53,7 +53,7 @@ status: moc - [[012-graph-memory/spec|Entity Graph Memory]] — entity graph, BFS recall, community detection, MAGMA typed edges, SYNAPSE spreading activation; works with [[004-memory/spec|Memory Pipeline]] - [[004-memory/004-6-graph-memory|Graph Memory (memory sub-spec)]] — concise reference within the memory subsystem: data model overview, MAGMA edge types, SYNAPSE config, key invariants - [[004-memory/004-16-memory-type-aware-retrieval|MemGuard Type-Aware Retrieval (memory sub-spec)]] — opt-in fetch-time gate on `schedule_context_fetchers`, `FunctionalType` enum, intent-scoped widening via existing `HeuristicRouter` (no new LLM call), `BehavioralRule` always-composed safety invariant; retrieval-only, byte-for-byte no-op when disabled; GitHub #6086, #6226 - - [[004-memory/004-16-shadow-memory-safety|Shadow Memory Safety (memory sub-spec)]] — `TrajectoryRiskAccumulator` MAGE multi-turn goal-hijacking detection, `ShadowMemory`/`GoalDriftResult`; SafeHarbor guardrail tree aspirational; GitHub #3695 + - [[004-memory/004-19-shadow-memory-safety|Shadow Memory Safety (memory sub-spec)]] — `TrajectoryRiskAccumulator` MAGE multi-turn goal-hijacking detection, `ShadowMemory`/`GoalDriftResult`; SafeHarbor guardrail tree aspirational; GitHub #3695 - [[004-memory/004-17-implicit-conflict-detection|Implicit Conflict Detection (memory sub-spec)]] — write-time `ImplicitConflictDetector` (STALE/CUPMem fuzzy predicate matching), propagation-aware SYNAPSE recall; GitHub #3702 - [[004-memory/004-18-five-signal-retrieval|Five-Signal Retrieval (memory sub-spec)]] — access frequency, causal distance, novelty, recency, goal-relevance signals + async consolidation daemon (MemTier); GitHub #3703 - [[067-knowledge-ingest/spec|Knowledge Ingest]] — `zeph knowledge ingest` operator command; static artifacts → semantic notes (existing `IngestionPipeline`, no graph), subagent transcripts → graph (gated by measurement spike); Phase 0 provenance (`origin`/`import_batch_id`/`source_uri`) + `rollback`; honors write-gate (004-9) + admission (004-3), bypasses only RPE; sanitizer on write path; external Claude/Codex import deferred; code stays in [[017-index/spec|zeph-index]] diff --git a/specs/README.md b/specs/README.md index 2dc753bd0..5c4ce9acf 100644 --- a/specs/README.md +++ b/specs/README.md @@ -90,8 +90,8 @@ Spec IDs follow a logical grouping (with gaps for open proposals and reserved nu | `004-memory/004-13-memory-memcot.md` | MemCoT: SemanticStateAccumulator, Zoom-In evidence localization, Zoom-Out causal expansion (#3592) | `zeph-memory` | | `004-memory/004-14-memory-tiering-rfc-decision.md` | RFC #4217 decision: memory tiering architecture analysis (MEMTIER, BudgetMem, Multi-Layer, LCM, MemRouter); adopt frequency signal + tier-aware gating + cost-aware routing (#4217) | `zeph-memory` | | `004-memory/004-15-memory-skill-coevolution-rfc-decision.md` | RFC #4218 decision: memory–skill coevolution analysis (MemQ, δ-mem, EvolveMem, SAGE-GraphMem, NanoResearch, Cognifold); adopt Cognifold idle-time folding + EvolveMem feedback routing; defer MemQ to P3 (#4218) | `zeph-memory`, `zeph-skills` | -| `004-memory/004-16-memory-type-aware-retrieval.md` | MemGuard type-aware retrieval composition: `FunctionalType` enum (episodic/user-fact/behavioral-rule/reasoning-strategy/cross-session-summary/graph-fact), opt-in fetch-time gate on `schedule_context_fetchers`, intent-scoped widening via existing `HeuristicRouter` (no new LLM call), `BehavioralRule` always-composed safety invariant; retrieval-only, byte-for-byte no-op when disabled (#6086, #6226). Note: this file intentionally reuses the `004-16` slot already used by `004-16-memory-type-aware-retrieval.md`'s sibling `004-16-shadow-memory-safety.md` below — see that file's own note; in-code rustdoc citations already reference "spec 004-16" (issue #6308), so renumbering requires a coordinated source-code + spec change, not a docs-only fix | `zeph-common`, `zeph-config`, `zeph-context`, `zeph-agent-context`, `zeph-memory` | -| `004-memory/004-16-shadow-memory-safety.md` | Shadow Memory Safety: `TrajectoryRiskAccumulator` MAGE multi-turn goal-hijacking detection via accumulating risk scores, `ShadowMemory`/`GoalDriftResult`; SafeHarbor hierarchical guardrail tree (aspirational, not yet implemented); GitHub #3695 | `zeph-sanitizer`, `zeph-memory`, `zeph-core` | +| `004-memory/004-16-memory-type-aware-retrieval.md` | MemGuard type-aware retrieval composition: `FunctionalType` enum (episodic/user-fact/behavioral-rule/reasoning-strategy/cross-session-summary/graph-fact), opt-in fetch-time gate on `schedule_context_fetchers`, intent-scoped widening via existing `HeuristicRouter` (no new LLM call), `BehavioralRule` always-composed safety invariant; retrieval-only, byte-for-byte no-op when disabled (#6086, #6226) | `zeph-common`, `zeph-config`, `zeph-context`, `zeph-agent-context`, `zeph-memory` | +| `004-memory/004-19-shadow-memory-safety.md` | Shadow Memory Safety: `TrajectoryRiskAccumulator` MAGE multi-turn goal-hijacking detection via accumulating risk scores, `ShadowMemory`/`GoalDriftResult`; SafeHarbor hierarchical guardrail tree (aspirational, not yet implemented); GitHub #3695 | `zeph-sanitizer`, `zeph-memory`, `zeph-core` | | `004-memory/004-17-implicit-conflict-detection.md` | Implicit Conflict Detection (STALE/CUPMem): write-time `ImplicitConflictDetector` (Levenshtein + embedding similarity fuzzy predicate matching), propagation-aware SYNAPSE recall, `implicit_conflict_candidates` staging table (migration 090); GitHub #3702 | `zeph-memory` | | `004-memory/004-18-five-signal-retrieval.md` | Five-Signal Retrieval (MemTier): access frequency, causal distance, novelty, recency, and goal-relevance signals composed into retrieval ranking + async consolidation daemon; migration 091; GitHub #3703 | `zeph-memory`, `zeph-scheduler` | | `005-skills/spec.md` | SKILL.md format, registry, matching, hot-reload, skill trust governance, two-stage matching, Wilson score confidence intervals, hub install pipeline, agent-invocable skills (`invoke_skill`), recursive WalkDir discovery (max depth 16), `SkillExtensions` manifest parser, concurrent semantic scan (`buffer_unordered(4)`, 300s timeout), skill egress attribution in `ToolCall`/`AuditEntry`/`EgressEvent` | `zeph-skills` |