chief-clancy 0.2.0 → 0.3.1
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.
- package/README.md +13 -24
- package/dist/bundle/clancy-afk.js +101 -0
- package/dist/bundle/clancy-once.js +13902 -0
- package/dist/installer/file-ops/file-ops.d.ts +32 -0
- package/dist/installer/file-ops/file-ops.d.ts.map +1 -0
- package/dist/installer/file-ops/file-ops.js +58 -0
- package/dist/installer/file-ops/file-ops.js.map +1 -0
- package/dist/installer/hook-installer/hook-installer.d.ts +29 -0
- package/dist/installer/hook-installer/hook-installer.d.ts.map +1 -0
- package/dist/installer/hook-installer/hook-installer.js +96 -0
- package/dist/installer/hook-installer/hook-installer.js.map +1 -0
- package/dist/installer/install.d.ts +3 -0
- package/dist/installer/install.d.ts.map +1 -0
- package/dist/installer/install.js +248 -0
- package/dist/installer/install.js.map +1 -0
- package/dist/installer/manifest/manifest.d.ts +41 -0
- package/dist/installer/manifest/manifest.d.ts.map +1 -0
- package/dist/installer/manifest/manifest.js +97 -0
- package/dist/installer/manifest/manifest.js.map +1 -0
- package/dist/installer/prompts/prompts.d.ts +33 -0
- package/dist/installer/prompts/prompts.d.ts.map +1 -0
- package/dist/installer/prompts/prompts.js +55 -0
- package/dist/installer/prompts/prompts.js.map +1 -0
- package/dist/schemas/env.d.ts +75 -0
- package/dist/schemas/env.d.ts.map +1 -0
- package/dist/schemas/env.js +40 -0
- package/dist/schemas/env.js.map +1 -0
- package/dist/schemas/github.d.ts +27 -0
- package/dist/schemas/github.d.ts.map +1 -0
- package/dist/schemas/github.js +17 -0
- package/dist/schemas/github.js.map +1 -0
- package/dist/schemas/index.d.ts +9 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +5 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/jira.d.ts +37 -0
- package/dist/schemas/jira.d.ts.map +1 -0
- package/dist/schemas/jira.js +37 -0
- package/dist/schemas/jira.js.map +1 -0
- package/dist/schemas/linear.d.ts +67 -0
- package/dist/schemas/linear.d.ts.map +1 -0
- package/dist/schemas/linear.js +50 -0
- package/dist/schemas/linear.js.map +1 -0
- package/dist/scripts/afk/afk.d.ts +21 -0
- package/dist/scripts/afk/afk.d.ts.map +1 -0
- package/dist/scripts/afk/afk.js +124 -0
- package/dist/scripts/afk/afk.js.map +1 -0
- package/dist/scripts/board/github/github.d.ts +40 -0
- package/dist/scripts/board/github/github.d.ts.map +1 -0
- package/dist/scripts/board/github/github.js +121 -0
- package/dist/scripts/board/github/github.js.map +1 -0
- package/dist/scripts/board/jira/jira.d.ts +90 -0
- package/dist/scripts/board/jira/jira.d.ts.map +1 -0
- package/dist/scripts/board/jira/jira.js +251 -0
- package/dist/scripts/board/jira/jira.js.map +1 -0
- package/dist/scripts/board/linear/linear.d.ts +85 -0
- package/dist/scripts/board/linear/linear.d.ts.map +1 -0
- package/dist/scripts/board/linear/linear.js +209 -0
- package/dist/scripts/board/linear/linear.js.map +1 -0
- package/dist/scripts/once/once.d.ts +12 -0
- package/dist/scripts/once/once.d.ts.map +1 -0
- package/dist/scripts/once/once.js +330 -0
- package/dist/scripts/once/once.js.map +1 -0
- package/dist/scripts/shared/branch/branch.d.ts +50 -0
- package/dist/scripts/shared/branch/branch.d.ts.map +1 -0
- package/dist/scripts/shared/branch/branch.js +61 -0
- package/dist/scripts/shared/branch/branch.js.map +1 -0
- package/dist/scripts/shared/claude-cli/claude-cli.d.ts +17 -0
- package/dist/scripts/shared/claude-cli/claude-cli.d.ts.map +1 -0
- package/dist/scripts/shared/claude-cli/claude-cli.js +35 -0
- package/dist/scripts/shared/claude-cli/claude-cli.js.map +1 -0
- package/dist/scripts/shared/env-parser/env-parser.d.ts +30 -0
- package/dist/scripts/shared/env-parser/env-parser.d.ts.map +1 -0
- package/dist/scripts/shared/env-parser/env-parser.js +64 -0
- package/dist/scripts/shared/env-parser/env-parser.js.map +1 -0
- package/dist/scripts/shared/env-schema/env-schema.d.ts +27 -0
- package/dist/scripts/shared/env-schema/env-schema.d.ts.map +1 -0
- package/dist/scripts/shared/env-schema/env-schema.js +46 -0
- package/dist/scripts/shared/env-schema/env-schema.js.map +1 -0
- package/dist/scripts/shared/git-ops/git-ops.d.ts +52 -0
- package/dist/scripts/shared/git-ops/git-ops.d.ts.map +1 -0
- package/dist/scripts/shared/git-ops/git-ops.js +107 -0
- package/dist/scripts/shared/git-ops/git-ops.js.map +1 -0
- package/dist/scripts/shared/http/http.d.ts +52 -0
- package/dist/scripts/shared/http/http.d.ts.map +1 -0
- package/dist/scripts/shared/http/http.js +74 -0
- package/dist/scripts/shared/http/http.js.map +1 -0
- package/dist/scripts/shared/notify/notify.d.ts +46 -0
- package/dist/scripts/shared/notify/notify.d.ts.map +1 -0
- package/dist/scripts/shared/notify/notify.js +88 -0
- package/dist/scripts/shared/notify/notify.js.map +1 -0
- package/dist/scripts/shared/preflight/preflight.d.ts +40 -0
- package/dist/scripts/shared/preflight/preflight.d.ts.map +1 -0
- package/dist/scripts/shared/preflight/preflight.js +84 -0
- package/dist/scripts/shared/preflight/preflight.js.map +1 -0
- package/dist/scripts/shared/progress/progress.d.ts +25 -0
- package/dist/scripts/shared/progress/progress.d.ts.map +1 -0
- package/dist/scripts/shared/progress/progress.js +46 -0
- package/dist/scripts/shared/progress/progress.js.map +1 -0
- package/dist/scripts/shared/prompt/prompt.d.ts +38 -0
- package/dist/scripts/shared/prompt/prompt.d.ts.map +1 -0
- package/dist/scripts/shared/prompt/prompt.js +77 -0
- package/dist/scripts/shared/prompt/prompt.js.map +1 -0
- package/dist/types/board.d.ts +13 -0
- package/dist/types/board.d.ts.map +1 -0
- package/dist/types/board.js +5 -0
- package/dist/types/board.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/ansi/ansi.d.ts +55 -0
- package/dist/utils/ansi/ansi.d.ts.map +1 -0
- package/dist/utils/ansi/ansi.js +55 -0
- package/dist/utils/ansi/ansi.js.map +1 -0
- package/dist/utils/parse-json/parse-json.d.ts +20 -0
- package/dist/utils/parse-json/parse-json.d.ts.map +1 -0
- package/dist/utils/parse-json/parse-json.js +27 -0
- package/dist/utils/parse-json/parse-json.js.map +1 -0
- package/hooks/clancy-check-update.js +2 -2
- package/hooks/clancy-credential-guard.js +8 -1
- package/package.json +48 -8
- package/registry/boards.json +3 -6
- package/src/templates/CLAUDE.md +1 -1
- package/src/workflows/doctor.md +32 -23
- package/src/workflows/init.md +101 -26
- package/src/workflows/logs.md +13 -6
- package/src/workflows/map-codebase.md +17 -16
- package/src/workflows/once.md +22 -12
- package/src/workflows/review.md +40 -27
- package/src/workflows/run.md +20 -12
- package/src/workflows/scaffold.md +5 -1034
- package/src/workflows/settings.md +9 -6
- package/src/workflows/status.md +17 -8
- package/src/workflows/uninstall.md +11 -6
- package/src/workflows/update.md +20 -13
- package/bin/install.js +0 -362
- package/src/templates/scripts/clancy-afk.sh +0 -111
- package/src/templates/scripts/clancy-once-github.sh +0 -249
- package/src/templates/scripts/clancy-once-linear.sh +0 -320
- package/src/templates/scripts/clancy-once.sh +0 -322
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
/**
|
|
8
|
+
* Ping an API endpoint and map common HTTP error codes to messages.
|
|
9
|
+
*
|
|
10
|
+
* Returns `{ ok: true }` on success, or `{ ok: false, error }` with
|
|
11
|
+
* a human-readable message on failure.
|
|
12
|
+
*
|
|
13
|
+
* @param url - The URL to ping.
|
|
14
|
+
* @param headers - HTTP headers to send.
|
|
15
|
+
* @param statusErrors - Map of HTTP status codes to error messages.
|
|
16
|
+
* @param networkError - Error message for network failures.
|
|
17
|
+
* @returns A ping result with `ok` and optional `error`.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* const result = await pingEndpoint(
|
|
22
|
+
* 'https://api.github.com/repos/owner/repo',
|
|
23
|
+
* { Authorization: 'Bearer tok_xxx' },
|
|
24
|
+
* { 401: '✗ Auth failed', 404: '✗ Not found' },
|
|
25
|
+
* '✗ Could not reach GitHub',
|
|
26
|
+
* );
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export async function pingEndpoint(url, headers, statusErrors, networkError) {
|
|
30
|
+
try {
|
|
31
|
+
const controller = new AbortController();
|
|
32
|
+
const timeout = setTimeout(() => controller.abort(), 10_000);
|
|
33
|
+
const response = await fetch(url, {
|
|
34
|
+
headers,
|
|
35
|
+
signal: controller.signal,
|
|
36
|
+
});
|
|
37
|
+
clearTimeout(timeout);
|
|
38
|
+
if (response.ok)
|
|
39
|
+
return { ok: true };
|
|
40
|
+
const mapped = statusErrors[response.status];
|
|
41
|
+
if (mapped)
|
|
42
|
+
return { ok: false, error: mapped };
|
|
43
|
+
return { ok: false, error: `✗ HTTP ${response.status}` };
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return { ok: false, error: networkError };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Build standard GitHub API request headers.
|
|
51
|
+
*
|
|
52
|
+
* @param token - The GitHub personal access token.
|
|
53
|
+
* @returns Headers object for GitHub REST API requests.
|
|
54
|
+
*/
|
|
55
|
+
export function githubHeaders(token) {
|
|
56
|
+
return {
|
|
57
|
+
Authorization: `Bearer ${token}`,
|
|
58
|
+
Accept: 'application/vnd.github+json',
|
|
59
|
+
'X-GitHub-Api-Version': '2022-11-28',
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Build standard Jira API request headers.
|
|
64
|
+
*
|
|
65
|
+
* @param auth - The Base64-encoded Basic auth string.
|
|
66
|
+
* @returns Headers object for Jira REST API requests.
|
|
67
|
+
*/
|
|
68
|
+
export function jiraHeaders(auth) {
|
|
69
|
+
return {
|
|
70
|
+
Authorization: `Basic ${auth}`,
|
|
71
|
+
Accept: 'application/json',
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../../../src/scripts/shared/http/http.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH;;;;;;;;;;;;;;;;;;;;;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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,88 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
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
|
|
@@ -0,0 +1 @@
|
|
|
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,CAgCjE"}
|
|
@@ -0,0 +1,84 @@
|
|
|
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
|
+
// Warn about uncommitted changes
|
|
77
|
+
let warning;
|
|
78
|
+
if (hasUncommittedChanges()) {
|
|
79
|
+
warning =
|
|
80
|
+
'⚠ Working directory has uncommitted changes — they will be included in the branch';
|
|
81
|
+
}
|
|
82
|
+
return { ok: true, env, warning };
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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,iCAAiC;IACjC,IAAI,OAA2B,CAAC;IAEhC,IAAI,qBAAqB,EAAE,EAAE,CAAC;QAC5B,OAAO;YACL,mFAAmF,CAAC;IACxF,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC;AACpC,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Format a date as `YYYY-MM-DD HH:MM`.
|
|
3
|
+
*
|
|
4
|
+
* @param date - The date to format.
|
|
5
|
+
* @returns The formatted date string.
|
|
6
|
+
*/
|
|
7
|
+
export declare function formatTimestamp(date: Date): string;
|
|
8
|
+
/**
|
|
9
|
+
* Append a progress entry to `.clancy/progress.txt`.
|
|
10
|
+
*
|
|
11
|
+
* Creates the file and parent directories if they don't exist.
|
|
12
|
+
*
|
|
13
|
+
* @param projectRoot - The root directory of the project.
|
|
14
|
+
* @param key - The ticket key (e.g., `'PROJ-123'`, `'#42'`).
|
|
15
|
+
* @param summary - The ticket summary/title.
|
|
16
|
+
* @param status - The completion status (`'DONE'` or `'SKIPPED'`).
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```ts
|
|
20
|
+
* appendProgress('/path/to/project', 'PROJ-123', 'Add login page', 'DONE');
|
|
21
|
+
* // Appends: "2024-01-15 14:30 | PROJ-123 | Add login page | DONE"
|
|
22
|
+
* ```
|
|
23
|
+
*/
|
|
24
|
+
export declare function appendProgress(projectRoot: string, key: string, summary: string, status: 'DONE' | 'SKIPPED'): void;
|
|
25
|
+
//# sourceMappingURL=progress.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.d.ts","sourceRoot":"","sources":["../../../../src/scripts/shared/progress/progress.ts"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAQlD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,MAAM,EACnB,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,MAAM,GAAG,SAAS,GACzB,IAAI,CASN"}
|
|
@@ -0,0 +1,46 @@
|
|
|
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 } 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.getFullYear();
|
|
17
|
+
const mo = String(date.getMonth() + 1).padStart(2, '0');
|
|
18
|
+
const d = String(date.getDate()).padStart(2, '0');
|
|
19
|
+
const h = String(date.getHours()).padStart(2, '0');
|
|
20
|
+
const mi = String(date.getMinutes()).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'`).
|
|
30
|
+
* @param summary - The ticket summary/title.
|
|
31
|
+
* @param status - The completion status (`'DONE'` or `'SKIPPED'`).
|
|
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
|
+
*/
|
|
39
|
+
export function appendProgress(projectRoot, key, summary, status) {
|
|
40
|
+
const filePath = join(projectRoot, '.clancy', 'progress.txt');
|
|
41
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
42
|
+
const timestamp = formatTimestamp(new Date());
|
|
43
|
+
const line = `${timestamp} | ${key} | ${summary} | ${status}\n`;
|
|
44
|
+
appendFileSync(filePath, line, 'utf8');
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=progress.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"progress.js","sourceRoot":"","sources":["../../../../src/scripts/shared/progress/progress.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,IAAU;IACxC,MAAM,CAAC,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC7B,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACxD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACnD,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAEtD,OAAO,GAAG,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;AACtC,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,cAAc,CAC5B,WAAmB,EACnB,GAAW,EACX,OAAe,EACf,MAA0B;IAE1B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,EAAE,cAAc,CAAC,CAAC;IAE9D,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAElD,MAAM,SAAS,GAAG,eAAe,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,GAAG,SAAS,MAAM,GAAG,MAAM,OAAO,MAAM,MAAM,IAAI,CAAC;IAEhE,cAAc,CAAC,QAAQ,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude prompt builder for ticket implementation.
|
|
3
|
+
*
|
|
4
|
+
* Generates the full prompt string piped to `claude --dangerously-skip-permissions`.
|
|
5
|
+
* The prompt structure matches the original shell scripts exactly.
|
|
6
|
+
*/
|
|
7
|
+
import type { BoardProvider } from '../../../types/index.js';
|
|
8
|
+
type PromptInput = {
|
|
9
|
+
provider: BoardProvider;
|
|
10
|
+
key: string;
|
|
11
|
+
title: string;
|
|
12
|
+
description: string;
|
|
13
|
+
/** Epic/milestone/parent info string (e.g., `'PROJ-100'`, `'Sprint 3'`, `'none'`). */
|
|
14
|
+
parentInfo: string;
|
|
15
|
+
/** Blocker info string (e.g., `'Blocked by: PROJ-99, PROJ-98'` or `'None'`). */
|
|
16
|
+
blockers?: string;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Build the full Claude prompt for implementing a ticket.
|
|
20
|
+
*
|
|
21
|
+
* @param input - The ticket data for the prompt.
|
|
22
|
+
* @returns The complete prompt string.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```ts
|
|
26
|
+
* const prompt = buildPrompt({
|
|
27
|
+
* provider: 'jira',
|
|
28
|
+
* key: 'PROJ-123',
|
|
29
|
+
* title: 'Add login page',
|
|
30
|
+
* description: 'Create a login page with email/password fields.',
|
|
31
|
+
* parentInfo: 'PROJ-100',
|
|
32
|
+
* blockers: 'None',
|
|
33
|
+
* });
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildPrompt(input: PromptInput): string;
|
|
37
|
+
export {};
|
|
38
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../../src/scripts/shared/prompt/prompt.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAEtD,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,aAAa,CAAC;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,sFAAsF;IACtF,UAAU,EAAE,MAAM,CAAC;IACnB,gFAAgF;IAChF,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB,CAAC;AA6BF;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAkCtD"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get the board-specific label for the ticket type.
|
|
3
|
+
*
|
|
4
|
+
* @param provider - The board provider.
|
|
5
|
+
* @returns The label used in prompts (e.g., `'Jira ticket'`, `'GitHub Issue'`).
|
|
6
|
+
*/
|
|
7
|
+
function ticketLabel(provider) {
|
|
8
|
+
switch (provider) {
|
|
9
|
+
case 'jira':
|
|
10
|
+
return 'Jira ticket';
|
|
11
|
+
case 'github':
|
|
12
|
+
return 'GitHub Issue';
|
|
13
|
+
case 'linear':
|
|
14
|
+
return 'Linear issue';
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get the board-specific label for the parent grouping.
|
|
19
|
+
*
|
|
20
|
+
* @param provider - The board provider.
|
|
21
|
+
* @returns The label (e.g., `'Epic'`, `'Milestone'`).
|
|
22
|
+
*/
|
|
23
|
+
function parentLabel(provider) {
|
|
24
|
+
return provider === 'github' ? 'Milestone' : 'Epic';
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Build the full Claude prompt for implementing a ticket.
|
|
28
|
+
*
|
|
29
|
+
* @param input - The ticket data for the prompt.
|
|
30
|
+
* @returns The complete prompt string.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ```ts
|
|
34
|
+
* const prompt = buildPrompt({
|
|
35
|
+
* provider: 'jira',
|
|
36
|
+
* key: 'PROJ-123',
|
|
37
|
+
* title: 'Add login page',
|
|
38
|
+
* description: 'Create a login page with email/password fields.',
|
|
39
|
+
* parentInfo: 'PROJ-100',
|
|
40
|
+
* blockers: 'None',
|
|
41
|
+
* });
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export function buildPrompt(input) {
|
|
45
|
+
const label = ticketLabel(input.provider);
|
|
46
|
+
const pLabel = parentLabel(input.provider);
|
|
47
|
+
const blockerLine = input.blockers && input.provider !== 'github'
|
|
48
|
+
? `\nBlockers: ${input.blockers}`
|
|
49
|
+
: '';
|
|
50
|
+
return `You are implementing ${label} ${input.key}.
|
|
51
|
+
|
|
52
|
+
${input.provider === 'github' ? 'Title' : 'Summary'}: ${input.title}
|
|
53
|
+
${pLabel}: ${input.parentInfo}${blockerLine}
|
|
54
|
+
|
|
55
|
+
Description:
|
|
56
|
+
${input.description}
|
|
57
|
+
|
|
58
|
+
Step 0 — Executability check (do this before any git or file operation):
|
|
59
|
+
Read the ${input.provider === 'github' ? 'issue title and description' : 'ticket summary and description'} above. Can this ${input.provider === 'github' ? 'issue' : 'ticket'} be implemented entirely
|
|
60
|
+
as a code change committed to this repo? Consult the 'Executability check' section of
|
|
61
|
+
CLAUDE.md for the full list of skip conditions.
|
|
62
|
+
|
|
63
|
+
If you must SKIP this ${input.provider === 'github' ? 'issue' : 'ticket'}:
|
|
64
|
+
1. Output: ⚠ Skipping [${input.key}]: {one-line reason}
|
|
65
|
+
2. Output: Ticket skipped — update it to be codebase-only work, then re-run.
|
|
66
|
+
3. Append to .clancy/progress.txt: YYYY-MM-DD HH:MM | ${input.key} | {reason} | SKIPPED
|
|
67
|
+
4. Stop — no branches, no file changes, no git operations.
|
|
68
|
+
|
|
69
|
+
If the ${input.provider === 'github' ? 'issue' : 'ticket'} IS implementable, continue:
|
|
70
|
+
1. Read core docs in .clancy/docs/: STACK.md, ARCHITECTURE.md, CONVENTIONS.md, GIT.md, DEFINITION-OF-DONE.md, CONCERNS.md
|
|
71
|
+
Also read if relevant to this ticket: INTEGRATIONS.md (external APIs/services/auth), TESTING.md (tests/specs/coverage), DESIGN-SYSTEM.md (UI/components/styles), ACCESSIBILITY.md (accessibility/ARIA/WCAG)
|
|
72
|
+
2. Follow the conventions in GIT.md exactly
|
|
73
|
+
3. Implement the ${input.provider === 'github' ? 'issue' : 'ticket'} fully
|
|
74
|
+
4. Commit your work following the conventions in GIT.md
|
|
75
|
+
5. When done, confirm you are finished.`;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../../../src/scripts/shared/prompt/prompt.ts"],"names":[],"mappings":"AAmBA;;;;;GAKG;AACH,SAAS,WAAW,CAAC,QAAuB;IAC1C,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,MAAM;YACT,OAAO,aAAa,CAAC;QACvB,KAAK,QAAQ;YACX,OAAO,cAAc,CAAC;QACxB,KAAK,QAAQ;YACX,OAAO,cAAc,CAAC;IAC1B,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,QAAuB;IAC1C,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,MAAM,CAAC;AACtD,CAAC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,WAAW,CAAC,KAAkB;IAC5C,MAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC3C,MAAM,WAAW,GACf,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,QAAQ,KAAK,QAAQ;QAC3C,CAAC,CAAC,eAAe,KAAK,CAAC,QAAQ,EAAE;QACjC,CAAC,CAAC,EAAE,CAAC;IAET,OAAO,wBAAwB,KAAK,IAAI,KAAK,CAAC,GAAG;;EAEjD,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,KAAK,KAAK,CAAC,KAAK;EACjE,MAAM,KAAK,KAAK,CAAC,UAAU,GAAG,WAAW;;;EAGzC,KAAK,CAAC,WAAW;;;WAGR,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,gCAAgC,oBAAoB,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;;;;wBAIrJ,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;yBAC/C,KAAK,CAAC,GAAG;;wDAEsB,KAAK,CAAC,GAAG;;;SAGxD,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;;;;mBAItC,KAAK,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,QAAQ;;wCAE3B,CAAC;AACzC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Board-related types shared across board scripts.
|
|
3
|
+
*/
|
|
4
|
+
/** Supported board providers. */
|
|
5
|
+
export type BoardProvider = 'jira' | 'github' | 'linear';
|
|
6
|
+
/** A normalised ticket from any board provider. */
|
|
7
|
+
export type Ticket = {
|
|
8
|
+
key: string;
|
|
9
|
+
title: string;
|
|
10
|
+
description: string;
|
|
11
|
+
provider: BoardProvider;
|
|
12
|
+
};
|
|
13
|
+
//# sourceMappingURL=board.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/types/board.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,iCAAiC;AACjC,MAAM,MAAM,aAAa,GAAG,MAAM,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEzD,mDAAmD;AACnD,MAAM,MAAM,MAAM,GAAG;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,aAAa,CAAC;CACzB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/types/board.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AACxD,YAAY,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,SAAS,EACT,SAAS,GACV,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ANSI escape code helpers for terminal output.
|
|
3
|
+
*
|
|
4
|
+
* Wraps strings in ANSI sequences for styling in CLI environments.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Dim the given string (reduced intensity).
|
|
8
|
+
*
|
|
9
|
+
* @param s - The string to style.
|
|
10
|
+
* @returns The string wrapped in ANSI dim codes.
|
|
11
|
+
*/
|
|
12
|
+
export declare const dim: (s: string) => string;
|
|
13
|
+
/**
|
|
14
|
+
* Bold the given string.
|
|
15
|
+
*
|
|
16
|
+
* @param s - The string to style.
|
|
17
|
+
* @returns The string wrapped in ANSI bold codes.
|
|
18
|
+
*/
|
|
19
|
+
export declare const bold: (s: string) => string;
|
|
20
|
+
/**
|
|
21
|
+
* Colour the given string blue (bold).
|
|
22
|
+
*
|
|
23
|
+
* @param s - The string to style.
|
|
24
|
+
* @returns The string wrapped in ANSI blue codes.
|
|
25
|
+
*/
|
|
26
|
+
export declare const blue: (s: string) => string;
|
|
27
|
+
/**
|
|
28
|
+
* Colour the given string cyan.
|
|
29
|
+
*
|
|
30
|
+
* @param s - The string to style.
|
|
31
|
+
* @returns The string wrapped in ANSI cyan codes.
|
|
32
|
+
*/
|
|
33
|
+
export declare const cyan: (s: string) => string;
|
|
34
|
+
/**
|
|
35
|
+
* Colour the given string green.
|
|
36
|
+
*
|
|
37
|
+
* @param s - The string to style.
|
|
38
|
+
* @returns The string wrapped in ANSI green codes.
|
|
39
|
+
*/
|
|
40
|
+
export declare const green: (s: string) => string;
|
|
41
|
+
/**
|
|
42
|
+
* Colour the given string red.
|
|
43
|
+
*
|
|
44
|
+
* @param s - The string to style.
|
|
45
|
+
* @returns The string wrapped in ANSI red codes.
|
|
46
|
+
*/
|
|
47
|
+
export declare const red: (s: string) => string;
|
|
48
|
+
/**
|
|
49
|
+
* Colour the given string yellow.
|
|
50
|
+
*
|
|
51
|
+
* @param s - The string to style.
|
|
52
|
+
* @returns The string wrapped in ANSI yellow codes.
|
|
53
|
+
*/
|
|
54
|
+
export declare const yellow: (s: string) => string;
|
|
55
|
+
//# sourceMappingURL=ansi.d.ts.map
|