fix(skills): adapt bug-triage skill to ReverbCode stack (#281)
* fix(skills): adapt bug-triage skill to ReverbCode stack The bug-triage skill was copied verbatim from the upstream TypeScript agent-orchestrator and never adapted to ReverbCode (Go + Electron). - Target repo: ComposioHQ/agent-orchestrator -> aoagents/ReverbCode - Stack translation: pm2/tmux/Node -> Go daemon on 127.0.0.1:3001 + Zellij runtime adapter; packages/*.ts paths -> verified backend/ Go paths; ao --version -> ao version; lsof :3000 -> :3001; SQLite at ~/.ao/data, handshake at ~/.ao/running.json - Add prominent CLI-footgun warning: bare 'ao' may resolve to a different AO install (old npm build on :3000); build /tmp/ao or use the bundled daemon and confirm 'ao status' shows port 3001 - Remove broken push_fix_to_github.py reference; replace 5f with a Go flow (branch + go build/test + gh pr create for trivial fixes; ao spawn worker for non-trivial) - Label guidance: check 'gh label list' first, only apply existing labels, state priority/confidence in the body otherwise - Add pitfall: verify the bug reproduces against ReverbCode (:3001) first Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * chore: format with prettier [skip ci] --------- Co-authored-by: itrytoohard <ayetrytoohard@gmail.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
This commit is contained in:
parent
ee044e4edb
commit
edf00de61b
|
|
@ -6,12 +6,54 @@ trigger: User reports a bug, or asks to triage/file an issue for a reported prob
|
|||
|
||||
# Bug Triage Skill
|
||||
|
||||
Triage bugs into well-structured GitHub issues on the correct upstream repo.
|
||||
Triage bugs into well-structured GitHub issues on the ReverbCode repo.
|
||||
|
||||
> **ReverbCode is Go + Electron.** The backend is a Go daemon (`backend/`)
|
||||
> exposing a loopback HTTP API on `127.0.0.1:3001`; the frontend is an Electron +
|
||||
> React supervisor (`frontend/`). There is **no** pm2/tmux/Node runtime here —
|
||||
> the daemon owns lifecycle and sessions run under the **Zellij** runtime
|
||||
> adapter. Triage against _this_ stack, not the old TypeScript agent-orchestrator.
|
||||
|
||||
## ⚠️ Which `ao` are you running?
|
||||
|
||||
**`ReverbCode` ships no `ao` on your PATH.** A bare `ao` very likely resolves to a
|
||||
**different** AO install — e.g. an old npm build at `~/.nvm/.../bin/ao` that talks
|
||||
to port **:3000**. Triaging with the wrong binary produces bugs that don't exist
|
||||
in ReverbCode (and miss ones that do).
|
||||
|
||||
Before any diagnostics:
|
||||
|
||||
```bash
|
||||
which -a ao # see every ao on PATH — expect surprises
|
||||
ao status 2>/dev/null # if this shows port 3000, it is NOT ReverbCode
|
||||
```
|
||||
|
||||
Use a ReverbCode binary explicitly:
|
||||
|
||||
```bash
|
||||
# Option A — build from this repo (preferred during triage)
|
||||
cd backend && go build -o /tmp/ao ./cmd/ao
|
||||
/tmp/ao status # must report port: 3001
|
||||
|
||||
# Option B — the packaged app's bundled daemon
|
||||
"/Applications/Agent Orchestrator.app/Contents/Resources/daemon/ao" status
|
||||
```
|
||||
|
||||
**Confirm `ao status` reports `port: 3001` before trusting any output.** Throughout
|
||||
this skill, `ao` means _your verified ReverbCode binary_ (`/tmp/ao` or the bundled
|
||||
one), never a bare PATH lookup.
|
||||
|
||||
> Note: spawned sessions get a PATH pin so the _session's_ `ao` resolves to the
|
||||
> daemon's own executable (see `hookPATH` in
|
||||
> `backend/internal/session_manager/manager.go`). That pin only applies inside
|
||||
> sessions — your interactive shell is still on its own PATH, so pin it yourself.
|
||||
|
||||
## 1. Pre-flight
|
||||
|
||||
- **Pull latest code:** `git pull origin main`. Stale code = bad triage.
|
||||
- **Target repo:** Always file on the **upstream org** (`ComposioHQ/agent-orchestrator`), not forks.
|
||||
- **Target repo:** Always file on **`aoagents/ReverbCode`** (the product repo, not
|
||||
a fork). ReverbCode is the product, not a thin fork of upstream.
|
||||
- **Verify your binary:** confirm `ao status` shows port **3001** (see warning above).
|
||||
- **Record source:** chat URL, reporter name, attachments.
|
||||
|
||||
## 2. Gather Context
|
||||
|
|
@ -21,8 +63,8 @@ Triage bugs into well-structured GitHub issues on the correct upstream repo.
|
|||
| Source | How to gather |
|
||||
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **Discord/Slack thread** | Read full thread. Extract: reporter name, original description (the thread starter, not whoever tagged you), screenshots, follow-ups |
|
||||
| **GitHub issue** | `gh issue view <number> --repo <repo> --json body,comments` |
|
||||
| **Live observation** | Pull live state via observability tools |
|
||||
| **GitHub issue** | `gh issue view <number> --repo aoagents/ReverbCode --json body,comments` |
|
||||
| **Live observation** | Pull live state via the daemon: `ao status`, `ao session ls`, `ao session get <id>` |
|
||||
|
||||
### 2b. Minimum viable report gate
|
||||
|
||||
|
|
@ -30,7 +72,7 @@ Before tracing code, verify the report has enough substance:
|
|||
|
||||
**Required (ALL):** what happened, where (page/command/feature), when (after upgrade? first time?)
|
||||
|
||||
**Required (2 of 4):** OS/shell/runtime, AO version (`ao --version`), reproducibility (consistent vs intermittent), reproduction steps
|
||||
**Required (2 of 4):** OS/shell, AO version (`ao version`), reproducibility (consistent vs intermittent), reproduction steps
|
||||
|
||||
If insufficient, ask:
|
||||
|
||||
|
|
@ -38,39 +80,54 @@ If insufficient, ask:
|
|||
|
||||
### 2c. Local diagnostics (if bug is on same machine)
|
||||
|
||||
Gather everything yourself before asking the reporter:
|
||||
Gather everything yourself before asking the reporter. Use your **verified**
|
||||
ReverbCode binary (`/tmp/ao` here) for every `ao` call:
|
||||
|
||||
```bash
|
||||
# Environment
|
||||
ao --version && node --version && echo $SHELL && uname -a
|
||||
cat agent-orchestrator.yaml
|
||||
cat ~/.agent-orchestrator/running.json
|
||||
/tmp/ao version && go version && echo $SHELL && uname -a
|
||||
which -a ao # confirm no rogue ao shadows the build
|
||||
cat ~/.ao/running.json # PID + port handshake (expect port 3001)
|
||||
|
||||
# Process health
|
||||
pm2 status
|
||||
tmux list-sessions
|
||||
lsof -i :3000
|
||||
# Daemon health
|
||||
/tmp/ao status # daemon up? port? health/ready probes
|
||||
/tmp/ao doctor # local health checks
|
||||
lsof -i :3001 # who's bound to the daemon port
|
||||
tail -n 100 ~/.ao/daemon.log # daemon log
|
||||
|
||||
# AO event log — structured timeline
|
||||
ao events list --limit 50 # recent events
|
||||
ao events list --session ao-5 --limit 100 # filter by session
|
||||
ao events list --log-level error --since 1h # errors only
|
||||
ao events search "spawn failed" # full-text search
|
||||
ao events stats # counts by kind/source
|
||||
# Sessions & runtime
|
||||
/tmp/ao session ls # all sessions and their state
|
||||
/tmp/ao session get <id> # one session: spawn config, runtime, lifecycle
|
||||
zellij list-sessions # Zellij runtime sessions backing terminals
|
||||
|
||||
# Session state files
|
||||
cat ~/.agent-orchestrator/projects/*/sessions/*.json | python3 -m json.tool
|
||||
# Durable state (SQLite at ~/.ao/data)
|
||||
sqlite3 ~/.ao/data/ao.db '.tables' # inspect schema/rows if state looks wrong
|
||||
```
|
||||
|
||||
Event kinds: `session.spawned`, `session.spawn_failed`, `session.killed`, `lifecycle.transition`, `ci.failing`, `review.pending`, `runtime.probe_failed`, `agent.process_probe_failed`, `reaction.escalated`, `lifecycle.poll_failed`. Sources: `lifecycle`, `session-manager`, `api`, `runtime`, `agent`, `reaction`.
|
||||
The daemon owns lifecycle, sessions, storage, and the terminal mux; structured
|
||||
state lives in `~/.ao/data/ao.db` (WAL: `ao.db-wal`, `ao.db-shm`). The PID+port
|
||||
handshake is `~/.ao/running.json`.
|
||||
|
||||
**Try the reproduction steps.** Running the actual command is worth 100 lines of code tracing.
|
||||
**Try the reproduction steps.** Running the actual command against the daemon on
|
||||
:3001 is worth 100 lines of code tracing.
|
||||
|
||||
## 3. Investigate
|
||||
|
||||
### 3a. Trace the code path
|
||||
|
||||
**Always trace the actual code** — don't surface-level diagnose. [#1129](https://github.com/ComposioHQ/agent-orchestrator/issues/1129) looked like a simple `ao stop` issue but was actually a session lineage/cascade problem.
|
||||
**Always trace the actual code** — don't surface-level diagnose. A symptom that
|
||||
looks like a simple `ao stop` issue is often a lifecycle/session-manager problem
|
||||
one layer down. ReverbCode's layers:
|
||||
|
||||
- CLI (Cobra, thin client over daemon HTTP): `backend/internal/cli/`, entrypoint
|
||||
`backend/cmd/ao/main.go`
|
||||
- Daemon (loopback HTTP on :3001): `backend/internal/daemon/daemon.go`,
|
||||
controllers under `backend/internal/httpd/controllers/`
|
||||
- Sessions & lifecycle: `backend/internal/session_manager/manager.go`
|
||||
- Runtime adapter (Zellij): `backend/internal/adapters/runtime/`
|
||||
- Agent harness adapters: `backend/internal/adapters/agent/<harness>/`
|
||||
- Terminal mux: `backend/internal/terminal/`
|
||||
- Agent hooks: `backend/internal/cli/hooks.go`
|
||||
|
||||
```bash
|
||||
git fetch origin main && git log --oneline origin/main -5 # current HEAD
|
||||
|
|
@ -84,32 +141,34 @@ git log --oneline -S 'exact-string' -- <file>
|
|||
git show <sha> -- <file> | grep -B 5 -A 10 'pattern'
|
||||
```
|
||||
|
||||
Example: [#1391](https://github.com/ComposioHQ/agent-orchestrator/issues/1391) traced a mobile layout break to a `display: flex` → `display: grid` change.
|
||||
|
||||
**Research upstream dependencies** (xterm, node-pty, React, etc.) — check installed vs latest version, search their GitHub issues, check changelogs. Root cause is often upstream.
|
||||
**Research dependencies** (Zellij, the agent harness binary, Electron, React, the
|
||||
SQLite driver) — check installed vs latest version, search their issue trackers,
|
||||
check changelogs. Root cause is sometimes in a dependency, not ReverbCode.
|
||||
|
||||
### 3b. Cross-platform check
|
||||
|
||||
AO runs on **Windows, macOS, Linux** as first-class targets. If env info indicates Windows (or is unknown), check for these patterns:
|
||||
AO targets **macOS, Linux, and Windows**. If env info indicates Windows (or is
|
||||
unknown), check for these patterns:
|
||||
|
||||
- **Path separators** — hardcoded `/` or `\` breaks cross-platform
|
||||
- **Path separators** — hardcoded `/` or `\`; use `filepath.Join`, not string concat
|
||||
- **Shell syntax** — PowerShell lacks `&&`, `$VAR`, `$(cat ...)`, `/dev/null`, here-docs
|
||||
- **`process.platform === "win32"` inline** — must use `isWindows()` from `@aoagents/ao-core`
|
||||
- **`process.kill(-pid)`** — POSIX-only; use `killProcessTree()`
|
||||
- **Named pipes vs Unix sockets** — Windows uses `\\.\pipe\ao-pty-<id>`
|
||||
- **`localhost`** — Windows resolves to `::1` first, causing ~21s stalls on IPv4-only servers
|
||||
- **NTFS case-insensitivity** — use `pathsEqual()`, not `===`
|
||||
- **ConPTY orphans** — can trigger WER dialogs if pty-host not shut down cooperatively
|
||||
- **`.cmd` shim resolution** — needs `shell: true` for `PATHEXT` lookup
|
||||
- **`runtime.GOOS == "windows"` scattered inline** — centralize platform checks
|
||||
- **Process-tree kills** — POSIX process groups vs Windows job objects
|
||||
- **`localhost`** — Windows resolves to `::1` first; the daemon binds the explicit
|
||||
loopback host (see `config.LoopbackHost`) to avoid IPv4/IPv6 stalls
|
||||
- **Case-insensitive filesystems** — don't compare paths with raw `==`
|
||||
- **PATH / binary resolution** — `.exe`/`PATHEXT` lookup, the session PATH pin
|
||||
(`hookPATH` in `backend/internal/session_manager/manager.go`)
|
||||
|
||||
Key files: `packages/core/src/platform.ts`, `docs/CROSS_PLATFORM.md`, `packages/plugins/runtime-process/`, `packages/cli/src/lib/path-equality.ts`
|
||||
Key files: `backend/internal/config/config.go`, `backend/internal/session_manager/manager.go`,
|
||||
`backend/internal/adapters/runtime/`, `backend/internal/terminal/`.
|
||||
|
||||
### 3c. Stop-and-ask triggers
|
||||
|
||||
Stop and ask for more info if:
|
||||
|
||||
- **3 failed hypotheses** — traced 3 code paths, none explain it
|
||||
- **Root cause is upstream** — file with upstream reference, don't guess a local fix
|
||||
- **Root cause is a dependency** — file with the dependency reference, don't guess a local fix
|
||||
- **UI-only bug** and you can't screenshot — ask reporter to describe
|
||||
- **Can't reproduce** — ask for different config/sequence
|
||||
|
||||
|
|
@ -118,16 +177,16 @@ Stop and ask for more info if:
|
|||
Search with multiple strategies, always using `--state all` (closed bugs regress):
|
||||
|
||||
```bash
|
||||
gh issue list --repo <repo> --state all --search "<symptom>"
|
||||
gh issue list --repo <repo> --state all --search "<component-name>"
|
||||
gh issue list --repo <repo> --state all --search "<error-message>"
|
||||
gh pr list --repo <repo> --state all --search "<keywords>"
|
||||
gh issue list --repo aoagents/ReverbCode --state all --search "<symptom>"
|
||||
gh issue list --repo aoagents/ReverbCode --state all --search "<component-name>"
|
||||
gh issue list --repo aoagents/ReverbCode --state all --search "<error-message>"
|
||||
gh pr list --repo aoagents/ReverbCode --state all --search "<keywords>"
|
||||
```
|
||||
|
||||
### Duplicate found → comment on existing issue
|
||||
|
||||
```bash
|
||||
gh issue comment <number> --repo <repo> --body "$(cat <<'EOF'
|
||||
gh issue comment <number> --repo aoagents/ReverbCode --body "$(cat <<'EOF'
|
||||
## New Report
|
||||
**Reported by:** @<reporter> in [chat](<url>)
|
||||
**Date:** <YYYY-MM-DD> | **Checkout:** `<commit-hash>`
|
||||
|
|
@ -144,7 +203,8 @@ EOF
|
|||
|
||||
- [ ] Reporter attribution correct (original reporter, not who tagged you)
|
||||
- [ ] Commit hash recorded
|
||||
- [ ] AO version recorded
|
||||
- [ ] AO version recorded (`ao version`)
|
||||
- [ ] Reproduced against ReverbCode (:3001 / Go code path), not another AO install
|
||||
- [ ] Root cause confidence scored (see 5c)
|
||||
- [ ] Related issues cross-linked
|
||||
- [ ] Reproduction steps are concrete
|
||||
|
|
@ -152,28 +212,28 @@ EOF
|
|||
|
||||
### 5b. Upload screenshots
|
||||
|
||||
**⛔ NEVER use placeholder URLs.** Upload BEFORE creating the issue. ([#1151](https://github.com/ComposioHQ/agent-orchestrator/issues/1151) RCA on this pattern.)
|
||||
**⛔ NEVER use placeholder URLs.** Upload BEFORE creating the issue.
|
||||
|
||||
```bash
|
||||
SLUG="descriptive-slug"
|
||||
# Create asset branch
|
||||
gh api -X POST repos/<repo>/git/refs \
|
||||
gh api -X POST repos/aoagents/ReverbCode/git/refs \
|
||||
-f ref="refs/heads/issue-assets-${SLUG}" \
|
||||
-f sha=$(git rev-parse origin/main)
|
||||
|
||||
# Upload (portable base64)
|
||||
IMG_B64=$(base64 < /path/to/screenshot.png | tr -d '\n')
|
||||
gh api -X PUT "repos/<repo>/contents/.issue-assets/${SLUG}/name.png" \
|
||||
gh api -X PUT "repos/aoagents/ReverbCode/contents/.issue-assets/${SLUG}/name.png" \
|
||||
-f message="chore: upload screenshot" \
|
||||
-f content="$IMG_B64" \
|
||||
-f branch="issue-assets-${SLUG}"
|
||||
# Use: 
|
||||
# Use: 
|
||||
```
|
||||
|
||||
### 5c. Create the issue
|
||||
|
||||
```bash
|
||||
gh issue create --repo <repo> --title "<title>" --body "$(cat <<'EOF'
|
||||
gh issue create --repo aoagents/ReverbCode --title "<title>" --body "$(cat <<'EOF'
|
||||
## Bug
|
||||
<summary>
|
||||
|
||||
|
|
@ -197,28 +257,34 @@ EOF
|
|||
|
||||
### 5d. Label and prioritize
|
||||
|
||||
**Check which labels actually exist first**, then apply only those:
|
||||
|
||||
```bash
|
||||
gh issue edit <number> --repo <repo> --add-label "bug"
|
||||
gh label list --repo aoagents/ReverbCode # source of truth — apply only these
|
||||
gh issue edit <number> --repo aoagents/ReverbCode --add-label "bug"
|
||||
```
|
||||
|
||||
| Priority label | Criteria |
|
||||
The repo currently carries `bug`, `enhancement`, `priority: critical/high/medium/low`,
|
||||
lane labels (`daemon`, `frontend`, `storage`, `coding-agents`, `lcm-sm`, `scm`,
|
||||
`core`, `port`, `adapter`, `domain`), and workflow labels (`needs-triage`,
|
||||
`needs-review`, `blocked`). **Do not invent labels** — if a priority or confidence
|
||||
label you want doesn't exist, **state it in the issue body instead** (e.g.
|
||||
"**Priority:** high — core feature broken, no workaround" / "**Confidence:** medium").
|
||||
|
||||
| Priority | Criteria |
|
||||
| -------------------- | ----------------------------------- |
|
||||
| `priority: critical` | Data loss, security, system down |
|
||||
| `priority: high` | Core feature broken, no workaround |
|
||||
| `priority: medium` | Feature degraded, workaround exists |
|
||||
| `priority: low` | Cosmetic, edge case |
|
||||
|
||||
**Confidence scoring** (include in issue body):
|
||||
**Confidence scoring** (always state in the issue body):
|
||||
|
||||
| Level | Meaning | Extra labels |
|
||||
| ---------- | ----------------------------------------------------------- | --------------------- |
|
||||
| **High** | Traced exact code path, specific lines, mechanism explained | `bug` only |
|
||||
| **Medium** | Strong hypothesis but unconfirmed | `bug`, `to-explore` |
|
||||
| **Low** | Can't trace, multiple conflicting theories | `bug`, `to-reproduce` |
|
||||
|
||||
Example: [PR #1608](https://github.com/ComposioHQ/agent-orchestrator/pull/1608) was diagnosed High as xterm v6 issue — real cause was a `=` prefix on tmux `set-option`. Should have been Medium.
|
||||
|
||||
**All available labels:** `priority: critical/high/medium/low`, `bug`, `enhancement`, `good-first-issue`, `to-reproduce`, `to-explore`. No others (no `p0`, `p1`, etc.).
|
||||
| Level | Meaning |
|
||||
| ---------- | ----------------------------------------------------------- |
|
||||
| **High** | Traced exact code path, specific lines, mechanism explained |
|
||||
| **Medium** | Strong hypothesis but unconfirmed |
|
||||
| **Low** | Can't trace, multiple conflicting theories |
|
||||
|
||||
### 5e. Cross-link related issues
|
||||
|
||||
|
|
@ -226,37 +292,53 @@ Search by subsystem and add a `## Related` section to the issue body:
|
|||
|
||||
```
|
||||
## Related
|
||||
- [#1020](url) — stale session blocking ao start (same subsystem)
|
||||
- [#1035](url) — same race condition
|
||||
- [#20](url) — stale session blocking ao start (same subsystem)
|
||||
- [#35](url) — same race condition
|
||||
```
|
||||
|
||||
### 5f. Push a fix PR (always attempt)
|
||||
|
||||
- **Trivial fix:** Push immediately.
|
||||
- **Complex fix:** Note in issue, suggest spawning an agent.
|
||||
- **Unclear fix:** Don't push a guess. Document and flag.
|
||||
ReverbCode is a Go repo — fixes go through a local branch, build, and `gh pr create`.
|
||||
There is no remote-patch script.
|
||||
|
||||
```bash
|
||||
OLD_STRING='<old>' NEW_STRING='<new>' \
|
||||
python3 skills/bug-triage/scripts/push_fix_to_github.py \
|
||||
<owner/repo> fix/slug path/to/file.tsx \
|
||||
"fix(scope): commit msg" "fix(scope): PR title" \
|
||||
"Fixes #<n>
|
||||
- **Unclear fix:** Don't push a guess. Document and flag in the issue.
|
||||
- **Trivial, verifiable fix** (you can build and test it yourself):
|
||||
|
||||
## Summary
|
||||
<what changed>
|
||||
```bash
|
||||
git checkout -b fix/<slug> origin/main
|
||||
# make the edit
|
||||
cd backend && go build ./... && go test ./... # must pass before pushing
|
||||
git commit -am "fix(<scope>): <summary>
|
||||
|
||||
## Test
|
||||
<how to verify>"
|
||||
```
|
||||
Fixes #<n>"
|
||||
git push -u origin fix/<slug>
|
||||
gh pr create --repo aoagents/ReverbCode --fill \
|
||||
--title "fix(<scope>): <summary>" \
|
||||
--body "Fixes #<n>
|
||||
|
||||
The script reads from GitHub API, applies one replacement, pushes, opens PR — no local checkout needed. **Verify `OLD_STRING` matches GitHub first:** `gh api repos/<repo>/contents/<path>?ref=main -q '.content' | python3 -c "import base64,sys; sys.stdout.buffer.write(base64.b64decode(sys.stdin.read()))"`
|
||||
## Summary
|
||||
<what changed>
|
||||
|
||||
**Multiple edits to same file:** The push script does one replacement per run. For multiple changes, use a Python script to read from the branch (`gh api` + `base64.b64decode`), apply all replacements, then push via `gh api -X PUT` with the updated SHA.
|
||||
## Test
|
||||
cd backend && go build ./... && go test ./..."
|
||||
```
|
||||
|
||||
- **Non-trivial fix** (broad change, needs iteration, or you can't fully verify):
|
||||
spawn a ReverbCode worker session to do the work in its own worktree instead of
|
||||
pushing a guess:
|
||||
|
||||
```bash
|
||||
ao spawn --project reverbcode --prompt "Fix #<n>: <one-line problem statement>. \
|
||||
Root cause: <file:line + mechanism>. Suggested approach: <approach>. \
|
||||
Build with 'cd backend && go build ./... && go test ./...' before opening a PR against aoagents/ReverbCode."
|
||||
```
|
||||
|
||||
Note the issue with which path you took (PR or spawned worker).
|
||||
|
||||
### 5g. Report back
|
||||
|
||||
Issue URL, PR URL (if created), labels, root cause summary, whether fix agent was suggested.
|
||||
Issue URL, PR URL (if created) or spawned worker session ID, labels applied (and
|
||||
any priority/confidence stated in the body), root cause summary.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -264,54 +346,76 @@ Issue URL, PR URL (if created), labels, root cause summary, whether fix agent wa
|
|||
|
||||
### A. Subsystem Quick Reference
|
||||
|
||||
| Subsystem | Collect | Key files |
|
||||
| ------------------------------- | ---------------------------------------- | -------------------------------------------------------------- |
|
||||
| **CLI** (`ao start/stop/spawn`) | Config YAML, install method, version, OS | `packages/cli/src/commands/` |
|
||||
| **Web UI** | Screenshot, browser, viewport | `packages/web/src/components/`, `globals.css` |
|
||||
| **Terminal** | Runtime type, tmux version, shell | `DirectTerminal.tsx`, `useXtermTerminal.ts` |
|
||||
| **Lifecycle** | State transitions, session IDs | `core/src/lifecycle-manager.ts`, `core/src/lifecycle-state.ts` |
|
||||
| **Sessions** | Session ID, spawn config, runtime | `core/src/session-manager.ts` |
|
||||
| **Plugins** | Plugin name, agent version | `packages/plugins/<agent>/` |
|
||||
| **Config** | YAML contents, project path | `packages/core/src/config.ts` |
|
||||
| Subsystem | Collect | Key files |
|
||||
| ------------------------------- | ----------------------------------------- | -------------------------------------------------------------------------- |
|
||||
| **CLI** (`ao start/stop/spawn`) | Version, install method, OS, which binary | `backend/internal/cli/`, `backend/cmd/ao/main.go` |
|
||||
| **Daemon / HTTP API** | `ao status`, port, daemon.log | `backend/internal/daemon/daemon.go`, `backend/internal/httpd/controllers/` |
|
||||
| **Sessions / Lifecycle** | Session ID, spawn config, runtime, state | `backend/internal/session_manager/manager.go` |
|
||||
| **Runtime (Zellij)** | Zellij version, `zellij list-sessions` | `backend/internal/adapters/runtime/` |
|
||||
| **Terminal mux** | Runtime type, shell, attach behavior | `backend/internal/terminal/` |
|
||||
| **Agent harness** | Harness name + version | `backend/internal/adapters/agent/<harness>/` |
|
||||
| **Storage** | DB state, migrations | `backend/internal/storage/sqlite/`, `~/.ao/data/ao.db` |
|
||||
| **Hooks** | Hook event, agent, payload | `backend/internal/cli/hooks.go` |
|
||||
| **Frontend (Electron/React)** | Screenshot, viewport, daemon connectivity | `frontend/src/` |
|
||||
|
||||
**Misrouting patterns:**
|
||||
|
||||
- Terminal bugs → tmux (runtime-tmux) vs xterm (web) vs PTY (runtime-process/Windows). Trace where bytes flow.
|
||||
- "Session stuck" → lifecycle state machine vs agent process vs runtime connection.
|
||||
- "Config not saving" → config loading (c12) vs project registration (running-state.ts) vs YAML write (permissions).
|
||||
- Terminal bugs → Zellij runtime adapter vs the terminal mux vs the Electron xterm
|
||||
surface. Trace where bytes flow (daemon → mux → frontend).
|
||||
- "Session stuck" → lifecycle/session-manager state vs agent harness process vs
|
||||
Zellij runtime connection.
|
||||
- "Config not saving" → config loading (`backend/internal/config/config.go`) vs
|
||||
project registration vs SQLite write (`~/.ao/data/ao.db`).
|
||||
- "Command does nothing / wrong port" → you're on the wrong `ao` binary (:3000 vs
|
||||
:3001). Re-check `which -a ao` and `ao status`.
|
||||
|
||||
### B. Remote Code Inspection (no local clone)
|
||||
|
||||
```bash
|
||||
gh api repos/{owner}/{repo}/git/trees/main?recursive=1 --jq '.tree[].path' # list files
|
||||
gh api repos/{owner}/{repo}/contents/{path} --jq '.content' | python3 -c "import base64,sys; sys.stdout.buffer.write(base64.b64decode(sys.stdin.read()))" # read file
|
||||
gh search code "term" --repo {owner}/{repo} --json path --jq '.[].path' # search code
|
||||
gh api "repos/{owner}/{repo}/commits?path={path}&per_page=10" --jq '.[] | "\(.sha[0:8]) \(.commit.message | split("\n")[0])"' # file history
|
||||
gh api repos/aoagents/ReverbCode/git/trees/main?recursive=1 --jq '.tree[].path' # list files
|
||||
gh api repos/aoagents/ReverbCode/contents/{path} --jq '.content' | python3 -c "import base64,sys; sys.stdout.buffer.write(base64.b64decode(sys.stdin.read()))" # read file
|
||||
gh search code "term" --repo aoagents/ReverbCode --json path --jq '.[].path' # search code
|
||||
gh api "repos/aoagents/ReverbCode/commits?path={path}&per_page=10" --jq '.[] | "\(.sha[0:8]) \(.commit.message | split("\n")[0])"' # file history
|
||||
```
|
||||
|
||||
### C. NPM Package Regression Diffing
|
||||
### C. Build / Version Diagnostics
|
||||
|
||||
Diff **published** packages (not local builds) when regression follows an upgrade:
|
||||
ReverbCode is built from source, not published to npm. Pin the binary under test
|
||||
and reproduce against a known build:
|
||||
|
||||
```bash
|
||||
mkdir -p /tmp/ao-diff/{v1,v2}
|
||||
curl -sL https://registry.npmjs.org/@scope/pkg/-/pkg-OLD.tgz | tar xz -C /tmp/ao-diff/v1
|
||||
curl -sL https://registry.npmjs.org/@scope/pkg/-/pkg-NEW.tgz | tar xz -C /tmp/ao-diff/v2
|
||||
diff -rq /tmp/ao-diff/v1/package/ /tmp/ao-diff/v2/package/
|
||||
cd backend && go build -o /tmp/ao ./cmd/ao # build the binary under test
|
||||
/tmp/ao version # record version/commit
|
||||
go version # toolchain (build issues are often here)
|
||||
git log --oneline origin/main -1 # the commit you're analyzing against
|
||||
```
|
||||
|
||||
Example: [PR #1608](https://github.com/ComposioHQ/agent-orchestrator/pull/1608) — source analysis led to wrong theories, npm diff showed the only change was a `=` prefix on tmux `set-option`.
|
||||
To bisect a regression, build `ao` at two commits and compare behavior:
|
||||
|
||||
```bash
|
||||
git stash; git checkout <good-sha>; (cd backend && go build -o /tmp/ao-good ./cmd/ao)
|
||||
git checkout <bad-sha>; (cd backend && go build -o /tmp/ao-bad ./cmd/ao)
|
||||
git checkout - ; git stash pop
|
||||
# run the repro against /tmp/ao-good vs /tmp/ao-bad
|
||||
```
|
||||
|
||||
## Formatting Rules
|
||||
|
||||
- **Linkify all issue/PR refs:** `[#123](https://github.com/ComposioHQ/agent-orchestrator/issues/123)`, `[PR #456](url)`. Never bare `#123`.
|
||||
- **Linkify all issue/PR refs:** `[#123](https://github.com/aoagents/ReverbCode/issues/123)`, `[PR #456](url)`. Never bare `#123`.
|
||||
|
||||
## Pitfalls
|
||||
|
||||
- **Wrong `ao` binary.** A bare `ao` may be a different AO install (old npm build on
|
||||
:3000). Always pin a ReverbCode binary and confirm `ao status` shows port **3001**.
|
||||
- **Verify the bug reproduces against ReverbCode (:3001 / Go code path) before
|
||||
filing** — symptoms first seen in another AO install may not reproduce here.
|
||||
- **Reporter ≠ person who tagged you.** Always attribute to the original reporter.
|
||||
- **Record the commit hash** you analyzed — code changes fast.
|
||||
- **GitHub issue is mandatory** — every triaged bug gets one, even if fix is trivial.
|
||||
- **Only apply labels that exist** (`gh label list --repo aoagents/ReverbCode`).
|
||||
State priority/confidence in the body when no matching label exists.
|
||||
- **Build before you push.** `cd backend && go build ./... && go test ./...` must
|
||||
pass; never open a PR with an unverified Go change.
|
||||
- **`gh api --jq .content` truncates large files** (>~100KB). Use local git instead.
|
||||
- **Push script arg limits** — long commit messages hit `OSError: Argument list too long`. Use a Python script with JSON payloads instead.
|
||||
- **`OLD_STRING` must match GitHub byte-for-byte** — local code may differ from `origin/main`.
|
||||
- **New fields on shared TS interfaces MUST be optional** (`field?: Type`). Downstream `Partial<X>` spreads break on required fields. Example: [PR #1523](https://github.com/ComposioHQ/agent-orchestrator/pull/1523).
|
||||
- **Don't invent Go file paths.** Grep the repo to confirm a path before citing it
|
||||
in an issue.
|
||||
|
|
|
|||
Loading…
Reference in New Issue