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
|
@@ -6,7 +6,8 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
# shellcheck disable=SC2034
|
|
10
|
+
VERSION="3.3.0"
|
|
10
11
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
12
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
13
|
|
|
@@ -72,7 +73,8 @@ detect_code_smells() {
|
|
|
72
73
|
|
|
73
74
|
# Check 1: Long functions (>60 lines in bash)
|
|
74
75
|
local func_count
|
|
75
|
-
func_count=$(grep -c "^[a-zA-Z_][a-zA-Z0-9_]*().*{" "$target_file" 2>/dev/null ||
|
|
76
|
+
func_count=$(grep -c "^[a-zA-Z_][a-zA-Z0-9_]*().*{" "$target_file" 2>/dev/null || true)
|
|
77
|
+
func_count="${func_count:-0}"
|
|
76
78
|
if [[ "$func_count" -gt 0 ]]; then
|
|
77
79
|
while IFS= read -r line; do
|
|
78
80
|
if [[ "$line" =~ ^[a-zA-Z_][a-zA-Z0-9_]*\(\).*\{ ]]; then
|
|
@@ -106,7 +108,8 @@ detect_code_smells() {
|
|
|
106
108
|
|
|
107
109
|
# Check 3: Duplicate code patterns (repeated >3 times)
|
|
108
110
|
local dup_count=0
|
|
109
|
-
dup_count=$(grep -c '^\s*\(cd\|cd\|mkdir\|rm\|echo\)' "$target_file" 2>/dev/null ||
|
|
111
|
+
dup_count=$(grep -c '^\s*\(cd\|cd\|mkdir\|rm\|echo\)' "$target_file" 2>/dev/null || true)
|
|
112
|
+
dup_count="${dup_count:-0}"
|
|
110
113
|
if [[ $dup_count -gt 3 ]]; then
|
|
111
114
|
issues+=("REPEATED_PATTERNS: Common operations appear $dup_count times (consider helper functions)")
|
|
112
115
|
fi
|
|
@@ -139,7 +142,8 @@ check_solid_principles() {
|
|
|
139
142
|
|
|
140
143
|
# Single Responsibility: Check if scripts do multiple unrelated things
|
|
141
144
|
local sourced_count
|
|
142
|
-
sourced_count=$(grep -c '^\s*source\|^\s*\.\s' "$target_file" 2>/dev/null ||
|
|
145
|
+
sourced_count=$(grep -c '^\s*source\|^\s*\.\s' "$target_file" 2>/dev/null || true)
|
|
146
|
+
sourced_count="${sourced_count:-0}"
|
|
143
147
|
if [[ $sourced_count -gt 3 ]]; then
|
|
144
148
|
violations+=("SRP_VIOLATION: Script sources $sourced_count modules (too many responsibilities)")
|
|
145
149
|
fi
|
|
@@ -159,7 +163,8 @@ check_solid_principles() {
|
|
|
159
163
|
if [[ "$line" =~ ^[a-zA-Z_][a-zA-Z0-9_]*\(\) ]]; then
|
|
160
164
|
local func_name="${line%%(*}"
|
|
161
165
|
local body
|
|
162
|
-
body=$(awk "/^${func_name}\\(\\)/,/^}/" "$target_file" | grep -c '\$[0-9]' ||
|
|
166
|
+
body=$(awk "/^${func_name}\\(\\)/,/^}/" "$target_file" | grep -c '\$[0-9]' || true)
|
|
167
|
+
body="${body:-0}"
|
|
163
168
|
if [[ $body -gt 5 ]]; then
|
|
164
169
|
violations+=("ISP_VIOLATION: Function $func_name uses >5 parameters")
|
|
165
170
|
fi
|
|
@@ -227,7 +232,9 @@ analyze_complexity() {
|
|
|
227
232
|
|
|
228
233
|
# Cyclomatic complexity: count decision points (if, elif, case, &&, ||)
|
|
229
234
|
local cc=1
|
|
230
|
-
|
|
235
|
+
local _cc_count
|
|
236
|
+
_cc_count=$(sed -n "${start_line},${end_line}p" "$target_file" | grep -cE '\s(if|elif|case|&&|\|\|)' || true)
|
|
237
|
+
cc=$((cc + ${_cc_count:-0}))
|
|
231
238
|
|
|
232
239
|
# Lines of code
|
|
233
240
|
local loc=$((end_line - start_line))
|
|
@@ -266,8 +273,12 @@ check_style_consistency() {
|
|
|
266
273
|
local has_trap=false
|
|
267
274
|
local has_set_e=false
|
|
268
275
|
|
|
269
|
-
|
|
270
|
-
|
|
276
|
+
local _trap_count
|
|
277
|
+
_trap_count=$(grep -c 'trap.*ERR' "$target_file" 2>/dev/null || true)
|
|
278
|
+
[[ "${_trap_count:-0}" -gt 0 ]] && has_trap=true
|
|
279
|
+
local _set_e_count
|
|
280
|
+
_set_e_count=$(grep -c 'set -e' "$target_file" 2>/dev/null || true)
|
|
281
|
+
[[ "${_set_e_count:-0}" -gt 0 ]] && has_set_e=true
|
|
271
282
|
|
|
272
283
|
if [[ "$has_set_e" == "true" ]] && [[ "$has_trap" == "false" ]]; then
|
|
273
284
|
issues+=("STYLE: Missing ERR trap despite 'set -e' (inconsistent error handling)")
|
|
@@ -276,8 +287,10 @@ check_style_consistency() {
|
|
|
276
287
|
# Check for inconsistent quote usage
|
|
277
288
|
local single_quotes
|
|
278
289
|
local double_quotes
|
|
279
|
-
single_quotes=$(grep -o "'" "$target_file" 2>/dev/null | wc -l ||
|
|
280
|
-
|
|
290
|
+
single_quotes=$(grep -o "'" "$target_file" 2>/dev/null | wc -l || true)
|
|
291
|
+
single_quotes="${single_quotes:-0}"
|
|
292
|
+
double_quotes=$(grep -o '"' "$target_file" 2>/dev/null | wc -l || true)
|
|
293
|
+
double_quotes="${double_quotes:-0}"
|
|
281
294
|
if [[ $single_quotes -gt $((double_quotes * 3)) ]] || [[ $double_quotes -gt $((single_quotes * 3)) ]]; then
|
|
282
295
|
issues+=("STYLE: Inconsistent quote style (mix of single and double quotes)")
|
|
283
296
|
fi
|
|
@@ -285,8 +298,10 @@ check_style_consistency() {
|
|
|
285
298
|
# Check for inconsistent spacing/indentation
|
|
286
299
|
local tab_count
|
|
287
300
|
local space_count
|
|
288
|
-
tab_count=$(grep -c $'^\t' "$target_file" 2>/dev/null ||
|
|
289
|
-
|
|
301
|
+
tab_count=$(grep -c $'^\t' "$target_file" 2>/dev/null || true)
|
|
302
|
+
tab_count="${tab_count:-0}"
|
|
303
|
+
space_count=$(grep -c '^ ' "$target_file" 2>/dev/null || true)
|
|
304
|
+
space_count="${space_count:-0}"
|
|
290
305
|
if [[ $tab_count -gt 0 ]] && [[ $space_count -gt 0 ]]; then
|
|
291
306
|
issues+=("STYLE: Mixed tabs and spaces")
|
|
292
307
|
fi
|
|
@@ -333,7 +348,8 @@ auto_fix() {
|
|
|
333
348
|
|
|
334
349
|
# Fix 2: Trailing whitespace
|
|
335
350
|
local trailing_ws
|
|
336
|
-
trailing_ws=$(grep -c '[[:space:]]$' "$target_file" 2>/dev/null ||
|
|
351
|
+
trailing_ws=$(grep -c '[[:space:]]$' "$target_file" 2>/dev/null || true)
|
|
352
|
+
trailing_ws="${trailing_ws:-0}"
|
|
337
353
|
if [[ $trailing_ws -gt 0 ]]; then
|
|
338
354
|
sed -i '' 's/[[:space:]]*$//' "$target_file"
|
|
339
355
|
info "Removed $trailing_ws lines of trailing whitespace"
|
|
@@ -349,7 +365,8 @@ auto_fix() {
|
|
|
349
365
|
|
|
350
366
|
# Fix 4: Consistent spacing around operators (simple cases)
|
|
351
367
|
local spacing_fixes=0
|
|
352
|
-
spacing_fixes=$(grep -c '==' "$target_file" 2>/dev/null ||
|
|
368
|
+
spacing_fixes=$(grep -c '==' "$target_file" 2>/dev/null || true)
|
|
369
|
+
spacing_fixes="${spacing_fixes:-0}"
|
|
353
370
|
if [[ $spacing_fixes -gt 0 ]]; then
|
|
354
371
|
info "Flagged $spacing_fixes operator spacing cases (manual review recommended)"
|
|
355
372
|
fi
|
|
@@ -415,7 +432,8 @@ review_changes() {
|
|
|
415
432
|
|
|
416
433
|
mkdir -p "${REPO_DIR}/.claude/pipeline-artifacts"
|
|
417
434
|
|
|
418
|
-
local review_output
|
|
435
|
+
local review_output
|
|
436
|
+
review_output="{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"scope\":\"$review_scope\",\"findings\":{}}"
|
|
419
437
|
local total_issues=0
|
|
420
438
|
|
|
421
439
|
# Get changed files (Bash 3.2 compatible — no mapfile)
|
|
@@ -498,18 +516,24 @@ review_changes() {
|
|
|
498
516
|
scan_codebase() {
|
|
499
517
|
info "Running full codebase quality scan..."
|
|
500
518
|
|
|
501
|
-
local scan_output
|
|
519
|
+
local scan_output
|
|
520
|
+
# shellcheck disable=SC2034
|
|
521
|
+
scan_output="{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"files\":[]}"
|
|
502
522
|
local total_issues=0
|
|
503
523
|
|
|
524
|
+
# shellcheck disable=SC2178,SC2128
|
|
504
525
|
find "$REPO_DIR/scripts" -name "*.sh" -type f 2>/dev/null | while read -r file; do
|
|
505
526
|
local file_rel="${file#$REPO_DIR/}"
|
|
506
527
|
local smells=0
|
|
507
528
|
local solids=0
|
|
508
529
|
local arch_issues=0
|
|
509
530
|
|
|
510
|
-
smells=$(detect_code_smells "$file" 2>/dev/null | wc -l ||
|
|
511
|
-
|
|
512
|
-
|
|
531
|
+
smells=$(detect_code_smells "$file" 2>/dev/null | wc -l || true)
|
|
532
|
+
smells="${smells:-0}"
|
|
533
|
+
solids=$(check_solid_principles "$file" 2>/dev/null | wc -l || true)
|
|
534
|
+
solids="${solids:-0}"
|
|
535
|
+
arch_issues=$(check_architecture_boundaries "$file" 2>/dev/null | wc -l || true)
|
|
536
|
+
arch_issues="${arch_issues:-0}"
|
|
513
537
|
|
|
514
538
|
local file_issues=$((smells + solids + arch_issues))
|
|
515
539
|
total_issues=$((total_issues + file_issues))
|
|
@@ -528,7 +552,8 @@ scan_codebase() {
|
|
|
528
552
|
complexity_report() {
|
|
529
553
|
info "Analyzing code complexity metrics..."
|
|
530
554
|
|
|
531
|
-
local complexity_data
|
|
555
|
+
local complexity_data
|
|
556
|
+
complexity_data="{\"timestamp\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"files\":[]}"
|
|
532
557
|
|
|
533
558
|
find "$REPO_DIR/scripts" -name "*.sh" -type f 2>/dev/null | while read -r file; do
|
|
534
559
|
local file_metrics
|
package/scripts/sw-connect.sh
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
set -euo pipefail
|
|
9
9
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
10
10
|
|
|
11
|
-
VERSION="3.
|
|
11
|
+
VERSION="3.3.0"
|
|
12
12
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
13
13
|
|
|
14
14
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -33,6 +33,7 @@ fi
|
|
|
33
33
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
34
34
|
emit_event() {
|
|
35
35
|
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
36
|
+
# shellcheck disable=SC2155
|
|
36
37
|
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
37
38
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
38
39
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
package/scripts/sw-context.sh
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="3.
|
|
9
|
+
VERSION="3.3.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
REPO_DIR="${SHIPWRIGHT_REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
12
12
|
|
|
@@ -387,6 +387,7 @@ gather_context() {
|
|
|
387
387
|
|
|
388
388
|
local tmp_file
|
|
389
389
|
tmp_file=$(mktemp "${TMPDIR:-/tmp}/sw-context-bundle.XXXXXX")
|
|
390
|
+
# shellcheck disable=SC2064
|
|
390
391
|
trap "rm -f '$tmp_file'" RETURN
|
|
391
392
|
|
|
392
393
|
# Write bundle header
|
package/scripts/sw-cost.sh
CHANGED
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="3.
|
|
9
|
+
VERSION="3.3.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
|
+
# shellcheck disable=SC2034
|
|
11
12
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
12
13
|
|
|
13
14
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -29,6 +30,7 @@ fi
|
|
|
29
30
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
30
31
|
emit_event() {
|
|
31
32
|
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
33
|
+
# shellcheck disable=SC2155
|
|
32
34
|
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
33
35
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
34
36
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
@@ -150,11 +152,11 @@ cost_record() {
|
|
|
150
152
|
# Always write to JSON (dual-write period)
|
|
151
153
|
(
|
|
152
154
|
if command -v flock >/dev/null 2>&1; then
|
|
153
|
-
flock -w 10 200 2>/dev/null || { warn "Cost lock timeout"; }
|
|
155
|
+
flock -w 10 200 2>/dev/null || { warn "Cost lock timeout — proceeding without lock"; }
|
|
154
156
|
fi
|
|
155
157
|
local tmp_file
|
|
156
|
-
tmp_file=$(mktemp "${COST_FILE}.tmp.XXXXXX")
|
|
157
|
-
jq --argjson input "$input_tokens" \
|
|
158
|
+
tmp_file=$(mktemp "${COST_FILE}.tmp.XXXXXX") || { error "mktemp failed for cost record"; exit 1; }
|
|
159
|
+
if ! jq --argjson input "$input_tokens" \
|
|
158
160
|
--argjson output "$output_tokens" \
|
|
159
161
|
--arg model "$model" \
|
|
160
162
|
--arg stage "$stage" \
|
|
@@ -172,7 +174,16 @@ cost_record() {
|
|
|
172
174
|
ts: $ts,
|
|
173
175
|
ts_epoch: $epoch
|
|
174
176
|
}] | .entries = (.entries | .[-1000:])' \
|
|
175
|
-
"$COST_FILE" > "$tmp_file"
|
|
177
|
+
"$COST_FILE" > "$tmp_file" 2>/dev/null; then
|
|
178
|
+
error "Cost jq transformation failed — entry may be lost"
|
|
179
|
+
rm -f "$tmp_file"
|
|
180
|
+
# Continue without updating cost file
|
|
181
|
+
else
|
|
182
|
+
mv "$tmp_file" "$COST_FILE" || {
|
|
183
|
+
error "Failed to update cost file"
|
|
184
|
+
rm -f "$tmp_file"
|
|
185
|
+
}
|
|
186
|
+
fi
|
|
176
187
|
) 200>"${COST_FILE}.lock"
|
|
177
188
|
|
|
178
189
|
emit_event "cost.record" \
|
|
@@ -602,6 +613,49 @@ cost_dashboard() {
|
|
|
602
613
|
|
|
603
614
|
if [[ "$entry_count" -eq 0 ]]; then
|
|
604
615
|
warn "No cost entries in the last ${period_days} day(s)."
|
|
616
|
+
# Still show context efficiency data if available
|
|
617
|
+
local events_file="${HOME}/.shipwright/events.jsonl"
|
|
618
|
+
if [[ -f "$events_file" ]]; then
|
|
619
|
+
local ctx_events
|
|
620
|
+
ctx_events=$(grep '"type":"loop.context_efficiency"' "$events_file" 2>/dev/null | tail -200 || true)
|
|
621
|
+
local ctx_count
|
|
622
|
+
ctx_count=$(echo "$ctx_events" | grep -c '"loop.context_efficiency"' 2>/dev/null || echo "0")
|
|
623
|
+
ctx_count="${ctx_count:-0}"
|
|
624
|
+
if [[ "$ctx_count" -gt 0 ]]; then
|
|
625
|
+
local avg_utilization avg_trim_ratio total_raw total_trimmed trim_count
|
|
626
|
+
eval "$(echo "$ctx_events" | awk -F'"' '
|
|
627
|
+
/"loop.context_efficiency"/ {
|
|
628
|
+
for (i=1; i<=NF; i++) {
|
|
629
|
+
if ($i == "budget_utilization") util = $(i+2)
|
|
630
|
+
if ($i == "trim_ratio") ratio = $(i+2)
|
|
631
|
+
if ($i == "raw_prompt_chars") raw = $(i+2)
|
|
632
|
+
if ($i == "trimmed_prompt_chars") trimmed = $(i+2)
|
|
633
|
+
}
|
|
634
|
+
total_util += util; total_ratio += ratio
|
|
635
|
+
total_raw += raw; total_trimmed += trimmed
|
|
636
|
+
if (ratio + 0 > 0) trim_events++
|
|
637
|
+
n++
|
|
638
|
+
}
|
|
639
|
+
END {
|
|
640
|
+
if (n > 0) {
|
|
641
|
+
printf "avg_utilization=%.1f\n", total_util / n
|
|
642
|
+
printf "avg_trim_ratio=%.1f\n", total_ratio / n
|
|
643
|
+
} else {
|
|
644
|
+
printf "avg_utilization=0\navg_trim_ratio=0\n"
|
|
645
|
+
}
|
|
646
|
+
printf "total_raw=%d\ntotal_trimmed=%d\ntrim_count=%d\n", total_raw, total_trimmed, (trim_events+0)
|
|
647
|
+
}
|
|
648
|
+
')"
|
|
649
|
+
local total_discarded=$(( total_raw - total_trimmed ))
|
|
650
|
+
echo -e "${BOLD} CONTEXT EFFICIENCY${RESET}"
|
|
651
|
+
echo -e " Avg budget used ${avg_utilization}%"
|
|
652
|
+
echo -e " Avg trim ratio ${avg_trim_ratio}%"
|
|
653
|
+
echo -e " Chars generated $(printf "%'d" "$total_raw")"
|
|
654
|
+
echo -e " Chars discarded $(printf "%'d" "$total_discarded")"
|
|
655
|
+
echo -e " Trim events ${trim_count} / ${ctx_count} iterations"
|
|
656
|
+
echo ""
|
|
657
|
+
fi
|
|
658
|
+
fi
|
|
605
659
|
return 0
|
|
606
660
|
fi
|
|
607
661
|
|
|
@@ -790,6 +844,54 @@ cost_dashboard() {
|
|
|
790
844
|
fi
|
|
791
845
|
fi
|
|
792
846
|
|
|
847
|
+
# Context efficiency (from loop.context_efficiency events)
|
|
848
|
+
local events_file="${HOME}/.shipwright/events.jsonl"
|
|
849
|
+
if [[ -f "$events_file" ]]; then
|
|
850
|
+
local ctx_events
|
|
851
|
+
ctx_events=$(grep '"type":"loop.context_efficiency"' "$events_file" 2>/dev/null | tail -200 || true)
|
|
852
|
+
local ctx_count
|
|
853
|
+
ctx_count=$(echo "$ctx_events" | grep -c '"loop.context_efficiency"' 2>/dev/null || echo "0")
|
|
854
|
+
ctx_count="${ctx_count:-0}"
|
|
855
|
+
|
|
856
|
+
if [[ "$ctx_count" -gt 0 ]]; then
|
|
857
|
+
# Parse metrics using awk (Bash 3.2 safe — no arrays needed)
|
|
858
|
+
local avg_utilization avg_trim_ratio total_raw total_trimmed trim_count
|
|
859
|
+
eval "$(echo "$ctx_events" | awk -F'"' '
|
|
860
|
+
/"loop.context_efficiency"/ {
|
|
861
|
+
for (i=1; i<=NF; i++) {
|
|
862
|
+
if ($i == "budget_utilization") util = $(i+2)
|
|
863
|
+
if ($i == "trim_ratio") ratio = $(i+2)
|
|
864
|
+
if ($i == "raw_prompt_chars") raw = $(i+2)
|
|
865
|
+
if ($i == "trimmed_prompt_chars") trimmed = $(i+2)
|
|
866
|
+
}
|
|
867
|
+
total_util += util; total_ratio += ratio
|
|
868
|
+
total_raw += raw; total_trimmed += trimmed
|
|
869
|
+
if (ratio + 0 > 0) trim_events++
|
|
870
|
+
n++
|
|
871
|
+
}
|
|
872
|
+
END {
|
|
873
|
+
if (n > 0) {
|
|
874
|
+
printf "avg_utilization=%.1f\n", total_util / n
|
|
875
|
+
printf "avg_trim_ratio=%.1f\n", total_ratio / n
|
|
876
|
+
} else {
|
|
877
|
+
printf "avg_utilization=0\navg_trim_ratio=0\n"
|
|
878
|
+
}
|
|
879
|
+
printf "total_raw=%d\ntotal_trimmed=%d\ntrim_count=%d\n", total_raw, total_trimmed, (trim_events+0)
|
|
880
|
+
}
|
|
881
|
+
')"
|
|
882
|
+
|
|
883
|
+
local total_discarded=$(( total_raw - total_trimmed ))
|
|
884
|
+
|
|
885
|
+
echo -e "${BOLD} CONTEXT EFFICIENCY${RESET}"
|
|
886
|
+
echo -e " Avg budget used ${avg_utilization}%"
|
|
887
|
+
echo -e " Avg trim ratio ${avg_trim_ratio}%"
|
|
888
|
+
echo -e " Chars generated $(printf "%'d" "$total_raw")"
|
|
889
|
+
echo -e " Chars discarded $(printf "%'d" "$total_discarded")"
|
|
890
|
+
echo -e " Trim events ${trim_count} / ${ctx_count} iterations"
|
|
891
|
+
echo ""
|
|
892
|
+
fi
|
|
893
|
+
fi
|
|
894
|
+
|
|
793
895
|
echo -e "${PURPLE}${BOLD}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${RESET}"
|
|
794
896
|
echo ""
|
|
795
897
|
}
|
package/scripts/sw-daemon.sh
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env bash
|
|
2
|
+
# shellcheck disable=SC2034 # config vars used by sourced scripts and subshells
|
|
2
3
|
# ╔═══════════════════════════════════════════════════════════════════════════╗
|
|
3
4
|
# ║ shipwright daemon — Autonomous GitHub Issue Watcher ║
|
|
4
5
|
# ║ Polls for labeled issues · Spawns pipelines · Manages worktrees ║
|
|
@@ -8,8 +9,11 @@ trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
|
8
9
|
|
|
9
10
|
# Allow spawning Claude CLI from within a Claude Code session (daemon, fleet, etc.)
|
|
10
11
|
unset CLAUDECODE 2>/dev/null || true
|
|
12
|
+
# Ignore SIGHUP so daemon survives tmux attach/detach
|
|
13
|
+
trap '' HUP
|
|
14
|
+
trap '' SIGPIPE
|
|
11
15
|
|
|
12
|
-
VERSION="3.
|
|
16
|
+
VERSION="3.3.0"
|
|
13
17
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
14
18
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
15
19
|
|
|
@@ -199,6 +203,8 @@ ISSUE_LIMIT=$(_config_get_int "daemon.issue_limit" 100 2>/dev/null || echo 100)
|
|
|
199
203
|
PIPELINE_TEMPLATE="autonomous"
|
|
200
204
|
SKIP_GATES=true
|
|
201
205
|
MODEL="opus"
|
|
206
|
+
EFFORT_LEVEL=""
|
|
207
|
+
FALLBACK_MODEL="sonnet"
|
|
202
208
|
BASE_BRANCH="main"
|
|
203
209
|
ON_SUCCESS_REMOVE_LABEL="shipwright"
|
|
204
210
|
ON_SUCCESS_ADD_LABEL="pipeline/complete"
|
|
@@ -381,6 +387,8 @@ load_config() {
|
|
|
381
387
|
PIPELINE_TEMPLATE=$(jq -r '.pipeline_template // "autonomous"' "$config_file")
|
|
382
388
|
SKIP_GATES=$(jq -r '.skip_gates // true' "$config_file")
|
|
383
389
|
MODEL=$(jq -r '.model // "opus"' "$config_file")
|
|
390
|
+
EFFORT_LEVEL=$(jq -r '.effort_level // ""' "$config_file")
|
|
391
|
+
FALLBACK_MODEL=$(jq -r '.fallback_model // "sonnet"' "$config_file")
|
|
384
392
|
BASE_BRANCH=$(jq -r '.base_branch // "main"' "$config_file")
|
|
385
393
|
|
|
386
394
|
# on_success settings
|
|
@@ -441,6 +449,7 @@ load_config() {
|
|
|
441
449
|
# intelligence engine settings (default "auto" = enable when Claude CLI available)
|
|
442
450
|
INTELLIGENCE_ENABLED=$(jq -r '.intelligence.enabled // "auto"' "$config_file")
|
|
443
451
|
INTELLIGENCE_CACHE_TTL=$(jq -r '.intelligence.cache_ttl_seconds // 3600' "$config_file")
|
|
452
|
+
INTELLIGENCE_MODEL=$(jq -r '.intelligence.model // "haiku"' "$config_file")
|
|
444
453
|
COMPOSER_ENABLED=$(jq -r '.intelligence.composer_enabled // "auto"' "$config_file")
|
|
445
454
|
|
|
446
455
|
# Auto-enable intelligence when Claude is available (unless explicitly disabled)
|
|
@@ -471,14 +480,27 @@ load_config() {
|
|
|
471
480
|
COMPOSER_ENABLED=false
|
|
472
481
|
fi
|
|
473
482
|
fi
|
|
474
|
-
OPTIMIZATION_ENABLED=$(jq -r '.intelligence.optimization_enabled //
|
|
475
|
-
PREDICTION_ENABLED=$(jq -r '.intelligence.prediction_enabled //
|
|
483
|
+
OPTIMIZATION_ENABLED=$(jq -r '.intelligence.optimization_enabled // "auto"' "$config_file")
|
|
484
|
+
PREDICTION_ENABLED=$(jq -r '.intelligence.prediction_enabled // "auto"' "$config_file")
|
|
476
485
|
ANOMALY_THRESHOLD=$(jq -r '.intelligence.anomaly_threshold // 3.0' "$config_file")
|
|
477
486
|
|
|
478
487
|
# adaptive thresholds (intelligence-driven operational tuning)
|
|
479
|
-
ADAPTIVE_THRESHOLDS_ENABLED=$(jq -r '.intelligence.adaptive_enabled //
|
|
488
|
+
ADAPTIVE_THRESHOLDS_ENABLED=$(jq -r '.intelligence.adaptive_enabled // "auto"' "$config_file")
|
|
480
489
|
PRIORITY_STRATEGY=$(jq -r '.intelligence.priority_strategy // "quick-wins-first"' "$config_file")
|
|
481
490
|
|
|
491
|
+
# Auto-resolve "auto" for prediction, optimization, adaptive (same pattern as intelligence/composer)
|
|
492
|
+
local _flag_val=""
|
|
493
|
+
for _flag_var in OPTIMIZATION_ENABLED PREDICTION_ENABLED ADAPTIVE_THRESHOLDS_ENABLED; do
|
|
494
|
+
eval "_flag_val=\"\${${_flag_var}}\""
|
|
495
|
+
if [[ "$_flag_val" == "auto" ]]; then
|
|
496
|
+
if command -v claude &>/dev/null; then
|
|
497
|
+
eval "${_flag_var}=true"
|
|
498
|
+
else
|
|
499
|
+
eval "${_flag_var}=false"
|
|
500
|
+
fi
|
|
501
|
+
fi
|
|
502
|
+
done
|
|
503
|
+
|
|
482
504
|
# gh_retry: enable retry wrapper on critical GitHub API calls
|
|
483
505
|
GH_RETRY_ENABLED=$(jq -r '.gh_retry // true' "$config_file")
|
|
484
506
|
|
|
@@ -544,19 +566,45 @@ setup_dirs() {
|
|
|
544
566
|
STATE_FILE="$DAEMON_DIR/daemon-state.json"
|
|
545
567
|
LOG_FILE="$DAEMON_DIR/daemon.log"
|
|
546
568
|
LOG_DIR="$DAEMON_DIR/logs"
|
|
547
|
-
|
|
569
|
+
|
|
570
|
+
# ── Worktree Directory (must be absolute for security) ──
|
|
571
|
+
# Always use repo-level .claude/worktrees (self-healing: create .claude if missing)
|
|
572
|
+
local _abs_cwd
|
|
573
|
+
_abs_cwd="$(cd "$(pwd)" && pwd)"
|
|
574
|
+
WORKTREE_DIR="${_abs_cwd}/.claude/worktrees"
|
|
575
|
+
|
|
548
576
|
PAUSE_FLAG="${HOME}/.shipwright/daemon-pause.flag"
|
|
549
577
|
|
|
550
578
|
mkdir -p "$LOG_DIR"
|
|
551
579
|
mkdir -p "$HOME/.shipwright/progress"
|
|
580
|
+
mkdir -p "$WORKTREE_DIR"
|
|
581
|
+
|
|
582
|
+
# Ensure worktrees are gitignored
|
|
583
|
+
local _gitignore="${_abs_cwd}/.gitignore"
|
|
584
|
+
if [[ -f "$_gitignore" ]] && ! grep -q '\.claude/worktrees' "$_gitignore" 2>/dev/null; then
|
|
585
|
+
echo ".claude/worktrees/" >> "$_gitignore"
|
|
586
|
+
fi
|
|
552
587
|
}
|
|
553
588
|
|
|
554
589
|
# ─── Adaptive Threshold Helpers ──────────────────────────────────────────────
|
|
555
590
|
# When intelligence.adaptive_enabled=true, operational thresholds are learned
|
|
556
591
|
# from historical data instead of using fixed defaults.
|
|
557
|
-
# Every function falls back to the
|
|
558
|
-
|
|
559
|
-
|
|
592
|
+
# Every function falls back to the config default when no data exists.
|
|
593
|
+
|
|
594
|
+
# Auto-resolve intelligence defaults when no config file is loaded.
|
|
595
|
+
# All three default to "auto" → true when Claude CLI is available.
|
|
596
|
+
_auto_resolve_intelligence() {
|
|
597
|
+
local val="${1:-auto}"
|
|
598
|
+
if [[ "$val" == "auto" ]]; then
|
|
599
|
+
command -v claude &>/dev/null && echo "true" || echo "false"
|
|
600
|
+
else
|
|
601
|
+
echo "$val"
|
|
602
|
+
fi
|
|
603
|
+
}
|
|
604
|
+
INTELLIGENCE_MODEL="${INTELLIGENCE_MODEL:-haiku}"
|
|
605
|
+
OPTIMIZATION_ENABLED=$(_auto_resolve_intelligence "${OPTIMIZATION_ENABLED:-auto}")
|
|
606
|
+
PREDICTION_ENABLED=$(_auto_resolve_intelligence "${PREDICTION_ENABLED:-auto}")
|
|
607
|
+
ADAPTIVE_THRESHOLDS_ENABLED=$(_auto_resolve_intelligence "${ADAPTIVE_THRESHOLDS_ENABLED:-auto}")
|
|
560
608
|
PRIORITY_STRATEGY="${PRIORITY_STRATEGY:-quick-wins-first}"
|
|
561
609
|
EMPTY_QUEUE_CYCLES=0
|
|
562
610
|
|
|
@@ -669,7 +717,8 @@ daemon_start() {
|
|
|
669
717
|
fi
|
|
670
718
|
|
|
671
719
|
# Export current PATH so detached session finds claude, gh, etc.
|
|
672
|
-
|
|
720
|
+
# Unset CLAUDECODE so daemon works when started from inside Claude Code
|
|
721
|
+
local tmux_cmd="unset CLAUDECODE 2>/dev/null; export PATH='${PATH}'; ${cmd_args[*]}"
|
|
673
722
|
tmux new-session -d -s "sw-daemon" "$tmux_cmd" 2>/dev/null || {
|
|
674
723
|
# Session may already exist — try killing and recreating
|
|
675
724
|
tmux kill-session -t "sw-daemon" 2>/dev/null || true
|
|
@@ -934,6 +983,11 @@ daemon_init() {
|
|
|
934
983
|
|
|
935
984
|
mkdir -p "$config_dir"
|
|
936
985
|
|
|
986
|
+
# Set restrictive umask for sensitive files (owner-only: 600)
|
|
987
|
+
local _old_umask
|
|
988
|
+
_old_umask=$(umask)
|
|
989
|
+
umask 0077
|
|
990
|
+
|
|
937
991
|
cat > "$config_file" << 'CONFIGEOF'
|
|
938
992
|
{
|
|
939
993
|
"watch_label": "shipwright",
|
|
@@ -999,10 +1053,12 @@ daemon_init() {
|
|
|
999
1053
|
"estimated_cost_per_job_usd": 5.0,
|
|
1000
1054
|
"intelligence": {
|
|
1001
1055
|
"enabled": "auto",
|
|
1056
|
+
"model": "haiku",
|
|
1002
1057
|
"cache_ttl_seconds": 3600,
|
|
1003
1058
|
"composer_enabled": "auto",
|
|
1004
|
-
"optimization_enabled":
|
|
1005
|
-
"prediction_enabled":
|
|
1059
|
+
"optimization_enabled": "auto",
|
|
1060
|
+
"prediction_enabled": "auto",
|
|
1061
|
+
"adaptive_enabled": "auto",
|
|
1006
1062
|
"adversarial_enabled": false,
|
|
1007
1063
|
"simulation_enabled": false,
|
|
1008
1064
|
"architecture_enabled": false,
|
|
@@ -1012,6 +1068,10 @@ daemon_init() {
|
|
|
1012
1068
|
}
|
|
1013
1069
|
CONFIGEOF
|
|
1014
1070
|
|
|
1071
|
+
# Restore umask and ensure file has restricted permissions
|
|
1072
|
+
umask "$_old_umask"
|
|
1073
|
+
chmod 600 "$config_file"
|
|
1074
|
+
|
|
1015
1075
|
success "Generated config: ${config_file}"
|
|
1016
1076
|
echo ""
|
|
1017
1077
|
echo -e "${DIM}Edit this file to customize the daemon behavior, then run:${RESET}"
|
package/scripts/sw-dashboard.sh
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
|
|
8
8
|
|
|
9
|
-
VERSION="3.
|
|
9
|
+
VERSION="3.3.0"
|
|
10
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
11
11
|
|
|
12
12
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
@@ -29,6 +29,7 @@ fi
|
|
|
29
29
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
30
30
|
emit_event() {
|
|
31
31
|
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
32
|
+
# shellcheck disable=SC2155
|
|
32
33
|
local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
33
34
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
34
35
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
@@ -41,6 +42,7 @@ TEAMS_DIR="${HOME}/.shipwright"
|
|
|
41
42
|
PID_FILE="${TEAMS_DIR}/dashboard.pid"
|
|
42
43
|
LOG_DIR="${TEAMS_DIR}/logs"
|
|
43
44
|
LOG_FILE="${LOG_DIR}/dashboard.log"
|
|
45
|
+
# shellcheck disable=SC2034
|
|
44
46
|
EVENTS_FILE="${TEAMS_DIR}/events.jsonl"
|
|
45
47
|
DEFAULT_PORT=$(_config_get_int "dashboard.port" 8767 2>/dev/null || echo 8767)
|
|
46
48
|
|