|
| 1 | +# inspect |
| 2 | + |
| 3 | +Investigate a fullsend agent run — pull together status, timing, agent output, and logs into a single report. |
| 4 | + |
| 5 | +## Usage |
| 6 | + |
| 7 | +``` |
| 8 | +/fullsend inspect <run-id> |
| 9 | +/fullsend inspect #<issue-number> |
| 10 | +/fullsend inspect |
| 11 | +``` |
| 12 | + |
| 13 | +- `<run-id>`: GitHub Actions run ID (numeric) |
| 14 | +- `#<issue-number>`: find the latest fullsend run triggered by this issue |
| 15 | +- No argument: inspect the most recent fullsend run |
| 16 | + |
| 17 | +Default repo: `../rhdh-agentic`. Override with `FULLSEND_REPO` env var or `--repo <owner/name>`. |
| 18 | + |
| 19 | +## Procedure |
| 20 | + |
| 21 | +### 1. Resolve the run |
| 22 | + |
| 23 | +Determine the GitHub repo owner/name and the run ID. |
| 24 | + |
| 25 | +**If run ID given** (bare number): |
| 26 | +```bash |
| 27 | +gh run view <run-id> --repo <owner/name> --json databaseId,status 2>&1 |
| 28 | +``` |
| 29 | +Verify it exists. If not, abort with "Run not found." |
| 30 | + |
| 31 | +**If `#N` given** (issue number): |
| 32 | +```bash |
| 33 | +gh run list --repo <owner/name> --limit 10 --json databaseId,event,status,conclusion,createdAt \ |
| 34 | + --jq '[.[] | select(.event == "issue_comment" or .event == "issues")] | .[0].databaseId' |
| 35 | +``` |
| 36 | +Then cross-reference: fetch issue N's comments for `fullsend:agent-status:<run-id>` anchors. Use the latest matching run ID. |
| 37 | + |
| 38 | +**If no argument**: |
| 39 | +```bash |
| 40 | +gh run list --repo <owner/name> --limit 5 --json databaseId,event,status,conclusion,createdAt \ |
| 41 | + --jq '[.[] | select(.event == "issue_comment" or .event == "issues")] | .[0]' |
| 42 | +``` |
| 43 | +Use the most recent fullsend-triggered run. |
| 44 | + |
| 45 | +### 2. Gather run overview |
| 46 | + |
| 47 | +```bash |
| 48 | +gh run view <run-id> --repo <owner/name> \ |
| 49 | + --json databaseId,status,conclusion,event,createdAt,updatedAt,jobs,url |
| 50 | +``` |
| 51 | + |
| 52 | +Extract: |
| 53 | +- **Status/conclusion**: `completed/success`, `completed/failure`, `in_progress`, etc. |
| 54 | +- **Duration**: compute from `createdAt` → `updatedAt` |
| 55 | +- **Trigger event**: `issue_comment`, `issues`, `pull_request` |
| 56 | +- **Jobs table**: for each job, extract name, status, conclusion, duration (startedAt → completedAt). Skip jobs with conclusion `skipped` from the duration calculation. |
| 57 | + |
| 58 | +Identify the **agent job** — the one that is NOT `Route` and NOT `stop-fix` and has conclusion != `skipped`. Its name (e.g., `dispatch / Code / Code`) tells you which agent ran. |
| 59 | + |
| 60 | +### 3. Gather agent status comment |
| 61 | + |
| 62 | +Find the triggering issue number. Strategy: |
| 63 | +1. If the user passed `#N`, use that. |
| 64 | +2. Otherwise, extract from the run's event payload — check the run's `headBranch` or use `gh api repos/<owner/name>/actions/runs/<run-id> --jq '.event'` combined with searching recent issue comments. |
| 65 | + |
| 66 | +Then fetch the status comment: |
| 67 | +```bash |
| 68 | +gh api repos/<owner/name>/issues/<N>/comments \ |
| 69 | + --jq '.[] | select(.body | test("fullsend:agent-status:<run-id>")) | {body, created_at}' |
| 70 | +``` |
| 71 | + |
| 72 | +Parse from the comment body: |
| 73 | +- Agent name and result (Success / Failure) |
| 74 | +- Commit SHA (from the `Commit:` backtick) |
| 75 | +- Timestamps |
| 76 | + |
| 77 | +If no status comment found, note: "No agent status comment — the run may have failed before posting." |
| 78 | + |
| 79 | +### 4. Check for PR or branch |
| 80 | + |
| 81 | +If a commit SHA was found in step 3: |
| 82 | + |
| 83 | +```bash |
| 84 | +# Find branches containing the commit (in the local clone) |
| 85 | +cd <repo-path> && git fetch --quiet && git branch -r --contains <sha> 2>/dev/null |
| 86 | +``` |
| 87 | + |
| 88 | +```bash |
| 89 | +# Check for PRs from that branch |
| 90 | +gh pr list --repo <owner/name> --state all --head <branch-name> \ |
| 91 | + --json number,title,state,url --jq '.[] | "\(.number) \(.state) \(.title)"' |
| 92 | +``` |
| 93 | + |
| 94 | +Report: |
| 95 | +- Branch name and whether it was pushed |
| 96 | +- PR number, state (OPEN/CLOSED/MERGED), title, URL |
| 97 | +- If no PR exists despite a successful commit: flag as `⚠️ No PR created` |
| 98 | + |
| 99 | +### 5. Download and summarize artifact |
| 100 | + |
| 101 | +```bash |
| 102 | +gh api repos/<owner/name>/actions/runs/<run-id>/artifacts \ |
| 103 | + --jq '.artifacts[] | {name, size_in_bytes, expired, archive_download_url}' |
| 104 | +``` |
| 105 | + |
| 106 | +If an artifact exists and `expired == false`: |
| 107 | + |
| 108 | +```bash |
| 109 | +# Download to temp dir |
| 110 | +TMPDIR=$(mktemp -d) |
| 111 | +gh run download <run-id> --repo <owner/name> --name <artifact-name> --dir "$TMPDIR" |
| 112 | +``` |
| 113 | + |
| 114 | +**Parse `output.jsonl`** (at `$TMPDIR/iteration-1/output.jsonl` or similar): |
| 115 | +- Count total conversation turns |
| 116 | +- Count tool_use calls by tool name |
| 117 | +- Find any `error` or `failure` messages |
| 118 | +- Extract the model ID used |
| 119 | + |
| 120 | +**Check sandbox logs** (at `$TMPDIR/logs/`): |
| 121 | +- `openshell-sandbox.log`: look for ERROR, FATAL, OOM, timeout |
| 122 | +- `openshell-gateway.log`: look for TLS errors, connection failures |
| 123 | + |
| 124 | +Clean up: `rm -rf "$TMPDIR"` after reading. |
| 125 | + |
| 126 | +If artifact expired or missing, note it and skip. If the run is still `in_progress`, artifacts won't be available yet — note this. |
| 127 | + |
| 128 | +### 6. Report |
| 129 | + |
| 130 | +Output a structured report: |
| 131 | + |
| 132 | +``` |
| 133 | +## Fullsend Run Inspection: <run-id> |
| 134 | +
|
| 135 | +### Overview |
| 136 | +| Field | Value | |
| 137 | +|-------|-------| |
| 138 | +| Run | [<run-id>](<url>) | |
| 139 | +| Trigger | issue_comment on #<N> | |
| 140 | +| Status | <status> / <conclusion> | |
| 141 | +| Duration | <Xm Ys> | |
| 142 | +| Agent | <agent-name> | |
| 143 | +
|
| 144 | +### Jobs |
| 145 | +| Job | Status | Duration | |
| 146 | +|-----|--------|----------| |
| 147 | +| Route | success | 12s | |
| 148 | +| Code | success | 2m 42s | |
| 149 | +| Review | skipped | — | |
| 150 | +| ... | ... | ... | |
| 151 | +
|
| 152 | +### Agent Output |
| 153 | +- Commit: `<sha>` — <commit message> |
| 154 | +- Branch: <branch-name> |
| 155 | +- PR: #<N> (<state>) / none |
| 156 | +- Status comment: ✅ Success / ❌ Failure |
| 157 | +
|
| 158 | +### Artifact Summary |
| 159 | +- Turns: <N> | Tool calls: <N> | Errors: <N> |
| 160 | +- Model: <model-id> |
| 161 | +- Sandbox logs: clean / ⚠️ <issue summary> |
| 162 | +
|
| 163 | +### Issues Found |
| 164 | +- ⚠️ <any anomalies detected> |
| 165 | +``` |
| 166 | + |
| 167 | +### Issue detection heuristics |
| 168 | + |
| 169 | +Flag these automatically: |
| 170 | + |
| 171 | +| Condition | Flag | |
| 172 | +|-----------|------| |
| 173 | +| Run succeeded but no commit SHA in status comment | ⚠️ Success with no output | |
| 174 | +| Commit exists but no PR was created | ⚠️ No PR created | |
| 175 | +| Run duration > `timeout_minutes` from harness | ⚠️ May have hit timeout | |
| 176 | +| Sandbox log contains ERROR/FATAL | ⚠️ Sandbox errors (show excerpts) | |
| 177 | +| Artifact is expired | ℹ️ Artifact expired, no transcript available | |
| 178 | +| Run is still in progress | ℹ️ Run still in progress, partial data | |
| 179 | +| Multiple agent jobs ran (not just one + Route) | ℹ️ Multiple agents dispatched | |
| 180 | + |
| 181 | +If no issues found, end with: **No anomalies detected.** |
0 commit comments