Skip to content

Address review on upstream PR #114: verified agy argv, devkit_ask depth guard, workdir check, timeout cap, docs - #1

Draft
Hieraphant wants to merge 69 commits into
feat/agy-runner-devkit-askfrom
ccr-40a9fd95-d119cx
Draft

Hieraphant wants to merge 69 commits into
feat/agy-runner-devkit-askfrom
ccr-40a9fd95-d119cx

Conversation

@Hieraphant

Copy link
Copy Markdown
Owner

What

Review fixes for upstream 5uck1ess/devkit#114 (review pullrequestreview-5293488905). Merging this into feat/agy-runner-devkit-ask updates that PR automatically. The branch is also merged with current upstream main (v2.1.53); there were no conflicts.

Review items → changes

# Reviewer asked Change
1 Unverified agy exec [-C dir] - argv Default is now agy --dangerously-skip-permissions --print, prompt on stdin, cwd via cmd.Dir — the shape the maintainer smoke-tested against agy v1.0.0 in 5uck1ess#102 and that the headless reference documents. --print goes last because the v1.5.2 release notes record a fix for a valueless prompt flag swallowing the next flag. Exit-0 Error: ... lines are surfaced as errors (agyOutputIsError from feat/agy-runner).
2 Recursion DEVKIT_ASK_DEPTH: refused at depth ≥ 1; every peer is launched with the depth incremented via new RunOpts.Env (applied by claude/codex/gemini/agy runners). Malformed values refused.
3 Sandbox / workdir workdir must be an existing directory, validated before anything is spawned. --dangerously-skip-permissions mirrors gemini -y. --sandbox is documented and present in the binary but not defaulted: the binary also reports "terminal sandbox unavailable" on some hosts and the combination is unverified. Opt in with AGY_ARGS.
4 Timeout Optional timeout (seconds), default 300, cap 1800; zero/negative/NaN/non-numeric/over-cap rejected; cap checked before Duration conversion; deadline hit reported as <peer> timed out after <d>.
5 Docs CLAUDE.md runners row lists agy.go; MCP tools row lists devkit_ask + depth guard. README tool list and runner lines updated.
6 "Generated with Claude Code" in PR body Not editable from this fork PR — replacement body for 5uck1ess#114 is in the follow-up notes.

Evidence for the agy invocation

agy could not be executed in the environment that produced this branch (the sandbox refused to run the downloaded binary). What was checked instead:

  • feat: add AgyRunner for Google Antigravity CLI 5uck1ess/devkit#102's smoke test against v1.0.0: stdin + --print works; an argv prompt was ignored.
  • Official headless reference: -p/--print/--prompt, --output-format, --input-format, --print-timeout (default 0s), --sandbox, --dangerously-skip-permissions; no working-directory flag.
  • Strings in the v1.5.2 Linux binary (sha512-verified download from the official installer's manifest): all of the above flags present; "Print mode: --dangerously-skip-permissions set, auto-approving all tool permissions"; "the %s tool(s) required approval that headless mode cannot prompt for, so they were auto-denied"; release notes stating print-timeout now exits 3 with an AGY_ERROR line on stderr, and the fix for --print --sandbox 'do the task' mis-parsing.

Open question for the maintainer

isDevkitMCPTool in src/cmd/guard.go allows any mcp__plugin_devkit_devkit-engine__* tool during enforced steps, so devkit_ask is already allowed there by prefix. Not changed here; flagged in case devkit_ask should be blocked during hard steps.

Verification

gofmt -l .            # clean
go vet ./...          # clean
go test ./... -race -count=1   # all packages pass

New tests: src/runners/agy_test.go, src/runners/agy_run_test.go (fake agy on PATH; unix only like claude_run_test.go), src/mcp/ask_test.go (fake peer injected via askDetectRunners).


Generated by Claude Code

dependabot Bot and others added 30 commits July 22, 2026 10:04
…5uck1ess#116)

Bumps the actions group with 2 updates in the / directory: [actions/checkout](https://github.com/actions/checkout) and [actions/setup-go](https://github.com/actions/setup-go).


Updates `actions/checkout` from 6 to 7
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](actions/checkout@v6...v7)

Updates `actions/setup-go` from 6 to 7
- [Release notes](https://github.com/actions/setup-go/releases)
- [Commits](actions/setup-go@v6...v7)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
- dependency-name: actions/setup-go
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: actions
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
…5uck1ess#115)

Bumps the go-deps group with 3 updates in the /src directory: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go), [golang.org/x/sys](https://github.com/golang/sys) and [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).


Updates `github.com/mark3labs/mcp-go` from 0.54.1 to 0.57.0
- [Release notes](https://github.com/mark3labs/mcp-go/releases)
- [Commits](mark3labs/mcp-go@v0.54.1...v0.57.0)

Updates `golang.org/x/sys` from 0.46.0 to 0.47.0
- [Commits](golang/sys@v0.46.0...v0.47.0)

Updates `modernc.org/sqlite` from 1.52.0 to 1.55.0
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.52.0...v1.55.0)

---
updated-dependencies:
- dependency-name: github.com/mark3labs/mcp-go
  dependency-version: 0.55.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/sys
  dependency-version: 0.47.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: modernc.org/sqlite
  dependency-version: 1.53.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Bumps the go-deps group with 3 updates in the /src directory: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go), [golang.org/x/sys](https://github.com/golang/sys) and [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).


Updates `github.com/mark3labs/mcp-go` from 0.57.0 to 1.0.0
- [Release notes](https://github.com/mark3labs/mcp-go/releases)
- [Commits](mark3labs/mcp-go@v0.57.0...v1.0.0)

Updates `golang.org/x/sys` from 0.47.0 to 0.48.0
- [Commits](golang/sys@v0.47.0...v0.48.0)

Updates `modernc.org/sqlite` from 1.55.0 to 1.58.0
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.55.0...v1.58.0)

---
updated-dependencies:
- dependency-name: github.com/mark3labs/mcp-go
  dependency-version: 1.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
  dependency-group: go-deps
- dependency-name: golang.org/x/sys
  dependency-version: 0.48.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: modernc.org/sqlite
  dependency-version: 1.58.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
…rc/go-deps-4888800e33

chore(deps): bump the go-deps group across 1 directory with 3 updates
Bumps the go-deps group in /src with 2 updates: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go) and [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).


Updates `github.com/mark3labs/mcp-go` from 1.0.0 to 1.1.0
- [Release notes](https://github.com/mark3labs/mcp-go/releases)
- [Commits](mark3labs/mcp-go@v1.0.0...v1.1.0)

Updates `modernc.org/sqlite` from 1.58.0 to 1.59.0
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.58.0...v1.59.0)

---
updated-dependencies:
- dependency-name: github.com/mark3labs/mcp-go
  dependency-version: 1.1.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: modernc.org/sqlite
  dependency-version: 1.59.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
…rc/go-deps-6339694ba2

chore(deps): bump the go-deps group in /src with 2 updates
Bumps the go-deps group in /src with 1 update: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go).


Updates `github.com/mark3labs/mcp-go` from 1.1.0 to 1.1.1
- [Release notes](https://github.com/mark3labs/mcp-go/releases)
- [Commits](mark3labs/mcp-go@v1.1.0...v1.1.1)

---
updated-dependencies:
- dependency-name: github.com/mark3labs/mcp-go
  dependency-version: 1.1.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
…rc/go-deps-bb733f8931

chore(deps): bump github.com/mark3labs/mcp-go from 1.1.0 to 1.1.1 in /src in the go-deps group
Bumps the go-deps group in /src with 1 update: [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).


Updates `modernc.org/sqlite` from 1.59.0 to 1.60.1
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.59.0...v1.60.1)

---
updated-dependencies:
- dependency-name: modernc.org/sqlite
  dependency-version: 1.60.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
…rc/go-deps-5fbebd389c

chore(deps): bump modernc.org/sqlite from 1.59.0 to 1.60.1 in /src in the go-deps group
Bumps the go-deps group in /src with 2 updates: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go) and [golang.org/x/sys](https://github.com/golang/sys).


Updates `github.com/mark3labs/mcp-go` from 1.1.1 to 1.2.1
- [Release notes](https://github.com/mark3labs/mcp-go/releases)
- [Commits](mark3labs/mcp-go@v1.1.1...v1.2.1)

Updates `golang.org/x/sys` from 0.48.0 to 0.49.0
- [Commits](golang/sys@v0.48.0...v0.49.0)

---
updated-dependencies:
- dependency-name: github.com/mark3labs/mcp-go
  dependency-version: 1.2.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: golang.org/x/sys
  dependency-version: 0.49.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
…rc/go-deps-7b16cbcd43

chore(deps): bump the go-deps group in /src with 2 updates
Bumps the go-deps group in /src with 1 update: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go).


Updates `github.com/mark3labs/mcp-go` from 1.2.1 to 1.3.0
- [Release notes](https://github.com/mark3labs/mcp-go/releases)
- [Commits](mark3labs/mcp-go@v1.2.1...v1.3.0)

---
updated-dependencies:
- dependency-name: github.com/mark3labs/mcp-go
  dependency-version: 1.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
…rc/go-deps-7b668c2967

chore(deps): bump github.com/mark3labs/mcp-go from 1.2.1 to 1.3.0 in /src in the go-deps group
Bumps the go-deps group in /src with 2 updates: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go) and [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).


Updates `github.com/mark3labs/mcp-go` from 1.3.0 to 1.4.0
- [Release notes](https://github.com/mark3labs/mcp-go/releases)
- [Commits](mark3labs/mcp-go@v1.3.0...v1.4.0)

Updates `modernc.org/sqlite` from 1.60.1 to 1.61.0
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.60.1...v1.61.0)

---
updated-dependencies:
- dependency-name: github.com/mark3labs/mcp-go
  dependency-version: 1.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: modernc.org/sqlite
  dependency-version: 1.61.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
…rc/go-deps-36130ccb47

chore(deps): bump the go-deps group in /src with 2 updates
runCommandWithTimeout only killed the sh process on deadline; a child
that inherited the output pipe kept cmd.Run blocked until it exited, so
the 124 timeout path was never reached.

Run commands in their own process group and SIGKILL the group on
cancel (Unix), and set cmd.WaitDelay so Wait stops reading inherited
pipes 5s after the shell exits or is killed. A shell that exits 0 while
a background child still holds the pipe is reported as success.

Fixes 5uck1ess#126
Treating exec.ErrWaitDelay as success let a truncated stream pass
expect/require/gate checks: '(sleep 7; echo FAIL) & echo PASS' reported
only PASS with exit 0. Return an error instead (the step halts) and
SIGKILL the leftover process group so it does not outlive the step.
Background jobs that redirect their output are unaffected.
… Bash carve-out

The substring match let any command through by appending a comment such as
'# codex-companion.mjs'. Parse the command into shell words and only allow a
single 'node <path>/{codex,gemini}-companion.mjs ...' call (optionally wrapped
in bash/sh -c), rejecting unquoted operators, comments, redirects, backticks
and $( ) substitution.
Cmd.Wait reports *exec.ExitError in preference to ErrWaitDelay, so a
shell that exits non-zero while a background child holds the output
pipe slipped past the incomplete-output check and its truncated output
reached expect/require/gate validation (e.g. an expect: failure step
accepting a captured PASS before the child's FAIL).

Own the output pipe instead: after the shell exits, drain it for up to
commandWaitDelay; if it is still open, the output is incomplete, so
kill the leftover process group and fail the step whatever the exit
code was.
5uck1ess and others added 30 commits November 4, 2026 05:15
…-run spend

- claude max-turns responses carry no result text; use errors[] and the
  subtype in the error message.
- runStep/runLoop record and charge the cost a failed run reports, so a
  loop of failing claude runs can't blow through the budget.
…top on last message alone

- subagent-stop also searches the tail of agent_transcript_path and
  recognises cargo/linter output, so a concise final summary isn't blocked.
- stop-gate only uses last_assistant_message to supplement a readable
  transcript; with no transcript it skips the cross-domain check. grep -a
  tolerates a multibyte character split by the byte-offset tail.
…n halt

- Guard treats a parallel dispatcher like a prompt step (Agent/Task allowed,
  Write/Edit/Bash blocked under hard). MCP now parks on the dispatcher, and
  the old allow-all default turned the tri-* fence off.
- A dispatcher without its own enforce is soft if any child is soft, so
  research/self-audit fan-outs keep their WebSearch/Bash.
- devkit_advance without output clears the step's earlier output, so a
  revisited step can't branch on a stale value.
- Dispatch response shows each child's require: contract.
- haltWorkflow persists the halted status before clearing state.
- Validation rejects branch: on a parallel dispatcher.
${PWN@P} prompt-expands the variable and runs any $(...) it holds, even
inside double quotes, so a value exported by an earlier step could execute
through an otherwise allowed companion call.
…d loop iterations

runParallel dropped the spend of failed children (including all-failed
dispatches), and runLoop didn't charge iterations that failed their
require: check, so overBudget under-counted and loops could overspend.
…check after transcript

Grepping the raw transcript tail counted file contents and task text that
mention 'go test' as evidence. Extract only Bash tool_use commands from the
JSONL. The suspiciously-short check now applies only when the transcript
shows no commands, so 'Done.' after a real test run isn't blocked.
fix(hooks): read real Claude Code hook fields; stop rtk auto-approving compound commands
Bumps the go-deps group in /src with 2 updates: [github.com/mark3labs/mcp-go](https://github.com/mark3labs/mcp-go) and [modernc.org/sqlite](https://gitlab.com/cznic/sqlite).


Updates `github.com/mark3labs/mcp-go` from 1.4.0 to 1.5.0
- [Release notes](https://github.com/mark3labs/mcp-go/releases)
- [Commits](mark3labs/mcp-go@v1.4.0...v1.5.0)

Updates `modernc.org/sqlite` from 1.61.0 to 1.61.1
- [Release notes](https://gitlab.com/cznic/sqlite/tags)
- [Changelog](https://gitlab.com/cznic/sqlite/blob/master/CHANGELOG.md)
- [Commits](https://gitlab.com/cznic/sqlite/compare/v1.61.0...v1.61.1)

---
updated-dependencies:
- dependency-name: github.com/mark3labs/mcp-go
  dependency-version: 1.5.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: go-deps
- dependency-name: modernc.org/sqlite
  dependency-version: 1.61.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: go-deps
...

Signed-off-by: dependabot[bot] <support@github.com>
…rc/go-deps-df70579d80

chore(deps): bump the go-deps group in /src with 2 updates
fix(mcp): skip parallel children, gate-respecting loops, end: steps
fix(guard): require a direct companion invocation for the prompt+hard Bash carve-out
fix(runners): treat claude is_error / non-zero exit as a failed run
Add an Env field to RunOpts and a childEnv helper that appends it to the
inherited environment (nil when empty, so existing callers are unchanged).
The claude, codex and gemini runners apply it to the exec.Cmd. devkit_ask
needs this to pass DEVKIT_ASK_DEPTH down the process tree.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgRGnqs2seLKpMvT585cYf
Replace the placeholder `agy exec [-C dir] -` argv, which was modelled on
codex and never run against agy, with `agy --dangerously-skip-permissions
--print` and the prompt on stdin:

- 5uck1ess#102 smoke-tested the stdin + --print shape against agy v1.0.0 (argv
  prompts were ignored there), and the headless reference documents the
  flag. --print goes last because the v1.5.2 release notes record a fix
  for a valueless prompt flag swallowing the next flag as its prompt.
- --dangerously-skip-permissions is the agy analogue of `gemini -y`;
  headless agy cannot prompt, so without it tools needing approval are
  soft-denied and the run still exits 0.
- agy has no working-directory flag, so WorkDir is applied via cmd.Dir
  only. --sandbox is documented but deliberately not defaulted: the CLI
  reports "terminal sandbox unavailable" on some hosts and the combination
  has not been exercised; opt in with AGY_ARGS.

Carry over the exit-0 "Error: ..." stdout heuristic (agyOutputIsError)
from feat/agy-runner so an agy-emitted error is never returned as a
model answer, honour RunOpts.Env, and expand {workdir} in AGY_ARGS to "."
when no WorkDir is set instead of leaving a dangling flag.

Tests: argv table incl. AGY_ARGS/{workdir}, AGY_CMD, Available, the error
heuristic, and a fake `agy` on PATH covering stdin piping, Env, cwd,
exit-0 error lines and non-zero exits with stderr (unix only, like
claude_run_test.go).

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgRGnqs2seLKpMvT585cYf
…imeout

- Recursion: the handler reads DEVKIT_ASK_DEPTH from its own environment
  and refuses once it reaches askMaxDepth (1); every peer is launched with
  the depth incremented via RunOpts.Env, so a peer that loads the devkit
  MCP server inherits the guard and cannot ask onward. A malformed value
  is refused too.
- workdir must be an existing directory; validated before anything is
  spawned.
- Optional `timeout` argument in seconds (default commandTimeout, max
  askMaxTimeout = 30m); zero, negative, NaN, non-numeric or over-cap
  values are rejected, and the cap is checked before converting to
  Duration so nothing can overflow. A deadline hit is reported as
  "<peer> timed out after <d>" instead of a raw kill signal.
- Peer discovery goes through askDetectRunners so tests can inject a fake
  peer and assert the prompt, workdir, Env and deadline the peer receives.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SgRGnqs2seLKpMvT585cYf
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants