1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
//! Temporal Derivative Kernel — Dual Fast/Slow Surprise Signal (Plan 277).
//!
//! Distilled from O'Reilly 2026, "This is how the Neocortex Learns"
//! ([arXiv:2606.08720](https://arxiv.org/abs/2606.08720)). Research note:
//! [`katgpt-rs/.research/435_Temporal_Derivative_Kernel_Neocortical_Learning.md`](../.research/435_Temporal_Derivative_Kernel_Neocortical_Learning.md).
//!
//! Turns any streaming latent scalar (or fixed-size vector) into a signed
//! "surprise" signal — the implicit prediction-error channel the neocortex
//! uses for credit assignment, computed locally from a signal's own time
//! series with no external target and no backprop.
//!
//! ## Why
//!
//! Every EMA currently in the codebase is a *single* integrator
//! (`simd_fused_decay_write`, `evolve_belief`, etc.). The dual
//! `(I_fast − I_slow)` band-pass derivative is the smallest missing
//! primitive that upgrades four existing pillars:
//!
//! - **belief companion** — `evolve_belief` tracks *what is*; derivative tracks
//! *how fast it is changing*.
//! - **δ-Mem write gate** — writes only on surprising events.
//! - **Collapse detector fusion** — prediction-derivative collapse is
//! orthogonal to entropy collapse.
//! - **Intrinsic curiosity** — `sigmoid(β · surprise_norm())` is a zero-cost
//! curiosity signal that needs no Solver.
//!
//! ## Latent vs raw boundary
//!
//! Operates on latent state; emits a bounded scalar (`surprise_norm`) that
//! may sync as a raw summary statistic. Full N-dim derivative vector stays
//! local per-entity.
//!
//! ## Sigmoid, never softmax
//!
//! Per `AGENTS.md`: the bridge projection [`sigmoid_surprise_gate`] uses
//! sigmoid. Softmax over a single scalar is meaningless.
//!
//! ## Co-extraction provenance (Plan 338 Phase 2)
//!
//! Promoted from `katgpt-core::temporal_deriv` (Plan 277) so that the
//! `katgpt-sense` crate can consume the kernel via the leaf only, breaking
//! the katgpt-core cycle. katgpt-core re-exports this via
//! `katgpt_core::temporal_deriv::*` (bit-for-bit path preserved). Tests stay
//! in katgpt-core (they exercise the kernel through the re-export).
use crate;
/// Dual fast/slow EMA temporal-derivative kernel.
///
/// `fast` tracks the signal with a short time constant; `slow` with a long
/// one. Their difference `(fast − slow)` is a signed band-pass derivative
/// that spikes on change and decays to zero when the signal is stationary
/// — the canonical neocortical prediction-error signal.
///
/// Generic over `N` (the signal dimension). Fixed-size array, zero
/// allocation, suitable for embedding inside per-NPC state structs.
///
/// # Invariants
///
/// - `0 < alpha_slow < alpha_fast <= 1` (validated at construction).
/// - State arrays are zero-initialized on [`new`](Self::new); use
/// [`with_initial`](Self::with_initial) for warm starts / snapshot
/// restore.
/// - All operations are branch-free and in-place; safe to call from hot
/// paths at any tier (plasma → cold).
/// Bridge helper: project a derivative vector onto a single bounded scalar
/// via `sigmoid(β · ‖derivative‖₂)`.
///
/// Canonical downstream projection per `AGENTS.md` latent→raw bridge rules.
/// **Never softmax** (single-scalar softmax is meaningless; sigmoid gives a
/// proper inject/skip probability).
///
/// `beta` is the inverse-temperature: large `beta` → sharp threshold,
/// small `beta` → soft gate. Typical operating value `beta ∈ [1, 10]`.
/// Validate `0 < alpha_slow < alpha_fast <= 1`. Debug panic on violation;
/// release clamp.