fix(boulder): count only top-level checkboxes in simple-mode plan progress
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -650,6 +650,65 @@ describe("boulder-state", () => {
|
||||
expect(progress.completed).toBe(1)
|
||||
expect(progress.isComplete).toBe(false)
|
||||
})
|
||||
|
||||
test("should count only top-level checkboxes for simple plans with nested tasks", () => {
|
||||
// given
|
||||
const planPath = join(TEST_DIR, "simple-nested-plan.md")
|
||||
writeFileSync(planPath, `# Plan
|
||||
|
||||
- [ ] Top-level task 1
|
||||
- [x] Nested task ignored
|
||||
- [x] Top-level task 2
|
||||
* [ ] Another nested task ignored
|
||||
`)
|
||||
|
||||
// when
|
||||
const progress = getPlanProgress(planPath)
|
||||
|
||||
// then
|
||||
expect(progress.total).toBe(2)
|
||||
expect(progress.completed).toBe(1)
|
||||
expect(progress.isComplete).toBe(false)
|
||||
})
|
||||
|
||||
test("should treat final-wave-only plans as structured mode", () => {
|
||||
// given
|
||||
const planPath = join(TEST_DIR, "final-wave-only-plan.md")
|
||||
writeFileSync(planPath, `# Plan
|
||||
|
||||
## Final Verification Wave
|
||||
- [ ] F1. Top-level final review
|
||||
- [x] Nested verification detail ignored
|
||||
`)
|
||||
|
||||
// when
|
||||
const progress = getPlanProgress(planPath)
|
||||
|
||||
// then
|
||||
expect(progress.total).toBe(1)
|
||||
expect(progress.completed).toBe(0)
|
||||
expect(progress.isComplete).toBe(false)
|
||||
})
|
||||
|
||||
test("should ignore mixed indentation levels in simple plans", () => {
|
||||
// given
|
||||
const planPath = join(TEST_DIR, "simple-mixed-indentation-plan.md")
|
||||
writeFileSync(planPath, `# Plan
|
||||
|
||||
* [x] Top-level star task
|
||||
- [ ] Indented task ignored
|
||||
- [x] Tab-indented task ignored
|
||||
- [ ] Top-level dash task
|
||||
`)
|
||||
|
||||
// when
|
||||
const progress = getPlanProgress(planPath)
|
||||
|
||||
// then
|
||||
expect(progress.total).toBe(2)
|
||||
expect(progress.completed).toBe(1)
|
||||
expect(progress.isComplete).toBe(false)
|
||||
})
|
||||
})
|
||||
|
||||
describe("getPlanName", () => {
|
||||
|
||||
@@ -226,7 +226,9 @@ export function getPlanProgress(planPath: string): PlanProgress {
|
||||
const lines = content.split(/\r?\n/)
|
||||
|
||||
// Check if the plan has structured sections (## TODOs / ## Final Verification Wave)
|
||||
const hasStructuredSections = lines.some((line) => TODO_HEADING_PATTERN.test(line))
|
||||
const hasStructuredSections = lines.some(
|
||||
(line) => TODO_HEADING_PATTERN.test(line) || FINAL_VERIFICATION_HEADING_PATTERN.test(line),
|
||||
)
|
||||
|
||||
if (hasStructuredSections) {
|
||||
// Structured plan: only count top-level checkboxes with numbered labels
|
||||
@@ -291,8 +293,8 @@ function getStructuredPlanProgress(lines: string[]): PlanProgress {
|
||||
}
|
||||
|
||||
function getSimplePlanProgress(content: string): PlanProgress {
|
||||
const uncheckedMatches = content.match(/^\s*[-*]\s*\[\s*\]/gm) || []
|
||||
const checkedMatches = content.match(/^\s*[-*]\s*\[[xX]\]/gm) || []
|
||||
const uncheckedMatches = content.match(/^[-*]\s*\[\s*\]/gm) || []
|
||||
const checkedMatches = content.match(/^[-*]\s*\[[xX]\]/gm) || []
|
||||
|
||||
const total = uncheckedMatches.length + checkedMatches.length
|
||||
const completed = checkedMatches.length
|
||||
|
||||
Reference in New Issue
Block a user