shipwright-cli 3.2.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 +4 -4
- 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/dashboard/middleware/auth.ts +134 -0
- package/dashboard/middleware/constants.ts +21 -0
- package/dashboard/public/index.html +2 -6
- package/dashboard/public/styles.css +100 -97
- package/dashboard/routes/auth.ts +38 -0
- package/dashboard/server.ts +66 -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/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 +2 -1
- package/dashboard/src/views/activity.ts +2 -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 +10 -0
- package/scripts/lib/daemon-dispatch.sh +106 -17
- package/scripts/lib/daemon-failure.sh +34 -4
- package/scripts/lib/daemon-patrol.sh +23 -2
- 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 +112 -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 +177 -4
- 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 +100 -2
- 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 +100 -1136
- package/scripts/lib/pipeline-quality-bash-compat.sh +182 -0
- package/scripts/lib/pipeline-quality-checks.sh +17 -715
- 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 +59 -2929
- 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 -2
- package/scripts/sw-adaptive.sh +2 -1
- 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 +5 -1
- package/scripts/sw-cleanup.sh +4 -26
- package/scripts/sw-code-review.sh +10 -4
- package/scripts/sw-connect.sh +2 -1
- package/scripts/sw-context.sh +2 -1
- package/scripts/sw-cost.sh +48 -3
- package/scripts/sw-daemon.sh +66 -9
- package/scripts/sw-dashboard.sh +3 -1
- package/scripts/sw-db.sh +59 -16
- 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 +325 -2
- 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 +4 -3
- package/scripts/sw-e2e-orchestrator.sh +17 -16
- package/scripts/sw-eventbus.sh +7 -1
- 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 +4 -1
- package/scripts/sw-fleet.sh +5 -1
- package/scripts/sw-github-app.sh +16 -3
- 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 +6 -1
- package/scripts/sw-incident.sh +265 -1
- package/scripts/sw-init.sh +18 -2
- package/scripts/sw-instrument.sh +10 -2
- package/scripts/sw-intelligence.sh +42 -6
- 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 +432 -1128
- package/scripts/sw-memory.sh +356 -2
- package/scripts/sw-mission-control.sh +6 -1
- package/scripts/sw-model-router.sh +481 -26
- package/scripts/sw-otel.sh +13 -4
- package/scripts/sw-oversight.sh +14 -5
- package/scripts/sw-patrol-meta.sh +334 -0
- package/scripts/sw-pipeline-composer.sh +5 -1
- package/scripts/sw-pipeline-vitals.sh +2 -1
- package/scripts/sw-pipeline.sh +53 -2664
- package/scripts/sw-pm.sh +12 -5
- package/scripts/sw-pr-lifecycle.sh +2 -1
- package/scripts/sw-predictive.sh +7 -1
- package/scripts/sw-prep.sh +185 -2
- package/scripts/sw-ps.sh +5 -25
- package/scripts/sw-public-dashboard.sh +15 -3
- package/scripts/sw-quality.sh +2 -1
- 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 +10 -3
- package/scripts/sw-security-audit.sh +6 -1
- package/scripts/sw-self-optimize.sh +6 -3
- 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 +4 -1
- package/scripts/sw-stream.sh +7 -1
- package/scripts/sw-swarm.sh +18 -6
- package/scripts/sw-team-stages.sh +13 -6
- package/scripts/sw-templates.sh +5 -29
- package/scripts/sw-testgen.sh +7 -1
- 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 +3 -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 +2 -1
- package/scripts/sw-upgrade.sh +3 -1
- package/scripts/sw-ux.sh +5 -2
- package/scripts/sw-webhook.sh +3 -1
- package/scripts/sw-widgets.sh +3 -1
- 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
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 ║
|
|
@@ -12,7 +13,7 @@ unset CLAUDECODE 2>/dev/null || true
|
|
|
12
13
|
trap '' HUP
|
|
13
14
|
trap '' SIGPIPE
|
|
14
15
|
|
|
15
|
-
VERSION="3.
|
|
16
|
+
VERSION="3.3.0"
|
|
16
17
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
17
18
|
REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
18
19
|
|
|
@@ -202,6 +203,8 @@ ISSUE_LIMIT=$(_config_get_int "daemon.issue_limit" 100 2>/dev/null || echo 100)
|
|
|
202
203
|
PIPELINE_TEMPLATE="autonomous"
|
|
203
204
|
SKIP_GATES=true
|
|
204
205
|
MODEL="opus"
|
|
206
|
+
EFFORT_LEVEL=""
|
|
207
|
+
FALLBACK_MODEL="sonnet"
|
|
205
208
|
BASE_BRANCH="main"
|
|
206
209
|
ON_SUCCESS_REMOVE_LABEL="shipwright"
|
|
207
210
|
ON_SUCCESS_ADD_LABEL="pipeline/complete"
|
|
@@ -384,6 +387,8 @@ load_config() {
|
|
|
384
387
|
PIPELINE_TEMPLATE=$(jq -r '.pipeline_template // "autonomous"' "$config_file")
|
|
385
388
|
SKIP_GATES=$(jq -r '.skip_gates // true' "$config_file")
|
|
386
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")
|
|
387
392
|
BASE_BRANCH=$(jq -r '.base_branch // "main"' "$config_file")
|
|
388
393
|
|
|
389
394
|
# on_success settings
|
|
@@ -444,6 +449,7 @@ load_config() {
|
|
|
444
449
|
# intelligence engine settings (default "auto" = enable when Claude CLI available)
|
|
445
450
|
INTELLIGENCE_ENABLED=$(jq -r '.intelligence.enabled // "auto"' "$config_file")
|
|
446
451
|
INTELLIGENCE_CACHE_TTL=$(jq -r '.intelligence.cache_ttl_seconds // 3600' "$config_file")
|
|
452
|
+
INTELLIGENCE_MODEL=$(jq -r '.intelligence.model // "haiku"' "$config_file")
|
|
447
453
|
COMPOSER_ENABLED=$(jq -r '.intelligence.composer_enabled // "auto"' "$config_file")
|
|
448
454
|
|
|
449
455
|
# Auto-enable intelligence when Claude is available (unless explicitly disabled)
|
|
@@ -474,14 +480,27 @@ load_config() {
|
|
|
474
480
|
COMPOSER_ENABLED=false
|
|
475
481
|
fi
|
|
476
482
|
fi
|
|
477
|
-
OPTIMIZATION_ENABLED=$(jq -r '.intelligence.optimization_enabled //
|
|
478
|
-
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")
|
|
479
485
|
ANOMALY_THRESHOLD=$(jq -r '.intelligence.anomaly_threshold // 3.0' "$config_file")
|
|
480
486
|
|
|
481
487
|
# adaptive thresholds (intelligence-driven operational tuning)
|
|
482
|
-
ADAPTIVE_THRESHOLDS_ENABLED=$(jq -r '.intelligence.adaptive_enabled //
|
|
488
|
+
ADAPTIVE_THRESHOLDS_ENABLED=$(jq -r '.intelligence.adaptive_enabled // "auto"' "$config_file")
|
|
483
489
|
PRIORITY_STRATEGY=$(jq -r '.intelligence.priority_strategy // "quick-wins-first"' "$config_file")
|
|
484
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
|
+
|
|
485
504
|
# gh_retry: enable retry wrapper on critical GitHub API calls
|
|
486
505
|
GH_RETRY_ENABLED=$(jq -r '.gh_retry // true' "$config_file")
|
|
487
506
|
|
|
@@ -547,11 +566,24 @@ setup_dirs() {
|
|
|
547
566
|
STATE_FILE="$DAEMON_DIR/daemon-state.json"
|
|
548
567
|
LOG_FILE="$DAEMON_DIR/daemon.log"
|
|
549
568
|
LOG_DIR="$DAEMON_DIR/logs"
|
|
550
|
-
|
|
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
|
+
|
|
551
576
|
PAUSE_FLAG="${HOME}/.shipwright/daemon-pause.flag"
|
|
552
577
|
|
|
553
578
|
mkdir -p "$LOG_DIR"
|
|
554
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
|
|
555
587
|
}
|
|
556
588
|
|
|
557
589
|
# ─── Adaptive Threshold Helpers ──────────────────────────────────────────────
|
|
@@ -559,7 +591,20 @@ setup_dirs() {
|
|
|
559
591
|
# from historical data instead of using fixed defaults.
|
|
560
592
|
# Every function falls back to the config default when no data exists.
|
|
561
593
|
|
|
562
|
-
|
|
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}")
|
|
563
608
|
PRIORITY_STRATEGY="${PRIORITY_STRATEGY:-quick-wins-first}"
|
|
564
609
|
EMPTY_QUEUE_CYCLES=0
|
|
565
610
|
|
|
@@ -672,7 +717,8 @@ daemon_start() {
|
|
|
672
717
|
fi
|
|
673
718
|
|
|
674
719
|
# Export current PATH so detached session finds claude, gh, etc.
|
|
675
|
-
|
|
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[*]}"
|
|
676
722
|
tmux new-session -d -s "sw-daemon" "$tmux_cmd" 2>/dev/null || {
|
|
677
723
|
# Session may already exist — try killing and recreating
|
|
678
724
|
tmux kill-session -t "sw-daemon" 2>/dev/null || true
|
|
@@ -937,6 +983,11 @@ daemon_init() {
|
|
|
937
983
|
|
|
938
984
|
mkdir -p "$config_dir"
|
|
939
985
|
|
|
986
|
+
# Set restrictive umask for sensitive files (owner-only: 600)
|
|
987
|
+
local _old_umask
|
|
988
|
+
_old_umask=$(umask)
|
|
989
|
+
umask 0077
|
|
990
|
+
|
|
940
991
|
cat > "$config_file" << 'CONFIGEOF'
|
|
941
992
|
{
|
|
942
993
|
"watch_label": "shipwright",
|
|
@@ -1002,10 +1053,12 @@ daemon_init() {
|
|
|
1002
1053
|
"estimated_cost_per_job_usd": 5.0,
|
|
1003
1054
|
"intelligence": {
|
|
1004
1055
|
"enabled": "auto",
|
|
1056
|
+
"model": "haiku",
|
|
1005
1057
|
"cache_ttl_seconds": 3600,
|
|
1006
1058
|
"composer_enabled": "auto",
|
|
1007
|
-
"optimization_enabled":
|
|
1008
|
-
"prediction_enabled":
|
|
1059
|
+
"optimization_enabled": "auto",
|
|
1060
|
+
"prediction_enabled": "auto",
|
|
1061
|
+
"adaptive_enabled": "auto",
|
|
1009
1062
|
"adversarial_enabled": false,
|
|
1010
1063
|
"simulation_enabled": false,
|
|
1011
1064
|
"architecture_enabled": false,
|
|
@@ -1015,6 +1068,10 @@ daemon_init() {
|
|
|
1015
1068
|
}
|
|
1016
1069
|
CONFIGEOF
|
|
1017
1070
|
|
|
1071
|
+
# Restore umask and ensure file has restricted permissions
|
|
1072
|
+
umask "$_old_umask"
|
|
1073
|
+
chmod 600 "$config_file"
|
|
1074
|
+
|
|
1018
1075
|
success "Generated config: ${config_file}"
|
|
1019
1076
|
echo ""
|
|
1020
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
|
|
package/scripts/sw-db.sh
CHANGED
|
@@ -14,9 +14,11 @@ if [[ -n "${_SW_DB_LOADED:-}" ]] && [[ "${BASH_SOURCE[0]}" != "$0" ]]; then
|
|
|
14
14
|
fi
|
|
15
15
|
_SW_DB_LOADED=1
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
# shellcheck disable=SC2034
|
|
18
|
+
VERSION="3.3.0"
|
|
18
19
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
19
|
-
|
|
20
|
+
# shellcheck disable=SC2034
|
|
21
|
+
REPO_DIR="${REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
|
|
20
22
|
|
|
21
23
|
# ─── Cross-platform compatibility ──────────────────────────────────────────
|
|
22
24
|
# shellcheck source=lib/compat.sh
|
|
@@ -37,7 +39,8 @@ fi
|
|
|
37
39
|
if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
|
|
38
40
|
emit_event() {
|
|
39
41
|
local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
|
|
40
|
-
local payload
|
|
42
|
+
local payload
|
|
43
|
+
payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
|
|
41
44
|
while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
|
|
42
45
|
echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
|
|
43
46
|
}
|
|
@@ -50,6 +53,7 @@ SCHEMA_VERSION=6
|
|
|
50
53
|
# JSON fallback paths
|
|
51
54
|
EVENTS_FILE="${DB_DIR}/events.jsonl"
|
|
52
55
|
DAEMON_STATE_FILE="${DB_DIR}/daemon-state.json"
|
|
56
|
+
# shellcheck disable=SC2034
|
|
53
57
|
DEVELOPER_REGISTRY_FILE="${DB_DIR}/developer-registry.json"
|
|
54
58
|
COST_FILE_JSON="${DB_DIR}/costs.json"
|
|
55
59
|
BUDGET_FILE_JSON="${DB_DIR}/budget.json"
|
|
@@ -107,12 +111,12 @@ ensure_db_dir() {
|
|
|
107
111
|
# ─── SQL Execution Helper ──────────────────────────────────────────────────
|
|
108
112
|
# Runs SQL with proper error handling. Silent on success.
|
|
109
113
|
_db_exec() {
|
|
110
|
-
sqlite3 "$DB_FILE" "$@" 2>/dev/null
|
|
114
|
+
sqlite3 -cmd ".timeout 5000" "$DB_FILE" "$@" 2>/dev/null
|
|
111
115
|
}
|
|
112
116
|
|
|
113
117
|
# Runs SQL and returns output. Returns 1 on failure.
|
|
114
118
|
_db_query() {
|
|
115
|
-
sqlite3 "$DB_FILE" "$@" 2>/dev/null || return 1
|
|
119
|
+
sqlite3 -cmd ".timeout 5000" "$DB_FILE" "$@" 2>/dev/null || return 1
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
# ─── Initialize Database Schema ──────────────────────────────────────────────
|
|
@@ -700,7 +704,10 @@ db_query_events() {
|
|
|
700
704
|
|
|
701
705
|
if [[ -f "$db_file" ]] && command -v sqlite3 &>/dev/null; then
|
|
702
706
|
local where_clause=""
|
|
703
|
-
[[ -n "$filter" ]]
|
|
707
|
+
if [[ -n "$filter" ]]; then
|
|
708
|
+
filter="${filter//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
709
|
+
where_clause="WHERE type = '$filter'"
|
|
710
|
+
fi
|
|
704
711
|
local result
|
|
705
712
|
result=$(sqlite3 -json "$db_file" "SELECT ts, ts_epoch, type, job_id, stage, status, duration_secs, metadata FROM events $where_clause ORDER BY ts_epoch DESC LIMIT $limit" 2>/dev/null) || true
|
|
706
713
|
if [[ -n "$result" ]]; then
|
|
@@ -728,13 +735,19 @@ db_query_events_since() {
|
|
|
728
735
|
local since_epoch="$1"
|
|
729
736
|
local event_type="${2:-}"
|
|
730
737
|
local to_epoch="${3:-}"
|
|
738
|
+
# Validate numeric epoch values
|
|
739
|
+
[[ ! "$since_epoch" =~ ^[0-9]+$ ]] && { echo "[]"; return 0; }
|
|
731
740
|
local db_file="${DB_FILE:-$HOME/.shipwright/shipwright.db}"
|
|
732
741
|
|
|
733
742
|
if [[ -f "$db_file" ]] && command -v sqlite3 &>/dev/null; then
|
|
734
743
|
local type_filter=""
|
|
735
|
-
[[ -n "$event_type" ]]
|
|
744
|
+
if [[ -n "$event_type" ]]; then
|
|
745
|
+
event_type="${event_type//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
746
|
+
type_filter="AND type = '$event_type'"
|
|
747
|
+
fi
|
|
736
748
|
local to_filter=""
|
|
737
|
-
|
|
749
|
+
# Numeric validation for epoch values
|
|
750
|
+
[[ -n "$to_epoch" && "$to_epoch" =~ ^[0-9]+$ ]] && to_filter="AND ts_epoch <= $to_epoch"
|
|
738
751
|
local result
|
|
739
752
|
result=$(sqlite3 -json "$db_file" "SELECT ts, ts_epoch, type, job_id, stage, status, duration_secs, metadata FROM events WHERE ts_epoch >= $since_epoch $type_filter $to_filter ORDER BY ts_epoch DESC" 2>/dev/null) || true
|
|
740
753
|
if [[ -n "$result" ]]; then
|
|
@@ -1182,8 +1195,12 @@ db_save_pattern() {
|
|
|
1182
1195
|
db_query_patterns() {
|
|
1183
1196
|
local repo_hash="$1" pattern_type="${2:-}" limit="${3:-20}"
|
|
1184
1197
|
if ! db_available; then echo "[]"; return 0; fi
|
|
1198
|
+
repo_hash="${repo_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1185
1199
|
local where="WHERE repo_hash = '$repo_hash'"
|
|
1186
|
-
[[ -n "$pattern_type" ]]
|
|
1200
|
+
if [[ -n "$pattern_type" ]]; then
|
|
1201
|
+
pattern_type="${pattern_type//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1202
|
+
where="$where AND pattern_type = '$pattern_type'"
|
|
1203
|
+
fi
|
|
1187
1204
|
_db_query -json "SELECT * FROM memory_patterns $where ORDER BY frequency DESC, last_seen_at DESC LIMIT $limit;" || echo "[]"
|
|
1188
1205
|
}
|
|
1189
1206
|
|
|
@@ -1191,6 +1208,8 @@ db_query_patterns() {
|
|
|
1191
1208
|
db_save_decision() {
|
|
1192
1209
|
local repo_hash="$1" decision_type="$2" context="$3" decision="$4" metadata="${5:-}"
|
|
1193
1210
|
if ! db_available; then return 1; fi
|
|
1211
|
+
repo_hash="${repo_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1212
|
+
decision_type="${decision_type//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1194
1213
|
context="${context//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1195
1214
|
decision="${decision//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1196
1215
|
metadata="${metadata//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
@@ -1201,17 +1220,24 @@ db_save_decision() {
|
|
|
1201
1220
|
db_update_decision_outcome() {
|
|
1202
1221
|
local decision_id="$1" outcome="$2" confidence="${3:-}"
|
|
1203
1222
|
if ! db_available; then return 1; fi
|
|
1223
|
+
# Validate numeric IDs to prevent injection
|
|
1224
|
+
[[ ! "$decision_id" =~ ^[0-9]+$ ]] && return 1
|
|
1204
1225
|
outcome="${outcome//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1205
|
-
local set_clause
|
|
1206
|
-
|
|
1226
|
+
local set_clause
|
|
1227
|
+
set_clause="outcome = '$outcome', updated_at = '$(now_iso)'"
|
|
1228
|
+
[[ -n "$confidence" && "$confidence" =~ ^[0-9.]+$ ]] && set_clause="$set_clause, confidence = $confidence"
|
|
1207
1229
|
_db_exec "UPDATE memory_decisions SET $set_clause WHERE id = $decision_id;"
|
|
1208
1230
|
}
|
|
1209
1231
|
|
|
1210
1232
|
db_query_decisions() {
|
|
1211
1233
|
local repo_hash="$1" decision_type="${2:-}" limit="${3:-20}"
|
|
1212
1234
|
if ! db_available; then echo "[]"; return 0; fi
|
|
1235
|
+
repo_hash="${repo_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1213
1236
|
local where="WHERE repo_hash = '$repo_hash'"
|
|
1214
|
-
[[ -n "$decision_type" ]]
|
|
1237
|
+
if [[ -n "$decision_type" ]]; then
|
|
1238
|
+
decision_type="${decision_type//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1239
|
+
where="$where AND decision_type = '$decision_type'"
|
|
1240
|
+
fi
|
|
1215
1241
|
_db_query -json "SELECT * FROM memory_decisions $where ORDER BY updated_at DESC LIMIT $limit;" || echo "[]"
|
|
1216
1242
|
}
|
|
1217
1243
|
|
|
@@ -1219,7 +1245,10 @@ db_query_decisions() {
|
|
|
1219
1245
|
db_save_embedding() {
|
|
1220
1246
|
local content_hash="$1" source_type="$2" content_text="$3" repo_hash="${4:-}"
|
|
1221
1247
|
if ! db_available; then return 1; fi
|
|
1248
|
+
content_hash="${content_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1249
|
+
source_type="${source_type//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1222
1250
|
content_text="${content_text//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1251
|
+
repo_hash="${repo_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1223
1252
|
_db_exec "INSERT OR IGNORE INTO memory_embeddings (content_hash, source_type, content_text, repo_hash, created_at)
|
|
1224
1253
|
VALUES ('$content_hash', '$source_type', '$content_text', '$repo_hash', '$(now_iso)');"
|
|
1225
1254
|
}
|
|
@@ -1228,8 +1257,14 @@ db_query_embeddings() {
|
|
|
1228
1257
|
local source_type="${1:-}" repo_hash="${2:-}" limit="${3:-50}"
|
|
1229
1258
|
if ! db_available; then echo "[]"; return 0; fi
|
|
1230
1259
|
local where="WHERE 1=1"
|
|
1231
|
-
[[ -n "$source_type" ]]
|
|
1232
|
-
|
|
1260
|
+
if [[ -n "$source_type" ]]; then
|
|
1261
|
+
source_type="${source_type//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1262
|
+
where="$where AND source_type = '$source_type'"
|
|
1263
|
+
fi
|
|
1264
|
+
if [[ -n "$repo_hash" ]]; then
|
|
1265
|
+
repo_hash="${repo_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1266
|
+
where="$where AND repo_hash = '$repo_hash'"
|
|
1267
|
+
fi
|
|
1233
1268
|
_db_query -json "SELECT id, content_hash, source_type, content_text, repo_hash, created_at FROM memory_embeddings $where ORDER BY created_at DESC LIMIT $limit;" || echo "[]"
|
|
1234
1269
|
}
|
|
1235
1270
|
|
|
@@ -1368,8 +1403,10 @@ db_sync_push() {
|
|
|
1368
1403
|
# Push via HTTP
|
|
1369
1404
|
local response
|
|
1370
1405
|
local auth_header=""
|
|
1406
|
+
# shellcheck disable=SC2089
|
|
1371
1407
|
[[ -n "${SYNC_TOKEN:-}" ]] && auth_header="-H 'Authorization: Bearer ${SYNC_TOKEN}'"
|
|
1372
1408
|
|
|
1409
|
+
# shellcheck disable=SC2090
|
|
1373
1410
|
response=$(curl -s --connect-timeout 10 --max-time 30 -w "%{http_code}" -o /dev/null \
|
|
1374
1411
|
-X POST "${SYNC_URL}/api/sync/push" \
|
|
1375
1412
|
-H "Content-Type: application/json" \
|
|
@@ -1400,9 +1437,11 @@ db_sync_pull() {
|
|
|
1400
1437
|
last_sync=$(_db_query "SELECT value FROM _sync_metadata WHERE key = 'last_pull_epoch';" || echo "0")
|
|
1401
1438
|
|
|
1402
1439
|
local auth_header=""
|
|
1440
|
+
# shellcheck disable=SC2089
|
|
1403
1441
|
[[ -n "${SYNC_TOKEN:-}" ]] && auth_header="-H 'Authorization: Bearer ${SYNC_TOKEN}'"
|
|
1404
1442
|
|
|
1405
1443
|
local response_body
|
|
1444
|
+
# shellcheck disable=SC2090
|
|
1406
1445
|
response_body=$(curl -s --connect-timeout 10 --max-time 30 \
|
|
1407
1446
|
"${SYNC_URL}/api/sync/pull?since=${last_sync}" \
|
|
1408
1447
|
-H "Accept: application/json" \
|
|
@@ -1451,6 +1490,7 @@ migrate_json_data() {
|
|
|
1451
1490
|
info "Importing events from ${EVENTS_FILE}..."
|
|
1452
1491
|
local evt_count=0
|
|
1453
1492
|
local evt_skipped=0
|
|
1493
|
+
# shellcheck disable=SC2106
|
|
1454
1494
|
while IFS= read -r line; do
|
|
1455
1495
|
[[ -z "$line" ]] && continue
|
|
1456
1496
|
local e_ts e_epoch e_type e_job e_stage e_status
|
|
@@ -1484,7 +1524,8 @@ migrate_json_data() {
|
|
|
1484
1524
|
j_result=$(echo "$job" | jq -r '.result // ""')
|
|
1485
1525
|
j_dur=$(echo "$job" | jq -r '.duration // ""')
|
|
1486
1526
|
j_at=$(echo "$job" | jq -r '.completed_at // ""')
|
|
1487
|
-
local j_id
|
|
1527
|
+
local j_id
|
|
1528
|
+
j_id="migrated-${j_issue}-$(echo "$j_at" | tr -dc '0-9' | tail -c 10)"
|
|
1488
1529
|
_db_exec "INSERT OR IGNORE INTO daemon_state (job_id, issue_number, status, result, duration, completed_at, started_at, updated_at) VALUES ('${j_id}', ${j_issue}, 'completed', '${j_result}', '${j_dur}', '${j_at}', '${j_at}', '$(now_iso)');" 2>/dev/null && job_count=$((job_count + 1))
|
|
1489
1530
|
done < <(jq -c '.completed[]' "$DAEMON_STATE_FILE" 2>/dev/null)
|
|
1490
1531
|
|
|
@@ -1583,7 +1624,7 @@ export_db() {
|
|
|
1583
1624
|
costs_json=$(_db_query "SELECT json_group_array(json_object('model', model, 'stage', stage, 'cost_usd', cost_usd, 'ts', ts)) FROM (SELECT * FROM cost_entries ORDER BY ts_epoch DESC LIMIT 1000);" || echo "[]")
|
|
1584
1625
|
|
|
1585
1626
|
local tmp_file
|
|
1586
|
-
tmp_file=$(mktemp "${output_file}.tmp.XXXXXX")
|
|
1627
|
+
tmp_file=$(mktemp "${output_file}.tmp.XXXXXX") || { error "mktemp failed for db export"; return 1; }
|
|
1587
1628
|
jq -n \
|
|
1588
1629
|
--arg exported_at "$(now_iso)" \
|
|
1589
1630
|
--argjson events "$events_json" \
|
|
@@ -1670,7 +1711,9 @@ show_status() {
|
|
|
1670
1711
|
# Sync status
|
|
1671
1712
|
local device_id last_push last_pull
|
|
1672
1713
|
device_id=$(_db_query "SELECT value FROM _sync_metadata WHERE key = 'device_id';" || echo "not set")
|
|
1714
|
+
# shellcheck disable=SC2034
|
|
1673
1715
|
last_push=$(_db_query "SELECT value FROM _sync_metadata WHERE key = 'last_push_epoch';" || echo "never")
|
|
1716
|
+
# shellcheck disable=SC2034
|
|
1674
1717
|
last_pull=$(_db_query "SELECT value FROM _sync_metadata WHERE key = 'last_pull_epoch';" || echo "never")
|
|
1675
1718
|
local unsynced_events unsynced_costs
|
|
1676
1719
|
unsynced_events=$(_db_query "SELECT COUNT(*) FROM events WHERE synced = 0;" || echo "0")
|
package/scripts/sw-decide.sh
CHANGED
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
# ╚═══════════════════════════════════════════════════════════════════════════╝
|
|
6
6
|
set -euo pipefail
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
# shellcheck disable=SC2034
|
|
9
|
+
VERSION="3.3.0"
|
|
9
10
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
10
11
|
|
|
11
12
|
# ─── Dependencies ─────────────────────────────────────────────────────────────
|
|
@@ -17,8 +18,10 @@ source "$SCRIPT_DIR/lib/decide-scoring.sh"
|
|
|
17
18
|
source "$SCRIPT_DIR/lib/decide-autonomy.sh"
|
|
18
19
|
|
|
19
20
|
# ─── Config ───────────────────────────────────────────────────────────────────
|
|
21
|
+
# shellcheck disable=SC2034
|
|
20
22
|
DECISION_ENABLED=$(policy_get ".decision.enabled" "false")
|
|
21
23
|
DEDUP_WINDOW_DAYS=$(policy_get ".decision.dedup_window_days" "7")
|
|
24
|
+
# shellcheck disable=SC2034
|
|
22
25
|
OUTCOME_LEARNING=$(policy_get ".decision.outcome_learning_enabled" "true")
|
|
23
26
|
OUTCOME_MIN_SAMPLES=$(policy_get ".decision.outcome_min_samples" "10")
|
|
24
27
|
|
|
@@ -227,7 +230,9 @@ decide_run() {
|
|
|
227
230
|
while [[ $# -gt 0 ]]; do
|
|
228
231
|
case "$1" in
|
|
229
232
|
--dry-run) dry_run=true; shift ;;
|
|
230
|
-
--once)
|
|
233
|
+
--once)
|
|
234
|
+
# shellcheck disable=SC2034
|
|
235
|
+
once=true; shift ;;
|
|
231
236
|
*) shift ;;
|
|
232
237
|
esac
|
|
233
238
|
done
|
|
@@ -432,6 +437,7 @@ decide_log() {
|
|
|
432
437
|
local found=false
|
|
433
438
|
for i in $(seq 0 $((days - 1))); do
|
|
434
439
|
local date_str
|
|
440
|
+
# shellcheck disable=SC2106
|
|
435
441
|
date_str=$(date -u -v-${i}d +%Y-%m-%d 2>/dev/null || date -u -d "${i} days ago" +%Y-%m-%d 2>/dev/null || continue)
|
|
436
442
|
local log_file="${DECISIONS_DIR}/daily-log-${date_str}.jsonl"
|
|
437
443
|
[[ ! -f "$log_file" ]] && continue
|