Commit Graph

22 Commits

Author SHA1 Message Date
David Blass cfd38d82fc refactor delegation system, add PR summary comments, and improve code quality (#334)
* refactor delegation system and add PR summary comments

Delegation system:
- replace mode-based delegation with select_mode → delegate two-step flow
- orchestrator crafts self-contained subagent prompts (clean context — no system/repo/event instructions leak)
- add role-based tool filtering via FastMCP authenticate hook (?role=subagent hides orchestrator-only tools)
- add select_mode tool for orchestrator guidance per mode
- add ask_question tool for lightweight research subagents
- extract shared subagent lifecycle into subagent.ts (create, complete, stdout, instructions)
- route set_output to per-subagent state when activeSubagentId is set
- track per-subagent state (SubagentState Map) replacing boolean delegationActive flag
- capture and aggregate AgentUsage across all agents (claude, codex, gemini, opencode)
- write usage summary table to GitHub job summary
- block built-in subagent spawning (Task for Claude, Task(*) for Cursor)
- increase activity timeout from 60s to 300s (subagent thinking phases)
- fix gh CLI misguidance in system prompt — explicitly forbid usage

PR summary comments:
- add prSummaryComment trigger (DB schema + migrations + Zod + UI toggle)
- dispatch mini-effort summary job alongside PR review on pr.created
- add update_pull_request_body MCP tool
- add defaultEffort option to webhook dispatch

Hardening:
- rewrite delegate/selectMode tests with simulated state management
- add toolFiltering.test.ts for role extraction, canAccess, set_output routing
- remove non-null assertions for PULLFROG_TEMP_DIR (proper error throws)
- use fetchWithRetry for direct tarball downloads
- DRY fix for rate limit check in test runner

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: add type keyword to Effort import in handleWebhook.ts

Co-authored-by: Cursor <cursoragent@cursor.com>

* clean up delegation system, improve code quality across the codebase

- simplify delegate tool to instructions + effort params with subagent lifecycle in subagent.ts
- add select_mode and ask_question orchestrator-only tools with canAccess filtering
- replace delegate.test.ts/selectMode.test.ts with toolFiltering.test.ts (live MCP integration)
- add set_output routing for subagent context and AgentUsage tracking across all agents
- add PR summary comment trigger (schema, UI, webhook dispatch with silent flag)
- add update_pull_request_body MCP tool
- fix changed-agents.sh to always include claude canary for non-agent action changes
- fix cursor pagination bug in getSelectedInstallationReposPage
- remove destructuring patterns, inline type definitions, and unsafe type casts
- replace non-null assertions with explicit checks in install.ts
- convert multi-param functions to single param objects (postCleanup, runActionLocal, etc.)
- use isHttpError helper in API routes instead of catch-any patterns
- add adhoc test fixtures for delegation scenarios (context isolation, error handling, synthesis, etc.)

Co-authored-by: Cursor <cursoragent@cursor.com>

* no subagent mutation, one mcp per subagent

* address review feedback: parallel-safe usage tracking, subagent isolation, minor improvements

* fix subagent state isolation: replace Object.freeze with shallow copy

Object.freeze throws TypeErrors when subagent tools (checkout_pr,
report_progress) write scalar properties to toolState. A shallow copy
achieves the same isolation for scalar fields while allowing tools to
work normally. Shared references (subagents Map, usageEntries array)
remain shared for coordination.

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
2026-02-22 14:12:43 +00:00
Colin McDonnell a90743e9fe 0.0.167
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-20 19:19:25 +00:00
Colin McDonnell 823fa3a39b 0.0.166
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-20 19:17:50 +00:00
Colin McDonnell caa3cf4d4b 0.0.165 2026-02-20 15:53:11 +00:00
pullfrog[bot] ee100354da fix: replace domain-specific exit handler with generic signal handler registry (#299)
* 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>
2026-02-20 10:23:56 +00:00
pullfrog[bot] 70f1c47a28 Audit core.warning/core.error usage (#269)
* 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>
2026-02-19 23:11:47 +00:00
Mateusz Burzyński 185ca7a832 Avoid using --ignore-workspace (#353) 2026-02-19 14:41:21 +00:00
Mateusz Burzyński 4ecff49b72 Request reviews from the PR's human initiator (#340)
* Request reviews from the PR's human initiator

* add logs

* await the request reviewers call
2026-02-19 14:00:57 +00:00
pullfrog[bot] 9948c08e7d run post action cleanup in play.ts (#344)
* 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>
2026-02-18 18:32:24 +00:00
Mateusz Burzyński 510f2c96f9 Fix the availability of some @anthropic-ai/claude-agent-sdk types (#322)
* Fix the availability of some `@anthropic-ai/claude-agent-sdk` types

* update it in the action too

* fix types
2026-02-18 12:12:40 +00:00
Colin McDonnell eb22433760 bump action patch version and sync queued waitlist updates
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>
2026-02-17 03:21:44 +00:00
Colin McDonnell 37dcea86b9 0.0.163 2026-02-16 04:42:33 +00:00
pullfrog[bot] 30812435f9 Fix file upload 401 by conditionally signing content-disposition header (#289)
* Fix file upload 401 by conditionally signing content-disposition header

* Bump version to 0.0.162

---------

Co-authored-by: pullfrog[bot] <226033991+pullfrog[bot]@users.noreply.github.com>
2026-02-13 19:14:32 +00:00
Colin McDonnell dc611c9f78 bypass Vercel deployment protection on preview API calls
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>
2026-02-13 15:25:32 +00:00
Colin McDonnell 78cf05f111 Clean up url resolution 2026-02-13 14:24:46 +00:00
Mateusz Burzyński 267a4586ae Use a stable NEXT_PUBLIC_VERCEL_BRANCH_URL for short links (#287)
* 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>
2026-02-13 12:27:27 +00:00
David Blass bc28c658f2 harden sandbox escape vectors for bash disabled/restricted modes (#257)
* harden sandbox escape vectors for bash disabled/restricted modes

block git config injection (-c flag as subcommand), dangerous subcommands
(config, submodule, rebase, bisect), code-executing arg flags (--exec,
--extcmd), .gitattributes/.gitmodules writes, and package lifecycle scripts.
add retry logic to test runner for transient failures. add security unit
tests and adhoc attack tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* only filter subcommands in nobash, remove nobash from ui

* use regex matching

* iterate on tests

* simplify githooks

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-11 02:02:41 +00:00
Colin McDonnell f37d02b292 upgrade Claude to Opus 4.6 with effort levels (#256)
* 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>
2026-02-10 23:34:13 +00:00
David Blass 19df8372cd add file_read/file_write tools, sandbox tests, CI improvements (#239)
* migrate to flags

* init

* iterate on file write lockdown tests

* improve ci

* fix lockfile

* fix typecheck

* fix lint

* improve pushRestricted

* ok

* fix more

* ok

* remove process.env spreading rule

Co-authored-by: Cursor <cursoragent@cursor.com>

* enhanced fs rw tools

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Colin McDonnell <colinmcd94@gmail.com>
2026-02-10 06:35:47 +00:00
pullfrog[bot] fb80343ffd feat(agents): add thinking time logging between tool calls (#244)
* 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>
2026-02-10 06:17:43 +00:00
Colin McDonnell 623e11c7ce Merge RepoSettings into Repo (#248)
* Merge RepoSettings into Repo

Inline all RepoSettings fields (triggers, tools, instructions, scripts,
defaultAgent) directly into the Repo model. Pivot Macro/Mode foreign keys
from repoSettingsId to repoId. Drop the repo_settings table entirely.

Migration backfills all existing data safely.

Co-authored-by: Cursor <cursoragent@cursor.com>

* Remove dead null-coalescing and defaultSettings fallback

All settings fields are now NOT NULL on Repo, so ?? fallbacks in
run-context are unnecessary. initialSettings is non-nullable, so
the defaultSettings memo in RepoConsole was dead code.

Co-authored-by: Cursor <cursoragent@cursor.com>

* drop dead /workflows route, extract getAuthenticatedRepoContext helper

- delete /api/repo/[owner]/[repo]/workflows/ (duplicate of /modes/, no consumers)
- extract shared auth helper that returns { account, owner, repo, token, dbRepo, role }
- update settings, macros, modes routes to use the helper

Co-authored-by: Cursor <cursoragent@cursor.com>

* type-safe API route returns via inferred NextResponse generics

- add ApiResponse<T> utility type that extracts JSON body from route handlers
- remove explicit return type annotations and dead interfaces from 5 routes
- update 3 routes with existing type exports to use ApiResponse<typeof handler>
- narrow error union in ReposTable fetchRepos

Co-authored-by: Cursor <cursoragent@cursor.com>

* run tests on push in addition to pull_request

Co-authored-by: Cursor <cursoragent@cursor.com>

* add rule: no --trailer flags on git commits

Co-authored-by: Cursor <cursoragent@cursor.com>

* move git trailer rule into Rules section

Co-authored-by: Cursor <cursoragent@cursor.com>

* consolidate Learnings into Rules section

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-09 20:46:34 +00:00
Anna Bocharova 60da0e5749 feat(action): Update "Leaping" comment when workflow failed or cancelled early (#230)
* feat(action): Do cleanup when workflow failed or cancelled early.

* fix: avoid naming collision with get-installation-token state.

* tmp: add more logging for debugging purposes.

* fix: rm wasUpdated state.

* FIX: changing approach, separate entrypoint, using db to handle cases when main() never ran.

* fix(cleanup): revert changes to exitHandler.

* FIX: using event payload for issue and comment retrieval instead of DB.

* FIX: use installation token.

* feat(docs): wiki article explaining how it works.

* fix(docs): shortening.

* fix(docs): shortening.

* fix: no console.

* todo: DNRY for findPullfrogComment.

* FIX(DNRY): upgrading octokit/rest and reusing findInitialComment() from triggerWorkflow.ts.

* Revert "FIX(DNRY): upgrading octokit/rest and reusing findInitialComment() from triggerWorkflow.ts."

This reverts commit 7dd239ba0986c5b0aeacb6ddc9f2deddb83aee82.

* fix: rm todo.

* fix(DNRY): shortening early exit logging statements.

* FIX(API): Avoid extra call for comment body.

* feat(DNRY): extracting and reusing buildWorkflowErrorMessage() from exitHandler.ts.

* fix(DNRY): extracting more similarities into buildErrorCommentBody.

* feat: Add conditional reason check.

* fix(merge): replacing resolveInstallationToken with getJobToken.

* fix(debug): using higher severity.

* fix: Adjusting the implementation of getIsCancelled to use job status instead of workflow.

* fix: Take steps conclusion into account when job is in progress.

* fix: generic log msg.

* fix: jsdoc.

* fix(docs): Updating the wiki article according to recent changes.

* fix(post): Handling the case when current job runs within matrix.

* fix: finding the most recent comment that is ours ANS stuck.

* feat(opt): using progressCommentId from object-based prompt when present.

* fix(docs): Shortening the documentation 3 times down.

* FIX: Only using the prompt.progressCommentId but with validation that it is stuck.
2026-02-06 18:10:08 +00:00