path to merge audit#260
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (29)
Disabled knowledge base sources:
📝 WalkthroughWalkthroughThis 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. ChangesPath-to-Merge Orchestration Integration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Suggested labels
🚥 Pre-merge checks | ✅ 3 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
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. |
There was a problem hiding this comment.
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
📒 Files selected for processing (22)
.gitignoreapps/ade-cli/src/bootstrap.tsapps/ade-cli/src/cli.test.tsapps/ade-cli/src/cli.tsapps/desktop/src/main/services/adeActions/registry.tsapps/desktop/src/main/services/prs/issueInventoryService.tsapps/desktop/src/main/services/prs/pathToMergeOrchestrator.test.tsapps/desktop/src/main/services/prs/pathToMergeOrchestrator.tsapps/desktop/src/main/services/prs/prIssueResolution.test.tsapps/desktop/src/main/services/state/kvDb.pipelineSettingsMigration.test.tsapps/desktop/src/main/services/state/kvDb.tsapps/desktop/src/renderer/components/prs/detail/PrDetailPane.issueResolver.test.tsxapps/desktop/src/renderer/components/prs/detail/PrDetailPane.tsxapps/desktop/src/renderer/components/prs/shared/PrConvergencePanel.test.tsxapps/desktop/src/renderer/components/prs/shared/PrConvergencePanel.tsxapps/desktop/src/renderer/components/prs/state/PrsContext.test.tsxapps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.test.tsapps/desktop/src/renderer/components/prs/tabs/QueueAutomateMergingModal.tsxapps/desktop/src/renderer/components/prs/tabs/queueAutomateMergingRuntime.tsapps/desktop/src/shared/types/prs.tsapps/ios/ADE/Resources/DatabaseBootstrap.sqlapps/ios/ADE/Services/Database.swift
| } | ||
| } | ||
|
|
||
| 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); |
There was a problem hiding this 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.
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.There was a problem hiding this comment.
Skipped: comment is from another GitHub bot.
3de9e4f to
9398fb5
Compare
9398fb5 to
c651bbd
Compare
* 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>
* 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>
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_mergeADE action (wired through desktop action registry and CLI planning), replacing the previous directpr_start_issue_resolutioninvocation 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
@copilotand, for large diffs,@greptile/@coderabbit). At-cap behavior is adjusted to be more CI-driven, pauses when an agent is awaiting user input, and limitsgh --adminmerges to branch-protection-style failures.Defaults shift toward automation:
PipelineSettings.autoMergeis nowtrueby default, DB schema defaults are updated accordingly (auto_merge,force_finalize_mode,at_cap_policy), and UI/queue flows are updated to handle “armedghauto-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
Improvements
Greptile Summary
Path to Merge is refactored into a dedicated
path_to_mergeADE 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), awaiting_for_commentsbot-check gate, and a newgithub_auto_merge_armedconverge state tracked by the queue modal. Default pipeline settings shift toautoMerge: true,forceFinalizeMode: \"conditional\", andatCapPolicy: \"ci_retry_once\"with a DB backfill migration.@copilot review(and optionally@greptile/@coderabbitfor large PRs) and waits up to 5 minutes for their CI checks to complete before dispatching the next fix agent. Deduplication uses a persistedlastBotPingHeadSha/lastBotPingAtpair that survives app restarts.--adminis now conditional onshouldAttemptAdminMergeForRestError, confining the admin rung to genuine branch-protection failures;ignoreReviewis exported but not yet wired to any call site.github_auto_merge_armedas a non-terminal wait state and promotespaused/convergedintoTERMINAL_FAILEDto 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
--adminrung is gated behindshouldAttemptAdminMergeForRestError, andignoreReviewis 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 owntry/catchand is idempotent viaptm_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
--admin-rung gating viashouldAttemptAdminMergeForRestError;ignoreReviewis exported but not passed by any caller.auto_merge,force_finalize_mode, andat_cap_policydefaults; addsptm_defaults_backfilled_versionidempotency guard; new convergence-state columns for bot-ping tracking.mergeWaitKind,lastBotPingHeadSha,lastBotPingAtto DB persistence; noisy-bot-comment filtering now marks previously stored bot comments as fixed; mixed tab/space indentation introduced in newly added block.isWaitingForGithubAutoMergeguard to keep polling when--autois armed; promotespaused/convergedtoTERMINAL_FAILEDfor correct queue-modal exit.canStartMergeOnlyPathescape hatch so at-cap PRs with all checks passing andautoMerge=truecan still start Path to Merge; button/tooltip states updated consistently.ConvergenceMergeWaitKindtype,mergeWaitKind/lastBotPingHeadSha/lastBotPingAtfields toConvergenceRuntimeState; updatesDEFAULT_PIPELINE_SETTINGSto new defaults.createPathToMergeOrchestratorandcreateLaneWorktreeLockService, 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 endComments Outside Diff (4)
apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts, line 606-610 (link)lastBotPingHeadShaandlastBotPingAtare hardcoded tonullhere, butpostReviewBotPingscallspersistInProcessStateto save them after posting. BecausemakeInProcessStateFromRuntimenever reads those persisted values back, every app restart resets the deduplication guard. The next iteration then seesinProc.lastBotPingHeadSha === null, considers the current head SHA as "new", and re-fires@copilot,@greptile, and@coderabbitpings 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
apps/desktop/src/main/services/prs/pathToMergeOrchestrator.ts, line 633-648 (link)The Copilot check has a 5-minute escape hatch via
REVIEW_BOT_WAIT_TIMEOUT_MS, but the Greptile/CodeRabbit branch only unblocks whencheck.status === "completed". If either check is stuck inqueuedorin_progressindefinitely (e.g., a hung runner, a bot outage),getPendingReviewBotswill keep returning them as pending and the orchestrator will spin inwaiting_for_commentsforever without surfacing an error or timeout to the user.Prompt To Fix With AI
.ade/logs/dev/desktop-dev-20260508-210242.log, line 1-10 (link)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.gitignoreto prevent this from recurring.Prompt To Fix With AI
apps/desktop/src/main/services/prs/pathToMergeOrchestrator.test.ts, line 266-279 (link)syncFromPrDatadoesn't include the newcommentsparameterThe production call at line 1299 of the orchestrator now passes four arguments (
prId, checks, reviewThreads, comments), but this test mock only declares three. Theas unknown ascast on theissueInventoryServiceobject hides the type mismatch, so the mock silently dropscomments. The new comment-based logic (Copilot response detection viahasCopilotResponse, etc.) is not exercised by tests that rely on this mock, reducing coverage of the new behavior.Prompt To Fix With AI
Prompt To Fix All With AI
Reviews (12): Last reviewed commit: "Keep review gates on at-cap PtM merges" | Re-trigger Greptile