Skip to content

path to merge audit#260

Merged
arul28 merged 24 commits into
mainfrom
ade/path-to-merge-audit-966dea25
May 9, 2026
Merged

path to merge audit#260
arul28 merged 24 commits into
mainfrom
ade/path-to-merge-audit-966dea25

Conversation

@arul28
Copy link
Copy Markdown
Owner

@arul28 arul28 commented May 9, 2026

Note

High Risk
Changes core Path-to-Merge orchestration and merge behavior (including new auto-merge defaults and merge-ladder logic), which can affect when PRs are merged and when agents are dispatched. Adds new GitHub-side interactions (posting bot pings/comments) that could create unexpected automation or noise if misconfigured.

Overview
Path to Merge now runs through a dedicated path_to_merge ADE action (wired through desktop action registry and CLI planning), replacing the previous direct pr_start_issue_resolution invocation for non-preview runs.

The orchestrator is tightened to sync PR data into inventory before making decisions, wait for pending review-bot checks / post-push bot responses, and ping review bots after observing a fix-agent push (posts @copilot and, for large diffs, @greptile/@coderabbit). At-cap behavior is adjusted to be more CI-driven, pauses when an agent is awaiting user input, and limits gh --admin merges to branch-protection-style failures.

Defaults shift toward automation: PipelineSettings.autoMerge is now true by default, DB schema defaults are updated accordingly (auto_merge, force_finalize_mode, at_cap_policy), and UI/queue flows are updated to handle “armed gh auto-merge” as a non-terminal wait state and allow merge-only Path to Merge starts when CI is green.

Reviewed by Cursor Bugbot for commit 87bac3f. Configure here.

Summary by CodeRabbit

  • New Features

    • Path-to-Merge start/stop controls and a merge-only start option when CI is green
    • Review-bot ping tracking to avoid duplicate pings
  • Improvements

    • Auto-merge enabled by default and updated default pipeline behavior
    • Faster/more targeted PR polling and detail refresh, improved hot-refresh pacing
    • Smarter at-cap merge handling, clearer failure messages, and refined disable-auto-converge error flow

Greptile Summary

Path to Merge is refactored into a dedicated path_to_merge ADE action wired through both the CLI and desktop action registry. The orchestrator gains inventory pre-sync each iteration, post-push review-bot pinging (@copilot, @greptile, @coderabbit), a waiting_for_comments bot-check gate, and a new github_auto_merge_armed converge state tracked by the queue modal. Default pipeline settings shift to autoMerge: true, forceFinalizeMode: \"conditional\", and atCapPolicy: \"ci_retry_once\" with a DB backfill migration.

  • New review-bot ping flow: after each fix-agent push the orchestrator posts @copilot review (and optionally @greptile/@coderabbit for large PRs) and waits up to 5 minutes for their CI checks to complete before dispatching the next fix agent. Deduplication uses a persisted lastBotPingHeadSha/lastBotPingAt pair that survives app restarts.
  • Merge ladder hardening: --admin is now conditional on shouldAttemptAdminMergeForRestError, confining the admin rung to genuine branch-protection failures; ignoreReview is exported but not yet wired to any call site.
  • Queue modal now handles github_auto_merge_armed as a non-terminal wait state and promotes paused/converged into TERMINAL_FAILED to surface blocked states earlier."

Confidence Score: 4/5

The orchestrator changes are substantial but carefully layered; the most sensitive paths (admin bypass, auto-merge defaults) are guarded by explicit conditions and idempotent DB backfills.

The new --admin rung is gated behind shouldAttemptAdminMergeForRestError, and ignoreReview is exported but not threaded through any real call site, so the review-bypass path that concerned earlier reviewers is not reachable in practice. The DB backfill UPDATE is correctly in its own try/catch and is idempotent via ptm_defaults_backfilled_version. The findings are style and minor behavioral gaps rather than logic failures. The sheer size of the orchestrator change and the shift of three defaults toward more-aggressive automation warrants careful integration testing before a wide rollout.

apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts deserves the most attention — it is the largest change and controls when PRs are merged and when agents are dispatched.

Important Files Changed

Filename Overview
apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts Core orchestrator gains review-bot ping flow, per-iteration inventory sync, at-cap gate restructuring, and --admin-rung gating via shouldAttemptAdminMergeForRestError; ignoreReview is exported but not passed by any caller.
apps/desktop/src/main/services/state/kvDb.ts Adds backfill UPDATE for existing rows to adopt new auto_merge, force_finalize_mode, and at_cap_policy defaults; adds ptm_defaults_backfilled_version idempotency guard; new convergence-state columns for bot-ping tracking.
apps/desktop/src/main/services/prs/issueInventoryService.ts Adds mergeWaitKind, lastBotPingHeadSha, lastBotPingAt to DB persistence; noisy-bot-comment filtering now marks previously stored bot comments as fixed; mixed tab/space indentation introduced in newly added block.
apps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.tsx Adds isWaitingForGithubAutoMerge guard to keep polling when --auto is armed; promotes paused/converged to TERMINAL_FAILED for correct queue-modal exit.
apps/desktop/src/renderer/components/prs/shared/PrConvergencePanel.tsx Adds canStartMergeOnlyPath escape hatch so at-cap PRs with all checks passing and autoMerge=true can still start Path to Merge; button/tooltip states updated consistently.
apps/desktop/src/renderer/components/prs/tabs/GitHubTab.tsx Hot-refresh window simplified from 3-minute adaptive multi-poll to a single 30-second one-shot timer; callers that re-invoke while the timer is live get no effect, reducing post-push refresh coverage.
apps/desktop/src/shared/types/prs.ts Adds ConvergenceMergeWaitKind type, mergeWaitKind/lastBotPingHeadSha/lastBotPingAt fields to ConvergenceRuntimeState; updates DEFAULT_PIPELINE_SETTINGS to new defaults.
apps/ios/ADE/Resources/DatabaseBootstrap.sql Bootstrap SQL updated in parallel with Desktop migration; same backfill UPDATE and new column additions applied correctly.
apps/ade-cli/src/bootstrap.ts CLI runtime now instantiates createPathToMergeOrchestrator and createLaneWorktreeLockService, wires them into the action registry, and disposes them on shutdown.

Sequence Diagram

sequenceDiagram
    participant CLI as CLI / Queue Modal
    participant PtM as PathToMergeOrchestrator
    participant Inv as IssueInventoryService
    participant PR as PrService (GitHub)
    participant GH as GitHub Merge API

    CLI->>PtM: startPathToMerge(prId)
    loop Each Iteration
        PtM->>PR: getChecks + getReviewThreads + getComments + getReviews
        PtM->>Inv: syncFromPrData(prId, checks, threads, comments)
        alt PR merged
            PtM->>Inv: "saveRuntime(status=merged)"
        else Fix-agent just pushed (new headSha)
            PtM->>PR: "addComment(@copilot review)"
            opt "changedFiles > 250"
                PtM->>PR: "addComment(@greptile review)"
                PtM->>PR: "addComment(@coderabbit review)"
            end
            PtM->>Inv: persist lastBotPingHeadSha + lastBotPingAt
            PtM->>PtM: schedule(justPushed)
        else Terminal gate passed and review bots pending
            PtM->>Inv: "saveRuntime(pollerStatus=waiting_for_comments)"
            PtM->>PtM: schedule(warming)
        else At-cap merge_now
            PtM->>GH: REST merge rung 1
            alt REST fails with branch-policy error
                PtM->>GH: gh pr merge --admin rung 2
            end
            alt Both rungs fail
                PtM->>GH: gh pr merge --auto rung 3
                PtM->>Inv: "saveRuntime(converged, waiting_for_checks, mergeWaitKind=github_auto_merge_armed)"
            end
        else Dispatch fix agent
            PtM->>Inv: saveRuntime(active session)
            PtM->>PtM: schedule(next round)
        end
    end
Loading

Comments Outside Diff (4)

  1. apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts, line 606-610 (link)

    P1 Bot pings re-sent after every app restart

    lastBotPingHeadSha and lastBotPingAt are hardcoded to null here, but postReviewBotPings calls persistInProcessState to save them after posting. Because makeInProcessStateFromRuntime never reads those persisted values back, every app restart resets the deduplication guard. The next iteration then sees inProc.lastBotPingHeadSha === null, considers the current head SHA as "new", and re-fires @copilot, @greptile, and @coderabbit pings for the same commit. PRs resumed after a crash or restart will accumulate duplicate review bot mentions on every wake-up cycle.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts
    Line: 606-610
    
    Comment:
    **Bot pings re-sent after every app restart**
    
    `lastBotPingHeadSha` and `lastBotPingAt` are hardcoded to `null` here, but `postReviewBotPings` calls `persistInProcessState` to save them after posting. Because `makeInProcessStateFromRuntime` never reads those persisted values back, every app restart resets the deduplication guard. The next iteration then sees `inProc.lastBotPingHeadSha === null`, considers the current head SHA as "new", and re-fires `@copilot`, `@greptile`, and `@coderabbit` pings for the same commit. PRs resumed after a crash or restart will accumulate duplicate review bot mentions on every wake-up cycle.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

  2. apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts, line 633-648 (link)

    P2 No timeout for Greptile/CodeRabbit check-based wait

    The Copilot check has a 5-minute escape hatch via REVIEW_BOT_WAIT_TIMEOUT_MS, but the Greptile/CodeRabbit branch only unblocks when check.status === "completed". If either check is stuck in queued or in_progress indefinitely (e.g., a hung runner, a bot outage), getPendingReviewBots will keep returning them as pending and the orchestrator will spin in waiting_for_comments forever without surfacing an error or timeout to the user.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts
    Line: 633-648
    
    Comment:
    **No timeout for Greptile/CodeRabbit check-based wait**
    
    The Copilot check has a 5-minute escape hatch via `REVIEW_BOT_WAIT_TIMEOUT_MS`, but the Greptile/CodeRabbit branch only unblocks when `check.status === "completed"`. If either check is stuck in `queued` or `in_progress` indefinitely (e.g., a hung runner, a bot outage), `getPendingReviewBots` will keep returning them as pending and the orchestrator will spin in `waiting_for_comments` forever without surfacing an error or timeout to the user.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

  3. .ade/logs/dev/desktop-dev-20260508-210242.log, line 1-10 (link)

    P2 Dev log file committed to the repository

    This file contains local machine paths (/Users/admin/Projects/ADE/...), local and VPN IP addresses (192.168.1.240, 100.75.20.63), and runtime debug output. It appears to be generated from a local dev session and was committed by accident. The .ade/logs/ directory should be added to .gitignore to prevent this from recurring.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: .ade/logs/dev/desktop-dev-20260508-210242.log
    Line: 1-10
    
    Comment:
    **Dev log file committed to the repository**
    
    This file contains local machine paths (`/Users/admin/Projects/ADE/...`), local and VPN IP addresses (`192.168.1.240`, `100.75.20.63`), and runtime debug output. It appears to be generated from a local dev session and was committed by accident. The `.ade/logs/` directory should be added to `.gitignore` to prevent this from recurring.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

  4. apps/desktop/src/main/services/prs/pathToMergeOrchestrator.test.ts, line 266-279 (link)

    P2 Test mock for syncFromPrData doesn't include the new comments parameter

    The production call at line 1299 of the orchestrator now passes four arguments (prId, checks, reviewThreads, comments), but this test mock only declares three. The as unknown as cast on the issueInventoryService object hides the type mismatch, so the mock silently drops comments. The new comment-based logic (Copilot response detection via hasCopilotResponse, etc.) is not exercised by tests that rely on this mock, reducing coverage of the new behavior.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/desktop/src/main/services/prs/pathToMergeOrchestrator.test.ts
    Line: 266-279
    
    Comment:
    **Test mock for `syncFromPrData` doesn't include the new `comments` parameter**
    
    The production call at line 1299 of the orchestrator now passes four arguments (`prId, checks, reviewThreads, comments`), but this test mock only declares three. The `as unknown as` cast on the `issueInventoryService` object hides the type mismatch, so the mock silently drops `comments`. The new comment-based logic (Copilot response detection via `hasCopilotResponse`, etc.) is not exercised by tests that rely on this mock, reducing coverage of the new behavior.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Fix in Claude Code

Fix All in Claude Code

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

---

### Issue 1 of 3
apps/desktop/src/main/services/prs/issueInventoryService.ts:1037-1068
Mixed tab/space indentation introduced in this block. All surrounding code uses 2-space indentation; the new lines use a tab + spaces, which will break any formatter or editor configured for spaces-only.

```suggestion
      const noisyIssueCommentIds = new Set<string>();
      for (const comment of comments) {
        if (comment.source !== "issue") continue;
        if (isNoisyIssueComment(comment)) {
          noisyIssueCommentIds.add(`comment:${comment.id}`);
          continue;
        }
        const body = comment.body ?? "";
        upsertItem(prId, `comment:${comment.id}`, {
          source: detectSource(comment.author),
          type: "issue_comment",
          filePath: comment.path,
          line: comment.line,
          severity: extractSeverity(body),
          headline: extractHeadline(body, `Comment by ${comment.author}`),
          body,
          author: comment.author,
          url: comment.url,
        });
      }
      for (const existing of existingRows) {
        if (existing.type !== "issue_comment") continue;
        if (!noisyIssueCommentIds.has(existing.external_id)) continue;
        if (existing.state === "fixed" || existing.state === "dismissed") continue;
        db.run(
          "update pr_issue_inventory set state = 'fixed', updated_at = ? where id = ?",
          [nowIso(), existing.id],
        );
      }

      return buildSnapshot(prId);
    },
```

### Issue 2 of 3
apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts:838-855
**Secondary bot pings silently dropped after partial failure**

If the `@copilot` comment posts successfully but the `@greptile review` or `@coderabbit review` comment throws, the loop catches and logs the error, then falls through to set `inProc.lastBotPingHeadSha = normalizedHeadSha`. On the next iteration `postReviewBotPings` exits early at the `lastBotPingHeadSha === normalizedHeadSha` guard, so the secondary bots are never re-requested for the same push. For large PRs (>250 changed files) this means a transient comment-API failure permanently skips `@greptile` and `@coderabbit` without any user-visible signal.

### Issue 3 of 3
apps/desktop/src/renderer/components/prs/tabs/GitHubTab.tsx:481-494
**Hot-refresh now fires exactly once; window-extension calls are no-ops**

The old `startHotRefreshWindow` extended `hotRefreshUntilRef.current` on re-invocation and scheduled ~7 refreshes over 3 minutes (every 5 s for the first minute, every 15 s after). The replacement sets a single 30 s timer and returns immediately on re-invocation while that timer is live (`if (hotRefreshTimerRef.current != null) return`). If a CI check completes after 30 s (e.g., a 45-second build), the GitHub tab is already past its single refresh and won't update until the next manual or orchestrator-driven reload.

Reviews (12): Last reviewed commit: "Keep review gates on at-cap PtM merges" | Re-trigger Greptile

@vercel
Copy link
Copy Markdown

vercel Bot commented May 9, 2026

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

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
ade Ignored Ignored Preview May 9, 2026 5:58am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a40e5c89-a202-4e93-8e75-f0dbed524eae

📥 Commits

Reviewing files that changed from the base of the PR and between 067c1f0 and 9085e9b.

📒 Files selected for processing (29)
  • .gitignore
  • apps/ade-cli/src/bootstrap.ts
  • apps/ade-cli/src/cli.test.ts
  • apps/ade-cli/src/cli.ts
  • apps/ade-cli/src/headlessLinearServices.ts
  • apps/desktop/package.json
  • apps/desktop/scripts/dev.cjs
  • apps/desktop/src/main/services/adeActions/registry.test.ts
  • apps/desktop/src/main/services/adeActions/registry.ts
  • apps/desktop/src/main/services/prs/issueInventoryService.ts
  • apps/desktop/src/main/services/prs/pathToMergeOrchestrator.test.ts
  • apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts
  • apps/desktop/src/main/services/prs/prIssueResolution.test.ts
  • apps/desktop/src/main/services/prs/resolverUtils.ts
  • apps/desktop/src/main/services/state/kvDb.pipelineSettingsMigration.test.ts
  • apps/desktop/src/main/services/state/kvDb.ts
  • apps/desktop/src/renderer/components/prs/detail/PrDetailPane.issueResolver.test.tsx
  • apps/desktop/src/renderer/components/prs/detail/PrDetailPane.tsx
  • apps/desktop/src/renderer/components/prs/shared/PrConvergencePanel.test.tsx
  • apps/desktop/src/renderer/components/prs/shared/PrConvergencePanel.tsx
  • apps/desktop/src/renderer/components/prs/state/PrsContext.test.tsx
  • apps/desktop/src/renderer/components/prs/tabs/GitHubTab.test.tsx
  • apps/desktop/src/renderer/components/prs/tabs/GitHubTab.tsx
  • apps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.test.ts
  • apps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.tsx
  • apps/desktop/src/renderer/components/prs/tabs/queueAutomateMergingRuntime.ts
  • apps/desktop/src/shared/types/prs.ts
  • apps/ios/ADE/Resources/DatabaseBootstrap.sql
  • apps/ios/ADE/Services/Database.swift

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.


📝 Walkthrough

Walkthrough

This PR wires a Path-to-Merge orchestrator into runtime and ADE actions, extends convergence runtime with bot-ping tracking and merge-wait kinds, updates pipeline defaults and DB migrations/backfills, adds orchestrator bot-ping posting and inventory sync per-iteration, updates renderer polling/gating and modal behavior, and expands tests and dev scripts.

Changes

Path-to-Merge Orchestration Integration

Layer / File(s) Summary
Config & Dev Infra
.gitignore, apps/desktop/package.json, apps/desktop/scripts/dev.cjs
Adds /.ade/logs/ to gitignore; changes predev script and adds dev:clean; dev script conditionally applies Vite --force via --force-vite or env.
Headless Service
apps/ade-cli/src/headlessLinearServices.ts
Adds agentChatService.previewSessionToolNames method and stub implementation returning empty array.
Types & Defaults
apps/ade-cli/src/bootstrap.ts, apps/desktop/src/shared/types/prs.ts
Adds optional pathToMergeOrchestrator on AdeRuntime; adds mergeWaitKind, lastBotPingHeadSha, lastBotPingAt to runtime state; updates DEFAULT_PIPELINE_SETTINGS defaults (autoMerge: true, forceFinalizeMode: conditional, atCapPolicy: ci_retry_once).
ADE Registry & CLI Wiring
apps/desktop/src/main/services/adeActions/registry.ts, apps/ade-cli/src/cli.ts, apps/ade-cli/src/cli.test.ts
Registers path_to_merge domain, allowlists CTO-only startPathToMerge/stopPathToMerge, wires runtime.pathToMergeOrchestrator, CLI invokes path_to_merge.startPathToMerge for non-preview flows; CLI tests updated.
DB Migrations & Backfill
apps/desktop/src/main/services/state/kvDb.ts, apps/ios/ADE/Resources/DatabaseBootstrap.sql, apps/ios/ADE/Services/Database.swift
Backfills/introduces PtM pipeline columns and marker, flips auto_merge default to 1, adds at-cap policy columns, and adds pr_convergence_state columns for last_bot_ping_* and merge_wait_kind.
Persistence & Inventory
apps/desktop/src/main/services/prs/issueInventoryService.ts
Extends row types and upsert to persist merge_wait_kind and last_bot_ping_*; validates/sanitizes new fields; maps greptile-appsgreptile; improves noisy comment handling and review-thread latest-comment selection.
Resolver Utils
apps/desktop/src/main/services/prs/resolverUtils.ts
Adds noisy comment patterns for Capy auto-review spend-limit and paused messages.
Orchestrator Core
apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts
Syncs checks/reviews/comments into inventory each iteration, tracks last bot-ping SHA/timestamp, posts review-bot pings once per head SHA, supports ignoreReview readiness option, adjusts hard-cap terminal gating, pauses when awaiting user input, and records mergeWaitKind when auto-merge armed.
Orchestrator Tests & Scaffolding
apps/desktop/src/main/services/prs/pathToMergeOrchestrator.test.ts
Test scaffolding and many tests added/updated for pending bot waits, posting pings, SHA deduplication, stale-bot timeout, inventory sync gating, at-cap behavior, and Copilot failure handling.
Renderer: PrDetailPane
apps/desktop/src/renderer/components/prs/detail/PrDetailPane.tsx
Adds PR/status keyed refresh effect, richer polling (checks/actionRuns/activity/reviewThreads), PtM 10s convergence runtime polling when active, and improved pathToMergeStop error handling to reload runtime and exit early on failure.
Renderer: PrConvergencePanel
apps/desktop/src/renderer/components/prs/shared/PrConvergencePanel.tsx
Adds merge-only start condition (autoMerge && allChecksPassing) to allow start at max rounds and adjusts disabled-reason messaging; tests added for max-round behavior.
Queue Modal & Runtime
apps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.tsx, apps/desktop/src/renderer/components/prs/tabs/queueAutomateMergingRuntime.ts
Adds isWaitingForGithubAutoMerge predicate, uses it to sleep-and-continue during modal polling, extends terminal failures to include paused/converged, and refines failure message precedence.
GitHub Tab & Tests
apps/desktop/src/renderer/components/prs/tabs/GitHubTab.tsx, apps/desktop/src/renderer/components/prs/tabs/GitHubTab.test.tsx
Changes hot-refresh to a single delayed forced snapshot, reduces fingerprint fields, and adds tests for refresh pacing and suppression on CI/review-only updates.
KV DB Migration Test
apps/desktop/src/main/services/state/kvDb.pipelineSettingsMigration.test.ts
Adds Vitest suite validating legacy-row backfill, user-override persistence, and idempotency across reopen.
Pr Issue Resolution Tests
apps/desktop/src/main/services/prs/prIssueResolution.test.ts
Updates mocks/expectations for new bot-ping fields, pipeline defaults, validation of mergeWaitKind, and detectSource mappings.
Misc Tests & Helpers
various *.test.tsx files
Updates test helpers to include new convergence fields and action-run refresh behaviors across multiple component tests and harnesses.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • arul28/ADE#241: Overlapping Path-to-Merge surface changes (orchestrator, registry, types, migrations, UI).
  • arul28/ADE#192: Related changes in PR convergence runtime, issueInventoryService, and UI components.
  • arul28/ADE#185: Prior changes extending AdeRuntime/bootstrapping and registry wiring.

Suggested labels

desktop, ios

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 18.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title 'path to merge audit' is vague and does not clearly convey the main changes in this substantial PR, which involve routing Path-to-Merge through a new ADE action, orchestrator improvements, defaults updates, and database migrations. Consider a more descriptive title such as 'Route Path-to-Merge through dedicated ADE action with review-bot pinging and defaults updates' or 'Implement Path-to-Merge audit: ADE routing, bot pings, and pipeline defaults migration'.
✅ Passed checks (3 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.

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

✨ 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/path-to-merge-audit-966dea25

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@capy-ai
Copy link
Copy Markdown

capy-ai Bot commented May 9, 2026

Capy auto-review is paused for this organization because the monthly auto-review limit has been reached. Increase the limit or turn it off in billing settings to resume automatic reviews.

Comment thread apps/desktop/src/main/services/state/kvDb.ts
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 10

🤖 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/ade-cli/src/bootstrap.ts`:
- Around line 156-166: createAdeRuntime currently constructs the runtime but
does not attach the new pathToMergeOrchestrator field, causing
getAdeActionDomainServices to receive null for path_to_merge at runtime; update
createAdeRuntime to wire the pathToMergeOrchestrator into the returned
AdeRuntime.runtime object (the same property name pathToMergeOrchestrator) so
callers like getAdeActionDomainServices and CLI commands can call
path_to_merge.startPathToMerge/stopPathToMerge; ensure the orchestrator is
created or passed in where other orchestrators are initialized and included in
the runtime return value, preserving the existing nullable typing.

In `@apps/desktop/src/main/services/adeActions/registry.ts`:
- Around line 303-306: The new path_to_merge domain exposes privileged actions
startPathToMerge and stopPathToMerge but lacks a CTO-only restriction; update
the ADE action registry in registry.ts to add an ADE_ACTION_CTO_ONLY entry for
the path_to_merge domain (so run_ade_action enforces CTO-only callers), ensuring
the domain’s allowlist includes the ADE_ACTION_CTO_ONLY marker and any existing
permission checks that consume that constant are exercised for
startPathToMerge/stopPathToMerge.

In `@apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts`:
- Around line 1040-1044: The current early return when opts.ignoreReview is true
bypasses CI verification (ctx.pr.checksStatus and the later getChecks()
validation), allowing the merge_now path to proceed without real check results;
modify the logic so opts.ignoreReview only skips review-thread blockers (the
block that checks ctx.pr.reviewStatus === "changes_requested") and does not
return before running the CI sanity checks—either move the opts.ignoreReview
short-circuit to after the CI/checks block or change the condition to only skip
the reviewStatus branch, ensuring getChecks() (and any subsequent checks) still
run before allowing merge_now.
- Around line 364-367: isWithinReviewBotWaitWindow currently treats missing or
unparsable timestamps as "still waiting" which lets checks with null startedAt
park forever; change its logic to fail closed for missing/unparsable values:
return false when timestamp is falsy or Date.parse(timestamp) is NaN, and only
return true when now() - parsedTimestamp < REVIEW_BOT_WAIT_TIMEOUT_MS. Also
audit callers (notably getPendingReviewBots which passes check.startedAt when
lastBotPingAt may exist) and ensure they pass the actual anchor timestamp (e.g.,
lastBotPingAt) or handle nulls so we don't forward null into
isWithinReviewBotWaitWindow; apply the same fix to the other occurrences
referenced (around the 379-381 region).

In `@apps/desktop/src/main/services/state/kvDb.ts`:
- Around line 3386-3417: The current one-shot marker
PIPELINE_SETTINGS_DEFAULTS_BACKFILL_MARKER plus the global kv check can
permanently miss late-arriving pr_pipeline_settings rows; change the migration
to be per-row idempotent by adding and/or using a per-row marker (e.g., a new
column like backfilled_ptm_defaults_version or storing a fingerprint in
pr_pipeline_settings) and update only rows that lack that per-row marker, then
set that marker on each updated row within the same transaction; modify the
db.run SQL (the UPDATE against pr_pipeline_settings) to include "and
coalesce(backfilled_ptm_defaults_version, '') <> ?" or "and
backfilled_ptm_defaults_version is null" and set backfilled_ptm_defaults_version
= ? in the UPDATE, and remove reliance on the single kv insert (or keep it as a
global audit but not the gating condition), using the same
PIPELINE_SETTINGS_DEFAULTS_BACKFILL_MARKER value as the per-row version token so
the operation is idempotent and will apply to late-arriving rows when they
appear.
- Around line 3363-3366: The pr_pipeline_settings table creation uses CREATE
TABLE IF NOT EXISTS so upgraded DBs keep the legacy auto_merge default; fix by
either 1) ensuring all insert/update paths explicitly supply the auto_merge
value (search for code that INSERTs/UPDATEs pr_pipeline_settings and add
explicit auto_merge assignments) or 2) implement a migration that rebuilds
pr_pipeline_settings with the new default (create a new table with correct
auto_merge default, copy data from the old table, drop/rename tables, and
recreate indexes) so existing databases get the corrected default; reference the
pr_pipeline_settings table and auto_merge column when making the changes.

In `@apps/desktop/src/renderer/components/prs/detail/PrDetailPane.tsx`:
- Around line 1718-1741: The poller currently collapses all loadConvergenceState
errors into null and then calls applyConvergenceRuntime(null), which wipes PtM
state on transient failures; update the pollRuntime logic so that
loadConvergenceState errors do not trigger applyConvergenceRuntime(null): call
applyConvergenceRuntime(runtime) only when the await succeeds (runtime may be
null meaning no runtime), and on catch keep the last known state (do not call
applyConvergenceRuntime) and optionally log the error; preserve the interval
retry behavior in pollRuntime and ensure inFlight/cancelled semantics remain the
same.

In `@apps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.tsx`:
- Around line 229-236: The code relies on free-form runtime.pauseReason text
(checked via isWaitingForGithubAutoMerge) to decide queue liveness, which is
brittle; change the contract to use an explicit enum/flag on the runtime (e.g.,
runtime.mergeState or runtime.pauseCode) and update consumers to check that
field instead of parsing pauseReason. Modify isWaitingForGithubAutoMerge to
accept and check the new explicit runtime property (and its type), update any
producers that set pauseReason to set the new field, and bump/update shared
types/preload IPC interfaces so the renderer uses the typed enum/flag rather
than string matching.

In `@apps/ios/ADE/Resources/DatabaseBootstrap.sql`:
- Around line 2612-2635: The update block that rewrites legacy defaults checks
for the marker key 'pr_pipeline_settings.ptm_defaults_backfilled.v1' in the kv
table but never sets it, so add logic to persist that marker after the update
(for example, an INSERT INTO kv (key, value) VALUES
('pr_pipeline_settings.ptm_defaults_backfilled.v1', '1') or an UPSERT) so the
backfill only runs once; place this write immediately after the update statement
(or within the same transaction if present) and ensure it references the exact
key string used in the EXISTS check.

In `@apps/ios/ADE/Services/Database.swift`:
- Around line 2248-2256: The ensureColumn calls for pr_pipeline_settings (e.g.,
ensureColumn(..., "force_finalize_mode"), "auto_agent_confidence_threshold",
"at_cap_policy", etc.) only add columns if missing and do not change defaults
for existing DBs; update the migration to either (A) perform a proper
table-rebuild migration that creates a new pr_pipeline_settings table with the
intended column definitions, copies data, drops the old table and renames the
new one, or (B) leave columns as-is but ensure all code paths that INSERT new
pr_pipeline_settings rows explicitly supply the intended default values (and add
an explicit backfill UPDATE for existing rows if needed); apply the same fix for
the other schema changes noted in the 2260–2294 range.
🪄 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

Run ID: eca9009a-715c-452e-a528-ebbff807767f

📥 Commits

Reviewing files that changed from the base of the PR and between 5a2c921 and 067c1f0.

📒 Files selected for processing (22)
  • .gitignore
  • apps/ade-cli/src/bootstrap.ts
  • apps/ade-cli/src/cli.test.ts
  • apps/ade-cli/src/cli.ts
  • apps/desktop/src/main/services/adeActions/registry.ts
  • apps/desktop/src/main/services/prs/issueInventoryService.ts
  • apps/desktop/src/main/services/prs/pathToMergeOrchestrator.test.ts
  • apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts
  • apps/desktop/src/main/services/prs/prIssueResolution.test.ts
  • apps/desktop/src/main/services/state/kvDb.pipelineSettingsMigration.test.ts
  • apps/desktop/src/main/services/state/kvDb.ts
  • apps/desktop/src/renderer/components/prs/detail/PrDetailPane.issueResolver.test.tsx
  • apps/desktop/src/renderer/components/prs/detail/PrDetailPane.tsx
  • apps/desktop/src/renderer/components/prs/shared/PrConvergencePanel.test.tsx
  • apps/desktop/src/renderer/components/prs/shared/PrConvergencePanel.tsx
  • apps/desktop/src/renderer/components/prs/state/PrsContext.test.tsx
  • apps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.test.ts
  • apps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.tsx
  • apps/desktop/src/renderer/components/prs/tabs/queueAutomateMergingRuntime.ts
  • apps/desktop/src/shared/types/prs.ts
  • apps/ios/ADE/Resources/DatabaseBootstrap.sql
  • apps/ios/ADE/Services/Database.swift

Comment thread apps/ade-cli/src/bootstrap.ts Outdated
Comment thread apps/desktop/src/main/services/adeActions/registry.ts
Comment thread apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts Outdated
Comment thread apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts Outdated
Comment thread apps/desktop/src/main/services/state/kvDb.ts
Comment thread apps/desktop/src/main/services/state/kvDb.ts Outdated
Comment thread apps/desktop/src/renderer/components/prs/detail/PrDetailPane.tsx
Comment thread apps/ios/ADE/Resources/DatabaseBootstrap.sql Outdated
Comment thread apps/ios/ADE/Services/Database.swift
Comment thread apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts
Comment on lines 807 to 853
}
}

async function postReviewBotPings(ctx: IterationContext, inProc: InProcessState, headSha: string | null): Promise<void> {
const normalizedHeadSha = headSha?.trim() || null;
if (!normalizedHeadSha) return;
if (inProc.lastBotPingHeadSha === normalizedHeadSha) return;

const bodies = ["@copilot review but do not make fixes"];
let changedFileCount = 0;
try {
changedFileCount = (await prService.getFiles(ctx.pr.id)).length;
} catch (err) {
logger.debug("ptm.bot_ping_file_count_failed", { prId: ctx.pr.id, error: getErrorMessage(err) });
}
if (changedFileCount > 250) {
bodies.push("@greptile review", "@coderabbit review");
}

let postedCount = 0;
let postedCopilotPing = false;
for (const body of bodies) {
try {
await prService.addComment({ prId: ctx.pr.id, body });
postedCount += 1;
if (/^@copilot\b/i.test(body)) {
postedCopilotPing = true;
}
} catch (err) {
logger.warn("ptm.bot_ping_failed", { prId: ctx.pr.id, body, error: getErrorMessage(err) });
}
}

if (!postedCopilotPing) {
logger.warn("ptm.bot_pings_not_recorded", { prId: ctx.pr.id, headSha: normalizedHeadSha, postedCount });
return;
}

inProc.lastBotPingHeadSha = normalizedHeadSha;
inProc.lastBotPingAt = nowIso();
persistInProcessState(ctx.pr.id, inProc);
logger.info("ptm.bot_pings_posted", { prId: ctx.pr.id, headSha: normalizedHeadSha, count: postedCount });
}

function pauseLoop(prId: string, reason: string, errorMessage?: string | null): ConvergenceRuntimeState {
clearTimer(prId);
releaseLoopLock(prId);
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 Greptile/CodeRabbit pings can duplicate when Copilot comment fails

On PRs with > 250 changed files, bodies contains ["@copilot ...", "@greptile review", "@coderabbit review"]. The for loop has a per-body catch that logs and continues — so if the @copilot post throws, the loop still posts @greptile review and @coderabbit review. Because postedCopilotPing remains false, the function returns without updating lastBotPingHeadSha. Every subsequent call to postReviewBotPings for the same headSha skips the early-exit guard and re-posts @greptile and @coderabbit, accumulating duplicate pings on every orchestrator cycle that observes the same push.

A simple fix: break out of the loop on a Copilot comment failure, or only post secondary bot pings after Copilot has been successfully recorded.

Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts
Line: 807-853

Comment:
**Greptile/CodeRabbit pings can duplicate when Copilot comment fails**

On PRs with > 250 changed files, `bodies` contains `["@copilot ...", "@greptile review", "@coderabbit review"]`. The `for` loop has a per-body `catch` that logs and continues — so if the `@copilot` post throws, the loop still posts `@greptile review` and `@coderabbit review`. Because `postedCopilotPing` remains `false`, the function returns without updating `lastBotPingHeadSha`. Every subsequent call to `postReviewBotPings` for the same `headSha` skips the early-exit guard and re-posts `@greptile` and `@coderabbit`, accumulating duplicate pings on every orchestrator cycle that observes the same push.

A simple fix: break out of the loop on a Copilot comment failure, or only post secondary bot pings after Copilot has been successfully recorded.

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

Fix in Claude Code

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Skipped: comment is from another GitHub bot.

@arul28 arul28 force-pushed the ade/path-to-merge-audit-966dea25 branch from 3de9e4f to 9398fb5 Compare May 9, 2026 05:40
@arul28 arul28 force-pushed the ade/path-to-merge-audit-966dea25 branch from 9398fb5 to c651bbd Compare May 9, 2026 05:41
Comment thread apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts
@arul28 arul28 merged commit df62f66 into main May 9, 2026
7 of 8 checks passed
@arul28 arul28 deleted the ade/path-to-merge-audit-966dea25 branch May 9, 2026 06:00
@arul28 arul28 mentioned this pull request May 10, 2026
3 tasks
arul28 added a commit that referenced this pull request May 10, 2026
* Virtualized file tree, shared Ade diff viewer, and finalize (CLI + docs) (#272)

* feat: virtualized file tree explorer + shared Ade diff viewer

Splits FilesPage into a virtualized FilesExplorer with local path filter,
inline F2 rename, and per-row git status badges, and replaces direct
MonacoDiffView usage in LaneDiffPane / PrDetailPane / ChatFileChangesPanel
with a shared AdeDiffViewer that supports split/unified/wrap toggles and
read-only patch rendering. Diff service gains getChanges (numstat +
renames) and getFilePatch with bounded output and worktree-escape checks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(finalize): allow diff.getFilePatch, CLI patch command, and docs

- Extend ADE_ACTION_ALLOWLIST.diff with getFilePatch for ade actions/CLI.
- Add ade diff patch wired to diff.getFilePatch; update README and tests.
- Refresh internal docs for files editor, lanes diff, chat composer, architecture IPC.

Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>

* Fix PR review feedback for diff viewer

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* path to merge audit (#260)

* Route path-to-merge through ADE actions

* Keep polling after GitHub auto-merge is armed

* Remove generated dev log from PtM lane

* Align PtM pipeline defaults in tests and iOS bootstrap

* Respect max rounds when starting PtM from PR panel

* Backfill legacy PtM pipeline defaults once

* Persist PtM review bot wait state

* Address PtM review automation gaps

* Fix PtM desktop typecheck import

* Keep admin merge behind explicit force policy

* Ignore Capy spend-limit notices in PR inventory

* Retire noisy PR issue comments during inventory sync

* Throttle GitHub PR hot refresh polling

* Limit GitHub PR hot refresh to one follow-up

* Avoid GitHub snapshot refreshes for PR status ticks

* Avoid duplicate review bot pings

* Refresh PR detail checks on status updates

* Keep action run polling results live

* Fix Path to Merge readiness refresh

* Fix PtM readiness test label

* Make PtM readiness test less brittle

* Refresh PtM external checks while polling

* Reuse Vite optimizer cache in dev

* Keep review gates on at-cap PtM merges

* Add Linear issue dropdown to lane creation (#274)

* Add Linear issue lane workflows

* Fix lane git mocks for branch validation; sync iOS bootstrap SQL

- Add defaultLaneBranchGitStub for check-ref-format and show-ref ade/* probes from resolveCreateBranchRef so laneService tests stub git consistently.
- Drop overly broad show-ref and ls-remote stubs that broke getDeleteRisk and remote-branch checks.
- Regenerate DatabaseBootstrap.sql from kvDb migrate SQL for lane_linear_issues table.

Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>

* Add Linear issue dropdown to lane creation

Surface a searchable Linear issue picker in the new-lane dialog so users
can attach a Linear issue at lane creation time instead of pasting an
identifier. Adds the supporting Linear browser, CLI plumbing, and doc
updates for the workflow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ship: iteration 1 — rebase + address Greptile/CodeRabbit/Cursor review

- N+1 fix: batch lane_linear_issues lookup in listLanes
- GraphQL: pass IssueFilter via variables, not string interpolation
- Branch sanitizer: strip @{, .., trailing .lock
- Magic words: skip duplicate ID prefix on commit messages
- RPC schema: nullable url/assignee* fields; validate first cap; reject
  non-object linearIssue payload; CLI mirrors the validation
- Empty-text steer allowed when context attachments present
- IPC picker/search return empty when tracker unavailable (no throw)
- Lane teardown deletes lane_linear_issues; full payload validated
- Adopted PR bodies now patched with Linear references too
- kvDb: unique index on (project_id, lane_id) for lane_linear_issues
- AgentChatPane resets context attachments on lane change
- LinearIssueBadge keyboard-focusable; popover open via focus-within
- LinearIssuePicker seeds pendingIssue from active selection too
- CreatePrModal clears Linear close-toggle and refs when issue dropped
- chatContextAttachments wraps Linear text as untrusted prompt data
- CLI Linear connection status forwards organization fields

* ship: iteration 2 — fix CI shards 1 & 3, align Linear RPC schema

- linearAuth.test.ts: assert filter via body.variables.filter to match
  the variables-based GraphQL contract from iter 1
- laneService.test.ts: stub check-ref-format --branch in the runGit mock
  so the new branch sanitizer round-trip is allowed
- kvDb.ts: replace UNIQUE index on lane_linear_issues with a
  bootstrap-time duplicate-coalescing sweep (CRRs disallow non-PK
  unique indices); app-layer enforcement remains
- adeRpcServer.ts: searchLinearIssues schema first.max 200 -> 50 to
  match runtime clamp + error message

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ship: iteration 3 — bootstrap SQL refresh + 4 new review fixes

- iOS DatabaseBootstrap.sql regenerated to track kvDb dedupe sweep
- agentChatService: Codex steer uses preparedSteer.submittedText so
  context-only steers send the fallback prompt
- agentChatService: Droid busy-steer routes through prepareSendMessage
  (allowActiveSession: true) like Cursor's busy path
- linearClient.normalizeSdkIssue: labels now accepts resolved
  connection objects, not just callable thunks
- prService.createFromLane: pass preserveExisting:false to
  ensureLinearPrReference so Refs upgrades to Fixes when
  closeLinearIssueOnMerge is true

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ship: iteration 4 — XML-escape untrusted text, fix adopt path Refs->Fixes, drop searchIssues min clamp

- chatContextAttachments.wrapUntrustedLinearText: HTML-entity-escape
  &/</>/"/' before wrapping so Linear titles can't break out of the
  <untrusted-data> tag (Greptile P1/security)
- prService adoption branch: pass preserveExisting:false to
  ensureLinearPrReference when closeLinearIssueOnMerge is true so
  Refs upgrades to Fixes on adopted PRs too (CodeRabbit Major)
- linearClient.searchIssues: lower clamp 10 -> 1 to match the
  schema contract (Cursor Low)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ship: iteration 5 — wrap all untrusted Linear fields, raw-GraphQL quick view, drop dead helpers

- chatContextAttachments: wrap assignee/creator/team/project/state/
  labels/branchName/url through wrapUntrustedLinearText so user-
  controlled Linear fields can't break out of the prompt sandbox
  (Greptile P1/security)
- linearClient.getQuickView: replace SDK lazy-loaded issues calls
  with searchIssues raw GraphQL using ISSUE_FIELDS_FRAGMENT (was
  ~168 round-trips per call, now 2) (Cursor Medium)
- linearClient: drop unused gqlString / gqlStringArray helpers
  (Cursor Low)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add remote runtime architecture spec

Comprehensive engineering specification for the runtime extraction,
multi-project unification, and SSH-tunneled remote runtime feature.
Captures all architectural decisions, audit findings, phased
implementation plan with file-level detail, migration path, and
parallelization tracks for the dev team.

* Address PR #275 review comments

- Linear tool schema: add nullable optional properties (description, url,
  projectName, teamName, assigneeId, assigneeName, creatorId, creatorName,
  dueDate, estimate, branchName) to required so OpenAI strict mode accepts
  create_lane calls. The anyOf [type, null] entries already make them
  safely omittable at the value level.
- linearClient.metadataTags: defensively read from node.metadata.tags so
  any populated data is preserved instead of silently dropped to [].
  Falls back to [] when the field is absent.
- kvDb pr_pipeline_settings backfill: log via console.warn on failure
  instead of swallowing silently. Documents that an invisible state
  split (existing rows on legacy defaults vs new rows on new defaults)
  could otherwise occur. ALTER TABLE catches stay silent because
  column-already-exists is the expected re-run path.
- laneService.resolveCreateBranchRef: don't blame Linear when the
  conflicting branch came from an explicit branchName arg or the
  fallback path. Differentiate the error message based on the source
  of the suggested branch.
- bootstrap.createPathToMergeOrchestrator: replace `as never` with a
  typed cast through Parameters<typeof createPathToMergeOrchestrator>[0]
  so any future tightening of PathToMergeDeps surfaces as a type error.
  Also drop a gratuitous `as never` on a call whose target accepts
  unknown.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
arul28 added a commit that referenced this pull request May 11, 2026
* Multi-window scaffolding, ade-code terminal client, and finalize CI/docs (#273)

* Multi-window scaffolding and ade-code launcher

Add multi-window project tab management to the desktop app, the `ade code` headless launcher backed by a new ade-code Ink terminal client, and an `app/navigate` RPC that routes external clients into a desktop window.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Finalize ade-code: isolated typecheck, CI jobs, docs, and navigation guard

Point ade-code imports at shared/types modules and load embedded ade-cli via
dynamic import so apps/ade-code tsc stays bounded. Extend CI install cache and
add typecheck/test/build jobs for ade-code. Document ade-code in ARCHITECTURE,
PRD, chat feature map, new docs/features/ade-code, and ade-cli README (ade code
socket semantics). Guard AppNavigationBridge when preload app API is absent
(tests and early bootstrap).

Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>

* Fix PR review findings for ade-code

* refactor(ade-code): share action helpers between attached and embedded RPC

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>

* Remote runtime architecture spec (#275)

* Virtualized file tree, shared Ade diff viewer, and finalize (CLI + docs) (#272)

* feat: virtualized file tree explorer + shared Ade diff viewer

Splits FilesPage into a virtualized FilesExplorer with local path filter,
inline F2 rename, and per-row git status badges, and replaces direct
MonacoDiffView usage in LaneDiffPane / PrDetailPane / ChatFileChangesPanel
with a shared AdeDiffViewer that supports split/unified/wrap toggles and
read-only patch rendering. Diff service gains getChanges (numstat +
renames) and getFilePatch with bounded output and worktree-escape checks.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* chore(finalize): allow diff.getFilePatch, CLI patch command, and docs

- Extend ADE_ACTION_ALLOWLIST.diff with getFilePatch for ade actions/CLI.
- Add ade diff patch wired to diff.getFilePatch; update README and tests.
- Refresh internal docs for files editor, lanes diff, chat composer, architecture IPC.

Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>

* Fix PR review feedback for diff viewer

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* path to merge audit (#260)

* Route path-to-merge through ADE actions

* Keep polling after GitHub auto-merge is armed

* Remove generated dev log from PtM lane

* Align PtM pipeline defaults in tests and iOS bootstrap

* Respect max rounds when starting PtM from PR panel

* Backfill legacy PtM pipeline defaults once

* Persist PtM review bot wait state

* Address PtM review automation gaps

* Fix PtM desktop typecheck import

* Keep admin merge behind explicit force policy

* Ignore Capy spend-limit notices in PR inventory

* Retire noisy PR issue comments during inventory sync

* Throttle GitHub PR hot refresh polling

* Limit GitHub PR hot refresh to one follow-up

* Avoid GitHub snapshot refreshes for PR status ticks

* Avoid duplicate review bot pings

* Refresh PR detail checks on status updates

* Keep action run polling results live

* Fix Path to Merge readiness refresh

* Fix PtM readiness test label

* Make PtM readiness test less brittle

* Refresh PtM external checks while polling

* Reuse Vite optimizer cache in dev

* Keep review gates on at-cap PtM merges

* Add Linear issue dropdown to lane creation (#274)

* Add Linear issue lane workflows

* Fix lane git mocks for branch validation; sync iOS bootstrap SQL

- Add defaultLaneBranchGitStub for check-ref-format and show-ref ade/* probes from resolveCreateBranchRef so laneService tests stub git consistently.
- Drop overly broad show-ref and ls-remote stubs that broke getDeleteRisk and remote-branch checks.
- Regenerate DatabaseBootstrap.sql from kvDb migrate SQL for lane_linear_issues table.

Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>

* Add Linear issue dropdown to lane creation

Surface a searchable Linear issue picker in the new-lane dialog so users
can attach a Linear issue at lane creation time instead of pasting an
identifier. Adds the supporting Linear browser, CLI plumbing, and doc
updates for the workflow.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ship: iteration 1 — rebase + address Greptile/CodeRabbit/Cursor review

- N+1 fix: batch lane_linear_issues lookup in listLanes
- GraphQL: pass IssueFilter via variables, not string interpolation
- Branch sanitizer: strip @{, .., trailing .lock
- Magic words: skip duplicate ID prefix on commit messages
- RPC schema: nullable url/assignee* fields; validate first cap; reject
  non-object linearIssue payload; CLI mirrors the validation
- Empty-text steer allowed when context attachments present
- IPC picker/search return empty when tracker unavailable (no throw)
- Lane teardown deletes lane_linear_issues; full payload validated
- Adopted PR bodies now patched with Linear references too
- kvDb: unique index on (project_id, lane_id) for lane_linear_issues
- AgentChatPane resets context attachments on lane change
- LinearIssueBadge keyboard-focusable; popover open via focus-within
- LinearIssuePicker seeds pendingIssue from active selection too
- CreatePrModal clears Linear close-toggle and refs when issue dropped
- chatContextAttachments wraps Linear text as untrusted prompt data
- CLI Linear connection status forwards organization fields

* ship: iteration 2 — fix CI shards 1 & 3, align Linear RPC schema

- linearAuth.test.ts: assert filter via body.variables.filter to match
  the variables-based GraphQL contract from iter 1
- laneService.test.ts: stub check-ref-format --branch in the runGit mock
  so the new branch sanitizer round-trip is allowed
- kvDb.ts: replace UNIQUE index on lane_linear_issues with a
  bootstrap-time duplicate-coalescing sweep (CRRs disallow non-PK
  unique indices); app-layer enforcement remains
- adeRpcServer.ts: searchLinearIssues schema first.max 200 -> 50 to
  match runtime clamp + error message

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ship: iteration 3 — bootstrap SQL refresh + 4 new review fixes

- iOS DatabaseBootstrap.sql regenerated to track kvDb dedupe sweep
- agentChatService: Codex steer uses preparedSteer.submittedText so
  context-only steers send the fallback prompt
- agentChatService: Droid busy-steer routes through prepareSendMessage
  (allowActiveSession: true) like Cursor's busy path
- linearClient.normalizeSdkIssue: labels now accepts resolved
  connection objects, not just callable thunks
- prService.createFromLane: pass preserveExisting:false to
  ensureLinearPrReference so Refs upgrades to Fixes when
  closeLinearIssueOnMerge is true

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ship: iteration 4 — XML-escape untrusted text, fix adopt path Refs->Fixes, drop searchIssues min clamp

- chatContextAttachments.wrapUntrustedLinearText: HTML-entity-escape
  &/</>/"/' before wrapping so Linear titles can't break out of the
  <untrusted-data> tag (Greptile P1/security)
- prService adoption branch: pass preserveExisting:false to
  ensureLinearPrReference when closeLinearIssueOnMerge is true so
  Refs upgrades to Fixes on adopted PRs too (CodeRabbit Major)
- linearClient.searchIssues: lower clamp 10 -> 1 to match the
  schema contract (Cursor Low)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* ship: iteration 5 — wrap all untrusted Linear fields, raw-GraphQL quick view, drop dead helpers

- chatContextAttachments: wrap assignee/creator/team/project/state/
  labels/branchName/url through wrapUntrustedLinearText so user-
  controlled Linear fields can't break out of the prompt sandbox
  (Greptile P1/security)
- linearClient.getQuickView: replace SDK lazy-loaded issues calls
  with searchIssues raw GraphQL using ISSUE_FIELDS_FRAGMENT (was
  ~168 round-trips per call, now 2) (Cursor Medium)
- linearClient: drop unused gqlString / gqlStringArray helpers
  (Cursor Low)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Add remote runtime architecture spec

Comprehensive engineering specification for the runtime extraction,
multi-project unification, and SSH-tunneled remote runtime feature.
Captures all architectural decisions, audit findings, phased
implementation plan with file-level detail, migration path, and
parallelization tracks for the dev team.

* Address PR #275 review comments

- Linear tool schema: add nullable optional properties (description, url,
  projectName, teamName, assigneeId, assigneeName, creatorId, creatorName,
  dueDate, estimate, branchName) to required so OpenAI strict mode accepts
  create_lane calls. The anyOf [type, null] entries already make them
  safely omittable at the value level.
- linearClient.metadataTags: defensively read from node.metadata.tags so
  any populated data is preserved instead of silently dropped to [].
  Falls back to [] when the field is absent.
- kvDb pr_pipeline_settings backfill: log via console.warn on failure
  instead of swallowing silently. Documents that an invisible state
  split (existing rows on legacy defaults vs new rows on new defaults)
  could otherwise occur. ALTER TABLE catches stay silent because
  column-already-exists is the expected re-run path.
- laneService.resolveCreateBranchRef: don't blame Linear when the
  conflicting branch came from an explicit branchName arg or the
  fallback path. Differentiate the error message based on the source
  of the suggested branch.
- bootstrap.createPathToMergeOrchestrator: replace `as never` with a
  typed cast through Parameters<typeof createPathToMergeOrchestrator>[0]
  so any future tightening of PathToMergeDeps surfaces as a type error.
  Also drop a gratuitous `as never` on a call whose target accepts
  unknown.

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>

* Runtime refactor desktop and CLI sync support (#279)

* Implement remote runtime packaging and remove OpenClaw

Add remote/local runtime orchestration, packaged runtime resources, standalone runtime release assets, runtime action routing, and remove legacy OpenClaw surfaces.

* Add runtime daemon docs and CLI/runtime features

Rework documentation and CLI to center on the per-machine ADE runtime daemon: extensive README and apps/ade-cli/README.md updates describe daemon/socket modes, new dev and packaging scripts, and the `ade runtime` / `ade desktop` command surface. Implement operational changes in the CLI/tests to support runtime/socket routing (tests updated to assert new plan kinds and to read ADE_RUNTIME_SOCKET_PATH), add runtime-related helper files (reactDevtools stub) and desktop runtime artifacts/scripts. Add @linear/sdk to ade-cli dependencies (package.json + lockfile updated). Minor housekeeping: remove openclawContextPolicy from .ade/cto/identity.yaml and add /apps/desktop/release-alpha to .gitignore.

* Polish runtime-refactor surface and consolidate runtime tests

Combines /finalize cleanups (lane UI, ade-cli rpc/tui touch-ups, runtime
docs) with /automate test-suite hygiene: merge remoteBootstrap upload
flow back into remoteBootstrap.test.ts and fold ade-cli sync host
discovery tests into syncHostService.test.ts to remove forbidden
{service}.{minor}.test.ts fragmentation.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Use materialize runtime resources with host env

Replace the previous apps/ade-cli build step with an apps/desktop npm task that runs materialize:runtime-resources and set ADE_RUNTIME_RESOURCES_ALLOW_HOST_ONLY=1 in the env. Keeps dryRun behavior and runtime artifact assertions, and cleans build intermediates as before. Also add .claude/scheduled_tasks.lock (scheduler lock file).

* Add Tailscale discovery and default SSH identity

Add Tailscale peer discovery and merge results with mDNS discovery, including parsing of `tailscale status --json` and a discoverTailscalePeers helper that calls the Tailscale CLI. Update discovery to run Bonjour browsing and Tailscale discovery in parallel and add tests for Tailscale peer-to-SSH conversion. Change registry path resolution to use resolveMachineAdeLayout (and add a test that registry files are stored under the active ADE_HOME). Improve SSH transport to pick the first readable OpenSSH default identity when no explicit key is set, allow injecting homeDir for testing, and add a test for default identity selection. Update UI labels to surface Tailscale targets. Modify package-channel script to read desktop version, clean host runtime artifacts, propagate a composed env (setting ADE_CLI_VERSION), and ensure host runtime resources are rebuilt with the proper environment.

* Handle scope dispose, SSH retries, and UI tweaks

Add disposal propagation and cache cleanup for project-scoped runtimes, plus tests: multiProjectRpcServer now registers a scope onDispose listener to drop cached handlers and event subscriptions when a ProjectScope is disposed; ProjectScopeRegistry exposes onDispose listeners and invokes provided onDisposeProject callback and registered listeners when a scope is disposed. Cleanup of the listener occurs on handler disposal. Tests updated/added to cover cache eviction on scope disposal and project-scope disposal callbacks.

Improve SSH transport resiliency and username handling: introduce username candidates and config candidates, prefer explicit SSH config user but fall back to local user and an "admin" retry, and retry connection attempts across username candidates while handling authentication failures. Refactor connectSsh to try multiple configs and add helpers (uniqueUsernames, isSshAuthenticationFailure), plus unit tests for username/config candidate behavior.

Remote targets UI/UX improvements: RemoteTargetForm now supports targetId in prefill and customizable busy/submit labels. RemoteTargetList prepares and applies prefill for editing saved targets, sets formprefill when selecting a target or discovered machine, removes replaced targets when saving edits, improves connection label hints (more granular default hints), and updates copy for discovered machines. Related tests/files updated accordingly.

* Refactor CLI tests and add auto-register check

Massively refactors apps/ade-cli/src/cli.test.ts to standardize multi-line arrays/objects and improve readability of assertions, JSON quoting and formatting. Adds a new test to assert shouldAutoRegisterProjectForPlan behavior for machine-scoped registry commands and introduces apps/ade-cli/src/services/projects/projectRegistry.test.ts. Also includes supporting changes across desktop and runtime code (new remoteConnectionService, tests/adjustments to resolveTailscaleCliPath, runtimeBridge, remoteConnectionPool, renderer components and IPC types) to align with test updates and tighten behavior. These changes improve test clarity and add coverage for project auto-registration logic.

* ship: prepare lane for review

* ship: iteration 1 address cursor review

* ship: iteration 2 fix runtime release workflow

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* Port ade code TUI branch onto runtime refactor (#280)

Port the ade-windows-and-cli-2 TUI, slash-command, sync, and docs changes onto ade-windows-and-cli after the runtime refactor. Includes review fixes from Cursor and Greptile.

* Fix static runtime dependency packaging

* Fix remote runtime native deps test fixture

* Harden project root restoration

* Address runtime release review findings

* Fix runtime service manager review findings

* Fix standalone daemon spawn fallback

* Scope Windows runtime task to current user

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Cursor Agent <cursoragent@cursor.com>
Co-authored-by: Arul Sharma <arul28@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
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