* feat: add encrypted account-level secrets with UI for adding API keys
Adds AccountSecret model with AES-256-GCM encryption, API routes for
CRUD, "Add secret" button in model costs section, and injects decrypted
secrets into action env (YAML secrets take precedence).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: repo secrets, sidebar icons, lazy learnings history
- add repo-level secrets with inheritance from org secrets
- add icons to console sidebar sections
- fix learnings history modal: lazy fetch with hover prefetch,
strip content from list response, load content per-expansion
Made-with: Cursor
* add input validation bounds for secrets and fix client-side name filter
Made-with: Cursor
* refactor: migrate all client-side data fetching to TanStack Query
Replace manual useState/useEffect/fetch patterns and the custom
usePolling hook with useQuery, useInfiniteQuery, and useMutation
across the entire frontend for consistent caching, background
refetching, and reactive invalidation.
- ActiveWorkflowRunsSection: useQuery + refetchInterval
- WorkflowRunHistory: useInfiniteQuery + polling query
- LearningsSection: useQuery per revision (lazy)
- FlagsSettings: self-contained useQuery + useMutation
- SecretsCard: useMutation for delete
- AddWorkflowButton, VerifyWorkflowButton: useMutation
- EmailSignupForm, email-waitlist: useMutation
- providers.tsx: enable refetchOnWindowFocus
- Delete usePolling.ts (no remaining consumers)
Made-with: Cursor
* address PR review: squash migrations, rename accountSecrets → dbSecrets
Squash the two separate secrets migrations into a single migration.
Rename the wire format field from accountSecrets to dbSecrets since
it now carries merged account + repo secrets.
Made-with: Cursor
* fix: update proxyKeys.ts imports after cache.ts -> yes package migration
Made-with: Cursor
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add Claude Code agent for Anthropic model users
Re-adds Claude Code support (removed in #478) so users with Anthropic API
keys or Claude Code OAuth tokens can use their Claude subscriptions directly.
When an Anthropic model is selected and Claude Code credentials are available,
the system auto-selects the Claude agent instead of OpenCode. The harness
mirrors opentoad's security model: native Bash blocked via --disallowedTools,
MCP ShellTool for restricted shell, ASKPASS for git auth. Includes NDJSON
streaming, provider error detection, cache/cost tracking, browser skill,
and todo progress tracking.
Key changes:
- action/agents/claude.ts: full Claude Code harness
- action/utils/agent.ts: auto-select Claude for anthropic/* models
- action/utils/providerErrors.ts: extracted shared provider error detection
- action/utils/skills.ts: extracted shared skill installation (agent-aware)
- action/models.ts: add CLAUDE_CODE_OAUTH_TOKEN to anthropic envVars
- action/utils/docker.ts: add CLAUDE_CODE_OAUTH_TOKEN to test env allowlist
- CI: add claude to test matrix, pass CLAUDE_CODE_OAUTH_TOKEN secret
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: remove unused toolId variable, fix apiKeys test env cleanup
The apiKeys test cleanup stripped *_API_KEY vars but missed
CLAUDE_CODE_OAUTH_TOKEN which doesn't match that pattern.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix: strip provider prefix from PULLFROG_MODEL in Claude agent
the env override path was returning the raw value (e.g.
"anthropic/claude-sonnet-4-5") without stripping the provider prefix,
causing the Claude CLI to receive an invalid model ID.
Made-with: Cursor
* fix: remove dead cliPath field, add CLAUDE_CODE_OAUTH_TOKEN to workflows
remove unused cliPath from Claude agent RunParams, and pass
CLAUDE_CODE_OAUTH_TOKEN through all pullfrog.yml workflow templates
so users with Claude Pro/Team subscriptions can use their membership.
Made-with: Cursor
* fix: block Bash subagent in Claude Code disallowedTools
Made-with: Cursor
* chore: update model snapshot (opencode/openrouter latest → qwen3.6-plus-free)
Made-with: Cursor
---------
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
GitHub markdown needs a blank line between </details> and subsequent
HTML elements. Without it, the footer renders inside the collapsed
section.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* fix false "without reporting progress" error + live todo tracking
clean up orphaned progress comments when review is skipped or only
set_output is used, preventing the false positive in handleAgentResult.
parse todowrite events from OpenCode's NDJSON stream and render a
live markdown checklist in the PR progress comment (2s debounce).
agent's explicit report_progress always takes priority.
Made-with: Cursor
* fix contradictory review/progress prompting
align Review and IncrementalReview mode prompts with their guidance —
mode prompts said "always submit" while guidance said "skip if clean."
remove the empty-approval submission that was silently dropped by the
tool. make progress comment lifecycle explicit: created on first call,
updated in place, removed after review submission.
Made-with: Cursor
* centralize todo tracking into shared TodoTracker module
extract inline todo tracking logic (~95 lines) from opentoad.ts into
action/utils/todoTracking.ts. the tracker is created once in main.ts
and passed to agents via AgentRunContext.todoTracker, making it
agent-agnostic and reusable for future agent implementations.
Made-with: Cursor
* fix todoTracker optional type to match file convention
add | undefined to todoTracker in AgentRunContext, matching every
other optional property in the same interface.
Made-with: Cursor
* instruct agents to always maintain a task list for live progress
system prompt now tells agents to create an internal task list at
the start of every run. the tracker renders it to the progress
comment automatically. report_progress is reserved for final
results only — no more intermediate "Checking..." messages that
cancel the tracker and leave stale text on the comment.
Made-with: Cursor
* require report_progress summary at end of every run
agents must always call report_progress with a final summary —
the completed task list should never be the end state of the
progress comment. updated all review mode prompts to call
report_progress after submitting (or not submitting) a review.
Made-with: Cursor
* keep progress comment after review with final summary
stop deleting the progress comment after review submission —
the agent now always calls report_progress with a summary at
the end, and that summary should persist as a record of what
was done.
Made-with: Cursor
* harden stranded progress comment cleanup
- main.ts: detect when tracker was last writer (agent never called
report_progress) and delete the stranded checklist instead of
leaving it as the final comment state
- postCleanup.ts: expand stuck-comment detection to also catch
stranded todo checklists (regex match for checklist patterns)
when the process is killed before normal cleanup runs
- modes.ts + selectMode.ts: add report_progress step to Summarize
and SummaryUpdate modes (only modes that were missing it)
Made-with: Cursor
* fix stale comments, typo, and build mode redundancy
- comment.ts: update deleteProgressComment docstring and inline comment
to reflect current usage (stranded-comment cleanup, not post-review)
- modes.ts: merge duplicate report_progress steps (8 + 10) into single
step 9, fix "optimizatfixons" typo
- wiki/post-cleanup.md: document checklist detection regex
Made-with: Cursor
* collapsible completed todos in final progress, hide set_output outside standalone mode
- add renderCollapsible() to TodoTracker, append completed task list as
<details> section when agent calls report_progress
- cancel tracker after agent's final report_progress so it doesn't
overwrite with raw checklist
- conditionally register SetOutputTool only in standalone mode or when
output_schema is provided
- remove unconditional set_output instruction from orchestrator task section
- update Summarize/SummaryUpdate mode guidance to not reference set_output
Made-with: Cursor
* show completion count in collapsible task list summary
Made-with: Cursor
* only count completed (not cancelled) in collapsible task list summary
Made-with: Cursor
* reinforce concise summary prompting across system prompt, modes, and tool description
Made-with: Cursor
* address review feedback: wasUpdated bypass, tracker false-positive, race condition
- remove wasUpdated=true from cleanup paths so handleAgentResult correctly
detects genuinely silent runs
- add hadProgressComment to ToolState as immutable snapshot for the safety check
- use todoTracker.hasPublished instead of enabled for stranded-comment cleanup
- serialize onUpdate calls via inflightPromise chain with post-cancel guard
- add settled() to wait for in-flight updates before writing final summary
Made-with: Cursor
* address round-2 review: hasPublished after success, finalSummaryWritten flag
- set hasPublished only after onUpdate resolves (not before) so failed
writes are not counted as published
- add finalSummaryWritten flag to ToolState, set after successful
non-plan reportProgress; decouple cleanup detection from
todoTracker.enabled so it survives API failures where cancel() ran
but the write didn't succeed
Made-with: Cursor
* add OpenRouter proxy for managed model routing and OSS program
proxy layer that mints ephemeral OpenRouter keys for users without BYOK
API keys. two paths: pro plan users get their selected model proxied via
OpenRouter; OSS program repos (hard-coded allowlist in config.ts) get
free Claude Opus. BYOK env vars (PULLFROG_MODEL/OPENCODE_MODEL) always
take precedence.
frontend: OSS repos see a static "Opus (Free)" badge with the model
dropdown disabled and no API key requirement. all models now carry
openRouterResolve metadata for proxy target resolution.
Made-with: Cursor
* implement OSS program: proxy infrastructure for free model credits
server-side OSS allowlist determines eligible repos. action mints
ephemeral OpenRouter keys via OIDC-authenticated /api/proxy-token
endpoint (idempotent on runId, $10 per-key safety limit). keys are
disabled on workflow completion when no running refs remain. HWM-based
usage sync tracks cumulative spend per account.
schema: ProxyKey model, Account.usageUsd/activeKeyId, WorkflowRun.proxyKeyId
action: OIDC credential stashing, resolveProxyModel uses server oss flag
frontend: isOss flows from server page to components (no client allowlist)
Made-with: Cursor
* address PR review: repo cross-check, key retirement lifecycle, dead code removal
- proxy-token: verify runId belongs to OIDC-authenticated repo via repo relation
- add retireKey() shared primitive: disable in OpenRouter first, then mark disabled in DB
- rotateKey: retire old active key after swap to prevent orphans
- webhook: replace inline cleanupProxyKey with retireKey calls
- syncAccountUsage: skip disabled keys
- remove vestigial AccountPlan/plan field from action types
- add disabled field to ProxyKey schema + migration
Made-with: Cursor
* replace deprecated opencode/mimo-v2-flash-free with mimo-v2-pro-free
Made-with: Cursor
* fix migration ordering: rename disabled migration to sort after table creation
Made-with: Cursor
* squash proxy key migrations into single migration
Made-with: Cursor
* add preview repo to OSS allowlist for testing
Made-with: Cursor
* populate OSS allowlist from oss-program-invitees.json
Made-with: Cursor
* format oss-program-invitees.json
Made-with: Cursor
* add installed public repos to OSS allowlist
split ossRepos into three provenance-tracked lists:
- internalRepos (pullfrog, colinhacks, RobinTail)
- installedPublicRepos (external public non-fork repos with active installs)
- invitees (from oss-program-invitees.json)
also adds scripts/list-oss-candidates.ts to regenerate the installed list
Made-with: Cursor
* fix: resolve tokens before clearing OIDC env vars
resolveTokens → acquireNewToken → isOIDCAvailable() checks
ACTIONS_ID_TOKEN_REQUEST_URL/TOKEN env vars. The new OIDC
stashing code was deleting them in restricted shell mode before
resolveTokens ran, causing it to fall through to the GitHub App
path which requires GITHUB_APP_ID/GITHUB_PRIVATE_KEY.
Made-with: Cursor
* derive proxy-token auth from OIDC claims, add ensureWorkflowRun upsert
- proxy-token no longer requires body.runId; uses claims.run_id + claims.repository
- shared ensureWorkflowRun upsert called from both webhook and proxy-token
- workflow_run_requested handler now eagerly creates WorkflowRun records
- eliminates race condition between webhook and action proxy-token call
Made-with: Cursor
* hardcode PULLFROG_ACCOUNT_ID, document preview debugging lessons
GitHub node IDs are constant — no reason for this to be an env var.
Removes the trailing-newline bug that caused P2025 errors.
Adds wiki docs on workflow testing, Vercel env gotchas, and Neon
preview branch discovery.
Made-with: Cursor
* fix: parse OpenRouter create-key response correctly
the API returns `key` at the top level, not inside `data`
Made-with: Cursor
* onboarding cards, unlock OSS model selection, simplify console
- add OnboardingCard component with two states: workflow install
and model+test (dispatches "Tell me a joke" for test run)
- replace PromptBox overlay gates with dedicated onboarding cards;
PromptBox is now just the form, always enabled
- use hasWorkflowRuns DB check to decide onboarding vs promptbox
- unlock ModelSelector for OSS repos (was locked to Opus badge);
resolve proxyModel from repo's selected model alias in run-context
- rename "API key" row to "Model costs" with pure client-side states:
OSS covered, auto-resolve, free model, BYOK with env var names
- add "(Recommended)" badge to model aliases with recommended: true
- remove OSS_MODEL_DISPLAY_NAME constant and secrets-fetching logic
Made-with: Cursor
* update stale xai model snapshot
Made-with: Cursor
* rename Permissions to Security, hide git push toggle, add shell isolation toggle with disabled state for public repos, remove opentoad agent name from logs
Made-with: Cursor
* chevron hover states, sidebar hooks/security entries
Made-with: Cursor
* address PR review feedback: rename recommended→preferred, fix dispatch orphan, update wiki docs
- rename `recommended` to `preferred` in model alias registry to distinguish
from the UI "Recommended" badge (which is hardcoded for opus + codex only)
- cancel precreated WorkflowRun when workflow lookup fails in dispatch-workflow
- replace run_sql/vercel env pull in wiki docs with neonctl + Prisma pattern
- extend scripts/neon-branch.ts to output DATABASE_URL via neonctl
- add Recommended badge to GPT Codex alongside Claude Opus in ModelSelector
Made-with: Cursor
* show model name in footer, drop pullfrog.com link
add model slug to buildPullfrogFooter so every Pullfrog comment
displays the active model (e.g. "Using `Big Pickle` (free)" or
"Using `Claude Opus`"). remove the pullfrog.com link from all footers.
Made-with: Cursor
* reject <br/> tags in comment bodies, add prompt guidance
add runtime validation in addFooter that throws if <br/> is followed
by a non-blank line (breaks GitHub heading rendering). the agent sees
the error and retries with clean markdown. also update Summarize mode
prompt to explicitly forbid <br/> tags.
Made-with: Cursor
* fix <br/> guidance: move to event instructions, clarify blank line rule
the formatting rule belongs in DEFAULT_PR_SUMMARY_INSTRUCTIONS (event
instructions), not the Summarize mode prompt. clarify that <br/> must
always be followed by a blank line before headings.
Made-with: Cursor
* generalize block-level HTML rule in summary instructions
add a prominent top-level rule about requiring blank lines between ALL
block-level HTML elements and markdown syntax, not just <br/>.
Made-with: Cursor
* move model to toolState instead of threading through params
model is set once at startup and read everywhere — it belongs on
toolState, not threaded as a separate param through 8 call sites.
postCleanup runs without toolState so it just omits the model label.
Made-with: Cursor
* update models.dev snapshot (openai latest changed)
Made-with: Cursor
* add comment to models snapshot test explaining its purpose
Made-with: Cursor
free models (big-pickle, gpt-5-nano, etc.) define envVars: [] and
isFree: true but validateAgentApiKey always required at least one
provider key. now the validation is model-aware: free models bypass
the check, keyed models validate their specific vars, and auto-select
still requires at least one known key.
closes#483
Made-with: Cursor
the runner's GITHUB_TOKEN (scoped to pullfrog/app) was leaking into
test subprocesses targeting pullfrog/test-repo, causing 400s from the
Pullfrog API on run-context fetches.
instead of deleting GITHUB_TOKEN from the subprocess env,
ensureGitHubToken now always mints a fresh OIDC token scoped to
GITHUB_REPOSITORY when OIDC is available — replacing any inherited
token with a correctly-scoped one.
also adds an informative throw in acquireTokenViaGitHubApp when
GITHUB_APP_ID/GITHUB_PRIVATE_KEY are missing.
Made-with: Cursor
* add Summarize mode for updatable PR summary comments
Introduces a Summarize mode that manages a single summary comment per PR,
updated in place on subsequent pushes. Mirrors the Plan/PlanEdit pattern:
API endpoint for existing-comment lookup at select_mode time, node ID
tracking on WorkflowRun, and SummaryUpdate guidance for edits.
Also fixes summary format instructions: Before/After uses inline <br/>
to avoid double line breaks, metadata line placed after key changes,
SHA-256 anchor instructions strengthened against fabrication.
Made-with: Cursor
* fix pre-existing lint error in checkout.ts
Made-with: Cursor
* fix dead restricted param in deepenForBeforeSha
GitAuthOptions dropped the restricted field in the ASKPASS refactor (#478)
but deepenForBeforeSha (#471) still passed it. Remove the field and the
now-unused shell param from DeepenForBeforeShaParams.
Made-with: Cursor
* agent & model refactor with ASKPASS git auth, UI restructure, clerk v7
Made-with: Cursor
* fix stale agent/effort refs, add tests for askpass + model resolution
- reviewCleanup.ts: payload.agent -> payload.model, remove effort
- selectMode.ts PlanEdit: remove delegation/subagent/effort references
- pullfrog.yml.ts: update env vars (drop GOOGLE_API_KEY/CURSOR_API_KEY,
add GOOGLE_GENERATIVE_AI_API_KEY/XAI_API_KEY/MOONSHOT_API_KEY/OPENCODE_API_KEY)
- FlagsSettings/RepoInstructionsSection: remove stale effort/timeout copy
- new: gitAuthServer.test.ts (10 tests — lifecycle, token delivery, tamper detection, script gen)
- new: agent.test.ts (4 tests — default opentoad, AGENT_OVERRIDE, invalid override)
- new: models.test.ts (19 tests — parseModel, resolution, registry invariants)
- update models.dev snapshot
Made-with: Cursor
* fix changed-agents.sh to filter legacy agent files from CI matrix
legacy agent files (claude.ts, codex.ts, etc.) are @ts-nocheck and not
exported from index.ts. changed-agents.sh now reads index.ts imports to
build the active agent set and treats changes to inactive files as
non-agent changes (opentoad canary only).
Made-with: Cursor
* remove MCP file tools, old agent harnesses, and obsolete security tests
ASKPASS-based git auth makes the old MCP file tool security layer unnecessary:
- token never in subprocess env, so symlink/gitattributes/hook attacks can't exfiltrate it
- agents now use native file tools (OpenCode builtin read/edit)
deleted:
- action/mcp/file.ts (file_read, file_write, file_edit, file_delete, list_directory)
- action/mcp/index.ts (dead re-export)
- agent harnesses: claude.ts, codex.ts, cursor.ts, gemini.ts, opencode.ts
- opencode-runner.ts (inlined into opentoad.ts)
- security tests that validated MCP file tool restrictions
- commented-out three-step review flow (~300 lines)
- sanitizeSchema/wrapSchema dead code from mcp/shared.ts
- OPENCODE_MODEL_MINI/MAX env vars (effort-level model overrides removed)
updated test prompts to use generic file ops instead of MCP tool names.
restored pkg-json-scripts + requirements-txt-attack (test --ignore-scripts defense).
Made-with: Cursor
* bump actions/checkout v4 → v6 (node 24)
node 20 actions deprecated june 2, 2026.
Made-with: Cursor
* temporarily disable fail-fast on agnostic tests to debug checkout@v6
Made-with: Cursor
* re-enable fail-fast on agnostic tests
Made-with: Cursor
* fix test token mismatch: mint OIDC tokens scoped to target repo
CI tests override GITHUB_REPOSITORY to pullfrog/test-repo but inherit
the runner's GITHUB_TOKEN (scoped to pullfrog/app), causing 401s on
every run-context fetch. Clear GITHUB_TOKEN in the test subprocess so
ensureGitHubToken() mints a properly scoped token via OIDC.
Also centralizes the default GITHUB_REPOSITORY in runAgentStreaming
instead of repeating it in every test file, and fixes preview-cleanup
to remove workers from all queues (not just name-matching ones).
Made-with: Cursor
* fix ensureGitHubToken to try OIDC when app credentials are absent
ensureGitHubToken only attempted token minting when GITHUB_APP_ID and
GITHUB_PRIVATE_KEY were set. In CI, OIDC is available but app creds
aren't exposed — so the guard prevented minting entirely.
Made-with: Cursor
* dead code cleanup: remove remnants of deleted agents, file tools, effort system
remove unused @anthropic-ai/claude-agent-sdk and @openai/codex-sdk deps,
orphaned file-tool security tests, dead GEMINI_MODEL passthrough, stale
opencode-runner wiki refs, deleted test file references, and MCP file tool
docs. rename docs/effort → docs/models. fix vitest setup: move dotenv to
globalSetup (runs once before forks instead of per-file, 19s → 200ms).
Made-with: Cursor
* address review feedback: remove dead code, update stale references
- remove AGENT_OVERRIDE (only opentoad exists)
- remove shellToolName plumbing (always restricted shell)
- bump action version to 0.0.179
- remove CURSOR_API_KEY from all workflows/configs
- remove OPENCODE_MODEL_MINI/MAX from workflows/docs
- delete wiki/effort.md, rewrite docs/effort.mdx as "Models"
- rewrite wiki/modes.md: orchestrator/subagent → single agent
- simplify flag system: drop builtin flag extraction (debug, effort,
timeout, agent), keep custom flag replacement only
- reserve all legacy flag names to prevent custom flag conflicts
Made-with: Cursor
* regenerate lockfile after removing claude-agent-sdk and codex-sdk
Made-with: Cursor
* fix import ordering, add lockfile check to pre-push hook
Made-with: Cursor
* remove dead debug payload field, stale packageExtensions
Made-with: Cursor
* merge proc-sandbox and token-exfil into a single test
proc-sandbox and token-exfil were duplicative — both tested that
SANDBOX_TEST_TOKEN couldn't be exfiltrated. consolidated into
token-exfil with shell:restricted (which actually exercises filterEnv)
and the /proc attack vector hints from proc-sandbox.
Made-with: Cursor
* fix wiki adversarial.md to match actual tokenExfil validator
Made-with: Cursor
* add mode instructions and restructure dashboard sidebar
- add modeInstructions JSONB field to Repo model for per-mode user instructions
- thread modeInstructions through settings API, run-context API, RepoSettings, ToolContext, and selectMode runtime
- merge user-defined mode instructions with hardcoded orchestrator guidance, with IncrementalReview inheriting from Review
- reduce visible built-in modes from 7 to 4 (Build, Review, Plan, Fix) with editable Instructions textareas
- add TRIGGERS group header to sidebar above Mentions, Pull requests, Issues
- add wiki/modes.md documenting triggers and modes conceptual model
Made-with: Cursor
* fix leaping comment deletion and address review feedback
- wrap post-createReview operations in try/finally so deleteProgressComment
runs even when updateReview or reportReviewNodeId throws
- add parseModeInstructions runtime guard to filter non-string values
from the JSONB field before passing to buildOrchestratorGuidance
- add useEffect sync for localInstructions when props change
- guard onBlur to skip save when instructions haven't changed
- update wiki/modes.md to reflect V2 is implemented (no longer "proposed")
Made-with: Cursor
* harden review cleanup, fix type cast, stabilize mode instructions state
- wrap deleteProgressComment in try/catch inside finally to prevent masking original errors
- replace `as Record<string,string>` cast with runtime parseModeInstructions + useMemo
- fix wiki dual-prompt table to reflect mode.prompt fallback status
Made-with: Cursor
* fix wiki tense and heading ambiguity from PR review
Made-with: Cursor
* fix review "edited" badge by using pending review + submit flow
create review as PENDING first (no event/body), build the footer with
the now-known review ID, then submitReview with the full body. single
atomic publish — no updateReview edit needed.
Made-with: Cursor
* add post-agent follow-up re-review dispatch
After the agent exits, check if PR HEAD moved past the reviewed commit
and dispatch a follow-up re-review. This closes the gap where push
webhooks are suppressed during in-flight reviews.
Made-with: Cursor
* add silent flag to follow-up re-review dispatch
Made-with: Cursor
* restructure dashboard for consistency and clarity
- consolidate tools into single grouped card (was 4 separate cards)
- merge coding + autofix CI into one section
- remove redundant trigger section descriptions
- add bidirectional crosslinks between modes and triggers
- inline instruction links (review/plan/build) into descriptions
- add save status indicators to all sections
- restructure flags with grouped built-in/custom cards
- flatten sidebar (remove dividers and group headers)
- tighten all descriptions
Made-with: Cursor
* update PR screenshots for new dashboard layout
Made-with: Cursor
* extend review context inline instead of dispatching new workflow
when commits are pushed during a review, the agent now handles them
inline: create_pull_request_review detects HEAD movement, returns
instructions to pull and review the incremental diff, and the agent
submits a second review covering only the new changes. this avoids
the cost of spinning up a full new workflow run.
also fixes a bug where reviewedSha was set to the submission HEAD
(current) rather than the checkout HEAD (what was actually reviewed),
which caused commits pushed between checkout and submission to be
silently missed by postReviewCleanup.
the workflow dispatch is kept as a safety net for agent timeout/error.
Made-with: Cursor
* polish dashboard UI: fix debug markers, crosslinks, title consistency, descriptions
- remove all red debug borders/labels and CM component
- remove all inline style={{}} debug outlines from crosslinks
- fix ambiguous crosslinks: Build→"Coding ↓", Plan→"Enrich issues ↓"
- add missing "Edit build instructions ↑" backlink on Auto-address reviews
- normalize card title weight to text-sm font-semibold across all cards
- rename "Default" subcard to "Setup" with broader description
- fix Mentions description to imperative tone
- broaden Flags section description to cover built-in and custom
- remove useless fragments in ModesSection and ToolsSettings
- restructure Agent section: remove ConsoleSection wrappers, add sidebar indent support
Made-with: Cursor
* extract PR quick links as standalone card, consistent with issues
- PR quick links is now its own card under Reviews (was a sub-toggle inside Review PRs disabled state)
- Review PRs OFF sets prCreated="none" instead of auto-falling back to "links"
- Review PRs card hides sub-toggles when disabled (re-review/approve don't apply)
- Both PRs and Issues now have identical Quick links card structure
Made-with: Cursor
* update reviews screenshot with standalone quick links card
Made-with: Cursor
* polish dashboard UI: revert quick links to inline toggles, fix fonts and spacing
- revert standalone PR/issue Quick Links cards back to inline toggles inside
Review PRs and Enrich Issues cards (fixes prCreated state coupling bug)
- restore original font-medium card titles across all trigger/settings cards
- fix sidebar: add CONSOLE heading, remove nested indentation, remove truncation
- right-justify Enrich Issues mode dropdown, group description with label
- move instructions links inline with behavior descriptions
- replace text save indicators with icon spinner/checkmark
- standardize section title spacing, move footer below danger zone
Made-with: Cursor
* fix formatting for biome lint
Made-with: Cursor
* address PR review feedback: cleanup guard, shared util, wiki update
- clear ctx.toolState.review after read to prevent double-execution of postReviewCleanup
- forward authorPermission in safety-net re-review dispatch
- extract parseModeInstructions to utils/schemas/modeInstructions.ts
- update wiki/modes.md: remove stale v1/v2 language, fix dashboard layout
- add typecheck to pre-push hook
Made-with: Cursor
* add action typecheck to pre-push, fix exactOptionalPropertyTypes errors
Made-with: Cursor
* fix duplicate actuallyReviewedSha from rebase
Made-with: Cursor
* remove PR screenshots
Made-with: Cursor
* add label/textarea association for mode instruction accessibility
Made-with: Cursor
---------
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
* feat(plans): Suggested plan for plan revisions.
* fix: add planCommentId to reduce GitHub API calls.
* Revert "fix: add planCommentId to reduce GitHub API calls."
This reverts commit ef9c24811fa291b12ac3601cc4cd3edb7c9a0fca.
* Improving plan revision: the implementation draft.
* fix schema composition order.
* fix: reusing existing retry helper (action) for reportPlanCommentToRun.
* mv: updatePlanCommentId.
* fix: higher severity for logging error.
* fix: add error handling when calling findExistingPlanCommentIdForIssue.
* feat: improving the revisit plan request detection by adding PLAN_REVISION_VERBS.
* Updating the plan with alternative non-determenistic solution.
* add more verbs to PLAN_REVISION_VERBS.
* fix: supply the previous plan in the event context as previousPlanBody, updating Plan mode instructions.
* fix: adjusting the way PLAN_REVISION_VERBS are used in sentences.
* fix: using GraphQL approach with NodeId to find commentId in findExistingPlanCommentIdForIssue.
* fix: use double word boundaries (both sides).
* fix condition in findExistingPlanCommentIdForIssue.
* fix: rm unused args from findExistingPlanCommentIdForIssue.
* bump the action version.
* fix(plan): rm everything related to approach A.
* fix(plan): No limit for progress comments.
* feat(plan): the new plan.
* Revert: changed to webhook (no longer involved).
* feat: mv plan comment lookup into a new API endpoint.
* Revert: changes to select_mode tool.
* FEAT: The new implementation.
* fix arktype issues.
* fix plan diagram.
* fix(selectMode): e2e type constraints for fetchExistingPlanComment.
* Revert "fix(selectMode): e2e type constraints for fetchExistingPlanComment."
This reverts commit 53f3b6650a9928e3080700faa9eead0052e94333.
* fix(selectMode): type constraints (copy) for fetchExistingPlanComment.
* feat: improving isHttpError helper and reusing it consistently instead of casting.
* address review: remove unconditional retry, add plan comment warning, dedupe type, remove dead guard, fix GraphQL types
* Fix: tightening the PlanEdit guidance.
* fix(select_mode): Providing the agent with existingPlanCommentId as well.
* fix(instructions): Adjusting the primary guidance to prefer Plan mode for issue-related ambiguous requests.
* fix(wiki): updating the delegation docs according to the current instructions.
* fix(instructions): rm implication to call for issue details.
* fix(select_mode): tweak for PlanEdit.
* fix(select_mode): more tweaks to PlanEdit.
* fix(select_mode): tweaks for the order of instructions and context.
* revert: to the state of 5c400efce1f1fec0a0855eeacad2bc3b721fd1bf.
* fix(select_mode): Correcting the guideline.
* rm the plan from the branch (impletemented).
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* 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>
When delegate() runs multiple subagents in parallel, their logs
interleave without visual distinction. Use AsyncLocalStorage to
automatically prefix every log line inside runSubagent() with the
task label in magenta (e.g. [frontend-review]).
Co-authored-by: Cursor <cursoragent@cursor.com>
Standardize orchestrator/subagent instructions on the MCP shell tool and format mode guidance as explicit checklists to make delegation flows easier to follow. Bump the action package version to 0.0.171 for this release.
Co-authored-by: Cursor <cursoragent@cursor.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>
Increment @pullfrog/pullfrog from 0.0.163 to 0.0.164 and include current beta/docs/waitlist script changes.
Co-authored-by: Cursor <cursoragent@cursor.com>
action API calls to preview deployments were getting 401'd by Vercel's
deployment protection. add x-vercel-protection-bypass header to the 3
server-to-server fetch sites when VERCEL_AUTOMATION_BYPASS_SECRET is set.
Co-authored-by: Cursor <cursoragent@cursor.com>
* Use a stable `NEXT_PUBLIC_VERCEL_BRANCH_URL` for short links
* Update JSDoc reference to NEXT_PUBLIC_VERCEL_BRANCH_URL
---------
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
* upgrade Claude to Opus 4.6 with --effort max for --max mode
- mini: haiku → sonnet
- auto: opusplan → opus (Opus 4.6)
- max: opus → opus + --effort max (Opus 4.6 max effort)
- bump @anthropic-ai/claude-agent-sdk 0.2.7 → 0.2.39
Co-authored-by: Cursor <cursoragent@cursor.com>
* update action lockfile for claude-agent-sdk 0.2.39
Co-authored-by: Cursor <cursoragent@cursor.com>
* add tool_use_summary handler for SDK 0.2.39
Co-authored-by: Cursor <cursoragent@cursor.com>
* integrate gpt-5.3-codex with runtime model availability detection
checks GET /v1/models at agent start to determine if gpt-5.3-codex is
available for the API key, falling back to gpt-5.2-codex when it isn't.
model resolution runs concurrently with CLI install for zero added latency.
also bumps @openai/codex-sdk from 0.80.0 to 0.98.0.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>