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
|
@@ -3,6 +3,28 @@
|
|
|
3
3
|
[[ -n "${_PIPELINE_GITHUB_LOADED:-}" ]] && return 0
|
|
4
4
|
_PIPELINE_GITHUB_LOADED=1
|
|
5
5
|
|
|
6
|
+
# Defaults for variables normally set by sw-pipeline.sh (safe under set -u).
|
|
7
|
+
NO_GITHUB="${NO_GITHUB:-false}"
|
|
8
|
+
GOAL="${GOAL:-}"
|
|
9
|
+
PIPELINE_NAME="${PIPELINE_NAME:-pipeline}"
|
|
10
|
+
PIPELINE_CONFIG="${PIPELINE_CONFIG:-}"
|
|
11
|
+
GIT_BRANCH="${GIT_BRANCH:-}"
|
|
12
|
+
PIPELINE_START_EPOCH="${PIPELINE_START_EPOCH:-}"
|
|
13
|
+
ARTIFACTS_DIR="${ARTIFACTS_DIR:-.claude/pipeline-artifacts}"
|
|
14
|
+
GH_AVAILABLE="${GH_AVAILABLE:-false}"
|
|
15
|
+
REPO_OWNER="${REPO_OWNER:-}"
|
|
16
|
+
REPO_NAME="${REPO_NAME:-}"
|
|
17
|
+
PROGRESS_COMMENT_ID="${PROGRESS_COMMENT_ID:-}"
|
|
18
|
+
|
|
19
|
+
# ─── Markdown Escaping ───────────────────────────────────────────────
|
|
20
|
+
# Escape markdown special characters to prevent injection
|
|
21
|
+
escape_markdown() {
|
|
22
|
+
local text="$1"
|
|
23
|
+
# Escape ], [, (, ), *, _, \, `, #, -, +, .
|
|
24
|
+
# This prevents markdown syntax injection in GitHub comments
|
|
25
|
+
echo "$text" | sed 's/\([\\`*_\[\]()#+\-\.!]\)/\\\1/g'
|
|
26
|
+
}
|
|
27
|
+
|
|
6
28
|
gh_init() {
|
|
7
29
|
if [[ "$NO_GITHUB" == "true" ]]; then
|
|
8
30
|
GH_AVAILABLE=false
|
|
@@ -107,9 +129,12 @@ gh_get_issue_meta() {
|
|
|
107
129
|
# Build a progress table for GitHub comment
|
|
108
130
|
# Usage: gh_build_progress_body
|
|
109
131
|
gh_build_progress_body() {
|
|
132
|
+
local escaped_goal
|
|
133
|
+
escaped_goal=$(escape_markdown "${GOAL}")
|
|
134
|
+
|
|
110
135
|
local body="## 🤖 Pipeline Progress — \`${PIPELINE_NAME}\`
|
|
111
136
|
|
|
112
|
-
**Delivering:** ${
|
|
137
|
+
**Delivering:** ${escaped_goal}
|
|
113
138
|
|
|
114
139
|
| Stage | Status | Duration | |
|
|
115
140
|
|-------|--------|----------|-|"
|
|
@@ -118,8 +143,8 @@ gh_build_progress_body() {
|
|
|
118
143
|
stages=$(jq -c '.stages[]' "$PIPELINE_CONFIG" 2>/dev/null)
|
|
119
144
|
while IFS= read -r -u 3 stage; do
|
|
120
145
|
local id enabled
|
|
121
|
-
id=$(echo "$stage" | jq -r '.id')
|
|
122
|
-
enabled=$(echo "$stage" | jq -r '.enabled')
|
|
146
|
+
id=$(echo "$stage" | jq -r '.id' 2>/dev/null) || id=""
|
|
147
|
+
enabled=$(echo "$stage" | jq -r '.enabled' 2>/dev/null) || enabled=""
|
|
123
148
|
|
|
124
149
|
if [[ "$enabled" != "true" ]]; then
|
|
125
150
|
body="${body}
|
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
# pipeline-intelligence-compound.sh — DoD/security/compound audit for pipeline-intelligence.sh
|
|
2
|
+
# Source from pipeline-intelligence.sh. Requires state, ARTIFACTS_DIR.
|
|
3
|
+
[[ -n "${_PIPELINE_INTELLIGENCE_COMPOUND_LOADED:-}" ]] && return 0
|
|
4
|
+
_PIPELINE_INTELLIGENCE_COMPOUND_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]}")/.."/bin/pwd)}"
|
|
9
|
+
NO_GITHUB="${NO_GITHUB:-false}"
|
|
10
|
+
|
|
11
|
+
pipeline_verify_dod() {
|
|
12
|
+
local artifacts_dir="${1:-$ARTIFACTS_DIR}"
|
|
13
|
+
local checks_total=0 checks_passed=0
|
|
14
|
+
local results=""
|
|
15
|
+
|
|
16
|
+
# 1. Test coverage: verify changed source files have test counterparts
|
|
17
|
+
local changed_files
|
|
18
|
+
changed_files=$(git diff --name-only "${BASE_BRANCH:-main}...HEAD" 2>/dev/null || true)
|
|
19
|
+
local missing_tests=""
|
|
20
|
+
local files_checked=0
|
|
21
|
+
|
|
22
|
+
if [[ -n "$changed_files" ]]; then
|
|
23
|
+
while IFS= read -r src_file; do
|
|
24
|
+
[[ -z "$src_file" ]] && continue
|
|
25
|
+
# Only check source code files
|
|
26
|
+
case "$src_file" in
|
|
27
|
+
*.ts|*.js|*.tsx|*.jsx|*.py|*.go|*.rs|*.sh)
|
|
28
|
+
# Skip test files themselves and config files
|
|
29
|
+
case "$src_file" in
|
|
30
|
+
*test*|*spec*|*__tests__*|*.config.*|*.d.ts) continue ;;
|
|
31
|
+
esac
|
|
32
|
+
files_checked=$((files_checked + 1))
|
|
33
|
+
checks_total=$((checks_total + 1))
|
|
34
|
+
# Check for corresponding test file
|
|
35
|
+
local base_name dir_name ext
|
|
36
|
+
base_name=$(basename "$src_file")
|
|
37
|
+
dir_name=$(dirname "$src_file")
|
|
38
|
+
ext="${base_name##*.}"
|
|
39
|
+
local stem="${base_name%.*}"
|
|
40
|
+
local test_found=false
|
|
41
|
+
# Common test file patterns
|
|
42
|
+
for pattern in \
|
|
43
|
+
"${dir_name}/${stem}.test.${ext}" \
|
|
44
|
+
"${dir_name}/${stem}.spec.${ext}" \
|
|
45
|
+
"${dir_name}/__tests__/${stem}.test.${ext}" \
|
|
46
|
+
"${dir_name}/${stem}-test.${ext}" \
|
|
47
|
+
"${dir_name}/test_${stem}.${ext}" \
|
|
48
|
+
"${dir_name}/${stem}_test.${ext}"; do
|
|
49
|
+
if [[ -f "$pattern" ]]; then
|
|
50
|
+
test_found=true
|
|
51
|
+
break
|
|
52
|
+
fi
|
|
53
|
+
done
|
|
54
|
+
if $test_found; then
|
|
55
|
+
checks_passed=$((checks_passed + 1))
|
|
56
|
+
else
|
|
57
|
+
missing_tests="${missing_tests}${src_file}\n"
|
|
58
|
+
fi
|
|
59
|
+
;;
|
|
60
|
+
esac
|
|
61
|
+
done <<EOF
|
|
62
|
+
$changed_files
|
|
63
|
+
EOF
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# 2. Test-added verification: if significant logic added, ensure tests were also added
|
|
67
|
+
local logic_lines=0 test_lines=0
|
|
68
|
+
if [[ -n "$changed_files" ]]; then
|
|
69
|
+
local full_diff
|
|
70
|
+
full_diff=$(git diff "${BASE_BRANCH:-main}...HEAD" 2>/dev/null || true)
|
|
71
|
+
if [[ -n "$full_diff" ]]; then
|
|
72
|
+
# Count added lines matching source patterns (rough heuristic)
|
|
73
|
+
logic_lines=$(echo "$full_diff" | grep -cE '^\+.*(function |class |if |for |while |return |export )' 2>/dev/null || true)
|
|
74
|
+
logic_lines="${logic_lines:-0}"
|
|
75
|
+
# Count added lines in test files
|
|
76
|
+
test_lines=$(echo "$full_diff" | grep -cE '^\+.*(it\(|test\(|describe\(|expect\(|assert|def test_|func Test)' 2>/dev/null || true)
|
|
77
|
+
test_lines="${test_lines:-0}"
|
|
78
|
+
fi
|
|
79
|
+
fi
|
|
80
|
+
checks_total=$((checks_total + 1))
|
|
81
|
+
local test_ratio_passed=true
|
|
82
|
+
if [[ "$logic_lines" -gt 20 && "$test_lines" -eq 0 ]]; then
|
|
83
|
+
test_ratio_passed=false
|
|
84
|
+
warn "DoD verification: ${logic_lines} logic lines added but no test lines detected"
|
|
85
|
+
else
|
|
86
|
+
checks_passed=$((checks_passed + 1))
|
|
87
|
+
fi
|
|
88
|
+
|
|
89
|
+
# 3. Behavioral verification: check DoD audit artifacts for evidence
|
|
90
|
+
local dod_audit_file="$artifacts_dir/dod-audit.md"
|
|
91
|
+
local dod_verified=0 dod_total_items=0
|
|
92
|
+
if [[ -f "$dod_audit_file" ]]; then
|
|
93
|
+
# Count items marked as passing
|
|
94
|
+
dod_total_items=$(grep -cE '^\s*-\s*\[x\]' "$dod_audit_file" 2>/dev/null || true)
|
|
95
|
+
dod_total_items="${dod_total_items:-0}"
|
|
96
|
+
local dod_failing
|
|
97
|
+
dod_failing=$(grep -cE '^\s*-\s*\[\s\]' "$dod_audit_file" 2>/dev/null || true)
|
|
98
|
+
dod_failing="${dod_failing:-0}"
|
|
99
|
+
dod_verified=$dod_total_items
|
|
100
|
+
checks_total=$((checks_total + dod_total_items + ${dod_failing:-0}))
|
|
101
|
+
checks_passed=$((checks_passed + dod_total_items))
|
|
102
|
+
fi
|
|
103
|
+
|
|
104
|
+
# Compute pass rate
|
|
105
|
+
local pass_rate=100
|
|
106
|
+
if [[ "$checks_total" -gt 0 ]]; then
|
|
107
|
+
pass_rate=$(( (checks_passed * 100) / checks_total ))
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
# Write results
|
|
111
|
+
local tmp_result
|
|
112
|
+
tmp_result=$(mktemp)
|
|
113
|
+
jq -n \
|
|
114
|
+
--argjson checks_total "$checks_total" \
|
|
115
|
+
--argjson checks_passed "$checks_passed" \
|
|
116
|
+
--argjson pass_rate "$pass_rate" \
|
|
117
|
+
--argjson files_checked "$files_checked" \
|
|
118
|
+
--arg missing_tests "$(echo -e "$missing_tests" | head -20)" \
|
|
119
|
+
--argjson logic_lines "$logic_lines" \
|
|
120
|
+
--argjson test_lines "$test_lines" \
|
|
121
|
+
--argjson test_ratio_passed "$test_ratio_passed" \
|
|
122
|
+
--argjson dod_verified "$dod_verified" \
|
|
123
|
+
'{
|
|
124
|
+
checks_total: $checks_total,
|
|
125
|
+
checks_passed: $checks_passed,
|
|
126
|
+
pass_rate: $pass_rate,
|
|
127
|
+
files_checked: $files_checked,
|
|
128
|
+
missing_tests: ($missing_tests | split("\n") | map(select(. != ""))),
|
|
129
|
+
logic_lines: $logic_lines,
|
|
130
|
+
test_lines: $test_lines,
|
|
131
|
+
test_ratio_passed: $test_ratio_passed,
|
|
132
|
+
dod_verified: $dod_verified
|
|
133
|
+
}' > "$tmp_result" 2>/dev/null
|
|
134
|
+
mv "$tmp_result" "$artifacts_dir/dod-verification.json"
|
|
135
|
+
|
|
136
|
+
emit_event "pipeline.dod_verification" \
|
|
137
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
138
|
+
"checks_total=$checks_total" \
|
|
139
|
+
"checks_passed=$checks_passed" \
|
|
140
|
+
"pass_rate=$pass_rate"
|
|
141
|
+
|
|
142
|
+
# Fail if pass rate < 70%
|
|
143
|
+
if [[ "$pass_rate" -lt 70 ]]; then
|
|
144
|
+
warn "DoD verification: ${pass_rate}% pass rate (${checks_passed}/${checks_total} checks)"
|
|
145
|
+
return 1
|
|
146
|
+
fi
|
|
147
|
+
|
|
148
|
+
success "DoD verification: ${pass_rate}% pass rate (${checks_passed}/${checks_total} checks)"
|
|
149
|
+
return 0
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
153
|
+
# 7. Source Code Security Scan
|
|
154
|
+
# Grep-based vulnerability pattern matching on changed files.
|
|
155
|
+
|
|
156
|
+
pipeline_security_source_scan() {
|
|
157
|
+
local base_branch="${1:-${BASE_BRANCH:-main}}"
|
|
158
|
+
local findings="[]"
|
|
159
|
+
local finding_count=0
|
|
160
|
+
|
|
161
|
+
local changed_files
|
|
162
|
+
changed_files=$(git diff --name-only "${base_branch}...HEAD" 2>/dev/null || true)
|
|
163
|
+
[[ -z "$changed_files" ]] && { echo "[]"; return 0; }
|
|
164
|
+
|
|
165
|
+
local tmp_findings
|
|
166
|
+
tmp_findings=$(mktemp)
|
|
167
|
+
echo "[]" > "$tmp_findings"
|
|
168
|
+
|
|
169
|
+
while IFS= read -r file; do
|
|
170
|
+
[[ -z "$file" || ! -f "$file" ]] && continue
|
|
171
|
+
# Only scan code files
|
|
172
|
+
case "$file" in
|
|
173
|
+
*.ts|*.js|*.tsx|*.jsx|*.py|*.go|*.rs|*.java|*.rb|*.php|*.sh) ;;
|
|
174
|
+
*) continue ;;
|
|
175
|
+
esac
|
|
176
|
+
|
|
177
|
+
# SQL injection patterns
|
|
178
|
+
local sql_matches
|
|
179
|
+
sql_matches=$(grep -nE '(query|execute|sql)\s*\(?\s*[`"'"'"']\s*.*\$\{|\.query\s*\(\s*[`"'"'"'].*\+' "$file" 2>/dev/null || true)
|
|
180
|
+
if [[ -n "$sql_matches" ]]; then
|
|
181
|
+
while IFS= read -r match; do
|
|
182
|
+
[[ -z "$match" ]] && continue
|
|
183
|
+
local line_num="${match%%:*}"
|
|
184
|
+
finding_count=$((finding_count + 1))
|
|
185
|
+
local current
|
|
186
|
+
current=$(cat "$tmp_findings")
|
|
187
|
+
echo "$current" | jq --arg f "$file" --arg l "$line_num" --arg p "sql_injection" \
|
|
188
|
+
'. + [{"file":$f,"line":($l|tonumber),"pattern":$p,"severity":"critical","description":"Potential SQL injection via string concatenation"}]' \
|
|
189
|
+
> "$tmp_findings" 2>/dev/null || true
|
|
190
|
+
done <<SQLEOF
|
|
191
|
+
$sql_matches
|
|
192
|
+
SQLEOF
|
|
193
|
+
fi
|
|
194
|
+
|
|
195
|
+
# XSS patterns
|
|
196
|
+
local xss_matches
|
|
197
|
+
xss_matches=$(grep -nE 'innerHTML\s*=|document\.write\s*\(|dangerouslySetInnerHTML' "$file" 2>/dev/null || true)
|
|
198
|
+
if [[ -n "$xss_matches" ]]; then
|
|
199
|
+
while IFS= read -r match; do
|
|
200
|
+
[[ -z "$match" ]] && continue
|
|
201
|
+
local line_num="${match%%:*}"
|
|
202
|
+
finding_count=$((finding_count + 1))
|
|
203
|
+
local current
|
|
204
|
+
current=$(cat "$tmp_findings")
|
|
205
|
+
echo "$current" | jq --arg f "$file" --arg l "$line_num" --arg p "xss" \
|
|
206
|
+
'. + [{"file":$f,"line":($l|tonumber),"pattern":$p,"severity":"critical","description":"Potential XSS via unsafe DOM manipulation"}]' \
|
|
207
|
+
> "$tmp_findings" 2>/dev/null || true
|
|
208
|
+
done <<XSSEOF
|
|
209
|
+
$xss_matches
|
|
210
|
+
XSSEOF
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
# Command injection patterns
|
|
214
|
+
local cmd_matches
|
|
215
|
+
cmd_matches=$(grep -nE 'eval\s*\(|child_process|os\.system\s*\(|subprocess\.(call|run|Popen)\s*\(' "$file" 2>/dev/null || true)
|
|
216
|
+
if [[ -n "$cmd_matches" ]]; then
|
|
217
|
+
while IFS= read -r match; do
|
|
218
|
+
[[ -z "$match" ]] && continue
|
|
219
|
+
local line_num="${match%%:*}"
|
|
220
|
+
finding_count=$((finding_count + 1))
|
|
221
|
+
local current
|
|
222
|
+
current=$(cat "$tmp_findings")
|
|
223
|
+
echo "$current" | jq --arg f "$file" --arg l "$line_num" --arg p "command_injection" \
|
|
224
|
+
'. + [{"file":$f,"line":($l|tonumber),"pattern":$p,"severity":"critical","description":"Potential command injection via unsafe execution"}]' \
|
|
225
|
+
> "$tmp_findings" 2>/dev/null || true
|
|
226
|
+
done <<CMDEOF
|
|
227
|
+
$cmd_matches
|
|
228
|
+
CMDEOF
|
|
229
|
+
fi
|
|
230
|
+
|
|
231
|
+
# Hardcoded secrets patterns
|
|
232
|
+
local secret_matches
|
|
233
|
+
secret_matches=$(grep -nEi '(password|api_key|secret|token)\s*=\s*['"'"'"][A-Za-z0-9+/=]{8,}['"'"'"]' "$file" 2>/dev/null || true)
|
|
234
|
+
if [[ -n "$secret_matches" ]]; then
|
|
235
|
+
while IFS= read -r match; do
|
|
236
|
+
[[ -z "$match" ]] && continue
|
|
237
|
+
local line_num="${match%%:*}"
|
|
238
|
+
finding_count=$((finding_count + 1))
|
|
239
|
+
local current
|
|
240
|
+
current=$(cat "$tmp_findings")
|
|
241
|
+
echo "$current" | jq --arg f "$file" --arg l "$line_num" --arg p "hardcoded_secret" \
|
|
242
|
+
'. + [{"file":$f,"line":($l|tonumber),"pattern":$p,"severity":"critical","description":"Potential hardcoded secret or credential"}]' \
|
|
243
|
+
> "$tmp_findings" 2>/dev/null || true
|
|
244
|
+
done <<SECEOF
|
|
245
|
+
$secret_matches
|
|
246
|
+
SECEOF
|
|
247
|
+
fi
|
|
248
|
+
|
|
249
|
+
# Insecure crypto patterns
|
|
250
|
+
local crypto_matches
|
|
251
|
+
crypto_matches=$(grep -nE '(md5|MD5|sha1|SHA1)\s*\(' "$file" 2>/dev/null || true)
|
|
252
|
+
if [[ -n "$crypto_matches" ]]; then
|
|
253
|
+
while IFS= read -r match; do
|
|
254
|
+
[[ -z "$match" ]] && continue
|
|
255
|
+
local line_num="${match%%:*}"
|
|
256
|
+
finding_count=$((finding_count + 1))
|
|
257
|
+
local current
|
|
258
|
+
current=$(cat "$tmp_findings")
|
|
259
|
+
echo "$current" | jq --arg f "$file" --arg l "$line_num" --arg p "insecure_crypto" \
|
|
260
|
+
'. + [{"file":$f,"line":($l|tonumber),"pattern":$p,"severity":"major","description":"Weak cryptographic function (consider SHA-256+)"}]' \
|
|
261
|
+
> "$tmp_findings" 2>/dev/null || true
|
|
262
|
+
done <<CRYEOF
|
|
263
|
+
$crypto_matches
|
|
264
|
+
CRYEOF
|
|
265
|
+
fi
|
|
266
|
+
done <<FILESEOF
|
|
267
|
+
$changed_files
|
|
268
|
+
FILESEOF
|
|
269
|
+
|
|
270
|
+
# Write to artifacts and output
|
|
271
|
+
findings=$(cat "$tmp_findings")
|
|
272
|
+
rm -f "$tmp_findings"
|
|
273
|
+
|
|
274
|
+
if [[ -n "${ARTIFACTS_DIR:-}" ]]; then
|
|
275
|
+
local tmp_scan
|
|
276
|
+
tmp_scan=$(mktemp)
|
|
277
|
+
echo "$findings" > "$tmp_scan"
|
|
278
|
+
mv "$tmp_scan" "$ARTIFACTS_DIR/security-source-scan.json"
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
emit_event "pipeline.security_source_scan" \
|
|
282
|
+
"issue=${ISSUE_NUMBER:-0}" \
|
|
283
|
+
"findings=$finding_count"
|
|
284
|
+
|
|
285
|
+
echo "$finding_count"
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
# ──────────────────────────────────────────────────────────────────────────────
|
|
289
|
+
# 8. Quality Score Recording
|
|
290
|
+
# Writes quality scores to JSONL for learning.
|
|
291
|
+
|
|
292
|
+
compound_rebuild_with_feedback() {
|
|
293
|
+
local feedback_file="$ARTIFACTS_DIR/quality-feedback.md"
|
|
294
|
+
|
|
295
|
+
# ── Intelligence: classify findings and determine routing ──
|
|
296
|
+
local route="correctness"
|
|
297
|
+
route=$(classify_quality_findings 2>/dev/null) || route="correctness"
|
|
298
|
+
|
|
299
|
+
# ── Build structured findings JSON alongside markdown ──
|
|
300
|
+
local structured_findings="[]"
|
|
301
|
+
local s_total_critical=0 s_total_major=0 s_total_minor=0
|
|
302
|
+
|
|
303
|
+
if [[ -f "$ARTIFACTS_DIR/classified-findings.json" ]]; then
|
|
304
|
+
s_total_critical=$(jq -r '.security // 0' "$ARTIFACTS_DIR/classified-findings.json" 2>/dev/null || echo "0")
|
|
305
|
+
s_total_major=$(jq -r '.correctness // 0' "$ARTIFACTS_DIR/classified-findings.json" 2>/dev/null || echo "0")
|
|
306
|
+
s_total_minor=$(jq -r '.style // 0' "$ARTIFACTS_DIR/classified-findings.json" 2>/dev/null || echo "0")
|
|
307
|
+
fi
|
|
308
|
+
|
|
309
|
+
local tmp_qf
|
|
310
|
+
tmp_qf="$(mktemp)"
|
|
311
|
+
jq -n \
|
|
312
|
+
--arg route "$route" \
|
|
313
|
+
--argjson total_critical "$s_total_critical" \
|
|
314
|
+
--argjson total_major "$s_total_major" \
|
|
315
|
+
--argjson total_minor "$s_total_minor" \
|
|
316
|
+
'{route: $route, total_critical: $total_critical, total_major: $total_major, total_minor: $total_minor}' \
|
|
317
|
+
> "$tmp_qf" 2>/dev/null && mv "$tmp_qf" "$ARTIFACTS_DIR/quality-findings.json" || rm -f "$tmp_qf"
|
|
318
|
+
|
|
319
|
+
# ── Architecture route: backtrack to design instead of rebuild ──
|
|
320
|
+
if [[ "$route" == "architecture" ]]; then
|
|
321
|
+
info "Architecture-level findings detected — attempting backtrack to design"
|
|
322
|
+
if pipeline_backtrack_to_stage "design" "architecture_violation" 2>/dev/null; then
|
|
323
|
+
return 0
|
|
324
|
+
fi
|
|
325
|
+
# Backtrack failed or already used — fall through to standard rebuild
|
|
326
|
+
warn "Backtrack unavailable — falling through to standard rebuild"
|
|
327
|
+
fi
|
|
328
|
+
|
|
329
|
+
# Collect all findings (prioritized by classification)
|
|
330
|
+
{
|
|
331
|
+
echo "# Quality Feedback — Issues to Fix"
|
|
332
|
+
echo ""
|
|
333
|
+
|
|
334
|
+
# Security findings first (highest priority)
|
|
335
|
+
if [[ "$route" == "security" || -f "$ARTIFACTS_DIR/security-audit.log" ]] && grep -qiE 'critical|high' "$ARTIFACTS_DIR/security-audit.log" 2>/dev/null; then
|
|
336
|
+
echo "## 🔴 PRIORITY: Security Findings (fix these first)"
|
|
337
|
+
cat "$ARTIFACTS_DIR/security-audit.log"
|
|
338
|
+
echo ""
|
|
339
|
+
echo "Security issues MUST be resolved before any other changes."
|
|
340
|
+
echo ""
|
|
341
|
+
fi
|
|
342
|
+
|
|
343
|
+
# Correctness findings
|
|
344
|
+
if [[ -f "$ARTIFACTS_DIR/adversarial-review.md" ]]; then
|
|
345
|
+
echo "## Adversarial Review Findings"
|
|
346
|
+
cat "$ARTIFACTS_DIR/adversarial-review.md"
|
|
347
|
+
echo ""
|
|
348
|
+
fi
|
|
349
|
+
if [[ -f "$ARTIFACTS_DIR/negative-review.md" ]]; then
|
|
350
|
+
echo "## Negative Prompting Concerns"
|
|
351
|
+
cat "$ARTIFACTS_DIR/negative-review.md"
|
|
352
|
+
echo ""
|
|
353
|
+
fi
|
|
354
|
+
if [[ -f "$ARTIFACTS_DIR/dod-audit.md" ]]; then
|
|
355
|
+
echo "## DoD Audit Failures"
|
|
356
|
+
grep "❌" "$ARTIFACTS_DIR/dod-audit.md" 2>/dev/null || true
|
|
357
|
+
echo ""
|
|
358
|
+
fi
|
|
359
|
+
if [[ -f "$ARTIFACTS_DIR/api-compat.log" ]] && grep -qi 'BREAKING' "$ARTIFACTS_DIR/api-compat.log" 2>/dev/null; then
|
|
360
|
+
echo "## API Breaking Changes"
|
|
361
|
+
cat "$ARTIFACTS_DIR/api-compat.log"
|
|
362
|
+
echo ""
|
|
363
|
+
fi
|
|
364
|
+
|
|
365
|
+
# Style findings last (deprioritized, informational)
|
|
366
|
+
if [[ -f "$ARTIFACTS_DIR/classified-findings.json" ]]; then
|
|
367
|
+
local style_count
|
|
368
|
+
style_count=$(jq -r '.style // 0' "$ARTIFACTS_DIR/classified-findings.json" 2>/dev/null || echo "0")
|
|
369
|
+
if [[ "$style_count" -gt 0 ]]; then
|
|
370
|
+
echo "## Style Notes (non-blocking, address if time permits)"
|
|
371
|
+
echo "${style_count} style suggestions found. These do not block the build."
|
|
372
|
+
echo ""
|
|
373
|
+
fi
|
|
374
|
+
fi
|
|
375
|
+
} > "$feedback_file"
|
|
376
|
+
|
|
377
|
+
# Validate feedback file has actual content
|
|
378
|
+
if [[ ! -s "$feedback_file" ]]; then
|
|
379
|
+
warn "No quality feedback collected — skipping rebuild"
|
|
380
|
+
return 1
|
|
381
|
+
fi
|
|
382
|
+
|
|
383
|
+
# Reset build/test stages
|
|
384
|
+
set_stage_status "build" "pending"
|
|
385
|
+
set_stage_status "test" "pending"
|
|
386
|
+
set_stage_status "review" "pending"
|
|
387
|
+
|
|
388
|
+
# Augment GOAL with quality feedback (route-specific instructions)
|
|
389
|
+
local original_goal="$GOAL"
|
|
390
|
+
local feedback_content
|
|
391
|
+
feedback_content=$(cat "$feedback_file")
|
|
392
|
+
|
|
393
|
+
local route_instruction=""
|
|
394
|
+
case "$route" in
|
|
395
|
+
security)
|
|
396
|
+
route_instruction="SECURITY PRIORITY: Fix all security vulnerabilities FIRST, then address other issues. Security issues are BLOCKING."
|
|
397
|
+
;;
|
|
398
|
+
performance)
|
|
399
|
+
route_instruction="PERFORMANCE PRIORITY: Address performance regressions and optimizations. Check for N+1 queries, memory leaks, and algorithmic complexity."
|
|
400
|
+
;;
|
|
401
|
+
testing)
|
|
402
|
+
route_instruction="TESTING PRIORITY: Add missing test coverage and fix flaky tests before addressing other issues."
|
|
403
|
+
;;
|
|
404
|
+
correctness)
|
|
405
|
+
route_instruction="Fix every issue listed above while keeping all existing functionality working."
|
|
406
|
+
;;
|
|
407
|
+
architecture)
|
|
408
|
+
route_instruction="ARCHITECTURE: Fix structural issues. Check dependency direction, layer boundaries, and separation of concerns."
|
|
409
|
+
;;
|
|
410
|
+
*)
|
|
411
|
+
route_instruction="Fix every issue listed above while keeping all existing functionality working."
|
|
412
|
+
;;
|
|
413
|
+
esac
|
|
414
|
+
|
|
415
|
+
GOAL="$GOAL
|
|
416
|
+
|
|
417
|
+
IMPORTANT — Compound quality review found issues (route: ${route}). Fix ALL of these:
|
|
418
|
+
$feedback_content
|
|
419
|
+
|
|
420
|
+
${route_instruction}"
|
|
421
|
+
|
|
422
|
+
# Re-run self-healing build→test
|
|
423
|
+
info "Rebuilding with quality feedback (route: ${route})..."
|
|
424
|
+
if self_healing_build_test; then
|
|
425
|
+
GOAL="$original_goal"
|
|
426
|
+
return 0
|
|
427
|
+
else
|
|
428
|
+
GOAL="$original_goal"
|
|
429
|
+
return 1
|
|
430
|
+
fi
|
|
431
|
+
}
|