Skip to content

Commit 2c8c17d

Browse files
feat: remove v2 from sprint-list-epics.sh (d775-4a36)
Remove TICKETS_DIR, INDEX_FILE, TK=, and _rebuild_index v2 patterns. Update tests to verify removal (24 passing).
1 parent 59996a2 commit 2c8c17d

File tree

2 files changed

+113
-388
lines changed

2 files changed

+113
-388
lines changed

plugins/dso/scripts/sprint-list-epics.sh

Lines changed: 11 additions & 199 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,7 @@
22
set -euo pipefail
33
# sprint-list-epics.sh — List unblocked epics for /dso:sprint Phase 1.
44
#
5-
# Reads .tickets/.index.json in a single Python pass instead of per-file scanning.
6-
# Blocked/ready classification uses the deps field from the extended index schema.
5+
# Reads ticket state from the v3 event-sourced tracker via ticket-reducer.py.
76
#
87
# Usage:
98
# sprint-list-epics.sh # List unblocked open epics, sorted by priority
@@ -27,46 +26,20 @@ show_all=false
2726
[[ "${1:-}" == "--all" ]] && show_all=true
2827

2928
REPO_ROOT=$(git rev-parse --show-toplevel)
30-
# Capture whether TICKETS_DIR was explicitly set by caller before applying defaults
31-
_TICKETS_DIR_EXPLICIT="${TICKETS_DIR+yes}"
32-
TICKETS_DIR="${TICKETS_DIR:-$REPO_ROOT/.tickets}"
33-
INDEX_FILE="$TICKETS_DIR/.index.json"
34-
TK="${TK:-$SCRIPT_DIR/tk}"
3529
REDUCER="$SCRIPT_DIR/ticket-reducer.py"
3630

3731
# ---------------------------------------------------------------------------
38-
# Detect v3 event-sourced ticket system.
39-
# v3 stores events in .tickets-tracker/ (or TICKETS_TRACKER_DIR env override).
40-
# When v3 is detected, build the index from the reducer instead of .md files.
32+
# v3 event-sourced ticket system.
33+
# Reads from .tickets-tracker/ (or TICKETS_TRACKER_DIR env override).
4134
# ---------------------------------------------------------------------------
42-
# Detection logic:
43-
# - TICKETS_TRACKER_DIR explicitly set → v3 (test override for v3)
44-
# - TICKETS_DIR explicitly set without TICKETS_TRACKER_DIR → v2 (test override for v2)
45-
# - Neither explicitly set → auto-detect: use v3 if .tickets-tracker/ exists
46-
USE_V3=false
47-
if [ -n "${TICKETS_TRACKER_DIR:-}" ]; then
48-
TRACKER_DIR="$TICKETS_TRACKER_DIR"
49-
USE_V3=true
50-
elif [ "$_TICKETS_DIR_EXPLICIT" != "yes" ]; then
51-
# TICKETS_DIR not explicitly set — auto-detect
52-
TRACKER_DIR="$REPO_ROOT/.tickets-tracker"
53-
if [ -d "$TRACKER_DIR" ]; then
54-
USE_V3=true
55-
fi
56-
else
57-
# TICKETS_DIR explicitly set, TICKETS_TRACKER_DIR not — use v2
58-
TRACKER_DIR="$REPO_ROOT/.tickets-tracker"
59-
fi
35+
TRACKER_DIR="${TICKETS_TRACKER_DIR:-$REPO_ROOT/.tickets-tracker}"
6036

6137
# ---------------------------------------------------------------------------
62-
# Build index from data source (v3 reducer or v2 .md files).
63-
# Both paths produce the same index format in SPRINT_INDEX_JSON env var.
38+
# Build index from v3 reducer.
6439
# ---------------------------------------------------------------------------
65-
if [ "$USE_V3" = true ]; then
66-
# v3 path: compile ticket state from event-sourced tracker via reducer
67-
export _SPRINT_TRACKER_DIR="$TRACKER_DIR"
68-
export _SPRINT_REDUCER="$REDUCER"
69-
index_and_counts=$(python3 -c "
40+
export _SPRINT_TRACKER_DIR="$TRACKER_DIR"
41+
export _SPRINT_REDUCER="$REDUCER"
42+
index_and_counts=$(python3 -c "
7043
import json, os, sys, importlib.util, collections
7144
7245
tracker_dir = os.environ['_SPRINT_TRACKER_DIR']
@@ -119,169 +92,8 @@ for entry_name in os.listdir(tracker_dir):
11992
print(json.dumps({'index': idx, 'child_counts': dict(child_counts)}))
12093
" 2>/dev/null || echo '{"index":{},"child_counts":{}}')
12194

122-
SPRINT_INDEX_JSON=$(echo "$index_and_counts" | python3 -c "import json,sys; print(json.dumps(json.load(sys.stdin)['index']))")
123-
child_counts_json=$(echo "$index_and_counts" | python3 -c "import json,sys; print(json.dumps(json.load(sys.stdin)['child_counts']))")
124-
else
125-
# v2 path: read .tickets/*.md files and build index
126-
127-
# Staleness guard: compare .md file count vs index entry count.
128-
_rebuild_index() {
129-
if [ -x "$TK" ] || command -v "$TK" >/dev/null 2>&1; then
130-
TICKETS_DIR="$TICKETS_DIR" "$TK" index-rebuild >/dev/null 2>&1 || true
131-
else
132-
python3 -c "
133-
import json, os, re, sys
134-
135-
tickets_dir = os.environ.get('TICKETS_DIR', '.tickets')
136-
idx = {}
137-
138-
try:
139-
files = [f for f in os.listdir(tickets_dir) if f.endswith('.md')]
140-
except OSError:
141-
files = []
142-
143-
for fname in files:
144-
fpath = os.path.join(tickets_dir, fname)
145-
try:
146-
content = open(fpath).read()
147-
except OSError:
148-
continue
149-
150-
lines = content.splitlines()
151-
in_front = False
152-
front_lines = []
153-
count = 0
154-
for line in lines:
155-
if line.strip() == '---':
156-
count += 1
157-
if count == 1:
158-
in_front = True
159-
continue
160-
elif count == 2:
161-
in_front = False
162-
break
163-
if in_front:
164-
front_lines.append(line)
165-
166-
def get_field(name):
167-
for l in front_lines:
168-
m = re.match(r'^' + re.escape(name) + r':\s*(.*)', l)
169-
if m:
170-
return m.group(1).strip()
171-
return ''
172-
173-
ticket_id = get_field('id')
174-
if not ticket_id:
175-
ticket_id = fname[:-3]
176-
177-
status = get_field('status') or 'open'
178-
type_ = get_field('type') or 'task'
179-
180-
raw_priority = get_field('priority')
181-
try:
182-
priority = int(raw_priority) if raw_priority != '' else None
183-
except (ValueError, TypeError):
184-
priority = None
185-
186-
raw_deps = get_field('deps')
187-
if raw_deps in ('', '[]'):
188-
deps = []
189-
else:
190-
inner = raw_deps.strip().lstrip('[').rstrip(']')
191-
deps = [s.strip().strip('\"').strip(chr(39)) for s in inner.split(',') if s.strip()]
192-
193-
title = ''
194-
for line in lines:
195-
if line.startswith('# '):
196-
title = line[2:].strip()
197-
break
198-
199-
parent = get_field('parent')
200-
201-
entry = {'title': title, 'status': status, 'type': type_}
202-
if priority is not None:
203-
entry['priority'] = priority
204-
if deps:
205-
entry['deps'] = deps
206-
if parent:
207-
entry['parent'] = parent
208-
idx[ticket_id] = entry
209-
210-
# Write atomically
211-
import tempfile
212-
tmp = os.path.join(tickets_dir, '.index.json.tmp')
213-
with open(tmp, 'w') as f:
214-
json.dump(idx, f, indent=2, sort_keys=True)
215-
os.replace(tmp, os.path.join(tickets_dir, '.index.json'))
216-
" 2>/dev/null || true
217-
fi
218-
}
219-
220-
_check_staleness() {
221-
local index_count md_count
222-
md_count=$(python3 -c "
223-
import os
224-
d = '$TICKETS_DIR'
225-
try:
226-
print(sum(1 for f in os.listdir(d) if f.endswith('.md')))
227-
except OSError:
228-
print(0)
229-
" 2>/dev/null || echo 0)
230-
index_count=$(python3 -c "
231-
import json
232-
try:
233-
with open('$INDEX_FILE') as f:
234-
data = json.load(f)
235-
print(len(data))
236-
except Exception:
237-
print(-1)
238-
" 2>/dev/null || echo -1)
239-
if [ "$index_count" -ne "$md_count" ]; then
240-
_rebuild_index
241-
fi
242-
}
243-
244-
_check_staleness
245-
246-
# Read index file for v2 path
247-
SPRINT_INDEX_JSON=$(cat "$INDEX_FILE" 2>/dev/null || echo '{}')
248-
249-
# Compute child counts from .md files
250-
child_counts_json=$(python3 -c "
251-
import os, re, collections, json
252-
253-
tickets_dir = '$TICKETS_DIR'
254-
counts = collections.defaultdict(int)
255-
256-
try:
257-
files = [f for f in os.listdir(tickets_dir) if f.endswith('.md')]
258-
except OSError:
259-
files = []
260-
261-
for fname in files:
262-
fpath = os.path.join(tickets_dir, fname)
263-
try:
264-
content = open(fpath).read()
265-
except OSError:
266-
continue
267-
in_front = False
268-
front_count = 0
269-
for line in content.splitlines():
270-
if line.strip() == '---':
271-
front_count += 1
272-
in_front = (front_count == 1)
273-
if front_count == 2:
274-
break
275-
continue
276-
if in_front:
277-
m = re.match(r'^parent:\s*(\S+)', line)
278-
if m:
279-
parent_id = m.group(1).rstrip('#').strip()
280-
counts[parent_id] += 1
281-
282-
print(json.dumps(dict(counts)))
283-
" 2>/dev/null || echo '{}')
284-
fi
95+
SPRINT_INDEX_JSON=$(echo "$index_and_counts" | python3 -c "import json,sys; print(json.dumps(json.load(sys.stdin)['index']))")
96+
child_counts_json=$(echo "$index_and_counts" | python3 -c "import json,sys; print(json.dumps(json.load(sys.stdin)['child_counts']))")
28597

28698
# ---------------------------------------------------------------------------
28799
# Single Python pass: read index once, classify epics, emit output.
@@ -291,7 +103,7 @@ import json, os, sys
291103
292104
show_all = os.environ.get('SPRINT_SHOW_ALL') == 'true'
293105
294-
# Load index from env var (built by v2 or v3 path above)
106+
# Load index from env var (built by v3 path above)
295107
try:
296108
index = json.loads(os.environ.get('SPRINT_INDEX_JSON', '{}'))
297109
except Exception:

0 commit comments

Comments
 (0)