specweave 0.28.17 → 0.28.19
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/dist/plugins/specweave-ado/lib/ado-board-resolver.d.ts +94 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.js +219 -0
- package/dist/plugins/specweave-ado/lib/ado-board-resolver.js.map +1 -0
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts +6 -11
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +6 -11
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.d.ts +19 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.js +380 -0
- package/dist/plugins/specweave-github/lib/github-increment-sync-cli.js.map +1 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.d.ts +92 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.d.ts.map +1 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.js +349 -0
- package/dist/plugins/specweave-github/lib/increment-issue-builder.js.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.d.ts +50 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.d.ts.map +1 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.js +84 -0
- package/dist/plugins/specweave-jira/lib/jira-board-resolver.js.map +1 -0
- package/dist/src/cli/commands/import-external.d.ts.map +1 -1
- package/dist/src/cli/commands/import-external.js +12 -7
- package/dist/src/cli/commands/import-external.js.map +1 -1
- package/dist/src/cli/helpers/init/external-import.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/external-import.js +122 -17
- package/dist/src/cli/helpers/init/external-import.js.map +1 -1
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.d.ts +65 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.js +278 -0
- package/dist/src/cli/helpers/issue-tracker/ado-area-selection.js.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.d.ts +64 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.d.ts.map +1 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.js +251 -0
- package/dist/src/cli/helpers/issue-tracker/jira-board-selection.js.map +1 -0
- package/dist/src/core/ac-test-validator-cli.js +4 -1
- package/dist/src/core/ac-test-validator-cli.js.map +1 -1
- package/dist/src/core/ac-test-validator.d.ts.map +1 -1
- package/dist/src/core/ac-test-validator.js +4 -1
- package/dist/src/core/ac-test-validator.js.map +1 -1
- package/dist/src/core/types/increment-metadata.d.ts +75 -0
- package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
- package/dist/src/core/types/sync-profile.d.ts +137 -5
- package/dist/src/core/types/sync-profile.d.ts.map +1 -1
- package/dist/src/core/types/sync-profile.js +63 -0
- package/dist/src/core/types/sync-profile.js.map +1 -1
- package/dist/src/importers/external-importer.d.ts +25 -0
- package/dist/src/importers/external-importer.d.ts.map +1 -1
- package/dist/src/importers/github-importer.d.ts.map +1 -1
- package/dist/src/importers/github-importer.js +5 -3
- package/dist/src/importers/github-importer.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +51 -0
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +39 -12
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/init/repo/types.d.ts +1 -1
- package/dist/src/living-docs/fs-id-allocator.d.ts +72 -3
- package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -1
- package/dist/src/living-docs/fs-id-allocator.js +142 -16
- package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
- package/dist/src/locales/de/cli.json +14 -0
- package/dist/src/locales/es/cli.json +14 -0
- package/dist/src/locales/fr/cli.json +14 -0
- package/dist/src/locales/ja/cli.json +14 -0
- package/dist/src/locales/ko/cli.json +14 -0
- package/dist/src/locales/pt/cli.json +14 -0
- package/dist/src/locales/ru/cli.json +14 -0
- package/dist/src/locales/zh/cli.json +14 -0
- package/dist/src/utils/chalk-fallback.d.ts +38 -0
- package/dist/src/utils/chalk-fallback.d.ts.map +1 -0
- package/dist/src/utils/chalk-fallback.js +118 -0
- package/dist/src/utils/chalk-fallback.js.map +1 -0
- package/dist/src/utils/project-id-generator.d.ts +127 -0
- package/dist/src/utils/project-id-generator.d.ts.map +1 -0
- package/dist/src/utils/project-id-generator.js +228 -0
- package/dist/src/utils/project-id-generator.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/agents/pm/AGENT.md +202 -0
- package/plugins/specweave/commands/specweave-import-external.md +5 -3
- package/plugins/specweave/commands/specweave-sync-docs.md +6 -2
- package/plugins/specweave/hooks/pre-task-completion.sh +35 -17
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.d.ts +16 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js +121 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator-cli.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.d.ts +111 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.js +295 -0
- package/plugins/specweave/lib/vendor/core/ac-test-validator.js.map +1 -0
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +75 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.d.ts +38 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.js +118 -0
- package/plugins/specweave/lib/vendor/utils/chalk-fallback.js.map +1 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.d.ts +179 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.js +319 -0
- package/plugins/specweave/lib/vendor/utils/fs-native.js.map +1 -0
- package/plugins/specweave/skills/code-reviewer/SKILL.md +1 -1
- package/plugins/specweave/skills/docs-updater/SKILL.md +61 -0
- package/plugins/specweave/skills/increment-planner/SKILL.md +10 -335
- package/plugins/specweave/skills/increment-planner/templates/metadata.json +13 -0
- package/plugins/specweave/skills/increment-planner/templates/plan.md +50 -0
- package/plugins/specweave/skills/increment-planner/templates/spec-multi-project.md +86 -0
- package/plugins/specweave/skills/increment-planner/templates/spec-single-project.md +50 -0
- package/plugins/specweave/skills/increment-planner/templates/tasks-multi-project.md +86 -0
- package/plugins/specweave/skills/increment-planner/templates/tasks-single-project.md +48 -0
- package/plugins/specweave-ado/commands/specweave-ado-import-areas.md +358 -0
- package/plugins/specweave-alternatives/skills/architecture-alternatives/SKILL.md +1 -0
- package/plugins/specweave-alternatives/skills/bmad-method/SKILL.md +1 -0
- package/plugins/specweave-core/skills/code-quality/SKILL.md +1 -0
- package/plugins/specweave-core/skills/design-patterns/SKILL.md +1 -0
- package/plugins/specweave-core/skills/software-architecture/SKILL.md +1 -0
- package/plugins/specweave-github/commands/specweave-github-cleanup-duplicates.md +14 -10
- package/plugins/specweave-github/commands/specweave-github-sync.md +57 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +68 -0
- package/plugins/specweave-github/lib/github-feature-sync.ts +6 -11
- package/plugins/specweave-github/lib/github-increment-sync-cli.js +343 -0
- package/plugins/specweave-github/lib/github-increment-sync-cli.ts +484 -0
- package/plugins/specweave-github/lib/increment-issue-builder.js +368 -0
- package/plugins/specweave-github/lib/increment-issue-builder.ts +471 -0
- package/plugins/specweave-github/skills/github-issue-standard/SKILL.md +19 -24
- package/plugins/specweave-infrastructure/agents/observability-engineer/AGENT.md +15 -23
- package/plugins/specweave-jira/commands/specweave-jira-import-boards.md +331 -0
- package/plugins/specweave-ml/agents/data-scientist/AGENT.md +16 -20
- package/plugins/specweave-ml/agents/ml-engineer/AGENT.md +18 -19
- package/plugins/specweave-ml/skills/{ml-pipeline-workflow → mlops-dag-builder}/SKILL.md +18 -14
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +102 -0
- package/plugins/specweave-ui/skills/browser-automation/SKILL.md +1 -1
- package/plugins/specweave-ui/skills/ui-testing/SKILL.md +10 -122
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts +0 -70
- package/dist/plugins/specweave-github/lib/epic-content-builder.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/epic-content-builder.js +0 -258
- package/dist/plugins/specweave-github/lib/epic-content-builder.js.map +0 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts +0 -83
- package/dist/plugins/specweave-github/lib/github-epic-sync.d.ts.map +0 -1
- package/dist/plugins/specweave-github/lib/github-epic-sync.js +0 -466
- package/dist/plugins/specweave-github/lib/github-epic-sync.js.map +0 -1
- package/plugins/specweave-github/lib/epic-content-builder.js +0 -265
- package/plugins/specweave-github/lib/epic-content-builder.ts +0 -376
- package/plugins/specweave-github/lib/github-epic-sync.js +0 -488
- package/plugins/specweave-github/lib/github-epic-sync.ts +0 -715
|
@@ -1,135 +1,23 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ui-testing
|
|
3
|
-
description: UI
|
|
3
|
+
description: Multi-framework UI testing expert - Cypress, Testing Library, component tests. Use for framework comparison, Cypress-specific testing, or React Testing Library. For DEEP Playwright expertise, use e2e-playwright skill instead. Activates for Cypress, Testing Library, component tests, React testing, Vue testing, framework comparison, which testing tool, Cypress vs Playwright.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# UI Testing Skill
|
|
7
7
|
|
|
8
|
-
Expert in UI
|
|
8
|
+
Expert in UI testing with **Cypress** and **Testing Library**. For deep Playwright expertise, see the `e2e-playwright` skill.
|
|
9
9
|
|
|
10
|
-
##
|
|
10
|
+
## Framework Selection Guide
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
| Framework | Best For | Key Strength |
|
|
13
|
+
|-----------|----------|--------------|
|
|
14
|
+
| **Playwright** | E2E, cross-browser | Auto-wait, multi-browser → Use `e2e-playwright` skill |
|
|
15
|
+
| **Cypress** | E2E, developer experience | Time-travel debugging, real-time reload |
|
|
16
|
+
| **Testing Library** | Component tests | User-centric queries, accessibility-first |
|
|
13
17
|
|
|
14
|
-
|
|
15
|
-
- Multi-browser support (Chromium, Firefox, WebKit)
|
|
16
|
-
- Auto-wait (no manual `waitFor` needed)
|
|
17
|
-
- Fast parallel execution
|
|
18
|
-
- Built-in assertions and fixtures
|
|
19
|
-
- Network interception and mocking
|
|
20
|
-
|
|
21
|
-
#### Basic Test Structure
|
|
22
|
-
|
|
23
|
-
```typescript
|
|
24
|
-
import { test, expect } from '@playwright/test';
|
|
25
|
-
|
|
26
|
-
test.describe('User Authentication', () => {
|
|
27
|
-
test('should login with valid credentials', async ({ page }) => {
|
|
28
|
-
// Navigate
|
|
29
|
-
await page.goto('https://example.com/login');
|
|
30
|
-
|
|
31
|
-
// Interact
|
|
32
|
-
await page.fill('input[name="email"]', 'user@example.com');
|
|
33
|
-
await page.fill('input[name="password"]', 'SecurePass123!');
|
|
34
|
-
await page.click('button[type="submit"]');
|
|
35
|
-
|
|
36
|
-
// Assert
|
|
37
|
-
await expect(page).toHaveURL('https://example.com/dashboard');
|
|
38
|
-
await expect(page.locator('h1')).toHaveText('Welcome, User');
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
test('should show error with invalid credentials', async ({ page }) => {
|
|
42
|
-
await page.goto('https://example.com/login');
|
|
43
|
-
|
|
44
|
-
await page.fill('input[name="email"]', 'wrong@example.com');
|
|
45
|
-
await page.fill('input[name="password"]', 'WrongPass');
|
|
46
|
-
await page.click('button[type="submit"]');
|
|
47
|
-
|
|
48
|
-
// Wait for error message
|
|
49
|
-
const errorMessage = page.locator('.error-message');
|
|
50
|
-
await expect(errorMessage).toBeVisible();
|
|
51
|
-
await expect(errorMessage).toHaveText('Invalid credentials');
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
```
|
|
55
|
-
|
|
56
|
-
#### Fixtures (Reusable Setup)
|
|
57
|
-
|
|
58
|
-
```typescript
|
|
59
|
-
// fixtures.ts
|
|
60
|
-
import { test as base } from '@playwright/test';
|
|
61
|
-
|
|
62
|
-
type Fixtures = {
|
|
63
|
-
authenticatedPage: Page;
|
|
64
|
-
};
|
|
65
|
-
|
|
66
|
-
export const test = base.extend<Fixtures>({
|
|
67
|
-
authenticatedPage: async ({ page }, use) => {
|
|
68
|
-
// Login before each test
|
|
69
|
-
await page.goto('https://example.com/login');
|
|
70
|
-
await page.fill('input[name="email"]', 'user@example.com');
|
|
71
|
-
await page.fill('input[name="password"]', 'SecurePass123!');
|
|
72
|
-
await page.click('button[type="submit"]');
|
|
73
|
-
await page.waitForURL('**/dashboard');
|
|
74
|
-
|
|
75
|
-
// Use the authenticated page
|
|
76
|
-
await use(page);
|
|
77
|
-
|
|
78
|
-
// Cleanup (logout)
|
|
79
|
-
await page.click('[data-testid="logout"]');
|
|
80
|
-
},
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// tests/dashboard.spec.ts
|
|
84
|
-
import { test, expect } from './fixtures';
|
|
85
|
-
|
|
86
|
-
test('should display user dashboard', async ({ authenticatedPage }) => {
|
|
87
|
-
// Already logged in via fixture
|
|
88
|
-
await expect(authenticatedPage.locator('h1')).toHaveText('Dashboard');
|
|
89
|
-
});
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
#### Page Object Model (POM)
|
|
93
|
-
|
|
94
|
-
```typescript
|
|
95
|
-
// pages/LoginPage.ts
|
|
96
|
-
export class LoginPage {
|
|
97
|
-
constructor(private page: Page) {}
|
|
98
|
-
|
|
99
|
-
async goto() {
|
|
100
|
-
await this.page.goto('https://example.com/login');
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
async login(email: string, password: string) {
|
|
104
|
-
await this.page.fill('input[name="email"]', email);
|
|
105
|
-
await this.page.fill('input[name="password"]', password);
|
|
106
|
-
await this.page.click('button[type="submit"]');
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
async getErrorMessage() {
|
|
110
|
-
const errorElement = this.page.locator('.error-message');
|
|
111
|
-
return errorElement.textContent();
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
async isLoginButtonDisabled() {
|
|
115
|
-
return this.page.locator('button[type="submit"]').isDisabled();
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// tests/login.spec.ts
|
|
120
|
-
import { LoginPage } from '../pages/LoginPage';
|
|
121
|
-
|
|
122
|
-
test('login with POM', async ({ page }) => {
|
|
123
|
-
const loginPage = new LoginPage(page);
|
|
124
|
-
|
|
125
|
-
await loginPage.goto();
|
|
126
|
-
await loginPage.login('user@example.com', 'SecurePass123!');
|
|
127
|
-
|
|
128
|
-
await expect(page).toHaveURL('**/dashboard');
|
|
129
|
-
});
|
|
130
|
-
```
|
|
18
|
+
---
|
|
131
19
|
|
|
132
|
-
|
|
20
|
+
## 1. Cypress (E2E Testing)
|
|
133
21
|
|
|
134
22
|
**Why Cypress?**
|
|
135
23
|
- Developer-friendly API
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Epic Content Builder - Hierarchical GitHub issue content for Feature Specs
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - Reads FS-* folder (FEATURE.md + us-*.md files)
|
|
6
|
-
* - Reads increment tasks.md files to map tasks to user stories
|
|
7
|
-
* - Generates hierarchical issue body:
|
|
8
|
-
* 1. User Stories section (with status + increment)
|
|
9
|
-
* 2. Tasks section (grouped by User Story)
|
|
10
|
-
*
|
|
11
|
-
* Key Features:
|
|
12
|
-
* - NO single "Increment" field (epics span multiple increments)
|
|
13
|
-
* - User Stories are checkable with status and increment link
|
|
14
|
-
* - Tasks grouped under their User Story
|
|
15
|
-
* - Shows which increment each US/task belongs to
|
|
16
|
-
*/
|
|
17
|
-
export declare class EpicContentBuilder {
|
|
18
|
-
private epicFolder;
|
|
19
|
-
private projectRoot;
|
|
20
|
-
constructor(epicFolder: string, projectRoot: string);
|
|
21
|
-
/**
|
|
22
|
-
* Build hierarchical GitHub issue body
|
|
23
|
-
*
|
|
24
|
-
* Format:
|
|
25
|
-
* - Epic overview
|
|
26
|
-
* - User Stories section (checkable, with status + increment)
|
|
27
|
-
* - Tasks section (grouped by User Story)
|
|
28
|
-
*/
|
|
29
|
-
buildIssueBody(): Promise<string>;
|
|
30
|
-
/**
|
|
31
|
-
* Read Epic FEATURE.md frontmatter
|
|
32
|
-
*/
|
|
33
|
-
private readEpicMetadata;
|
|
34
|
-
/**
|
|
35
|
-
* Read all user stories from us-*.md files
|
|
36
|
-
*/
|
|
37
|
-
private readUserStories;
|
|
38
|
-
/**
|
|
39
|
-
* Extract tasks for a user story from its Implementation section
|
|
40
|
-
*/
|
|
41
|
-
private extractTasksForUserStory;
|
|
42
|
-
/**
|
|
43
|
-
* Extract acceptance criteria from user story content
|
|
44
|
-
*
|
|
45
|
-
* Parses the "## Acceptance Criteria" section and extracts all checkable items.
|
|
46
|
-
* Format: - [x] **AC-US2-01**: Description...
|
|
47
|
-
*/
|
|
48
|
-
private extractAcceptanceCriteria;
|
|
49
|
-
/**
|
|
50
|
-
* Build overview section
|
|
51
|
-
*/
|
|
52
|
-
private buildOverviewSection;
|
|
53
|
-
/**
|
|
54
|
-
* Build User Stories section
|
|
55
|
-
*/
|
|
56
|
-
private buildUserStoriesSection;
|
|
57
|
-
/**
|
|
58
|
-
* Build Tasks section (grouped by User Story)
|
|
59
|
-
*/
|
|
60
|
-
private buildTasksSection;
|
|
61
|
-
/**
|
|
62
|
-
* Normalize status values
|
|
63
|
-
*/
|
|
64
|
-
private normalizeStatus;
|
|
65
|
-
/**
|
|
66
|
-
* Get status emoji
|
|
67
|
-
*/
|
|
68
|
-
private getStatusEmoji;
|
|
69
|
-
}
|
|
70
|
-
//# sourceMappingURL=epic-content-builder.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"epic-content-builder.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/epic-content-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA8CH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,WAAW,CAAS;gBAEhB,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM;IAKnD;;;;;;;OAOG;IACG,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAgBvC;;OAEG;YACW,gBAAgB;IAY9B;;OAEG;YACW,eAAe;IA8C7B;;OAEG;YACW,wBAAwB;IAoEtC;;;;;OAKG;IACH,OAAO,CAAC,yBAAyB;IAgCjC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAI5B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IA8B/B;;OAEG;IACH,OAAO,CAAC,iBAAiB;IAiCzB;;OAEG;IACH,OAAO,CAAC,eAAe;IAUvB;;OAEG;IACH,OAAO,CAAC,cAAc;CAgBvB"}
|
|
@@ -1,258 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Epic Content Builder - Hierarchical GitHub issue content for Feature Specs
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - Reads FS-* folder (FEATURE.md + us-*.md files)
|
|
6
|
-
* - Reads increment tasks.md files to map tasks to user stories
|
|
7
|
-
* - Generates hierarchical issue body:
|
|
8
|
-
* 1. User Stories section (with status + increment)
|
|
9
|
-
* 2. Tasks section (grouped by User Story)
|
|
10
|
-
*
|
|
11
|
-
* Key Features:
|
|
12
|
-
* - NO single "Increment" field (epics span multiple increments)
|
|
13
|
-
* - User Stories are checkable with status and increment link
|
|
14
|
-
* - Tasks grouped under their User Story
|
|
15
|
-
* - Shows which increment each US/task belongs to
|
|
16
|
-
*/
|
|
17
|
-
import { readdir, readFile } from 'fs/promises';
|
|
18
|
-
import { existsSync } from 'fs';
|
|
19
|
-
import * as path from 'path';
|
|
20
|
-
import * as yaml from 'yaml';
|
|
21
|
-
export class EpicContentBuilder {
|
|
22
|
-
constructor(epicFolder, projectRoot) {
|
|
23
|
-
this.epicFolder = epicFolder;
|
|
24
|
-
this.projectRoot = projectRoot;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Build hierarchical GitHub issue body
|
|
28
|
-
*
|
|
29
|
-
* Format:
|
|
30
|
-
* - Epic overview
|
|
31
|
-
* - User Stories section (checkable, with status + increment)
|
|
32
|
-
* - Tasks section (grouped by User Story)
|
|
33
|
-
*/
|
|
34
|
-
async buildIssueBody() {
|
|
35
|
-
// 1. Read Epic metadata
|
|
36
|
-
const epicData = await this.readEpicMetadata();
|
|
37
|
-
// 2. Read User Stories
|
|
38
|
-
const userStories = await this.readUserStories();
|
|
39
|
-
// 3. Build sections
|
|
40
|
-
const overview = this.buildOverviewSection(epicData);
|
|
41
|
-
const userStoriesSection = this.buildUserStoriesSection(userStories);
|
|
42
|
-
const tasksSection = this.buildTasksSection(userStories);
|
|
43
|
-
// 4. Combine
|
|
44
|
-
return `${overview}\n\n---\n\n${userStoriesSection}\n\n---\n\n${tasksSection}\n\n---\n\n🤖 Auto-created by SpecWeave Epic Sync`;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Read Epic FEATURE.md frontmatter
|
|
48
|
-
*/
|
|
49
|
-
async readEpicMetadata() {
|
|
50
|
-
const featurePath = path.join(this.epicFolder, 'FEATURE.md');
|
|
51
|
-
const content = await readFile(featurePath, 'utf-8');
|
|
52
|
-
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
53
|
-
if (!match) {
|
|
54
|
-
throw new Error('FEATURE.md missing YAML frontmatter');
|
|
55
|
-
}
|
|
56
|
-
return yaml.parse(match[1]);
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Read all user stories from us-*.md files
|
|
60
|
-
*/
|
|
61
|
-
async readUserStories() {
|
|
62
|
-
const files = await readdir(this.epicFolder);
|
|
63
|
-
const usFiles = files.filter((f) => f.startsWith('us-') && f.endsWith('.md'));
|
|
64
|
-
const userStories = [];
|
|
65
|
-
for (const file of usFiles.sort()) {
|
|
66
|
-
const filePath = path.join(this.epicFolder, file);
|
|
67
|
-
const content = await readFile(filePath, 'utf-8');
|
|
68
|
-
const match = content.match(/^---\n([\s\S]*?)\n---/);
|
|
69
|
-
if (!match) {
|
|
70
|
-
console.warn(` ⚠️ ${file} missing frontmatter, skipping`);
|
|
71
|
-
continue;
|
|
72
|
-
}
|
|
73
|
-
const frontmatter = yaml.parse(match[1]);
|
|
74
|
-
const bodyContent = content.slice(match[0].length).trim();
|
|
75
|
-
// Extract increment from Implementation section
|
|
76
|
-
const incrementMatch = bodyContent.match(/\*\*Increment\*\*:\s*\[([^\]]+)\]/);
|
|
77
|
-
const increment = incrementMatch ? incrementMatch[1] : null;
|
|
78
|
-
// Extract acceptance criteria from AC section
|
|
79
|
-
const acceptanceCriteria = this.extractAcceptanceCriteria(bodyContent);
|
|
80
|
-
// Extract tasks from Implementation section
|
|
81
|
-
const tasks = await this.extractTasksForUserStory(frontmatter.id, increment, bodyContent);
|
|
82
|
-
userStories.push({
|
|
83
|
-
id: frontmatter.id,
|
|
84
|
-
title: frontmatter.title,
|
|
85
|
-
status: this.normalizeStatus(frontmatter.status),
|
|
86
|
-
increment,
|
|
87
|
-
acceptanceCriteria,
|
|
88
|
-
tasks,
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
return userStories;
|
|
92
|
-
}
|
|
93
|
-
/**
|
|
94
|
-
* Extract tasks for a user story from its Implementation section
|
|
95
|
-
*/
|
|
96
|
-
async extractTasksForUserStory(userStoryId, incrementId, content) {
|
|
97
|
-
if (!incrementId) {
|
|
98
|
-
return []; // No increment yet, no tasks
|
|
99
|
-
}
|
|
100
|
-
// Find increment folder
|
|
101
|
-
const incrementFolder = path.join(this.projectRoot, '.specweave', 'increments', incrementId);
|
|
102
|
-
if (!existsSync(incrementFolder)) {
|
|
103
|
-
console.warn(` ⚠️ Increment folder not found: ${incrementId}`);
|
|
104
|
-
return [];
|
|
105
|
-
}
|
|
106
|
-
const tasksPath = path.join(incrementFolder, 'tasks.md');
|
|
107
|
-
if (!existsSync(tasksPath)) {
|
|
108
|
-
console.warn(` ⚠️ tasks.md not found in ${incrementId}`);
|
|
109
|
-
return [];
|
|
110
|
-
}
|
|
111
|
-
// Read tasks.md
|
|
112
|
-
const tasksContent = await readFile(tasksPath, 'utf-8');
|
|
113
|
-
// Extract task links from user story's Implementation section
|
|
114
|
-
// Format: - [T-001: Title](link#t-001-title)
|
|
115
|
-
const taskLinkPattern = /- \[([T-\d]+):\s*([^\]]+)\]/g;
|
|
116
|
-
const taskLinks = [];
|
|
117
|
-
let match;
|
|
118
|
-
while ((match = taskLinkPattern.exec(content)) !== null) {
|
|
119
|
-
taskLinks.push({
|
|
120
|
-
id: match[1], // e.g., "T-001"
|
|
121
|
-
title: match[2].trim(),
|
|
122
|
-
});
|
|
123
|
-
}
|
|
124
|
-
// Parse tasks from tasks.md to get completion status
|
|
125
|
-
const tasks = [];
|
|
126
|
-
for (const taskLink of taskLinks) {
|
|
127
|
-
// Find task in tasks.md by heading pattern: ### T-001: Title
|
|
128
|
-
const taskPattern = new RegExp(`###\\s+${taskLink.id}:\\s*([^\\n]+)[\\s\\S]*?\\*\\*Status\\*\\*:\\s*\\[([x\\s])\\]`, 'i');
|
|
129
|
-
const taskMatch = tasksContent.match(taskPattern);
|
|
130
|
-
const isCompleted = taskMatch ? taskMatch[2] === 'x' : false;
|
|
131
|
-
tasks.push({
|
|
132
|
-
id: taskLink.id,
|
|
133
|
-
title: taskLink.title,
|
|
134
|
-
status: isCompleted,
|
|
135
|
-
userStoryId,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return tasks;
|
|
139
|
-
}
|
|
140
|
-
/**
|
|
141
|
-
* Extract acceptance criteria from user story content
|
|
142
|
-
*
|
|
143
|
-
* Parses the "## Acceptance Criteria" section and extracts all checkable items.
|
|
144
|
-
* Format: - [x] **AC-US2-01**: Description...
|
|
145
|
-
*/
|
|
146
|
-
extractAcceptanceCriteria(content) {
|
|
147
|
-
const acceptanceCriteria = [];
|
|
148
|
-
// Find Acceptance Criteria section
|
|
149
|
-
const acSectionMatch = content.match(/##\s+Acceptance Criteria\s*\n([\s\S]*?)(?=\n##|\n---|\n$)/i);
|
|
150
|
-
if (!acSectionMatch) {
|
|
151
|
-
return acceptanceCriteria; // No AC section found
|
|
152
|
-
}
|
|
153
|
-
const acSection = acSectionMatch[1];
|
|
154
|
-
// Parse each AC line: - [x] **AC-US2-01**: Description (P1, testable)
|
|
155
|
-
// Pattern matches both checked [x] and unchecked [ ] boxes
|
|
156
|
-
const acPattern = /^-\s+\[([x\s])\]\s+\*\*([^*]+)\*\*:\s*(.+)$/gm;
|
|
157
|
-
let match;
|
|
158
|
-
while ((match = acPattern.exec(acSection)) !== null) {
|
|
159
|
-
const completed = match[1].trim().toLowerCase() === 'x';
|
|
160
|
-
const acId = match[2].trim(); // e.g., "AC-US2-01"
|
|
161
|
-
const description = match[3].trim(); // e.g., "Spec frontmatter includes linked_increments mapping (P1, testable)"
|
|
162
|
-
acceptanceCriteria.push({
|
|
163
|
-
id: acId,
|
|
164
|
-
description,
|
|
165
|
-
completed,
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
return acceptanceCriteria;
|
|
169
|
-
}
|
|
170
|
-
/**
|
|
171
|
-
* Build overview section
|
|
172
|
-
*/
|
|
173
|
-
buildOverviewSection(epic) {
|
|
174
|
-
return `# [${epic.id}] ${epic.title}\n\n**Status**: ${epic.status}\n**Created**: ${epic.created}\n**Last Updated**: ${epic.last_updated}`;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Build User Stories section
|
|
178
|
-
*/
|
|
179
|
-
buildUserStoriesSection(userStories) {
|
|
180
|
-
const total = userStories.length;
|
|
181
|
-
const completed = userStories.filter((us) => us.status === 'complete').length;
|
|
182
|
-
const percentage = total > 0 ? Math.round((completed / total) * 100) : 0;
|
|
183
|
-
let section = `## User Stories\n\nProgress: ${completed}/${total} user stories complete (${percentage}%)\n\n`;
|
|
184
|
-
for (const us of userStories) {
|
|
185
|
-
const checkbox = us.status === 'complete' ? '[x]' : '[ ]';
|
|
186
|
-
const statusEmoji = this.getStatusEmoji(us.status);
|
|
187
|
-
const incrementLink = us.increment
|
|
188
|
-
? `[${us.increment}](../../increments/${us.increment}/)`
|
|
189
|
-
: 'TBD';
|
|
190
|
-
section += `- ${checkbox} **${us.id}: ${us.title}** (${statusEmoji} ${us.status} | Increment: ${incrementLink})\n`;
|
|
191
|
-
// Add Acceptance Criteria checkboxes under each user story
|
|
192
|
-
if (us.acceptanceCriteria.length > 0) {
|
|
193
|
-
section += '\n **Acceptance Criteria**:\n';
|
|
194
|
-
for (const ac of us.acceptanceCriteria) {
|
|
195
|
-
const acCheckbox = ac.completed ? '[x]' : '[ ]';
|
|
196
|
-
section += ` - ${acCheckbox} **${ac.id}**: ${ac.description}\n`;
|
|
197
|
-
}
|
|
198
|
-
section += '\n';
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return section;
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Build Tasks section (grouped by User Story)
|
|
205
|
-
*/
|
|
206
|
-
buildTasksSection(userStories) {
|
|
207
|
-
const totalTasks = userStories.reduce((sum, us) => sum + us.tasks.length, 0);
|
|
208
|
-
const completedTasks = userStories.reduce((sum, us) => sum + us.tasks.filter((t) => t.status).length, 0);
|
|
209
|
-
const percentage = totalTasks > 0 ? Math.round((completedTasks / totalTasks) * 100) : 0;
|
|
210
|
-
let section = `## Tasks by User Story\n\nProgress: ${completedTasks}/${totalTasks} tasks complete (${percentage}%)\n\n`;
|
|
211
|
-
for (const us of userStories) {
|
|
212
|
-
if (us.tasks.length === 0) {
|
|
213
|
-
continue; // Skip user stories with no tasks yet
|
|
214
|
-
}
|
|
215
|
-
const incrementLink = us.increment
|
|
216
|
-
? `[${us.increment}](../../increments/${us.increment}/tasks.md)`
|
|
217
|
-
: 'TBD';
|
|
218
|
-
section += `### ${us.id}: ${us.title} (Increment: ${incrementLink})\n\n`;
|
|
219
|
-
for (const task of us.tasks) {
|
|
220
|
-
const checkbox = task.status ? '[x]' : '[ ]';
|
|
221
|
-
section += `- ${checkbox} ${task.id}: ${task.title}\n`;
|
|
222
|
-
}
|
|
223
|
-
section += '\n';
|
|
224
|
-
}
|
|
225
|
-
return section;
|
|
226
|
-
}
|
|
227
|
-
/**
|
|
228
|
-
* Normalize status values
|
|
229
|
-
*/
|
|
230
|
-
normalizeStatus(status) {
|
|
231
|
-
const normalized = status.toLowerCase();
|
|
232
|
-
if (normalized === 'complete' || normalized === 'completed')
|
|
233
|
-
return 'complete';
|
|
234
|
-
if (normalized === 'active' || normalized === 'in-progress')
|
|
235
|
-
return 'active';
|
|
236
|
-
if (normalized === 'planning')
|
|
237
|
-
return 'planning';
|
|
238
|
-
return 'not-started';
|
|
239
|
-
}
|
|
240
|
-
/**
|
|
241
|
-
* Get status emoji
|
|
242
|
-
*/
|
|
243
|
-
getStatusEmoji(status) {
|
|
244
|
-
switch (status) {
|
|
245
|
-
case 'complete':
|
|
246
|
-
return '✅';
|
|
247
|
-
case 'active':
|
|
248
|
-
return '🚧';
|
|
249
|
-
case 'planning':
|
|
250
|
-
return '📋';
|
|
251
|
-
case 'not-started':
|
|
252
|
-
return '⏳';
|
|
253
|
-
default:
|
|
254
|
-
return '❓';
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
//# sourceMappingURL=epic-content-builder.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"epic-content-builder.js","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/epic-content-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* GitHub Epic Sync - Hierarchical synchronization for Epic folder structure
|
|
3
|
-
*
|
|
4
|
-
* Architecture:
|
|
5
|
-
* - Epic (FS-001) → GitHub Milestone
|
|
6
|
-
* - Increment (0001-core-framework) → GitHub Issue (linked to Milestone)
|
|
7
|
-
*
|
|
8
|
-
* This implements the Universal Hierarchy architecture for GitHub.
|
|
9
|
-
*/
|
|
10
|
-
import { GitHubClientV2 } from './github-client-v2.js';
|
|
11
|
-
export declare class GitHubEpicSync {
|
|
12
|
-
private client;
|
|
13
|
-
private specsDir;
|
|
14
|
-
constructor(client: GitHubClientV2, specsDir: string);
|
|
15
|
-
/**
|
|
16
|
-
* Sync Epic folder to GitHub (Milestone + Issues)
|
|
17
|
-
*/
|
|
18
|
-
syncEpicToGitHub(epicId: string): Promise<{
|
|
19
|
-
milestoneNumber: number;
|
|
20
|
-
milestoneUrl: string;
|
|
21
|
-
issuesCreated: number;
|
|
22
|
-
issuesUpdated: number;
|
|
23
|
-
duplicatesDetected: number;
|
|
24
|
-
}>;
|
|
25
|
-
/**
|
|
26
|
-
* Validate sync results - check for duplicate issues
|
|
27
|
-
*
|
|
28
|
-
* Searches GitHub for all issues with the Epic ID and detects duplicates
|
|
29
|
-
* (multiple issues with the same title).
|
|
30
|
-
*
|
|
31
|
-
* @param epicId - Epic ID (e.g., FS-031)
|
|
32
|
-
* @returns Validation result with duplicate count and groups
|
|
33
|
-
*/
|
|
34
|
-
private validateSync;
|
|
35
|
-
/**
|
|
36
|
-
* Find existing GitHub issue for increment (duplicate detection!)
|
|
37
|
-
*
|
|
38
|
-
* Searches GitHub for issues matching the Epic ID and Increment ID.
|
|
39
|
-
* This prevents creating duplicates when frontmatter is lost/corrupted.
|
|
40
|
-
*
|
|
41
|
-
* @param epicId - Epic ID (e.g., FS-031)
|
|
42
|
-
* @param incrementId - Increment ID (e.g., 0031-feature-name)
|
|
43
|
-
* @returns GitHub issue number if found, null otherwise
|
|
44
|
-
*/
|
|
45
|
-
private findExistingIssue;
|
|
46
|
-
/**
|
|
47
|
-
* Find Epic folder by ID (FS-001 or just 001)
|
|
48
|
-
*/
|
|
49
|
-
private findEpicFolder;
|
|
50
|
-
/**
|
|
51
|
-
* Parse Epic FEATURE.md to extract frontmatter
|
|
52
|
-
*/
|
|
53
|
-
private parseEpicReadme;
|
|
54
|
-
/**
|
|
55
|
-
* Parse increment file to extract title and overview
|
|
56
|
-
*/
|
|
57
|
-
private parseIncrementFile;
|
|
58
|
-
/**
|
|
59
|
-
* Create GitHub Milestone
|
|
60
|
-
*/
|
|
61
|
-
private createMilestone;
|
|
62
|
-
/**
|
|
63
|
-
* Update GitHub Milestone
|
|
64
|
-
*/
|
|
65
|
-
private updateMilestone;
|
|
66
|
-
/**
|
|
67
|
-
* Create GitHub Issue for Epic with hierarchical content (US → Tasks)
|
|
68
|
-
*/
|
|
69
|
-
private createIssue;
|
|
70
|
-
/**
|
|
71
|
-
* Update GitHub Issue for Epic with hierarchical content (US → Tasks)
|
|
72
|
-
*/
|
|
73
|
-
private updateIssue;
|
|
74
|
-
/**
|
|
75
|
-
* Update Epic FEATURE.md with GitHub Milestone ID
|
|
76
|
-
*/
|
|
77
|
-
private updateEpicReadme;
|
|
78
|
-
/**
|
|
79
|
-
* Update increment external link in both Epic README and increment file
|
|
80
|
-
*/
|
|
81
|
-
private updateIncrementExternalLink;
|
|
82
|
-
}
|
|
83
|
-
//# sourceMappingURL=github-epic-sync.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"github-epic-sync.d.ts","sourceRoot":"","sources":["../../../../plugins/specweave-github/lib/github-epic-sync.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAMH,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAiEvD,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAAiB;IAC/B,OAAO,CAAC,QAAQ,CAAS;gBAEb,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM;IAKpD;;OAEG;IACG,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC;QAC9C,eAAe,EAAE,MAAM,CAAC;QACxB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,kBAAkB,EAAE,MAAM,CAAC;KAC5B,CAAC;IAwIF;;;;;;;;OAQG;YACW,YAAY;IA8D1B;;;;;;;;;OASG;YACW,iBAAiB;IAgE/B;;OAEG;YACW,cAAc;IAe5B;;OAEG;YACW,eAAe;IAc7B;;OAEG;YACW,kBAAkB;IAyChC;;OAEG;YACW,eAAe;IAqC7B;;OAEG;YACW,eAAe;IA4B7B;;OAEG;YACW,WAAW;IAmDzB;;OAEG;YACW,WAAW;IA6CzB;;OAEG;YACW,gBAAgB;IAuB9B;;OAEG;YACW,2BAA2B;CAuD1C"}
|