shipwright-cli 2.4.0 → 3.1.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 (169) hide show
  1. package/README.md +16 -11
  2. package/completions/_shipwright +248 -94
  3. package/completions/shipwright.bash +68 -19
  4. package/completions/shipwright.fish +310 -42
  5. package/config/decision-tiers.json +55 -0
  6. package/config/defaults.json +111 -0
  7. package/config/event-schema.json +218 -0
  8. package/config/policy.json +21 -18
  9. package/dashboard/coverage/coverage-summary.json +14 -0
  10. package/dashboard/public/index.html +1 -1
  11. package/dashboard/server.ts +306 -17
  12. package/dashboard/src/components/charts/bar.test.ts +79 -0
  13. package/dashboard/src/components/charts/donut.test.ts +68 -0
  14. package/dashboard/src/components/charts/pipeline-rail.test.ts +117 -0
  15. package/dashboard/src/components/charts/sparkline.test.ts +125 -0
  16. package/dashboard/src/core/api.test.ts +309 -0
  17. package/dashboard/src/core/helpers.test.ts +301 -0
  18. package/dashboard/src/core/router.test.ts +307 -0
  19. package/dashboard/src/core/router.ts +7 -0
  20. package/dashboard/src/core/sse.test.ts +144 -0
  21. package/dashboard/src/views/metrics.test.ts +186 -0
  22. package/dashboard/src/views/overview.test.ts +173 -0
  23. package/dashboard/src/views/pipelines.test.ts +183 -0
  24. package/dashboard/src/views/team.test.ts +253 -0
  25. package/dashboard/vitest.config.ts +14 -5
  26. package/docs/TIPS.md +1 -1
  27. package/docs/patterns/README.md +1 -1
  28. package/package.json +7 -9
  29. package/scripts/adapters/docker-deploy.sh +1 -1
  30. package/scripts/adapters/tmux-adapter.sh +11 -1
  31. package/scripts/adapters/wezterm-adapter.sh +1 -1
  32. package/scripts/check-version-consistency.sh +1 -1
  33. package/scripts/lib/architecture.sh +127 -0
  34. package/scripts/lib/bootstrap.sh +75 -0
  35. package/scripts/lib/compat.sh +89 -6
  36. package/scripts/lib/config.sh +91 -0
  37. package/scripts/lib/daemon-adaptive.sh +3 -3
  38. package/scripts/lib/daemon-dispatch.sh +63 -17
  39. package/scripts/lib/daemon-failure.sh +0 -0
  40. package/scripts/lib/daemon-health.sh +1 -1
  41. package/scripts/lib/daemon-patrol.sh +64 -17
  42. package/scripts/lib/daemon-poll.sh +54 -25
  43. package/scripts/lib/daemon-state.sh +125 -23
  44. package/scripts/lib/daemon-triage.sh +31 -9
  45. package/scripts/lib/decide-autonomy.sh +295 -0
  46. package/scripts/lib/decide-scoring.sh +228 -0
  47. package/scripts/lib/decide-signals.sh +462 -0
  48. package/scripts/lib/fleet-failover.sh +63 -0
  49. package/scripts/lib/helpers.sh +29 -6
  50. package/scripts/lib/pipeline-detection.sh +2 -2
  51. package/scripts/lib/pipeline-github.sh +9 -9
  52. package/scripts/lib/pipeline-intelligence.sh +105 -38
  53. package/scripts/lib/pipeline-quality-checks.sh +17 -16
  54. package/scripts/lib/pipeline-quality.sh +1 -1
  55. package/scripts/lib/pipeline-stages.sh +440 -59
  56. package/scripts/lib/pipeline-state.sh +54 -4
  57. package/scripts/lib/policy.sh +0 -0
  58. package/scripts/lib/test-helpers.sh +247 -0
  59. package/scripts/postinstall.mjs +78 -12
  60. package/scripts/signals/example-collector.sh +36 -0
  61. package/scripts/sw +17 -7
  62. package/scripts/sw-activity.sh +1 -11
  63. package/scripts/sw-adaptive.sh +109 -85
  64. package/scripts/sw-adversarial.sh +4 -14
  65. package/scripts/sw-architecture-enforcer.sh +1 -11
  66. package/scripts/sw-auth.sh +8 -17
  67. package/scripts/sw-autonomous.sh +111 -49
  68. package/scripts/sw-changelog.sh +1 -11
  69. package/scripts/sw-checkpoint.sh +144 -20
  70. package/scripts/sw-ci.sh +2 -12
  71. package/scripts/sw-cleanup.sh +13 -17
  72. package/scripts/sw-code-review.sh +16 -36
  73. package/scripts/sw-connect.sh +5 -12
  74. package/scripts/sw-context.sh +9 -26
  75. package/scripts/sw-cost.sh +17 -18
  76. package/scripts/sw-daemon.sh +76 -71
  77. package/scripts/sw-dashboard.sh +57 -17
  78. package/scripts/sw-db.sh +524 -26
  79. package/scripts/sw-decide.sh +685 -0
  80. package/scripts/sw-decompose.sh +1 -11
  81. package/scripts/sw-deps.sh +15 -25
  82. package/scripts/sw-developer-simulation.sh +1 -11
  83. package/scripts/sw-discovery.sh +138 -30
  84. package/scripts/sw-doc-fleet.sh +7 -17
  85. package/scripts/sw-docs-agent.sh +6 -16
  86. package/scripts/sw-docs.sh +4 -12
  87. package/scripts/sw-doctor.sh +134 -43
  88. package/scripts/sw-dora.sh +11 -19
  89. package/scripts/sw-durable.sh +35 -52
  90. package/scripts/sw-e2e-orchestrator.sh +11 -27
  91. package/scripts/sw-eventbus.sh +115 -115
  92. package/scripts/sw-evidence.sh +114 -30
  93. package/scripts/sw-feedback.sh +3 -13
  94. package/scripts/sw-fix.sh +2 -20
  95. package/scripts/sw-fleet-discover.sh +1 -11
  96. package/scripts/sw-fleet-viz.sh +10 -18
  97. package/scripts/sw-fleet.sh +13 -17
  98. package/scripts/sw-github-app.sh +6 -16
  99. package/scripts/sw-github-checks.sh +1 -11
  100. package/scripts/sw-github-deploy.sh +1 -11
  101. package/scripts/sw-github-graphql.sh +2 -12
  102. package/scripts/sw-guild.sh +1 -11
  103. package/scripts/sw-heartbeat.sh +49 -12
  104. package/scripts/sw-hygiene.sh +45 -43
  105. package/scripts/sw-incident.sh +48 -74
  106. package/scripts/sw-init.sh +35 -37
  107. package/scripts/sw-instrument.sh +1 -11
  108. package/scripts/sw-intelligence.sh +368 -53
  109. package/scripts/sw-jira.sh +5 -14
  110. package/scripts/sw-launchd.sh +2 -12
  111. package/scripts/sw-linear.sh +8 -17
  112. package/scripts/sw-logs.sh +4 -12
  113. package/scripts/sw-loop.sh +905 -104
  114. package/scripts/sw-memory.sh +263 -20
  115. package/scripts/sw-mission-control.sh +2 -12
  116. package/scripts/sw-model-router.sh +73 -34
  117. package/scripts/sw-otel.sh +15 -23
  118. package/scripts/sw-oversight.sh +1 -11
  119. package/scripts/sw-patrol-meta.sh +5 -11
  120. package/scripts/sw-pipeline-composer.sh +7 -17
  121. package/scripts/sw-pipeline-vitals.sh +1 -11
  122. package/scripts/sw-pipeline.sh +550 -122
  123. package/scripts/sw-pm.sh +2 -12
  124. package/scripts/sw-pr-lifecycle.sh +33 -28
  125. package/scripts/sw-predictive.sh +16 -22
  126. package/scripts/sw-prep.sh +6 -16
  127. package/scripts/sw-ps.sh +1 -11
  128. package/scripts/sw-public-dashboard.sh +2 -12
  129. package/scripts/sw-quality.sh +85 -14
  130. package/scripts/sw-reaper.sh +1 -11
  131. package/scripts/sw-recruit.sh +15 -25
  132. package/scripts/sw-regression.sh +11 -21
  133. package/scripts/sw-release-manager.sh +19 -28
  134. package/scripts/sw-release.sh +8 -16
  135. package/scripts/sw-remote.sh +1 -11
  136. package/scripts/sw-replay.sh +48 -44
  137. package/scripts/sw-retro.sh +70 -92
  138. package/scripts/sw-review-rerun.sh +1 -1
  139. package/scripts/sw-scale.sh +174 -41
  140. package/scripts/sw-security-audit.sh +12 -22
  141. package/scripts/sw-self-optimize.sh +239 -23
  142. package/scripts/sw-session.sh +5 -15
  143. package/scripts/sw-setup.sh +8 -18
  144. package/scripts/sw-standup.sh +5 -15
  145. package/scripts/sw-status.sh +32 -23
  146. package/scripts/sw-strategic.sh +129 -13
  147. package/scripts/sw-stream.sh +1 -11
  148. package/scripts/sw-swarm.sh +76 -36
  149. package/scripts/sw-team-stages.sh +10 -20
  150. package/scripts/sw-templates.sh +4 -14
  151. package/scripts/sw-testgen.sh +3 -13
  152. package/scripts/sw-tmux-pipeline.sh +1 -19
  153. package/scripts/sw-tmux-role-color.sh +0 -10
  154. package/scripts/sw-tmux-status.sh +3 -11
  155. package/scripts/sw-tmux.sh +2 -20
  156. package/scripts/sw-trace.sh +1 -19
  157. package/scripts/sw-tracker-github.sh +0 -10
  158. package/scripts/sw-tracker-jira.sh +1 -11
  159. package/scripts/sw-tracker-linear.sh +1 -11
  160. package/scripts/sw-tracker.sh +7 -24
  161. package/scripts/sw-triage.sh +29 -39
  162. package/scripts/sw-upgrade.sh +5 -23
  163. package/scripts/sw-ux.sh +1 -19
  164. package/scripts/sw-webhook.sh +18 -32
  165. package/scripts/sw-widgets.sh +3 -21
  166. package/scripts/sw-worktree.sh +11 -27
  167. package/scripts/update-homebrew-sha.sh +73 -0
  168. package/templates/pipelines/tdd.json +72 -0
  169. package/scripts/sw-pipeline.sh.mock +0 -7
@@ -0,0 +1,253 @@
1
+ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest";
2
+ import { store } from "../core/state";
3
+ import type { FleetState, TeamData } from "../types/api";
4
+
5
+ vi.mock("../core/api", () => ({
6
+ fetchTeam: vi
7
+ .fn()
8
+ .mockResolvedValue({
9
+ developers: [],
10
+ total_online: 0,
11
+ total_active_pipelines: 0,
12
+ total_queued: 0,
13
+ }),
14
+ fetchTeamActivity: vi.fn().mockResolvedValue([]),
15
+ createTeamInvite: vi
16
+ .fn()
17
+ .mockResolvedValue({ url: "https://invite.example.com/abc" }),
18
+ fetchLinearStatus: vi.fn().mockResolvedValue({ connected: false }),
19
+ fetchDbHealth: vi.fn().mockResolvedValue({ ok: true }),
20
+ fetchDbEvents: vi.fn().mockResolvedValue([]),
21
+ fetchDbJobs: vi.fn().mockResolvedValue([]),
22
+ fetchDbHeartbeats: vi.fn().mockResolvedValue([]),
23
+ fetchDbCostsToday: vi.fn().mockResolvedValue([]),
24
+ claimIssue: vi.fn().mockResolvedValue({ approved: true }),
25
+ releaseIssue: vi.fn().mockResolvedValue({}),
26
+ }));
27
+
28
+ function createTeamDOM(): void {
29
+ const grid = document.createElement("div");
30
+ grid.id = "team-grid";
31
+ document.body.appendChild(grid);
32
+
33
+ const statOnline = document.createElement("span");
34
+ statOnline.id = "team-stat-online";
35
+ document.body.appendChild(statOnline);
36
+
37
+ const statPipelines = document.createElement("span");
38
+ statPipelines.id = "team-stat-pipelines";
39
+ document.body.appendChild(statPipelines);
40
+
41
+ const statQueued = document.createElement("span");
42
+ statQueued.id = "team-stat-queued";
43
+ document.body.appendChild(statQueued);
44
+
45
+ const activity = document.createElement("div");
46
+ activity.id = "team-activity";
47
+ document.body.appendChild(activity);
48
+
49
+ const inviteResult = document.createElement("div");
50
+ inviteResult.id = "team-invite-result";
51
+ inviteResult.style.display = "none";
52
+ document.body.appendChild(inviteResult);
53
+
54
+ const btnInvite = document.createElement("button");
55
+ btnInvite.id = "btn-create-invite";
56
+ document.body.appendChild(btnInvite);
57
+
58
+ const integrations = document.createElement("div");
59
+ integrations.id = "integrations-status";
60
+ document.body.appendChild(integrations);
61
+
62
+ const adminOutput = document.createElement("div");
63
+ adminOutput.id = "admin-debug-output";
64
+ document.body.appendChild(adminOutput);
65
+
66
+ const claimResult = document.createElement("div");
67
+ claimResult.id = "claim-result";
68
+ document.body.appendChild(claimResult);
69
+
70
+ const claimIssue = document.createElement("input");
71
+ claimIssue.id = "claim-issue";
72
+ document.body.appendChild(claimIssue);
73
+
74
+ const claimMachine = document.createElement("input");
75
+ claimMachine.id = "claim-machine";
76
+ document.body.appendChild(claimMachine);
77
+
78
+ const btnClaim = document.createElement("button");
79
+ btnClaim.id = "btn-claim";
80
+ document.body.appendChild(btnClaim);
81
+
82
+ const btnRelease = document.createElement("button");
83
+ btnRelease.id = "btn-release";
84
+ document.body.appendChild(btnRelease);
85
+
86
+ [
87
+ "btn-db-health",
88
+ "btn-db-events",
89
+ "btn-db-jobs",
90
+ "btn-db-heartbeats",
91
+ "btn-db-costs",
92
+ ].forEach((id) => {
93
+ const btn = document.createElement("button");
94
+ btn.id = id;
95
+ document.body.appendChild(btn);
96
+ });
97
+ }
98
+
99
+ function cleanupTeamDOM(): void {
100
+ const ids = [
101
+ "team-grid",
102
+ "team-stat-online",
103
+ "team-stat-pipelines",
104
+ "team-stat-queued",
105
+ "team-activity",
106
+ "team-invite-result",
107
+ "btn-create-invite",
108
+ "integrations-status",
109
+ "admin-debug-output",
110
+ "claim-result",
111
+ "claim-issue",
112
+ "claim-machine",
113
+ "btn-claim",
114
+ "btn-release",
115
+ "btn-db-health",
116
+ "btn-db-events",
117
+ "btn-db-jobs",
118
+ "btn-db-heartbeats",
119
+ "btn-db-costs",
120
+ ];
121
+ ids.forEach((id) => document.getElementById(id)?.remove());
122
+ }
123
+
124
+ function emptyFleetState(): FleetState {
125
+ return {
126
+ timestamp: new Date().toISOString(),
127
+ daemon: {
128
+ running: false,
129
+ pid: null,
130
+ uptime_s: 0,
131
+ maxParallel: 0,
132
+ pollInterval: 5,
133
+ },
134
+ pipelines: [],
135
+ queue: [],
136
+ events: [],
137
+ scale: {},
138
+ metrics: {},
139
+ agents: [],
140
+ machines: [],
141
+ cost: { today_spent: 0, daily_budget: 0, pct_used: 0 },
142
+ dora: {} as any,
143
+ };
144
+ }
145
+
146
+ describe("TeamView", () => {
147
+ beforeEach(() => {
148
+ store.set("teamCache", null);
149
+ createTeamDOM();
150
+ });
151
+
152
+ afterEach(() => {
153
+ cleanupTeamDOM();
154
+ vi.clearAllMocks();
155
+ });
156
+
157
+ it("renders team members when data provided", async () => {
158
+ const { teamView } = await import("./team");
159
+ const teamData: TeamData = {
160
+ total_online: 2,
161
+ total_active_pipelines: 1,
162
+ total_queued: 0,
163
+ developers: [
164
+ {
165
+ developer_id: "alice",
166
+ machine_name: "macbook-pro",
167
+ daemon_running: true,
168
+ active_jobs: [{ issue: 42, title: "Fix bug", stage: "code" }],
169
+ queued: [],
170
+ },
171
+ ],
172
+ };
173
+ const data = emptyFleetState();
174
+ data.team = teamData;
175
+ teamView.render(data);
176
+ const grid = document.getElementById("team-grid");
177
+ expect(grid).toBeTruthy();
178
+ expect(grid!.innerHTML).toContain("alice");
179
+ expect(grid!.innerHTML).toContain("macbook-pro");
180
+ expect(grid!.innerHTML).toContain("#42");
181
+ expect(grid!.innerHTML).toContain("presence-dot");
182
+ });
183
+
184
+ it("handles empty team", async () => {
185
+ const { teamView } = await import("./team");
186
+ const data = emptyFleetState();
187
+ data.team = {
188
+ developers: [],
189
+ total_online: 0,
190
+ total_active_pipelines: 0,
191
+ total_queued: 0,
192
+ };
193
+ teamView.render(data);
194
+ const grid = document.getElementById("team-grid");
195
+ expect(grid).toBeTruthy();
196
+ expect(grid!.innerHTML).toContain("No developers connected");
197
+ });
198
+
199
+ it("shows activity indicators when team has active jobs", async () => {
200
+ const { teamView } = await import("./team");
201
+ const teamData: TeamData = {
202
+ developers: [
203
+ {
204
+ developer_id: "bob",
205
+ machine_name: "dev-machine",
206
+ daemon_running: true,
207
+ active_jobs: [
208
+ { issue: 10, stage: "plan" },
209
+ { issue: 20, stage: "code" },
210
+ ],
211
+ queued: [30],
212
+ },
213
+ ],
214
+ };
215
+ const data = emptyFleetState();
216
+ data.team = teamData;
217
+ teamView.render(data);
218
+ const grid = document.getElementById("team-grid");
219
+ expect(grid!.innerHTML).toContain("team-card-pipeline-item");
220
+ expect(grid!.innerHTML).toContain("#10");
221
+ expect(grid!.innerHTML).toContain("#20");
222
+ });
223
+
224
+ it("uses teamCache when data.team is absent", async () => {
225
+ const { teamView } = await import("./team");
226
+ const cachedTeam: TeamData = {
227
+ developers: [
228
+ {
229
+ developer_id: "cached",
230
+ machine_name: "cache-machine",
231
+ daemon_running: false,
232
+ active_jobs: [],
233
+ queued: [],
234
+ },
235
+ ],
236
+ total_online: 1,
237
+ total_active_pipelines: 0,
238
+ total_queued: 0,
239
+ };
240
+ store.set("teamCache", cachedTeam);
241
+ const data = emptyFleetState();
242
+ data.team = undefined;
243
+ teamView.render(data);
244
+ const grid = document.getElementById("team-grid");
245
+ expect(grid!.innerHTML).toContain("cached");
246
+ });
247
+
248
+ it("init and destroy do not throw", async () => {
249
+ const { teamView } = await import("./team");
250
+ expect(() => teamView.init()).not.toThrow();
251
+ expect(() => teamView.destroy()).not.toThrow();
252
+ });
253
+ });
@@ -10,12 +10,21 @@ export default defineConfig({
10
10
  provider: "v8",
11
11
  reporter: ["text", "json-summary"],
12
12
  include: ["src/**/*.ts"],
13
- exclude: ["src/**/*.test.ts", "src/types/**"],
13
+ exclude: [
14
+ "src/**/*.test.ts",
15
+ "src/types/**",
16
+ "src/views/**",
17
+ "src/canvas/**",
18
+ "src/components/header.ts",
19
+ "src/components/modal.ts",
20
+ "src/components/terminal.ts",
21
+ "src/main.ts",
22
+ ],
14
23
  thresholds: {
15
- statements: 60,
16
- branches: 50,
17
- functions: 60,
18
- lines: 60,
24
+ statements: 70,
25
+ branches: 60,
26
+ functions: 70,
27
+ lines: 70,
19
28
  },
20
29
  },
21
30
  },
package/docs/TIPS.md CHANGED
@@ -131,7 +131,7 @@ This compacts the conversation when it hits 70% of the context window (default i
131
131
 
132
132
  ### Watch all agents at once
133
133
 
134
- Use `shipwright status` (alias: `sw`, `cct`) to see a dashboard of running team sessions:
134
+ Use `shipwright status` (alias: `sw`) to see a dashboard of running team sessions:
135
135
 
136
136
  ```bash
137
137
  shipwright status
@@ -85,7 +85,7 @@ Each agent writes its results to a markdown file in this directory. The team lea
85
85
 
86
86
  ## Quick Start
87
87
 
88
- Pick a pattern, then use `shipwright` (alias: `sw`, `cct`) to set up the team:
88
+ Pick a pattern, then use `shipwright` (alias: `sw`) to set up the team:
89
89
 
90
90
  ```bash
91
91
  # Start a tmux session
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "shipwright-cli",
3
- "version": "2.4.0",
3
+ "version": "3.1.0",
4
4
  "description": "Orchestrate autonomous Claude Code agent teams in tmux",
5
5
  "bin": {
6
- "shipwright": "./scripts/sw",
7
- "sw": "./scripts/sw",
8
- "cct": "./scripts/sw"
6
+ "shipwright": "scripts/sw",
7
+ "sw": "scripts/sw",
8
+ "cct": "scripts/sw"
9
9
  },
10
10
  "files": [
11
11
  "config/",
@@ -36,9 +36,9 @@
36
36
  "dashboard:test": "vitest run --config dashboard/vitest.config.ts",
37
37
  "dashboard:test:watch": "vitest --config dashboard/vitest.config.ts",
38
38
  "dashboard:test:coverage": "vitest run --config dashboard/vitest.config.ts --coverage",
39
- "test": "bash scripts/sw-agi-roadmap-test.sh && bash scripts/sw-activity-test.sh && bash scripts/sw-adaptive-test.sh && bash scripts/sw-adversarial-test.sh && bash scripts/sw-architecture-enforcer-test.sh && bash scripts/sw-auth-test.sh && bash scripts/sw-autonomous-test.sh && bash scripts/sw-changelog-test.sh && bash scripts/sw-checkpoint-test.sh && bash scripts/sw-ci-test.sh && bash scripts/sw-cleanup-test.sh && bash scripts/sw-code-review-test.sh && bash scripts/sw-connect-test.sh && bash scripts/sw-context-test.sh && bash scripts/sw-cost-test.sh && bash scripts/sw-daemon-test.sh && bash scripts/sw-dashboard-test.sh && bash scripts/sw-db-test.sh && bash scripts/sw-decompose-test.sh && bash scripts/sw-deps-test.sh && bash scripts/sw-developer-simulation-test.sh && bash scripts/sw-discovery-test.sh && bash scripts/sw-doc-fleet-test.sh && bash scripts/sw-docs-agent-test.sh && bash scripts/sw-docs-test.sh && bash scripts/sw-doctor-test.sh && bash scripts/sw-dora-test.sh && bash scripts/sw-durable-test.sh && bash scripts/sw-e2e-orchestrator-test.sh && bash scripts/sw-eventbus-test.sh && bash scripts/sw-feedback-test.sh && bash scripts/sw-fix-test.sh && bash scripts/sw-fleet-discover-test.sh && bash scripts/sw-fleet-test.sh && bash scripts/sw-fleet-viz-test.sh && bash scripts/sw-frontier-test.sh && bash scripts/sw-github-app-test.sh && bash scripts/sw-github-checks-test.sh && bash scripts/sw-github-deploy-test.sh && bash scripts/sw-github-graphql-test.sh && bash scripts/sw-guild-test.sh && bash scripts/sw-heartbeat-test.sh && bash scripts/sw-hygiene-test.sh && bash scripts/sw-incident-test.sh && bash scripts/sw-init-test.sh && bash scripts/sw-instrument-test.sh && bash scripts/sw-intelligence-test.sh && bash scripts/sw-jira-test.sh && bash scripts/sw-launchd-test.sh && bash scripts/sw-linear-test.sh && bash scripts/sw-logs-test.sh && bash scripts/sw-loop-test.sh && bash scripts/sw-memory-test.sh && bash scripts/sw-mission-control-test.sh && bash scripts/sw-model-router-test.sh && bash scripts/sw-otel-test.sh && bash scripts/sw-oversight-test.sh && bash scripts/sw-patrol-meta-test.sh && bash scripts/sw-pipeline-composer-test.sh && bash scripts/sw-pipeline-test.sh && bash scripts/sw-pipeline-vitals-test.sh && bash scripts/sw-pm-test.sh && bash scripts/sw-pr-lifecycle-test.sh && bash scripts/sw-predictive-test.sh && bash scripts/sw-prep-test.sh && bash scripts/sw-ps-test.sh && bash scripts/sw-public-dashboard-test.sh && bash scripts/sw-quality-test.sh && bash scripts/sw-reaper-test.sh && bash scripts/sw-recruit-test.sh && bash scripts/sw-regression-test.sh && bash scripts/sw-release-manager-test.sh && bash scripts/sw-release-test.sh && bash scripts/sw-remote-test.sh && bash scripts/sw-replay-test.sh && bash scripts/sw-retro-test.sh && bash scripts/sw-scale-test.sh && bash scripts/sw-security-audit-test.sh && bash scripts/sw-self-optimize-test.sh && bash scripts/sw-session-test.sh && bash scripts/sw-setup-test.sh && bash scripts/sw-standup-test.sh && bash scripts/sw-status-test.sh && bash scripts/sw-strategic-test.sh && bash scripts/sw-stream-test.sh && bash scripts/sw-swarm-test.sh && bash scripts/sw-team-stages-test.sh && bash scripts/sw-templates-test.sh && bash scripts/sw-testgen-test.sh && bash scripts/sw-tmux-pipeline-test.sh && bash scripts/sw-tmux-test.sh && bash scripts/sw-trace-test.sh && bash scripts/sw-tracker-test.sh && bash scripts/sw-triage-test.sh && bash scripts/sw-upgrade-test.sh && bash scripts/sw-ux-test.sh && bash scripts/sw-webhook-test.sh && bash scripts/sw-widgets-test.sh && bash scripts/sw-worktree-test.sh && bash scripts/sw-policy-e2e-test.sh && bash scripts/sw-e2e-smoke-test.sh && bash scripts/sw-dashboard-e2e-test.sh",
39
+ "test": "bash scripts/sw-agi-roadmap-test.sh && bash scripts/sw-activity-test.sh && bash scripts/sw-adaptive-test.sh && bash scripts/sw-adversarial-test.sh && bash scripts/sw-architecture-enforcer-test.sh && bash scripts/sw-auth-test.sh && bash scripts/sw-autonomous-test.sh && bash scripts/sw-changelog-test.sh && bash scripts/sw-checkpoint-test.sh && bash scripts/sw-ci-test.sh && bash scripts/sw-cleanup-test.sh && bash scripts/sw-code-review-test.sh && bash scripts/sw-connect-test.sh && bash scripts/sw-context-test.sh && bash scripts/sw-cost-test.sh && bash scripts/sw-daemon-test.sh && bash scripts/sw-dashboard-test.sh && bash scripts/sw-db-test.sh && bash scripts/sw-decompose-test.sh && bash scripts/sw-decide-test.sh && bash scripts/sw-deps-test.sh && bash scripts/sw-developer-simulation-test.sh && bash scripts/sw-discovery-test.sh && bash scripts/sw-doc-fleet-test.sh && bash scripts/sw-docs-agent-test.sh && bash scripts/sw-docs-test.sh && bash scripts/sw-doctor-test.sh && bash scripts/sw-dora-test.sh && bash scripts/sw-durable-test.sh && bash scripts/sw-e2e-orchestrator-test.sh && bash scripts/sw-eventbus-test.sh && bash scripts/sw-feedback-test.sh && bash scripts/sw-fix-test.sh && bash scripts/sw-fleet-discover-test.sh && bash scripts/sw-fleet-test.sh && bash scripts/sw-fleet-viz-test.sh && bash scripts/sw-frontier-test.sh && bash scripts/sw-github-app-test.sh && bash scripts/sw-github-checks-test.sh && bash scripts/sw-github-deploy-test.sh && bash scripts/sw-github-graphql-test.sh && bash scripts/sw-guild-test.sh && bash scripts/sw-heartbeat-test.sh && bash scripts/sw-hygiene-test.sh && bash scripts/sw-incident-test.sh && bash scripts/sw-init-test.sh && bash scripts/sw-instrument-test.sh && bash scripts/sw-intelligence-test.sh && bash scripts/sw-jira-test.sh && bash scripts/sw-launchd-test.sh && bash scripts/sw-linear-test.sh && bash scripts/sw-logs-test.sh && bash scripts/sw-loop-test.sh && bash scripts/sw-memory-test.sh && bash scripts/sw-mission-control-test.sh && bash scripts/sw-model-router-test.sh && bash scripts/sw-otel-test.sh && bash scripts/sw-oversight-test.sh && bash scripts/sw-patrol-meta-test.sh && bash scripts/sw-pipeline-composer-test.sh && bash scripts/sw-pipeline-test.sh && bash scripts/sw-pipeline-vitals-test.sh && bash scripts/sw-pm-test.sh && bash scripts/sw-pr-lifecycle-test.sh && bash scripts/sw-predictive-test.sh && bash scripts/sw-prep-test.sh && bash scripts/sw-ps-test.sh && bash scripts/sw-public-dashboard-test.sh && bash scripts/sw-quality-test.sh && bash scripts/sw-reaper-test.sh && bash scripts/sw-recruit-test.sh && bash scripts/sw-regression-test.sh && bash scripts/sw-release-manager-test.sh && bash scripts/sw-release-test.sh && bash scripts/sw-remote-test.sh && bash scripts/sw-replay-test.sh && bash scripts/sw-retro-test.sh && bash scripts/sw-scale-test.sh && bash scripts/sw-security-audit-test.sh && bash scripts/sw-self-optimize-test.sh && bash scripts/sw-session-test.sh && bash scripts/sw-setup-test.sh && bash scripts/sw-standup-test.sh && bash scripts/sw-status-test.sh && bash scripts/sw-strategic-test.sh && bash scripts/sw-stream-test.sh && bash scripts/sw-swarm-test.sh && bash scripts/sw-team-stages-test.sh && bash scripts/sw-templates-test.sh && bash scripts/sw-testgen-test.sh && bash scripts/sw-tmux-pipeline-test.sh && bash scripts/sw-tmux-test.sh && bash scripts/sw-trace-test.sh && bash scripts/sw-tracker-test.sh && bash scripts/sw-triage-test.sh && bash scripts/sw-upgrade-test.sh && bash scripts/sw-ux-test.sh && bash scripts/sw-webhook-test.sh && bash scripts/sw-widgets-test.sh && bash scripts/sw-worktree-test.sh && bash scripts/sw-lib-compat-test.sh && bash scripts/sw-lib-helpers-test.sh && bash scripts/sw-lib-daemon-dispatch-test.sh && bash scripts/sw-lib-daemon-failure-test.sh && bash scripts/sw-lib-daemon-poll-test.sh && bash scripts/sw-lib-daemon-state-test.sh && bash scripts/sw-lib-daemon-triage-test.sh && bash scripts/sw-lib-pipeline-detection-test.sh && bash scripts/sw-lib-pipeline-intelligence-test.sh && bash scripts/sw-lib-pipeline-quality-checks-test.sh && bash scripts/sw-lib-pipeline-stages-test.sh && bash scripts/sw-lib-pipeline-state-test.sh && bash scripts/sw-adapters-test.sh && bash scripts/sw-evidence-test.sh && bash scripts/sw-review-rerun-test.sh && bash scripts/sw-tracker-providers-test.sh && bash scripts/sw-budget-chaos-test.sh && bash scripts/sw-autonomous-e2e-test.sh && bash scripts/sw-memory-discovery-e2e-test.sh && bash scripts/sw-policy-e2e-test.sh && bash scripts/sw-e2e-smoke-test.sh && bash scripts/sw-dashboard-e2e-test.sh",
40
40
  "test:smoke": "bash scripts/sw-e2e-smoke-test.sh",
41
- "test:integration": "bash scripts/sw-e2e-integration-test.sh",
41
+ "test:integration": "bash scripts/sw-e2e-integration-test.sh && bash scripts/sw-e2e-system-test.sh && bash scripts/sw-server-api-test.sh && bash scripts/sw-integration-claude-test.sh",
42
42
  "harness:evidence:capture": "bash scripts/sw-evidence.sh capture",
43
43
  "harness:evidence:verify": "bash scripts/sw-evidence.sh verify",
44
44
  "harness:evidence:pre-pr": "bash scripts/sw-evidence.sh pre-pr",
@@ -48,9 +48,7 @@
48
48
  "harness:evidence:capture:cli": "bash scripts/sw-evidence.sh capture cli",
49
49
  "harness:ui:capture-browser-evidence": "bash scripts/sw-evidence.sh capture browser",
50
50
  "harness:ui:verify-browser-evidence": "bash scripts/sw-evidence.sh verify",
51
- "harness:ui:pre-pr": "bash scripts/sw-evidence.sh pre-pr browser",
52
- "harness:risk-tier": "bash scripts/sw-pr-lifecycle.sh risk-tier",
53
- "harness:policy-gate": "bash scripts/sw-pr-lifecycle.sh policy-gate"
51
+ "harness:ui:pre-pr": "bash scripts/sw-evidence.sh pre-pr browser"
54
52
  },
55
53
  "keywords": [
56
54
  "claude",
@@ -38,7 +38,7 @@ get_rollback_cmd() {
38
38
  }
39
39
 
40
40
  get_health_url() {
41
- echo "http://localhost:3000/health"
41
+ echo "http://localhost:8767/health"
42
42
  }
43
43
 
44
44
  get_smoke_cmd() {
@@ -14,9 +14,14 @@
14
14
  # Track spawned panes by agent name → pane ID (file-based for bash 3.2 compat)
15
15
  _TMUX_PANE_MAP="${TMPDIR:-/tmp}/shipwright-tmux-pane-map.$$"
16
16
  : > "$_TMUX_PANE_MAP"
17
- trap 'rm -f "$_TMUX_PANE_MAP"' EXIT
17
+ trap '
18
+ if [[ -f "$_TMUX_PANE_MAP" ]] && [[ ! -s "$_TMUX_PANE_MAP" ]]; then
19
+ rm -f "$_TMUX_PANE_MAP"
20
+ fi
21
+ ' EXIT
18
22
 
19
23
  spawn_agent() {
24
+ [[ -z "${WINDOW_NAME:-}" ]] && { echo "ERROR: WINDOW_NAME not set" >&2; return 1; }
20
25
  local name="$1"
21
26
  local working_dir="${2:-#{pane_current_path}}"
22
27
  local command="${3:-}"
@@ -32,6 +37,11 @@ spawn_agent() {
32
37
  new_pane_id=$(tmux split-window -t "$WINDOW_NAME" -c "$working_dir" -P -F '#{pane_id}')
33
38
  fi
34
39
 
40
+ if [[ -z "$new_pane_id" ]]; then
41
+ echo "ERROR: Failed to create tmux pane for agent '$name'" >&2
42
+ return 1
43
+ fi
44
+
35
45
  # Record the mapping: name → pane_id
36
46
  echo "${name}=${new_pane_id}" >> "$_TMUX_PANE_MAP"
37
47
 
@@ -9,7 +9,7 @@
9
9
  # ╚═══════════════════════════════════════════════════════════════════════════╝
10
10
 
11
11
  # Verify wezterm CLI is available
12
- if ! command -v wezterm &>/dev/null; then
12
+ if ! command -v wezterm >/dev/null 2>&1; then
13
13
  echo -e "\033[38;2;248;113;113m\033[1m✗\033[0m wezterm CLI not found. Install WezTerm first." >&2
14
14
  exit 1
15
15
  fi
@@ -11,7 +11,7 @@ REPO_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
11
11
 
12
12
  CANONICAL=""
13
13
  if [[ -f "$REPO_ROOT/package.json" ]]; then
14
- if command -v jq &>/dev/null; then
14
+ if command -v jq >/dev/null 2>&1; then
15
15
  CANONICAL="$(jq -r .version "$REPO_ROOT/package.json")"
16
16
  else
17
17
  CANONICAL="$(grep -oE '"version":\s*"[^"]+"' "$REPO_ROOT/package.json" | head -1 | sed 's/.*"\([^"]*\)".*/\1/')"
@@ -0,0 +1,127 @@
1
+ # architecture.sh — Gather call-graph and dependency context for plan/design stages
2
+ # Source from pipeline-stages. Requires compat (detect_primary_language).
3
+ [[ -n "${_ARCHITECTURE_CONTEXT_LOADED:-}" ]] && return 0
4
+ _ARCHITECTURE_CONTEXT_LOADED=1
5
+
6
+ # Gather rich architecture context: structure, imports, modules, entry points, test map
7
+ gather_architecture_context() {
8
+ local repo_root="${1:-.}"
9
+ local context=""
10
+
11
+ # 1. File structure
12
+ context="## Project Structure
13
+ $(find "$repo_root" -type f \( -name '*.ts' -o -name '*.js' -o -name '*.py' -o -name '*.sh' -o -name '*.go' -o -name '*.rs' \) 2>/dev/null | grep -v node_modules | grep -v .git | head -100 | sort)
14
+
15
+ "
16
+
17
+ # 2. Import/dependency graph (language-specific)
18
+ local lang=""
19
+ if type detect_primary_language >/dev/null 2>&1; then
20
+ lang=$(detect_primary_language "$repo_root" 2>/dev/null || echo "unknown")
21
+ else
22
+ lang="unknown"
23
+ fi
24
+
25
+ case "$lang" in
26
+ typescript|javascript|nodejs)
27
+ context="${context}## Import Graph (Top Dependencies)
28
+ "
29
+ local imports=""
30
+ for dir in "$repo_root/src" "$repo_root/lib" "$repo_root/app"; do
31
+ [[ -d "$dir" ]] || continue
32
+ imports=$(grep -rh "^import .* from\|require(" "$dir" 2>/dev/null | \
33
+ grep -oE "from ['\"]([^'\"]+)['\"]|require\\(['\"]([^'\"]+)['\"]\\)" | \
34
+ sed "s/from ['\"]//;s/['\"]//g;s/require(//;s/)//g" | \
35
+ sort | uniq -c | sort -rn | head -20)
36
+ [[ -n "$imports" ]] && context="${context}${imports}
37
+ "
38
+ done
39
+ [[ -z "$imports" ]] && context="${context}(none detected)
40
+ "
41
+
42
+ context="${context}## Module Export Counts
43
+ "
44
+ local f
45
+ while IFS= read -r f; do
46
+ [[ -f "$f" ]] || continue
47
+ local exports=0
48
+ exports=$(grep -c "^export " "$f" 2>/dev/null || true)
49
+ exports="${exports:-0}"
50
+ [[ "$exports" -gt 2 ]] 2>/dev/null && context="${context} $(basename "$f"): $exports exports
51
+ "
52
+ done < <(find "$repo_root/src" "$repo_root/lib" -name "*.ts" -o -name "*.js" 2>/dev/null | head -30)
53
+ ;;
54
+
55
+ python)
56
+ context="${context}## Import Graph (Top Dependencies)
57
+ "
58
+ local py_imports=""
59
+ py_imports=$(find "$repo_root" -name "*.py" -type f 2>/dev/null | \
60
+ xargs grep -h "^from \|^import " 2>/dev/null | \
61
+ grep -v __pycache__ | sort | uniq -c | sort -rn | head -20)
62
+ context="${context}${py_imports}
63
+ "
64
+ ;;
65
+
66
+ bash|shell)
67
+ context="${context}## Source Dependencies
68
+ "
69
+ local sh_imports=""
70
+ [[ -d "$repo_root/scripts" ]] && \
71
+ sh_imports=$(grep -rh "^source \|^\. " "$repo_root/scripts" --include="*.sh" 2>/dev/null | \
72
+ sort | uniq -c | sort -rn | head -20)
73
+ context="${context}${sh_imports}
74
+ "
75
+ ;;
76
+ *)
77
+ context="${context}## Dependencies
78
+ (Language: $lang — no specific import analysis)
79
+ "
80
+ ;;
81
+ esac
82
+
83
+ # 3. Module boundaries (directories with >2 files = modules)
84
+ context="${context}## Module Boundaries
85
+ "
86
+ local dir
87
+ while IFS= read -r dir; do
88
+ [[ -d "$dir" ]] || continue
89
+ local count=0
90
+ count=$(find "$dir" -maxdepth 1 -type f \( -name "*.ts" -o -name "*.js" -o -name "*.py" -o -name "*.sh" \) 2>/dev/null | wc -l | tr -d ' ')
91
+ [[ "$count" -gt 2 ]] 2>/dev/null && context="${context} $(basename "$dir")/: $count files
92
+ "
93
+ done < <(find "$repo_root/src" "$repo_root/lib" "$repo_root/scripts" -maxdepth 2 -type d 2>/dev/null | head -30)
94
+
95
+ # 4. Entry points
96
+ context="${context}## Entry Points
97
+ "
98
+ if [[ -f "$repo_root/package.json" ]] && command -v jq >/dev/null 2>&1; then
99
+ local main
100
+ main=$(jq -r '.main // .bin // "index.js" | if type == "object" then (. | keys[0]) else . end' "$repo_root/package.json" 2>/dev/null || echo "")
101
+ [[ -n "$main" && "$main" != "null" ]] && context="${context} package.json: $main
102
+ "
103
+ fi
104
+ if [[ -f "$repo_root/Makefile" ]]; then
105
+ local targets
106
+ targets=$(grep '^[a-zA-Z][a-zA-Z0-9_-]*:' "$repo_root/Makefile" 2>/dev/null | cut -d: -f1 | head -10 | tr '\n' ', ')
107
+ [[ -n "$targets" ]] && context="${context} Makefile targets: $targets
108
+ "
109
+ fi
110
+
111
+ # 5. Test-to-source mapping
112
+ context="${context}## Test Coverage Map
113
+ "
114
+ local test_file
115
+ while IFS= read -r test_file; do
116
+ [[ -f "$test_file" ]] || continue
117
+ local base
118
+ base=$(basename "$test_file" | sed 's/[-.]test//;s/[-.]spec//;s/__tests__//;s/\..*$//' | head -c 50)
119
+ [[ -z "$base" ]] && continue
120
+ local source
121
+ source=$(find "$repo_root/src" "$repo_root/lib" "$repo_root/scripts" -name "${base}.*" -type f 2>/dev/null | head -1)
122
+ [[ -n "$source" ]] && context="${context} $test_file -> $source
123
+ "
124
+ done < <(find "$repo_root" -path "*node_modules" -prune -o -path "*/.git" -prune -o \( -name "*test*" -o -name "*spec*" \) -type f -print 2>/dev/null | head -20)
125
+
126
+ echo "$context"
127
+ }
@@ -0,0 +1,75 @@
1
+ #!/usr/bin/env bash
2
+ # ╔═══════════════════════════════════════════════════════════════════════════╗
3
+ # ║ shipwright bootstrap — Cold-start initialization for optimization data ║
4
+ # ║ Creates sensible defaults when no historical data exists (new installs) ║
5
+ # ╚═══════════════════════════════════════════════════════════════════════════╝
6
+
7
+ # bootstrap_optimization — create default iteration model, template weights, model routing
8
+ bootstrap_optimization() {
9
+ local opt_dir="$HOME/.shipwright/optimization"
10
+ mkdir -p "$opt_dir"
11
+
12
+ # Default iteration model based on common patterns
13
+ if [[ ! -f "$opt_dir/iteration-model.json" ]]; then
14
+ cat > "$opt_dir/iteration-model.json" << 'JSON'
15
+ {
16
+ "low": {"mean": 5, "stddev": 2, "samples": 0, "source": "bootstrap"},
17
+ "medium": {"mean": 12, "stddev": 4, "samples": 0, "source": "bootstrap"},
18
+ "high": {"mean": 25, "stddev": 8, "samples": 0, "source": "bootstrap"}
19
+ }
20
+ JSON
21
+ fi
22
+
23
+ # Default template weights
24
+ if [[ ! -f "$opt_dir/template-weights.json" ]]; then
25
+ cat > "$opt_dir/template-weights.json" << 'JSON'
26
+ {
27
+ "standard": 1.0,
28
+ "hotfix": 1.0,
29
+ "docs": 1.0,
30
+ "refactor": 1.0,
31
+ "source": "bootstrap"
32
+ }
33
+ JSON
34
+ fi
35
+
36
+ # Default model routing
37
+ if [[ ! -f "$opt_dir/model-routing.json" ]]; then
38
+ cat > "$opt_dir/model-routing.json" << 'JSON'
39
+ {
40
+ "routes": {
41
+ "plan": {"recommended": "opus", "source": "bootstrap"},
42
+ "design": {"recommended": "opus", "source": "bootstrap"},
43
+ "build": {"recommended": "sonnet", "source": "bootstrap"},
44
+ "test": {"recommended": "sonnet", "source": "bootstrap"},
45
+ "review": {"recommended": "sonnet", "source": "bootstrap"}
46
+ },
47
+ "default": "sonnet",
48
+ "source": "bootstrap"
49
+ }
50
+ JSON
51
+ fi
52
+ }
53
+
54
+ # bootstrap_memory — create initial memory patterns based on project type
55
+ bootstrap_memory() {
56
+ local mem_dir="$HOME/.shipwright/memory"
57
+ mkdir -p "$mem_dir"
58
+
59
+ if [[ ! -f "$mem_dir/patterns.json" ]]; then
60
+ # Detect project type and create initial patterns
61
+ local project_type="unknown"
62
+ [[ -f "package.json" ]] && project_type="nodejs"
63
+ [[ -f "requirements.txt" || -f "pyproject.toml" ]] && project_type="python"
64
+ [[ -f "Cargo.toml" ]] && project_type="rust"
65
+ [[ -f "go.mod" ]] && project_type="go"
66
+
67
+ cat > "$mem_dir/patterns.json" << JSON
68
+ {
69
+ "project_type": "$project_type",
70
+ "detected_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)",
71
+ "source": "bootstrap"
72
+ }
73
+ JSON
74
+ fi
75
+ }