* chore(oss): add yamcodes/arkenv to OSS program
* fix(test): strip CODEX_AUTH_JSON in apiKeys auto-select test
The beforeEach strip list omitted CODEX_AUTH_JSON, which is in
`knownApiKeys` via the openai provider's managedCredentials. When the
env has CODEX_AUTH_JSON set, the auto-select "throws when no provider
keys are present" assertion finds it and fails to throw.
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* action: retry transient GitHub 422 "internal error" on review submission
GitHub sometimes 422s POST /pulls/{n}/reviews with body
"An internal error occurred, please try again." — a server-side hiccup
that the existing 422 handler framed with the generic
"likely causes (1)(2)(3)" prompt listing affected comments. the agent
dutifully refetched the diff, dropped comments, and resubmitted, hitting
the same transient error on a shifting affected-comments list until
GitHub accepted. some runs logged 8+ spurious retries with ~11 minutes
of wall-clock, dropping valid inline comments along the way.
detect the transient body explicitly, retry in-tool twice with 1s/3s
backoff, and surface a distinct error on exhaustion that tells the agent
this is a GitHub-side issue — do not modify inline comments, wait and
retry or fall back to a body-only review. closes#584.
* action: use retry util for transient review 422, drop isTransientReviewError tests
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* fix(action): tighten provider error detection and propagate agent error events
Both bugs from #562:
1. detectProviderError used substring matches against "429", "rate limit",
etc. — false-positives on commit SHAs containing 429 and on x-ratelimit-*
response headers in dumped 401 error JSON. rewrote with anchored regexes:
numeric status codes only match adjacent to a recognised status key, and
`\brate[_ ]limit(?=[_ ]|\b)` rejects ratelimit-* headers (no separator).
word-boundary anchors on INTERNAL / UNAVAILABLE / quota / limit:0 reject
INTERNAL_SERVER_ERROR / time_limit:0 substrings. added 11-case regression
test.
2. opencode 401s slipped through `eventCount === 0 && lastProviderError`
because opencode's own type=error event increments eventCount before
the guard runs. added an explicit `error:` handler that captures the
event and propagates it to a non-success AgentResult. opencode emits
the message under `error.data.message`, not the top level. mirror fix
in claude.ts: error_max_turns / error_during_execution / any error*
subtype on the result event now flips success: false.
* fix(action): match quota inside identifiers like insufficient_quota
\bquota\b missed insufficient_quota / quota_exceeded / quotaExceeded
because _ is a word character and camelCase has no boundary. quota is
specific enough to be matched as a plain substring.
* fix(action): match `rate limited` and `rate limits exceeded`
Drop the trailing `(?=[_ ]|\b)` lookahead from the rate-limit regex. The
lookahead failed when `limit` was followed by another word character
(`limited`, `limits`), so `rate limited` and `rate limits exceeded` were
slipping past detection. The leading `\b` plus `[_ ]` separator already
rejects `x-ratelimit-*` / `anthropic-ratelimit-*` headers without it.
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: David Blass <david@arktype.io>
- checkoutPrBranch now removes .git/shallow.lock, .git/index.lock, and
.git/objects/maintenance.lock when older than 30s before the first fetch.
prior runs that crashed mid-fetch left these behind on self-hosted runners,
causing checkout_pr to abort with `Unable to create '.git/shallow.lock':
File exists` until the agent shelled out to rm -f.
- GitFetchTool catches `Could not read <sha>` and `remote did not send all
necessary objects` on shallow clones and retries once with --deepen=1000
instead of bouncing the failure back to the agent. agents previously had
to fall back to checking out FETCH_HEAD, losing branch context.
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: David Blass <david@arktype.io>
* fix(action): flip wasUpdated on substantive MCP write tools (#563)
Review/Respond/etc. agents that submit a `create_pull_request_review`,
`create_issue_comment`, or `update_pull_request_body` and exit without
calling `report_progress` were being marked as workflow failures by the
strict completion check in handleAgentResult. Extend the set of tools
that flip toolState.wasUpdated so a substantive user-visible artifact
satisfies the check. The isReviewMode bypass is retained for
IncrementalReview's non-substantive path.
Flag is set BEFORE patchWorkflowRunFields / deleteProgressComment in
each tool so a best-effort cleanup failure does not undo the signal.
* fix(action): use finalSummaryWritten for stranded progress cleanup
The stranded-progress-comment cleanup at the end of main() previously
fired only when toolState.wasUpdated was false (or the tracker was the
last writer). With wasUpdated now set by additional MCP write tools
(create_issue_comment, update_pull_request_body), an agent that produced
a substantive artifact via one of those tools and skipped report_progress
would leave the placeholder "Leaping into action" comment intact — the
post-script then converted it into an error message on a successful run.
Key the cleanup off finalSummaryWritten instead. That flag is only set
when report_progress actually wrote the progress comment, so it cleanly
distinguishes "comment is finalized" from "agent did other work but
never touched the progress comment".
* refactor(mcp): extract markSubstantiveArtifact() helper
replaces 4 inline `ctx.toolState.wasUpdated = true` flips in CreateCommentTool, UpdatePullRequestBodyTool, and CreatePullRequestReviewTool with a single helper in mcp/server.ts. JSDoc on the helper documents the contract (call BEFORE downstream patch/cleanup; gates the strict completion check and stranded-comment cleanup) so future MCP write tool authors only need to grep for one symbol.
no behavioral change.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(mcp): only flip finalSummaryWritten after non-skipped write
Previously the flag was set unconditionally on any non-plan call,
including paths where reportProgress skipped (silent events, deleted
comment, no issue/PR target). The cleanup check in main.ts is
safeguarded by toolState.progressComment so the bug doesn't manifest
today, but aligning the flag with actual writes matches the wasUpdated
pattern and the design intent in the cleanup plan.
* refactor(mcp): inline markSubstantiveArtifact helper
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: David Blass <david@arktype.io>
Co-authored-by: Cursor <cursoragent@cursor.com>
checkout_pr unconditionally rebuilds ctx.toolState.diffCoverage via
createDiffCoverageState, which initialised coveragePreflightRan to false.
a second checkout_pr therefore reset the "one-time nudge per review
session" guarantee in runDiffCoveragePreflight, and the next
create_pull_request_review threw the diff-coverage pre-flight error
again — even after the agent had already gone through the
read-and-resubmit dance once.
createDiffCoverageState now accepts an optional previous state and
carries forward coveragePreflightRan. coveredRanges are intentionally
not carried because their line numbers are tied to the previous diff's
content (especially under incremental diffs).
closes#566
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: David Blass <david@arktype.io>
* share GitHub rate limit tracking between the action and the worker
The action now counts all GitHub API requests and captures the latest
`x-ratelimit-remaining`/`x-ratelimit-reset` headers via a global
request hook on every Octokit instance.
On exit, the usage summary is written atomically to a path specified
by `PULLFROG_USAGE_SUMMARY_PATH`. The worker sets this env var before
sandbox execution, reads the file afterward, and feeds the data into
the Durable Object's rate limit state.
This closes the visibility gap where the worker had no insight into
API calls made by the sandboxed action process.
* address review: refactor rate limit state, randomize usage summary path
* track actual rate limit cost using x-ratelimit-remaining delta
* refactor usage summary writing to use onExitSignal API
Replace the monolithic registerUsageSummaryHandler with direct use of
onExitSignal in main.ts and a writeGitHubUsageSummaryToFile utility
in github.ts. This keeps exitHandler.ts as a pure signal handler
registry (from #299) and also writes the summary on normal exit.
* tweak
* unify
* deduplicate stuff
* improve error handling
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
* Standardize on top-level `triggerer` property
- Rename `triggeringUser` → `triggerer` as the single top-level payload property
- Remove redundant `triggerer` from `FixReviewEvent`, add `approvedOnly` boolean
- Auto-apply `approved_by` filtering in `get_review_comments` when `approvedOnly` is set
- Auto-assign created PRs to the triggerer
- Simplify `AddressReviews` mode prompt
- Accept both `triggerer` and `triggeringUser` in schema for backward compat
* Address review feedback: simplify approved_only, remove addAssignees, drop approved_by param
* Fix formatting in `action/mcp/pr.ts`
* re-add triggeringUser backward-compat fallback in payload schema
* auto-assign created PRs to the triggerer
* Revert "auto-assign created PRs to the triggerer"
This reverts commit c088c425fea33793eb299a001ffd253798d2c674.
* Revert "re-add triggeringUser backward-compat fallback in payload schema"
This reverts commit ae5b3cb3f1377cd4a634b2d48962c785c31013f3.
* backend compat
* tweak prompt to ensure compat
* Address review feedback
* chore: remove triggeringUser fallback
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
* add "Rerun failed job" link to error comment footer
* Remove issueNumber guard from rerun link
The rerun action only needs run_id — the issue number in the trigger
URL path is just a route segment requirement. Use 0 as a fallback
so the link is always shown when a run ID is available.
* Overload `[number]` path segment as `runId` for the rerun action
For the rerun trigger, the `[number]` path param now carries the
workflow run ID instead of an issue number. The rerun link changes
from `/trigger/o/r/ISSUE?action=rerun&run_id=RID` to
`/trigger/o/r/RID?action=rerun`.
- Remove `run_id` query param from page.tsx and searchParams type
- Add error handling around `reRunWorkflow` for invalid run IDs
- Drop `issueNumber` from `BuildErrorCommentBodyParams` and all
rerun link builders (errorReport, exitHandler, postCleanup)
* Reorder validation: action first, then rerun, then issueNumber
* address review: remove early toolState assignment, restructure rerun into dedicated block
* revert self-contained rerun block, share auth logic via issueOrRunId
* improve error handling
* normalize runid early
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
* Add "Fix it" link for body-only PR reviews
When a PR review has only body-level feedback (no inline comments),
the footer now includes a "Fix it" link that triggers the fix flow.
Also fetches the review body in the fix action's prompt so the agent
can address body-level feedback even when there are no inline comments.
* Move review body fetching into `get_review_comments` tool
Instead of fetching the review body in the trigger page and appending
it to the prompt, the `get_review_comments` MCP tool now fetches the
review body via the GitHub API and includes it in its markdown output
under a "Review Body" section. This keeps the trigger page simple and
lets the tool provide all review context in one place.
* fetch body early
* get reviewer from a better place
* cleanup structure to reuse more in test
* simplify
* simplify
* typecheck
* fetch review body via REST API; skip listFiles for body-only reviews
* update snapshot
* formatting
* cleanup
* fix line counting with `countNewlines` utility using `indexOf` loop
* rename `countNewlines` to `countLines` with 1-based line counting
* suppress biome lint warning for assignment in while condition
* remove unused `body` field from GraphQL review query and type
* add `approved` parameter to `create_pull_request_review` and skip fix links for approvals
* vibe instructions
* tighten up prompting
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
* restrict review comments to PR diff in tool description
* fix constraint text: only files (not lines) are restricted to the diff
* Revert "fix constraint text: only files (not lines) are restricted to the diff"
This reverts commit 3f2e3d05e41c308f6640a468230fb0d69c0cc3e1.
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
* fix: report errors to progress comment when agent fails without throwing
when an agent returns success: false without throwing (e.g., opencode exits
with code 0 despite provider errors), the catch block in main.ts is never
reached, leaving the progress comment stuck on "leaping into action."
two fixes:
- opencode: return success: false when 0 events processed and a provider
error was detected (converts silent failures to explicit failures)
- main.ts: after handleAgentResult, check if the progress comment was ever
updated — if not, report the error to the comment as a safety net
Co-authored-by: Cursor <cursoragent@cursor.com>
* address review: use result directly and force failure on unreported progress
* refactor: move safety-net logic into handleAgentResult
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Anna Bocharova <robin_tail@me.com>
* fix: replace domain-specific exit handler with generic signal handler registry
Rewrite exitHandler.ts as a generic, domain-agnostic exit signal module
that exports onExitSignal(handler) returning a dispose function.
- subprocess.ts now registers via onExitSignal instead of direct
process.on(SIGINT/SIGTERM) calls
- resolveTokens registers a signal handler that captures tokens by
closure, fixing the race condition where the exit handler would
read the wrong token after disposal
- Remove setupExitHandler and runCleanup — domain cleanup is handled
by post.ts + await using
Co-authored-by: Cursor <cursoragent@cursor.com>
* tweaks
* simplify handler installation
* extract to util
* fix race in dispose
* wrap dispose body in try/finally to ensure disposingRef always settles
---------
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* Stop using command-based logs for warnings and errors
Co-authored-by: Cursor <cursoragent@cursor.com>
* revert
* tweak
* de-noise
* Remove redundant ts() timestamp prefix from log calls
* Restore timestamped logging and refine debug output routing.
Bring back timestamp prefixes for standard logs and make log.debug emit via core.debug when runner debug is enabled, while still surfacing debug lines for --debug runs.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Mateusz Burzyński <mateuszburzynski@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
* run post action cleanup in play script after main completes
* clarify that GITHUB_RUN_ID is the actual bail-out gate in play context
* treat GITHUB_RUN_ID as optional in post cleanup
* replace dynamic import with static import of `runPostCleanup`
Export `runPostCleanup` from post.ts and guard the top-level
execution with `import.meta.url` so it only auto-runs as an
entry point. play.ts now statically imports and calls it.
* move runPostCleanup into finally block and let failures propagate
* refactor post cleanup into utility module
move post cleanup logic into a dedicated utility and keep post.ts as a pure script entrypoint. update play.ts to import the shared utility directly and normalize direct-execution detection.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add `comment_type: "issue"` to `IssueCommentCreatedEvent` interface and
dispatch sites so agents can distinguish issue comments from PR review
comments
- Add dedicated "Progress reporting" section to system prompt making
`report_progress` the mandatory tool for sharing results
- Update `reply_to_review_comment` description to clarify it only works
for inline review comments on PR diffs, not issue comments
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Update Build, AddressReviews, and Prompt modes to ensure tests are run
BEFORE committing and pushing code. This prevents redundant workflow
triggers when tests fail and need fixes.
Previously, the Build and Prompt modes would:
1. Make code changes
2. Commit and push
3. Test (oops, too late!)
Now all modes follow the correct order:
1. Make code changes
2. Test (if tests fail, fix and repeat)
3. Commit and push
This addresses the inefficiency observed in #268 where the agent pushed
code before verifying it worked, then had to fix and push again.
Closes#273
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* Replace Date.now() with performance.now() for duration measurements
- Import performance from node:perf_hooks in all affected files
- Update Timer and ThinkingTimer classes to use performance.now()
- Update activity tracking (markActivity, getIdleMs) to use performance.now()
- Update cache duration measurements to use performance.now()
- Update agent execution timing (cursor, opencode) to use performance.now()
- Update subprocess execution timing to use performance.now()
- Update API performance monitoring to use performance.now()
- Update prep phase timing to use performance.now()
- Update timer.test.ts to mock performance.now() instead of Date.now()
Benefits:
- Monotonic clock immune to system clock adjustments
- Higher precision (microsecond vs millisecond resolution)
- Purpose-built for performance measurement
Fixes#245
* fix lint.
* Round float durations to integers in logging
Preserve original behavior by rounding performance.now() float values
to integers when displaying/logging millisecond durations.
* fix lint.
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Robin Tail <robin_tail@me.com>
* feat(agents): add thinking time logging between tool calls
Adds a ThinkingTimer utility that tracks the gap between tool results and
the next tool call. When the gap exceeds 3 seconds, it logs the duration
with a stopwatch emoji (⏱️ 4.2s).
Uses performance.now() for high-resolution timing and Intl.NumberFormat
for rendering duration in seconds with optional fraction digits.
Integrated across all 5 agents: Claude, Codex, Cursor, Gemini, OpenCode.
Closes#127
* fix: adjusting tests for mocking performance.now.
* fix: reducing diff for claude.
* fix: rm unused args for claude.
* rm unused args for codex.
* fix: rm unused args for gemini.
* fix: rm unused args for opencode.
* mv THINKING_THRESHOLD.
* rev: I decided to pospone node:perf_hooks integration since it requires more comprehensive refactoring.
* fix: using Intl unit formatting.
* tests for ThinkingTimer.
* fix: narrow unit.
* fix: making durationFormatter a class instance property since using one agent per run.
* fix: inverting condition in markToolCall.
* thinking timer improvements and fix actions/checkout v6 auth
- thinking timer: use » chevron and "thought for X seconds" format
- thinking timer: add debug timestamps for sanity checking
- demote PID namespace isolation logs to debug
- remove redundant "setting up git authentication" log
- fix duplicate Authorization header with actions/checkout v6: clean up
includeIf credential entries that v6 persists via external config files
Co-authored-by: Cursor <cursoragent@cursor.com>
* standardize tool call log prefix to » double chevron
Co-authored-by: Cursor <cursoragent@cursor.com>
* update timer tests for new thinking log format
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Robin Tail <robin_tail@me.com>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
* flatten lifecycle hooks into RepoSettings string fields
replace the separate LifecycleHook model with setupScript and
postCheckoutScript string fields directly on RepoSettings. move the UI
into the Agent settings section alongside environment variables and
custom instructions. delete the standalone lifecycle-hooks API route,
component, and schema since the existing settings PATCH endpoint
handles the new fields automatically.
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix: pass env to lifecycle hook spawn so scripts can use package managers
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Update Build and Prompt mode instructions to explicitly reference
`issue_number` from EVENT DATA and instruct agents to include
"Closes #<issue_number>" in PR bodies when working in the context
of an issue (where `is_pr` is not true).
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* feat: post "Leaping..." comment immediately without polling GitHub API
This change makes the initial comment response much faster by avoiding
the expensive GitHub API polling that was waiting for workflows to
dequeue (up to 12s+ in some cases).
New architecture:
1. Create WorkflowRun record BEFORE dispatching (no runId yet)
2. Post "Leaping into action..." comment with shortlink URL immediately
3. Dispatch workflow and return
4. workflow_run.requested webhook fills in runId when GitHub dequeues
Shortlink redirect at /api/workflow-run/[id]/logs:
- If runId available: redirects to GitHub workflow run
- If runId null: shows polling page that checks DB every 1.5s
Changes:
- Make `runId` optional on WorkflowRun model (filled in via webhook)
- Add `workflow_run` to expected webhook events
- Add handler for workflow_run.requested to update DB with runId
- Create /api/workflow-run/[id]/logs shortlink redirect route
- Refactor triggerWorkflow.ts to use eager comment pattern
- Update trigger page to use new pattern
Closes#141
* chore: add migration for nullable runId in WorkflowRun
* fix: rm dead code.
* fix: Adjusting the issueNumber prop usage comment.
* fix: shortening and JSDoc for createWorkflowRunRecord.
* fix: Reducing diff, reducing confusion on naming the id.
* Revert "fix: Adjusting the issueNumber prop usage comment."
This reverts commit 34d87c2f8bc58782a53ce5eb14a40935232a4924.
* refactor: reuse buildShortlinkUrl in trigger page
* fix: Reducing confusion on param naming.
* fix: shorter JSDoc.
* Apply suggestion from @RobinTail
* chore: remove unnecessary JSDoc comment from buildShortlinkUrl
* Revert "chore: remove unnecessary JSDoc comment from buildShortlinkUrl"
This reverts commit 491ba6ba3f31c874c9f391871739efa50adb0446.
* fix: confusing naming of var.
* fix: redundant 'let'.
* refactor: move route from `/api/workflow-run/[id]/logs` to `/api/workflow-run-logs/[id]`
Avoids confusion with existing `/api/workflow-run/[runId]` route which uses
GitHub's runId, whereas this new route uses the internal WorkflowRun record id.
* chore: remove old route directory
* refactor: reuse `buildShortlinkUrl()` with `shouldPoll` param
* refactor: add script prop to generateLeapingLoaderHtml
Instead of string-replacing to inject scripts, the function now
accepts an optional script prop that gets wrapped in <script> tags.
* mv script into new LeapingLoaderHtmlProps.
* refactor: extract `buildGithubUrl` helper to avoid repetition
* fix: shorening.
* fix: More clear subtitle.
* refactor: reuse `WORKFLOW_FILENAME` from `app/globals.ts`
* fix: shortening.
* feat: add integrity_id for reliable workflow matching
Pass WorkflowRun record id as integrity_id when dispatching workflows.
The webhook handler parses integrity_id from display_title (via run-name)
for reliable matching, with fallback to repo/owner lookup when missing.
Note: workflow template changes (.github/workflows/pullfrog.yml) need to be
applied manually as the GitHub App lacks workflows permission.
* Revert "feat: add integrity_id for reliable workflow matching"
This reverts commit dbc601233a0dd85ac5f0d608a221e7015e265aaa.
* Add todo for consideration later.
* docs: add plan for action-initiated workflow run correlation
Addresses review feedback requesting research into secure alternatives
to exposing HOOKDECK_API_KEY. Proposes leveraging existing OIDC token
exchange to pass WorkflowRun record ID and correlate with run_id.
* Revert "docs: add plan for action-initiated workflow run correlation"
This reverts commit b9279d0e99db4d85e4144675634afa941858333a.
* FEAT: Add optional integrity_id input, used by run-name, set with partial record id, read by handler for lookup.
* Add integrity_id to app/trigger/[owner]/[repo]/[number]/page.tsx
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* feat: Extracting INTEGRITY_ID_LENGTH.
* Add integrity_id to the workflow files of the repo.
* fix: Use Vercel Preview deployment URL into account in buildShortlinkUrl().
* fix: add missing `.rest` prefix in Octokit API call
* revert: remove unnecessary escaping of backticks in comment
* fix: add polling timeout and wrap DB update in try-catch
- Add 3-minute timeout to polling page to prevent indefinite polling
- Wrap updateWorkflowRunComment in try-catch to prevent orphaned comments
* feat: restore job-level deep linking for workflow runs
Adds jobId to WorkflowRun model and captures the first job ID via
listJobsForWorkflowRun() when the workflow_run_in_progress event fires.
The shortlink redirect now appends /job/{jobId} when available, providing
a direct link to the job rather than just the workflow run.
* fix: handle only `workflow_run.in_progress` to avoid race condition
Combine the handling of `runId` and `jobId` into a single update when
`workflow_run.in_progress` fires, avoiding the race condition where
`in_progress` could arrive before `requested` was processed.
* Renae integrity_id -> name
* Clean up
* Clean up
* Shorter timeout
* Add fallback
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Robin Tail <robin_tail@me.com>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
- Build mode: rewrote steps 8-9 to consolidate PR creation logic into step 8
with explicit default/branch-only behaviors, removing the false claim that
create_pull_request is needed for commit attribution
- Prompt mode: updated step 2 with the same conditional PR creation logic
Fixes#84
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* add api key existence check when selecting agent
- create getSecretNames utility to fetch GitHub Actions secret names
- add /api/repo/[owner]/[repo]/secrets endpoint to check secrets
- update AgentSettings to fetch and display secret validation status
- show green check when required API key exists
- show amber warning when required API key is missing
- show loading state while checking secrets
* Add API key checking
* Fix null agent test
* Tweaks
* Switch to getrepoorgsecretes
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
* fix: prevent log.writeSummary from overwriting reportProgress content
The run summary was showing logs instead of the final reportProgress content
because log.writeSummary() was called after reportProgress. Now
log.writeSummary() checks if the summary was already overwritten by
reportProgress and skips if so.
Fixes#86
* refactor: replace dynamic import with static import in cli.ts
Replace unnecessary dynamic import of wasSummaryOverwritten with
static import. No circular dependency exists since comment.ts doesn't
import from cli.ts.
* Fix run summary writing
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
* implement github suggestion format instructions
add instructions for agents to use github's suggestion format (```suggestion blocks) when providing code suggestions in comments. this enables one-click apply for suggested changes.
updated:
- action/mcp/review.ts: added suggestion format guidance to create_pull_request_review tool description and comment body parameter
- action/mcp/comment.ts: added suggestion format guidance to all comment tools with clarification that suggestions only work on pr line-level review comments
- action/modes.ts: added detailed example in review mode and reminder in address reviews mode
fixes#70
* Address PR review feedback
- Remove suggestion format guidance from report_progress (not applicable)
- De-duplicate description across Comment, EditComment, ReplyToReviewComment
- Drop outer fence in suggestion format example
- Clarify that suggestions only work for self-contained changes
- Remove useless example comment from review tool description
---------
Co-authored-by: pullfrog <team@pullfrog.com>