shipwright-cli 3.1.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 (283) 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 +22 -8
  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/config/defaults.json +25 -2
  17. package/config/policy.json +1 -1
  18. package/dashboard/middleware/auth.ts +134 -0
  19. package/dashboard/middleware/constants.ts +21 -0
  20. package/dashboard/public/index.html +8 -6
  21. package/dashboard/public/styles.css +176 -97
  22. package/dashboard/routes/auth.ts +38 -0
  23. package/dashboard/server.ts +117 -25
  24. package/dashboard/services/config.ts +26 -0
  25. package/dashboard/services/db.ts +118 -0
  26. package/dashboard/src/canvas/pixel-agent.ts +298 -0
  27. package/dashboard/src/canvas/pixel-sprites.ts +440 -0
  28. package/dashboard/src/canvas/shipyard-effects.ts +367 -0
  29. package/dashboard/src/canvas/shipyard-scene.ts +616 -0
  30. package/dashboard/src/canvas/submarine-layout.ts +267 -0
  31. package/dashboard/src/components/header.ts +8 -7
  32. package/dashboard/src/core/api.ts +5 -0
  33. package/dashboard/src/core/router.ts +1 -0
  34. package/dashboard/src/design/submarine-theme.ts +253 -0
  35. package/dashboard/src/main.ts +2 -0
  36. package/dashboard/src/types/api.ts +12 -1
  37. package/dashboard/src/views/activity.ts +2 -1
  38. package/dashboard/src/views/metrics.ts +69 -1
  39. package/dashboard/src/views/shipyard.ts +39 -0
  40. package/dashboard/types/index.ts +166 -0
  41. package/docs/plans/2026-02-28-compound-audit-and-shipyard-design.md +186 -0
  42. package/docs/plans/2026-02-28-skipper-shipwright-implementation-plan.md +1182 -0
  43. package/docs/plans/2026-02-28-skipper-shipwright-integration-design.md +531 -0
  44. package/docs/plans/2026-03-01-ai-powered-skill-injection-design.md +298 -0
  45. package/docs/plans/2026-03-01-ai-powered-skill-injection-plan.md +1109 -0
  46. package/docs/plans/2026-03-01-capabilities-cleanup-plan.md +658 -0
  47. package/docs/plans/2026-03-01-clean-architecture-plan.md +924 -0
  48. package/docs/plans/2026-03-01-compound-audit-cascade-design.md +191 -0
  49. package/docs/plans/2026-03-01-compound-audit-cascade-plan.md +921 -0
  50. package/docs/plans/2026-03-01-deep-integration-plan.md +851 -0
  51. package/docs/plans/2026-03-01-pipeline-audit-trail-design.md +145 -0
  52. package/docs/plans/2026-03-01-pipeline-audit-trail-plan.md +770 -0
  53. package/docs/plans/2026-03-01-refined-depths-brand-design.md +382 -0
  54. package/docs/plans/2026-03-01-refined-depths-implementation.md +599 -0
  55. package/docs/plans/2026-03-01-skipper-kernel-integration-design.md +203 -0
  56. package/docs/plans/2026-03-01-unified-platform-design.md +272 -0
  57. package/docs/plans/2026-03-07-claude-code-feature-integration-design.md +189 -0
  58. package/docs/plans/2026-03-07-claude-code-feature-integration-plan.md +1165 -0
  59. package/docs/research/BACKLOG_QUICK_REFERENCE.md +352 -0
  60. package/docs/research/CUTTING_EDGE_RESEARCH_2026.md +546 -0
  61. package/docs/research/RESEARCH_INDEX.md +439 -0
  62. package/docs/research/RESEARCH_SOURCES.md +440 -0
  63. package/docs/research/RESEARCH_SUMMARY.txt +275 -0
  64. package/docs/superpowers/specs/2026-03-10-pipeline-quality-revolution-design.md +341 -0
  65. package/package.json +2 -2
  66. package/scripts/lib/adaptive-model.sh +427 -0
  67. package/scripts/lib/adaptive-timeout.sh +316 -0
  68. package/scripts/lib/audit-trail.sh +309 -0
  69. package/scripts/lib/auto-recovery.sh +471 -0
  70. package/scripts/lib/bandit-selector.sh +431 -0
  71. package/scripts/lib/bootstrap.sh +104 -2
  72. package/scripts/lib/causal-graph.sh +455 -0
  73. package/scripts/lib/compat.sh +126 -0
  74. package/scripts/lib/compound-audit.sh +337 -0
  75. package/scripts/lib/constitutional.sh +454 -0
  76. package/scripts/lib/context-budget.sh +359 -0
  77. package/scripts/lib/convergence.sh +594 -0
  78. package/scripts/lib/cost-optimizer.sh +634 -0
  79. package/scripts/lib/daemon-adaptive.sh +14 -2
  80. package/scripts/lib/daemon-dispatch.sh +106 -17
  81. package/scripts/lib/daemon-failure.sh +34 -4
  82. package/scripts/lib/daemon-patrol.sh +25 -4
  83. package/scripts/lib/daemon-poll-github.sh +361 -0
  84. package/scripts/lib/daemon-poll-health.sh +299 -0
  85. package/scripts/lib/daemon-poll.sh +27 -611
  86. package/scripts/lib/daemon-state.sh +119 -66
  87. package/scripts/lib/daemon-triage.sh +10 -0
  88. package/scripts/lib/dod-scorecard.sh +442 -0
  89. package/scripts/lib/error-actionability.sh +300 -0
  90. package/scripts/lib/formal-spec.sh +461 -0
  91. package/scripts/lib/helpers.sh +180 -5
  92. package/scripts/lib/intent-analysis.sh +409 -0
  93. package/scripts/lib/loop-convergence.sh +350 -0
  94. package/scripts/lib/loop-iteration.sh +682 -0
  95. package/scripts/lib/loop-progress.sh +48 -0
  96. package/scripts/lib/loop-restart.sh +185 -0
  97. package/scripts/lib/memory-effectiveness.sh +506 -0
  98. package/scripts/lib/mutation-executor.sh +352 -0
  99. package/scripts/lib/outcome-feedback.sh +521 -0
  100. package/scripts/lib/pipeline-cli.sh +336 -0
  101. package/scripts/lib/pipeline-commands.sh +1216 -0
  102. package/scripts/lib/pipeline-detection.sh +101 -3
  103. package/scripts/lib/pipeline-execution.sh +897 -0
  104. package/scripts/lib/pipeline-github.sh +28 -3
  105. package/scripts/lib/pipeline-intelligence-compound.sh +431 -0
  106. package/scripts/lib/pipeline-intelligence-scoring.sh +407 -0
  107. package/scripts/lib/pipeline-intelligence-skip.sh +181 -0
  108. package/scripts/lib/pipeline-intelligence.sh +104 -1138
  109. package/scripts/lib/pipeline-quality-bash-compat.sh +182 -0
  110. package/scripts/lib/pipeline-quality-checks.sh +17 -711
  111. package/scripts/lib/pipeline-quality-gates.sh +563 -0
  112. package/scripts/lib/pipeline-stages-build.sh +730 -0
  113. package/scripts/lib/pipeline-stages-delivery.sh +965 -0
  114. package/scripts/lib/pipeline-stages-intake.sh +1133 -0
  115. package/scripts/lib/pipeline-stages-monitor.sh +407 -0
  116. package/scripts/lib/pipeline-stages-review.sh +1022 -0
  117. package/scripts/lib/pipeline-stages.sh +161 -2901
  118. package/scripts/lib/pipeline-state.sh +36 -5
  119. package/scripts/lib/pipeline-util.sh +487 -0
  120. package/scripts/lib/policy-learner.sh +438 -0
  121. package/scripts/lib/process-reward.sh +493 -0
  122. package/scripts/lib/project-detect.sh +649 -0
  123. package/scripts/lib/quality-profile.sh +334 -0
  124. package/scripts/lib/recruit-commands.sh +885 -0
  125. package/scripts/lib/recruit-learning.sh +739 -0
  126. package/scripts/lib/recruit-roles.sh +648 -0
  127. package/scripts/lib/reward-aggregator.sh +458 -0
  128. package/scripts/lib/rl-optimizer.sh +362 -0
  129. package/scripts/lib/root-cause.sh +427 -0
  130. package/scripts/lib/scope-enforcement.sh +445 -0
  131. package/scripts/lib/session-restart.sh +493 -0
  132. package/scripts/lib/skill-memory.sh +300 -0
  133. package/scripts/lib/skill-registry.sh +775 -0
  134. package/scripts/lib/spec-driven.sh +476 -0
  135. package/scripts/lib/test-helpers.sh +18 -7
  136. package/scripts/lib/test-holdout.sh +429 -0
  137. package/scripts/lib/test-optimizer.sh +511 -0
  138. package/scripts/shipwright-file-suggest.sh +45 -0
  139. package/scripts/skills/adversarial-quality.md +61 -0
  140. package/scripts/skills/api-design.md +44 -0
  141. package/scripts/skills/architecture-design.md +50 -0
  142. package/scripts/skills/brainstorming.md +43 -0
  143. package/scripts/skills/data-pipeline.md +44 -0
  144. package/scripts/skills/deploy-safety.md +64 -0
  145. package/scripts/skills/documentation.md +38 -0
  146. package/scripts/skills/frontend-design.md +45 -0
  147. package/scripts/skills/generated/.gitkeep +0 -0
  148. package/scripts/skills/generated/_refinements/.gitkeep +0 -0
  149. package/scripts/skills/generated/_refinements/adversarial-quality.patch.md +3 -0
  150. package/scripts/skills/generated/_refinements/architecture-design.patch.md +3 -0
  151. package/scripts/skills/generated/_refinements/brainstorming.patch.md +3 -0
  152. package/scripts/skills/generated/cli-version-management.md +29 -0
  153. package/scripts/skills/generated/collection-system-validation.md +99 -0
  154. package/scripts/skills/generated/large-scale-c-refactoring-coordination.md +97 -0
  155. package/scripts/skills/generated/pattern-matching-similarity-scoring.md +195 -0
  156. package/scripts/skills/generated/test-parallelization-detection.md +65 -0
  157. package/scripts/skills/observability.md +79 -0
  158. package/scripts/skills/performance.md +48 -0
  159. package/scripts/skills/pr-quality.md +49 -0
  160. package/scripts/skills/product-thinking.md +43 -0
  161. package/scripts/skills/security-audit.md +49 -0
  162. package/scripts/skills/systematic-debugging.md +40 -0
  163. package/scripts/skills/testing-strategy.md +47 -0
  164. package/scripts/skills/two-stage-review.md +52 -0
  165. package/scripts/skills/validation-thoroughness.md +55 -0
  166. package/scripts/sw +9 -3
  167. package/scripts/sw-activity.sh +9 -8
  168. package/scripts/sw-adaptive.sh +8 -7
  169. package/scripts/sw-adversarial.sh +2 -1
  170. package/scripts/sw-architecture-enforcer.sh +3 -1
  171. package/scripts/sw-auth.sh +12 -2
  172. package/scripts/sw-autonomous.sh +5 -1
  173. package/scripts/sw-changelog.sh +4 -1
  174. package/scripts/sw-checkpoint.sh +2 -1
  175. package/scripts/sw-ci.sh +15 -6
  176. package/scripts/sw-cleanup.sh +4 -26
  177. package/scripts/sw-code-review.sh +45 -20
  178. package/scripts/sw-connect.sh +2 -1
  179. package/scripts/sw-context.sh +2 -1
  180. package/scripts/sw-cost.sh +107 -5
  181. package/scripts/sw-daemon.sh +71 -11
  182. package/scripts/sw-dashboard.sh +3 -1
  183. package/scripts/sw-db.sh +71 -20
  184. package/scripts/sw-decide.sh +8 -2
  185. package/scripts/sw-decompose.sh +360 -17
  186. package/scripts/sw-deps.sh +4 -1
  187. package/scripts/sw-developer-simulation.sh +4 -1
  188. package/scripts/sw-discovery.sh +378 -5
  189. package/scripts/sw-doc-fleet.sh +4 -1
  190. package/scripts/sw-docs-agent.sh +3 -1
  191. package/scripts/sw-docs.sh +2 -1
  192. package/scripts/sw-doctor.sh +453 -2
  193. package/scripts/sw-dora.sh +4 -1
  194. package/scripts/sw-durable.sh +12 -7
  195. package/scripts/sw-e2e-orchestrator.sh +17 -16
  196. package/scripts/sw-eventbus.sh +13 -4
  197. package/scripts/sw-evidence.sh +364 -12
  198. package/scripts/sw-feedback.sh +550 -9
  199. package/scripts/sw-fix.sh +20 -1
  200. package/scripts/sw-fleet-discover.sh +6 -2
  201. package/scripts/sw-fleet-viz.sh +9 -4
  202. package/scripts/sw-fleet.sh +5 -1
  203. package/scripts/sw-github-app.sh +18 -4
  204. package/scripts/sw-github-checks.sh +3 -2
  205. package/scripts/sw-github-deploy.sh +3 -2
  206. package/scripts/sw-github-graphql.sh +18 -7
  207. package/scripts/sw-guild.sh +5 -1
  208. package/scripts/sw-heartbeat.sh +5 -30
  209. package/scripts/sw-hello.sh +67 -0
  210. package/scripts/sw-hygiene.sh +10 -3
  211. package/scripts/sw-incident.sh +273 -5
  212. package/scripts/sw-init.sh +18 -2
  213. package/scripts/sw-instrument.sh +10 -2
  214. package/scripts/sw-intelligence.sh +44 -7
  215. package/scripts/sw-jira.sh +5 -1
  216. package/scripts/sw-launchd.sh +2 -1
  217. package/scripts/sw-linear.sh +4 -1
  218. package/scripts/sw-logs.sh +4 -1
  219. package/scripts/sw-loop.sh +436 -1076
  220. package/scripts/sw-memory.sh +357 -3
  221. package/scripts/sw-mission-control.sh +6 -1
  222. package/scripts/sw-model-router.sh +483 -27
  223. package/scripts/sw-otel.sh +15 -4
  224. package/scripts/sw-oversight.sh +14 -5
  225. package/scripts/sw-patrol-meta.sh +334 -0
  226. package/scripts/sw-pipeline-composer.sh +7 -1
  227. package/scripts/sw-pipeline-vitals.sh +12 -6
  228. package/scripts/sw-pipeline.sh +54 -2653
  229. package/scripts/sw-pm.sh +16 -8
  230. package/scripts/sw-pr-lifecycle.sh +2 -1
  231. package/scripts/sw-predictive.sh +17 -5
  232. package/scripts/sw-prep.sh +185 -2
  233. package/scripts/sw-ps.sh +5 -25
  234. package/scripts/sw-public-dashboard.sh +17 -4
  235. package/scripts/sw-quality.sh +14 -6
  236. package/scripts/sw-reaper.sh +8 -25
  237. package/scripts/sw-recruit.sh +156 -2303
  238. package/scripts/sw-regression.sh +19 -12
  239. package/scripts/sw-release-manager.sh +3 -1
  240. package/scripts/sw-release.sh +4 -1
  241. package/scripts/sw-remote.sh +3 -1
  242. package/scripts/sw-replay.sh +7 -1
  243. package/scripts/sw-retro.sh +158 -1
  244. package/scripts/sw-review-rerun.sh +3 -1
  245. package/scripts/sw-scale.sh +14 -5
  246. package/scripts/sw-security-audit.sh +6 -1
  247. package/scripts/sw-self-optimize.sh +173 -6
  248. package/scripts/sw-session.sh +9 -3
  249. package/scripts/sw-setup.sh +3 -1
  250. package/scripts/sw-stall-detector.sh +406 -0
  251. package/scripts/sw-standup.sh +15 -7
  252. package/scripts/sw-status.sh +3 -1
  253. package/scripts/sw-strategic.sh +14 -6
  254. package/scripts/sw-stream.sh +13 -4
  255. package/scripts/sw-swarm.sh +20 -7
  256. package/scripts/sw-team-stages.sh +13 -6
  257. package/scripts/sw-templates.sh +7 -31
  258. package/scripts/sw-testgen.sh +17 -6
  259. package/scripts/sw-tmux-pipeline.sh +4 -1
  260. package/scripts/sw-tmux-role-color.sh +2 -0
  261. package/scripts/sw-tmux-status.sh +1 -1
  262. package/scripts/sw-tmux.sh +37 -1
  263. package/scripts/sw-trace.sh +3 -1
  264. package/scripts/sw-tracker-github.sh +3 -0
  265. package/scripts/sw-tracker-jira.sh +3 -0
  266. package/scripts/sw-tracker-linear.sh +3 -0
  267. package/scripts/sw-tracker.sh +3 -1
  268. package/scripts/sw-triage.sh +3 -2
  269. package/scripts/sw-upgrade.sh +3 -1
  270. package/scripts/sw-ux.sh +5 -2
  271. package/scripts/sw-webhook.sh +5 -2
  272. package/scripts/sw-widgets.sh +9 -4
  273. package/scripts/sw-worktree.sh +15 -3
  274. package/scripts/test-skill-injection.sh +1233 -0
  275. package/templates/pipelines/autonomous.json +27 -3
  276. package/templates/pipelines/cost-aware.json +34 -8
  277. package/templates/pipelines/deployed.json +12 -0
  278. package/templates/pipelines/enterprise.json +12 -0
  279. package/templates/pipelines/fast.json +6 -0
  280. package/templates/pipelines/full.json +27 -3
  281. package/templates/pipelines/hotfix.json +6 -0
  282. package/templates/pipelines/standard.json +12 -0
  283. 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.1.0-00d4ff?style=flat-square" alt="v3.1.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.1.0](#whats-new-in-v310)
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)
@@ -77,7 +77,8 @@ Shipwright extends the Code Factory pattern with capabilities most implementatio
77
77
  - **12-stage pipeline** with self-healing builds, adversarial review, and compound quality gates
78
78
  - **Predictive risk scoring** using GitHub signals (security alerts, contributor expertise, file churn)
79
79
  - **Persistent memory** — failure patterns, fix effectiveness, and prediction accuracy compound over time
80
- - **Auto-learning** — self-optimize runs automatically after every pipeline completion
80
+ - **Auto-learning** — self-optimize runs automatically after every pipeline completion, including context efficiency tuning
81
+ - **Decision engine** — tiered autonomous decisions with outcome learning and deduplication
81
82
  - **Unified model routing** — single source of truth for model selection across all components
82
83
  - **Evidence-gated merges** — SHA discipline ensures all evidence validated against current PR head
83
84
  - **Semantic quality audits** — Claude-powered audits with grep fallback when Claude unavailable
@@ -108,7 +109,7 @@ shipwright incident gap sla
108
109
 
109
110
  ---
110
111
 
111
- ## What's New in v3.1.0
112
+ ## What's New in v3.3.0
112
113
 
113
114
  **Code Factory pattern** — deterministic, risk-aware agent delivery with machine-verifiable evidence:
114
115
 
@@ -282,7 +283,7 @@ Each stage is configurable with quality gates that auto-proceed or pause for app
282
283
 
283
284
  ### Intelligence Layer
284
285
 
285
- 7 modules that make the pipeline smarter over time. **Auto mode**: intelligence is enabled when Claude CLI is available; set `intelligence.enabled=false` to disable. All modules degrade gracefully.
286
+ 7 modules that make the pipeline smarter over time. **Enabled by default**: intelligence is on when Claude CLI is available, with optimization and prediction active out of the box. Set `intelligence.enabled=false` to disable. All modules degrade gracefully.
286
287
 
287
288
  | Module | What It Does |
288
289
  | ---------------------------- | --------------------------------------------------------------------------------------------------------------------- |
@@ -290,7 +291,7 @@ Each stage is configurable with quality gates that auto-proceed or pause for app
290
291
  | **Pipeline Composer** | Generates custom pipeline configs from codebase analysis (file churn, test coverage, dependencies) |
291
292
  | **Predictive Risk** | Scores issues for risk using GitHub signals (security alerts, similar past issues, contributor expertise) |
292
293
  | **Adversarial Review** | Red-team code review — finds security flaws, edge cases, failure modes. Cross-checks against CodeQL/Dependabot alerts |
293
- | **Self-Optimization** | Reads DORA metrics and auto-tunes daemon config. Proportional template weighting, adaptive memory timescales |
294
+ | **Self-Optimization** | Reads DORA metrics and auto-tunes daemon config. Includes context efficiency closed loop for token budget tuning |
294
295
  | **Developer Simulation** | 3-persona review (security, performance, maintainability) before PR creation |
295
296
  | **Architecture Enforcement** | Living architectural model with violation detection and dependency direction rules |
296
297
 
@@ -309,6 +310,19 @@ Native GitHub API integration enriches every intelligence module:
309
310
  | **Contributors** | CODEOWNERS-based reviewer routing, top-contributor fallback, auto-approve as last resort |
310
311
  | **Branch Protection** | Checks required reviews and status checks before attempting auto-merge |
311
312
 
313
+ ### Decision Engine
314
+
315
+ The autonomous decision engine (`config/policy.json` → `decision` section) handles routine operational decisions with outcome learning. Decisions are tiered by risk, with low-risk actions auto-approved and higher tiers escalated. The engine learns from outcomes to improve future decisions.
316
+
317
+ ### Context Engineering
318
+
319
+ Intelligent context window management for pipeline agents:
320
+
321
+ - **Budget-aware trimming** — Configurable character budgets for prompt composition (`context_budget_chars`)
322
+ - **Section-level trimming** — Independent limits for memory, git history, hotspot files, and test output
323
+ - **Context efficiency metrics** — Tracks budget utilization and trim ratios per iteration
324
+ - **Self-tuning** — The self-optimization loop analyzes context efficiency events and recommends budget adjustments
325
+
312
326
  ### Autonomous Daemon
313
327
 
314
328
  ```bash
@@ -354,7 +368,7 @@ Per-pipeline cost tracking with model pricing, budget enforcement, and ROI analy
354
368
  shipwright dashboard start
355
369
  ```
356
370
 
357
- Web dashboard with live pipeline progress, GitHub context (security alerts, contributors, deployments), DORA metrics, and cost tracking. WebSocket-powered, updates in real-time.
371
+ Web dashboard with live pipeline progress, GitHub context (security alerts, contributors, deployments), DORA metrics, cost tracking, and context efficiency metrics. WebSocket-powered, updates in real-time.
358
372
 
359
373
  ### Webhook Receiver
360
374
 
@@ -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
+ }
@@ -25,6 +25,7 @@
25
25
  "build_test_retries": 3,
26
26
  "claude_timeout": 1800,
27
27
  "heartbeat_interval": 30,
28
+ "composed_cache_ttl": 3600,
28
29
  "branch_pattern": "shipwright/issue-{issue}",
29
30
  "stage_order": [
30
31
  "intake",
@@ -47,7 +48,12 @@
47
48
  "max_restarts": 0,
48
49
  "fast_test_interval": 5,
49
50
  "convergence_threshold": 3,
50
- "multi_agent_sleep": 5
51
+ "multi_agent_sleep": 5,
52
+ "context_budget_chars": 180000,
53
+ "context_trim_memory_chars": 20000,
54
+ "context_trim_git_entries": 10,
55
+ "context_trim_hotspot_files": 5,
56
+ "context_trim_test_lines": 50
51
57
  },
52
58
  "dashboard": {
53
59
  "port": 8767,
@@ -77,12 +83,29 @@
77
83
  "ab_test_ratio": 0.2,
78
84
  "claude_timeout": 60
79
85
  },
86
+ "predictive": {
87
+ "default_risk_score": 50,
88
+ "keyword_risk_score": 70
89
+ },
90
+ "api_optimization": {
91
+ "programmatic_tool_calling": true,
92
+ "tool_search_enabled": true,
93
+ "tool_search_type": "bm25",
94
+ "defer_unused_tools": true,
95
+ "web_search_version": "web_search_20260209",
96
+ "web_fetch_version": "web_fetch_20260209",
97
+ "dynamic_filtering": true,
98
+ "code_execution_sandbox": true,
99
+ "beta_header": "code-execution-web-tools-2026-02-09"
100
+ },
80
101
  "quality": {
81
102
  "gate_score_threshold": 70,
82
103
  "secret_threshold": 3,
83
104
  "min_file_count": 10,
84
105
  "score_weight_per_file": 25,
85
- "pass_rate_threshold": 5.0
106
+ "pass_rate_threshold": 5.0,
107
+ "bundle_growth_legacy_pct": 20,
108
+ "perf_regression_legacy_pct": 30
86
109
  },
87
110
  "cleanup": {
88
111
  "artifact_age_days": 7,
@@ -224,7 +224,7 @@
224
224
  "promote_threshold_success_rate": 85
225
225
  },
226
226
  "decision": {
227
- "enabled": false,
227
+ "enabled": true,
228
228
  "cycle_interval_seconds": 1800,
229
229
  "tiers_file": "config/decision-tiers.json",
230
230
  "outcome_learning_enabled": true,
@@ -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 };