shipwright-cli 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (279) hide show
  1. package/.claude/agents/code-reviewer.md +2 -0
  2. package/.claude/agents/devops-engineer.md +2 -0
  3. package/.claude/agents/doc-fleet-agent.md +2 -0
  4. package/.claude/agents/pipeline-agent.md +2 -0
  5. package/.claude/agents/shell-script-specialist.md +2 -0
  6. package/.claude/agents/test-specialist.md +2 -0
  7. package/.claude/hooks/agent-crash-capture.sh +32 -0
  8. package/.claude/hooks/post-tool-use.sh +3 -2
  9. package/.claude/hooks/pre-tool-use.sh +35 -3
  10. package/README.md +4 -4
  11. package/claude-code/hooks/config-change.sh +18 -0
  12. package/claude-code/hooks/instructions-reloaded.sh +7 -0
  13. package/claude-code/hooks/worktree-create.sh +25 -0
  14. package/claude-code/hooks/worktree-remove.sh +20 -0
  15. package/config/code-constitution.json +130 -0
  16. package/dashboard/middleware/auth.ts +134 -0
  17. package/dashboard/middleware/constants.ts +21 -0
  18. package/dashboard/public/index.html +2 -6
  19. package/dashboard/public/styles.css +100 -97
  20. package/dashboard/routes/auth.ts +38 -0
  21. package/dashboard/server.ts +66 -25
  22. package/dashboard/services/config.ts +26 -0
  23. package/dashboard/services/db.ts +118 -0
  24. package/dashboard/src/canvas/pixel-agent.ts +298 -0
  25. package/dashboard/src/canvas/pixel-sprites.ts +440 -0
  26. package/dashboard/src/canvas/shipyard-effects.ts +367 -0
  27. package/dashboard/src/canvas/shipyard-scene.ts +616 -0
  28. package/dashboard/src/canvas/submarine-layout.ts +267 -0
  29. package/dashboard/src/components/header.ts +8 -7
  30. package/dashboard/src/core/router.ts +1 -0
  31. package/dashboard/src/design/submarine-theme.ts +253 -0
  32. package/dashboard/src/main.ts +2 -0
  33. package/dashboard/src/types/api.ts +2 -1
  34. package/dashboard/src/views/activity.ts +2 -1
  35. package/dashboard/src/views/shipyard.ts +39 -0
  36. package/dashboard/types/index.ts +166 -0
  37. package/docs/plans/2026-02-28-compound-audit-and-shipyard-design.md +186 -0
  38. package/docs/plans/2026-02-28-skipper-shipwright-implementation-plan.md +1182 -0
  39. package/docs/plans/2026-02-28-skipper-shipwright-integration-design.md +531 -0
  40. package/docs/plans/2026-03-01-ai-powered-skill-injection-design.md +298 -0
  41. package/docs/plans/2026-03-01-ai-powered-skill-injection-plan.md +1109 -0
  42. package/docs/plans/2026-03-01-capabilities-cleanup-plan.md +658 -0
  43. package/docs/plans/2026-03-01-clean-architecture-plan.md +924 -0
  44. package/docs/plans/2026-03-01-compound-audit-cascade-design.md +191 -0
  45. package/docs/plans/2026-03-01-compound-audit-cascade-plan.md +921 -0
  46. package/docs/plans/2026-03-01-deep-integration-plan.md +851 -0
  47. package/docs/plans/2026-03-01-pipeline-audit-trail-design.md +145 -0
  48. package/docs/plans/2026-03-01-pipeline-audit-trail-plan.md +770 -0
  49. package/docs/plans/2026-03-01-refined-depths-brand-design.md +382 -0
  50. package/docs/plans/2026-03-01-refined-depths-implementation.md +599 -0
  51. package/docs/plans/2026-03-01-skipper-kernel-integration-design.md +203 -0
  52. package/docs/plans/2026-03-01-unified-platform-design.md +272 -0
  53. package/docs/plans/2026-03-07-claude-code-feature-integration-design.md +189 -0
  54. package/docs/plans/2026-03-07-claude-code-feature-integration-plan.md +1165 -0
  55. package/docs/research/BACKLOG_QUICK_REFERENCE.md +352 -0
  56. package/docs/research/CUTTING_EDGE_RESEARCH_2026.md +546 -0
  57. package/docs/research/RESEARCH_INDEX.md +439 -0
  58. package/docs/research/RESEARCH_SOURCES.md +440 -0
  59. package/docs/research/RESEARCH_SUMMARY.txt +275 -0
  60. package/docs/superpowers/specs/2026-03-10-pipeline-quality-revolution-design.md +341 -0
  61. package/package.json +2 -2
  62. package/scripts/lib/adaptive-model.sh +427 -0
  63. package/scripts/lib/adaptive-timeout.sh +316 -0
  64. package/scripts/lib/audit-trail.sh +309 -0
  65. package/scripts/lib/auto-recovery.sh +471 -0
  66. package/scripts/lib/bandit-selector.sh +431 -0
  67. package/scripts/lib/bootstrap.sh +104 -2
  68. package/scripts/lib/causal-graph.sh +455 -0
  69. package/scripts/lib/compat.sh +126 -0
  70. package/scripts/lib/compound-audit.sh +337 -0
  71. package/scripts/lib/constitutional.sh +454 -0
  72. package/scripts/lib/context-budget.sh +359 -0
  73. package/scripts/lib/convergence.sh +594 -0
  74. package/scripts/lib/cost-optimizer.sh +634 -0
  75. package/scripts/lib/daemon-adaptive.sh +10 -0
  76. package/scripts/lib/daemon-dispatch.sh +106 -17
  77. package/scripts/lib/daemon-failure.sh +34 -4
  78. package/scripts/lib/daemon-patrol.sh +23 -2
  79. package/scripts/lib/daemon-poll-github.sh +361 -0
  80. package/scripts/lib/daemon-poll-health.sh +299 -0
  81. package/scripts/lib/daemon-poll.sh +27 -611
  82. package/scripts/lib/daemon-state.sh +112 -66
  83. package/scripts/lib/daemon-triage.sh +10 -0
  84. package/scripts/lib/dod-scorecard.sh +442 -0
  85. package/scripts/lib/error-actionability.sh +300 -0
  86. package/scripts/lib/formal-spec.sh +461 -0
  87. package/scripts/lib/helpers.sh +177 -4
  88. package/scripts/lib/intent-analysis.sh +409 -0
  89. package/scripts/lib/loop-convergence.sh +350 -0
  90. package/scripts/lib/loop-iteration.sh +682 -0
  91. package/scripts/lib/loop-progress.sh +48 -0
  92. package/scripts/lib/loop-restart.sh +185 -0
  93. package/scripts/lib/memory-effectiveness.sh +506 -0
  94. package/scripts/lib/mutation-executor.sh +352 -0
  95. package/scripts/lib/outcome-feedback.sh +521 -0
  96. package/scripts/lib/pipeline-cli.sh +336 -0
  97. package/scripts/lib/pipeline-commands.sh +1216 -0
  98. package/scripts/lib/pipeline-detection.sh +100 -2
  99. package/scripts/lib/pipeline-execution.sh +897 -0
  100. package/scripts/lib/pipeline-github.sh +28 -3
  101. package/scripts/lib/pipeline-intelligence-compound.sh +431 -0
  102. package/scripts/lib/pipeline-intelligence-scoring.sh +407 -0
  103. package/scripts/lib/pipeline-intelligence-skip.sh +181 -0
  104. package/scripts/lib/pipeline-intelligence.sh +100 -1136
  105. package/scripts/lib/pipeline-quality-bash-compat.sh +182 -0
  106. package/scripts/lib/pipeline-quality-checks.sh +17 -715
  107. package/scripts/lib/pipeline-quality-gates.sh +563 -0
  108. package/scripts/lib/pipeline-stages-build.sh +730 -0
  109. package/scripts/lib/pipeline-stages-delivery.sh +965 -0
  110. package/scripts/lib/pipeline-stages-intake.sh +1133 -0
  111. package/scripts/lib/pipeline-stages-monitor.sh +407 -0
  112. package/scripts/lib/pipeline-stages-review.sh +1022 -0
  113. package/scripts/lib/pipeline-stages.sh +59 -2929
  114. package/scripts/lib/pipeline-state.sh +36 -5
  115. package/scripts/lib/pipeline-util.sh +487 -0
  116. package/scripts/lib/policy-learner.sh +438 -0
  117. package/scripts/lib/process-reward.sh +493 -0
  118. package/scripts/lib/project-detect.sh +649 -0
  119. package/scripts/lib/quality-profile.sh +334 -0
  120. package/scripts/lib/recruit-commands.sh +885 -0
  121. package/scripts/lib/recruit-learning.sh +739 -0
  122. package/scripts/lib/recruit-roles.sh +648 -0
  123. package/scripts/lib/reward-aggregator.sh +458 -0
  124. package/scripts/lib/rl-optimizer.sh +362 -0
  125. package/scripts/lib/root-cause.sh +427 -0
  126. package/scripts/lib/scope-enforcement.sh +445 -0
  127. package/scripts/lib/session-restart.sh +493 -0
  128. package/scripts/lib/skill-memory.sh +300 -0
  129. package/scripts/lib/skill-registry.sh +775 -0
  130. package/scripts/lib/spec-driven.sh +476 -0
  131. package/scripts/lib/test-helpers.sh +18 -7
  132. package/scripts/lib/test-holdout.sh +429 -0
  133. package/scripts/lib/test-optimizer.sh +511 -0
  134. package/scripts/shipwright-file-suggest.sh +45 -0
  135. package/scripts/skills/adversarial-quality.md +61 -0
  136. package/scripts/skills/api-design.md +44 -0
  137. package/scripts/skills/architecture-design.md +50 -0
  138. package/scripts/skills/brainstorming.md +43 -0
  139. package/scripts/skills/data-pipeline.md +44 -0
  140. package/scripts/skills/deploy-safety.md +64 -0
  141. package/scripts/skills/documentation.md +38 -0
  142. package/scripts/skills/frontend-design.md +45 -0
  143. package/scripts/skills/generated/.gitkeep +0 -0
  144. package/scripts/skills/generated/_refinements/.gitkeep +0 -0
  145. package/scripts/skills/generated/_refinements/adversarial-quality.patch.md +3 -0
  146. package/scripts/skills/generated/_refinements/architecture-design.patch.md +3 -0
  147. package/scripts/skills/generated/_refinements/brainstorming.patch.md +3 -0
  148. package/scripts/skills/generated/cli-version-management.md +29 -0
  149. package/scripts/skills/generated/collection-system-validation.md +99 -0
  150. package/scripts/skills/generated/large-scale-c-refactoring-coordination.md +97 -0
  151. package/scripts/skills/generated/pattern-matching-similarity-scoring.md +195 -0
  152. package/scripts/skills/generated/test-parallelization-detection.md +65 -0
  153. package/scripts/skills/observability.md +79 -0
  154. package/scripts/skills/performance.md +48 -0
  155. package/scripts/skills/pr-quality.md +49 -0
  156. package/scripts/skills/product-thinking.md +43 -0
  157. package/scripts/skills/security-audit.md +49 -0
  158. package/scripts/skills/systematic-debugging.md +40 -0
  159. package/scripts/skills/testing-strategy.md +47 -0
  160. package/scripts/skills/two-stage-review.md +52 -0
  161. package/scripts/skills/validation-thoroughness.md +55 -0
  162. package/scripts/sw +9 -3
  163. package/scripts/sw-activity.sh +9 -2
  164. package/scripts/sw-adaptive.sh +2 -1
  165. package/scripts/sw-adversarial.sh +2 -1
  166. package/scripts/sw-architecture-enforcer.sh +3 -1
  167. package/scripts/sw-auth.sh +12 -2
  168. package/scripts/sw-autonomous.sh +5 -1
  169. package/scripts/sw-changelog.sh +4 -1
  170. package/scripts/sw-checkpoint.sh +2 -1
  171. package/scripts/sw-ci.sh +5 -1
  172. package/scripts/sw-cleanup.sh +4 -26
  173. package/scripts/sw-code-review.sh +10 -4
  174. package/scripts/sw-connect.sh +2 -1
  175. package/scripts/sw-context.sh +2 -1
  176. package/scripts/sw-cost.sh +48 -3
  177. package/scripts/sw-daemon.sh +66 -9
  178. package/scripts/sw-dashboard.sh +3 -1
  179. package/scripts/sw-db.sh +59 -16
  180. package/scripts/sw-decide.sh +8 -2
  181. package/scripts/sw-decompose.sh +360 -17
  182. package/scripts/sw-deps.sh +4 -1
  183. package/scripts/sw-developer-simulation.sh +4 -1
  184. package/scripts/sw-discovery.sh +325 -2
  185. package/scripts/sw-doc-fleet.sh +4 -1
  186. package/scripts/sw-docs-agent.sh +3 -1
  187. package/scripts/sw-docs.sh +2 -1
  188. package/scripts/sw-doctor.sh +453 -2
  189. package/scripts/sw-dora.sh +4 -1
  190. package/scripts/sw-durable.sh +4 -3
  191. package/scripts/sw-e2e-orchestrator.sh +17 -16
  192. package/scripts/sw-eventbus.sh +7 -1
  193. package/scripts/sw-evidence.sh +364 -12
  194. package/scripts/sw-feedback.sh +550 -9
  195. package/scripts/sw-fix.sh +20 -1
  196. package/scripts/sw-fleet-discover.sh +6 -2
  197. package/scripts/sw-fleet-viz.sh +4 -1
  198. package/scripts/sw-fleet.sh +5 -1
  199. package/scripts/sw-github-app.sh +16 -3
  200. package/scripts/sw-github-checks.sh +3 -2
  201. package/scripts/sw-github-deploy.sh +3 -2
  202. package/scripts/sw-github-graphql.sh +18 -7
  203. package/scripts/sw-guild.sh +5 -1
  204. package/scripts/sw-heartbeat.sh +5 -30
  205. package/scripts/sw-hello.sh +67 -0
  206. package/scripts/sw-hygiene.sh +6 -1
  207. package/scripts/sw-incident.sh +265 -1
  208. package/scripts/sw-init.sh +18 -2
  209. package/scripts/sw-instrument.sh +10 -2
  210. package/scripts/sw-intelligence.sh +42 -6
  211. package/scripts/sw-jira.sh +5 -1
  212. package/scripts/sw-launchd.sh +2 -1
  213. package/scripts/sw-linear.sh +4 -1
  214. package/scripts/sw-logs.sh +4 -1
  215. package/scripts/sw-loop.sh +432 -1128
  216. package/scripts/sw-memory.sh +356 -2
  217. package/scripts/sw-mission-control.sh +6 -1
  218. package/scripts/sw-model-router.sh +481 -26
  219. package/scripts/sw-otel.sh +13 -4
  220. package/scripts/sw-oversight.sh +14 -5
  221. package/scripts/sw-patrol-meta.sh +334 -0
  222. package/scripts/sw-pipeline-composer.sh +5 -1
  223. package/scripts/sw-pipeline-vitals.sh +2 -1
  224. package/scripts/sw-pipeline.sh +53 -2664
  225. package/scripts/sw-pm.sh +12 -5
  226. package/scripts/sw-pr-lifecycle.sh +2 -1
  227. package/scripts/sw-predictive.sh +7 -1
  228. package/scripts/sw-prep.sh +185 -2
  229. package/scripts/sw-ps.sh +5 -25
  230. package/scripts/sw-public-dashboard.sh +15 -3
  231. package/scripts/sw-quality.sh +2 -1
  232. package/scripts/sw-reaper.sh +8 -25
  233. package/scripts/sw-recruit.sh +156 -2303
  234. package/scripts/sw-regression.sh +19 -12
  235. package/scripts/sw-release-manager.sh +3 -1
  236. package/scripts/sw-release.sh +4 -1
  237. package/scripts/sw-remote.sh +3 -1
  238. package/scripts/sw-replay.sh +7 -1
  239. package/scripts/sw-retro.sh +158 -1
  240. package/scripts/sw-review-rerun.sh +3 -1
  241. package/scripts/sw-scale.sh +10 -3
  242. package/scripts/sw-security-audit.sh +6 -1
  243. package/scripts/sw-self-optimize.sh +6 -3
  244. package/scripts/sw-session.sh +9 -3
  245. package/scripts/sw-setup.sh +3 -1
  246. package/scripts/sw-stall-detector.sh +406 -0
  247. package/scripts/sw-standup.sh +15 -7
  248. package/scripts/sw-status.sh +3 -1
  249. package/scripts/sw-strategic.sh +4 -1
  250. package/scripts/sw-stream.sh +7 -1
  251. package/scripts/sw-swarm.sh +18 -6
  252. package/scripts/sw-team-stages.sh +13 -6
  253. package/scripts/sw-templates.sh +5 -29
  254. package/scripts/sw-testgen.sh +7 -1
  255. package/scripts/sw-tmux-pipeline.sh +4 -1
  256. package/scripts/sw-tmux-role-color.sh +2 -0
  257. package/scripts/sw-tmux-status.sh +1 -1
  258. package/scripts/sw-tmux.sh +3 -1
  259. package/scripts/sw-trace.sh +3 -1
  260. package/scripts/sw-tracker-github.sh +3 -0
  261. package/scripts/sw-tracker-jira.sh +3 -0
  262. package/scripts/sw-tracker-linear.sh +3 -0
  263. package/scripts/sw-tracker.sh +3 -1
  264. package/scripts/sw-triage.sh +2 -1
  265. package/scripts/sw-upgrade.sh +3 -1
  266. package/scripts/sw-ux.sh +5 -2
  267. package/scripts/sw-webhook.sh +3 -1
  268. package/scripts/sw-widgets.sh +3 -1
  269. package/scripts/sw-worktree.sh +15 -3
  270. package/scripts/test-skill-injection.sh +1233 -0
  271. package/templates/pipelines/autonomous.json +27 -3
  272. package/templates/pipelines/cost-aware.json +34 -8
  273. package/templates/pipelines/deployed.json +12 -0
  274. package/templates/pipelines/enterprise.json +12 -0
  275. package/templates/pipelines/fast.json +6 -0
  276. package/templates/pipelines/full.json +27 -3
  277. package/templates/pipelines/hotfix.json +6 -0
  278. package/templates/pipelines/standard.json +12 -0
  279. package/templates/pipelines/tdd.json +12 -0
@@ -2,6 +2,8 @@
2
2
 
3
3
  You are a code review specialist for the Shipwright project. Your job is to review shell scripts, GitHub Actions workflows, and configuration files for correctness, security, and adherence to project conventions.
4
4
 
5
+ **Model Guidance**: Use Opus 4.6 for thorough architectural reviews. Set `maxTurns: 2` to prevent context bloat during iterative reviews. Use `worktree: true` for parallel code review runs.
6
+
5
7
  ## Review Checklist
6
8
 
7
9
  ### Bash 3.2 Compatibility (Blockers)
@@ -2,6 +2,8 @@
2
2
 
3
3
  You are a DevOps and CI/CD specialist for the Shipwright project. You work on GitHub Actions workflows, deployment pipelines, infrastructure automation, and operational tooling.
4
4
 
5
+ **Model Guidance**: Use Opus 4.6 for complex infrastructure changes. Use `worktree: true` to isolate concurrent infrastructure updates. Set `maxTurns: 2` for exploratory work.
6
+
5
7
  ## GitHub Actions Workflows
6
8
 
7
9
  Workflows live in `.github/workflows/` with the `shipwright-*.yml` naming prefix:
@@ -2,6 +2,8 @@
2
2
 
3
3
  You are a specialized agent in the Shipwright documentation fleet. The fleet orchestrates multiple agents, each with a focused documentation role. Your specific role is assigned at spawn time.
4
4
 
5
+ **Model Guidance**: Use Sonnet 4.6 for documentation work. Use `background: true` for parallel doc fleet agents (audit, refactor, enhance). Set `maxTurns: 2` per role to focus on specialized tasks.
6
+
5
7
  ## Fleet Roles
6
8
 
7
9
  ### 1. Doc Architect (leader)
@@ -2,6 +2,8 @@
2
2
 
3
3
  You are an autonomous agent running inside the Shipwright delivery pipeline's build stage. You were spawned by `shipwright loop`, which was called by `shipwright pipeline` during the build stage.
4
4
 
5
+ **Model Guidance**: Use Opus 4.6 for complex builds, Sonnet 4.6 for standard features, and Haiku for simple bug fixes. For background tasks (long-running test suites), set `background: true` and allow pre-approved tool permissions.
6
+
5
7
  ## Your Context
6
8
 
7
9
  Your goal comes from the **enriched goal** assembled by the pipeline, which includes:
@@ -2,6 +2,8 @@
2
2
 
3
3
  You are a shell script development specialist for the Shipwright project — an autonomous delivery platform built entirely in Bash (37+ scripts, 25,000+ lines).
4
4
 
5
+ **Model Guidance**: Use Sonnet 4.6 for script development. For long-running test harnesses, use `background: true` with pre-approved permissions.
6
+
5
7
  ## Bash 3.2 Compatibility (CRITICAL)
6
8
 
7
9
  Shipwright must run on macOS default Bash 3.2. The following are **forbidden**:
@@ -2,6 +2,8 @@
2
2
 
3
3
  You are a test development specialist for the Shipwright project. The project has 90+ test suites (see `package.json` scripts.test and the AUTO:test-suites table in `.claude/CLAUDE.md`), all written in Bash following a consistent harness pattern.
4
4
 
5
+ **Model Guidance**: Use Sonnet 4.6 for test development. Use `background: true` and `maxTurns: 3` for long test runs to prevent context bloat.
6
+
5
7
  ## Test Harness Conventions
6
8
 
7
9
  ### File Structure
@@ -0,0 +1,32 @@
1
+ #!/usr/bin/env bash
2
+ # Hook: Capture diagnostics when a Skipper agent crashes
3
+ # Trigger: Post-tool-use on Bash failures that look like agent crashes
4
+
5
+ set -euo pipefail
6
+
7
+ # Read stdin for tool result context
8
+ INPUT="$(cat)"
9
+
10
+ # Check if this looks like an agent crash
11
+ if echo "$INPUT" | grep -qi "panic\|segfault\|killed\|oom\|fatal\|crash"; then
12
+ TIMESTAMP="$(date +%Y%m%d_%H%M%S)"
13
+ CRASH_DIR="${HOME}/.shipwright/crash-reports"
14
+ mkdir -p "$CRASH_DIR"
15
+
16
+ REPORT_FILE="${CRASH_DIR}/crash_${TIMESTAMP}.json"
17
+
18
+ # Capture diagnostics
19
+ cat > "$REPORT_FILE" << EOF
20
+ {
21
+ "timestamp": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
22
+ "working_directory": "$(pwd)",
23
+ "git_branch": "$(git branch --show-current 2>/dev/null || echo 'unknown')",
24
+ "git_commit": "$(git rev-parse HEAD 2>/dev/null || echo 'unknown')",
25
+ "error_context": $(echo "$INPUT" | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()[:2000]))" 2>/dev/null || echo '"capture_failed"'),
26
+ "pipeline_state": "$(cat .claude/pipeline-state.md 2>/dev/null | head -20 | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '"none"')",
27
+ "recent_commits": "$(git log --oneline -5 2>/dev/null | python3 -c "import sys,json; print(json.dumps(sys.stdin.read()))" 2>/dev/null || echo '"none"')"
28
+ }
29
+ EOF
30
+
31
+ echo "Crash report saved to $REPORT_FILE" >&2
32
+ fi
@@ -19,8 +19,9 @@ if [[ "$tool_name" == "Bash" ]] && [[ "${exit_code:-0}" != "0" ]]; then
19
19
  # Classify error type
20
20
  error_type="unknown"
21
21
  case "$error_snippet" in
22
- *"test"*|*"FAIL"*|*"assert"*|*"expect"*) error_type="test" ;;
23
- *"syntax"*|*"unexpected"*|*"parse error"*) error_type="syntax" ;;
22
+ *"syntax"*|*"parse error"*) error_type="syntax" ;;
23
+ *"unexpected token"*|*"unexpected end"*) error_type="syntax" ;;
24
+ *"test"*|*"FAIL"*|*"assert"*|*"expect"*) error_type="test" ;;
24
25
  *"not found"*|*"No such"*|*"ENOENT"*) error_type="missing" ;;
25
26
  *"permission"*|*"denied"*|*"EACCES"*) error_type="permission" ;;
26
27
  *"timeout"*|*"timed out"*|*"ETIMEDOUT"*) error_type="timeout" ;;
@@ -1,14 +1,46 @@
1
1
  #!/usr/bin/env bash
2
- # Hook: PreToolUse — Context injection for .sh file editing
2
+ # Hook: PreToolUse — Security checks and context injection
3
3
  # Triggered before Write/Edit tools
4
4
 
5
5
  # Read tool input from stdin (JSON)
6
6
  input=$(cat)
7
7
 
8
- # Extract file path from tool input
8
+ # Extract tool name and file path
9
+ tool_name=$(echo "$input" | jq -r '.tool_name // empty' 2>/dev/null)
9
10
  file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty' 2>/dev/null)
11
+ new_string=$(echo "$input" | jq -r '.tool_input.new_string // empty' 2>/dev/null)
12
+ tool_input=$(echo "$input" | jq -r '.tool_input // empty' 2>/dev/null)
10
13
 
11
- # Only trigger for shell script files
14
+ # Security check: Block git push --no-verify (bypasses pre-commit hooks)
15
+ if echo "$tool_input" | grep -qE 'git\s+push.*--no-verify'; then
16
+ echo '{"message":"Blocked: git push --no-verify bypasses safety checks. Remove --no-verify flag."}'
17
+ exit 2
18
+ fi
19
+
20
+ # Security check: Detect secrets being written to non-secret files
21
+ if [[ "$tool_name" == "Edit" || "$tool_name" == "Write" ]]; then
22
+ # Sensitive files that should not be added to version control
23
+ if [[ ! "$file_path" =~ (\.env|\.secret|secret|credential|key|token|private) ]]; then
24
+ # Check for common secret patterns
25
+ secret_patterns="sk-ant-|ANTHROPIC_API_KEY|GITHUB_TOKEN|OPENAI_API_KEY|AWS_SECRET|DATABASE_URL|PRIVATE_KEY|api_key|BEGIN RSA PRIVATE KEY|BEGIN PRIVATE KEY"
26
+
27
+ if echo "$new_string" | grep -qE "$secret_patterns"; then
28
+ cat << "SECURITY_WARNING"
29
+ ⚠️ SECURITY WARNING: Secret pattern detected in non-secret file
30
+
31
+ The content being written to this file contains a potential secret.
32
+ File: $file_path
33
+
34
+ Sensitive data should NEVER be committed to version control.
35
+
36
+ If this is intentional (e.g., example code), please review carefully.
37
+ SECURITY_WARNING
38
+ exit 2
39
+ fi
40
+ fi
41
+ fi
42
+
43
+ # Shell script context injection
12
44
  if [[ "$file_path" == *.sh ]]; then
13
45
  cat << 'REMINDER'
14
46
  SHIPWRIGHT SHELL RULES:
package/README.md CHANGED
@@ -13,9 +13,9 @@
13
13
  <a href="https://github.com/sethdford/shipwright/actions/workflows/test.yml"><img src="https://github.com/sethdford/shipwright/actions/workflows/test.yml/badge.svg" alt="Tests"></a>
14
14
  <a href="https://github.com/sethdford/shipwright/actions/workflows/shipwright-pipeline.yml"><img src="https://github.com/sethdford/shipwright/actions/workflows/shipwright-pipeline.yml/badge.svg" alt="Pipeline"></a>
15
15
  <img src="https://img.shields.io/badge/tests-141_suites_passing-4ade80?style=flat-square" alt="141 suites">
16
- <img src="https://img.shields.io/badge/version-3.2.0-00d4ff?style=flat-square" alt="v3.2.0">
16
+ <img src="https://img.shields.io/badge/version-3.3.0-00d4ff?style=flat-square" alt="v3.3.0">
17
17
  <img src="https://img.shields.io/badge/license-MIT-green?style=flat-square" alt="MIT License">
18
- <img src="https://img.shields.io/badge/bash-3.2%2B-7c3aed?style=flat-square" alt="Bash 3.2+">
18
+ <img src="https://img.shields.io/badge/bash-3.2%2B-555a66?style=flat-square" alt="Bash 3.2+">
19
19
  </p>
20
20
 
21
21
  ---
@@ -24,7 +24,7 @@
24
24
 
25
25
  - [Shipwright Builds Itself](#shipwright-builds-itself)
26
26
  - [Code Factory Pattern](#code-factory-pattern)
27
- - [What's New in v3.2.0](#whats-new-in-v320)
27
+ - [What's New in v3.3.0](#whats-new-in-v330)
28
28
  - [How It Works](#how-it-works)
29
29
  - [Install](#install)
30
30
  - [Quick Start](#quick-start)
@@ -109,7 +109,7 @@ shipwright incident gap sla
109
109
 
110
110
  ---
111
111
 
112
- ## What's New in v3.2.0
112
+ ## What's New in v3.3.0
113
113
 
114
114
  **Code Factory pattern** — deterministic, risk-aware agent delivery with machine-verifiable evidence:
115
115
 
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env bash
2
+ # Hook: ConfigChange — notify daemon of config updates
3
+ set -euo pipefail
4
+
5
+ input=$(cat)
6
+
7
+ # Log config change event
8
+ mkdir -p "$HOME/.shipwright" 2>/dev/null || true
9
+ echo "{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"config.changed\",\"detail\":$(echo "$input" | jq -c '.' 2>/dev/null || echo '{}')}" >> "$HOME/.shipwright/events.jsonl" 2>/dev/null || true
10
+
11
+ # Signal running daemon to reload config (if PID file exists)
12
+ pid_file="$HOME/.shipwright/daemon.pid"
13
+ if [[ -f "$pid_file" ]]; then
14
+ daemon_pid=$(cat "$pid_file" 2>/dev/null || true)
15
+ if [[ -n "$daemon_pid" ]] && kill -0 "$daemon_pid" 2>/dev/null; then
16
+ kill -USR1 "$daemon_pid" 2>/dev/null || true
17
+ fi
18
+ fi
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env bash
2
+ # Hook: InstructionsLoaded (matcher: "compact")
3
+ # After auto-compaction, log reload event for observability
4
+ set -euo pipefail
5
+
6
+ mkdir -p "$HOME/.shipwright" 2>/dev/null || true
7
+ echo "{\"ts\":\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\",\"type\":\"instructions.reloaded\",\"trigger\":\"compaction\"}" >> "$HOME/.shipwright/events.jsonl" 2>/dev/null || true
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env bash
2
+ # Hook: WorktreeCreate — auto-setup worktree for pipeline agents
3
+ # Copies essential config into new worktrees so agents inherit settings
4
+ set -euo pipefail
5
+
6
+ # Read hook input from stdin (JSON with worktree details)
7
+ input=$(cat)
8
+ worktree_path=$(echo "$input" | jq -r '.worktree_path // empty' 2>/dev/null || true)
9
+
10
+ [[ -z "$worktree_path" ]] && exit 0
11
+
12
+ # Copy daemon config if it exists
13
+ src_root=$(git rev-parse --show-toplevel 2>/dev/null || true)
14
+ if [[ -n "$src_root" ]]; then
15
+ src_config="$src_root/.claude/daemon-config.json"
16
+ if [[ -f "$src_config" ]]; then
17
+ mkdir -p "$worktree_path/.claude" 2>/dev/null || true
18
+ cp "$src_config" "$worktree_path/.claude/daemon-config.json" 2>/dev/null || true
19
+ fi
20
+
21
+ # Copy pipeline artifacts directory structure
22
+ if [[ -d "$src_root/.claude/pipeline-artifacts" ]]; then
23
+ mkdir -p "$worktree_path/.claude/pipeline-artifacts" 2>/dev/null || true
24
+ fi
25
+ fi
@@ -0,0 +1,20 @@
1
+ #!/usr/bin/env bash
2
+ # Hook: WorktreeRemove — clean up state for removed worktree agents
3
+ set -euo pipefail
4
+
5
+ input=$(cat)
6
+ worktree_path=$(echo "$input" | jq -r '.worktree_path // empty' 2>/dev/null || true)
7
+
8
+ [[ -z "$worktree_path" ]] && exit 0
9
+
10
+ # Clean up heartbeat files associated with this worktree
11
+ heartbeat_dir="$HOME/.shipwright/heartbeats"
12
+ if [[ -d "$heartbeat_dir" ]]; then
13
+ for hb in "$heartbeat_dir"/*.json; do
14
+ [[ -f "$hb" ]] || continue
15
+ hb_path=$(jq -r '.worktree // empty' "$hb" 2>/dev/null || true)
16
+ if [[ "$hb_path" == "$worktree_path" ]]; then
17
+ rm -f "$hb"
18
+ fi
19
+ done
20
+ fi
@@ -0,0 +1,130 @@
1
+ {
2
+ "version": "1.0",
3
+ "description": "Constitutional principles for autonomous code self-critique",
4
+ "principles": {
5
+ "security": [
6
+ {
7
+ "id": "SEC-001",
8
+ "rule": "No hardcoded secrets, API keys, or passwords",
9
+ "severity": "critical",
10
+ "check": "grep -nE '(password|api_key|secret_key|api_secret|auth_token)\\s*=\\s*[\"'\"'\"']' {file}"
11
+ },
12
+ {
13
+ "id": "SEC-002",
14
+ "rule": "All user inputs must be validated before use",
15
+ "severity": "critical"
16
+ },
17
+ {
18
+ "id": "SEC-003",
19
+ "rule": "No eval() or exec() with dynamic content",
20
+ "severity": "critical",
21
+ "check": "grep -nE '\\beval\\b.*\\$|\\bexec\\b.*\\$' {file}"
22
+ },
23
+ {
24
+ "id": "SEC-004",
25
+ "rule": "No SQL string concatenation — use parameterized queries",
26
+ "severity": "high"
27
+ },
28
+ {
29
+ "id": "SEC-005",
30
+ "rule": "No shell injection via unquoted variables in commands",
31
+ "severity": "critical",
32
+ "check": "grep -nE '\\$\\{?[A-Za-z_]+\\}?[^\"'\"'\"']' {file}"
33
+ }
34
+ ],
35
+ "error_handling": [
36
+ {
37
+ "id": "ERR-001",
38
+ "rule": "No empty catch blocks — all errors must be handled or re-thrown",
39
+ "severity": "high",
40
+ "check": "grep -nE 'catch\\s*\\([^)]*\\)\\s*\\{\\s*\\}' {file}"
41
+ },
42
+ {
43
+ "id": "ERR-002",
44
+ "rule": "Error messages must be descriptive — no generic 'Error occurred'",
45
+ "severity": "medium",
46
+ "check": "grep -niE '(error occurred|something went wrong|an error happened)' {file}"
47
+ },
48
+ {
49
+ "id": "ERR-003",
50
+ "rule": "Return values from commands must be checked",
51
+ "severity": "high"
52
+ },
53
+ {
54
+ "id": "ERR-004",
55
+ "rule": "No silent failures — failed operations must log or propagate errors",
56
+ "severity": "medium"
57
+ }
58
+ ],
59
+ "quality": [
60
+ {
61
+ "id": "QUA-001",
62
+ "rule": "Functions should be under 100 lines",
63
+ "severity": "medium"
64
+ },
65
+ {
66
+ "id": "QUA-002",
67
+ "rule": "No TODO/FIXME/HACK comments in production code",
68
+ "severity": "low",
69
+ "check": "grep -nE '(TODO|FIXME|HACK|XXX)' {file}"
70
+ },
71
+ {
72
+ "id": "QUA-003",
73
+ "rule": "No magic numbers — use named constants",
74
+ "severity": "low"
75
+ },
76
+ {
77
+ "id": "QUA-004",
78
+ "rule": "No duplicate code blocks over 10 lines",
79
+ "severity": "medium"
80
+ },
81
+ {
82
+ "id": "QUA-005",
83
+ "rule": "No console.log or print statements left in production code",
84
+ "severity": "low",
85
+ "check": "grep -nE '\\bconsole\\.log\\b|\\bprint\\(' {file}"
86
+ }
87
+ ],
88
+ "testing": [
89
+ {
90
+ "id": "TST-001",
91
+ "rule": "New functions must have corresponding tests",
92
+ "severity": "high"
93
+ },
94
+ {
95
+ "id": "TST-002",
96
+ "rule": "Tests must cover error and edge cases, not just happy path",
97
+ "severity": "medium"
98
+ },
99
+ {
100
+ "id": "TST-003",
101
+ "rule": "No test-only code in production files",
102
+ "severity": "medium",
103
+ "check": "grep -nE '(if.*TEST|ifdef.*TEST|IS_TEST)' {file}"
104
+ },
105
+ {
106
+ "id": "TST-004",
107
+ "rule": "Test assertions must be specific — no assertTrue(result) without message",
108
+ "severity": "low"
109
+ }
110
+ ],
111
+ "performance": [
112
+ {
113
+ "id": "PRF-001",
114
+ "rule": "All database queries must have .limit() or LIMIT clause",
115
+ "severity": "high"
116
+ },
117
+ {
118
+ "id": "PRF-002",
119
+ "rule": "No unbounded loops over external data",
120
+ "severity": "medium"
121
+ },
122
+ {
123
+ "id": "PRF-003",
124
+ "rule": "Avoid synchronous file I/O in hot paths",
125
+ "severity": "medium",
126
+ "check": "grep -nE 'readFileSync|writeFileSync' {file}"
127
+ }
128
+ ]
129
+ }
130
+ }
@@ -0,0 +1,134 @@
1
+ import { join, extname } from "path";
2
+ import { readFileSync, existsSync, writeFileSync, mkdirSync, renameSync } from "fs";
3
+ import type { Session, AuthMode } from "../types/index.js";
4
+ import { SESSION_TTL_MS } from "./constants.js";
5
+
6
+ // Auth Config
7
+ const GITHUB_CLIENT_ID = process.env.GITHUB_CLIENT_ID || "";
8
+ const GITHUB_CLIENT_SECRET = process.env.GITHUB_CLIENT_SECRET || "";
9
+ const GITHUB_PAT = process.env.GITHUB_PAT || "";
10
+ const DASHBOARD_REPO = process.env.DASHBOARD_REPO || "";
11
+ const SESSION_SECRET = process.env.SESSION_SECRET || crypto.randomUUID();
12
+
13
+ const HOME = process.env.HOME || "";
14
+ const SESSIONS_FILE = join(HOME, ".shipwright", "sessions.json");
15
+
16
+ export const sessions = new Map<string, Session>();
17
+
18
+ export function createSession(data: Omit<Session, "expiresAt">): string {
19
+ const sessionId = crypto.randomUUID();
20
+ sessions.set(sessionId, {
21
+ ...data,
22
+ expiresAt: Date.now() + SESSION_TTL_MS,
23
+ });
24
+ saveSessions();
25
+ return sessionId;
26
+ }
27
+
28
+ export function getSession(req: Request): Session | null {
29
+ const cookie = req.headers.get("cookie");
30
+ if (!cookie) return null;
31
+
32
+ const match = cookie.match(/fleet_session=([^;]+)/);
33
+ if (!match) return null;
34
+
35
+ const sessionId = match[1];
36
+ const session = sessions.get(sessionId);
37
+ if (!session) return null;
38
+
39
+ if (Date.now() > session.expiresAt) {
40
+ sessions.delete(sessionId);
41
+ saveSessions();
42
+ return null;
43
+ }
44
+
45
+ return session;
46
+ }
47
+
48
+ export function getSessionFromCookie(cookie: string | null): Session | null {
49
+ if (!cookie) return null;
50
+ const match = cookie.match(/fleet_session=([^;]+)/);
51
+ if (!match) return null;
52
+ const session = sessions.get(match[1]);
53
+ if (!session || Date.now() > session.expiresAt) return null;
54
+ return session;
55
+ }
56
+
57
+ export function sessionCookie(sessionId: string): string {
58
+ return `fleet_session=${sessionId}; Path=/; HttpOnly; SameSite=Lax; Max-Age=${Math.floor(SESSION_TTL_MS / 1000)}`;
59
+ }
60
+
61
+ export function isLocalConnection(req: Request): boolean {
62
+ const host = req.headers.get("host") || "";
63
+ return (
64
+ host.startsWith("localhost:") ||
65
+ host.startsWith("127.0.0.1:") ||
66
+ host.startsWith("[::1]:")
67
+ );
68
+ }
69
+
70
+ export function clearSessionCookie(): string {
71
+ return "fleet_session=; Path=/; HttpOnly; SameSite=Lax; Max-Age=0";
72
+ }
73
+
74
+ export function loadSessions(): void {
75
+ try {
76
+ if (existsSync(SESSIONS_FILE)) {
77
+ const data = JSON.parse(readFileSync(SESSIONS_FILE, "utf-8"));
78
+ const now = Date.now();
79
+ if (data && typeof data === "object") {
80
+ for (const [id, sess] of Object.entries(data)) {
81
+ const s = sess as Session;
82
+ if (s.expiresAt > now) {
83
+ sessions.set(id, s);
84
+ }
85
+ }
86
+ }
87
+ }
88
+ } catch {
89
+ /* start fresh */
90
+ }
91
+ }
92
+
93
+ export function saveSessions(): void {
94
+ const dir = join(HOME, ".shipwright");
95
+ if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
96
+ const obj: Record<string, Session> = {};
97
+ for (const [id, sess] of sessions) {
98
+ obj[id] = sess;
99
+ }
100
+ const tmp = SESSIONS_FILE + ".tmp";
101
+ writeFileSync(tmp, JSON.stringify(obj, null, 2));
102
+ renameSync(tmp, SESSIONS_FILE);
103
+ }
104
+
105
+ export function getAuthMode(): AuthMode {
106
+ if (GITHUB_CLIENT_ID && GITHUB_CLIENT_SECRET && DASHBOARD_REPO)
107
+ return "oauth";
108
+ if (GITHUB_PAT && DASHBOARD_REPO) return "pat";
109
+ return "none";
110
+ }
111
+
112
+ export function isAuthEnabled(): boolean {
113
+ return getAuthMode() !== "none";
114
+ }
115
+
116
+ export function isPublicRoute(pathname: string): boolean {
117
+ return (
118
+ pathname === "/login" ||
119
+ pathname.startsWith("/auth/") ||
120
+ pathname === "/api/health" ||
121
+ pathname === "/api/ws-status" ||
122
+ pathname.startsWith("/api/join/") ||
123
+ pathname.startsWith("/api/connect/") ||
124
+ pathname === "/api/team" ||
125
+ pathname === "/api/team/activity" ||
126
+ pathname === "/api/team/invite" ||
127
+ pathname.startsWith("/api/team/invite/") ||
128
+ pathname === "/api/claim" ||
129
+ pathname === "/api/claim/release" ||
130
+ pathname === "/api/webhook/ci"
131
+ );
132
+ }
133
+
134
+ export { SESSION_SECRET, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET, GITHUB_PAT, DASHBOARD_REPO };
@@ -0,0 +1,21 @@
1
+ // Shared constants and configuration
2
+ export const CORS_HEADERS = {
3
+ "Access-Control-Allow-Origin": "*",
4
+ "Access-Control-Allow-Methods": "GET, POST, PATCH, DELETE, OPTIONS",
5
+ "Access-Control-Allow-Headers": "Content-Type",
6
+ };
7
+
8
+ export const WS_PUSH_INTERVAL_MS = 2000;
9
+ export const MAX_WS_CLIENTS = 50;
10
+ export const WS_CONNECTION_TIMEOUT_MS = 30 * 60 * 1000; // 30 minutes
11
+
12
+ export const SESSION_TTL_MS = 24 * 60 * 60 * 1000; // 24 hours
13
+ export const ALLOWED_PERMISSIONS = ["admin", "write"];
14
+
15
+ // ANSI color codes
16
+ export const CYAN = "\x1b[38;2;0;212;255m";
17
+ export const GREEN = "\x1b[38;2;74;222;128m";
18
+ export const BOLD = "\x1b[1m";
19
+ export const DIM = "\x1b[2m";
20
+ export const ULINE = "\x1b[4m";
21
+ export const RESET = "\x1b[0m";
@@ -4,12 +4,6 @@
4
4
  <meta charset="UTF-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
6
  <title>Fleet Command — Shipwright</title>
7
- <link rel="preconnect" href="https://fonts.googleapis.com" />
8
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
9
- <link
10
- href="https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=JetBrains+Mono:wght@400;500;700&family=Plus+Jakarta+Sans:wght@300;400;500;600;700&display=swap"
11
- rel="stylesheet"
12
- />
13
7
  <link rel="stylesheet" href="styles.css" />
14
8
  <link
15
9
  rel="icon"
@@ -113,6 +107,7 @@
113
107
  <button class="tab-btn" data-tab="fleet-map">Map</button>
114
108
  <button class="tab-btn" data-tab="pipeline-theater">Theater</button>
115
109
  <button class="tab-btn" data-tab="agent-cockpit">Cockpit</button>
110
+ <button class="tab-btn" data-tab="shipyard">Shipyard</button>
116
111
  <div class="tab-indicator" id="tab-indicator"></div>
117
112
  </div>
118
113
  </nav>
@@ -1032,6 +1027,7 @@
1032
1027
  <div class="tab-panel" id="panel-fleet-map"></div>
1033
1028
  <div class="tab-panel" id="panel-pipeline-theater"></div>
1034
1029
  <div class="tab-panel" id="panel-agent-cockpit"></div>
1030
+ <div class="tab-panel" id="panel-shipyard"></div>
1035
1031
 
1036
1032
  <script src="dist/main.js"></script>
1037
1033
  </body>