shipwright-cli 3.1.0 → 3.3.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 +2 -0
- package/.claude/agents/devops-engineer.md +2 -0
- package/.claude/agents/doc-fleet-agent.md +2 -0
- package/.claude/agents/pipeline-agent.md +2 -0
- package/.claude/agents/shell-script-specialist.md +2 -0
- package/.claude/agents/test-specialist.md +2 -0
- package/.claude/hooks/agent-crash-capture.sh +32 -0
- package/.claude/hooks/post-tool-use.sh +3 -2
- package/.claude/hooks/pre-tool-use.sh +35 -3
- package/README.md +22 -8
- package/claude-code/hooks/config-change.sh +18 -0
- package/claude-code/hooks/instructions-reloaded.sh +7 -0
- package/claude-code/hooks/worktree-create.sh +25 -0
- package/claude-code/hooks/worktree-remove.sh +20 -0
- package/config/code-constitution.json +130 -0
- package/config/defaults.json +25 -2
- package/config/policy.json +1 -1
- package/dashboard/middleware/auth.ts +134 -0
- package/dashboard/middleware/constants.ts +21 -0
- package/dashboard/public/index.html +8 -6
- package/dashboard/public/styles.css +176 -97
- package/dashboard/routes/auth.ts +38 -0
- package/dashboard/server.ts +117 -25
- package/dashboard/services/config.ts +26 -0
- package/dashboard/services/db.ts +118 -0
- package/dashboard/src/canvas/pixel-agent.ts +298 -0
- package/dashboard/src/canvas/pixel-sprites.ts +440 -0
- package/dashboard/src/canvas/shipyard-effects.ts +367 -0
- package/dashboard/src/canvas/shipyard-scene.ts +616 -0
- package/dashboard/src/canvas/submarine-layout.ts +267 -0
- package/dashboard/src/components/header.ts +8 -7
- package/dashboard/src/core/api.ts +5 -0
- package/dashboard/src/core/router.ts +1 -0
- package/dashboard/src/design/submarine-theme.ts +253 -0
- package/dashboard/src/main.ts +2 -0
- package/dashboard/src/types/api.ts +12 -1
- package/dashboard/src/views/activity.ts +2 -1
- package/dashboard/src/views/metrics.ts +69 -1
- package/dashboard/src/views/shipyard.ts +39 -0
- package/dashboard/types/index.ts +166 -0
- package/docs/plans/2026-02-28-compound-audit-and-shipyard-design.md +186 -0
- package/docs/plans/2026-02-28-skipper-shipwright-implementation-plan.md +1182 -0
- package/docs/plans/2026-02-28-skipper-shipwright-integration-design.md +531 -0
- package/docs/plans/2026-03-01-ai-powered-skill-injection-design.md +298 -0
- package/docs/plans/2026-03-01-ai-powered-skill-injection-plan.md +1109 -0
- package/docs/plans/2026-03-01-capabilities-cleanup-plan.md +658 -0
- package/docs/plans/2026-03-01-clean-architecture-plan.md +924 -0
- package/docs/plans/2026-03-01-compound-audit-cascade-design.md +191 -0
- package/docs/plans/2026-03-01-compound-audit-cascade-plan.md +921 -0
- package/docs/plans/2026-03-01-deep-integration-plan.md +851 -0
- package/docs/plans/2026-03-01-pipeline-audit-trail-design.md +145 -0
- package/docs/plans/2026-03-01-pipeline-audit-trail-plan.md +770 -0
- package/docs/plans/2026-03-01-refined-depths-brand-design.md +382 -0
- package/docs/plans/2026-03-01-refined-depths-implementation.md +599 -0
- package/docs/plans/2026-03-01-skipper-kernel-integration-design.md +203 -0
- package/docs/plans/2026-03-01-unified-platform-design.md +272 -0
- package/docs/plans/2026-03-07-claude-code-feature-integration-design.md +189 -0
- package/docs/plans/2026-03-07-claude-code-feature-integration-plan.md +1165 -0
- package/docs/research/BACKLOG_QUICK_REFERENCE.md +352 -0
- package/docs/research/CUTTING_EDGE_RESEARCH_2026.md +546 -0
- package/docs/research/RESEARCH_INDEX.md +439 -0
- package/docs/research/RESEARCH_SOURCES.md +440 -0
- package/docs/research/RESEARCH_SUMMARY.txt +275 -0
- package/docs/superpowers/specs/2026-03-10-pipeline-quality-revolution-design.md +341 -0
- package/package.json +2 -2
- package/scripts/lib/adaptive-model.sh +427 -0
- package/scripts/lib/adaptive-timeout.sh +316 -0
- package/scripts/lib/audit-trail.sh +309 -0
- package/scripts/lib/auto-recovery.sh +471 -0
- package/scripts/lib/bandit-selector.sh +431 -0
- package/scripts/lib/bootstrap.sh +104 -2
- package/scripts/lib/causal-graph.sh +455 -0
- package/scripts/lib/compat.sh +126 -0
- package/scripts/lib/compound-audit.sh +337 -0
- package/scripts/lib/constitutional.sh +454 -0
- package/scripts/lib/context-budget.sh +359 -0
- package/scripts/lib/convergence.sh +594 -0
- package/scripts/lib/cost-optimizer.sh +634 -0
- package/scripts/lib/daemon-adaptive.sh +14 -2
- package/scripts/lib/daemon-dispatch.sh +106 -17
- package/scripts/lib/daemon-failure.sh +34 -4
- package/scripts/lib/daemon-patrol.sh +25 -4
- package/scripts/lib/daemon-poll-github.sh +361 -0
- package/scripts/lib/daemon-poll-health.sh +299 -0
- package/scripts/lib/daemon-poll.sh +27 -611
- package/scripts/lib/daemon-state.sh +119 -66
- package/scripts/lib/daemon-triage.sh +10 -0
- package/scripts/lib/dod-scorecard.sh +442 -0
- package/scripts/lib/error-actionability.sh +300 -0
- package/scripts/lib/formal-spec.sh +461 -0
- package/scripts/lib/helpers.sh +180 -5
- package/scripts/lib/intent-analysis.sh +409 -0
- package/scripts/lib/loop-convergence.sh +350 -0
- package/scripts/lib/loop-iteration.sh +682 -0
- package/scripts/lib/loop-progress.sh +48 -0
- package/scripts/lib/loop-restart.sh +185 -0
- package/scripts/lib/memory-effectiveness.sh +506 -0
- package/scripts/lib/mutation-executor.sh +352 -0
- package/scripts/lib/outcome-feedback.sh +521 -0
- package/scripts/lib/pipeline-cli.sh +336 -0
- package/scripts/lib/pipeline-commands.sh +1216 -0
- package/scripts/lib/pipeline-detection.sh +101 -3
- package/scripts/lib/pipeline-execution.sh +897 -0
- package/scripts/lib/pipeline-github.sh +28 -3
- package/scripts/lib/pipeline-intelligence-compound.sh +431 -0
- package/scripts/lib/pipeline-intelligence-scoring.sh +407 -0
- package/scripts/lib/pipeline-intelligence-skip.sh +181 -0
- package/scripts/lib/pipeline-intelligence.sh +104 -1138
- package/scripts/lib/pipeline-quality-bash-compat.sh +182 -0
- package/scripts/lib/pipeline-quality-checks.sh +17 -711
- package/scripts/lib/pipeline-quality-gates.sh +563 -0
- package/scripts/lib/pipeline-stages-build.sh +730 -0
- package/scripts/lib/pipeline-stages-delivery.sh +965 -0
- package/scripts/lib/pipeline-stages-intake.sh +1133 -0
- package/scripts/lib/pipeline-stages-monitor.sh +407 -0
- package/scripts/lib/pipeline-stages-review.sh +1022 -0
- package/scripts/lib/pipeline-stages.sh +161 -2901
- package/scripts/lib/pipeline-state.sh +36 -5
- package/scripts/lib/pipeline-util.sh +487 -0
- package/scripts/lib/policy-learner.sh +438 -0
- package/scripts/lib/process-reward.sh +493 -0
- package/scripts/lib/project-detect.sh +649 -0
- package/scripts/lib/quality-profile.sh +334 -0
- package/scripts/lib/recruit-commands.sh +885 -0
- package/scripts/lib/recruit-learning.sh +739 -0
- package/scripts/lib/recruit-roles.sh +648 -0
- package/scripts/lib/reward-aggregator.sh +458 -0
- package/scripts/lib/rl-optimizer.sh +362 -0
- package/scripts/lib/root-cause.sh +427 -0
- package/scripts/lib/scope-enforcement.sh +445 -0
- package/scripts/lib/session-restart.sh +493 -0
- package/scripts/lib/skill-memory.sh +300 -0
- package/scripts/lib/skill-registry.sh +775 -0
- package/scripts/lib/spec-driven.sh +476 -0
- package/scripts/lib/test-helpers.sh +18 -7
- package/scripts/lib/test-holdout.sh +429 -0
- package/scripts/lib/test-optimizer.sh +511 -0
- package/scripts/shipwright-file-suggest.sh +45 -0
- package/scripts/skills/adversarial-quality.md +61 -0
- package/scripts/skills/api-design.md +44 -0
- package/scripts/skills/architecture-design.md +50 -0
- package/scripts/skills/brainstorming.md +43 -0
- package/scripts/skills/data-pipeline.md +44 -0
- package/scripts/skills/deploy-safety.md +64 -0
- package/scripts/skills/documentation.md +38 -0
- package/scripts/skills/frontend-design.md +45 -0
- package/scripts/skills/generated/.gitkeep +0 -0
- package/scripts/skills/generated/_refinements/.gitkeep +0 -0
- package/scripts/skills/generated/_refinements/adversarial-quality.patch.md +3 -0
- package/scripts/skills/generated/_refinements/architecture-design.patch.md +3 -0
- package/scripts/skills/generated/_refinements/brainstorming.patch.md +3 -0
- package/scripts/skills/generated/cli-version-management.md +29 -0
- package/scripts/skills/generated/collection-system-validation.md +99 -0
- package/scripts/skills/generated/large-scale-c-refactoring-coordination.md +97 -0
- package/scripts/skills/generated/pattern-matching-similarity-scoring.md +195 -0
- package/scripts/skills/generated/test-parallelization-detection.md +65 -0
- package/scripts/skills/observability.md +79 -0
- package/scripts/skills/performance.md +48 -0
- package/scripts/skills/pr-quality.md +49 -0
- package/scripts/skills/product-thinking.md +43 -0
- package/scripts/skills/security-audit.md +49 -0
- package/scripts/skills/systematic-debugging.md +40 -0
- package/scripts/skills/testing-strategy.md +47 -0
- package/scripts/skills/two-stage-review.md +52 -0
- package/scripts/skills/validation-thoroughness.md +55 -0
- package/scripts/sw +9 -3
- package/scripts/sw-activity.sh +9 -8
- package/scripts/sw-adaptive.sh +8 -7
- package/scripts/sw-adversarial.sh +2 -1
- package/scripts/sw-architecture-enforcer.sh +3 -1
- package/scripts/sw-auth.sh +12 -2
- package/scripts/sw-autonomous.sh +5 -1
- package/scripts/sw-changelog.sh +4 -1
- package/scripts/sw-checkpoint.sh +2 -1
- package/scripts/sw-ci.sh +15 -6
- package/scripts/sw-cleanup.sh +4 -26
- package/scripts/sw-code-review.sh +45 -20
- package/scripts/sw-connect.sh +2 -1
- package/scripts/sw-context.sh +2 -1
- package/scripts/sw-cost.sh +107 -5
- package/scripts/sw-daemon.sh +71 -11
- package/scripts/sw-dashboard.sh +3 -1
- package/scripts/sw-db.sh +71 -20
- package/scripts/sw-decide.sh +8 -2
- package/scripts/sw-decompose.sh +360 -17
- package/scripts/sw-deps.sh +4 -1
- package/scripts/sw-developer-simulation.sh +4 -1
- package/scripts/sw-discovery.sh +378 -5
- package/scripts/sw-doc-fleet.sh +4 -1
- package/scripts/sw-docs-agent.sh +3 -1
- package/scripts/sw-docs.sh +2 -1
- package/scripts/sw-doctor.sh +453 -2
- package/scripts/sw-dora.sh +4 -1
- package/scripts/sw-durable.sh +12 -7
- package/scripts/sw-e2e-orchestrator.sh +17 -16
- package/scripts/sw-eventbus.sh +13 -4
- package/scripts/sw-evidence.sh +364 -12
- package/scripts/sw-feedback.sh +550 -9
- package/scripts/sw-fix.sh +20 -1
- package/scripts/sw-fleet-discover.sh +6 -2
- package/scripts/sw-fleet-viz.sh +9 -4
- package/scripts/sw-fleet.sh +5 -1
- package/scripts/sw-github-app.sh +18 -4
- package/scripts/sw-github-checks.sh +3 -2
- package/scripts/sw-github-deploy.sh +3 -2
- package/scripts/sw-github-graphql.sh +18 -7
- package/scripts/sw-guild.sh +5 -1
- package/scripts/sw-heartbeat.sh +5 -30
- package/scripts/sw-hello.sh +67 -0
- package/scripts/sw-hygiene.sh +10 -3
- package/scripts/sw-incident.sh +273 -5
- package/scripts/sw-init.sh +18 -2
- package/scripts/sw-instrument.sh +10 -2
- package/scripts/sw-intelligence.sh +44 -7
- package/scripts/sw-jira.sh +5 -1
- package/scripts/sw-launchd.sh +2 -1
- package/scripts/sw-linear.sh +4 -1
- package/scripts/sw-logs.sh +4 -1
- package/scripts/sw-loop.sh +436 -1076
- package/scripts/sw-memory.sh +357 -3
- package/scripts/sw-mission-control.sh +6 -1
- package/scripts/sw-model-router.sh +483 -27
- package/scripts/sw-otel.sh +15 -4
- package/scripts/sw-oversight.sh +14 -5
- package/scripts/sw-patrol-meta.sh +334 -0
- package/scripts/sw-pipeline-composer.sh +7 -1
- package/scripts/sw-pipeline-vitals.sh +12 -6
- package/scripts/sw-pipeline.sh +54 -2653
- package/scripts/sw-pm.sh +16 -8
- package/scripts/sw-pr-lifecycle.sh +2 -1
- package/scripts/sw-predictive.sh +17 -5
- package/scripts/sw-prep.sh +185 -2
- package/scripts/sw-ps.sh +5 -25
- package/scripts/sw-public-dashboard.sh +17 -4
- package/scripts/sw-quality.sh +14 -6
- package/scripts/sw-reaper.sh +8 -25
- package/scripts/sw-recruit.sh +156 -2303
- package/scripts/sw-regression.sh +19 -12
- package/scripts/sw-release-manager.sh +3 -1
- package/scripts/sw-release.sh +4 -1
- package/scripts/sw-remote.sh +3 -1
- package/scripts/sw-replay.sh +7 -1
- package/scripts/sw-retro.sh +158 -1
- package/scripts/sw-review-rerun.sh +3 -1
- package/scripts/sw-scale.sh +14 -5
- package/scripts/sw-security-audit.sh +6 -1
- package/scripts/sw-self-optimize.sh +173 -6
- package/scripts/sw-session.sh +9 -3
- package/scripts/sw-setup.sh +3 -1
- package/scripts/sw-stall-detector.sh +406 -0
- package/scripts/sw-standup.sh +15 -7
- package/scripts/sw-status.sh +3 -1
- package/scripts/sw-strategic.sh +14 -6
- package/scripts/sw-stream.sh +13 -4
- package/scripts/sw-swarm.sh +20 -7
- package/scripts/sw-team-stages.sh +13 -6
- package/scripts/sw-templates.sh +7 -31
- package/scripts/sw-testgen.sh +17 -6
- package/scripts/sw-tmux-pipeline.sh +4 -1
- package/scripts/sw-tmux-role-color.sh +2 -0
- package/scripts/sw-tmux-status.sh +1 -1
- package/scripts/sw-tmux.sh +37 -1
- package/scripts/sw-trace.sh +3 -1
- package/scripts/sw-tracker-github.sh +3 -0
- package/scripts/sw-tracker-jira.sh +3 -0
- package/scripts/sw-tracker-linear.sh +3 -0
- package/scripts/sw-tracker.sh +3 -1
- package/scripts/sw-triage.sh +3 -2
- package/scripts/sw-upgrade.sh +3 -1
- package/scripts/sw-ux.sh +5 -2
- package/scripts/sw-webhook.sh +5 -2
- package/scripts/sw-widgets.sh +9 -4
- package/scripts/sw-worktree.sh +15 -3
- package/scripts/test-skill-injection.sh +1233 -0
- package/templates/pipelines/autonomous.json +27 -3
- package/templates/pipelines/cost-aware.json +34 -8
- package/templates/pipelines/deployed.json +12 -0
- package/templates/pipelines/enterprise.json +12 -0
- package/templates/pipelines/fast.json +6 -0
- package/templates/pipelines/full.json +27 -3
- package/templates/pipelines/hotfix.json +6 -0
- package/templates/pipelines/standard.json +12 -0
- package/templates/pipelines/tdd.json +12 -0
|
@@ -0,0 +1,427 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# ╔═══════════════════════════════════════════════════════════════════════════╗
|
|
3
|
+
# ║ root-cause — Failure Root Cause Classification & Platform Issue Auto-Create
|
|
4
|
+
# ║
|
|
5
|
+
# ║ Categorizes pipeline failures into systematic root cause types:
|
|
6
|
+
# ║ - code_bug: User code problems (test failures, syntax errors)
|
|
7
|
+
# ║ - infra_issue: Infrastructure problems (timeouts, disk, network)
|
|
8
|
+
# ║ - rate_limit: API rate limiting (Claude, GitHub)
|
|
9
|
+
# ║ - context_exhaustion: Claude context window exceeded
|
|
10
|
+
# ║ - platform_bug: Shipwright script errors, missing functions
|
|
11
|
+
# ║ - config_error: Invalid pipeline/environment configuration
|
|
12
|
+
# ║ - external_dep: Dependency failures (npm, pip, cargo, etc.)
|
|
13
|
+
# ║
|
|
14
|
+
# ║ Auto-creates GitHub issues for platform bugs (confidence >70%)
|
|
15
|
+
# ║ Records classification patterns for learning
|
|
16
|
+
# ║ Provides automated fix suggestions and MTTR analytics
|
|
17
|
+
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
18
|
+
set -euo pipefail
|
|
19
|
+
|
|
20
|
+
VERSION="3.3.0"
|
|
21
|
+
|
|
22
|
+
# Module guard
|
|
23
|
+
[[ -n "${_ROOT_CAUSE_LOADED:-}" ]] && return 0; _ROOT_CAUSE_LOADED=1
|
|
24
|
+
|
|
25
|
+
# ─── Defaults ──────────────────────────────────────────────────────────────
|
|
26
|
+
SCRIPT_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
|
|
27
|
+
REPO_DIR="${REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
28
|
+
PROJECT_ROOT="${PROJECT_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
|
|
29
|
+
STATE_DIR="${STATE_DIR:-$PROJECT_ROOT/.claude}"
|
|
30
|
+
ARTIFACTS_DIR="${ARTIFACTS_DIR:-$STATE_DIR/pipeline-artifacts}"
|
|
31
|
+
NO_GITHUB="${NO_GITHUB:-}"
|
|
32
|
+
|
|
33
|
+
# Ensure helpers are loaded
|
|
34
|
+
[[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh" 2>/dev/null || true
|
|
35
|
+
[[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo "$*"; }
|
|
36
|
+
[[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo "$*" >&2; }
|
|
37
|
+
[[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo "$*" >&2; }
|
|
38
|
+
[[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo "$*"; }
|
|
39
|
+
[[ "$(type -t emit_event 2>/dev/null)" == "function" ]] || emit_event() { true; }
|
|
40
|
+
|
|
41
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
42
|
+
# Classify a failure into root cause categories
|
|
43
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
44
|
+
|
|
45
|
+
rootcause_classify() {
|
|
46
|
+
local error_message="${1:-}"
|
|
47
|
+
local stage="${2:-unknown}"
|
|
48
|
+
local exit_code="${3:-1}"
|
|
49
|
+
|
|
50
|
+
[[ -z "$error_message" ]] && { echo '{"category":"unknown","confidence":0,"evidence":[],"suggested_action":"Review error logs"}'; return 0; }
|
|
51
|
+
|
|
52
|
+
local category="unknown"
|
|
53
|
+
local confidence=0
|
|
54
|
+
local evidence=()
|
|
55
|
+
|
|
56
|
+
# ─── Rate Limit Detection ───────────────────────────────────────────────────
|
|
57
|
+
if echo "$error_message" | grep -qiE '(rate limit|429|too many requests|throttled|limited|quota|backoff)'; then
|
|
58
|
+
category="rate_limit"
|
|
59
|
+
confidence=95
|
|
60
|
+
evidence+=("Explicit rate limit message detected")
|
|
61
|
+
[[ "$error_message" =~ claude ]] && evidence+=("Claude API rate limit")
|
|
62
|
+
[[ "$error_message" =~ github ]] && evidence+=("GitHub API rate limit")
|
|
63
|
+
# ─── Context Exhaustion ──────────────────────────────────────────────────────
|
|
64
|
+
elif echo "$error_message" | grep -qiE '(context window|context.*exceed|token.*limit|auto-compact|maximum context|context.*exhaust)'; then
|
|
65
|
+
category="context_exhaustion"
|
|
66
|
+
confidence=90
|
|
67
|
+
evidence+=("Context window exhaustion detected")
|
|
68
|
+
# ─── Infrastructure Issues ───────────────────────────────────────────────────
|
|
69
|
+
elif echo "$error_message" | grep -qiE '(timeout|timed out|ETIMEDOUT|ECONNREFUSED|ECONNRESET|network|socket hang|OOM|out of memory|killed|signal 9|cannot allocate|disk full|no space|ENOMEM|ENOSPC)'; then
|
|
70
|
+
category="infra_issue"
|
|
71
|
+
confidence=85
|
|
72
|
+
evidence+=("Infrastructure problem detected")
|
|
73
|
+
[[ "$error_message" =~ timeout ]] && evidence+=("Timeout detected")
|
|
74
|
+
[[ "$error_message" =~ OOM|memory ]] && evidence+=("Memory exhaustion")
|
|
75
|
+
[[ "$error_message" =~ disk|space ]] && evidence+=("Disk space issue")
|
|
76
|
+
[[ "$error_message" =~ network|socket ]] && evidence+=("Network issue")
|
|
77
|
+
# ─── Platform Bugs (Shipwright errors) ──────────────────────────────────────
|
|
78
|
+
elif echo "$error_message" | grep -qiE '(sw-.*\.sh|shipwright|unbound variable|command not found.*sw-|pipeline-state|unexpected end)'; then
|
|
79
|
+
category="platform_bug"
|
|
80
|
+
confidence=80
|
|
81
|
+
evidence+=("Shipwright platform error detected")
|
|
82
|
+
[[ "$error_message" =~ unbound ]] && evidence+=("Unbound variable in Shipwright code")
|
|
83
|
+
[[ "$error_message" =~ "command not found" ]] && evidence+=("Missing Shipwright function or script")
|
|
84
|
+
# ─── Configuration Errors ───────────────────────────────────────────────────
|
|
85
|
+
elif echo "$error_message" | grep -qiE '(missing.*config|invalid.*json|PIPELINE_CONFIG|no such template|bad config|invalid.*template|unknown.*option)'; then
|
|
86
|
+
category="config_error"
|
|
87
|
+
confidence=85
|
|
88
|
+
evidence+=("Configuration error detected")
|
|
89
|
+
[[ "$error_message" =~ config ]] && evidence+=("Missing or invalid configuration")
|
|
90
|
+
[[ "$error_message" =~ template ]] && evidence+=("Unknown pipeline template")
|
|
91
|
+
# ─── External Dependency Failures ───────────────────────────────────────────
|
|
92
|
+
elif echo "$error_message" | grep -qiE '(npm ERR|pip.*install|gem.*install|cargo.*error|go.*get|npm:.*not found|cannot find module|dependency.*fail)'; then
|
|
93
|
+
category="external_dep"
|
|
94
|
+
confidence=80
|
|
95
|
+
evidence+=("Dependency installation failure")
|
|
96
|
+
[[ "$error_message" =~ npm ]] && evidence+=("npm dependency issue")
|
|
97
|
+
[[ "$error_message" =~ pip ]] && evidence+=("Python pip issue")
|
|
98
|
+
[[ "$error_message" =~ cargo ]] && evidence+=("Rust cargo issue")
|
|
99
|
+
# ─── Code Bug Detection ──────────────────────────────────────────────────────
|
|
100
|
+
elif echo "$error_message" | grep -qiE '(AssertionError|assert.*fail|Expected.*but.*got|TypeError|ReferenceError|SyntaxError|CompileError|type mismatch|cannot assign|incompatible type|FAILED.*test|Test.*failed|test.*fail)'; then
|
|
101
|
+
category="code_bug"
|
|
102
|
+
confidence=85
|
|
103
|
+
evidence+=("Code logic error detected")
|
|
104
|
+
[[ "$exit_code" != "0" ]] && evidence+=("Non-zero exit code")
|
|
105
|
+
[[ "$stage" == "test" ]] && evidence+=("Failure in test stage")
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# ─── Default to code_bug if no match ────────────────────────────────────────
|
|
109
|
+
if [[ "$category" == "unknown" ]]; then
|
|
110
|
+
category="code_bug"
|
|
111
|
+
confidence=45
|
|
112
|
+
evidence+=("No infrastructure/platform patterns detected; likely user code issue")
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# Output JSON result
|
|
116
|
+
printf '{"category":"%s","confidence":%d,"evidence":%s,"suggested_action":"See rootcause_suggest_fix"}\n' \
|
|
117
|
+
"$category" "$confidence" "$(printf '"%s"' "${evidence[@]}" | jq -Rs 'split("\n") | map(select(length > 0))')"
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
121
|
+
# Analyze error-log.jsonl for error patterns
|
|
122
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
123
|
+
|
|
124
|
+
rootcause_analyze_error_log() {
|
|
125
|
+
local error_log="${ARTIFACTS_DIR}/error-log.jsonl"
|
|
126
|
+
[[ ! -f "$error_log" ]] && { echo '{"patterns_analyzed":0,"top_categories":[],"summary":"No error log found"}'; return 0; }
|
|
127
|
+
|
|
128
|
+
local tmp_dir
|
|
129
|
+
tmp_dir=$(mktemp -d) || return 1
|
|
130
|
+
trap "rm -rf '$tmp_dir'" RETURN
|
|
131
|
+
|
|
132
|
+
# Analyze each error entry and collect classifications
|
|
133
|
+
local classifications="$tmp_dir/classifications.json"
|
|
134
|
+
> "$classifications"
|
|
135
|
+
|
|
136
|
+
local entry_count=0
|
|
137
|
+
while IFS= read -r line; do
|
|
138
|
+
[[ -z "$line" ]] && continue
|
|
139
|
+
local error_msg
|
|
140
|
+
error_msg=$(echo "$line" | jq -r '.error // .message // .' 2>/dev/null || echo "$line")
|
|
141
|
+
[[ -z "$error_msg" || "$error_msg" == "null" ]] && continue
|
|
142
|
+
|
|
143
|
+
local classification
|
|
144
|
+
classification=$(rootcause_classify "$error_msg" "unknown" "1" 2>/dev/null || echo '{}')
|
|
145
|
+
echo "$classification" >> "$classifications"
|
|
146
|
+
entry_count=$((entry_count + 1))
|
|
147
|
+
done < <(tail -50 "$error_log" 2>/dev/null)
|
|
148
|
+
|
|
149
|
+
# Count patterns by category
|
|
150
|
+
local summary
|
|
151
|
+
if [[ "$entry_count" -gt 0 ]]; then
|
|
152
|
+
summary=$(jq -s '[.[] | .category] | group_by(.) | map({category: .[0], count: length}) | sort_by(-.count)' "$classifications" 2>/dev/null || echo "[]")
|
|
153
|
+
else
|
|
154
|
+
summary="[]"
|
|
155
|
+
fi
|
|
156
|
+
|
|
157
|
+
# Safely output JSON
|
|
158
|
+
echo '{"patterns_analyzed":'$entry_count',"top_categories":'$summary',"summary":"Analysis complete"}'
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
162
|
+
# Create GitHub issue for platform bugs
|
|
163
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
164
|
+
|
|
165
|
+
rootcause_create_platform_issue() {
|
|
166
|
+
local classification_json="${1:-}"
|
|
167
|
+
local error_message="${2:-}"
|
|
168
|
+
local stage="${3:-unknown}"
|
|
169
|
+
|
|
170
|
+
[[ -n "$NO_GITHUB" ]] && { info "Skipping GitHub issue creation (NO_GITHUB set)"; return 0; }
|
|
171
|
+
[[ ! -x "$(command -v gh 2>/dev/null)" ]] && { warn "gh CLI not found, cannot create issue"; return 1; }
|
|
172
|
+
|
|
173
|
+
# Parse classification
|
|
174
|
+
local category confidence
|
|
175
|
+
category=$(echo "$classification_json" | jq -r '.category // "unknown"' 2>/dev/null || echo "unknown")
|
|
176
|
+
confidence=$(echo "$classification_json" | jq -r '.confidence // 0' 2>/dev/null || echo "0")
|
|
177
|
+
|
|
178
|
+
# Only create issues for high-confidence platform/config errors
|
|
179
|
+
if [[ ! "$category" =~ ^(platform_bug|config_error)$ ]] || [[ "$confidence" -lt 70 ]]; then
|
|
180
|
+
info "Skipping issue creation: category=$category, confidence=$confidence (threshold: platform_bug|config_error with >70%)"
|
|
181
|
+
return 0
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
# Check for duplicate issues first
|
|
185
|
+
local error_sig
|
|
186
|
+
error_sig=$(echo "$error_message" | cksum | awk '{print $1}')
|
|
187
|
+
local existing_issues
|
|
188
|
+
existing_issues=$(gh issue list --state open --search "error-sig:$error_sig" --limit 1 2>/dev/null || true)
|
|
189
|
+
|
|
190
|
+
if [[ -n "$existing_issues" ]]; then
|
|
191
|
+
info "Duplicate issue already exists for error signature $error_sig"
|
|
192
|
+
echo "$existing_issues" | grep -oE '#[0-9]+' | head -1
|
|
193
|
+
return 0
|
|
194
|
+
fi
|
|
195
|
+
|
|
196
|
+
# Build issue body with context
|
|
197
|
+
local pipeline_config="unknown"
|
|
198
|
+
[[ -f "$STATE_DIR/pipeline-config.json" ]] && pipeline_config=$(cat "$STATE_DIR/pipeline-config.json" | head -20)
|
|
199
|
+
|
|
200
|
+
local issue_title="[PLATFORM BUG] $category in $stage stage"
|
|
201
|
+
local issue_body="## Root Cause Classification
|
|
202
|
+
|
|
203
|
+
**Category:** \`$category\`
|
|
204
|
+
**Confidence:** $confidence%
|
|
205
|
+
**Stage:** $stage
|
|
206
|
+
**Error Signature:** \`$error_sig\`
|
|
207
|
+
|
|
208
|
+
## Error Message
|
|
209
|
+
\`\`\`
|
|
210
|
+
$(echo "$error_message" | head -20)
|
|
211
|
+
\`\`\`
|
|
212
|
+
|
|
213
|
+
## Pipeline Configuration
|
|
214
|
+
\`\`\`json
|
|
215
|
+
$pipeline_config
|
|
216
|
+
\`\`\`
|
|
217
|
+
|
|
218
|
+
## System Info
|
|
219
|
+
- Shipwright version: $VERSION
|
|
220
|
+
- Pipeline state: see .claude/pipeline-state.md
|
|
221
|
+
- Error log: see .claude/pipeline-artifacts/error-log.jsonl
|
|
222
|
+
|
|
223
|
+
## Auto-Created
|
|
224
|
+
This issue was automatically created by Shipwright's root cause classifier.
|
|
225
|
+
If this is not a platform bug, please close with \`resolution:not-our-bug\`.
|
|
226
|
+
If you've fixed this, tag it with \`resolved\`.
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
error-sig: $error_sig
|
|
230
|
+
"
|
|
231
|
+
|
|
232
|
+
# Create the issue
|
|
233
|
+
local issue_url
|
|
234
|
+
issue_url=$(gh issue create \
|
|
235
|
+
--title "$issue_title" \
|
|
236
|
+
--body "$issue_body" \
|
|
237
|
+
--label "platform-bug,auto-created" \
|
|
238
|
+
2>/dev/null || echo "")
|
|
239
|
+
|
|
240
|
+
if [[ -n "$issue_url" ]]; then
|
|
241
|
+
success "Created platform bug issue: $issue_url"
|
|
242
|
+
echo "$issue_url" | grep -oE '#[0-9]+' | tr -d '#'
|
|
243
|
+
emit_event "rootcause.platform_issue_created" "error_sig=$error_sig" "issue=$issue_url"
|
|
244
|
+
return 0
|
|
245
|
+
fi
|
|
246
|
+
|
|
247
|
+
warn "Failed to create GitHub issue"
|
|
248
|
+
return 1
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
252
|
+
# Suggest automated fixes by category
|
|
253
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
254
|
+
|
|
255
|
+
rootcause_suggest_fix() {
|
|
256
|
+
local category="${1:-unknown}"
|
|
257
|
+
local error_message="${2:-}"
|
|
258
|
+
local stage="${3:-unknown}"
|
|
259
|
+
|
|
260
|
+
local suggestions=""
|
|
261
|
+
local actionability=0
|
|
262
|
+
|
|
263
|
+
case "$category" in
|
|
264
|
+
rate_limit)
|
|
265
|
+
suggestions="Rate limit detected. Suggested fixes: Wait and retry with exponential backoff, check API quota with shipwright cost show, reduce concurrency in daemon-config.json, time-shift pipeline execution to off-peak hours"
|
|
266
|
+
actionability=85
|
|
267
|
+
;;
|
|
268
|
+
context_exhaustion)
|
|
269
|
+
suggestions="Context window exhausted. Suggested fixes: Increase max-restarts for fresh session, reduce codebase context via .claudeignore, simplify pipeline goal or break into subtasks, check memory usage with shipwright memory show"
|
|
270
|
+
actionability=75
|
|
271
|
+
;;
|
|
272
|
+
infra_issue)
|
|
273
|
+
suggestions="Infrastructure problem. Suggested fixes: Check disk space with df -h, check memory with free -h or vm_stat, check network connectivity with ping github.com, restart daemon, check system load with uptime"
|
|
274
|
+
actionability=70
|
|
275
|
+
;;
|
|
276
|
+
platform_bug)
|
|
277
|
+
suggestions="Shipwright platform bug. Suggested fixes: Check .claude/pipeline-state.md for context, run shipwright doctor to validate setup, review recent changes with git log, check .claude/hooks for interfering hooks, upgrade with shipwright upgrade"
|
|
278
|
+
actionability=80
|
|
279
|
+
;;
|
|
280
|
+
config_error)
|
|
281
|
+
suggestions="Configuration error. Suggested fixes: Run shipwright doctor to validate setup, check .claude/daemon-config.json for syntax errors, verify environment variables, check pipeline template exists, review .claudeignore and .claude/rules"
|
|
282
|
+
actionability=90
|
|
283
|
+
;;
|
|
284
|
+
external_dep)
|
|
285
|
+
suggestions="External dependency failure. Suggested fixes: Clear dependency cache, retry install with npm install or pip install, check package registry health, increase timeout for slow networks, try offline mirror or alternative registry"
|
|
286
|
+
actionability=75
|
|
287
|
+
;;
|
|
288
|
+
code_bug)
|
|
289
|
+
suggestions="Code logic error in user code. Suggested fixes: Review test output in .claude/pipeline-artifacts, check recent commits with git diff, run tests locally, enable debug logging for the stage, use shipwright loop with debug mode"
|
|
290
|
+
actionability=65
|
|
291
|
+
;;
|
|
292
|
+
*)
|
|
293
|
+
suggestions="Unknown error. Start debugging: Check error logs in .claude/pipeline-artifacts, run shipwright doctor for setup validation, enable verbose logging with DEBUG=1, review pipeline state with shipwright status"
|
|
294
|
+
actionability=50
|
|
295
|
+
;;
|
|
296
|
+
esac
|
|
297
|
+
|
|
298
|
+
# Use jq to safely create JSON with proper escaping
|
|
299
|
+
jq -n --arg cat "$category" --arg sug "$suggestions" --arg act "$actionability" \
|
|
300
|
+
'{category: $cat, suggestions: $sug, actionability: ($act | tonumber)}'
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
304
|
+
# Feed classified failures into learning system
|
|
305
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
306
|
+
|
|
307
|
+
rootcause_learn() {
|
|
308
|
+
local category="${1:-unknown}"
|
|
309
|
+
local confidence="${2:-0}"
|
|
310
|
+
local error_message="${3:-}"
|
|
311
|
+
|
|
312
|
+
local learn_file="${HOME}/.shipwright/optimization/root-causes.jsonl"
|
|
313
|
+
mkdir -p "${HOME}/.shipwright/optimization" 2>/dev/null || return 1
|
|
314
|
+
|
|
315
|
+
local entry
|
|
316
|
+
entry=$(jq -c -n \
|
|
317
|
+
--arg cat "$category" \
|
|
318
|
+
--arg conf "$confidence" \
|
|
319
|
+
--arg msg "$(echo "$error_message" | head -c 200)" \
|
|
320
|
+
--arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
|
|
321
|
+
'{category: $cat, confidence: ($conf | tonumber), message: $msg, recorded_at: $ts}')
|
|
322
|
+
|
|
323
|
+
# Atomic append
|
|
324
|
+
local tmp_learn
|
|
325
|
+
tmp_learn=$(mktemp) || return 1
|
|
326
|
+
echo "$entry" >> "$tmp_learn"
|
|
327
|
+
cat "$learn_file" >> "$tmp_learn" 2>/dev/null || true
|
|
328
|
+
mv "$tmp_learn" "$learn_file" 2>/dev/null || { rm -f "$tmp_learn"; return 1; }
|
|
329
|
+
chmod 600 "$learn_file" 2>/dev/null || true
|
|
330
|
+
|
|
331
|
+
emit_event "rootcause.learned" "category=$category" "confidence=$confidence"
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
335
|
+
# Generate root cause report
|
|
336
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
337
|
+
|
|
338
|
+
rootcause_report() {
|
|
339
|
+
local learn_file="${HOME}/.shipwright/optimization/root-causes.jsonl"
|
|
340
|
+
[[ ! -f "$learn_file" ]] && { info "No root cause history yet"; return 0; }
|
|
341
|
+
|
|
342
|
+
local total_entries
|
|
343
|
+
total_entries=$(wc -l < "$learn_file" 2>/dev/null || echo "0")
|
|
344
|
+
|
|
345
|
+
# Category distribution
|
|
346
|
+
local dist
|
|
347
|
+
dist=$(jq -s 'group_by(.category) | map({category: .[0].category, count: length}) | sort_by(-.count)' "$learn_file" 2>/dev/null || echo "[]")
|
|
348
|
+
|
|
349
|
+
# Top 5 most frequent root causes (by message)
|
|
350
|
+
local top_5
|
|
351
|
+
top_5=$(jq -s 'group_by(.message) | map({message: .[0].message, category: .[0].category, occurrences: length}) | sort_by(-.occurrences) | .[0:5]' "$learn_file" 2>/dev/null || echo "[]")
|
|
352
|
+
|
|
353
|
+
# Trend: are platform bugs increasing?
|
|
354
|
+
local platform_bugs_1d platform_bugs_7d
|
|
355
|
+
platform_bugs_1d=$(jq -s --arg cutoff "$(date -u -d '1 day ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-1d +%Y-%m-%dT%H:%M:%SZ)" \
|
|
356
|
+
"[.[] | select(.recorded_at > \$cutoff and .category == \"platform_bug\")] | length" "$learn_file" 2>/dev/null || echo "0")
|
|
357
|
+
platform_bugs_7d=$(jq -s --arg cutoff "$(date -u -d '7 days ago' +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -v-7d +%Y-%m-%dT%H:%M:%SZ)" \
|
|
358
|
+
"[.[] | select(.recorded_at > \$cutoff and .category == \"platform_bug\")] | length" "$learn_file" 2>/dev/null || echo "0")
|
|
359
|
+
|
|
360
|
+
# MTTR by category
|
|
361
|
+
local mttr_by_cat
|
|
362
|
+
mttr_by_cat=$(jq -s 'group_by(.category) | map({category: .[0].category, avg_confidence: (map(.confidence) | add / length)}) | sort_by(-.avg_confidence)' "$learn_file" 2>/dev/null || echo "[]")
|
|
363
|
+
|
|
364
|
+
{
|
|
365
|
+
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
366
|
+
echo " Root Cause Analysis Report"
|
|
367
|
+
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
368
|
+
echo ""
|
|
369
|
+
echo "Total analyzed failures: $total_entries"
|
|
370
|
+
echo ""
|
|
371
|
+
echo "─── Category Distribution ───────────────────────────────────────────────────"
|
|
372
|
+
echo "$dist" | jq -r '.[] | " \(.category): \(.count) occurrences"'
|
|
373
|
+
echo ""
|
|
374
|
+
echo "─── Top 5 Most Frequent Root Causes ──────────────────────────────────────"
|
|
375
|
+
echo "$top_5" | jq -r '.[] | " [\(.category)] \(.occurrences)x: \(.message | .[0:70])"'
|
|
376
|
+
echo ""
|
|
377
|
+
echo "─── Platform Bug Trend ───────────────────────────────────────────────────"
|
|
378
|
+
echo " Last 24h: $platform_bugs_1d platform bugs"
|
|
379
|
+
echo " Last 7d: $platform_bugs_7d platform bugs"
|
|
380
|
+
[[ "$platform_bugs_7d" -gt 0 ]] && {
|
|
381
|
+
local trend
|
|
382
|
+
trend=$((platform_bugs_1d * 100 / platform_bugs_7d))
|
|
383
|
+
[[ "$trend" -gt 100 ]] && echo " ⚠️ INCREASING trend!" || echo " ✓ Decreasing or stable"
|
|
384
|
+
}
|
|
385
|
+
echo ""
|
|
386
|
+
echo "─── Average Confidence by Category ───────────────────────────────────────"
|
|
387
|
+
echo "$mttr_by_cat" | jq -r '.[] | " \(.category): \(.avg_confidence | round)% confidence"'
|
|
388
|
+
echo ""
|
|
389
|
+
echo "═══════════════════════════════════════════════════════════════════════════"
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
394
|
+
# Main entry point: Classify and optionally create issue
|
|
395
|
+
# ═══════════════════════════════════════════════════════════════════════════════
|
|
396
|
+
|
|
397
|
+
rootcause_main() {
|
|
398
|
+
local error_message="${1:-}"
|
|
399
|
+
local stage="${2:-unknown}"
|
|
400
|
+
local exit_code="${3:-1}"
|
|
401
|
+
|
|
402
|
+
[[ -z "$error_message" ]] && { error "Usage: rootcause_main <error_message> [stage] [exit_code]"; return 1; }
|
|
403
|
+
|
|
404
|
+
# Classify the error
|
|
405
|
+
local classification
|
|
406
|
+
classification=$(rootcause_classify "$error_message" "$stage" "$exit_code")
|
|
407
|
+
|
|
408
|
+
# Extract category and confidence
|
|
409
|
+
local category confidence
|
|
410
|
+
category=$(echo "$classification" | jq -r '.category' 2>/dev/null || echo "unknown")
|
|
411
|
+
confidence=$(echo "$classification" | jq -r '.confidence' 2>/dev/null || echo "0")
|
|
412
|
+
|
|
413
|
+
# Suggest fix
|
|
414
|
+
local fix_suggestion
|
|
415
|
+
fix_suggestion=$(rootcause_suggest_fix "$category" "$error_message" "$stage")
|
|
416
|
+
|
|
417
|
+
# Learn from this failure
|
|
418
|
+
rootcause_learn "$category" "$confidence" "$error_message"
|
|
419
|
+
|
|
420
|
+
# Try to create issue for platform bugs
|
|
421
|
+
[[ "$category" =~ ^(platform_bug|config_error)$ ]] && [[ "$confidence" -gt 70 ]] && {
|
|
422
|
+
rootcause_create_platform_issue "$classification" "$error_message" "$stage" || true
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
# Output result
|
|
426
|
+
printf '{"classification":%s,"fix":%s}\n' "$classification" "$fix_suggestion"
|
|
427
|
+
}
|