@codeyam/codeyam-cli 0.1.12 → 0.1.14
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 +6 -6
- package/analyzer-template/log.txt +3 -3
- package/codeyam-cli/src/cli.js +9 -0
- package/codeyam-cli/src/cli.js.map +1 -1
- package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js +51 -0
- package/codeyam-cli/src/commands/__tests__/editor.isolateArgs.test.js.map +1 -0
- package/codeyam-cli/src/commands/editor.js +202 -40
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/commands/editorIsolateArgs.js +25 -0
- package/codeyam-cli/src/commands/editorIsolateArgs.js.map +1 -0
- package/codeyam-cli/src/commands/telemetry.js +37 -0
- package/codeyam-cli/src/commands/telemetry.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +101 -0
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js +70 -0
- package/codeyam-cli/src/utils/__tests__/editorEntityChangeStatus.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js +58 -4
- package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +37 -0
- package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/telemetry.test.js +159 -0
- package/codeyam-cli/src/utils/__tests__/telemetry.test.js.map +1 -0
- package/codeyam-cli/src/utils/editorAudit.js +38 -5
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorEntityChangeStatus.js +13 -7
- package/codeyam-cli/src/utils/editorEntityChangeStatus.js.map +1 -1
- package/codeyam-cli/src/utils/editorEntityHelpers.js +18 -3
- package/codeyam-cli/src/utils/editorEntityHelpers.js.map +1 -1
- package/codeyam-cli/src/utils/editorScenarios.js +6 -1
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/utils/telemetry.js +106 -0
- package/codeyam-cli/src/utils/telemetry.js.map +1 -0
- package/codeyam-cli/src/utils/telemetryMiddleware.js +22 -0
- package/codeyam-cli/src/utils/telemetryMiddleware.js.map +1 -0
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js +28 -0
- package/codeyam-cli/src/webserver/__tests__/editorProxy.test.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DYqG1D_d.js +58 -0
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-DggyRwOr.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-BOi8kpwd.js → entity._sha.scenarios._scenarioId.dev-D1eikpe1.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-DRvOjyO3.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{manifest-b3f77062.js → manifest-f4212c17.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{root-D5Zi3U2Z.js → root-F-k2uYj5.js} +15 -15
- package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-yTyb36j3.js → analysisRunner-if8kM_1Q.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-Cr7d_IsG.js → index-CHymws6l.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{init-M_wqNAfu.js → init-D3HkMDbI.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-DTCzJQiH.js +551 -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/src/webserver/editorProxy.js +19 -2
- package/codeyam-cli/src/webserver/editorProxy.js.map +1 -1
- package/codeyam-cli/src/webserver/server.js +32 -0
- package/codeyam-cli/src/webserver/server.js.map +1 -1
- package/codeyam-cli/templates/nextjs-prisma-sqlite/package.json +1 -1
- package/codeyam-cli/templates/nextjs-prisma-supabase/package.json +1 -1
- package/package.json +2 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DmBK1JBK.js +0 -58
- package/codeyam-cli/src/webserver/build/client/assets/editorPreview-DBa7T2FK.js +0 -41
- package/codeyam-cli/src/webserver/build/client/assets/globals-CGrDAxj0.css +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-_ybRgrlc.js +0 -551
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"buildTimestamp": "2026-03-
|
|
3
|
-
"buildTime":
|
|
4
|
-
"gitCommit": "
|
|
2
|
+
"buildTimestamp": "2026-03-18T14:58:22.078Z",
|
|
3
|
+
"buildTime": 1773845902078,
|
|
4
|
+
"gitCommit": "4dda2c78ef15ac678fb9a0e8f4d270c514f30f81",
|
|
5
5
|
"nodeVersion": "v20.20.1",
|
|
6
6
|
"contentHash": "b046e014847d5b02d10d6795839ccd0d5117627cbd0be413260824610596a63d",
|
|
7
|
-
"buildNumber":
|
|
8
|
-
"semanticVersion": "0.1.
|
|
9
|
-
"version": "0.1.
|
|
7
|
+
"buildNumber": 1092,
|
|
8
|
+
"semanticVersion": "0.1.1092",
|
|
9
|
+
"version": "0.1.1092 (2026-03-18T14:58+b046e01)"
|
|
10
10
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
[3/
|
|
3
|
-
[3/
|
|
2
|
+
[3/18/2026, 2:58:21 PM] > codeyam-combo@1.0.0 mergeDependencies
|
|
3
|
+
[3/18/2026, 2:58:21 PM] > node ./scripts/mergePackageJsonFiles.cjs
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
[3/
|
|
6
|
+
[3/18/2026, 2:58:22 PM] Merged dependencies into root package.json
|
|
7
7
|
|
package/codeyam-cli/src/cli.js
CHANGED
|
@@ -27,8 +27,11 @@ import memoryCommand from "./commands/memory.js";
|
|
|
27
27
|
import editorCommand from "./commands/editor.js";
|
|
28
28
|
import setupSimulationsCommand from "./commands/setup-simulations.js";
|
|
29
29
|
import { syncMocksMiddleware } from "./utils/syncMocksMiddleware.js";
|
|
30
|
+
import { telemetryMiddleware } from "./utils/telemetryMiddleware.js";
|
|
31
|
+
import { captureEvent } from "./utils/telemetry.js";
|
|
30
32
|
import { getDisplayVersion } from "./utils/versionInfo.js";
|
|
31
33
|
import { simulationGateMiddleware, buildSimulationEpilogue, } from "./utils/simulationGateMiddleware.js";
|
|
34
|
+
import telemetryCommand from "./commands/telemetry.js";
|
|
32
35
|
// Install global signal handlers for automatic process cleanup
|
|
33
36
|
// This ensures all child processes (analyzer, capture, etc.) are cleaned up on:
|
|
34
37
|
// - Ctrl+C (SIGINT)
|
|
@@ -49,11 +52,13 @@ yargs(hideBin(process.argv))
|
|
|
49
52
|
.usage('CodeYam local development CLI')
|
|
50
53
|
.middleware(simulationGateMiddleware)
|
|
51
54
|
.middleware(syncMocksMiddleware)
|
|
55
|
+
.middleware(telemetryMiddleware)
|
|
52
56
|
// Core commands (always visible in help)
|
|
53
57
|
.command(defaultCommand)
|
|
54
58
|
.command(startCommand)
|
|
55
59
|
.command(stopCommand)
|
|
56
60
|
.command(memoryCommand)
|
|
61
|
+
.command(telemetryCommand)
|
|
57
62
|
// Hidden commands (shown in epilogue when simulations are enabled)
|
|
58
63
|
.command(withoutDescribe(initCommand))
|
|
59
64
|
.command(withoutDescribe(updateConfigCommand))
|
|
@@ -81,6 +86,10 @@ yargs(hideBin(process.argv))
|
|
|
81
86
|
.strict()
|
|
82
87
|
.parseAsync()
|
|
83
88
|
.catch((error) => {
|
|
89
|
+
captureEvent('cli_error', {
|
|
90
|
+
command: process.argv[2] ?? 'unknown',
|
|
91
|
+
error_type: error?.constructor?.name ?? 'Error',
|
|
92
|
+
});
|
|
84
93
|
console.error('CLI Error:', error.message);
|
|
85
94
|
process.exit(1);
|
|
86
95
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli.ts"],"names":[],"mappings":";AAEA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AACzD,0BAA0B;AAC1B,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAClD,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,kBAAkB,MAAM,yBAAyB,CAAC;AACzD,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,cAAc,MAAM,oBAAoB,CAAC;AAChD,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAC3D,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,oBAAoB,MAAM,oCAAoC,CAAC;AACtE,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAC3D,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,YAAY,MAAM,kBAAkB,CAAC;AAC5C,OAAO,gBAAgB,MAAM,sBAAsB,CAAC;AACpD,OAAO,mBAAmB,MAAM,0BAA0B,CAAC;AAC3D,OAAO,WAAW,MAAM,iBAAiB,CAAC;AAC1C,OAAO,eAAe,MAAM,qBAAqB,CAAC;AAClD,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,aAAa,MAAM,mBAAmB,CAAC;AAC9C,OAAO,uBAAuB,MAAM,8BAA8B,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EACL,wBAAwB,EACxB,uBAAuB,GACxB,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../../src/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tests that `codeyam editor isolate` correctly parses multiple component
|
|
3
|
+
* names whether passed as separate args or a single quoted string.
|
|
4
|
+
*
|
|
5
|
+
* Bug: `codeyam editor isolate A B C` failed because yargs .strict()
|
|
6
|
+
* rejected extra positionals beyond the two declared (step, json).
|
|
7
|
+
* Claude would then try one at a time, wasting time and tokens.
|
|
8
|
+
*/
|
|
9
|
+
import { parseIsolateArgs } from "../editorIsolateArgs.js";
|
|
10
|
+
describe('parseIsolateArgs', () => {
|
|
11
|
+
it('should parse a single component name from json arg', () => {
|
|
12
|
+
expect(parseIsolateArgs('LogoMark', [])).toEqual(['LogoMark']);
|
|
13
|
+
});
|
|
14
|
+
it('should parse space-separated names from a single quoted json arg', () => {
|
|
15
|
+
// codeyam editor isolate "LogoMark AppHeader Button"
|
|
16
|
+
expect(parseIsolateArgs('LogoMark AppHeader Button', [])).toEqual([
|
|
17
|
+
'LogoMark',
|
|
18
|
+
'AppHeader',
|
|
19
|
+
'Button',
|
|
20
|
+
]);
|
|
21
|
+
});
|
|
22
|
+
it('should parse comma-separated names from json arg', () => {
|
|
23
|
+
expect(parseIsolateArgs('LogoMark,AppHeader,Button', [])).toEqual([
|
|
24
|
+
'LogoMark',
|
|
25
|
+
'AppHeader',
|
|
26
|
+
'Button',
|
|
27
|
+
]);
|
|
28
|
+
});
|
|
29
|
+
it('should collect extra positional args from argv._', () => {
|
|
30
|
+
// codeyam editor isolate LogoMark AppHeader Button
|
|
31
|
+
// yargs: json="LogoMark", argv._=["editor", "AppHeader", "Button"]
|
|
32
|
+
expect(parseIsolateArgs('LogoMark', ['editor', 'AppHeader', 'Button'])).toEqual(['LogoMark', 'AppHeader', 'Button']);
|
|
33
|
+
});
|
|
34
|
+
it('should deduplicate names from json and extras', () => {
|
|
35
|
+
expect(parseIsolateArgs('LogoMark', ['editor', 'LogoMark', 'AppHeader'])).toEqual(['LogoMark', 'AppHeader']);
|
|
36
|
+
});
|
|
37
|
+
it('should filter out empty strings', () => {
|
|
38
|
+
expect(parseIsolateArgs('LogoMark AppHeader', [])).toEqual([
|
|
39
|
+
'LogoMark',
|
|
40
|
+
'AppHeader',
|
|
41
|
+
]);
|
|
42
|
+
});
|
|
43
|
+
it('should return empty array when no names provided', () => {
|
|
44
|
+
expect(parseIsolateArgs(undefined, [])).toEqual([]);
|
|
45
|
+
expect(parseIsolateArgs('', [])).toEqual([]);
|
|
46
|
+
});
|
|
47
|
+
it('should filter out "editor" from argv._', () => {
|
|
48
|
+
expect(parseIsolateArgs(undefined, ['editor', 'LogoMark', 'AppHeader'])).toEqual(['LogoMark', 'AppHeader']);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
//# sourceMappingURL=editor.isolateArgs.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"editor.isolateArgs.test.js","sourceRoot":"","sources":["../../../../../src/commands/__tests__/editor.isolateArgs.test.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,QAAQ,CAAC,kBAAkB,EAAE,GAAG,EAAE;IAChC,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,gBAAgB,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;IACjE,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kEAAkE,EAAE,GAAG,EAAE;QAC1E,qDAAqD;QACrD,MAAM,CAAC,gBAAgB,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAChE,UAAU;YACV,WAAW;YACX,QAAQ;SACT,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,gBAAgB,CAAC,2BAA2B,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAChE,UAAU;YACV,WAAW;YACX,QAAQ;SACT,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,mDAAmD;QACnD,mEAAmE;QACnE,MAAM,CACJ,gBAAgB,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAChE,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,CACJ,gBAAgB,CAAC,UAAU,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAClE,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,iCAAiC,EAAE,GAAG,EAAE;QACzC,MAAM,CAAC,gBAAgB,CAAC,qBAAqB,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAC1D,UAAU;YACV,WAAW;SACZ,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QACpD,MAAM,CAAC,gBAAgB,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,MAAM,CACJ,gBAAgB,CAAC,SAAS,EAAE,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CACjE,CAAC,OAAO,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;IACvC,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -939,13 +939,29 @@ function printStep2(root, feature) {
|
|
|
939
939
|
console.log();
|
|
940
940
|
console.log(chalk.bold('Build the feature:'));
|
|
941
941
|
}
|
|
942
|
+
else {
|
|
943
|
+
console.log(chalk.bold('Prepare the database for this feature:'));
|
|
944
|
+
checkbox('List existing scenarios: `codeyam editor scenarios`');
|
|
945
|
+
console.log(chalk.dim(' Review existing scenarios to find seed data that best demonstrates the feature.'));
|
|
946
|
+
console.log(chalk.dim(" Don't create throwaway seed data — use what's already been curated."));
|
|
947
|
+
checkbox('Pick the scenario with seed data most relevant to this feature');
|
|
948
|
+
console.log(chalk.dim(" Think: which existing data state best exercises the feature you're building?"));
|
|
949
|
+
console.log(chalk.dim(' A scenario with diverse, realistic data is usually the best starting point.'));
|
|
950
|
+
checkbox('Load that scenario to seed the database and preview it:');
|
|
951
|
+
console.log(chalk.dim(` codeyam editor preview '{"scenarioId":"<id>","dimension":"${dim}"}'`));
|
|
952
|
+
console.log(chalk.dim(' This switches the active scenario, runs the seed adapter, and refreshes the preview.'));
|
|
953
|
+
console.log(chalk.dim(' If no existing scenario fits, use the default seed: npm run db:seed'));
|
|
954
|
+
console.log();
|
|
955
|
+
}
|
|
942
956
|
console.log(chalk.bold('Checklist:'));
|
|
943
957
|
checkbox('Create API routes that read from the database via Prisma');
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
958
|
+
if (!projectExists) {
|
|
959
|
+
checkbox('Seed the database with demo data');
|
|
960
|
+
checkbox('Create `.codeyam/seed-adapter.ts` so CodeYam can seed the database for scenarios');
|
|
961
|
+
console.log(chalk.dim(' The seed adapter reads a JSON file (path passed as CLI arg), wipes tables, inserts rows.'));
|
|
962
|
+
console.log(chalk.dim(" Use the project's own ORM (Prisma, Drizzle, etc.). See template for example."));
|
|
963
|
+
console.log(chalk.dim(' Run with: npx tsx .codeyam/seed-adapter.ts <path-to-seed-data.json>'));
|
|
964
|
+
}
|
|
949
965
|
checkbox('Verify the dev server shows the changes');
|
|
950
966
|
checkbox('If the feature involves auth, email, payments, or other common patterns: read FEATURE_PATTERNS.md');
|
|
951
967
|
// Responsive design guidance when building a mobile-responsive web app
|
|
@@ -1428,8 +1444,6 @@ function printStep12(root, feature) {
|
|
|
1428
1444
|
}
|
|
1429
1445
|
// ─── Step 13: Present ─────────────────────────────────────────────────
|
|
1430
1446
|
function printStep13(root, feature) {
|
|
1431
|
-
const port = getServerPort();
|
|
1432
|
-
const { defaultName: dim, names: dimNames } = getProjectDimensions(root);
|
|
1433
1447
|
const prevState = readState(root);
|
|
1434
1448
|
const isResuming = prevState?.step === 13;
|
|
1435
1449
|
const now = new Date().toISOString();
|
|
@@ -1448,18 +1462,9 @@ function printStep13(root, feature) {
|
|
|
1448
1462
|
console.log('Present the results to the user and get their approval.');
|
|
1449
1463
|
console.log();
|
|
1450
1464
|
console.log(chalk.bold('Checklist:'));
|
|
1451
|
-
checkbox('Fetch all scenarios: `codeyam editor scenarios`');
|
|
1452
|
-
console.log(chalk.dim(' Each scenario has a `changeStatus` field: "new", "edited", "impacted", or null.'));
|
|
1453
|
-
checkbox('Pick the best scenario to showcase from this working session:');
|
|
1454
|
-
console.log(chalk.dim(' Prefer scenarios with changeStatus "new" or "edited" (directly changed in this session).'));
|
|
1455
|
-
console.log(chalk.dim(' For app-level scenarios, prefer those showing the new/changed functionality.'));
|
|
1456
|
-
console.log(chalk.dim(' NEVER pick a scenario with changeStatus null — those are unchanged from a previous commit.'));
|
|
1457
|
-
checkbox('Switch the preview to that scenario using its `id` and `dimension`:');
|
|
1458
|
-
console.log(chalk.dim(` codeyam editor preview '{"scenarioId":"<id>","dimension":"${dim}"}'`));
|
|
1459
|
-
console.log(chalk.dim(' Use the dimension that matches the scenario — check its registered dimensions.'));
|
|
1460
|
-
printDimensionGuidance(dim, dimNames);
|
|
1461
1465
|
checkbox(`Show the results panel: \`codeyam editor show-results\``);
|
|
1462
1466
|
console.log(chalk.dim(' This opens a visual panel below the terminal showing all scenarios with screenshots.'));
|
|
1467
|
+
console.log(chalk.dim(' The preview automatically switches to the first app-level scenario.'));
|
|
1463
1468
|
console.log(chalk.dim(' The user can click scenarios to switch the live preview.'));
|
|
1464
1469
|
checkbox('Write a 1-2 sentence summary of what was built');
|
|
1465
1470
|
checkbox('Report test count and audit status (one line)');
|
|
@@ -1689,7 +1694,6 @@ function printMigrateStep4(root) {
|
|
|
1689
1694
|
}
|
|
1690
1695
|
const { pageName, pageIndex, totalPages } = pageInfo;
|
|
1691
1696
|
writeMigrationStepState(root, 4, pageName, pageIndex, totalPages);
|
|
1692
|
-
const { defaultName: dim, names: dimNames } = getProjectDimensions(root);
|
|
1693
1697
|
console.log();
|
|
1694
1698
|
console.log(chalk.bold.cyan(`━━━ Migration Step 4: Preview — ${pageName} (${pageIndex + 1}/${totalPages}) ━━━`));
|
|
1695
1699
|
console.log();
|
|
@@ -1699,11 +1703,8 @@ function printMigrateStep4(root) {
|
|
|
1699
1703
|
checkbox('Review all scenario screenshots for this page — do they look correct?');
|
|
1700
1704
|
checkbox('Check for client errors: `codeyam editor client-errors`');
|
|
1701
1705
|
checkbox('If any issues: fix the scenario data, re-register affected scenarios');
|
|
1702
|
-
checkbox('Fetch all scenarios: `codeyam editor scenarios`');
|
|
1703
|
-
checkbox('Pick the best scenario to showcase:');
|
|
1704
|
-
console.log(chalk.dim(` codeyam editor preview '{"scenarioId":"<id>","dimension":"${dim}"}'`));
|
|
1705
|
-
printDimensionGuidance(dim, dimNames);
|
|
1706
1706
|
checkbox('Show results: `codeyam editor show-results`');
|
|
1707
|
+
console.log(chalk.dim(' The preview automatically switches to the first app-level scenario.'));
|
|
1707
1708
|
console.log();
|
|
1708
1709
|
console.log(chalk.dim('The user should now see their existing page with live screenshots in the preview.'));
|
|
1709
1710
|
migrationStopGate(4, pageName, pageIndex, totalPages);
|
|
@@ -1863,18 +1864,14 @@ function printMigrateStep10(root) {
|
|
|
1863
1864
|
}
|
|
1864
1865
|
const { pageName, pageIndex, totalPages } = pageInfo;
|
|
1865
1866
|
writeMigrationStepState(root, 10, pageName, pageIndex, totalPages);
|
|
1866
|
-
const { defaultName: dim, names: dimNames } = getProjectDimensions(root);
|
|
1867
1867
|
console.log();
|
|
1868
1868
|
console.log(chalk.bold.cyan(`━━━ Migration Step 10: Present — ${pageName} (${pageIndex + 1}/${totalPages}) ━━━`));
|
|
1869
1869
|
console.log();
|
|
1870
1870
|
console.log("Show results and commit this page's migration.");
|
|
1871
1871
|
console.log();
|
|
1872
1872
|
console.log(chalk.bold('Checklist:'));
|
|
1873
|
-
checkbox('Fetch all scenarios: `codeyam editor scenarios`');
|
|
1874
|
-
checkbox('Pick the best scenario to showcase:');
|
|
1875
|
-
console.log(chalk.dim(` codeyam editor preview '{"scenarioId":"<id>","dimension":"${dim}"}'`));
|
|
1876
|
-
printDimensionGuidance(dim, dimNames);
|
|
1877
1873
|
checkbox('Show results: `codeyam editor show-results`');
|
|
1874
|
+
console.log(chalk.dim(' The preview automatically switches to the first app-level scenario.'));
|
|
1878
1875
|
checkbox('Write a 1-2 sentence summary of what was migrated');
|
|
1879
1876
|
console.log();
|
|
1880
1877
|
console.log(chalk.bold('Present a selection menu (AskUserQuestion with these EXACT option labels):'));
|
|
@@ -2347,6 +2344,8 @@ async function handleAnalyzeImports(options = {}) {
|
|
|
2347
2344
|
sha: e.sha,
|
|
2348
2345
|
name: e.name,
|
|
2349
2346
|
filePath: e.filePath || '',
|
|
2347
|
+
isDefaultExport: e.metadata?.notExported === false &&
|
|
2348
|
+
e.metadata?.namedExport === false,
|
|
2350
2349
|
})));
|
|
2351
2350
|
if (backfillResult.updated > 0 && !options.silent) {
|
|
2352
2351
|
console.log(chalk.green(`Linked ${backfillResult.updated} scenario(s) to their entities.`));
|
|
@@ -2955,10 +2954,69 @@ async function checkAuditGate() {
|
|
|
2955
2954
|
}
|
|
2956
2955
|
// Re-check after fix
|
|
2957
2956
|
const retry = await fetchAuditResult();
|
|
2958
|
-
|
|
2957
|
+
if (retry?.summary?.allPassing === true)
|
|
2958
|
+
return true;
|
|
2959
2959
|
}
|
|
2960
|
+
// Print specific failures so Claude knows what to fix without running audit separately
|
|
2961
|
+
printAuditGateFailures(data);
|
|
2960
2962
|
return false;
|
|
2961
2963
|
}
|
|
2964
|
+
/**
|
|
2965
|
+
* Print a concise summary of audit failures for the gate block message.
|
|
2966
|
+
* This gives Claude immediate context about what to fix without needing
|
|
2967
|
+
* to run `codeyam editor audit` as a separate step.
|
|
2968
|
+
*/
|
|
2969
|
+
function printAuditGateFailures(data) {
|
|
2970
|
+
const s = data.summary;
|
|
2971
|
+
if (!s)
|
|
2972
|
+
return;
|
|
2973
|
+
const issues = [];
|
|
2974
|
+
if (s.componentsMissing > 0)
|
|
2975
|
+
issues.push(`${s.componentsMissing} component(s) missing scenarios`);
|
|
2976
|
+
if (s.componentsWithErrors > 0)
|
|
2977
|
+
issues.push(`${s.componentsWithErrors} component(s) with client errors (browser API or runtime errors in captured scenarios)`);
|
|
2978
|
+
if (s.functionsMissing > 0)
|
|
2979
|
+
issues.push(`${s.functionsMissing} function(s) missing test files`);
|
|
2980
|
+
if (s.functionsFailing > 0)
|
|
2981
|
+
issues.push(`${s.functionsFailing} function(s) with failing tests`);
|
|
2982
|
+
if (s.functionsRunnerError > 0)
|
|
2983
|
+
issues.push(`${s.functionsRunnerError} function(s) with test runner errors (the runner crashed — not a test failure)`);
|
|
2984
|
+
if (s.functionsNameMismatch > 0)
|
|
2985
|
+
issues.push(`${s.functionsNameMismatch} function(s) with test name mismatch`);
|
|
2986
|
+
if (s.missingFromGlossary > 0)
|
|
2987
|
+
issues.push(`${s.missingFromGlossary} file(s) with scenarios not in glossary`);
|
|
2988
|
+
if (s.incompleteEntities > 0)
|
|
2989
|
+
issues.push(`${s.incompleteEntities} entity/entities need import analysis`);
|
|
2990
|
+
if (s.miscategorizedScenarios > 0)
|
|
2991
|
+
issues.push(`${s.miscategorizedScenarios} component(s) using page URLs instead of isolation routes`);
|
|
2992
|
+
if (issues.length > 0) {
|
|
2993
|
+
console.error(chalk.yellow('\nAudit failures:'));
|
|
2994
|
+
for (const issue of issues) {
|
|
2995
|
+
console.error(chalk.yellow(` • ${issue}`));
|
|
2996
|
+
}
|
|
2997
|
+
}
|
|
2998
|
+
// Surface client error details inline — these are the most common cause of
|
|
2999
|
+
// Claude looping because the errors require code fixes, not audit re-runs.
|
|
3000
|
+
if (data.components) {
|
|
3001
|
+
const withErrors = data.components.filter((c) => c.status === 'has_errors' && c.clientErrors?.length > 0);
|
|
3002
|
+
if (withErrors.length > 0) {
|
|
3003
|
+
console.error(chalk.yellow('\nClient errors found:'));
|
|
3004
|
+
for (const c of withErrors) {
|
|
3005
|
+
console.error(chalk.red(` ${c.name}:`));
|
|
3006
|
+
for (const err of c.clientErrors.slice(0, 3)) {
|
|
3007
|
+
console.error(chalk.red(` → ${err}`));
|
|
3008
|
+
}
|
|
3009
|
+
if (c.clientErrors.length > 3) {
|
|
3010
|
+
console.error(chalk.dim(` … and ${c.clientErrors.length - 3} more`));
|
|
3011
|
+
}
|
|
3012
|
+
}
|
|
3013
|
+
console.error(chalk.yellow('\nFix: Fix the code errors above, then re-capture the affected scenarios.'));
|
|
3014
|
+
console.error(chalk.yellow('If errors reference browser APIs (localStorage, sessionStorage, window, document),'));
|
|
3015
|
+
console.error(chalk.yellow('create a universal mock: codeyam detect-universal-mocks'));
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
console.error(chalk.dim('\nRun `codeyam editor audit` for full details.\n'));
|
|
3019
|
+
}
|
|
2962
3020
|
// ─── Audit subcommand ────────────────────────────────────────────────
|
|
2963
3021
|
/**
|
|
2964
3022
|
* `codeyam editor audit`
|
|
@@ -3027,6 +3085,14 @@ async function handleAudit() {
|
|
|
3027
3085
|
if (c.clientErrors.length > 3) {
|
|
3028
3086
|
console.log(chalk.dim(` … and ${c.clientErrors.length - 3} more`));
|
|
3029
3087
|
}
|
|
3088
|
+
// Detect browser API errors and provide actionable guidance
|
|
3089
|
+
const browserApiPattern = /\b(localStorage|sessionStorage|window\.|document\.|navigator\.|indexedDB|matchMedia|ResizeObserver|IntersectionObserver|MutationObserver)\b/;
|
|
3090
|
+
const hasBrowserApiErrors = c.clientErrors.some((err) => browserApiPattern.test(err));
|
|
3091
|
+
if (hasBrowserApiErrors) {
|
|
3092
|
+
console.log(chalk.yellow(` ⚠ These errors are caused by browser APIs that don't exist during server-side analysis.`));
|
|
3093
|
+
console.log(chalk.yellow(` Fix: Create a universal mock to stub the missing API. Run: codeyam detect-universal-mocks`));
|
|
3094
|
+
console.log(chalk.yellow(` DO NOT re-run the audit or analyze-imports — the error will persist until a mock is created.`));
|
|
3095
|
+
}
|
|
3030
3096
|
}
|
|
3031
3097
|
}
|
|
3032
3098
|
console.log();
|
|
@@ -3041,6 +3107,14 @@ async function handleAudit() {
|
|
|
3041
3107
|
case 'ok':
|
|
3042
3108
|
detail = chalk.dim(` (${f.testFile})`);
|
|
3043
3109
|
break;
|
|
3110
|
+
case 'runner_error':
|
|
3111
|
+
detail = chalk.red(` — test runner crashed: ${f.testFile}`);
|
|
3112
|
+
if (f.errorMessage) {
|
|
3113
|
+
detail += `\n ${chalk.red(f.errorMessage)}`;
|
|
3114
|
+
detail += `\n ${chalk.yellow('Note: This is NOT a test failure — the test runner itself could not execute.')}`;
|
|
3115
|
+
detail += `\n ${chalk.yellow('Try running the test manually: npx vitest run ' + f.testFile)}`;
|
|
3116
|
+
}
|
|
3117
|
+
break;
|
|
3044
3118
|
case 'failing':
|
|
3045
3119
|
detail = chalk.red(` — tests failing: ${f.testFile}`);
|
|
3046
3120
|
break;
|
|
@@ -3077,9 +3151,13 @@ async function handleAudit() {
|
|
|
3077
3151
|
}
|
|
3078
3152
|
if (autoRemediationFailed) {
|
|
3079
3153
|
console.log(chalk.red(' analyze-imports was run automatically but these entities are STILL incomplete.'));
|
|
3080
|
-
console.log(chalk.red('
|
|
3081
|
-
console.log(chalk.yellow('
|
|
3082
|
-
console.log(chalk.yellow('
|
|
3154
|
+
console.log(chalk.red(' DO NOT re-run analyze-imports or the audit in a loop — the result will be the same.'));
|
|
3155
|
+
console.log(chalk.yellow(' This means the analysis failed for these entities. Common causes:'));
|
|
3156
|
+
console.log(chalk.yellow(' • Entity code uses browser APIs (localStorage, window, document) — create a universal mock'));
|
|
3157
|
+
console.log(chalk.yellow(' • Source file was renamed/deleted but glossary still references the old path'));
|
|
3158
|
+
console.log(chalk.yellow(' • Entity has import errors that prevent analysis'));
|
|
3159
|
+
console.log(chalk.yellow(' To investigate: run `codeyam editor analyze-imports` (without --silent) to see the full error.'));
|
|
3160
|
+
console.log(chalk.yellow(' To fix browser API issues: run `codeyam detect-universal-mocks`'));
|
|
3083
3161
|
}
|
|
3084
3162
|
else {
|
|
3085
3163
|
console.log(chalk.yellow(' Run `codeyam editor analyze-imports` to analyze these entities'));
|
|
@@ -3121,6 +3199,9 @@ async function handleAudit() {
|
|
|
3121
3199
|
if (summary.functionsFailing > 0) {
|
|
3122
3200
|
parts.push(`${summary.functionsFailing} function${summary.functionsFailing !== 1 ? 's' : ''} with failing tests`);
|
|
3123
3201
|
}
|
|
3202
|
+
if (summary.functionsRunnerError > 0) {
|
|
3203
|
+
parts.push(`${summary.functionsRunnerError} function${summary.functionsRunnerError !== 1 ? 's' : ''} with test runner errors (not test failures — see details above)`);
|
|
3204
|
+
}
|
|
3124
3205
|
if (summary.functionsNameMismatch > 0) {
|
|
3125
3206
|
parts.push(`${summary.functionsNameMismatch} function${summary.functionsNameMismatch !== 1 ? 's' : ''} with test name mismatch (missing top-level describe)`);
|
|
3126
3207
|
}
|
|
@@ -3267,6 +3348,8 @@ async function handleScenarioCoverage() {
|
|
|
3267
3348
|
sha: e.sha,
|
|
3268
3349
|
name: e.name,
|
|
3269
3350
|
filePath: e.filePath || '',
|
|
3351
|
+
isDefaultExport: e.metadata?.notExported === false &&
|
|
3352
|
+
e.metadata?.namedExport === false,
|
|
3270
3353
|
})));
|
|
3271
3354
|
}
|
|
3272
3355
|
}
|
|
@@ -3812,7 +3895,9 @@ const editorCommand = {
|
|
|
3812
3895
|
describe: 'Debug: output directory for the bundle',
|
|
3813
3896
|
});
|
|
3814
3897
|
}
|
|
3815
|
-
|
|
3898
|
+
// Allow extra positional args for subcommands like `isolate A B C`
|
|
3899
|
+
// without yargs rejecting them as unknown.
|
|
3900
|
+
return builder.strict(false);
|
|
3816
3901
|
},
|
|
3817
3902
|
handler: async (argv) => {
|
|
3818
3903
|
const root = getProjectRoot();
|
|
@@ -3897,13 +3982,10 @@ const editorCommand = {
|
|
|
3897
3982
|
return;
|
|
3898
3983
|
}
|
|
3899
3984
|
// Subcommand: codeyam editor isolate "StarRating CategoryBadge DrinkCard"
|
|
3985
|
+
// Also supports: codeyam editor isolate StarRating CategoryBadge DrinkCard
|
|
3900
3986
|
if (argv.step === 'isolate') {
|
|
3901
|
-
const
|
|
3902
|
-
|
|
3903
|
-
names.push(...argv.json.split(/[\s,]+/).filter(Boolean));
|
|
3904
|
-
// Collect any extra positional args (yargs puts them in argv._)
|
|
3905
|
-
const extras = argv._.filter((a) => typeof a === 'string' && a !== 'editor');
|
|
3906
|
-
names.push(...extras);
|
|
3987
|
+
const { parseIsolateArgs } = await import('./editorIsolateArgs.js');
|
|
3988
|
+
const names = parseIsolateArgs(argv.json, argv._);
|
|
3907
3989
|
handleIsolate(names);
|
|
3908
3990
|
return;
|
|
3909
3991
|
}
|
|
@@ -4091,6 +4173,41 @@ const editorCommand = {
|
|
|
4091
4173
|
catch {
|
|
4092
4174
|
// Non-fatal — migration failure shouldn't block editor startup
|
|
4093
4175
|
}
|
|
4176
|
+
// Auto-seed on fresh clone: if no scenario has ever been activated
|
|
4177
|
+
// (active-scenario.json doesn't exist), seed the application database
|
|
4178
|
+
// with the first application scenario that has seed data.
|
|
4179
|
+
const activeScenarioPath = path.join(projectRoot, '.codeyam', 'active-scenario.json');
|
|
4180
|
+
if (!fs.existsSync(activeScenarioPath)) {
|
|
4181
|
+
try {
|
|
4182
|
+
const { getDatabase: getDb } = await import('../../../packages/database/index.js');
|
|
4183
|
+
const seedDb = getDb();
|
|
4184
|
+
const appScenario = await seedDb
|
|
4185
|
+
.selectFrom('editor_scenarios')
|
|
4186
|
+
.select(['id', 'name', 'type'])
|
|
4187
|
+
.where('project_id', '=', project.id)
|
|
4188
|
+
.where('type', '=', 'application')
|
|
4189
|
+
.orderBy('created_at', 'asc')
|
|
4190
|
+
.executeTakeFirst();
|
|
4191
|
+
if (appScenario) {
|
|
4192
|
+
const seedFile = path.join(projectRoot, '.codeyam', 'editor-scenarios', `${appScenario.id}.seed.json`);
|
|
4193
|
+
if (fs.existsSync(seedFile)) {
|
|
4194
|
+
const { switchActiveScenario } = await import('../utils/editorScenarioSwitch.js');
|
|
4195
|
+
const seedResult = await switchActiveScenario({
|
|
4196
|
+
scenarioId: appScenario.id,
|
|
4197
|
+
scenarioName: appScenario.name || undefined,
|
|
4198
|
+
scenarioType: appScenario.type || undefined,
|
|
4199
|
+
projectRoot,
|
|
4200
|
+
});
|
|
4201
|
+
if (seedResult.seedResult?.success) {
|
|
4202
|
+
console.log(chalk.green(` Auto-seeded database with scenario: ${appScenario.name || appScenario.id}`));
|
|
4203
|
+
}
|
|
4204
|
+
}
|
|
4205
|
+
}
|
|
4206
|
+
}
|
|
4207
|
+
catch {
|
|
4208
|
+
// Non-fatal — auto-seed is best-effort
|
|
4209
|
+
}
|
|
4210
|
+
}
|
|
4094
4211
|
// `codeyam editor` (no step) always implies editor mode.
|
|
4095
4212
|
// The empty-folder heuristic is no longer needed here — running this
|
|
4096
4213
|
// command IS the signal. We still detect empty folders so that
|
|
@@ -4235,6 +4352,48 @@ const editorCommand = {
|
|
|
4235
4352
|
}
|
|
4236
4353
|
}
|
|
4237
4354
|
}
|
|
4355
|
+
// Backfill page_file_path for application scenarios that have a URL but
|
|
4356
|
+
// no page_file_path. This resolves the file from the URL using Next.js
|
|
4357
|
+
// routing conventions, enabling syncScenarioEntityShas to link them to
|
|
4358
|
+
// entities. Covers fresh clones where JSON files lack pageFilePath.
|
|
4359
|
+
try {
|
|
4360
|
+
const { getDatabase: getDb } = await import('../../../packages/database/index.js');
|
|
4361
|
+
const pfpDb = getDb();
|
|
4362
|
+
const unresolved = await pfpDb
|
|
4363
|
+
.selectFrom('editor_scenarios')
|
|
4364
|
+
.select(['id', 'url'])
|
|
4365
|
+
.where('project_id', '=', project.id)
|
|
4366
|
+
.where('component_name', 'is', null)
|
|
4367
|
+
.where('page_file_path', 'is', null)
|
|
4368
|
+
.where('url', 'is not', null)
|
|
4369
|
+
.execute();
|
|
4370
|
+
if (unresolved.length > 0) {
|
|
4371
|
+
const { scanPageFilePaths: scanPfp } = await import('../utils/entityChangeStatus.server.js');
|
|
4372
|
+
const { matchUrlToPageFile } = await import('../utils/routePatternMatching');
|
|
4373
|
+
const { allFiles: pfpFiles } = scanPfp(projectRoot);
|
|
4374
|
+
let pfpResolved = 0;
|
|
4375
|
+
for (const row of unresolved) {
|
|
4376
|
+
const r = row;
|
|
4377
|
+
if (!r.url)
|
|
4378
|
+
continue;
|
|
4379
|
+
const matched = matchUrlToPageFile(r.url, pfpFiles);
|
|
4380
|
+
if (matched) {
|
|
4381
|
+
await pfpDb
|
|
4382
|
+
.updateTable('editor_scenarios')
|
|
4383
|
+
.set({ page_file_path: matched })
|
|
4384
|
+
.where('id', '=', r.id)
|
|
4385
|
+
.execute();
|
|
4386
|
+
pfpResolved++;
|
|
4387
|
+
}
|
|
4388
|
+
}
|
|
4389
|
+
if (pfpResolved > 0) {
|
|
4390
|
+
console.log(chalk.green(` Resolved page_file_path for ${pfpResolved} scenario(s) from URL`));
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4394
|
+
catch {
|
|
4395
|
+
/* Non-fatal — page_file_path backfill from URL */
|
|
4396
|
+
}
|
|
4238
4397
|
// Backfill entity_sha on scenarios that were synced before entities existed.
|
|
4239
4398
|
// This runs independently of analyze-imports so fresh clones and file-synced
|
|
4240
4399
|
// scenarios get linked to their entities even when auto-analyze doesn't trigger.
|
|
@@ -4247,6 +4406,8 @@ const editorCommand = {
|
|
|
4247
4406
|
sha: e.sha,
|
|
4248
4407
|
name: e.name,
|
|
4249
4408
|
filePath: e.filePath || '',
|
|
4409
|
+
isDefaultExport: e.metadata?.notExported === false &&
|
|
4410
|
+
e.metadata?.namedExport === false,
|
|
4250
4411
|
})));
|
|
4251
4412
|
if (result.updated > 0) {
|
|
4252
4413
|
console.log(chalk.green(` Linked ${result.updated} scenario(s) to their entities`));
|
|
@@ -4341,8 +4502,9 @@ const editorCommand = {
|
|
|
4341
4502
|
if (step >= 8) {
|
|
4342
4503
|
const auditOk = await checkAuditGate();
|
|
4343
4504
|
if (!auditOk) {
|
|
4344
|
-
|
|
4345
|
-
console.error(chalk.
|
|
4505
|
+
// checkAuditGate() already printed specific failure details above
|
|
4506
|
+
console.error(chalk.red.bold('BLOCKED: The audit has not passed. Fix the issues listed above before proceeding.'));
|
|
4507
|
+
console.error(chalk.yellow('DO NOT re-run the audit in a loop — fix the underlying issues first.'));
|
|
4346
4508
|
process.exit(1);
|
|
4347
4509
|
}
|
|
4348
4510
|
}
|