Skip to content

feat: dry run covers the full selected window — background drain (backend) - #119

Merged
Bonobo791 merged 10 commits into
devfrom
feat-dry-run-window
Aug 6, 2026
Merged

Bonobo791 merged 10 commits into
devfrom
feat-dry-run-window

Conversation

@Bonobo791

@Bonobo791 Bonobo791 commented Aug 6, 2026 •

Copy link
Copy Markdown
Collaborator

User description

What

Fixes the audited no-op: the dry-run preview fetched with the live cursor and deduped against stored comments ids, so on any channel with moderation history it wrote nothing. The dry run now covers all comments over a selected time period — including comments real runs already moderated.

  • Migration 0019 — channels.dry_run_boundary / dry_run_page_token (nullable; both null = no drain in flight). Independent of the live cursor — real runs keep advancing undisturbed. Applied + PRAGMA-verified on dev (20 migrations). (Note: history_next_page_token/history_boundary from Live-first scanning during long history drains #70 are dead columns — nothing on main reads them; dropping them is DB-lane, out of scope.)
  • runChannel window mode — window: { boundary, pageToken } with forceDryRun: fetches one page bounded by the window (cursor/checkpoint ignored, maxPages forced to 1), and decideNewComments gains rescore which skips the stored-IDs dedupe (within-batch dedupe stays). Returns windowNextPageToken/windowComplete; persists nothing itself (I8).
  • Dashboard dryRun action — validates months ∈ {1,3,6,12,24} (default 3, same presets as Analyze history), scores the first page synchronously under the atomic lease, and persists the drain continuation (or clears it when the window completes). Response gains months and background.
  • Cron — after the normal run, one drain page per invocation while a preview is in flight (shared deadline; partial → state untouched, retried next run). Channels with a drain in flight sort first in the rotation so previews don't starve. Drain failures are loud, surfaced in the payload, and never mask the normal run.

Out of scope (frontend lane follow-up)

  • Months <select> on the dry-run form (same presets, default 3) — backend accepts/defaults months, so the shipped button already works with the 3-month window.
  • Success message wording for the background drain.

Verification

  • npm run test: 953 passed — new failing-first tests: window fetch semantics + rescore + continuation (pipeline), months validation/default/drain-state persist/reset (dashboard), drain continuation/clear/rotation-order/failure-isolation (cron).
  • npm run check: 0 errors / 0 warnings. npm run build: green.

CodeAnt-AI Description

Extend dry-run previews across a selected comment history window

What Changed

  • Dry-run previews now cover a selectable 1, 3, 6, 12, or 24-month window, defaulting to 3 months.
  • Previews rescore comments that were already handled by live moderation, so existing moderation history no longer causes the preview to return no results.
  • The first page runs immediately; remaining pages continue in the background through scheduled runs without advancing or changing the live scan.
  • In-progress previews are prioritized, retain their continuation state across runs, and report drain failures without hiding the normal moderation result.
  • Window previews are always simulation-only; attempts to run them as live moderation are rejected.

Impact

✅ Complete previews across the selected history window
✅ Existing moderated comments included in dry-run results
✅ Live moderation cursor remains undisturbed

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

@cla-bot cla-bot Bot added the cla-signed label Aug 6, 2026
@codeant-ai

codeant-ai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

🤖 CodeAnt AI — Review Status

Status Commit Started (UTC) Finished (UTC)
✅ Incremental review completed c80ba0f Aug 06, 2026 · 11:41 11:42
✅ Incremental review completed 11398d8 Aug 06, 2026 · 11:25 11:28
✅ Reviewed your PR 457d44c Aug 06, 2026 · 10:49 10:53

@netlify

netlify Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for moderaty ready!

Name Link
🔨 Latest commit 62102ee
🔍 Latest deploy log https://app.netlify.com/projects/moderaty/deploys/6a7474532eeb4100086d7e28
😎 Deploy Preview https://deploy-preview-119--moderaty.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
🤖 Make changes Run an agent on this branch

To edit notification comments on pull requests, go to your Netlify project configuration.

@codeant-ai

codeant-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files label Aug 6, 2026
@codeant-ai

codeant-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Sequence Diagram

The dashboard previews the first page of a selected comment window and stores continuation state when more pages remain. Later cron runs continue one drain page after the normal channel run, rescoring previously moderated comments until the window completes.

sequenceDiagram
    participant User
    participant Dashboard
    participant Backend
    participant YouTube
    participant Storage
    participant Cron

    User->>Dashboard: Start dry run with month window
    Dashboard->>Backend: Claim channel and request first window page
    Backend->>YouTube: Fetch comments bounded by window
    YouTube-->>Backend: Return comment page
    Backend->>Storage: Save preview audits and drain state
    Backend-->>Dashboard: Return preview counts and background status

    Cron->>Backend: Run normal channel scan
    Backend->>Backend: Drain one preview page
    Backend->>YouTube: Fetch next window page and rescore comments
    Backend->>Storage: Update continuation or clear completed drain
Loading

Generated by CodeAnt AI

@amazon-q-developer amazon-q-developer Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The implementation successfully addresses the dry-run audit issue by enabling full historical window previews. The changes are well-architected with proper separation of concerns:

Key Strengths:

  • Database migration properly adds independent dry-run state tracking (dryRunBoundary/dryRunPageToken)
  • Window mode correctly bypasses stored-ID deduplication via the rescore flag, enabling re-scoring of already-moderated comments
  • Background drain continuation is properly isolated from live cursor state
  • Comprehensive test coverage (953 tests passed, 0 errors/warnings)
  • Proper concurrency control with atomic lease claims prevents race conditions
  • Cron prioritizes channels with active drains to prevent starvation

Architecture:
The implementation correctly separates dry-run window state from live moderation, ensuring real runs continue undisturbed while previews drain in the background. The window boundary validation limits cost exposure (presets: 1,3,6,12,24 months), and the shared deadline prevents runaway operations.

No blocking defects identified. The feature is ready for merge.


You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.

@codeant-ai

codeant-ai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

🏁 CodeAnt Quality Gate Results

Commit: 62102ee2
Scan Time: 2026-08-06 12:10:32 UTC

✅ Overall Status: PASSED

Quality Gate Details

Quality Gate Status Details
Secrets ✅ PASSED 0 secrets found
Duplicate Code ✅ PASSED 0.0% duplicated
SAST ✅ PASSED No security issues
Bugs ✅ PASSED Rating S: No bugs
IAC ✅ PASSED Rating S: No issues

View Full Results

@qodo-code-review

Copy link
Copy Markdown

PR Summary by Qodo

Dry-run window preview with background drain and independent continuation

🐞 Bug fix ✨ Enhancement 🧪 Tests 📝 Documentation ⚙️ Configuration changes 🕐 40+ Minutes

Grey Divider

AI Description

• Fix dry-run preview no-op by rescoring all comments within a selected time window.
• Persist dry-run drain state on channels and have cron drain one page per run.
• Add tests covering window fetch, rescore semantics, persistence, and cron isolation.
Diagram

graph TD
  U["Dashboard dryRun"] --> RC["runChannel (window)"] --> FNC["fetchNewComments"] --> YT{{"YouTube API"}}
  CR["Cron job"] --> RN["runChannel (normal)"]
  CR --> RD["runChannel (drain)"] --> FNC
  RC --> DNC["decideNewComments (rescore)"] --> AL[("audit_log")]
  U --> CH[("channels")]
  CR --> CH

  subgraph Legend
    direction LR
    _svc["Handler/Service"] ~~~ _db[("DB table")] ~~~ _ext{{"External"}}
  end
Loading
High-Level Assessment

The following are alternative approaches to this PR:

1. Dedicated dry-run drain job table
  • ➕ Avoids overloading channels with operational state
  • ➕ Supports multiple concurrent drains per channel/user
  • ➕ Easier audit/debugging of drain progress
  • ➖ More schema/API surface area and cleanup logic
  • ➖ More joins/locking to keep lease semantics consistent
  • ➖ Overkill if only one drain can exist at a time
2. Queue-based background worker (separate from cron)
  • ➕ Lower latency for completing previews (no wait for next cron tick)
  • ➕ Natural retry/backoff semantics
  • ➕ Separates normal moderation SLA from preview drain work
  • ➖ Requires job infrastructure and deployment changes
  • ➖ More moving pieces to secure/operate
  • ➖ Harder to keep a single shared deadline/lease model without careful design

Recommendation: Current approach is appropriate given the existing bounded-cron model: store minimal continuation state on channels, drain one page per cron invocation, and keep the live cursor untouched. The explicit failure isolation (drain errors never mask normal runs) and the enforced one-page bound in window mode are good guardrails; a separate job table/worker would only be warranted if multiple drains or faster completion becomes a product requirement.

Files changed (13) +1315 / -34

Enhancement (3) +64 / -8
schema.tsAdd dry-run drain fields to channels table definition +2/-0

Add dry-run drain fields to channels table definition

• Adds dryRunBoundary and dryRunPageToken to the Drizzle channels schema, documenting their role as independent dry-run window drain state.

src/lib/server/db/schema.ts

+page.server.tsSupport months-based dry-run window and persist drain continuation +26/-5

Support months-based dry-run window and persist drain continuation

• Adds months validation (1/3/6/12/24, default 3) and computes a boundary timestamp. Runs the first window page under the lease and persists/clears channels dry-run drain state based on window completion, returning months and background indicators.

src/routes/(app)/dashboard/+page.server.ts

+server.tsDrain one dry-run window page per cron run and prioritize drain channels +36/-3

Drain one dry-run window page per cron run and prioritize drain channels

• Prioritizes channels with a dry-run drain in flight in selection order. After the normal run, executes a dry-run window drain step under the same lease/deadline, updates continuation state, and surfaces drain failures in the response without masking the normal run.

src/routes/api/cron/+server.ts

Bug fix (1) +47 / -19
pipeline.tsImplement runChannel window mode with rescore and continuation output +47/-19

Implement runChannel window mode with rescore and continuation output

• Adds optional window parameters to runChannel to fetch exactly one bounded page independent of live state. Updates decideNewComments to support rescore (skip stored-IDs dedupe), and returns windowNextPageToken/windowComplete in dry-run window mode without persisting state.

src/lib/server/pipeline.ts

Tests (5) +236 / -6
schema.test.tsExtend channels schema expectations for dry-run columns +2/-0

Extend channels schema expectations for dry-run columns

• Updates schema tests to assert the new dry_run_boundary and dry_run_page_token columns exist and are nullable.

src/lib/server/db/schema.test.ts

pipeline.test.tsAdd pipeline tests for window-mode fetching, rescore, and continuation +57/-0

Add pipeline tests for window-mode fetching, rescore, and continuation

• Introduces failing-first tests ensuring window mode ignores the live cursor/checkpoint, rescoring bypasses stored-ID dedupe, and window continuation is reported but not persisted by runChannel.

src/lib/server/pipeline.test.ts

testdb.tsAdd dry-run columns to test DB schema +2/-0

Add dry-run columns to test DB schema

• Extends the test SQLite schema for channels to include dry_run_boundary and dry_run_page_token so tests can persist drain state.

src/lib/server/testdb.ts

actions.test.tsTest months validation and drain state persist/clear on dryRun action +74/-6

Test months validation and drain state persist/clear on dryRun action

• Updates dryRun tests to assert default months behavior, boundary computation, and correct persistence/clearing of dry-run drain state. Adds a 400 case for unsupported months presets and verifies background=true when continuation exists.

src/routes/(app)/dashboard/actions.test.ts

cron.test.tsTest cron drain continuation, ordering, completion, and failure isolation +101/-0

Test cron drain continuation, ordering, completion, and failure isolation

• Adds tests covering: draining one page after the normal run, token persistence, clearing on completion, prioritization of draining channels, and ensuring drain failures are loud and do not break normal cron behavior.

src/routes/api/cron/cron.test.ts

Documentation (1) +7 / -1
AGENTS.mdDocument dry-run window preview and background drain behavior +7/-1

Document dry-run window preview and background drain behavior

• Extends the I8 guidance to explain month-window dry-run previews and the cron-driven drain mechanism. Clarifies that window mode intentionally rescoring previously moderated comments is expected.

AGENTS.md

Other (3) +961 / -0
0019_channels_dry_run_window.sqlAdd channels dry-run drain state columns +2/-0

Add channels dry-run drain state columns

• Introduces nullable channels.dry_run_boundary and channels.dry_run_page_token to persist dry-run window drain continuation state. Both null indicates no drain in flight.

drizzle/0019_channels_dry_run_window.sql

0019_snapshot.jsonUpdate Drizzle schema snapshot for migration 0019 +952/-0

Update Drizzle schema snapshot for migration 0019

• Captures updated SQLite schema metadata including the new dry_run_boundary and dry_run_page_token columns on channels.

drizzle/meta/0019_snapshot.json

_journal.jsonRegister migration 0019 in Drizzle journal +7/-0

Register migration 0019 in Drizzle journal

• Adds the 0019_channels_dry_run_window migration entry to the Drizzle migration journal.

drizzle/meta/_journal.json

@codacy-production

codacy-production Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 59 complexity · 0 duplication

Metric Results
Complexity ✅ 59 (≤ 100 complexity)
Duplication ✅ 0 (≤ 1 duplication)

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@codeant-ai

codeant-ai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

PR Code Suggestions ✨

Previous suggestions up to commit 457d44c
CategorySuggestion                                                                                                                                    SeverityGenerated at (UTC)
Performance
Shared deadline can starve the dry-run drain after an expensive normal run

The normal run and the drain share the same deadline, but the normal run always
executes first. If it consumes the 20-second budget, the drain starts after its
deadline and returns partial without a continuation, so the prioritized preview can
make no progress on every invocation. Reserve budget for the drain or run the drain
independently with an appropriate deadline.

src/routes/api/cron/+server.ts [107-111]

Why it matters? 🤔
  • ⚠️ Slow moderation runs prevent preview-drain progress.
  • ⚠️ Background dry-run completion becomes unpredictable.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/routes/api/cron/+server.ts
**Line:** 107:111
**Comment:**
	*Performance: The normal run and the drain share the same deadline, but the normal run always executes first. If it consumes the 20-second budget, the drain starts after its deadline and returns partial without a continuation, so the prioritized preview can make no progress on every invocation. Reserve budget for the drain or run the drain independently with an appropriate deadline.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
Major2026-08-06 10:52

Latest suggestions up to commit 11398d8
CategorySuggestion                                                                                                                                    SeverityGenerated at (UTC)
Logic error
Failed window pages can create duplicate dry-run audit records on retry

Window-mode audit rows are inserted before the failures check. If one comment
decision fails, runChannel throws after auditing the successful decisions, so the
caller leaves the same page token in place; the next retry rescoring that page
inserts duplicate dry-run audit rows for those comments. Make the audit insertion
and failure handling atomic, or ensure successful decisions from a failed page
cannot be persisted before retry.

src/lib/server/pipeline.ts [626-637]

Why it matters? 🤔
  • ❌ Failed previews duplicate successful dry-run audit entries.
  • ⚠️ Channel logs show repeated results after retries.
  • ⚠️ Cron retries can inflate preview history and counts.

Fix in Cursor Fix in VSCode Claude

(Use Cmd/Ctrl + Click for best experience)

Prompt for AI Agent 🤖
This is a comment left during a code review.

**Path:** src/lib/server/pipeline.ts
**Line:** 626:637
**Comment:**
	*Logic Error: Window-mode audit rows are inserted before the `failures` check. If one comment decision fails, `runChannel` throws after auditing the successful decisions, so the caller leaves the same page token in place; the next retry rescoring that page inserts duplicate dry-run audit rows for those comments. Make the audit insertion and failure handling atomic, or ensure successful decisions from a failed page cannot be persisted before retry.

Validate the correctness of the flagged issue. If correct, How can I resolve this? If you propose a fix, implement it and please make it concise.
Once fix is implemented, also check other comments on the same PR, and ask user if the user wants to fix the rest of the comments as well. if said yes, then fetch all the comments validate the correctness and implement a minimal fix
Major2026-08-06 11:28

@qodo-code-review

qodo-code-review Bot commented Aug 6, 2026 •

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (0) 📘 Rule violations (1) 📜 Skill insights (0)

Grey Divider


Action required

1. Window runs can go live ✓ Resolved 🐞 Bug ≡ Correctness
Description
runChannel() applies window fetch + rescore behavior even when dryRun is false, so a caller
that passes window without forceDryRun can stage/enforce moderation and/or overwrite live
checkpoint state with window pagination state. This is especially dangerous because rescore
disables the stored-ID dedupe, making stageDecisions() attempt inserts for already-stored comment
IDs (PK violations) and/or re-enforcing actions on older comments.
Code

src/lib/server/pipeline.ts[R597-600]

+		const page = await fetchNewComments(channelId, accessToken, window ? window.boundary : channel.cursor, {
+			maxPages: window ? 1 : maxPages,
+			pageToken: window ? window.pageToken : channel.nextPageToken,
			deadline
Relevance

●●● Strong

Guarding window mode to require forceDryRun prevents accidental live side effects; aligns with docs
intent.

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
runChannel computes dryRun only from forceDryRun/env, but independently applies window to
fetching and sets rescore, which disables stored-ID dedupe. If dryRun is false, the function
stages decisions and persists results, meaning window pagination/checkpoint data can leak into the
live run path and can attempt duplicate inserts.

src/lib/server/pipeline.ts[576-650]
src/lib/server/pipeline.ts[279-323]
src/lib/server/pipeline.ts[375-384]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
`runChannel()` accepts the new `window` option but does not enforce the documented invariant that window mode is only meaningful with `forceDryRun`. If `window` is provided while `env.DRY_RUN === 'false'` and `forceDryRun !== true`, the function proceeds down the live path (staging DB rows, running YouTube enforcement, and persisting cursor/page-token state) using the window cursor and page token.

### Issue Context
Window mode intentionally skips stored-ID dedupe (`rescore`) and fetches with `window.boundary` + `window.pageToken`. That behavior is safe only when the run is guaranteed to be dry-run (no durable checkpoint writes, no moderation enforcement).

### Fix Focus Areas
- src/lib/server/pipeline.ts[576-650]
- src/lib/server/pipeline.ts[279-323]
- src/lib/server/pipeline.ts[375-384]

### Proposed fix
- Enforce one of these (prefer explicit guard):
 - **Guard**: `if (window && forceDryRun !== true) throw new Error('window mode requires forceDryRun');`
 - Or **force dryRun** when `window` is provided: `dryRun = true` (but still ensure no checkpoint persistence / enforcement paths can be reached).
- Make `rescore` depend on `window && dryRun` (not just `window !== undefined`).
- Add a regression test: calling `runChannel(..., { window: ..., forceDryRun: false })` should throw (or should behave as dry-run, depending on the chosen policy).

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Remediation recommended

2. Timeout leaves stale drain ✓ Resolved 🐞 Bug ☼ Reliability
Description
The dashboard dryRun action only clears/persists channels.dry_run_boundary/dry_run_page_token
when result.windowComplete is strictly true/false; when runChannel returns a
deadline-partial result, those fields are absent and any previously in-flight drain remains. Cron
keys off dryRunBoundary being non-null, so it will keep draining the old preview window even after
a user initiated a new preview that timed out.
Code

src/routes/(app)/dashboard/+page.server.ts[R226-229]

+			if (result.windowComplete === true) {
+				await db
+					.update(channels)
+					.set({ dryRunBoundary: null, dryRunPageToken: null })
Relevance

●● Moderate

Stale drain on deadline-partial is plausible but may be intended retry behavior; no close precedent.

PR-#111

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The dashboard action only updates drain state when windowComplete is exactly true/false. The
timeout path in runChannel returns a partial result without window continuation fields, so the
dashboard update is skipped and any old drain state remains, which cron will keep draining because
it checks for non-null dryRunBoundary.

src/routes/(app)/dashboard/+page.server.ts[178-251]
src/lib/server/pipeline.ts[651-654]
src/routes/api/cron/+server.ts[98-131]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

### Issue description
When the synchronous preview run times out (deadline exceeded), `runChannel` returns `{ partial: true }` without `windowComplete/windowNextPageToken`. The dashboard action currently does nothing to `dry_run_boundary/dry_run_page_token` in that case. If an older drain was already in flight, cron will continue draining it, which is stale relative to the user’s new request.

### Issue Context
Cron triggers the drain whenever `channels.dryRunBoundary` is non-null.

### Fix Focus Areas
- src/routes/(app)/dashboard/+page.server.ts[178-251]
- src/lib/server/pipeline.ts[651-654]
- src/routes/api/cron/+server.ts[98-131]

### Proposed fix
Pick and implement a clear policy for deadline-partial previews, e.g.:
- **Cancel/replace existing drains on click**: clear `dryRunBoundary/dryRunPageToken` immediately after claiming the lease (before calling `runChannel`) so any new preview attempt always supersedes old drain state, even if the attempt times out.
 - Or,
- **On partial result**: explicitly clear `dryRunBoundary/dryRunPageToken` (so cron stops draining stale work) and return `background: false`.

Add a test that seeds an existing drain state, forces `runChannel` to return `{ partial: true, dryRun: true }`, and asserts the resulting DB drain state matches the chosen policy.

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools



Informational

3. Spaces in drizzle JSON indent 📘 Rule violation ⚙ Maintainability
Description
drizzle/meta/0019_snapshot.json and the updated drizzle/meta/_journal.json use leading spaces
for indentation, violating the tabs-only indentation requirement. This can cause formatting
inconsistency and tooling lint/format failures if the repo enforces tabs.
Code

drizzle/meta/0019_snapshot.json[R2-4]

+  "version": "6",
+  "dialect": "sqlite",
+  "id": "3b38b750-beab-4aac-bd45-0765cecdb95e",
Relevance

● Weak

Tabs-in-Drizzle-meta formatting change was previously rejected as generated-file noise.

PR-#78

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
PR Compliance ID 2401137 requires tabs for indentation. The added/modified JSON lines in
drizzle/meta/0019_snapshot.json and drizzle/meta/_journal.json start with spaces (e.g., `
\"version\"...,     {`), demonstrating noncompliance.

Rule 2401137: Use tabs for indentation, never spaces
drizzle/meta/0019_snapshot.json[1-12]
drizzle/meta/_journal.json[134-143]

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
New/modified drizzle metadata JSON files are indented with leading spaces, but the repo compliance rule requires tabs for indentation.

## Issue Context
This PR adds `drizzle/meta/0019_snapshot.json` and updates `drizzle/meta/_journal.json`; both contain lines whose indentation begins with spaces.

## Fix Focus Areas
- drizzle/meta/0019_snapshot.json[1-30]
- drizzle/meta/_journal.json[134-145]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context used
✅ Compliance rules (platform): 90 rules

To customize comments, go to the Qodo configuration screen, or learn more in the docs.

Qodo Logo

Comment thread src/lib/server/pipeline.ts
Comment thread src/routes/(app)/dashboard/+page.server.ts
@codeant-ai

codeant-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot added size:XXL This PR changes 1000+ lines, ignoring generated files and removed size:XXL This PR changes 1000+ lines, ignoring generated files labels Aug 6, 2026
@coderabbitai

coderabbitai Bot commented Aug 6, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Added configurable dry-run history windows, defaulting to three months.
    • Large previews now continue processing in the background until complete.
    • Previously moderated comments can be rescored during dry runs.
    • Preview progress is retained across scheduled processing and cleared when finished.
  • Bug Fixes

    • Improved handling of incomplete previews, continuation tokens, failures, and skipped runs.
    • Active preview processing now takes priority in scheduled jobs.

Walkthrough

Changes

Dry-run preview continuation

Layer / File(s) Summary
Persisted dry-run window state
drizzle/0019_channels_dry_run_window.sql, drizzle/meta/*, src/lib/server/db/schema.ts, src/lib/server/db/schema.test.ts, src/lib/server/testdb.ts
Adds nullable channel fields for the dry-run boundary and continuation page token. Updates migration metadata and schema tests.
Bounded dry-run pipeline
src/lib/server/pipeline.ts, src/lib/server/pipeline.test.ts, AGENTS.md
Adds selectable window parameters, bounded single-page fetching, rescoring of stored comments, continuation results, and dry-run-only validation.
Dashboard window orchestration
src/routes/(app)/dashboard/+page.server.ts, src/routes/(app)/dashboard/actions.test.ts
Validates month presets, starts the first page, persists incomplete windows, clears completed windows, and reports background continuation.
Cron dry-run draining
src/routes/api/cron/+server.ts, src/routes/api/cron/cron.test.ts
Prioritizes pending drains, processes one page per cron run, updates continuation state, and preserves normal run results when draining fails.

Estimated code review effort: 3 (Moderate) | ~30 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Dashboard
  participant Pipeline
  participant Channels
  participant Cron
  Dashboard->>Pipeline: run dry-run window page
  Pipeline-->>Dashboard: decisions and continuation state
  Dashboard->>Channels: persist boundary and page token
  Cron->>Channels: select pending dry-run channel
  Cron->>Pipeline: drain one bounded page
  Pipeline-->>Cron: next token or completion
  Cron->>Channels: persist token or clear state
Loading

Possibly related PRs

  • Bonobo791/Moderaty#69: Both changes extend channel history-window handling and background drain behavior.
  • Bonobo791/Moderaty#71: Both changes add independent persisted pagination and boundary state for background drains.
  • Bonobo791/Moderaty#117: This change extends the existing dashboard dryRun workflow with configurable windows and continuation.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 53.85% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title clearly summarizes the main change: extending dry-run coverage across a selected window with backend background draining.
Description check ✅ Passed The description directly explains the dry-run window, rescoring, persistence, cron draining, validation, and verification for this changeset.
✨ Finishing Touches 💡 2
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat-dry-run-window

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.

@Bonobo791

Copy link
Copy Markdown
Collaborator Author

Triage summary — all review feedback addressed:

@qodo-code-review[bot] — both findings valid, fixed in 3774b9a (failing tests first):

  1. Window runs can go live — runChannel now refuses window without dry-run semantics loudly, before any fetch or write.
  2. Timeout leaves stale drain — a deadline-partial preview now replaces the in-flight drain with the NEW window (restart from top) instead of letting cron keep draining the abandoned one.

Codacy (10 new code clones): fixed in 11398d8 — extracted shared helpers in the three touched test files (runResult/seedDrainChannel/channelRow in cron.test.ts, runWindowPage in pipeline.test.ts, dryRunResult/seedStaleDrain/expectBoundaryMonthsAgo in actions.test.ts).

@CodeRabbit / Amazon Q: review noted, no blocking defects — thanks.

Snyk (code/snyk: "Code test limit reached"; security/snyk): the code check is a quota limit, not a finding, and security/snyk fails identically on dependency-free PRs — please check the Snyk dashboard org settings; this remains a repo-level config issue, not something this PR can fix.

Gate before push: 955 tests passing, npm run check clean (0 errors/warnings), npm run build green.

Merge note: this PR carries migration 0019 (channels.dry_run_boundary / dry_run_page_token). After merge, prod will 503 via the deploy-guard until npm run db:migrate runs with .env.prod sourced — expect 20 migrations applied.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@Bonobo791 Acknowledged. The reported fixes cover the window safety guard and stale-drain replacement. The test, check, and build results are noted.

Before production traffic reaches the updated service, run npm run db:migrate with .env.prod sourced. Migration 0019 must add channels.dry_run_boundary and channels.dry_run_page_token.


✏️ Learnings added
Learnt from: Bonobo791
URL: https://github.com/Bonobo791/Moderaty/pull/119

Timestamp: 2026-08-06T11:28:42.100Z
Learning: For the Moderaty backend, PRs that add database migrations require `npm run db:migrate` with `.env.prod` sourced before production deployment. The deploy guard returns HTTP 503 until migrations are applied. Migration 0019 adds nullable `channels.dry_run_boundary` and `channels.dry_run_page_token`.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

You are interacting with an AI system.

@qodo-code-review

Copy link
Copy Markdown

Triage summary — all review feedback addressed:

@qodo-code-review[bot] — both findings valid, fixed in 3774b9a (failing tests first):

  1. Window runs can go live — runChannel now refuses window without dry-run semantics loudly, before any fetch or write.
  2. Timeout leaves stale drain — a deadline-partial preview now replaces the in-flight drain with the NEW window (restart from top) instead of letting cron keep draining the abandoned one.

Codacy (10 new code clones): fixed in 11398d8 — extracted shared helpers in the three touched test files (runResult/seedDrainChannel/channelRow in cron.test.ts, runWindowPage in pipeline.test.ts, dryRunResult/seedStaleDrain/expectBoundaryMonthsAgo in actions.test.ts).

@CodeRabbit / Amazon Q: review noted, no blocking defects — thanks.

Snyk (code/snyk: "Code test limit reached"; security/snyk): the code check is a quota limit, not a finding, and security/snyk fails identically on dependency-free PRs — please check the Snyk dashboard org settings; this remains a repo-level config issue, not something this PR can fix.

Gate before push: 955 tests passing, npm run check clean (0 errors/warnings), npm run build green.

Merge note: this PR carries migration 0019 (channels.dry_run_boundary / dry_run_page_token). After merge, prod will 503 via the deploy-guard until npm run db:migrate runs with .env.prod sourced — expect 20 migrations applied.

The two actionable Qodo findings are addressed: finding 1 and finding 2 are marked implemented, and the described safeguards cover the reported cases.

One review item remains open: finding 3 is still pending and concerns spaces used for indentation in drizzle/meta/0019_snapshot.json (and _journal.json). It is informational, but the “all review feedback addressed” status is not yet accurate unless you reformat those JSON files or explicitly close that finding.

The reported test, check, and build results—and the Snyk quota/configuration issue—can be treated as merge-gate context. The migration/deploy-guard sequencing note is also clear: apply migration 0019 before normal production traffic.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Warning

CodeRabbit couldn't request changes on this pull request because it doesn't have sufficient GitHub permissions.

Please grant CodeRabbit Pull requests: Read and write permission and re-run the review.

👉 Steps to fix this

Actionable comments posted: 2

🤖 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 `@src/routes/api/cron/`+server.ts:
- Around line 112-122: Update the completed-window branch in the drain handling
to restrict the `dryRunBoundary`/`dryRunPageToken` reset to the channel’s
currently active dry-run boundary, adding that predicate alongside the existing
channel ID condition. Keep the incomplete-window token update unchanged so an
abandoned drain cannot clear replacement preview state.

In `@src/routes/api/cron/cron.test.ts`:
- Line 416: Update the test around the console.error spy to assert the exact
drain log message emitted by the cron handler, rather than only verifying that
console.error was called. Match the established exact-message assertion style
used by the nearby tests and the message produced in the cron server’s drain
path.
🪄 Autofix

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: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: b55dd0da-2d72-4dc1-947d-7e0d0042ab37

📥 Commits

Reviewing files that changed from the base of the PR and between 654ec45 and 11398d8.

📒 Files selected for processing (13)
  • AGENTS.md
  • drizzle/0019_channels_dry_run_window.sql
  • drizzle/meta/0019_snapshot.json
  • drizzle/meta/_journal.json
  • src/lib/server/db/schema.test.ts
  • src/lib/server/db/schema.ts
  • src/lib/server/pipeline.test.ts
  • src/lib/server/pipeline.ts
  • src/lib/server/testdb.ts
  • src/routes/(app)/dashboard/+page.server.ts
  • src/routes/(app)/dashboard/actions.test.ts
  • src/routes/api/cron/+server.ts
  • src/routes/api/cron/cron.test.ts

Comment thread src/routes/api/cron/+server.ts
Comment thread src/routes/api/cron/cron.test.ts Outdated
@codeant-ai

codeant-ai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@codeant-ai codeant-ai Bot removed the size:XXL This PR changes 1000+ lines, ignoring generated files label Aug 6, 2026
@codeant-ai codeant-ai Bot added the size:XXL This PR changes 1000+ lines, ignoring generated files label Aug 6, 2026
@sonarqubecloud

sonarqubecloud Bot commented Aug 6, 2026

Copy link
Copy Markdown

@Bonobo791

Copy link
Copy Markdown
Collaborator Author

Triage update — round 2 review feedback addressed:

@coderabbitai — both findings valid, fixed (failing tests first):

  1. Stale drain cleanup can wipe a replanted preview — real race: cron reads the channel row before the atomic claim, so a replanted window could be cleared/overwritten by the stale drain. Both drain writes are now predicated on the drained boundary (0ed0fb0), including the continuation-token update the suggestion left unchanged (same race class).
  2. Assert the exact drain log message — done (c80ba0f).

Codacy: now green ("up to standards") — the remaining clones were collapsed via test.each merges and drain-state assertion helpers (62102ee).

Snyk (security/snyk): still failing — unchanged recurring repo-level issue; this PR touches no dependencies. Please check the Snyk dashboard org settings.

Gate: 957 tests passing, npm run check clean, npm run build green. Codacy, Amazon Q, CodeAnt, SonarCloud, CodeQL all pass.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@Bonobo791 Confirmed. The boundary predicate now protects both stale-drain write paths from overwriting a replanted preview. The added exact-message assertion covers the drain failure log contract.

The reported test, check, build, and third-party review results are noted. The remaining Snyk failure is a repository-level configuration issue and is not caused by this PR.

🐇 ✅


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

You are interacting with an AI system.

@Bonobo791

Copy link
Copy Markdown
Collaborator Author

Consolidation note (maintainer decision): to cut Netlify production-deploy credit spend, this repo is moving to a single-dev-branch model with one full-stack dev. This PR's base has been retargeted from main to dev — the diff is unchanged (dev currently == main), so the existing approval stands. It will merge into dev and ship to production later in a batched dev → main merge.

@Bonobo791
Bonobo791 changed the base branch from main to dev August 6, 2026 12:09
@Bonobo791
Bonobo791 merged commit b0bf8d6 into dev Aug 6, 2026
18 of 20 checks passed
@Bonobo791
Bonobo791 deleted the feat-dry-run-window branch August 6, 2026 12:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

cla-signed size:XXL This PR changes 1000+ lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant