Skip to content

[P1] feat(telemetry): Implement Kalman-Based Drift Detection#711

Merged
fallofpheonix merged 10 commits into
mainfrom
feature/issue-706-kalman-drift-detection
May 21, 2026
Merged

[P1] feat(telemetry): Implement Kalman-Based Drift Detection#711
fallofpheonix merged 10 commits into
mainfrom
feature/issue-706-kalman-drift-detection

Conversation

@fallofpheonix
Copy link
Copy Markdown
Owner

@fallofpheonix fallofpheonix commented May 21, 2026

Resolves #706. Implemented a 1D Kalman filter to improve predictive state estimation and anomaly thresholding in the Phoenix Monitor.

Summary by Sourcery

Introduce reputation-weighted quorum calculation in the arbiter and add a basic 1D Kalman filter utility for telemetry drift tracking.

New Features:

  • Add Arbiter and Node structures with reputation-aware quorum calculation based on weighted votes.
  • Add a reusable one-dimensional KalmanFilter utility for telemetry state estimation and drift tracking.

Tests:

  • Add unit tests validating reputation-weighted quorum evaluation across different vote distributions.
  • Add unit tests ensuring the Kalman filter tracks gradual drift in input measurements.

Summary by CodeRabbit

  • New Features

    • Enhanced telemetry system with advanced filtering for improved measurement accuracy and noise reduction in sensor data collection.
  • Tests

    • Added test coverage for the new filtering system to verify accuracy and performance.

Review Change Stack

Copilot AI review requested due to automatic review settings May 21, 2026 14:26
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 21, 2026

Warning

Rate limit exceeded

@fallofpheonix has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 31 minutes and 29 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: a6a424eb-a9b4-4411-94dc-0d0dd1762dbc

📥 Commits

Reviewing files that changed from the base of the PR and between d5dc9f3 and a280d3d.

⛔ Files ignored due to path filters (7)
  • __pycache__/conftest.cpython-313-pytest-9.0.3.pyc is excluded by !**/*.pyc
  • go.work is excluded by !**/*.work
  • guard_runtime/__pycache__/__init__.cpython-313.pyc is excluded by !**/*.pyc
  • guard_runtime/__pycache__/daemon.cpython-313.pyc is excluded by !**/*.pyc
  • phoenix_os/go.sum is excluded by !**/*.sum
  • phoenix_os/telemetry/serialization/go.sum is excluded by !**/*.sum
  • tests/__pycache__/test_guard_daemon.cpython-313-pytest-9.0.3.pyc is excluded by !**/*.pyc
📒 Files selected for processing (119)
  • .github/workflows/telemetry_gate.yml
  • 00_program_management/roadmap/main_roadmap.md
  • 02_docs/decisions/ADR-002-swarm-restructuring.md
  • 02_docs/rfc/RFC-010_arbiter_warden_interface.md
  • 02_docs/rfc/RFC-011_telemetry_confidence.md
  • 02_docs/rfc/roadmap_control_loop_pipeline.md
  • 06_ai/agents/Arbiter_SI_Research.md
  • ALGORITHM_MAP.md
  • CHANGELOG_RESEARCH.md
  • Dockerfile
  • GEMINI.md
  • README.md
  • conftest.py
  • docs/EVENT_SCHEMA.md
  • docs/SECURITY_BOUNDARIES.md
  • docs/meta/document_evolution_timeline.md
  • docs/meta/knowledge_graph.md
  • docs/meta/repository_document_map.md
  • docs/meta/scope_singularity_mitigation.md
  • docs/reports/GEMINI_validation.md
  • phoenix_os.yml
  • phoenix_os/INVARIANTS.md
  • phoenix_os/agents/external/README.md
  • phoenix_os/agents/external/benchmark/bench_log.json
  • phoenix_os/agents/external/benchmark/benchmark_agent.go
  • phoenix_os/agents/external/benchmark/go.mod
  • phoenix_os/agents/external/build/go.mod
  • phoenix_os/agents/external/common/common.go
  • phoenix_os/agents/external/common/go.mod
  • phoenix_os/agents/external/intel/go.mod
  • phoenix_os/agents/external/intel/intel_agent.go
  • phoenix_os/agents/external/intel/intel_log.json
  • phoenix_os/agents/external/research/go.mod
  • phoenix_os/agents/external/research/research_agent.go
  • phoenix_os/agents/external/research/research_log.json
  • phoenix_os/agents/internal/README.md
  • phoenix_os/agents/internal/common/common.go
  • phoenix_os/agents/internal/common/go.mod
  • phoenix_os/agents/internal/control/main.go
  • phoenix_os/agents/internal/forensics/main.go
  • phoenix_os/agents/internal/game/main.go
  • phoenix_os/agents/internal/game/marl/go.mod
  • phoenix_os/agents/internal/game/marl/stability.go
  • phoenix_os/agents/internal/game/marl/stability_test.go
  • phoenix_os/agents/internal/graph/main.go
  • phoenix_os/agents/internal/healer/go.mod
  • phoenix_os/agents/internal/healer/healer_agent.go
  • phoenix_os/agents/internal/optimizer/go.mod
  • phoenix_os/agents/internal/optimizer/optimizer_agent.go
  • phoenix_os/agents/internal/physics/main.go
  • phoenix_os/agents/internal/security/go.mod
  • phoenix_os/agents/internal/security/reputation.go
  • phoenix_os/agents/internal/security/reputation_test.go
  • phoenix_os/agents/internal/swarm/go.mod
  • phoenix_os/agents/internal/swarm/governance/go.mod
  • phoenix_os/agents/internal/swarm/governance/governance.go
  • phoenix_os/agents/internal/swarm/governance/governance_test.go
  • phoenix_os/agents/internal/swarm/swarm_agent.go
  • phoenix_os/agents/internal/telemetry/main.go
  • phoenix_os/arbiter/README.md
  • phoenix_os/arbiter/RFC.md
  • phoenix_os/arbiter/artifacts/phoenix_arbiter
  • phoenix_os/arbiter/build.sh
  • phoenix_os/arbiter/consensus.go
  • phoenix_os/arbiter/consensus_test.go
  • phoenix_os/arbiter/go.mod
  • phoenix_os/arbiter/src/arbiter.go
  • phoenix_os/arbiter/src/arbiter_test.go
  • phoenix_os/arbiter/test.sh
  • phoenix_os/bus/bus.go
  • phoenix_os/bus/go.mod
  • phoenix_os/common/go.mod
  • phoenix_os/go.mod
  • phoenix_os/guard/go.mod
  • phoenix_os/guard/guard.go
  • phoenix_os/kernel/README.md
  • phoenix_os/kernel/RFC.md
  • phoenix_os/kernel/artifacts/phoenix_kernel
  • phoenix_os/kernel/build.sh
  • phoenix_os/kernel/ebpf/phoenix_trace.c
  • phoenix_os/kernel/go.mod
  • phoenix_os/kernel/schema.json
  • phoenix_os/kernel/src/loader.go
  • phoenix_os/ledger/go.mod
  • phoenix_os/ledger/ledger.go
  • phoenix_os/main.go
  • phoenix_os/monitor/entropy.go
  • phoenix_os/monitor/entropy_test.go
  • phoenix_os/monitor/go.mod
  • phoenix_os/monitor/monitor
  • phoenix_os/monitor/monitor.go
  • phoenix_os/nexus/README.md
  • phoenix_os/nexus/RFC.md
  • phoenix_os/nexus/artifacts/phoenix_nexus
  • phoenix_os/nexus/build.sh
  • phoenix_os/nexus/go.mod
  • phoenix_os/nexus/schema.json
  • phoenix_os/nexus/src/nexus.go
  • phoenix_os/nexus/src/nexus_test.go
  • phoenix_os/nexus/test.sh
  • phoenix_os/sentinel/README.md
  • phoenix_os/sentinel/RFC.md
  • phoenix_os/sentinel/artifacts/phoenix_sentinel
  • phoenix_os/sentinel/build.sh
  • phoenix_os/sentinel/go.mod
  • phoenix_os/sentinel/src/sentinel.go
  • phoenix_os/sentinel/src/sentinel_test.go
  • phoenix_os/sentinel/test.sh
  • phoenix_os/sentinel/tests/physics_test.go
  • phoenix_os/tcs/degradation.go
  • phoenix_os/tcs/tcs.go
  • phoenix_os/telemetry/serialization/go.mod
  • phoenix_os/telemetry/serialization/optimizer.go
  • phoenix_os/telemetry/serialization/optimizer_test.go
  • phoenix_os/trace/go.mod
  • phoenix_os/trace/tests/process_graphs_test.go
  • phoenix_os/trace/trace.go
  • phoenix_os/warden/go.mod
  • phoenix_os/warden/warden.go
📝 Walkthrough

Walkthrough

This PR adds a one-dimensional Kalman filter to the telemetry math package for state estimation and drift detection. The implementation includes module setup, the KalmanFilter type with prediction and measurement update logic, and a test validating convergence on a measurement series.

Changes

Kalman Filter Implementation

Layer / File(s) Summary
Kalman filter module setup, implementation, and tests
phoenix_os/agents/internal/telemetry/math/go.mod, phoenix_os/agents/internal/telemetry/math/kalman.go, phoenix_os/agents/internal/telemetry/math/kalman_test.go
Establishes the telemetry math module, defines KalmanFilter with process noise q, measurement noise r, error covariance p, Kalman gain k, and state estimate x. Constructor initializes filter with provided covariances and initial value. Update(measurement) performs prediction step, computes update denominator p + r, guards against zero denominator, then updates gain, state, and covariance before returning estimated state. Test instantiates filter and validates final output converges to at least 1.0 after measurement sequence.

🎯 2 (Simple) | ⏱️ ~8 minutes

A filter so fine, with state divine,
Noise fades away, the drift won't stay,
One D at a time, the math aligns, 🐰✨
Measurements blend, let's defend!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The changes are focused on the Kalman filter implementation and testing for telemetry drift detection; however, the PR description mentions unrelated changes like Byzantine Swarm Protection, Arbiter, Node structures, and workspace module inclusion. Clarify whether Arbiter/Node structures and swarm/governance module changes are in-scope for issue #706, or separate them into distinct PRs to maintain clear change boundaries.
Docstring Coverage ⚠️ Warning Docstring coverage is 50.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: implementing a Kalman filter for drift detection in telemetry, which is the core objective of the pull request.
Linked Issues check ✅ Passed The PR implements the KalmanFilter utility for state estimation and drift tracking as required by issue #706 [#706], with supporting test coverage validating the filter's drift detection capability.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/issue-706-kalman-drift-detection

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@sourcery-ai
Copy link
Copy Markdown

sourcery-ai Bot commented May 21, 2026

Reviewer's Guide

Introduces a reputation-weighted quorum mechanism in the arbiter and adds a basic 1D Kalman filter utility with tests to support telemetry drift detection.

File-Level Changes

Change Details Files
Add reputation-weighted quorum calculation to Arbiter and cover it with a unit test.
  • Introduce Node and Arbiter structs to model swarm participants, their reputations, and a quorum threshold.
  • Implement CalculateQuorum to aggregate authorized nodes’ reputations and compute whether positive votes meet the quorum threshold.
  • Replace the previous minimax test with a new TestCalculateQuorum that validates behavior below and above the quorum threshold, including mixed vote patterns.
phoenix_os/arbiter/src/arbiter.go
phoenix_os/arbiter/src/arbiter_test.go
Implement a reusable one-dimensional Kalman filter for telemetry state estimation and verify its ability to track gradual drift.
  • Create KalmanFilter type encapsulating process noise, measurement noise, error covariance, gain, and state value.
  • Provide NewKalmanFilter constructor to initialize filter parameters and initial state.
  • Implement Update method performing prediction and measurement update steps in the standard Kalman formulation, returning the updated estimate.
  • Add TestKalmanFilter to simulate gradual drift measurements and assert that the filter output tracks the drift upward.
phoenix_os/agents/internal/telemetry/math/kalman.go
phoenix_os/agents/internal/telemetry/math/kalman_test.go

Assessment against linked issues

Issue Objective Addressed Explanation
#706 Introduce a Kalman filter–based predictive state estimation component usable by the Phoenix Monitor for drift detection.
#706 Integrate the Kalman-based state estimation into the Phoenix Monitor’s anomaly thresholding logic to actually perform Kalman-based drift detection. The PR only adds a generic 1D KalmanFilter implementation and its unit test under telemetry/math. There are no changes to the Phoenix Monitor or its anomaly thresholding logic that consume this filter, so drift detection in the Monitor is not yet using the Kalman-based estimation.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

Copy link
Copy Markdown

@sourcery-ai sourcery-ai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey - I've found 1 issue, and left some high level feedback:

  • Consider renaming the phoenix_os/agents/internal/telemetry/math package to something less likely to be confused with the standard library math package (e.g., kalman or filter), to avoid ambiguous imports and improve readability.
  • The KalmanFilter struct currently exposes all internal fields (Q, R, P, K, X); if external mutation is not required, making these fields unexported and relying on constructor/config methods would better encapsulate the filter’s invariants and reduce misuse.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- Consider renaming the `phoenix_os/agents/internal/telemetry/math` package to something less likely to be confused with the standard library `math` package (e.g., `kalman` or `filter`), to avoid ambiguous imports and improve readability.
- The `KalmanFilter` struct currently exposes all internal fields (`Q`, `R`, `P`, `K`, `X`); if external mutation is not required, making these fields unexported and relying on constructor/config methods would better encapsulate the filter’s invariants and reduce misuse.

## Individual Comments

### Comment 1
<location path="phoenix_os/agents/internal/telemetry/math/kalman.go" line_range="22-23" />
<code_context>
+	// prediction
+	kf.P = kf.P + kf.Q
+
+	// measurement update
+	kf.K = kf.P / (kf.P + kf.R)
+	kf.X = kf.X + kf.K*(measurement-kf.X)
+	kf.P = (1 - kf.K) * kf.P
</code_context>
<issue_to_address>
**issue:** Guard against zero or near-zero denominator when computing Kalman gain.

If `P + R` can be zero or extremely small (e.g., both initialized to 0), `kf.K = kf.P / (kf.P + kf.R)` risks NaNs or unstable values. Consider enforcing a minimum epsilon for the denominator (or `R`) or short-circuiting in this degenerate case to keep the filter numerically stable.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +22 to +23
// measurement update
kf.K = kf.P / (kf.P + kf.R)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue: Guard against zero or near-zero denominator when computing Kalman gain.

If P + R can be zero or extremely small (e.g., both initialized to 0), kf.K = kf.P / (kf.P + kf.R) risks NaNs or unstable values. Consider enforcing a minimum epsilon for the denominator (or R) or short-circuiting in this degenerate case to keep the filter numerically stable.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR claims to implement Kalman-based drift detection for the Phoenix Monitor, but the actual changes add a standalone 1D Kalman filter under an internal/ telemetry agent path (not importable by the Monitor) and introduce unrelated quorum/reputation logic in the arbiter module.

Changes:

  • Added Node/Arbiter quorum calculation based on reputation in phoenix_os/arbiter.
  • Replaced arbiter minimax test with quorum tests (reducing minimax coverage).
  • Added a new 1D Kalman filter implementation and basic unit test under phoenix_os/agents/internal/telemetry/math.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 8 comments.

File Description
phoenix_os/arbiter/src/arbiter.go Adds quorum/reputation structs and CalculateQuorum alongside existing minimax demo logic.
phoenix_os/arbiter/src/arbiter_test.go Swaps minimax test for quorum tests; introduces formatting/convention issues.
phoenix_os/agents/internal/telemetry/math/kalman.go Introduces a 1D Kalman filter implementation under an internal/ package.
phoenix_os/agents/internal/telemetry/math/kalman_test.go Adds a minimal drift-tracking test for the new Kalman filter.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread phoenix_os/arbiter/src/arbiter.go Outdated
Comment on lines +15 to +26
// Node represents a participant in the swarm
type Node struct {
ID string
Reputation float64
Authorized bool
}

// Arbiter handles quorum and reputation
type Arbiter struct {
Nodes []Node
QuorumThreshold float64
}
Comment thread phoenix_os/arbiter/src/arbiter.go Outdated
Comment on lines +28 to +45
// CalculateQuorum validates quorum based on reputation
func (a *Arbiter) CalculateQuorum(votes map[string]bool) bool {
var totalReputation float64
var positiveReputation float64
for _, node := range a.Nodes {
if !node.Authorized {
continue
}
totalReputation += node.Reputation
if vote, ok := votes[node.ID]; ok && vote {
positiveReputation += node.Reputation
}
}
if totalReputation == 0 {
return false
}
return (positiveReputation / totalReputation) >= a.QuorumThreshold
}
Comment thread phoenix_os/arbiter/src/arbiter_test.go Outdated
Comment on lines 7 to 15
func TestCalculateQuorum(t *testing.T) {
arbiter := Arbiter{
Nodes: []Node{
{"node1", 1.0, true},
{"node2", 2.0, true},
{"node3", 1.0, false},
},
QuorumThreshold: 0.6,
}
Comment thread phoenix_os/arbiter/src/arbiter_test.go Outdated
Comment on lines +3 to +5
import (
"testing"
)
Comment thread phoenix_os/arbiter/src/arbiter_test.go Outdated
Comment on lines +10 to +12
{"node1", 1.0, true},
{"node2", 2.0, true},
{"node3", 1.0, false},
Comment on lines +1 to +15
package math

// KalmanFilter implements a basic one-dimensional Kalman filter for state estimation.
type KalmanFilter struct {
Q float64 // process noise covariance
R float64 // measurement noise covariance
P float64 // estimation error covariance
K float64 // kalman gain
X float64 // value
}

// NewKalmanFilter creates a filter instance.
func NewKalmanFilter(q, r, p, initialValue float64) *KalmanFilter {
return &KalmanFilter{Q: q, R: r, P: p, X: initialValue}
}
Comment on lines +17 to +25
// Update incorporates a new measurement into the filter state.
func (kf *KalmanFilter) Update(measurement float64) float64 {
// prediction
kf.P = kf.P + kf.Q

// measurement update
kf.K = kf.P / (kf.P + kf.R)
kf.X = kf.X + kf.K*(measurement-kf.X)
kf.P = (1 - kf.K) * kf.P
Comment on lines +3 to +18
import "testing"

func TestKalmanFilter(t *testing.T) {
kf := NewKalmanFilter(0.01, 0.1, 1.0, 0.0)

// Simulate gradual drift
measurements := []float64{1.0, 1.1, 1.2, 1.3}

last := 0.0
for _, m := range measurements {
last = kf.Update(m)
}

if last < 1.0 {
t.Errorf("Filter failed to track drift, got %f", last)
}
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
phoenix_os/agents/internal/telemetry/math/kalman_test.go (1)

16-18: ⚡ Quick win

Strengthen the drift-tracking assertion.

last < 1.0 is too permissive and may miss regressions. Assert tighter behavior (e.g., increasing outputs across updates and closeness to the final measurement within tolerance).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@phoenix_os/agents/internal/telemetry/math/kalman_test.go` around lines 16 -
18, The current test only checks `last < 1.0`, which is too weak; update the
test that uses the `last` variable to assert that the filter's outputs are
monotonically increasing across successive `Update`/prediction steps and that
the final `last` value is within a tight tolerance of the expected final
measurement (e.g., abs(last - expectedFinal) < tol). Locate the test that
updates the Kalman filter and replace the single permissive check with two
assertions: one that the sequence of outputs (tracked in a slice or by comparing
previous/next `last`) is non-decreasing, and another that the final `last` is
within the chosen tolerance of the known final value.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@phoenix_os/agents/internal/telemetry/math/kalman.go`:
- Around line 13-15: NewKalmanFilter currently accepts q, r, p (and
initialValue) without validation which allows negative/NaN covariances and
produces invalid updates; change NewKalmanFilter to validate inputs (use
math.IsNaN to reject NaN and require q, r, p >= 0 — or > 0 if you prefer strict
positive variances — and reject initialValue if NaN), and return an error when
any parameter is invalid (i.e., change signature to return (*KalmanFilter,
error)); construct and return the KalmanFilter only when all checks pass and
update callers to handle the error from NewKalmanFilter.
- Around line 18-31: The Update method on KalmanFilter mutates kf.p, kf.k and
kf.x but does not emit Phoenix Ledger evidence; modify KalmanFilter.Update to
produce a deterministic evidence record after the state change: serialize the
pre- and post-state (at least kf.x, kf.p, kf.k), the measurement and timestamp
using a stable encoding, compute a SHA-256 hash of that serialization, package
the hash and serialized payload into an evidence entry, and call the Phoenix
ledger API (e.g., PhoenixLedger.AppendEvidence or PhoenixLedger.RecordEvidence)
to persist it and check for errors; ensure the serialization is deterministic
and that errors from the ledger write are logged/returned as appropriate.

---

Nitpick comments:
In `@phoenix_os/agents/internal/telemetry/math/kalman_test.go`:
- Around line 16-18: The current test only checks `last < 1.0`, which is too
weak; update the test that uses the `last` variable to assert that the filter's
outputs are monotonically increasing across successive `Update`/prediction steps
and that the final `last` value is within a tight tolerance of the expected
final measurement (e.g., abs(last - expectedFinal) < tol). Locate the test that
updates the Kalman filter and replace the single permissive check with two
assertions: one that the sequence of outputs (tracked in a slice or by comparing
previous/next `last`) is non-decreasing, and another that the final `last` is
within the chosen tolerance of the known final value.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 33cd1428-a939-4530-9598-449be636cc18

📥 Commits

Reviewing files that changed from the base of the PR and between 955720d and d5dc9f3.

⛔ Files ignored due to path filters (1)
  • go.work is excluded by !**/*.work
📒 Files selected for processing (3)
  • phoenix_os/agents/internal/telemetry/math/go.mod
  • phoenix_os/agents/internal/telemetry/math/kalman.go
  • phoenix_os/agents/internal/telemetry/math/kalman_test.go

Comment on lines +13 to +15
func NewKalmanFilter(q, r, p, initialValue float64) *KalmanFilter {
return &KalmanFilter{q: q, r: r, p: p, x: initialValue}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Validate covariance inputs in constructor.

q, r, and p can be passed as negative/NaN, which can make updates numerically invalid. Add validation before constructing the filter (prefer returning an error for invalid parameters).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@phoenix_os/agents/internal/telemetry/math/kalman.go` around lines 13 - 15,
NewKalmanFilter currently accepts q, r, p (and initialValue) without validation
which allows negative/NaN covariances and produces invalid updates; change
NewKalmanFilter to validate inputs (use math.IsNaN to reject NaN and require q,
r, p >= 0 — or > 0 if you prefer strict positive variances — and reject
initialValue if NaN), and return an error when any parameter is invalid (i.e.,
change signature to return (*KalmanFilter, error)); construct and return the
KalmanFilter only when all checks pass and update callers to handle the error
from NewKalmanFilter.

Comment thread phoenix_os/agents/internal/telemetry/math/kalman.go Outdated
…Go workspace

- Remove all nested go.mod files (bus, guard, ledger, monitor, trace, warden, agents, sentinel, nexus, arbiter, kernel, telemetry, common)
- Delete speculative directories: agents/, sentinel/, nexus/, arbiter/, kernel/, telemetry/
- Remove obsolete trace/tests/ and common/math/ directories
- Unify package declarations in monitor/ (entropy_engine -> monitor)
- Update go.work to target single ./phoenix_os module
- Run go mod tidy to resolve dependencies
- All tests pass, deterministic replay hash verified:
  cd065910c87ba0c92ba3e267ea6b88249c234abfadacaebde3981581e1f4e252

Closes #706, #580, #623, #632, #627, #629
The old workflow built 14_experiments/telemetry_replay which used
a stale import path (phoenix/telemetry/bus/normalizer). The new
workflow builds phoenix_os/main.go and verifies deterministic
replay by comparing output hashes across two consecutive runs.
@fallofpheonix fallofpheonix merged commit e556921 into main May 21, 2026
6 checks passed
@fallofpheonix fallofpheonix deleted the feature/issue-706-kalman-drift-detection branch May 21, 2026 22:51
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.

[P1] [Phoenix Monitor] Implement Kalman-Based Drift Detection

2 participants