Skip to content

fix(exec): stop false INCOMPLETE downgrades on conversational final messages#608

Merged
kevincodex1 merged 3 commits into
Gitlawb:mainfrom
euxaristia:fix/self-report-incompletion-false-positives
Jul 10, 2026
Merged

fix(exec): stop false INCOMPLETE downgrades on conversational final messages#608
kevincodex1 merged 3 commits into
Gitlawb:mainfrom
euxaristia:fix/self-report-incompletion-false-positives

Conversation

@euxaristia

@euxaristia euxaristia commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

Summary

Headless zero exec runs driven by a chat frontend get wrongly downgraded to INCOMPLETE (exit 4) by the completion gate's self-report check. Two distinct causes, fixed by the two commits:

  1. selfReportedIncompletion matched inability stems anywhere in the final message, so a recap of a past exchange tripped it. Real transcript: "You asked if I could work autonomously on zero if you gave me a GitHub account. I was honest that my sandbox had no repo, no build system, and no network wired up yet, so I couldn't actually do it at the time." The turn's objective (summarize where we left off) was fully met, but the run ended incomplete: the final message admits the objective was not met ("i couldn't ..."). The detector is now sentence-scoped: quoted spans are dropped and sentences that retell a past exchange ("you asked", "at the time", "when we last") are skipped. That transcript is a regression test. Present-tense admissions and genuine past-tense failure reports about the current task still fire, and the existing chess-incident regression tests still pass.

  2. Some admissions are true and still should not fail the run. With an operator present, "the sandbox blocks network egress, so I can't run gh auth status; approve network and I'll continue" is a complete answer that hands the turn back. No phrase heuristic can distinguish that, so this adds zero exec --no-completion-gate, mapping to RequireCompletionSignal=false, for conversational callers. Plain zero exec is unchanged and keeps full gate semantics for CI and cron use.

Linked issue

None. Opening directly under my contributor exception to the community PR policy.

Checklist

  • The linked issue already has the issue-approved label. (Not applicable, see above.)
  • go build ./..., go vet ./..., and go test ./... pass locally. (internal/agent and internal/cli pass. Three failures elsewhere are local-environment issues untouched by this diff: two provideroauth ChatGPT loopback-callback tests that cannot bind port 1455 on this machine, and internal/sandbox TestWindowsUnelevatedSetupMarkerEvictsOldestPastCap.)
  • gofmt clean.
  • Tests added/updated for the change (and run under -race where relevant).
  • UI changes include screenshots or a short recording where possible. (No UI changes; the only visible change is the new line in zero exec --help.)

Summary by CodeRabbit

  • New Features
    • Added a --no-completion-gate option for zero exec, allowing a final no-tool-call reply to be accepted without requiring a completion signal.
  • Bug Fixes
    • Improved “incomplete response” detection to reduce false triggers from quoted text, recap-style narration, and earlier-message references.
    • Expanded coverage for genuine incomplete final answers, including delimiter/quote edge cases.
  • Documentation
    • Updated zero exec help text for the new --no-completion-gate flag, and added validation that it can’t be combined with --use-spec.

…urrent objective

The detector matched inability stems anywhere in the final message, so a
conversational recap of a past exchange ("You asked if I could work
autonomously ... so I couldn't actually do it at the time") downgraded a
completed run to INCOMPLETE. Match per sentence instead, drop quoted spans,
and skip sentences that retell a past exchange. The real transcript is now a
regression test, and genuine admissions still fire, both present tense and
past tense about the current task.
A chat frontend driving zero exec has an operator present, so a final
message that hands the turn back ("the sandbox blocks network egress,
approve it and I'll continue") is a complete conversational answer, not an
unfinished task. The headless completion gate still stamped such runs
INCOMPLETE (exit 4) on the honest inability phrasing, and no phrase
heuristic can fix that case because the admission is true. The new flag
maps to RequireCompletionSignal=false so conversational callers can opt
out. Default behavior is unchanged.
@coderabbitai

coderabbitai Bot commented Jul 9, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 9c706220-eb31-4644-8513-fde63f79ae13

📥 Commits

Reviewing files that changed from the base of the PR and between 46f90f6 and 2cb885c.

📒 Files selected for processing (4)
  • internal/agent/acceptance_gate_test.go
  • internal/agent/guardrails.go
  • internal/cli/exec_parse.go
  • internal/cli/exec_parse_completion_gate_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • internal/cli/exec_parse.go
  • internal/agent/acceptance_gate_test.go
  • internal/agent/guardrails.go

Walkthrough

This PR refines self-reported incompletion detection by filtering quoted and narrative fragments before matching admissions, and adds a --no-completion-gate exec flag that disables the completion-signal requirement. It also updates tests and CLI help/validation.

Changes

Self-report detection and completion gate flag

Layer / File(s) Summary
Narrative/quoted filtering helpers
internal/agent/guardrails.go
Adds helpers for identifying narrative fragments, stripping balanced quoted spans, splitting text into sentence-like fragments, and checking substrings.
selfReportedIncompletion rewrite and tests
internal/agent/guardrails.go, internal/agent/acceptance_gate_test.go
Detection now works per fragment after quote stripping and narrative filtering, and the acceptance matrix adds new false-positive and true-positive cases for delimiter edge conditions.
--no-completion-gate flag wiring
internal/cli/exec.go, internal/cli/exec_parse.go, internal/cli/app.go, internal/cli/exec_parse_completion_gate_test.go
Adds the exec option and parser support, rejects the flag with --use-spec, wires it into RequireCompletionSignal, updates help text, and covers the new behavior with tests.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

  • Gitlawb/zero#325: Directly refines the same selfReportedIncompletion detection logic in internal/agent/guardrails.go and its test matrix.

Suggested reviewers: gnanam1990, Vasanthdev2004, anandh8x

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main fix: preventing false INCOMPLETE downgrades for conversational exec messages.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/agent/guardrails.go`:
- Around line 209-225: The stripQuoted helper in guardrails.go is over-stripping
when it sees an opening quote/backtick without a matching closer, which can
remove later content needed by selfReportedIncompletion. Update stripQuoted to
only remove balanced quoted segments and preserve the original text when the
input contains dangling delimiters, using the existing stripQuoted and
selfReportedIncompletion flow as the main touchpoints. Add a regression test
covering truncated double quotes, curly quotes, and backticks to ensure
unbalanced input is left intact.

In `@internal/cli/exec.go`:
- Around line 558-561: Reject the combination of --no-completion-gate and
--use-spec during exec parsing so the flag is not silently ignored on the
runExecSpecDraft path. Add the validation alongside the existing --self-correct
+ --use-spec check in exec_parse.go, using the same option parsing flow that
populates options.noCompletionGate and options.useSpec. Ensure the parser
returns an explicit error before exec reaches runExecSpecDraft or agent.Run,
matching the existing early-rejection behavior for incompatible flags.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0c7b5a88-a301-4143-9198-04071eb07464

📥 Commits

Reviewing files that changed from the base of the PR and between a7cfb99 and 46f90f6.

📒 Files selected for processing (6)
  • internal/agent/acceptance_gate_test.go
  • internal/agent/guardrails.go
  • internal/cli/app.go
  • internal/cli/exec.go
  • internal/cli/exec_parse.go
  • internal/cli/exec_parse_completion_gate_test.go

Comment thread internal/agent/guardrails.go
Comment thread internal/cli/exec.go
…combination

stripQuoted now removes only balanced quoted spans: an opening delimiter
that never closes is restored verbatim, so a stray quote cannot swallow
the rest of the message and hide a genuine admission from the detector.
Regression tests cover dangling straight, curly, and backtick delimiters.

--no-completion-gate combined with --use-spec is now rejected at parse
time, mirroring the --self-correct check: the spec-draft path never
consults the completion gate, so the flag would be silently ignored.

@anandh8x anandh8x left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

Sentence-scoped self-report detection (strip balanced quotes, skip narrative recap sentences) fixes the real false positive without gutting the gate. Present-tense / current-task admissions still fire, and the chess-style cases stay covered.

--no-completion-gate is the right opt-out for chat frontends with an operator present; default zero exec keeps RequireCompletionSignal on. Rejecting it with --use-spec matches the existing --self-correct pattern.

Tests pin both sides. All CI green. Ship it.

@gnanam1990 gnanam1990 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review

Verdict: Approve with notes. Agree with @anandh8x.

Sentence-scoped self-report detection (balanced quote strip + skip narrative-recap sentences) fixes the real conversational false positive without removing the gate. Present-tense / current-task admissions still fire in the new tests; chess-style coverage still passes. --no-completion-gate is the right opt-out for chat frontends; default zero exec keeps RequireCompletionSignal. Rejecting it with --use-spec matches the --self-correct pattern. CI green; focused agent/cli tests pass with -race.

Notes

  1. Residual FN risk (non-blocking): whole-sentence skip on markers like you asked / at the time / last time can miss a single sentence that both recaps and admits current failure (e.g. "You asked me to port the parser and I couldn't finish the second half.", "I couldn't complete the refactor at the time."). Split sentences still fire. Worth watching / tightening markers if CI incompletes go silent.
  2. Process: no linked issue (issue-approved); author claims contributor exception.

No disagreement with shipping the core fix.

@kevincodex1
kevincodex1 merged commit b6117af into Gitlawb:main Jul 10, 2026
7 checks passed
@euxaristia
euxaristia deleted the fix/self-report-incompletion-false-positives branch July 17, 2026 21:05
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.

4 participants