fix(auto): route Ralph oscillation replay through UNSTUCK_LATERAL#1187
Conversation
Keep PR Q00#1175's minimal-substrate direction intact by applying the existing oscillation_detected to UNSTUCK_LATERAL route consistently at fresh handoff, resume polling, and re-attach terminal consumers instead of adding a new escalation ladder or detector.\n\nConstraint: PR Q00#1175 is already merged, so this lands as a follow-up correction PR on current main.\nRejected: New L5 state machine or new oscillation detector | Q00#1157 explicitly scopes L5-a to plumbing existing Ralph stop_reason into existing unstuck substrate.\nConfidence: high\nScope-risk: narrow\nDirective: Keep non-oscillation Ralph blocked reasons as direct budget-terminal BLOCKED outcomes unless Q00#1157 changes.\nTested: SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OUROBOROS_AI=0.0.0 SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 uv run pytest tests/unit/auto/test_pipeline_oscillation_lateral.py tests/unit/auto/test_pipeline_ralph_handoff.py -q; SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OUROBOROS_AI=0.0.0 SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 uv run pytest tests/unit/auto -q; uv run ruff check src/ouroboros/auto/pipeline.py tests/unit/auto/test_pipeline_oscillation_lateral.py; uv run ruff format --check src/ouroboros/auto/pipeline.py tests/unit/auto/test_pipeline_oscillation_lateral.py; SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OUROBOROS_AI=0.0.0 SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 uv run mypy src/ouroboros/auto/pipeline.py\nNot-tested: Full repository test suite outside tests/unit/auto.
Request bot and CI re-evaluation for the already-pushed Q00#1175 follow-up correction without changing code. Constraint: GitHub reported no checks or bot reviews after the initial PR push.\nConfidence: high\nScope-risk: narrow\nDirective: Do not treat this commit as a code change; review the previous commit for implementation substance.\nTested: Not rerun; empty trigger commit only.\nNot-tested: Bot availability. Co-authored-by: OmX <omx@oh-my-codex.dev>
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: APPROVE
Reviewing commit
415b08afor PR #1187
Review record:
f8288a27-c679-402c-ae1e-6656b256e2db
Blocking Findings
No in-scope blocking findings remained after policy filtering.
Non-blocking Suggestions
None.
Design Notes
Unable to assess architecture or implementation because the provided source snapshot and diff could not be read in this runner.
Policy Notes
- Omitted 1 finding(s) that referenced files outside the current PR changed-files scope.
Recovery Notes
First recoverable review artifact generated from codex analysis log.
Reviewed by ouroboros-agent[bot] via Codex deep analysis
Merge-readiness rationaleWhat this PR fixesThis PR is a narrow follow-up to merged PR #1175. PR #1175 correctly implemented the L5-a live-path behavior from #1157: when Ralph terminates with The latest review on #1175 found the real gap: the same Ralph terminal contract had three consumers, but only the fresh handoff consumer used the L5-a route. Resume polling and direct re-attach still mapped Why this is aligned with #961 / #1157This keeps the AgentOS /
That matches #1157's L5-a scope: "plumb the existing detection signal into the existing recovery substrate." It also fits #961's current Track B sequencing: this is a narrow What changed technically
Why it is safe to merge
Current statusThis PR improves the already-merged #1175 behavior to the level the later bot review requested. It preserves the SSOT direction, avoids over-engineering, and closes the replay/resume consistency gap. I consider it ready to merge. |
PR Review SummaryVerdictApprove Scope Reviewed
Blocking IssuesNone. WarningsNone. Mutation-Test Thinking
Complexity / CRAP-style Risk
Test Quality Assessment (6/7)
Security / Operational RiskNone. No new I/O, no secrets, no auth/authz surface, no migration, and no external dependency. The change only adjusts existing in-process terminal mapping for a known Ralph stop reason. Looks Good
Final RecommendationApprove. This PR is merge-ready: it fixes the replay/resume consistency gap from #1175, stays aligned with the #961/#1157 SSOT direction, avoids over-engineering, and has adequate regression coverage plus green CI. |
Independent merge-readiness review — 2026-05-23I re-reviewed PR #1187 independently against the current #961 / #1157 SSOT direction, ignoring bot-review conclusions and using the local worktree at head What this PR doesThis PR is a narrow follow-up to #1175. It fixes the consumer side of the L5-a contract: when Ralph returns
SSOT / AgentOS direction checkThis matches the #961 / #1157 direction. L5-a is explicitly the minimal-substrate path: plumb the existing Ralph That is the important over-engineering check: the change centralizes duplicated terminal-consumer policy in one helper and reuses the existing lateral path. Non-oscillation budget/regression terminals still block directly, so the PR does not broaden recovery beyond the SSOT-approved case. Current action plan and resultRecommended action: merge as-is. I did not push any new commit because the current implementation already satisfies the SSOT and no blocker or cleanup-worthy over-engineering issue was found. Verification I ran locally from a separate worktree:
GitHub checks are also green at head Conclusion: PR #1187 is merge-ready. It is a narrow, correct L5-a replay/resume consistency fix and remains aligned with the AgentOS minimal-substrate direction. |
PR Review SummaryVerdictApprove Scope Reviewed
Blocking IssuesNone. WarningsNone. Mutation-Test Thinking
Complexity / CRAP-style Risk
Test Quality Assessment (6/7)
Security / Operational RiskNone. No new external I/O, credentials, subprocess behavior, migration, auth/authz surface, or dependency is introduced. Looks Good
Final RecommendationApprove. PR #1187 is merge-ready and should be safe to merge as a minimal-substrate L5-a consistency correction. |
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: APPROVE
Reviewing commit
415b08afor PR #1187
Review record:
b3c232d6-c112-4ed6-9755-06dce1d49034
Blocking Findings
No in-scope blocking findings remained after policy filtering.
Non-blocking Suggestions
None.
Design Notes
Unable to assess architecture or implementation details because the local snapshot and diff could not be read due to the sandbox namespace failure.
Policy Notes
- Omitted 1 finding(s) that referenced files outside the current PR changed-files scope.
Recovery Notes
First recoverable review artifact generated from codex analysis log.
Reviewed by ouroboros-agent[bot] via Codex deep analysis
There was a problem hiding this comment.
Review — ouroboros-agent[bot]
Verdict: REQUEST_CHANGES
PR #1187
Branch: fix/pr1175-ralph-oscillation-replay | 2 files, +231/-50 | CI: Bridge TypeScript pass 19s https://github.com/Q00/ouroboros/actions/runs/26292809379/job/77397292834
Scope: architecture-level
HEAD checked: 415b08ae7468effa42cdb272f62baa7d50bcc179
What Improved
- The Ralph
oscillation_detectedrouting is now centralized and used by fresh handoff, resume polling, and direct re-attach. - Resume/re-attach paths can recover the persisted Seed artifact before entering
UNSTUCK_LATERAL. - Added focused L5-a regression coverage;
tests/unit/auto/test_pipeline_oscillation_lateral.py -qpasses with 5 tests.
Issue #N/A Requirements
| Requirement | Status |
|---|---|
| Shared L5-a helper for Ralph oscillation route | Met |
Fresh _handoff_to_ralph routes oscillation_detected through lateral recovery |
Met |
_poll_ralph_job resume polling routes oscillation_detected through lateral recovery |
Met |
_reattach_ralph_job terminal observation routes oscillation_detected through lateral recovery |
Met |
| Replay/re-attach can recover persisted Seed artifact | Met |
| Regression tests for resume and re-attach lateral recovery | Met |
| Plugin/runtime metadata remains consistent with release source of truth | Not met |
| Claude hook commands remain usable from a normal repository checkout | Not met |
Prior Findings Status
| Prior Finding | Status |
|---|---|
| Prior review context | MODIFIED — Prior persistence/replay concern was modified: the Ralph oscillation consumer boundary is now shared across fresh handoff, resume polling, and direct re-attach. New current-HEAD blockers remain in the plugin metadata and Claude hook consumer boundaries. |
Blockers
| # | File:Line | Severity | Confidence | Finding |
|---|---|---|---|---|
| 1 | .claude-plugin/plugin.json:3 | High | 95% | Current HEAD advertises the Claude plugin as 0.39.1, while the repo's own version source is still v0.24.0-1172-g415b08ae; python scripts/sync-plugin-version.py reports drift for .claude-plugin/plugin.json, .claude-plugin/marketplace.json, and skills/setup/SKILL.md. This breaks the plugin/version publication contract and can cause consumers to install or trust metadata for a release that does not match the Python package being built from this commit. |
| 2 | .claude/settings.json:8 | High | 85% | The repo-local Claude hooks now depend solely on ${CLAUDE_PLUGIN_ROOT}; when that variable is unset in a normal checkout, the command expands to `python3 "/scripts/keyword-detector.py" |
Follow-ups
| # | File:Line | Priority | Confidence | Suggestion |
|---|---|---|---|---|
| — | — | — | — | None. |
Test Coverage
- Ran
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OUROBOROS_AI=0.0.0 SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 uv run pytest tests/unit/auto/test_pipeline_oscillation_lateral.py -q: 5 passed. - Ran
python scripts/sync-plugin-version.py: failed drift check, confirming the plugin metadata/version mismatch. - Missing coverage: no CI check currently prevents committed plugin metadata from drifting from hatch-vcs, and no hook test covers
.claude/settings.jsonwithCLAUDE_PLUGIN_ROOTunset.
Design / Roadmap Gate
Affected-boundary review: the state-machine/persistence/replay boundary for L5-a is coherent at current HEAD: failed Ralph terminal statuses with stop_reason="oscillation_detected" enter the same UNSTUCK_LATERAL path from live handoff, resume polling, and re-attach, while non-oscillation blocked reasons still terminate as BLOCKED.
However, the merged diff also changed consumer-facing plugin metadata and Claude hook execution surfaces. Those boundaries are now inconsistent: plugin manifests advertise a version that the repo's own sync/version tool rejects, and repo-local Claude hooks no longer resolve their scripts unless a plugin-specific environment variable is present. Those are current-HEAD blockers independent of the L5-a state-machine fix.
Merge Recommendation
Post-merge audit recommendation: keep the L5-a replay fix, but follow up immediately on current HEAD to restore plugin version consistency and make Claude hook script resolution work both in plugin-root and normal checkout contexts.
Review-Metadata:
verdict: REQUEST_CHANGES
github_event: COMMENT
review_kind: post_merge_audit
merge_eligible: false
head_sha: 415b08a
source_read_ok: true
diff_read_ok: true
blocking_count: 0
Summary
Follow-up correction to merged PR #1175 after the latest ouroboros-agent review correctly identified a persistence/replay contract gap.
PR #1175 implemented the L5-a live handoff route:
Ralph failed + stop_reason="oscillation_detected" + complete_product + lateral_thinker -> UNSTUCK_LATERALbut the same Ralph terminal status could still be consumed by resume polling and the direct re-attach observer as a legacy direct
BLOCKEDoutcome. Since #1157 defines L5-a as plumbing Ralph's existingoscillation_detectedsignal into the existingooo unstucksubstrate, the terminal consumer boundary needs to be consistent across fresh handoff, resume polling, and re-attach.What changed
src/ouroboros/auto/pipeline.pyfor the L5-a Ralph oscillation route._handoff_to_ralph,_poll_ralph_jobresume polling,_reattach_ralph_jobterminal observation.Seedobject in hand.oscillation_detectedand can continue into the existing recovery redispatch path.Why this stays minimal-substrate
This intentionally does not add a new escalation ladder, new detector, new terminal taxonomy, or new state machine. It only makes the existing L5-a route single-sourced across the three existing Ralph terminal consumers. Other Ralph blocked reasons (
iteration_timeout,wall_clock_exhausted,grade_regressing,max_generations reached) still go directly toBLOCKEDas budget/regression terminals.Verification
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_OUROBOROS_AI=0.0.0 SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 uv run pytest tests/unit/auto/test_pipeline_oscillation_lateral.py tests/unit/auto/test_pipeline_ralph_handoff.py -q→ 46 passedSETUPTOOLS_SCM_PRETEND_VERSION_FOR_OUROBOROS_AI=0.0.0 SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 uv run pytest tests/unit/auto -q→ 907 passeduv run ruff check src/ouroboros/auto/pipeline.py tests/unit/auto/test_pipeline_oscillation_lateral.py→ cleanuv run ruff format --check src/ouroboros/auto/pipeline.py tests/unit/auto/test_pipeline_oscillation_lateral.py→ cleanSETUPTOOLS_SCM_PRETEND_VERSION_FOR_OUROBOROS_AI=0.0.0 SETUPTOOLS_SCM_PRETEND_VERSION=0.0.0 uv run mypy src/ouroboros/auto/pipeline.py→ cleanRefs #1175, #1157, #961.