specweave 1.0.235 → 1.0.239
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 +89 -193
- package/dist/plugins/specweave-github/lib/github-ac-comment-poster.d.ts +37 -0
- package/dist/plugins/specweave-github/lib/github-ac-comment-poster.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-ac-comment-poster.js +176 -0
- package/dist/plugins/specweave-github/lib/github-ac-comment-poster.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-batch-sync.d.ts +36 -0
- package/dist/plugins/specweave-github/lib/github-batch-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-batch-sync.js +115 -0
- package/dist/plugins/specweave-github/lib/github-batch-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-board-resolver-v2.d.ts +37 -0
- package/dist/plugins/specweave-github/lib/github-board-resolver-v2.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-board-resolver-v2.js +56 -0
- package/dist/plugins/specweave-github/lib/github-board-resolver-v2.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-conflict-resolver.d.ts +68 -0
- package/dist/plugins/specweave-github/lib/github-conflict-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-conflict-resolver.js +102 -0
- package/dist/plugins/specweave-github/lib/github-conflict-resolver.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-cross-repo-sync.d.ts +64 -0
- package/dist/plugins/specweave-github/lib/github-cross-repo-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-cross-repo-sync.js +162 -0
- package/dist/plugins/specweave-github/lib/github-cross-repo-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-field-sync.d.ts +50 -0
- package/dist/plugins/specweave-github/lib/github-field-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-field-sync.js +107 -0
- package/dist/plugins/specweave-github/lib/github-field-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-graphql-client.d.ts +53 -0
- package/dist/plugins/specweave-github/lib/github-graphql-client.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-graphql-client.js +138 -0
- package/dist/plugins/specweave-github/lib/github-graphql-client.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-issue-body-generator.d.ts +40 -0
- package/dist/plugins/specweave-github/lib/github-issue-body-generator.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-issue-body-generator.js +50 -0
- package/dist/plugins/specweave-github/lib/github-issue-body-generator.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-issue-body-parser.d.ts +30 -0
- package/dist/plugins/specweave-github/lib/github-issue-body-parser.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-issue-body-parser.js +75 -0
- package/dist/plugins/specweave-github/lib/github-issue-body-parser.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-pull-sync.d.ts +94 -0
- package/dist/plugins/specweave-github/lib/github-pull-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-pull-sync.js +232 -0
- package/dist/plugins/specweave-github/lib/github-pull-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-push-sync.d.ts +50 -0
- package/dist/plugins/specweave-github/lib/github-push-sync.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-push-sync.js +114 -0
- package/dist/plugins/specweave-github/lib/github-push-sync.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-rate-limiter.d.ts +53 -0
- package/dist/plugins/specweave-github/lib/github-rate-limiter.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-rate-limiter.js +109 -0
- package/dist/plugins/specweave-github/lib/github-rate-limiter.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.d.ts +21 -0
- package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.js +161 -0
- package/dist/plugins/specweave-github/lib/github-spec-frontmatter-updater.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-sync-orchestrator.d.ts +46 -0
- package/dist/plugins/specweave-github/lib/github-sync-orchestrator.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-sync-orchestrator.js +99 -0
- package/dist/plugins/specweave-github/lib/github-sync-orchestrator.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-us-auto-closer.d.ts +43 -0
- package/dist/plugins/specweave-github/lib/github-us-auto-closer.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-us-auto-closer.js +153 -0
- package/dist/plugins/specweave-github/lib/github-us-auto-closer.js.map +1 -0
- package/dist/plugins/specweave-github/lib/index.d.ts +1 -4
- package/dist/plugins/specweave-github/lib/index.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/index.js +1 -4
- package/dist/plugins/specweave-github/lib/index.js.map +1 -1
- package/dist/plugins/specweave-testing/lib/playwright-ci-defaults.d.ts +7 -0
- package/dist/plugins/specweave-testing/lib/playwright-ci-defaults.d.ts.map +1 -0
- package/dist/plugins/specweave-testing/lib/playwright-ci-defaults.js +15 -0
- package/dist/plugins/specweave-testing/lib/playwright-ci-defaults.js.map +1 -0
- package/dist/plugins/specweave-testing/lib/playwright-cli-detector.d.ts +10 -0
- package/dist/plugins/specweave-testing/lib/playwright-cli-detector.d.ts.map +1 -0
- package/dist/plugins/specweave-testing/lib/playwright-cli-detector.js +36 -0
- package/dist/plugins/specweave-testing/lib/playwright-cli-detector.js.map +1 -0
- package/dist/plugins/specweave-testing/lib/playwright-cli-runner.d.ts +25 -0
- package/dist/plugins/specweave-testing/lib/playwright-cli-runner.d.ts.map +1 -0
- package/dist/plugins/specweave-testing/lib/playwright-cli-runner.js +57 -0
- package/dist/plugins/specweave-testing/lib/playwright-cli-runner.js.map +1 -0
- package/dist/plugins/specweave-testing/lib/playwright-routing.d.ts +7 -0
- package/dist/plugins/specweave-testing/lib/playwright-routing.d.ts.map +1 -0
- package/dist/plugins/specweave-testing/lib/playwright-routing.js +17 -0
- package/dist/plugins/specweave-testing/lib/playwright-routing.js.map +1 -0
- package/dist/src/cli/commands/auto.d.ts.map +1 -1
- package/dist/src/cli/commands/auto.js +1 -2
- package/dist/src/cli/commands/auto.js.map +1 -1
- package/dist/src/cli/commands/cancel-auto.js +1 -2
- package/dist/src/cli/commands/cancel-auto.js.map +1 -1
- package/dist/src/cli/commands/living-docs.js +2 -2
- package/dist/src/cli/commands/living-docs.js.map +1 -1
- package/dist/src/cli/commands/update.d.ts.map +1 -1
- package/dist/src/cli/commands/update.js +1 -2
- package/dist/src/cli/commands/update.js.map +1 -1
- package/dist/src/core/config/types.d.ts +8 -0
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js +3 -0
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/types/sync-profile.d.ts +72 -0
- package/dist/src/core/types/sync-profile.d.ts.map +1 -1
- package/dist/src/core/types/sync-profile.js +6 -0
- package/dist/src/core/types/sync-profile.js.map +1 -1
- package/package.json +2 -2
- package/plugins/specweave/hooks/hooks.json +2 -2
- package/plugins/specweave/hooks/startup-health-check.sh +1 -1
- package/plugins/specweave/hooks/stop-auto-v5.sh +166 -0
- package/plugins/specweave/hooks/user-prompt-submit.sh +10 -0
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +21 -1
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +1 -1
- package/plugins/specweave/skills/auto/SKILL.md +71 -251
- package/plugins/specweave/skills/team-build/SKILL.md +370 -0
- package/plugins/specweave/skills/team-merge/SKILL.md +123 -0
- package/plugins/specweave/skills/team-orchestrate/SKILL.md +800 -0
- package/plugins/specweave/skills/team-status/SKILL.md +89 -0
- package/plugins/specweave-github/MULTI-PROJECT-SYNC-ARCHITECTURE.md +94 -8
- package/plugins/specweave-github/commands/sync.md +17 -3
- package/plugins/specweave-github/hooks/github-ac-sync-handler.sh +255 -0
- package/plugins/specweave-github/hooks/github-auto-create-handler.sh +455 -0
- package/plugins/specweave-github/lib/github-ac-comment-poster.js +150 -0
- package/plugins/specweave-github/lib/github-ac-comment-poster.ts +245 -0
- package/plugins/specweave-github/lib/github-batch-sync.js +93 -0
- package/plugins/specweave-github/lib/github-batch-sync.ts +152 -0
- package/plugins/specweave-github/lib/github-board-resolver-v2.js +47 -0
- package/plugins/specweave-github/lib/github-board-resolver-v2.ts +73 -0
- package/plugins/specweave-github/lib/github-conflict-resolver.js +90 -0
- package/plugins/specweave-github/lib/github-conflict-resolver.ts +154 -0
- package/plugins/specweave-github/lib/github-cross-repo-sync.js +168 -0
- package/plugins/specweave-github/lib/github-cross-repo-sync.ts +252 -0
- package/plugins/specweave-github/lib/github-field-sync.js +116 -0
- package/plugins/specweave-github/lib/github-field-sync.ts +165 -0
- package/plugins/specweave-github/lib/github-graphql-client.js +129 -0
- package/plugins/specweave-github/lib/github-graphql-client.ts +181 -0
- package/plugins/specweave-github/lib/github-issue-body-generator.js +30 -0
- package/plugins/specweave-github/lib/github-issue-body-generator.ts +76 -0
- package/plugins/specweave-github/lib/github-issue-body-parser.js +55 -0
- package/plugins/specweave-github/lib/github-issue-body-parser.ts +92 -0
- package/plugins/specweave-github/lib/github-pull-sync.js +185 -0
- package/plugins/specweave-github/lib/github-pull-sync.ts +343 -0
- package/plugins/specweave-github/lib/github-push-sync.js +119 -0
- package/plugins/specweave-github/lib/github-push-sync.ts +174 -0
- package/plugins/specweave-github/lib/github-rate-limiter.js +96 -0
- package/plugins/specweave-github/lib/github-rate-limiter.ts +143 -0
- package/plugins/specweave-github/lib/github-spec-frontmatter-updater.js +117 -0
- package/plugins/specweave-github/lib/github-spec-frontmatter-updater.ts +180 -0
- package/plugins/specweave-github/lib/github-sync-orchestrator.js +84 -0
- package/plugins/specweave-github/lib/github-sync-orchestrator.ts +156 -0
- package/plugins/specweave-github/lib/github-us-auto-closer.js +134 -0
- package/plugins/specweave-github/lib/github-us-auto-closer.ts +226 -0
- package/plugins/specweave-github/lib/index.js +1 -7
- package/plugins/specweave-github/lib/index.ts +1 -4
- package/plugins/specweave-github/skills/github-sync/SKILL.md +76 -4
- package/plugins/specweave-testing/commands/e2e-setup.md +18 -0
- package/plugins/specweave-testing/commands/ui-automate.md +2 -0
- package/plugins/specweave-testing/commands/ui-inspect.md +8 -0
- package/plugins/specweave-testing/lib/playwright-ci-defaults.d.ts +6 -0
- package/plugins/specweave-testing/lib/playwright-ci-defaults.js +14 -0
- package/plugins/specweave-testing/lib/playwright-ci-defaults.ts +24 -0
- package/plugins/specweave-testing/lib/playwright-cli-detector.js +33 -0
- package/plugins/specweave-testing/lib/playwright-cli-detector.ts +48 -0
- package/plugins/specweave-testing/lib/playwright-cli-runner.js +58 -0
- package/plugins/specweave-testing/lib/playwright-cli-runner.ts +80 -0
- package/plugins/specweave-testing/lib/playwright-routing.js +16 -0
- package/plugins/specweave-testing/lib/playwright-routing.ts +38 -0
- package/plugins/specweave-testing/skills/e2e-testing/SKILL.md +38 -0
- package/src/templates/CLAUDE.md.template +7 -0
- package/src/templates/config.json.template +9 -1
- package/dist/plugins/specweave-github/lib/subtask-sync.d.ts +0 -51
- package/dist/plugins/specweave-github/lib/subtask-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/subtask-sync.js +0 -147
- package/dist/plugins/specweave-github/lib/subtask-sync.js.map +0 -1
- package/dist/plugins/specweave-github/lib/task-parser.d.ts +0 -37
- package/dist/plugins/specweave-github/lib/task-parser.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/task-parser.js +0 -211
- package/dist/plugins/specweave-github/lib/task-parser.js.map +0 -1
- package/dist/plugins/specweave-github/lib/task-sync.d.ts +0 -56
- package/dist/plugins/specweave-github/lib/task-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/task-sync.js +0 -375
- package/dist/plugins/specweave-github/lib/task-sync.js.map +0 -1
- package/plugins/specweave/hooks/validate-completion-conditions.sh +0 -474
- package/plugins/specweave-github/lib/subtask-sync.d.ts +0 -51
- package/plugins/specweave-github/lib/subtask-sync.d.ts.map +0 -1
- package/plugins/specweave-github/lib/subtask-sync.js +0 -154
- package/plugins/specweave-github/lib/subtask-sync.js.map +0 -1
- package/plugins/specweave-github/lib/subtask-sync.ts +0 -225
- package/plugins/specweave-github/lib/task-parser.d.js +0 -0
- package/plugins/specweave-github/lib/task-parser.d.ts +0 -37
- package/plugins/specweave-github/lib/task-parser.d.ts.map +0 -1
- package/plugins/specweave-github/lib/task-parser.js +0 -195
- package/plugins/specweave-github/lib/task-parser.js.map +0 -1
- package/plugins/specweave-github/lib/task-parser.ts +0 -246
- package/plugins/specweave-github/lib/task-sync.d.js +0 -0
- package/plugins/specweave-github/lib/task-sync.d.ts +0 -51
- package/plugins/specweave-github/lib/task-sync.d.ts.map +0 -1
- package/plugins/specweave-github/lib/task-sync.js +0 -415
- package/plugins/specweave-github/lib/task-sync.js.map +0 -1
- package/plugins/specweave-github/lib/task-sync.ts +0 -451
- package/plugins/specweave-github/skills/github-issue-tracker/SKILL.md +0 -496
- /package/plugins/specweave/hooks/{stop-auto.sh → _archive/stop-auto-v4-legacy.sh} +0 -0
- /package/plugins/{specweave-github/lib/subtask-sync.d.js → specweave-testing/lib/playwright-ci-defaults.d.js} +0 -0
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Field Sync — Status and Priority field sync for Projects V2
|
|
3
|
+
*
|
|
4
|
+
* Syncs Status and Priority custom fields on Projects V2 items
|
|
5
|
+
* using configurable field mappings.
|
|
6
|
+
*
|
|
7
|
+
* @module github-field-sync
|
|
8
|
+
*/
|
|
9
|
+
import type { GitHubGraphQLClient } from './github-graphql-client.js';
|
|
10
|
+
export interface FieldSyncConfig {
|
|
11
|
+
projectId: string;
|
|
12
|
+
statusFieldMapping?: Record<string, string>;
|
|
13
|
+
priorityFieldMapping?: Record<string, string>;
|
|
14
|
+
}
|
|
15
|
+
export interface FieldSyncItem {
|
|
16
|
+
itemId: string;
|
|
17
|
+
status?: string;
|
|
18
|
+
priority?: string;
|
|
19
|
+
}
|
|
20
|
+
export interface FieldSyncResult {
|
|
21
|
+
updated: Array<{
|
|
22
|
+
itemId: string;
|
|
23
|
+
field: string;
|
|
24
|
+
value: string;
|
|
25
|
+
}>;
|
|
26
|
+
warnings: Array<{
|
|
27
|
+
itemId: string;
|
|
28
|
+
field: string;
|
|
29
|
+
message: string;
|
|
30
|
+
}>;
|
|
31
|
+
}
|
|
32
|
+
export declare class GitHubFieldSync {
|
|
33
|
+
private client;
|
|
34
|
+
private config;
|
|
35
|
+
private statusField?;
|
|
36
|
+
private priorityField?;
|
|
37
|
+
private fieldsLoaded;
|
|
38
|
+
constructor(client: GitHubGraphQLClient, config: FieldSyncConfig);
|
|
39
|
+
/**
|
|
40
|
+
* Load project fields and cache field IDs and option IDs.
|
|
41
|
+
*/
|
|
42
|
+
loadFields(): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Sync fields for one or more items.
|
|
45
|
+
* Auto-calls loadFields if not called yet.
|
|
46
|
+
*/
|
|
47
|
+
syncItemFields(items: FieldSyncItem[]): Promise<FieldSyncResult>;
|
|
48
|
+
private syncField;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=github-field-sync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-field-sync.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-field-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAEtE,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC5C,oBAAoB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/C;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACjE,QAAQ,EAAE,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACrE;AAqBD,qBAAa,eAAe;IAC1B,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAAkB;IAChC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,aAAa,CAAC,CAAc;IACpC,OAAO,CAAC,YAAY,CAAS;gBAEjB,MAAM,EAAE,mBAAmB,EAAE,MAAM,EAAE,eAAe;IAKhE;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAwBjC;;;OAGG;IACG,cAAc,CAAC,KAAK,EAAE,aAAa,EAAE,GAAG,OAAO,CAAC,eAAe,CAAC;YAwBxD,SAAS;CAkDxB"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Field Sync — Status and Priority field sync for Projects V2
|
|
3
|
+
*
|
|
4
|
+
* Syncs Status and Priority custom fields on Projects V2 items
|
|
5
|
+
* using configurable field mappings.
|
|
6
|
+
*
|
|
7
|
+
* @module github-field-sync
|
|
8
|
+
*/
|
|
9
|
+
const DEFAULT_STATUS_MAPPING = {
|
|
10
|
+
'planned': 'Todo',
|
|
11
|
+
'in-progress': 'In Progress',
|
|
12
|
+
'completed': 'Done',
|
|
13
|
+
};
|
|
14
|
+
const DEFAULT_PRIORITY_MAPPING = {
|
|
15
|
+
'P1': 'Urgent',
|
|
16
|
+
'P2': 'High',
|
|
17
|
+
'P3': 'Medium',
|
|
18
|
+
'P4': 'Low',
|
|
19
|
+
};
|
|
20
|
+
export class GitHubFieldSync {
|
|
21
|
+
constructor(client, config) {
|
|
22
|
+
this.fieldsLoaded = false;
|
|
23
|
+
this.client = client;
|
|
24
|
+
this.config = config;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Load project fields and cache field IDs and option IDs.
|
|
28
|
+
*/
|
|
29
|
+
async loadFields() {
|
|
30
|
+
if (this.fieldsLoaded)
|
|
31
|
+
return;
|
|
32
|
+
const fields = await this.client.getProjectFields(this.config.projectId);
|
|
33
|
+
for (const field of fields) {
|
|
34
|
+
if (field.name === 'Status' && field.options) {
|
|
35
|
+
this.statusField = {
|
|
36
|
+
id: field.id,
|
|
37
|
+
name: field.name,
|
|
38
|
+
options: new Map(field.options.map(o => [o.name, o.id])),
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
else if (field.name === 'Priority' && field.options) {
|
|
42
|
+
this.priorityField = {
|
|
43
|
+
id: field.id,
|
|
44
|
+
name: field.name,
|
|
45
|
+
options: new Map(field.options.map(o => [o.name, o.id])),
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
this.fieldsLoaded = true;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Sync fields for one or more items.
|
|
53
|
+
* Auto-calls loadFields if not called yet.
|
|
54
|
+
*/
|
|
55
|
+
async syncItemFields(items) {
|
|
56
|
+
if (!this.fieldsLoaded) {
|
|
57
|
+
await this.loadFields();
|
|
58
|
+
}
|
|
59
|
+
const result = { updated: [], warnings: [] };
|
|
60
|
+
for (const item of items) {
|
|
61
|
+
// Sync Status field
|
|
62
|
+
if (item.status !== undefined) {
|
|
63
|
+
await this.syncField(item, 'Status', item.status, this.statusField, this.config.statusFieldMapping ?? DEFAULT_STATUS_MAPPING, result);
|
|
64
|
+
}
|
|
65
|
+
// Sync Priority field
|
|
66
|
+
if (item.priority !== undefined) {
|
|
67
|
+
await this.syncField(item, 'Priority', item.priority, this.priorityField, this.config.priorityFieldMapping ?? DEFAULT_PRIORITY_MAPPING, result);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return result;
|
|
71
|
+
}
|
|
72
|
+
async syncField(item, fieldName, value, cachedField, mapping, result) {
|
|
73
|
+
if (!cachedField) {
|
|
74
|
+
result.warnings.push({
|
|
75
|
+
itemId: item.itemId,
|
|
76
|
+
field: fieldName,
|
|
77
|
+
message: `${fieldName} field not found on project`,
|
|
78
|
+
});
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const mappedValue = mapping[value];
|
|
82
|
+
if (!mappedValue) {
|
|
83
|
+
result.warnings.push({
|
|
84
|
+
itemId: item.itemId,
|
|
85
|
+
field: fieldName,
|
|
86
|
+
message: `No mapping found for ${fieldName} value "${value}"`,
|
|
87
|
+
});
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
const optionId = cachedField.options.get(mappedValue);
|
|
91
|
+
if (!optionId) {
|
|
92
|
+
result.warnings.push({
|
|
93
|
+
itemId: item.itemId,
|
|
94
|
+
field: fieldName,
|
|
95
|
+
message: `Option "${mappedValue}" not found on ${fieldName} field`,
|
|
96
|
+
});
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
await this.client.updateItemFieldValue(this.config.projectId, item.itemId, cachedField.id, { singleSelectOptionId: optionId });
|
|
100
|
+
result.updated.push({
|
|
101
|
+
itemId: item.itemId,
|
|
102
|
+
field: fieldName,
|
|
103
|
+
value: mappedValue,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
//# sourceMappingURL=github-field-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-field-sync.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-field-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AA2BH,MAAM,sBAAsB,GAA2B;IACrD,SAAS,EAAE,MAAM;IACjB,aAAa,EAAE,aAAa;IAC5B,WAAW,EAAE,MAAM;CACpB,CAAC;AAEF,MAAM,wBAAwB,GAA2B;IACvD,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,QAAQ;IACd,IAAI,EAAE,KAAK;CACZ,CAAC;AAEF,MAAM,OAAO,eAAe;IAO1B,YAAY,MAA2B,EAAE,MAAuB;QAFxD,iBAAY,GAAG,KAAK,CAAC;QAG3B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU;QACd,IAAI,IAAI,CAAC,YAAY;YAAE,OAAO;QAE9B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAEzE,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBAC7C,IAAI,CAAC,WAAW,GAAG;oBACjB,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,OAAO,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;iBACzD,CAAC;YACJ,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;gBACtD,IAAI,CAAC,aAAa,GAAG;oBACnB,EAAE,EAAE,KAAK,CAAC,EAAE;oBACZ,IAAI,EAAE,KAAK,CAAC,IAAI;oBAChB,OAAO,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;iBACzD,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;IAC3B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,cAAc,CAAC,KAAsB;QACzC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;YACvB,MAAM,IAAI,CAAC,UAAU,EAAE,CAAC;QAC1B,CAAC;QAED,MAAM,MAAM,GAAoB,EAAE,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC;QAE9D,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,oBAAoB;YACpB,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;gBAC9B,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,EAChE,IAAI,CAAC,MAAM,CAAC,kBAAkB,IAAI,sBAAsB,EAAE,MAAM,CAAC,CAAC;YACtE,CAAC;YAED,sBAAsB;YACtB,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS,EAAE,CAAC;gBAChC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,aAAa,EACtE,IAAI,CAAC,MAAM,CAAC,oBAAoB,IAAI,wBAAwB,EAAE,MAAM,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,KAAK,CAAC,SAAS,CACrB,IAAmB,EACnB,SAAiB,EACjB,KAAa,EACb,WAAoC,EACpC,OAA+B,EAC/B,MAAuB;QAEvB,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,GAAG,SAAS,6BAA6B;aACnD,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,EAAE,CAAC;YACjB,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,wBAAwB,SAAS,WAAW,KAAK,GAAG;aAC9D,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACtD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;gBACnB,MAAM,EAAE,IAAI,CAAC,MAAM;gBACnB,KAAK,EAAE,SAAS;gBAChB,OAAO,EAAE,WAAW,WAAW,kBAAkB,SAAS,QAAQ;aACnE,CAAC,CAAC;YACH,OAAO;QACT,CAAC;QAED,MAAM,IAAI,CAAC,MAAM,CAAC,oBAAoB,CACpC,IAAI,CAAC,MAAM,CAAC,SAAS,EACrB,IAAI,CAAC,MAAM,EACX,WAAW,CAAC,EAAE,EACd,EAAE,oBAAoB,EAAE,QAAQ,EAAE,CACnC,CAAC;QAEF,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC;YAClB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,WAAW;SACnB,CAAC,CAAC;IACL,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub GraphQL Client for Projects V2
|
|
3
|
+
*
|
|
4
|
+
* Wraps `gh api graphql` CLI calls for GitHub Projects V2 operations.
|
|
5
|
+
* All calls use child_process.execFile for security (no shell interpolation).
|
|
6
|
+
*
|
|
7
|
+
* @module github-graphql-client
|
|
8
|
+
*/
|
|
9
|
+
interface ProjectField {
|
|
10
|
+
id: string;
|
|
11
|
+
name: string;
|
|
12
|
+
options?: Array<{
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
}>;
|
|
16
|
+
}
|
|
17
|
+
export declare class GitHubGraphQLClient {
|
|
18
|
+
private token?;
|
|
19
|
+
constructor(token?: string);
|
|
20
|
+
/**
|
|
21
|
+
* Resolve an owner login (user or org) to a node ID.
|
|
22
|
+
* Tries user first, falls back to organization.
|
|
23
|
+
*/
|
|
24
|
+
getOwnerNodeId(login: string): Promise<string>;
|
|
25
|
+
/**
|
|
26
|
+
* Create a new GitHub Projects V2 board.
|
|
27
|
+
*/
|
|
28
|
+
createProjectV2(ownerId: string, title: string): Promise<{
|
|
29
|
+
id: string;
|
|
30
|
+
number: number;
|
|
31
|
+
}>;
|
|
32
|
+
/**
|
|
33
|
+
* Add an issue (by node ID) to a Projects V2 board.
|
|
34
|
+
* Returns the project item ID. Idempotent.
|
|
35
|
+
*/
|
|
36
|
+
addProjectV2Item(projectId: string, contentId: string): Promise<string>;
|
|
37
|
+
/**
|
|
38
|
+
* Update a field value on a Projects V2 item.
|
|
39
|
+
*/
|
|
40
|
+
updateItemFieldValue(projectId: string, itemId: string, fieldId: string, value: {
|
|
41
|
+
singleSelectOptionId: string;
|
|
42
|
+
}): Promise<void>;
|
|
43
|
+
/**
|
|
44
|
+
* Get field definitions for a Projects V2 board.
|
|
45
|
+
*/
|
|
46
|
+
getProjectFields(projectId: string): Promise<ProjectField[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Execute a GraphQL query via `gh api graphql`.
|
|
49
|
+
*/
|
|
50
|
+
private executeGraphQL;
|
|
51
|
+
}
|
|
52
|
+
export {};
|
|
53
|
+
//# sourceMappingURL=github-graphql-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-graphql-client.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-graphql-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,UAAU,YAAY;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CAC/C;AAOD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,KAAK,CAAC,CAAS;gBAEX,KAAK,CAAC,EAAE,MAAM;IAI1B;;;OAGG;IACG,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAoBpD;;OAEG;IACG,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAY9F;;;OAGG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAY7E;;OAEG;IACG,oBAAoB,CACxB,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,KAAK,EAAE;QAAE,oBAAoB,EAAE,MAAM,CAAA;KAAE,GACtC,OAAO,CAAC,IAAI,CAAC;IAehB;;OAEG;IACG,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAkClE;;OAEG;IACH,OAAO,CAAC,cAAc;CAiCvB"}
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub GraphQL Client for Projects V2
|
|
3
|
+
*
|
|
4
|
+
* Wraps `gh api graphql` CLI calls for GitHub Projects V2 operations.
|
|
5
|
+
* All calls use child_process.execFile for security (no shell interpolation).
|
|
6
|
+
*
|
|
7
|
+
* @module github-graphql-client
|
|
8
|
+
*/
|
|
9
|
+
import { execFile } from 'child_process';
|
|
10
|
+
export class GitHubGraphQLClient {
|
|
11
|
+
constructor(token) {
|
|
12
|
+
this.token = token;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resolve an owner login (user or org) to a node ID.
|
|
16
|
+
* Tries user first, falls back to organization.
|
|
17
|
+
*/
|
|
18
|
+
async getOwnerNodeId(login) {
|
|
19
|
+
// Try user query first
|
|
20
|
+
const userQuery = `query { user(login: "${login}") { id } }`;
|
|
21
|
+
const userResult = await this.executeGraphQL(userQuery);
|
|
22
|
+
if (userResult.data?.user && userResult.data.user.id) {
|
|
23
|
+
return userResult.data.user.id;
|
|
24
|
+
}
|
|
25
|
+
// Fallback to organization
|
|
26
|
+
const orgQuery = `query { organization(login: "${login}") { id } }`;
|
|
27
|
+
const orgResult = await this.executeGraphQL(orgQuery);
|
|
28
|
+
if (orgResult.data?.organization && orgResult.data.organization.id) {
|
|
29
|
+
return orgResult.data.organization.id;
|
|
30
|
+
}
|
|
31
|
+
throw new Error(`Could not resolve to a User or Organization with the login of '${login}'.`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Create a new GitHub Projects V2 board.
|
|
35
|
+
*/
|
|
36
|
+
async createProjectV2(ownerId, title) {
|
|
37
|
+
const query = `mutation {
|
|
38
|
+
createProjectV2(input: { ownerId: "${ownerId}", title: "${title}" }) {
|
|
39
|
+
projectV2 { id number }
|
|
40
|
+
}
|
|
41
|
+
}`;
|
|
42
|
+
const result = await this.executeGraphQL(query);
|
|
43
|
+
const project = result.data?.createProjectV2?.projectV2;
|
|
44
|
+
return { id: project.id, number: project.number };
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Add an issue (by node ID) to a Projects V2 board.
|
|
48
|
+
* Returns the project item ID. Idempotent.
|
|
49
|
+
*/
|
|
50
|
+
async addProjectV2Item(projectId, contentId) {
|
|
51
|
+
const query = `mutation {
|
|
52
|
+
addProjectV2ItemById(input: { projectId: "${projectId}", contentId: "${contentId}" }) {
|
|
53
|
+
item { id }
|
|
54
|
+
}
|
|
55
|
+
}`;
|
|
56
|
+
const result = await this.executeGraphQL(query);
|
|
57
|
+
const item = result.data?.addProjectV2ItemById?.item;
|
|
58
|
+
return item.id;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Update a field value on a Projects V2 item.
|
|
62
|
+
*/
|
|
63
|
+
async updateItemFieldValue(projectId, itemId, fieldId, value) {
|
|
64
|
+
const query = `mutation {
|
|
65
|
+
updateProjectV2ItemFieldValue(input: {
|
|
66
|
+
projectId: "${projectId}",
|
|
67
|
+
itemId: "${itemId}",
|
|
68
|
+
fieldId: "${fieldId}",
|
|
69
|
+
value: { singleSelectOptionId: "${value.singleSelectOptionId}" }
|
|
70
|
+
}) {
|
|
71
|
+
projectV2Item { id }
|
|
72
|
+
}
|
|
73
|
+
}`;
|
|
74
|
+
await this.executeGraphQL(query);
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Get field definitions for a Projects V2 board.
|
|
78
|
+
*/
|
|
79
|
+
async getProjectFields(projectId) {
|
|
80
|
+
const query = `query {
|
|
81
|
+
node(id: "${projectId}") {
|
|
82
|
+
... on ProjectV2 {
|
|
83
|
+
fields(first: 50) {
|
|
84
|
+
nodes {
|
|
85
|
+
... on ProjectV2Field { id name dataType }
|
|
86
|
+
... on ProjectV2SingleSelectField {
|
|
87
|
+
id name dataType
|
|
88
|
+
options { id name }
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}`;
|
|
95
|
+
const result = await this.executeGraphQL(query);
|
|
96
|
+
const fields = result.data?.node?.fields?.nodes || [];
|
|
97
|
+
return fields.map((f) => {
|
|
98
|
+
const field = { id: f.id, name: f.name };
|
|
99
|
+
if (f.options && f.options.length > 0) {
|
|
100
|
+
field.options = f.options;
|
|
101
|
+
}
|
|
102
|
+
return field;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Execute a GraphQL query via `gh api graphql`.
|
|
107
|
+
*/
|
|
108
|
+
executeGraphQL(query) {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
const args = ['api', 'graphql', '-f', `query=${query}`];
|
|
111
|
+
const opts = {};
|
|
112
|
+
if (this.token) {
|
|
113
|
+
opts.env = { ...process.env, GH_TOKEN: this.token };
|
|
114
|
+
}
|
|
115
|
+
execFile('gh', args, opts, (err, stdout, stderr) => {
|
|
116
|
+
if (err) {
|
|
117
|
+
reject(new Error(stderr || err.message));
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
let parsed;
|
|
121
|
+
try {
|
|
122
|
+
parsed = JSON.parse(stdout);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
reject(new Error(`Failed to parse GraphQL response: ${stdout.slice(0, 200)}`));
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (parsed.errors && parsed.errors.length > 0) {
|
|
129
|
+
const messages = parsed.errors.map((e) => e.message).join('; ');
|
|
130
|
+
reject(new Error(`GraphQL error: ${messages}`));
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
resolve(parsed);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
//# sourceMappingURL=github-graphql-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-graphql-client.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-graphql-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Issue Body Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates GitHub issue body markdown from a User Story.
|
|
5
|
+
* Used by the spec-to-issue push sync to create rich issue content
|
|
6
|
+
* with AC checkboxes, priority badges, and sync markers.
|
|
7
|
+
*
|
|
8
|
+
* @module github-issue-body-generator
|
|
9
|
+
*/
|
|
10
|
+
export interface UserStoryInput {
|
|
11
|
+
/** User story ID, e.g., "US-001" */
|
|
12
|
+
id: string;
|
|
13
|
+
/** User story title */
|
|
14
|
+
title: string;
|
|
15
|
+
/** User story description */
|
|
16
|
+
description: string;
|
|
17
|
+
/** Priority, e.g., "P1" */
|
|
18
|
+
priority: string;
|
|
19
|
+
/** Acceptance criteria */
|
|
20
|
+
acceptanceCriteria: Array<{
|
|
21
|
+
id: string;
|
|
22
|
+
description: string;
|
|
23
|
+
completed: boolean;
|
|
24
|
+
}>;
|
|
25
|
+
/** Spec ID, e.g., "spec-001" */
|
|
26
|
+
specId?: string;
|
|
27
|
+
/** Local file path to the spec */
|
|
28
|
+
specPath?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Generate a GitHub issue body from a User Story input.
|
|
32
|
+
*
|
|
33
|
+
* Output format:
|
|
34
|
+
* - Description section
|
|
35
|
+
* - AC checkboxes between specweave markers
|
|
36
|
+
* - Priority badge
|
|
37
|
+
* - Sync footer marker
|
|
38
|
+
*/
|
|
39
|
+
export declare function generateIssueBody(userStory: UserStoryInput): string;
|
|
40
|
+
//# sourceMappingURL=github-issue-body-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-issue-body-generator.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-issue-body-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,cAAc;IAC7B,oCAAoC;IACpC,EAAE,EAAE,MAAM,CAAC;IACX,uBAAuB;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,6BAA6B;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,0BAA0B;IAC1B,kBAAkB,EAAE,KAAK,CAAC;QACxB,EAAE,EAAE,MAAM,CAAC;QACX,WAAW,EAAE,MAAM,CAAC;QACpB,SAAS,EAAE,OAAO,CAAC;KACpB,CAAC,CAAC;IACH,gCAAgC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,cAAc,GAAG,MAAM,CAmCnE"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Issue Body Generator
|
|
3
|
+
*
|
|
4
|
+
* Generates GitHub issue body markdown from a User Story.
|
|
5
|
+
* Used by the spec-to-issue push sync to create rich issue content
|
|
6
|
+
* with AC checkboxes, priority badges, and sync markers.
|
|
7
|
+
*
|
|
8
|
+
* @module github-issue-body-generator
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Generate a GitHub issue body from a User Story input.
|
|
12
|
+
*
|
|
13
|
+
* Output format:
|
|
14
|
+
* - Description section
|
|
15
|
+
* - AC checkboxes between specweave markers
|
|
16
|
+
* - Priority badge
|
|
17
|
+
* - Sync footer marker
|
|
18
|
+
*/
|
|
19
|
+
export function generateIssueBody(userStory) {
|
|
20
|
+
const lines = [];
|
|
21
|
+
// Description
|
|
22
|
+
lines.push('## Description');
|
|
23
|
+
lines.push('');
|
|
24
|
+
lines.push(userStory.description);
|
|
25
|
+
lines.push('');
|
|
26
|
+
// Priority badge
|
|
27
|
+
lines.push(`**Priority**: ${userStory.priority}`);
|
|
28
|
+
lines.push('');
|
|
29
|
+
// Acceptance Criteria with markers
|
|
30
|
+
if (userStory.acceptanceCriteria.length > 0) {
|
|
31
|
+
lines.push('## Acceptance Criteria');
|
|
32
|
+
lines.push('');
|
|
33
|
+
lines.push('<!-- specweave:ac-start -->');
|
|
34
|
+
for (const ac of userStory.acceptanceCriteria) {
|
|
35
|
+
const checkbox = ac.completed ? '[x]' : '[ ]';
|
|
36
|
+
lines.push(`- ${checkbox} **${ac.id}**: ${ac.description}`);
|
|
37
|
+
}
|
|
38
|
+
lines.push('<!-- specweave:ac-end -->');
|
|
39
|
+
lines.push('');
|
|
40
|
+
}
|
|
41
|
+
// Sync footer marker
|
|
42
|
+
const syncParts = [];
|
|
43
|
+
if (userStory.specId) {
|
|
44
|
+
syncParts.push(`spec=${userStory.specId}`);
|
|
45
|
+
}
|
|
46
|
+
syncParts.push(`us=${userStory.id}`);
|
|
47
|
+
lines.push(`<!-- specweave:sync ${syncParts.join(' ')} -->`);
|
|
48
|
+
return lines.join('\n');
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=github-issue-body-generator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-issue-body-generator.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-issue-body-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAuBH;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,SAAyB;IACzD,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,cAAc;IACd,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC7B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAClC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,iBAAiB;IACjB,KAAK,CAAC,IAAI,CAAC,iBAAiB,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;IAClD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,mCAAmC;IACnC,IAAI,SAAS,CAAC,kBAAkB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACf,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC1C,KAAK,MAAM,EAAE,IAAI,SAAS,CAAC,kBAAkB,EAAE,CAAC;YAC9C,MAAM,QAAQ,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC;YAC9C,KAAK,CAAC,IAAI,CAAC,KAAK,QAAQ,MAAM,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,WAAW,EAAE,CAAC,CAAC;QAC9D,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;QACxC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC;IAED,qBAAqB;IACrB,MAAM,SAAS,GAAa,EAAE,CAAC;IAC/B,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrB,SAAS,CAAC,IAAI,CAAC,QAAQ,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IAC7C,CAAC;IACD,SAAS,CAAC,IAAI,CAAC,MAAM,SAAS,CAAC,EAAE,EAAE,CAAC,CAAC;IACrC,KAAK,CAAC,IAAI,CAAC,uBAAuB,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE7D,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Issue Body Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses AC checkbox state and sync metadata from a GitHub issue body.
|
|
5
|
+
* Used by the pull sync to detect changes made on GitHub.
|
|
6
|
+
*
|
|
7
|
+
* @module github-issue-body-parser
|
|
8
|
+
*/
|
|
9
|
+
export interface ParsedIssueBody {
|
|
10
|
+
/** AC ID → checked state and description */
|
|
11
|
+
acceptanceCriteria: Record<string, {
|
|
12
|
+
checked: boolean;
|
|
13
|
+
description: string;
|
|
14
|
+
}>;
|
|
15
|
+
/** Sync marker metadata (if present) */
|
|
16
|
+
syncMarker?: {
|
|
17
|
+
specId: string;
|
|
18
|
+
userStoryId: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse a GitHub issue body to extract AC checkbox states and sync metadata.
|
|
23
|
+
*
|
|
24
|
+
* Strategy:
|
|
25
|
+
* 1. Try to find ACs within "## Acceptance Criteria" section
|
|
26
|
+
* 2. Fallback: scan entire body for AC-pattern checkboxes
|
|
27
|
+
* 3. Parse sync footer marker if present
|
|
28
|
+
*/
|
|
29
|
+
export declare function parseIssueBody(body: string): ParsedIssueBody;
|
|
30
|
+
//# sourceMappingURL=github-issue-body-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-issue-body-parser.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-issue-body-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,eAAe;IAC9B,4CAA4C;IAC5C,kBAAkB,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9E,wCAAwC;IACxC,UAAU,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;CACtD;AAQD;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,CA6D5D"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GitHub Issue Body Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses AC checkbox state and sync metadata from a GitHub issue body.
|
|
5
|
+
* Used by the pull sync to detect changes made on GitHub.
|
|
6
|
+
*
|
|
7
|
+
* @module github-issue-body-parser
|
|
8
|
+
*/
|
|
9
|
+
// Regex to match AC checkboxes: - [x] **AC-US1-01**: Description
|
|
10
|
+
const AC_CHECKBOX_RE = /^-\s+\[([ xX])\]\s+\*\*(?<acId>AC-[A-Z0-9]+-\d+)\*\*:\s*(?<desc>.+)$/;
|
|
11
|
+
// Regex to match sync footer marker
|
|
12
|
+
const SYNC_MARKER_RE = /<!--\s*specweave:sync\s+(?:spec=(?<specId>[^\s]+)\s+)?us=(?<usId>[^\s]+)\s*-->/;
|
|
13
|
+
/**
|
|
14
|
+
* Parse a GitHub issue body to extract AC checkbox states and sync metadata.
|
|
15
|
+
*
|
|
16
|
+
* Strategy:
|
|
17
|
+
* 1. Try to find ACs within "## Acceptance Criteria" section
|
|
18
|
+
* 2. Fallback: scan entire body for AC-pattern checkboxes
|
|
19
|
+
* 3. Parse sync footer marker if present
|
|
20
|
+
*/
|
|
21
|
+
export function parseIssueBody(body) {
|
|
22
|
+
const result = {
|
|
23
|
+
acceptanceCriteria: {},
|
|
24
|
+
};
|
|
25
|
+
if (!body || !body.trim()) {
|
|
26
|
+
return result;
|
|
27
|
+
}
|
|
28
|
+
const lines = body.split('\n');
|
|
29
|
+
// Try to find the "## Acceptance Criteria" section
|
|
30
|
+
let inAcSection = false;
|
|
31
|
+
let foundAcSection = false;
|
|
32
|
+
for (const line of lines) {
|
|
33
|
+
// Detect section boundaries
|
|
34
|
+
if (/^##\s+Acceptance Criteria/i.test(line)) {
|
|
35
|
+
inAcSection = true;
|
|
36
|
+
foundAcSection = true;
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
if (inAcSection && /^##\s+/.test(line)) {
|
|
40
|
+
inAcSection = false;
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
if (inAcSection) {
|
|
44
|
+
const match = line.match(AC_CHECKBOX_RE);
|
|
45
|
+
if (match?.groups) {
|
|
46
|
+
result.acceptanceCriteria[match.groups.acId] = {
|
|
47
|
+
checked: match[1] !== ' ',
|
|
48
|
+
description: match.groups.desc.trim(),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Fallback: if no AC section found, scan the entire body
|
|
54
|
+
if (!foundAcSection) {
|
|
55
|
+
for (const line of lines) {
|
|
56
|
+
const match = line.match(AC_CHECKBOX_RE);
|
|
57
|
+
if (match?.groups) {
|
|
58
|
+
result.acceptanceCriteria[match.groups.acId] = {
|
|
59
|
+
checked: match[1] !== ' ',
|
|
60
|
+
description: match.groups.desc.trim(),
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
// Parse sync footer marker
|
|
66
|
+
const syncMatch = body.match(SYNC_MARKER_RE);
|
|
67
|
+
if (syncMatch?.groups?.usId) {
|
|
68
|
+
result.syncMarker = {
|
|
69
|
+
specId: syncMatch.groups.specId || '',
|
|
70
|
+
userStoryId: syncMatch.groups.usId,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=github-issue-body-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-issue-body-parser.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-issue-body-parser.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AASH,iEAAiE;AACjE,MAAM,cAAc,GAAG,sEAAsE,CAAC;AAE9F,oCAAoC;AACpC,MAAM,cAAc,GAAG,gFAAgF,CAAC;AAExG;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY;IACzC,MAAM,MAAM,GAAoB;QAC9B,kBAAkB,EAAE,EAAE;KACvB,CAAC;IAEF,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;QAC1B,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE/B,mDAAmD;IACnD,IAAI,WAAW,GAAG,KAAK,CAAC;IACxB,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,4BAA4B;QAC5B,IAAI,4BAA4B,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5C,WAAW,GAAG,IAAI,CAAC;YACnB,cAAc,GAAG,IAAI,CAAC;YACtB,SAAS;QACX,CAAC;QACD,IAAI,WAAW,IAAI,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACvC,WAAW,GAAG,KAAK,CAAC;YACpB,SAAS;QACX,CAAC;QAED,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACzC,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;gBAClB,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;oBAC7C,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;oBACzB,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;iBACtC,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,yDAAyD;IACzD,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACzC,IAAI,KAAK,EAAE,MAAM,EAAE,CAAC;gBAClB,MAAM,CAAC,kBAAkB,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG;oBAC7C,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,KAAK,GAAG;oBACzB,WAAW,EAAE,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE;iBACtC,CAAC;YACJ,CAAC;QACH,CAAC;IACH,CAAC;IAED,2BAA2B;IAC3B,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;IAC7C,IAAI,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;QAC5B,MAAM,CAAC,UAAU,GAAG;YAClB,MAAM,EAAE,SAAS,CAAC,MAAM,CAAC,MAAM,IAAI,EAAE;YACrC,WAAW,EAAE,SAAS,CAAC,MAAM,CAAC,IAAI;SACnC,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|