Skip to content

refactor(slm-backend): retire the 7 dead SLM monitoring modules whose function is live elsewhere (#16282) - #16308

Merged
mrveiss merged 7 commits into
mainfrom
issue-16282
Sep 13, 2026
Merged

mrveiss merged 7 commits into
mainfrom
issue-16282

Conversation

@mrveiss

@mrveiss mrveiss commented Sep 11, 2026 •

Copy link
Copy Markdown
Owner

Refs #16282. #16305, #16306 and #16307 (its sub-issues) carry the three modules that stay, and performance_monitor, which they still import.

Thinking Path

Retired (lines on base) Where its function lives now (base d5a0c6dcb)
advanced_apm_system (877) middleware/api_request_counter.py:35 with autobot_shared/monitoring/metrics/api_requests.py:39 record_request; api/performance.py:610 get_traces, :743 create_alert_rule
ai_performance_analytics (830) api/npu.py:457 GET /metrics; in autobot_shared/monitoring/metrics/: performance.py:295 update_npu_metrics, knowledge_base.py:225 record_search, llm_provider.py:26 LLMProviderMetricsRecorder
claude_api_monitor (596) autobot_shared/monitoring/prometheus_metrics.py:428 record_claude_api_request; autobot_shared/monitoring/metrics/claude_api.py:17 ClaudeAPIMetricsRecorder. It was already marked DEPRECATED (#348).
comprehensive_monitoring_controller (588), monitor_control (680) main.py:688-689 run the monitoring and performance routers in-process, behind dependencies=_SM, so no separate monitoring process remains to control
metrics_adapter (222) it wrapped get_metrics_manager(), which callers use directly
performance_dashboard (724) api/monitoring.py:695 /dashboard, :354 /metrics/fleet

What Changed

Deleted (10 files)

  • The 7 modules.
  • monitoring/start_monitoring.sh. It launched only the controller (:191, :209) and individual modules (:225-228), none of which can run: the controller and APM/analytics are retired, and the monitor and BI can't be imported.
  • monitoring/monitoring_config.yaml. Its only reader was monitor_control.py:186.
  • tests/test_claude_api_monitor.py. It exercised only claude_api_monitor.

Baselines

  • 4 entries each dropped from scripts/python_file_size_known_large.py and repo_tests/python_file_size_ratchet_baseline.py. performance_monitor's entry stays.
  • The SLM performance_dashboard line dropped from pipeline-scripts/hardcoded_values_baseline.txt.
  • .flake8:159 (performance_dashboard) dropped.

Operator scripts in autobot-infrastructure/shared/scripts/ (pytest's testpaths reach only shared/scripts/hooks, so CI collects none of these)

  • test_phase2_migration.py records Claude calls through the metrics manager instead of ClaudeAPIMonitor.
  • test_prometheus_metrics.py: removed the MetricsAdapter block, because its Prometheus writes are already exercised at :61-70. Also removed a duplicate logger assignment and a hardcoded IP.
  • test_phase5_cleanup.py: the ClaudeAPIMonitor check now asserts that the file is absent and that record_claude_api_request is still defined. It reads this through the AST, the way the compat check does. Removed the SLM sys.path insertion, which existed only for that import, and the now-unused asyncio, Callable and _emits_deprecation.

Docs

Commits

  1. 547e111bc: the retirement.
  2. c0c647809: removed the quick-deploy-verification.sh checks on logs/performance_monitor.log.
  3. Keeps performance_monitor.py, its baseline entries, its doc lines and those log checks, so relative to base, commit 2 nets out to nothing.

Not touched (boundary)

Verification

  • No importer is left for the 7. After the change, git grep -wE over the retired names (bare name and path form) turns up only the README, the phase-5 constant, and the boundary items above. performance_monitor.py's own imports (:12-30) include none of the 7.
  • Only the intended files differ from base. performance_monitor.py, quick-deploy-verification.sh and README_ASYNC_VALIDATION.md are identical to base.
  • Hooks and linters. Pre-commit passed on every commit, including the Python file size guard, Detect Hardcoded Values (Strict), Function Length Check, the Python canonical check, flake8 F821 over the whole repo, and Detect Mass Deletions. black, isort and flake8 are clean over the changed Python files.
  • CI is the evidence for the SLM and repo suites. Nothing was run locally.

Model Used

Claude Opus 5 (claude-opus-5)

Single-issue rationale

The owner split off #16282's three remaining modules as #16305, #16306 and #16307. They're different scopes (an SLM feature, the reconciler, and Company OS), and each lands in its own PR. What's left of #16282 is retiring the 7 modules whose function is already live elsewhere, and no other open issue shares that scope.

…ction is live elsewhere (#16282)

advanced_apm_system, ai_performance_analytics, claude_api_monitor,
comprehensive_monitoring_controller, metrics_adapter, monitor_control,
performance_dashboard and performance_monitor had no live importer, and each
one's function already lives in the SLM API or the shared Prometheus recorders.
Their launcher (start_monitoring.sh), monitor_control's config, the test that
exercised only claude_api_monitor, and their size, hardcoded-value and flake8
baseline entries go with them. The README now maps each retired module to its
live equivalent.

The operator scripts that imported them now record through the metrics
manager, and the phase-5 check asserts that claude_api_monitor is gone and its
successor is still defined.

performance_benchmark, performance_optimizer and business_intelligence_dashboard
stay: they are being wired in under #16305, #16306 and #16307.
… monitor's log (#16282)

quick-deploy-verification.sh read logs/performance_monitor.log, which only the SLM's monitoring/performance_monitor.py wrote (its line 159). That module never imported (it needed the main backend's config.ConfigManager) and is retired in this PR, so both checks read a file nothing writes.
@coderabbitai

coderabbitai Bot commented Sep 11, 2026 •

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Advanced

Run ID: 25efd458-a641-49e4-be83-f44a6032ee12


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.

@mrveiss

mrveiss commented Sep 11, 2026

Copy link
Copy Markdown
Owner Author

Review at c0c6478097: changes requested. Seven of the eight retirements hold, but performance_monitor.py can't go yet. It's a dependency of all three modules the owner ruled kept (09:05Z on #16282).

# Severity Where Finding Fix
1 High autobot-slm-backend/monitoring/performance_monitor.py (deleted) All three kept modules import from it by its bare name:
• business_intelligence_dashboard.py:35: from performance_monitor import ALERT_THRESHOLDS (#16307)
• performance_benchmark.py:27: from performance_monitor import VMS (#16305)
• performance_optimizer.py:19: from performance_monitor import PerformanceMonitor (#16306)
No live code imports those three today, so nothing breaks at runtime yet. But after this PR none of them can import, and the owner's ruling is that none of them is retired: they get wired in. So performance_monitor isn't "imported by no live code" in the sense the deletion rule means. It's a dependency of work the owner chose to keep. test_bi_dashboard.py stubs a fake performance_monitor module (:44, :89), so that test keeps passing and hides the break.
Either keep performance_monitor.py in this PR (retire seven), and retire it in whichever of #16305–#16307 lands last. Or move ALERT_THRESHOLDS, VMS and PerformanceMonitor somewhere the three kept modules import from, and point them at it here. Either way, record the dependency on #16305–#16307 (a note or a blocked_by), so wiring them in doesn't start from a missing import.

Verified, and it holds for the other seven (advanced_apm_system, ai_performance_analytics, claude_api_monitor, comprehensive_monitoring_controller, metrics_adapter, monitor_control, performance_dashboard):

  • No code file references them in import or path form, and neither start_monitoring.sh nor monitoring_config.yaml is referenced outside docs. The three claude_api_monitor mentions left are in test_phase5_cleanup.py, which asserts that file is absent (:185). phase_validation_system.py:756 points at a different, older path, scripts/performance_dashboard.py.
  • Every live equivalent the body cites exists on base d5a0c6dcb at its cited line. I spot-checked all 12: middleware/api_request_counter.py:35, api_requests.py:39 record_request, api/performance.py:610 and :743 and :833, api/npu.py:457, performance.py:295 update_npu_metrics, prometheus_metrics.py:428 record_claude_api_request, claude_api.py:17 ClaudeAPIMetricsRecorder, main.py:688, api/monitoring.py:695 and :354.
  • Baselines only shrink, and only for deleted files: .flake8 −1, hardcoded-values −1, and both ratchet files −5. Nothing is added.
  • Tests: test_claude_api_monitor.py goes with its module. The two SLM tests that change do so in comments only, and test_phase2_migration.py moves off ClaudeAPIMonitor onto the metrics manager.
  • quick-deploy-verification.sh: its two checks of logs/performance_monitor.log go with the log's only writer, and the body flags it.

Refs #16282 is right either way, since three modules remain.

@mrveiss

mrveiss commented Sep 11, 2026

Copy link
Copy Markdown
Owner Author

Addendum to the finding above: this PR's CI will go green even though the three kept modules can't import, so a green run is not evidence the deletion is safe.

Nothing in CI can see the break. It has to be settled in the diff (keep the module, or move the three symbols), and the tests for #16305–#16307 should import the real dependency rather than a stub.

…eing wired in still import (#16282)

business_intelligence_dashboard, performance_benchmark and performance_optimizer import performance_monitor by its bare name, and #16305, #16306 and #16307 wire those three in rather than retiring them. Deleting it would leave them one more import to replace. So it stays until the last of the three lands, along with its size-baseline entries and the two quick-deploy-verification.sh checks that read its log. The README records who removes it.
@mrveiss

mrveiss commented Sep 11, 2026

Copy link
Copy Markdown
Owner Author

Delta re-review since my changes-requested review at c0c6478097: approved at 20c6a53818. It merges on a settled green at that SHA. It now retires 7 modules, and performance_monitor.py stays until the last of #16305–#16307 lands.

Check Evidence at 20c6a5381
performance_monitor.py is restored unchanged Its blob is byte-identical to base d5a0c6dcb, so the three kept modules' imports (ALERT_THRESHOLDS, VMS, PerformanceMonitor) resolve again. quick-deploy-verification.sh is also byte-identical to base, so commit 2 nets out to nothing.
Keeping it doesn't keep a retired dependency performance_monitor.py imports none of the seven retired modules, and it doesn't read the deleted monitoring_config.yaml or start_monitoring.sh. Its only file access is appending to a metrics file (:583).
Deleted set Exactly the seven modules (advanced_apm_system, ai_performance_analytics, claude_api_monitor, comprehensive_monitoring_controller, metrics_adapter, monitor_control, performance_dashboard), plus monitoring_config.yaml, start_monitoring.sh and test_claude_api_monitor.py.
Baselines only shrink, and only for retired files .flake8 and the hardcoded-values baseline drop performance_dashboard.py. Both ratchet files drop advanced_apm_system.py, ai_performance_analytics.py, monitor_control.py and performance_dashboard.py. Nothing is added, and performance_monitor's entries stay.
The dependency is recorded #16282 (09:19Z): #16308 retires 7 of the 11, the rest stay, and the issue closes after its sub-issues rather than on this PR. The README records that whichever of #16305–#16307 lands last removes performance_monitor.py.

Everything from my first review of the seven stands: no code references, and all 12 cited live equivalents verified at their lines on base. Refs #16282 is right. When #16305–#16307 come for review, their tests should import the real performance_monitor, not the sys.modules stub test_bi_dashboard*.py installs, so the dependency is actually exercised.

@github-actions

Copy link
Copy Markdown
Contributor

✅ SSOT Configuration Compliance: Passing

🎉 No new hardcoded values of either class — ssot and other both block.

Known backlog in pipeline-scripts/hardcoded_values_baseline.txt is suppressed and tracked in #14371.

mrveiss added a commit that referenced this pull request Sep 11, 2026
mrveiss added a commit that referenced this pull request Sep 11, 2026
…e count, so deleting unique code can't fail it (#16319) (#16323)

* chore(claim): helper-02 takes the duplication-guard unit fix (#16319)

* ci(duplication-guard): gate each scope on its absolute duplicated-line count, so deleting unique code can't fail it (#16319)

The guard pinned jscpd's duplicated-lines percentage a hair above its
measurement. #16308 deleted about 4.5k unique lines and failed it. It kept the
same 135 clones and 4,729 duplicated lines, but a smaller denominator moved
the ratio from 1.82% to 1.85%. The rule is "no new duplication", so the count
is what gets pinned now.

- scripts/duplication_gate.py reads jscpd's Total row and applies the pin. It
  is the only parser: both gate steps and "Explain failure" call it, and the
  awk parser in "Explain failure" is gone.
- The pins come from base run 34581036896 (d5a0c6d, jscpd 5.0.6):
  MAX_DUP_LINES 11723 and SLM_MAX_DUP_LINES 4729. The main pin tightens: its
  1.05% was never lowered as duplication fell to 0.74%.
- The report-only pre-scan of the SLM trees is gone, since the gate prints the
  figure on every run.
- The tests cover the parser on the verbatim #16163 row, #16308's figures
  passing, one added duplicated line failing, and the unmeasured, non-count
  and unreadable cases. The repo test now pins each gate's scanned trees, and
  "Explain failure" reports the overage in lines.
- RATCHET_BASELINES.md gains rule 7: pin the quantity the rule limits, not a
  ratio of it.

* fix(ci): drop a stray escaped space that passed jscpd an extra argument in the SLM gate (#16319)

The SLM gate's -i line ended in `\\ \\`: the rewrite appended a line continuation to a line that already carried one, so jscpd received a one-space string as an extra argument. Review finding on #16323.
…DFATHERED list (#16308)

This PR deletes autobot-slm-backend/tests/test_claude_api_monitor.py
along with the rest of the legacy monitoring module it tested, so the
file no longer exists for the sweep to scan. It drops out of the
offenders set and the GRANDFATHERED entry goes stale --
test_the_grandfathered_list_has_not_gone_stale catches exactly this:
an entry that no longer offends must be removed, since the list only
shrinks.

The other two GRANDFATHERED files this PR touches
(test_api_request_counter.py, test_prometheus_registry_endpoint.py)
only had a stale comment reference fixed and still carry their
unrestored sys.modules writes, so they stay grandfathered.
@mrveiss mrveiss added this to the v0.9.0 milestone Sep 12, 2026
@mrveiss mrveiss self-assigned this Sep 12, 2026
@mrveiss

mrveiss commented Sep 12, 2026

Copy link
Copy Markdown
Owner Author

Content review: approve.

Verified independently against base ([] no manual link, body is Refs-only): grepped for live importers of all 7 retired modules across autobot-slm-backend — none found outside the retired set itself (metrics_adapter.py imports claude_api_monitor, but metrics_adapter is also being retired in this same PR, so that's not an external dependency). Spot-checked two of the table's line-number claims against base: prometheus_metrics.py:428 record_claude_api_request and api/monitoring.py:354 /metrics/fleet both match exactly.

Good boundary discipline: performance_monitor stays because all 3 modules the owner chose to wire in (#16305/16306/16307) still import it by bare name — retiring it here would break work in flight elsewhere. The README documents which sub-issue removes it last, so that decision isn't lost.

closingIssuesReferences=[] matches body (Refs #16282 only). CI green, no missing required contexts. Ready.

@mrveiss
mrveiss merged commit b277e82 into main Sep 13, 2026
81 checks passed
@mrveiss
mrveiss deleted the issue-16282 branch September 13, 2026 00:45
mrveiss added a commit that referenced this pull request Oct 3, 2026
…pulation (#17142)

RATCHET_BASELINES.md rule 7 says "pin the quantity the rule limits, not a ratio of it", and #17142
replaces two absolute floors with fractions. A reviewer reading that rule would reasonably flag it,
so the rule gains the discriminator rather than this change claiming an exception -- because the
question rule 7 already asks is the right question, and this change passes it.

The discriminator is whether numerator and denominator are the SAME population. jscpd failed
because they were not: duplicated lines over all scanned lines, so deleting unique code moved the
denominator alone and #16308 failed by removing 4.5k lines of dead code. The reach floor passes
because they are: the sweep's own suffix-matched files over an independent count of the same set,
so `.md`/`.ts`/`.vue` churn moves neither side and adding or splitting a `.py` file moves both.

The part worth recording is that rule 7 was ALREADY WRITTEN when the first version of #17142 got
this wrong. That version took a fraction of the whole tracked tree as a floor on a counted subset --
precisely the failure the rule describes -- and the rule did not fire, because I did not read it
before freezing a ratio. So the entry says "ask the question for the ratio you are about to freeze,
not for ratios in general", which is the form that would have caught it.

Rule 8 is new and is the one 50 asked to be made durable: a migration assertion inherits the
baseline it records. #17142's `_SUPERSEDED` recorded the tracked-file count as the denominator for a
guard that bounds a subset. Fix the declaration, leave the baseline, and the test written to stop
the claim drifting certifies the drift -- failing in the one direction nobody re-checks, because a
passing migration test reads as a faithful migration. Hence: change the recorded baseline in the
same commit, and state which quantity the number is of.
mrveiss added a commit that referenced this pull request Oct 3, 2026
…pulation (#17142)

RATCHET_BASELINES.md rule 7 says "pin the quantity the rule limits, not a ratio of it", and #17142
replaces two absolute floors with fractions. A reviewer reading that rule would reasonably flag it,
so the rule gains the discriminator rather than this change claiming an exception -- because the
question rule 7 already asks is the right question, and this change passes it.

The discriminator is whether numerator and denominator are the SAME population. jscpd failed
because they were not: duplicated lines over all scanned lines, so deleting unique code moved the
denominator alone and #16308 failed by removing 4.5k lines of dead code. The reach floor passes
because they are: the sweep's own suffix-matched files over an independent count of the same set,
so `.md`/`.ts`/`.vue` churn moves neither side and adding or splitting a `.py` file moves both.

The part worth recording is that rule 7 was ALREADY WRITTEN when the first version of #17142 got
this wrong. That version took a fraction of the whole tracked tree as a floor on a counted subset --
precisely the failure the rule describes -- and the rule did not fire, because I did not read it
before freezing a ratio. So the entry says "ask the question for the ratio you are about to freeze,
not for ratios in general", which is the form that would have caught it.

Rule 8 is new and is the one 50 asked to be made durable: a migration assertion inherits the
baseline it records. #17142's `_SUPERSEDED` recorded the tracked-file count as the denominator for a
guard that bounds a subset. Fix the declaration, leave the baseline, and the test written to stop
the claim drifting certifies the drift -- failing in the one direction nobody re-checks, because a
passing migration test reads as a faithful migration. Hence: change the recorded baseline in the
same commit, and state which quantity the number is of.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant