fix: skip github-deleted records in shadow diff (CM-1473) - #4778
Conversation
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
|
|
PR SummaryMedium Risk Overview New
Reviewed by Cursor Bugbot for commit 18a850c. Bugbot is set up for automated code reviews on this repo. Configure here. |
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Partial GraphQL errors can suppress valid mismatches, synthetic timeline records remain unresolved, and tests are uncommitted.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
Open (3)
What changed in this PR
Adds GitHub deletion confirmation to reduce false-positive shadow-diff mismatches.
Changes:
- Batch-checks missing records through GitHub GraphQL.
- Integrates deletion filtering with existing force-push confirmation.
| File | Description |
|---|---|
deletedRecords.ts |
Implements deletion confirmation and filtering. |
shadowDiffActivities.ts |
Applies filtering during shadow diff processing. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| export async function dropConfirmedDeletedRecords( | ||
| syncName: string, | ||
| mismatches: IShadowDiffMismatch[], | ||
| http: ConnectorHttp, | ||
| log: Logger, | ||
| ): Promise<DeletedRecordFilterResult> { |
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 3b493a7. Configure here.
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
Signed-off-by: Mouad BANI <mouad-mb@outlook.com>
There was a problem hiding this comment.
Copilot review overview
🟡 Changes recommended
Per-unit 60-second budgets can collectively exceed the activity’s five-minute timeout before results are persisted.
Get a fresh assessment by requesting another Copilot review.
Review effort: Balanced
Findings: 1
| if (hasDeletedRecordCandidates(unit.syncName, result.mismatches)) { | ||
| const { mismatches, confirmedDeletedCount, keptUnconfirmedCount } = | ||
| await dropConfirmedDeletedRecords(unit.syncName, result.mismatches, http, svc.log) |




Problem
The daily shadow-diff Temporal workflow compares Nango records against our shadow GitHub connector records and persists
missing_in_shadowmismatches. Nango never retracts deletes, so records that were deleted on GitHub after Nango captured them (issue/PR comments, pull requests + their timeline events, review comments, forks) surface as steady false-positivemissing_in_shadownoise — around 200-700/day on busy repos (e.g. openclaw/openclaw bot comments, NousResearch/hermes-agent deleted-account PRs and children), all confirmed via GraphQLnode(id:)returning null/NOT_FOUND.An analogous confirm-before-flag filter already exists for force-pushed commits (
forcePushedCommits.ts), but commitsourceIds are SHAs, not GraphQL node ids, so it can't cover these record kinds.Fix
Adds
services/apps/connectors_worker/src/deletedRecords.ts, mirroringforcePushedCommits.ts's structure:hasDeletedRecordCandidates/dropConfirmedDeletedRecordsapply to any sync other thanpull-request-commits, since every other record kind'ssourceIdis a GitHub GraphQL node id (issue/PR comments, pull requests, reviews, review comments, forks, discussions). Synthetic composite ids generated for PR/issue timeline events (gen-..., not real node ids) are excluded from lookup.nodes(ids: [...])GraphQL query, instead of per-record calls.dataand per-idnullentries (withNOT_FOUNDinerrors) is treated as a valid confirmation that the node is deleted — dropped from the mismatch list. A response with no top-leveldata(request error, timeout, forbidden, etc.) is treated as unconfirmed and the record is kept asmissing_in_shadow(fail open).runShadowDiffForChannelright after the existing force-push filter, reusing the same GitHub confirmation HTTP client/token pool. Logs how many records were confirmed deleted vs kept unconfirmed.Validation
services/apps/connectors_worker/src/deletedRecords.test.ts(written and run locally, not committed per repo convention): confirmed-deleted dropped, alive kept, request-error kept, no-data-with-NOT_FOUND-errors treated as confirmation, commit sync untouched, syntheticgen-ids skipped, budget-exhaustion keeps the remainder unconfirmed. All 10 pass, plus the existingshadowDiffActivities.test.tssuite (11 tests) still passes.pnpm lint:fix+pnpm formatrun;npx oxfmt --checkandnpx oxlint --deny-warningspass clean on the changed files.npx tsc -b services/apps/connectors_worker/tsconfig.json(forced full rebuild) passes with no errors. Rootpnpm tsc-checkstill fails on the 2 pre-existing unrelated errors (resolveCdpEmails.test.ts TS2550, backend/src/database/models/index.ts TS2339).🤖 Generated with Claude Code