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
@@ -6,32 +6,42 @@
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
-
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"; }
16
+ # Canonical helpers (colors, output, events)
17
+ # shellcheck source=lib/helpers.sh
18
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
19
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
20
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
21
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
22
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
23
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
24
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
25
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
26
+ now_epoch() { date +%s; }
27
+ fi
28
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
29
+ emit_event() {
30
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
31
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
32
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
33
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
34
+ }
35
+ fi
36
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
37
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
38
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
39
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
40
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
41
+ RED="${RED:-\033[38;2;248;113;113m}"
42
+ DIM="${DIM:-\033[2m}"
43
+ BOLD="${BOLD:-\033[1m}"
44
+ RESET="${RESET:-\033[0m}"
35
45
 
36
46
  # ─── Audit State ───────────────────────────────────────────────────────────
37
47
  FINDINGS=()
@@ -6,54 +6,47 @@
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
- info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
29
- success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
30
- warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
31
- error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
32
-
33
- now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
34
- 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}"
35
46
 
36
47
  # ─── Structured Event Log ────────────────────────────────────────────────────
37
48
  EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
38
49
 
39
- emit_event() {
40
- local event_type="$1"
41
- shift
42
- local json_fields=""
43
- for kv in "$@"; do
44
- local key="${kv%%=*}"
45
- local val="${kv#*=}"
46
- if [[ "$val" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
47
- json_fields="${json_fields},\"${key}\":${val}"
48
- else
49
- val="${val//\"/\\\"}"
50
- json_fields="${json_fields},\"${key}\":\"${val}\""
51
- fi
52
- done
53
- mkdir -p "${HOME}/.shipwright"
54
- echo "{\"ts\":\"$(now_iso)\",\"ts_epoch\":$(now_epoch),\"type\":\"${event_type}\"${json_fields}}" >> "$EVENTS_FILE"
55
- }
56
-
57
50
  # ─── Storage Paths ───────────────────────────────────────────────────────────
58
51
  OPTIMIZATION_DIR="${HOME}/.shipwright/optimization"
59
52
  OUTCOMES_FILE="${OPTIMIZATION_DIR}/outcomes.jsonl"
@@ -176,6 +169,9 @@ optimize_analyze_outcome() {
176
169
  rm -f "$tmp_outcome"
177
170
  echo "$outcome_line" >> "$OUTCOMES_FILE"
178
171
 
172
+ # Rotate outcomes file to prevent unbounded growth
173
+ type rotate_jsonl &>/dev/null 2>&1 && rotate_jsonl "$OUTCOMES_FILE" 10000
174
+
179
175
  # Record GitHub CI metrics alongside outcome
180
176
  local gh_ci_metrics
181
177
  gh_ci_metrics=$(_optimize_github_metrics 2>/dev/null || echo "{}")
@@ -8,29 +8,45 @@
8
8
  # ║ Supports --template to scaffold from a team template and --terminal ║
9
9
  # ║ to select a terminal adapter (tmux, iterm2, wezterm). ║
10
10
  # ╚═══════════════════════════════════════════════════════════════════════════╝
11
- VERSION="2.1.2"
11
+ VERSION="2.2.0"
12
12
  set -euo pipefail
13
13
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
14
14
 
15
15
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
16
 
17
- # ─── Colors ──────────────────────────────────────────────────────────────────
18
- CYAN='\033[38;2;0;212;255m'
19
- PURPLE='\033[38;2;124;58;237m'
20
- GREEN='\033[38;2;74;222;128m'
21
- YELLOW='\033[38;2;250;204;21m'
22
- RED='\033[38;2;248;113;113m'
23
- DIM='\033[2m'
24
- BOLD='\033[1m'
25
- RESET='\033[0m'
26
-
27
17
  # ─── Cross-platform compatibility ──────────────────────────────────────────
28
18
  # shellcheck source=lib/compat.sh
29
19
  [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
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; }
20
+
21
+ # Canonical helpers (colors, output, events)
22
+ # shellcheck source=lib/helpers.sh
23
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
24
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
25
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
26
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
27
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
28
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
29
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
30
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
31
+ now_epoch() { date +%s; }
32
+ fi
33
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
34
+ emit_event() {
35
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
36
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
37
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
38
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
39
+ }
40
+ fi
41
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
42
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
43
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
44
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
45
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
46
+ RED="${RED:-\033[38;2;248;113;113m}"
47
+ DIM="${DIM:-\033[2m}"
48
+ BOLD="${BOLD:-\033[1m}"
49
+ RESET="${RESET:-\033[0m}"
34
50
 
35
51
  # ─── Parse Arguments ────────────────────────────────────────────────────────
36
52
 
@@ -10,30 +10,44 @@
10
10
  set -euo pipefail
11
11
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
12
12
 
13
- VERSION="2.1.2"
13
+ VERSION="2.2.0"
14
14
 
15
15
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
16
16
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
17
17
 
18
- # ─── Colors ──────────────────────────────────────────────────────────────────
19
- CYAN='\033[38;2;0;212;255m'
20
- PURPLE='\033[38;2;124;58;237m'
21
- GREEN='\033[38;2;74;222;128m'
22
- YELLOW='\033[38;2;250;204;21m'
23
- RED='\033[38;2;248;113;113m'
24
- DIM='\033[2m'
25
- BOLD='\033[1m'
26
- RESET='\033[0m'
27
-
28
18
  # ─── Cross-platform compatibility ──────────────────────────────────────────
29
19
  # shellcheck source=lib/compat.sh
30
20
  [[ -f "$SCRIPT_DIR/lib/compat.sh" ]] && source "$SCRIPT_DIR/lib/compat.sh"
31
21
 
32
- # ─── 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; }
22
+ # Canonical helpers (colors, output, events)
23
+ # shellcheck source=lib/helpers.sh
24
+ [[ -f "$SCRIPT_DIR/lib/helpers.sh" ]] && source "$SCRIPT_DIR/lib/helpers.sh"
25
+ # Fallbacks when helpers not loaded (e.g. test env with overridden SCRIPT_DIR)
26
+ [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "\033[38;2;0;212;255m\033[1m▸\033[0m $*"; }
27
+ [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "\033[38;2;74;222;128m\033[1m✓\033[0m $*"; }
28
+ [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "\033[38;2;250;204;21m\033[1m⚠\033[0m $*"; }
29
+ [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m $*" >&2; }
30
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
31
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
32
+ now_epoch() { date +%s; }
33
+ fi
34
+ if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
35
+ emit_event() {
36
+ local event_type="$1"; shift; mkdir -p "${HOME}/.shipwright"
37
+ local payload="{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"$event_type\""
38
+ while [[ $# -gt 0 ]]; do local key="${1%%=*}" val="${1#*=}"; payload="${payload},\"${key}\":\"${val}\""; shift; done
39
+ echo "${payload}}" >> "${HOME}/.shipwright/events.jsonl"
40
+ }
41
+ fi
42
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
43
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
44
+ BLUE="${BLUE:-\033[38;2;0;102;255m}"
45
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
46
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
47
+ RED="${RED:-\033[38;2;248;113;113m}"
48
+ DIM="${DIM:-\033[2m}"
49
+ BOLD="${BOLD:-\033[1m}"
50
+ RESET="${RESET:-\033[0m}"
37
51
 
38
52
  PASS=0
39
53
  WARN=0
@@ -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
  # ─── Constants ──────────────────────────────────────────────────────────────
38
48
  STANDUP_DIR="${HOME}/.shipwright/standups"
@@ -4,26 +4,46 @@
4
4
  # ║ ║
5
5
  # ║ Shows running teams, agent windows, and task progress. ║
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
11
  # ─── Cross-platform compatibility ──────────────────────────────────────────
23
- _COMPAT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/lib/compat.sh"
12
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
13
+ _COMPAT="$SCRIPT_DIR/lib/compat.sh"
24
14
  # shellcheck source=lib/compat.sh
25
15
  [[ -f "$_COMPAT" ]] && source "$_COMPAT"
26
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
+
27
47
  # ─── Argument Parsing ─────────────────────────────────────────────────────────
28
48
  JSON_OUTPUT="false"
29
49
  while [[ $# -gt 0 ]]; do
@@ -7,67 +7,61 @@
7
7
  # When sourced, do NOT add set -euo pipefail — the parent handles that.
8
8
  # When run directly, main() sets up the error handling.
9
9
 
10
- VERSION="2.1.2"
11
-
12
- # ─── Colors (matches Seth's tmux theme) ─────────────────────────────────────
13
- CYAN='\033[38;2;0;212;255m'
14
- PURPLE='\033[38;2;124;58;237m'
15
- BLUE='\033[38;2;0;102;255m'
16
- GREEN='\033[38;2;74;222;128m'
17
- YELLOW='\033[38;2;250;204;21m'
18
- RED='\033[38;2;248;113;113m'
19
- DIM='\033[2m'
20
- BOLD='\033[1m'
21
- RESET='\033[0m'
22
-
23
- # ─── Helpers (define fallbacks if not provided by parent) ─────────────────────
24
- # When sourced by sw-daemon.sh, these are already defined. When run standalone
25
- # or sourced by tests, we define them here.
26
- [[ "$(type -t info 2>/dev/null)" == "function" ]] || info() { echo -e "${CYAN}${BOLD}▸${RESET} $*"; }
27
- [[ "$(type -t success 2>/dev/null)" == "function" ]] || success() { echo -e "${GREEN}${BOLD}✓${RESET} $*"; }
28
- [[ "$(type -t warn 2>/dev/null)" == "function" ]] || warn() { echo -e "${YELLOW}${BOLD}⚠${RESET} $*"; }
29
- [[ "$(type -t error 2>/dev/null)" == "function" ]] || error() { echo -e "${RED}${BOLD}✗${RESET} $*" >&2; }
30
- [[ "$(type -t now_epoch 2>/dev/null)" == "function" ]] || now_epoch() { date +%s; }
31
- [[ "$(type -t now_iso 2>/dev/null)" == "function" ]] || now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
10
+ VERSION="2.2.0"
32
11
 
33
12
  # ─── Paths (set defaults if not provided by parent) ──────────────────────────
34
13
  SCRIPT_DIR="${SCRIPT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)}"
35
14
  REPO_DIR="${REPO_DIR:-$(cd "$SCRIPT_DIR/.." && pwd)}"
36
15
  EVENTS_FILE="${EVENTS_FILE:-${HOME}/.shipwright/events.jsonl}"
37
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, sourced by daemon)
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; }
38
25
  if [[ "$(type -t emit_event 2>/dev/null)" != "function" ]]; then
39
- emit_event() {
40
- local event_type="$1"
41
- shift
42
- local json_fields=""
43
- for kv in "$@"; do
44
- local key="${kv%%=*}"
45
- local val="${kv#*=}"
46
- if [[ "$val" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
47
- json_fields="${json_fields},\"${key}\":${val}"
48
- else
49
- local escaped_val
50
- escaped_val=$(printf '%s' "$val" | jq -Rs '.' 2>/dev/null || printf '"%s"' "${val//\"/\\\"}")
51
- json_fields="${json_fields},\"${key}\":${escaped_val}"
52
- fi
53
- done
54
- mkdir -p "${HOME}/.shipwright"
55
- echo "{\"ts\":\"$(now_iso)\",\"ts_epoch\":$(now_epoch),\"type\":\"${event_type}\"${json_fields}}" >> "$EVENTS_FILE"
56
- }
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
+ }
57
32
  fi
58
-
59
- # ─── Constants ────────────────────────────────────────────────────────────────
33
+ if [[ "$(type -t now_iso 2>/dev/null)" != "function" ]]; then
34
+ now_iso() { date -u +"%Y-%m-%dT%H:%M:%SZ"; }
35
+ now_epoch() { date +%s; }
36
+ fi
37
+ CYAN="${CYAN:-\033[38;2;0;212;255m}"
38
+ PURPLE="${PURPLE:-\033[38;2;124;58;237m}"
39
+ GREEN="${GREEN:-\033[38;2;74;222;128m}"
40
+ YELLOW="${YELLOW:-\033[38;2;250;204;21m}"
41
+ RED="${RED:-\033[38;2;248;113;113m}"
42
+ DIM="${DIM:-\033[2m}"
43
+ BOLD="${BOLD:-\033[1m}"
44
+ RESET="${RESET:-\033[0m}"
45
+
46
+ # ─── Constants (policy overrides when config/policy.json exists) ─────────────
60
47
  STRATEGIC_MAX_ISSUES=5
61
48
  STRATEGIC_COOLDOWN_SECONDS=14400 # 4 hours
62
49
  STRATEGIC_MODEL="claude-sonnet-4-5-20250929"
63
50
  STRATEGIC_MAX_TOKENS=4096
64
51
  STRATEGIC_STRATEGY_LINES=200
65
52
  STRATEGIC_LABELS="auto-patrol,ready-to-build,strategic,shipwright"
53
+ STRATEGIC_OVERLAP_THRESHOLD=60 # Skip if >60% word overlap
54
+ [[ -f "${SCRIPT_DIR:-}/lib/policy.sh" ]] && source "${SCRIPT_DIR:-}/lib/policy.sh"
55
+ if type policy_get &>/dev/null 2>&1; then
56
+ STRATEGIC_MAX_ISSUES=$(policy_get ".strategic.max_issues_per_cycle" "5")
57
+ STRATEGIC_COOLDOWN_SECONDS=$(policy_get ".strategic.cooldown_seconds" "14400")
58
+ STRATEGIC_STRATEGY_LINES=$(policy_get ".strategic.strategy_lines" "200")
59
+ STRATEGIC_OVERLAP_THRESHOLD=$(policy_get ".strategic.overlap_threshold_percent" "60")
60
+ fi
66
61
 
67
62
  # ─── Semantic Dedup ─────────────────────────────────────────────────────────
68
63
  # Cache of existing issue titles (open + recently closed) loaded at cycle start.
69
64
  STRATEGIC_TITLE_CACHE=""
70
- STRATEGIC_OVERLAP_THRESHOLD=60 # Skip if >60% word overlap
71
65
 
72
66
  # Compute word-overlap similarity between two titles (0-100).
73
67
  # Uses lowercase word sets, ignoring common stop words.
@@ -346,6 +340,20 @@ strategic_build_prompt() {
346
340
  recent_closed="(GitHub access disabled)"
347
341
  fi
348
342
 
343
+ # Platform health (hygiene + platform-refactor scan) — for AGI-level self-improvement
344
+ local platform_health_section="(No platform hygiene data — run \`shipwright hygiene platform-refactor\` or \`shipwright hygiene scan\` to generate .claude/platform-hygiene.json)"
345
+ if [[ -f "${repo_dir}/.claude/platform-hygiene.json" ]]; then
346
+ local ph_summary
347
+ ph_summary=$(jq -r '
348
+ "Counts: hardcoded=\(.counts.hardcoded // 0), fallback=\(.counts.fallback // 0), TODO=\(.counts.todo // 0), FIXME=\(.counts.fixme // 0), HACK/KLUDGE=\(.counts.hack // 0). " +
349
+ "Largest scripts (lines): " + ((.script_size_hotspots // [] | .[0:5] | map("\(.script):\(.lines)") | join(", ")) // "none") + ". " +
350
+ "Sample findings: " + (((.findings_sample // [] | length) | tostring) + " file:line entries.")
351
+ ' "${repo_dir}/.claude/platform-hygiene.json" 2>/dev/null || echo "")
352
+ if [[ -n "$ph_summary" ]]; then
353
+ platform_health_section="Platform refactor scan (AGI-level self-improvement): $ph_summary Use this to suggest refactor, reduce-hardcoding, or clean-architecture issues when it would move the platform toward full autonomy."
354
+ fi
355
+ fi
356
+
349
357
  # Compose the prompt
350
358
  cat <<PROMPT_EOF
351
359
  You are the Strategic PM for Shipwright — an autonomous software delivery system. Your job is to analyze the current state and recommend 1-3 high-impact improvements to build next.
@@ -370,6 +378,9 @@ ${open_issues}
370
378
  ## Recently Completed (already built — do NOT recreate these)
371
379
  ${recent_closed}
372
380
 
381
+ ## Platform Health (refactor / hardcoded / AGI-level readiness)
382
+ ${platform_health_section}
383
+
373
384
  ## Your Task
374
385
  Based on the strategy priorities and current data, recommend 1-3 concrete improvements to build next. Each should be a single, well-scoped task completable by one autonomous pipeline run.
375
386
 
@@ -391,6 +402,7 @@ Rules:
391
402
  - Balance: reliability/DX fixes AND strategic new capabilities
392
403
  - Think about what would make the biggest impact on success rate, developer experience, and system intelligence
393
404
  - Be ambitious — push the platform forward, don't just maintain it
405
+ - AGI-level criterion: Consider what's hardcoded, static, or not clean architecture. When platform health data supports it, one of your recommendations MAY be a platform refactor or hygiene/architecture improvement (e.g. reduce hardcoded policy, move tunables to config, split monolithic scripts) so the platform can improve itself.
394
406
  - Maximum ${STRATEGIC_MAX_ISSUES} issues
395
407
  PROMPT_EOF
396
408
  }