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
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
|
|
@@ -812,7 +825,9 @@ add_event() {
|
|
|
812
825
|
|
|
813
826
|
# Try SQLite first
|
|
814
827
|
if db_available; then
|
|
815
|
-
_db_exec "INSERT OR IGNORE INTO events (ts, ts_epoch, type, job_id, stage, status, duration_secs, metadata, created_at, synced) VALUES ('${ts}', ${ts_epoch}, '${event_type}', '${job_id}', '${stage}', '${status}', ${duration_secs}, '${metadata}', '${ts}', 0);"
|
|
828
|
+
if ! _db_exec "INSERT OR IGNORE INTO events (ts, ts_epoch, type, job_id, stage, status, duration_secs, metadata, created_at, synced) VALUES ('${ts}', ${ts_epoch}, '${event_type}', '${job_id}', '${stage}', '${status}', ${duration_secs}, '${metadata}', '${ts}', 0);" 2>/dev/null; then
|
|
829
|
+
warn "db_add_event: SQLite insert failed for event type=${event_type}" >&2
|
|
830
|
+
fi
|
|
816
831
|
fi
|
|
817
832
|
|
|
818
833
|
# Always write to JSONL for backward compat (dual-write period)
|
|
@@ -934,7 +949,9 @@ db_dequeue_next() {
|
|
|
934
949
|
next=$(_db_query "SELECT issue_key FROM daemon_queue ORDER BY added_at ASC LIMIT 1;" || echo "")
|
|
935
950
|
if [[ -n "$next" ]]; then
|
|
936
951
|
escaped="${next//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
937
|
-
_db_exec "DELETE FROM daemon_queue WHERE issue_key = '${escaped}';" 2>/dev/null
|
|
952
|
+
if ! _db_exec "DELETE FROM daemon_queue WHERE issue_key = '${escaped}';" 2>/dev/null; then
|
|
953
|
+
warn "db_dequeue_next: failed to delete queue entry for ${next}" >&2
|
|
954
|
+
fi
|
|
938
955
|
echo "$next"
|
|
939
956
|
fi
|
|
940
957
|
}
|
|
@@ -1178,8 +1195,12 @@ db_save_pattern() {
|
|
|
1178
1195
|
db_query_patterns() {
|
|
1179
1196
|
local repo_hash="$1" pattern_type="${2:-}" limit="${3:-20}"
|
|
1180
1197
|
if ! db_available; then echo "[]"; return 0; fi
|
|
1198
|
+
repo_hash="${repo_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1181
1199
|
local where="WHERE repo_hash = '$repo_hash'"
|
|
1182
|
-
[[ -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
|
|
1183
1204
|
_db_query -json "SELECT * FROM memory_patterns $where ORDER BY frequency DESC, last_seen_at DESC LIMIT $limit;" || echo "[]"
|
|
1184
1205
|
}
|
|
1185
1206
|
|
|
@@ -1187,6 +1208,8 @@ db_query_patterns() {
|
|
|
1187
1208
|
db_save_decision() {
|
|
1188
1209
|
local repo_hash="$1" decision_type="$2" context="$3" decision="$4" metadata="${5:-}"
|
|
1189
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}"
|
|
1190
1213
|
context="${context//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1191
1214
|
decision="${decision//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1192
1215
|
metadata="${metadata//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
@@ -1197,17 +1220,24 @@ db_save_decision() {
|
|
|
1197
1220
|
db_update_decision_outcome() {
|
|
1198
1221
|
local decision_id="$1" outcome="$2" confidence="${3:-}"
|
|
1199
1222
|
if ! db_available; then return 1; fi
|
|
1223
|
+
# Validate numeric IDs to prevent injection
|
|
1224
|
+
[[ ! "$decision_id" =~ ^[0-9]+$ ]] && return 1
|
|
1200
1225
|
outcome="${outcome//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1201
|
-
local set_clause
|
|
1202
|
-
|
|
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"
|
|
1203
1229
|
_db_exec "UPDATE memory_decisions SET $set_clause WHERE id = $decision_id;"
|
|
1204
1230
|
}
|
|
1205
1231
|
|
|
1206
1232
|
db_query_decisions() {
|
|
1207
1233
|
local repo_hash="$1" decision_type="${2:-}" limit="${3:-20}"
|
|
1208
1234
|
if ! db_available; then echo "[]"; return 0; fi
|
|
1235
|
+
repo_hash="${repo_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1209
1236
|
local where="WHERE repo_hash = '$repo_hash'"
|
|
1210
|
-
[[ -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
|
|
1211
1241
|
_db_query -json "SELECT * FROM memory_decisions $where ORDER BY updated_at DESC LIMIT $limit;" || echo "[]"
|
|
1212
1242
|
}
|
|
1213
1243
|
|
|
@@ -1215,7 +1245,10 @@ db_query_decisions() {
|
|
|
1215
1245
|
db_save_embedding() {
|
|
1216
1246
|
local content_hash="$1" source_type="$2" content_text="$3" repo_hash="${4:-}"
|
|
1217
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}"
|
|
1218
1250
|
content_text="${content_text//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1251
|
+
repo_hash="${repo_hash//$_SQL_SQ/$_SQL_SQ$_SQL_SQ}"
|
|
1219
1252
|
_db_exec "INSERT OR IGNORE INTO memory_embeddings (content_hash, source_type, content_text, repo_hash, created_at)
|
|
1220
1253
|
VALUES ('$content_hash', '$source_type', '$content_text', '$repo_hash', '$(now_iso)');"
|
|
1221
1254
|
}
|
|
@@ -1224,8 +1257,14 @@ db_query_embeddings() {
|
|
|
1224
1257
|
local source_type="${1:-}" repo_hash="${2:-}" limit="${3:-50}"
|
|
1225
1258
|
if ! db_available; then echo "[]"; return 0; fi
|
|
1226
1259
|
local where="WHERE 1=1"
|
|
1227
|
-
[[ -n "$source_type" ]]
|
|
1228
|
-
|
|
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
|
|
1229
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 "[]"
|
|
1230
1269
|
}
|
|
1231
1270
|
|
|
@@ -1364,8 +1403,10 @@ db_sync_push() {
|
|
|
1364
1403
|
# Push via HTTP
|
|
1365
1404
|
local response
|
|
1366
1405
|
local auth_header=""
|
|
1406
|
+
# shellcheck disable=SC2089
|
|
1367
1407
|
[[ -n "${SYNC_TOKEN:-}" ]] && auth_header="-H 'Authorization: Bearer ${SYNC_TOKEN}'"
|
|
1368
1408
|
|
|
1409
|
+
# shellcheck disable=SC2090
|
|
1369
1410
|
response=$(curl -s --connect-timeout 10 --max-time 30 -w "%{http_code}" -o /dev/null \
|
|
1370
1411
|
-X POST "${SYNC_URL}/api/sync/push" \
|
|
1371
1412
|
-H "Content-Type: application/json" \
|
|
@@ -1396,9 +1437,11 @@ db_sync_pull() {
|
|
|
1396
1437
|
last_sync=$(_db_query "SELECT value FROM _sync_metadata WHERE key = 'last_pull_epoch';" || echo "0")
|
|
1397
1438
|
|
|
1398
1439
|
local auth_header=""
|
|
1440
|
+
# shellcheck disable=SC2089
|
|
1399
1441
|
[[ -n "${SYNC_TOKEN:-}" ]] && auth_header="-H 'Authorization: Bearer ${SYNC_TOKEN}'"
|
|
1400
1442
|
|
|
1401
1443
|
local response_body
|
|
1444
|
+
# shellcheck disable=SC2090
|
|
1402
1445
|
response_body=$(curl -s --connect-timeout 10 --max-time 30 \
|
|
1403
1446
|
"${SYNC_URL}/api/sync/pull?since=${last_sync}" \
|
|
1404
1447
|
-H "Accept: application/json" \
|
|
@@ -1447,6 +1490,7 @@ migrate_json_data() {
|
|
|
1447
1490
|
info "Importing events from ${EVENTS_FILE}..."
|
|
1448
1491
|
local evt_count=0
|
|
1449
1492
|
local evt_skipped=0
|
|
1493
|
+
# shellcheck disable=SC2106
|
|
1450
1494
|
while IFS= read -r line; do
|
|
1451
1495
|
[[ -z "$line" ]] && continue
|
|
1452
1496
|
local e_ts e_epoch e_type e_job e_stage e_status
|
|
@@ -1480,7 +1524,8 @@ migrate_json_data() {
|
|
|
1480
1524
|
j_result=$(echo "$job" | jq -r '.result // ""')
|
|
1481
1525
|
j_dur=$(echo "$job" | jq -r '.duration // ""')
|
|
1482
1526
|
j_at=$(echo "$job" | jq -r '.completed_at // ""')
|
|
1483
|
-
local j_id
|
|
1527
|
+
local j_id
|
|
1528
|
+
j_id="migrated-${j_issue}-$(echo "$j_at" | tr -dc '0-9' | tail -c 10)"
|
|
1484
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))
|
|
1485
1530
|
done < <(jq -c '.completed[]' "$DAEMON_STATE_FILE" 2>/dev/null)
|
|
1486
1531
|
|
|
@@ -1579,7 +1624,7 @@ export_db() {
|
|
|
1579
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 "[]")
|
|
1580
1625
|
|
|
1581
1626
|
local tmp_file
|
|
1582
|
-
tmp_file=$(mktemp "${output_file}.tmp.XXXXXX")
|
|
1627
|
+
tmp_file=$(mktemp "${output_file}.tmp.XXXXXX") || { error "mktemp failed for db export"; return 1; }
|
|
1583
1628
|
jq -n \
|
|
1584
1629
|
--arg exported_at "$(now_iso)" \
|
|
1585
1630
|
--argjson events "$events_json" \
|
|
@@ -1666,7 +1711,9 @@ show_status() {
|
|
|
1666
1711
|
# Sync status
|
|
1667
1712
|
local device_id last_push last_pull
|
|
1668
1713
|
device_id=$(_db_query "SELECT value FROM _sync_metadata WHERE key = 'device_id';" || echo "not set")
|
|
1714
|
+
# shellcheck disable=SC2034
|
|
1669
1715
|
last_push=$(_db_query "SELECT value FROM _sync_metadata WHERE key = 'last_push_epoch';" || echo "never")
|
|
1716
|
+
# shellcheck disable=SC2034
|
|
1670
1717
|
last_pull=$(_db_query "SELECT value FROM _sync_metadata WHERE key = 'last_pull_epoch';" || echo "never")
|
|
1671
1718
|
local unsynced_events unsynced_costs
|
|
1672
1719
|
unsynced_events=$(_db_query "SELECT COUNT(*) FROM events WHERE synced = 0;" || echo "0")
|
|
@@ -1829,8 +1876,12 @@ main() {
|
|
|
1829
1876
|
ensure_db_dir
|
|
1830
1877
|
init_schema
|
|
1831
1878
|
# Set schema version
|
|
1832
|
-
_db_exec "INSERT OR REPLACE INTO _schema (version, created_at, applied_at) VALUES (${SCHEMA_VERSION}, '$(now_iso)', '$(now_iso)');" 2>/dev/null
|
|
1833
|
-
|
|
1879
|
+
if ! _db_exec "INSERT OR REPLACE INTO _schema (version, created_at, applied_at) VALUES (${SCHEMA_VERSION}, '$(now_iso)', '$(now_iso)');" 2>/dev/null; then
|
|
1880
|
+
warn "db init: failed to write schema version ${SCHEMA_VERSION}" >&2
|
|
1881
|
+
fi
|
|
1882
|
+
if ! _db_exec "INSERT OR IGNORE INTO _sync_metadata (key, value, updated_at) VALUES ('device_id', '$(uname -n)-$$-$(now_epoch)', '$(now_iso)');" 2>/dev/null; then
|
|
1883
|
+
warn "db init: failed to write device_id metadata" >&2
|
|
1884
|
+
fi
|
|
1834
1885
|
success "Database initialized at ${DB_FILE} (WAL mode, schema v${SCHEMA_VERSION})"
|
|
1835
1886
|
;;
|
|
1836
1887
|
migrate)
|
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
|