From bb7827ba664b3ba73e04812b289c5008b48a01d3 Mon Sep 17 00:00:00 2001 From: Arul Sharma <31745423+arul28@users.noreply.github.com> Date: Sat, 29 Aug 2026 20:02:48 -0400 Subject: [PATCH 1/2] feat(chat,cli): auto-resume after usage limits, ade triage, attachment overhaul Three features plus dev-loop hardening: - Chats arm a durable, cancellable auto-resume when a provider usage limit reports a reset time (Claude, Codex); capped at two consecutive arms, cancelled by user activity, visible on the recovery card and in Chat info. - ade triage builds a redacted context + maintained playbook and hands a broken install to the user's own agent CLI; --agent mode prints the handoff for an already-running agent. - Attachments: 50MB any-file staging with a path-copy leg (local), a ticketed HTTP upload leg (remote, hello_ok attachmentUploadV1), chip UI in the composer, and a universal preview modal reusing the Files viewers. - AGENTS.md surface checklist + hazards + PR house style; quality rule 11 surface sweep; receipts-not-sleeps test doctrine; ship-lane PR template. Co-Authored-By: Claude Fable 5 --- .agents/skills/quality/SKILL.md | 3 +- .../quality/references/ade-review-rules.md | 27 + .agents/skills/test/SKILL.md | 1 + .gitignore | 6 + AGENTS.md | 40 +- CLAUDE.md | 35 +- apps/ade-cli/README.md | 41 + apps/ade-cli/src/bootstrap.ts | 5 + apps/ade-cli/src/cli.test.ts | 11 + apps/ade-cli/src/cli.ts | 103 +++ apps/ade-cli/src/commands/reportIssue.ts | 12 + apps/ade-cli/src/commands/triage.test.ts | 872 ++++++++++++++++++ apps/ade-cli/src/commands/triage.ts | 277 ++++++ apps/ade-cli/src/commands/triageContext.ts | 287 ++++++ apps/ade-cli/src/commands/triageErrors.ts | 18 + apps/ade-cli/src/commands/triageLaunch.ts | 238 +++++ apps/ade-cli/src/commands/triagePlaybook.ts | 304 ++++++ apps/ade-cli/src/services/imageAttachment.ts | 40 +- .../personalChats/personalChatScope.ts | 5 +- .../sync/attachmentUploadService.test.ts | 221 +++++ .../services/sync/attachmentUploadService.ts | 369 ++++++++ .../src/services/sync/sharedSyncListener.ts | 22 + .../src/services/sync/syncHostService.ts | 64 ++ .../sync/syncRemoteCommandService.test.ts | 104 ++- .../services/sync/syncRemoteCommandService.ts | 48 +- .../src/tuiClient/__tests__/adeApi.test.ts | 29 + apps/ade-cli/src/tuiClient/adeApi.ts | 18 +- apps/desktop/package.json | 4 + apps/desktop/resources/ade-cli-help.txt | 72 +- apps/desktop/scripts/regen-ade-cli-help.cjs | 1 + .../scripts/validate-mac-artifacts.mjs | 6 + .../scripts/validate-win-artifacts.mjs | 6 + apps/desktop/src/main/main.ts | 5 + .../main/services/adeActions/registry.test.ts | 101 ++ .../src/main/services/adeActions/registry.ts | 82 +- .../analytics/agentTurnProductAnalytics.ts | 23 + .../analytics/productAnalyticsPolicy.ts | 10 + .../analytics/productAnalyticsService.test.ts | 23 + .../services/chat/agentChatService.test.ts | 610 ++++++++++++ .../main/services/chat/agentChatService.ts | 143 ++- .../services/chat/attachmentInlineGuard.ts | 45 + .../chat/buildClaudeV2Message.test.ts | 38 + .../services/chat/buildClaudeV2Message.ts | 11 + .../chat/chatAutoResumeCoordinator.test.ts | 179 ++++ .../chat/chatAutoResumeCoordinator.ts | 489 ++++++++++ .../chat/chatScheduledWorkScheduler.ts | 12 + .../services/chat/heicAttachmentConverter.ts | 10 +- .../services/chat/workerAttachmentImages.ts | 12 +- .../src/main/services/ipc/ipcTimeouts.ts | 7 + .../src/main/services/ipc/registerIpc.ts | 84 +- .../src/main/services/ipc/runtimeBridge.ts | 43 + .../attachmentUploadClient.test.ts | 75 ++ .../remoteRuntime/attachmentUploadClient.ts | 135 +++ .../attachmentUploadRoute.test.ts | 80 ++ .../remoteRuntime/attachmentUploadRoute.ts | 54 ++ .../remoteRuntime/remoteConnectionPool.ts | 29 + .../remoteConnectionService.test.ts | 176 +++- .../remoteRuntime/remoteConnectionService.ts | 78 ++ .../storage/storageInsightsService.ts | 3 +- apps/desktop/src/preload/global.d.ts | 13 +- apps/desktop/src/preload/preload.ts | 63 +- apps/desktop/src/renderer/browserMock.ts | 9 + .../chat/AgentChatComposer.test.tsx | 15 +- .../components/chat/AgentChatComposer.tsx | 189 ++-- .../components/chat/AgentChatMessageList.tsx | 10 +- .../components/chat/AgentChatPane.test.tsx | 293 ++++++ .../components/chat/AgentChatPane.tsx | 93 +- .../chat/ChatAttachmentPreviewModal.tsx | 234 +++++ .../chat/ChatAttachmentTray.test.tsx | 141 ++- .../components/chat/ChatAttachmentTray.tsx | 311 ++++--- .../chat/ProviderFailureRecoveryCard.tsx | 86 +- .../chat/UserMessageIssueContext.tsx | 8 + .../chat/attachmentViewerTarget.test.ts | 99 ++ .../components/chat/attachmentViewerTarget.ts | 71 ++ .../chat/chatAttachmentStaging.test.ts | 145 +++ .../components/chat/chatAttachmentStaging.ts | 169 ++++ .../renderer/webclient/adapter/agentChat.ts | 13 + .../src/shared/chatAttachmentLimits.ts | 71 ++ .../shared/chatAttachmentStagingFs.test.ts | 221 +++++ .../src/shared/chatAttachmentStagingFs.ts | 163 ++++ .../desktop/src/shared/chatAutoResume.test.ts | 135 +++ apps/desktop/src/shared/chatAutoResume.ts | 156 ++++ apps/desktop/src/shared/ipc.ts | 3 + apps/desktop/src/shared/types/chat.ts | 39 + apps/desktop/src/shared/types/sync.ts | 15 + .../Views/Work/WorkChatAttachmentTray.swift | 4 + apps/ios/ADETests/ADETests.swift | 58 ++ docs/ARCHITECTURE.md | 20 +- docs/features/chat/README.md | 59 +- docs/features/chat/composer-and-ui.md | 58 +- docs/features/storage-and-recovery/README.md | 53 ++ docs/features/sync-and-multi-device/README.md | 106 ++- docs/logging.md | 37 + docs/playbooks/ship-lane.md | 10 + docs/triage/PLAYBOOK.md | 327 +++++++ reference/cli.mdx | 2 + reference/troubleshooting.mdx | 2 + 97 files changed, 9015 insertions(+), 332 deletions(-) create mode 100644 apps/ade-cli/src/commands/triage.test.ts create mode 100644 apps/ade-cli/src/commands/triage.ts create mode 100644 apps/ade-cli/src/commands/triageContext.ts create mode 100644 apps/ade-cli/src/commands/triageErrors.ts create mode 100644 apps/ade-cli/src/commands/triageLaunch.ts create mode 100644 apps/ade-cli/src/commands/triagePlaybook.ts create mode 100644 apps/ade-cli/src/services/sync/attachmentUploadService.test.ts create mode 100644 apps/ade-cli/src/services/sync/attachmentUploadService.ts create mode 100644 apps/desktop/src/main/services/chat/attachmentInlineGuard.ts create mode 100644 apps/desktop/src/main/services/chat/chatAutoResumeCoordinator.test.ts create mode 100644 apps/desktop/src/main/services/chat/chatAutoResumeCoordinator.ts create mode 100644 apps/desktop/src/main/services/remoteRuntime/attachmentUploadClient.test.ts create mode 100644 apps/desktop/src/main/services/remoteRuntime/attachmentUploadClient.ts create mode 100644 apps/desktop/src/main/services/remoteRuntime/attachmentUploadRoute.test.ts create mode 100644 apps/desktop/src/main/services/remoteRuntime/attachmentUploadRoute.ts create mode 100644 apps/desktop/src/renderer/components/chat/ChatAttachmentPreviewModal.tsx create mode 100644 apps/desktop/src/renderer/components/chat/attachmentViewerTarget.test.ts create mode 100644 apps/desktop/src/renderer/components/chat/attachmentViewerTarget.ts create mode 100644 apps/desktop/src/renderer/components/chat/chatAttachmentStaging.test.ts create mode 100644 apps/desktop/src/renderer/components/chat/chatAttachmentStaging.ts create mode 100644 apps/desktop/src/shared/chatAttachmentLimits.ts create mode 100644 apps/desktop/src/shared/chatAttachmentStagingFs.test.ts create mode 100644 apps/desktop/src/shared/chatAttachmentStagingFs.ts create mode 100644 apps/desktop/src/shared/chatAutoResume.test.ts create mode 100644 apps/desktop/src/shared/chatAutoResume.ts create mode 100644 docs/triage/PLAYBOOK.md diff --git a/.agents/skills/quality/SKILL.md b/.agents/skills/quality/SKILL.md index 0dcc5dc417..1710d127ee 100644 --- a/.agents/skills/quality/SKILL.md +++ b/.agents/skills/quality/SKILL.md @@ -197,7 +197,8 @@ Apply all three reference files: null services on bypassed IPC routes, daemon action-domain wiring, cr-sqlite CRR constraints, mobile-host compatibility, IPC/preload/shared/renderer contract drift, fast-tier loading, Node/test-env gotchas, worktree path - discipline. + discipline, and the surface coverage sweep (entry points, clients, + providers, reverse states, connection modes — rule 11). 3. **`references/windows-quirks.md`** — the Windows failure classes ADE has actually hit and the named helper that resolves each one. Windows parity is a default requirement (see **Windows parity rules** above), so this file diff --git a/.agents/skills/quality/references/ade-review-rules.md b/.agents/skills/quality/references/ade-review-rules.md index 696ac8a20b..1e082ba68c 100644 --- a/.agents/skills/quality/references/ade-review-rules.md +++ b/.agents/skills/quality/references/ade-review-rules.md @@ -156,6 +156,33 @@ these foundation-specific checks apply on top of the default review: reboot/restart, installed updates, and GUI artifacts as external proof. Code or mocked tests cannot close those gates. +## 11. Surface coverage sweep + +**Class:** A change that works on the one path the author tested and is missing +everywhere else — the single most common defect shape in multi-client, +multi-provider repos. This is the review-side enforcement of the AGENTS.md +"Hit every ADE surface" checklist. + +**Check:** For each behavior the diff adds or changes, walk the checklist and +demand an answer per entry — present, deliberately excluded (where is that +recorded?), or missed: + +- **Entry points:** desktop UI, `ade` CLI, `ade code` TUI, deeplinks, command + palette, keybindings. A behavior wired into one entry point but reachable + from others is a finding. +- **Clients:** desktop, hosted web, iOS, TUI. Logic duplicated into one client + instead of the shared service/type layer is a finding. +- **Providers:** Claude / Codex / Cursor / OpenCode / Droid. A provider-shaped + feature needs a per-adapter decision; silence for an adapter is a finding, + an explicit capability gate is not. +- **Reverse states:** every new way in needs the way out and the way to see it + (snooze/unsnooze, settle/unsettle, link/unlink). A one-way door is a finding. +- **Connection modes:** local runtime, remote runtime, relay, offline, + phone-newer-than-host. A feature that assumes local-only must say so. + +Raise one finding per missed surface, severity by reachability: a reachable +crash or dead control is High; a missing deliberate-exclusion record is Low. + --- ## Output diff --git a/.agents/skills/test/SKILL.md b/.agents/skills/test/SKILL.md index ae34a22880..d362479b55 100644 --- a/.agents/skills/test/SKILL.md +++ b/.agents/skills/test/SKILL.md @@ -265,6 +265,7 @@ Rules: - Mock only at process boundaries: file system, network, child processes, Electron APIs, IPC. - Tests must FAIL LOUDLY — assert preconditions explicitly. - Use `node` environment unless DOM is genuinely required. +- Wait on events, receipts, resolved promises, or fake timers — never on wall-clock sleeps. A test that needs a real `sleep` or a raised timeout to pass is testing a race, not a contract; fix the seam (expose the completion signal) instead of padding the wait. ### 3d. Run as you write diff --git a/.gitignore b/.gitignore index bee1ac68c5..06f1075c7d 100644 --- a/.gitignore +++ b/.gitignore @@ -104,3 +104,9 @@ apps/web/public/images/updatedImages/ # Windows CI runner — the checkout, not a test. Ignore them so a broad # `git add -A` cannot sweep them in when a test throws before its cleanup. *\\* + +# Agent work artifacts: research notes an agent writes at the repo root while +# investigating. They are scratch for one task, never product, and a broad +# `git add -A` would otherwise sweep them into a PR (AGENTS.md work-artifacts +# rule). Anything worth keeping goes under docs/. +T3CODE_RESEARCH_*.md diff --git a/AGENTS.md b/AGENTS.md index 9d6847b43b..e7dbacf566 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -21,6 +21,8 @@ Day-to-day work follows a five-stage loop, each stage an agent-folder skill unde - **/test** — test steward: prune/consolidate/add + docs/mobile/CLI/TUI parity + CI-mirrored shards; records a named regression test or exact alternate verification for every accepted correctness finding. - **/ship** — autonomous PR→merge loop (poll → fix → rebase → merge). Run baseline `/quality` and `/test` first; after any ship-loop mutation, ship reruns commit-bound `/quality` revalidation before pushing or merging. Wraps `docs/playbooks/ship-lane.md`. +**"Run the dev loop"** — when the user says this (or "dev loop") after work is implemented, it names one task, not a suggestion: invoke `/quality`, then `/test`, then `/ship`, in that order. Actually invoke each skill — approximating one (running tests is not `/test`; green CI is not `/quality`) does not count. Print each skill's summary, then continue to the next without stopping; stop early only for a genuine blocker (a failing gate or a decision only the user can make) and name it. + Utilities (run when relevant, not part of the core loop): **/audit** (targeted bug hunt), **/finalize** (optional pre-push local-CI gate), **/optimize** (perf profiling), **/release** (cut a release). ## Playbooks @@ -28,6 +30,19 @@ Utilities (run when relevant, not part of the core loop): **/audit** (targeted b - `docs/playbooks/ship-lane.md` — autonomous PR-to-merge driver (poll → fix → rebase → merge). Baseline `/quality` and `/test` run before it; mutation-specific commit-bound quality revalidation runs inside it. Any agent CLI can follow it directly; Claude Code invokes it via the `/ship` skill. - `docs/playbooks/windows-signed-release.md` — maintainer handoff for taking the gated Windows x64 build through signing, clean-host and installed-update proof, draft verification, publication, and website enablement without changing the macOS or iOS release paths. +## Hit every ADE surface + +The most common defect class in this repo is a change that works on the path you tested and is missing everywhere else. Before you call a change done (and again in `/quality`), walk this list and state which entries applied: + +- **Entry points.** A behavior reachable from the desktop UI is usually also reachable from the `ade` CLI, the `ade code` TUI, deeplinks, the command palette, and keybindings. Fixing one entry point is not fixing the feature. +- **Clients.** Desktop (Electron), hosted web, iOS, and the TUI attach to the same brain. Shared logic belongs in shared services and types, not re-implemented per client. +- **Providers.** Claude, Codex, Cursor, OpenCode, and Droid each have an adapter with different capabilities. A provider-shaped feature needs a decision per adapter, even when the decision is "not supported here" — record it in the capability gate, not by silence. +- **Contracts.** Anything crossing a boundary is typed once: main-process handler, `src/shared` types, preload exposure, renderer caller, daemon action domain, tests/mocks. Change the contract and all of them move together. +- **Reverse states.** If you add a way in, add the way out and the way to see it. Snooze needs unsnooze; settle needs unsettle; a link needs unlink. A one-way door is a bug. +- **Connection modes.** Local runtime, remote runtime, and relay behave differently. Multi-device and offline cases are real; the phone can be newer than the host. +- **Windows.** Parity is part of "done" for all new code, never a follow-up. +- **Docs.** User-visible behavior changes update the matching `docs/features/` doc in present tense. + ## Working norms - Preserve existing desktop app patterns before introducing new abstractions. @@ -37,6 +52,28 @@ Utilities (run when relevant, not part of the core loop): **/audit** (targeted b - For computer-use changes, treat policy enforcement and artifact ownership as hard requirements, not prompt guidance. - `ade search "" --text` searches everything in ADE (chats, terminal scrollback, PRs, commits, branches, lanes, files, Linear) instead of grepping `.ade/` internals; see the ade-search skill. +## Ways to hurt yourself + +These are the operational hazards of developing ADE from inside ADE. Each one has caused real damage. + +1. **Killing by pattern.** Do not `pkill -f`, `pgrep | kill`, or kill a PID you found by matching a name or path. Your own agent process carries this worktree's path in its argv, `pgrep -f xcodebuild` also matches xcodebuildmcp and its wrapper shell, and this machine runs the real ADE brain plus other dev runtimes. Kill only a PID you captured at spawn time, after confirming its cwd is your worktree. +2. **Writing to live state.** The project root's `.ade/` (database, secrets, artifacts) and the installed brain are the developer's real, in-use ADE instance. Read from them for realistic data; never point a dev server at them, never open them read-write, never "clean them up". Isolated dev state belongs under your worktree or a temp directory. +3. **Editing outside the lane worktree.** Every edit targets `.ade/worktrees//...`, never the project-root checkout. Search tools may print root-checkout paths — translate them before editing, or the change lands on the wrong branch. +4. **Restarting shared runtimes casually.** `ensureRuntime`-style commands can restart a brain another session is using. Check what is running before starting or restarting sockets, brains, or dev servers. + +## Work artifacts + +- Keep implementation plans, research notes, and agent scratch files out of the repository. They are inputs to the work, not project documentation. The merged PR is the implementation record. +- Docs describe the present tense. When behavior changes, update the matching `docs/features/` doc in the same branch. A task-tracking list in a feature doc must be kept current by the branch that changes the feature, or deleted — a stale checklist misleads every later agent. +- Track future work in Linear (see the ade-linear skill), not in committed TODO files. + +## Pull requests + +- Conventional commit titles in plain language: `fix(desktop): new chats no longer spike CPU`. +- Body house style, in order: **Problem** (a sentence or two), **Cause** (when known), **Change and boundary** (what moved, what deliberately did not), **Verification** (the exact focused tests/typechecks run and their counts). End with the model and harness that did the work. +- UI changes need before/after images. Motion or timing needs a short video. Upload evidence to GitHub; never commit screenshots or PR-only assets to the repo. +- One concern per PR. If the description says "also", consider splitting it. + ## Validation - Desktop checks: @@ -48,8 +85,9 @@ Utilities (run when relevant, not part of the core loop): **/audit** (targeted b - `npm --prefix apps/ade-cli run typecheck` - `npm --prefix apps/ade-cli run test` - `npm --prefix apps/ade-cli run build` -- Run the smallest relevant subset first when iterating, then finish with the broader checks that cover the touched surfaces. +- **Smallest proof first.** Run the narrowest check that proves the change: the touched test files, a scoped typecheck, one shard. Do not run full local suites by default — CI owns the full matrix, and `/finalize` is the opt-in local full gate before a push. - Run full desktop tests with the root `npm run test:desktop:sharded` command; use single-file or single-shard Vitest commands for iteration. +- Tests wait on events, receipts, and promises — never on wall-clock sleeps. A test that needs a `sleep` or a raised timeout to pass is wrong; fix the seam instead. - Installing deps: use `npm run install:apps` from the repo root, or `cd apps/ && npm install`. Never `npm --prefix apps/ install`. `--prefix` only redirects where npm writes `node_modules`; the package npm treats as "the one being installed" is still the one in the *current working directory*. From the repo root that is the root package `ade`, so npm installs the repo into the sub-app: it writes `"ade": "file:../.."` into the app's `package.json` and `package-lock.json` and leaves an `apps//node_modules/ade` symlink back to the root. Revert that churn if you hit it. `npm --prefix apps/ run