@codeyam/codeyam-cli 0.1.27 → 0.1.29
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/analyzer-template/package.json +1 -1
- package/analyzer-template/packages/aws/package.json +5 -5
- package/codeyam-cli/src/commands/editor.js +232 -5
- package/codeyam-cli/src/commands/editor.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +136 -0
- package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/editorRoadmap.test.js +398 -0
- package/codeyam-cli/src/utils/__tests__/editorRoadmap.test.js.map +1 -0
- package/codeyam-cli/src/utils/designSystemShowcase.js +810 -0
- package/codeyam-cli/src/utils/designSystemShowcase.js.map +1 -0
- package/codeyam-cli/src/utils/editorAudit.js +6 -1
- package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
- package/codeyam-cli/src/utils/editorRoadmap.js +301 -0
- package/codeyam-cli/src/utils/editorRoadmap.js.map +1 -0
- package/codeyam-cli/src/utils/editorScenarios.js +10 -0
- package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
- package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js +1 -0
- package/codeyam-cli/src/webserver/__tests__/api.interactive-switch-scenario.test.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-CLe80MMu.js → CopyButton-DTBZZfSk.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-Crt_KN_U.js → EntityItem-BxclONWq.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-CD7lGABo.js → EntityTypeIcon-BsnEOJZ_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-CgTNOhnu.js → InlineSpinner-ByaELMbv.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-DtYTSPL2.js → InteractivePreview-6WjVfhxX.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-D3s1MFkb.js → LibraryFunctionPreview-ChX-Hp7W.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CM5zg40N.js → LogViewer-C-9zQdXg.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{MiniClaudeChat-CQENLSrF.js → MiniClaudeChat-BusrvT2F.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-C2PLkej3.js → ReportIssueModal-DQsceHVv.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-DanvyBPb.js → SafeScreenshot-DThcm_9M.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-CefgqbCr.js → ScenarioViewer-Cl4oOA3A.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{Spinner-Bc8BG-Lw.js → Spinner-CIil5-gb.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ViewportInspectBar-BA_Ry-rs.js → ViewportInspectBar-BqkA9zyZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{_index-C1YkzTAV.js → _index-DnOgyseQ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-yH46LLUz.js → activity.(_tab)-DqM9hbNE.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{addon-web-links-CHx25PAe.js → addon-web-links-C58dYPwR.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-Bg3e7q4S.js → agent-transcripts-B8NCeOrm.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/api.editor-roadmap-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{book-open-CL-lMgHh.js → book-open-BFSIqZgO.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-GmAjGS9-.js → chevron-down-B9fDzFVh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/chunk-UVKPFVEO-Bmq2apuh.js +43 -0
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-DFcQkN5j.js → circle-check-DLPObLUx.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{copy-C6iF61Xs.js → copy-DXEmO0TD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-4ImjHTVC.js → createLucideIcon-BwyFiRot.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-CRepiabR.js → dev.empty-iRhRIFlp.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor._tab-BZPBzV73.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-785deXbZ.js +147 -0
- package/codeyam-cli/src/webserver/build/client/assets/{editorPreview-CluPkvXJ.js → editorPreview-C6fEYHrh.js} +6 -6
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-DYJRGiDI.js → entity._sha._-Ce1s4OQ1.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-wdiwx5-Z.js → entity._sha.scenarios._scenarioId.dev-C8AyYgYT.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-BrkN-40Y.js → entity._sha.scenarios._scenarioId.fullscreen-DziaVQX1.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-DxfhekTZ.js → entity._sha_.create-scenario-BTcpgIpC.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-CRXJWmpB.js → entity._sha_.edit._scenarioId-D_O_ajfZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-SuW9syRS.js → entry.client-j1Vi0bco.js} +6 -6
- package/codeyam-cli/src/webserver/build/client/assets/{files-D-xGrg29.js → files-kuny2Q_s.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{git-Bq_fbXP5.js → git-DgCZPMie.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-Bt7TsgQz.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{index-Bp1l4hSv.js → index-BliGSSpl.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-DE3jI_dv.js → index-SqjQKTdH.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-CWV9XZiG.js → index-vyrZD2g4.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{labs-B_IX45ih.js → labs-c3yLxSEp.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-De-7qQ2u.js → loader-circle-D-q28GLF.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-3d8cde80.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{memory-Cx2xEx7s.js → memory-CEWIUC4t.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{pause-CFxEKL1u.js → pause-BP6fitdh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{root-dKFRTYcy.js → root-CVjDQwjJ.js} +6 -6
- package/codeyam-cli/src/webserver/build/client/assets/{search-BdBb5aqc.js → search-BooqacKS.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{settings-DdE-Untf.js → settings-BM0nbryO.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-DSCdE99u.js → simulations-ovy6FjRY.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{terminal-CrplD4b1.js → terminal-DHemCJIs.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-DqJ0j69l.js → triangle-alert-D87ekDl8.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-DhXHbEjP.js → useCustomSizes-Dk0Tciqg.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-D9QZKaLJ.js → useLastLogLine-C8QvIe05.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-Cy5Qg_UR.js → useReportContext-jkCytuYz.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-5HR2j9ZE.js → useToast-BgqkixU9.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-OLsM110H.js → analysisRunner-CTJYMVFP.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-WHdB6WTN.js → index-CCth4Hgw.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{init-DbSiZoE6.js → init-UXl-3vVp.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{server-build-DZbLY6O_.js → server-build-DSW2mE30.js} +198 -147
- 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/server.js +67 -0
- package/codeyam-cli/src/webserver/server.js.map +1 -1
- package/codeyam-cli/src/webserver/terminalServer.js +21 -0
- package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
- package/codeyam-cli/templates/editor-step-hook.py +4 -4
- package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +36 -1
- package/codeyam-cli/templates/expo-react-native/app.json +11 -0
- package/codeyam-cli/templates/expo-react-native/package.json +1 -0
- package/package.json +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/chunk-JZWAC4HX-BAdwhyCx.js +0 -43
- package/codeyam-cli/src/webserver/build/client/assets/editor._tab-Gbk_i5Js.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-CRxPi2BB.js +0 -96
- package/codeyam-cli/src/webserver/build/client/assets/globals-BsGHu8WX.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-9032538f.js +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
|
-
"buildTimestamp": "2026-03-
|
|
3
|
-
"buildTime":
|
|
4
|
-
"gitCommit": "
|
|
2
|
+
"buildTimestamp": "2026-03-30T23:54:54.800Z",
|
|
3
|
+
"buildTime": 1774914894800,
|
|
4
|
+
"gitCommit": "0e92e67476166610824f499bf4183ae1ea4b4fcd",
|
|
5
5
|
"nodeVersion": "v20.20.1",
|
|
6
6
|
"contentHash": "c92230c027acb71cab56d2a696876a6a52206bfadd59fbc31a512b00a7ee8826",
|
|
7
|
-
"buildNumber":
|
|
8
|
-
"semanticVersion": "0.1.
|
|
9
|
-
"version": "0.1.
|
|
7
|
+
"buildNumber": 1299,
|
|
8
|
+
"semanticVersion": "0.1.1299",
|
|
9
|
+
"version": "0.1.1299 (2026-03-30T23:54+c92230c)"
|
|
10
10
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
|
|
2
|
-
[3/
|
|
3
|
-
[3/
|
|
2
|
+
[3/30/2026, 11:54:54 PM] > codeyam-combo@1.0.0 mergeDependencies
|
|
3
|
+
[3/30/2026, 11:54:54 PM] > node ./scripts/mergePackageJsonFiles.cjs
|
|
4
4
|
|
|
5
5
|
|
|
6
|
-
[3/
|
|
6
|
+
[3/30/2026, 11:54:54 PM] Merged dependencies into root package.json
|
|
7
7
|
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"yargs": "^18.0.0",
|
|
46
46
|
"json5": "^2.2.3",
|
|
47
47
|
"@anthropic-ai/sdk": "^0.78.0",
|
|
48
|
-
"@aws-sdk/s3-request-presigner": "^3.
|
|
48
|
+
"@aws-sdk/s3-request-presigner": "^3.1019.0",
|
|
49
49
|
"better-sqlite3": "^12.6.2",
|
|
50
50
|
"fetch-retry": "^6.0.0",
|
|
51
51
|
"kysely": "^0.28.14",
|
|
@@ -14,12 +14,12 @@
|
|
|
14
14
|
"@aws-sdk/client-codebuild": "^3.1014.0",
|
|
15
15
|
"@aws-sdk/client-cloudwatch-logs": "^3.990.0",
|
|
16
16
|
"@aws-sdk/client-dynamodb": "^3.990.0",
|
|
17
|
-
"@aws-sdk/client-ecr": "^3.
|
|
17
|
+
"@aws-sdk/client-ecr": "^3.1019.0",
|
|
18
18
|
"@aws-sdk/client-ecs": "^3.1009.0",
|
|
19
|
-
"@aws-sdk/client-s3": "^3.
|
|
20
|
-
"@aws-sdk/client-sqs": "^3.
|
|
21
|
-
"@aws-sdk/lib-storage": "^3.
|
|
22
|
-
"@aws-sdk/s3-request-presigner": "^3.
|
|
19
|
+
"@aws-sdk/client-s3": "^3.1019.0",
|
|
20
|
+
"@aws-sdk/client-sqs": "^3.1019.0",
|
|
21
|
+
"@aws-sdk/lib-storage": "^3.1019.0",
|
|
22
|
+
"@aws-sdk/s3-request-presigner": "^3.1019.0",
|
|
23
23
|
"@aws-sdk/util-dynamodb": "^3.990.0"
|
|
24
24
|
}
|
|
25
25
|
}
|
|
@@ -227,6 +227,143 @@ function getTechStackContext(root) {
|
|
|
227
227
|
: 'FEATURE_PATTERNS.md',
|
|
228
228
|
};
|
|
229
229
|
}
|
|
230
|
+
/**
|
|
231
|
+
* Returns a pre-populated tech stack for a given template ID.
|
|
232
|
+
* Written to .codeyam/config.json during `codeyam editor template`.
|
|
233
|
+
*/
|
|
234
|
+
function getTechStackForTemplate(templateId) {
|
|
235
|
+
switch (templateId) {
|
|
236
|
+
case 'nextjs-prisma-sqlite':
|
|
237
|
+
return {
|
|
238
|
+
languages: [
|
|
239
|
+
{
|
|
240
|
+
name: 'TypeScript',
|
|
241
|
+
url: 'https://typescriptlang.org',
|
|
242
|
+
description: 'Statically typed JavaScript superset',
|
|
243
|
+
version: '5',
|
|
244
|
+
},
|
|
245
|
+
],
|
|
246
|
+
frameworks: [
|
|
247
|
+
{
|
|
248
|
+
name: 'Next.js',
|
|
249
|
+
url: 'https://nextjs.org',
|
|
250
|
+
description: 'Full-stack React framework with App Router, SSR, and API routes',
|
|
251
|
+
version: '15',
|
|
252
|
+
},
|
|
253
|
+
{
|
|
254
|
+
name: 'React',
|
|
255
|
+
url: 'https://react.dev',
|
|
256
|
+
description: 'Component-based UI library',
|
|
257
|
+
version: '19',
|
|
258
|
+
},
|
|
259
|
+
],
|
|
260
|
+
databases: [
|
|
261
|
+
{
|
|
262
|
+
name: 'SQLite',
|
|
263
|
+
url: 'https://sqlite.org',
|
|
264
|
+
description: 'Embedded relational database — zero config, upgradeable to hosted DB',
|
|
265
|
+
},
|
|
266
|
+
],
|
|
267
|
+
libraries: [
|
|
268
|
+
{
|
|
269
|
+
name: 'Prisma',
|
|
270
|
+
url: 'https://prisma.io',
|
|
271
|
+
description: 'Type-safe database ORM and query builder',
|
|
272
|
+
version: '7',
|
|
273
|
+
},
|
|
274
|
+
{
|
|
275
|
+
name: 'Tailwind CSS',
|
|
276
|
+
url: 'https://tailwindcss.com',
|
|
277
|
+
description: 'Utility-first CSS framework',
|
|
278
|
+
version: '4',
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
};
|
|
282
|
+
case 'chrome-extension-react':
|
|
283
|
+
return {
|
|
284
|
+
languages: [
|
|
285
|
+
{
|
|
286
|
+
name: 'TypeScript',
|
|
287
|
+
url: 'https://typescriptlang.org',
|
|
288
|
+
description: 'Statically typed JavaScript superset',
|
|
289
|
+
version: '5',
|
|
290
|
+
},
|
|
291
|
+
],
|
|
292
|
+
frameworks: [
|
|
293
|
+
{
|
|
294
|
+
name: 'React',
|
|
295
|
+
url: 'https://react.dev',
|
|
296
|
+
description: 'Component-based UI library for the popup and options pages',
|
|
297
|
+
version: '19',
|
|
298
|
+
},
|
|
299
|
+
{
|
|
300
|
+
name: 'Vite',
|
|
301
|
+
url: 'https://vite.dev',
|
|
302
|
+
description: 'Fast build tool and dev server',
|
|
303
|
+
version: '6',
|
|
304
|
+
},
|
|
305
|
+
],
|
|
306
|
+
libraries: [
|
|
307
|
+
{
|
|
308
|
+
name: 'Tailwind CSS',
|
|
309
|
+
url: 'https://tailwindcss.com',
|
|
310
|
+
description: 'Utility-first CSS framework',
|
|
311
|
+
version: '4',
|
|
312
|
+
},
|
|
313
|
+
],
|
|
314
|
+
infrastructure: [
|
|
315
|
+
{
|
|
316
|
+
name: 'Chrome Manifest V3',
|
|
317
|
+
url: 'https://developer.chrome.com/docs/extensions/develop/migrate/what-is-mv3',
|
|
318
|
+
description: 'Extension platform with service workers, declarative APIs, and chrome.storage',
|
|
319
|
+
},
|
|
320
|
+
],
|
|
321
|
+
};
|
|
322
|
+
case 'expo-react-native':
|
|
323
|
+
return {
|
|
324
|
+
languages: [
|
|
325
|
+
{
|
|
326
|
+
name: 'TypeScript',
|
|
327
|
+
url: 'https://typescriptlang.org',
|
|
328
|
+
description: 'Statically typed JavaScript superset',
|
|
329
|
+
version: '5',
|
|
330
|
+
},
|
|
331
|
+
],
|
|
332
|
+
frameworks: [
|
|
333
|
+
{
|
|
334
|
+
name: 'Expo',
|
|
335
|
+
url: 'https://expo.dev',
|
|
336
|
+
description: 'React Native development platform with managed workflow and OTA updates',
|
|
337
|
+
version: 'SDK 54',
|
|
338
|
+
},
|
|
339
|
+
{
|
|
340
|
+
name: 'React Native',
|
|
341
|
+
url: 'https://reactnative.dev',
|
|
342
|
+
description: 'Cross-platform mobile UI framework',
|
|
343
|
+
},
|
|
344
|
+
{
|
|
345
|
+
name: 'Expo Router',
|
|
346
|
+
url: 'https://docs.expo.dev/router/introduction/',
|
|
347
|
+
description: 'File-based navigation for React Native apps',
|
|
348
|
+
},
|
|
349
|
+
],
|
|
350
|
+
libraries: [
|
|
351
|
+
{
|
|
352
|
+
name: 'NativeWind',
|
|
353
|
+
url: 'https://www.nativewind.dev',
|
|
354
|
+
description: 'Tailwind CSS for React Native',
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
name: 'AsyncStorage',
|
|
358
|
+
url: 'https://react-native-async-storage.github.io/async-storage/',
|
|
359
|
+
description: 'Persistent key-value storage for React Native',
|
|
360
|
+
},
|
|
361
|
+
],
|
|
362
|
+
};
|
|
363
|
+
default:
|
|
364
|
+
return {};
|
|
365
|
+
}
|
|
366
|
+
}
|
|
230
367
|
/**
|
|
231
368
|
* Print dimension guidance when the project has multiple screen sizes.
|
|
232
369
|
* Tells Claude to pick the right dimension for the content being previewed
|
|
@@ -376,6 +513,12 @@ function printExtractionPlanInstructions() {
|
|
|
376
513
|
console.log(chalk.yellow(' Every component that renders multiple distinct sections should be split into sub-components.'));
|
|
377
514
|
console.log(chalk.yellow(' If a component has N visually distinct parts, it should compose N sub-components.'));
|
|
378
515
|
console.log();
|
|
516
|
+
console.log(chalk.bold.red('THE DECOMPOSITION RULE: All code should do one thing.'));
|
|
517
|
+
console.log(chalk.yellow(' Code either contains logic OR brings together smaller pieces to form a coordinated whole.'));
|
|
518
|
+
console.log(chalk.yellow(' Every opportunity to extract code into a sensible function, helper, or sub-component MUST be taken.'));
|
|
519
|
+
console.log(chalk.yellow(' Then extract AGAIN from the extracted code — keep going until each piece does one clearly defined thing.'));
|
|
520
|
+
console.log(chalk.yellow(' This applies to ALL code: backend routes, business logic, frontend components, utilities — everything.'));
|
|
521
|
+
console.log();
|
|
379
522
|
console.log(chalk.bold('Checklist:'));
|
|
380
523
|
checkbox('Read `.codeyam/glossary.json` — note reusable functions/components');
|
|
381
524
|
checkbox('Read EVERY file used by this page/feature');
|
|
@@ -386,6 +529,12 @@ function printExtractionPlanInstructions() {
|
|
|
386
529
|
console.log(chalk.yellow(' Functions: data transforms, calculations, formatting, validation,'));
|
|
387
530
|
console.log(chalk.yellow(' API response shaping, any logic that is not directly about rendering'));
|
|
388
531
|
console.log(chalk.yellow(' Hooks: data fetching, state management, side effects'));
|
|
532
|
+
console.log(chalk.yellow(' Inline logic — backend AND frontend (MUST be extracted as named functions):'));
|
|
533
|
+
console.log(chalk.yellow(' conditionals/ternaries, computed/derived values, data transformations,'));
|
|
534
|
+
console.log(chalk.yellow(' string formatting/interpolation, array filtering/sorting/mapping callbacks,'));
|
|
535
|
+
console.log(chalk.yellow(' default value logic, null/undefined guards, date/number formatting,'));
|
|
536
|
+
console.log(chalk.yellow(' permission/role checks, status derivation (e.g. isOverdue(task)),'));
|
|
537
|
+
console.log(chalk.yellow(' request/response shaping, error message construction, config lookups'));
|
|
389
538
|
console.log();
|
|
390
539
|
checkbox('Write a numbered extraction plan listing EVERYTHING you will extract');
|
|
391
540
|
console.log(chalk.yellow(' The end state: every page file is ONLY imports + component composition.'));
|
|
@@ -396,6 +545,15 @@ function printExtractionPlanInstructions() {
|
|
|
396
545
|
console.log(chalk.yellow(' — What it is (component, function, hook)'));
|
|
397
546
|
console.log(chalk.yellow(' — Where it currently lives (source file + approximate lines)'));
|
|
398
547
|
console.log(chalk.yellow(' — Where it will go (new file path)'));
|
|
548
|
+
console.log(chalk.yellow(' — How you will test it (key inputs/outputs and edge cases)'));
|
|
549
|
+
console.log(chalk.yellow(' — What logic inside it can be further extracted as a separate testable function'));
|
|
550
|
+
console.log();
|
|
551
|
+
console.log(chalk.bold.red('BEFORE FINALIZING THE PLAN:'));
|
|
552
|
+
console.log(chalk.yellow(' Re-read every file ONE MORE TIME. For each piece of code, ask:'));
|
|
553
|
+
console.log(chalk.yellow(' 1. Does this do more than one thing? → Split it into pieces that each do one thing.'));
|
|
554
|
+
console.log(chalk.yellow(' 2. Is there logic here that could be its own function with clear inputs/outputs? → Extract it.'));
|
|
555
|
+
console.log(chalk.yellow(' 3. Can the extracted code itself be broken down further? → Keep extracting.'));
|
|
556
|
+
console.log(chalk.yellow(' If your plan has fewer functions than components, you probably missed extractable logic.'));
|
|
399
557
|
console.log();
|
|
400
558
|
console.log(chalk.dim('Present the numbered plan, then proceed to step 7 to execute it.'));
|
|
401
559
|
}
|
|
@@ -1008,6 +1166,15 @@ function printStep1(root, feature, options, userPrompt) {
|
|
|
1008
1166
|
console.log(chalk.dim(' -H "Content-Type: application/json" \\'));
|
|
1009
1167
|
console.log(chalk.dim(' -d \'{"projectTitle":"My App","projectDescription":"A short description of what this app does"}\''));
|
|
1010
1168
|
console.log();
|
|
1169
|
+
checkbox('Detect and set the project tech stack:');
|
|
1170
|
+
console.log(chalk.dim(' Scan package.json, framework configs (.env, .env.example, tsconfig.json, next.config.*, prisma/schema.prisma, etc.)'));
|
|
1171
|
+
console.log(chalk.dim(' to detect languages, frameworks, databases, services, libraries, and infrastructure.'));
|
|
1172
|
+
console.log(chalk.dim(' Each item MUST have name, url, and description. version and envKeys are optional.'));
|
|
1173
|
+
console.log(chalk.dim(` curl -s -X POST http://localhost:${port}/api/editor-project-info \\`));
|
|
1174
|
+
console.log(chalk.dim(' -H "Content-Type: application/json" \\'));
|
|
1175
|
+
console.log(chalk.dim(' -d \'{"techStack":{"languages":[{"name":"TypeScript","url":"https://typescriptlang.org","description":"Statically typed JavaScript superset","version":"5"}],"frameworks":[{"name":"Next.js","url":"https://nextjs.org","description":"Full-stack React framework with SSR and API routes","version":"15"}],"databases":[{"name":"SQLite","url":"https://sqlite.org","description":"Embedded relational database"}],"services":[{"name":"Stripe","url":"https://stripe.com","description":"Payment processing and billing","envKeys":["STRIPE_SECRET_KEY"]}],"libraries":[{"name":"Prisma","url":"https://prisma.io","description":"Type-safe database ORM","version":"7"}],"infrastructure":[]}}\''));
|
|
1176
|
+
console.log(chalk.dim(' Replace the example values with what you detect in this project. Omit empty categories.'));
|
|
1177
|
+
console.log();
|
|
1011
1178
|
const designSystem = readDesignSystem(root);
|
|
1012
1179
|
if (designSystem) {
|
|
1013
1180
|
console.log(chalk.bold.magenta('Design System (from .codeyam/design-system.md):'));
|
|
@@ -1085,6 +1252,21 @@ function printStep2(root, feature) {
|
|
|
1085
1252
|
console.log();
|
|
1086
1253
|
console.log(chalk.dim(' Read MOBILE_SETUP.md for data storage, navigation, and testing patterns.'));
|
|
1087
1254
|
console.log();
|
|
1255
|
+
checkbox('Ask the user what to name the app (use AskUserQuestion), then update app.json');
|
|
1256
|
+
console.log(chalk.dim(' Update name, slug, scheme, ios.bundleIdentifier (com.codeyam.<slug>), and android.package'));
|
|
1257
|
+
console.log(chalk.dim(' Also set the projectTitle via: curl -s -X POST http://localhost:' +
|
|
1258
|
+
port +
|
|
1259
|
+
'/api/editor-project-info -H "Content-Type: application/json" -d \'{"projectTitle":"<name>"}\''));
|
|
1260
|
+
console.log();
|
|
1261
|
+
checkbox('Generate an app icon using `sharp`');
|
|
1262
|
+
console.log(chalk.dim(' Create `scripts/generate-icon.mjs` and `mkdir -p assets`'));
|
|
1263
|
+
console.log(chalk.yellow(' ICON DESIGN GOAL: The icon must look distinctive on a home screen full of other app icons.'));
|
|
1264
|
+
console.log(chalk.yellow(' Use multiple bold colors from the design system and complex, overlapping shapes.'));
|
|
1265
|
+
console.log(chalk.yellow(' NO simple/minimal icons — no single glyph on a flat background, no plain text, no basic circles.'));
|
|
1266
|
+
console.log(chalk.yellow(' Make it colorful, layered, and dense. Use gradients, multiple contrasting fills, and depth.'));
|
|
1267
|
+
console.log(chalk.dim(' Use sharp to render SVG to 1024x1024 PNG. iOS: flatten onto background (no alpha channel).'));
|
|
1268
|
+
console.log(chalk.dim(' Generate: icon.png, adaptive-icon.png, favicon.png (48x48). Run `node scripts/generate-icon.mjs`'));
|
|
1269
|
+
console.log();
|
|
1088
1270
|
}
|
|
1089
1271
|
else if (ctx.isChromeExt) {
|
|
1090
1272
|
// Chrome Extension: use chrome.storage
|
|
@@ -1219,6 +1401,10 @@ function printStep3(root, feature) {
|
|
|
1219
1401
|
console.log(chalk.dim(' Bad: color: "#333", fontSize: 14, padding: 12'));
|
|
1220
1402
|
console.log(chalk.dim(' Good: color: theme.colors.textPrimary, fontSize: theme.fontSize.sm, padding: theme.spacing.md'));
|
|
1221
1403
|
console.log(chalk.dim(' Do NOT use CSS custom properties (var(--token)) — they do not work in React Native.'));
|
|
1404
|
+
checkbox('Buttons: put backgroundColor, borderRadius, borderStyle on a wrapping <View>, NOT on <Pressable>');
|
|
1405
|
+
console.log(chalk.dim(' Pressable renders these styles on web but FAILS SILENTLY on native devices.'));
|
|
1406
|
+
console.log(chalk.dim(' Use a <View> with overflow:"hidden" for the visual shell, <Pressable> inside for touch only.'));
|
|
1407
|
+
console.log(chalk.dim(' For press feedback: use onPressIn/onPressOut + useState to toggle opacity, not function-style style.'));
|
|
1222
1408
|
}
|
|
1223
1409
|
else {
|
|
1224
1410
|
checkbox('Define ALL design tokens as CSS custom properties in globals.css — not just colors');
|
|
@@ -1426,6 +1612,9 @@ function printStep7(root, feature) {
|
|
|
1426
1612
|
checkbox('For each function/hook: write MULTIPLE failing tests FIRST, then extract to make them pass');
|
|
1427
1613
|
console.log(chalk.dim(' Cover: typical inputs, edge cases, empty/null inputs, error conditions'));
|
|
1428
1614
|
console.log(chalk.dim(' Aim for 3-8 test cases per function depending on complexity'));
|
|
1615
|
+
console.log(chalk.dim(' EVERY conditional branch in the function MUST have a test that exercises it'));
|
|
1616
|
+
console.log(chalk.dim(' EVERY return path MUST be tested — if a function can return 3 different things, write 3+ tests'));
|
|
1617
|
+
console.log(chalk.dim(' Boundary values: 0, 1, -1, empty string, empty array, undefined, null'));
|
|
1429
1618
|
console.log(chalk.dim(' Hooks count as functions — useDrinks, useAuth, etc. all need test files'));
|
|
1430
1619
|
console.log(chalk.dim(' Wrap all tests in a describe("FunctionName", ...) block — the audit matches on this name'));
|
|
1431
1620
|
if (ctx.isExpo) {
|
|
@@ -1442,6 +1631,23 @@ function printStep7(root, feature) {
|
|
|
1442
1631
|
console.log(chalk.yellow(` Check: does any file contain raw ${ctx.rawPrimitivesList}?`));
|
|
1443
1632
|
console.log(chalk.yellow(' If yes → that JSX section is a component waiting to be extracted.'));
|
|
1444
1633
|
console.log();
|
|
1634
|
+
console.log(chalk.bold('Decomposition pass (backend AND frontend):'));
|
|
1635
|
+
checkbox('Re-read EVERY file you created or modified. For each, extract a function/helper/sub-component for:');
|
|
1636
|
+
console.log(chalk.yellow(' — Conditionals (e.g. `isOverdue ? "red" : "green"` → `getStatusColor(date)`)'));
|
|
1637
|
+
console.log(chalk.yellow(' — Computed values (e.g. `items.filter(...).length` → `countActiveItems(items)`)'));
|
|
1638
|
+
console.log(chalk.yellow(' — Formatting (e.g. `${price.toFixed(2)}` → `formatPrice(price)`)'));
|
|
1639
|
+
console.log(chalk.yellow(' — Data transforms, validation, request/response shaping'));
|
|
1640
|
+
console.log(chalk.yellow(' — Anything doing more than one thing → split until each piece does one clearly defined thing'));
|
|
1641
|
+
checkbox('Then look at what you just extracted — can IT be broken down further? Keep going.');
|
|
1642
|
+
checkbox('Write tests for every extracted function (same TDD: failing tests FIRST)');
|
|
1643
|
+
console.log();
|
|
1644
|
+
console.log(chalk.bold.red('TEST QUALITY SELF-CHECK (before proceeding):'));
|
|
1645
|
+
checkbox('For EACH test file: count the test cases. Fewer than 3 tests for any function is a red flag.');
|
|
1646
|
+
checkbox('For EACH tested function: read the function, count the conditional branches. Every branch MUST have a test.');
|
|
1647
|
+
checkbox('For EACH tested function: verify you test at least one error/edge case, not just happy paths.');
|
|
1648
|
+
console.log(chalk.yellow(' If a function has an if/else, switch, or ternary — each path needs its own test case.'));
|
|
1649
|
+
console.log(chalk.yellow(' If a function handles null/undefined/empty — test those inputs explicitly.'));
|
|
1650
|
+
console.log();
|
|
1445
1651
|
console.log(chalk.bold('Verify before proceeding:'));
|
|
1446
1652
|
checkbox('Run all tests and verify they pass');
|
|
1447
1653
|
checkbox(`Page files contain ONLY imports + component composition — no raw ${ctx.isExpo ? 'React Native primitives' : 'HTML tags'}`);
|
|
@@ -1520,6 +1726,15 @@ function printStep9(root, feature) {
|
|
|
1520
1726
|
console.log();
|
|
1521
1727
|
console.log(chalk.dim('Do not proceed until both component isolations and library tests pass.'));
|
|
1522
1728
|
console.log();
|
|
1729
|
+
console.log(chalk.bold.red('DECOMPOSITION & COVERAGE REVIEW (before running audit):'));
|
|
1730
|
+
checkbox('Re-read every file. Extract any logic that could be its own function/helper/sub-component.');
|
|
1731
|
+
console.log(chalk.yellow(' Code either contains logic OR brings together smaller pieces.'));
|
|
1732
|
+
console.log(chalk.yellow(' Keep extracting until each piece does one clearly defined thing.'));
|
|
1733
|
+
console.log(chalk.yellow(' For each extraction: write failing test first, then extract, then make test pass.'));
|
|
1734
|
+
checkbox('Open each test file and verify: ≥3 test cases per function, happy path + edge case + error case');
|
|
1735
|
+
checkbox('If any function has fewer tests than conditional branches, add the missing tests NOW');
|
|
1736
|
+
checkbox('Update `.codeyam/glossary.json` with any new functions before running audit');
|
|
1737
|
+
console.log();
|
|
1523
1738
|
checkbox('Run `codeyam editor audit` to verify all components have scenarios and all functions/hooks have tests');
|
|
1524
1739
|
console.log(chalk.red.bold(' The audit is a HARD GATE — step 10 will refuse to run until the audit passes.'));
|
|
1525
1740
|
console.log(chalk.dim(' The audit auto-fixes incomplete entities by running targeted analysis on just the affected files.'));
|
|
@@ -2502,11 +2717,11 @@ function printStep18(root, feature) {
|
|
|
2502
2717
|
console.log(chalk.dim(' If the user wants help, guide them through `gh repo create` or manual GitHub setup, then push.'));
|
|
2503
2718
|
console.log(chalk.dim(' Task management is handled by the ━━━ TASK ━━━ directive below.'));
|
|
2504
2719
|
console.log();
|
|
2505
|
-
|
|
2506
|
-
console.log(chalk.yellow('
|
|
2720
|
+
const port = getServerPort();
|
|
2721
|
+
console.log(chalk.bold.yellow('IMPORTANT: After the push succeeds (or the user skips it), the feature is DONE.'));
|
|
2722
|
+
console.log(chalk.yellow(` Signal the UI by running: curl -s -X POST http://localhost:${port}/api/editor-feature-complete`));
|
|
2723
|
+
console.log(chalk.yellow(' Then STOP and wait. Do NOT ask the user what to build next — the UI handles the transition.'));
|
|
2507
2724
|
console.log(chalk.yellow(' Do NOT use `codeyam editor change` or start building directly.'));
|
|
2508
|
-
console.log(chalk.yellow(' Ask the user what they want to build. Once they tell you, run `codeyam editor 1` yourself.'));
|
|
2509
|
-
console.log(chalk.yellow(' NEVER tell the user to run `codeyam editor` commands — these are internal. Just ask what to build.'));
|
|
2510
2725
|
console.log(chalk.yellow(' The change workflow is ONLY for modifications during steps 1-15, not after commit.'));
|
|
2511
2726
|
stopGate(18, { confirm: true });
|
|
2512
2727
|
}
|
|
@@ -3999,7 +4214,12 @@ async function handleAudit(options) {
|
|
|
3999
4214
|
let detail;
|
|
4000
4215
|
switch (f.status) {
|
|
4001
4216
|
case 'ok':
|
|
4002
|
-
|
|
4217
|
+
if (f.testCaseCount !== undefined && f.testCaseCount < 3) {
|
|
4218
|
+
detail = chalk.yellow(` (${f.testFile}) — ⚠ only ${f.testCaseCount} test case${f.testCaseCount !== 1 ? 's' : ''}, consider adding more`);
|
|
4219
|
+
}
|
|
4220
|
+
else {
|
|
4221
|
+
detail = chalk.dim(` (${f.testFile}${f.testCaseCount !== undefined ? `, ${f.testCaseCount} tests` : ''})`);
|
|
4222
|
+
}
|
|
4003
4223
|
break;
|
|
4004
4224
|
case 'runner_error':
|
|
4005
4225
|
detail = chalk.red(` — test runner crashed: ${f.testFile}`);
|
|
@@ -4032,6 +4252,9 @@ async function handleAudit(options) {
|
|
|
4032
4252
|
}
|
|
4033
4253
|
console.log(` ${icon} ${f.name}${detail}`);
|
|
4034
4254
|
}
|
|
4255
|
+
if (summary.functionsThinCoverage > 0) {
|
|
4256
|
+
console.log(chalk.yellow.bold(` ⚠ ${summary.functionsThinCoverage} function${summary.functionsThinCoverage !== 1 ? 's' : ''} with thin test coverage (< 3 test cases). Add more tests to cover all branches.`));
|
|
4257
|
+
}
|
|
4035
4258
|
console.log();
|
|
4036
4259
|
}
|
|
4037
4260
|
// Missing from glossary
|
|
@@ -4605,6 +4828,10 @@ async function handleTemplate() {
|
|
|
4605
4828
|
if (stack?.supportedFormats) {
|
|
4606
4829
|
config.appFormats = stack.supportedFormats;
|
|
4607
4830
|
}
|
|
4831
|
+
// Pre-populate tech stack from template
|
|
4832
|
+
if (stack) {
|
|
4833
|
+
config.techStack = getTechStackForTemplate(stack.id);
|
|
4834
|
+
}
|
|
4608
4835
|
// Set mobile-first defaults for mobile-app projects
|
|
4609
4836
|
if (stack?.supportedFormats?.includes('mobile-app')) {
|
|
4610
4837
|
config.defaultScreenSize = {
|