Implement if/elif/else clause support#45
Implement if/elif/else clause support#45gh-worker-dd-mergequeue-cf854d[bot] merged 17 commits intomainfrom
Conversation
Add support for POSIX if/elif/else conditional constructs in the shell interpreter. This removes the validation block on *syntax.IfClause and adds execution logic following the same pattern as mvdan/sh's reference implementation. Key changes: - Remove IfClause block from validate.go (child node validation still applies, so blocked features like subshells in conditions are rejected) - Add case *syntax.IfClause in cmd() dispatcher in runner_exec.go - Fix stmts() to check break/continue/exit between statements, ensuring break inside if bodies within loops propagates correctly - Clamp excess break/continue levels at outermost loop (matches bash) - Comprehensive YAML scenario tests and Go tests covering basic if/else, elif chains, nested ifs, conditions (pipes, &&/||, test builtin, negation), exit code propagation, and loop interaction - Pentest tests for deeply nested ifs, context cancellation, blocked features in conditions, and break/continue edge cases Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implementation ResultsCore Implementation (12 lines)
Bug Fix Discovered During Pentest
Test Coverage (45 new files, 844 lines)
Verification
|
Add 10 YAML scenario tests and 9 Go tests covering: - String equality/inequality with [ = ] and [ != ] - Integer comparisons: -eq, -lt, -le, -gt, -ge, -ne - Elif chains with integer range classification - Empty/non-empty string checks with -z and -n - File and directory existence with -f and -d - Combined [ ] conditions with && and || - Negated [ ] conditions with ! - Elif + test builtin inside for loops Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Move all if/elif/else tests that can be expressed as YAML scenarios out of if_clause_test.go into scenario files. Delete if_clause_test.go entirely — every test it contained already has a YAML scenario equivalent. Keep only the pentest Go tests (deeply nested ifs, context cancellation, programmatic script generation) which require Go. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Something went wrong! If you want me to try again, please let me know. |
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
AlexandreYang
left a comment
There was a problem hiding this comment.
Review Summary
Reviewed the implementation of if/elif/else clause support across 3 commits (validation unblock, execution logic, stmts fix, 46 YAML scenarios, 13 pentest tests).
Overall assessment: safe to merge ✅
Security
- Removing
*syntax.IfClausefromvalidate.gois safe — the AST walker still recurses into child nodes, so blocked features (subshells, command substitution, function declarations, background&) inside if conditions/bodies are still rejected before execution. Verified byblocked_in_condition.yamland pentest tests. - No new filesystem access, imports, or command execution paths introduced.
- The
stmts()break/continue propagation fix is a security improvement — without it, statements afterbreakinside an if body within a loop could still execute.
Bash Compatibility
- POSIX if semantics correctly implemented: execute Cond → if exit 0 then Then, else reset exit to 0 and recurse into Else.
- No-branch-taken → exit 0 matches bash.
- Excess break/continue level clamping (
break 99with 1 loop) matches bash behavior. - All YAML scenarios (except intentionally skipped ones) verified against bash.
Correctness
- IfClause correctly checks
exit.exiting,breakEnclosing,contnEnclosingafter evaluating Cond before branching — consistent with the BinaryCmd pattern. stmts()now stops iterating when break/continue/exit is pending — fixes a pre-existing bug exposed by this feature.- Excess level clamping at outermost for loop prevents post-loop commands from being skipped.
Test Coverage
- 46 YAML scenario files organized by concern (basic, conditions, exit_code, loop_interaction, edge_cases)
- 13 pentest Go tests covering deeply nested ifs (100 levels), 50 elif branches, context cancellation, break/continue edge cases, exit in various positions, blocked features in conditions/body, sequential ifs, if in pipeline
- Good coverage of test/
[builtin combinations with if/elif
Positive Observations
- Clean, minimal implementation (13 lines for IfClause case) following existing patterns
- The
stmts()fix is well-motivated and well-tested — a genuine pre-existing bug fix - Excellent test organization with YAML scenarios grouped by concern
- Pentest tests cover important edge cases (deeply nested, context cancellation, break/continue propagation)
Code Review ResultsAssessment: Safe to merge ✅ — no P0/P1/P2 findings. Two P3 (nice-to-have) suggestions:
See full review for details. |
|
Reviewed. I don’t see any blocking issues in this PR. ✅ What I checked
✅ Validation run
ℹ️ NoteA full
These appear unrelated to the if-clause changes in this PR. If you want, I can do a second pass focused specifically on CI-hardening and propose extra edge-case tests likely to catch regressions early. |
- if_in_pipeline.yaml: fix misleading description (said "blocked" but test expects success) - exit_in_then.yaml: remove unnecessary skip_assert_against_bash (bash produces same output) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
AlexandreYang
left a comment
There was a problem hiding this comment.
Review Summary (2nd pass — post-fix)
Re-reviewed the full implementation of if/elif/else clause support after the fix commit (f6117f0): 4 commits, 3 modified Go files, 1 new test file, 46 YAML scenarios.
Overall assessment: safe to merge ✅ (would APPROVE but can't approve own PR)
No P0, P1, or P2 findings. Previous P3 findings have been addressed.
Security
- Sandbox integrity preserved: Removing
*syntax.IfClausefromvalidate.gois safe — the AST walker returnstruefor unhandled nodes, so it still recurses into child nodes. Blocked features (subshells, command substitution, function declarations, background&) inside if conditions/bodies remain rejected before execution. - No new filesystem access: The IfClause handler only calls
stmts()andcmd()— no directos.Open, no new imports. - Break/continue propagation fix: The
stmts()change prevents executing statements afterbreak/continuein if bodies within loops — a pre-existing bug fix with security implications.
Bash Compatibility
- POSIX if semantics correctly implemented. All 46 YAML scenarios now assert against bash (no unnecessary
skip_assert_against_bashremaining). - Excess break/continue clamping matches bash behavior.
Correctness
- Context cancellation:
fatal()setsexiting = true, so context cancellation propagates correctly through the IfClauser.exit.exitingcheck. - stmts() callers:
Block,IfClause, andapi.gotop-level — break/continue check is correct for all. At top level, counters are always 0 so early return never fires. - loopStmtsBroken: Doesn't explicitly check
exit.exitingbut relies onstop()insidestmt()— correct and consistent.
Positive Observations
- Clean, minimal 13-line IfClause implementation following existing patterns
- The
stmts()fix addresses a genuine pre-existing bug (break in brace group within loop) - Excellent test coverage: 46 YAML scenarios + 13 pentest Go tests
- Previous P3 findings (misleading description, unnecessary skip_assert_against_bash) addressed in fix commit
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3b5417e24c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
AlexandreYang
left a comment
There was a problem hiding this comment.
Code Review Summary
Verdict: APPROVE (submitted as COMMENT since GitHub disallows self-approval)
This is a clean, well-implemented PR that adds POSIX if/elif/else support. The core implementation in runner_exec.go correctly handles all branches, follows the mvdan/sh AST structure (where Else is an *IfClause for both elif and bare else), and properly propagates exit/break/continue signals.
Key observations
Correctness (all good):
- The condition-check logic (
r.exit.ok()afterr.stmts(ctx, cm.Cond)) correctly uses the last command's exit code, matching bash behavior for multi-statement conditions (if false; true; then ...). - The
r.exit = exitStatus{}reset before checkingcm.Elseensures the "no branch taken, no else" case returns exit code 0, matching bash. - The recursive
r.cmd(ctx, cm.Else)correctly handles bothelif(re-entersIfClausecase) and bareelse(emptyCond, body inThen). - Break/continue/exit propagation from conditions is properly short-circuited.
The stmts() fix is broader than if-clause (P3):
The added early-return check in stmts() for break/continue/exit also fixes a pre-existing latent bug in brace groups (Block): before this change, { break; echo hello; } inside a loop would incorrectly execute echo hello after break, since stop() only checks exiting and context errors, not breakEnclosing/contnEnclosing. This is a good fix worth noting.
Break/continue clamping (correct):
The clamping of excess breakEnclosing/contnEnclosing at the outermost loop matches bash behavior (break 99 with 1 loop just exits that loop).
Test coverage is excellent:
33 YAML scenario tests + 13 Go pentest tests covering deep nesting, context cancellation, blocked features, and edge cases. Good use of Go tests for the things scenarios cannot express (deep nesting, timeouts).
Minor suggestions (P3)
- A few Go pentest tests (
TestIfPentestSequentialIfs,TestIfPentestBreakInCondition,TestIfPentestContinueInElif) could be scenario tests per project preference in AGENTS.md, though having them as Go tests is not wrong. - Consider mentioning in the PR description that the
stmts()fix also improves brace group behavior, since it's a broader correctness improvement.
Overall, excellent work. No P0/P1/P2 findings.
|
I can only run on private repositories. |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add review-fix-loop skill for iterative self-review and fix coordination Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Update review-fix-loop: auto-detect current branch PR, request external reviews in parallel Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Add cut builtin implementation with byte/field/complement modes and scenario tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Add cut builtin tests, pentest, GNU compat tests, and scenario tests Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Improve review-fix-loop skill reliability with structured task gating and gate checks Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Fix stripNewline to preserve \r bytes, matching GNU cut behavior GNU cut treats only \n as the line terminator. The \r byte in a \r\n sequence is a regular content byte at a regular position. The previous implementation incorrectly stripped \r after \n, which: - Lost \r bytes from line content - Shifted byte positions (e.g. for "ab\r\n", byte 3 should be \r) - Corrupted field content (e.g. for "a:b:c\r\n" -d: -f3, lost the \r) Add tests for CRLF last-field and byte-mode to verify \r preservation. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Add sub-steps and parallel annotations to review-fix-loop task list Expand the task list from 4 to 9 items (including 2A–2E sub-steps), add parallelism indicators, and improve the execution order diagram. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Split review-fix-loop parallel sub-steps into distinct tasks Split 2A into 2A1 (self-review) and 2A2 (external reviews) as parallel sub-steps. Split 2B into 2B1 (address-pr-comments) and 2B2 (fix-ci-tests) as parallel sub-steps. Update all cross-references. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Make 2B1 (address-pr-comments) and 2B2 (fix-ci-tests) sequential Run address-pr-comments before fix-ci-tests so CI fixes operate on code that already incorporates review feedback. Simplify 2C since parallel conflict resolution is no longer needed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> seq Rename review-fix-loop sequential sub-steps 2B1/2B2 to 2B/2C and shift subsequent steps Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Add Step 3 fallback to Step 2 when verification fails Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Address review comments: bash compatibility fixes for cut builtin - Remove -h short flag (GNU cut doesn't support it, exits 1 for cut -h) - Make -c (character mode) behave byte-wise matching GNU cut behavior - Remove processChars function (now unused since -c routes to processBytes) - Replace sort.Slice with slices.SortFunc to reduce import allowlist surface - Remove sort.Slice from import allowlist, remove unused unicode/utf8 import - Clean up noSplitMultibyte field (stored but never read, -n is a no-op) - Update test expectations for -c multibyte to match GNU byte-wise behavior Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Update CODEOWNERS Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> improve .claude/skills/code-review/SKILL.md tests coverage Merge branch 'main' into alex/builtin-cut Co-authored-by: alexandre.yang <alexandre.yang@datadoghq.com>
Fail import allowlist test on unused symbols Add a check that every symbol in builtinAllowedSymbols is actually referenced by at least one builtin file. This keeps the allowlist minimal and prevents stale entries from accumulating. Remove io/fs.DirEntry which was the one unused symbol caught. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Rename import allowlist test to allowed symbols test Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Fix Windows CI: ls sandbox test expects wrong error for /etc On Windows, /etc is not an absolute path (no drive letter), so it resolves to <cwd>/etc inside the sandbox, yielding "no such file or directory" instead of "permission denied". Add stderr_windows override. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Merge branch 'main' into alex/allowed_symbols_fail_unused Merge branch 'main' into alex/allowed_symbols_fail_unused Co-authored-by: alexandre.yang <alexandre.yang@datadoghq.com>
Add grep cmd and docs Merge branch 'main' into aj/add-grep-skill Update interp/builtins/grep/grep.go Co-authored-by: Matthew DeGuzman <91019033+matt-dz@users.noreply.github.com> Merge branch 'main' into aj/add-grep-skill Merge branch 'aj/add-grep-skill' of github.com:DataDog/rshell into aj/add-grep-skill Fix grep exit code on mixed file errors more tests, fix -o, exit with conflicting matchers Merge branch 'aj/add-grep-skill' of github.com:DataDog/rshell into aj/add-grep-skill Fix grep -l/-L precedence and -c behavior Fix grep -h/-H precedence, -o context suppression, newline patterns - Implement last-option-wins for -h/-H using orderedBoolFlag (matches GNU grep) - Suppress context lines (-A/-B/-C) when -o is active (GNU grep behavior) - Split newline-delimited patterns before compilation (GNU grep behavior) - Reduce MaxContextLines from 10k to 1k to limit memory exposure - Add strings.Split and strconv.ParseBool to import allowlist Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Merge remote-tracking branch 'origin/main' into aj/add-grep-skill # Conflicts: # tests/import_allowlist_test.go Merge branch 'main' into aj/add-grep-skill Co-authored-by: datadog-datadog-prod-us1[bot] <88084959+datadog-datadog-prod-us1[bot]@users.noreply.github.com> Co-authored-by: datadog-prod-us1-5[bot] <266081015+datadog-prod-us1-5[bot]@users.noreply.github.com> Co-authored-by: aj.stuyvenberg <aj.stuyvenberg@datadoghq.com>
Add dependabot.yml for weekly GitHub Actions and Go module updates Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: alexandre.yang <alexandre.yang@datadoghq.com>
Bump the go-dependencies group with 2 updates Bumps the go-dependencies group with 2 updates: [github.com/spf13/pflag](https://github.com/spf13/pflag) and [mvdan.cc/sh/v3](https://github.com/mvdan/sh). Updates `github.com/spf13/pflag` from 1.0.9 to 1.0.10 - [Release notes](https://github.com/spf13/pflag/releases) - [Commits](spf13/pflag@v1.0.9...v1.0.10) Updates `mvdan.cc/sh/v3` from 3.12.0 to 3.13.0 - [Release notes](https://github.com/mvdan/sh/releases) - [Changelog](https://github.com/mvdan/sh/blob/master/CHANGELOG.md) - [Commits](mvdan/sh@v3.12.0...v3.13.0) --- updated-dependencies: - dependency-name: github.com/spf13/pflag dependency-version: 1.0.10 dependency-type: direct:production update-type: version-update:semver-patch dependency-group: go-dependencies - dependency-name: mvdan.cc/sh/v3 dependency-version: 3.13.0 dependency-type: direct:production update-type: version-update:semver-minor dependency-group: go-dependencies ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: alexandre.yang <alexandre.yang@datadoghq.com>
Bump the gh-actions-packages group with 2 updates Bumps the gh-actions-packages group with 2 updates: [actions/checkout](https://github.com/actions/checkout) and [actions/setup-go](https://github.com/actions/setup-go). Updates `actions/checkout` from 4.2.2 to 6.0.2 - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](actions/checkout@11bd719...de0fac2) Updates `actions/setup-go` from 5.6.0 to 6.3.0 - [Release notes](https://github.com/actions/setup-go/releases) - [Commits](actions/setup-go@40f1582...4b73464) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: 6.0.2 dependency-type: direct:production update-type: version-update:semver-major dependency-group: gh-actions-packages - dependency-name: actions/setup-go dependency-version: 6.3.0 dependency-type: direct:production update-type: version-update:semver-major dependency-group: gh-actions-packages ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: alexandre.yang <alexandre.yang@datadoghq.com>
Add builtins strings Fix strings -o/-t flag ordering and empty radix validation Implement last-flag-wins semantics for -o and -t by replacing the StringP/BoolP pair with custom pflag.Value types (radixFlagVal, octalFlagVal) that share the same *radixFormat pointer. pflag calls Set() in parse order, so whichever flag appears last on the command line naturally wins — matching GNU strings behavior where -o is just an alias for -t o. Also fix empty radix validation: the old `if *radix != ""` guard silently treated --radix= / -t '' as "no radix set". With Set() validation, empty values hit the default case and pflag reports an error before the handler runs. Add test scenarios: - errors/empty_radix: --radix= is rejected as invalid - offset/flag_order_t_then_o: -t d -o → octal (last wins) - offset/flag_order_o_then_t: -o -t d → decimal (last wins) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: alexandre.yang <alexandre.yang@datadoghq.com>
When `continue N` exceeded the loop nesting depth (e.g. `continue 99` in a single loop), the shell incorrectly treated it like `break` and exited the loop after the first iteration. Bash discards excess levels and continues iterating. The fix checks for excess continue levels after `loopStmtsBroken` returns and clamps them at the outermost loop, allowing iteration to continue. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Codex Review: Didn't find any major issues. More of your lovely PRs please. ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
AlexandreYang
left a comment
There was a problem hiding this comment.
Code Review — PR #45: Implement if/elif/else
Overall assessment: safe to merge ✅
(Note: Cannot self-approve own PR, submitting as COMMENT)
This is a clean, well-structured implementation of if/elif/else support. The change is minimal, correct, and thoroughly tested.
Review Summary
| # | Priority | File | Finding |
|---|---|---|---|
| — | — | — | No issues found |
Security
- Sandbox integrity: No new command execution paths introduced. The if clause handler only controls flow using existing
r.stmtsandr.cmdcalls. All commands inside if conditions/bodies are still validated byvalidateNodebefore execution. ✓ - Break/continue propagation: Correctly stops executing remaining statements in if bodies when break/continue/exit fires. ✓
- No new imports or external calls: The implementation uses only existing interpreter primitives. ✓
Bash Compatibility
- Condition evaluation: Uses exit code of last statement in condition list — matches bash. ✓
- elif chains: Recursive
IfClause.Elsehandling correctly mirrors bash's elif/else semantics. ✓ - Exit code when no branch taken (
if false; then ...; fi): Correctly resets to 0, matching bash. ✓ - Break/continue through if inside loops: Correctly propagates, matching bash. ✓
Correctness
stmtsearly-return fix (line 207): The newexit.exiting || breakEnclosing > 0 || contnEnclosing > 0check is essential — without it, statements after break/continue/exit in if bodies (and brace groups) would still execute. This is a broader correctness fix that also benefitsBlockhandling. ✓- Excess continue clamping (line 183-185): Correctly handles
continue 99at the outermost loop by clamping and continuing iteration, matching bash behavior. ✓ - Post-loop clamping (line 192-195): Safety net that clears excess break/continue levels at the outermost loop boundary. ✓
r.exit = exitStatus{}in else branch (line 162): Correctly resets exit before processing elif/else — thebreakguard at line 156-158 ensures fatal exits are not cleared. ✓
Test Coverage
| Code path | Scenario test | Go test | Status |
|---|---|---|---|
| Basic if true/false | basic_if.yaml, basic_if_false.yaml | — | Covered |
| if-else | if_else.yaml | — | Covered |
| if-elif-else chain | if_elif.yaml, if_elif_else.yaml, if_elif_first_true.yaml, if_elif_second_true.yaml | — | Covered |
| Conditions (&&, pipes, !, test) | 14 condition scenarios | — | Covered |
| Exit codes (then, else, elif, no-branch) | 4 exit_code scenarios | — | Covered |
| Loop interaction (break, continue) | break_in_if.yaml, continue_in_if.yaml, break_in_else.yaml, for_in_if_body.yaml | TestIfPentestBreakInCondition, TestIfPentestContinueInElif | Covered |
| Nested if, if-as-condition | nested_if.yaml, nested_if_else.yaml, if_condition_as_nested_if.yaml | — | Covered |
| Edge cases (pipeline, assignment, blocked features) | 8 edge case scenarios | — | Covered |
| Deep nesting (100 levels) | — | TestIfPentestDeeplyNestedIf, TestIfPentestDeeplyNestedElif | Covered |
| Context cancellation | — | TestIfPentestContextCancellation | Covered |
| Exit in various positions | — | TestIfPentestExitInCondition/Else/Elif | Covered |
| Blocked features in if | — | TestIfPentestSubshellInCondition, TestIfPentestFuncDeclInBody, TestIfPentestBackgroundInBody | Covered |
| continue 99 multi-iteration | continue_exceeds_depth_multi_iter.yaml | — | Covered |
Coverage: Adequate — all new/changed code paths are covered by scenario and/or Go tests.
Positive Observations
- Elegant recursive design: Using
IfClause.Elserecursion for elif/else mirrors the AST structure and keeps the handler minimal (~12 lines). - Defensive
stmtsfix: The early-return instmtsis a broader correctness improvement that benefits brace groups too. - Comprehensive test battery: 40+ scenario tests plus pentest Go tests covering deep nesting, context cancellation, blocked features, and break/continue edge cases.
- Validation consistency: The blocked-command tests were cleanly updated to use
whileinstead ofif, maintaining test coverage for the validation path. - Documentation updated: SHELL_FEATURES.md correctly reflects the new support.
|
I can only run on private repositories. |
Review-Fix Loop Summary
Iteration log
Final state
Remaining issuesNone. PR is clean and ready to merge. |
AlexandreYang
left a comment
There was a problem hiding this comment.
Code Review (iteration 2) — PR #45: Implement if/elif/else
Overall assessment: safe to merge ✅ — No findings.
Re-reviewed at the same HEAD (aa2a6d7). All previous analysis holds:
- Security: No sandbox escapes. If clause uses existing
r.stmts/r.cmdprimitives;validateNodestill walks the full AST. - Bash compatibility: Condition evaluation, elif chains, exit codes, break/continue propagation all match bash.
- Correctness:
stmtsearly-return fix is essential and correct. Excess break/continue clamping at outermost loop is correct. - Test coverage: Adequate — 40+ scenario tests + pentest Go tests.
- No P0–P3 findings.
|
I can only run on private repositories. |
Review-Fix Loop Summary (Run 2)
Iteration log
Final state
Remaining issuesNone. PR is clean and ready to merge. |
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
/merge |
|
View all feedbacks in Devflow UI.
The expected merge time in
|
|
Codex Review: Didn't find any major issues. Nice work! ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. Codex can also answer questions or update the PR. Try commenting "@codex address that feedback". |
Summary
if/elif/elseconditional construct support to the shell interpreter*syntax.IfClausewhile keeping child node validation (blocked features like subshells in conditions are still rejected)case *syntax.IfClauseincmd()dispatcher following mvdan/sh's reference patternstmts()to check break/continue/exit between statements, ensuringbreakinside if bodies within loops propagates correctlybreak 99with 1 loop)Test plan
if_clause_test.gogo test ./interp/... ./tests/...RSHELL_BASH_TEST=1 go test ./tests/ -run TestShellScenariosAgainstBash🤖 Generated with Claude Code