shipwright-cli 2.1.2 → 2.2.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.
Files changed (129) hide show
  1. package/.claude/agents/devops-engineer.md +14 -12
  2. package/.claude/agents/doc-fleet-agent.md +99 -0
  3. package/.claude/agents/test-specialist.md +5 -3
  4. package/README.md +48 -27
  5. package/claude-code/CLAUDE.md.shipwright +2 -2
  6. package/config/policy.json +73 -0
  7. package/config/policy.schema.json +75 -0
  8. package/docs/AGI-PLATFORM-PLAN.md +122 -0
  9. package/docs/AGI-WHATS-NEXT.md +69 -0
  10. package/docs/KNOWN-ISSUES.md +1 -23
  11. package/docs/PLATFORM-TODO-BACKLOG.md +41 -0
  12. package/docs/PLATFORM-TODO-TRIAGE.md +56 -0
  13. package/docs/README.md +83 -0
  14. package/docs/TIPS.md +39 -2
  15. package/docs/config-policy.md +40 -0
  16. package/docs/definition-of-done.example.md +2 -0
  17. package/docs/patterns/README.md +5 -0
  18. package/docs/strategy/02-mission-and-brand.md +3 -3
  19. package/docs/strategy/README.md +4 -3
  20. package/docs/tmux-research/TMUX-AUDIT.md +2 -0
  21. package/docs/tmux-research/TMUX-RESEARCH-INDEX.md +17 -0
  22. package/package.json +3 -2
  23. package/scripts/lib/daemon-health.sh +32 -0
  24. package/scripts/lib/pipeline-quality.sh +23 -0
  25. package/scripts/lib/policy.sh +32 -0
  26. package/scripts/sw +5 -1
  27. package/scripts/sw-activity.sh +35 -46
  28. package/scripts/sw-adaptive.sh +30 -39
  29. package/scripts/sw-adversarial.sh +30 -36
  30. package/scripts/sw-architecture-enforcer.sh +30 -33
  31. package/scripts/sw-auth.sh +30 -42
  32. package/scripts/sw-autonomous.sh +60 -40
  33. package/scripts/sw-changelog.sh +29 -30
  34. package/scripts/sw-checkpoint.sh +30 -18
  35. package/scripts/sw-ci.sh +30 -42
  36. package/scripts/sw-cleanup.sh +32 -15
  37. package/scripts/sw-code-review.sh +26 -32
  38. package/scripts/sw-connect.sh +30 -19
  39. package/scripts/sw-context.sh +30 -19
  40. package/scripts/sw-cost.sh +30 -40
  41. package/scripts/sw-daemon.sh +66 -36
  42. package/scripts/sw-dashboard.sh +31 -40
  43. package/scripts/sw-db.sh +30 -20
  44. package/scripts/sw-decompose.sh +30 -38
  45. package/scripts/sw-deps.sh +30 -41
  46. package/scripts/sw-developer-simulation.sh +30 -36
  47. package/scripts/sw-discovery.sh +36 -19
  48. package/scripts/sw-doc-fleet.sh +822 -0
  49. package/scripts/sw-docs-agent.sh +30 -36
  50. package/scripts/sw-docs.sh +29 -31
  51. package/scripts/sw-doctor.sh +52 -20
  52. package/scripts/sw-dora.sh +29 -34
  53. package/scripts/sw-durable.sh +30 -20
  54. package/scripts/sw-e2e-orchestrator.sh +36 -21
  55. package/scripts/sw-eventbus.sh +30 -17
  56. package/scripts/sw-feedback.sh +30 -41
  57. package/scripts/sw-fix.sh +30 -40
  58. package/scripts/sw-fleet-discover.sh +30 -41
  59. package/scripts/sw-fleet-viz.sh +30 -20
  60. package/scripts/sw-fleet.sh +30 -40
  61. package/scripts/sw-github-app.sh +30 -41
  62. package/scripts/sw-github-checks.sh +30 -41
  63. package/scripts/sw-github-deploy.sh +30 -41
  64. package/scripts/sw-github-graphql.sh +30 -38
  65. package/scripts/sw-guild.sh +30 -37
  66. package/scripts/sw-heartbeat.sh +30 -19
  67. package/scripts/sw-hygiene.sh +134 -42
  68. package/scripts/sw-incident.sh +30 -39
  69. package/scripts/sw-init.sh +31 -14
  70. package/scripts/sw-instrument.sh +30 -41
  71. package/scripts/sw-intelligence.sh +39 -44
  72. package/scripts/sw-jira.sh +31 -41
  73. package/scripts/sw-launchd.sh +30 -17
  74. package/scripts/sw-linear.sh +31 -41
  75. package/scripts/sw-logs.sh +32 -17
  76. package/scripts/sw-loop.sh +32 -19
  77. package/scripts/sw-memory.sh +32 -43
  78. package/scripts/sw-mission-control.sh +31 -40
  79. package/scripts/sw-model-router.sh +30 -20
  80. package/scripts/sw-otel.sh +30 -20
  81. package/scripts/sw-oversight.sh +30 -36
  82. package/scripts/sw-patrol-meta.sh +31 -0
  83. package/scripts/sw-pipeline-composer.sh +30 -39
  84. package/scripts/sw-pipeline-vitals.sh +30 -44
  85. package/scripts/sw-pipeline.sh +275 -6388
  86. package/scripts/sw-pm.sh +31 -41
  87. package/scripts/sw-pr-lifecycle.sh +30 -42
  88. package/scripts/sw-predictive.sh +32 -34
  89. package/scripts/sw-prep.sh +30 -19
  90. package/scripts/sw-ps.sh +32 -17
  91. package/scripts/sw-public-dashboard.sh +30 -40
  92. package/scripts/sw-quality.sh +42 -40
  93. package/scripts/sw-reaper.sh +32 -15
  94. package/scripts/sw-recruit.sh +428 -48
  95. package/scripts/sw-regression.sh +30 -38
  96. package/scripts/sw-release-manager.sh +30 -38
  97. package/scripts/sw-release.sh +29 -31
  98. package/scripts/sw-remote.sh +31 -40
  99. package/scripts/sw-replay.sh +30 -18
  100. package/scripts/sw-retro.sh +33 -42
  101. package/scripts/sw-scale.sh +41 -24
  102. package/scripts/sw-security-audit.sh +30 -20
  103. package/scripts/sw-self-optimize.sh +33 -37
  104. package/scripts/sw-session.sh +31 -15
  105. package/scripts/sw-setup.sh +30 -16
  106. package/scripts/sw-standup.sh +30 -20
  107. package/scripts/sw-status.sh +33 -13
  108. package/scripts/sw-strategic.sh +55 -43
  109. package/scripts/sw-stream.sh +33 -37
  110. package/scripts/sw-swarm.sh +30 -21
  111. package/scripts/sw-team-stages.sh +30 -38
  112. package/scripts/sw-templates.sh +31 -16
  113. package/scripts/sw-testgen.sh +30 -31
  114. package/scripts/sw-tmux-pipeline.sh +29 -31
  115. package/scripts/sw-tmux-role-color.sh +31 -0
  116. package/scripts/sw-tmux-status.sh +31 -0
  117. package/scripts/sw-tmux.sh +31 -15
  118. package/scripts/sw-trace.sh +30 -19
  119. package/scripts/sw-tracker-github.sh +31 -0
  120. package/scripts/sw-tracker-jira.sh +31 -0
  121. package/scripts/sw-tracker-linear.sh +31 -0
  122. package/scripts/sw-tracker.sh +30 -40
  123. package/scripts/sw-triage.sh +68 -61
  124. package/scripts/sw-upgrade.sh +30 -16
  125. package/scripts/sw-ux.sh +30 -35
  126. package/scripts/sw-webhook.sh +30 -25
  127. package/scripts/sw-widgets.sh +30 -19
  128. package/scripts/sw-worktree.sh +32 -15
  129. package/tmux/templates/doc-fleet.json +43 -0
@@ -4,26 +4,41 @@
4
4
  # ║ ║
5
5
  # ║ Captures tmux pane scrollback and provides log browsing/search. ║
6
6
  # ╚═══════════════════════════════════════════════════════════════════════════╝
7
- VERSION="2.1.2"
7
+ VERSION="2.2.0"
8
8
  set -euo pipefail
9
9
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
10
10
 
11
- # ─── Colors ──────────────────────────────────────────────────────────────────
12
- CYAN='\033[38;2;0;212;255m'
13
- PURPLE='\033[38;2;124;58;237m'
14
- BLUE='\033[38;2;0;102;255m'
15
- GREEN='\033[38;2;74;222;128m'
16
- YELLOW='\033[38;2;250;204;21m'
17
- RED='\033[38;2;248;113;113m'
18
- DIM='\033[2m'
19
- BOLD='\033[1m'
20
- RESET='\033[0m'
21
-
22
- # ─── Helpers ─────────────────────────────────────────────────────────────────
23
- info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
24
- success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
25
- warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
26
- error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
11
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
+
13
+ # Canonical helpers (colors, output, events)
14
+ # shellcheck source=lib/helpers.sh
15
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
16
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
17
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
18
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
19
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
20
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
21
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
22
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
23
+ now_epoch() { date +%s; }
24
+ fi
25
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
26
+ emit_event() {
27
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
28
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
29
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
30
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
31
+ }
32
+ fi
33
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
34
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
35
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
36
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
37
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
38
+ RED="${RED:-\033[38;2;248;113;113m}"
39
+ DIM="${DIM:-\033[2m}"
40
+ BOLD="${BOLD:-\033[1m}"
41
+ RESET="${RESET:-\033[0m}"
27
42
 
28
43
  LOGS_DIR="$HOME/.shipwright/logs"
29
44
 
@@ -17,25 +17,38 @@ trap '' HUP
17
17
 
18
18
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
19
19
 
20
- # ─── Colors (matches shipwright theme) ──────────────────────────────────────────────
21
- CYAN='\033[38;2;0;212;255m'
22
- PURPLE='\033[38;2;124;58;237m'
23
- BLUE='\033[38;2;0;102;255m'
24
- GREEN='\033[38;2;74;222;128m'
25
- YELLOW='\033[38;2;250;204;21m'
26
- RED='\033[38;2;248;113;113m'
27
- DIM='\033[2m'
28
- BOLD='\033[1m'
29
- RESET='\033[0m'
30
-
31
20
  # ─── Cross-platform compatibility ──────────────────────────────────────────
32
21
  # shellcheck source=lib/compat.sh
33
22
  [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
34
-
35
- info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
36
- success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
37
- warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
38
- error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
23
+ # Canonical helpers (colors, output, events)
24
+ # shellcheck source=lib/helpers.sh
25
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
26
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
27
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
28
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
29
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
30
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
31
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
32
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
33
+ now_epoch() { date +%s; }
34
+ fi
35
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
36
+ emit_event() {
37
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
38
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
39
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
40
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
41
+ }
42
+ fi
43
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
44
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
45
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
46
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
47
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
48
+ RED="${RED:-\033[38;2;248;113;113m}"
49
+ DIM="${DIM:-\033[2m}"
50
+ BOLD="${BOLD:-\033[1m}"
51
+ RESET="${RESET:-\033[0m}"
39
52
 
40
53
  # ─── Defaults ─────────────────────────────────────────────────────────────────
41
54
  GOAL=""
@@ -58,7 +71,7 @@ MAX_RESTARTS=0
58
71
  SESSION_RESTART=false
59
72
  RESTART_COUNT=0
60
73
  REPO_OVERRIDE=""
61
- VERSION="2.1.2"
74
+ VERSION="2.2.0"
62
75
 
63
76
  # ─── Token Tracking ─────────────────────────────────────────────────────────
64
77
  LOOP_INPUT_TOKENS=0
@@ -1675,8 +1688,8 @@ compose_worker_prompt() {
1675
1688
  reviewer) role_desc="Focus on code review — look for bugs, security issues, edge cases in recent commits. Make fixes via commits." ;;
1676
1689
  tester) role_desc="Focus on test coverage — write new tests, fix failing tests, improve assertions and edge case coverage." ;;
1677
1690
  optimizer) role_desc="Focus on performance — profile hot paths, reduce complexity, optimize algorithms and data structures." ;;
1678
- docs) role_desc="Focus on documentation — update README, add docstrings, write usage guides for new features." ;;
1679
- security) role_desc="Focus on security — audit for vulnerabilities, fix injection risks, validate inputs, check auth boundaries." ;;
1691
+ docs|docs-writer) role_desc="Focus on documentation — update README, add docstrings, write usage guides for new features." ;;
1692
+ security|security-auditor) role_desc="Focus on security — audit for vulnerabilities, fix injection risks, validate inputs, check auth boundaries." ;;
1680
1693
  *) role_desc="Focus on: ${role}. Apply your expertise in this area to advance the goal." ;;
1681
1694
  esac
1682
1695
  fi
@@ -6,59 +6,48 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.1.2"
9
+ VERSION="2.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
- REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
-
13
- # ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
14
- CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
15
- PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
16
- BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
17
- GREEN='\033[38;2;74;222;128m' # success
18
- YELLOW='\033[38;2;250;204;21m' # warning
19
- RED='\033[38;2;248;113;113m' # error
20
- DIM='\033[2m'
21
- BOLD='\033[1m'
22
- RESET='\033[0m'
11
+ REPO_DIR="${REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
23
12
 
24
13
  # ─── Cross-platform compatibility ──────────────────────────────────────────
25
14
  # shellcheck source=lib/compat.sh
26
15
  [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
27
16
 
17
+ # Canonical helpers (colors, output, events)
18
+ # shellcheck source=lib/helpers.sh
19
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
20
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
21
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
22
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
23
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
24
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
25
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
26
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
27
+ now_epoch() { date +%s; }
28
+ fi
29
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
30
+ emit_event() {
31
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
32
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
34
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
35
+ }
36
+ fi
37
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
38
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
39
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
40
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
41
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
42
+ RED="${RED:-\033[38;2;248;113;113m}"
43
+ DIM="${DIM:-\033[2m}"
44
+ BOLD="${BOLD:-\033[1m}"
45
+ RESET="${RESET:-\033[0m}"
46
+
28
47
  # ─── Intelligence Engine (optional) ──────────────────────────────────────────
29
48
  # shellcheck source=sw-intelligence.sh
30
49
  [[ -f "$SCRIPT_DIR/sw-intelligence.sh" ]] && source "$SCRIPT_DIR/sw-intelligence.sh"
31
50
 
32
- # ─── Output Helpers ─────────────────────────────────────────────────────────
33
- info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
34
- success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
35
- warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
36
- error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
37
-
38
- now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
39
- now_epoch() { date +%s; }
40
-
41
- # ─── Structured Event Log ──────────────────────────────────────────────────
42
- EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
43
-
44
- emit_event() {
45
- local event_type="$1"
46
- shift
47
- local json_fields=""
48
- for kv in "$@"; do
49
- local key="${kv%%=*}"
50
- local val="${kv#*=}"
51
- if [[ "$val" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
52
- json_fields="${json_fields},\"${key}\":${val}"
53
- else
54
- val="${val//\"/\\\"}"
55
- json_fields="${json_fields},\"${key}\":\"${val}\""
56
- fi
57
- done
58
- mkdir -p "${HOME}/.shipwright"
59
- echo "{\"ts\":\"$(now_iso)\",\"ts_epoch\":$(now_epoch),\"type\":\"${event_type}\"${json_fields}}" >> "$EVENTS_FILE"
60
- }
61
-
62
51
  # ─── Memory Storage Paths ──────────────────────────────────────────────────
63
52
  MEMORY_ROOT="${HOME}/.shipwright/memory"
64
53
  GLOBAL_MEMORY="${MEMORY_ROOT}/global.json"
@@ -7,33 +7,43 @@
7
7
  set -euo pipefail
8
8
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
9
9
 
10
- VERSION="2.1.2"
10
+ VERSION="2.2.0"
11
11
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
12
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
13
13
 
14
- # ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
15
- CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
16
- PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
17
- BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
18
- GREEN='\033[38;2;74;222;128m' # success
19
- YELLOW='\033[38;2;250;204;21m' # warning
20
- RED='\033[38;2;248;113;113m' # error
21
- DIM='\033[2m'
22
- BOLD='\033[1m'
23
- RESET='\033[0m'
24
-
25
14
  # ─── Cross-platform compatibility ──────────────────────────────────────────
26
15
  # shellcheck source=lib/compat.sh
27
16
  [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
28
17
 
29
- # ─── Output Helpers ─────────────────────────────────────────────────────────
30
- info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
31
- success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
32
- warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
33
- error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
34
-
35
- now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
36
- now_epoch() { date +%s; }
18
+ # Canonical helpers (colors, output, events)
19
+ # shellcheck source=lib/helpers.sh
20
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
21
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
22
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
23
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
24
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
25
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
26
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
27
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
28
+ now_epoch() { date +%s; }
29
+ fi
30
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
31
+ emit_event() {
32
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
33
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
34
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
35
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
36
+ }
37
+ fi
38
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
39
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
40
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
41
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
42
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
43
+ RED="${RED:-\033[38;2;248;113;113m}"
44
+ DIM="${DIM:-\033[2m}"
45
+ BOLD="${BOLD:-\033[1m}"
46
+ RESET="${RESET:-\033[0m}"
37
47
 
38
48
  format_duration() {
39
49
  local secs="$1"
@@ -46,29 +56,10 @@ format_duration() {
46
56
  fi
47
57
  }
48
58
 
49
- # ─── Structured Event Log ──────────────────────────────────────────────────
59
+ # ─── Daemon State ───────────────────────────────────────────────────────────
50
60
  EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
51
61
  DAEMON_STATE="${HOME}/.shipwright/daemon-state.json"
52
62
 
53
- emit_event() {
54
- local event_type="$1"
55
- shift
56
- local json_fields=""
57
- for kv in "$@"; do
58
- local key="${kv%%=*}"
59
- local val="${kv#*=}"
60
- if [[ "$val" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
61
- json_fields="${json_fields},\"${key}\":${val}"
62
- else
63
- local escaped_val
64
- escaped_val=$(printf '%s' "$val" | jq -Rs '.' 2>/dev/null || printf '"%s"' "${val//\"/\\\"}")
65
- json_fields="${json_fields},\"${key}\":${escaped_val}"
66
- fi
67
- done
68
- mkdir -p "${HOME}/.shipwright"
69
- echo "{\"ts\":\"$(now_iso)\",\"ts_epoch\":$(now_epoch),\"type\":\"${event_type}\"${json_fields}}" >> "$EVENTS_FILE"
70
- }
71
-
72
63
  # ─── Daemon State Access ───────────────────────────────────────────────────
73
64
  load_daemon_state() {
74
65
  if [[ ! -f "$DAEMON_STATE" ]]; then
@@ -7,33 +7,43 @@
7
7
  set -euo pipefail
8
8
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
9
9
 
10
- VERSION="2.1.2"
10
+ VERSION="2.2.0"
11
11
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
12
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
13
13
 
14
- # ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
15
- CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
16
- PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
17
- BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
18
- GREEN='\033[38;2;74;222;128m' # success
19
- YELLOW='\033[38;2;250;204;21m' # warning
20
- RED='\033[38;2;248;113;113m' # error
21
- DIM='\033[2m'
22
- BOLD='\033[1m'
23
- RESET='\033[0m'
24
-
25
14
  # ─── Cross-platform compatibility ──────────────────────────────────────────
26
15
  # shellcheck source=lib/compat.sh
27
16
  [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
28
17
 
29
- # ─── Output Helpers ─────────────────────────────────────────────────────────
30
- info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
31
- success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
32
- warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
33
- error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
34
-
35
- now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
36
- now_epoch() { date +%s; }
18
+ # Canonical helpers (colors, output, events)
19
+ # shellcheck source=lib/helpers.sh
20
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
21
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
22
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
23
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
24
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
25
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
26
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
27
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
28
+ now_epoch() { date +%s; }
29
+ fi
30
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
31
+ emit_event() {
32
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
33
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
34
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
35
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
36
+ }
37
+ fi
38
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
39
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
40
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
41
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
42
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
43
+ RED="${RED:-\033[38;2;248;113;113m}"
44
+ DIM="${DIM:-\033[2m}"
45
+ BOLD="${BOLD:-\033[1m}"
46
+ RESET="${RESET:-\033[0m}"
37
47
 
38
48
  # ─── File Paths ────────────────────────────────────────────────────────────
39
49
  MODEL_ROUTING_CONFIG="${HOME}/.shipwright/model-routing.json"
@@ -6,33 +6,43 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="2.1.2"
9
+ VERSION="2.2.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12
 
13
- # ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
14
- CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
15
- PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
16
- BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
17
- GREEN='\033[38;2;74;222;128m' # success
18
- YELLOW='\033[38;2;250;204;21m' # warning
19
- RED='\033[38;2;248;113;113m' # error
20
- DIM='\033[2m'
21
- BOLD='\033[1m'
22
- RESET='\033[0m'
23
-
24
13
  # ─── Cross-platform compatibility ──────────────────────────────────────────
25
14
  # shellcheck source=lib/compat.sh
26
15
  [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
27
16
 
28
- # ─── Output Helpers ─────────────────────────────────────────────────────────
29
- info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
30
- success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
31
- warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
32
- error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
33
-
34
- now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
35
- now_epoch() { date +%s; }
17
+ # Canonical helpers (colors, output, events)
18
+ # shellcheck source=lib/helpers.sh
19
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
20
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
21
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
22
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
23
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
24
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
25
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
26
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
27
+ now_epoch() { date +%s; }
28
+ fi
29
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
30
+ emit_event() {
31
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
32
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
34
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
35
+ }
36
+ fi
37
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
38
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
39
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
40
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
41
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
42
+ RED="${RED:-\033[38;2;248;113;113m}"
43
+ DIM="${DIM:-\033[2m}"
44
+ BOLD="${BOLD:-\033[1m}"
45
+ RESET="${RESET:-\033[0m}"
36
46
 
37
47
  # ─── State Directories ──────────────────────────────────────────────────────
38
48
  OTEL_DIR="${HOME}/.shipwright/otel"
@@ -7,52 +7,46 @@
7
7
  set -euo pipefail
8
8
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
9
9
 
10
- VERSION="2.1.2"
10
+ VERSION="2.2.0"
11
11
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
12
12
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
13
13
 
14
- # ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
15
- CYAN='\033[38;2;0;212;255m' # #00d4ff — primary accent
16
- PURPLE='\033[38;2;124;58;237m' # #7c3aed — secondary
17
- BLUE='\033[38;2;0;102;255m' # #0066ff — tertiary
18
- GREEN='\033[38;2;74;222;128m' # success
19
- YELLOW='\033[38;2;250;204;21m' # warning
20
- RED='\033[38;2;248;113;113m' # error
21
- DIM='\033[2m'
22
- BOLD='\033[1m'
23
- RESET='\033[0m'
24
-
25
14
  # ─── Cross-platform compatibility ──────────────────────────────────────────
26
15
  # shellcheck source=lib/compat.sh
27
16
  [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
28
-
29
- # ─── Output Helpers ─────────────────────────────────────────────────────────
30
- info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
31
- success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
32
- warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
33
- error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
34
-
35
- now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
36
- now_epoch() { date +%s; }
17
+ # Canonical helpers (colors, output, events)
18
+ # shellcheck source=lib/helpers.sh
19
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
20
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
21
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
22
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
23
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
24
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
25
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
26
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
27
+ now_epoch() { date +%s; }
28
+ fi
29
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
30
+ emit_event() {
31
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
32
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
33
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
34
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
35
+ }
36
+ fi
37
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
38
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
39
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
40
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
41
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
42
+ RED="${RED:-\033[38;2;248;113;113m}"
43
+ DIM="${DIM:-\033[2m}"
44
+ BOLD="${BOLD:-\033[1m}"
45
+ RESET="${RESET:-\033[0m}"
37
46
 
38
47
  # ─── Structured Event Log ────────────────────────────────────────────────
39
48
  EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
40
49
 
41
- emit_event() {
42
- local event_type="$1"; shift
43
- local json_fields=""
44
- for kv in "$@"; do
45
- local key="${kv%%=*}"; local val="${kv#*=}"
46
- if [[ "$val" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
47
- json_fields="${json_fields},\"${key}\":${val}"
48
- else
49
- val="${val//\"/\\\"}"; json_fields="${json_fields},\"${key}\":\"${val}\""
50
- fi
51
- done
52
- mkdir -p "${HOME}/.shipwright"
53
- echo "{\"ts\":\"$(now_iso)\",\"ts_epoch\":$(now_epoch),\"type\":\"${event_type}\"${json_fields}}" >> "$EVENTS_FILE"
54
- }
55
-
56
50
  # ─── State & Configuration ────────────────────────────────────────────────
57
51
  OVERSIGHT_ROOT="${HOME}/.shipwright/oversight"
58
52
  BOARD_CONFIG="${OVERSIGHT_ROOT}/config.json"
@@ -6,6 +6,37 @@
6
6
  # NOTE: This file is sourced (not executed). Do NOT add set -euo pipefail.
7
7
  # All functions from the parent (sw-daemon.sh) are available.
8
8
 
9
+ SCRIPT_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
10
+ # Canonical helpers (colors, output, events)
11
+ # shellcheck source=lib/helpers.sh
12
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
13
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
14
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
15
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
16
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
17
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
18
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
19
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
20
+ now_epoch() { date +%s; }
21
+ fi
22
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
23
+ emit_event() {
24
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
25
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
26
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
27
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
28
+ }
29
+ fi
30
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
31
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
32
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
33
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
34
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
35
+ RED="${RED:-\033[38;2;248;113;113m}"
36
+ DIM="${DIM:-\033[2m}"
37
+ BOLD="${BOLD:-\033[1m}"
38
+ RESET="${RESET:-\033[0m}"
39
+
9
40
  # ─── Helper: Create issue if not duplicate ─────────────────────────────────
10
41
  patrol_meta_create_issue() {
11
42
  local title="$1"