Commit Graph

1645 Commits

Author SHA1 Message Date
VenkataSakethDakuri 35012bd96e
feat: enrich PR observation context (#2492) 2026-07-08 14:02:15 +05:30
Deepak Modi 60ed6610be
fix(installer): point Windows NSIS shortcut at the real binary (#2414) (#2467)
electron-builder derives the Windows exe name -- and thus the Start menu
shortcut's TargetPath and IconLocation -- from win.executableName, falling
back to productName when it is unset. The NSIS maker only forwarded
productName ("Agent Orchestrator"), so electron-builder generated a shortcut
targeting "Agent Orchestrator.exe" while Forge's packager actually produced
"agent-orchestrator.exe". The shortcut pointed at a file that does not exist:
clicking it silently did nothing, and its icon fell back to a generic glyph.

Forward win.executableName ("agent-orchestrator") so the shortcut targets the
real binary, and hoist the name into a single EXECUTABLE_NAME constant shared
by the packager and the NSIS/deb makers so they cannot drift apart again.

Verified on Windows 11 by building the installer and silent-installing it: the
Start menu shortcut now targets
%LOCALAPPDATA%\Programs\agent-orchestrator\agent-orchestrator.exe with
IconLocation set to the same exe, and the app launches.
2026-07-08 13:14:36 +05:30
NIKHIL ACHALE 09768f29b9
Refactor Kimi and Qwen agent adapters for improved prompt delivery an… (#2497)
* Refactor Kimi and Qwen agent adapters for improved prompt delivery and session management

- Updated Kimi adapter to launch interactive sessions and handle prompt delivery after startup, avoiding non-interactive `-p` mode.
- Introduced `GetPromptDeliveryStrategy` method in Kimi to specify prompt delivery strategy.
- Modified Qwen adapter to utilize remote-input bridge for worker sessions, ensuring tasks are submitted into the interactive TUI after startup.
- Enhanced session manager to support new prompt delivery strategies, including handling prompts after session start.
- Added tests for prompt delivery behavior in both Kimi and Qwen adapters, ensuring correct command generation and session state management.
- Updated LaunchConfig to include DataDir for better session management.

* fix(qwen): initialize command slice with capacity for improved performance

* fix: harden qwen spawn cleanup
2026-07-08 01:45:31 +05:30
Pulkit Saraf eb6820b866
Revert "feat(session): switch a session's agent mid-flight (#2412)" (#2502)
This reverts commit a8f14090d6.

Co-authored-by: NIKHIL ACHALE <96230495+nikhilachale@users.noreply.github.com>
2026-07-08 00:52:05 +05:30
Laxman a54003e777
Track AO version in PostHog telemetry (#2482)
* Track AO version in PostHog telemetry

* chore: format with prettier [skip ci]

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-07 22:39:12 +05:30
Akshit joshi afa547632c
fix(cli): wrong exit code on too many args for review submit and preview (#2457) 2026-07-07 22:33:10 +05:30
neversettle 7a87caae79
feat: combine workspace project stack (#2460)
* feat: materialize workspace project sessions

* fix: clear workspace project PR CI failures

* fix: finalize workspace lifecycle row handling

* feat: add workspace session prompt context

* fix: preallocate workspace prompt repo list

* test: use os paths for workspace project records

* chore: format spawn orchestrator helper

* feat: add workspace project lifecycle teardown

* refactor: reuse workspace lifecycle for child repos

* feat: observe workspace project SCM repos

* fix: require workspace child origin remotes

* fix: keep workspace teardown minimal

* fix: prune stale workspace worktree registrations

* fix: restore legacy saved worktree markers

* fix: retain restored workspace project inventory

* fix: address workspace lifecycle review gaps

* chore: resync workspace scm PR

* feat: add workspace import UI flow

* chore: format with prettier [skip ci]

* fix: refresh frontend npm lockfile

* fix: address workspace import review feedback

* fix: harden workspace import edge cases

* chore: format sidebar import flow

* fix: harden workspace lifecycle cleanup

* fix: satisfy workspace lifecycle lint

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-07 22:25:50 +05:30
Deepak Modi 6d53e1155c
[codex] Guard latest desktop release (#2463)
* ci: guard latest desktop release

* fix(ci): self-heal a hijacked releases/latest pointer (#2462)

The guard previously only detected a hijacked latest pointer and failed the
run, still requiring a maintainer with delete rights to remove the junk
release by hand.

Add a remediation step that, on scheduled/manual runs, deletes a release
carrying the unambiguous hijack signature -- published, non-prerelease, a
non-semver tag, and zero electron-updater feed assets (latest.yml /
latest-mac.yml / latest-linux.yml) -- along with its tag, so GitHub
re-points latest to the newest real stable release. A real stable release
always has a semver tag and the feed assets, so this can never match one; an
in-progress real release keeps its semver tag, so it is excluded too, and the
step never runs on `release` events to avoid racing an asset upload.

This lets merging the PR resolve #2462 via the Actions token with no manual
admin action, while the verify step stays as the tripwire for anything
outside the auto-remediable signature. Bumps the job permission from
contents:read to contents:write for the delete.

* Revert "fix(ci): self-heal a hijacked releases/latest pointer (#2462)"

This reverts commit 185bc563a9.
2026-07-07 21:34:07 +05:30
VenkataSakethDakuri 3423dde505
Fix PR reaction nudge control flow (#2458)
* fix: send all actionable PR nudges

* Test commit

* fix: format PR reaction lifecycle code

* Test commit

* fix: format lifecycle reactions file

* Test commit

* fix: reduce PR reaction comment
2026-07-07 21:17:25 +05:30
NIKHIL ACHALE bc74028414
feat(pi): update Pi agent to support interactive sessions and adjust command arguments (#2480) 2026-07-07 20:37:44 +05:30
Harshit Singh Bhandari 863853e3ac
docs: remove docs/superpowers plans and specs (#2466)
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-07 00:16:12 +05:30
Dhruv Sharma fdd9c4357b
docs: fix readme agent links (#2461) 2026-07-06 23:18:09 +05:30
Pulkit Saraf a8f14090d6
feat(session): switch a session's agent mid-flight (#2412)
* feat(session): switch a session's agent mid-flight

Add the ability to change a session's agent (harness) without losing the
worktree. Previously a session's harness was fixed at spawn and could never
change; mixing agents on one task (e.g. codex to test, claude-code to write,
a cheaper model for cost) was impossible.

A switch keeps the same git worktree (all code + uncommitted work preserved)
and launches the new agent fresh — there is no native resume, since a
different harness cannot read the outgoing agent's session. An optional model
override rides the same path.

Two cases are handled:
- Live session: swap in place. The old agent is torn down only AFTER the new
  launch command validates, so a bad/unknown harness never disrupts the
  running session. A BeginSwitch/EndSwitch guard on the lifecycle manager makes
  the reaper ignore the brief runtime gap so it is not mistaken for a crash.
- Terminated session (e.g. the agent exited): relaunch-as. The worktree is
  restored and the new agent launched fresh under it — the way to bring a
  finished task back under a different agent (plain restore keeps the harness).

lifecycle.MarkSwitched atomically changes the persisted harness, points at the
new runtime handle, and clears the harness-specific AgentSessionID (which
MarkSpawned's merge cannot), resetting activity/first-signal so the new agent
re-proves its hook pipeline.

Surfaces:
- Backend: sessionmanager.SwitchHarness + lifecycle guard/MarkSwitched.
- API: POST /sessions/{id}/switch {harness, model?} (400/404/409 mapped);
  OpenAPI spec + frontend schema.ts regenerated.
- CLI: `ao session switch <id> --harness <agent> [--model ...]`.
- UI: the session inspector's Overview "Agent" row is now a dropdown that
  switches the agent in place (or relaunches a terminated one); merged sessions
  stay read-only.

Tests cover: live swap clears AgentSessionID, unknown harness leaves the agent
running, terminated relaunch-as, create-failure terminates cleanly, the reaper
guard suppresses termination during a switch, and MarkSwitched semantics.

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

* chore: format with prettier [skip ci]

* fix(session): address review — atomic switch guard + terminated resumability

P1: the switch-in-progress guard was a check-then-act (IsSwitching + later
BeginSwitch) and the terminated path never claimed it, so two concurrent
switches could both proceed and race two teardown/relaunch cycles over one
worktree. Replace with an atomic lifecycle.TryBeginSwitch (single-critical-
section compare-and-set) claimed once at the top of SwitchHarness for both the
live and terminated paths, released via defer.

P2: relaunchTerminatedWithHarness always fresh-launched with meta.Prompt,
bypassing restoreArgv's guard. Since the new harness cannot native-resume the
old agent's session, a terminated worker with no saved prompt would blank-
relaunch — which Restore deliberately refuses. Reject the same promptless-
worker case with ErrNotResumable (orchestrators stay promptless by design).

Tests: reject concurrent switch, terminated promptless worker rejected;
lifecycle TryBeginSwitch compare-and-set.

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

* chore: format with prettier [skip ci]

* fix(session): persist restored worktree on switch + resume previously-used agents

Two fixes on the agent-switch path.

Medium (review): terminated relaunch-as restored the worktree to ws.Path but
MarkSwitched only updated the runtime handle, leaving the old
Metadata.WorkspacePath/Branch. A changed session prefix or managed root could
restore to a different path while the stored session still pointed at the old
one, breaking later terminal/workspace/cleanup ops. MarkSwitched now takes full
SessionMetadata and persists WorkspacePath/Branch from the launch.

Bug: switching to a harness that had already run the session relaunched it
fresh, colliding with the agent's own prior native session — Claude Code pins a
deterministic --session-id, so a fresh relaunch failed with "Session ID <uuid>
is already in use". Sessions now track the set of harnesses they've launched
(SessionMetadata.LaunchedHarnesses); a previously-used harness RESUMES (via the
adapter's restore command) while a new one launches fresh. The promptless-worker
guard now applies only to fresh launches (a resume needs no saved prompt).

Tests: MarkSwitched persists workspace path/branch + launched set; resume for a
previously-used harness; fresh launch (and set update) for a new harness.

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

* fix(session): clear lingering runtime on terminated switch + gate dropdown to authed agents

A terminated agent's tmux session can outlive the agent process (the keep-alive
shell keeps it open), so its deterministic session name stays taken. The
terminated relaunch-as path skipped Destroy (it assumed no live runtime) and
went straight to Create, which failed with "duplicate session <id>" (surfaced
as a 500). It now tears down any leftover runtime handle before Create — Destroy
is idempotent, so an already-gone session is a no-op. The live path already did
this. Test: terminated relaunch with a lingering handle destroys it before Create.

UI: the Agent-row switch dropdown now lists only agents whose local auth probe
passed (the catalog's authorized set, same source the spawn dialogs use) instead
of every known harness, so users don't pick an agent that just fails at launch.
Empty/loading states render a disabled hint.

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

* fix(session): persist launched-harnesses set so switch resume actually triggers

The previous commit tracked LaunchedHarnesses on SessionMetadata to drive the
resume-vs-fresh switch decision, but the SQLite store maps metadata to explicit
columns and had no column for it — so it was silently dropped on write and read
back empty. The resume branch never fired, and switching back to a
previously-used deterministic-id agent (Claude Code) still fresh-launched and
collided ("Session ID <uuid> is already in use").

Add a durable launched_harnesses column (migration 0022), thread it through the
InsertSession/UpdateSession/Select queries (sqlc regenerated), and serialise the
harness set as a comma-separated string in the store. The set now round-trips,
so a previously-used harness resumes instead of colliding, surviving daemon
restarts (the agent's on-disk session does too).

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

* fix(session): don't resume with a foreign session id; reject merged at service layer

Two correctness gaps from review.

1. The resume path keyed only on LaunchedHarnesses but still handed restoreArgv
   the single meta.AgentSessionID — which MarkSwitched clears on each switch and
   which may hold *another* harness's id (durable state tracks harness names, not
   per-harness native ids). For adapters whose restore needs their own captured
   id (Codex/OpenCode/Goose/Copilot), that meant resuming against a wrong/empty
   id. Clear AgentSessionID on the resume path so restoreArgv resumes ONLY
   adapters that deterministically derive their session id (e.g. Claude Code);
   the rest cleanly fall through to a fresh launch, which never collides for them.

2. "merged" is a derived read-model status (from PR facts), so the internal
   manager can't enforce the merged lock — only the inspector UI did, leaving
   direct API/CLI callers able to switch a merged session. Service.SwitchHarness
   now derives the session status and rejects StatusMerged (409 SESSION_MERGED)
   before delegating.

Tests: resume does not leak a foreign session id (fresh-launches instead);
merged session is rejected at the service layer without reaching the manager.

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

* fix(session): update prepareWorkspace calls for new signature + gofmt store

Merge with main changed prepareWorkspace to take systemPrompt + agentConfig;
update both switch call sites (live swap and terminated relaunch) to pass them,
restoring the build. Run gofmt on session_store.go so the added
LaunchedHarnesses struct field is realigned and the gofmt gate passes.

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-06 22:54:17 +05:30
Harshit Singh Bhandari b92427362d
release: desktop-release runbook + fix the Prettier CI treadmill (#2394)
* docs(release): rewrite desktop-release.md as a full stable-release runbook

Written from the v0.10.2 cut. Documents the tag-only stamp commit, the
desktop-v* trigger tag, the release environment approval gate (with the
current approver list and how to query it), release-notes generation,
and post-release verification. Replaces the stale pre-signing checklist:
secrets are configured and the workflow now covers all platforms.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* docs(release): clarify that the approval gate, not the tag push, controls who can cut a release

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci(nightly): format frontend-nightly.yml so the check-only Prettier gate passes on every PR

The important-flag input (#2378) merged with single-quoted YAML that
Prettier rewrites, and since the Prettier workflow is check-only and
PR-triggered (#2356), every open PR inherits the failure.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* ci(prettier): run on pull_request and check only changed files

The push-only trigger skipped fork PRs entirely (e.g. #2378, which
merged the unformatted nightly workflow with no format check run), and
the whole-repo check made every open PR go red for files it never
touched once one bad file landed on main. Trigger on pull_request so
every PR is checked regardless of origin, and diff against the merge
base so a PR is only ever red for its own files.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 22:19:34 +05:30
Dhruv Sharma 3b56a8cb6f
feat(frontend): replace empty board shells with first-run onboarding states (#2432)
* feat(frontend): replace empty board shells with first-run onboarding states

First launch dropped users into four empty kanban columns with no
orientation (onboarding audit finding #1, high severity). The global
board now shows a centered welcome when no projects exist: what the app
does, three steps to a first merge, a column-dot legend that pre-teaches
the board vocabulary, and an Add-project CTA driving the same folder
picker -> agent sheet flow as the sidebar +. A project board with no
sessions shows a smaller "No sessions yet" invitation with the header's
Orchestrator / New task actions.

Also fixes a silent failure this surfaced: SessionsBoard.openOrchestrator
swallowed spawn rejections (try/finally without catch), so a daemon 409
(e.g. orchestrator branch checked out in another worktree) left the
button apparently dead. The error now renders in the empty state and
beside the header actions.

CreateProjectFlow is extracted verbatim from Sidebar.tsx so both entry
points share one implementation.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* style: format merged main files

* fix(frontend): preserve project startup spawn errors

* fix(frontend): address onboarding copy review + hide Board header on welcome

Per review on #2432: welcome body now names the kanban board explicitly,
step copy tightened to the reviewer's wording, the project empty state
says "No worker sessions yet" (an orchestrator session may already
exist), and the "Board" subhead is hidden on the first-launch welcome
since it described a board that isn't rendered there.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-06 21:58:51 +05:30
Laxman 2083bc200c
feat(telemetry): instrument renderer failure and CTA events (#2407)
Add PostHog instrumentation for app failures and user CTAs:
- daemon_failure (machine-readable code on DaemonStatus, IPC-forwarded)
- api_error central interceptor (categorized, IDs stripped)
- terminal_attach_failed (pane error + open timeout)
- CTA triads: task_create, session_kill, settings_save,
  orchestrator_spawn (board/restore_dialog), notification open/read

All events sanitized: project_id hashed, enum-only codes, raw error
messages never sent.

Co-authored-by: Pritom14 <pritommazumdar1995@gmail.com>
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-07-06 18:42:08 +05:30
NIKHIL ACHALE 0b45b676bd
fix(amp): update launch command to ignore unsupported system prompt flags (#2446) 2026-07-06 15:02:59 +05:30
NIKHIL ACHALE a7d7455bff
fix: improve prompt delivery strategy handling and update launch command logic (#2450) 2026-07-06 15:02:27 +05:30
Khushi Diwan aae38fd5cd
New README (#2419)
* docs: refresh README

* docs: refine README layout and add actual agent logos

* docs: fix image quality and url in twitter journey section

* chore: format spawn orchestrator helper

* docs: align README tweet screenshots

* fix
2026-07-06 13:26:36 +05:30
NIKHIL ACHALE d51ddd6130
feat: enhance Kiro agent integration with custom AO agent prompts (#2444)
* feat: enhance Kiro agent integration with system prompts and agent configuration

* fix(kiro): clear stale model from hooks when configuration is removed
2026-07-06 02:58:08 +05:30
Apoorv Singh 71fc914afa
fix(desktop): wheel-scroll opencode transcripts and surface native Windows notifications (#2422) 2026-07-06 01:56:14 +05:30
Pritom Mazumdar 0f2295c0c0
feat(telemetry): instrument renderer failure and CTA events (#2360) 2026-07-05 21:42:54 +05:30
Mukesh R 860fa5a242
fix(sidebar): open New Project tooltip rightward when collapsed (#2431)
Fixes #2430
2026-07-05 19:05:47 +05:30
neversettle 21294e6481
fix: consolidate PR summary status details (#2406)
* fix: consolidate pr summary status details

* chore: format pr summary changes

* chore: format rebased frontend files

* chore: format generated route tree

* fix: count pr summary overflow by rendered links

* fix: remove duplicate pr summary action copy

* fix: preserve pr summary hidden link totals

* fix: keep board pr footer lifecycle-only
2026-07-05 18:50:42 +05:30
PRADEEP SAHU 608333bd54
fix(ui): deduplicate agent catalog error messages in CreateProjectAgentSheet (#2428) 2026-07-05 18:45:43 +05:30
neversettle cbaffd2cb4
fix: simplify kanban pr footer (#2374) 2026-07-05 18:40:45 +05:30
Apoorv Singh 6cc7cc3e4e
fix(browser): remove excess padding around the inspector Browser tab (#2423) 2026-07-05 17:48:15 +05:30
NIKHIL ACHALE 821cda64a8
feat(cli): context-aware agent spawn with agent catalog and auth preflight (#2411)
* feat(cli): add agent command for listing and refreshing agent catalog

- Implemented `ao agent ls` command to list supported agents and their installation/auth readiness.
- Added `--refresh` flag to refresh local install/auth probes before listing agents.
- Introduced JSON output option with `--json` for raw agent catalog response.
- Updated tests to cover new agent command functionality, including cached catalog usage and refresh behavior.
- Enhanced error handling and output formatting for better user experience.

* docs: add CLI Guide link to README for direct usage instructions

* docs: clarify direct CLI usage

* fix: tighten spawn agent preflight

* feat(cli): implement agent readiness probe and update API specifications
2026-07-04 21:23:03 +05:30
Harshit Singh Bhandari 2c08597ee6
refactor(adapters): cut ~3,100 LOC of redundancy in the agent adapter layer (#2349) (#2355)
* refactor(adapters): add shared helpers for adapter dedup (#2349)

Introduce the shared building blocks the per-adapter cleanup will use:
- ports.NormalizePermissionMode (finding 3)
- hookutil.FileExists (finding 10)
- binaryutil.ResolveBinary + BinarySpec (finding 2)
- activitystate.StandardDeriveActivityState (finding 4)
- agentbase.Base embed + StandardSessionInfo (findings 6-9)

No adapters wired up yet; behavior unchanged.

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

* refactor(goose): convert to shared adapter helpers (reference) (#2349)

Reference conversion proving the shared packages against real tests:
- hooks.go collapses onto hooksjson.Manager (finding 1)
- ResolveGooseBinary via binaryutil.BinarySpec (finding 2)
- gooseMode uses ports.NormalizePermissionMode (finding 3)
- activity.go deleted; dispatch points at activitystate (findings 4, 5)
- SessionInfo via agentbase.StandardSessionInfo; Base embed drops the
  GetConfigSpec/GetPromptDeliveryStrategy no-ops (findings 6-8)
- fileExists/atomicWriteFile copies removed (findings 5, 10)

Also adds hooksjson package + activitystate test. goose: 327->~90 LOC.

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

* refactor(adapters): dedup remaining 22 agent adapters onto shared helpers (#2349)

Applies the shared helpers across every remaining adapter:
- hooksjson.Manager for the matcher-group cohort (claudecode, qwen, droid)
- binaryutil.BinarySpec for 19 binary resolvers (aider/cursor/opencode/codex
  keep their special resolvers; all now use hookutil.FileExists)
- ports.NormalizePermissionMode replaces 15 private copies
- agentbase.Base embed drops the GetConfigSpec/GetPromptDeliveryStrategy no-ops
  (and GetAgentHooks/GetRestoreCommand/SessionInfo no-ops on hookless adapters)
- agentbase.StandardSessionInfo replaces the per-adapter metadata readers
- activitystate.StandardDeriveActivityState via dispatch for the 8 name-only
  derivers; their activity.go files removed (claudecode/codex/droid/agy/opencode
  keep payload-parsing derivers)
- 4 private atomicWriteFile copies missing fsync now use hookutil.AtomicWriteFile
- 23 private fileExists copies removed

Full backend build + vet + test suite green (1647 tests).

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

* chore: format with prettier [skip ci]

* fix(binaryutil): preserve per-adapter Windows candidate order (#2349)

Review feedback: the shared resolver hardcoded Windows candidate order as
APPDATA then LOCALAPPDATA, which flipped Kiro's lookup so the npm shim
(%APPDATA%\npm\kiro-cli.*) was probed before the native install
(%LOCALAPPDATA%\Programs\kiro\kiro-cli.exe). A fixed order can't preserve every
adapter's original order (goose/vibe want APPDATA first, kiro wants LOCALAPPDATA
first), so BinarySpec now takes an ordered WinPaths []WinPath list where each
entry names its base (WinAppData/WinLocalAppData/WinHome). Every adapter's list
reproduces its pre-refactor order exactly; kiro's native path is restored to
first.

go build / vet / test all green (1647 tests).

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

* test(adapters): drop unused resolvedBinary writes flagged by govet (#2349)

Embedding agentbase.Base (value receiver) lets govet's unusedwrite analyzer
prove that setting resolvedBinary in tests that only call Base-promoted methods
(GetConfigSpec/GetPromptDeliveryStrategy/SessionInfo/cancellation) is a dead
write. Drop the field from those 23 constructions; GetLaunchCommand/GetRestore
tests that actually read it keep it.

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

* style: gofmt manager_test.go struct alignment (#2349)

Inherited via the merge of main: a SessionRecord literal aligned its Metadata
field across a multi-key line, which gofmt/goimports rejects. One-line reformat
to unblock CI.

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

* docs(adapters): fix stale resolver fallback comments (#2349)

Review nit: 6 Resolve*Binary functions now delegate to binaryutil.ResolveBinary,
which returns a wrapped ports.ErrAgentBinaryNotFound rather than the bare binary
name. Update their doc comments (kiro, vibe, amp, agy, crush, cline) to match.

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

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-04 20:49:15 +05:30
Khushi Diwan 5d7ad6137d
Fix restored terminal reconnect (#2313)
* fix: reconnect restored terminals

- Reopen terminal mux after restored sessions become live
- Cover restore with unchanged terminal handles

* fix: limit restored terminal reconnects

* chore: format with prettier [skip ci]

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-04 18:29:04 +05:30
NIKHIL ACHALE cc75a519ab
fix: replace orchestrators through safe canonical branch handoff (#2338)
* fix: replace orchestrators through canonical handoff

* fix(tests): correct logic in TestRetireForReplacementCapturesAndReleasesWorkspace

* fix: enhance tests and add project config handling in service and workspace components

* fix: update project summary to include orchestrator agent and adjust related tests

* fix: block orchestrator replacement on runtime teardown failure

* fix: enhance orchestrator handling in ProjectSettingsForm and SessionsBoard components

* fix: rename parameter for clarity in projectConfigPtr function
2026-07-04 11:35:03 +05:30
NIKHIL ACHALE a639e2025c
feat: add agent catalog/auth API and safer orchestrator switching (#2309)
* feat: add agent catalog API and integrate with project settings

- Implemented AgentsController to handle /agents endpoint, returning a list of supported and installed agents.
- Created agent inventory service to manage agent data and detect installed agents.
- Updated ProjectSettingsForm to fetch and display agent information, including installed and supported agents.
- Enhanced error handling for agent detection and orchestrator restarts.
- Added tests for agent catalog and service to ensure correct functionality and error handling.

* Implement agent authorization status checks and update frontend to reflect changes

- Added `AuthStatus` method to various agent plugins to check authorization status using CLI probes.
- Introduced `authprobe` package to handle common CLI command checks for agent authorization.
- Updated backend tests to include scenarios for authorized and unauthorized agents.
- Modified frontend API schema to include `authorized` counts and `authStatus` for agents.
- Enhanced `ProjectSettingsForm` to display authorized agents and their statuses, including prompts for login when necessary.
- Adjusted agent selection logic to prioritize authorized agents and provide feedback for unauthorized or uninstalled agents.

* fix: simplify orchestrator replacement retry flow

* refactor:  cache agent catalog ,remove AgentCounts schema and related references from API and frontend

* fix: clarify orchestrator replacement recovery state

* feat: enhance project settings and agent management

- Updated NewTaskDialog tests to increase timeout for async operations.
- Modified ProjectSettingsForm tests to improve agent handling and validation messages.
- Refactored ProjectSettingsForm component to streamline agent selection and validation logic.
- Introduced new agent service to manage agent inventory and authentication status.
- Improved Sidebar tests to ensure proper agent options are loaded and handled.
- Enhanced SessionsBoard component by removing unused imports and optimizing state management.
- Fixed Select component styling for better consistency in UI.
- Added error handling for AO daemon readiness in ShellLayout.

* chore: format with prettier [skip ci]

* feat: add AuthStatus method documentation and improve error handling in session manager

* feat: enhance agent authentication and configuration management

- Implement local authentication status checks for PI, Qwen, and Vibe agents.
- Introduce JSON-based authentication status retrieval for PI agents.
- Add environment variable checks for Qwen agents and improve settings file parsing.
- Enhance Vibe agent authentication with support for environment variables and session logs.
- Update agent service to handle asynchronous probing for installed and authorized agents.
- Modify session manager to support prompt delivery strategies based on agent capabilities.
- Improve frontend agent selection UI with loading states and error handling.
- Add tests for new authentication logic and session management features.

* chore: format with prettier [skip ci]

* test: fix session manager fake after rebase

* feat: enhance agent authentication status checks

- Implement local authentication status checks for the Devin, Droid, Kiro, and other agents.
- Add support for reading credentials from specific configuration files and environment variables.
- Introduce new tests for various agents to ensure proper authentication status reporting.
- Refactor existing authentication logic to improve clarity and maintainability.
- Remove deprecated agent setup warnings from the SessionsBoard component in the frontend.

* feat: clear environment variables in auth status tests for Aider and OpenCode

* feat: enhance error handling in authentication status functions and update component props

* feat: integrate fallback agents in RequiredAgentField and streamline props handling

* fix: refactor Sidebar test imports and parameters for clarity

* refactor: remove orchestrator retirement logic and related tests

- Deleted the RetireOrchestrator function and its associated error handling.
- Removed tests related to orchestrator retirement and state management.
- Simplified ProjectSettingsForm by eliminating orchestrator restart logic and related UI elements.
- Updated API client mocks to reflect the removal of orchestrator-related functionality.

* feat: enhance agent management and error handling

- Added agent refresh functionality in ProjectSettingsForm with UI updates for agent availability.
- Implemented `refreshAgents` API call to fetch the latest agent catalog.
- Updated agent selection logic to disable unavailable agents and show appropriate error messages.
- Enhanced error handling in `apiErrorMessage` to include daemon error codes alongside messages.
- Created new test cases for agent availability and error handling in Sidebar component.
- Introduced `ResolveBinary` method for multiple agent adapters to standardize binary resolution.
- Added new agent adapter files for various agents (e.g., Aider, Claude Code, etc.) to support binary resolution.

* chore: format with prettier [skip ci]

* fix: satisfy backend lint checks

* refactor: clean up authentication logic and improve error handling across agents

* chore: format with prettier [skip ci]

* feat(authprobe): enhance status classification for authentication outputs and add tests for explicit false/true keys
chore(docs): update README to remove outdated agent adapter contract references
fix(components): improve agent selection logic to handle unknown auth status and update related tests

* chore: format with prettier [skip ci]

* refactor: remove shell environment authentication logic and update related tests

* feat(tests): integrate QueryClient for agent data in CreateProjectAgentSheet tests

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-04 10:59:34 +05:30
Anirudh Sharma d18ea87f57
feat(tracker): GitHub issue intake (backend + dashboard) (#2325)
* feat(tracker): GitHub issue intake observer

Adds an opt-in daemon poll loop that spawns one worker session per
eligible open GitHub issue, keyed by the canonical "github:<native>"
id so restarts cannot double-spawn. Eligibility requires an explicit
label or assignee rule to avoid draining an entire backlog.

Provider dispatch goes through a TrackerResolver interface
(SingleTrackerResolver for now) so Linear/Jira can be added later as
new adapters plus a resolver-map entry, without touching the poll,
eligibility, or backoff logic. Reuses the existing rate-limit-aware
GitHub tracker adapter and backs off per-project on any poll failure
(including rate limits) instead of retrying in a tight loop.

Closes #2324.

* feat(frontend): surface GitHub tracker intake in project settings

Adds a Tracker Intake card to project settings (enable, repository
override, labels, assignee) with inline validation requiring at
least one label or assignee before intake can be saved. Session
cards and the inspector show the canonical "github:<native>" issue
id when a session was spawned by intake.

Regenerated frontend/src/api/schema.ts against the backend's
TrackerIntakeConfig. The provider is currently fixed to "github";
adding a picker for future providers is additive once the backend
enum grows.

Closes #2324.

* fix(tracker): start the intake observer unconditionally at boot

startTrackerIntake scanned projects once at daemon startup and skipped
starting the observer loop entirely when none had intake enabled yet.
Poll() already re-reads every project's config on each tick and skips
disabled projects there, so the boot-time gate only broke the common
case: enabling intake on a project after the daemon is already running
silently never got picked up until the next restart, with no error or
log line to explain why.

Always start the loop; the adapter (and its token resolution) stays
lazy regardless, so there's no added cost when intake is unused.

Found while manually verifying issue intake end-to-end against a live
dev daemon: enabled intake via the settings UI, saved successfully,
but no session ever spawned for a matching labeled issue.

* fix(frontend): show auto-detected repo link, hide labels input for now

The Electron app only registers git projects today, so the daemon
always has a usable git origin to derive owner/repo from when
trackerIntake.repo is unset (trackerRepo() in observer.go, already
covered by every Poll-level test in observer_test.go). Replace the
manual Repository input with a read-only link derived client-side
from the project's own git origin, purely for display — the daemon's
own derivation at poll time is unaffected either way.

Comment out the Labels input; Assignee is the only intake eligibility
rule editable from this form for now. form.intakeLabels/intakeRepo
stay wired into buildIntake so a value set via the CLI round-trips
on a UI save instead of being silently cleared.

* chore: format with prettier [skip ci]

* feat(frontend): offer issue intake at project creation

Add the GitHub tracker intake controls to the create-project sheet so a
project can opt into issue-driven worker spawning at creation time, not
only later via Settings.

- Extract the shared IntakeFields component (enable toggle, assignee
  input, validation, credential hint) plus buildIntake/intakeNeedsRule/
  deriveGitHubRepo helpers into IntakeFields.tsx, and consume it from
  ProjectSettingsForm so the two surfaces can't drift.
- CreateProjectAgentSheet renders IntakeFields (no repo-preview row,
  since the git origin isn't known there; the daemon derives the repo).
  The selection now carries an optional trackerIntake payload, gated by
  the same "requires a label or assignee" rule the backend enforces.
- Thread trackerIntake through Sidebar's onCreateProject into the
  POST /api/v1/projects config. No backend change: the endpoint already
  accepts a full ProjectConfig and the intake observer picks up newly
  enabled projects on its next tick.

Verified in the web preview: enabling reveals the assignee field and
gates submit until a rule is set; submit builds the intake payload.

* chore: format with prettier [skip ci]

* feat(frontend): simplify intake controls in the create-project sheet

Reduce the create sheet's tracker-intake block to the essentials: the
enable toggle plus an info icon whose hover tooltip explains what
enabling does, then the assignee input. Drop the descriptive intro
paragraph, the inline "requires a label or assignee" guard text, and
the credential hint — the sheet stays minimal and submit gating already
communicates the missing rule via the disabled button.

- IntakeFields gains a `compact` prop: hides the prose, folds the
  explanation into an Info tooltip, and drops the trailing help text.
  The tooltip is wrapped in its own TooltipProvider so the component is
  self-contained regardless of ancestor. The verbose settings card is
  unchanged (renders without `compact`).
- Assignee placeholder reworded to "type username or * for any".

Verified in the web preview: the info tooltip surfaces the one-line
description on hover, the assignee placeholder is updated, and no other
copy remains in the create sheet.

* perf(tracker): cache GitHub issue lists with ETag conditional requests

The intake observer polls Tracker.List for the same repo+filter every
tick, and each poll did an uncached GET + full JSON decode even when
nothing changed. Add HTTP conditional requests so unchanged polls are
cheap and don't consume the primary rate limit.

- Tracker holds a per-request-path cache of {etag, mapped issues},
  guarded by a mutex. The key space is bounded by intake-enabled
  repo/filter pairs, so no eviction is needed.
- List sends If-None-Match with the cached ETag (verbatim, preserving
  weak validators). On 304 it returns the cached issues without
  re-decoding (GitHub 304s don't count against the primary rate limit);
  a rotated ETag on the 304 is recorded. On 200 it stores the new
  {etag, issues}, or drops a stale entry if the response omits an ETag.
  A 304 without a prior validator falls back to an unconditional refetch.
- Extract the HTTP round-trip into roundTrip(); do() delegates to it so
  Get and Preflight keep byte-for-byte identical behavior. roundTrip
  owns If-None-Match, ETag capture, and 304 handling before
  classifyError.

Tests cover revalidation returning cached issues on 304, ETag rotation
on change, separate cache keys per filter, and no caching when the
response carries no ETag.

* feat(frontend): trim tracker intake copy in project settings

Reduce the settings Tracker Intake card to a one-line description
("Auto-spawn worker sessions from matching tracker issues.") and drop
the trailing credential/daemon-restart hint. The compact create sheet is
unaffected (it already renders neither).

* feat(tracker): scope v1 intake to assignee-only

Per PR review, labels were a persisted/API/CLI eligibility rule while the
UI only ever exposed assignee — surface beyond the intended v1 scope.
Remove labels from intake end-to-end; assignee becomes the required and
only eligibility rule.

- domain: drop TrackerIntakeConfig.Labels; Validate() now requires a
  non-empty assignee when enabled (was "labels or assignee").
- observer: pass only State+Assignee into ListFilter; drop the label
  match loop in issueMatchesConfig.
- CLI: remove --tracker-label and its plumbing.
- Regenerate openapi.yaml + schema.ts (labels gone from the schema).
- frontend: drop labels from IntakeForm/buildIntake/intakeNeedsRule and
  the settings form state; validation copy now "requires an assignee".
  Remove the label round-trip test; keep assignee coverage.

The generic domain.ListFilter.Labels adapter capability is retained;
only intake stops using it.

* fix(tracker): paginate GitHub issue listing with page-aware ETag cache

Per PR review, single-page listing is a correctness bug for intake, not
just a bounded v1 tradeoff: with more than a page of eligible open
issues, AO re-sees the same first page every poll, the persisted
issue_id dedupe skips the already-spawned first-page issues, and later
pages are never fetched or spawned.

- List now requests per_page=100 and follows the GitHub Link header
  rel="next" until no next link remains, accumulating issues across all
  pages. A maxListPages guard fails loud on a pathological Link cycle.
- The ETag cache is page-aware: each entry stores {etag, issues,
  nextPath} keyed by the per-page request path, so a 304 Not Modified
  still continues to the cached next page. roundTrip now surfaces the
  parsed next path alongside the ETag; do() delegates unchanged so
  Get/Preflight keep identical behavior.
- ListFilter.Limit becomes an optional total-result cap (page size is
  fixed at the provider max).

Tests cover multi-page accumulation, all-304 revalidation continuing the
cached chain, page-count shrink orphaning a stale entry, and Link
header parsing.

* style(session_manager): gofmt manager_test.go to unblock CI

The session-restart test carried a struct-literal alignment that gofmt
(and golangci-lint's goimports) reject, failing the build-test and lint
jobs. Whitespace-only reformat; no test logic changes.

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: whoisasx <adil.business4064@gmail.com>
2026-07-04 02:52:14 +05:30
Adil Shaikh 4557146681
fix: render raw activity state in inspector (#2278)
* fix: render raw session activity in inspector

* fix: hide unknown activity state in inspector
2026-07-04 00:29:32 +05:30
Harshit Singh Bhandari 8cadea5b16
fix(ci): gofmt manager_test.go to unbreak main (#2386)
manager_test.go landed from #2350 with a gofmt violation (extra spaces
aligning a struct field), turning main red: build-test's `gofmt -l .`
and lint's goimports both flag it. #2350's merge push never ran the Go
workflow, so it went unnoticed until the next push surfaced it.

Pure `gofmt -w` output, one whitespace line, no behavior change.
2026-07-03 22:42:27 +05:30
Harshit Singh Bhandari c9cff5f22e
feat(sidebar): nightly channel badge on the wordmark (#2379)
* feat(sidebar): purple nightly badge on the wordmark

Add a small purple pill labeled "nightly" next to the "Agent Orchestrator"
wordmark in the sidebar header. The badge:
- is derived from the running app version string (contains "-nightly."),
  not the update-channel setting, so it reflects the actual binary identity
- is hidden in the collapsed icon rail (group-data-[collapsible=icon]:hidden)
- uses a new --purple CSS token added to both dark (#a78bfa) and light
  (#7c3aed) palette blocks in styles.css, styled via color-mix following
  the existing reviewer-status idiom
- is shrink-0 so it does not crowd the flex-1 truncate wordmark span

Stable builds show no badge. Dev builds ("0.0.0-preview") show no badge.

Part of AgentWrapper/agent-orchestrator#2377.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* chore: format with prettier [skip ci]

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-03 22:29:07 +05:30
Harshit Singh Bhandari 6f09a1fc78
fix(frontend): show session display name in terminal toolbar header (#2382)
* fix(frontend): show session display name in terminal toolbar header

The terminal toolbar showed the raw session id. Show the display name
(session.title, same field the sidebar renders) instead, and
'Orchestrator' for orchestrator sessions.

Fixes #2380

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* test(frontend): cover terminal toolbar session label

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 22:23:57 +05:30
Harshit Singh Bhandari f92ff1111a
feat(release): add important flag to nightly feed manifests (#2378)
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-03 22:23:03 +05:30
Vaibhaav Tiwari 52d8c6051a
docs: add contributing guide (#2385)
Co-authored-by: Vaibhaav <user@example.com>
2026-07-03 22:17:02 +05:30
Vaibhaav Tiwari 365c99f705
docs: add first-timer README overview (#2384)
Co-authored-by: Vaibhaav <user@example.com>
2026-07-03 21:59:51 +05:30
Harshit Singh Bhandari a32d507eb8
feat(scm): detect cross-fork PRs by scanning all project remotes (#2368)
The SCM observer only polled a project's push origin for open PRs, so a
PR opened from the fork against an upstream base repo (the standard
fork -> upstream flow) was never discovered: GitHub lists a PR under its
base repo, not its head, so an origin-only scan can't see it. Sessions
that opened such PRs showed no PR on the dashboard.

Scan every GitHub remote in the project checkout (origin + upstreams /
mirrors) for open PRs, and attribute a PR to a session only when its
head branch lives in that session's push origin. This surfaces
cross-fork PRs while preserving the no-misattribution guarantee: a
stranger's fork PR has a head repo no session owns and is dropped.

Tracked cross-fork PRs are keyed for refresh by their own recorded repo
(the upstream base) so the GraphQL refetch targets the right repo.
2026-07-03 20:50:41 +05:30
Harshit Singh Bhandari 3aa8e044b2
test(session_manager): prove agent sessions survive daemon restart/upgrade (#2335) (#2350)
* test(session_manager): prove sessions survive daemon restart and re-adopt (#2335)

Add an end-to-end Reconcile() durability test covering the full mix of
session states a daemon restart/upgrade leaves behind: an alive
orchestrator and worker are adopted in place under their original ids
(no id increment, runtime never torn down), a worker whose runtime died
with the daemon is captured and relaunched under its original id, and a
truly-dead unmarked session is not resurrected.

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

* chore: format with prettier [skip ci]

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-03 19:59:27 +05:30
Harshit Singh Bhandari 57ba468fea
feat(skills): add using-ao skill, install it under the data dir, and wire it into session prompts (#2365)
* feat(prompt): point sessions at using-ao skill for CLI usage

Append a short standing-prompt pointer to skills/using-ao/SKILL.md so
orchestrator and worker sessions read the skill catalog before using the
ao CLI, instead of inlining the whole command surface.

* docs(skills): add using-ao skill cataloging the ao CLI

Full command catalog sourced verbatim from 'ao --help' recursively:
SKILL.md (top-level catalog), commands/*.md (one per command with every
subcommand, flag, and examples), and references.md (natural-language to
command table).

* feat(skills): install using-ao skill under the data dir on daemon boot

A repo-relative skills/ path only resolves when a worker's project is the
AO repo itself; the ao CLI is used in every session regardless of project.
Move the skill into the Go module, embed it, and clobber-install it into
<dataDir>/skills/using-ao at daemon boot (before any session spawns, so no
locking is needed). The embedded copy is the single source of truth: a new
daemon build always refreshes it, so there is no version marker to drift.

Flip the session-prompt pointer to the absolute installed path so it
resolves from any project's worktree.

* fix(skillassets): tighten install perms to satisfy gosec

golangci-lint gosec flagged G301 (dir perms) and G306 (file perms).
Use 0o750 for dirs and 0o600 for files, matching the repo convention
for daemon-owned single-user state.

* Update preview.md with dev server instructions

Added note about using the correct URL for the dev server.

---------

Co-authored-by: Vaibhaav Tiwari <155460282+Vaibhaav-Tiwari@users.noreply.github.com>
2026-07-03 18:11:15 +05:30
Dushyant Singh Hada 7e409d438b
fix: clear stale preview URL from SQLite and prevent stale white screen on preview clear (#2358)
* fix: remove auto-switch-to-summary effect, keep browser tab on clear

* fix: clear browser preview when session is terminated
2026-07-03 15:38:43 +05:30
VenkataSakethDakuri fadbdd26cd
Fix and enrich the orchestrator coordinator system prompt so it matches the current CLI and teaches harness selection + command discovery (#2361)
* Prompt changed for correct agent spawning

* Fix formatting issue
2026-07-03 01:36:14 +05:30
Harshit Singh Bhandari e56248759e
ci(prettier): make workflow check-only instead of auto-committing (#2356)
Convert the Prettier workflow from auto-formatting and pushing commits
back to the PR branch into a check-only job. It now runs
`prettier@3 --check .`, which annotates and fails on unformatted files
but never writes, commits, or pushes anything. Drops the auto-commit
step and narrows permissions to `contents: read`.

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-02 22:49:29 +05:30
Harshit Singh Bhandari 6186458df7
docs(bug-triage): retarget skill at the Go rewrite and upstream repo (#2339)
* docs(bug-triage): retarget skill at the Go rewrite and upstream repo

Rewrite the bug-triage skill for this repository: file issues/PRs on the
upstream AgentWrapper/agent-orchestrator, swap the Zellij runtime notes for
tmux (ConPTY on Windows), refresh the label list to match upstream, and drop
ReverbCode-specific naming. Port 3001, ~/.ao paths, and the CLI/daemon layout
are unchanged and were re-verified against backend/.

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

* chore: format with prettier [skip ci]

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-02 22:03:13 +05:30
Anirudh Sharma e74fb65a85
feat(review): support additional reviewer harnesses (#2306)
* feat(review): support more reviewer harnesses

* fix(review): preserve reviewer daemon context

* fix(review): allow printf-piped review commands in reviewer allowlists

The review prompt now pipes JSON into `gh api` and `ao review submit`
via `printf '%s' ... | cmd` (heredocs break in interactive PTY panes).
Widen the claude-code allowlist with `Bash(printf:*)` and the opencode
permission policy with `printf * | gh api *` / `printf * | ao review
submit *` so those piped commands pass each tool's allowlist. Cover
both with tests that model each tool's matching semantics.

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

* chore: format with prettier [skip ci]

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-07-02 19:25:18 +05:30
VenkataSakethDakuri c267420632
feat(projects): default worker and orchestrator agents to claude-code (#2321)
Pre-fill both role agents with claude-code in the create-project dialog and project settings instead of requiring a selection; the required-agent validation gate is removed. Users can still change either agent at creation or later in settings.
2026-07-01 21:56:00 +05:30
Laxman f74ebf379f
docs: add telemetry.md with accurate description of PostHog integration (#2308)
Replaces the inaccurate opt-in framing. Documents that telemetry is on
by default in the renderer, covers session recording, privacy redaction,
the persistent install ID, and how to override or disable via build-time
env vars.

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-01 14:15:45 +05:30