Skip to content

fix(safety): parseAxmeGate strips trailing quote/punct from pr/repo (B-008)#107

Merged
George-iam merged 1 commit intomainfrom
fix/axme-gate-regex-20260414
Apr 14, 2026
Merged

fix(safety): parseAxmeGate strips trailing quote/punct from pr/repo (B-008)#107
George-iam merged 1 commit intomainfrom
fix/axme-gate-regex-20260414

Conversation

@George-iam
Copy link
Copy Markdown
Contributor

Summary

Fixes B-008: when the agent placed #!axme pr=N repo=OWNER/REPO inside a git commit -m "..." quoted string, the safety hook fail-closed on every retry with Cannot verify PR #N status (gh CLI error). The greedy \S+ regex captured the closing " as part of the repo name, then gh pr view rejected the malformed value and the hook treated it as a network error.

Discovered live during axme-blog PR #6 work — the agent (me) burned ~6 retry cycles before realising the regex, not the network, was eating the call.

Root cause

src/storage/safety.ts:341-344\S+ matched anything non-whitespace including ", ', `. So:

git commit -m "fix #!axme pr=6 repo=AxmeAI/axme-blog"

repo = "AxmeAI/axme-blog\"" (quote glued on) → gh pr view 6 --repo "AxmeAI/axme-blog\"" ...gh rejects → execSync throws → checkAxmeGate returns fail-closed verdict (correct safety behavior, wrong root cause).

Fix

src/storage/safety.ts:

  • Tighten value capture from \S+ to [^\s"']+for bothpr=andrepo=` so quote/backtick characters never end up inside the captured value.
  • Defensively strip trailing ), ], ,, ;, . after capture (covers $(...) expansions, comment lists, other shell punctuation).
  • Reject parses where stripping leaves an empty value (returns null instead of building a bad lookup).
  • AXME_GATE_INSTRUCTION now reminds the agent to put the marker AFTER the closing " of -m "...", not inside it.

test/axme-gate.test.ts:

  • B-008 reproducer: marker placed inside -m "..." parses cleanly.
  • Same for '...' and `...`.
  • Trailing ) and , from $(...) / comment list also stripped.
  • pr=" alone (nothing left after strip) returns null instead of constructing a bad gate.

Verification

  • npm test489/489 pass (5 new cases; previous baseline 484)
  • npx tsc --noEmit — clean
  • npm run build — clean

Test plan

  • Existing gate tests still pass (no regression on the LAST-marker-wins, HEREDOC, or live gh checks)
  • Manual: in a follow-up agent session, place #!axme inside -m "..." and confirm hook no longer blocks (slated for v0.5.0 release smoke test)

Fixes B-008.

🤖 Generated with Claude Code

…B-008)

When the agent placed `#!axme pr=N repo=OWNER/REPO` INSIDE a
`git commit -m "..."` quoted string, the safety hook fail-closed
on every retry with `Cannot verify PR #N status (gh CLI error)` —
because `\S+` is greedy and captured the closing `"` as part of
the repo name. The hook then shelled out to:

    gh pr view N --repo "OWNER/REPO\"" --json state --jq .state

which `gh` rejects → execSync throws → fail-closed. Discovered
during axme-blog PR #6 work after ~6 blocked retries before
realising the regex, not the network, was eating the call.

Changes (src/storage/safety.ts):
- Tighten value capture from `\S+` to `[^\s"'`]+` for both `pr=`
  and `repo=` so quote/backtick characters never end up inside
  the captured value.
- After capture, defensively strip trailing `)`, `]`, `,`, `;`, `.`
  via a single regex. Covers $(...) expansions, comment lists,
  and other shell punctuation that can sneak in next to the
  marker.
- Reject parses where stripping leaves an empty value (returns
  null instead of producing a bad lookup).
- Update AXME_GATE_INSTRUCTION to remind the agent to put the
  marker AFTER the closing `"` of any -m argument, not inside
  it. The previous message described the format but not the
  placement, so under retry pressure the agent kept re-emitting
  the same broken pattern.

Tests (test/axme-gate.test.ts):
- B-008 reproducer: marker placed inside `-m "..."` parses
  cleanly to repo without trailing quote.
- Same for `-m '...'` and `-m \`...\``.
- Trailing `)` and `,` from $(...) / comment list also stripped.
- pr=" alone (nothing left after strip) returns null instead
  of constructing a bad gate.

Verified:
- 489/489 unit tests pass (5 new cases; previous baseline 484)
- `tsc --noEmit` clean
- `npm run build` clean

Fixes B-008.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@George-iam George-iam merged commit d36fb96 into main Apr 14, 2026
George-iam added a commit that referenced this pull request Apr 14, 2026
Patch release containing three bug fixes already merged on main:

- B-006 (#105): audit worker fileURLToPath(undefined) crash on every
  session close. pathToClaudeCodeExecutable now set on all three
  direct sdk.query() call sites in session-auditor + memory-extractor.
- B-007 (#106): classifyError vocabulary extended with node_invalid_arg
  / module_not_found / spawn_error / out_of_memory / type_error /
  reference_error. audit_complete failures now stamp category="audit"
  and fatal=false so they index correctly on the backend.
- B-008 (#107): #!axme safety gate regex tightened so a closing quote
  from a surrounding -m "..." string no longer gets glued onto the
  parsed repo name. Hook stops false-blocking commits on every retry.

Files bumped:
- package.json
- .claude-plugin/plugin.json
- templates/plugin-README.md (version badge)

CHANGELOG entry added under [0.2.8] - 2026-04-14.

Verified: 489/489 unit tests pass, npx tsc --noEmit clean,
npm run build clean.

Release flow after this PR merges:
1. user runs: git tag v0.2.8 && git push origin v0.2.8
2. release-binary.yml workflow auto-runs the chain:
   build (4 platforms) -> GitHub Release ->
   npm publish @axme/code@0.2.8 -> sync to axme-code-plugin

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.

1 participant