diff --git a/docs/roadmap/implementation.md b/docs/roadmap/implementation.md index c97f71f..b5561c3 100644 --- a/docs/roadmap/implementation.md +++ b/docs/roadmap/implementation.md @@ -468,6 +468,10 @@ creation (previously 9, 135, and 8,255). Prompt requirements tests pass on Go comparisons retain known/skipped/unknown outcomes, inactive computed names, optional index behavior, root access, and meaningful incompleteness. +Completion: `if` and `with` share branch traversal while retaining distinct body +and else dot scopes. Focused internal and public requirements tests pass on Go +1.27.3, including existing independent rendering and skipped-path cases. + ## Stage 18: Add Bounded Diagnostic Prefix Encoding **Catalog:** 17, encoding primitive. **Files:** repair formatter private helpers/tests. diff --git a/internal/prompt/requirements.go b/internal/prompt/requirements.go index a6373a0..4c02e76 100644 --- a/internal/prompt/requirements.go +++ b/internal/prompt/requirements.go @@ -451,6 +451,34 @@ func (walker *requirementWalker) walkTemplate(compiled *template.Template) error return err } +func (walker *requirementWalker) visitBranch(branch *parse.BranchNode, reach requirementReachability, dot dotIdentity, changesDot bool) error { + condition := conditionEvaluation{} + if reach == requirementInactive { + if err := walker.visit(branch.Pipe, requirementInactive, dot); err != nil { + return err + } + } else { + condition = walker.evaluateCondition(branch.Pipe, reach, dot) + } + before := walker.dependencies + bodyDot := dot + if changesDot { + bodyDot = walker.withDotIdentity(branch.Pipe, dot, condition) + } + thenReach := branchReach(reach, condition.known, condition.truth(), true) + elseReach := branchReach(reach, condition.known, condition.truth(), false) + if err := walker.visit(branch.List, thenReach, bodyDot); err != nil { + return err + } + if err := walker.visit(branch.ElseList, elseReach, dot); err != nil { + return err + } + if reach != requirementInactive && !condition.known && walker.dependencies != before { + walker.recordConditionLimitation(condition) + } + return nil +} + func (walker *requirementWalker) visit(node parse.Node, reach requirementReachability, dot dotIdentity) error { if err := walker.ctx.Err(); err != nil { return err @@ -471,55 +499,9 @@ func (walker *requirementWalker) visit(node parse.Node, reach requirementReachab case *parse.ActionNode: return walker.visit(node.Pipe, reach, dot) case *parse.IfNode: - if reach == requirementInactive { - if err := walker.visit(node.Pipe, requirementInactive, dot); err != nil { - return err - } - if err := walker.visit(node.List, requirementInactive, dot); err != nil { - return err - } - return walker.visit(node.ElseList, requirementInactive, dot) - } - condition := walker.evaluateCondition(node.Pipe, reach, dot) - before := walker.dependencies - thenReach := branchReach(reach, condition.known, condition.truth(), true) - elseReach := branchReach(reach, condition.known, condition.truth(), false) - if err := walker.visit(node.List, thenReach, dot); err != nil { - return err - } - if err := walker.visit(node.ElseList, elseReach, dot); err != nil { - return err - } - if !condition.known && walker.dependencies != before { - walker.recordConditionLimitation(condition) - } - return nil + return walker.visitBranch(&node.BranchNode, reach, dot, false) case *parse.WithNode: - if reach == requirementInactive { - if err := walker.visit(node.Pipe, requirementInactive, dot); err != nil { - return err - } - bodyDot := walker.withDotIdentity(node.Pipe, dot, conditionEvaluation{}) - if err := walker.visit(node.List, requirementInactive, bodyDot); err != nil { - return err - } - return walker.visit(node.ElseList, requirementInactive, dot) - } - condition := walker.evaluateCondition(node.Pipe, reach, dot) - before := walker.dependencies - thenReach := branchReach(reach, condition.known, condition.truth(), true) - elseReach := branchReach(reach, condition.known, condition.truth(), false) - bodyDot := walker.withDotIdentity(node.Pipe, dot, condition) - if err := walker.visit(node.List, thenReach, bodyDot); err != nil { - return err - } - if err := walker.visit(node.ElseList, elseReach, dot); err != nil { - return err - } - if !condition.known && walker.dependencies != before { - walker.recordConditionLimitation(condition) - } - return nil + return walker.visitBranch(&node.BranchNode, reach, dot, true) case *parse.RangeNode: if err := walker.visit(node.Pipe, reach, dot); err != nil { return err