@codeyam/codeyam-cli 0.1.5 → 0.1.6
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/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +2 -2
- package/analyzer-template/packages/ai/package.json +1 -1
- package/analyzer-template/packages/ai/src/lib/completionCall.ts +102 -113
- package/analyzer-template/packages/aws/package.json +1 -1
- package/codeyam-cli/src/cli.js +5 -11
- package/codeyam-cli/src/cli.js.map +1 -1
- package/codeyam-cli/src/utils/install-skills.js +4 -4
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/requireSimulations.js +1 -1
- package/codeyam-cli/src/utils/requireSimulations.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +5 -6
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -1
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +2 -5
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -1
- package/codeyam-cli/src/utils/rules/__tests__/rulePlacement.test.js +72 -0
- package/codeyam-cli/src/utils/rules/__tests__/rulePlacement.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js +11 -18
- package/codeyam-cli/src/utils/rules/__tests__/sourceFiles.test.js.map +1 -1
- package/codeyam-cli/src/utils/rules/rulePlacement.js +65 -0
- package/codeyam-cli/src/utils/rules/rulePlacement.js.map +1 -0
- package/codeyam-cli/src/utils/rules/sourceFiles.js +2 -6
- package/codeyam-cli/src/utils/rules/sourceFiles.js.map +1 -1
- package/codeyam-cli/src/utils/simulationGateMiddleware.js +63 -42
- package/codeyam-cli/src/utils/simulationGateMiddleware.js.map +1 -1
- package/codeyam-cli/src/webserver/app/routes/api.agent-transcripts.js +486 -0
- package/codeyam-cli/src/webserver/app/routes/api.agent-transcripts.js.map +1 -0
- package/codeyam-cli/src/webserver/backgroundServer.js +10 -0
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-jNYXRRNI.js → CopyButton-CtmbP4Gl.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-bwuHPyTa.js → EntityItem-DlMph_Hm.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-CvzqMxcu.js → EntityTypeBadge-B-0PjGOU.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BH0XDim7.js → EntityTypeIcon-DN9eiJAO.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-EhOseatT.js → InlineSpinner-C1rIyZdV.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-yjIHlOGa.js → InteractivePreview-rE_fI2h2.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-Cq5o8jL4.js → LibraryFunctionPreview-CnatsCw2.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-BvMu2i-g.js → LoadingDots-CSP6DZrh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-kgBTLoJD.js → LogViewer-CMK8Q7yk.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-BzPgx-xO.js → ReportIssueModal-TCV_HBjy.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CwZrv-Ok.js → SafeScreenshot-CG2uh31y.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-BX2Ny2Qj.js → ScenarioViewer-CU_TDYd8.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-CDpEprKa.js → TruncatedFilePath-D7IoaWUW.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{_index-BRx8ZGZo.js → _index-B8z7mjR-.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-4S4yPfFw.js → activity.(_tab)-DZu78RI1.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DxCa1oBt.js +23 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.rule-path-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{book-open-D4IPYH_y.js → book-open-Bp5FLkd4.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-CG65viiV.js → chevron-down-DQJA9f4o.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chunk-JZWAC4HX-DB3aFuEO.js → chunk-JZWAC4HX-7VptmeIr.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-igfMr5DY.js → circle-check-B6C4LY9o.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{copy-Coc4o_8c.js → copy-6nzYCu0G.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-D1zB-pYc.js → createLucideIcon-D-QUFOwe.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-JTAjQ54M.js → dev.empty-DmzSmblj.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-B0h9AqE6.js → entity._sha._--zvFJ4OH.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-DjLxr2JB.js → entity._sha.scenarios._scenarioId.fullscreen-DVTcUnur.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-CtYowLOt.js → entity._sha_.create-scenario-BVgNO76F.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-PePWg17F.js → entity._sha_.edit._scenarioId-C7ysA4Jq.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-I-Wo99C_.js → entry.client-CU6EUArK.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-9sMMAiWJ.js → fileTableUtils-EWpfFU4X.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{files-Co65J0s3.js → files-CrxAoWIL.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{git-BdHOxVfg.js → git-BldHtKeW.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-CUM5iXwc.js → index-7-1FmlHo.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-_417gcQW.js → index-DuYcwYp_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{labs-DAvt-sy-.js → labs-CPPVOSWB.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-TzRHMVog.js → loader-circle-BnDcD54R.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-c1fc3656.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{memory-bAp4y2hv.js → memory-CfpYxpNu.js} +19 -18
- package/codeyam-cli/src/webserver/build/client/assets/{pause-hjzB7t2z.js → pause-DhQX2g22.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{root-DoB3B10-.js → root-CAAbm4U5.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{search-DcAwD_Ln.js → search-DborVoKD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{settings-CclxrcPK.js → settings-BpLDWmGh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-DVNJVQgD.js → simulations-BtrtCYJg.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{terminal-DbEAHMbA.js → terminal-Bs4NC-VZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-CAD5b1o_.js → triangle-alert-DTf3Jojp.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-BqgrAzs3.js → useCustomSizes-D_bDZyDU.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-DAFqfEDH.js → useLastLogLine-DZp6rrQD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-DZlYx2c4.js → useReportContext-BsQb6rFd.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-ihdMtlf6.js → useToast-BOur3mUv.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-C_nP9_jr.js → index-B8A_aaGG.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-69rRZnZo.js +286 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/templates/codeyam-new-rule.md +0 -2
- package/codeyam-cli/templates/hooks/staleness-check.sh +43 -0
- package/codeyam-cli/templates/prompts/conversation-guidance.txt +32 -0
- package/codeyam-cli/templates/prompts/conversation-prompt.txt +28 -0
- package/codeyam-cli/templates/prompts/interruption-prompt.txt +31 -0
- package/codeyam-cli/templates/prompts/stale-rules-prompt.txt +24 -0
- package/codeyam-cli/templates/rules-instructions.md +33 -88
- package/package.json +1 -1
- package/packages/ai/src/lib/completionCall.js +0 -5
- package/packages/ai/src/lib/completionCall.js.map +1 -1
- package/codeyam-cli/src/commands/detect-universal-mocks.js +0 -120
- package/codeyam-cli/src/commands/detect-universal-mocks.js.map +0 -1
- package/codeyam-cli/src/commands/list.js +0 -31
- package/codeyam-cli/src/commands/list.js.map +0 -1
- package/codeyam-cli/src/commands/webapp-info.js +0 -146
- package/codeyam-cli/src/commands/webapp-info.js.map +0 -1
- package/codeyam-cli/src/utils/universal-mocks.js +0 -152
- package/codeyam-cli/src/utils/universal-mocks.js.map +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DHKuQSmR.js +0 -17
- package/codeyam-cli/src/webserver/build/client/assets/manifest-e24d6600.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-BEaMCeTu.js +0 -273
- package/codeyam-cli/templates/codeyam-stop-hook.sh +0 -284
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { computeRulePlacement } from "../rulePlacement.js";
|
|
2
|
+
describe('computeRulePlacement', () => {
|
|
3
|
+
describe('single file path', () => {
|
|
4
|
+
it('returns the directory of the file', () => {
|
|
5
|
+
expect(computeRulePlacement(['src/api/auth.ts'])).toBe('src/api');
|
|
6
|
+
});
|
|
7
|
+
it('handles deeply nested file', () => {
|
|
8
|
+
expect(computeRulePlacement(['packages/ai/src/lib/generateMockData.ts'])).toBe('packages/ai/src/lib');
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
describe('multiple file paths in the same directory', () => {
|
|
12
|
+
it('returns their shared directory', () => {
|
|
13
|
+
expect(computeRulePlacement([
|
|
14
|
+
'packages/ai/src/lib/foo.ts',
|
|
15
|
+
'packages/ai/src/lib/bar.ts',
|
|
16
|
+
])).toBe('packages/ai/src/lib');
|
|
17
|
+
});
|
|
18
|
+
});
|
|
19
|
+
describe('multiple file paths in different directories', () => {
|
|
20
|
+
it('returns the deepest common directory', () => {
|
|
21
|
+
expect(computeRulePlacement([
|
|
22
|
+
'packages/ai/src/lib/a.ts',
|
|
23
|
+
'packages/ai/src/utils/b.ts',
|
|
24
|
+
])).toBe('packages/ai/src');
|
|
25
|
+
});
|
|
26
|
+
it('handles paths with no shared directory beyond root', () => {
|
|
27
|
+
expect(computeRulePlacement(['src/api/auth.ts', 'lib/utils/helpers.ts'])).toBe('');
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe('glob patterns', () => {
|
|
31
|
+
it('strips ** from directory glob', () => {
|
|
32
|
+
expect(computeRulePlacement(['codeyam-cli/**'])).toBe('codeyam-cli');
|
|
33
|
+
});
|
|
34
|
+
it('strips **/*.ext pattern', () => {
|
|
35
|
+
expect(computeRulePlacement(['packages/ai/src/**/*.ts'])).toBe('packages/ai/src');
|
|
36
|
+
});
|
|
37
|
+
it('strips trailing * wildcard', () => {
|
|
38
|
+
expect(computeRulePlacement(['src/utils/*.ts'])).toBe('src/utils');
|
|
39
|
+
});
|
|
40
|
+
it('finds common directory across multiple globs', () => {
|
|
41
|
+
expect(computeRulePlacement(['packages/ai/**', 'packages/types/**'])).toBe('packages');
|
|
42
|
+
});
|
|
43
|
+
it('finds common directory between glob and file path', () => {
|
|
44
|
+
expect(computeRulePlacement([
|
|
45
|
+
'packages/ai/src/**/*.ts',
|
|
46
|
+
'packages/ai/src/lib/foo.ts',
|
|
47
|
+
])).toBe('packages/ai/src');
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
describe('edge cases', () => {
|
|
51
|
+
it('throws on empty paths array', () => {
|
|
52
|
+
expect(() => computeRulePlacement([])).toThrow();
|
|
53
|
+
});
|
|
54
|
+
it('handles root-level file', () => {
|
|
55
|
+
expect(computeRulePlacement(['config.ts'])).toBe('');
|
|
56
|
+
});
|
|
57
|
+
it('handles root-level glob', () => {
|
|
58
|
+
expect(computeRulePlacement(['**/*.ts'])).toBe('');
|
|
59
|
+
});
|
|
60
|
+
it('handles paths with trailing slashes', () => {
|
|
61
|
+
expect(computeRulePlacement(['src/utils/'])).toBe('src/utils');
|
|
62
|
+
});
|
|
63
|
+
it('handles mix of files, globs, and directories', () => {
|
|
64
|
+
expect(computeRulePlacement([
|
|
65
|
+
'packages/ai/src/lib/foo.ts',
|
|
66
|
+
'packages/ai/src/**/*.ts',
|
|
67
|
+
'packages/ai/src/utils/',
|
|
68
|
+
])).toBe('packages/ai/src');
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
//# sourceMappingURL=rulePlacement.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rulePlacement.test.js","sourceRoot":"","sources":["../../../../../../src/utils/rules/__tests__/rulePlacement.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,7 +10,7 @@ describe('findSourceFilesInProject', () => {
|
|
|
10
10
|
afterEach(() => {
|
|
11
11
|
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
12
12
|
});
|
|
13
|
-
it('returns
|
|
13
|
+
it('returns files with correct relative paths', () => {
|
|
14
14
|
fs.mkdirSync(path.join(tempDir, 'src'), { recursive: true });
|
|
15
15
|
fs.writeFileSync(path.join(tempDir, 'src', 'index.ts'), '');
|
|
16
16
|
fs.writeFileSync(path.join(tempDir, 'src', 'App.tsx'), '');
|
|
@@ -18,33 +18,26 @@ describe('findSourceFilesInProject', () => {
|
|
|
18
18
|
expect(files.sort()).toEqual(['src/App.tsx', 'src/index.ts']);
|
|
19
19
|
});
|
|
20
20
|
});
|
|
21
|
-
it('
|
|
21
|
+
it('includes files of any extension', () => {
|
|
22
22
|
fs.writeFileSync(path.join(tempDir, 'a.ts'), '');
|
|
23
23
|
fs.writeFileSync(path.join(tempDir, 'b.tsx'), '');
|
|
24
24
|
fs.writeFileSync(path.join(tempDir, 'c.js'), '');
|
|
25
|
-
fs.writeFileSync(path.join(tempDir, 'd.
|
|
26
|
-
fs.writeFileSync(path.join(tempDir, 'e.
|
|
27
|
-
fs.writeFileSync(path.join(tempDir, 'f.
|
|
25
|
+
fs.writeFileSync(path.join(tempDir, 'd.json'), '{}');
|
|
26
|
+
fs.writeFileSync(path.join(tempDir, 'e.css'), '');
|
|
27
|
+
fs.writeFileSync(path.join(tempDir, 'f.md'), '');
|
|
28
|
+
fs.writeFileSync(path.join(tempDir, 'g.vue'), '');
|
|
28
29
|
return findSourceFilesInProject(tempDir).then((files) => {
|
|
29
30
|
expect(files.sort()).toEqual([
|
|
30
31
|
'a.ts',
|
|
31
32
|
'b.tsx',
|
|
32
33
|
'c.js',
|
|
33
|
-
'd.
|
|
34
|
-
'e.
|
|
35
|
-
'f.
|
|
34
|
+
'd.json',
|
|
35
|
+
'e.css',
|
|
36
|
+
'f.md',
|
|
37
|
+
'g.vue',
|
|
36
38
|
]);
|
|
37
39
|
});
|
|
38
40
|
});
|
|
39
|
-
it('excludes non-source extensions', () => {
|
|
40
|
-
fs.writeFileSync(path.join(tempDir, 'readme.md'), '');
|
|
41
|
-
fs.writeFileSync(path.join(tempDir, 'style.css'), '');
|
|
42
|
-
fs.writeFileSync(path.join(tempDir, 'data.json'), '');
|
|
43
|
-
fs.writeFileSync(path.join(tempDir, 'real.ts'), '');
|
|
44
|
-
return findSourceFilesInProject(tempDir).then((files) => {
|
|
45
|
-
expect(files).toEqual(['real.ts']);
|
|
46
|
-
});
|
|
47
|
-
});
|
|
48
41
|
it('skips excluded directories', () => {
|
|
49
42
|
const excludedDirs = [
|
|
50
43
|
'node_modules',
|
|
@@ -65,7 +58,7 @@ describe('findSourceFilesInProject', () => {
|
|
|
65
58
|
expect(files).toEqual(['src/real.ts']);
|
|
66
59
|
});
|
|
67
60
|
});
|
|
68
|
-
it('returns empty array for projects with no
|
|
61
|
+
it('returns empty array for projects with no files', () => {
|
|
69
62
|
return findSourceFilesInProject(tempDir).then((files) => {
|
|
70
63
|
expect(files).toEqual([]);
|
|
71
64
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sourceFiles.test.js","sourceRoot":"","sources":["../../../../../../src/utils/rules/__tests__/sourceFiles.test.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,EAAE,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAE1D,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,IAAI,OAAe,CAAC;IAEpB,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,sBAAsB,CAAC,CAAC,CAAC;IAC3E,CAAC,CAAC,CAAC;IAEH,SAAS,CAAC,GAAG,EAAE;QACb,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"sourceFiles.test.js","sourceRoot":"","sources":["../../../../../../src/utils/rules/__tests__/sourceFiles.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compute the correct .claude/rules/ subdirectory for a rule based on its frontmatter paths.
|
|
3
|
+
*
|
|
4
|
+
* Algorithm:
|
|
5
|
+
* 1. For each path, extract the directory portion (strip filenames and glob segments)
|
|
6
|
+
* 2. Find the longest common directory prefix across all paths
|
|
7
|
+
* 3. Return that prefix (to be used as .claude/rules/<prefix>/)
|
|
8
|
+
*
|
|
9
|
+
* @param paths - Array of path patterns from rule frontmatter
|
|
10
|
+
* @returns The deepest common directory (e.g., "packages/ai/src/lib"), or "" for root
|
|
11
|
+
* @throws If paths array is empty
|
|
12
|
+
*/
|
|
13
|
+
export function computeRulePlacement(paths) {
|
|
14
|
+
if (paths.length === 0) {
|
|
15
|
+
throw new Error('paths array must not be empty');
|
|
16
|
+
}
|
|
17
|
+
const directories = paths.map(extractDirectory);
|
|
18
|
+
// Find the longest common prefix of directory segments
|
|
19
|
+
const segmentArrays = directories.map((d) => (d === '' ? [] : d.split('/')));
|
|
20
|
+
const commonSegments = segmentArrays.reduce((common, segments) => {
|
|
21
|
+
const result = [];
|
|
22
|
+
for (let i = 0; i < Math.min(common.length, segments.length); i++) {
|
|
23
|
+
if (common[i] === segments[i]) {
|
|
24
|
+
result.push(common[i]);
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
break;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
});
|
|
32
|
+
return commonSegments.join('/');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extract the directory portion from a path pattern, stripping:
|
|
36
|
+
* - Filenames (anything with an extension after the last /)
|
|
37
|
+
* - Glob segments (**, *, *.ext)
|
|
38
|
+
* - Trailing slashes
|
|
39
|
+
*/
|
|
40
|
+
function extractDirectory(pathPattern) {
|
|
41
|
+
// Remove trailing slashes
|
|
42
|
+
const p = pathPattern.replace(/\/+$/, '');
|
|
43
|
+
const segments = p.split('/');
|
|
44
|
+
// Walk backwards, dropping segments that are globs or filenames
|
|
45
|
+
while (segments.length > 0) {
|
|
46
|
+
const last = segments[segments.length - 1];
|
|
47
|
+
if (isGlobOrFile(last)) {
|
|
48
|
+
segments.pop();
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
break;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return segments.join('/');
|
|
55
|
+
}
|
|
56
|
+
function isGlobOrFile(segment) {
|
|
57
|
+
// Glob patterns: **, *, *.ext, **/*.ext
|
|
58
|
+
if (segment.includes('*'))
|
|
59
|
+
return true;
|
|
60
|
+
// Files: have an extension like .ts, .tsx, .js, etc.
|
|
61
|
+
if (/\.\w+$/.test(segment))
|
|
62
|
+
return true;
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=rulePlacement.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rulePlacement.js","sourceRoot":"","sources":["../../../../../src/utils/rules/rulePlacement.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAe;IAClD,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,+BAA+B,CAAC,CAAC;IACnD,CAAC;IAED,MAAM,WAAW,GAAG,KAAK,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAEhD,uDAAuD;IACvD,MAAM,aAAa,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IAC7E,MAAM,cAAc,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE;QAC/D,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAClE,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC;gBAC9B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACzB,CAAC;iBAAM,CAAC;gBACN,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;IAEH,OAAO,cAAc,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClC,CAAC;AAED;;;;;GAKG;AACH,SAAS,gBAAgB,CAAC,WAAmB;IAC3C,0BAA0B;IAC1B,MAAM,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IAE1C,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAE9B,gEAAgE;IAChE,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC3B,MAAM,IAAI,GAAG,QAAQ,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAC3C,IAAI,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,QAAQ,CAAC,GAAG,EAAE,CAAC;QACjB,CAAC;aAAM,CAAC;YACN,MAAM;QACR,CAAC;IACH,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACnC,wCAAwC;IACxC,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,qDAAqD;IACrD,IAAI,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACxC,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import * as fs from 'fs/promises';
|
|
2
2
|
import * as path from 'path';
|
|
3
|
-
const SOURCE_EXTENSIONS = ['.ts', '.tsx', '.js', '.jsx', '.vue', '.svelte'];
|
|
4
3
|
const EXCLUDED_DIRS = new Set([
|
|
5
4
|
'node_modules',
|
|
6
5
|
'.git',
|
|
@@ -11,7 +10,7 @@ const EXCLUDED_DIRS = new Set([
|
|
|
11
10
|
'coverage',
|
|
12
11
|
]);
|
|
13
12
|
/**
|
|
14
|
-
* Find all
|
|
13
|
+
* Find all files in a project, returning paths relative to projectRoot.
|
|
15
14
|
*/
|
|
16
15
|
export async function findSourceFilesInProject(projectRoot) {
|
|
17
16
|
const sourceFiles = [];
|
|
@@ -30,10 +29,7 @@ export async function findSourceFilesInProject(projectRoot) {
|
|
|
30
29
|
await walkDir(fullPath, relPath);
|
|
31
30
|
}
|
|
32
31
|
else if (entry.isFile()) {
|
|
33
|
-
|
|
34
|
-
if (SOURCE_EXTENSIONS.includes(ext)) {
|
|
35
|
-
sourceFiles.push(relPath);
|
|
36
|
-
}
|
|
32
|
+
sourceFiles.push(relPath);
|
|
37
33
|
}
|
|
38
34
|
}
|
|
39
35
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sourceFiles.js","sourceRoot":"","sources":["../../../../../src/utils/rules/sourceFiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,
|
|
1
|
+
{"version":3,"file":"sourceFiles.js","sourceRoot":"","sources":["../../../../../src/utils/rules/sourceFiles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,aAAa,CAAC;AAClC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC;IAC5B,cAAc;IACd,MAAM;IACN,MAAM;IACN,UAAU;IACV,SAAS;IACT,OAAO;IACP,UAAU;CACX,CAAC,CAAC;AAEH;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,WAAmB;IAEnB,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,UAAU,OAAO,CAAC,GAAW,EAAE,YAAoB;QACtD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAE/D,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC5C,MAAM,OAAO,GAAG,YAAY;oBAC1B,CAAC,CAAC,GAAG,YAAY,IAAI,KAAK,CAAC,IAAI,EAAE;oBACjC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC;gBAEf,IAAI,KAAK,CAAC,WAAW,EAAE,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;oBACzD,SAAS;gBACX,CAAC;gBAED,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACxB,MAAM,OAAO,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACnC,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,EAAE,CAAC;oBAC1B,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBAC5B,CAAC;YACH,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,+BAA+B;QACjC,CAAC;IACH,CAAC;IAED,MAAM,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC/B,OAAO,WAAW,CAAC;AACrB,CAAC"}
|
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
import { findProjectRoot } from "./project.js";
|
|
2
2
|
import { initializeEnvironment, requireBranchAndProject } from "./database.js";
|
|
3
|
-
import
|
|
3
|
+
import Database from 'better-sqlite3';
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as path from 'path';
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Commands hidden from the default help section.
|
|
8
|
+
* All require simulations to be enabled via the dashboard.
|
|
9
|
+
*/
|
|
10
|
+
export const HIDDEN_COMMANDS = [
|
|
11
|
+
{ name: 'init', describe: 'Initialize a project for CodeYam CLI analysis' },
|
|
12
|
+
{ name: 'update-config', describe: 'Update project configuration' },
|
|
13
|
+
{ name: 'setup-simulations', describe: 'Enable simulation commands' },
|
|
7
14
|
{ name: 'analyze', describe: 'Analyze local code changes before committing' },
|
|
8
15
|
{
|
|
9
16
|
name: 'verify',
|
|
10
17
|
describe: 'Detect changed visual/library entities and verify',
|
|
11
18
|
},
|
|
12
|
-
{
|
|
13
|
-
name: 'detect-universal-mocks',
|
|
14
|
-
describe: 'Detect universal mocks needed for startup',
|
|
15
|
-
},
|
|
16
19
|
{
|
|
17
20
|
name: 'test-startup',
|
|
18
21
|
describe: 'Test project startup without external services',
|
|
@@ -21,14 +24,8 @@ export const SIMULATION_COMMANDS = [
|
|
|
21
24
|
name: 'setup-sandbox',
|
|
22
25
|
describe: 'Create sandbox copy for iterating on startup',
|
|
23
26
|
},
|
|
24
|
-
{
|
|
25
|
-
|
|
26
|
-
describe: 'Re-run capture for an analysis or scenario',
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
name: 'baseline',
|
|
30
|
-
describe: 'Run baseline analysis of all entities',
|
|
31
|
-
},
|
|
27
|
+
{ name: 'recapture', describe: 'Re-run capture for an analysis or scenario' },
|
|
28
|
+
{ name: 'baseline', describe: 'Run baseline analysis of all entities' },
|
|
32
29
|
{
|
|
33
30
|
name: 'debug',
|
|
34
31
|
describe: 'Setup debug environment for an analysis or scenario',
|
|
@@ -37,19 +34,9 @@ export const SIMULATION_COMMANDS = [
|
|
|
37
34
|
name: 'generate-data-structure',
|
|
38
35
|
describe: 'Generate Jest mock template via partial analysis',
|
|
39
36
|
},
|
|
40
|
-
{
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
name: 'status',
|
|
46
|
-
describe: 'Show status of local code changes vs database',
|
|
47
|
-
},
|
|
48
|
-
{
|
|
49
|
-
name: 'entities',
|
|
50
|
-
describe: 'Search for entities in the project by name',
|
|
51
|
-
},
|
|
52
|
-
{ name: 'list', describe: 'List entities or analyses' },
|
|
37
|
+
{ name: 'suggest', describe: 'Suggest components for analysis' },
|
|
38
|
+
{ name: 'status', describe: 'Show status of local code changes vs database' },
|
|
39
|
+
{ name: 'entities', describe: 'Search for entities in the project by name' },
|
|
53
40
|
{ name: 'queue', describe: 'Show the current job queue status' },
|
|
54
41
|
{
|
|
55
42
|
name: 'validate-mock',
|
|
@@ -59,16 +46,12 @@ export const SIMULATION_COMMANDS = [
|
|
|
59
46
|
name: 'report',
|
|
60
47
|
describe: 'Create a debug bundle for sharing with the CodeYam team',
|
|
61
48
|
},
|
|
62
|
-
{
|
|
63
|
-
name: 'webapp-info',
|
|
64
|
-
describe: 'Show webapp info for a scenario, analysis, or file',
|
|
65
|
-
},
|
|
66
49
|
{
|
|
67
50
|
name: 'wipe',
|
|
68
51
|
describe: 'Delete all analysis data (entities, analyses, scenarios)',
|
|
69
52
|
},
|
|
70
53
|
];
|
|
71
|
-
export const
|
|
54
|
+
export const HIDDEN_COMMAND_NAMES = HIDDEN_COMMANDS.map((c) => c.name);
|
|
72
55
|
/**
|
|
73
56
|
* Load project context from the DB for middleware use.
|
|
74
57
|
* Stashes the result on argv.__projectContext to avoid duplicate loads
|
|
@@ -100,7 +83,7 @@ export async function loadProjectForMiddleware(argv) {
|
|
|
100
83
|
*/
|
|
101
84
|
export async function simulationGateMiddleware(argv) {
|
|
102
85
|
const command = String(argv._[0] ?? '');
|
|
103
|
-
if (!
|
|
86
|
+
if (!HIDDEN_COMMAND_NAMES.includes(command)) {
|
|
104
87
|
return;
|
|
105
88
|
}
|
|
106
89
|
try {
|
|
@@ -111,7 +94,7 @@ export async function simulationGateMiddleware(argv) {
|
|
|
111
94
|
}
|
|
112
95
|
if (!context.project.metadata?.labs?.simulations) {
|
|
113
96
|
console.error(`\n"codeyam ${command}" requires simulations to be enabled.`);
|
|
114
|
-
console.error('
|
|
97
|
+
console.error('Enable simulations from the CodeYam dashboard.\n');
|
|
115
98
|
process.exit(1);
|
|
116
99
|
}
|
|
117
100
|
}
|
|
@@ -121,18 +104,56 @@ export async function simulationGateMiddleware(argv) {
|
|
|
121
104
|
}
|
|
122
105
|
}
|
|
123
106
|
/**
|
|
124
|
-
*
|
|
125
|
-
*
|
|
107
|
+
* Synchronously check if the current project has simulations enabled
|
|
108
|
+
* by reading the SQLite database directly. Returns false if not in a
|
|
109
|
+
* project or if the flag isn't set.
|
|
110
|
+
*/
|
|
111
|
+
function areSimulationsEnabled() {
|
|
112
|
+
try {
|
|
113
|
+
const projectRoot = findProjectRoot();
|
|
114
|
+
if (!projectRoot)
|
|
115
|
+
return false;
|
|
116
|
+
const configPath = path.join(projectRoot, '.codeyam', 'config.json');
|
|
117
|
+
if (!fs.existsSync(configPath))
|
|
118
|
+
return false;
|
|
119
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
120
|
+
const { projectSlug } = config;
|
|
121
|
+
if (!projectSlug)
|
|
122
|
+
return false;
|
|
123
|
+
const dbPath = path.join(projectRoot, '.codeyam', 'db.sqlite3');
|
|
124
|
+
if (!fs.existsSync(dbPath))
|
|
125
|
+
return false;
|
|
126
|
+
const db = new Database(dbPath, { readonly: true });
|
|
127
|
+
try {
|
|
128
|
+
const row = db
|
|
129
|
+
.prepare('SELECT metadata FROM projects WHERE slug = ?')
|
|
130
|
+
.get(projectSlug);
|
|
131
|
+
if (!row?.metadata)
|
|
132
|
+
return false;
|
|
133
|
+
const metadata = JSON.parse(row.metadata);
|
|
134
|
+
return !!metadata?.labs?.simulations;
|
|
135
|
+
}
|
|
136
|
+
finally {
|
|
137
|
+
db.close();
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Build the epilogue string for --help. Only shows hidden commands
|
|
146
|
+
* when simulations are enabled for the current project.
|
|
126
147
|
*/
|
|
127
148
|
export function buildSimulationEpilogue() {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const maxNameLen = Math.max(...
|
|
132
|
-
const lines =
|
|
149
|
+
if (!areSimulationsEnabled()) {
|
|
150
|
+
return 'Enable simulations from the CodeYam dashboard to unlock more commands.';
|
|
151
|
+
}
|
|
152
|
+
const maxNameLen = Math.max(...HIDDEN_COMMANDS.map((c) => c.name.length));
|
|
153
|
+
const lines = HIDDEN_COMMANDS.map((c) => {
|
|
133
154
|
const padded = c.name.padEnd(maxNameLen + 2);
|
|
134
155
|
return ` codeyam ${padded}${c.describe}`;
|
|
135
156
|
});
|
|
136
|
-
return
|
|
157
|
+
return `All Commands:\n${lines.join('\n')}`;
|
|
137
158
|
}
|
|
138
159
|
//# sourceMappingURL=simulationGateMiddleware.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"simulationGateMiddleware.js","sourceRoot":"","sources":["../../../../src/utils/simulationGateMiddleware.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,
|
|
1
|
+
{"version":3,"file":"simulationGateMiddleware.js","sourceRoot":"","sources":["../../../../src/utils/simulationGateMiddleware.ts"],"names":[],"mappings":"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"}
|