Packages

A library for validating Markdown task lists with structured format specifications. Features: checkbox subtasks, dependencies, code quality KPIs, task categories, multi-project prefixes, and comprehensive error handling documentation.

Current section

16 Versions

Jump to

Compare versions

5 files changed
+1117 additions
-131 deletions
  @@ -9,7 +9,7 @@ Add `task_validator` to your list of dependencies in `mix.exs`:
9 9 ```elixir
10 10 def deps do
11 11 [
12 - {:task_validator, "~> 0.5.0"}
12 + {:task_validator, "~> 0.6.0"}
13 13 ]
14 14 end
15 15 ```
  @@ -30,6 +30,10 @@ mix create_template
30 30
31 31 # Create a template with custom prefix
32 32 mix create_template --prefix SSH
33 +
34 + # Create a template for a specific category
35 + mix create_template --category features
36 + mix create_template --category documentation
33 37 ```
34 38
35 39 ### Programmatic
  @@ -48,17 +52,26 @@ end
48 52 The TaskValidator enforces a specific format for task lists with a strong focus on error handling:
49 53
50 54 - Task IDs must follow a consistent pattern: 2-4 uppercase letters followed by 3-4 digits (e.g., SSH0001, SCP0001, ERR001, REF0002)
51 - - Subtasks must use the same prefix as their parent task (e.g., SSH0001-1 for a subtask of SSH0001)
55 + - Subtasks can use either numeric suffixes (SSH0001-1) or letter suffixes for checkbox style (SSH0001a)
56 + - Checkbox subtasks are supported: `- [ ] Subtask description [SSH0001a]`
57 + - Dependencies field tracks relationships between tasks
58 + - Code Quality KPIs enforce limits: max 5 functions/module, 15 lines/function, call depth 2
59 + - Task categories with specific number ranges:
60 + * Core infrastructure: 1-99
61 + * Features: 100-199
62 + * Documentation: 200-299
63 + * Testing: 300-399
52 64 - Main tasks and subtasks have different error handling section requirements:
53 65 * Main tasks: Comprehensive error handling documentation including GenServer specifics
54 66 * Subtasks: Simplified error handling focused on task-specific approaches
55 - - Other required sections include Description, Status, Priority, etc.
67 + - Other required sections include Description, Status, Priority, Dependencies, etc.
56 68 - Tasks marked as "In Progress" must have subtasks
57 69 - Review ratings must follow the specified format (1-5 scale)
70 + - Support for reference definitions to reduce repetition (e.g., {{error-handling-main}})
58 71
59 72 ### Error Handling Requirements
60 73
61 - Main tasks must include the following comprehensive error handling sections:
74 + Main tasks must include the following comprehensive error handling sections (or use the `{{error-handling-main}}` reference):
62 75
63 76 ```markdown
64 77 **Error Handling**
  @@ -80,6 +93,8 @@ Main tasks must include the following comprehensive error handling sections:
80 93 - Process linking considerations
81 94 ```
82 95
96 + Or simply use: `{{error-handling-main}}`
97 +
83 98 Subtasks have a simplified error handling format:
84 99
85 100 ```markdown
  @@ -90,6 +105,105 @@ Subtasks have a simplified error handling format:
90 105 - Monitoring approach
91 106 ```
92 107
108 + Or use: `{{error-handling-subtask}}`
109 +
110 + ### Dependencies
111 +
112 + Tasks can specify dependencies on other tasks using the Dependencies field:
113 +
114 + ```markdown
115 + **Dependencies**
116 + - SSH0001 (Authentication must be complete)
117 + - ERR001 (Error handling framework required)
118 + ```
119 +
120 + The validator ensures all referenced tasks exist in the task list.
121 +
122 + ### Checkbox Subtasks
123 +
124 + Subtasks can use checkbox format for better visual tracking:
125 +
126 + ```markdown
127 + ## Task Details
128 +
129 + ### SSH0001: SSH Session Initialization
130 +
131 + **Subtasks**
132 + - [x] Connection setup [SSH0001a]
133 + - [ ] Authentication flow [SSH0001b]
134 + - [ ] Session establishment [SSH0001c]
135 + ```
136 +
137 + ### Code Quality KPIs
138 +
139 + All tasks must include code quality metrics that adhere to these limits:
140 + - Maximum functions per module: 5
141 + - Maximum lines per function: 15
142 + - Maximum call depth: 2
143 +
144 + ```markdown
145 + **Code Quality KPIs**
146 + - Functions per module: 3
147 + - Lines per function: 12
148 + - Call depth: 2
149 + ```
150 +
151 + Or use: `{{standard-kpis}}`
152 +
153 + ### Reference Definitions
154 +
155 + To reduce repetition in task lists, you can define reusable content blocks:
156 +
157 + ```markdown
158 + ## Reference Definitions
159 +
160 + ### error-handling-main
161 + **Error Handling**
162 + **Core Principles**
163 + - Pass raw errors
164 + ...
165 +
166 + ### standard-kpis
167 + **Code Quality KPIs**
168 + - Functions per module: 3
169 + ...
170 + ```
171 +
172 + Then use them in tasks with `{{reference-name}}`:
173 +
174 + ```markdown
175 + ### SSH0001: Some task
176 +
177 + **Dependencies**
178 + - None
179 +
180 + {{standard-kpis}}
181 +
182 + {{error-handling-main}}
183 +
184 + **Status**: Planned
185 + ```
186 +
187 + This significantly reduces file size and maintains consistency across tasks.
188 +
189 + ### Task Categories
190 +
191 + Tasks are organized into categories based on their ID number:
192 + - **Core Infrastructure (1-99)**: Essential system components
193 + - **Features (100-199)**: User-facing functionality
194 + - **Documentation (200-299)**: Documentation tasks
195 + - **Testing (300-399)**: Test implementation
196 +
197 + Each category has specific required sections. For example, feature tasks require:
198 + - Feature Specification
199 + - User Impact
200 + - Integration Points
201 +
202 + Documentation tasks require:
203 + - Documentation Scope
204 + - Target Audience
205 + - Related Documents
206 +
93 207 ## Multi-Project Support
94 208
95 209 The task validator supports multiple project prefixes in the same task list. Each prefix typically represents a different component or subproject:
  @@ -2,9 +2,9 @@
2 2 [{<<"Docs">>,<<"https://hexdocs.pm/task_validator">>},
3 3 {<<"GitHub">>,<<"https://github.com/ZenHive/task_validator">>}]}.
4 4 {<<"name">>,<<"task_validator">>}.
5 - {<<"version">>,<<"0.5.0">>}.
5 + {<<"version">>,<<"0.6.0">>}.
6 6 {<<"description">>,
7 - <<"A library for validating Markdown task lists with structured format specifications.\nEnforces error handling documentation, supports multi-project prefixes (SSH0001, ERR001),\nand ensures consistent task tracking with ID formats and required sections.">>}.
7 + <<"A library for validating Markdown task lists with structured format specifications.\nFeatures: checkbox subtasks, dependencies, code quality KPIs, task categories,\nmulti-project prefixes, and comprehensive error handling documentation.">>}.
8 8 {<<"elixir">>,<<"~> 1.18">>}.
9 9 {<<"app">>,<<"task_validator">>}.
10 10 {<<"files">>,
  @@ -13,24 +13,63 @@ defmodule Mix.Tasks.TaskValidator.CreateTemplate do
13 13 ## Options
14 14
15 15 --path Path where to create the TaskList.md file (default: ./TaskList.md)
16 - --prefix Project prefix for example tasks (default: PRJ)
16 + --prefix Project prefix for example tasks (default: PRJ)
17 + --category Task category to generate template for: core, features, documentation, testing (default: features)
17 18
18 19 ## Example
19 20
20 21 mix task_validator.create_template
21 - mix task_validator.create_template --path ./docs/TaskList.md --prefix SSH
22 + mix task_validator.create_template --path ./docs/TaskList.md --prefix SSH --category core
23 + mix task_validator.create_template --category documentation
22 24 """
23 25
24 26 use Mix.Task
25 27
26 - @template """
28 + @reference_definitions """
29 +
30 + ## Reference Definitions
31 +
32 + ### error-handling-main
33 + **Error Handling**
34 + **Core Principles**
35 + - Pass raw errors
36 + - Use {:ok, result} | {:error, reason}
37 + - Let it crash
38 + **Error Implementation**
39 + - No wrapping
40 + - Minimal rescue
41 + - function/1 & /! versions
42 + **Error Examples**
43 + - Raw error passthrough
44 + - Simple rescue case
45 + - Supervisor handling
46 + **GenServer Specifics**
47 + - Handle_call/3 error pattern
48 + - Terminate/2 proper usage
49 + - Process linking considerations
50 +
51 + ### error-handling-subtask
52 + **Error Handling**
53 + **Task-Specific Approach**
54 + - Error pattern for this task
55 + **Error Reporting**
56 + - Monitoring approach
57 +
58 + ### standard-kpis
59 + **Code Quality KPIs**
60 + - Functions per module: 3
61 + - Lines per function: 12
62 + - Call depth: 2
63 + """
64 +
65 + @features_template """
27 66 # Project Task List
28 67
29 68 ## Current Tasks
30 69
31 70 | ID | Description | Status | Priority | Assignee | Review Rating |
32 71 | --- | --- | --- | --- | --- | --- |
33 - | <%= @prefix %>0001 | Implement core functionality | In Progress | High | - | - |
72 + | <%= @prefix %><%= @task_number %> | Implement core functionality | In Progress | High | - | - |
34 73 | <%= @prefix %>0002 | Add documentation framework | Planned | Medium | - | - |
35 74
36 75 ## Completed Tasks
  @@ -41,7 +80,7 @@ defmodule Mix.Tasks.TaskValidator.CreateTemplate do
41 80
42 81 ## Active Task Details
43 82
44 - ### <%= @prefix %>0001: Implement core functionality
83 + ### <%= @prefix %><%= @task_number %>: Implement core functionality
45 84
46 85 **Description**
47 86 Develop and implement the core functionality with a focus on maintainability and extensibility.
  @@ -89,53 +128,46 @@ defmodule Mix.Tasks.TaskValidator.CreateTemplate do
89 128 **TypeSpec Verification**
90 129 Use Dialyzer to verify type correctness
91 130
92 - **Error Handling**
93 - **Core Principles**
94 - - Pass raw errors
95 - - Use {:ok, result} | {:error, reason}
96 - - Let it crash
97 - **Error Implementation**
98 - - No wrapping
99 - - Minimal rescue
100 - - function/1 & /! versions
101 - **Error Examples**
102 - - Raw error passthrough
103 - - Simple rescue case
104 - - Supervisor handling
105 - **GenServer Specifics**
106 - - Handle_call/3 error pattern
107 - - Terminate/2 proper usage
108 - - Process linking considerations
131 + **Dependencies**
132 + - None
109 133
110 - **Status**: In Progress
134 + {{standard-kpis}}
135 +
136 + {{error-handling-main}}
137 +
138 + **Status**: Planned
111 139 **Priority**: High
112 140
113 - #### 1. Basic structure implementation (<%= @prefix %>0001-1)
141 + **Architecture Notes**
142 + Core system component design
143 +
144 + **Complexity Assessment**
145 + Medium - Requires careful design but implementation is straightforward
146 +
147 + **System Impact**
148 + Foundation for other modules
149 +
150 + **Dependency Analysis**
151 + No external dependencies
152 +
153 + #### 1. Basic structure implementation (<%= @prefix %><%= @task_number %>-1)
114 154
115 155 **Description**
116 156 Create the foundational structure and interfaces
117 157
118 - **Error Handling**
119 - **Task-Specific Approach**
120 - - Error pattern for this task
121 - **Error Reporting**
122 - - Monitoring approach
158 + {{error-handling-subtask}}
123 159
124 160 **Status**: Completed
125 161 **Review Rating**: 4.5
126 162
127 - #### 2. Essential features (<%= @prefix %>0001-2)
163 + #### 2. Essential features (<%= @prefix %><%= @task_number %>-2)
128 164
129 165 **Description**
130 166 Implement core features and functionality
131 167
132 - **Error Handling**
133 - **Task-Specific Approach**
134 - - Error pattern for this task
135 - **Error Reporting**
136 - - Monitoring approach
168 + {{error-handling-subtask}}
137 169
138 - **Status**: In Progress
170 + **Status**: Planned
139 171
140 172 ### <%= @prefix %>0002: Add documentation framework
141 173
  @@ -180,42 +212,463 @@ defmodule Mix.Tasks.TaskValidator.CreateTemplate do
180 212 **TypeSpec Verification**
181 213 Regular verification of documentation accuracy
182 214
183 - **Error Handling**
184 - **Core Principles**
185 - - Pass raw errors
186 - - Use {:ok, result} | {:error, reason}
187 - - Let it crash
188 - **Error Implementation**
189 - - No wrapping
190 - - Minimal rescue
191 - - function/1 & /! versions
192 - **Error Examples**
193 - - Raw error passthrough
194 - - Simple rescue case
195 - - Supervisor handling
196 - **GenServer Specifics**
197 - - Handle_call/3 error pattern
198 - - Terminate/2 proper usage
199 - - Process linking considerations
215 + **Dependencies**
216 + - None
217 +
218 + {{standard-kpis}}
219 +
220 + {{error-handling-main}}
200 221
201 222 **Status**: Planned
202 223 **Priority**: Medium
224 +
225 + **Architecture Notes**
226 + Documentation framework choice
227 +
228 + **Complexity Assessment**
229 + Low - Standard documentation setup
230 +
231 + **System Impact**
232 + Developer experience improvement
233 +
234 + **Dependency Analysis**
235 + Depends on core module
236 + """
237 +
238 + @core_template """
239 + # Project Task List
240 +
241 + ## Current Tasks
242 +
243 + | ID | Description | Status | Priority | Assignee | Review Rating |
244 + | --- | --- | --- | --- | --- | --- |
245 + | <%= @prefix %>0001 | Core architecture implementation | Planned | High | - | - |
246 + | <%= @prefix %>0002 | Add documentation framework | Planned | Medium | - | - |
247 +
248 + ## Completed Tasks
249 +
250 + | ID | Description | Status | Completed By | Review Rating |
251 + | --- | --- | --- | ------------ | ------------- |
252 + | <%= @prefix %>0003 | Project setup | Completed | @developer | 4.5 |
253 +
254 + ## Active Task Details
255 +
256 + ### <%= @prefix %><%= @task_number %>: Core architecture implementation
257 +
258 + **Description**
259 + Implement core system architecture with focus on performance and reliability.
260 +
261 + **Simplicity Progression Plan**
262 + 1. Design core interfaces
263 + 2. Implement basic functionality
264 + 3. Add error handling
265 + 4. Optimize performance
266 +
267 + **Simplicity Principle**
268 + Focus on essential functionality with minimal complexity and maximum reliability.
269 +
270 + **Abstraction Evaluation**
271 + Low-level implementation with clear separation of concerns
272 +
273 + **Requirements**
274 + - High performance architecture
275 + - Robust error handling
276 + - Scalable design patterns
277 + - Comprehensive testing
278 +
279 + **ExUnit Test Requirements**
280 + - Performance benchmarks
281 + - Load testing
282 + - Failure scenario testing
283 +
284 + **Integration Test Scenarios**
285 + - System integration tests
286 + - Performance under load
287 + - Failure recovery testing
288 +
289 + **Typespec Requirements**
290 + - Core type definitions
291 + - Interface specifications
292 +
293 + **TypeSpec Documentation**
294 + Complete documentation of all core types and interfaces
295 +
296 + **TypeSpec Verification**
297 + Strict type checking with Dialyzer
298 +
299 + **Dependencies**
300 + - None
301 +
302 + **Code Quality KPIs**
303 + - Functions per module: 3
304 + - Lines per function: 12
305 + - Call depth: 2
306 +
307 + **Architecture Notes**
308 + Core system design using proven patterns and minimal dependencies
309 +
310 + **Complexity Assessment**
311 + Medium complexity focused on correctness and performance
312 +
313 + {{error-handling-main}}
314 +
315 + **Status**: Planned
316 + **Priority**: High
317 +
318 + **Architecture Notes**
319 + Simple initial design
320 +
321 + **Complexity Assessment**
322 + Low - Basic structure only
323 +
324 + #### 1. Basic structure implementation (<%= @prefix %><%= @task_number %>-1)
325 +
326 + **Description**
327 + Create the foundational architecture and core interfaces
328 +
329 + {{error-handling-subtask}}
330 +
331 + **Status**: Completed
332 + **Review Rating**: 4.5
333 +
334 + #### 2. Performance optimization (<%= @prefix %><%= @task_number %>-2)
335 +
336 + **Description**
337 + Implement performance optimizations and monitoring
338 +
339 + {{error-handling-subtask}}
340 +
341 + **Status**: Planned
342 +
343 +
344 + ### <%= @prefix %>0002: Add documentation framework
345 +
346 + **Description**
347 + Set up and implement the documentation framework for the project.
348 +
349 + **Simplicity Progression Plan**
350 + 1. Set up documentation tools
351 + 2. Create basic structure
352 + 3. Add API documentation
353 + 4. Create user guides
354 +
355 + **Simplicity Principle**
356 + Keep documentation clear, concise, and maintainable
357 +
358 + **Abstraction Evaluation**
359 + Low - straightforward documentation structure
360 +
361 + **Requirements**
362 + - Documentation tool setup
363 + - API documentation
364 + - User guides
365 + - Example code
366 +
367 + **ExUnit Test Requirements**
368 + - Documentation generation tests
369 + - Link validation
370 + - Code example tests
371 +
372 + **Integration Test Scenarios**
373 + - Documentation generation
374 + - Format validation
375 + - Cross-reference checks
376 +
377 + **Typespec Requirements**
378 + - Document type specifications
379 + - Include type examples
380 +
381 + **TypeSpec Documentation**
382 + Clear documentation of all public types
383 +
384 + **TypeSpec Verification**
385 + Regular verification of documentation accuracy
386 +
387 + **Dependencies**
388 + - <%= @prefix %>0001
389 +
390 + {{standard-kpis}}
391 +
392 + **Architecture Notes**
393 + Standard documentation framework
394 +
395 + **Complexity Assessment**
396 + Low - Standard tooling
397 +
398 + {{error-handling-main}}
399 +
400 + **Status**: Planned
401 + **Priority**: Medium
402 +
403 + ## Completed Task Details
404 +
405 + ### <%= @prefix %>0003: Project setup
406 +
407 + **Description**
408 + Initial project setup and structure implementation
409 +
410 + **Simplicity Progression Plan**
411 + 1. Create directory structure
412 + 2. Set up build configuration
413 + 3. Initialize version control
414 +
415 + **Simplicity Principle**
416 + Standard project layout with minimal configuration
417 +
418 + **Abstraction Evaluation**
419 + Low - Direct implementation
420 +
421 + **Requirements**
422 + - Directory structure
423 + - Build configuration
424 + - Initial documentation
425 +
426 + **ExUnit Test Requirements**
427 + - Verify build process
428 + - Test configuration loading
429 +
430 + **Integration Test Scenarios**
431 + - Full project build and test
432 +
433 + **Typespec Requirements**
434 + - Basic type definitions
435 + - Module specifications
436 +
437 + **TypeSpec Documentation**
438 + Document core type specifications
439 +
440 + **TypeSpec Verification**
441 + Initial Dialyzer setup and verification
442 +
443 + **Dependencies**
444 + - None
445 +
446 + {{standard-kpis}}
447 +
448 + **Architecture Notes**
449 + Simple standard structure
450 +
451 + **Complexity Assessment**
452 + Low - Basic setup only
453 +
454 + {{error-handling-main}}
455 +
456 + **Error Handling Implementation**
457 + Standard error patterns
458 +
459 + **Status**: Completed
460 + **Priority**: High
461 +
462 + **Implementation Notes**
463 + Basic project structure created
464 +
465 + **Maintenance Impact**
466 + Minimal - standard structure
467 +
468 + **Review Rating**: 4.5
469 +
470 + """
471 +
472 + @documentation_template """
473 + # Project Task List
474 +
475 + ## Current Tasks
476 +
477 + | ID | Description | Status | Priority | Assignee | Review Rating |
478 + | --- | --- | --- | --- | --- | --- |
479 + | <%= @prefix %><%= @task_number %> | Create comprehensive documentation | Planned | Medium | - | - |
480 +
481 + ## Completed Tasks
482 +
483 + | ID | Description | Status | Completed By | Review Rating |
484 + | --- | --- | --- | ------------ | ------------- |
485 +
486 + ## Active Task Details
487 +
488 + ### <%= @prefix %><%= @task_number %>: Create comprehensive documentation
489 +
490 + **Description**
491 + Develop user-focused documentation with clear examples and usage patterns.
492 +
493 + **Simplicity Progression Plan**
494 + 1. Analyze target audience
495 + 2. Create content structure
496 + 3. Write core documentation
497 + 4. Add examples and tutorials
498 +
499 + **Simplicity Principle**
500 + Clear, concise documentation that enables users to succeed quickly.
501 +
502 + **Abstraction Evaluation**
503 + Documentation structure that hides complexity while providing necessary details
504 +
505 + **Requirements**
506 + - User-focused content
507 + - Clear examples
508 + - Comprehensive API documentation
509 + - Getting started guides
510 +
511 + **ExUnit Test Requirements**
512 + - Documentation example tests
513 + - Link validation
514 + - Code snippet verification
515 +
516 + **Integration Test Scenarios**
517 + - Documentation build process
518 + - Cross-reference validation
519 + - Example code execution
520 +
521 + **Typespec Requirements**
522 + - Documented type examples
523 + - Usage pattern documentation
524 +
525 + **TypeSpec Documentation**
526 + Clear examples of type usage in documentation
527 +
528 + **TypeSpec Verification**
529 + Ensure all documented types are valid
530 +
531 + **Dependencies**
532 + - None
533 +
534 + **Code Quality KPIs**
535 + - Functions per module: 3
536 + - Lines per function: 12
537 + - Call depth: 2
538 +
539 + **Content Strategy**
540 + User-focused approach with progressive disclosure and practical examples
541 +
542 + **Audience Analysis**
543 + Target developers with varying experience levels, prioritize clarity over completeness
544 +
545 + {{error-handling-main}}
546 +
547 + **Status**: Planned
548 + **Priority**: Medium
549 + **Dependencies**: None
550 + """
551 +
552 + @testing_template """
553 + # Project Task List
554 +
555 + ## Current Tasks
556 +
557 + | ID | Description | Status | Priority | Assignee | Review Rating |
558 + | --- | --- | --- | --- | --- | --- |
559 + | <%= @prefix %><%= @task_number %> | Implement comprehensive testing strategy | Planned | High | - | - |
560 +
561 + ## Completed Tasks
562 +
563 + | ID | Description | Status | Completed By | Review Rating |
564 + | --- | --- | --- | ------------ | ------------- |
565 +
566 + ## Active Task Details
567 +
568 + ### <%= @prefix %><%= @task_number %>: Implement comprehensive testing strategy
569 +
570 + **Description**
571 + Design and implement comprehensive testing approach covering unit, integration, and performance testing.
572 +
573 + **Simplicity Progression Plan**
574 + 1. Define testing strategy
575 + 2. Implement unit tests
576 + 3. Add integration tests
577 + 4. Set up performance testing
578 +
579 + **Simplicity Principle**
580 + Comprehensive test coverage with maintainable test code and clear assertions.
581 +
582 + **Abstraction Evaluation**
583 + Test abstractions that simplify test writing while maintaining clarity
584 +
585 + **Requirements**
586 + - Unit test coverage
587 + - Integration test scenarios
588 + - Performance benchmarks
589 + - Continuous integration
590 +
591 + **ExUnit Test Requirements**
592 + - Comprehensive unit tests
593 + - Property-based testing
594 + - Mock and stub strategies
595 +
596 + **Integration Test Scenarios**
597 + - End-to-end workflow testing
598 + - External service integration
599 + - Error condition testing
600 +
601 + **Typespec Requirements**
602 + - Test helper type definitions
603 + - Mock interface specifications
604 +
605 + **TypeSpec Documentation**
606 + Clear documentation of test interfaces and utilities
607 +
608 + **TypeSpec Verification**
609 + Type-safe test utilities and helpers
610 +
611 + **Dependencies**
612 + - None
613 +
614 + **Code Quality KPIs**
615 + - Functions per module: 3
616 + - Lines per function: 12
617 + - Call depth: 2
618 +
619 + **Test Strategy**
620 + Comprehensive approach using unit tests, integration tests, and performance benchmarks
621 +
622 + **Coverage Requirements**
623 + Minimum 90% code coverage with focus on critical business logic and error paths
624 +
625 + {{error-handling-main}}
626 +
627 + **Status**: Planned
628 + **Priority**: High
629 +
630 + **Architecture Notes**
631 + Simple initial design
632 +
633 + **Complexity Assessment**
634 + Low - Basic structure only
203 635 """
204 636
205 637 def run(args) do
206 - {options, _, _} = OptionParser.parse(args, strict: [path: :string, prefix: :string])
638 + {options, _, _} =
639 + OptionParser.parse(args, strict: [path: :string, prefix: :string, category: :string])
640 +
207 641 path = options[:path] || "TaskList.md"
208 642 prefix = options[:prefix] || "PRJ"
643 + category = options[:category] || "features"
644 +
645 + # Validate category
646 + valid_categories = ["core", "features", "documentation", "testing"]
647 +
648 + unless category in valid_categories do
649 + Mix.shell().error(
650 + "Invalid category: #{category}. Valid options: #{Enum.join(valid_categories, ", ")}"
651 + )
652 +
653 + exit({:shutdown, 1})
654 + end
209 655
210 656 if File.exists?(path) do
211 657 Mix.shell().yes?("File #{path} already exists. Overwrite?") || exit(:normal)
212 658 end
213 659
214 - content = EEx.eval_string(@template, assigns: [prefix: prefix])
660 + # Generate appropriate task number for the category
661 + task_number = get_category_task_number(category)
662 + template = get_template_for_category(category)
663 +
664 + content =
665 + EEx.eval_string(template <> @reference_definitions,
666 + assigns: [prefix: prefix, task_number: task_number]
667 + )
215 668
216 669 case File.write(path, content) do
217 670 :ok ->
218 - Mix.shell().info("✅ Created template task list at #{path}")
671 + Mix.shell().info("✅ Created #{category} category template task list at #{path}")
219 672 validate_template(path)
220 673
221 674 {:error, reason} ->
  @@ -224,6 +677,24 @@ defmodule Mix.Tasks.TaskValidator.CreateTemplate do
224 677 end
225 678 end
226 679
680 + defp get_category_task_number(category) do
681 + case category do
682 + "core" -> "0001"
683 + "features" -> "0101"
684 + "documentation" -> "0201"
685 + "testing" -> "0301"
686 + end
687 + end
688 +
689 + defp get_template_for_category(category) do
690 + case category do
691 + "core" -> @core_template
692 + "features" -> @features_template
693 + "documentation" -> @documentation_template
694 + "testing" -> @testing_template
695 + end
696 + end
697 +
227 698 defp validate_template(path) do
228 699 case TaskValidator.validate_file(path) do
229 700 {:ok, _} ->
  @@ -68,9 +68,23 @@ defmodule TaskValidator do
68 68 @valid_statuses ["Planned", "In Progress", "Review", "Completed", "Blocked"]
69 69 @valid_priorities ["Critical", "High", "Medium", "Low"]
70 70 # Support various prefixes (2-4 uppercase letters) followed by digits
71 - @id_regex ~r/^[A-Z]{2,4}\d{3,4}(-\d+)?$/
71 + # Also support letter suffix for checkbox-style subtasks (e.g., WNX0019a)
72 + @id_regex ~r/^[A-Z]{2,4}\d{3,4}(-\d+|[a-z])?$/
72 73 @rating_regex ~r/^([1-5](\.\d)?)\s*(\(partial\))?$/
73 74
75 + # Code quality KPI limits
76 + @max_functions_per_module 5
77 + @max_lines_per_function 15
78 + @max_call_depth 2
79 +
80 + # Task category ranges
81 + @category_ranges %{
82 + "core" => {1, 99},
83 + "features" => {100, 199},
84 + "documentation" => {200, 299},
85 + "testing" => {300, 399}
86 + }
87 +
74 88 # Required sections for error handling - machine-readable, token-optimized format
75 89 @error_handling_sections [
76 90 "**Error Handling**",
  @@ -118,13 +132,98 @@ defmodule TaskValidator do
118 132 def validate_file(file_path) do
119 133 with {:ok, content} <- File.read(file_path),
120 134 {:ok, lines} <- {:ok, String.split(content, "\n")},
121 - {:ok, tasks} <- extract_tasks(lines),
135 + {:ok, references} <- extract_references(lines),
136 + {:ok, resolved_lines} <- resolve_references(lines, references),
137 + {:ok, tasks} <- extract_tasks(resolved_lines),
122 138 :ok <- validate_task_ids(tasks),
123 - :ok <- validate_task_details(lines, tasks) do
139 + :ok <- validate_task_details(resolved_lines, tasks) do
124 140 {:ok, "TaskList.md validation passed!"}
125 141 end
126 142 end
127 143
144 + @doc """
145 + Extracts reference definitions from the content.
146 + Reference definitions are in the format:
147 + ## Reference Definitions
148 + ### error-handling
149 + **Error Handling**
150 + **Core Principles**
151 + ...
152 + """
153 + @spec extract_references(list(String.t())) :: {:ok, map()}
154 + def extract_references(lines) do
155 + # Find the Reference Definitions section
156 + ref_start = Enum.find_index(lines, &(&1 == "## Reference Definitions"))
157 +
158 + if ref_start do
159 + references =
160 + lines
161 + |> Enum.drop(ref_start + 1)
162 + |> extract_reference_blocks(%{})
163 +
164 + {:ok, references}
165 + else
166 + # No reference definitions found, that's OK
167 + {:ok, %{}}
168 + end
169 + end
170 +
171 + defp extract_reference_blocks([], acc), do: acc
172 +
173 + defp extract_reference_blocks(lines, acc) do
174 + case lines do
175 + ["### " <> ref_name | rest] ->
176 + # Extract content until next ### or end
177 + {content, remaining} =
178 + Enum.split_while(rest, fn line ->
179 + !String.starts_with?(line, "### ") && !String.starts_with?(line, "## ")
180 + end)
181 +
182 + # Store the reference content
183 + updated_acc = Map.put(acc, ref_name, content)
184 + extract_reference_blocks(remaining, updated_acc)
185 +
186 + [_ | rest] ->
187 + extract_reference_blocks(rest, acc)
188 +
189 + [] ->
190 + acc
191 + end
192 + end
193 +
194 + @doc """
195 + Resolves references in the content by replacing {{ref-name}} with actual content.
196 + """
197 + @spec resolve_references(list(String.t()), map()) :: {:ok, list(String.t())}
198 + def resolve_references(lines, references) do
199 + resolved_lines =
200 + Enum.map(lines, fn line ->
201 + # Check if line contains a reference like {{error-handling}}
202 + if String.contains?(line, "{{") && String.contains?(line, "}}") do
203 + case Regex.run(~r/\{\{([^}]+)\}\}/, line) do
204 + [_full_match, ref_name] ->
205 + case Map.get(references, ref_name) do
206 + nil ->
207 + # Reference not found, keep as is
208 + line
209 +
210 + ref_content ->
211 + # Replace the line with the reference content
212 + ref_content
213 + end
214 +
215 + _ ->
216 + line
217 + end
218 + else
219 + line
220 + end
221 + end)
222 + |> List.flatten()
223 +
224 + {:ok, resolved_lines}
225 + end
226 +
128 227 @doc """
129 228 Extracts tasks from the TaskList.md content.
130 229 """
  @@ -309,32 +408,63 @@ defmodule TaskValidator do
309 408 end
310 409
311 410 defp extract_subtasks(task_content) do
312 - # Find lines starting with "#### "
411 + # Find lines starting with "#### " or checkbox format "- [ ]"
313 412 task_content
314 413 |> Enum.with_index()
315 414 |> Enum.filter(fn {line, _} ->
316 - String.match?(line, ~r/^#### \d+\./)
415 + String.match?(line, ~r/^#### \d+\./) || String.match?(line, ~r/^- \[[x\s]\]/)
317 416 end)
318 417 |> Enum.map(fn {line, idx} ->
319 - # Extract subtask ID from the line (PREFIX####-#)
320 - case Regex.run(~r/\(([A-Z]{2,4}\d{3,4}-\d+)\)/, line) do
321 - [_, subtask_id] -> %{id: subtask_id, line: idx}
322 - _ -> %{id: "INVALID_FORMAT", line: idx}
418 + cond do
419 + # Traditional numbered subtask format
420 + String.match?(line, ~r/^#### \d+\./) ->
421 + case Regex.run(~r/\(([A-Z]{2,4}\d{3,4}-\d+)\)/, line) do
422 + [_, subtask_id] -> %{id: subtask_id, line: idx, format: :numbered}
423 + _ -> %{id: "INVALID_FORMAT", line: idx, format: :numbered}
424 + end
425 +
426 + # Checkbox subtask format
427 + String.match?(line, ~r/^- \[[x\s]\]/) ->
428 + # Extract subtask ID from checkbox line
429 + # Support both formats: "- [ ] Description [CHK0001a]" and "- [ ] **CHK0001a**: Description"
430 + subtask_id =
431 + case Regex.run(~r/\[([A-Z]{2,4}\d{3,4}[a-z]?)\]$/, line) do
432 + [_, id] ->
433 + id
434 +
435 + _ ->
436 + case Regex.run(~r/\*\*([A-Z]{2,4}\d{3,4}[a-z]?)\*\*/, line) do
437 + [_, id] -> id
438 + _ -> "INVALID_FORMAT"
439 + end
440 + end
441 +
442 + # Determine if checkbox is checked
443 + checked = String.contains?(line, "[x]")
444 + %{id: subtask_id, line: idx, format: :checkbox, checked: checked}
323 445 end
324 446 end)
325 447 end
326 448
327 449 defp validate_detailed_tasks(detailed_tasks) do
450 + # First, collect all valid task IDs for dependency validation
451 + all_task_ids =
452 + detailed_tasks
453 + |> Enum.flat_map(fn task ->
454 + [task.id | Enum.map(task.subtasks, & &1.id)]
455 + end)
456 + |> MapSet.new()
457 +
328 458 # Validate each detailed task
329 459 Enum.reduce_while(detailed_tasks, :ok, fn task, _acc ->
330 - case validate_task_structure(task) do
460 + case validate_task_structure(task, all_task_ids) do
331 461 :ok -> {:cont, :ok}
332 462 {:error, reason} -> {:halt, {:error, reason}}
333 463 end
334 464 end)
335 465 end
336 466
337 - defp validate_task_structure(task) do
467 + defp validate_task_structure(task, all_task_ids) do
338 468 # First, check subtask prefix consistency
339 469 subtask_prefix_result =
340 470 if task.subtasks != [] do
  @@ -382,8 +512,10 @@ defmodule TaskValidator do
382 512 "**Typespec Requirements**",
383 513 "**TypeSpec Documentation**",
384 514 "**TypeSpec Verification**",
515 + "**Code Quality KPIs**",
385 516 "**Status**",
386 - "**Priority**"
517 + "**Priority**",
518 + "**Dependencies**"
387 519 ]
388 520
389 521 # First check if all base required sections are present
  @@ -435,44 +567,134 @@ defmodule TaskValidator do
435 567
436 568 if missing_sections == [] do
437 569 # Extract status and validate
438 - status_line =
439 - Enum.find(task.content, fn line -> String.starts_with?(line, "**Status**") end)
570 + status_idx =
571 + Enum.find_index(task.content, fn line -> String.starts_with?(line, "**Status**") end)
440 572
441 573 status =
442 - if status_line do
443 - status_line
444 - |> String.replace("**Status**:", "")
445 - |> String.replace("**Status**", "")
446 - |> String.trim()
447 - else
448 - "MISSING"
574 + cond do
575 + is_nil(status_idx) ->
576 + "MISSING"
577 +
578 + # Check if status is on the same line (e.g., "**Status**: In Progress")
579 + String.contains?(Enum.at(task.content, status_idx), ":") ->
580 + Enum.at(task.content, status_idx)
581 + |> String.replace("**Status**:", "")
582 + |> String.replace("**Status**", "")
583 + |> String.trim()
584 +
585 + # Status is on the next line
586 + status_idx + 1 < length(task.content) ->
587 + Enum.at(task.content, status_idx + 1)
588 + |> String.trim()
589 +
590 + true ->
591 + "MISSING"
449 592 end
450 593
451 594 if status != "MISSING" && !Enum.member?(@valid_statuses, status) do
452 595 {:error, "Task #{task.id} has invalid status: #{status}"}
453 596 else
454 597 # Extract priority and validate
455 - priority_line =
456 - Enum.find(task.content, fn line -> String.starts_with?(line, "**Priority**") end)
598 + priority_idx =
599 + Enum.find_index(task.content, fn line ->
600 + String.starts_with?(line, "**Priority**")
601 + end)
457 602
458 603 priority =
459 - if priority_line do
460 - priority_line
461 - |> String.replace("**Priority**:", "")
462 - |> String.replace("**Priority**", "")
463 - |> String.trim()
464 - else
465 - "MISSING"
604 + cond do
605 + is_nil(priority_idx) ->
606 + "MISSING"
607 +
608 + # Check if priority is on the same line
609 + String.contains?(Enum.at(task.content, priority_idx), ":") ->
610 + Enum.at(task.content, priority_idx)
611 + |> String.replace("**Priority**:", "")
612 + |> String.replace("**Priority**", "")
613 + |> String.trim()
614 +
615 + # Priority is on the next line
616 + priority_idx + 1 < length(task.content) ->
617 + Enum.at(task.content, priority_idx + 1)
618 + |> String.trim()
619 +
620 + true ->
621 + "MISSING"
466 622 end
467 623
468 624 if priority != "MISSING" && !Enum.member?(@valid_priorities, priority) do
469 625 {:error, "Task #{task.id} has invalid priority: #{priority}"}
470 626 else
471 - # Validate subtasks if task is "In Progress"
472 - if status == "In Progress" && task.subtasks == [] do
473 - {:error, "Task #{task.id} is in progress but has no subtasks"}
474 - else
475 - validate_subtasks(task)
627 + # Extract and validate dependencies
628 + dependencies_line =
629 + Enum.find(task.content, fn line ->
630 + String.starts_with?(line, "**Dependencies**")
631 + end)
632 +
633 + dependencies =
634 + if dependencies_line do
635 + dependencies_line
636 + |> String.replace("**Dependencies**:", "")
637 + |> String.replace("**Dependencies**", "")
638 + |> String.trim()
639 + else
640 + "MISSING"
641 + end
642 +
643 + # Validate dependencies if not "None" or missing
644 + dependency_validation =
645 + if dependencies != "MISSING" && dependencies != "None" do
646 + # Parse dependencies (comma-separated task IDs)
647 + dep_ids =
648 + dependencies
649 + |> String.split(",")
650 + |> Enum.map(&String.trim/1)
651 + |> Enum.reject(&(&1 == ""))
652 +
653 + # Check if all dependencies exist
654 + invalid_deps =
655 + Enum.reject(dep_ids, fn dep_id ->
656 + MapSet.member?(all_task_ids, dep_id)
657 + end)
658 +
659 + if invalid_deps == [] do
660 + :ok
661 + else
662 + {:error,
663 + "Task #{task.id} has invalid dependencies: #{Enum.join(invalid_deps, ", ")}"}
664 + end
665 + else
666 + :ok
667 + end
668 +
669 + case dependency_validation do
670 + {:error, reason} ->
671 + {:error, reason}
672 +
673 + :ok ->
674 + # Validate Code Quality KPIs section
675 + kpi_validation = validate_code_quality_kpis(task)
676 +
677 + case kpi_validation do
678 + {:error, reason} ->
679 + {:error, reason}
680 +
681 + :ok ->
682 + # Validate task category
683 + category_validation = validate_task_category(task)
684 +
685 + case category_validation do
686 + {:error, reason} ->
687 + {:error, reason}
688 +
689 + :ok ->
690 + # Validate subtasks if task is "In Progress"
691 + if status == "In Progress" && task.subtasks == [] do
692 + {:error, "Task #{task.id} is in progress but has no subtasks"}
693 + else
694 + validate_subtasks(task)
695 + end
696 + end
697 + end
476 698 end
477 699 end
478 700 end
  @@ -483,6 +705,137 @@ defmodule TaskValidator do
483 705 end
484 706 end
485 707
708 + defp validate_task_category(task) do
709 + # Extract numeric part from task ID to determine category
710 + case Regex.run(~r/^[A-Z]{2,4}(\d{3,4})/, task.id) do
711 + [_, number_str] ->
712 + number = String.to_integer(number_str)
713 +
714 + # Find which category this number belongs to
715 + category =
716 + Enum.find(@category_ranges, fn {_category, {min, max}} ->
717 + number >= min && number <= max
718 + end)
719 +
720 + case category do
721 + {category_name, _range} ->
722 + # Validate that the task has appropriate sections for its category
723 + validate_category_specific_sections(task, category_name)
724 +
725 + nil ->
726 + {:error, "Task #{task.id} number #{number} doesn't fit any defined category range"}
727 + end
728 +
729 + nil ->
730 + {:error, "Task #{task.id} has invalid ID format for category validation"}
731 + end
732 + end
733 +
734 + defp validate_category_specific_sections(task, category_name) do
735 + # Define category-specific required sections
736 + category_sections =
737 + case category_name do
738 + "core" ->
739 + ["**Architecture Notes**", "**Complexity Assessment**"]
740 +
741 + "features" ->
742 + ["**Abstraction Evaluation**", "**Simplicity Progression Plan**"]
743 +
744 + "documentation" ->
745 + ["**Content Strategy**", "**Audience Analysis**"]
746 +
747 + "testing" ->
748 + ["**Test Strategy**", "**Coverage Requirements**"]
749 +
750 + _ ->
751 + []
752 + end
753 +
754 + # Check if all category-specific sections are present
755 + missing_sections =
756 + Enum.filter(category_sections, fn section ->
757 + !Enum.any?(task.content, fn line ->
758 + String.starts_with?(line, section)
759 + end)
760 + end)
761 +
762 + if missing_sections == [] do
763 + :ok
764 + else
765 + {:error,
766 + "Task #{task.id} (#{category_name} category) missing required sections: #{Enum.join(missing_sections, ", ")}"}
767 + end
768 + end
769 +
770 + defp validate_code_quality_kpis(task) do
771 + # Find the Code Quality KPIs section
772 + kpi_section_start =
773 + Enum.find_index(task.content, fn line ->
774 + String.starts_with?(line, "**Code Quality KPIs**")
775 + end)
776 +
777 + if kpi_section_start == nil do
778 + {:error, "Task #{task.id} is missing Code Quality KPIs section"}
779 + else
780 + # Extract the KPI section content
781 + kpi_content =
782 + task.content
783 + |> Enum.drop(kpi_section_start + 1)
784 + |> Enum.take_while(fn line ->
785 + !String.match?(line, ~r/^\*\*[^*]+\*\*/) && String.trim(line) != ""
786 + end)
787 + |> Enum.reject(&(String.trim(&1) == ""))
788 +
789 + # Parse KPI values
790 + kpis = %{
791 + functions_per_module: extract_kpi_value(kpi_content, ~r/functions per module:\s*(\d+)/i),
792 + lines_per_function: extract_kpi_value(kpi_content, ~r/lines per function:\s*(\d+)/i),
793 + call_depth: extract_kpi_value(kpi_content, ~r/call depth:\s*(\d+)/i)
794 + }
795 +
796 + # Check all KPIs are present
797 + missing_kpis =
798 + [:functions_per_module, :lines_per_function, :call_depth]
799 + |> Enum.filter(fn key -> is_nil(kpis[key]) end)
800 + |> Enum.map(fn
801 + :functions_per_module -> "Functions per module"
802 + :lines_per_function -> "Lines per function"
803 + :call_depth -> "Call depth"
804 + end)
805 +
806 + if missing_kpis != [] do
807 + {:error, "Task #{task.id} missing KPIs: #{Enum.join(missing_kpis, ", ")}"}
808 + else
809 + # Validate KPI values are within limits
810 + cond do
811 + kpis.functions_per_module > @max_functions_per_module ->
812 + {:error,
813 + "Task #{task.id} exceeds max functions per module: #{kpis.functions_per_module} > #{@max_functions_per_module}"}
814 +
815 + kpis.lines_per_function > @max_lines_per_function ->
816 + {:error,
817 + "Task #{task.id} exceeds max lines per function: #{kpis.lines_per_function} > #{@max_lines_per_function}"}
818 +
819 + kpis.call_depth > @max_call_depth ->
820 + {:error,
821 + "Task #{task.id} exceeds max call depth: #{kpis.call_depth} > #{@max_call_depth}"}
822 +
823 + true ->
824 + :ok
825 + end
826 + end
827 + end
828 + end
829 +
830 + defp extract_kpi_value(content, regex) do
831 + Enum.find_value(content, fn line ->
832 + case Regex.run(regex, line) do
833 + [_, value] -> String.to_integer(value)
834 + _ -> nil
835 + end
836 + end)
837 + end
838 +
486 839 defp validate_subtasks(task) do
487 840 # Get the task prefix for checking subtask consistency
488 841 task_prefix =
  @@ -497,10 +850,17 @@ defmodule TaskValidator do
497 850 # Check subtask ID prefix consistency with parent task
498 851 if task_prefix != nil do
499 852 subtask_prefix =
500 - if String.match?(subtask.id, ~r/^[A-Z]{2,4}\d{3,4}-\d+$/) do
501 - Regex.run(~r/^([A-Z]{2,4})/, subtask.id) |> Enum.at(1)
502 - else
503 - nil
853 + cond do
854 + # Traditional numbered format (SSH0001-1)
855 + String.match?(subtask.id, ~r/^[A-Z]{2,4}\d{3,4}-\d+$/) ->
856 + Regex.run(~r/^([A-Z]{2,4})/, subtask.id) |> Enum.at(1)
857 +
858 + # Checkbox format (WNX0019a)
859 + String.match?(subtask.id, ~r/^[A-Z]{2,4}\d{3,4}[a-z]$/) ->
860 + Regex.run(~r/^([A-Z]{2,4})/, subtask.id) |> Enum.at(1)
861 +
862 + true ->
863 + nil
504 864 end
505 865
506 866 if subtask_prefix != nil && subtask_prefix != task_prefix do
  @@ -515,47 +875,88 @@ defmodule TaskValidator do
515 875
516 876 # For completed subtasks, check rating
517 877 subtask_content =
518 - task.content
519 - |> Enum.slice(subtask.line..length(task.content))
520 - |> Enum.take_while(fn line ->
521 - !String.match?(line, ~r/^####/) || line == Enum.at(task.content, subtask.line)
522 - end)
878 + if Map.get(subtask, :format) == :checkbox do
879 + # For checkbox format, content is usually on the same line or immediately following
880 + # Take the checkbox line and any following lines until next checkbox or section
881 + task.content
882 + |> Enum.slice(subtask.line..length(task.content))
883 + |> Enum.take_while(fn line ->
884 + (!String.match?(line, ~r/^####/) && !String.match?(line, ~r/^- \[[x\s]\]/)) ||
885 + line == Enum.at(task.content, subtask.line)
886 + end)
887 + else
888 + # Traditional numbered format
889 + task.content
890 + |> Enum.slice(subtask.line..length(task.content))
891 + |> Enum.take_while(fn line ->
892 + !String.match?(line, ~r/^####/) || line == Enum.at(task.content, subtask.line)
893 + end)
894 + end
523 895
524 896 # Extract status first
525 - status_line =
526 - Enum.find(subtask_content, fn line -> String.starts_with?(line, "**Status**") end)
527 -
528 897 status =
529 - if status_line do
530 - status_line
531 - |> String.replace("**Status**:", "")
532 - |> String.replace("**Status**", "")
533 - |> String.trim()
898 + if Map.get(subtask, :format) == :checkbox do
899 + # For checkbox format, checked means completed
900 + if Map.get(subtask, :checked, false) do
901 + "Completed"
902 + else
903 + "Planned"
904 + end
534 905 else
535 - "MISSING"
906 + # Traditional format uses Status field
907 + status_idx =
908 + Enum.find_index(subtask_content, fn line ->
909 + String.starts_with?(line, "**Status**")
910 + end)
911 +
912 + cond do
913 + is_nil(status_idx) ->
914 + "MISSING"
915 +
916 + # Check if status is on the same line
917 + String.contains?(Enum.at(subtask_content, status_idx), ":") ->
918 + Enum.at(subtask_content, status_idx)
919 + |> String.replace("**Status**:", "")
920 + |> String.replace("**Status**", "")
921 + |> String.trim()
922 +
923 + # Status is on the next line
924 + status_idx + 1 < length(subtask_content) ->
925 + Enum.at(subtask_content, status_idx + 1)
926 + |> String.trim()
927 +
928 + true ->
929 + "MISSING"
930 + end
536 931 end
537 932
538 933 # Check if status is valid
539 934 if status != "MISSING" && !Enum.member?(@valid_statuses, status) do
540 935 {:halt, {:error, "Subtask #{subtask.id} has invalid status: #{status}"}}
541 936 else
542 - # Check if subtask has required sections, including error handling
543 - # Use simplified error handling format for subtasks
544 - required_subtask_sections =
545 - [
546 - "**Status**"
547 - ] ++ @subtask_error_handling_sections
548 -
937 + # Check if subtask has required sections
549 938 missing_sections =
550 - Enum.filter(required_subtask_sections, fn section ->
551 - !Enum.any?(subtask_content, fn line ->
552 - String.starts_with?(line, section)
939 + if Map.get(subtask, :format) == :checkbox do
940 + # Checkbox format subtasks don't require separate sections
941 + # They're typically one-line items
942 + []
943 + else
944 + # Traditional format requires status and error handling sections
945 + required_subtask_sections =
946 + [
947 + "**Status**"
948 + ] ++ @subtask_error_handling_sections
949 +
950 + Enum.filter(required_subtask_sections, fn section ->
951 + !Enum.any?(subtask_content, fn line ->
952 + String.starts_with?(line, section)
953 + end)
553 954 end)
554 - end)
955 + end
555 956
556 957 if missing_sections == [] do
557 - # If completed, check review rating (after confirming no missing sections)
558 - if status == "Completed" do
958 + # If completed, check review rating (only for traditional format)
959 + if status == "Completed" && Map.get(subtask, :format) != :checkbox do
559 960 rating_line =
560 961 Enum.find(subtask_content, fn line ->
561 962 String.starts_with?(line, "**Review Rating**")
  @@ -4,7 +4,7 @@ defmodule TaskValidator.MixProject do
4 4 def project do
5 5 [
6 6 app: :task_validator,
7 - version: "0.5.0",
7 + version: "0.6.0",
8 8 elixir: "~> 1.18",
9 9 start_permanent: Mix.env() == :prod,
10 10 description: description(),
  @@ -33,8 +33,8 @@ defmodule TaskValidator.MixProject do
33 33 defp description do
34 34 """
35 35 A library for validating Markdown task lists with structured format specifications.
36 - Enforces error handling documentation, supports multi-project prefixes (SSH0001, ERR001),
37 - and ensures consistent task tracking with ID formats and required sections.
36 + Features: checkbox subtasks, dependencies, code quality KPIs, task categories,
37 + multi-project prefixes, and comprehensive error handling documentation.
38 38 """
39 39 end