Skip to content

fix(sdd): fail closed on empty task results - #2186

Merged
Alan-TheGentleman merged 13 commits into
Gentleman-Programming:mainfrom
dnlrsls:fix/2117-sdd-empty-task-result
Aug 6, 2026
Merged

fix(sdd): fail closed on empty task results#2186
Alan-TheGentleman merged 13 commits into
Gentleman-Programming:mainfrom
dnlrsls:fix/2117-sdd-empty-task-result

Conversation

@dnlrsls

@dnlrsls dnlrsls commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

🔗 Linked Issue

Closes #2117

🏷️ PR Type

  • type:bug — Bug fix (non-breaking change that fixes an issue)
  • type:feature — New feature
  • type:docs — Documentation only
  • type:refactor — Code refactoring
  • type:chore — Build, CI, or tooling changes
  • type:breaking-change — Breaking change

📝 Summary

  • Fails closed when configured SDD phase agents return empty or malformed task results.
  • Blocks automatic retries and downstream SDD launches in the failed session without intercepting unrelated agents.
  • Adds focused regressions and the tr01-sdd-empty-task-result benchmark friction journey.

📂 Changes

File / Area What Changed
OpenCode result-artifact plugin Added typed SDD task-result classification and session-scoped terminal blocking while preserving review behavior.
SDD contracts Documented transport failures as terminal, non-retryable outcomes.
Asset/plugin tests Covered empty, malformed, profile-scoped, unrelated-agent, artifact-preservation, and downstream-blocking behavior.
Benchmark Added the opt-in sdd-task-result axis and Windows executable-boundary support.

🧪 Test Plan

  • go test ./internal/assets -run "^TestSDDTaskResultFailuresAreTerminalAndScoped$" -count=1
  • go test ./internal/assets -run "^TestReviewResultArtifactsPluginContract$" -count=1
  • go test . -run "^(TestSDDTaskResultAxisRegistration|TestSDDTaskResultAxisSkipsWithoutExternalPlugin|TestExecutableRecognizesBuiltBenchmarkBinary)$" -count=1 from bench
  • Direct Node plugin probe: typed empty/malformed failures, retry/downstream blocking, and unrelated-agent pass-through
  • Benchmark journey: 1 completed, 0 unsupported, 0 failed
  • Missing benchmark prerequisite: 0 completed, 1 unsupported, 0 failed
  • git diff --check
  • Full go test ./... from bench is blocked on Windows by pre-existing POSIX fake-binary tests: TestProbeCapabilityRejectsAMissingFlag, TestProbeAndHelpProbeDoNotShareACacheEntry, and TestReadBackBlanksGitTrace.
  • Native POSIX review-plugin stub scenarios are unavailable on Windows; the unchanged review route is covered by the passing asset contract.

✅ Contributor Checklist

  • PR is linked to an issue with status:approved
  • PR stays within 400 changed lines (328 authored additions + deletions)
  • Exactly one type:* label is applied
  • Focused unit and runtime checks pass
  • Documentation/contracts were updated where behavior changed
  • Commit follows Conventional Commits format
  • Commit does not include Co-Authored-By trailers

💬 Notes for Reviewers

The provider/runtime may have performed hidden side effects before returning an invalid result, so this change intentionally does not retry. It marks the session terminal for SDD and requires an explicit user decision. Receipt-driven development was globally disabled for this work unit, so delivery is reported as disabled/unmanaged rather than carrying a native review receipt.

Summary by CodeRabbit

  • New Features

    • Added an opt-in benchmark for validating SDD task-result handling.
    • Added typed terminal failures for empty or malformed task results, with downstream phases blocked.
    • Added guidance to require explicit approval before retrying or starting another phase.
    • Existing proposal artifacts are preserved when task-result processing fails.
  • Bug Fixes

    • Benchmark executable detection now works correctly on Windows.
    • Unavailable plugins or runtime capabilities are reported as unsupported instead of causing misleading failures.
    • Resolved SDD session failures correctly clear when sessions are disposed.

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The plugin treats empty or malformed SDD task results as terminal failures. It blocks downstream SDD phases and preserves existing artifacts. A benchmark validates this behavior and skips when dependencies are unavailable. Windows executable detection is also supported.

Changes

SDD task-result handling

Layer / File(s) Summary
SDD task-result classification and blocking
internal/assets/opencode/plugins/review-result-artifacts.ts
The plugin classifies empty and malformed task results, records failed SDD sessions, blocks later SDD phases, and clears failure state when sessions end.
Failure contract and recovery validation
internal/assets/assets_test.go, internal/assets/review_plugin_recovery_test.go, internal/assets/opencode/sdd-orchestrator.md, internal/assets/skills/_shared/sdd-phase-common.md
Tests and guidance define terminal SDD failures, prevent retries and phase launches, preserve artifacts, and isolate unrelated sdd- agents.
Benchmark availability and execution
bench/runner.go, bench/main.go, bench/main_test.go, bench/axis_sdd_task_result.go, bench/axis_sdd_task_result_test.go
The runner skips unsupported steps. Executable detection supports Windows .exe files. The new axis runs the Node plugin harness and validates typed failures and artifact preservation.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Benchmark
  participant NodeHarness
  participant ReviewResultPlugin
  participant SDDOrchestrator
  Benchmark->>NodeHarness: Execute empty task-result scenario
  NodeHarness->>ReviewResultPlugin: Submit empty task_result
  ReviewResultPlugin-->>NodeHarness: Return sdd_task_result_empty
  NodeHarness->>SDDOrchestrator: Attempt downstream SDD phase
  SDDOrchestrator->>ReviewResultPlugin: Route sdd-apply
  ReviewResultPlugin-->>SDDOrchestrator: Block with terminal failure
  NodeHarness-->>Benchmark: Report failures and unchanged artifact
Loading

Possibly related PRs

Suggested reviewers: alan-thegentleman

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the primary change: SDD now fails closed when task results are empty.
Linked Issues check ✅ Passed The changes provide typed failures for empty or malformed results, block retries and downstream phases, and preserve artifacts as required by issue #2117.
Out of Scope Changes check ✅ Passed The benchmark, Windows executable support, tests, and documentation directly support the SDD failure-handling objectives.
✨ 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.

@dnlrsls dnlrsls added the type:bug Bug fix label Aug 1, 2026

@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: 4

🤖 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 `@bench/axis_sdd_task_result.go`:
- Around line 97-102: Update the Node subprocess setup around cmd.Run in the
benchmark flow to use context.WithTimeout with an appropriate bounded duration,
then create the command via exec.CommandContext. Ensure the context is canceled
and timeout failures propagate as command errors while preserving the existing
output capture and command arguments.
- Around line 47-59: The sddTaskResultUnavailable preflight must verify that the
available Node runtime can parse and strip the TypeScript plugin, not merely
that node exists on PATH. Add a capability check using the existing
plugin/harness execution path and return the documented unavailable message when
unsupported; update the corresponding axis description to state the required
unflagged Node version or --experimental-strip-types support.

In `@internal/assets/opencode/plugins/review-result-artifacts.ts`:
- Around line 496-504: Update the returned hooks object’s dispose method to
clear both admissionRecoveries and failedSDDSessions, preserving dispose as a
complete reset point for reused session IDs.

In `@internal/assets/review_plugin_recovery_test.go`:
- Around line 51-65: Update the SDD scenario mapping and table in
TestSDDTaskResultFailuresAreTerminalAndScoped so the scenario that supplies an
empty result also uses the "sdd-profile-empty" name, exercising the
"sdd-propose-cheap" phase and isSDDPhase suffix branch. Remove or replace the
currently unreachable empty-case naming while preserving the malformed
scenario’s existing coverage.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e63a4c44-9449-4f09-b7ca-93d7d4bf5f29

📥 Commits

Reviewing files that changed from the base of the PR and between b6ecb3e and 5131b4f.

📒 Files selected for processing (10)
  • bench/axis_sdd_task_result.go
  • bench/axis_sdd_task_result_test.go
  • bench/main.go
  • bench/main_test.go
  • bench/runner.go
  • internal/assets/assets_test.go
  • internal/assets/opencode/plugins/review-result-artifacts.ts
  • internal/assets/opencode/sdd-orchestrator.md
  • internal/assets/review_plugin_recovery_test.go
  • internal/assets/skills/_shared/sdd-phase-common.md

Comment thread bench/axis_sdd_task_result.go
Comment thread bench/axis_sdd_task_result.go Outdated
Comment thread internal/assets/opencode/plugins/review-result-artifacts.ts
Comment thread internal/assets/review_plugin_recovery_test.go

@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: 1

🤖 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 `@bench/axis_sdd_task_result.go`:
- Around line 59-79: Update sddTaskResultNodeUnavailable to run the Node
capability probe with exec.CommandContext and a bounded timeout, creating the
context before launching node and cancelling it afterward. Preserve the existing
output handling and error message behavior, including reporting timeout-related
errors through the current detail fallback.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 44dd069a-fc46-452d-af06-a934b4e40827

📥 Commits

Reviewing files that changed from the base of the PR and between 5131b4f and 5a8e793.

⛔ Files ignored due to path filters (1)
  • testdata/golden/sdd-opencode-multi-settings.golden is excluded by !testdata/**
📒 Files selected for processing (5)
  • bench/axis_sdd_task_result.go
  • bench/axis_sdd_task_result_test.go
  • internal/assets/assets_test.go
  • internal/assets/opencode/plugins/review-result-artifacts.ts
  • internal/assets/review_plugin_recovery_test.go

Comment thread bench/axis_sdd_task_result.go Outdated
@MarcosArispe

Copy link
Copy Markdown

The fail-closed, non-retryable behavior in this PR matches the recovery semantics we need. Preserving artifacts and blocking downstream phases is the correct response when hidden side effects cannot be ruled out.

One scope gap needs clarification before this PR closes #2117: my reported occurrence involved a background general actor, not an sdd-* phase agent. This PR intentionally passes unrelated agents through, so it will not produce a typed failure for that occurrence.

Could you either:

  1. Explicitly document that non-SDD/general task-result failures are out of scope and link a follow-up issue, or
  2. Add bounded handling if those actors are also expected to be covered by bug(sdd): tasks executor returns empty result on v2.2.4 #2117?

The currently available beta build 2.2.5-0...ece470d does not include this PR. After merge, a tagged prerelease would let us validate the SDD path using a disposable, non-mutating reproduction without retrying preserved consumer state.

@dnlrsls

dnlrsls commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

Scope note: #2117's approved scope covers only unsuffixed and profile-scoped sdd-* phase agents. Empty or malformed results from general actors remain intentionally out of scope for this PR and need a separate follow-up.

@Alan-TheGentleman
Alan-TheGentleman merged commit d256280 into Gentleman-Programming:main Aug 6, 2026
16 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type:bug Bug fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug(sdd): tasks executor returns empty result on v2.2.4

3 participants