Skip to content

GitHub App integration + banner system, PR reconcile-on-focus, and CRR sync-host wedge fix#887

Merged
arul28 merged 11 commits into
mainfrom
ade/lane-open-other-project-users-9ee5bfd6
Jul 23, 2026
Merged

GitHub App integration + banner system, PR reconcile-on-focus, and CRR sync-host wedge fix#887
arul28 merged 11 commits into
mainfrom
ade/lane-open-other-project-users-9ee5bfd6

Conversation

@arul28

@arul28 arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner

Why

Real-time PR status was silently failing for projects that weren't focused (e.g. a lane in another project whose PR merged overnight showed no badge). Root cause was a chain: the ADE GitHub App wasn't installed on the repo / the App user-token was expired, so no webhooks flowed; the only fallback (the snapshot poller) is desktop-side and runs solely for the focused project; and the settings UI conflated account-token failure with per-repo install, hiding the real cause.

What

GitHub App integration + honest settings

  • Shared two-axis derivation (githubIntegrationStatus.ts): account user-token (valid/expired/missing) vs per-repo App install (connected/not_installed/access_pending/no_repo).
  • Settings GitHub panel redesigned into two honest blocks; removed the always-green permission chips.

Consolidated banner system

  • New shared Banner primitive + central IntegrationBannerHost (severity-ordered, capped at 2 + collapse) with a durable, fingerprint-aware dismiss contract (survives restart, auto-resurfaces on regression).
  • Migrates the connection-health family (GitHub App, gh-CLI, missing-AI, mock-provider) and adds a per-repo "App not connected" banner.

PR reconcile-on-focus safety net

  • prService.reconcileOnFocus (in-memory 90s throttle, single-flight, bounded merged-heal, 30-min closed-sweep for merged-but-unmapped PRs) + syncLanePr (manual per-badge ⟳) + post-auth auto-heal.
  • Global cap-1 jittered limiter so opening many projects can't stampede; in production the desktop context is dormant, so the reconcile is routed to the daemon pr.reconcileOnFocus action (with fire-time live-context re-resolution).

Daemon reliability

  • Fix the cr-sqlite sync-host wedge: rebuildTableInTransaction drops any leftover __ade_crr_repair_* staging table before CREATE, plus a startup orphan-sweep.
  • Bound the root cause: automation_ingress_events now has a hard 10k per-project cap so the table can't bloat and abort the rebuild.

Testing

  • typecheck 0, lint 0 errors, affected suites green (prService/kvDb/automationService/registry/banner/githubIntegrationStatus/ChatGitToolbar).
  • Regression test pinning reconcileOnFocus/syncLanePr in the daemon action allowlist (the /quality Blocker).
  • Docs updated (pull-requests, onboarding-and-settings, ARCHITECTURE, crdt-model). No iOS/CLI/TUI parity changes required.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • PRs now automatically catch up when projects open or return to focus, with queued background scheduling.
    • Added manual lane PR sync and an immediate “reconcile now” action (including API access).
    • PR badge/menu now shows “syncing…” while reconciliation runs.
    • Introduced consolidated integration banners with severity, actions, expand/collapse, and durable dismissal.
  • Bug Fixes

    • Improved automation ingress retention using active + total caps, preventing oversized event growth.
    • Increased database repair/staging-table resilience by cleaning up orphaned/stale artifacts.
    • Refined GitHub integration status/banner behavior after auth/connect changes.

Greptile Summary

This PR adds GitHub App integration status, centralized integration banners, PR catch-up reconciliation, and CRR repair hardening. The main changes are:

  • Two-axis GitHub account-token and repo App-install status derivation.
  • Shared banner rendering with durable fingerprint-aware dismissals.
  • Focus/open PR reconciliation plus manual per-lane PR sync.
  • CRR staging-table cleanup and automation ingress row caps.

Confidence Score: 4/5

Mostly safe to merge after fixing one contained production-path issue.

The main reconcile, banner, and DB repair changes are scoped and covered by targeted tests. One payload mismatch breaks the new runtime-backed manual lane sync path, while the broader focus reconcile path remains intact.

apps/desktop/src/preload/preload.ts

T-Rex T-Rex Logs

What T-Rex did

  • Reproduced the runtime sync lane behavior: the preload payload with arg "lane-1" is rejected with prs.syncLanePr requires laneId, and the syncLanePr mock is not invoked, while the daemon payload { laneId: "lane-1" } is accepted and calls syncLanePr once with laneId lane-1.
  • Collected validation evidence from the runtime tests: the proof log documents the full verbose test run, the command and working directory, and an exit code of 0, with relevant tests including prService.reconcileOnFocus and ADE_ACTION_ALLOWLIST shape confirming runtime-backed safety checks.

View all artifacts

T-Rex Ran code and verified through T-Rex

Important Files Changed

Filename Overview
apps/desktop/src/preload/preload.ts Adds PR sync/reconcile bridge methods; runtime-backed syncLanePr sends the lane id under the wrong payload key.
apps/desktop/src/main/main.ts Adds jittered global scheduling for focus/open PR reconciliation with live-context re-resolution.
apps/desktop/src/main/services/prs/prService.ts Adds throttled reconcile-on-focus and manual lane sync flows, plus branch-backfill candidate selection safeguards.
apps/desktop/src/main/services/state/dbMaintenanceApi.ts Centralizes automation ingress active and hard-cap pruning SQL.
apps/desktop/src/main/services/state/kvDb.ts Adds staging-table drop guards and startup orphan sweeping for repair rebuilds.
apps/desktop/src/renderer/components/app/IntegrationBannerHost.tsx Introduces centralized integration banner derivation, refresh handling, severity ordering, and durable dismissal integration.
apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx Adds PR reconcile spinner state and manual per-badge sync affordance.
apps/desktop/src/renderer/components/github/GitHubAppInstallPanel.tsx Redesigns GitHub settings around separate account-token and repo App-install status axes.

Sequence Diagram

sequenceDiagram
participant UI as Renderer PR badge / focus
participant Preload as Electron preload
participant Main as Desktop main scheduler
participant Daemon as Runtime daemon action
participant PR as prService
participant GH as GitHub API

UI->>Main: project open/focus
Main->>Main: scheduleReconcile (cap 1 + jitter)
Main->>Daemon: pr.reconcileOnFocus (runtime-backed)
Daemon->>PR: reconcileOnFocus()
PR->>GH: open PR snapshot
PR->>PR: refresh stale mapped PR rows
PR->>GH: "periodic state=all closed sweep"
PR-->>UI: pr-reconcile / prs-updated events
UI->>Preload: syncLanePr(laneId)
Preload->>Daemon: prs.syncLanePr payload
Daemon->>PR: syncLanePr(laneId)
PR->>GH: "refresh mapped PR or state=all backfill"
Loading

Fix All in Claude Code

Prompt To Fix All With AI
Fix the following 1 code review issue. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 1
apps/desktop/src/preload/preload.ts:7848-7851
**Runtime sync drops lane**
The runtime-backed path sends `{ arg: laneId }`, but the daemon handler for `prs.syncLanePr` parses `payload.laneId` via `parseLaneIdArgs`, so the manual ⟳ action is rejected before reaching `prService.syncLanePr`. In production this makes the new per-badge sync silently fall back to `null` instead of healing the lane PR.

Reviews (5): Last reviewed commit: "ship: iter 8 — Codex P2s: honor account-..." | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

arul28 and others added 3 commits July 23, 2026 15:19
Real-time PR status was silently failing for unfocused projects. Root causes and
fixes:

Settings + banners
- Separate the two independent GitHub App axes (account user-token vs per-repo
  install) via a shared renderer helper (githubIntegrationStatus.ts). Settings
  now shows two honest blocks and drops the always-green permission chips.
- New shared Banner primitive + central IntegrationBannerHost (severity-ordered,
  capped at 2 + collapse) with a durable, fingerprint-based dismiss contract that
  survives restart and auto-resurfaces on regression. Migrates the connection-
  health family (GitHub, missing-AI, mock-provider) and adds a per-repo "GitHub
  App not connected" banner distinct from the gh-CLI banner.

Reconcile-on-focus safety net (the always-on brain has no PR poller)
- prService.reconcileOnFocus: in-memory throttle (90s), single-flight, bounded
  merged-heal, 30-min closed-sweep to heal merged-but-unmapped PRs. Global cap-1
  jittered limiter in main.ts so opening many projects can't stampede.
- prService.syncLanePr + a manual per-badge ⟳ on the PR chip, with a debounced
  "syncing…" indicator driven by a new pr-reconcile event. Post-auth auto-heal
  kicks reconcileNow so badges light up after authorizing.

Daemon reliability
- Fix the cr-sqlite sync-host wedge: rebuildTableInTransaction now drops any
  leftover __ade_crr_repair_* staging table before CREATE, plus a startup
  orphan-sweep. Bound the root cause: dispatched/failed automation_ingress_events
  rows now respect a hard 10k per-project cap so the table can't bloat and abort
  the rebuild.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…cleanups

Correctness (load-bearing):
- Expose reconcileOnFocus + syncLanePr through the daemon action allowlist
  (registry.ts). Without this both new PR actions were rejected in the
  runtime-backed production build (manual ⟳ a silent no-op, post-auth
  reconcileNow an unhandled rejection).
- Route reconcile-on-focus to the daemon in production: scheduleReconcile now
  takes a runner that re-resolves the live context at fire time and calls the
  daemon pr.reconcileOnFocus action when the desktop context is dormant
  (prService null). Fixes both the dead-in-production hook and the stale-closure
  captured-prService concern.
- Guard the fire-and-forget reconcileNow with .catch.

Cleanups:
- Delete dead statusView (~90 lines) + isGitHubAppRepoAccessPending alias; move
  its test to githubIntegrationStatus.test.ts.
- De-duplicate ingress-prune SQL into pruneIngressEventRowsForProject
  (dbMaintenanceApi.ts), called from automationService + kvDb maintenance.
- Move describeGithubCliBanner into the shared githubIntegrationStatus helper.
- Drop dead ?? "global" dismiss-key fallback.
- Fix stuck ⟳ spinner: split the pr-reconcile subscription into its own effect
  so a linkedPr change can't strand the idle-hide timer.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- registry.test.ts: regression test pinning reconcileOnFocus + syncLanePr in
  ADE_ACTION_ALLOWLIST.pr (the daemon rejects un-allowlisted actions; without
  this the reconcile safety net + manual ⟳ are dead in the production
  runtime-backed build).
- docs: pull-requests (reconcile-on-focus + manual sync freshness layers),
  onboarding-and-settings (two-axis GitHub App panel + githubIntegrationStatus),
  ARCHITECTURE (Banner primitive/host + CRR rebuild self-heal + ingress cap),
  sync-and-multi-device/crdt-model (orphan staging sweep + hard cap).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@vercel

vercel Bot commented Jul 23, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored Preview Jul 23, 2026 10:49pm

@arul28 arul28 changed the title realtime-pr-badge-sync -> Primary GitHub App integration + banner system, PR reconcile-on-focus, and CRR sync-host wedge fix Jul 23, 2026
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change adds throttled PR reconciliation and lane synchronization, centralizes ingress retention and SQLite repair cleanup, and replaces inline integration banners with shared GitHub status derivation, durable dismissal, and unified rendering.

Changes

PR reconciliation

Layer / File(s) Summary
Reconcile service and lifecycle events
apps/desktop/src/main/services/prs/*, apps/desktop/src/shared/types/prs.ts
Adds throttled, single-flight reconciliation, lane synchronization, closed-sweep cadence, authoritative lane backfill selection, and pr-reconcile lifecycle events with tests.
Startup and focus scheduling
apps/desktop/src/main/main.ts
Enables reconciliation by default, limits concurrent runs, resolves live project contexts, and schedules warm-focus and cold-open reconciliation.
Runtime actions and manual synchronization
apps/desktop/src/main/services/adeActions/*, apps/desktop/src/main/services/ipc/registerIpc.ts, apps/desktop/src/preload/*, apps/desktop/src/renderer/webclient/adapter/*, apps/ade-cli/src/services/sync/*
Exposes forced reconciliation and lane synchronization through runtime actions, remote commands, IPC, preload APIs, and the webclient adapter.
Toolbar synchronization controls
apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx
Adds manual PR syncing and reconciliation activity indicators.

Retention and database repair safety

Layer / File(s) Summary
Shared ingress retention
apps/desktop/src/main/services/state/dbMaintenanceApi.ts, apps/desktop/src/main/services/automations/*, apps/desktop/src/main/services/state/kvDb.ts
Centralizes two-stage ingress pruning with active and total row caps, including regression coverage.
Repair staging cleanup
apps/desktop/src/main/services/state/kvDb.ts, apps/desktop/src/main/services/state/kvDb.test.ts
Removes colliding repair staging tables and sweeps orphaned staging tables while preserving ambiguous bases.

Integration banner consolidation

Layer / File(s) Summary
GitHub status and banner dismissal contracts
apps/desktop/src/renderer/lib/githubIntegrationStatus.ts, apps/desktop/src/renderer/lib/bannerDismiss.ts
Adds shared GitHub state derivation and durable fingerprint-aware banner dismissal utilities with tests.
Unified banner rendering
apps/desktop/src/renderer/components/shared/Banner.tsx, apps/desktop/src/renderer/components/app/IntegrationBannerHost.tsx
Adds severity-ranked banner rendering, project-scoped dismissal, status loading, overflow expansion, and component tests.
AppShell and GitHub panel integration
apps/desktop/src/renderer/components/app/AppShell.tsx, apps/desktop/src/renderer/components/github/GitHubAppInstallPanel.tsx
Centralizes AppShell banners, updates dismissal-aware polling, refactors GitHub integration presentation, and triggers reconciliation after authorization.

Estimated code review effort: 4 (Complex) | ~60 minutes

Possibly related PRs

  • arul28/ADE#240: Overlaps with lane PR backfill selection and authoritative PR-row handling.
  • arul28/ADE#289: Relates to the getGithubSnapshot options used by PR reconciliation.
  • arul28/ADE#670: Also modifies PR refresh behavior in ChatGitToolbar.tsx.

Suggested labels: desktop, docs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.53% 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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately captures the main themes of the changes: GitHub App/banner work, PR reconcile-on-focus, and the CRR repair-staging fix.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ade/lane-open-other-project-users-9ee5bfd6

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.

Comment thread apps/desktop/src/renderer/components/app/AppShell.tsx

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 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 `@apps/desktop/src/main/services/prs/prService.ts`:
- Around line 9814-9822: Add force: true to both non-forced getGithubSnapshot
calls in apps/desktop/src/main/services/prs/prService.ts at lines 9814-9822 and
9856-9859: update the closed-sweep call in reconcileOnFocus and the unmapped-PR
fallback in syncLanePr. No other sites require changes. Ensure both paths
perform an awaited live GitHub fetch rather than returning projected local data.
- Around line 9759-9837: Update the Phase 3 closed-sweep call in
reconcileOnFocus to force a fresh GitHub snapshot when includeExternalClosed is
enabled, rather than allowing the normal snapshot TTL cache to satisfy it.
Preserve the existing cadence gate, timestamp update, and closedSwept result
behavior.

In `@apps/desktop/src/main/services/state/kvDb.ts`:
- Around line 1244-1263: Update the orphan enumeration in
sweepOrphanedRepairStagingTables to exclude __crsql_clock and __crsql_pks
sibling tables, so only actual repair staging parents are processed by the
ambiguousTables check and dropRepairStagingTable. Preserve shadow tables
belonging to ambiguous staging bases and ensure dropped counts do not include
those siblings; extend the existing sweepOrphanedRepairStagingTables test with
an ambiguous base and shadow sibling.

In `@apps/desktop/src/renderer/components/app/IntegrationBannerHost.tsx`:
- Around line 153-174: Update the repo action construction in the block.repo
branch so access_pending exposes only a Recheck action that invokes
loadAppStatus(true), matching GitHubAppInstallPanel’s repoActions behavior. Keep
the existing install/manage actions for other repository states.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5dcfbb1f-974f-4e58-9816-265d094181b9

📥 Commits

Reviewing files that changed from the base of the PR and between 102fbe0 and fd7336a.

⛔ Files ignored due to path filters (4)
  • docs/ARCHITECTURE.md is excluded by !docs/**
  • docs/features/onboarding-and-settings/README.md is excluded by !docs/**
  • docs/features/pull-requests/README.md is excluded by !docs/**
  • docs/features/sync-and-multi-device/crdt-model.md is excluded by !docs/**
📒 Files selected for processing (27)
  • apps/desktop/src/main/main.ts
  • apps/desktop/src/main/services/adeActions/registry.test.ts
  • apps/desktop/src/main/services/adeActions/registry.ts
  • apps/desktop/src/main/services/automations/automationService.test.ts
  • apps/desktop/src/main/services/automations/automationService.ts
  • apps/desktop/src/main/services/ipc/registerIpc.ts
  • apps/desktop/src/main/services/prs/prService.test.ts
  • apps/desktop/src/main/services/prs/prService.ts
  • apps/desktop/src/main/services/state/dbMaintenanceApi.ts
  • apps/desktop/src/main/services/state/kvDb.test.ts
  • apps/desktop/src/main/services/state/kvDb.ts
  • apps/desktop/src/preload/global.d.ts
  • apps/desktop/src/preload/preload.ts
  • apps/desktop/src/renderer/components/app/AppShell.aiStatus.test.tsx
  • apps/desktop/src/renderer/components/app/AppShell.tsx
  • apps/desktop/src/renderer/components/app/IntegrationBannerHost.test.tsx
  • apps/desktop/src/renderer/components/app/IntegrationBannerHost.tsx
  • apps/desktop/src/renderer/components/chat/ChatGitToolbar.tsx
  • apps/desktop/src/renderer/components/github/GitHubAppInstallPanel.test.ts
  • apps/desktop/src/renderer/components/github/GitHubAppInstallPanel.tsx
  • apps/desktop/src/renderer/components/shared/Banner.tsx
  • apps/desktop/src/renderer/lib/bannerDismiss.test.ts
  • apps/desktop/src/renderer/lib/bannerDismiss.ts
  • apps/desktop/src/renderer/lib/githubIntegrationStatus.test.ts
  • apps/desktop/src/renderer/lib/githubIntegrationStatus.ts
  • apps/desktop/src/shared/ipc.ts
  • apps/desktop/src/shared/types/prs.ts
💤 Files with no reviewable changes (1)
  • apps/desktop/src/renderer/components/github/GitHubAppInstallPanel.test.ts

Comment thread apps/desktop/src/main/services/prs/prService.ts
Comment thread apps/desktop/src/main/services/prs/prService.ts
Comment thread apps/desktop/src/main/services/state/kvDb.ts
Comment thread apps/desktop/src/renderer/components/app/IntegrationBannerHost.tsx
CI:
- secret-scan: gitleaks generic-api-key false positive on the bannerDismiss
  localStorage key name; added a scoped .gitleaksignore fingerprint.

Review (CodeRabbit Major/Minor, verified):
- reconcileOnFocus closed-sweep + syncLanePr unmapped fallback now pass
  force:true to getGithubSnapshot({includeExternalClosed}); without it the
  projected/cached snapshot is returned and the merged/closed backfill (the
  #402 heal) never runs synchronously.
- kvDb orphan-sweep excludes __crsql_clock/__crsql_pks siblings from
  enumeration so an ambiguous base's shadow tables aren't over-dropped; added
  a regression test.
- IntegrationBannerHost: access_pending repo banner shows Recheck (re-fetch
  status) instead of Install/Manage, matching the Settings panel.

Skipped (verified false positive):
- Greptile P1 "missing-provider banner suppressed": aiStatus===null with
  aiStatusLoaded===true is the AI-status FETCH-ERROR state (setAiStatus(null)
  in .catch); the aiStatus!==null guard intentionally suppresses the banner
  then. Applying the suggestion would show a spurious "No AI provider" banner
  on any transient status-fetch error.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28

arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fb405dac1b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +73 to +75
if (status.repo === null) return "no_repo";
if (status.installed) return "connected";
if (status.state === "not_installed") return "not_installed";

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Require relay and webhook health before reporting connected

When an app is installed but the relay is unconfigured, or GitHub reports webhookState === "deleted", this branch still derives connected; isGithubRealtimeHealthy then marks the integration healthy, Settings says “Real-time PR updates are on,” and the banner exposes no blocker. The previous presentation explicitly warned for both states, so installation alone must not imply real-time delivery.

AGENTS.md reference: AGENTS.md:L59-L60

Useful? React with 👍 / 👎.

Comment on lines +90 to +93
const entry = readMap()[trimmed];
if (!entry) return false;
if (entry.fingerprint !== fingerprint) return false;
return nowMs - entry.dismissedAt < graceMs;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear dismissals after an integration becomes healthy

If a user dismisses an issue, fixes it, and the same issue returns within 14 days—for example, they dismiss “No AI provider,” configure one, then remove it—the stored entry still has the same fingerprint, so this check suppresses the newly regressed banner. Nothing clears entries while a model is absent from the active issue list, meaning the promised resurface-after-recovery behavior does not occur for any issue that returns to the same state.

AGENTS.md reference: AGENTS.md:L59-L60

Useful? React with 👍 / 👎.

Comment on lines +115 to +120
const disposers: Array<() => void> = [];
const refresh = () => {
void loadAppStatus(true);
};
const offPrs = window.ade?.prs?.onEvent?.(refresh);
if (offPrs) disposers.push(offPrs);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Avoid force-refreshing app status for every PR event

For every PR event this callback calls loadAppStatus(true), bypassing the preload cache and issuing a relay /status?refresh=1 request. In particular, each new focus reconcile emits both pr-reconcile: running and pr-reconcile: idle, so a single focus produces two forced status checks in addition to the initial load; the sequence guard only discards stale UI results and does not cancel those requests. Refreshing only on the completion event or coalescing these callbacks would avoid the repeated network work.

Useful? React with 👍 / 👎.

…ing)

- githubIntegrationStatus: "connected" now requires relayConfigured AND
  webhookState !== "deleted". New "webhook_off" state (installed but real-time
  delivery not wired) surfaces a banner + Settings warning instead of a
  false-healthy "real-time on". Rendered in the panel + banner host.
- bannerDismiss: add clearBannerDismissal(key); the host clears a dismissal once
  its condition is healthy so a later regression to the same state resurfaces a
  fresh banner (the promised resurface-on-recovery, previously blocked by the
  matching-fingerprint suppression within the 14-day grace).
- IntegrationBannerHost: stop force-refetching App status on every PR event —
  ignore pr-reconcile pings entirely and debounce the rest into one non-forced,
  cache-served read; onStatusChanged remains the immediate forced trigger.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28

arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 38cf503fd9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +108 to +110
useEffect(() => {
setAppStatusLoaded(false);
void loadAppStatus(false);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Bind loaded App status to its project

When switching directly between projects, this effect resets appStatusLoaded only after React has already rendered with the new currentProjectRoot and the previous project's appInstall/appAuth. That paint can show the old repository's warning and actionable Install/Manage links in the new project, contrary to the stated project-switch isolation. Track the root associated with the loaded status and render it only when it matches the current root.

Useful? React with 👍 / 👎.

Comment on lines +155 to +157
const account = deriveGithubAccountAuthState(appAuth);
const repo = deriveGithubRepoConnectionState(appInstall);
if (account === "valid") clearDismissal(`github-app-account:${currentProjectRoot}`);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Clear account dismissals across projects after recovery

GitHub App account authorization is machine/account-wide, but both its dismissal and recovery clearing are scoped to currentProjectRoot. If the missing/expired warning is dismissed in project A, authorization becomes healthy while project B is active, and the same account condition later regresses, A's stale matching dismissal still suppresses the warning for up to 14 days. Use a global account dismissal key or clear all account-scoped entries when authorization becomes valid.

Useful? React with 👍 / 👎.

…ismiss key

- IntegrationBannerHost: bind a completed App-status read to the project it was
  loaded for (loadedRoot); gate the App block + clear-on-recovery on
  loadedRoot === currentProjectRoot so a direct project switch can't paint the
  previous repo's warning/Install-Manage for a frame before the reload lands.
- The GitHub App account (user-token) auth is machine/account-wide, so its
  dismiss + clear-on-recovery key is now global ("github-app-account") instead
  of per-project — a per-project key left a dismiss in project A suppressing the
  same account warning after a cross-project regression.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28

arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 408819c11d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +72 to +74
where project_id = ?
order by received_at desc, rowid desc
limit -1 offset ${INGRESS_EVENT_HARD_MAX_ROWS_PER_PROJECT}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve active ingress rows under the hard cap

When a project exceeds 10,000 ingress rows and newer terminal rows coexist with older received rows still being matched or dispatched, this unfiltered oldest-first delete can remove those active rows despite the preceding query allowing up to 2,000 of them. Subsequent updateIngressEvent calls then update nothing, the audit record disappears, and a redelivery is no longer deduplicated, potentially running the automation twice. Apply the hard cap preferentially to terminal statuses or otherwise reserve the active-row allowance.

Useful? React with 👍 / 👎.

Comment on lines +1254 to +1256
and (name like '__ade_crr_repair_%' or name like '__ade_fk_repair_%')
and name not like '%__crsql_clock'
and name not like '%__crsql_pks'`,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Match repair staging prefixes literally

SQLite treats every _ in a LIKE pattern as a single-character wildcard, so this query is broader than the intended __ade_crr_repair_ and __ade_fk_repair_ prefixes. For example, a legitimate table named xxadeXcrrYrepairZfoo matches, fails the subsequent literal startsWith("__ade_crr_repair_") check, and is passed to dropRepairStagingTable, which deletes it during every database open. Use a literal prefix comparison or escape the wildcard characters before dropping anything.

Useful? React with 👍 / 👎.

Comment on lines +309 to +310
try {
await window.ade.prs.syncLanePr(laneId);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Expose PR sync in the web adapter

In the standalone web client, window.ade.prs comes from createPrsNamespace, whose PR namespace still jumps from getForLane to listAll without defining syncLanePr. Clicking this newly rendered sync button therefore calls undefined; the broad catch hides the failure and only rereads the cached mobile snapshot, so merged or unmapped PRs are never synchronized on that supported surface. Add the new method to the web-client adapter, along with its command routing.

AGENTS.md reference: AGENTS.md:L32-L35

Useful? React with 👍 / 👎.

…eep prefix, web PR sync

- dbMaintenanceApi: the 10k hard cap now orders active (non-terminal) rows first
  so it only ever trims the oldest TERMINAL rows. An old 'received' row that's
  still being matched/dispatched is no longer sacrificed (which would lose its
  audit row and break redelivery dedup → double-run). + regression test.
- kvDb orphan sweep: require a LITERAL prefix before dropping. SQLite treats `_`
  in LIKE as a wildcard, so the enumeration could match a legit table; a literal
  startsWith guard ensures we never drop a non-repair table.
- Web PR sync parity: createPrsNamespace gains syncLanePr + reconcileNow, AND the
  host command registry (syncRemoteCommandService) registers prs.syncLanePr /
  prs.reconcileOnFocus (+ SyncRemoteCommandAction union) so the ⟳ button and
  post-auth reconcile actually reach the heal path on web/mobile, not a no-op.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28

arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d03c16be55

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// projected (local github_pr_projections) snapshot when projections
// exist and only dispatches the live fetch in the background, so the
// merged/closed backfill never runs synchronously. This is the #402 heal.
await getGithubSnapshot({ force: true, includeExternalClosed: true });

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Avoid backfilling every historical PR onto one lane

When a lane reuses a branch that has multiple historical PRs, this state: "all" snapshot sends every matching PR through backfillLanePrRowsFromGithubPulls. That function processes the newest-first response sequentially, while upsertRow(..., { allowRepoPrAdoption: true }) identifies the existing row by lane and branch, so each older PR overwrites the same row and the oldest fetched PR can replace the lane's current PR number, URL, and state. Because this sweep now runs automatically on focus, merely opening such a project can make an active PR appear merged or closed; select one authoritative PR per lane branch before invoking the backfill.

Useful? React with 👍 / 👎.

backfillLanePrRowsFromGithubPulls now selects ONE authoritative PR per lane
before upserting (prefer open/draft, else newest PR number), instead of
upserting every matching PR. A reused branch carries multiple historical PRs in
a state:"all" snapshot; upserting all of them adopts the same lane row
repeatedly (upsertRow identifies by lane+branch), so the last-processed —
newest-first response ⇒ oldest — PR would win and flip an active PR to a stale
merged/closed one. Since the closed sweep now runs on focus reconcile, that
could mis-mark a PR just by opening a project. Single-PR-per-branch behavior is
unchanged (verified by the existing closed-history snapshot suite).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28

arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/desktop/src/main/services/prs/prService.ts (1)

9830-9833: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Report successful heals, not attempted heals.

refreshPrIds tolerates individual failures and returns only successful refreshes, but healed is set to the attempted count. Use the returned array length so callers do not receive an inflated reconcile result.

Proposed fix
-        if (staleFirst.length > 0) {
-          await refreshPrIds(staleFirst.map((pr) => pr.id));
-          healed = staleFirst.length;
+        if (staleFirst.length > 0) {
+          const refreshed = await refreshPrIds(staleFirst.map((pr) => pr.id));
+          healed = refreshed.length;
🤖 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 `@apps/desktop/src/main/services/prs/prService.ts` around lines 9830 - 9833,
Update the stale-first healing branch around refreshPrIds to assign healed from
the length of the array returned by refreshPrIds, rather than staleFirst.length.
Preserve the existing ID mapping and await behavior so the reconcile result
reports only successful refreshes.
🤖 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.

Outside diff comments:
In `@apps/desktop/src/main/services/prs/prService.ts`:
- Around line 9830-9833: Update the stale-first healing branch around
refreshPrIds to assign healed from the length of the array returned by
refreshPrIds, rather than staleFirst.length. Preserve the existing ID mapping
and await behavior so the reconcile result reports only successful refreshes.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 42515ba6-9934-4680-a790-24750a9cfaf0

📥 Commits

Reviewing files that changed from the base of the PR and between 38cf503 and 642b682.

📒 Files selected for processing (9)
  • apps/ade-cli/src/services/sync/syncRemoteCommandService.ts
  • apps/desktop/src/main/services/automations/automationService.test.ts
  • apps/desktop/src/main/services/prs/prService.ts
  • apps/desktop/src/main/services/state/dbMaintenanceApi.ts
  • apps/desktop/src/main/services/state/kvDb.ts
  • apps/desktop/src/renderer/components/app/IntegrationBannerHost.tsx
  • apps/desktop/src/renderer/webclient/adapter/__tests__/adapter.test.ts
  • apps/desktop/src/renderer/webclient/adapter/prs.ts
  • apps/desktop/src/shared/types/sync.ts
🚧 Files skipped from review as they are similar to previous changes (3)
  • apps/desktop/src/main/services/state/dbMaintenanceApi.ts
  • apps/desktop/src/renderer/components/app/IntegrationBannerHost.tsx
  • apps/desktop/src/main/services/state/kvDb.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 642b6821d2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// Throttled per-project + globally capped, so this never blocks focus.
// The runner routes in-process vs. daemon and re-resolves the live
// context at fire time (production contexts are dormant here).
scheduleReconcile(buildReconcileRunner(normalizedRoot));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Schedule reconcile from the actual window-focus handler

When a production runtime-backed project remains open while its window loses focus, returning to that same window does not call bindWindowToProject, so this scheduling path never runs. The actual win.on("focus") handler at lines 6188–6202 only updates the foreground project; because these contexts have no local PR poller, a PR merged while ADE was unfocused remains stale despite the reconcile-on-focus feature until the user switches projects or manually syncs. Schedule the throttled runner from that focus handler as well.

Useful? React with 👍 / 👎.

Also schedule the throttled reconcile from win.on("focus") for the focused
project root. Returning to an already-open project (window regains OS focus)
doesn't re-run bindWindowToProject, so without this the reconcile-on-focus
safety net never fired for the most common "come back to ADE after being away"
case — a PR merged while unfocused stayed stale until a project switch or manual
sync. The per-project 90s throttle + single-flight + app-wide cap-1 limiter
collapse refocus storms into at most one reconcile.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28

arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b7832314ab

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +16 to +22
* Hard ceiling on TOTAL ingress rows per project regardless of status. Well
* above the 2,000 active-row cap so normal dedup/audit history survives, but
* bounds dispatched/failed rows so an always-on brain dispatching high webhook
* volume can't bloat automation_ingress_events within the 7-day window and
* wedge the cr-sqlite table rebuild.
*/
export const INGRESS_EVENT_HARD_MAX_ROWS_PER_PROJECT = 10_000;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep the storage ledger aligned with the hard row cap

When a project accumulates terminal ingress events, this new policy permits up to 10,000 total rows, but apps/desktop/src/main/services/storage/storageLedger.ts still declares maxRows: INGRESS_EVENT_MAX_ROWS_PER_PROJECT (2,000). That makes the ledger's persisted-data policy inaccurate and contradicts the nearby claim that the ledger and enforcement constants cannot drift; update the ledger to represent the 10,000-row total ceiling, or model both the active and total caps explicitly.

Useful? React with 👍 / 👎.

storageLedger's automation_ingress_events policy declared maxRows = 2,000 (the
active-row cap), but the table's real total ceiling is now the 10,000 hard cap.
Point maxRows at INGRESS_EVENT_HARD_MAX_ROWS_PER_PROJECT so the persisted-data
size policy is accurate and the ledger/enforcement constants don't drift.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28

arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1cb1635336

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

account: GithubAccountAuthState,
repo: GithubRepoConnectionState,
): GithubRealtimeBlock {
if (account === "missing" || account === "expired") return { kind: "account", account };

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Honor the account-token relay path

For an ADE-account-signed-in user without github.appUserToken.v1, this always reports an account blocker even when the repository status is connected. githubService.getAppInstallationStatus accepts getAccountAccessToken, and automationIngressService uses that same account-token fallback for relay polling/subscription, so real-time updates can already work without the device-flow token. The banner and Settings therefore persistently claim that a healthy integration is unauthorized; expose the effective relay credential in the shared status or derive health from the actual service result.

AGENTS.md reference: AGENTS.md:L33-L34

Useful? React with 👍 / 👎.

Comment on lines +94 to +100
try {
const auth = (await api.getAppUserAuthStatus?.()) ?? null;
if (!isCurrent()) return;
setAppAuth(auth);
} catch {
if (!isCurrent()) return;
setAppAuth(null);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Suppress App warnings when web status is unsupported

When the renderer uses createAdeWebAdapter, these calls do not return runtime GitHub App status: adapter/misc.ts returns the legacy { authenticated, user } object for getAppUserAuthStatus and only { installed: false, state: "unknown" } for installation status. This code nevertheless marks the read as loaded, interprets missing tokenStored as an unauthorized account, and shows every bound hosted-web project a false GitHub App warning. Route these methods through the sync host with the full shared DTOs, or explicitly treat the adapter result as unsupported and omit the banner.

AGENTS.md reference: AGENTS.md:L34-L34

Useful? React with 👍 / 👎.

Comment on lines +1311 to +1312
{!hideSidebar && !showWelcome && project?.rootPath ? (
<IntegrationBannerHost

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep GitHub integration banners off onboarding

When a project is on /onboarding, this now mounts the integration host even though the removed GitHub banner explicitly excluded that route. The onboarding GitHub card already renders GitHubAppInstallPanel (components/onboarding/GitHubCard.tsx:89), so users missing App authorization or installation see duplicate GitHub setup warnings and CTAs above the dedicated setup card. Retain the prior !isOnboardingRoute guard for the GitHub integration host or suppress its GitHub models on that route.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Verified — the host is already gated off onboarding. hideSidebar = isOnboardingRoute || shouldHoldProjectRouteForOnboarding (AppShell.tsx:1158) and the host mounts under !hideSidebar (AppShell.tsx:1311), so on /onboarding it doesn't render and there's no duplication with GitHubCard's panel. Not applying.

…ub banner

- deriveGithubRealtimeBlock: a connected repo proves a working relay credential
  (the install/webhook check succeeded, possibly via the ADE account-token
  fallback), so surface no blocker even when the device-flow user token is
  absent — fixes the persistent false "not authorized" for account-token users.
- IntegrationBannerHost: the standalone web-client adapter returns App-status
  stubs ({authenticated,user} / {installed:false,state:"unknown"}) that lack the
  real DTO fields; require the real shape (appName/relayConfigured/configured)
  before deriving the App block, so hosted-web projects no longer flash a false
  "GitHub App not authorized" banner.
- (onboarding-route duplication was a false positive: hideSidebar already gates
  the host off /onboarding — replied on-thread.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@arul28

arul28 commented Jul 23, 2026

Copy link
Copy Markdown
Owner Author

@codex review

Comment on lines +7848 to +7851
syncLanePr: async (laneId: string): Promise<PrSummary | null> =>
callPrReadRuntimeActionOr("syncLanePr", { arg: laneId }, () =>
ipcRenderer.invoke(IPC.prsSyncLanePr, { laneId }),
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Runtime sync drops lane
The runtime-backed path sends { arg: laneId }, but the daemon handler for prs.syncLanePr parses payload.laneId via parseLaneIdArgs, so the manual ⟳ action is rejected before reaching prService.syncLanePr. In production this makes the new per-badge sync silently fall back to null instead of healing the lane PR.

Artifacts

Repro: focused TypeScript harness for prs.syncLanePr payload handling

  • Evidence file captured while the check ran.

Repro: execution log showing arg payload rejection and laneId payload success

  • The full command output behind this check.

View artifacts

T-Rex Ran code and verified through T-Rex

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/preload/preload.ts
Line: 7848-7851

Comment:
**Runtime sync drops lane**
The runtime-backed path sends `{ arg: laneId }`, but the daemon handler for `prs.syncLanePr` parses `payload.laneId` via `parseLaneIdArgs`, so the manual ⟳ action is rejected before reaching `prService.syncLanePr`. In production this makes the new per-badge sync silently fall back to `null` instead of healing the lane PR.

How can I resolve this? If you propose a fix, please make it concise.

Fix in Claude Code

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Breezy!

Reviewed commit: 1a9dec8aed

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@arul28
arul28 merged commit 1dfc713 into main Jul 23, 2026
34 checks passed
@arul28
arul28 deleted the ade/lane-open-other-project-users-9ee5bfd6 branch July 23, 2026 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant