chief-clancy 0.7.0 → 0.7.2

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 (189) hide show
  1. package/README.md +4 -1
  2. package/dist/bundle/clancy-once.js +50 -50
  3. package/package.json +5 -2
  4. package/src/roles/planner/commands/approve-plan.md +3 -0
  5. package/src/roles/planner/commands/plan.md +1 -0
  6. package/src/roles/planner/workflows/approve-plan.md +3 -1
  7. package/src/roles/planner/workflows/plan.md +5 -5
  8. package/src/roles/strategist/commands/approve-brief.md +1 -0
  9. package/src/roles/strategist/workflows/approve-brief.md +3 -1
  10. package/src/roles/strategist/workflows/brief.md +38 -20
  11. package/src/templates/.env.example.github +19 -1
  12. package/src/templates/.env.example.jira +25 -1
  13. package/src/templates/.env.example.linear +19 -1
  14. package/dist/schemas/bitbucket-pr.d.ts +0 -137
  15. package/dist/schemas/bitbucket-pr.d.ts.map +0 -1
  16. package/dist/schemas/bitbucket-pr.js +0 -75
  17. package/dist/schemas/bitbucket-pr.js.map +0 -1
  18. package/dist/schemas/env.d.ts +0 -170
  19. package/dist/schemas/env.d.ts.map +0 -1
  20. package/dist/schemas/env.js +0 -69
  21. package/dist/schemas/env.js.map +0 -1
  22. package/dist/schemas/github-issues.d.ts +0 -105
  23. package/dist/schemas/github-issues.d.ts.map +0 -1
  24. package/dist/schemas/github-issues.js +0 -54
  25. package/dist/schemas/github-issues.js.map +0 -1
  26. package/dist/schemas/gitlab-mr.d.ts +0 -73
  27. package/dist/schemas/gitlab-mr.d.ts.map +0 -1
  28. package/dist/schemas/gitlab-mr.js +0 -33
  29. package/dist/schemas/gitlab-mr.js.map +0 -1
  30. package/dist/schemas/jira.d.ts +0 -59
  31. package/dist/schemas/jira.d.ts.map +0 -1
  32. package/dist/schemas/jira.js +0 -56
  33. package/dist/schemas/jira.js.map +0 -1
  34. package/dist/schemas/linear.d.ts +0 -108
  35. package/dist/schemas/linear.d.ts.map +0 -1
  36. package/dist/schemas/linear.js +0 -84
  37. package/dist/schemas/linear.js.map +0 -1
  38. package/dist/scripts/afk/afk.d.ts +0 -21
  39. package/dist/scripts/afk/afk.d.ts.map +0 -1
  40. package/dist/scripts/afk/afk.js +0 -145
  41. package/dist/scripts/afk/afk.js.map +0 -1
  42. package/dist/scripts/afk/report/report.d.ts +0 -47
  43. package/dist/scripts/afk/report/report.d.ts.map +0 -1
  44. package/dist/scripts/afk/report/report.js +0 -194
  45. package/dist/scripts/afk/report/report.js.map +0 -1
  46. package/dist/scripts/board/github/github.d.ts +0 -104
  47. package/dist/scripts/board/github/github.d.ts.map +0 -1
  48. package/dist/scripts/board/github/github.js +0 -291
  49. package/dist/scripts/board/github/github.js.map +0 -1
  50. package/dist/scripts/board/jira/jira.d.ts +0 -139
  51. package/dist/scripts/board/jira/jira.d.ts.map +0 -1
  52. package/dist/scripts/board/jira/jira.js +0 -378
  53. package/dist/scripts/board/jira/jira.js.map +0 -1
  54. package/dist/scripts/board/linear/linear.d.ts +0 -129
  55. package/dist/scripts/board/linear/linear.d.ts.map +0 -1
  56. package/dist/scripts/board/linear/linear.js +0 -393
  57. package/dist/scripts/board/linear/linear.js.map +0 -1
  58. package/dist/scripts/once/board-ops/board-ops.d.ts +0 -26
  59. package/dist/scripts/once/board-ops/board-ops.d.ts.map +0 -1
  60. package/dist/scripts/once/board-ops/board-ops.js +0 -113
  61. package/dist/scripts/once/board-ops/board-ops.js.map +0 -1
  62. package/dist/scripts/once/cost/cost.d.ts +0 -10
  63. package/dist/scripts/once/cost/cost.d.ts.map +0 -1
  64. package/dist/scripts/once/cost/cost.js +0 -23
  65. package/dist/scripts/once/cost/cost.js.map +0 -1
  66. package/dist/scripts/once/deliver/deliver.d.ts +0 -37
  67. package/dist/scripts/once/deliver/deliver.d.ts.map +0 -1
  68. package/dist/scripts/once/deliver/deliver.js +0 -253
  69. package/dist/scripts/once/deliver/deliver.js.map +0 -1
  70. package/dist/scripts/once/fetch-ticket/fetch-ticket.d.ts +0 -22
  71. package/dist/scripts/once/fetch-ticket/fetch-ticket.d.ts.map +0 -1
  72. package/dist/scripts/once/fetch-ticket/fetch-ticket.js +0 -123
  73. package/dist/scripts/once/fetch-ticket/fetch-ticket.js.map +0 -1
  74. package/dist/scripts/once/git-token/git-token.d.ts +0 -13
  75. package/dist/scripts/once/git-token/git-token.d.ts.map +0 -1
  76. package/dist/scripts/once/git-token/git-token.js +0 -30
  77. package/dist/scripts/once/git-token/git-token.js.map +0 -1
  78. package/dist/scripts/once/lock/lock.d.ts +0 -17
  79. package/dist/scripts/once/lock/lock.d.ts.map +0 -1
  80. package/dist/scripts/once/lock/lock.js +0 -70
  81. package/dist/scripts/once/lock/lock.js.map +0 -1
  82. package/dist/scripts/once/once.d.ts +0 -12
  83. package/dist/scripts/once/once.d.ts.map +0 -1
  84. package/dist/scripts/once/once.js +0 -452
  85. package/dist/scripts/once/once.js.map +0 -1
  86. package/dist/scripts/once/pr-creation/pr-creation.d.ts +0 -11
  87. package/dist/scripts/once/pr-creation/pr-creation.d.ts.map +0 -1
  88. package/dist/scripts/once/pr-creation/pr-creation.js +0 -50
  89. package/dist/scripts/once/pr-creation/pr-creation.js.map +0 -1
  90. package/dist/scripts/once/resume/resume.d.ts +0 -24
  91. package/dist/scripts/once/resume/resume.d.ts.map +0 -1
  92. package/dist/scripts/once/resume/resume.js +0 -159
  93. package/dist/scripts/once/resume/resume.js.map +0 -1
  94. package/dist/scripts/once/rework/rework.d.ts +0 -32
  95. package/dist/scripts/once/rework/rework.d.ts.map +0 -1
  96. package/dist/scripts/once/rework/rework.js +0 -208
  97. package/dist/scripts/once/rework/rework.js.map +0 -1
  98. package/dist/scripts/once/types/types.d.ts +0 -13
  99. package/dist/scripts/once/types/types.d.ts.map +0 -1
  100. package/dist/scripts/once/types/types.js +0 -2
  101. package/dist/scripts/once/types/types.js.map +0 -1
  102. package/dist/scripts/shared/branch/branch.d.ts +0 -50
  103. package/dist/scripts/shared/branch/branch.d.ts.map +0 -1
  104. package/dist/scripts/shared/branch/branch.js +0 -61
  105. package/dist/scripts/shared/branch/branch.js.map +0 -1
  106. package/dist/scripts/shared/claude-cli/claude-cli.d.ts +0 -31
  107. package/dist/scripts/shared/claude-cli/claude-cli.d.ts.map +0 -1
  108. package/dist/scripts/shared/claude-cli/claude-cli.js +0 -60
  109. package/dist/scripts/shared/claude-cli/claude-cli.js.map +0 -1
  110. package/dist/scripts/shared/env-schema/env-schema.d.ts +0 -27
  111. package/dist/scripts/shared/env-schema/env-schema.d.ts.map +0 -1
  112. package/dist/scripts/shared/env-schema/env-schema.js +0 -47
  113. package/dist/scripts/shared/env-schema/env-schema.js.map +0 -1
  114. package/dist/scripts/shared/feasibility/feasibility.d.ts +0 -30
  115. package/dist/scripts/shared/feasibility/feasibility.d.ts.map +0 -1
  116. package/dist/scripts/shared/feasibility/feasibility.js +0 -68
  117. package/dist/scripts/shared/feasibility/feasibility.js.map +0 -1
  118. package/dist/scripts/shared/format/format.d.ts +0 -11
  119. package/dist/scripts/shared/format/format.d.ts.map +0 -1
  120. package/dist/scripts/shared/format/format.js +0 -23
  121. package/dist/scripts/shared/format/format.js.map +0 -1
  122. package/dist/scripts/shared/git-ops/git-ops.d.ts +0 -90
  123. package/dist/scripts/shared/git-ops/git-ops.d.ts.map +0 -1
  124. package/dist/scripts/shared/git-ops/git-ops.js +0 -190
  125. package/dist/scripts/shared/git-ops/git-ops.js.map +0 -1
  126. package/dist/scripts/shared/http/http.d.ts +0 -54
  127. package/dist/scripts/shared/http/http.d.ts.map +0 -1
  128. package/dist/scripts/shared/http/http.js +0 -76
  129. package/dist/scripts/shared/http/http.js.map +0 -1
  130. package/dist/scripts/shared/notify/notify.d.ts +0 -46
  131. package/dist/scripts/shared/notify/notify.d.ts.map +0 -1
  132. package/dist/scripts/shared/notify/notify.js +0 -88
  133. package/dist/scripts/shared/notify/notify.js.map +0 -1
  134. package/dist/scripts/shared/preflight/preflight.d.ts +0 -40
  135. package/dist/scripts/shared/preflight/preflight.d.ts.map +0 -1
  136. package/dist/scripts/shared/preflight/preflight.js +0 -96
  137. package/dist/scripts/shared/preflight/preflight.js.map +0 -1
  138. package/dist/scripts/shared/progress/progress.d.ts +0 -88
  139. package/dist/scripts/shared/progress/progress.d.ts.map +0 -1
  140. package/dist/scripts/shared/progress/progress.js +0 -210
  141. package/dist/scripts/shared/progress/progress.js.map +0 -1
  142. package/dist/scripts/shared/prompt/prompt.d.ts +0 -58
  143. package/dist/scripts/shared/prompt/prompt.d.ts.map +0 -1
  144. package/dist/scripts/shared/prompt/prompt.js +0 -123
  145. package/dist/scripts/shared/prompt/prompt.js.map +0 -1
  146. package/dist/scripts/shared/pull-request/bitbucket/bitbucket.d.ts +0 -82
  147. package/dist/scripts/shared/pull-request/bitbucket/bitbucket.d.ts.map +0 -1
  148. package/dist/scripts/shared/pull-request/bitbucket/bitbucket.js +0 -301
  149. package/dist/scripts/shared/pull-request/bitbucket/bitbucket.js.map +0 -1
  150. package/dist/scripts/shared/pull-request/github/github.d.ts +0 -72
  151. package/dist/scripts/shared/pull-request/github/github.d.ts.map +0 -1
  152. package/dist/scripts/shared/pull-request/github/github.js +0 -226
  153. package/dist/scripts/shared/pull-request/github/github.js.map +0 -1
  154. package/dist/scripts/shared/pull-request/gitlab/gitlab.d.ts +0 -74
  155. package/dist/scripts/shared/pull-request/gitlab/gitlab.d.ts.map +0 -1
  156. package/dist/scripts/shared/pull-request/gitlab/gitlab.js +0 -220
  157. package/dist/scripts/shared/pull-request/gitlab/gitlab.js.map +0 -1
  158. package/dist/scripts/shared/pull-request/post-pr/post-pr.d.ts +0 -31
  159. package/dist/scripts/shared/pull-request/post-pr/post-pr.d.ts.map +0 -1
  160. package/dist/scripts/shared/pull-request/post-pr/post-pr.js +0 -61
  161. package/dist/scripts/shared/pull-request/post-pr/post-pr.js.map +0 -1
  162. package/dist/scripts/shared/pull-request/pr-body/pr-body.d.ts +0 -41
  163. package/dist/scripts/shared/pull-request/pr-body/pr-body.d.ts.map +0 -1
  164. package/dist/scripts/shared/pull-request/pr-body/pr-body.js +0 -93
  165. package/dist/scripts/shared/pull-request/pr-body/pr-body.js.map +0 -1
  166. package/dist/scripts/shared/pull-request/rework-comment/rework-comment.d.ts +0 -23
  167. package/dist/scripts/shared/pull-request/rework-comment/rework-comment.d.ts.map +0 -1
  168. package/dist/scripts/shared/pull-request/rework-comment/rework-comment.js +0 -30
  169. package/dist/scripts/shared/pull-request/rework-comment/rework-comment.js.map +0 -1
  170. package/dist/scripts/shared/remote/remote.d.ts +0 -41
  171. package/dist/scripts/shared/remote/remote.d.ts.map +0 -1
  172. package/dist/scripts/shared/remote/remote.js +0 -227
  173. package/dist/scripts/shared/remote/remote.js.map +0 -1
  174. package/dist/types/board.d.ts +0 -13
  175. package/dist/types/board.d.ts.map +0 -1
  176. package/dist/types/board.js +0 -5
  177. package/dist/types/board.js.map +0 -1
  178. package/dist/types/index.d.ts +0 -4
  179. package/dist/types/index.d.ts.map +0 -1
  180. package/dist/types/index.js +0 -2
  181. package/dist/types/index.js.map +0 -1
  182. package/dist/types/remote.d.ts +0 -55
  183. package/dist/types/remote.d.ts.map +0 -1
  184. package/dist/types/remote.js +0 -5
  185. package/dist/types/remote.js.map +0 -1
  186. package/dist/utils/parse-json/parse-json.d.ts +0 -20
  187. package/dist/utils/parse-json/parse-json.d.ts.map +0 -1
  188. package/dist/utils/parse-json/parse-json.js +0 -27
  189. package/dist/utils/parse-json/parse-json.js.map +0 -1
@@ -1,76 +0,0 @@
1
- /**
2
- * Shared HTTP helpers for board scripts.
3
- *
4
- * Provides a generic ping function and header builders to reduce
5
- * boilerplate across Jira, GitHub, and Linear integrations.
6
- */
7
- /** Default GitHub API base URL. */
8
- export const GITHUB_API = 'https://api.github.com';
9
- /**
10
- * Ping an API endpoint and map common HTTP error codes to messages.
11
- *
12
- * Returns `{ ok: true }` on success, or `{ ok: false, error }` with
13
- * a human-readable message on failure.
14
- *
15
- * @param url - The URL to ping.
16
- * @param headers - HTTP headers to send.
17
- * @param statusErrors - Map of HTTP status codes to error messages.
18
- * @param networkError - Error message for network failures.
19
- * @returns A ping result with `ok` and optional `error`.
20
- *
21
- * @example
22
- * ```ts
23
- * const result = await pingEndpoint(
24
- * 'https://api.github.com/repos/owner/repo',
25
- * { Authorization: 'Bearer tok_xxx' },
26
- * { 401: '✗ Auth failed', 404: '✗ Not found' },
27
- * '✗ Could not reach GitHub',
28
- * );
29
- * ```
30
- */
31
- export async function pingEndpoint(url, headers, statusErrors, networkError) {
32
- try {
33
- const controller = new AbortController();
34
- const timeout = setTimeout(() => controller.abort(), 10_000);
35
- const response = await fetch(url, {
36
- headers,
37
- signal: controller.signal,
38
- });
39
- clearTimeout(timeout);
40
- if (response.ok)
41
- return { ok: true };
42
- const mapped = statusErrors[response.status];
43
- if (mapped)
44
- return { ok: false, error: mapped };
45
- return { ok: false, error: `✗ HTTP ${response.status}` };
46
- }
47
- catch {
48
- return { ok: false, error: networkError };
49
- }
50
- }
51
- /**
52
- * Build standard GitHub API request headers.
53
- *
54
- * @param token - The GitHub personal access token.
55
- * @returns Headers object for GitHub REST API requests.
56
- */
57
- export function githubHeaders(token) {
58
- return {
59
- Authorization: `Bearer ${token}`,
60
- Accept: 'application/vnd.github+json',
61
- 'X-GitHub-Api-Version': '2022-11-28',
62
- };
63
- }
64
- /**
65
- * Build standard Jira API request headers.
66
- *
67
- * @param auth - The Base64-encoded Basic auth string.
68
- * @returns Headers object for Jira REST API requests.
69
- */
70
- export function jiraHeaders(auth) {
71
- return {
72
- Authorization: `Basic ${auth}`,
73
- Accept: 'application/json',
74
- };
75
- }
76
- //# sourceMappingURL=http.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../../src/scripts/shared/http/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,mCAAmC;AACnC,MAAM,CAAC,MAAM,UAAU,GAAG,wBAAwB,CAAC;AAQnD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,GAAW,EACX,OAA+B,EAC/B,YAA4B,EAC5B,YAAoB;IAEpB,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,MAAM,CAAC,CAAC;QAE7D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,OAAO;YACP,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B,CAAC,CAAC;QAEH,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,QAAQ,CAAC,EAAE;YAAE,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;QAErC,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QAC7C,IAAI,MAAM;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAEhD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,UAAU,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;IAC3D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,YAAY,EAAE,CAAC;IAC5C,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,OAAO;QACL,aAAa,EAAE,UAAU,KAAK,EAAE;QAChC,MAAM,EAAE,6BAA6B;QACrC,sBAAsB,EAAE,YAAY;KACrC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,OAAO;QACL,aAAa,EAAE,SAAS,IAAI,EAAE;QAC9B,MAAM,EAAE,kBAAkB;KAC3B,CAAC;AACJ,CAAC"}
@@ -1,46 +0,0 @@
1
- /**
2
- * Webhook notification sender for Slack and Microsoft Teams.
3
- *
4
- * Sends completion notifications after a ticket is processed.
5
- * Best-effort — never throws on failure.
6
- */
7
- /**
8
- * Detect whether a webhook URL is for Slack (vs Teams/other).
9
- *
10
- * @param url - The webhook URL to check.
11
- * @returns `true` if the URL contains `hooks.slack.com`.
12
- */
13
- export declare function isSlackWebhook(url: string): boolean;
14
- /**
15
- * Build a Slack webhook payload.
16
- *
17
- * @param message - The notification message text.
18
- * @returns The JSON payload string for a Slack incoming webhook.
19
- */
20
- export declare function buildSlackPayload(message: string): string;
21
- /**
22
- * Build a Microsoft Teams webhook payload using an adaptive card.
23
- *
24
- * @param message - The notification message text.
25
- * @returns The JSON payload string for a Teams incoming webhook.
26
- */
27
- export declare function buildTeamsPayload(message: string): string;
28
- /**
29
- * Send a notification to a webhook URL.
30
- *
31
- * Automatically detects Slack vs Teams format based on the URL.
32
- * Best-effort — logs a warning on failure but never throws.
33
- *
34
- * @param webhookUrl - The Slack or Teams webhook URL.
35
- * @param message - The notification message to send.
36
- *
37
- * @example
38
- * ```ts
39
- * await sendNotification(
40
- * 'https://hooks.slack.com/services/xxx/yyy/zzz',
41
- * '✓ Clancy completed [PROJ-123] Add login page',
42
- * );
43
- * ```
44
- */
45
- export declare function sendNotification(webhookUrl: string, message: string): Promise<void>;
46
- //# sourceMappingURL=notify.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notify.d.ts","sourceRoot":"","sources":["../../../../src/scripts/shared/notify/notify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAqBzD;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,gBAAgB,CACpC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAkBf"}
@@ -1,88 +0,0 @@
1
- /**
2
- * Webhook notification sender for Slack and Microsoft Teams.
3
- *
4
- * Sends completion notifications after a ticket is processed.
5
- * Best-effort — never throws on failure.
6
- */
7
- /**
8
- * Detect whether a webhook URL is for Slack (vs Teams/other).
9
- *
10
- * @param url - The webhook URL to check.
11
- * @returns `true` if the URL contains `hooks.slack.com`.
12
- */
13
- export function isSlackWebhook(url) {
14
- return url.includes('hooks.slack.com');
15
- }
16
- /**
17
- * Build a Slack webhook payload.
18
- *
19
- * @param message - The notification message text.
20
- * @returns The JSON payload string for a Slack incoming webhook.
21
- */
22
- export function buildSlackPayload(message) {
23
- return JSON.stringify({ text: message });
24
- }
25
- /**
26
- * Build a Microsoft Teams webhook payload using an adaptive card.
27
- *
28
- * @param message - The notification message text.
29
- * @returns The JSON payload string for a Teams incoming webhook.
30
- */
31
- export function buildTeamsPayload(message) {
32
- return JSON.stringify({
33
- type: 'message',
34
- attachments: [
35
- {
36
- contentType: 'application/vnd.microsoft.card.adaptive',
37
- content: {
38
- $schema: 'http://adaptivecards.io/schemas/adaptive-card.json',
39
- type: 'AdaptiveCard',
40
- version: '1.4',
41
- body: [
42
- {
43
- type: 'TextBlock',
44
- text: message,
45
- wrap: true,
46
- },
47
- ],
48
- },
49
- },
50
- ],
51
- });
52
- }
53
- /**
54
- * Send a notification to a webhook URL.
55
- *
56
- * Automatically detects Slack vs Teams format based on the URL.
57
- * Best-effort — logs a warning on failure but never throws.
58
- *
59
- * @param webhookUrl - The Slack or Teams webhook URL.
60
- * @param message - The notification message to send.
61
- *
62
- * @example
63
- * ```ts
64
- * await sendNotification(
65
- * 'https://hooks.slack.com/services/xxx/yyy/zzz',
66
- * '✓ Clancy completed [PROJ-123] Add login page',
67
- * );
68
- * ```
69
- */
70
- export async function sendNotification(webhookUrl, message) {
71
- const payload = isSlackWebhook(webhookUrl)
72
- ? buildSlackPayload(message)
73
- : buildTeamsPayload(message);
74
- try {
75
- const response = await fetch(webhookUrl, {
76
- method: 'POST',
77
- headers: { 'Content-Type': 'application/json' },
78
- body: payload,
79
- });
80
- if (!response.ok) {
81
- console.warn(`⚠ Notification failed: HTTP ${response.status}`);
82
- }
83
- }
84
- catch {
85
- console.warn('⚠ Notification failed: could not reach webhook');
86
- }
87
- }
88
- //# sourceMappingURL=notify.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"notify.js","sourceRoot":"","sources":["../../../../src/scripts/shared/notify/notify.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,GAAW;IACxC,OAAO,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AACzC,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,OAAO,IAAI,CAAC,SAAS,CAAC;QACpB,IAAI,EAAE,SAAS;QACf,WAAW,EAAE;YACX;gBACE,WAAW,EAAE,yCAAyC;gBACtD,OAAO,EAAE;oBACP,OAAO,EAAE,oDAAoD;oBAC7D,IAAI,EAAE,cAAc;oBACpB,OAAO,EAAE,KAAK;oBACd,IAAI,EAAE;wBACJ;4BACE,IAAI,EAAE,WAAW;4BACjB,IAAI,EAAE,OAAO;4BACb,IAAI,EAAE,IAAI;yBACX;qBACF;iBACF;aACF;SACF;KACF,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,UAAkB,EAClB,OAAe;IAEf,MAAM,OAAO,GAAG,cAAc,CAAC,UAAU,CAAC;QACxC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC;QAC5B,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE/B,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,UAAU,EAAE;YACvC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,OAAO;SACd,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,OAAO,CAAC,IAAI,CAAC,+BAA+B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;QACjE,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,gDAAgD,CAAC,CAAC;IACjE,CAAC;AACH,CAAC"}
@@ -1,40 +0,0 @@
1
- type PreflightResult = {
2
- ok: boolean;
3
- error?: string;
4
- warning?: string;
5
- env?: Record<string, string>;
6
- };
7
- /**
8
- * Check whether a binary is available on the system PATH.
9
- *
10
- * @param name - The binary name to check (e.g., `'git'`, `'curl'`).
11
- * @returns `true` if the binary is found.
12
- */
13
- export declare function binaryExists(name: string): boolean;
14
- /**
15
- * Check whether the current directory is inside a git repository.
16
- *
17
- * @returns `true` if a `.git` directory is found.
18
- */
19
- export declare function isGitRepo(): boolean;
20
- /**
21
- * Run all preflight checks common to every board script.
22
- *
23
- * Checks for required binaries (`claude`, `git`), the `.clancy/.env` file,
24
- * git repository state, and uncommitted changes.
25
- *
26
- * @param projectRoot - The root directory of the project.
27
- * @returns A result object with `ok`, optional `error`/`warning`, and parsed `env`.
28
- *
29
- * @example
30
- * ```ts
31
- * const result = runPreflight('/path/to/project');
32
- * if (!result.ok) {
33
- * console.error(result.error);
34
- * process.exit(0);
35
- * }
36
- * ```
37
- */
38
- export declare function runPreflight(projectRoot: string): PreflightResult;
39
- export {};
40
- //# sourceMappingURL=preflight.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"preflight.d.ts","sourceRoot":"","sources":["../../../../src/scripts/shared/preflight/preflight.ts"],"names":[],"mappings":"AAWA,KAAK,eAAe,GAAG;IACrB,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAOlD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,IAAI,OAAO,CAOnC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,eAAe,CA6CjE"}
@@ -1,96 +0,0 @@
1
- /**
2
- * Preflight checks shared across board scripts.
3
- *
4
- * Validates the environment before running a ticket:
5
- * required binaries, .env file, git repository, and working directory state.
6
- */
7
- import { execFileSync } from 'node:child_process';
8
- import { loadClancyEnv } from '../../../scripts/shared/env-parser/env-parser.js';
9
- import { hasUncommittedChanges } from '../../../scripts/shared/git-ops/git-ops.js';
10
- /**
11
- * Check whether a binary is available on the system PATH.
12
- *
13
- * @param name - The binary name to check (e.g., `'git'`, `'curl'`).
14
- * @returns `true` if the binary is found.
15
- */
16
- export function binaryExists(name) {
17
- try {
18
- execFileSync('which', [name], { stdio: 'ignore' });
19
- return true;
20
- }
21
- catch {
22
- return false;
23
- }
24
- }
25
- /**
26
- * Check whether the current directory is inside a git repository.
27
- *
28
- * @returns `true` if a `.git` directory is found.
29
- */
30
- export function isGitRepo() {
31
- try {
32
- execFileSync('git', ['rev-parse', '--git-dir'], { stdio: 'ignore' });
33
- return true;
34
- }
35
- catch {
36
- return false;
37
- }
38
- }
39
- /**
40
- * Run all preflight checks common to every board script.
41
- *
42
- * Checks for required binaries (`claude`, `git`), the `.clancy/.env` file,
43
- * git repository state, and uncommitted changes.
44
- *
45
- * @param projectRoot - The root directory of the project.
46
- * @returns A result object with `ok`, optional `error`/`warning`, and parsed `env`.
47
- *
48
- * @example
49
- * ```ts
50
- * const result = runPreflight('/path/to/project');
51
- * if (!result.ok) {
52
- * console.error(result.error);
53
- * process.exit(0);
54
- * }
55
- * ```
56
- */
57
- export function runPreflight(projectRoot) {
58
- // Check required binaries
59
- for (const bin of ['claude', 'git']) {
60
- if (!binaryExists(bin)) {
61
- return { ok: false, error: `✗ ${bin} is required but not found` };
62
- }
63
- }
64
- // Check .env file
65
- const env = loadClancyEnv(projectRoot);
66
- if (!env) {
67
- return {
68
- ok: false,
69
- error: '✗ .clancy/.env not found — run /clancy:init first',
70
- };
71
- }
72
- // Check git repo
73
- if (!isGitRepo()) {
74
- return { ok: false, error: '✗ Not inside a git repository' };
75
- }
76
- // Check connectivity to remote (warning-only, never blocks)
77
- let warning;
78
- try {
79
- execFileSync('git', ['ls-remote', 'origin', 'HEAD'], {
80
- encoding: 'utf8',
81
- timeout: 5000,
82
- stdio: ['pipe', 'pipe', 'pipe'],
83
- });
84
- }
85
- catch {
86
- warning =
87
- '⚠ Could not reach origin. PR creation and rework detection may not work.';
88
- }
89
- // Warn about uncommitted changes
90
- if (hasUncommittedChanges()) {
91
- const dirtyWarning = '⚠ Working directory has uncommitted changes — they will be included in the branch';
92
- warning = warning ? `${warning}\n${dirtyWarning}` : dirtyWarning;
93
- }
94
- return { ok: true, env, warning };
95
- }
96
- //# sourceMappingURL=preflight.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../../../src/scripts/shared/preflight/preflight.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,OAAO,EAAE,aAAa,EAAE,MAAM,2CAA2C,CAAC;AAC1E,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAS5E;;;;;GAKG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,IAAI,CAAC;QACH,YAAY,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,SAAS;IACvB,IAAI,CAAC;QACH,YAAY,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrE,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,0BAA0B;IAC1B,KAAK,MAAM,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,4BAA4B,EAAE,CAAC;QACpE,CAAC;IACH,CAAC;IAED,kBAAkB;IAClB,MAAM,GAAG,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAEvC,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO;YACL,EAAE,EAAE,KAAK;YACT,KAAK,EAAE,mDAAmD;SAC3D,CAAC;IACJ,CAAC;IAED,iBAAiB;IACjB,IAAI,CAAC,SAAS,EAAE,EAAE,CAAC;QACjB,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAC;IAC/D,CAAC;IAED,4DAA4D;IAC5D,IAAI,OAA2B,CAAC;IAEhC,IAAI,CAAC;QACH,YAAY,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,MAAM,CAAC,EAAE;YACnD,QAAQ,EAAE,MAAM;YAChB,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;YACL,0EAA0E,CAAC;IAC/E,CAAC;IAED,iCAAiC;IACjC,IAAI,qBAAqB,EAAE,EAAE,CAAC;QAC5B,MAAM,YAAY,GAChB,mFAAmF,CAAC;QACtF,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,KAAK,YAAY,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC;IACnE,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
@@ -1,88 +0,0 @@
1
- import type { ProgressStatus } from '../../../types/index.js';
2
- /** A single parsed entry from the progress log. */
3
- export type ProgressEntry = {
4
- timestamp: string;
5
- key: string;
6
- summary: string;
7
- status: ProgressStatus;
8
- prNumber?: number;
9
- parent?: string;
10
- };
11
- /**
12
- * Format a date as `YYYY-MM-DD HH:MM`.
13
- *
14
- * @param date - The date to format.
15
- * @returns The formatted date string.
16
- */
17
- export declare function formatTimestamp(date: Date): string;
18
- /**
19
- * Append a progress entry to `.clancy/progress.txt`.
20
- *
21
- * Creates the file and parent directories if they don't exist.
22
- *
23
- * @param projectRoot - The root directory of the project.
24
- * @param key - The ticket key (e.g., `'PROJ-123'`, `'#42'`) or brief slug (e.g., `'add-dark-mode'`) for BRIEF/APPROVE_BRIEF statuses.
25
- * @param summary - The ticket summary/title, or detail text for brief entries (e.g., `'4 proposed tickets'`).
26
- * @param status - The completion status.
27
- *
28
- * @example
29
- * ```ts
30
- * appendProgress('/path/to/project', 'PROJ-123', 'Add login page', 'DONE');
31
- * // Appends: "2024-01-15 14:30 | PROJ-123 | Add login page | DONE"
32
- *
33
- * appendProgress('/path/to/project', 'PROJ-101', 'Add login', 'PR_CREATED', 42, 'PROJ-100');
34
- * // Appends: "2024-01-15 14:30 | PROJ-101 | Add login | PR_CREATED | pr:42 | parent:PROJ-100"
35
- *
36
- * appendProgress('/path/to/project', 'add-dark-mode', '4 proposed tickets', 'BRIEF');
37
- * // Appends: "2024-01-15 14:30 | BRIEF | add-dark-mode | 4 proposed tickets"
38
- * ```
39
- */
40
- export declare function appendProgress(projectRoot: string, key: string, summary: string, status: ProgressStatus, prNumber?: number, parent?: string): void;
41
- /**
42
- * Parse a progress file into an array of entries.
43
- *
44
- * Each line is expected to follow the format:
45
- * `YYYY-MM-DD HH:MM | KEY | summary | STATUS [| pr:N] [| parent:KEY]`
46
- *
47
- * The `pr:` and `parent:` suffixes can appear in any order after the status.
48
- * Uses named-prefix matching to identify these fields rather than positional
49
- * indexing, ensuring backward compatibility with entries that lack them.
50
- *
51
- * Lines that don't match the minimum format are silently skipped.
52
- */
53
- export declare function parseProgressFile(projectRoot: string): ProgressEntry[];
54
- /**
55
- * Find the last progress entry for a given ticket key.
56
- *
57
- * @param projectRoot - The root directory of the project.
58
- * @param key - The ticket key to search for (case-insensitive).
59
- * @returns The last matching entry, or `undefined` if not found.
60
- *
61
- * @example
62
- * ```ts
63
- * const entry = findLastEntry('/path/to/project', 'PROJ-123');
64
- * // { timestamp: '2024-01-15 14:30', key: 'PROJ-123', summary: 'Add login', status: 'DONE' }
65
- * ```
66
- */
67
- export declare function findLastEntry(projectRoot: string, key: string): ProgressEntry | undefined;
68
- /**
69
- * Count how many times a ticket has been sent back for rework.
70
- *
71
- * @param projectRoot - The root directory of the project.
72
- * @param key - The ticket key to search for (case-insensitive).
73
- * @returns The number of `REWORK` entries for the given key.
74
- */
75
- export declare function countReworkCycles(projectRoot: string, key: string): number;
76
- /**
77
- * Find all ticket keys whose most recent progress entry has the given status.
78
- *
79
- * Scans progress.txt and returns the latest entry per ticket key,
80
- * filtered to only those with the specified status. This is used to find
81
- * tickets that have open PRs (status PR_CREATED) that may need rework.
82
- *
83
- * @param projectRoot - The project root directory.
84
- * @param status - The status to filter by (e.g. 'PR_CREATED').
85
- * @returns Array of progress entries (latest per key) with the given status.
86
- */
87
- export declare function findEntriesWithStatus(projectRoot: string, status: ProgressStatus): ProgressEntry[];
88
- //# sourceMappingURL=progress.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../../src/scripts/shared/progress/progress.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAEvD,mDAAmD;AACnD,MAAM,MAAM,aAAa,GAAG;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAQlD;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,cAAc,EACtB,QAAQ,CAAC,EAAE,MAAM,EACjB,MAAM,CAAC,EAAE,MAAM,GACd,IAAI,CAoBN;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,aAAa,EAAE,CAoFtE;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,aAAa,CAC3B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,GACV,aAAa,GAAG,SAAS,CAY3B;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAY1E;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,qBAAqB,CACnC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,cAAc,GACrB,aAAa,EAAE,CASjB"}
@@ -1,210 +0,0 @@
1
- /**
2
- * Progress logger for completed tickets.
3
- *
4
- * Appends entries to `.clancy/progress.txt` with a timestamp,
5
- * ticket key, summary, and status.
6
- */
7
- import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
8
- import { dirname, join } from 'node:path';
9
- /**
10
- * Format a date as `YYYY-MM-DD HH:MM`.
11
- *
12
- * @param date - The date to format.
13
- * @returns The formatted date string.
14
- */
15
- export function formatTimestamp(date) {
16
- const y = date.getUTCFullYear();
17
- const mo = String(date.getUTCMonth() + 1).padStart(2, '0');
18
- const d = String(date.getUTCDate()).padStart(2, '0');
19
- const h = String(date.getUTCHours()).padStart(2, '0');
20
- const mi = String(date.getUTCMinutes()).padStart(2, '0');
21
- return `${y}-${mo}-${d} ${h}:${mi}`;
22
- }
23
- /**
24
- * Append a progress entry to `.clancy/progress.txt`.
25
- *
26
- * Creates the file and parent directories if they don't exist.
27
- *
28
- * @param projectRoot - The root directory of the project.
29
- * @param key - The ticket key (e.g., `'PROJ-123'`, `'#42'`) or brief slug (e.g., `'add-dark-mode'`) for BRIEF/APPROVE_BRIEF statuses.
30
- * @param summary - The ticket summary/title, or detail text for brief entries (e.g., `'4 proposed tickets'`).
31
- * @param status - The completion status.
32
- *
33
- * @example
34
- * ```ts
35
- * appendProgress('/path/to/project', 'PROJ-123', 'Add login page', 'DONE');
36
- * // Appends: "2024-01-15 14:30 | PROJ-123 | Add login page | DONE"
37
- *
38
- * appendProgress('/path/to/project', 'PROJ-101', 'Add login', 'PR_CREATED', 42, 'PROJ-100');
39
- * // Appends: "2024-01-15 14:30 | PROJ-101 | Add login | PR_CREATED | pr:42 | parent:PROJ-100"
40
- *
41
- * appendProgress('/path/to/project', 'add-dark-mode', '4 proposed tickets', 'BRIEF');
42
- * // Appends: "2024-01-15 14:30 | BRIEF | add-dark-mode | 4 proposed tickets"
43
- * ```
44
- */
45
- export function appendProgress(projectRoot, key, summary, status, prNumber, parent) {
46
- const filePath = join(projectRoot, '.clancy', 'progress.txt');
47
- mkdirSync(dirname(filePath), { recursive: true });
48
- const timestamp = formatTimestamp(new Date());
49
- // BRIEF/APPROVE_BRIEF use slug-based format: timestamp | STATUS | slug | detail
50
- if (status === 'BRIEF' || status === 'APPROVE_BRIEF') {
51
- const line = `${timestamp} | ${status} | ${key} | ${summary}\n`;
52
- appendFileSync(filePath, line, 'utf8');
53
- return;
54
- }
55
- // Standard format: timestamp | key | summary | STATUS [| pr:N] [| parent:KEY]
56
- const prSuffix = prNumber != null ? ` | pr:${prNumber}` : '';
57
- const parentSuffix = parent ? ` | parent:${parent}` : '';
58
- const line = `${timestamp} | ${key} | ${summary} | ${status}${prSuffix}${parentSuffix}\n`;
59
- appendFileSync(filePath, line, 'utf8');
60
- }
61
- /**
62
- * Parse a progress file into an array of entries.
63
- *
64
- * Each line is expected to follow the format:
65
- * `YYYY-MM-DD HH:MM | KEY | summary | STATUS [| pr:N] [| parent:KEY]`
66
- *
67
- * The `pr:` and `parent:` suffixes can appear in any order after the status.
68
- * Uses named-prefix matching to identify these fields rather than positional
69
- * indexing, ensuring backward compatibility with entries that lack them.
70
- *
71
- * Lines that don't match the minimum format are silently skipped.
72
- */
73
- export function parseProgressFile(projectRoot) {
74
- const filePath = join(projectRoot, '.clancy', 'progress.txt');
75
- let content;
76
- try {
77
- content = readFileSync(filePath, 'utf8');
78
- }
79
- catch {
80
- return [];
81
- }
82
- const entries = [];
83
- for (const line of content.split('\n')) {
84
- const trimmed = line.trim();
85
- if (!trimmed)
86
- continue;
87
- const parts = trimmed.split(' | ');
88
- if (parts.length < 4)
89
- continue;
90
- // Fixed position: timestamp is always first
91
- const timestamp = parts[0];
92
- // BRIEF / APPROVE_BRIEF entries use a slug-based format:
93
- // timestamp | STATUS | slug | detail
94
- // Standard entries use:
95
- // timestamp | key | summary | STATUS [| pr:N] [| parent:KEY]
96
- if (parts[1] === 'BRIEF' || parts[1] === 'APPROVE_BRIEF') {
97
- entries.push({
98
- timestamp,
99
- key: parts[2],
100
- summary: parts.slice(3).join(' | '),
101
- status: parts[1],
102
- });
103
- continue;
104
- }
105
- const key = parts[1];
106
- // Scan remaining segments for named prefixes and status
107
- let status;
108
- let prNumber;
109
- let parent;
110
- const summaryParts = [];
111
- for (let i = 2; i < parts.length; i++) {
112
- const segment = parts[i];
113
- const prMatch = segment.match(/^pr:(\d+)$/);
114
- const parentMatch = segment.match(/^parent:(.+)$/);
115
- if (prMatch) {
116
- prNumber = parseInt(prMatch[1], 10);
117
- }
118
- else if (parentMatch) {
119
- parent = parentMatch[1];
120
- }
121
- else if (i >= 3 &&
122
- !status &&
123
- segment === segment.toUpperCase() &&
124
- segment.length > 1) {
125
- // Status is an ALL_CAPS segment after the summary (position 3+)
126
- status = segment;
127
- }
128
- else {
129
- summaryParts.push(segment);
130
- }
131
- }
132
- if (!status)
133
- continue;
134
- // Backward compat: old progress.txt entries may use 'APPROVE' (renamed to APPROVE_PLAN in v0.6.0)
135
- if (status === 'APPROVE') {
136
- status = 'APPROVE_PLAN';
137
- }
138
- entries.push({
139
- timestamp,
140
- key,
141
- summary: summaryParts.join(' | '),
142
- status,
143
- ...(prNumber != null && { prNumber }),
144
- ...(parent != null && { parent }),
145
- });
146
- }
147
- return entries;
148
- }
149
- /**
150
- * Find the last progress entry for a given ticket key.
151
- *
152
- * @param projectRoot - The root directory of the project.
153
- * @param key - The ticket key to search for (case-insensitive).
154
- * @returns The last matching entry, or `undefined` if not found.
155
- *
156
- * @example
157
- * ```ts
158
- * const entry = findLastEntry('/path/to/project', 'PROJ-123');
159
- * // { timestamp: '2024-01-15 14:30', key: 'PROJ-123', summary: 'Add login', status: 'DONE' }
160
- * ```
161
- */
162
- export function findLastEntry(projectRoot, key) {
163
- const entries = parseProgressFile(projectRoot);
164
- const needle = key.toLowerCase();
165
- let last;
166
- for (const entry of entries) {
167
- if (entry.key.toLowerCase() === needle) {
168
- last = entry;
169
- }
170
- }
171
- return last;
172
- }
173
- /**
174
- * Count how many times a ticket has been sent back for rework.
175
- *
176
- * @param projectRoot - The root directory of the project.
177
- * @param key - The ticket key to search for (case-insensitive).
178
- * @returns The number of `REWORK` entries for the given key.
179
- */
180
- export function countReworkCycles(projectRoot, key) {
181
- const entries = parseProgressFile(projectRoot);
182
- const needle = key.toLowerCase();
183
- let count = 0;
184
- for (const entry of entries) {
185
- if (entry.key.toLowerCase() === needle && entry.status === 'REWORK') {
186
- count++;
187
- }
188
- }
189
- return count;
190
- }
191
- /**
192
- * Find all ticket keys whose most recent progress entry has the given status.
193
- *
194
- * Scans progress.txt and returns the latest entry per ticket key,
195
- * filtered to only those with the specified status. This is used to find
196
- * tickets that have open PRs (status PR_CREATED) that may need rework.
197
- *
198
- * @param projectRoot - The project root directory.
199
- * @param status - The status to filter by (e.g. 'PR_CREATED').
200
- * @returns Array of progress entries (latest per key) with the given status.
201
- */
202
- export function findEntriesWithStatus(projectRoot, status) {
203
- const entries = parseProgressFile(projectRoot);
204
- const latestByKey = new Map();
205
- for (const entry of entries) {
206
- latestByKey.set(entry.key, entry);
207
- }
208
- return [...latestByKey.values()].filter((entry) => entry.status === status);
209
- }
210
- //# sourceMappingURL=progress.js.map