sdd-agent-pack 1.3.4 → 1.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -61,7 +61,16 @@ TASKS_FILE = "specs/tasks.md"
|
|
|
61
61
|
|
|
62
62
|
|
|
63
63
|
def parse_epics(file_path: str) -> list[dict]:
|
|
64
|
-
"""Parse incomplete epics from tasks.md
|
|
64
|
+
"""Parse incomplete epics from tasks.md.
|
|
65
|
+
|
|
66
|
+
Detects epic headings like:
|
|
67
|
+
## Epic EPIC-001 — Title
|
|
68
|
+
## Epic TDS.1: Title
|
|
69
|
+
### Epic Something
|
|
70
|
+
|
|
71
|
+
An epic is "incomplete" if any checkbox (- [ ]) is unchecked under it.
|
|
72
|
+
An epic is "complete" if all its checkboxes are checked or there are none.
|
|
73
|
+
"""
|
|
65
74
|
if not os.path.exists(file_path):
|
|
66
75
|
print(f"✗ tasks.md not found at {file_path}")
|
|
67
76
|
print(" Run this from your repository root.")
|
|
@@ -71,43 +80,35 @@ def parse_epics(file_path: str) -> list[dict]:
|
|
|
71
80
|
content = f.read()
|
|
72
81
|
|
|
73
82
|
epics = []
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
r"status:\s*(pending|in-progress)", line
|
|
104
|
-
):
|
|
105
|
-
epics.append(
|
|
106
|
-
{"id": current_epic, "title": current_epic, "status": "pending"}
|
|
107
|
-
)
|
|
108
|
-
current_epic = None
|
|
109
|
-
elif current_epic and re.search(r"status:\s*complete", line):
|
|
110
|
-
current_epic = None
|
|
83
|
+
lines = content.split("\n")
|
|
84
|
+
|
|
85
|
+
epic_heading_re = re.compile(r"^#{2,4}\s+Epic\s+(.+)$", re.IGNORECASE)
|
|
86
|
+
|
|
87
|
+
current_epic = None
|
|
88
|
+
has_unchecked = False
|
|
89
|
+
|
|
90
|
+
for line in lines:
|
|
91
|
+
heading_match = epic_heading_re.match(line)
|
|
92
|
+
if heading_match:
|
|
93
|
+
# Save previous epic if it has unchecked tasks
|
|
94
|
+
if current_epic and has_unchecked:
|
|
95
|
+
epics.append({
|
|
96
|
+
"id": current_epic,
|
|
97
|
+
"title": current_epic,
|
|
98
|
+
"status": "incomplete",
|
|
99
|
+
})
|
|
100
|
+
current_epic = heading_match.group(1).strip()
|
|
101
|
+
has_unchecked = False
|
|
102
|
+
elif current_epic and re.match(r"^\s*-\s+\[\s*\]", line):
|
|
103
|
+
has_unchecked = True
|
|
104
|
+
|
|
105
|
+
# Don't forget the last epic
|
|
106
|
+
if current_epic and has_unchecked:
|
|
107
|
+
epics.append({
|
|
108
|
+
"id": current_epic,
|
|
109
|
+
"title": current_epic,
|
|
110
|
+
"status": "incomplete",
|
|
111
|
+
})
|
|
111
112
|
|
|
112
113
|
return epics
|
|
113
114
|
|
|
@@ -68,24 +68,36 @@ echo "━━━ SDD Agent Pack — Epic Orchestrator ━━━"
|
|
|
68
68
|
echo ""
|
|
69
69
|
|
|
70
70
|
# Parse incomplete epics from tasks.md
|
|
71
|
-
# Looks for
|
|
71
|
+
# Looks for epic headings (## Epic XXX — Title) and checks if any
|
|
72
|
+
# of their tasks or requirements have unchecked boxes (- [ ]).
|
|
73
|
+
# An epic is "incomplete" if any checkbox under it is unchecked.
|
|
72
74
|
echo "Scanning $TASKS_FILE for incomplete epics..."
|
|
73
75
|
|
|
74
76
|
epics=()
|
|
75
77
|
current_epic=""
|
|
78
|
+
has_unchecked=false
|
|
76
79
|
|
|
77
80
|
while IFS= read -r line; do
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
current_epic=""
|
|
81
|
+
# Detect epic heading: ## Epic XXX — Title or ## Epic XXX: Title
|
|
82
|
+
if [[ "$line" =~ ^[#]+\ +Epic\ +(.+)$ ]]; then
|
|
83
|
+
# Save previous epic if it has unchecked tasks
|
|
84
|
+
if [ -n "$current_epic" ] && [ "$has_unchecked" = true ]; then
|
|
85
|
+
epics+=("$current_epic")
|
|
86
|
+
fi
|
|
87
|
+
current_epic="${BASH_REMATCH[1]}"
|
|
88
|
+
current_epic="$(echo "$current_epic" | sed 's/^[#[:space:]]*//' | xargs)"
|
|
89
|
+
has_unchecked=false
|
|
90
|
+
# Detect unchecked checkbox
|
|
91
|
+
elif [[ "$line" =~ ^[[:space:]]*-\ +\[\ \] ]] && [ -n "$current_epic" ]; then
|
|
92
|
+
has_unchecked=true
|
|
86
93
|
fi
|
|
87
94
|
done < "$TASKS_FILE"
|
|
88
95
|
|
|
96
|
+
# Don't forget the last epic
|
|
97
|
+
if [ -n "$current_epic" ] && [ "$has_unchecked" = true ]; then
|
|
98
|
+
epics+=("$current_epic")
|
|
99
|
+
fi
|
|
100
|
+
|
|
89
101
|
if [ ${#epics[@]} -eq 0 ]; then
|
|
90
102
|
echo "✓ All epics are complete! Nothing to do."
|
|
91
103
|
exit 0
|