shipwright-cli 1.9.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 (117) hide show
  1. package/.claude/hooks/post-tool-use.sh +12 -5
  2. package/README.md +114 -36
  3. package/completions/_shipwright +212 -32
  4. package/completions/shipwright.bash +97 -25
  5. package/docs/strategy/01-market-research.md +619 -0
  6. package/docs/strategy/02-mission-and-brand.md +587 -0
  7. package/docs/strategy/03-gtm-and-roadmap.md +759 -0
  8. package/docs/strategy/QUICK-START.txt +289 -0
  9. package/docs/strategy/README.md +172 -0
  10. package/package.json +4 -2
  11. package/scripts/sw +217 -2
  12. package/scripts/sw-activity.sh +500 -0
  13. package/scripts/sw-adaptive.sh +925 -0
  14. package/scripts/sw-adversarial.sh +1 -1
  15. package/scripts/sw-architecture-enforcer.sh +1 -1
  16. package/scripts/sw-auth.sh +613 -0
  17. package/scripts/sw-autonomous.sh +664 -0
  18. package/scripts/sw-changelog.sh +704 -0
  19. package/scripts/sw-checkpoint.sh +79 -1
  20. package/scripts/sw-ci.sh +602 -0
  21. package/scripts/sw-cleanup.sh +192 -7
  22. package/scripts/sw-code-review.sh +637 -0
  23. package/scripts/sw-connect.sh +1 -1
  24. package/scripts/sw-context.sh +605 -0
  25. package/scripts/sw-cost.sh +1 -1
  26. package/scripts/sw-daemon.sh +812 -138
  27. package/scripts/sw-dashboard.sh +1 -1
  28. package/scripts/sw-db.sh +540 -0
  29. package/scripts/sw-decompose.sh +539 -0
  30. package/scripts/sw-deps.sh +551 -0
  31. package/scripts/sw-developer-simulation.sh +1 -1
  32. package/scripts/sw-discovery.sh +412 -0
  33. package/scripts/sw-docs-agent.sh +539 -0
  34. package/scripts/sw-docs.sh +1 -1
  35. package/scripts/sw-doctor.sh +59 -1
  36. package/scripts/sw-dora.sh +615 -0
  37. package/scripts/sw-durable.sh +710 -0
  38. package/scripts/sw-e2e-orchestrator.sh +535 -0
  39. package/scripts/sw-eventbus.sh +393 -0
  40. package/scripts/sw-feedback.sh +471 -0
  41. package/scripts/sw-fix.sh +1 -1
  42. package/scripts/sw-fleet-discover.sh +567 -0
  43. package/scripts/sw-fleet-viz.sh +404 -0
  44. package/scripts/sw-fleet.sh +8 -1
  45. package/scripts/sw-github-app.sh +596 -0
  46. package/scripts/sw-github-checks.sh +1 -1
  47. package/scripts/sw-github-deploy.sh +1 -1
  48. package/scripts/sw-github-graphql.sh +1 -1
  49. package/scripts/sw-guild.sh +569 -0
  50. package/scripts/sw-heartbeat.sh +1 -1
  51. package/scripts/sw-hygiene.sh +559 -0
  52. package/scripts/sw-incident.sh +617 -0
  53. package/scripts/sw-init.sh +88 -1
  54. package/scripts/sw-instrument.sh +699 -0
  55. package/scripts/sw-intelligence.sh +1 -1
  56. package/scripts/sw-jira.sh +1 -1
  57. package/scripts/sw-launchd.sh +366 -31
  58. package/scripts/sw-linear.sh +1 -1
  59. package/scripts/sw-logs.sh +1 -1
  60. package/scripts/sw-loop.sh +507 -51
  61. package/scripts/sw-memory.sh +198 -3
  62. package/scripts/sw-mission-control.sh +487 -0
  63. package/scripts/sw-model-router.sh +545 -0
  64. package/scripts/sw-otel.sh +596 -0
  65. package/scripts/sw-oversight.sh +689 -0
  66. package/scripts/sw-pipeline-composer.sh +8 -8
  67. package/scripts/sw-pipeline-vitals.sh +1096 -0
  68. package/scripts/sw-pipeline.sh +2451 -180
  69. package/scripts/sw-pm.sh +693 -0
  70. package/scripts/sw-pr-lifecycle.sh +522 -0
  71. package/scripts/sw-predictive.sh +1 -1
  72. package/scripts/sw-prep.sh +1 -1
  73. package/scripts/sw-ps.sh +4 -3
  74. package/scripts/sw-public-dashboard.sh +798 -0
  75. package/scripts/sw-quality.sh +595 -0
  76. package/scripts/sw-reaper.sh +5 -3
  77. package/scripts/sw-recruit.sh +573 -0
  78. package/scripts/sw-regression.sh +642 -0
  79. package/scripts/sw-release-manager.sh +736 -0
  80. package/scripts/sw-release.sh +706 -0
  81. package/scripts/sw-remote.sh +1 -1
  82. package/scripts/sw-replay.sh +520 -0
  83. package/scripts/sw-retro.sh +691 -0
  84. package/scripts/sw-scale.sh +444 -0
  85. package/scripts/sw-security-audit.sh +505 -0
  86. package/scripts/sw-self-optimize.sh +109 -8
  87. package/scripts/sw-session.sh +31 -9
  88. package/scripts/sw-setup.sh +1 -1
  89. package/scripts/sw-standup.sh +712 -0
  90. package/scripts/sw-status.sh +192 -1
  91. package/scripts/sw-strategic.sh +658 -0
  92. package/scripts/sw-stream.sh +450 -0
  93. package/scripts/sw-swarm.sh +583 -0
  94. package/scripts/sw-team-stages.sh +511 -0
  95. package/scripts/sw-templates.sh +1 -1
  96. package/scripts/sw-testgen.sh +515 -0
  97. package/scripts/sw-tmux-pipeline.sh +554 -0
  98. package/scripts/sw-tmux.sh +1 -1
  99. package/scripts/sw-trace.sh +485 -0
  100. package/scripts/sw-tracker-github.sh +188 -0
  101. package/scripts/sw-tracker-jira.sh +172 -0
  102. package/scripts/sw-tracker-linear.sh +251 -0
  103. package/scripts/sw-tracker.sh +117 -2
  104. package/scripts/sw-triage.sh +603 -0
  105. package/scripts/sw-upgrade.sh +1 -1
  106. package/scripts/sw-ux.sh +677 -0
  107. package/scripts/sw-webhook.sh +627 -0
  108. package/scripts/sw-widgets.sh +530 -0
  109. package/scripts/sw-worktree.sh +1 -1
  110. package/templates/pipelines/autonomous.json +8 -1
  111. package/templates/pipelines/cost-aware.json +21 -0
  112. package/templates/pipelines/deployed.json +40 -6
  113. package/templates/pipelines/enterprise.json +16 -2
  114. package/templates/pipelines/fast.json +19 -0
  115. package/templates/pipelines/full.json +16 -2
  116. package/templates/pipelines/hotfix.json +19 -0
  117. package/templates/pipelines/standard.json +19 -0
@@ -0,0 +1,605 @@
1
+ #!/usr/bin/env bash
2
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
3
+ # ║ shipwright context — Context Engine for Pipeline Stages ║
4
+ # ║ Gather architecture decisions · File hotspots · PR outcomes · Memory ║
5
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
6
+ set -euo pipefail
7
+ trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
+
9
+ VERSION="2.0.0"
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'
23
+
24
+ # ─── Cross-platform compatibility ──────────────────────────────────────────
25
+ # shellcheck source=lib/compat.sh
26
+ [[ -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"; }
35
+
36
+ # ─── Paths ────────────────────────────────────────────────────────────────
37
+ ARTIFACTS_DIR="${REPO_DIR}/.claude/pipeline-artifacts"
38
+ CONTEXT_BUNDLE="${ARTIFACTS_DIR}/context-bundle.md"
39
+ CLAUDE_CONFIG="${REPO_DIR}/.claude/CLAUDE.md"
40
+ INTELLIGENCE_CACHE="${REPO_DIR}/.claude/intelligence-cache.json"
41
+ MEMORY_ROOT="${HOME}/.shipwright/memory"
42
+
43
+ # ─── Get repo identifier for memory lookups ────────────────────────────────
44
+ repo_hash() {
45
+ local origin
46
+ origin=$(git config --get remote.origin.url 2>/dev/null || echo "local")
47
+ echo -n "$origin" | shasum -a 256 | cut -c1-12
48
+ }
49
+
50
+ repo_memory_dir() {
51
+ echo "${MEMORY_ROOT}/$(repo_hash)"
52
+ }
53
+
54
+ # ─── Extract codebase patterns from CLAUDE.md ──────────────────────────────
55
+ extract_codebase_patterns() {
56
+ if [[ ! -f "$CLAUDE_CONFIG" ]]; then
57
+ echo "# Codebase Patterns"
58
+ echo "(No CLAUDE.md found)"
59
+ return
60
+ fi
61
+
62
+ local patterns_section
63
+ patterns_section=$(sed -n '/^## Shell Standards/,/^## [A-Z]/p' "$CLAUDE_CONFIG" 2>/dev/null || true)
64
+
65
+ if [[ -n "$patterns_section" ]]; then
66
+ echo "$patterns_section"
67
+ fi
68
+
69
+ echo ""
70
+ echo "### Common Pitfalls"
71
+ local pitfalls_section
72
+ pitfalls_section=$(sed -n '/^### Common Pitfalls/,/^## [A-Z]/p' "$CLAUDE_CONFIG" 2>/dev/null || true)
73
+ if [[ -n "$pitfalls_section" ]]; then
74
+ echo "$pitfalls_section"
75
+ fi
76
+ }
77
+
78
+ # ─── Extract file hotspots from intelligence cache ────────────────────────
79
+ extract_file_hotspots() {
80
+ if [[ ! -f "$INTELLIGENCE_CACHE" ]]; then
81
+ echo "# File Hotspots"
82
+ echo "(Intelligence cache not available)"
83
+ return
84
+ fi
85
+
86
+ echo "# File Hotspots"
87
+ echo ""
88
+ echo "From intelligence analysis:"
89
+ echo ""
90
+
91
+ # Try to extract relevance data from cache
92
+ local hotspots
93
+ hotspots=$(jq -r '.entries[].result.results[]? | "\(.file): \(.relevance)% — \(.summary)"' "$INTELLIGENCE_CACHE" 2>/dev/null || true)
94
+
95
+ if [[ -n "$hotspots" ]]; then
96
+ echo "$hotspots" | sort -rn | uniq
97
+ else
98
+ echo "(No file hotspot data in cache)"
99
+ fi
100
+ }
101
+
102
+ # ─── Get recent merged PRs ───────────────────────────────────────────────
103
+ extract_recent_prs() {
104
+ echo "# Recent PR Outcomes"
105
+ echo ""
106
+
107
+ if [[ "${NO_GITHUB:-}" == "true" ]]; then
108
+ echo "(GitHub disabled, using git log)"
109
+ echo ""
110
+ local recent_commits
111
+ recent_commits=$(git log --oneline --all --max-count=5 2>/dev/null || echo "(no git history)" | head -5)
112
+ echo "$recent_commits"
113
+ return
114
+ fi
115
+
116
+ if ! command -v gh &>/dev/null; then
117
+ echo "(gh CLI not available, using git log)"
118
+ echo ""
119
+ local recent_commits
120
+ recent_commits=$(git log --oneline --all --max-count=5 2>/dev/null | head -5 || echo "(no history)")
121
+ echo "$recent_commits"
122
+ return
123
+ fi
124
+
125
+ # Fetch last 5 merged PRs
126
+ local prs_json
127
+ prs_json=$(gh pr list --state merged --limit 5 --json title,mergedAt,additions,deletions,author 2>/dev/null || echo "[]")
128
+
129
+ if [[ "$prs_json" != "[]" ]] && [[ -n "$prs_json" ]]; then
130
+ echo "## Merged PRs (last 5)"
131
+ echo ""
132
+ echo "$prs_json" | jq -r '.[] | "\(.title) (author: \(.author.login), +\(.additions)−\(.deletions))"' 2>/dev/null || true
133
+ else
134
+ echo "(No merged PRs found or GitHub access limited)"
135
+ fi
136
+ }
137
+
138
+ # ─── Extract relevant memory entries ───────────────────────────────────────
139
+ extract_memory_entries() {
140
+ echo "# Relevant Memory"
141
+ echo ""
142
+
143
+ local mem_dir
144
+ mem_dir="$(repo_memory_dir)"
145
+
146
+ if [[ ! -d "$mem_dir" ]]; then
147
+ echo "(No memory entries yet)"
148
+ return
149
+ fi
150
+
151
+ # Check for failures
152
+ if [[ -f "$mem_dir/failures.json" ]]; then
153
+ local failure_count
154
+ failure_count=$(jq '.failures | length' "$mem_dir/failures.json" 2>/dev/null || echo "0")
155
+ if [[ "$failure_count" -gt 0 ]]; then
156
+ echo "## Failure Patterns"
157
+ echo ""
158
+ jq -r '.failures[] | "- **\(.category)**: \(.summary)"' "$mem_dir/failures.json" 2>/dev/null | head -5 || true
159
+ echo ""
160
+ fi
161
+ fi
162
+
163
+ # Check for patterns
164
+ if [[ -f "$mem_dir/patterns.json" ]]; then
165
+ local pattern_count
166
+ pattern_count=$(jq 'length' "$mem_dir/patterns.json" 2>/dev/null || echo "0")
167
+ if [[ "$pattern_count" -gt 0 ]]; then
168
+ echo "## Successful Patterns"
169
+ echo ""
170
+ jq -r 'to_entries[] | "- **\(.key)**: \(.value)"' "$mem_dir/patterns.json" 2>/dev/null | head -5 || true
171
+ echo ""
172
+ fi
173
+ fi
174
+
175
+ # Check for decisions
176
+ if [[ -f "$mem_dir/decisions.json" ]]; then
177
+ local decision_count
178
+ decision_count=$(jq '.decisions | length' "$mem_dir/decisions.json" 2>/dev/null || echo "0")
179
+ if [[ "$decision_count" -gt 0 ]]; then
180
+ echo "## Architecture Decisions"
181
+ echo ""
182
+ jq -r '.decisions[] | "- \(.decision): \(.rationale)"' "$mem_dir/decisions.json" 2>/dev/null | head -5 || true
183
+ echo ""
184
+ fi
185
+ fi
186
+ }
187
+
188
+ # ─── Extract relevant file previews based on goal ─────────────────────────
189
+ extract_file_previews() {
190
+ local goal="$1"
191
+ echo "# Relevant File Previews"
192
+ echo ""
193
+
194
+ # Try to identify relevant files from goal keywords
195
+ local keywords
196
+ keywords=$(echo "$goal" | tr '[:upper:]' '[:lower:]' | grep -oE '\b[a-z]+\b' | sort -u | head -10 || true)
197
+
198
+ if [[ -z "$keywords" ]]; then
199
+ echo "(Could not identify relevant files from goal)"
200
+ return
201
+ fi
202
+
203
+ # Find files matching keywords in their name or content
204
+ local relevant_files=""
205
+ local count=0
206
+
207
+ for kw in $keywords; do
208
+ if [[ $count -ge 3 ]]; then break; fi
209
+
210
+ # Search for files matching keyword
211
+ local found
212
+ found=$(find "$REPO_DIR" -type f \( -name "*.sh" -o -name "*.md" -o -name "*.ts" -o -name "*.json" \) \
213
+ -not -path "*/.git/*" \
214
+ -not -path "*/node_modules/*" \
215
+ -not -path "*/.claude/*" \
216
+ ! -size +100k \
217
+ 2>/dev/null | grep -i "$kw" | head -2 || true)
218
+
219
+ while IFS= read -r file; do
220
+ [[ -z "$file" ]] && continue
221
+ echo "$relevant_files" | grep -q "$file" && continue
222
+ relevant_files="${relevant_files}${file}"$'\n'
223
+ ((count++)) || true
224
+ if [[ $count -ge 3 ]]; then break 2; fi
225
+ done <<< "$found"
226
+ done
227
+
228
+ if [[ -z "$relevant_files" ]]; then
229
+ echo "(No matching files found)"
230
+ return
231
+ fi
232
+
233
+ while IFS= read -r file; do
234
+ [[ -z "$file" ]] && continue
235
+ if [[ ! -f "$file" ]]; then continue; fi
236
+
237
+ echo "## File: $(basename "$file")"
238
+ echo ""
239
+ echo '```'
240
+ head -20 "$file" 2>/dev/null | sed 's/^/ /'
241
+ echo '```'
242
+ echo ""
243
+ done <<< "$relevant_files"
244
+ }
245
+
246
+ # ─── Extract architecture decisions from docs ──────────────────────────────
247
+ extract_architecture_decisions() {
248
+ echo "# Architecture Decision Records"
249
+ echo ""
250
+
251
+ local adr_file="${REPO_DIR}/.claude/ARCHITECTURE.md"
252
+ if [[ -f "$adr_file" ]]; then
253
+ head -40 "$adr_file" | sed 's/^//'
254
+ echo ""
255
+ else
256
+ echo "(No ARCHITECTURE.md found)"
257
+ fi
258
+ }
259
+
260
+ # ─── Stage-specific guidance ───────────────────────────────────────────────
261
+ stage_guidance() {
262
+ local stage="$1"
263
+
264
+ case "$stage" in
265
+ plan)
266
+ cat <<'EOF'
267
+ # Plan Stage Guidance
268
+
269
+ ## Focus Areas
270
+ - Break down goal into measurable milestones
271
+ - Identify dependencies and blockers
272
+ - Estimate scope and complexity
273
+ - Consider edge cases and error paths
274
+
275
+ ## Key Questions
276
+ - What are the success criteria?
277
+ - What are the known constraints?
278
+ - What existing patterns apply here?
279
+ - Are there similar completed features to reference?
280
+
281
+ ## Anti-patterns to Avoid
282
+ - Over-scoping the initial plan
283
+ - Missing edge cases in requirement analysis
284
+ - Ignoring technical debt in design phase
285
+ EOF
286
+ ;;
287
+ design)
288
+ cat <<'EOF'
289
+ # Design Stage Guidance
290
+
291
+ ## Focus Areas
292
+ - Define interfaces and contracts
293
+ - Establish layer boundaries
294
+ - Document state management approach
295
+ - Plan error handling and recovery
296
+
297
+ ## Architectural Constraints
298
+ - Follow established naming conventions from codebase
299
+ - Respect layer dependencies (check ARCHITECTURE.md)
300
+ - Use patterns validated in memory system
301
+ - Consider testability from the start
302
+
303
+ ## Common Pitfalls
304
+ - Designing without understanding existing patterns
305
+ - Over-engineering for future extensibility
306
+ - Inconsistent error handling strategies
307
+ EOF
308
+ ;;
309
+ build)
310
+ cat <<'EOF'
311
+ # Build Stage Guidance
312
+
313
+ ## Standards to Follow
314
+ - Match existing code style (imports, naming, structure)
315
+ - Use patterns from hotspot files
316
+ - Implement with full error handling
317
+ - Write as you go, not after
318
+
319
+ ## Testing Strategy
320
+ - Write tests alongside implementation
321
+ - Test error paths and edge cases
322
+ - Verify integration with existing code
323
+ - Use coverage targets from memory
324
+
325
+ ## Quick Wins
326
+ - Look at similar recently-merged PRs for patterns
327
+ - Check failure patterns to avoid repeating mistakes
328
+ - Use mock patterns from test specialists
329
+ - Reference file previews for coding style
330
+ EOF
331
+ ;;
332
+ test)
333
+ cat <<'EOF'
334
+ # Test Stage Guidance
335
+
336
+ ## Testing Focus
337
+ - Cover both happy and error paths
338
+ - Test boundaries and edge cases
339
+ - Verify integration with existing code
340
+ - Achieve coverage targets from memory
341
+
342
+ ## Mock Patterns
343
+ - Study existing test files for mock approach
344
+ - Use established test harness conventions
345
+ - Mock external dependencies consistently
346
+ - Validate error scenarios
347
+
348
+ ## Coverage Requirements
349
+ - Unit tests for all public functions
350
+ - Integration tests for multi-component flows
351
+ - End-to-end tests for user-facing features
352
+ - Document coverage gaps
353
+ EOF
354
+ ;;
355
+ review)
356
+ cat <<'EOF'
357
+ # Review Stage Guidance
358
+
359
+ ## Review Checklist
360
+ - Code matches established patterns from hotspots
361
+ - No violations of architecture layer boundaries
362
+ - Error handling is complete and tested
363
+ - Breaking changes are documented
364
+ - Performance impact is acceptable
365
+
366
+ ## Security Check
367
+ - No credential or secret exposure
368
+ - Input validation at boundaries
369
+ - Authorization checks where needed
370
+ - Dependencies are reviewed
371
+
372
+ ## Common Issues
373
+ - Deviations from established patterns
374
+ - Incomplete error handling
375
+ - Test coverage gaps
376
+ - Missing documentation updates
377
+ EOF
378
+ ;;
379
+ *)
380
+ echo "# Stage-Specific Guidance"
381
+ echo "(No specific guidance for stage: $stage)"
382
+ ;;
383
+ esac
384
+ }
385
+
386
+ # ─── Main gather function ─────────────────────────────────────────────────
387
+ gather_context() {
388
+ local goal="$1"
389
+ local stage="${2:-build}"
390
+
391
+ info "Building context bundle for ${CYAN}${stage}${RESET} stage..."
392
+
393
+ mkdir -p "$ARTIFACTS_DIR"
394
+
395
+ local tmp_file
396
+ tmp_file=$(mktemp "${TMPDIR:-/tmp}/sw-context-bundle.XXXXXX")
397
+
398
+ # Write bundle header
399
+ {
400
+ echo "# Pipeline Context Bundle"
401
+ echo ""
402
+ echo "Generated: $(now_iso)"
403
+ echo "Stage: ${stage}"
404
+ echo "Goal: ${goal}"
405
+ echo ""
406
+ echo "---"
407
+ echo ""
408
+ } >> "$tmp_file"
409
+
410
+ # Section: Codebase Patterns
411
+ {
412
+ echo ""
413
+ extract_codebase_patterns
414
+ echo ""
415
+ echo "---"
416
+ echo ""
417
+ } >> "$tmp_file"
418
+
419
+ # Section: File Hotspots
420
+ {
421
+ extract_file_hotspots
422
+ echo ""
423
+ echo "---"
424
+ echo ""
425
+ } >> "$tmp_file"
426
+
427
+ # Section: Recent PR Outcomes
428
+ {
429
+ extract_recent_prs
430
+ echo ""
431
+ echo "---"
432
+ echo ""
433
+ } >> "$tmp_file"
434
+
435
+ # Section: Memory Entries
436
+ {
437
+ extract_memory_entries
438
+ echo ""
439
+ echo "---"
440
+ echo ""
441
+ } >> "$tmp_file"
442
+
443
+ # Section: File Previews
444
+ {
445
+ extract_file_previews "$goal"
446
+ echo ""
447
+ echo "---"
448
+ echo ""
449
+ } >> "$tmp_file"
450
+
451
+ # Section: Architecture Decisions
452
+ {
453
+ extract_architecture_decisions
454
+ echo ""
455
+ echo "---"
456
+ echo ""
457
+ } >> "$tmp_file"
458
+
459
+ # Section: Stage-Specific Guidance
460
+ {
461
+ echo ""
462
+ stage_guidance "$stage"
463
+ echo ""
464
+ } >> "$tmp_file"
465
+
466
+ # Atomically move to final location
467
+ mv "$tmp_file" "$CONTEXT_BUNDLE"
468
+ success "Context bundle written to ${CYAN}${CONTEXT_BUNDLE}${RESET}"
469
+
470
+ return 0
471
+ }
472
+
473
+ # ─── Show current bundle ───────────────────────────────────────────────────
474
+ show_context() {
475
+ if [[ ! -f "$CONTEXT_BUNDLE" ]]; then
476
+ warn "No context bundle found at ${CONTEXT_BUNDLE}"
477
+ echo "Run '${CYAN}shipwright context gather --goal \"...\" --stage plan${RESET}' first"
478
+ return 1
479
+ fi
480
+
481
+ cat "$CONTEXT_BUNDLE"
482
+ }
483
+
484
+ # ─── Clear stale bundle ────────────────────────────────────────────────────
485
+ clear_context() {
486
+ if [[ -f "$CONTEXT_BUNDLE" ]]; then
487
+ rm -f "$CONTEXT_BUNDLE"
488
+ success "Context bundle cleared"
489
+ else
490
+ warn "No context bundle to clear"
491
+ fi
492
+ }
493
+
494
+ # ─── Help ──────────────────────────────────────────────────────────────────
495
+ show_help() {
496
+ cat <<EOF
497
+ ${CYAN}${BOLD}shipwright context${RESET} ${DIM}v${VERSION}${RESET} — Context gathering engine for pipeline stages
498
+
499
+ ${BOLD}USAGE${RESET}
500
+ ${CYAN}shipwright context${RESET} <command> [options]
501
+
502
+ ${BOLD}COMMANDS${RESET}
503
+ ${CYAN}gather${RESET} --goal "..." --stage plan Generate context bundle
504
+ ${CYAN}gather${RESET} --issue N --stage build Generate from GitHub issue
505
+ ${CYAN}show${RESET} Display current bundle
506
+ ${CYAN}clear${RESET} Remove stale bundle
507
+ ${CYAN}help${RESET} Show this help
508
+
509
+ ${BOLD}OPTIONS${RESET}
510
+ ${CYAN}--goal${RESET} TEXT Goal or description for context gathering
511
+ ${CYAN}--issue${RESET} N GitHub issue number
512
+ ${CYAN}--stage${RESET} STAGE Pipeline stage: plan, design, build, test, review
513
+
514
+ ${BOLD}EXAMPLES${RESET}
515
+ ${DIM}shipwright context gather --goal "Add OAuth" --stage design${RESET}
516
+ ${DIM}shipwright context gather --issue 42 --stage build${RESET}
517
+ ${DIM}shipwright context show${RESET}
518
+ ${DIM}shipwright context clear${RESET}
519
+
520
+ ${BOLD}BUNDLE INCLUDES${RESET}
521
+ • Codebase patterns and standards
522
+ • File hotspots from intelligence analysis
523
+ • Recent merged PR outcomes
524
+ • Failure patterns and learned patterns
525
+ • Relevant file previews with code samples
526
+ • Architecture decision records
527
+ • Stage-specific guidance and checklists
528
+
529
+ ${DIM}The context bundle is written to .claude/pipeline-artifacts/context-bundle.md${RESET}
530
+ ${DIM}and automatically included in pipeline prompts.${RESET}
531
+
532
+ EOF
533
+ }
534
+
535
+ # ─── Main dispatcher ───────────────────────────────────────────────────────
536
+ main() {
537
+ local cmd="${1:-help}"
538
+ shift 2>/dev/null || true
539
+
540
+ case "$cmd" in
541
+ gather)
542
+ local goal="" issue="" stage="build"
543
+
544
+ while [[ $# -gt 0 ]]; do
545
+ case "$1" in
546
+ --goal)
547
+ goal="$2"
548
+ shift 2
549
+ ;;
550
+ --issue)
551
+ issue="$2"
552
+ shift 2
553
+ ;;
554
+ --stage)
555
+ stage="$2"
556
+ shift 2
557
+ ;;
558
+ *)
559
+ error "Unknown option: $1"
560
+ echo ""
561
+ show_help
562
+ exit 1
563
+ ;;
564
+ esac
565
+ done
566
+
567
+ if [[ -z "$goal" && -z "$issue" ]]; then
568
+ error "Must provide --goal or --issue"
569
+ echo ""
570
+ show_help
571
+ exit 1
572
+ fi
573
+
574
+ # If issue provided, fetch from GitHub
575
+ if [[ -n "$issue" ]]; then
576
+ if [[ "${NO_GITHUB:-}" == "true" ]] || ! command -v gh &>/dev/null; then
577
+ goal="GitHub issue #$issue (fetch unavailable)"
578
+ else
579
+ goal=$(gh issue view "$issue" --json title,body --template '{{.title}}: {{.body}}' 2>/dev/null || echo "GitHub issue #$issue")
580
+ fi
581
+ fi
582
+
583
+ gather_context "$goal" "$stage"
584
+ ;;
585
+ show)
586
+ show_context
587
+ ;;
588
+ clear)
589
+ clear_context
590
+ ;;
591
+ help|--help|-h)
592
+ show_help
593
+ ;;
594
+ *)
595
+ error "Unknown command: $cmd"
596
+ echo ""
597
+ show_help
598
+ exit 1
599
+ ;;
600
+ esac
601
+ }
602
+
603
+ if [[ "${BASH_SOURCE[0]}" == "$0" ]]; then
604
+ main "$@"
605
+ fi
@@ -6,7 +6,7 @@
6
6
  set -euo pipefail
7
7
  trap 'echo "ERROR: $BASH_SOURCE:$LINENO exited with status $?" >&2' ERR
8
8
 
9
- VERSION="1.9.0"
9
+ VERSION="2.0.0"
10
10
  SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
11
11
  REPO_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
12
12