Skip to content

Commit feff213

Browse files
authored
Merge pull request #2083 from trillium/trilliumsmith/ts.751
Update mongodb-memory-server to 8.2.3
2 parents ab9caf6 + bdca337 commit feff213

17 files changed

+3314
-2297
lines changed
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
#!/bin/bash
2+
3+
##############################################################################
4+
# VRMS Stale Issue Verification Skill
5+
#
6+
# Purpose: Automatically verify open stale issues (>1 year old) and determine
7+
# if they should be closed, kept open, or flagged for PM triage
8+
#
9+
# Usage: ./verify-stale-issue.sh <issue_number>
10+
# ./verify-stale-issue.sh 1163
11+
#
12+
# Output: JSON object with verdict, reasoning, and action steps
13+
##############################################################################
14+
15+
set -e
16+
17+
ISSUE_NUM="${1:-}"
18+
19+
if [ -z "$ISSUE_NUM" ]; then
20+
echo "Usage: $0 <issue_number>"
21+
echo "Example: $0 1163"
22+
exit 1
23+
fi
24+
25+
# Helper function to calculate days since date
26+
days_since() {
27+
local date_str="$1"
28+
local date_epoch=$(date -j -f "%Y-%m-%d" "$date_str" "+%s" 2>/dev/null || date -d "$date_str" "+%s" 2>/dev/null || echo 0)
29+
local now_epoch=$(date "+%s")
30+
if [ "$date_epoch" -eq 0 ]; then
31+
echo "unknown"
32+
else
33+
echo $(( (now_epoch - date_epoch) / 86400 ))
34+
fi
35+
}
36+
37+
# Fetch issue data
38+
ISSUE_DATA=$(gh issue view "$ISSUE_NUM" --json number,title,state,labels,createdAt,updatedAt,assignees,body,milestone 2>/dev/null)
39+
40+
if [ -z "$ISSUE_DATA" ]; then
41+
echo "{\"error\": \"Issue #$ISSUE_NUM not found\"}"
42+
exit 1
43+
fi
44+
45+
# Extract fields
46+
TITLE=$(echo "$ISSUE_DATA" | jq -r '.title')
47+
STATE=$(echo "$ISSUE_DATA" | jq -r '.state')
48+
CREATED=$(echo "$ISSUE_DATA" | jq -r '.createdAt' | cut -d'T' -f1)
49+
UPDATED=$(echo "$ISSUE_DATA" | jq -r '.updatedAt' | cut -d'T' -f1)
50+
ASSIGNEES=$(echo "$ISSUE_DATA" | jq -r '.assignees[].login' | tr '\n' ',' | sed 's/,$//')
51+
LABELS=$(echo "$ISSUE_DATA" | jq -r '.labels[].name' | tr '\n' '|')
52+
BODY=$(echo "$ISSUE_DATA" | jq -r '.body // ""')
53+
54+
# Categorize by labels/metadata
55+
HAS_DRAFT=$(echo "$LABELS" | grep -q "draft" && echo "true" || echo "false")
56+
HAS_EPIC=$(echo "$LABELS" | grep -q "Epic\|epic" && echo "true" || echo "false")
57+
HAS_PM_READY=$(echo "$LABELS" | grep -q "ready for product manager" && echo "true" || echo "false")
58+
HAS_STAKEHOLDER=$(echo "$TITLE" | grep -q "Stakeholder\|stakeholder" && echo "true" || echo "false")
59+
HAS_MEETING=$(echo "$LABELS" | grep -q "Agenda\|agenda\|meeting" && echo "true" || echo "false")
60+
HAS_SECURITY=$(echo "$LABELS" | grep -q "security\|Security" && echo "true" || echo "false")
61+
HAS_BLOCKED=$(echo "$LABELS" | grep -q "blocked\|Blocked" && echo "true" || echo "false")
62+
63+
DAYS_CREATED=$(days_since "$CREATED")
64+
DAYS_UPDATED=$(days_since "$UPDATED")
65+
66+
# Decision tree logic
67+
VERDICT=""
68+
CATEGORY=""
69+
REASONING=""
70+
ACTION=""
71+
BLOCKER=""
72+
CONFIDENCE=""
73+
74+
# 1. Check if recurring meeting
75+
if [ "$HAS_MEETING" = "true" ]; then
76+
VERDICT="KEEP_OPEN"
77+
CATEGORY="recurring_process"
78+
REASONING="This is a recurring meeting agenda or status item"
79+
ACTION="Keep open - this is a legitimate ongoing process"
80+
CONFIDENCE="high"
81+
82+
# 2. Check draft status
83+
elif [ "$HAS_DRAFT" = "true" ] && [ "$HAS_PM_READY" = "false" ]; then
84+
VERDICT="FLAG_PM"
85+
CATEGORY="draft_status"
86+
BLOCKER="DRAFT - not ready for work"
87+
REASONING="Issue is in draft status and not ready for prioritization"
88+
ACTION="FLAG FOR PM: Review and decide if draft should be completed or closed"
89+
CONFIDENCE="high"
90+
91+
# 3. Check if PM decision needed
92+
elif [ "$HAS_PM_READY" = "true" ]; then
93+
VERDICT="FLAG_PM"
94+
CATEGORY="stakeholder_decision"
95+
BLOCKER="STAKEHOLDER - needs PM approval"
96+
REASONING="Issue requires PM/product manager review for prioritization or approval"
97+
ACTION="FLAG FOR PM: Prioritize this issue or decide if it should be closed"
98+
CONFIDENCE="high"
99+
100+
# 4. Check if stakeholder feedback
101+
elif [ "$HAS_STAKEHOLDER" = "true" ]; then
102+
VERDICT="FLAG_PM"
103+
CATEGORY="stakeholder_decision"
104+
BLOCKER="STAKEHOLDER - awaiting feedback incorporation"
105+
REASONING="Issue involves stakeholder input/feedback that needs PM triage"
106+
ACTION="FLAG FOR PM: Incorporate stakeholder feedback or decide on closure"
107+
CONFIDENCE="high"
108+
109+
# 5. Check if Epic
110+
elif [ "$HAS_EPIC" = "true" ]; then
111+
VERDICT="FLAG_PM"
112+
CATEGORY="epic_scope"
113+
BLOCKER="EPIC - needs scope clarification"
114+
REASONING="Epic issue requires scope review and active management"
115+
ACTION="FLAG FOR PM: Clarify epic scope, status, and current priority"
116+
CONFIDENCE="high"
117+
118+
# 6. Check for security issues
119+
elif [ "$HAS_SECURITY" = "true" ]; then
120+
VERDICT="VERIFY_CODE"
121+
CATEGORY="security"
122+
REASONING="Security issue needs verification of current status/fix"
123+
ACTION="VERIFY: Check if security concern has been addressed in code"
124+
CONFIDENCE="medium"
125+
126+
# 7. Check if blocked
127+
elif [ "$HAS_BLOCKED" = "true" ]; then
128+
VERDICT="FLAG_PM"
129+
CATEGORY="blocked"
130+
BLOCKER="BLOCKED - awaiting dependencies"
131+
REASONING="Issue is blocked on other work"
132+
ACTION="FLAG FOR PM: Review blocking issues and unblock if ready"
133+
CONFIDENCE="high"
134+
135+
# 8. Check if unassigned and very old
136+
elif [ -z "$ASSIGNEES" ] && [ "$DAYS_CREATED" -gt 900 ] && [ "$DAYS_UPDATED" -gt 180 ]; then
137+
VERDICT="CLOSE"
138+
CATEGORY="abandoned"
139+
REASONING="Unassigned, created ${DAYS_CREATED}+ days ago, no updates in ${DAYS_UPDATED}+ days"
140+
ACTION="CLOSE: Issue appears abandoned with no recent activity"
141+
CONFIDENCE="high"
142+
143+
# 9. Default: needs classification
144+
else
145+
VERDICT="VERIFY_CODE"
146+
CATEGORY="needs_classification"
147+
REASONING="Insufficient data in labels/metadata - requires code verification or PM input"
148+
ACTION="INVESTIGATE: Check code state and/or flag for PM if still relevant"
149+
CONFIDENCE="medium"
150+
fi
151+
152+
# Generate JSON output
153+
cat <<EOJSON
154+
{
155+
"issue": $ISSUE_NUM,
156+
"title": $(echo "$TITLE" | jq -R .),
157+
"state": "$STATE",
158+
"verdict": "$VERDICT",
159+
"category": "$CATEGORY",
160+
"confidence": "$CONFIDENCE",
161+
"reasoning": $(echo "$REASONING" | jq -R .),
162+
"action": $(echo "$ACTION" | jq -R .),
163+
"blocker": $([ -n "$BLOCKER" ] && echo "$BLOCKER" | jq -R . || echo "null"),
164+
"dates": {
165+
"created": "$CREATED",
166+
"updated": "$UPDATED",
167+
"days_since_created": $DAYS_CREATED,
168+
"days_since_updated": $DAYS_UPDATED
169+
},
170+
"metadata": {
171+
"assigned_to": $([ -n "$ASSIGNEES" ] && echo "\"$ASSIGNEES\"" || echo "null"),
172+
"has_draft": $HAS_DRAFT,
173+
"has_epic": $HAS_EPIC,
174+
"has_pm_ready": $HAS_PM_READY,
175+
"has_stakeholder": $HAS_STAKEHOLDER,
176+
"has_meeting": $HAS_MEETING,
177+
"has_security": $HAS_SECURITY,
178+
"has_blocked": $HAS_BLOCKED
179+
}
180+
}
181+
EOJSON
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
#!/bin/bash
2+
3+
##############################################################################
4+
# VRMS Stale Issues Batch Verification
5+
#
6+
# Purpose: Run verification on multiple stale issues and generate report
7+
#
8+
# Usage: ./verify-stale-issues-batch.sh [output_file]
9+
# ./verify-stale-issues-batch.sh report.json
10+
#
11+
# Output: JSON report with categorized verdicts and summary statistics
12+
##############################################################################
13+
14+
OUTPUT_FILE="${1:-stale_issues_report.json}"
15+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16+
17+
# Load or create issues.json if it doesn't exist
18+
if [ ! -f "issues.json" ]; then
19+
echo "Generating issues.json..." >&2
20+
gh issue list --state all --limit 500 --json number,title,state,createdAt,updatedAt,labels | \
21+
jq '[.[] | select(.createdAt < "2024-03-17") | select(.state == "OPEN")]' > issues.json
22+
fi
23+
24+
TOTAL_ISSUES=$(jq 'length' issues.json)
25+
echo "Processing $TOTAL_ISSUES stale open issues..." >&2
26+
27+
# Initialize report structure
28+
REPORT_JSON='{
29+
"metadata": {
30+
"generated_at": "'$(date -u +"%Y-%m-%dT%H:%M:%SZ")'",
31+
"total_issues": '$TOTAL_ISSUES'
32+
},
33+
"verdicts": {
34+
"CLOSE": [],
35+
"KEEP_OPEN": [],
36+
"FLAG_PM": [],
37+
"VERIFY_CODE": []
38+
},
39+
"by_category": {},
40+
"summary": {}
41+
}'
42+
43+
# Track counts
44+
declare -A verdict_counts category_counts
45+
verdict_counts[CLOSE]=0
46+
verdict_counts[KEEP_OPEN]=0
47+
verdict_counts[FLAG_PM]=0
48+
verdict_counts[VERIFY_CODE]=0
49+
50+
count=0
51+
# Process each issue
52+
jq -r '.[] | .number' issues.json | while read issue_num; do
53+
count=$((count + 1))
54+
55+
# Run verification
56+
result=$(bash "$SCRIPT_DIR/verify-stale-issue.sh" "$issue_num" 2>/dev/null)
57+
58+
verdict=$(echo "$result" | jq -r '.verdict')
59+
category=$(echo "$result" | jq -r '.category')
60+
61+
# Add to report by verdict
62+
REPORT_JSON=$(echo "$REPORT_JSON" | jq --argjson result "$result" \
63+
".verdicts[$verdict] += [\$result]")
64+
65+
# Track by category
66+
REPORT_JSON=$(echo "$REPORT_JSON" | jq --arg cat "$category" --argjson result "$result" \
67+
".by_category[\$cat] //= [] | .by_category[\$cat] += [\$result]")
68+
69+
if [ $((count % 10)) -eq 0 ]; then
70+
echo " Processed $count/$TOTAL_ISSUES..." >&2
71+
fi
72+
done
73+
74+
# Generate summary counts
75+
REPORT_JSON=$(echo "$REPORT_JSON" | jq \
76+
'.summary = {
77+
"close_count": (.verdicts.CLOSE | length),
78+
"keep_open_count": (.verdicts.KEEP_OPEN | length),
79+
"flag_pm_count": (.verdicts.FLAG_PM | length),
80+
"verify_code_count": (.verdicts.VERIFY_CODE | length)
81+
}')
82+
83+
# Add action items
84+
REPORT_JSON=$(echo "$REPORT_JSON" | jq \
85+
'.action_items = {
86+
"immediate_closes": (.verdicts.CLOSE | map({issue: .issue, title: .title, action: .action})),
87+
"pm_flags": (.verdicts.FLAG_PM | map({issue: .issue, title: .title, blocker: .blocker, action: .action}) | sort_by(.issue)),
88+
"code_verifications": (.verdicts.VERIFY_CODE | map({issue: .issue, title: .title, action: .action}))
89+
}')
90+
91+
# Write output
92+
echo "$REPORT_JSON" | jq '.' > "$OUTPUT_FILE"
93+
94+
echo "" >&2
95+
echo "✅ Report generated: $OUTPUT_FILE" >&2
96+
echo "" >&2
97+
jq '.summary' "$OUTPUT_FILE" >&2

0 commit comments

Comments
 (0)