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,407 @@
|
|
|
1
|
+
# pipeline-intelligence-scoring.sh — Complexity scoring and adaptation for pipeline-intelligence.sh
|
|
2
|
+
# Source from pipeline-intelligence.sh. Requires state, ARTIFACTS_DIR.
|
|
3
|
+
[[ -n "${_PIPELINE_INTELLIGENCE_SCORING_LOADED:-}" ]] && return 0
|
|
4
|
+
_PIPELINE_INTELLIGENCE_SCORING_LOADED=1
|
|
5
|
+
|
|
6
|
+
# Defaults for variables normally set by sw-pipeline.sh (safe under set -u).
|
|
7
|
+
ARTIFACTS_DIR="${ARTIFACTS_DIR:-.claude/pipeline-artifacts}"
|
|
8
|
+
SCRIPT_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)}"
|
|
9
|
+
NO_GITHUB="${NO_GITHUB:-false}"
|
|
10
|
+
|
|
11
|
+
pipeline_adaptive_cycles() {
|
|
12
|
+
local base_limit="$1"
|
|
13
|
+
local context="${2:-compound_quality}" # compound_quality or build_test
|
|
14
|
+
local current_issue_count="${3:-0}"
|
|
15
|
+
local prev_issue_count="${4:--1}"
|
|
16
|
+
|
|
17
|
+
local adjusted="$base_limit"
|
|
18
|
+
local hard_ceiling=$((base_limit * 2))
|
|
19
|
+
|
|
20
|
+
# ── Learned iteration model ──
|
|
21
|
+
local model_file="${HOME}/.shipwright/optimization/iteration-model.json"
|
|
22
|
+
if [[ -f "$model_file" ]]; then
|
|
23
|
+
local learned
|
|
24
|
+
learned=$(jq -r --arg ctx "$context" '.[$ctx].recommended_cycles // 0' "$model_file" 2>/dev/null || echo "0")
|
|
25
|
+
if [[ "$learned" -gt 0 && "$learned" -le "$hard_ceiling" ]]; then
|
|
26
|
+
adjusted="$learned"
|
|
27
|
+
fi
|
|
28
|
+
fi
|
|
29
|
+
|
|
30
|
+
# ── Convergence acceleration ──
|
|
31
|
+
# If issue count drops >50% per cycle, extend limit by 1 (we're making progress)
|
|
32
|
+
if [[ "$prev_issue_count" -gt 0 && "$current_issue_count" -ge 0 ]]; then
|
|
33
|
+
local half_prev=$((prev_issue_count / 2))
|
|
34
|
+
if [[ "$current_issue_count" -le "$half_prev" && "$current_issue_count" -gt 0 ]]; then
|
|
35
|
+
# Rapid convergence — extend by 1
|
|
36
|
+
local new_limit=$((adjusted + 1))
|
|
37
|
+
if [[ "$new_limit" -le "$hard_ceiling" ]]; then
|
|
38
|
+
adjusted="$new_limit"
|
|
39
|
+
emit_event "intelligence.convergence_acceleration" \
|
|
40
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
41
|
+
"context=$context" \
|
|
42
|
+
"prev_issues=$prev_issue_count" \
|
|
43
|
+
"current_issues=$current_issue_count" \
|
|
44
|
+
"new_limit=$adjusted"
|
|
45
|
+
fi
|
|
46
|
+
fi
|
|
47
|
+
|
|
48
|
+
# ── Divergence detection ──
|
|
49
|
+
# If issue count increases, reduce remaining cycles
|
|
50
|
+
if [[ "$current_issue_count" -gt "$prev_issue_count" ]]; then
|
|
51
|
+
local reduced=$((adjusted - 1))
|
|
52
|
+
if [[ "$reduced" -ge 1 ]]; then
|
|
53
|
+
adjusted="$reduced"
|
|
54
|
+
emit_event "intelligence.divergence_detected" \
|
|
55
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
56
|
+
"context=$context" \
|
|
57
|
+
"prev_issues=$prev_issue_count" \
|
|
58
|
+
"current_issues=$current_issue_count" \
|
|
59
|
+
"new_limit=$adjusted"
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# ── Budget gate ──
|
|
65
|
+
if [[ "$IGNORE_BUDGET" != "true" ]] && [[ -x "$SCRIPT_DIR/sw-cost.sh" ]]; then
|
|
66
|
+
local budget_rc=0
|
|
67
|
+
bash "$SCRIPT_DIR/sw-cost.sh" check-budget 2>/dev/null || budget_rc=$?
|
|
68
|
+
if [[ "$budget_rc" -eq 2 ]]; then
|
|
69
|
+
# Budget exhausted — cap at current cycle
|
|
70
|
+
adjusted=0
|
|
71
|
+
emit_event "intelligence.budget_cap" \
|
|
72
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
73
|
+
"context=$context"
|
|
74
|
+
fi
|
|
75
|
+
fi
|
|
76
|
+
|
|
77
|
+
# ── Enforce hard ceiling ──
|
|
78
|
+
if [[ "$adjusted" -gt "$hard_ceiling" ]]; then
|
|
79
|
+
adjusted="$hard_ceiling"
|
|
80
|
+
fi
|
|
81
|
+
|
|
82
|
+
echo "$adjusted"
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
86
|
+
# 5. Intelligent Audit Selection
|
|
87
|
+
# AI-driven audit selection — all audits enabled, intensity varies.
|
|
88
|
+
|
|
89
|
+
pipeline_select_audits() {
|
|
90
|
+
local audit_intensity
|
|
91
|
+
audit_intensity=$(jq -r --arg id "compound_quality" \
|
|
92
|
+
'(.stages[] | select(.id == $id) | .config.audit_intensity) // "auto"' \
|
|
93
|
+
"$PIPELINE_CONFIG" 2>/dev/null) || true
|
|
94
|
+
[[ -z "$audit_intensity" || "$audit_intensity" == "null" ]] && audit_intensity="auto"
|
|
95
|
+
|
|
96
|
+
# Short-circuit for explicit overrides
|
|
97
|
+
case "$audit_intensity" in
|
|
98
|
+
off)
|
|
99
|
+
echo '{"adversarial":"off","architecture":"off","simulation":"off","security":"off","dod":"off"}'
|
|
100
|
+
return 0
|
|
101
|
+
;;
|
|
102
|
+
full|lightweight)
|
|
103
|
+
jq -n --arg i "$audit_intensity" \
|
|
104
|
+
'{adversarial:$i,architecture:$i,simulation:$i,security:$i,dod:$i}'
|
|
105
|
+
return 0
|
|
106
|
+
;;
|
|
107
|
+
esac
|
|
108
|
+
|
|
109
|
+
# ── Auto mode: data-driven intensity ──
|
|
110
|
+
local default_intensity="targeted"
|
|
111
|
+
local security_intensity="targeted"
|
|
112
|
+
|
|
113
|
+
# Read last 5 quality scores for this repo
|
|
114
|
+
local quality_scores_file="${HOME}/.shipwright/optimization/quality-scores.jsonl"
|
|
115
|
+
local repo_name
|
|
116
|
+
repo_name=$(basename "${PROJECT_ROOT:-.}") || true
|
|
117
|
+
if [[ -f "$quality_scores_file" ]]; then
|
|
118
|
+
local recent_scores
|
|
119
|
+
recent_scores=$(grep "\"repo\":\"${repo_name}\"" "$quality_scores_file" 2>/dev/null | tail -5) || true
|
|
120
|
+
if [[ -n "$recent_scores" ]]; then
|
|
121
|
+
# Check for critical findings in recent history
|
|
122
|
+
local has_critical
|
|
123
|
+
has_critical=$(echo "$recent_scores" | jq -s '[.[].findings.critical // 0] | add' 2>/dev/null || echo "0")
|
|
124
|
+
has_critical="${has_critical:-0}"
|
|
125
|
+
if [[ "$has_critical" -gt 0 ]]; then
|
|
126
|
+
security_intensity="full"
|
|
127
|
+
fi
|
|
128
|
+
|
|
129
|
+
# Compute average quality score
|
|
130
|
+
local avg_score
|
|
131
|
+
avg_score=$(echo "$recent_scores" | jq -s 'if length > 0 then ([.[].quality_score] | add / length | floor) else 70 end' 2>/dev/null || echo "70")
|
|
132
|
+
avg_score="${avg_score:-70}"
|
|
133
|
+
|
|
134
|
+
if [[ "$avg_score" -lt 60 ]]; then
|
|
135
|
+
default_intensity="full"
|
|
136
|
+
security_intensity="full"
|
|
137
|
+
elif [[ "$avg_score" -gt 80 ]]; then
|
|
138
|
+
default_intensity="lightweight"
|
|
139
|
+
[[ "$security_intensity" != "full" ]] && security_intensity="lightweight"
|
|
140
|
+
fi
|
|
141
|
+
fi
|
|
142
|
+
fi
|
|
143
|
+
|
|
144
|
+
# Intelligence cache: upgrade targeted→full for complex changes
|
|
145
|
+
local intel_cache="${PROJECT_ROOT}/.claude/intelligence-cache.json"
|
|
146
|
+
if [[ -f "$intel_cache" && "$default_intensity" == "targeted" ]]; then
|
|
147
|
+
local complexity
|
|
148
|
+
complexity=$(jq -r '.complexity // "medium"' "$intel_cache" 2>/dev/null || echo "medium")
|
|
149
|
+
if [[ "$complexity" == "high" || "$complexity" == "very_high" ]]; then
|
|
150
|
+
default_intensity="full"
|
|
151
|
+
security_intensity="full"
|
|
152
|
+
fi
|
|
153
|
+
fi
|
|
154
|
+
|
|
155
|
+
emit_event "pipeline.audit_selection" \
|
|
156
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
157
|
+
"default_intensity=$default_intensity" \
|
|
158
|
+
"security_intensity=$security_intensity" \
|
|
159
|
+
"repo=$repo_name"
|
|
160
|
+
|
|
161
|
+
jq -n \
|
|
162
|
+
--arg adv "$default_intensity" \
|
|
163
|
+
--arg arch "$default_intensity" \
|
|
164
|
+
--arg sim "$default_intensity" \
|
|
165
|
+
--arg sec "$security_intensity" \
|
|
166
|
+
--arg dod "$default_intensity" \
|
|
167
|
+
'{adversarial:$adv,architecture:$arch,simulation:$sim,security:$sec,dod:$dod}'
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
pipeline_record_quality_score() {
|
|
171
|
+
local quality_score="${1:-0}"
|
|
172
|
+
local critical="${2:-0}"
|
|
173
|
+
local major="${3:-0}"
|
|
174
|
+
local minor="${4:-0}"
|
|
175
|
+
local dod_pass_rate="${5:-0}"
|
|
176
|
+
local audits_run="${6:-}"
|
|
177
|
+
|
|
178
|
+
local scores_dir="${HOME}/.shipwright/optimization"
|
|
179
|
+
local scores_file="${scores_dir}/quality-scores.jsonl"
|
|
180
|
+
mkdir -p "$scores_dir"
|
|
181
|
+
|
|
182
|
+
local repo_name
|
|
183
|
+
repo_name=$(basename "${PROJECT_ROOT:-.}") || true
|
|
184
|
+
|
|
185
|
+
local tmp_score
|
|
186
|
+
tmp_score=$(mktemp)
|
|
187
|
+
jq -n \
|
|
188
|
+
--arg repo "$repo_name" \
|
|
189
|
+
--arg issue "${ISSUE_NUMBER:-0}" \
|
|
190
|
+
--arg ts "$(now_iso)" \
|
|
191
|
+
--argjson score "$quality_score" \
|
|
192
|
+
--argjson critical "$critical" \
|
|
193
|
+
--argjson major "$major" \
|
|
194
|
+
--argjson minor "$minor" \
|
|
195
|
+
--argjson dod "$dod_pass_rate" \
|
|
196
|
+
--arg template "${PIPELINE_NAME:-standard}" \
|
|
197
|
+
--arg audits "$audits_run" \
|
|
198
|
+
'{
|
|
199
|
+
repo: $repo,
|
|
200
|
+
issue: ($issue | tonumber),
|
|
201
|
+
timestamp: $ts,
|
|
202
|
+
quality_score: $score,
|
|
203
|
+
findings: {critical: $critical, major: $major, minor: $minor},
|
|
204
|
+
dod_pass_rate: $dod,
|
|
205
|
+
template: $template,
|
|
206
|
+
audits_run: ($audits | split(",") | map(select(. != "")))
|
|
207
|
+
}' > "$tmp_score" 2>/dev/null
|
|
208
|
+
|
|
209
|
+
cat "$tmp_score" >> "$scores_file"
|
|
210
|
+
rm -f "$tmp_score"
|
|
211
|
+
|
|
212
|
+
# Rotate quality scores file to prevent unbounded growth
|
|
213
|
+
type rotate_jsonl >/dev/null 2>&1 && rotate_jsonl "$scores_file" 5000
|
|
214
|
+
|
|
215
|
+
emit_event "pipeline.quality_score_recorded" \
|
|
216
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
217
|
+
"quality_score=$quality_score" \
|
|
218
|
+
"critical=$critical" \
|
|
219
|
+
"major=$major" \
|
|
220
|
+
"minor=$minor"
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
|
|
224
|
+
pipeline_reassess_complexity() {
|
|
225
|
+
local initial_complexity="${INTELLIGENCE_COMPLEXITY:-5}"
|
|
226
|
+
local reassessment_file="$ARTIFACTS_DIR/reassessment.json"
|
|
227
|
+
|
|
228
|
+
# ── Gather actual metrics ──
|
|
229
|
+
local files_changed=0 lines_changed=0 first_try_pass=false self_heal_cycles=0
|
|
230
|
+
|
|
231
|
+
files_changed=$(git diff "${BASE_BRANCH:-main}...HEAD" --name-only 2>/dev/null | wc -l | tr -d ' ') || files_changed=0
|
|
232
|
+
files_changed="${files_changed:-0}"
|
|
233
|
+
|
|
234
|
+
# Count lines changed (insertions + deletions) without pipefail issues
|
|
235
|
+
lines_changed=0
|
|
236
|
+
local _diff_stat
|
|
237
|
+
_diff_stat=$(git diff "${BASE_BRANCH:-main}...HEAD" --stat 2>/dev/null | tail -1) || true
|
|
238
|
+
if [[ -n "${_diff_stat:-}" ]]; then
|
|
239
|
+
local _ins _del
|
|
240
|
+
_ins=$(echo "$_diff_stat" | grep -oE '[0-9]+ insertion' | grep -oE '[0-9]+') || true
|
|
241
|
+
_del=$(echo "$_diff_stat" | grep -oE '[0-9]+ deletion' | grep -oE '[0-9]+') || true
|
|
242
|
+
lines_changed=$(( ${_ins:-0} + ${_del:-0} ))
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
self_heal_cycles="${SELF_HEAL_COUNT:-0}"
|
|
246
|
+
if [[ "$self_heal_cycles" -eq 0 ]]; then
|
|
247
|
+
first_try_pass=true
|
|
248
|
+
fi
|
|
249
|
+
|
|
250
|
+
# ── Compare to expectations ──
|
|
251
|
+
local actual_complexity="$initial_complexity"
|
|
252
|
+
local assessment="as_expected"
|
|
253
|
+
local skip_stages="[]"
|
|
254
|
+
|
|
255
|
+
# Simpler than expected: small diff, tests passed first try
|
|
256
|
+
if [[ "$lines_changed" -lt 50 && "$first_try_pass" == "true" && "$files_changed" -lt 5 ]]; then
|
|
257
|
+
actual_complexity=$((initial_complexity > 2 ? initial_complexity - 2 : 1))
|
|
258
|
+
assessment="simpler_than_expected"
|
|
259
|
+
# Mark compound_quality as skippable, simplify review
|
|
260
|
+
skip_stages='["compound_quality"]'
|
|
261
|
+
# Much simpler
|
|
262
|
+
elif [[ "$lines_changed" -lt 20 && "$first_try_pass" == "true" && "$files_changed" -lt 3 ]]; then
|
|
263
|
+
actual_complexity=1
|
|
264
|
+
assessment="much_simpler"
|
|
265
|
+
skip_stages='["compound_quality","review"]'
|
|
266
|
+
# Harder than expected: large diff, multiple self-heal cycles
|
|
267
|
+
elif [[ "$lines_changed" -gt 500 || "$self_heal_cycles" -gt 2 ]]; then
|
|
268
|
+
actual_complexity=$((initial_complexity < 9 ? initial_complexity + 2 : 10))
|
|
269
|
+
assessment="harder_than_expected"
|
|
270
|
+
# Ensure compound_quality runs, possibly upgrade model
|
|
271
|
+
skip_stages='[]'
|
|
272
|
+
# Much harder
|
|
273
|
+
elif [[ "$lines_changed" -gt 1000 || "$self_heal_cycles" -gt 4 ]]; then
|
|
274
|
+
actual_complexity=10
|
|
275
|
+
assessment="much_harder"
|
|
276
|
+
skip_stages='[]'
|
|
277
|
+
fi
|
|
278
|
+
|
|
279
|
+
# ── Write reassessment ──
|
|
280
|
+
local tmp_reassess
|
|
281
|
+
tmp_reassess="$(mktemp)"
|
|
282
|
+
jq -n \
|
|
283
|
+
--argjson initial "$initial_complexity" \
|
|
284
|
+
--argjson actual "$actual_complexity" \
|
|
285
|
+
--arg assessment "$assessment" \
|
|
286
|
+
--argjson files_changed "$files_changed" \
|
|
287
|
+
--argjson lines_changed "$lines_changed" \
|
|
288
|
+
--argjson self_heal_cycles "$self_heal_cycles" \
|
|
289
|
+
--argjson first_try "$first_try_pass" \
|
|
290
|
+
--argjson skip_stages "$skip_stages" \
|
|
291
|
+
'{
|
|
292
|
+
initial_complexity: $initial,
|
|
293
|
+
actual_complexity: $actual,
|
|
294
|
+
assessment: $assessment,
|
|
295
|
+
files_changed: $files_changed,
|
|
296
|
+
lines_changed: $lines_changed,
|
|
297
|
+
self_heal_cycles: $self_heal_cycles,
|
|
298
|
+
first_try_pass: $first_try,
|
|
299
|
+
skip_stages: $skip_stages
|
|
300
|
+
}' > "$tmp_reassess" 2>/dev/null && mv "$tmp_reassess" "$reassessment_file" || rm -f "$tmp_reassess"
|
|
301
|
+
|
|
302
|
+
# Update global complexity for downstream stages
|
|
303
|
+
PIPELINE_ADAPTIVE_COMPLEXITY="$actual_complexity"
|
|
304
|
+
|
|
305
|
+
emit_event "intelligence.reassessment" \
|
|
306
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
307
|
+
"initial=$initial_complexity" \
|
|
308
|
+
"actual=$actual_complexity" \
|
|
309
|
+
"assessment=$assessment" \
|
|
310
|
+
"files=$files_changed" \
|
|
311
|
+
"lines=$lines_changed" \
|
|
312
|
+
"self_heals=$self_heal_cycles"
|
|
313
|
+
|
|
314
|
+
# ── Store for learning ──
|
|
315
|
+
local learning_file="${HOME}/.shipwright/optimization/complexity-actuals.jsonl"
|
|
316
|
+
mkdir -p "${HOME}/.shipwright/optimization" 2>/dev/null || true
|
|
317
|
+
echo "{\"issue\":\"${ISSUE_NUMBER:-0}\",\"initial\":$initial_complexity,\"actual\":$actual_complexity,\"files\":$files_changed,\"lines\":$lines_changed,\"ts\":\"$(now_iso)\"}" \
|
|
318
|
+
>> "$learning_file" 2>/dev/null || true
|
|
319
|
+
|
|
320
|
+
echo "$assessment"
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
324
|
+
# 5. Backtracking Support
|
|
325
|
+
# When compound_quality detects architecture-level problems, backtracks to
|
|
326
|
+
# the design stage instead of just feeding findings to the build loop.
|
|
327
|
+
|
|
328
|
+
pipeline_backtrack_to_stage() {
|
|
329
|
+
local target_stage="$1"
|
|
330
|
+
local reason="${2:-architecture_violation}"
|
|
331
|
+
|
|
332
|
+
# Prevent infinite backtracking
|
|
333
|
+
if [[ "$PIPELINE_BACKTRACK_COUNT" -ge "$PIPELINE_MAX_BACKTRACKS" ]]; then
|
|
334
|
+
warn "Max backtracks ($PIPELINE_MAX_BACKTRACKS) reached — cannot backtrack to $target_stage"
|
|
335
|
+
emit_event "intelligence.backtrack_blocked" \
|
|
336
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
337
|
+
"target=$target_stage" \
|
|
338
|
+
"reason=max_backtracks_reached" \
|
|
339
|
+
"count=$PIPELINE_BACKTRACK_COUNT"
|
|
340
|
+
return 1
|
|
341
|
+
fi
|
|
342
|
+
|
|
343
|
+
PIPELINE_BACKTRACK_COUNT=$((PIPELINE_BACKTRACK_COUNT + 1))
|
|
344
|
+
|
|
345
|
+
info "Backtracking to ${BOLD}${target_stage}${RESET} stage (reason: ${reason})"
|
|
346
|
+
|
|
347
|
+
emit_event "intelligence.backtrack" \
|
|
348
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
349
|
+
"target=$target_stage" \
|
|
350
|
+
"reason=$reason"
|
|
351
|
+
|
|
352
|
+
# Gather architecture context from findings
|
|
353
|
+
local arch_context=""
|
|
354
|
+
if [[ -f "$ARTIFACTS_DIR/compound-architecture-validation.json" ]]; then
|
|
355
|
+
arch_context=$(jq -r '[.[] | select(.severity == "critical" or .severity == "high") | .message // .description // ""] | join("\n")' \
|
|
356
|
+
"$ARTIFACTS_DIR/compound-architecture-validation.json" 2>/dev/null || true)
|
|
357
|
+
fi
|
|
358
|
+
if [[ -f "$ARTIFACTS_DIR/adversarial-review.md" ]]; then
|
|
359
|
+
local arch_lines
|
|
360
|
+
arch_lines=$(grep -iE 'architect|layer.*violation|circular.*depend|coupling|design.*flaw' \
|
|
361
|
+
"$ARTIFACTS_DIR/adversarial-review.md" 2>/dev/null || true)
|
|
362
|
+
if [[ -n "$arch_lines" ]]; then
|
|
363
|
+
arch_context="${arch_context}
|
|
364
|
+
${arch_lines}"
|
|
365
|
+
fi
|
|
366
|
+
fi
|
|
367
|
+
|
|
368
|
+
# Reset stages from target onward
|
|
369
|
+
set_stage_status "$target_stage" "pending"
|
|
370
|
+
set_stage_status "build" "pending"
|
|
371
|
+
set_stage_status "test" "pending"
|
|
372
|
+
|
|
373
|
+
# Augment goal with architecture context for re-run
|
|
374
|
+
local original_goal="$GOAL"
|
|
375
|
+
if [[ -n "$arch_context" ]]; then
|
|
376
|
+
GOAL="$GOAL
|
|
377
|
+
|
|
378
|
+
IMPORTANT — Architecture violations were detected during quality review. Redesign to fix:
|
|
379
|
+
$arch_context
|
|
380
|
+
|
|
381
|
+
Update the design to address these violations, then rebuild."
|
|
382
|
+
fi
|
|
383
|
+
|
|
384
|
+
# Re-run design stage
|
|
385
|
+
info "Re-running ${BOLD}${target_stage}${RESET} with architecture context..."
|
|
386
|
+
if "stage_${target_stage}" 2>/dev/null; then
|
|
387
|
+
mark_stage_complete "$target_stage"
|
|
388
|
+
success "Backtrack: ${target_stage} re-run complete"
|
|
389
|
+
else
|
|
390
|
+
GOAL="$original_goal"
|
|
391
|
+
error "Backtrack: ${target_stage} re-run failed"
|
|
392
|
+
return 1
|
|
393
|
+
fi
|
|
394
|
+
|
|
395
|
+
# Re-run build+test
|
|
396
|
+
info "Re-running build→test after backtracked ${target_stage}..."
|
|
397
|
+
if self_healing_build_test; then
|
|
398
|
+
success "Backtrack: build→test passed after ${target_stage} redesign"
|
|
399
|
+
GOAL="$original_goal"
|
|
400
|
+
return 0
|
|
401
|
+
else
|
|
402
|
+
GOAL="$original_goal"
|
|
403
|
+
error "Backtrack: build→test failed after ${target_stage} redesign"
|
|
404
|
+
return 1
|
|
405
|
+
fi
|
|
406
|
+
}
|
|
407
|
+
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
# pipeline-intelligence-skip.sh — Intelligence-driven stage skipping and findings classification
|
|
2
|
+
# Source from pipeline-intelligence.sh. Requires ARTIFACTS_DIR, ISSUE_LABELS.
|
|
3
|
+
[[ -n "${_PIPELINE_INTELLIGENCE_SKIP_LOADED:-}" ]] && return 0
|
|
4
|
+
_PIPELINE_INTELLIGENCE_SKIP_LOADED=1
|
|
5
|
+
|
|
6
|
+
# Defaults for variables normally set by sw-pipeline.sh (safe under set -u).
|
|
7
|
+
ARTIFACTS_DIR="${ARTIFACTS_DIR:-.claude/pipeline-artifacts}"
|
|
8
|
+
ISSUE_LABELS="${ISSUE_LABELS:-}"
|
|
9
|
+
INTELLIGENCE_COMPLEXITY="${INTELLIGENCE_COMPLEXITY:-5}"
|
|
10
|
+
BASE_BRANCH="${BASE_BRANCH:-main}"
|
|
11
|
+
|
|
12
|
+
# ─── classify_quality_findings ────────────────────────────────────────────
|
|
13
|
+
# Analyzes adversarial review and other audit artifacts to classify findings.
|
|
14
|
+
# Returns a routing decision (security, performance, architecture, correctness).
|
|
15
|
+
# Creates classified-findings.json with breakdown by category.
|
|
16
|
+
|
|
17
|
+
classify_quality_findings() {
|
|
18
|
+
local adversarial_file="$ARTIFACTS_DIR/adversarial-review.md"
|
|
19
|
+
local security_audit="$ARTIFACTS_DIR/security-audit.log"
|
|
20
|
+
local arch_validation="$ARTIFACTS_DIR/compound-architecture-validation.json"
|
|
21
|
+
local negative_review="$ARTIFACTS_DIR/negative-review.md"
|
|
22
|
+
|
|
23
|
+
# Initialize counts
|
|
24
|
+
local security_count=0
|
|
25
|
+
local performance_count=0
|
|
26
|
+
local arch_count=0
|
|
27
|
+
local testing_count=0
|
|
28
|
+
local correctness_count=0
|
|
29
|
+
local style_count=0
|
|
30
|
+
|
|
31
|
+
# Parse adversarial review
|
|
32
|
+
if [[ -f "$adversarial_file" ]]; then
|
|
33
|
+
# Count security-related findings
|
|
34
|
+
local sec_tmp=0
|
|
35
|
+
sec_tmp=$(grep -ciE 'security|vulnerability|injection|xss|csrf|auth|crypt' "$adversarial_file" 2>/dev/null) || sec_tmp=0
|
|
36
|
+
security_count=$((security_count + sec_tmp))
|
|
37
|
+
|
|
38
|
+
# Count performance findings
|
|
39
|
+
local perf_tmp=0
|
|
40
|
+
perf_tmp=$(grep -ciE 'performance|bottleneck|n\+1|memory|leak|slow|timeout|hang' "$adversarial_file" 2>/dev/null) || perf_tmp=0
|
|
41
|
+
performance_count=$((performance_count + perf_tmp))
|
|
42
|
+
|
|
43
|
+
# Count architecture findings
|
|
44
|
+
local arch_tmp=0
|
|
45
|
+
arch_tmp=$(grep -ciE 'architecture|circular|dependency|coupling|layer|module|violation' "$adversarial_file" 2>/dev/null) || arch_tmp=0
|
|
46
|
+
arch_count=$((arch_count + arch_tmp))
|
|
47
|
+
|
|
48
|
+
# Count testing findings
|
|
49
|
+
local testing_tmp=0
|
|
50
|
+
testing_tmp=$(grep -ciE 'test|coverage|flaky|mock|assertion|stub' "$adversarial_file" 2>/dev/null) || testing_tmp=0
|
|
51
|
+
testing_count=$((testing_count + testing_tmp))
|
|
52
|
+
|
|
53
|
+
# Count correctness findings
|
|
54
|
+
local correct_tmp=0
|
|
55
|
+
correct_tmp=$(grep -ciE 'bug|logic|error|broken|fail' "$adversarial_file" 2>/dev/null) || correct_tmp=0
|
|
56
|
+
correctness_count=$((correctness_count + correct_tmp))
|
|
57
|
+
|
|
58
|
+
# Count style findings
|
|
59
|
+
local style_tmp=0
|
|
60
|
+
style_tmp=$(grep -ciE 'style|convention|naming|format|whitespace|comment' "$adversarial_file" 2>/dev/null) || style_tmp=0
|
|
61
|
+
style_count=$((style_count + style_tmp))
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
# Parse security audit if present
|
|
65
|
+
if [[ -f "$security_audit" ]]; then
|
|
66
|
+
local sec_audit_findings=0
|
|
67
|
+
sec_audit_findings=$(grep -ciE 'critical|high|vulnerability' "$security_audit" 2>/dev/null) || sec_audit_findings=0
|
|
68
|
+
security_count=$((security_count + sec_audit_findings))
|
|
69
|
+
fi
|
|
70
|
+
|
|
71
|
+
# Parse architecture validation JSON if present
|
|
72
|
+
if [[ -f "$arch_validation" ]]; then
|
|
73
|
+
local arch_json_count=0
|
|
74
|
+
arch_json_count=$(jq '[.[] | select(.severity == "critical" or .severity == "high")] | length' "$arch_validation" 2>/dev/null) || arch_json_count=0
|
|
75
|
+
arch_count=$((arch_count + arch_json_count))
|
|
76
|
+
fi
|
|
77
|
+
|
|
78
|
+
# Parse negative review
|
|
79
|
+
if [[ -f "$negative_review" ]]; then
|
|
80
|
+
local neg_critical=0
|
|
81
|
+
neg_critical=$(grep -ciE '\[Critical\]' "$negative_review" 2>/dev/null) || neg_critical=0
|
|
82
|
+
correctness_count=$((correctness_count + neg_critical))
|
|
83
|
+
|
|
84
|
+
local neg_security=0
|
|
85
|
+
neg_security=$(grep -ciE 'security|vulnerability' "$negative_review" 2>/dev/null) || neg_security=0
|
|
86
|
+
security_count=$((security_count + neg_security))
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# Create classified findings JSON (safely, handling jq failure)
|
|
90
|
+
local tmp_findings
|
|
91
|
+
tmp_findings=$(mktemp)
|
|
92
|
+
{
|
|
93
|
+
echo "{"
|
|
94
|
+
echo " \"security\": $security_count,"
|
|
95
|
+
echo " \"performance\": $performance_count,"
|
|
96
|
+
echo " \"architecture\": $arch_count,"
|
|
97
|
+
echo " \"testing\": $testing_count,"
|
|
98
|
+
echo " \"correctness\": $correctness_count,"
|
|
99
|
+
echo " \"style\": $style_count"
|
|
100
|
+
echo "}"
|
|
101
|
+
} > "$tmp_findings"
|
|
102
|
+
mv "$tmp_findings" "$ARTIFACTS_DIR/classified-findings.json" 2>/dev/null || rm -f "$tmp_findings"
|
|
103
|
+
|
|
104
|
+
# Determine routing based on severity
|
|
105
|
+
if [[ "$security_count" -gt 0 ]]; then
|
|
106
|
+
echo "security"
|
|
107
|
+
elif [[ "$performance_count" -gt 0 ]]; then
|
|
108
|
+
echo "performance"
|
|
109
|
+
elif [[ "$arch_count" -gt 0 ]]; then
|
|
110
|
+
echo "architecture"
|
|
111
|
+
elif [[ "$testing_count" -gt 0 ]]; then
|
|
112
|
+
echo "testing"
|
|
113
|
+
elif [[ "$correctness_count" -gt 0 ]]; then
|
|
114
|
+
echo "correctness"
|
|
115
|
+
else
|
|
116
|
+
echo "correctness"
|
|
117
|
+
fi
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
# ─── pipeline_should_skip_stage ────────────────────────────────────────
|
|
121
|
+
# Determines if a pipeline stage should be skipped based on:
|
|
122
|
+
# - Issue labels (documentation, hotfix, etc.)
|
|
123
|
+
# - Complexity assessment
|
|
124
|
+
# - Reassessment overrides
|
|
125
|
+
|
|
126
|
+
pipeline_should_skip_stage() {
|
|
127
|
+
local stage="$1"
|
|
128
|
+
|
|
129
|
+
# Check for skip overrides in reassessment
|
|
130
|
+
local reassessment_file="$ARTIFACTS_DIR/reassessment.json"
|
|
131
|
+
if [[ -f "$reassessment_file" ]]; then
|
|
132
|
+
# Validate JSON before parsing to prevent jq errors
|
|
133
|
+
if ! jq empty "$reassessment_file" 2>/dev/null; then
|
|
134
|
+
# File exists but is not valid JSON — skip it
|
|
135
|
+
return 1
|
|
136
|
+
fi
|
|
137
|
+
local skip_stages
|
|
138
|
+
skip_stages=$(jq -r '.skip_stages[]?' "$reassessment_file" 2>/dev/null) || true
|
|
139
|
+
while IFS= read -r skip_stage; do
|
|
140
|
+
[[ -z "$skip_stage" ]] && continue
|
|
141
|
+
[[ "$skip_stage" == "$stage" ]] && echo "reassessment" && return 0
|
|
142
|
+
done <<< "$skip_stages"
|
|
143
|
+
fi
|
|
144
|
+
|
|
145
|
+
# Check labels for skip signals
|
|
146
|
+
case "$stage" in
|
|
147
|
+
compound_quality)
|
|
148
|
+
if echo "$ISSUE_LABELS" | grep -qiE 'documentation|typo|docs'; then
|
|
149
|
+
echo "label:documentation"
|
|
150
|
+
return 0
|
|
151
|
+
fi
|
|
152
|
+
if echo "$ISSUE_LABELS" | grep -qiE 'hotfix|urgent'; then
|
|
153
|
+
echo "label:hotfix"
|
|
154
|
+
return 0
|
|
155
|
+
fi
|
|
156
|
+
;;
|
|
157
|
+
design)
|
|
158
|
+
# Low complexity skips design
|
|
159
|
+
if [[ "${INTELLIGENCE_COMPLEXITY:-5}" -lt 3 ]]; then
|
|
160
|
+
echo "complexity"
|
|
161
|
+
return 0
|
|
162
|
+
fi
|
|
163
|
+
;;
|
|
164
|
+
review)
|
|
165
|
+
# Documentation labels skip review
|
|
166
|
+
if echo "$ISSUE_LABELS" | grep -qiE 'docs?|documentation'; then
|
|
167
|
+
echo "label"
|
|
168
|
+
return 0
|
|
169
|
+
fi
|
|
170
|
+
;;
|
|
171
|
+
plan)
|
|
172
|
+
# Hotfix labels skip plan
|
|
173
|
+
if echo "$ISSUE_LABELS" | grep -qiE 'hotfix|p0|urgent'; then
|
|
174
|
+
echo "label:hotfix"
|
|
175
|
+
return 0
|
|
176
|
+
fi
|
|
177
|
+
;;
|
|
178
|
+
esac
|
|
179
|
+
|
|
180
|
+
return 1
|
|
181
|
+
}
|