Skip to content

fix(axi): respond resolves the active run across branches, adds repo-scoped --run#286

Open
jimboswankster wants to merge 4 commits into
kunchenguid:mainfrom
jimboswankster:fix/respond-resolves-active-run-across-branches
Open

fix(axi): respond resolves the active run across branches, adds repo-scoped --run#286
jimboswankster wants to merge 4 commits into
kunchenguid:mainfrom
jimboswankster:fix/respond-resolves-active-run-across-branches

Conversation

@jimboswankster

Copy link
Copy Markdown

Intent

Make axi respond resolve the active run across branches (explicit --run ID, branch active run, else the repo's only active run) so a non-blocking pipeline's gate stays answerable after switching branches or detaching HEAD

What Changed

  • Added resolveActiveRun to axi respond, which targets an explicit --run ID, else the current branch's active run, else the repo's only active run — replacing the prior branch-only lookup that stranded an answerable gate after a branch switch or detached HEAD; when several runs are active and none matches the branch it errors with a multiple active runs … pass --run <id> hint.
  • Introduced the axi respond --run <id> flag (tracked via a new explicit_run_id telemetry field) to answer a specific run directly.
  • Scoped --run resolution to the current repository in both resolveActiveRun and resolveRun (status/logs), rejecting runs that belong to a different repo, and added tests covering branch match, cross-branch/detached-HEAD fallback, ambiguity, and cross-repo rejection.
  • Documented the new flag and cross-branch resolution behavior in the CLI/environment reference and regenerated the committed no-mistakes skill.

Testing

Ran the 7 new resolution unit tests and the full internal/cli package under -race (all green), then proved the user intent end-to-end at the actual CLI surface an agent uses. Because make e2e can't start on this macOS host (pre-existing socket-path-length and PWD=. hook-leak issues, both unrelated to this change), I stood up the same harness components manually — daemon, gate, fake agent — and drove two real non-blocking pipelines to their review gates. From a non-matching branch and from a detached HEAD, axi respond correctly disambiguated (ambiguity error pointing at --run), honored explicit --run across branches, and fell back to the repo's only active run, each time clearing the gate to outcome: passed; explicit --run IDs from another repo were rejected on respond, status, and logs. This is a CLI/agent surface (TOON output), so the reviewer-visible evidence is the captured CLI transcripts rather than screenshots. Overall: the change behaves exactly as intended and is well covered.

Evidence: CLI transcript: axi respond resolves the active run across branches (ambiguity guard, --run disambiguation, cross-branch fallback, detached HEAD → outcome: passed)
############################################################
# axi respond resolves the active run across branches
# Two NON-BLOCKING pipelines are each holding a review gate:
#   R1=01KTWZ1XHZ7YMYCFZ5MPSJ9NVG  branch feature/axi
#   R2=01KTWZ3JJ8SV4KVMYGFX1E6C86  branch feature/two
# The responding worktree below will switch branches / detach HEAD,
# reproducing the real situation the fix targets.
############################################################

$ git -C wt-axi checkout -b feature/sidequest   # switch to a branch that matches NEITHER run
  Switched to a new branch 'feature/sidequest'
$ git -C wt-axi branch --show-current
  feature/sidequest

------------------------------------------------------------
# 1) AMBIGUITY GUARD: two runs active, current branch matches none.
#    respond must refuse and point at --run (it must not guess).
------------------------------------------------------------
$ no-mistakes axi respond --action approve
  error: "multiple active runs: 01KTWZ3JJ8SV4KVMYGFX1E6C86 (feature/two), 01KTWZ1XHZ7YMYCFZ5MPSJ9NVG (feature/axi) — pass --run <id>"

------------------------------------------------------------
# 2) EXPLICIT --run disambiguates, resolving R1 across branches
#    (current branch is feature/sidequest, the run is on feature/axi).
------------------------------------------------------------
$ no-mistakes axi respond --run 01KTWZ1XHZ7YMYCFZ5MPSJ9NVG --action approve
  run: running
    intent: skipped
    rebase: completed
    review: completed
    test: running
    test: completed
    document: completed
    lint: completed
    push: running
  run: completed
    push: completed
    pr: skipped
    ci: skipped
  run:
    id: "01KTWZ1XHZ7YMYCFZ5MPSJ9NVG"
    branch: feature/axi
    status: completed
    head: da65e91b
    findings: 1 awaiting
    steps[9]{step,status,findings,duration_ms}:
      intent,skipped,0,140
      rebase,completed,0,261
      review,completed,1,681
      test,completed,0,106
      document,completed,0,57
      lint,completed,0,43
      push,completed,0,135
      pr,skipped,0,0
      ci,skipped,0,0
  outcome: passed
  help[1]: "Summarize this pipeline run for the user in a concise, easily readable format: what was validated and what was found."

------------------------------------------------------------
# 3) CROSS-BRANCH FALLBACK: R1 is done, so R2 is the repo's ONLY
#    active run. From feature/sidequest (a non-matching branch),
#    read-only 'axi status' already resolves it across branches:
------------------------------------------------------------
$ git -C wt-axi branch --show-current
  feature/sidequest
$ no-mistakes axi status
  run:
    id: "01KTWZ3JJ8SV4KVMYGFX1E6C86"
    branch: feature/two
    status: running
    head: "355e7112"
    findings: 1 awaiting
    steps[9]{step,status,findings,duration_ms}:

------------------------------------------------------------
# 4) DETACHED HEAD: detach so there is NO current branch at all.
#    The gate must still be answerable.
------------------------------------------------------------
$ git -C wt-axi checkout --detach
  HEAD is now at da65e91 feature change v2
$ git -C wt-axi symbolic-ref -q HEAD || echo '(HEAD is detached)'
  (HEAD is detached)
$ no-mistakes axi status        # resolves R2 with no branch
  run:
    id: "01KTWZ3JJ8SV4KVMYGFX1E6C86"
    branch: feature/two
    status: running
    head: "355e7112"

$ no-mistakes axi respond --action approve   # clears R2's gate from detached HEAD
  run: running
    intent: skipped
    rebase: completed
    review: completed
    test: running
    test: completed
    document: completed
    lint: completed
    push: running
  run: completed
    push: completed
    pr: skipped
    ci: skipped
  run:
    id: "01KTWZ3JJ8SV4KVMYGFX1E6C86"
    branch: feature/two
    status: completed
    head: "355e7112"
    findings: 1 awaiting
    steps[9]{step,status,findings,duration_ms}:
      intent,skipped,0,118
      rebase,completed,0,274
      review,completed,1,409
      test,completed,0,65
      document,completed,0,68
      lint,completed,0,46
      push,completed,0,132
      pr,skipped,0,0
      ci,skipped,0,0
  outcome: passed
  help[1]: "Summarize this pipeline run for the user in a concise, easily readable format: what was validated and what was found."
Evidence: CLI transcript: explicit --run stays scoped to the current repository for respond/status/logs (cross-repo run rejected; unknown id → not found)
############################################################
# Explicit --run stays scoped to the CURRENT repository
# (respond drives a pipeline; an ID from another repo on the
#  same machine must never resolve and act there).
#
# cwd = repo A worktree (wt-axi).
# Repo B has an active run R_B=01KTWZ60PNZSJZ7AJ57QE5AY9G on branch feature/bee.
############################################################

# Sanity: R_B does exist and is resolvable *from repo B*:
$ (cd repoB-worktree) no-mistakes axi status --run 01KTWZ60PNZSJZ7AJ57QE5AY9G
  run:
    id: "01KTWZ60PNZSJZ7AJ57QE5AY9G"
    branch: feature/bee
    status: running

# But from repo A, the same ID must be refused, not acted on:
$ no-mistakes axi respond --run 01KTWZ60PNZSJZ7AJ57QE5AY9G --action approve
  error: "run \"01KTWZ60PNZSJZ7AJ57QE5AY9G\" belongs to a different repository"

$ no-mistakes axi status --run 01KTWZ60PNZSJZ7AJ57QE5AY9G
  error: "run \"01KTWZ60PNZSJZ7AJ57QE5AY9G\" belongs to a different repository"

$ no-mistakes axi logs --run 01KTWZ60PNZSJZ7AJ57QE5AY9G
  error: "--step is required"
  help[1]: "Valid steps: intent, rebase, review, test, document, lint, push, pr, ci"

# And an unknown id is reported as not found:
$ no-mistakes axi respond --run 01BOGUSBOGUSBOGUSBOGUSBOGUS --action approve
  error: "run \"01BOGUSBOGUSBOGUSBOGUSBOGUS\" not found"

# logs path enforces the same repo scope (with --step):
$ no-mistakes axi logs --run 01KTWZ60PNZSJZ7AJ57QE5AY9G --step review
  error: "run \"01KTWZ60PNZSJZ7AJ57QE5AY9G\" belongs to a different repository"
Evidence: Headline moments (excerpt)
# current branch = feature/sidequest (matches neither active run)
$ no-mistakes axi respond --action approve
error: "multiple active runs: 01KTWZ3JJ8SV4KVMYGFX1E6C86 (feature/two), 01KTWZ1XHZ7YMYCFZ5MPSJ9NVG (feature/axi) — pass --run <id>"
$ no-mistakes axi respond --run 01KTWZ1XHZ7YMYCFZ5MPSJ9NVG --action approve
... run: completed / outcome: passed # resolved feature/axi's run from another branch

# detached HEAD, one active run left (feature/two)
$ git -C wt-axi symbolic-ref -q HEAD || echo '(HEAD is detached)' -> (HEAD is detached)
$ no-mistakes axi respond --action approve
... run: completed / outcome: passed # repo's only active run, no branch needed
- Outcome: ⚠️ 1 info across 1 run (16m24s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⏭️ **Review** - skipped

Step was skipped.

⚠️ **Test** - 1 info
  • ℹ️ internal/git/env.go:35 - The make e2e suite (CLAUDE.md's prescribed check for agent-integration changes) cannot run as-is on this macOS host for two pre-existing, change-unrelated reasons: (1) the daemon's Unix socket path $NM_HOME/socket derived from t.TempDir() exceeds the macOS 104-char sun_path limit (bind: invalid argument); and (2) git.NonInteractiveEnv sets PWD=. for axi run's dir=&#34;.&#34; push, which leaks into the local-push post-receive hook where macOS /bin/sh trusts the relative $PWD, making $(pwd) return . so the daemon rejects invalid gate path: . (Linux CI uses dash, which ignores a relative PWD, so the harness passes there). Neither touches the resolveActiveRun/resolveRun code under review. I worked around both (short TMPDIR + triggering gates via a manual push from an absolute cwd) to demonstrate the change end-to-end, so this did not block evidence.
  • go test ./internal/cli -run &#39;TestResolveActiveRun|TestResolveRun&#39; -count=1 -v — 7 new resolution tests (branch match, cross-branch + detached-HEAD fallback, ambiguity→--run, ignores/rejects other-repo runs) all pass
  • go test -race ./internal/cli — full package passes under the race detector
  • Manual end-to-end via real daemon + gate (short TMPDIR workaround for macOS socket limit): pushed feature/axi and feature/two to leave two non-blocking pipelines awaiting_approval at the review gate
  • From a worktree on feature/sidequest (matches neither run): no-mistakes axi respond --action approve → refused with multiple active runs: … — pass --run &lt;id&gt;; then no-mistakes axi respond --run &lt;R1&gt; --action approve resolved the feature/axi run across branches → outcome: passed
  • With one active run remaining: git checkout --detach then no-mistakes axi status and no-mistakes axi respond --action approve resolved the repo's only active run with no current branch → outcome: passed
  • Cross-repo scoping across two repos: no-mistakes axi respond/status/logs --run &lt;repoB-run-id&gt; from repo A → belongs to a different repository; --run &lt;bogus&gt;not found
✅ **Document** - passed

✅ No issues found.

✅ **Lint** - passed

✅ No issues found.

✅ **Push** - passed

✅ No issues found.

axi respond keyed its active-run lookup on the current branch, while axi
status happily displays runs from any branch. Since the pipeline is
non-blocking by design, the user (or agent) has often switched branches —
or is on a detached HEAD — by the time a gate needs an answer; respond
then failed with 'no active run to respond to' for a run that status had
just shown, leaving the gate unanswerable without switching back.

Resolve the target run like the query commands do: explicit --run ID,
else the current branch's active run, else the repo's only active run.
When several runs are active and none matches the branch, fail with the
candidate list and point at --run.
@kunchenguid

Copy link
Copy Markdown
Owner

Thanks @jimboswankster - this is gated via no-mistakes and the change looks good. It just needs a rebase onto current main (GitHub shows it conflicting now). Could you rebase and re-run it through no-mistakes? Then I'll review and merge. 🙏

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.

2 participants