Skip to content

test(autonudge): gate the prompt-loop double that carries probe state - #8317

Merged
bolichen97 merged 1 commit into
mainfrom
fix/autonudge-fake-loop-gate
Sep 3, 2026
Merged

test(autonudge): gate the prompt-loop double that carries probe state#8317
bolichen97 merged 1 commit into
mainfrom
fix/autonudge-fake-loop-gate

Conversation

@bolichen97

Copy link
Copy Markdown
Collaborator

Problem / Motivation

main is red: Backend Tests (3.12, 1) and Backend Tests (Windows) (1) fail 5 tests in test/test_autonudge_stop_auth.py (test_applier_owed_terminal_turn_is_not_reported_as_a_spent_cap, test_applier_owed_blocked_turn_is_not_reported_as_a_merge, test_applier_settled_terminal_loop_is_not_reported_as_a_manual_pause, test_applier_a_settled_outcome_outranks_a_stale_owed_turn, test_applier_a_spent_cap_with_no_terminal_news_still_revives) with

AssertionError: assert 'without merging' in 'monitor_update cannot apply legacy fields to a structured monitor: max_cycles'

Reproduces on a pure origin/main checkout.

Why it matters

Every open PR inherits the two red backend shards, so PR Readiness cannot pass for anyone until this is fixed.

What changed (motivation → approach → change)

The five tests (from #8201) build a prompt loop whose monitor carries terminal_pending / outcome, but the _FakeLoop double never sets gate. is_structured_monitor_loop (from #5184) reads monitor is not None and not gate, so an ungated loop with probe state is classified as a controller-owned structured monitor, and apply_session_directive("monitor_update", ...) routes to _structured_monitor_update, which refuses message / max_cycles / active as legacy fields. The assertions then run against that refusal string.

A real prompt loop only ever carries probe state when it is gated — the service infers a MonitorState only when loop.gate is true, and the NudgeLoop.monitor field documents that gate=True records belong to the prompt path. The double was violating the invariant the discriminator relies on. Fix: _FakeLoop gains a gate parameter (default False, matching NudgeLoop) and the five tests pass gate=True. No production code changes.

Tests

test/test_autonudge_stop_auth.py: 50 passed locally (was 45 passed / 5 failed on origin/main). black / isort / flake8 clean on the file.

Manual verification

N/A — unit coverage sufficient; the change is confined to a test double.

Related Issues

no linked issue: main-red introduced by the interaction of #8201 and #5184, caught by CI on open PRs.

Pattern harvest

Rule candidate: review-prompt
Pattern: a hand-rolled test double omits a field a production discriminator reads via getattr(obj, name, default), so the default silently selects the wrong code path.

Checklist

  • At most two commits (one is the norm), with a Conventional Commits title (feat|fix|docs|refactor|perf|test|chore|ci|build|revert: ...)
  • Existing tests pass and new tests added for new functionality
  • Self-review completed; code follows project style guidelines
  • Documentation updated (if applicable)
  • No secrets, credentials, or internal references in the diff

The five monitor_update paused-loop tests build a prompt loop whose
monitor holds a terminal_pending / outcome, but the double never sets
gate. is_structured_monitor_loop reads "monitor is not None and not
gate", so an ungated loop with probe state is a controller-owned
structured monitor and the applier refuses message/max_cycles/active as
legacy fields -- every assertion then fails against that refusal.

A real prompt loop only ever carries probe state when it is gated (the
service infers a monitor only when loop.gate is true), so the double now
takes gate and the five tests set it, matching the invariant the
production discriminator relies on. No production code changes.
@bolichen97
bolichen97 requested a review from a team as a code owner September 3, 2026 23:26
@bolichen97
bolichen97 merged commit 18a88e3 into main Sep 3, 2026
42 of 43 checks passed
@bolichen97
bolichen97 deleted the fix/autonudge-fake-loop-gate branch September 3, 2026 23:46
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Opus 4.8 Review — ✅ no blocking findings

Reviewed a326fc576ec34cb0360a716424d6b0481a853a5a — this comment is updated in place on each push.

Review details

No findings.

[OPUS-REVIEWED] a326fc5

Verdict parsed from the review's SHA-scoped output markers for commit a326fc576ec34cb0360a716424d6b0481a853a5a.

False positive or not applicable? A repository writer can comment:
/ai-review override fable a326fc576ec34cb0360a716424d6b0481a853a5a: <one-sentence reason>

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Design Review (Fable 5) — ✅ PASS

Design-level review of a326fc576ec34cb0360a716424d6b0481a853a5a — updated in place on each push. A BLOCK verdict blocks PR readiness; PASS/CONCERNS are advisory.

Test-only change verified against production code; the double now mirrors the NudgeLoop.gate invariant the discriminator at src/kiro_crew/autonudge.py:518 actually reads.

Design-Verdict: PASS

Test-only alignment of a hand-rolled double with the real gate discriminator; matches the production invariant exactly, no design concerns.

Suggestions

  • _FakeLoop drifting from NudgeLoop is the root cause here; constructing real NudgeLoop records (or asserting field parity once) would prevent the next silent-drift recurrence — follow-up, not this PR.

[DESIGN-REVIEWED] a326fc5

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

GPT 5.6 Review — ✅ no blocking findings

GPT 5.6 completed its review of a326fc576ec34cb0360a716424d6b0481a853a5a and found no blocking issues.

This comment is updated in place on each push.

Review details

No findings.
[GPT-REVIEWED] a326fc5

False positive or not applicable? A repository writer can comment:
/ai-review override gpt a326fc576ec34cb0360a716424d6b0481a853a5a: <one-sentence reason>

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