fix(runtime): accept custom outcome values for multi-way conditional routing#3
Merged
Merged
Conversation
…routing The reference dotfiles (semport.dot, consensus_task.dot) and the english-to-dotfile skill document custom outcome values like "process", "done", "port", "skip" for multi-way edge routing. However, ParseStageStatus only accepted 5 canonical values and rejected everything else, causing DecodeOutcomeJSON to silently discard custom outcomes and fall back to the handler's default status. This meant edge conditions like `outcome=process` could never match, breaking any pipeline that used custom routing outcomes. Changes: - ParseStageStatus now passes through non-canonical values as-is (normalized to lowercase) instead of returning an error - Added IsCanonical() helper to distinguish canonical from custom statuses, for use in retry/failure logic that needs the distinction - Empty strings still return an error Tests: - TestParseStageStatus_CustomOutcomes: custom values parse correctly - TestStageStatus_IsCanonical: canonical detection works - TestDecodeOutcomeJSON_CustomOutcome_Canonical: status.json with custom status decodes via canonical format - TestDecodeOutcomeJSON_CustomOutcome_Legacy: custom status decodes via legacy format - TestEvaluate_CustomOutcome: edge condition matching works for custom outcome values - All 111 existing engine tests pass with no changes Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
5ec5aa4 to
50e6caf
Compare
Owner
|
Closing this PR — the core fix for custom outcome routing is correct and valuable, but there's a blocking issue with the A profound thanks from codex — the depth of thought here is genuinely impressive. The diagnosis of the silent fallback-to-default-outcome bug was spot-on, the |
danshapiro
pushed a commit
that referenced
this pull request
Feb 14, 2026
- Fix #1: goreleaser check now uses command -v guard, not error masking - Fix #2: remove hardcoded occurrence counts from commit message - Fix #3: add Safety section update to release skill edits - Fix #4: add RELEASE_NOTES.md mechanism for hand-crafted release notes - Fix #5: add version_test.go for --version output coverage - Fix #6: use fully qualified brew install danshapiro/kilroy/kilroy Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
danshapiro
pushed a commit
that referenced
this pull request
Feb 14, 2026
- Fix #1: remove invalid release_notes top-level config key, pass --release-notes=RELEASE_NOTES.md as CLI flag in workflow instead - Fix #2: remove RELEASE_NOTES.md from .gitignore — it must be committed as part of the release so goreleaser can read it at the tagged commit - Fix #3: strengthen version test to assert Version == 'dev', not just non-empty - Fix #4: add mandatory goreleaser check step to GitHub Actions workflow so config is always validated in CI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
danshapiro
pushed a commit
that referenced
this pull request
Feb 14, 2026
- Fix #1: change git add -A to git add -u to avoid staging untracked files - Fix #2: remove go mod tidy from goreleaser before hooks — avoids mutating dependencies after tests have already validated them - Fix #3: add deprecation note for brews config key (still current, but may change in future goreleaser versions) - Fix #4: add *.md to verification grep so markdown files are checked Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
danshapiro
pushed a commit
that referenced
this pull request
Feb 14, 2026
- Fix #1 (major): add full go test ./... step after module path rename to catch regressions beyond just compilation - Fix #2 (minor): remove hardcoded '123 files' count that goes stale - Fix #3 (nit): use tilde fences for outer code block in Task 8 to avoid nested triple-backtick rendering issues Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
danshapiro
pushed a commit
that referenced
this pull request
Feb 14, 2026
- Fix #1: move test baseline capture to Step 1 (before the rename), then compare after rename in Step 5 - Fix #2: use grep -E '^(ok|FAIL)' instead of grep '^---' to capture package-level build failures, not just test-case failures - Fix #3: remove *.md from leftover-reference grep since this plan file intentionally keeps old-path references; narrow check to *.go and go.mod (the compiled code that actually matters) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This was referenced Apr 24, 2026
mattleaverton
added a commit
that referenced
this pull request
Apr 27, 2026
* fix: require condition on inbound-to-terminal edges from fallible predecessors (#3) * fix: reconcile all_conditional_edges with terminal_condition_edge; fix existing graphs The new terminal_condition_edge rule and the existing all_conditional_edges rule were in tension: the natural fix for the new rule (adding condition="outcome=success" to edges flagged by terminal_condition_edge) triggered all_conditional_edges, which fires when a node has only conditional outgoing edges with no fallback. all_conditional_edges now exempts two patterns: 1. Every outgoing edge targets a terminal node — "no condition matched" terminates the run by intent; terminal_condition_edge governs those edges instead. 2. Conditions are exhaustive via an outcome=X / outcome!=X pair — the pair covers the full outcome space, so there is no runtime routing gap. Also adds explicit conditions to the inbound-to-terminal edges in the three existing workflow graphs (build-test, coding-loop, multi-tool-exercise) so all three now validate clean. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
ParseStageStatusnow accepts custom outcome values (e.g.process,done,port,skip) instead of rejecting them as invalidIsCanonical()helper to distinguish canonical statuses from custom routing valuesFixes the spec/implementation drift where reference dotfiles (
semport.dot,consensus_task.dot) and theenglish-to-dotfileskill document custom outcomes as a working feature, but the engine silently discards them.Root cause
ParseStageStatus()only accepted 5 canonical values (success,partial_success,retry,fail,skipped). When an LLM wrotestatus.jsonwith{"status": "process"}:DecodeOutcomeJSONcalledCanonicalize()→ParseStageStatus("process")→ errorsuccess)condition="outcome=process"compared against"success"and never matchedWhat changed
runtime/status.goParseStageStatusdefault case now returnsStageStatus(normalized)instead of errorruntime/status.goIsCanonical()method onStageStatusruntime/status_test.gocond/cond_test.goTest plan
TestParseStageStatus_CustomOutcomes— custom values likeprocess,done,port,needs_dod,has_dod,yesall parse correctly (normalized to lowercase)TestStageStatus_IsCanonical— canonical statuses return true, custom values return falseTestDecodeOutcomeJSON_CustomOutcome_Canonical—{"status":"process"}decodes correctlyTestDecodeOutcomeJSON_CustomOutcome_Legacy—{"outcome":"done"}decodes correctlyTestEvaluate_CustomOutcome—outcome=processmatches when status is "process", doesn't match "done"🤖 Generated with Claude Code