@lbruton/specflow 3.0.0 → 3.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +89 -0
- package/README.md +34 -26
- package/dist/core/__tests__/convention-detector.test.d.ts +2 -0
- package/dist/core/__tests__/convention-detector.test.d.ts.map +1 -0
- package/dist/core/__tests__/convention-detector.test.js +199 -0
- package/dist/core/__tests__/convention-detector.test.js.map +1 -0
- package/dist/core/__tests__/security-utils.test.js +2 -2
- package/dist/core/__tests__/security-utils.test.js.map +1 -1
- package/dist/core/__tests__/template-generator.test.d.ts +2 -0
- package/dist/core/__tests__/template-generator.test.d.ts.map +1 -0
- package/dist/core/__tests__/template-generator.test.js +167 -0
- package/dist/core/__tests__/template-generator.test.js.map +1 -0
- package/dist/core/convention-detector.d.ts +36 -0
- package/dist/core/convention-detector.d.ts.map +1 -0
- package/dist/core/convention-detector.js +298 -0
- package/dist/core/convention-detector.js.map +1 -0
- package/dist/core/project-registry.d.ts +6 -0
- package/dist/core/project-registry.d.ts.map +1 -1
- package/dist/core/project-registry.js +17 -1
- package/dist/core/project-registry.js.map +1 -1
- package/dist/core/security-utils.js +2 -2
- package/dist/core/security-utils.js.map +1 -1
- package/dist/core/template-generator.d.ts +21 -0
- package/dist/core/template-generator.d.ts.map +1 -0
- package/dist/core/template-generator.js +217 -0
- package/dist/core/template-generator.js.map +1 -0
- package/dist/markdown/templates/design-template.md +8 -6
- package/dist/markdown/templates/tasks-template.md +23 -20
- package/dist/prompts/index.d.ts.map +1 -1
- package/dist/prompts/index.js +3 -0
- package/dist/prompts/index.js.map +1 -1
- package/dist/tools/spec-status.d.ts.map +1 -1
- package/dist/tools/spec-status.js +35 -8
- package/dist/tools/spec-status.js.map +1 -1
- package/dist/tools/spec-workflow-guide.js +25 -15
- package/dist/tools/spec-workflow-guide.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
2
|
+
// Mock fs/promises before importing the module under test
|
|
3
|
+
vi.mock('fs/promises', () => ({
|
|
4
|
+
readFile: vi.fn(),
|
|
5
|
+
mkdir: vi.fn(),
|
|
6
|
+
writeFile: vi.fn(),
|
|
7
|
+
stat: vi.fn(),
|
|
8
|
+
}));
|
|
9
|
+
import { readFile, mkdir, writeFile, stat } from 'fs/promises';
|
|
10
|
+
import { generateUserTemplates, writeUserTemplates } from '../template-generator.js';
|
|
11
|
+
const mockReadFile = vi.mocked(readFile);
|
|
12
|
+
const mockMkdir = vi.mocked(mkdir);
|
|
13
|
+
const mockWriteFile = vi.mocked(writeFile);
|
|
14
|
+
const mockStat = vi.mocked(stat);
|
|
15
|
+
/** Helper: create a fake Stats for a file. */
|
|
16
|
+
function fakeFileStat() {
|
|
17
|
+
return { isFile: () => true, isDirectory: () => false };
|
|
18
|
+
}
|
|
19
|
+
/** Minimal design template with a Testing Strategy section. */
|
|
20
|
+
const MOCK_DESIGN_TEMPLATE = `# Design
|
|
21
|
+
|
|
22
|
+
## Architecture
|
|
23
|
+
[Architecture details]
|
|
24
|
+
|
|
25
|
+
## Testing Strategy
|
|
26
|
+
[Default testing strategy placeholder]
|
|
27
|
+
|
|
28
|
+
## Rollback Plan
|
|
29
|
+
[Rollback details]
|
|
30
|
+
`;
|
|
31
|
+
/** Minimal tasks template with a Standard Closing Tasks section. */
|
|
32
|
+
const MOCK_TASKS_TEMPLATE = `# Tasks
|
|
33
|
+
|
|
34
|
+
- [ ] 1. First task
|
|
35
|
+
- Do the thing
|
|
36
|
+
|
|
37
|
+
## Standard Closing Tasks
|
|
38
|
+
|
|
39
|
+
- [ ] 6. Default closing task
|
|
40
|
+
- Default details
|
|
41
|
+
`;
|
|
42
|
+
/** Build a conventions object with sensible defaults and overrides. */
|
|
43
|
+
function makeConventions(overrides = {}) {
|
|
44
|
+
return {
|
|
45
|
+
schemaVersion: 1,
|
|
46
|
+
detectedAt: '2026-04-03T00:00:00.000Z',
|
|
47
|
+
testing: {
|
|
48
|
+
framework: null,
|
|
49
|
+
command: null,
|
|
50
|
+
configFile: null,
|
|
51
|
+
testDir: null,
|
|
52
|
+
hasBrowserbase: false,
|
|
53
|
+
...overrides.testing,
|
|
54
|
+
},
|
|
55
|
+
versioning: {
|
|
56
|
+
hasVersionLock: false,
|
|
57
|
+
lockFile: null,
|
|
58
|
+
packageVersion: null,
|
|
59
|
+
userDeclinedSetup: false,
|
|
60
|
+
...overrides.versioning,
|
|
61
|
+
},
|
|
62
|
+
changelog: {
|
|
63
|
+
hasChangelog: false,
|
|
64
|
+
file: null,
|
|
65
|
+
format: null,
|
|
66
|
+
docvaultFallback: false,
|
|
67
|
+
...overrides.changelog,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
beforeEach(() => {
|
|
72
|
+
vi.resetAllMocks();
|
|
73
|
+
const enoent = Object.assign(new Error('ENOENT'), { code: 'ENOENT' });
|
|
74
|
+
mockStat.mockRejectedValue(enoent);
|
|
75
|
+
mockReadFile.mockRejectedValue(enoent);
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* Set up readFile to serve mock templates.
|
|
79
|
+
* readDefaultTemplate checks project .spec-workflow/templates/ first, then bundled.
|
|
80
|
+
* We simulate the bundled fallback by matching on the path containing 'markdown/templates/'.
|
|
81
|
+
*/
|
|
82
|
+
function setupTemplateReads() {
|
|
83
|
+
mockReadFile.mockImplementation(async (p) => {
|
|
84
|
+
const path = String(p);
|
|
85
|
+
if (path.includes('markdown/templates/design-template.md'))
|
|
86
|
+
return MOCK_DESIGN_TEMPLATE;
|
|
87
|
+
if (path.includes('markdown/templates/tasks-template.md'))
|
|
88
|
+
return MOCK_TASKS_TEMPLATE;
|
|
89
|
+
throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' });
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
describe('generateUserTemplates', () => {
|
|
93
|
+
it('should generate browserbase-specific templates', async () => {
|
|
94
|
+
setupTemplateReads();
|
|
95
|
+
const conventions = makeConventions({
|
|
96
|
+
testing: { hasBrowserbase: true, framework: 'bb-test', testDir: 'tests/runbook/' },
|
|
97
|
+
});
|
|
98
|
+
const result = await generateUserTemplates('/fake/project', conventions);
|
|
99
|
+
// Design template should contain Runbook E2E Tests section
|
|
100
|
+
expect(result.designTemplate).toContain('Runbook E2E Tests');
|
|
101
|
+
expect(result.designTemplate).toContain('tests/runbook/');
|
|
102
|
+
// Tasks template should contain /bb-test references
|
|
103
|
+
expect(result.tasksTemplate).toContain('/bb-test');
|
|
104
|
+
expect(result.tasksTemplate).toContain('runbook');
|
|
105
|
+
});
|
|
106
|
+
it('should generate vitest-specific templates', async () => {
|
|
107
|
+
setupTemplateReads();
|
|
108
|
+
const conventions = makeConventions({
|
|
109
|
+
testing: { framework: 'vitest', command: 'npx vitest', configFile: 'vitest.config.ts' },
|
|
110
|
+
});
|
|
111
|
+
const result = await generateUserTemplates('/fake/project', conventions);
|
|
112
|
+
// Should reference vitest
|
|
113
|
+
expect(result.designTemplate).toContain('vitest');
|
|
114
|
+
expect(result.tasksTemplate).toContain('npx vitest');
|
|
115
|
+
// Should NOT contain browserbase references
|
|
116
|
+
expect(result.designTemplate).not.toContain('bb-test');
|
|
117
|
+
expect(result.designTemplate).not.toContain('runbook');
|
|
118
|
+
expect(result.tasksTemplate).not.toContain('bb-test');
|
|
119
|
+
expect(result.tasksTemplate).not.toContain('Runbook');
|
|
120
|
+
});
|
|
121
|
+
it('should use generic fallbacks when all testing fields are null', async () => {
|
|
122
|
+
setupTemplateReads();
|
|
123
|
+
const conventions = makeConventions(); // all defaults (null)
|
|
124
|
+
const result = await generateUserTemplates('/fake/project', conventions);
|
|
125
|
+
// Should use generic fallback values
|
|
126
|
+
expect(result.designTemplate).toContain('npm test');
|
|
127
|
+
expect(result.designTemplate).toContain('tests/');
|
|
128
|
+
expect(result.tasksTemplate).toContain('npm test');
|
|
129
|
+
// Should NOT contain browserbase references
|
|
130
|
+
expect(result.designTemplate).not.toContain('bb-test');
|
|
131
|
+
expect(result.tasksTemplate).not.toContain('bb-test');
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
describe('writeUserTemplates', () => {
|
|
135
|
+
it('should not overwrite existing user-template files', async () => {
|
|
136
|
+
// Simulate that the design template already exists
|
|
137
|
+
mockStat.mockImplementation(async (p) => {
|
|
138
|
+
const path = String(p);
|
|
139
|
+
if (path.endsWith('user-templates/design-template.md'))
|
|
140
|
+
return fakeFileStat();
|
|
141
|
+
throw Object.assign(new Error('ENOENT'), { code: 'ENOENT' });
|
|
142
|
+
});
|
|
143
|
+
const templates = {
|
|
144
|
+
designTemplate: '# New design',
|
|
145
|
+
tasksTemplate: '# New tasks',
|
|
146
|
+
};
|
|
147
|
+
await writeUserTemplates('/fake/project', templates);
|
|
148
|
+
// Should NOT have written anything since a user-template already exists
|
|
149
|
+
expect(mockWriteFile).not.toHaveBeenCalled();
|
|
150
|
+
expect(mockMkdir).not.toHaveBeenCalled();
|
|
151
|
+
});
|
|
152
|
+
it('should write templates when no user-templates exist', async () => {
|
|
153
|
+
// All stat calls reject (no existing files) — default from beforeEach
|
|
154
|
+
mockMkdir.mockResolvedValue(undefined);
|
|
155
|
+
mockWriteFile.mockResolvedValue(undefined);
|
|
156
|
+
const templates = {
|
|
157
|
+
designTemplate: '# Generated design',
|
|
158
|
+
tasksTemplate: '# Generated tasks',
|
|
159
|
+
};
|
|
160
|
+
await writeUserTemplates('/fake/project', templates);
|
|
161
|
+
expect(mockMkdir).toHaveBeenCalledWith('/fake/project/.spec-workflow/user-templates', { recursive: true });
|
|
162
|
+
expect(mockWriteFile).toHaveBeenCalledTimes(2);
|
|
163
|
+
expect(mockWriteFile).toHaveBeenCalledWith('/fake/project/.spec-workflow/user-templates/design-template.md', '# Generated design', 'utf-8');
|
|
164
|
+
expect(mockWriteFile).toHaveBeenCalledWith('/fake/project/.spec-workflow/user-templates/tasks-template.md', '# Generated tasks', 'utf-8');
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
//# sourceMappingURL=template-generator.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-generator.test.js","sourceRoot":"","sources":["../../../src/core/__tests__/template-generator.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export interface ProjectConventions {
|
|
2
|
+
schemaVersion: 1;
|
|
3
|
+
detectedAt: string;
|
|
4
|
+
testing: {
|
|
5
|
+
framework: string | null;
|
|
6
|
+
command: string | null;
|
|
7
|
+
configFile: string | null;
|
|
8
|
+
testDir: string | null;
|
|
9
|
+
hasBrowserbase: boolean;
|
|
10
|
+
};
|
|
11
|
+
versioning: {
|
|
12
|
+
hasVersionLock: boolean;
|
|
13
|
+
lockFile: string | null;
|
|
14
|
+
packageVersion: string | null;
|
|
15
|
+
userDeclinedSetup: boolean;
|
|
16
|
+
};
|
|
17
|
+
changelog: {
|
|
18
|
+
hasChangelog: boolean;
|
|
19
|
+
file: string | null;
|
|
20
|
+
format: string | null;
|
|
21
|
+
docvaultFallback: boolean;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Scan a project directory and detect its testing, versioning, and changelog conventions.
|
|
26
|
+
*
|
|
27
|
+
* All filesystem errors are handled gracefully — missing files produce null values, never throw.
|
|
28
|
+
* Works on any project directory, including empty ones.
|
|
29
|
+
*/
|
|
30
|
+
export declare function detectConventions(projectPath: string): Promise<ProjectConventions>;
|
|
31
|
+
/**
|
|
32
|
+
* Write detected conventions to `.spec-workflow/project-conventions.json`.
|
|
33
|
+
* Creates the `.spec-workflow` directory if it does not exist.
|
|
34
|
+
*/
|
|
35
|
+
export declare function writeConventions(projectPath: string, conventions: ProjectConventions): Promise<void>;
|
|
36
|
+
//# sourceMappingURL=convention-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convention-detector.d.ts","sourceRoot":"","sources":["../../src/core/convention-detector.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,aAAa,EAAE,CAAC,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE;QACP,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;QACzB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;QACvB,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,UAAU,EAAE;QACV,cAAc,EAAE,OAAO,CAAC;QACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;QAC9B,iBAAiB,EAAE,OAAO,CAAC;KAC5B,CAAC;IACF,SAAS,EAAE;QACT,YAAY,EAAE,OAAO,CAAC;QACtB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;QACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;QACtB,gBAAgB,EAAE,OAAO,CAAC;KAC3B,CAAC;CACH;AAyRD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAcxF;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,WAAW,EAAE,MAAM,EAAE,WAAW,EAAE,kBAAkB,GAAG,OAAO,CAAC,IAAI,CAAC,CAS1G"}
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
import { readFile, readdir, stat, mkdir, writeFile } from 'fs/promises';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
/** Safely read a file, returning null on any error. */
|
|
4
|
+
async function safeReadFile(filePath) {
|
|
5
|
+
try {
|
|
6
|
+
return await readFile(filePath, 'utf-8');
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Check if a path exists and is a directory. */
|
|
13
|
+
async function isDirectory(dirPath) {
|
|
14
|
+
try {
|
|
15
|
+
const s = await stat(dirPath);
|
|
16
|
+
return s.isDirectory();
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
/** Check if a file exists. */
|
|
23
|
+
async function fileExists(filePath) {
|
|
24
|
+
try {
|
|
25
|
+
const s = await stat(filePath);
|
|
26
|
+
return s.isFile();
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
return false;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Find the first existing file from a list of candidates. Returns the relative path or null. */
|
|
33
|
+
async function findFirstFile(projectPath, candidates) {
|
|
34
|
+
for (const candidate of candidates) {
|
|
35
|
+
if (await fileExists(join(projectPath, candidate))) {
|
|
36
|
+
return candidate;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
/** Detect testing framework, command, config file, test directory, and browserbase usage. */
|
|
42
|
+
async function detectTesting(projectPath) {
|
|
43
|
+
let framework = null;
|
|
44
|
+
let command = null;
|
|
45
|
+
let configFile = null;
|
|
46
|
+
let testDir = null;
|
|
47
|
+
let hasBrowserbase = false;
|
|
48
|
+
// --- Framework detection (priority order) ---
|
|
49
|
+
// Vitest
|
|
50
|
+
const vitestConfigs = [
|
|
51
|
+
'vitest.config.ts', 'vitest.config.js', 'vitest.config.mts', 'vitest.config.mjs',
|
|
52
|
+
];
|
|
53
|
+
const vitestConfig = await findFirstFile(projectPath, vitestConfigs);
|
|
54
|
+
if (vitestConfig) {
|
|
55
|
+
framework = 'vitest';
|
|
56
|
+
command = 'npx vitest';
|
|
57
|
+
configFile = vitestConfig;
|
|
58
|
+
}
|
|
59
|
+
// Jest (only if vitest not found)
|
|
60
|
+
if (!framework) {
|
|
61
|
+
const jestConfigs = [
|
|
62
|
+
'jest.config.ts', 'jest.config.js', 'jest.config.mjs', 'jest.config.cjs', 'jest.config.json',
|
|
63
|
+
];
|
|
64
|
+
const jestConfig = await findFirstFile(projectPath, jestConfigs);
|
|
65
|
+
if (jestConfig) {
|
|
66
|
+
framework = 'jest';
|
|
67
|
+
command = 'npx jest';
|
|
68
|
+
configFile = jestConfig;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// Pytest
|
|
72
|
+
if (!framework) {
|
|
73
|
+
const pytestConfigs = ['pytest.ini', 'pyproject.toml', 'setup.cfg'];
|
|
74
|
+
for (const candidate of pytestConfigs) {
|
|
75
|
+
const content = await safeReadFile(join(projectPath, candidate));
|
|
76
|
+
if (content !== null) {
|
|
77
|
+
// For pyproject.toml and setup.cfg, check for pytest section
|
|
78
|
+
if (candidate === 'pytest.ini') {
|
|
79
|
+
framework = 'pytest';
|
|
80
|
+
command = 'pytest';
|
|
81
|
+
configFile = candidate;
|
|
82
|
+
break;
|
|
83
|
+
}
|
|
84
|
+
if (candidate === 'pyproject.toml' && content.includes('[tool.pytest')) {
|
|
85
|
+
framework = 'pytest';
|
|
86
|
+
command = 'pytest';
|
|
87
|
+
configFile = candidate;
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
if (candidate === 'setup.cfg' && content.includes('[tool:pytest]')) {
|
|
91
|
+
framework = 'pytest';
|
|
92
|
+
command = 'pytest';
|
|
93
|
+
configFile = candidate;
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Mocha (check package.json devDependencies or config files)
|
|
100
|
+
if (!framework) {
|
|
101
|
+
const mochaConfigs = ['.mocharc.yml', '.mocharc.yaml', '.mocharc.js', '.mocharc.json', '.mocharc.cjs'];
|
|
102
|
+
const mochaConfig = await findFirstFile(projectPath, mochaConfigs);
|
|
103
|
+
if (mochaConfig) {
|
|
104
|
+
framework = 'mocha';
|
|
105
|
+
command = 'npx mocha';
|
|
106
|
+
configFile = mochaConfig;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// package.json scripts.test fallback
|
|
110
|
+
if (!framework) {
|
|
111
|
+
const pkgContent = await safeReadFile(join(projectPath, 'package.json'));
|
|
112
|
+
if (pkgContent) {
|
|
113
|
+
try {
|
|
114
|
+
const pkg = JSON.parse(pkgContent);
|
|
115
|
+
const testScript = pkg?.scripts?.test;
|
|
116
|
+
if (testScript) {
|
|
117
|
+
// Infer framework from test script content
|
|
118
|
+
if (testScript.includes('vitest')) {
|
|
119
|
+
framework = 'vitest';
|
|
120
|
+
configFile = 'package.json';
|
|
121
|
+
}
|
|
122
|
+
else if (testScript.includes('jest')) {
|
|
123
|
+
framework = 'jest';
|
|
124
|
+
configFile = 'package.json';
|
|
125
|
+
}
|
|
126
|
+
else if (testScript.includes('mocha')) {
|
|
127
|
+
framework = 'mocha';
|
|
128
|
+
configFile = 'package.json';
|
|
129
|
+
}
|
|
130
|
+
else if (testScript.includes('pytest')) {
|
|
131
|
+
framework = 'pytest';
|
|
132
|
+
configFile = 'package.json';
|
|
133
|
+
}
|
|
134
|
+
command = testScript.startsWith('npm') ? testScript : `npm test`;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
// Invalid JSON — ignore
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
// --- Browserbase / bb-test detection ---
|
|
143
|
+
const runbookDir = join(projectPath, 'tests', 'runbook');
|
|
144
|
+
if (await isDirectory(runbookDir)) {
|
|
145
|
+
hasBrowserbase = true;
|
|
146
|
+
if (!framework) {
|
|
147
|
+
framework = 'bb-test';
|
|
148
|
+
testDir = 'tests/runbook/';
|
|
149
|
+
// Count runbook sections for the command hint
|
|
150
|
+
try {
|
|
151
|
+
const entries = await readdir(runbookDir);
|
|
152
|
+
const sections = entries.filter(e => !e.startsWith('.')).length;
|
|
153
|
+
command = `/bb-test sections=${sections}`;
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
command = '/bb-test';
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Check CLAUDE.md for bb-test references
|
|
161
|
+
if (!hasBrowserbase) {
|
|
162
|
+
const claudeMd = await safeReadFile(join(projectPath, 'CLAUDE.md'));
|
|
163
|
+
if (claudeMd && (claudeMd.includes('/bb-test') || claudeMd.includes('bb-test'))) {
|
|
164
|
+
hasBrowserbase = true;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
// --- Test directory detection ---
|
|
168
|
+
if (!testDir) {
|
|
169
|
+
const testDirCandidates = [
|
|
170
|
+
'src/__tests__',
|
|
171
|
+
'tests/',
|
|
172
|
+
'test/',
|
|
173
|
+
'__tests__/',
|
|
174
|
+
];
|
|
175
|
+
for (const candidate of testDirCandidates) {
|
|
176
|
+
const candidatePath = join(projectPath, candidate.replace(/\/$/, ''));
|
|
177
|
+
if (await isDirectory(candidatePath)) {
|
|
178
|
+
testDir = candidate;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return { framework, command, configFile, testDir, hasBrowserbase };
|
|
184
|
+
}
|
|
185
|
+
/** Detect versioning conventions. */
|
|
186
|
+
async function detectVersioning(projectPath) {
|
|
187
|
+
let hasVersionLock = false;
|
|
188
|
+
let lockFile = null;
|
|
189
|
+
let packageVersion = null;
|
|
190
|
+
const userDeclinedSetup = false;
|
|
191
|
+
// Check devops/version.lock
|
|
192
|
+
const versionLockPath = join(projectPath, 'devops', 'version.lock');
|
|
193
|
+
if (await fileExists(versionLockPath)) {
|
|
194
|
+
hasVersionLock = true;
|
|
195
|
+
lockFile = 'devops/version.lock';
|
|
196
|
+
}
|
|
197
|
+
// Check package.json version
|
|
198
|
+
const pkgContent = await safeReadFile(join(projectPath, 'package.json'));
|
|
199
|
+
if (pkgContent) {
|
|
200
|
+
try {
|
|
201
|
+
const pkg = JSON.parse(pkgContent);
|
|
202
|
+
if (pkg?.version && typeof pkg.version === 'string') {
|
|
203
|
+
packageVersion = pkg.version;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
catch {
|
|
207
|
+
// Invalid JSON — ignore
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Check .version file
|
|
211
|
+
if (!hasVersionLock && !packageVersion) {
|
|
212
|
+
const dotVersionPath = join(projectPath, '.version');
|
|
213
|
+
const dotVersion = await safeReadFile(dotVersionPath);
|
|
214
|
+
if (dotVersion !== null) {
|
|
215
|
+
hasVersionLock = true;
|
|
216
|
+
lockFile = '.version';
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return { hasVersionLock, lockFile, packageVersion, userDeclinedSetup };
|
|
220
|
+
}
|
|
221
|
+
/** Detect changelog presence and format. */
|
|
222
|
+
async function detectChangelog(projectPath) {
|
|
223
|
+
let hasChangelog = false;
|
|
224
|
+
let file = null;
|
|
225
|
+
let format = null;
|
|
226
|
+
const docvaultFallback = false;
|
|
227
|
+
const changelogCandidates = ['CHANGELOG.md', 'CHANGES.md', 'HISTORY.md'];
|
|
228
|
+
for (const candidate of changelogCandidates) {
|
|
229
|
+
const content = await safeReadFile(join(projectPath, candidate));
|
|
230
|
+
if (content !== null) {
|
|
231
|
+
hasChangelog = true;
|
|
232
|
+
file = candidate;
|
|
233
|
+
format = detectChangelogFormat(content);
|
|
234
|
+
break;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
return { hasChangelog, file, format, docvaultFallback };
|
|
238
|
+
}
|
|
239
|
+
/** Detect changelog format from file content (reads first ~20 lines). */
|
|
240
|
+
function detectChangelogFormat(content) {
|
|
241
|
+
const lines = content.split('\n').slice(0, 20);
|
|
242
|
+
const header = lines.join('\n');
|
|
243
|
+
// keepachangelog: has ## [Unreleased] or ## [X.Y.Z] with Added/Changed/Fixed sections
|
|
244
|
+
const hasVersionHeaders = /## \[(Unreleased|\d+\.\d+\.\d+)]/i.test(header);
|
|
245
|
+
const hasSections = /(### (Added|Changed|Deprecated|Removed|Fixed|Security))/i.test(header);
|
|
246
|
+
if (hasVersionHeaders && hasSections) {
|
|
247
|
+
return 'keepachangelog';
|
|
248
|
+
}
|
|
249
|
+
// Also match keepachangelog if just the version header pattern is present with the right title
|
|
250
|
+
if (hasVersionHeaders && /keep.?a.?changelog/i.test(header)) {
|
|
251
|
+
return 'keepachangelog';
|
|
252
|
+
}
|
|
253
|
+
// conventional-changelog: typically starts with # followed by version + date and has commit-style entries
|
|
254
|
+
if (/^#+ \d+\.\d+\.\d+/m.test(header) && /\* \*\*\w+:\*\*/m.test(header)) {
|
|
255
|
+
return 'conventional';
|
|
256
|
+
}
|
|
257
|
+
// If it has version headers but doesn't match the above patterns
|
|
258
|
+
if (hasVersionHeaders) {
|
|
259
|
+
return 'keepachangelog';
|
|
260
|
+
}
|
|
261
|
+
return 'custom';
|
|
262
|
+
}
|
|
263
|
+
/**
|
|
264
|
+
* Scan a project directory and detect its testing, versioning, and changelog conventions.
|
|
265
|
+
*
|
|
266
|
+
* All filesystem errors are handled gracefully — missing files produce null values, never throw.
|
|
267
|
+
* Works on any project directory, including empty ones.
|
|
268
|
+
*/
|
|
269
|
+
export async function detectConventions(projectPath) {
|
|
270
|
+
const [testing, versioning, changelog] = await Promise.all([
|
|
271
|
+
detectTesting(projectPath),
|
|
272
|
+
detectVersioning(projectPath),
|
|
273
|
+
detectChangelog(projectPath),
|
|
274
|
+
]);
|
|
275
|
+
return {
|
|
276
|
+
schemaVersion: 1,
|
|
277
|
+
detectedAt: new Date().toISOString(),
|
|
278
|
+
testing,
|
|
279
|
+
versioning,
|
|
280
|
+
changelog,
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
/**
|
|
284
|
+
* Write detected conventions to `.spec-workflow/project-conventions.json`.
|
|
285
|
+
* Creates the `.spec-workflow` directory if it does not exist.
|
|
286
|
+
*/
|
|
287
|
+
export async function writeConventions(projectPath, conventions) {
|
|
288
|
+
const dir = join(projectPath, '.spec-workflow');
|
|
289
|
+
try {
|
|
290
|
+
await mkdir(dir, { recursive: true });
|
|
291
|
+
}
|
|
292
|
+
catch {
|
|
293
|
+
// Directory may already exist — ignore
|
|
294
|
+
}
|
|
295
|
+
const filePath = join(dir, 'project-conventions.json');
|
|
296
|
+
await writeFile(filePath, JSON.stringify(conventions, null, 2) + '\n', 'utf-8');
|
|
297
|
+
}
|
|
298
|
+
//# sourceMappingURL=convention-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"convention-detector.js","sourceRoot":"","sources":["../../src/core/convention-detector.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AA0B5B,uDAAuD;AACvD,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC1C,IAAI,CAAC;QACH,OAAO,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,iDAAiD;AACjD,KAAK,UAAU,WAAW,CAAC,OAAe;IACxC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,CAAC;QAC9B,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,8BAA8B;AAC9B,KAAK,UAAU,UAAU,CAAC,QAAgB;IACxC,IAAI,CAAC;QACH,MAAM,CAAC,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAC;QAC/B,OAAO,CAAC,CAAC,MAAM,EAAE,CAAC;IACpB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,iGAAiG;AACjG,KAAK,UAAU,aAAa,CAAC,WAAmB,EAAE,UAAoB;IACpE,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;QACnC,IAAI,MAAM,UAAU,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC;YACnD,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,6FAA6F;AAC7F,KAAK,UAAU,aAAa,CAAC,WAAmB;IAC9C,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,IAAI,UAAU,GAAkB,IAAI,CAAC;IACrC,IAAI,OAAO,GAAkB,IAAI,CAAC;IAClC,IAAI,cAAc,GAAG,KAAK,CAAC;IAE3B,+CAA+C;IAE/C,SAAS;IACT,MAAM,aAAa,GAAG;QACpB,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,mBAAmB;KACjF,CAAC;IACF,MAAM,YAAY,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,aAAa,CAAC,CAAC;IACrE,IAAI,YAAY,EAAE,CAAC;QACjB,SAAS,GAAG,QAAQ,CAAC;QACrB,OAAO,GAAG,YAAY,CAAC;QACvB,UAAU,GAAG,YAAY,CAAC;IAC5B,CAAC;IAED,kCAAkC;IAClC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,WAAW,GAAG;YAClB,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,kBAAkB;SAC7F,CAAC;QACF,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACjE,IAAI,UAAU,EAAE,CAAC;YACf,SAAS,GAAG,MAAM,CAAC;YACnB,OAAO,GAAG,UAAU,CAAC;YACrB,UAAU,GAAG,UAAU,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,SAAS;IACT,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,aAAa,GAAG,CAAC,YAAY,EAAE,gBAAgB,EAAE,WAAW,CAAC,CAAC;QACpE,KAAK,MAAM,SAAS,IAAI,aAAa,EAAE,CAAC;YACtC,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;YACjE,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;gBACrB,6DAA6D;gBAC7D,IAAI,SAAS,KAAK,YAAY,EAAE,CAAC;oBAC/B,SAAS,GAAG,QAAQ,CAAC;oBACrB,OAAO,GAAG,QAAQ,CAAC;oBACnB,UAAU,GAAG,SAAS,CAAC;oBACvB,MAAM;gBACR,CAAC;gBACD,IAAI,SAAS,KAAK,gBAAgB,IAAI,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;oBACvE,SAAS,GAAG,QAAQ,CAAC;oBACrB,OAAO,GAAG,QAAQ,CAAC;oBACnB,UAAU,GAAG,SAAS,CAAC;oBACvB,MAAM;gBACR,CAAC;gBACD,IAAI,SAAS,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;oBACnE,SAAS,GAAG,QAAQ,CAAC;oBACrB,OAAO,GAAG,QAAQ,CAAC;oBACnB,UAAU,GAAG,SAAS,CAAC;oBACvB,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,YAAY,GAAG,CAAC,cAAc,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,cAAc,CAAC,CAAC;QACvG,MAAM,WAAW,GAAG,MAAM,aAAa,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;QACnE,IAAI,WAAW,EAAE,CAAC;YAChB,SAAS,GAAG,OAAO,CAAC;YACpB,OAAO,GAAG,WAAW,CAAC;YACtB,UAAU,GAAG,WAAW,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,qCAAqC;IACrC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;QACzE,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;gBACnC,MAAM,UAAU,GAAuB,GAAG,EAAE,OAAO,EAAE,IAAI,CAAC;gBAC1D,IAAI,UAAU,EAAE,CAAC;oBACf,2CAA2C;oBAC3C,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;wBAClC,SAAS,GAAG,QAAQ,CAAC;wBACrB,UAAU,GAAG,cAAc,CAAC;oBAC9B,CAAC;yBAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;wBACvC,SAAS,GAAG,MAAM,CAAC;wBACnB,UAAU,GAAG,cAAc,CAAC;oBAC9B,CAAC;yBAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;wBACxC,SAAS,GAAG,OAAO,CAAC;wBACpB,UAAU,GAAG,cAAc,CAAC;oBAC9B,CAAC;yBAAM,IAAI,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;wBACzC,SAAS,GAAG,QAAQ,CAAC;wBACrB,UAAU,GAAG,cAAc,CAAC;oBAC9B,CAAC;oBACD,OAAO,GAAG,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;gBACnE,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,wBAAwB;YAC1B,CAAC;QACH,CAAC;IACH,CAAC;IAED,0CAA0C;IAC1C,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;IACzD,IAAI,MAAM,WAAW,CAAC,UAAU,CAAC,EAAE,CAAC;QAClC,cAAc,GAAG,IAAI,CAAC;QACtB,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,SAAS,GAAG,SAAS,CAAC;YACtB,OAAO,GAAG,gBAAgB,CAAC;YAC3B,8CAA8C;YAC9C,IAAI,CAAC;gBACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,UAAU,CAAC,CAAC;gBAC1C,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;gBAChE,OAAO,GAAG,qBAAqB,QAAQ,EAAE,CAAC;YAC5C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,GAAG,UAAU,CAAC;YACvB,CAAC;QACH,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC,CAAC;QACpE,IAAI,QAAQ,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC;YAChF,cAAc,GAAG,IAAI,CAAC;QACxB,CAAC;IACH,CAAC;IAED,mCAAmC;IACnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,iBAAiB,GAAG;YACxB,eAAe;YACf,QAAQ;YACR,OAAO;YACP,YAAY;SACb,CAAC;QACF,KAAK,MAAM,SAAS,IAAI,iBAAiB,EAAE,CAAC;YAC1C,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;YACtE,IAAI,MAAM,WAAW,CAAC,aAAa,CAAC,EAAE,CAAC;gBACrC,OAAO,GAAG,SAAS,CAAC;gBACpB,MAAM;YACR,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;AACrE,CAAC;AAED,qCAAqC;AACrC,KAAK,UAAU,gBAAgB,CAAC,WAAmB;IACjD,IAAI,cAAc,GAAG,KAAK,CAAC;IAC3B,IAAI,QAAQ,GAAkB,IAAI,CAAC;IACnC,IAAI,cAAc,GAAkB,IAAI,CAAC;IACzC,MAAM,iBAAiB,GAAG,KAAK,CAAC;IAEhC,4BAA4B;IAC5B,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;IACpE,IAAI,MAAM,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QACtC,cAAc,GAAG,IAAI,CAAC;QACtB,QAAQ,GAAG,qBAAqB,CAAC;IACnC,CAAC;IAED,6BAA6B;IAC7B,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC,CAAC;IACzE,IAAI,UAAU,EAAE,CAAC;QACf,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;YACnC,IAAI,GAAG,EAAE,OAAO,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ,EAAE,CAAC;gBACpD,cAAc,GAAG,GAAG,CAAC,OAAO,CAAC;YAC/B,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wBAAwB;QAC1B,CAAC;IACH,CAAC;IAED,sBAAsB;IACtB,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,EAAE,CAAC;QACvC,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,CAAC;QACrD,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,cAAc,CAAC,CAAC;QACtD,IAAI,UAAU,KAAK,IAAI,EAAE,CAAC;YACxB,cAAc,GAAG,IAAI,CAAC;YACtB,QAAQ,GAAG,UAAU,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,EAAE,CAAC;AACzE,CAAC;AAED,4CAA4C;AAC5C,KAAK,UAAU,eAAe,CAAC,WAAmB;IAChD,IAAI,YAAY,GAAG,KAAK,CAAC;IACzB,IAAI,IAAI,GAAkB,IAAI,CAAC;IAC/B,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,MAAM,gBAAgB,GAAG,KAAK,CAAC;IAE/B,MAAM,mBAAmB,GAAG,CAAC,cAAc,EAAE,YAAY,EAAE,YAAY,CAAC,CAAC;IACzE,KAAK,MAAM,SAAS,IAAI,mBAAmB,EAAE,CAAC;QAC5C,MAAM,OAAO,GAAG,MAAM,YAAY,CAAC,IAAI,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC,CAAC;QACjE,IAAI,OAAO,KAAK,IAAI,EAAE,CAAC;YACrB,YAAY,GAAG,IAAI,CAAC;YACpB,IAAI,GAAG,SAAS,CAAC;YACjB,MAAM,GAAG,qBAAqB,CAAC,OAAO,CAAC,CAAC;YACxC,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC;AAC1D,CAAC;AAED,yEAAyE;AACzE,SAAS,qBAAqB,CAAC,OAAe;IAC5C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC/C,MAAM,MAAM,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEhC,sFAAsF;IACtF,MAAM,iBAAiB,GAAG,mCAAmC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC3E,MAAM,WAAW,GAAG,0DAA0D,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC5F,IAAI,iBAAiB,IAAI,WAAW,EAAE,CAAC;QACrC,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IACD,+FAA+F;IAC/F,IAAI,iBAAiB,IAAI,qBAAqB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC5D,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,0GAA0G;IAC1G,IAAI,oBAAoB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,kBAAkB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACzE,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,iEAAiE;IACjE,IAAI,iBAAiB,EAAE,CAAC;QACtB,OAAO,gBAAgB,CAAC;IAC1B,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,WAAmB;IACzD,MAAM,CAAC,OAAO,EAAE,UAAU,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACzD,aAAa,CAAC,WAAW,CAAC;QAC1B,gBAAgB,CAAC,WAAW,CAAC;QAC7B,eAAe,CAAC,WAAW,CAAC;KAC7B,CAAC,CAAC;IAEH,OAAO;QACL,aAAa,EAAE,CAAC;QAChB,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,OAAO;QACP,UAAU;QACV,SAAS;KACV,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,WAAmB,EAAE,WAA+B;IACzF,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAChD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IAAC,MAAM,CAAC;QACP,uCAAuC;IACzC,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,0BAA0B,CAAC,CAAC;IACvD,MAAM,SAAS,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,OAAO,CAAC,CAAC;AAClF,CAAC"}
|
|
@@ -48,6 +48,12 @@ export declare class ProjectRegistry {
|
|
|
48
48
|
* so we assume processes are alive if path translation is enabled.
|
|
49
49
|
*/
|
|
50
50
|
private isProcessAlive;
|
|
51
|
+
/**
|
|
52
|
+
* Check if a path is under one of the configured project roots.
|
|
53
|
+
* SPEC_WORKFLOW_PROJECT_ROOT accepts colon-separated paths.
|
|
54
|
+
* Returns true (allow) when no root is configured.
|
|
55
|
+
*/
|
|
56
|
+
private isUnderProjectRoot;
|
|
51
57
|
/**
|
|
52
58
|
* Register a project in the global registry
|
|
53
59
|
* Self-healing: If a project exists with dead PIDs, cleans them up and adds new PID
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-registry.d.ts","sourceRoot":"","sources":["../../src/core/project-registry.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CASlG;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,mBAAmB,CAAkB;;IAO7C;;OAEG;YACW,iBAAiB;IAkB/B;;;OAGG;YACW,YAAY;IA0D1B;;OAEG;YACW,aAAa;IAY3B;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAkBtB;;;;OAIG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"project-registry.d.ts","sourceRoot":"","sources":["../../src/core/project-registry.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB;IACrC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,CAI9D;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,aAAa,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CASlG;AAED,qBAAa,eAAe;IAC1B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,mBAAmB,CAAkB;;IAO7C;;OAEG;YACW,iBAAiB;IAkB/B;;;OAGG;YACW,YAAY;IA0D1B;;OAEG;YACW,aAAa;IAY3B;;;;OAIG;IACH,OAAO,CAAC,cAAc;IAkBtB;;;;OAIG;IACH,OAAO,CAAC,kBAAkB;IAQ1B;;;;OAIG;IACG,eAAe,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,sBAA2B,GAAG,OAAO,CAAC,MAAM,CAAC;IA8C9G;;;;OAIG;IACG,iBAAiB,CAAC,WAAW,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAwBzE;;OAEG;IACG,qBAAqB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM7D;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAKvD;;OAEG;IACG,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAO3E;;OAEG;IACG,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,GAAG,IAAI,CAAC;IAK7E;;;;OAIG;IACG,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IA6B7C;;OAEG;IACG,mBAAmB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAOhE;;OAEG;IACH,eAAe,IAAI,MAAM;CAG1B"}
|
|
@@ -147,14 +147,30 @@ export class ProjectRegistry {
|
|
|
147
147
|
return false;
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Check if a path is under one of the configured project roots.
|
|
152
|
+
* SPEC_WORKFLOW_PROJECT_ROOT accepts colon-separated paths.
|
|
153
|
+
* Returns true (allow) when no root is configured.
|
|
154
|
+
*/
|
|
155
|
+
isUnderProjectRoot(absolutePath) {
|
|
156
|
+
const rootEnv = process.env.SPEC_WORKFLOW_PROJECT_ROOT;
|
|
157
|
+
if (!rootEnv)
|
|
158
|
+
return true;
|
|
159
|
+
const roots = rootEnv.split(':').map(r => resolve(r.trim())).filter(Boolean);
|
|
160
|
+
return roots.some(root => absolutePath.startsWith(root));
|
|
161
|
+
}
|
|
150
162
|
/**
|
|
151
163
|
* Register a project in the global registry
|
|
152
164
|
* Self-healing: If a project exists with dead PIDs, cleans them up and adds new PID
|
|
153
165
|
* Multi-instance: Allows unlimited MCP server instances per project
|
|
154
166
|
*/
|
|
155
167
|
async registerProject(projectPath, pid, options = {}) {
|
|
156
|
-
const registry = await this.readRegistry();
|
|
157
168
|
const workspacePath = resolve(projectPath);
|
|
169
|
+
// Skip registration for paths outside configured project root(s)
|
|
170
|
+
if (!this.isUnderProjectRoot(workspacePath)) {
|
|
171
|
+
return generateProjectId(workspacePath);
|
|
172
|
+
}
|
|
173
|
+
const registry = await this.readRegistry();
|
|
158
174
|
const workflowRootPath = resolve(options.workflowRootPath || projectPath);
|
|
159
175
|
const projectId = generateProjectId(workspacePath);
|
|
160
176
|
const projectName = options.projectName || generateProjectDisplayName(workspacePath, workflowRootPath);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-registry.js","sourceRoot":"","sources":["../../src/core/project-registry.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"project-registry.js","sourceRoot":"","sources":["../../src/core/project-registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AAoBvE;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,YAAoB;IACpD,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;IACzE,2CAA2C;IAC3C,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,0BAA0B,CAAC,aAAqB,EAAE,gBAAwB;IACxF,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,CAAC;IAC9C,MAAM,QAAQ,GAAG,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IAE5C,IAAI,aAAa,KAAK,gBAAgB,EAAE,CAAC;QACvC,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,OAAO,GAAG,QAAQ,MAAM,aAAa,EAAE,CAAC;AAC1C,CAAC;AAED,MAAM,OAAO,eAAe;IAClB,YAAY,CAAS;IACrB,WAAW,CAAS;IACpB,mBAAmB,GAAY,KAAK,CAAC;IAE7C;QACE,IAAI,CAAC,WAAW,GAAG,YAAY,EAAE,CAAC;QAClC,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,qBAAqB,CAAC,CAAC;IACpE,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB;QAC7B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,sDAAsD;YACtD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO;YACT,CAAC;YACD,kDAAkD;YAClD,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACtD,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,kBAAkB,EAAE,IAAI,CAAC,WAAW,CAAC,CAAC,CAAC;gBAC5E,MAAM,KAAK,CAAC;YACd,CAAC;YACD,wBAAwB;YACxB,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,YAAY;QACxB,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;YAC9D,wCAAwC;YACxC,MAAM,cAAc,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,cAAc,EAAE,CAAC;gBACpB,OAAO,CAAC,KAAK,CAAC,8BAA8B,IAAI,CAAC,YAAY,6CAA6C,CAAC,CAAC;gBAC5G,sCAAsC;gBACtC,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;gBAChC,OAAO,IAAI,GAAG,EAAE,CAAC;YACnB,CAAC;YACD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,cAAc,CAAyC,CAAC;YAChF,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAgC,CAAC;YAEzD,oDAAoD;YACpD,6BAA6B;YAC7B,oCAAoC;YACpC,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACtD,MAAM,qBAAqB,GAAG,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;gBACzD,MAAM,0BAA0B,GAAG,OAAO,CAAC,KAAK,CAAC,gBAAgB,IAAI,KAAK,CAAC,WAAW,CAAC,CAAC;gBAExF,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE;oBACtB,GAAG,KAAK;oBACR,WAAW,EAAE,qBAAqB;oBAClC,gBAAgB,EAAE,0BAA0B;oBAC5C,WAAW,EAAE,KAAK,CAAC,WAAW,IAAI,0BAA0B,CAAC,qBAAqB,EAAE,0BAA0B,CAAC;oBAC/G,SAAS,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE;iBACjE,CAAC,CAAC;YACL,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC5B,2CAA2C;gBAC3C,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;gBAChC,OAAO,IAAI,GAAG,EAAE,CAAC;YACnB,CAAC;YACD,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;gBACjC,oDAAoD;gBACpD,OAAO,CAAC,KAAK,CAAC,4CAA4C,IAAI,CAAC,YAAY,KAAK,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;gBACjG,OAAO,CAAC,KAAK,CAAC,gFAAgF,CAAC,CAAC;gBAChG,6BAA6B;gBAC7B,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,GAAG,IAAI,CAAC,YAAY,cAAc,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC;oBAClE,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;oBACjD,OAAO,CAAC,KAAK,CAAC,kDAAkD,UAAU,EAAE,CAAC,CAAC;gBAChF,CAAC;gBAAC,OAAO,WAAW,EAAE,CAAC;oBACrB,uBAAuB;gBACzB,CAAC;gBACD,IAAI,CAAC,mBAAmB,GAAG,IAAI,CAAC;gBAChC,OAAO,IAAI,GAAG,EAAE,CAAC;YACnB,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CAAC,QAA2C;QACrE,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE/B,MAAM,IAAI,GAAG,MAAM,CAAC,WAAW,CAAC,QAAQ,CAAC,CAAC;QAC1C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAE9C,kEAAkE;QAClE,MAAM,QAAQ,GAAG,GAAG,IAAI,CAAC,YAAY,MAAM,CAAC;QAC5C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QAC/C,MAAM,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/C,CAAC;IAED;;;;OAIG;IACK,cAAc,CAAC,GAAW;QAChC,4EAA4E;QAC5E,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC;QAC9D,MAAM,eAAe,GAAG,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC;QACxE,IAAI,UAAU,IAAI,eAAe,EAAE,CAAC;YAClC,0DAA0D;YAC1D,OAAO,IAAI,CAAC;QACd,CAAC;QAED,IAAI,CAAC;YACH,8EAA8E;YAC9E,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACrB,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;;;OAIG;IACK,kBAAkB,CAAC,YAAoB;QAC7C,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC;QACvD,IAAI,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QAE1B,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;QAC7E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,eAAe,CAAC,WAAmB,EAAE,GAAW,EAAE,UAAkC,EAAE;QAC1F,MAAM,aAAa,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAE3C,iEAAiE;QACjE,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,aAAa,CAAC,EAAE,CAAC;YAC5C,OAAO,iBAAiB,CAAC,aAAa,CAAC,CAAC;QAC1C,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,MAAM,gBAAgB,GAAG,OAAO,CAAC,OAAO,CAAC,gBAAgB,IAAI,WAAW,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,iBAAiB,CAAC,aAAa,CAAC,CAAC;QACnD,MAAM,WAAW,GAAG,OAAO,CAAC,WAAW,IAAI,0BAA0B,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;QAEvG,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAEzC,IAAI,QAAQ,EAAE,CAAC;YACb,qCAAqC;YACrC,MAAM,aAAa,GAAG,QAAQ,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAEjF,6DAA6D;YAC7D,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,EAAE,CAAC;gBAC5C,aAAa,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;YACtE,CAAC;YAED,+DAA+D;YAC/D,QAAQ,CAAC,WAAW,GAAG,aAAa,CAAC;YACrC,QAAQ,CAAC,gBAAgB,GAAG,gBAAgB,CAAC;YAC7C,QAAQ,CAAC,WAAW,GAAG,WAAW,CAAC;YACnC,QAAQ,CAAC,SAAS,GAAG,aAAa,CAAC;YACnC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACpC,CAAC;aAAM,CAAC;YACN,cAAc;YACd,MAAM,KAAK,GAAyB;gBAClC,SAAS;gBACT,WAAW,EAAE,aAAa;gBAC1B,gBAAgB;gBAChB,WAAW;gBACX,SAAS,EAAE,CAAC,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;aAC7D,CAAC;YACF,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACjC,CAAC;QAED,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;QACnC,OAAO,SAAS,CAAC;IACnB,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,iBAAiB,CAAC,WAAmB,EAAE,GAAY;QACvD,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAElD,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACtC,IAAI,CAAC,KAAK;YAAE,OAAO;QAEnB,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;YACtB,kCAAkC;YAClC,KAAK,CAAC,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC;YAC7D,IAAI,KAAK,CAAC,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBACjC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;YAC7B,CAAC;iBAAM,CAAC;gBACN,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;aAAM,CAAC;YACN,2CAA2C;YAC3C,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;QAED,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,qBAAqB,CAAC,SAAiB;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC3B,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;IACrC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc;QAClB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,OAAO,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACvC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,UAAU,CAAC,WAAmB;QAClC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAClD,OAAO,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,cAAc,CAAC,SAAiB;QACpC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,OAAO,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC;IACzC,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,oBAAoB;QACxB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,IAAI,oBAAoB,GAAG,CAAC,CAAC;QAC7B,IAAI,UAAU,GAAG,IAAI,CAAC,mBAAmB,CAAC,CAAC,qCAAqC;QAEhF,KAAK,MAAM,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC;YACpD,MAAM,aAAa,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;YAC9E,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,CAAC,MAAM,GAAG,aAAa,CAAC,MAAM,CAAC;YAEhE,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;gBAClB,oBAAoB,IAAI,SAAS,CAAC;gBAClC,UAAU,GAAG,IAAI,CAAC;gBAElB,mFAAmF;gBACnF,gFAAgF;gBAChF,yEAAyE;gBACzE,KAAK,CAAC,SAAS,GAAG,aAAa,CAAC;gBAChC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YACjC,CAAC;QACH,CAAC;QAED,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,IAAI,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YACnC,IAAI,CAAC,mBAAmB,GAAG,KAAK,CAAC,CAAC,oCAAoC;QACxE,CAAC;QAED,OAAO,oBAAoB,CAAC;IAC9B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,mBAAmB,CAAC,WAAmB;QAC3C,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,YAAY,EAAE,CAAC;QAC3C,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;QAC1C,MAAM,SAAS,GAAG,iBAAiB,CAAC,YAAY,CAAC,CAAC;QAClD,OAAO,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACjC,CAAC;IAED;;OAEG;IACH,eAAe;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -217,7 +217,7 @@ export class AuditLogger {
|
|
|
217
217
|
export function createSecurityHeadersMiddleware(port) {
|
|
218
218
|
const actualPort = port || DEFAULT_DASHBOARD_PORT;
|
|
219
219
|
// Build connect-src directive with WebSocket endpoints
|
|
220
|
-
let connectSrc = `'self' ws://localhost:${actualPort} ws://127.0.0.1:${actualPort} wss://specdash.lbruton.cc
|
|
220
|
+
let connectSrc = `'self' ws://localhost:${actualPort} ws://127.0.0.1:${actualPort} wss://specdash.lbruton.cc`;
|
|
221
221
|
// In non-production environments, also allow Vite dev server connections
|
|
222
222
|
if (process.env.NODE_ENV !== 'production') {
|
|
223
223
|
connectSrc += ` ws://localhost:${VITE_DEV_PORT} ws://127.0.0.1:${VITE_DEV_PORT}`;
|
|
@@ -231,7 +231,7 @@ export function createSecurityHeadersMiddleware(port) {
|
|
|
231
231
|
// CSP for dashboard
|
|
232
232
|
// Note: cdn.jsdelivr.net is required for highlight.js stylesheets used by the MDX editor
|
|
233
233
|
// connect-src allows WebSocket connections to the dashboard on the actual port
|
|
234
|
-
reply.header('Content-Security-Policy', `default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; img-src 'self' data:; connect-src ${connectSrc}; frame-src https://polldash.lbruton.cc
|
|
234
|
+
reply.header('Content-Security-Policy', `default-src 'self'; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline' https://cdn.jsdelivr.net; img-src 'self' data:; connect-src ${connectSrc}; frame-src https://polldash.lbruton.cc;`);
|
|
235
235
|
};
|
|
236
236
|
}
|
|
237
237
|
/**
|