feat(health): weekly report#264
Conversation
✅ Deploy Preview for agentscan ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
📝 WalkthroughWalkthroughThe PR migrates scan output to weekly JSON plus temporary raw results, adds weekly and current-week health APIs, updates health consumers and charts, and revises Discord notifications and workflow staging for the new files. ChangesWeekly ecosystem health
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant ScanUsers
participant WeeklyAggregator
participant TempResults
participant WeeklyResults
participant HealthAPI
participant HealthUI
ScanUsers->>TempResults: accumulate scan results
ScanUsers->>WeeklyAggregator: build weekly entry on Sunday
WeeklyAggregator->>WeeklyResults: write weekly health record
HealthUI->>HealthAPI: request health data
HealthAPI->>WeeklyResults: read weekly records
WeeklyResults-->>HealthAPI: return weekly data
HealthAPI-->>HealthUI: return counts, trends, dates, and closure metrics
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (1)
scripts/notify-discord.ts (1)
17-38: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winLog the webhook response body on failure.
Discord often returns helpful error details (like invalid format structures or rate-limiting info) in the response body when a request fails. Logging the response text will make debugging much easier when the webhook drops a payload.
♻️ Proposed refactor
if (!discordRes.ok) { - console.error('Discord webhook failed:', discordRes.status) + console.error('Discord webhook failed:', discordRes.status, await discordRes.text().catch(() => '')) process.exit(1) }🤖 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 `@scripts/notify-discord.ts` around lines 17 - 38, Update sendDiscordNotification so that when discordRes.ok is false, it reads the webhook response body and includes the response text in the existing console.error call alongside the status before exiting.
🤖 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 `@app/components/Report/WeeklyClassification.vue`:
- Line 16: Update the data source in WeeklyClassification to use the weekly
health endpoint backed by getClassificationByDateChunks() with rolling disabled,
rather than useEcosystemHealthCurrentWeek(). Preserve the chart’s existing
classification rendering while ensuring it receives complete Monday–Sunday week
data.
In `@scripts/migrate-scan-results-to-weekly.ts`:
- Around line 65-67: Update the fallback in the droppedLeadingDays filter to use
'0000-00-00' instead of '9999-99-99' when completeWeekStarts[0] is absent,
ensuring leftoverDays are preserved as trailing data when no complete weeks
exist.
In `@scripts/scan-users.ts`:
- Around line 279-288: The weekly aggregation around isEndOfWeek must process
every complete week present in tmpResults, not only when the current UTC day is
Sunday. Reuse the detection, extraction, and flushing logic from
migrate-scan-results-to-weekly.ts so missed or delayed runs aggregate older
complete weeks, retain incomplete records, and clear tmpResults only after
successful processing.
In `@server/api/health-current-week.get.ts`:
- Around line 15-20: Update the raw-file handling in the current-week health
endpoint to distinguish a missing scan-results-tmp.txt file from an existing
file with empty content. Preserve the missing-file error, but when the loaded
content is empty, return the endpoint’s normal empty response shape instead of
calling unpack or producing HTTP 500.
---
Nitpick comments:
In `@scripts/notify-discord.ts`:
- Around line 17-38: Update sendDiscordNotification so that when discordRes.ok
is false, it reads the webhook response body and includes the response text in
the existing console.error call alongside the status before exiting.
🪄 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: b35d55e8-0b5f-40cd-af45-39c5e4fb1a78
📒 Files selected for processing (19)
.github/workflows/scan-users.ymlapp/components/Chart/FeaturedPackageHealthRanking.vueapp/components/Chart/GlobalEventsEvolution.vueapp/components/Chart/HealthResponseSparklines.vueapp/components/Health/TrendItemList.vueapp/components/Report/WeeklyClassification.vueapp/composables/useEcosystemHealthCurrentWeek.tsapp/pages/lab.vuedata/scan-results-tmp.txtdata/scan-results.jsondata/scan-results.txtscripts/migrate-scan-results-to-weekly.tsscripts/notify-discord.tsscripts/scan-users.tsserver/api/health-current-week.get.tsserver/api/health.get.tsshared/types/ecosystem-health.tsshared/utils/count-classification-by-date.tsshared/utils/weekly-aggregator.ts
| import('vue-data-ui/style.css') | ||
|
|
||
| const { data } = useEcosystemHealth() | ||
| const { data } = useEcosystemHealthCurrentWeek() |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
rg -n -A80 -B10 \
"health-current-week|defineEventHandler|current.?week|weekly" \
server/api/health-current-week.get.ts \
server/api/health.get.ts
rg -n -A5 -B5 \
"useEcosystemHealth(CurrentWeek)?" \
app/composablesRepository: MatteoGabriele/agentscan
Length of output: 10825
🏁 Script executed:
#!/bin/bash
set -euo pipefail
ast-grep outline app/components/Report/WeeklyClassification.vue --view expanded || true
printf '\n---\n'
cat -n app/components/Report/WeeklyClassification.vue
printf '\n---\n'
ast-grep outline shared/utils/count-classification-by-date.ts --view expanded || true
printf '\n---\n'
cat -n shared/utils/count-classification-by-date.tsRepository: MatteoGabriele/agentscan
Length of output: 22952
Keep the weekly report on the weekly health endpoint.
getClassificationByDateChunks() with rolling: false only renders complete Monday–Sunday weeks. useEcosystemHealthCurrentWeek() exposes the current partial week, so this chart stays empty until Sunday and then resets to another partial week.
-const { data } = useEcosystemHealthCurrentWeek()
+const { data } = useEcosystemHealth()📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const { data } = useEcosystemHealthCurrentWeek() | |
| const { data } = useEcosystemHealth() |
🤖 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 `@app/components/Report/WeeklyClassification.vue` at line 16, Update the data
source in WeeklyClassification to use the weekly health endpoint backed by
getClassificationByDateChunks() with rolling disabled, rather than
useEcosystemHealthCurrentWeek(). Preserve the chart’s existing classification
rendering while ensuring it receives complete Monday–Sunday week data.
| const droppedLeadingDays = leftoverDays.filter( | ||
| (day) => day < (completeWeekStarts[0] ?? '9999-99-99'), | ||
| ) |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Safeguard against data loss when no complete weeks exist.
If there are no complete weeks (e.g., less than 7 days of historical data), completeWeekStarts will be empty. completeWeekStarts[0] evaluates to undefined, causing the fallback '9999-99-99' to be used. Because all dates will evaluate as strictly less than '9999-99-99', all data points will be classified as leading days and incorrectly dropped instead of being preserved as trailing days.
Change the fallback to '0000-00-00' to safely retain trailing data when no complete weeks exist.
🛡️ Proposed fix to preserve data
const droppedLeadingDays = leftoverDays.filter(
- (day) => day < (completeWeekStarts[0] ?? '9999-99-99'),
+ (day) => day < (completeWeekStarts[0] ?? '0000-00-00'),
)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const droppedLeadingDays = leftoverDays.filter( | |
| (day) => day < (completeWeekStarts[0] ?? '9999-99-99'), | |
| ) | |
| const droppedLeadingDays = leftoverDays.filter( | |
| (day) => day < (completeWeekStarts[0] ?? '0000-00-00'), | |
| ) |
🤖 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 `@scripts/migrate-scan-results-to-weekly.ts` around lines 65 - 67, Update the
fallback in the droppedLeadingDays filter to use '0000-00-00' instead of
'9999-99-99' when completeWeekStarts[0] is absent, ensuring leftoverDays are
preserved as trailing data when no complete weeks exist.
| const isEndOfWeek = new Date(now).getUTCDay() === 0 // Sunday | ||
|
|
||
| if (isEndOfWeek) { | ||
| const weeklyResults = dryRun ? [] : loadWeeklyResults() | ||
| weeklyResults.push(buildWeeklyEntry(tmpResults, now)) | ||
| saveWeeklyResults(weeklyResults, dryRun) | ||
| saveTmpResults([], dryRun) | ||
| } else { | ||
| saveTmpResults(tmpResults, dryRun) | ||
| } |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
Potential data loss if a Sunday run is missed or delayed.
If the cron job fails on a Sunday (e.g., due to a GitHub API outage) or is delayed just past midnight UTC into Monday, isEndOfWeek will evaluate to false. The week's data will correctly remain in tmpResults.
However, on the following Sunday, buildWeeklyEntry(tmpResults, now) will only extract records matching that specific new week, completely ignoring the older records. The subsequent saveTmpResults([], dryRun) will then clear the file, permanently deleting the previous week's data without ever aggregating it.
Consider reusing the logic from migrate-scan-results-to-weekly.ts to detect, extract, and flush all complete weeks found within tmpResults regardless of the current execution day, rather than relying strictly on getUTCDay() === 0 and now.
🤖 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 `@scripts/scan-users.ts` around lines 279 - 288, The weekly aggregation around
isEndOfWeek must process every complete week present in tmpResults, not only
when the current UTC day is Sunday. Reuse the detection, extraction, and
flushing logic from migrate-scan-results-to-weekly.ts so missed or delayed runs
aggregate older complete weeks, retain incomplete records, and clear tmpResults
only after successful processing.
| if (!raw) { | ||
| throw new Error('scan-results-tmp.txt not found') | ||
| } | ||
|
|
||
| const content = Buffer.isBuffer(raw) ? raw.toString('utf-8') : String(raw) | ||
| const results: EcosystemHealthItem[] = unpack(content) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
Return an empty payload when the temporary results file is empty.
An empty scan-results-tmp.txt is an expected rollover state, but !raw turns it into HTTP 500 and breaks current-week charts. Distinguish a missing file from empty content and return the normal response shape.
Proposed fix
- if (!raw) {
+ if (raw == null) {
throw new Error('scan-results-tmp.txt not found')
}
const content = Buffer.isBuffer(raw) ? raw.toString('utf-8') : String(raw)
+
+ if (!content.trim()) {
+ return {
+ results: [],
+ categoryProgression: {
+ automation: calcLinearProgression([]),
+ mixed: calcLinearProgression([]),
+ organic: calcLinearProgression([]),
+ },
+ countsByDate: {},
+ dates: [],
+ scanTimes: [],
+ }
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if (!raw) { | |
| throw new Error('scan-results-tmp.txt not found') | |
| } | |
| const content = Buffer.isBuffer(raw) ? raw.toString('utf-8') : String(raw) | |
| const results: EcosystemHealthItem[] = unpack(content) | |
| if (raw == null) { | |
| throw new Error('scan-results-tmp.txt not found') | |
| } | |
| const content = Buffer.isBuffer(raw) ? raw.toString('utf-8') : String(raw) | |
| if (!content.trim()) { | |
| return { | |
| results: [], | |
| categoryProgression: { | |
| automation: calcLinearProgression([]), | |
| mixed: calcLinearProgression([]), | |
| organic: calcLinearProgression([]), | |
| }, | |
| countsByDate: {}, | |
| dates: [], | |
| scanTimes: [], | |
| } | |
| } | |
| const results: EcosystemHealthItem[] = unpack(content) |
🤖 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 `@server/api/health-current-week.get.ts` around lines 15 - 20, Update the
raw-file handling in the current-week health endpoint to distinguish a missing
scan-results-tmp.txt file from an existing file with empty content. Preserve the
missing-file error, but when the loaded content is empty, return the endpoint’s
normal empty response shape instead of calling unpack or producing HTTP 500.
Summary by CodeRabbit
New Features
Bug Fixes