ComplexityScore returns a value in [0, 10] estimating how much a task would benefit from up-front planning. The score blends three signals: - distinct action verbs (capped at 5 contributions) - distinct file artifacts mentioned (capped at 3) - sequencer tokens that imply ordered sub-steps (capped a
(task string)
| 67 | // refactor ("update auth.go and add tests/auth_test.go then run go test") |
| 68 | // hits the 6+ threshold and triggers Plan-First when Mode=auto. |
| 69 | func ComplexityScore(task string) int { |
| 70 | if strings.TrimSpace(task) == "" { |
| 71 | return 0 |
| 72 | } |
| 73 | lower := strings.ToLower(task) |
| 74 | |
| 75 | // Action verbs (cap 5). |
| 76 | verbs := countDistinctVerbs(lower, 5) |
| 77 | |
| 78 | // Concrete file artifacts (cap 3). |
| 79 | files := countDistinctMatches(fileExtensionRE.FindAllString(task, -1), 3) |
| 80 | files += countDistinctMatches(dockerfilesRE.FindAllString(task, -1), 3-files) |
| 81 | |
| 82 | // Sequencer tokens (cap 2). |
| 83 | seqs := 0 |
| 84 | for _, s := range sequencers { |
| 85 | if strings.Contains(lower, s) { |
| 86 | seqs++ |
| 87 | if seqs >= 2 { |
| 88 | break |
| 89 | } |
| 90 | } |
| 91 | } |
| 92 | |
| 93 | score := verbs + files + seqs |
| 94 | if score > 10 { |
| 95 | score = 10 |
| 96 | } |
| 97 | if score < 0 { |
| 98 | score = 0 |
| 99 | } |
| 100 | return score |
| 101 | } |
| 102 | |
| 103 | // ShouldPlanFirst decides whether the orchestrator should synthesize a |
| 104 | // structured plan before dispatching, given the user-configured mode and |