Skip to content

Commit dec1e33

Browse files
committed
fix: address PR #20 review findings and scope reviewer to diff only
- workflow-run.ts: retry checkConclusionJobCompleted once on API error, then proceed instead of dropping the ingest on continued failure - comment.ts: findExistingComment now throws on paginate error so upsertComment aborts rather than falling through to create a duplicate - run.ts: only overwrite resolvedWorkflowName when runData.workflowName is non-empty, preserving the companion workflow name as fallback - workflow-run.ts: anchor issue-branch regex to full name (^agent/issue-N$) to prevent substring matches in longer branch names - run.ts: prefer resolvedTriggerType over resolvedTriggerEvent in buildTriggerRef so manual trigger_number without trigger_event doesn't mislabel PRs as generic #N issues - README.md: make turns field conditional in printf snippet so an unset TURNS var doesn't write invalid JSON into the artifact - agent-review.md: remove bash tools (no full-file reads), instruct reviewer to only comment on lines present in the diff
1 parent 6a76177 commit dec1e33

7 files changed

Lines changed: 598 additions & 607 deletions

File tree

.github/workflows/agent-review.lock.yml

Lines changed: 542 additions & 571 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.github/workflows/agent-review.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ permissions:
1919
pull-requests: read
2020

2121
tools:
22-
bash: ["cat", "head", "tail", "grep", "wc", "ls", "find"]
2322
github:
2423
toolsets: [repos, pull_requests]
2524

@@ -41,19 +40,21 @@ Review PR #{{ github.event.pull_request.number }}: "{{ github.event.pull_request
4140

4241
## Review Process
4342

44-
1. **Fetch the PR diff** using the GitHub tool.
45-
2. **Review for:**
43+
1. **Fetch the PR diff** using the GitHub tool (`get-pull-request-diff` or equivalent).
44+
2. **Review only the changed lines** (`+` lines in the diff). Do not fetch or read full file contents — your entire review must be scoped to lines present in the diff.
45+
3. **Review for:**
4646
- TypeScript type safety issues (strict mode — no `any`, no unchecked nulls)
4747
- Code style: JSDoc block above every function, alphabetical params, explicit return types
4848
- Logic errors or bugs
4949
- Missing test coverage for new logic
50-
3. **Post inline review comments** on specific lines where you find issues.
51-
4. **Submit your review:**
50+
4. **Post inline review comments** only on lines that appear in the diff.
51+
5. **Submit your review:**
5252
- No issues: use `noop` with a brief summary.
5353
- Issues found: COMMENT with specific, actionable feedback.
5454

5555
## Important
5656

57+
- **Only comment on lines in the diff.** Do not flag pre-existing code that was not touched by this PR.
5758
- Be concise and constructive.
5859
- Don't nitpick formatting — Biome handles that.
5960
- Focus on correctness and type safety.

README.md

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -288,8 +288,12 @@ If you're not using gh-aw, add these two steps to your agent job to write and up
288288
- name: Write token counts
289289
if: always()
290290
run: |
291-
printf '{"input_tokens":%s,"output_tokens":%s,"cache_read_tokens":%s,"cache_write_tokens":%s,"turns":%s}\n' \
292-
"$INPUT_TOKENS" "$OUTPUT_TOKENS" "$CACHE_READ_TOKENS" "$CACHE_WRITE_TOKENS" "$TURNS" \
291+
turns_field=""
292+
if [ -n "$TURNS" ]; then
293+
turns_field=",\"turns\":$TURNS"
294+
fi
295+
printf '{"input_tokens":%s,"output_tokens":%s,"cache_read_tokens":%s,"cache_write_tokens":%s%s}\n' \
296+
"$INPUT_TOKENS" "$OUTPUT_TOKENS" "$CACHE_READ_TOKENS" "$CACHE_WRITE_TOKENS" "$turns_field" \
293297
> /tmp/agent-tokens.json
294298
295299
- uses: actions/upload-artifact@v4

dist/index.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/comment.ts

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -302,21 +302,17 @@ async function findExistingComment({
302302
repo: string;
303303
issueOrPrNumber: number;
304304
}): Promise<{ id: number; body: string } | null> {
305-
try {
306-
const gh = octokit as ReturnType<typeof import('@actions/github').getOctokit>;
307-
const comments = await gh.paginate(gh.rest.issues.listComments, {
308-
owner,
309-
repo,
310-
issue_number: issueOrPrNumber,
311-
per_page: 100,
312-
});
305+
const gh = octokit as ReturnType<typeof import('@actions/github').getOctokit>;
306+
const comments = await gh.paginate(gh.rest.issues.listComments, {
307+
owner,
308+
repo,
309+
issue_number: issueOrPrNumber,
310+
per_page: 100,
311+
});
313312

314-
const existing = comments.find((c) => c.body?.includes(COMMENT_MARKER));
315-
if (!existing) return null;
316-
return { id: existing.id, body: existing.body ?? '' };
317-
} catch {
318-
return null;
319-
}
313+
const existing = comments.find((c) => c.body?.includes(COMMENT_MARKER));
314+
if (!existing) return null;
315+
return { id: existing.id, body: existing.body ?? '' };
320316
}
321317

322318
/**

src/run.ts

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -99,9 +99,10 @@ export async function run(): Promise<void> {
9999
if (!inputs.triggerEvent) resolvedTriggerEvent = runData.triggerEvent;
100100
resolvedTriggerRef = runData.triggerRef;
101101
resolvedTriggerType = runData.triggerType;
102-
// Always use the agent workflow's name from the run data — ctx.workflowName is the
103-
// companion workflow and would misattribute if used as a fallback here.
104-
resolvedWorkflowName = runData.workflowName;
102+
// Prefer the agent workflow's name from the run data over ctx.workflowName (which is the
103+
// companion workflow). Only overwrite when non-empty so a failed getWorkflowRun() doesn't
104+
// blank out the name entirely.
105+
if (runData.workflowName) resolvedWorkflowName = runData.workflowName;
105106
workflowRunTokens = runData.tokens;
106107
artifactTurns = runData.artifactTurns;
107108
}
@@ -138,11 +139,17 @@ export async function run(): Promise<void> {
138139
// Fall back to resolvedTriggerRef from resolveTrigger (companion workflow_run mode — it knows
139140
// whether a PR was found regardless of the triggering event name, e.g. issue_comment on a PR).
140141
// Last resort: buildTriggerRef from the event name and number.
142+
// Prefer resolvedTriggerType (set by resolveTrigger in workflow_run mode — already knows
143+
// PR vs issue) over resolvedTriggerEvent when building the ref label, so a manual
144+
// trigger_number without trigger_event doesn't default to the generic '#N' form for PRs.
141145
const triggerRef =
142146
ctx.triggerRef ??
143147
resolvedTriggerRef ??
144148
(resolvedTriggerNumber !== null
145-
? buildTriggerRef({ eventName: resolvedTriggerEvent, number: resolvedTriggerNumber })
149+
? buildTriggerRef({
150+
eventName: resolvedTriggerType ?? resolvedTriggerEvent,
151+
number: resolvedTriggerNumber,
152+
})
146153
: null);
147154

148155
// resolvedTriggerType is only set in companion workflow_run mode (from resolveTrigger).

src/workflow-run.ts

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ async function checkConclusionJobCompleted({
180180
/** Workflow run ID */
181181
workflowRunId: number;
182182
}): Promise<boolean> {
183-
try {
183+
const attemptCheck = async (): Promise<boolean> => {
184184
const { data } = await octokit.rest.actions.listJobsForWorkflowRun({
185185
owner,
186186
repo,
@@ -198,12 +198,24 @@ async function checkConclusionJobCompleted({
198198
}
199199
core.info(`AgentMeter: conclusion job completed (${conclusionJob.conclusion}) — proceeding.`);
200200
return true;
201-
} catch (error) {
202-
// Fail closed on API errors — proceeding on a failed gate check risks double-ingest.
203-
// A missing conclusion job (non-gh-aw workflow) is handled above as a successful
204-
// API call that returns no matching job, not as an exception.
205-
core.warning(`AgentMeter: could not check conclusion job status: ${error}. Skipping.`);
206-
return false;
201+
};
202+
203+
try {
204+
return await attemptCheck();
205+
} catch (firstError) {
206+
core.warning(
207+
`AgentMeter: could not check conclusion job status (attempt 1): ${firstError}. Retrying…`
208+
);
209+
try {
210+
return await attemptCheck();
211+
} catch (secondError) {
212+
// Both attempts failed — proceed rather than silently dropping the ingest. A transient
213+
// API hiccup or token-scope issue should not cause permanent data loss.
214+
core.warning(
215+
`AgentMeter: could not check conclusion job status (attempt 2): ${secondError}. Proceeding.`
216+
);
217+
return true;
218+
}
207219
}
208220
}
209221

@@ -334,9 +346,9 @@ async function resolveTrigger({
334346
}
335347
}
336348

337-
// gh-aw issue branches are named agent/issue-N — require the full prefix to
338-
// avoid mismatching unrelated branches like feature/fix-issue-12-auth.
339-
const issueMatch = headBranch.match(/\bagent\/issue-(\d+)\b/);
349+
// gh-aw issue branches are named agent/issue-N — anchor to the full branch name to
350+
// avoid substring matches in longer branch names like feature/agent/issue-12-fix.
351+
const issueMatch = headBranch.match(/^agent\/issue-(\d+)$/);
340352
if (issueMatch?.[1]) {
341353
const num = parseInt(issueMatch[1], 10);
342354
return {

0 commit comments

Comments
 (0)