chief-clancy 0.2.0-beta.3 → 0.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 (143) hide show
  1. package/README.md +13 -24
  2. package/dist/installer/file-ops/file-ops.d.ts +32 -0
  3. package/dist/installer/file-ops/file-ops.d.ts.map +1 -0
  4. package/dist/installer/file-ops/file-ops.js +58 -0
  5. package/dist/installer/file-ops/file-ops.js.map +1 -0
  6. package/dist/installer/hook-installer/hook-installer.d.ts +29 -0
  7. package/dist/installer/hook-installer/hook-installer.d.ts.map +1 -0
  8. package/dist/installer/hook-installer/hook-installer.js +96 -0
  9. package/dist/installer/hook-installer/hook-installer.js.map +1 -0
  10. package/dist/installer/install.d.ts +3 -0
  11. package/dist/installer/install.d.ts.map +1 -0
  12. package/dist/installer/install.js +227 -0
  13. package/dist/installer/install.js.map +1 -0
  14. package/dist/installer/manifest/manifest.d.ts +41 -0
  15. package/dist/installer/manifest/manifest.d.ts.map +1 -0
  16. package/dist/installer/manifest/manifest.js +97 -0
  17. package/dist/installer/manifest/manifest.js.map +1 -0
  18. package/dist/installer/prompts/prompts.d.ts +33 -0
  19. package/dist/installer/prompts/prompts.d.ts.map +1 -0
  20. package/dist/installer/prompts/prompts.js +55 -0
  21. package/dist/installer/prompts/prompts.js.map +1 -0
  22. package/dist/schemas/env.d.ts +75 -0
  23. package/dist/schemas/env.d.ts.map +1 -0
  24. package/dist/schemas/env.js +40 -0
  25. package/dist/schemas/env.js.map +1 -0
  26. package/dist/schemas/github.d.ts +27 -0
  27. package/dist/schemas/github.d.ts.map +1 -0
  28. package/dist/schemas/github.js +17 -0
  29. package/dist/schemas/github.js.map +1 -0
  30. package/dist/schemas/index.d.ts +9 -0
  31. package/dist/schemas/index.d.ts.map +1 -0
  32. package/dist/schemas/index.js +5 -0
  33. package/dist/schemas/index.js.map +1 -0
  34. package/dist/schemas/jira.d.ts +37 -0
  35. package/dist/schemas/jira.d.ts.map +1 -0
  36. package/dist/schemas/jira.js +37 -0
  37. package/dist/schemas/jira.js.map +1 -0
  38. package/dist/schemas/linear.d.ts +67 -0
  39. package/dist/schemas/linear.d.ts.map +1 -0
  40. package/dist/schemas/linear.js +50 -0
  41. package/dist/schemas/linear.js.map +1 -0
  42. package/dist/scripts/afk/afk.d.ts +21 -0
  43. package/dist/scripts/afk/afk.d.ts.map +1 -0
  44. package/dist/scripts/afk/afk.js +116 -0
  45. package/dist/scripts/afk/afk.js.map +1 -0
  46. package/dist/scripts/board/github/github.d.ts +56 -0
  47. package/dist/scripts/board/github/github.d.ts.map +1 -0
  48. package/dist/scripts/board/github/github.js +142 -0
  49. package/dist/scripts/board/github/github.js.map +1 -0
  50. package/dist/scripts/board/jira/jira.d.ts +90 -0
  51. package/dist/scripts/board/jira/jira.d.ts.map +1 -0
  52. package/dist/scripts/board/jira/jira.js +251 -0
  53. package/dist/scripts/board/jira/jira.js.map +1 -0
  54. package/dist/scripts/board/linear/linear.d.ts +85 -0
  55. package/dist/scripts/board/linear/linear.d.ts.map +1 -0
  56. package/dist/scripts/board/linear/linear.js +209 -0
  57. package/dist/scripts/board/linear/linear.js.map +1 -0
  58. package/dist/scripts/once/once.d.ts +12 -0
  59. package/dist/scripts/once/once.d.ts.map +1 -0
  60. package/dist/scripts/once/once.js +323 -0
  61. package/dist/scripts/once/once.js.map +1 -0
  62. package/dist/scripts/shared/branch/branch.d.ts +50 -0
  63. package/dist/scripts/shared/branch/branch.d.ts.map +1 -0
  64. package/dist/scripts/shared/branch/branch.js +61 -0
  65. package/dist/scripts/shared/branch/branch.js.map +1 -0
  66. package/dist/scripts/shared/claude-cli/claude-cli.d.ts +17 -0
  67. package/dist/scripts/shared/claude-cli/claude-cli.d.ts.map +1 -0
  68. package/dist/scripts/shared/claude-cli/claude-cli.js +35 -0
  69. package/dist/scripts/shared/claude-cli/claude-cli.js.map +1 -0
  70. package/dist/scripts/shared/env-parser/env-parser.d.ts +30 -0
  71. package/dist/scripts/shared/env-parser/env-parser.d.ts.map +1 -0
  72. package/dist/scripts/shared/env-parser/env-parser.js +64 -0
  73. package/dist/scripts/shared/env-parser/env-parser.js.map +1 -0
  74. package/dist/scripts/shared/env-schema/env-schema.d.ts +27 -0
  75. package/dist/scripts/shared/env-schema/env-schema.d.ts.map +1 -0
  76. package/dist/scripts/shared/env-schema/env-schema.js +46 -0
  77. package/dist/scripts/shared/env-schema/env-schema.js.map +1 -0
  78. package/dist/scripts/shared/git-ops/git-ops.d.ts +52 -0
  79. package/dist/scripts/shared/git-ops/git-ops.d.ts.map +1 -0
  80. package/dist/scripts/shared/git-ops/git-ops.js +107 -0
  81. package/dist/scripts/shared/git-ops/git-ops.js.map +1 -0
  82. package/dist/scripts/shared/http/http.d.ts +52 -0
  83. package/dist/scripts/shared/http/http.d.ts.map +1 -0
  84. package/dist/scripts/shared/http/http.js +74 -0
  85. package/dist/scripts/shared/http/http.js.map +1 -0
  86. package/dist/scripts/shared/notify/notify.d.ts +46 -0
  87. package/dist/scripts/shared/notify/notify.d.ts.map +1 -0
  88. package/dist/scripts/shared/notify/notify.js +88 -0
  89. package/dist/scripts/shared/notify/notify.js.map +1 -0
  90. package/dist/scripts/shared/preflight/preflight.d.ts +40 -0
  91. package/dist/scripts/shared/preflight/preflight.d.ts.map +1 -0
  92. package/dist/scripts/shared/preflight/preflight.js +84 -0
  93. package/dist/scripts/shared/preflight/preflight.js.map +1 -0
  94. package/dist/scripts/shared/progress/progress.d.ts +25 -0
  95. package/dist/scripts/shared/progress/progress.d.ts.map +1 -0
  96. package/dist/scripts/shared/progress/progress.js +46 -0
  97. package/dist/scripts/shared/progress/progress.js.map +1 -0
  98. package/dist/scripts/shared/prompt/prompt.d.ts +38 -0
  99. package/dist/scripts/shared/prompt/prompt.d.ts.map +1 -0
  100. package/dist/scripts/shared/prompt/prompt.js +77 -0
  101. package/dist/scripts/shared/prompt/prompt.js.map +1 -0
  102. package/dist/types/board.d.ts +13 -0
  103. package/dist/types/board.d.ts.map +1 -0
  104. package/dist/types/board.js +5 -0
  105. package/dist/types/board.js.map +1 -0
  106. package/dist/types/index.d.ts +3 -0
  107. package/dist/types/index.d.ts.map +1 -0
  108. package/dist/types/index.js +2 -0
  109. package/dist/types/index.js.map +1 -0
  110. package/dist/utils/ansi/ansi.d.ts +55 -0
  111. package/dist/utils/ansi/ansi.d.ts.map +1 -0
  112. package/dist/utils/ansi/ansi.js +55 -0
  113. package/dist/utils/ansi/ansi.js.map +1 -0
  114. package/dist/utils/index.d.ts +3 -0
  115. package/dist/utils/index.d.ts.map +1 -0
  116. package/dist/utils/index.js +3 -0
  117. package/dist/utils/index.js.map +1 -0
  118. package/dist/utils/parse-json/parse-json.d.ts +20 -0
  119. package/dist/utils/parse-json/parse-json.d.ts.map +1 -0
  120. package/dist/utils/parse-json/parse-json.js +27 -0
  121. package/dist/utils/parse-json/parse-json.js.map +1 -0
  122. package/hooks/clancy-check-update.js +2 -2
  123. package/hooks/clancy-credential-guard.js +8 -1
  124. package/package.json +52 -8
  125. package/registry/boards.json +3 -6
  126. package/src/templates/CLAUDE.md +1 -1
  127. package/src/workflows/doctor.md +32 -23
  128. package/src/workflows/init.md +88 -19
  129. package/src/workflows/logs.md +13 -6
  130. package/src/workflows/map-codebase.md +17 -16
  131. package/src/workflows/once.md +22 -12
  132. package/src/workflows/review.md +40 -27
  133. package/src/workflows/run.md +20 -12
  134. package/src/workflows/scaffold.md +12 -1023
  135. package/src/workflows/settings.md +9 -6
  136. package/src/workflows/status.md +17 -8
  137. package/src/workflows/uninstall.md +11 -6
  138. package/src/workflows/update.md +13 -11
  139. package/bin/install.js +0 -362
  140. package/src/templates/scripts/clancy-afk.sh +0 -111
  141. package/src/templates/scripts/clancy-once-github.sh +0 -249
  142. package/src/templates/scripts/clancy-once-linear.sh +0 -320
  143. package/src/templates/scripts/clancy-once.sh +0 -322
@@ -0,0 +1,323 @@
1
+ /**
2
+ * Unified once orchestrator — replaces all three `clancy-once-*.sh` scripts.
3
+ *
4
+ * Full lifecycle: preflight → detect board → fetch ticket → compute branches →
5
+ * [dry-run gate] → transition In Progress → create branch → invoke Claude →
6
+ * squash merge → transition Done → log → notify.
7
+ *
8
+ * All errors exit with code 0 (not 1). This is intentional — the AFK runner
9
+ * detects stop conditions by parsing stdout, not exit codes.
10
+ */
11
+ import { closeIssue, fetchIssue as fetchGitHubIssue, isValidRepo, pingGitHub, } from '../../scripts/board/github/github.js';
12
+ import { buildAuthHeader, fetchTicket as fetchJiraTicket, isSafeJqlValue, pingJira, transitionIssue as transitionJiraIssue, } from '../../scripts/board/jira/jira.js';
13
+ import { fetchIssue as fetchLinearIssue, isValidTeamId, pingLinear, transitionIssue as transitionLinearIssue, } from '../../scripts/board/linear/linear.js';
14
+ import { computeTargetBranch, computeTicketBranch, } from '../../scripts/shared/branch/branch.js';
15
+ import { invokeClaudeSession } from '../../scripts/shared/claude-cli/claude-cli.js';
16
+ import { detectBoard } from '../../scripts/shared/env-schema/env-schema.js';
17
+ import { checkout, currentBranch, deleteBranch, ensureBranch, squashMerge, } from '../../scripts/shared/git-ops/git-ops.js';
18
+ import { sendNotification } from '../../scripts/shared/notify/notify.js';
19
+ import { runPreflight } from '../../scripts/shared/preflight/preflight.js';
20
+ import { appendProgress } from '../../scripts/shared/progress/progress.js';
21
+ import { buildPrompt } from '../../scripts/shared/prompt/prompt.js';
22
+ import { bold, dim, green, red, yellow } from '../../utils/ansi/ansi.js';
23
+ // ─── Helpers ──────────────────────────────────────────────────────────────────
24
+ function formatDuration(ms) {
25
+ const secs = Math.floor(ms / 1000);
26
+ if (secs < 60)
27
+ return `${secs}s`;
28
+ const mins = Math.floor(secs / 60);
29
+ const remSecs = secs % 60;
30
+ return remSecs > 0 ? `${mins}m ${remSecs}s` : `${mins}m`;
31
+ }
32
+ // ─── Board-specific fetch ────────────────────────────────────────────────────
33
+ async function fetchTicket(config) {
34
+ switch (config.provider) {
35
+ case 'jira': {
36
+ const { env } = config;
37
+ const auth = buildAuthHeader(env.JIRA_USER, env.JIRA_API_TOKEN);
38
+ const ticket = await fetchJiraTicket(env.JIRA_BASE_URL, auth, env.JIRA_PROJECT_KEY, env.CLANCY_JQL_STATUS ?? 'To Do', env.CLANCY_JQL_SPRINT, env.CLANCY_LABEL);
39
+ if (!ticket)
40
+ return undefined;
41
+ const blockerStr = ticket.blockers.length
42
+ ? `Blocked by: ${ticket.blockers.join(', ')}`
43
+ : 'None';
44
+ return {
45
+ key: ticket.key,
46
+ title: ticket.title,
47
+ description: ticket.description,
48
+ parentInfo: ticket.epicKey ?? 'none',
49
+ blockers: blockerStr,
50
+ };
51
+ }
52
+ case 'github': {
53
+ const { env } = config;
54
+ const ticket = await fetchGitHubIssue(env.GITHUB_TOKEN, env.GITHUB_REPO, env.CLANCY_LABEL);
55
+ if (!ticket)
56
+ return undefined;
57
+ return {
58
+ key: ticket.key,
59
+ title: ticket.title,
60
+ description: ticket.description,
61
+ parentInfo: ticket.milestone ?? 'none',
62
+ blockers: 'None',
63
+ };
64
+ }
65
+ case 'linear': {
66
+ const { env } = config;
67
+ const ticket = await fetchLinearIssue({
68
+ LINEAR_API_KEY: env.LINEAR_API_KEY,
69
+ LINEAR_TEAM_ID: env.LINEAR_TEAM_ID,
70
+ CLANCY_LABEL: env.CLANCY_LABEL,
71
+ });
72
+ if (!ticket)
73
+ return undefined;
74
+ return {
75
+ key: ticket.key,
76
+ title: ticket.title,
77
+ description: ticket.description,
78
+ parentInfo: ticket.parentIdentifier ?? 'none',
79
+ blockers: 'None',
80
+ linearIssueId: ticket.issueId,
81
+ };
82
+ }
83
+ }
84
+ }
85
+ // ─── Board-specific ping ─────────────────────────────────────────────────────
86
+ async function pingBoard(config) {
87
+ switch (config.provider) {
88
+ case 'jira': {
89
+ const { env } = config;
90
+ const auth = buildAuthHeader(env.JIRA_USER, env.JIRA_API_TOKEN);
91
+ return pingJira(env.JIRA_BASE_URL, env.JIRA_PROJECT_KEY, auth);
92
+ }
93
+ case 'github':
94
+ return pingGitHub(config.env.GITHUB_TOKEN, config.env.GITHUB_REPO);
95
+ case 'linear':
96
+ return pingLinear(config.env.LINEAR_API_KEY);
97
+ }
98
+ }
99
+ // ─── Board-specific validation ───────────────────────────────────────────────
100
+ function validateInputs(config) {
101
+ switch (config.provider) {
102
+ case 'jira': {
103
+ const { env } = config;
104
+ if (!isSafeJqlValue(env.JIRA_PROJECT_KEY)) {
105
+ return '✗ JIRA_PROJECT_KEY contains invalid characters';
106
+ }
107
+ if (env.CLANCY_LABEL && !isSafeJqlValue(env.CLANCY_LABEL)) {
108
+ return '✗ CLANCY_LABEL contains invalid characters';
109
+ }
110
+ if (env.CLANCY_JQL_STATUS && !isSafeJqlValue(env.CLANCY_JQL_STATUS)) {
111
+ return '✗ CLANCY_JQL_STATUS contains invalid characters';
112
+ }
113
+ return undefined;
114
+ }
115
+ case 'github': {
116
+ if (!isValidRepo(config.env.GITHUB_REPO)) {
117
+ return '✗ GITHUB_REPO format is invalid — expected owner/repo';
118
+ }
119
+ return undefined;
120
+ }
121
+ case 'linear': {
122
+ if (!isValidTeamId(config.env.LINEAR_TEAM_ID)) {
123
+ return '✗ LINEAR_TEAM_ID contains invalid characters';
124
+ }
125
+ return undefined;
126
+ }
127
+ }
128
+ }
129
+ // ─── Board-specific transitions ──────────────────────────────────────────────
130
+ async function transitionToStatus(config, ticket, statusName) {
131
+ switch (config.provider) {
132
+ case 'jira': {
133
+ const { env } = config;
134
+ const auth = buildAuthHeader(env.JIRA_USER, env.JIRA_API_TOKEN);
135
+ const issueKey = ticket.key;
136
+ const ok = await transitionJiraIssue(env.JIRA_BASE_URL, auth, issueKey, statusName);
137
+ if (ok)
138
+ console.log(` → Transitioned to ${statusName}`);
139
+ break;
140
+ }
141
+ case 'github': {
142
+ // GitHub Issues only has open/closed — status transitions not applicable
143
+ // closeIssue is called separately after merge
144
+ break;
145
+ }
146
+ case 'linear': {
147
+ const { env } = config;
148
+ if (!ticket.linearIssueId)
149
+ break;
150
+ const ok = await transitionLinearIssue(env.LINEAR_API_KEY, env.LINEAR_TEAM_ID, ticket.linearIssueId, statusName);
151
+ if (ok)
152
+ console.log(` → Transitioned to ${statusName}`);
153
+ break;
154
+ }
155
+ }
156
+ }
157
+ // ─── Main orchestrator ───────────────────────────────────────────────────────
158
+ /**
159
+ * Run the once orchestrator — full ticket lifecycle.
160
+ *
161
+ * @param argv - Process arguments (supports `--dry-run` flag).
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * await run(process.argv);
166
+ * ```
167
+ */
168
+ export async function run(argv) {
169
+ const dryRun = argv.includes('--dry-run');
170
+ const startTime = Date.now();
171
+ console.log(dim('┌──────────────────────────────────────┐'));
172
+ console.log(dim('│') + bold(' 🤖 Clancy — once mode ') + dim('│'));
173
+ console.log(dim('│') + dim(' "Let\'s roll." ') + dim('│'));
174
+ console.log(dim('└──────────────────────────────────────┘'));
175
+ console.log('');
176
+ let originalBranch;
177
+ try {
178
+ // 1. Preflight
179
+ const preflight = runPreflight(process.cwd());
180
+ if (!preflight.ok) {
181
+ console.log(preflight.error);
182
+ return;
183
+ }
184
+ if (preflight.warning) {
185
+ console.log(preflight.warning);
186
+ }
187
+ // 2. Detect board
188
+ const boardResult = detectBoard(preflight.env);
189
+ if (typeof boardResult === 'string') {
190
+ console.log(boardResult);
191
+ return;
192
+ }
193
+ const config = boardResult;
194
+ // 3. Validate board-specific inputs
195
+ const validationError = validateInputs(config);
196
+ if (validationError) {
197
+ console.log(validationError);
198
+ return;
199
+ }
200
+ // 4. Ping board
201
+ const ping = await pingBoard(config);
202
+ if (!ping.ok) {
203
+ console.log(ping.error);
204
+ return;
205
+ }
206
+ console.log(green('✅ Preflight passed'));
207
+ // 5. Fetch ticket
208
+ const ticket = await fetchTicket(config);
209
+ if (!ticket) {
210
+ console.log(dim('No tickets found. All done!'));
211
+ return;
212
+ }
213
+ // 6. Compute branches
214
+ const baseBranch = config.env.CLANCY_BASE_BRANCH ?? 'main';
215
+ const parent = ticket.parentInfo !== 'none' ? ticket.parentInfo : undefined;
216
+ const ticketBranch = computeTicketBranch(config.provider, ticket.key);
217
+ const targetBranch = computeTargetBranch(config.provider, baseBranch, parent);
218
+ // 7. Dry-run gate
219
+ if (dryRun) {
220
+ const parentLabel = config.provider === 'github' ? 'Milestone' : 'Epic';
221
+ console.log('');
222
+ console.log(yellow('── Dry Run ──────────────────────────────────────'));
223
+ console.log(` Ticket: ${bold(`[${ticket.key}]`)} ${ticket.title}`);
224
+ console.log(` ${parentLabel}:${' '.repeat(14 - parentLabel.length)}${ticket.parentInfo}`);
225
+ if (config.provider !== 'github') {
226
+ console.log(` Blockers: ${ticket.blockers}`);
227
+ }
228
+ console.log(` Target branch: ${ticketBranch} → ${targetBranch}`);
229
+ console.log(yellow('─────────────────────────────────────────────────'));
230
+ console.log(dim(' No changes made. Remove --dry-run to run for real.'));
231
+ return;
232
+ }
233
+ // 8. Print ticket info
234
+ const parentLabel = config.provider === 'github' ? 'Milestone' : 'Epic';
235
+ console.log('');
236
+ console.log(`🎫 ${bold(`[${ticket.key}]`)} ${ticket.title}`);
237
+ console.log(dim(` ${parentLabel}: ${ticket.parentInfo} | Branch: ${ticketBranch} → ${targetBranch}`));
238
+ if (config.provider !== 'github' && ticket.blockers !== 'None') {
239
+ console.log(yellow(` Blockers: ${ticket.blockers}`));
240
+ }
241
+ console.log('');
242
+ // 9. Git: set up branches
243
+ originalBranch = currentBranch();
244
+ ensureBranch(targetBranch, baseBranch);
245
+ checkout(targetBranch);
246
+ checkout(ticketBranch, true);
247
+ // 10. Transition to In Progress (best-effort)
248
+ const statusInProgress = config.env.CLANCY_STATUS_IN_PROGRESS;
249
+ if (statusInProgress) {
250
+ await transitionToStatus(config, ticket, statusInProgress);
251
+ }
252
+ // 11. Build prompt and invoke Claude
253
+ const prompt = buildPrompt({
254
+ provider: config.provider,
255
+ key: ticket.key,
256
+ title: ticket.title,
257
+ description: ticket.description,
258
+ parentInfo: ticket.parentInfo,
259
+ blockers: config.provider !== 'github' ? ticket.blockers : undefined,
260
+ });
261
+ const claudeOk = invokeClaudeSession(prompt, config.env.CLANCY_MODEL);
262
+ if (!claudeOk) {
263
+ console.log(yellow('⚠ Claude session exited with an error. Skipping merge.'));
264
+ return;
265
+ }
266
+ // 12. Squash merge
267
+ checkout(targetBranch);
268
+ const commitMsg = `feat(${ticket.key}): ${ticket.title}`;
269
+ const hadChanges = squashMerge(ticketBranch, commitMsg);
270
+ if (!hadChanges) {
271
+ console.log(yellow('⚠ No changes staged after squash merge. Claude may not have committed any work.'));
272
+ }
273
+ // 13. Delete feature branch
274
+ deleteBranch(ticketBranch);
275
+ // 14. Transition to Done / close issue (best-effort)
276
+ const statusDone = config.env.CLANCY_STATUS_DONE;
277
+ if (config.provider === 'github') {
278
+ const issueNumber = parseInt(ticket.key.replace('#', ''), 10);
279
+ if (Number.isNaN(issueNumber)) {
280
+ console.log(`⚠ Could not parse issue number from ${ticket.key}. Close it manually on GitHub.`);
281
+ }
282
+ else {
283
+ const closed = await closeIssue(config.env.GITHUB_TOKEN, config.env.GITHUB_REPO, issueNumber);
284
+ if (!closed) {
285
+ console.log(`⚠ Could not close issue ${ticket.key}. Close it manually on GitHub.`);
286
+ }
287
+ }
288
+ }
289
+ else if (statusDone) {
290
+ await transitionToStatus(config, ticket, statusDone);
291
+ }
292
+ // 15. Log progress
293
+ appendProgress(process.cwd(), ticket.key, ticket.title, 'DONE');
294
+ const elapsed = formatDuration(Date.now() - startTime);
295
+ console.log('');
296
+ console.log(green(`🏁 ${ticket.key} complete`) + dim(` (${elapsed})`));
297
+ console.log(dim(' "Bake \'em away, toys."'));
298
+ // 16. Send notification (best-effort)
299
+ const webhook = config.env.CLANCY_NOTIFY_WEBHOOK;
300
+ if (webhook) {
301
+ await sendNotification(webhook, `✓ Clancy completed [${ticket.key}] ${ticket.title}`);
302
+ }
303
+ }
304
+ catch (error) {
305
+ // Unexpected errors — print and exit cleanly (exit 0 for AFK loop compat)
306
+ const msg = error instanceof Error ? error.message : String(error);
307
+ const elapsed = formatDuration(Date.now() - startTime);
308
+ console.error('');
309
+ console.error(red(`❌ Clancy stopped`) + dim(` (${elapsed})`));
310
+ console.error(red(` ${msg}`));
311
+ console.error(dim(' "I\'d rather let Herman go."'));
312
+ // Best-effort: restore the branch the user was on before Clancy started
313
+ if (originalBranch) {
314
+ try {
315
+ checkout(originalBranch);
316
+ }
317
+ catch {
318
+ // Ignore — branch restore is best-effort
319
+ }
320
+ }
321
+ }
322
+ }
323
+ //# sourceMappingURL=once.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"once.js","sourceRoot":"","sources":["../../../src/scripts/once/once.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Branch name computation for ticket workflows.
3
+ *
4
+ * Pure functions that compute feature and target branch names
5
+ * based on the board provider and ticket metadata.
6
+ */
7
+ import type { BoardProvider } from '../../../types/index.js';
8
+ /**
9
+ * Compute the feature branch name for a ticket.
10
+ *
11
+ * - Jira/Linear: `feature/{key-lowercase}` (e.g., `feature/proj-123`)
12
+ * - GitHub: `feature/issue-{number}` (e.g., `feature/issue-42`)
13
+ *
14
+ * @param provider - The board provider.
15
+ * @param key - The ticket key (e.g., `'PROJ-123'`, `'#42'`, `'ENG-123'`).
16
+ * @returns The feature branch name.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * computeTicketBranch('jira', 'PROJ-123'); // 'feature/proj-123'
21
+ * computeTicketBranch('github', '#42'); // 'feature/issue-42'
22
+ * computeTicketBranch('linear', 'ENG-123'); // 'feature/eng-123'
23
+ * ```
24
+ */
25
+ export declare function computeTicketBranch(provider: BoardProvider, key: string): string;
26
+ /**
27
+ * Compute the target branch for merging.
28
+ *
29
+ * If the ticket has a parent (epic/milestone), branches from that parent's
30
+ * branch. Otherwise falls back to the base branch.
31
+ *
32
+ * - Jira: epic key → `epic/{key-lowercase}`
33
+ * - GitHub: milestone → `milestone/{slug}`
34
+ * - Linear: parent identifier → `epic/{id-lowercase}`
35
+ *
36
+ * @param provider - The board provider.
37
+ * @param baseBranch - The default base branch (e.g., `'main'`).
38
+ * @param parent - Optional parent identifier (epic key, milestone title, parent ID).
39
+ * @returns The target branch name.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * computeTargetBranch('jira', 'main', 'PROJ-100'); // 'epic/proj-100'
44
+ * computeTargetBranch('github', 'main', 'Sprint 3'); // 'milestone/sprint-3'
45
+ * computeTargetBranch('linear', 'main', 'ENG-50'); // 'epic/eng-50'
46
+ * computeTargetBranch('jira', 'main'); // 'main'
47
+ * ```
48
+ */
49
+ export declare function computeTargetBranch(provider: BoardProvider, baseBranch: string, parent?: string): string;
50
+ //# sourceMappingURL=branch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch.d.ts","sourceRoot":"","sources":["../../../../src/scripts/shared/branch/branch.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,aAAa,EACvB,GAAG,EAAE,MAAM,GACV,MAAM,CAOR;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,aAAa,EACvB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,MAAM,CAaR"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Compute the feature branch name for a ticket.
3
+ *
4
+ * - Jira/Linear: `feature/{key-lowercase}` (e.g., `feature/proj-123`)
5
+ * - GitHub: `feature/issue-{number}` (e.g., `feature/issue-42`)
6
+ *
7
+ * @param provider - The board provider.
8
+ * @param key - The ticket key (e.g., `'PROJ-123'`, `'#42'`, `'ENG-123'`).
9
+ * @returns The feature branch name.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * computeTicketBranch('jira', 'PROJ-123'); // 'feature/proj-123'
14
+ * computeTicketBranch('github', '#42'); // 'feature/issue-42'
15
+ * computeTicketBranch('linear', 'ENG-123'); // 'feature/eng-123'
16
+ * ```
17
+ */
18
+ export function computeTicketBranch(provider, key) {
19
+ if (provider === 'github') {
20
+ const number = key.replace('#', '');
21
+ return `feature/issue-${number}`;
22
+ }
23
+ return `feature/${key.toLowerCase()}`;
24
+ }
25
+ /**
26
+ * Compute the target branch for merging.
27
+ *
28
+ * If the ticket has a parent (epic/milestone), branches from that parent's
29
+ * branch. Otherwise falls back to the base branch.
30
+ *
31
+ * - Jira: epic key → `epic/{key-lowercase}`
32
+ * - GitHub: milestone → `milestone/{slug}`
33
+ * - Linear: parent identifier → `epic/{id-lowercase}`
34
+ *
35
+ * @param provider - The board provider.
36
+ * @param baseBranch - The default base branch (e.g., `'main'`).
37
+ * @param parent - Optional parent identifier (epic key, milestone title, parent ID).
38
+ * @returns The target branch name.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * computeTargetBranch('jira', 'main', 'PROJ-100'); // 'epic/proj-100'
43
+ * computeTargetBranch('github', 'main', 'Sprint 3'); // 'milestone/sprint-3'
44
+ * computeTargetBranch('linear', 'main', 'ENG-50'); // 'epic/eng-50'
45
+ * computeTargetBranch('jira', 'main'); // 'main'
46
+ * ```
47
+ */
48
+ export function computeTargetBranch(provider, baseBranch, parent) {
49
+ if (!parent)
50
+ return baseBranch;
51
+ if (provider === 'github') {
52
+ const slug = parent
53
+ .toLowerCase()
54
+ .replace(/\s+/g, '-')
55
+ .replace(/[^a-z0-9-]/g, '');
56
+ return `milestone/${slug}`;
57
+ }
58
+ // Jira and Linear both use epic/ prefix
59
+ return `epic/${parent.toLowerCase()}`;
60
+ }
61
+ //# sourceMappingURL=branch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"branch.js","sourceRoot":"","sources":["../../../../src/scripts/shared/branch/branch.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAuB,EACvB,GAAW;IAEX,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACpC,OAAO,iBAAiB,MAAM,EAAE,CAAC;IACnC,CAAC;IAED,OAAO,WAAW,GAAG,CAAC,WAAW,EAAE,EAAE,CAAC;AACxC,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,UAAU,mBAAmB,CACjC,QAAuB,EACvB,UAAkB,EAClB,MAAe;IAEf,IAAI,CAAC,MAAM;QAAE,OAAO,UAAU,CAAC;IAE/B,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,MAAM;aAChB,WAAW,EAAE;aACb,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;aACpB,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;QAC9B,OAAO,aAAa,IAAI,EAAE,CAAC;IAC7B,CAAC;IAED,wCAAwC;IACxC,OAAO,QAAQ,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;AACxC,CAAC"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Invoke a Claude Code session with the given prompt.
3
+ *
4
+ * Pipes the prompt to stdin and streams stdout/stderr live.
5
+ * Uses `--dangerously-skip-permissions` for autonomous operation.
6
+ *
7
+ * @param prompt - The full implementation prompt.
8
+ * @param model - Optional model override (e.g., `'opus'`, `'sonnet'`).
9
+ * @returns `true` if Claude exited successfully (code 0), `false` otherwise.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * invokeClaudeSession('You are implementing PROJ-123...', 'opus');
14
+ * ```
15
+ */
16
+ export declare function invokeClaudeSession(prompt: string, model?: string): boolean;
17
+ //# sourceMappingURL=claude-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-cli.d.ts","sourceRoot":"","sources":["../../../../src/scripts/shared/claude-cli/claude-cli.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAc3E"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Claude CLI invocation for ticket implementation.
3
+ *
4
+ * Spawns `claude --dangerously-skip-permissions` with the prompt piped
5
+ * to stdin. Output streams live to the user's terminal.
6
+ */
7
+ import { spawnSync } from 'node:child_process';
8
+ /**
9
+ * Invoke a Claude Code session with the given prompt.
10
+ *
11
+ * Pipes the prompt to stdin and streams stdout/stderr live.
12
+ * Uses `--dangerously-skip-permissions` for autonomous operation.
13
+ *
14
+ * @param prompt - The full implementation prompt.
15
+ * @param model - Optional model override (e.g., `'opus'`, `'sonnet'`).
16
+ * @returns `true` if Claude exited successfully (code 0), `false` otherwise.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * invokeClaudeSession('You are implementing PROJ-123...', 'opus');
21
+ * ```
22
+ */
23
+ export function invokeClaudeSession(prompt, model) {
24
+ const args = ['--dangerously-skip-permissions'];
25
+ if (model) {
26
+ args.push('--model', model);
27
+ }
28
+ const result = spawnSync('claude', args, {
29
+ input: prompt,
30
+ stdio: ['pipe', 'inherit', 'inherit'],
31
+ encoding: 'utf8',
32
+ });
33
+ return result.status === 0 && !result.error;
34
+ }
35
+ //# sourceMappingURL=claude-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"claude-cli.js","sourceRoot":"","sources":["../../../../src/scripts/shared/claude-cli/claude-cli.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAE/C;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,mBAAmB,CAAC,MAAc,EAAE,KAAc;IAChE,MAAM,IAAI,GAAG,CAAC,gCAAgC,CAAC,CAAC;IAEhD,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAC9B,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE;QACvC,KAAK,EAAE,MAAM;QACb,KAAK,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,CAAC;QACrC,QAAQ,EAAE,MAAM;KACjB,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;AAC9C,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Parse a .env file content string into a key-value record.
3
+ *
4
+ * Handles single-quoted, double-quoted, and unquoted values.
5
+ * Ignores blank lines and lines starting with `#`.
6
+ *
7
+ * @param content - The raw .env file content.
8
+ * @returns A record of environment variable key-value pairs.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * parseEnvContent('JIRA_BASE_URL=https://example.atlassian.net\nJIRA_USER=user@example.com');
13
+ * // { JIRA_BASE_URL: 'https://example.atlassian.net', JIRA_USER: 'user@example.com' }
14
+ * ```
15
+ */
16
+ export declare function parseEnvContent(content: string): Record<string, string>;
17
+ /**
18
+ * Load environment variables from a `.clancy/.env` file.
19
+ *
20
+ * @param projectRoot - The root directory of the project containing `.clancy/`.
21
+ * @returns The parsed environment variables, or `undefined` if the file doesn't exist.
22
+ *
23
+ * @example
24
+ * ```ts
25
+ * const env = loadClancyEnv('/path/to/project');
26
+ * // env?.JIRA_BASE_URL === 'https://example.atlassian.net'
27
+ * ```
28
+ */
29
+ export declare function loadClancyEnv(projectRoot: string): Record<string, string> | undefined;
30
+ //# sourceMappingURL=env-parser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-parser.d.ts","sourceRoot":"","sources":["../../../../src/scripts/shared/env-parser/env-parser.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4BvE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,GAClB,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,SAAS,CAQpC"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Clancy .env file parser.
3
+ *
4
+ * Reads key=value pairs from `.clancy/.env` files. Supports quoted values,
5
+ * comments, and blank lines. Does NOT use dotenv — zero dependencies.
6
+ */
7
+ import { existsSync, readFileSync } from 'node:fs';
8
+ import { join } from 'node:path';
9
+ /**
10
+ * Parse a .env file content string into a key-value record.
11
+ *
12
+ * Handles single-quoted, double-quoted, and unquoted values.
13
+ * Ignores blank lines and lines starting with `#`.
14
+ *
15
+ * @param content - The raw .env file content.
16
+ * @returns A record of environment variable key-value pairs.
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * parseEnvContent('JIRA_BASE_URL=https://example.atlassian.net\nJIRA_USER=user@example.com');
21
+ * // { JIRA_BASE_URL: 'https://example.atlassian.net', JIRA_USER: 'user@example.com' }
22
+ * ```
23
+ */
24
+ export function parseEnvContent(content) {
25
+ const env = {};
26
+ for (const line of content.split('\n')) {
27
+ const trimmed = line.trim();
28
+ if (!trimmed || trimmed.startsWith('#'))
29
+ continue;
30
+ const eqIndex = trimmed.indexOf('=');
31
+ if (eqIndex === -1)
32
+ continue;
33
+ const key = trimmed.slice(0, eqIndex).trim();
34
+ let value = trimmed.slice(eqIndex + 1).trim();
35
+ // Strip surrounding quotes (minimum 2 chars to avoid stripping a lone quote)
36
+ if (value.length >= 2 &&
37
+ ((value.startsWith('"') && value.endsWith('"')) ||
38
+ (value.startsWith("'") && value.endsWith("'")))) {
39
+ value = value.slice(1, -1);
40
+ }
41
+ env[key] = value;
42
+ }
43
+ return env;
44
+ }
45
+ /**
46
+ * Load environment variables from a `.clancy/.env` file.
47
+ *
48
+ * @param projectRoot - The root directory of the project containing `.clancy/`.
49
+ * @returns The parsed environment variables, or `undefined` if the file doesn't exist.
50
+ *
51
+ * @example
52
+ * ```ts
53
+ * const env = loadClancyEnv('/path/to/project');
54
+ * // env?.JIRA_BASE_URL === 'https://example.atlassian.net'
55
+ * ```
56
+ */
57
+ export function loadClancyEnv(projectRoot) {
58
+ const envPath = join(projectRoot, '.clancy', '.env');
59
+ if (!existsSync(envPath))
60
+ return undefined;
61
+ const content = readFileSync(envPath, 'utf8');
62
+ return parseEnvContent(content);
63
+ }
64
+ //# sourceMappingURL=env-parser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-parser.js","sourceRoot":"","sources":["../../../../src/scripts/shared/env-parser/env-parser.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACnD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,eAAe,CAAC,OAAe;IAC7C,MAAM,GAAG,GAA2B,EAAE,CAAC;IAEvC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAE5B,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,GAAG,CAAC;YAAE,SAAS;QAElD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QAErC,IAAI,OAAO,KAAK,CAAC,CAAC;YAAE,SAAS;QAE7B,MAAM,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;QAC7C,IAAI,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAE9C,6EAA6E;QAC7E,IACE,KAAK,CAAC,MAAM,IAAI,CAAC;YACjB,CAAC,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAC7C,CAAC,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EACjD,CAAC;YACD,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACnB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAC3B,WAAmB;IAEnB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,MAAM,CAAC,CAAC;IAErD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,SAAS,CAAC;IAE3C,MAAM,OAAO,GAAG,YAAY,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAE9C,OAAO,eAAe,CAAC,OAAO,CAAC,CAAC;AAClC,CAAC"}