Skip to content

feat: separate human vs bot activity in health dashboard#3917

Merged
marcusquinn merged 3 commits intomainfrom
feature/activity-human-bot-split
Mar 8, 2026
Merged

feat: separate human vs bot activity in health dashboard#3917
marcusquinn merged 3 commits intomainfrom
feature/activity-human-bot-split

Conversation

@marcusquinn
Copy link
Owner

@marcusquinn marcusquinn commented Mar 8, 2026

Summary

  • Replaces unreliable "productive hours" metric with commit-type breakdown (Direct vs PR Merges) using the git committer email field to distinguish GitHub squash-merges from direct pushes
  • Adds cross-repo totals table to health issues — aggregates activity across all pulse-enabled repos without revealing repo names (privacy-safe)
  • New cross-repo-summary command in contributor-activity-helper.sh for aggregating stats across multiple repos

Changes

contributor-activity-helper.sh

  • Git log format now includes committer email (%ce) alongside author email (%ae)
  • is_pr_merge() detects GitHub squash-merges (committer = noreply@github.com)
  • Drops productive_hours and daily_spans tracking — replaced with direct_commits and pr_merges counters
  • New cross-repo-summary command accepts multiple repo paths, outputs privacy-safe aggregated table
  • user command updated with same direct/PR-merge breakdown
  • Table columns: Contributor | Direct | PR Merges | Total | Active Days | Avg/Day
  • Cross-repo table adds Repos column showing how many repos each contributor is active in

pulse-wrapper.sh

  • Activity section now calls cross-repo-summary with all pulse-enabled repo paths from repos.json
  • Health issue body includes new "Cross-Repo Totals (last 30 days)" section below per-repo stats
  • Graceful fallback: shows "Single repo or cross-repo data unavailable." when only one repo or repos.json missing

Testing

Verified against all 8 managed repos:

  • Per-repo summary: correct direct/PR-merge split
  • Cross-repo summary: aggregates across 8 repos, no repo names exposed
  • Edge cases: non-git dir → error, no args → error, help → usage text
  • ShellCheck: clean (only pre-existing SC1091 info for external source)

Summary by CodeRabbit

  • New Features

    • Cross-repo totals: aggregate contributor activity across multiple repositories and include a consolidated section in per-repo health reports.
    • New command to produce cross-repo summaries for reuse across reports.
  • Updates

    • Activity reporting now separates Direct Commits and PR Merges, and sorts by their combined total.
    • Tables show Direct, PR Merges, Total, Active Days, and Avg/Day; bots are more comprehensively filtered.
  • Removed

    • Per-day productive-hours metric replaced by commit-type totals.

Replace unreliable 'productive hours' metric with commit-type breakdown
using the committer email field to distinguish PR merges (GitHub squash-
merge, committer=noreply@github.com) from direct commits.

New columns: Direct | PR Merges | Total | Active Days | Avg/Day

Add cross-repo-summary command that aggregates activity across all
pulse-enabled repos without revealing repo names (privacy-safe).
Health issues now show per-repo stats and cross-repo totals.
@github-actions github-actions bot added the enhancement Auto-created from TODO.md tag label Mar 8, 2026
@gemini-code-assist
Copy link

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the contributor activity tracking system by providing a more accurate and insightful view of development efforts. It moves beyond a simple commit count to categorize contributions by their origin (direct push vs. PR merge) and offers a consolidated, high-level summary of activity across an entire portfolio of repositories. This change improves the understanding of team dynamics and overall project health by focusing on meaningful engagement rather than just raw output.

Highlights

  • Activity Type Differentiation: Replaced the 'productive hours' metric with a more granular breakdown of commit types, distinguishing between 'Direct' commits (human-initiated pushes) and 'PR Merges' (GitHub squash-merges), using the Git committer email to identify the source.
  • Cross-Repository Activity Summary: Introduced a new feature to aggregate contributor activity across multiple pulse-enabled repositories into a single, privacy-safe totals table, without revealing individual repository names.
  • New CLI Command: Added a new cross-repo-summary command to contributor-activity-helper.sh to facilitate the aggregation of statistics across various repositories.
  • Enhanced Health Dashboard: The health dashboard now includes a 'Cross-Repo Totals' section, providing a consolidated view of activity, with graceful fallback for when cross-repo data is unavailable.
Changelog
  • .agents/scripts/contributor-activity-helper.sh
    • Updated script comments to detail the new commit type detection logic.
    • Added cross-repo-summary to the script's usage instructions.
    • Modified activity computation to track 'Direct commits' and 'PR merges' instead of 'Total commits' and 'Productive hours'.
    • Changed git log format to include committer email for accurate commit type identification.
    • Introduced is_bot and is_pr_merge Python functions for filtering bot activity and identifying PR merges.
    • Refactored Python script logic to count direct commits and PR merges, removing productive hours calculation.
    • Adjusted markdown table output to display 'Direct', 'PR Merges', and 'Total' columns.
    • Updated user_activity function to also use committer email for commit type breakdown.
    • Implemented the cross_repo_summary shell function with an embedded Python script to aggregate activity data from multiple repositories.
    • Expanded the main command handler to include the new cross-repo-summary command and updated help text with commit type explanations.
  • .agents/scripts/pulse-wrapper.sh
    • Modified the script to call the new cross-repo-summary command from contributor-activity-helper.sh.
    • Integrated the cross-repo activity summary into the health issue body, creating a dedicated 'Cross-Repo Totals' section.
    • Added a fallback message for when cross-repo activity data is not available.
Activity
  • No human activity (comments, reviews) was detected on this pull request.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 8, 2026

Warning

Rate limit exceeded

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

⌛ 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f6da3555-e6f5-452a-a58e-e655ce8a9b8d

📥 Commits

Reviewing files that changed from the base of the PR and between 0aa4dca and d4bb867.

📒 Files selected for processing (2)
  • .agents/scripts/contributor-activity-helper.sh
  • .agents/scripts/pulse-wrapper.sh

Walkthrough

Enhanced contributor activity analysis with commit-type awareness (direct commits vs PR merges), bot-filtering logic, and cross-repository aggregation. New cross_repo_summary() function computes activity metrics across multiple repositories, while updated metrics distinguish commit origins and track active days alongside averaged contribution rates.

Changes

Cohort / File(s) Summary
Contributor Activity Enhancement
.agents/scripts/contributor-activity-helper.sh
Introduces commit-type differentiation via committer email detection (identifies PR merges vs direct commits), adds bot-filtering logic, expands email-based input parsing, restructures aggregation to compute direct_commits, pr_merges, total_commits, active_days, and avg commits/day; adds cross_repo_summary() function for multi-repo aggregation with JSON and markdown output support; updates help documentation and output formats.
Cross-Repo Integration
.agents/scripts/pulse-wrapper.sh
Integrates cross-repository activity totals into pulse output by invoking contributor-activity-helper.sh's cross-repo-summary command when multiple repos are detected; injects cross-repo data into pulse body under "Cross-Repo Totals (last 30 days)" section.

Sequence Diagram

sequenceDiagram
    participant PW as pulse-wrapper.sh
    participant CAH as contributor-activity-helper.sh
    participant RJ as repos.json
    participant R as Repository

    PW->>RJ: Check if repos exist
    alt Multiple repos detected
        PW->>PW: Initialize cross_repo_md
        PW->>CAH: cross-repo-summary [paths] --period 30
        CAH->>R: Iterate repositories
        R->>CAH: Extract commits (filter bots)
        CAH->>CAH: Classify commits (direct/PR merge)
        CAH->>CAH: Aggregate per-repo metrics
        CAH->>CAH: Compute totals across repos
        CAH-->>PW: Return aggregated JSON/markdown
        PW->>PW: Insert into pulse body
        PW-->>PW: Include "Cross-Repo Totals" section
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

📊 Commits now wear their colors true,
Direct or merged—we know which flew,
Bots filtered out with careful grace,
Cross-repos counted in one place. 🚀

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Title check ⚠️ Warning The title 'separate human vs bot activity in health dashboard' is somewhat misleading—the main changes focus on distinguishing direct commits from PR merges, not human vs bot activity. Consider revising the title to 'feat: distinguish direct commits from PR merges in activity metrics' to accurately reflect the primary change.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feature/activity-human-bot-split

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.

@github-actions
Copy link

github-actions bot commented Mar 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 367 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Mar 8 19:06:51 UTC 2026: Code review monitoring started
Sun Mar 8 19:06:51 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 367

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 367
  • VULNERABILITIES: 0

Generated on: Sun Mar 8 19:06:54 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

coderabbitai[bot]
coderabbitai bot previously requested changes Mar 8, 2026
Copy link
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/scripts/contributor-activity-helper.sh:
- Around line 339-345: The aggregation currently concatenates per-repo JSON
counts (repo_json) into all_json and then sums active_days, which double-counts
users active in multiple repos on the same calendar day; change
compute_activity(...) calls to return per-user per-day keys (e.g., list of ISO
dates or raw commit rows) instead of only counts, then update the aggregation
logic that builds all_json and computes Active Days/Avg/Day to deduplicate by
unique user+date before counting active_days; specifically modify the
compute_activity caller in this script (where repo_json is assigned) to request
the day-level output and change the downstream merging logic (all_json assembly
and the active_days/Avg/Day rollup routines) to union user-date entries rather
than summing per-repo counts so cross-repo overlaps are not double-counted.

In @.agents/scripts/pulse-wrapper.sh:
- Around line 1974-1987: The cross-repo markdown is being regenerated inside the
per-repo loop inside _update_health_issue_for_repo, causing redundant scans;
move the logic that builds cross_repo_md (the block using repos_json_path, jq,
cross_args and calling bash "$activity_helper" cross-repo-summary) out of
_update_health_issue_for_repo and build it once in update_health_issues() before
iterating repos, store it in a shared variable (e.g., shared_cross_repo_md) and
pass that value into each call to _update_health_issue_for_repo (or memoize
access) so the heavy git log walk runs only once per pulse.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: d18a8996-b6b4-45e6-808a-da864899cbcc

📥 Commits

Reviewing files that changed from the base of the PR and between 2a680e7 and 0aa4dca.

📒 Files selected for processing (2)
  • .agents/scripts/contributor-activity-helper.sh
  • .agents/scripts/pulse-wrapper.sh

Copy link

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request enhances contributor activity metrics by replacing the less reliable "productive hours" metric with a breakdown of direct commits versus PR merges, and introduces a cross-repository activity summary for a holistic view. A critical security concern has been identified: a potential command injection vulnerability in .agents/scripts/contributor-activity-helper.sh due to unquoted variable usage in a shell command, which should be addressed by proper quoting. Additionally, a significant logical error in the calculation of cross-repository active days results in inflated metrics, which is critical to address for the reliability of this feature. There is also a minor maintainability concern with some duplicated Python helper functions.

local git_data
# shellcheck disable=SC2086
git_data=$(git -C "$repo_path" log --all --format='%ae|%aI' $since_arg) || git_data=""
git_data=$(git -C "$repo_path" log --all --format='%ae|%ce|%aI' $since_arg) || git_data=""

Choose a reason for hiding this comment

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

security-high high

The variable $since_arg is used without double quotes in the git log command. While this is likely intended to allow word splitting for multiple arguments (e.g., --since='...'), it can lead to command injection if the input used to construct $since_arg is not strictly validated. In the cross_repo_summary function, the period argument is taken directly from the command line and passed to compute_activity, which then uses it to build $since_arg. An attacker could potentially inject arbitrary shell commands by providing a malicious --period value.

Suggested change
git_data=$(git -C "$repo_path" log --all --format='%ae|%ce|%aI' $since_arg) || git_data=""
git_data=$(git -C "$repo_path" log --all --format='%ae|%ce|%aI' "$since_arg") || git_data=""
References
  1. To prevent command injection from shell metacharacters, wrap variables in single quotes. This is a POSIX-compliant method to prevent all shell expansion, including $(...), backticks, and variable expansion. While double quotes are used in the suggestion, the core principle of preventing command injection through proper quoting is aligned with this rule.

Comment on lines 168 to 169
'active_days': active_days,
'productive_hours': round(total_hours, 1),
'avg_commits_per_day': round(avg_per_day, 1)

Choose a reason for hiding this comment

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

high

To enable correct aggregation of active days in the cross-repo-summary command, the JSON output from this function needs to include the raw list of active days for each contributor. This is a prerequisite for the fix in cross_repo_summary.

Suggested change
'active_days': active_days,
'productive_hours': round(total_hours, 1),
'avg_commits_per_day': round(avg_per_day, 1)
'active_days': active_days,
'active_days_list': list(data['days']),
'avg_commits_per_day': round(avg_per_day, 1)

Comment on lines +361 to +392
# Aggregate per contributor across all repos
totals = {}
for repo in repos:
for entry in repo.get('data', []):
login = entry['login']
if login not in totals:
totals[login] = {
'direct_commits': 0,
'pr_merges': 0,
'total_commits': 0,
'active_days': 0,
'repo_count': 0,
}
totals[login]['direct_commits'] += entry.get('direct_commits', 0)
totals[login]['pr_merges'] += entry.get('pr_merges', 0)
totals[login]['total_commits'] += entry.get('total_commits', 0)
totals[login]['active_days'] += entry.get('active_days', 0)
if entry.get('total_commits', 0) > 0:
totals[login]['repo_count'] += 1

results = []
for login, data in sorted(totals.items(), key=lambda x: -x[1]['total_commits']):
avg = data['total_commits'] / data['active_days'] if data['active_days'] > 0 else 0
results.append({
'login': login,
'direct_commits': data['direct_commits'],
'pr_merges': data['pr_merges'],
'total_commits': data['total_commits'],
'active_days': data['active_days'],
'repos_active': data['repo_count'],
'avg_commits_per_day': round(avg, 1),
})

Choose a reason for hiding this comment

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

high

The current implementation incorrectly calculates active_days in the cross-repo summary by summing the counts from each repository. This leads to inflated values if a contributor is active in multiple repos on the same day. The correct approach is to count the number of unique active days across all repositories. This also makes the Avg/Day calculation inaccurate.

This can be fixed by using a set to collect unique day strings from the active_days_list (which needs to be added to the compute_activity output) and then calculating the total active days from the size of the set.

# Aggregate per contributor across all repos
totals = {}
for repo in repos:
    for entry in repo.get('data', []):
        login = entry['login']
        if login not in totals:
            totals[login] = {
                'direct_commits': 0,
                'pr_merges': 0,
                'total_commits': 0,
                'active_days_set': set(),
                'repo_count': 0,
            }
        totals[login]['direct_commits'] += entry.get('direct_commits', 0)
        totals[login]['pr_merges'] += entry.get('pr_merges', 0)
        totals[login]['total_commits'] += entry.get('total_commits', 0)
        totals[login]['active_days_set'].update(entry.get('active_days_list', []))
        if entry.get('total_commits', 0) > 0:
            totals[login]['repo_count'] += 1

results = []
for login, data in sorted(totals.items(), key=lambda x: -x[1]['total_commits']):
    active_days = len(data['active_days_set'])
    avg = data['total_commits'] / active_days if active_days > 0 else 0
    results.append({
        'login': login,
        'direct_commits': data['direct_commits'],
        'pr_merges': data['pr_merges'],
        'total_commits': data['total_commits'],
        'active_days': active_days,
        'repos_active': data['repo_count'],
        'avg_commits_per_day': round(avg, 1),
    })

Comment on lines +218 to +227
def email_to_login(email):
if email.endswith('@users.noreply.github.com'):
local = email.split('@')[0]
return local.split('+', 1)[1] if '+' in local else local
local_part = email.split('@')[0]
return local_part.split('+', 1)[1] if '+' in local_part else local_part
if email in ('actions@github.com', 'action@github.com'):
return 'github-actions'
return email.split('@')[0]

def is_pr_merge(committer_email):
return committer_email == 'noreply@github.com'

Choose a reason for hiding this comment

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

medium

The helper functions email_to_login and is_pr_merge are duplicated between the Python scripts in compute_activity and user_activity. This creates a maintainability issue, as any changes to this logic would need to be applied in multiple places. Consider refactoring this shared logic into a common location that can be sourced by both Python snippets to avoid duplication. For example, you could define the functions in a separate Python file and prepend its content to the python3 -c command string.

- JSON output now includes active_days_list for cross-repo set union
- Cross-repo active days uses set union instead of sum, fixing inflation
  where same-day commits in multiple repos were double-counted
- Cross-repo summary computed once in update_health_issues() and passed
  to each _update_health_issue_for_repo() call, avoiding N×N git walks
- Extract shared Python helpers (email_to_login, is_bot, is_pr_merge)
  into PYTHON_HELPERS shell variable, injected into all Python blocks
- Add comment explaining SC2086 since_arg safety (hardcoded case values)
@github-actions
Copy link

github-actions bot commented Mar 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 367 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Mar 8 19:18:55 UTC 2026: Code review monitoring started
Sun Mar 8 19:18:55 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 367

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 367
  • VULNERABILITIES: 0

Generated on: Sun Mar 8 19:18:58 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@marcusquinn
Copy link
Owner Author

@coderabbitai review

Addressed both review findings:

  1. Active days deduplication: JSON output now includes active_days_list (sorted day strings). Cross-repo aggregation uses set union instead of summing counts — verified: marcusquinn shows 29 deduplicated days (was 40 when summed).
  2. Cross-repo computed once: Moved cross-repo summary computation from _update_health_issue_for_repo() to update_health_issues(), computed once and passed as $3 to each per-repo call.
  3. Shared Python helpers: Extracted email_to_login, is_bot, is_pr_merge into PYTHON_HELPERS shell variable, injected into all Python blocks.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 8, 2026

@marcusquinn — thanks for the detailed update! All three fixes look well-considered:

  1. Active days deduplication — set union is the correct approach; summing counts across repos would inflate the metric for contributors active in multiple repos simultaneously. Good to see the 29 vs. 40 verification.
  2. Cross-repo computed once — moving the computation to update_health_issues() and passing it as $3 is a clean architectural improvement, avoiding redundant subprocess calls per repo.
  3. Shared PYTHON_HELPERS — DRY principle applied correctly; single source of truth for email_to_login, is_bot, and is_pr_merge across all Python blocks reduces drift risk.

Triggering a fresh review now to assess the updated implementation.


🧠 Learnings used
Learnt from: marcusquinn
Repo: marcusquinn/aidevops PR: 0
File: :0-0
Timestamp: 2026-03-03T16:33:18.313Z
Learning: For the marcusquinn/aidevops repository: The daily quality sweep system (pulse-wrapper.sh) should only mention coderabbitai for full codebase review when there are significant changes (Quality Gate failure, +10 issues in one day, etc.), not on every automated sweep with stable metrics.

Learnt from: marcusquinn
Repo: marcusquinn/aidevops PR: 3893
File: .agents/scripts/pulse-wrapper.sh:452-455
Timestamp: 2026-03-08T16:59:32.817Z
Learning: In marcusquinn/aidevops, the `supervisor` label has been in production on all managed repos for months as a role label for health dashboard issues. The `contributor` label was added in PR `#3893` following the same convention for non-maintainer health dashboards. Renaming these labels would break existing health issues and require migration logic — label namespacing is a known deferred follow-up item, not an immediate fix requirement. Both labels are only created on repos with `pulse: true` in repos.json, which are fully framework-managed repos.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai bot previously requested changes Mar 8, 2026
Copy link
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.agents/scripts/contributor-activity-helper.sh:
- Around line 148-151: Replace the literal equality check against
'github-actions' with the existing is_bot(...) helper: after computing
committer_login = email_to_login(committer_email) use is_bot(committer_login)
(or is_bot(committer_email) if that helper expects an email) to skip any bot
committers; update the identical check later in the script (the other occurrence
using committer_login) to the same is_bot(...) call so all bot variants like
'github-actions[bot]' or 'dependabot[bot]' are filtered consistently.
- Around line 339-345: The loop over repo_paths in cross-repo-summary silently
skips non-git paths (the if checking "$rp/.git" then continue), causing false
"no activity" exits; change this to fail fast: when a path lacks a .git entry,
write a clear error to stderr including the offending repo path (use the same
variable rp) and exit with a non-zero status instead of continuing. Update
handling around compute_activity and repo_json so the script does not mask input
errors (i.e., only allow repo_json="[]" for genuine compute_activity failures,
not for invalid paths), and ensure any callers of this script see the non-zero
exit code on invalid repo paths.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0b2b9191-9d6b-47bb-be7c-8008288932d5

📥 Commits

Reviewing files that changed from the base of the PR and between 0aa4dca and d3ac586.

📒 Files selected for processing (2)
  • .agents/scripts/contributor-activity-helper.sh
  • .agents/scripts/pulse-wrapper.sh

Comment on lines +339 to +345
for rp in "${repo_paths[@]}"; do
if [[ ! -d "$rp/.git" && ! -f "$rp/.git" ]]; then
continue
fi
local repo_json
repo_json=$(compute_activity "$rp" "$period" "json") || repo_json="[]"
if [[ "$first" == "true" ]]; then
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Fail fast on invalid repo paths in cross-repo-summary.

Right now nongit inputs are silently skipped, so this command can exit 0 and print “no activity” for bad paths. That makes operator mistakes look like empty data instead of an input error.

Suggested fix
  for rp in "${repo_paths[@]}"; do
  	if [[ ! -d "$rp/.git" && ! -f "$rp/.git" ]]; then
- 		continue
+ 		echo "Error: $rp is not a git repository" >&2
+ 		return 1
  	fi
  	local repo_json
  	repo_json=$(compute_activity "$rp" "$period" "json") || repo_json="[]"

As per coding guidelines, automation scripts should focus on clear logging and feedback and proper exit codes.

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

In @.agents/scripts/contributor-activity-helper.sh around lines 339 - 345, The
loop over repo_paths in cross-repo-summary silently skips non-git paths (the if
checking "$rp/.git" then continue), causing false "no activity" exits; change
this to fail fast: when a path lacks a .git entry, write a clear error to stderr
including the offending repo path (use the same variable rp) and exit with a
non-zero status instead of continuing. Update handling around compute_activity
and repo_json so the script does not mask input errors (i.e., only allow
repo_json="[]" for genuine compute_activity failures, not for invalid paths),
and ensure any callers of this script see the non-zero exit code on invalid repo
paths.

- Replace literal 'github-actions' check with is_bot(committer_login)
  in both compute_activity and user_activity Python blocks, catching
  dependabot[bot] and other bot committers consistently
- Add stderr warning for invalid repo paths in cross-repo-summary
  instead of silent skip (keeps resilient behaviour for unmounted drives)
@marcusquinn
Copy link
Owner Author

@coderabbitai review

Round 2 fixes applied:

  1. is_bot() for committer filtering — replaced literal == 'github-actions' with is_bot(committer_login) in both compute_activity and user_activity Python blocks. Now catches dependabot[bot], renovate[bot], etc.
  2. Warning on invalid repo pathscross-repo-summary now emits a stderr warning for non-git paths instead of silently skipping. Keeps resilient behaviour (continues with remaining repos) but makes operator mistakes visible.
  3. Active days deduplication — this was already fixed in the previous commit (line 378-392 uses active_days_set with set union). The comment on line 350 appears to be a stale finding from the first review.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Mar 8, 2026

@marcusquinn — thanks for the Round 2 summary! All three points are well-addressed:

  1. is_bot() for committer filtering — using the shared helper for committer filtering is the right call; the literal == 'github-actions' check was a fragile single-case guard. The generalised is_bot() now provides consistent coverage across [bot]-suffixed and -bot-suffixed accounts in both Python blocks.

  2. Warning on invalid repo paths — stderr warning with continued execution is the correct resilience pattern here: operators get visibility on misconfigured paths without halting the entire cross-repo sweep.

  3. Active days deduplication — noted, and you're right. The active_days_set / set union approach at lines 378–392 was already in place from the prior commit. The comment on line 350 was a stale finding from the first review pass — I should have caught that. Apologies for the noise.

Triggering a fresh review now against the current state of the branch.


🧠 Learnings used
Learnt from: marcusquinn
Repo: marcusquinn/aidevops PR: 0
File: :0-0
Timestamp: 2026-03-03T16:33:18.313Z
Learning: For the marcusquinn/aidevops repository: The daily quality sweep system (pulse-wrapper.sh) should only mention coderabbitai for full codebase review when there are significant changes (Quality Gate failure, +10 issues in one day, etc.), not on every automated sweep with stable metrics.

Learnt from: marcusquinn
Repo: marcusquinn/aidevops PR: 3893
File: .agents/scripts/pulse-wrapper.sh:452-455
Timestamp: 2026-03-08T16:59:32.817Z
Learning: In marcusquinn/aidevops, the `supervisor` label has been in production on all managed repos for months as a role label for health dashboard issues. The `contributor` label was added in PR `#3893` following the same convention for non-maintainer health dashboards. Renaming these labels would break existing health issues and require migration logic — label namespacing is a known deferred follow-up item, not an immediate fix requirement. Both labels are only created on repos with `pulse: true` in repos.json, which are fully framework-managed repos.
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@github-actions
Copy link

github-actions bot commented Mar 8, 2026

🔍 Code Quality Report

�[0;35m[MONITOR]�[0m Code Review Monitoring Report

�[0;34m[INFO]�[0m Latest Quality Status:
SonarCloud: 0 bugs, 0 vulnerabilities, 367 code smells

�[0;34m[INFO]�[0m Recent monitoring activity:
Sun Mar 8 19:27:15 UTC 2026: Code review monitoring started
Sun Mar 8 19:27:16 UTC 2026: SonarCloud - Bugs: 0, Vulnerabilities: 0, Code Smells: 367

📈 Current Quality Metrics

  • BUGS: 0
  • CODE SMELLS: 367
  • VULNERABILITIES: 0

Generated on: Sun Mar 8 19:27:19 UTC 2026


Generated by AI DevOps Framework Code Review Monitoring

@sonarqubecloud
Copy link

sonarqubecloud bot commented Mar 8, 2026

@marcusquinn marcusquinn dismissed stale reviews from coderabbitai[bot] and coderabbitai[bot] March 8, 2026 19:31

All findings addressed in commits d3ac586 and d4bb867.

@marcusquinn marcusquinn merged commit 0dffa55 into main Mar 8, 2026
12 checks passed
@marcusquinn marcusquinn deleted the feature/activity-human-bot-split branch March 8, 2026 19:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement Auto-created from TODO.md tag

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant