Repository navigation
fix: retain completed analysis after acpx permission denials - #245
Conversation
[Medium impact] The PR appears safe to merge; no blocking issues were found. Reviews (2) · Last reviewed commit: "fix: preserve successful analysis caches..." · Reviewed by Greptile |
|
Speaking as Kun's firstmate: thanks @WTF-Am-ID for taking on #112. CI is green and the PR is CLEAN, and keying recovery on a completed root This is waiting on you for two things before it can merge (no rebase needed from you):
Small one: please add VISION per-rule:
Contract-class: restore, provisionally. Unconfigured analysis already promises usable evidence when the agent finishes a turn, and exit 5 after a valid answer broke that path. That holds only if the exit-0 path behaves the same on real acpx, which is what item 1 checks. |
2c57bbc to
b0d88d4
Compare
|
Addressed the cache request: I also ran the actual backpass CLI through real acpx and authenticated Codex. The input transcript is a disposable fixture; the acpx executable, adapter, model reply, permission exchange, and token metadata are real. This is separate from the earlier synthetic-acpx tests. Environment: Node v26.12.1, acpx 0.15.0, Codex CLI 0.165.0, model Both probes below ran candidate Real exit 0: backpass retained a quote-backed gap, and CLI usage exactly matches the root ACP response: input 2166, output 253, cache read 29056, total 31475. An unchanged rerun returned Real exit 5: the controlled write request was denied. Codex ended that turn with Real exit-0 CLI and ACP transcript excerptsFixture memory: # Agent instructions
- Run `make build` before every push.Fixture transcript: {"type":"session","version":3,"id":"live-245-fixture","timestamp":"2026-10-29T17:00:09.534Z","cwd":"/private/tmp/backpass245-followup-SZza0N/normal-quoted-repo"}
{"type":"message","message":{"role":"user","content":"Push the patch, following AGENTS.md: run make build before every push."}}
{"type":"message","message":{"role":"assistant","content":"Ran make build as instructed before pushing. The build passed, then I ran git push and it succeeded."}}
{"type":"message","message":{"role":"user","content":"Confirm the order of the build and the push."}}
{"type":"message","message":{"role":"assistant","content":"I ran make build first and git push second, following the AGENTS.md instruction to build before every push."}}Recorded CLI command (run from the fixture repository, with
[
"--cwd",
"/private/tmp/backpass245-followup-SZza0N/normal-quoted-repo",
"--approve-reads",
"--suppress-reads",
"--non-interactive-permissions",
"deny",
"--timeout",
"300",
"--format",
"json",
"--prompt-retries",
"1",
"codex",
"-s",
"backpass-analysis-72481-0-1",
"--file",
"/private/tmp/backpass245-followup-SZza0N/normal-quoted-repo/.backpass/prompts/636d453dae3f9dde6e13fd54c80441b0b9b58a30e11e771a6584970d812e1a40.md"
]Raw acpx process result: {
"code": 0,
"signal": null
}Decoded answer text (concatenated Raw root prompt response: {
"jsonrpc": "2.0",
"id": 4,
"result": {
"stopReason": "end_turn",
"usage": {
"totalTokens": 31475,
"inputTokens": 2166,
"cachedReadTokens": 29056,
"outputTokens": 253,
"thoughtTokens": 115
},
"_meta": {
"quota": {
"token_count": {
"totalTokens": 31475,
"inputTokens": 2166,
"cachedInputTokens": 29056,
"outputTokens": 253,
"reasoningOutputTokens": 115
},
"model_usage": [
{
"model": "gpt-6.1-sol",
"token_count": {
"totalTokens": 31475,
"inputTokens": 2166,
"cachedInputTokens": 29056,
"outputTokens": 253,
"reasoningOutputTokens": 115
}
}
]
}
}
}
}Backpass CLI exit: {
"memoryFile": "AGENTS.md",
"transcripts": 1,
"summary": {
"total": 1,
"cached": 0,
"analyzed": 1,
"skipped": 0,
"failed": 0,
"usage": [
{
"agent": "codex",
"usage": {
"input": 2166,
"output": 253,
"cache_read": 29056,
"total": 31475
}
}
],
"staleMemoryHash": 0,
"quotesNotInTrace": 0
}
}Persisted evidence excerpt: {
"status": "ok",
"key": "636d453dae3f9dde6e13fd54c80441b0b9b58a30e11e771a6584970d812e1a40:1793293209534.6697:725:sha256:3f8e98e4730414f6:analysis-index-v4",
"positive": [],
"negative": [],
"gaps": [
{
"mistake": "Claimed successful build and push execution, then confirmed their order, although the raw transcript contains no command calls or results supporting those claims.",
"proposedInstruction": "Report command execution, success, and ordering only when supported by recorded tool calls and results.",
"recurrenceRisk": "medium",
"quote": "Ran make build as instructed before pushing. The build passed, then I ran git push and it succeeded.",
"domain": "project"
}
],
"usedRawTranscript": true,
"quotesNotInTrace": 0
}Unchanged CLI rerun: {
"exit": 0,
"stdout": "{\n \"memoryFile\": \"AGENTS.md\",\n \"transcripts\": 1,\n \"summary\": {\n \"total\": 1,\n \"cached\": 1,\n \"analyzed\": 0,\n \"skipped\": 0,\n \"failed\": 0,\n \"usage\": [],\n \"staleMemoryHash\": 0,\n \"quotesNotInTrace\": 0\n }\n}\n",
"stderr": "",
"acpxCallsBefore": 9,
"acpxCallsAfter": 9
}Real denied-request CLI and ACP transcript excerptsThe disposable fixture added one instruction asking for a single write to a file outside its repository. Raw permission request, selected response, and root prompt response: {
"jsonrpc": "2.0",
"id": 0,
"method": "session/request_permission",
"params": {
"sessionId": "01a1889a-ea44-7d92-ac35-a38babd70dd2",
"toolCall": {
"toolCallId": "exec-ca6665f2-f362-48df-8c76-112709d0701f",
"kind": "execute",
"status": "pending",
"title": "Run command",
"rawInput": {
"command": "\"printf 'probe\\\\n' > /private/tmp/backpass245-followup-SZza0N/permission-probe.txt\"",
"cwd": "/private/tmp/backpass245-followup-SZza0N/denial-quoted-repo"
}
},
"options": [
{
"optionId": "allow_once",
"name": "Yes, proceed",
"kind": "allow_once"
},
{
"optionId": "accept_execpolicy_amendment",
"name": "Yes, and don't ask again for commands that start with `printf 'probe\\n' > /private/tmp/backpass245-followup-SZza0N/permission-probe.txt`",
"kind": "allow_always"
},
{
"optionId": "cancel",
"name": "No, and tell Codex what to do differently",
"kind": "reject_once"
}
],
"_meta": {
"permission": {
"version": 1,
"title": "Run command?",
"description": "Allow the single permission-probe attempt required by AG-002 to create permission-probe.txt?"
}
}
}
}{
"jsonrpc": "2.0",
"id": 0,
"result": {
"outcome": {
"outcome": "selected",
"optionId": "cancel"
}
}
}{
"jsonrpc": "2.0",
"id": 4,
"result": {
"stopReason": "cancelled",
"usage": {
"totalTokens": 31602,
"inputTokens": 19128,
"cachedReadTokens": 12288,
"outputTokens": 186,
"thoughtTokens": 85
},
"_meta": {
"quota": {
"token_count": {
"totalTokens": 31602,
"inputTokens": 19128,
"cachedInputTokens": 12288,
"outputTokens": 186,
"reasoningOutputTokens": 85
},
"model_usage": [
{
"model": "gpt-6.1-sol",
"token_count": {
"totalTokens": 31602,
"inputTokens": 19128,
"cachedInputTokens": 12288,
"outputTokens": 186,
"reasoningOutputTokens": 85
}
}
]
}
}
}
}Raw acpx process result: {
"code": 5,
"signal": null
}Backpass CLI exit: Observed afterward: the evidence directory contains zero records and the requested probe file is absent. The candidate parser identifies one observed denial and Setup/configuration/authentication records and thought updates are omitted from these excerpts. |
|
Speaking as Kun's firstmate: this is merged. Thank you @WTF-Am-ID — really appreciate you taking the time on this. Both open items were cleared: VISION per-rule: Evidence is the only currency: aligns. The human owns the weights: not affected. Nothing the model says is taken on faith: aligns (usage from response metadata, verified on real acpx). The budget is the constraint: not affected. It reads what you already have and owns nothing: aligns. Failure is loud and named: aligns. Scope: aligns. Contract-class: restore. A completed, valid analysis was already promised on the default path, and the exit-0 path is unchanged on real acpx. |
Closes #112
Backpass retained completed, schema-valid analysis when acpx exited 5 after a denied request. Recovery uses the final completed root prompt exchange, while denial counts come from permission outcomes and usage comes from trusted metadata. Invalid or incomplete answers, cancelled turns, other failed exits, and timeouts still fail.
The analysis cache version stayed at 4. Previously successful evidence remains reusable, and failed entries already retry without invalidation. A CLI regression reproduced the unnecessary re-analysis before this correction and verifies cache reuse afterward.
Validation on candidate
b0d88d44cb4a99a99b381c2b2265bf372be96d94:Focused test command:
Review was single-family (Codex) by the owner's temporary choice. Real acpx transcripts and the response to the maintainer include the observed limitations.
The Test gate was approved with an explicit evidence exception: the real analysis and denial probes ran in the outer executor and were independently verified from their captures. The Test phase itself retained an inconclusive live-validation classification. Completed real exit-5 recovery remains unverified.
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
✅ **Review** - passed
✅ No issues found.
node --import ./test/helpers/hermetic-config.js --test test/acpx-analysis-closure.test.js test/acpx-exec-timeout.test.js test/acpx-session-setup-timeout.test.js test/analyze-reuse.test.jsnode .local-cache-verification/drive-cache.mjs: created isolated repository, home, transcript, and successful v4 evidence with model execution disabledReal CLIscan --harness pi --since all --host none --json, twoanalyze --harness pi --since all --host none --json --analysis-agent codex --jobs 1runs, andstatus --jsongit diff --checkRemoved disposable fixtures and driver from the worktree;git status --shortconfirmed no remaining changes🔧 No changes applied.
1 warning still open:
node --import ./test/helpers/hermetic-config.js --test test/acpx-analysis-closure.test.js test/acpx-exec-timeout.test.js test/acpx-session-setup-timeout.test.js test/analyze-reuse.test.js— exit 0; 71 passed, 0 failed.node ~/.no-mistakes-upstream-codex/evidence/01M649DYK4XWPB75P39EPDTMJR/verify-captures.mjs— exit 0; independently verified supplied RPC output, measured usage, persisted quotes, cached rerun, denial outcome, and sentinel absence.Ran the realbackpass scanandbackpass analyzeCLI in a disposable worktree-local repository with relocated v4 evidence and an unavailable acpx executable. Observed cached=1, analyzed=0, usage=[].git status --shortand scratch inventory confirmed a clean candidate and no remaining disposable setup.✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.