Skip to content

feat: enhance Civic Intelligence Engine delta and emerging concern logic#491

Open
RohanExploit wants to merge 2 commits intomainfrom
feature/daily-civic-intelligence-engine-3734117019519320683
Open

feat: enhance Civic Intelligence Engine delta and emerging concern logic#491
RohanExploit wants to merge 2 commits intomainfrom
feature/daily-civic-intelligence-engine-3734117019519320683

Conversation

@RohanExploit
Copy link
Owner

@RohanExploit RohanExploit commented Feb 28, 2026

This submission improves the Daily Civic Intelligence Refinement Engine by allowing the system to accurately highlight the top_emerging_concern using mathematically calculated volume growth comparisons (instead of just pure volume). It also enriches the generated snapshot's civic_index with delta and delta_str attributes (e.g. +3.1 from yesterday) to help track system performance and user behavior trends effectively.

Also included is a newly created test suite, test_civic_intelligence_delta.py which mocks out filesystem, caching, and DB components to confidently test the new mathematical growth calculations over simulated consecutive daily operations. All tests execute successfully.


PR created automatically by Jules for task 3734117019519320683 started by @RohanExploit


Summary by cubic

Improve the Daily Civic Intelligence Engine to rank emerging concerns by percentage growth and to show day-over-day index changes. Adds tests for growth logic and delta formatting.

  • New Features
    • Compute top_emerging_concern using highest percentage increase; handle new surges and fall back to volume.
    • Add civic_index.delta and civic_index.delta_str (e.g., +3.1 from yesterday) when a previous score exists.
    • Add tests simulating consecutive days to assert growth ranking and delta output.

Written for commit 8ed2d12. Summary will update on new commits.

Summary by CodeRabbit

  • New Features
    • Added category growth tracking to identify top emerging concerns based on highest growth percentage during spike detection
    • Civic Intelligence Index now displays day-over-day score changes, showing how the index moved from the previous day

- Updated `backend/civic_intelligence.py` to calculate the Civic Intelligence Index delta and properly assign `top_emerging_concern` based on the highest category percentage growth.
- Added a new suite of unit tests in `backend/tests/test_civic_intelligence_delta.py` that fully cover logic around index deltas and emerging concerns.
Copilot AI review requested due to automatic review settings February 28, 2026 19:01
@google-labs-jules
Copy link
Contributor

👋 Jules, reporting for duty! I'm here to lend a hand with this pull request.

When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down.

I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job!

For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with @jules. You can find this option in the Pull Request section of your global Jules UI settings. You can always switch back!

New to Jules? Learn more at jules.google/docs.


For security, I will only act on instructions from the user who triggered this task.

@netlify
Copy link

netlify bot commented Feb 28, 2026

Deploy Preview for fixmybharat canceled.

Name Link
🔨 Latest commit 8ed2d12
🔍 Latest deploy log https://app.netlify.com/projects/fixmybharat/deploys/69a33c8341e8fc0008bc91c1

@github-actions
Copy link

🙏 Thank you for your contribution, @RohanExploit!

PR Details:

Quality Checklist:
Please ensure your PR meets the following criteria:

  • Code follows the project's style guidelines
  • Self-review of code completed
  • Code is commented where necessary
  • Documentation updated (if applicable)
  • No new warnings generated
  • Tests added/updated (if applicable)
  • All tests passing locally
  • No breaking changes to existing functionality

Review Process:

  1. Automated checks will run on your code
  2. A maintainer will review your changes
  3. Address any requested changes promptly
  4. Once approved, your PR will be merged! 🎉

Note: The maintainers will monitor code quality and ensure the overall project flow isn't broken.

@coderabbitai
Copy link

coderabbitai bot commented Feb 28, 2026

📝 Walkthrough

Walkthrough

This PR enhances the Civic Intelligence Index with day-over-day delta tracking and improves emerging concern detection by computing category growth metrics during spike detection, complemented by comprehensive unit tests for the new functionality.

Changes

Cohort / File(s) Summary
Core Delta & Growth Logic
backend/civic_intelligence.py
Added category_growth tracking during spike detection to identify top_emerging_concern based on highest percentage growth. Updated _calculate_index method signature to accept previous_snapshot parameter and compute delta scores (current vs. previous day). Extended index results with delta and delta_str fields when available. Modified top emerging concern logic to prefer trends.top_emerging_concern with fallback to category_distribution.
Delta & Growth Test Coverage
backend/tests/test_civic_intelligence_delta.py
Added two new unit tests: test_emerging_concern_growth_logic validates that emerging concerns are correctly ranked by growth percentage; test_civic_intelligence_index_delta verifies delta calculation (e.g., delta of +2.0 with delta_str "+2.0 from yesterday"). Uses mocked dependencies including SessionLocal, trend_analyzer, and file I/O to validate daily cycle behavior.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Suggested labels

size/m

Poem

🐰 With whiskers twitched and nose held high,
We track the delta way up sky,
Each growth spike marked, each concern found,
Yesterday's echo in data sound,
The trends emerge, so crisp and clear—
Intelligence grows year by year!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main changes: enhancing the Civic Intelligence Engine with delta tracking and emerging concern logic based on growth calculations.
Description check ✅ Passed The PR description is comprehensive and well-structured, clearly explaining the improvements to the Civic Intelligence Engine with specific examples of new features (delta tracking, growth-based ranking).

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

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/daily-civic-intelligence-engine-3734117019519320683

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.

Copy link
Contributor

@cubic-dev-ai cubic-dev-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.

No issues found across 2 files

Copy link
Contributor

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

Enhances the Daily Civic Intelligence Refinement Engine to (a) identify top_emerging_concern using growth-based comparisons and (b) enrich the generated snapshot’s civic_index with day-over-day delta and delta_str, with accompanying tests covering the new behaviors.

Changes:

  • Add growth-based emerging-concern selection and persist trends.top_emerging_concern in the daily snapshot.
  • Extend civic_index generation to compute and emit delta and delta_str from the previous snapshot score.
  • Add a new pytest suite to validate emerging concern growth ranking and civic index delta output.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
backend/civic_intelligence.py Implements growth-based spike/emerging concern logic and adds civic index delta fields derived from the prior snapshot.
backend/tests/test_civic_intelligence_delta.py Adds tests that mock filesystem/DB dependencies to validate emerging concern growth logic and civic index delta formatting.

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

Comment on lines +74 to +85
category_growth[category] = increase
elif prev_count == 0 and count > 5:
spikes.append(category) # New surge
# Represent "infinite" growth for new surges by assigning a high placeholder
# or based on pure volume, for ranking emerging concerns
category_growth[category] = float(count)

trends['spikes'] = spikes
# Find the top emerging concern based on highest percentage growth
top_emerging = "None"
if category_growth:
top_emerging = max(category_growth, key=category_growth.get)
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

category_growth stores percent-growth ratios for existing categories (increase) but uses float(count) for new surges (prev_count == 0). That mixes units (ratio vs absolute count), so max(category_growth, key=...) can pick a “top emerging concern” based on incomparable values. Use a consistent metric (e.g., treat new surges as float('inf')/a very large sentinel, or store a tuple like (is_new, increase, count) and compare deterministically).

Suggested change
category_growth[category] = increase
elif prev_count == 0 and count > 5:
spikes.append(category) # New surge
# Represent "infinite" growth for new surges by assigning a high placeholder
# or based on pure volume, for ranking emerging concerns
category_growth[category] = float(count)
trends['spikes'] = spikes
# Find the top emerging concern based on highest percentage growth
top_emerging = "None"
if category_growth:
top_emerging = max(category_growth, key=category_growth.get)
# Store as (is_new, percent_increase, current_count) for consistent comparison
category_growth[category] = (0, increase, count)
elif prev_count == 0 and count > 5:
spikes.append(category) # New surge
# Represent new surges explicitly; they outrank existing spikes via is_new flag
category_growth[category] = (1, 0.0, count)
trends['spikes'] = spikes
# Find the top emerging concern based on highest percentage growth
top_emerging = "None"
if category_growth:
# Select category with highest (is_new, percent_increase, count) tuple
top_emerging = max(category_growth.items(), key=lambda item: item[1])[0]

Copilot uses AI. Check for mistakes.
Comment on lines +246 to +251
if delta is not None:
result["delta"] = delta
# Format string delta like "+3.1 from yesterday"
sign = "+" if delta >= 0 else ""
result["delta_str"] = f"{sign}{delta} from yesterday"

Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

delta_str can become malformed for small negative deltas that round to -0.0 (Python keeps the sign), because the sign is computed from delta >= 0 and then interpolated with the negative-zero value (resulting in "+-0.0 from yesterday"). Normalize delta to 0.0 when it rounds to zero (or format using an explicit sign formatter like f"{delta:+.1f}" after normalization).

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +5
import os
from unittest.mock import MagicMock, patch, mock_open
from datetime import datetime, timezone
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

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

This test module includes unused imports (os, datetime, timezone), which adds noise and can trip linting if enabled. Remove them or use them in the tests.

Suggested change
import os
from unittest.mock import MagicMock, patch, mock_open
from datetime import datetime, timezone
from unittest.mock import MagicMock, patch, mock_open

Copilot uses AI. Check for mistakes.
Copy link

@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.

🧹 Nitpick comments (3)
backend/civic_intelligence.py (2)

189-189: Use explicit Optional type hint.

Per PEP 484, a parameter with a None default should have an explicit optional type. The static analysis tool correctly flagged this.

-    def _calculate_index(self, db: Session, issues_24h: List[Issue], trends: Dict[str, Any], previous_snapshot: Dict[str, Any] = None) -> Dict[str, Any]:
+    def _calculate_index(self, db: Session, issues_24h: List[Issue], trends: Dict[str, Any], previous_snapshot: Dict[str, Any] | None = None) -> Dict[str, Any]:

Or if targeting Python <3.10:

from typing import Optional
# ...
previous_snapshot: Optional[Dict[str, Any]] = None
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/civic_intelligence.py` at line 189, The parameter previous_snapshot
in the _calculate_index method has a default of None but lacks an explicit
Optional type; update the signature of _calculate_index to annotate
previous_snapshot as Optional[Dict[str, Any]] (and add "from typing import
Optional" if not already imported) so the type correctly reflects a nullable
dictionary.

75-79: Clarify the growth placeholder heuristic for new surges.

Using float(count) as a growth proxy for new categories (where prev_count == 0) creates an implicit weighting scheme: a new surge with 6+ issues will always rank higher than an existing category with <500% growth. If this prioritization is intentional (new categories are more alarming), consider documenting it. Otherwise, a consistent approach could use a fixed high constant (e.g., float('inf') or 1000.0) to clearly signal "new surge always wins."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/civic_intelligence.py` around lines 75 - 79, The code path handling
new surges (elif prev_count == 0 and count > 5) currently sets
category_growth[category] = float(count), which implicitly weights new
categories by raw volume and can unfairly outrank large-percentage growths;
change this to use a clear, consistent placeholder (for example float('inf') or
a defined constant like NEW_SURGE_WEIGHT = 1000.0) and add a one-line comment
explaining the chosen heuristic so the behavior is explicit; update the
assignment in the branch that appends to spikes and set
category_growth[category] to the new constant instead of float(count).
backend/tests/test_civic_intelligence_delta.py (1)

1-12: Unused imports.

datetime and timezone (line 5) and os (line 3) are imported but not directly used in the test code. The engine uses its own internal datetime. Consider removing unused imports.

 import pytest
 import json
-import os
 from unittest.mock import MagicMock, patch, mock_open
-from datetime import datetime, timezone
 
 from backend.models import Issue
 from backend.civic_intelligence import CivicIntelligenceEngine
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/tests/test_civic_intelligence_delta.py` around lines 1 - 12, Remove
the unused imports in the test module: delete the os import and the datetime,
timezone imports from the top of backend/tests/test_civic_intelligence_delta.py
so only required imports remain (keep pytest, json, and the unittest.mock
imports as needed) and ensure the CivicIntelligenceEngine fixture function name
engine() and referenced symbols (CivicIntelligenceEngine, Issue) remain
unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@backend/civic_intelligence.py`:
- Line 189: The parameter previous_snapshot in the _calculate_index method has a
default of None but lacks an explicit Optional type; update the signature of
_calculate_index to annotate previous_snapshot as Optional[Dict[str, Any]] (and
add "from typing import Optional" if not already imported) so the type correctly
reflects a nullable dictionary.
- Around line 75-79: The code path handling new surges (elif prev_count == 0 and
count > 5) currently sets category_growth[category] = float(count), which
implicitly weights new categories by raw volume and can unfairly outrank
large-percentage growths; change this to use a clear, consistent placeholder
(for example float('inf') or a defined constant like NEW_SURGE_WEIGHT = 1000.0)
and add a one-line comment explaining the chosen heuristic so the behavior is
explicit; update the assignment in the branch that appends to spikes and set
category_growth[category] to the new constant instead of float(count).

In `@backend/tests/test_civic_intelligence_delta.py`:
- Around line 1-12: Remove the unused imports in the test module: delete the os
import and the datetime, timezone imports from the top of
backend/tests/test_civic_intelligence_delta.py so only required imports remain
(keep pytest, json, and the unittest.mock imports as needed) and ensure the
CivicIntelligenceEngine fixture function name engine() and referenced symbols
(CivicIntelligenceEngine, Issue) remain unchanged.

ℹ️ Review info

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 62aa431 and c1b90f3.

📒 Files selected for processing (2)
  • backend/civic_intelligence.py
  • backend/tests/test_civic_intelligence_delta.py

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants