shipwright-cli 1.10.0 → 2.0.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 (108) hide show
  1. package/README.md +114 -36
  2. package/completions/_shipwright +212 -32
  3. package/completions/shipwright.bash +97 -25
  4. package/docs/strategy/01-market-research.md +619 -0
  5. package/docs/strategy/02-mission-and-brand.md +587 -0
  6. package/docs/strategy/03-gtm-and-roadmap.md +759 -0
  7. package/docs/strategy/QUICK-START.txt +289 -0
  8. package/docs/strategy/README.md +172 -0
  9. package/package.json +4 -2
  10. package/scripts/sw +208 -1
  11. package/scripts/sw-activity.sh +500 -0
  12. package/scripts/sw-adaptive.sh +925 -0
  13. package/scripts/sw-adversarial.sh +1 -1
  14. package/scripts/sw-architecture-enforcer.sh +1 -1
  15. package/scripts/sw-auth.sh +613 -0
  16. package/scripts/sw-autonomous.sh +664 -0
  17. package/scripts/sw-changelog.sh +704 -0
  18. package/scripts/sw-checkpoint.sh +1 -1
  19. package/scripts/sw-ci.sh +602 -0
  20. package/scripts/sw-cleanup.sh +1 -1
  21. package/scripts/sw-code-review.sh +637 -0
  22. package/scripts/sw-connect.sh +1 -1
  23. package/scripts/sw-context.sh +605 -0
  24. package/scripts/sw-cost.sh +1 -1
  25. package/scripts/sw-daemon.sh +432 -130
  26. package/scripts/sw-dashboard.sh +1 -1
  27. package/scripts/sw-db.sh +540 -0
  28. package/scripts/sw-decompose.sh +539 -0
  29. package/scripts/sw-deps.sh +551 -0
  30. package/scripts/sw-developer-simulation.sh +1 -1
  31. package/scripts/sw-discovery.sh +412 -0
  32. package/scripts/sw-docs-agent.sh +539 -0
  33. package/scripts/sw-docs.sh +1 -1
  34. package/scripts/sw-doctor.sh +59 -1
  35. package/scripts/sw-dora.sh +615 -0
  36. package/scripts/sw-durable.sh +710 -0
  37. package/scripts/sw-e2e-orchestrator.sh +535 -0
  38. package/scripts/sw-eventbus.sh +393 -0
  39. package/scripts/sw-feedback.sh +471 -0
  40. package/scripts/sw-fix.sh +1 -1
  41. package/scripts/sw-fleet-discover.sh +567 -0
  42. package/scripts/sw-fleet-viz.sh +404 -0
  43. package/scripts/sw-fleet.sh +8 -1
  44. package/scripts/sw-github-app.sh +596 -0
  45. package/scripts/sw-github-checks.sh +1 -1
  46. package/scripts/sw-github-deploy.sh +1 -1
  47. package/scripts/sw-github-graphql.sh +1 -1
  48. package/scripts/sw-guild.sh +569 -0
  49. package/scripts/sw-heartbeat.sh +1 -1
  50. package/scripts/sw-hygiene.sh +559 -0
  51. package/scripts/sw-incident.sh +617 -0
  52. package/scripts/sw-init.sh +88 -1
  53. package/scripts/sw-instrument.sh +699 -0
  54. package/scripts/sw-intelligence.sh +1 -1
  55. package/scripts/sw-jira.sh +1 -1
  56. package/scripts/sw-launchd.sh +363 -28
  57. package/scripts/sw-linear.sh +1 -1
  58. package/scripts/sw-logs.sh +1 -1
  59. package/scripts/sw-loop.sh +64 -3
  60. package/scripts/sw-memory.sh +1 -1
  61. package/scripts/sw-mission-control.sh +487 -0
  62. package/scripts/sw-model-router.sh +545 -0
  63. package/scripts/sw-otel.sh +596 -0
  64. package/scripts/sw-oversight.sh +689 -0
  65. package/scripts/sw-pipeline-composer.sh +1 -1
  66. package/scripts/sw-pipeline-vitals.sh +1 -1
  67. package/scripts/sw-pipeline.sh +687 -24
  68. package/scripts/sw-pm.sh +693 -0
  69. package/scripts/sw-pr-lifecycle.sh +522 -0
  70. package/scripts/sw-predictive.sh +1 -1
  71. package/scripts/sw-prep.sh +1 -1
  72. package/scripts/sw-ps.sh +1 -1
  73. package/scripts/sw-public-dashboard.sh +798 -0
  74. package/scripts/sw-quality.sh +595 -0
  75. package/scripts/sw-reaper.sh +1 -1
  76. package/scripts/sw-recruit.sh +573 -0
  77. package/scripts/sw-regression.sh +642 -0
  78. package/scripts/sw-release-manager.sh +736 -0
  79. package/scripts/sw-release.sh +706 -0
  80. package/scripts/sw-remote.sh +1 -1
  81. package/scripts/sw-replay.sh +520 -0
  82. package/scripts/sw-retro.sh +691 -0
  83. package/scripts/sw-scale.sh +444 -0
  84. package/scripts/sw-security-audit.sh +505 -0
  85. package/scripts/sw-self-optimize.sh +1 -1
  86. package/scripts/sw-session.sh +1 -1
  87. package/scripts/sw-setup.sh +1 -1
  88. package/scripts/sw-standup.sh +712 -0
  89. package/scripts/sw-status.sh +1 -1
  90. package/scripts/sw-strategic.sh +658 -0
  91. package/scripts/sw-stream.sh +450 -0
  92. package/scripts/sw-swarm.sh +583 -0
  93. package/scripts/sw-team-stages.sh +511 -0
  94. package/scripts/sw-templates.sh +1 -1
  95. package/scripts/sw-testgen.sh +515 -0
  96. package/scripts/sw-tmux-pipeline.sh +554 -0
  97. package/scripts/sw-tmux.sh +1 -1
  98. package/scripts/sw-trace.sh +485 -0
  99. package/scripts/sw-tracker-github.sh +188 -0
  100. package/scripts/sw-tracker-jira.sh +172 -0
  101. package/scripts/sw-tracker-linear.sh +251 -0
  102. package/scripts/sw-tracker.sh +117 -2
  103. package/scripts/sw-triage.sh +603 -0
  104. package/scripts/sw-upgrade.sh +1 -1
  105. package/scripts/sw-ux.sh +677 -0
  106. package/scripts/sw-webhook.sh +627 -0
  107. package/scripts/sw-widgets.sh +530 -0
  108. package/scripts/sw-worktree.sh +1 -1
@@ -0,0 +1,573 @@
1
+ #!/usr/bin/env bash
2
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
3
+ # ║ sw-recruit.sh — Agent Recruitment & Talent Management System ║
4
+ # ║ ║
5
+ # ║ Role definitions · Skill matching · Performance evaluation · Team ║
6
+ # ║ composition recommendations · Agent promotion/demotion based on metrics ║
7
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
8
+ set -euo pipefail
9
+ trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
10
+
11
+ VERSION="2.0.0"
12
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
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
+ # ─── Cross-platform compatibility ──────────────────────────────────────────
26
+ # shellcheck source=lib/compat.sh
27
+ [[ -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; }
37
+
38
+ # ─── Structured Event Log ──────────────────────────────────────────────────
39
+ EVENTS_FILE="${HOME}/.shipwright/events.jsonl"
40
+
41
+ emit_event() {
42
+ local event_type="$1"
43
+ shift
44
+ local json_fields=""
45
+ for kv in "$@"; do
46
+ local key="${kv%%=*}"
47
+ local val="${kv#*=}"
48
+ if [[ "$val" =~ ^-?[0-9]+\.?[0-9]*$ ]]; then
49
+ json_fields="${json_fields},\"${key}\":${val}"
50
+ else
51
+ val="${val//\"/\\\"}"
52
+ json_fields="${json_fields},\"${key}\":\"${val}\""
53
+ fi
54
+ done
55
+ mkdir -p "${HOME}/.shipwright"
56
+ echo "{\"ts\":\"$(now_iso)\",\"ts_epoch\":$(now_epoch),\"type\":\"${event_type}\"${json_fields}}" >> "$EVENTS_FILE"
57
+ }
58
+
59
+ # ─── Recruitment Storage Paths ─────────────────────────────────────────────
60
+ RECRUIT_ROOT="${HOME}/.shipwright/recruitment"
61
+ ROLES_DB="${RECRUIT_ROOT}/roles.json"
62
+ PROFILES_DB="${RECRUIT_ROOT}/profiles.json"
63
+ TALENT_DB="${RECRUIT_ROOT}/talent.json"
64
+ ONBOARDING_DB="${RECRUIT_ROOT}/onboarding.json"
65
+
66
+ ensure_recruit_dir() {
67
+ mkdir -p "$RECRUIT_ROOT"
68
+ [[ -f "$ROLES_DB" ]] || echo '{}' > "$ROLES_DB"
69
+ [[ -f "$PROFILES_DB" ]] || echo '{}' > "$PROFILES_DB"
70
+ [[ -f "$TALENT_DB" ]] || echo '[]' > "$TALENT_DB"
71
+ [[ -f "$ONBOARDING_DB" ]] || echo '{}' > "$ONBOARDING_DB"
72
+ }
73
+
74
+ # ─── Built-in Role Definitions ────────────────────────────────────────────
75
+ initialize_builtin_roles() {
76
+ ensure_recruit_dir
77
+
78
+ # Check if roles already initialized
79
+ if jq -e '.architect' "$ROLES_DB" &>/dev/null 2>&1; then
80
+ return 0
81
+ fi
82
+
83
+ local roles_json=$(cat <<'EOF'
84
+ {
85
+ "architect": {
86
+ "title": "Architect",
87
+ "description": "System design, architecture decisions, scalability planning",
88
+ "required_skills": ["system-design", "technology-evaluation", "code-review", "documentation"],
89
+ "recommended_model": "opus",
90
+ "context_needs": ["codebase-architecture", "system-patterns", "past-designs", "dependency-graph"],
91
+ "success_metrics": ["design-quality", "implementation-feasibility", "team-alignment"],
92
+ "estimated_cost_per_task_usd": 2.5
93
+ },
94
+ "builder": {
95
+ "title": "Builder",
96
+ "description": "Feature implementation, core development, code generation",
97
+ "required_skills": ["coding", "testing", "debugging", "performance-optimization"],
98
+ "recommended_model": "sonnet",
99
+ "context_needs": ["codebase-structure", "api-specs", "test-patterns", "build-system"],
100
+ "success_metrics": ["tests-passing", "code-quality", "productivity", "bug-rate"],
101
+ "estimated_cost_per_task_usd": 1.5
102
+ },
103
+ "reviewer": {
104
+ "title": "Code Reviewer",
105
+ "description": "Code review, quality assurance, best practices enforcement",
106
+ "required_skills": ["code-review", "static-analysis", "security-review", "best-practices"],
107
+ "recommended_model": "sonnet",
108
+ "context_needs": ["coding-standards", "previous-reviews", "common-errors", "team-patterns"],
109
+ "success_metrics": ["review-quality", "issue-detection-rate", "feedback-clarity"],
110
+ "estimated_cost_per_task_usd": 1.2
111
+ },
112
+ "tester": {
113
+ "title": "Test Specialist",
114
+ "description": "Test strategy, test case generation, test automation, quality validation",
115
+ "required_skills": ["testing", "coverage-analysis", "automation", "edge-case-detection"],
116
+ "recommended_model": "sonnet",
117
+ "context_needs": ["test-framework", "coverage-metrics", "failure-patterns", "requirements"],
118
+ "success_metrics": ["coverage-increase", "bug-detection", "test-execution-time"],
119
+ "estimated_cost_per_task_usd": 1.2
120
+ },
121
+ "security-auditor": {
122
+ "title": "Security Auditor",
123
+ "description": "Security analysis, vulnerability detection, compliance verification",
124
+ "required_skills": ["security-analysis", "threat-modeling", "penetration-testing", "compliance"],
125
+ "recommended_model": "opus",
126
+ "context_needs": ["security-policies", "vulnerability-database", "threat-models", "compliance-reqs"],
127
+ "success_metrics": ["vulnerabilities-found", "severity-accuracy", "remediation-quality"],
128
+ "estimated_cost_per_task_usd": 2.0
129
+ },
130
+ "docs-writer": {
131
+ "title": "Documentation Writer",
132
+ "description": "Documentation creation, API docs, user guides, onboarding materials",
133
+ "required_skills": ["documentation", "clarity", "completeness", "example-generation"],
134
+ "recommended_model": "haiku",
135
+ "context_needs": ["codebase-knowledge", "api-specs", "user-personas", "doc-templates"],
136
+ "success_metrics": ["documentation-completeness", "clarity-score", "example-coverage"],
137
+ "estimated_cost_per_task_usd": 0.8
138
+ },
139
+ "optimizer": {
140
+ "title": "Performance Optimizer",
141
+ "description": "Performance analysis, optimization, profiling, efficiency improvements",
142
+ "required_skills": ["performance-analysis", "profiling", "optimization", "metrics-analysis"],
143
+ "recommended_model": "sonnet",
144
+ "context_needs": ["performance-benchmarks", "profiling-tools", "optimization-history"],
145
+ "success_metrics": ["performance-gain", "memory-efficiency", "latency-reduction"],
146
+ "estimated_cost_per_task_usd": 1.5
147
+ },
148
+ "devops": {
149
+ "title": "DevOps Engineer",
150
+ "description": "Infrastructure, deployment pipelines, CI/CD, monitoring, reliability",
151
+ "required_skills": ["infrastructure-as-code", "deployment", "monitoring", "incident-response"],
152
+ "recommended_model": "sonnet",
153
+ "context_needs": ["infrastructure-config", "deployment-pipelines", "monitoring-setup", "runbooks"],
154
+ "success_metrics": ["deployment-success-rate", "incident-response-time", "uptime"],
155
+ "estimated_cost_per_task_usd": 1.8
156
+ },
157
+ "pm": {
158
+ "title": "Project Manager",
159
+ "description": "Task decomposition, priority management, stakeholder communication, tracking",
160
+ "required_skills": ["task-decomposition", "prioritization", "communication", "planning"],
161
+ "recommended_model": "sonnet",
162
+ "context_needs": ["project-state", "requirements", "team-capacity", "past-estimates"],
163
+ "success_metrics": ["estimation-accuracy", "deadline-met", "scope-management"],
164
+ "estimated_cost_per_task_usd": 1.0
165
+ },
166
+ "incident-responder": {
167
+ "title": "Incident Responder",
168
+ "description": "Crisis management, root cause analysis, rapid issue resolution, hotfixes",
169
+ "required_skills": ["crisis-management", "root-cause-analysis", "debugging", "communication"],
170
+ "recommended_model": "opus",
171
+ "context_needs": ["incident-history", "system-health", "alerting-rules", "past-incidents"],
172
+ "success_metrics": ["incident-resolution-time", "accuracy", "escalation-prevention"],
173
+ "estimated_cost_per_task_usd": 2.0
174
+ }
175
+ }
176
+ EOF
177
+ )
178
+ echo "$roles_json" | jq '.' > "$ROLES_DB"
179
+ success "Initialized 10 built-in agent roles"
180
+ }
181
+
182
+ # ─── Command Implementations ───────────────────────────────────────────────
183
+
184
+ cmd_roles() {
185
+ ensure_recruit_dir
186
+ initialize_builtin_roles
187
+
188
+ info "Available Agent Roles:"
189
+ echo ""
190
+
191
+ jq -r 'to_entries | .[] |
192
+ "\(.key): \(.value.title) — \(.value.description)\n Model: \(.value.recommended_model) | Cost: $\(.value.estimated_cost_per_task_usd)/task\n Skills: \(.value.required_skills | join(", "))\n"' \
193
+ "$ROLES_DB"
194
+ }
195
+
196
+ cmd_match() {
197
+ local task_description="${1:-}"
198
+
199
+ if [[ -z "$task_description" ]]; then
200
+ error "Usage: shipwright recruit match \"<task description>\""
201
+ exit 1
202
+ fi
203
+
204
+ ensure_recruit_dir
205
+ initialize_builtin_roles
206
+
207
+ info "Analyzing task: ${CYAN}${task_description}${RESET}"
208
+ echo ""
209
+
210
+ # Simple keyword-based matching (can be enhanced with Claude)
211
+ local detected_skills=""
212
+
213
+ [[ "$task_description" =~ (architecture|design|scalability) ]] && detected_skills="${detected_skills}architect "
214
+ [[ "$task_description" =~ (build|feature|implement|code) ]] && detected_skills="${detected_skills}builder "
215
+ [[ "$task_description" =~ (review|quality|best.practice) ]] && detected_skills="${detected_skills}reviewer "
216
+ [[ "$task_description" =~ (test|coverage|automation) ]] && detected_skills="${detected_skills}tester "
217
+ [[ "$task_description" =~ (security|vulnerability|compliance) ]] && detected_skills="${detected_skills}security-auditor "
218
+ [[ "$task_description" =~ (doc|guide|readme) ]] && detected_skills="${detected_skills}docs-writer "
219
+ [[ "$task_description" =~ (performance|optimization|profile) ]] && detected_skills="${detected_skills}optimizer "
220
+ [[ "$task_description" =~ (deploy|infra|ci.cd|monitoring) ]] && detected_skills="${detected_skills}devops "
221
+ [[ "$task_description" =~ (plan|decompose|estimate|priorit) ]] && detected_skills="${detected_skills}pm "
222
+ [[ "$task_description" =~ (urgent|incident|crisis|hotfix) ]] && detected_skills="${detected_skills}incident-responder "
223
+
224
+ # Default to builder if no match
225
+ if [[ -z "$detected_skills" ]]; then
226
+ detected_skills="builder"
227
+ fi
228
+
229
+ # Show top recommendations
230
+ local primary_role
231
+ primary_role=$(echo "$detected_skills" | awk '{print $1}')
232
+
233
+ success "Recommended role: ${CYAN}${primary_role}${RESET}"
234
+ echo ""
235
+
236
+ local role_info
237
+ role_info=$(jq ".\"${primary_role}\"" "$ROLES_DB")
238
+ echo " $(echo "$role_info" | jq -r '.description')"
239
+ echo " Model: $(echo "$role_info" | jq -r '.recommended_model')"
240
+ echo " Skills: $(echo "$role_info" | jq -r '.required_skills | join(", ")')"
241
+
242
+ if [[ "$(echo "$detected_skills" | wc -w)" -gt 1 ]]; then
243
+ echo ""
244
+ warn "Secondary roles detected: $(echo "$detected_skills" | cut -d' ' -f2-)"
245
+ fi
246
+ }
247
+
248
+ cmd_evaluate() {
249
+ local agent_id="${1:-}"
250
+
251
+ if [[ -z "$agent_id" ]]; then
252
+ error "Usage: shipwright recruit evaluate <agent-id>"
253
+ exit 1
254
+ fi
255
+
256
+ ensure_recruit_dir
257
+
258
+ info "Evaluating agent: ${CYAN}${agent_id}${RESET}"
259
+ echo ""
260
+
261
+ # Get agent profile
262
+ local profile
263
+ profile=$(jq ".\"${agent_id}\"" "$PROFILES_DB" 2>/dev/null || echo "{}")
264
+
265
+ if [[ "$profile" == "{}" ]]; then
266
+ warn "No evaluation history for ${agent_id}"
267
+ return 0
268
+ fi
269
+
270
+ echo "Performance Metrics:"
271
+ echo " Success Rate: $(echo "$profile" | jq -r '.success_rate // "N/A"')%"
272
+ echo " Avg Time: $(echo "$profile" | jq -r '.avg_time_minutes // "N/A"') minutes"
273
+ echo " Quality Score: $(echo "$profile" | jq -r '.quality_score // "N/A"')/10"
274
+ echo " Cost Efficiency: $(echo "$profile" | jq -r '.cost_efficiency // "N/A"')%"
275
+ echo " Tasks Completed: $(echo "$profile" | jq -r '.tasks_completed // "0"')"
276
+ echo ""
277
+
278
+ # Recommendation
279
+ local success_rate
280
+ success_rate=$(echo "$profile" | jq -r '.success_rate // 0')
281
+
282
+ if (( $(echo "$success_rate < 70" | bc -l 2>/dev/null || echo "1") )); then
283
+ warn "Performance below threshold. Consider downgrading or retraining."
284
+ elif (( $(echo "$success_rate >= 90" | bc -l 2>/dev/null || echo "0") )); then
285
+ success "Excellent performance. Consider for promotion."
286
+ else
287
+ success "Acceptable performance. Continue current assignment."
288
+ fi
289
+ }
290
+
291
+ cmd_team() {
292
+ local issue_or_project="${1:-}"
293
+
294
+ if [[ -z "$issue_or_project" ]]; then
295
+ error "Usage: shipwright recruit team <issue|project>"
296
+ exit 1
297
+ fi
298
+
299
+ ensure_recruit_dir
300
+ initialize_builtin_roles
301
+
302
+ info "Recommending team composition for: ${CYAN}${issue_or_project}${RESET}"
303
+ echo ""
304
+
305
+ # Default recommendation: builder + reviewer + tester
306
+ local recommended_team=("builder" "reviewer" "tester")
307
+
308
+ # Add security auditor for security-related issues
309
+ if echo "$issue_or_project" | grep -qiE "security|vulnerability|compliance"; then
310
+ recommended_team+=("security-auditor")
311
+ fi
312
+
313
+ # Add architect for design issues
314
+ if echo "$issue_or_project" | grep -qiE "architecture|design|refactor"; then
315
+ recommended_team+=("architect")
316
+ fi
317
+
318
+ success "Recommended Team Composition (${#recommended_team[@]} members):"
319
+ echo ""
320
+
321
+ for role in "${recommended_team[@]}"; do
322
+ local role_info
323
+ role_info=$(jq ".\"${role}\"" "$ROLES_DB")
324
+ printf " • ${CYAN}%-20s${RESET} (${PURPLE}%s${RESET}) — %s\n" \
325
+ "$role" \
326
+ "$(echo "$role_info" | jq -r '.recommended_model')" \
327
+ "$(echo "$role_info" | jq -r '.title')"
328
+ done
329
+
330
+ echo ""
331
+ local total_cost
332
+ total_cost=$(printf "%.2f" $(
333
+ for role in "${recommended_team[@]}"; do
334
+ jq ".\"${role}\".estimated_cost_per_task_usd" "$ROLES_DB"
335
+ done | awk '{sum+=$1} END {print sum}'
336
+ ))
337
+ echo "Estimated Team Cost: \$${total_cost}/task"
338
+ }
339
+
340
+ cmd_profiles() {
341
+ ensure_recruit_dir
342
+
343
+ info "Agent Performance Profiles:"
344
+ echo ""
345
+
346
+ if [[ ! -s "$PROFILES_DB" || "$(jq 'length' "$PROFILES_DB" 2>/dev/null || echo 0)" -eq 0 ]]; then
347
+ warn "No performance profiles recorded yet"
348
+ return 0
349
+ fi
350
+
351
+ jq -r 'to_entries | .[] |
352
+ "\(.key):\n Success: \(.value.success_rate // "N/A")% | Quality: \(.value.quality_score // "N/A")/10 | Tasks: \(.value.tasks_completed // 0)\n Avg Time: \(.value.avg_time_minutes // "N/A")min | Efficiency: \(.value.cost_efficiency // "N/A")%\n"' \
353
+ "$PROFILES_DB"
354
+ }
355
+
356
+ cmd_promote() {
357
+ local agent_id="${1:-}"
358
+
359
+ if [[ -z "$agent_id" ]]; then
360
+ error "Usage: shipwright recruit promote <agent-id>"
361
+ exit 1
362
+ fi
363
+
364
+ ensure_recruit_dir
365
+
366
+ info "Evaluating promotion eligibility for: ${CYAN}${agent_id}${RESET}"
367
+ echo ""
368
+
369
+ local profile
370
+ profile=$(jq ".\"${agent_id}\"" "$PROFILES_DB" 2>/dev/null || echo "{}")
371
+
372
+ if [[ "$profile" == "{}" ]]; then
373
+ warn "No profile found for ${agent_id}"
374
+ return 1
375
+ fi
376
+
377
+ local success_rate quality_score
378
+ success_rate=$(echo "$profile" | jq -r '.success_rate // 0')
379
+ quality_score=$(echo "$profile" | jq -r '.quality_score // 0')
380
+
381
+ local current_model
382
+ current_model=$(echo "$profile" | jq -r '.model // "haiku"')
383
+
384
+ local recommended_model="$current_model"
385
+ local promotion_reason=""
386
+
387
+ if (( $(echo "$success_rate >= 95 && $quality_score >= 9" | bc -l 2>/dev/null || echo "0") )); then
388
+ case "$current_model" in
389
+ haiku) recommended_model="sonnet"; promotion_reason="Excellent performance on Haiku" ;;
390
+ sonnet) recommended_model="opus"; promotion_reason="Outstanding results on Sonnet" ;;
391
+ opus) promotion_reason="Already on best model"; recommended_model="opus" ;;
392
+ esac
393
+ elif (( $(echo "$success_rate < 60 || $quality_score < 5" | bc -l 2>/dev/null || echo "0") )); then
394
+ case "$current_model" in
395
+ opus) recommended_model="sonnet"; promotion_reason="Struggling on Opus, try Sonnet" ;;
396
+ sonnet) recommended_model="haiku"; promotion_reason="Poor performance, reduce cost" ;;
397
+ haiku) promotion_reason="Consider retraining"; recommended_model="haiku" ;;
398
+ esac
399
+ fi
400
+
401
+ if [[ "$recommended_model" != "$current_model" ]]; then
402
+ success "Recommend upgrading from ${CYAN}${current_model}${RESET} to ${PURPLE}${recommended_model}${RESET}"
403
+ echo " Reason: $promotion_reason"
404
+ emit_event "recruit_promotion" "agent_id=${agent_id}" "from=${current_model}" "to=${recommended_model}" "reason=${promotion_reason}"
405
+ else
406
+ info "No model change recommended for ${agent_id}"
407
+ echo " Current: ${current_model} | Success: ${success_rate}% | Quality: ${quality_score}/10"
408
+ fi
409
+ }
410
+
411
+ cmd_onboard() {
412
+ local agent_role="${1:-builder}"
413
+
414
+ ensure_recruit_dir
415
+ initialize_builtin_roles
416
+
417
+ info "Generating onboarding context for: ${CYAN}${agent_role}${RESET}"
418
+ echo ""
419
+
420
+ local role_info
421
+ role_info=$(jq ".${agent_role}" "$ROLES_DB" 2>/dev/null)
422
+
423
+ if [[ -z "$role_info" || "$role_info" == "null" ]]; then
424
+ error "Unknown role: ${agent_role}"
425
+ exit 1
426
+ fi
427
+
428
+ # Create onboarding document
429
+ local onboarding_doc=$(cat <<EOF
430
+ # Onboarding Context: ${agent_role}
431
+
432
+ ## Role Profile
433
+ **Title:** $(echo "$role_info" | jq -r '.title')
434
+ **Description:** $(echo "$role_info" | jq -r '.description')
435
+ **Recommended Model:** $(echo "$role_info" | jq -r '.recommended_model')
436
+
437
+ ## Required Skills
438
+ $(echo "$role_info" | jq -r '.required_skills[]' | sed 's/^/- /')
439
+
440
+ ## Context Needs
441
+ $(echo "$role_info" | jq -r '.context_needs[]' | sed 's/^/- /')
442
+
443
+ ## Success Metrics
444
+ $(echo "$role_info" | jq -r '.success_metrics[]' | sed 's/^/- /')
445
+
446
+ ## Cost Profile
447
+ Estimated cost per task: \$$(echo "$role_info" | jq -r '.estimated_cost_per_task_usd')
448
+
449
+ ## Getting Started
450
+ 1. Review the role profile above
451
+ 2. Study the codebase architecture
452
+ 3. Familiarize yourself with coding standards
453
+ 4. Review past pipeline runs for patterns
454
+ 5. Ask questions about unclear requirements
455
+
456
+ ## Resources
457
+ - Codebase: /path/to/repo
458
+ - Documentation: See .claude/ directory
459
+ - Team patterns: Reviewed in memory system
460
+ - Past learnings: Available in ~/.shipwright/memory/
461
+ EOF
462
+ )
463
+
464
+ # Save to onboarding DB
465
+ local onboarding_key=$(date +%s)
466
+ jq --arg key "$onboarding_key" --arg doc "$onboarding_doc" '.[$key] = $doc' "$ONBOARDING_DB" > "${ONBOARDING_DB}.tmp"
467
+ mv "${ONBOARDING_DB}.tmp" "$ONBOARDING_DB"
468
+
469
+ success "Onboarding context generated for ${agent_role}"
470
+ echo ""
471
+ echo "$onboarding_doc"
472
+ emit_event "recruit_onboarding" "role=${agent_role}" "timestamp=$(now_epoch)"
473
+ }
474
+
475
+ cmd_stats() {
476
+ ensure_recruit_dir
477
+
478
+ info "Recruitment Statistics & Talent Trends:"
479
+ echo ""
480
+
481
+ # Count roles
482
+ local role_count
483
+ role_count=$(jq 'length' "$ROLES_DB" 2>/dev/null || echo 0)
484
+
485
+ # Count profiles
486
+ local profile_count
487
+ profile_count=$(jq 'length' "$PROFILES_DB" 2>/dev/null || echo 0)
488
+
489
+ # Count talent entries
490
+ local talent_count
491
+ talent_count=$(jq 'length' "$TALENT_DB" 2>/dev/null || echo 0)
492
+
493
+ echo " Roles Defined: $role_count"
494
+ echo " Agents Profiled: $profile_count"
495
+ echo " Talent Records: $talent_count"
496
+ echo ""
497
+
498
+ # Average metrics
499
+ if [[ "$profile_count" -gt 0 ]]; then
500
+ local avg_success
501
+ avg_success=$(jq '[.[].success_rate // 0] | add / length' "$PROFILES_DB" 2>/dev/null || echo "0")
502
+
503
+ local avg_quality
504
+ avg_quality=$(jq '[.[].quality_score // 0] | add / length' "$PROFILES_DB" 2>/dev/null || echo "0")
505
+
506
+ echo " Avg Success Rate: ${avg_success}%"
507
+ echo " Avg Quality Score: ${avg_quality}/10"
508
+ echo ""
509
+ fi
510
+
511
+ success "Use 'shipwright recruit profiles' for detailed breakdown"
512
+ }
513
+
514
+ cmd_help() {
515
+ cat <<EOF
516
+ ${BOLD}${CYAN}shipwright recruit${RESET} — Agent Recruitment & Talent Management
517
+
518
+ ${BOLD}USAGE${RESET}
519
+ ${CYAN}shipwright recruit${RESET} <command> [options]
520
+
521
+ ${BOLD}COMMANDS${RESET}
522
+ ${CYAN}roles${RESET} List all available agent roles and skill requirements
523
+ ${CYAN}match${RESET} "<task>" Analyze task and recommend best agent role
524
+ ${CYAN}evaluate${RESET} <id> Score an agent's recent performance
525
+ ${CYAN}team${RESET} "<issue>" Recommend optimal team composition for an issue/project
526
+ ${CYAN}profiles${RESET} Show performance profiles by agent type
527
+ ${CYAN}promote${RESET} <id> Recommend model upgrades for agents (haiku→sonnet→opus)
528
+ ${CYAN}onboard${RESET} <role> Generate onboarding context for a new agent
529
+ ${CYAN}stats${RESET} Show recruitment statistics and talent trends
530
+ ${CYAN}help${RESET} Show this help message
531
+
532
+ ${BOLD}EXAMPLES${RESET}
533
+ ${DIM}shipwright recruit roles${RESET}
534
+ ${DIM}shipwright recruit match "Add authentication system"${RESET}
535
+ ${DIM}shipwright recruit team issue-123${RESET}
536
+ ${DIM}shipwright recruit evaluate agent-builder-001${RESET}
537
+ ${DIM}shipwright recruit promote agent-builder-001${RESET}
538
+ ${DIM}shipwright recruit onboard architect${RESET}
539
+
540
+ ${BOLD}ROLE CATALOG${RESET}
541
+ Built-in roles: architect, builder, reviewer, tester, security-auditor,
542
+ docs-writer, optimizer, devops, pm, incident-responder
543
+
544
+ ${DIM}Store: ~/.shipwright/recruitment/${RESET}
545
+ EOF
546
+ }
547
+
548
+ # ─── Main Router ──────────────────────────────────────────────────────────
549
+
550
+ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
551
+ ensure_recruit_dir
552
+
553
+ cmd="${1:-help}"
554
+ shift 2>/dev/null || true
555
+
556
+ case "$cmd" in
557
+ roles) cmd_roles ;;
558
+ match) cmd_match "$@" ;;
559
+ evaluate) cmd_evaluate "$@" ;;
560
+ team) cmd_team "$@" ;;
561
+ profiles) cmd_profiles ;;
562
+ promote) cmd_promote "$@" ;;
563
+ onboard) cmd_onboard "$@" ;;
564
+ stats) cmd_stats ;;
565
+ help|--help|-h) cmd_help ;;
566
+ *)
567
+ error "Unknown command: ${cmd}"
568
+ echo ""
569
+ cmd_help
570
+ exit 1
571
+ ;;
572
+ esac
573
+ fi