shipwright-cli 1.7.1 → 1.9.0
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.
- package/.claude/agents/code-reviewer.md +90 -0
- package/.claude/agents/devops-engineer.md +142 -0
- package/.claude/agents/pipeline-agent.md +80 -0
- package/.claude/agents/shell-script-specialist.md +150 -0
- package/.claude/agents/test-specialist.md +196 -0
- package/.claude/hooks/post-tool-use.sh +38 -0
- package/.claude/hooks/pre-tool-use.sh +25 -0
- package/.claude/hooks/session-started.sh +37 -0
- package/README.md +212 -814
- package/claude-code/CLAUDE.md.shipwright +54 -0
- package/claude-code/hooks/notify-idle.sh +2 -2
- package/claude-code/hooks/session-start.sh +24 -0
- package/claude-code/hooks/task-completed.sh +6 -2
- package/claude-code/settings.json.template +12 -0
- package/dashboard/public/app.js +4422 -0
- package/dashboard/public/index.html +816 -0
- package/dashboard/public/styles.css +4755 -0
- package/dashboard/server.ts +4315 -0
- package/docs/KNOWN-ISSUES.md +18 -10
- package/docs/TIPS.md +38 -26
- package/docs/patterns/README.md +33 -23
- package/package.json +9 -5
- package/scripts/adapters/iterm2-adapter.sh +1 -1
- package/scripts/adapters/tmux-adapter.sh +52 -23
- package/scripts/adapters/wezterm-adapter.sh +26 -14
- package/scripts/lib/compat.sh +200 -0
- package/scripts/lib/helpers.sh +72 -0
- package/scripts/postinstall.mjs +72 -13
- package/scripts/{cct → sw} +109 -21
- package/scripts/sw-adversarial.sh +274 -0
- package/scripts/sw-architecture-enforcer.sh +330 -0
- package/scripts/sw-checkpoint.sh +390 -0
- package/scripts/{cct-cleanup.sh → sw-cleanup.sh} +3 -1
- package/scripts/sw-connect.sh +619 -0
- package/scripts/{cct-cost.sh → sw-cost.sh} +368 -34
- package/scripts/{cct-daemon.sh → sw-daemon.sh} +2217 -204
- package/scripts/sw-dashboard.sh +477 -0
- package/scripts/sw-developer-simulation.sh +252 -0
- package/scripts/sw-docs.sh +635 -0
- package/scripts/sw-doctor.sh +907 -0
- package/scripts/{cct-fix.sh → sw-fix.sh} +10 -6
- package/scripts/{cct-fleet.sh → sw-fleet.sh} +498 -22
- package/scripts/sw-github-checks.sh +521 -0
- package/scripts/sw-github-deploy.sh +533 -0
- package/scripts/sw-github-graphql.sh +972 -0
- package/scripts/sw-heartbeat.sh +293 -0
- package/scripts/{cct-init.sh → sw-init.sh} +144 -11
- package/scripts/sw-intelligence.sh +1196 -0
- package/scripts/sw-jira.sh +643 -0
- package/scripts/sw-launchd.sh +364 -0
- package/scripts/sw-linear.sh +648 -0
- package/scripts/{cct-logs.sh → sw-logs.sh} +72 -2
- package/scripts/{cct-loop.sh → sw-loop.sh} +534 -44
- package/scripts/{cct-memory.sh → sw-memory.sh} +321 -38
- package/scripts/sw-patrol-meta.sh +417 -0
- package/scripts/sw-pipeline-composer.sh +455 -0
- package/scripts/{cct-pipeline.sh → sw-pipeline.sh} +2319 -178
- package/scripts/sw-predictive.sh +820 -0
- package/scripts/{cct-prep.sh → sw-prep.sh} +339 -49
- package/scripts/{cct-ps.sh → sw-ps.sh} +6 -4
- package/scripts/{cct-reaper.sh → sw-reaper.sh} +6 -4
- package/scripts/sw-remote.sh +687 -0
- package/scripts/sw-self-optimize.sh +947 -0
- package/scripts/sw-session.sh +519 -0
- package/scripts/sw-setup.sh +234 -0
- package/scripts/sw-status.sh +605 -0
- package/scripts/{cct-templates.sh → sw-templates.sh} +9 -4
- package/scripts/sw-tmux.sh +591 -0
- package/scripts/sw-tracker-jira.sh +277 -0
- package/scripts/sw-tracker-linear.sh +292 -0
- package/scripts/sw-tracker.sh +409 -0
- package/scripts/{cct-upgrade.sh → sw-upgrade.sh} +103 -46
- package/scripts/{cct-worktree.sh → sw-worktree.sh} +3 -0
- package/templates/pipelines/autonomous.json +27 -5
- package/templates/pipelines/full.json +12 -0
- package/templates/pipelines/standard.json +12 -0
- package/tmux/{claude-teams-overlay.conf → shipwright-overlay.conf} +27 -9
- package/tmux/templates/accessibility.json +34 -0
- package/tmux/templates/api-design.json +35 -0
- package/tmux/templates/architecture.json +1 -0
- package/tmux/templates/bug-fix.json +9 -0
- package/tmux/templates/code-review.json +1 -0
- package/tmux/templates/compliance.json +36 -0
- package/tmux/templates/data-pipeline.json +36 -0
- package/tmux/templates/debt-paydown.json +34 -0
- package/tmux/templates/devops.json +1 -0
- package/tmux/templates/documentation.json +1 -0
- package/tmux/templates/exploration.json +1 -0
- package/tmux/templates/feature-dev.json +1 -0
- package/tmux/templates/full-stack.json +8 -0
- package/tmux/templates/i18n.json +34 -0
- package/tmux/templates/incident-response.json +36 -0
- package/tmux/templates/migration.json +1 -0
- package/tmux/templates/observability.json +35 -0
- package/tmux/templates/onboarding.json +33 -0
- package/tmux/templates/performance.json +35 -0
- package/tmux/templates/refactor.json +1 -0
- package/tmux/templates/release.json +35 -0
- package/tmux/templates/security-audit.json +8 -0
- package/tmux/templates/spike.json +34 -0
- package/tmux/templates/testing.json +1 -0
- package/tmux/tmux.conf +98 -9
- package/scripts/cct-doctor.sh +0 -414
- package/scripts/cct-session.sh +0 -284
- package/scripts/cct-status.sh +0 -169
|
@@ -0,0 +1,417 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ╔═══════════════════════════════════════════════════════════════════════════╗
|
|
3
|
+
# ║ sw-patrol-meta.sh — Shipwright Self-Improvement Patrol ║
|
|
4
|
+
# ║ Sourced by sw-daemon.sh during patrol — creates improvement issues ║
|
|
5
|
+
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
6
|
+
# NOTE: This file is sourced (not executed). Do NOT add set -euo pipefail.
|
|
7
|
+
# All functions from the parent (sw-daemon.sh) are available.
|
|
8
|
+
|
|
9
|
+
# ─── Helper: Create issue if not duplicate ─────────────────────────────────
|
|
10
|
+
patrol_meta_create_issue() {
|
|
11
|
+
local title="$1"
|
|
12
|
+
local body="$2"
|
|
13
|
+
local extra_labels="${3:-}"
|
|
14
|
+
|
|
15
|
+
if [[ "${NO_GITHUB:-false}" == "true" ]]; then
|
|
16
|
+
info " [dry-run] Would create: $title"
|
|
17
|
+
return 0
|
|
18
|
+
fi
|
|
19
|
+
|
|
20
|
+
# Dedup: check if an open issue with this exact title already exists
|
|
21
|
+
local existing
|
|
22
|
+
existing=$(gh issue list --state open --search "$title" --json number,title --jq ".[].title" 2>/dev/null || echo "")
|
|
23
|
+
if echo "$existing" | grep -qF "$title" 2>/dev/null; then
|
|
24
|
+
info " Skipping duplicate: $title"
|
|
25
|
+
return 0
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
local labels="auto-patrol,meta-improvement,ready-to-build"
|
|
29
|
+
if [[ -n "$extra_labels" ]]; then
|
|
30
|
+
labels="${labels},${extra_labels}"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
gh issue create \
|
|
34
|
+
--title "$title" \
|
|
35
|
+
--body "$body" \
|
|
36
|
+
--label "$labels" 2>/dev/null || {
|
|
37
|
+
warn " Failed to create issue: $title"
|
|
38
|
+
return 1
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
issues_created=$((issues_created + 1))
|
|
42
|
+
total_findings=$((total_findings + 1))
|
|
43
|
+
emit_event "patrol.meta_issue_created" "title=$title"
|
|
44
|
+
success " Created issue: $title"
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
# ─── Check 1: Untested Scripts ──────────────────────────────────────────────
|
|
48
|
+
patrol_meta_untested_scripts() {
|
|
49
|
+
info " Checking for untested Shipwright scripts..."
|
|
50
|
+
local count=0
|
|
51
|
+
|
|
52
|
+
for script in "$SCRIPT_DIR"/sw-*.sh; do
|
|
53
|
+
[[ ! -f "$script" ]] && continue
|
|
54
|
+
local base
|
|
55
|
+
base=$(basename "$script" .sh)
|
|
56
|
+
|
|
57
|
+
# Skip test scripts themselves
|
|
58
|
+
[[ "$base" == *-test ]] && continue
|
|
59
|
+
# Skip sourced provider scripts (no standalone execution)
|
|
60
|
+
[[ "$base" == sw-tracker-linear ]] && continue
|
|
61
|
+
[[ "$base" == sw-tracker-jira ]] && continue
|
|
62
|
+
[[ "$base" == sw-patrol-meta ]] && continue
|
|
63
|
+
|
|
64
|
+
local test_file="$SCRIPT_DIR/${base}-test.sh"
|
|
65
|
+
if [[ ! -f "$test_file" ]]; then
|
|
66
|
+
count=$((count + 1))
|
|
67
|
+
patrol_meta_create_issue \
|
|
68
|
+
"[Meta] Add tests for ${base}.sh" \
|
|
69
|
+
"## Missing Test Suite
|
|
70
|
+
|
|
71
|
+
The script \`scripts/${base}.sh\` does not have a corresponding test file \`scripts/${base}-test.sh\`.
|
|
72
|
+
|
|
73
|
+
### Requirements
|
|
74
|
+
- Create \`scripts/${base}-test.sh\` following the existing test patterns
|
|
75
|
+
- Use mock environment (TEMP_DIR with mock binaries on PATH)
|
|
76
|
+
- Include PASS/FAIL counters, colored output, summary section
|
|
77
|
+
- Add ERR trap: \`trap 'echo \"ERROR: \\\$BASH_SOURCE:\\\$LINENO exited with status \\\$?\" >&2' ERR\`
|
|
78
|
+
- Register in \`package.json\` test script chain
|
|
79
|
+
- Aim for at least 10 meaningful test cases
|
|
80
|
+
|
|
81
|
+
### Context
|
|
82
|
+
All other Shipwright scripts follow this test pattern. See \`scripts/sw-daemon-test.sh\` as a reference.
|
|
83
|
+
|
|
84
|
+
_Auto-generated by Shipwright meta-patrol_"
|
|
85
|
+
fi
|
|
86
|
+
done
|
|
87
|
+
|
|
88
|
+
if [[ "$count" -eq 0 ]]; then
|
|
89
|
+
echo -e " ${GREEN}●${RESET} All scripts have test suites"
|
|
90
|
+
else
|
|
91
|
+
echo -e " ${CYAN}●${RESET} Found ${count} untested script(s)"
|
|
92
|
+
fi
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
# ─── Check 2: Bash 3.2 Compatibility ───────────────────────────────────────
|
|
96
|
+
patrol_meta_bash_compat() {
|
|
97
|
+
info " Checking Bash 3.2 compatibility..."
|
|
98
|
+
local count=0
|
|
99
|
+
|
|
100
|
+
for script in "$SCRIPT_DIR"/sw-*.sh; do
|
|
101
|
+
[[ ! -f "$script" ]] && continue
|
|
102
|
+
local base
|
|
103
|
+
base=$(basename "$script")
|
|
104
|
+
|
|
105
|
+
# Look for Bash 4+ patterns
|
|
106
|
+
local violations=""
|
|
107
|
+
local v
|
|
108
|
+
|
|
109
|
+
# declare -A (associative arrays)
|
|
110
|
+
v=$(grep -n 'declare -A' "$script" 2>/dev/null | head -3 || true)
|
|
111
|
+
[[ -n "$v" ]] && violations="${violations}\n- \`declare -A\` (associative arrays): ${v}"
|
|
112
|
+
|
|
113
|
+
# readarray / mapfile
|
|
114
|
+
v=$(grep -n 'readarray\|mapfile' "$script" 2>/dev/null | head -3 || true)
|
|
115
|
+
[[ -n "$v" ]] && violations="${violations}\n- \`readarray/mapfile\`: ${v}"
|
|
116
|
+
|
|
117
|
+
# ${var,,} lowercase
|
|
118
|
+
v=$(grep -n '${[a-zA-Z_]*,,}' "$script" 2>/dev/null | head -3 || true)
|
|
119
|
+
[[ -n "$v" ]] && violations="${violations}\n- \`\${var,,}\` lowercase: ${v}"
|
|
120
|
+
|
|
121
|
+
# ${var^^} uppercase
|
|
122
|
+
v=$(grep -n '${[a-zA-Z_]*\^\^}' "$script" 2>/dev/null | head -3 || true)
|
|
123
|
+
[[ -n "$v" ]] && violations="${violations}\n- \`\${var^^}\` uppercase: ${v}"
|
|
124
|
+
|
|
125
|
+
if [[ -n "$violations" ]]; then
|
|
126
|
+
count=$((count + 1))
|
|
127
|
+
patrol_meta_create_issue \
|
|
128
|
+
"[Meta] Fix Bash 3.2 incompatibility in ${base}" \
|
|
129
|
+
"## Bash 3.2 Compatibility Issue
|
|
130
|
+
|
|
131
|
+
The script \`scripts/${base}\` uses Bash 4+ features that break on macOS default Bash (3.2).
|
|
132
|
+
|
|
133
|
+
### Violations Found
|
|
134
|
+
$(echo -e "$violations")
|
|
135
|
+
|
|
136
|
+
### Required Changes
|
|
137
|
+
- Replace \`declare -A\` with indexed arrays or separate variables
|
|
138
|
+
- Replace \`readarray\` with \`while IFS= read -r\` loops
|
|
139
|
+
- Replace \`\${var,,}\` with \`echo \"\$var\" | tr '[:upper:]' '[:lower:]'\`
|
|
140
|
+
- Replace \`\${var^^}\` with \`echo \"\$var\" | tr '[:lower:]' '[:upper:]'\`
|
|
141
|
+
|
|
142
|
+
_Auto-generated by Shipwright meta-patrol_"
|
|
143
|
+
fi
|
|
144
|
+
done
|
|
145
|
+
|
|
146
|
+
if [[ "$count" -eq 0 ]]; then
|
|
147
|
+
echo -e " ${GREEN}●${RESET} All scripts are Bash 3.2 compatible"
|
|
148
|
+
else
|
|
149
|
+
echo -e " ${CYAN}●${RESET} Found ${count} script(s) with Bash 4+ patterns"
|
|
150
|
+
fi
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# ─── Check 3: VERSION Sync ─────────────────────────────────────────────────
|
|
154
|
+
patrol_meta_version_sync() {
|
|
155
|
+
info " Checking VERSION consistency..."
|
|
156
|
+
local versions=""
|
|
157
|
+
local mismatches=""
|
|
158
|
+
local reference_version=""
|
|
159
|
+
|
|
160
|
+
for script in "$SCRIPT_DIR"/sw-*.sh "$SCRIPT_DIR/sw"; do
|
|
161
|
+
[[ ! -f "$script" ]] && continue
|
|
162
|
+
local base
|
|
163
|
+
base=$(basename "$script")
|
|
164
|
+
local ver
|
|
165
|
+
ver=$(grep -m1 '^VERSION=' "$script" 2>/dev/null | sed 's/VERSION="//' | sed 's/"//' || true)
|
|
166
|
+
if [[ -n "$ver" ]]; then
|
|
167
|
+
if [[ -z "$reference_version" ]]; then
|
|
168
|
+
reference_version="$ver"
|
|
169
|
+
elif [[ "$ver" != "$reference_version" ]]; then
|
|
170
|
+
mismatches="${mismatches}\n- \`${base}\`: ${ver} (expected ${reference_version})"
|
|
171
|
+
fi
|
|
172
|
+
fi
|
|
173
|
+
done
|
|
174
|
+
|
|
175
|
+
if [[ -n "$mismatches" ]]; then
|
|
176
|
+
patrol_meta_create_issue \
|
|
177
|
+
"[Meta] Fix VERSION mismatch across scripts" \
|
|
178
|
+
"## VERSION Mismatch
|
|
179
|
+
|
|
180
|
+
Some scripts have different VERSION values. All scripts should use the same version.
|
|
181
|
+
|
|
182
|
+
### Reference Version: \`${reference_version}\`
|
|
183
|
+
|
|
184
|
+
### Mismatches
|
|
185
|
+
$(echo -e "$mismatches")
|
|
186
|
+
|
|
187
|
+
### Fix
|
|
188
|
+
Update all VERSION= lines to match the reference version.
|
|
189
|
+
|
|
190
|
+
_Auto-generated by Shipwright meta-patrol_"
|
|
191
|
+
echo -e " ${CYAN}●${RESET} VERSION mismatch detected"
|
|
192
|
+
else
|
|
193
|
+
echo -e " ${GREEN}●${RESET} All script versions match: ${reference_version:-unknown}"
|
|
194
|
+
fi
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
# ─── Check 4: DORA Trends (30-day) ─────────────────────────────────────────
|
|
198
|
+
patrol_meta_dora_trends() {
|
|
199
|
+
info " Analyzing 30-day DORA trends..."
|
|
200
|
+
|
|
201
|
+
if [[ ! -f "$EVENTS_FILE" ]]; then
|
|
202
|
+
echo -e " ${DIM}●${RESET} No events data available"
|
|
203
|
+
return
|
|
204
|
+
fi
|
|
205
|
+
|
|
206
|
+
local now_e
|
|
207
|
+
now_e=$(now_epoch)
|
|
208
|
+
local thirty_days_ago=$(( now_e - 2592000 ))
|
|
209
|
+
local fifteen_days_ago=$(( now_e - 1296000 ))
|
|
210
|
+
|
|
211
|
+
# Compare first half (days 16-30) vs second half (days 1-15)
|
|
212
|
+
local first_half_lt second_half_lt
|
|
213
|
+
first_half_lt=$(jq -s "[.[] | select(.type == \"pipeline.completed\" and .result == \"success\" and (.ts_epoch // 0) >= $thirty_days_ago and (.ts_epoch // 0) < $fifteen_days_ago) | .duration_s // 0] | if length > 0 then (add / length) else 0 end" "$EVENTS_FILE" 2>/dev/null || echo "0")
|
|
214
|
+
second_half_lt=$(jq -s "[.[] | select(.type == \"pipeline.completed\" and .result == \"success\" and (.ts_epoch // 0) >= $fifteen_days_ago) | .duration_s // 0] | if length > 0 then (add / length) else 0 end" "$EVENTS_FILE" 2>/dev/null || echo "0")
|
|
215
|
+
|
|
216
|
+
# Check if lead time regressed > 20%
|
|
217
|
+
if [[ "$first_half_lt" != "0" ]] && [[ "$second_half_lt" != "0" ]]; then
|
|
218
|
+
local increase_pct
|
|
219
|
+
increase_pct=$(echo "$first_half_lt $second_half_lt" | awk '{if ($1 > 0) printf "%.0f", (($2 - $1) / $1) * 100; else print "0"}')
|
|
220
|
+
|
|
221
|
+
if [[ "$increase_pct" -gt 20 ]]; then
|
|
222
|
+
patrol_meta_create_issue \
|
|
223
|
+
"[Meta] Investigate lead time regression (+${increase_pct}%)" \
|
|
224
|
+
"## DORA Lead Time Regression
|
|
225
|
+
|
|
226
|
+
Average pipeline lead time has increased by **${increase_pct}%** over the last 30 days.
|
|
227
|
+
|
|
228
|
+
| Period | Avg Lead Time |
|
|
229
|
+
|--------|--------------|
|
|
230
|
+
| Days 16-30 | ${first_half_lt}s |
|
|
231
|
+
| Days 1-15 | ${second_half_lt}s |
|
|
232
|
+
|
|
233
|
+
### Suggested Actions
|
|
234
|
+
- Check if pipeline template complexity has increased
|
|
235
|
+
- Review build stage iteration counts
|
|
236
|
+
- Look for test suite slowdowns
|
|
237
|
+
- Check if retry rates have increased
|
|
238
|
+
|
|
239
|
+
_Auto-generated by Shipwright meta-patrol_"
|
|
240
|
+
echo -e " ${CYAN}●${RESET} Lead time regression: +${increase_pct}%"
|
|
241
|
+
else
|
|
242
|
+
echo -e " ${GREEN}●${RESET} Lead time stable (${increase_pct}% change)"
|
|
243
|
+
fi
|
|
244
|
+
else
|
|
245
|
+
echo -e " ${DIM}●${RESET} Insufficient data for trend analysis"
|
|
246
|
+
fi
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
# ─── Check 5: Template Effectiveness ───────────────────────────────────────
|
|
250
|
+
patrol_meta_template_effectiveness() {
|
|
251
|
+
info " Analyzing pipeline template effectiveness..."
|
|
252
|
+
|
|
253
|
+
if [[ ! -f "$EVENTS_FILE" ]]; then
|
|
254
|
+
echo -e " ${DIM}●${RESET} No events data available"
|
|
255
|
+
return
|
|
256
|
+
fi
|
|
257
|
+
|
|
258
|
+
# Get success rates by template from the last 30 days
|
|
259
|
+
local template_stats
|
|
260
|
+
template_stats=$(jq -s '
|
|
261
|
+
[.[] | select(.type == "pipeline.completed" and (.ts_epoch // 0) > (now - 2592000))]
|
|
262
|
+
| group_by(.template // "unknown")
|
|
263
|
+
| map({
|
|
264
|
+
template: .[0].template // "unknown",
|
|
265
|
+
total: length,
|
|
266
|
+
successes: [.[] | select(.result == "success")] | length
|
|
267
|
+
})
|
|
268
|
+
| map(. + { rate: (if .total > 0 then (.successes * 100 / .total) else 0 end) })
|
|
269
|
+
| sort_by(-.rate)
|
|
270
|
+
' "$EVENTS_FILE" 2>/dev/null || echo "[]")
|
|
271
|
+
|
|
272
|
+
local template_count
|
|
273
|
+
template_count=$(echo "$template_stats" | jq 'length' 2>/dev/null || echo "0")
|
|
274
|
+
|
|
275
|
+
if [[ "$template_count" -gt 1 ]]; then
|
|
276
|
+
local best_template best_rate worst_template worst_rate
|
|
277
|
+
best_template=$(echo "$template_stats" | jq -r '.[0].template' 2>/dev/null || echo "unknown")
|
|
278
|
+
best_rate=$(echo "$template_stats" | jq -r '.[0].rate' 2>/dev/null || echo "0")
|
|
279
|
+
worst_template=$(echo "$template_stats" | jq -r '.[-1].template' 2>/dev/null || echo "unknown")
|
|
280
|
+
worst_rate=$(echo "$template_stats" | jq -r '.[-1].rate' 2>/dev/null || echo "0")
|
|
281
|
+
|
|
282
|
+
local rate_diff=$(( ${best_rate%.*} - ${worst_rate%.*} ))
|
|
283
|
+
|
|
284
|
+
if [[ "$rate_diff" -gt 30 ]]; then
|
|
285
|
+
patrol_meta_create_issue \
|
|
286
|
+
"[Meta] Consider defaulting to '${best_template}' pipeline template" \
|
|
287
|
+
"## Template Effectiveness Analysis
|
|
288
|
+
|
|
289
|
+
The **${best_template}** template significantly outperforms other templates.
|
|
290
|
+
|
|
291
|
+
### Success Rates (Last 30 Days)
|
|
292
|
+
$(echo "$template_stats" | jq -r '.[] | "| \(.template) | \(.successes)/\(.total) | \(.rate)% |"' 2>/dev/null || echo "No data")
|
|
293
|
+
|
|
294
|
+
### Recommendation
|
|
295
|
+
Consider setting \`pipeline_template: \"${best_template}\"\` as the default in \`daemon-config.json\`.
|
|
296
|
+
|
|
297
|
+
_Auto-generated by Shipwright meta-patrol_"
|
|
298
|
+
echo -e " ${CYAN}●${RESET} '${best_template}' outperforms by ${rate_diff}%"
|
|
299
|
+
else
|
|
300
|
+
echo -e " ${GREEN}●${RESET} Templates performing similarly (${rate_diff}% spread)"
|
|
301
|
+
fi
|
|
302
|
+
else
|
|
303
|
+
echo -e " ${DIM}●${RESET} Not enough template variety for comparison"
|
|
304
|
+
fi
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
# ─── Check 6: Memory Pruning ───────────────────────────────────────────────
|
|
308
|
+
patrol_meta_memory_pruning() {
|
|
309
|
+
info " Checking memory file sizes..."
|
|
310
|
+
|
|
311
|
+
local memory_dir="$HOME/.shipwright/memory"
|
|
312
|
+
if [[ ! -d "$memory_dir" ]]; then
|
|
313
|
+
echo -e " ${DIM}●${RESET} No memory directory"
|
|
314
|
+
return
|
|
315
|
+
fi
|
|
316
|
+
|
|
317
|
+
local total_size
|
|
318
|
+
total_size=$(du -sk "$memory_dir" 2>/dev/null | awk '{print $1}' || echo "0")
|
|
319
|
+
local total_mb=$(( total_size / 1024 ))
|
|
320
|
+
|
|
321
|
+
if [[ "$total_mb" -gt 10 ]]; then
|
|
322
|
+
patrol_meta_create_issue \
|
|
323
|
+
"[Meta] Prune memory files (${total_mb}MB)" \
|
|
324
|
+
"## Memory Storage Cleanup Needed
|
|
325
|
+
|
|
326
|
+
The Shipwright memory directory has grown to **${total_mb}MB**.
|
|
327
|
+
|
|
328
|
+
### Location
|
|
329
|
+
\`~/.shipwright/memory/\`
|
|
330
|
+
|
|
331
|
+
### Suggested Actions
|
|
332
|
+
- Archive old memory files (older than 90 days)
|
|
333
|
+
- Deduplicate similar failure patterns
|
|
334
|
+
- Compress rarely-accessed memories
|
|
335
|
+
- Consider implementing automatic memory rotation
|
|
336
|
+
|
|
337
|
+
_Auto-generated by Shipwright meta-patrol_"
|
|
338
|
+
echo -e " ${CYAN}●${RESET} Memory files: ${total_mb}MB (needs pruning)"
|
|
339
|
+
else
|
|
340
|
+
echo -e " ${GREEN}●${RESET} Memory files: ${total_mb}MB (healthy)"
|
|
341
|
+
fi
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
# ─── Check 7: Event Analysis (Top Recurring Failures) ──────────────────────
|
|
345
|
+
patrol_meta_event_analysis() {
|
|
346
|
+
info " Analyzing recurring failure patterns..."
|
|
347
|
+
|
|
348
|
+
if [[ ! -f "$EVENTS_FILE" ]]; then
|
|
349
|
+
echo -e " ${DIM}●${RESET} No events data available"
|
|
350
|
+
return
|
|
351
|
+
fi
|
|
352
|
+
|
|
353
|
+
# Find top 3 most common failure reasons in the last 7 days
|
|
354
|
+
local now_e
|
|
355
|
+
now_e=$(now_epoch)
|
|
356
|
+
local seven_days_ago=$(( now_e - 604800 ))
|
|
357
|
+
|
|
358
|
+
local top_failures
|
|
359
|
+
top_failures=$(jq -s "
|
|
360
|
+
[.[] | select(.type == \"pipeline.completed\" and .result != \"success\" and (.ts_epoch // 0) >= $seven_days_ago)]
|
|
361
|
+
| group_by(.failed_stage // \"unknown\")
|
|
362
|
+
| map({ stage: .[0].failed_stage // \"unknown\", count: length })
|
|
363
|
+
| sort_by(-.count)
|
|
364
|
+
| .[0:3]
|
|
365
|
+
" "$EVENTS_FILE" 2>/dev/null || echo "[]")
|
|
366
|
+
|
|
367
|
+
local failure_count
|
|
368
|
+
failure_count=$(echo "$top_failures" | jq 'length' 2>/dev/null || echo "0")
|
|
369
|
+
|
|
370
|
+
if [[ "$failure_count" -gt 0 ]]; then
|
|
371
|
+
local created=0
|
|
372
|
+
while IFS= read -r failure; do
|
|
373
|
+
local stage count
|
|
374
|
+
stage=$(echo "$failure" | jq -r '.stage' 2>/dev/null || echo "unknown")
|
|
375
|
+
count=$(echo "$failure" | jq -r '.count' 2>/dev/null || echo "0")
|
|
376
|
+
|
|
377
|
+
if [[ "$count" -ge 3 ]]; then
|
|
378
|
+
patrol_meta_create_issue \
|
|
379
|
+
"[Meta] Investigate recurring '${stage}' stage failures (${count}x in 7d)" \
|
|
380
|
+
"## Recurring Pipeline Failure
|
|
381
|
+
|
|
382
|
+
The **${stage}** stage has failed **${count} times** in the last 7 days.
|
|
383
|
+
|
|
384
|
+
### Suggested Investigation
|
|
385
|
+
- Check events.jsonl for error details: \`jq 'select(.type == \"pipeline.completed\" and .failed_stage == \"${stage}\")' ~/.shipwright/events.jsonl\`
|
|
386
|
+
- Review memory patterns: \`shipwright memory search \"${stage}\"\`
|
|
387
|
+
- Check if a specific issue type triggers this failure
|
|
388
|
+
|
|
389
|
+
_Auto-generated by Shipwright meta-patrol_"
|
|
390
|
+
created=$((created + 1))
|
|
391
|
+
fi
|
|
392
|
+
done < <(echo "$top_failures" | jq -c '.[]' 2>/dev/null)
|
|
393
|
+
|
|
394
|
+
if [[ "$created" -gt 0 ]]; then
|
|
395
|
+
echo -e " ${CYAN}●${RESET} Created ${created} issue(s) for recurring failures"
|
|
396
|
+
else
|
|
397
|
+
echo -e " ${GREEN}●${RESET} No recurring failures above threshold"
|
|
398
|
+
fi
|
|
399
|
+
else
|
|
400
|
+
echo -e " ${GREEN}●${RESET} No failures in last 7 days"
|
|
401
|
+
fi
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
# ─── Main Entry Point ──────────────────────────────────────────────────────
|
|
405
|
+
patrol_meta_run() {
|
|
406
|
+
echo -e "\n ${BOLD}Meta Self-Improvement Checks${RESET}"
|
|
407
|
+
|
|
408
|
+
patrol_meta_untested_scripts
|
|
409
|
+
patrol_meta_bash_compat
|
|
410
|
+
patrol_meta_version_sync
|
|
411
|
+
patrol_meta_dora_trends
|
|
412
|
+
patrol_meta_template_effectiveness
|
|
413
|
+
patrol_meta_memory_pruning
|
|
414
|
+
patrol_meta_event_analysis
|
|
415
|
+
|
|
416
|
+
echo ""
|
|
417
|
+
}
|