@codeyam/codeyam-cli 0.1.14 → 0.1.16

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.
Files changed (106) hide show
  1. package/analyzer-template/.build-info.json +6 -6
  2. package/analyzer-template/log.txt +3 -3
  3. package/codeyam-cli/src/commands/editor.js +108 -12
  4. package/codeyam-cli/src/commands/editor.js.map +1 -1
  5. package/codeyam-cli/src/commands/init.js +1 -0
  6. package/codeyam-cli/src/commands/init.js.map +1 -1
  7. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +400 -1
  8. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
  9. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +39 -0
  10. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
  11. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +57 -0
  12. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -1
  13. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +180 -1
  14. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -1
  15. package/codeyam-cli/src/utils/backgroundServer.js +1 -1
  16. package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
  17. package/codeyam-cli/src/utils/editorAudit.js +93 -1
  18. package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
  19. package/codeyam-cli/src/utils/editorScenarios.js +5 -1
  20. package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
  21. package/codeyam-cli/src/utils/install-skills.js +5 -0
  22. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  23. package/codeyam-cli/src/utils/scenarioCoverage.js +4 -1
  24. package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -1
  25. package/codeyam-cli/src/utils/scenariosManifest.js +36 -0
  26. package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -1
  27. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +40 -0
  28. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -1
  29. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +92 -21
  30. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -1
  31. package/codeyam-cli/src/webserver/app/lib/clientErrors.js +7 -1
  32. package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -1
  33. package/codeyam-cli/src/webserver/backgroundServer.js +42 -57
  34. package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
  35. package/codeyam-cli/src/webserver/build/client/assets/{CopyButton-CzTDWkF2.js → CopyButton-CLe80MMu.js} +1 -1
  36. package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-BFbq6iFk.js → EntityItem-Crt_KN_U.js} +1 -1
  37. package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-B6OMi58N.js → EntityTypeIcon-CD7lGABo.js} +1 -1
  38. package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-DuYodzo1.js → InlineSpinner-CgTNOhnu.js} +1 -1
  39. package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CXo9EeCl.js → InteractivePreview-CKeQT5Ty.js} +2 -2
  40. package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-DYCNb2It.js → LibraryFunctionPreview-D3s1MFkb.js} +1 -1
  41. package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CZgY3sxX.js → LogViewer-CM5zg40N.js} +1 -1
  42. package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-CnYYwRDw.js → ReportIssueModal-C2PLkej3.js} +1 -1
  43. package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CDoF7ZpU.js → SafeScreenshot-DanvyBPb.js} +1 -1
  44. package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DrnfvaLL.js → ScenarioViewer-DUMfcNVK.js} +1 -1
  45. package/codeyam-cli/src/webserver/build/client/assets/{Spinner-Df3UCi8k.js → Spinner-D0LgAaSa.js} +1 -1
  46. package/codeyam-cli/src/webserver/build/client/assets/{ViewportInspectBar-DRKR9T0U.js → ViewportInspectBar-BA_Ry-rs.js} +1 -1
  47. package/codeyam-cli/src/webserver/build/client/assets/{_index-ClR-g3tY.js → _index-BAWd-Xjf.js} +1 -1
  48. package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-DTH6ydEA.js → activity.(_tab)-BOARiB-g.js} +1 -1
  49. package/codeyam-cli/src/webserver/build/client/assets/{addon-web-links-74hnHF59.js → addon-web-links-CHx25PAe.js} +1 -1
  50. package/codeyam-cli/src/webserver/build/client/assets/{agent-transcripts-B8CYhCO9.js → agent-transcripts-Bg3e7q4S.js} +1 -1
  51. package/codeyam-cli/src/webserver/build/client/assets/{book-open-CLaoh4ac.js → book-open-CL-lMgHh.js} +1 -1
  52. package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-BZ2DZxbW.js → chevron-down-GmAjGS9-.js} +1 -1
  53. package/codeyam-cli/src/webserver/build/client/assets/{chunk-JZWAC4HX-BBXArFPl.js → chunk-JZWAC4HX-BAdwhyCx.js} +11 -11
  54. package/codeyam-cli/src/webserver/build/client/assets/{circle-check-CT4unAk-.js → circle-check-DFcQkN5j.js} +1 -1
  55. package/codeyam-cli/src/webserver/build/client/assets/{copy-zK0B6Nu-.js → copy-C6iF61Xs.js} +1 -1
  56. package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-DJB0YQJL.js → createLucideIcon-4ImjHTVC.js} +1 -1
  57. package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-CkXFP_i-.js → dev.empty-C8y4mmyv.js} +1 -1
  58. package/codeyam-cli/src/webserver/build/client/assets/editor._tab-Gbk_i5Js.js +1 -0
  59. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DN5ouXAl.js +58 -0
  60. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-oepecPae.js +41 -0
  61. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BqAN7hyG.js → entity._sha._-Blfy9UlN.js} +1 -1
  62. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-D1eikpe1.js → entity._sha.scenarios._scenarioId.dev-KTQuL0aj.js} +1 -1
  63. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-Dg1NhIms.js → entity._sha.scenarios._scenarioId.fullscreen-C6eeL24i.js} +1 -1
  64. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-CJX6kkkV.js → entity._sha_.create-scenario-DQM8E7L4.js} +1 -1
  65. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BhVjZhKg.js → entity._sha_.edit._scenarioId-CAoXLsQr.js} +1 -1
  66. package/codeyam-cli/src/webserver/build/client/assets/{entry.client-_gzKltPN.js → entry.client-SuW9syRS.js} +1 -1
  67. package/codeyam-cli/src/webserver/build/client/assets/{files-CV_17tZS.js → files-D-xGrg29.js} +1 -1
  68. package/codeyam-cli/src/webserver/build/client/assets/{git-D-YXmMbR.js → git-Bq_fbXP5.js} +1 -1
  69. package/codeyam-cli/src/webserver/build/client/assets/globals-fAqOD9ex.css +1 -0
  70. package/codeyam-cli/src/webserver/build/client/assets/{index-CCrgCshv.js → index-Bp1l4hSv.js} +1 -1
  71. package/codeyam-cli/src/webserver/build/client/assets/{index-BsX0F-9C.js → index-CWV9XZiG.js} +1 -1
  72. package/codeyam-cli/src/webserver/build/client/assets/{index-Blo6EK8G.js → index-DE3jI_dv.js} +1 -1
  73. package/codeyam-cli/src/webserver/build/client/assets/{labs-Byazq8Pv.js → labs-B_IX45ih.js} +1 -1
  74. package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-DVQ0oHR7.js → loader-circle-De-7qQ2u.js} +1 -1
  75. package/codeyam-cli/src/webserver/build/client/assets/manifest-389033be.js +1 -0
  76. package/codeyam-cli/src/webserver/build/client/assets/{memory-b-VmA2Vj.js → memory-Cx2xEx7s.js} +1 -1
  77. package/codeyam-cli/src/webserver/build/client/assets/{pause-DGcndCAa.js → pause-CFxEKL1u.js} +1 -1
  78. package/codeyam-cli/src/webserver/build/client/assets/root-DB3O9_9j.js +67 -0
  79. package/codeyam-cli/src/webserver/build/client/assets/{search-C0Uw0bcK.js → search-BdBb5aqc.js} +1 -1
  80. package/codeyam-cli/src/webserver/build/client/assets/{settings-OoNgHIfW.js → settings-DdE-Untf.js} +1 -1
  81. package/codeyam-cli/src/webserver/build/client/assets/{simulations-Bcemfu8a.js → simulations-DSCdE99u.js} +1 -1
  82. package/codeyam-cli/src/webserver/build/client/assets/{terminal-BgMmG7R9.js → terminal-CrplD4b1.js} +1 -1
  83. package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-Cs87hJYK.js → triangle-alert-DqJ0j69l.js} +1 -1
  84. package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-BR3Rs7JY.js → useCustomSizes-DhXHbEjP.js} +1 -1
  85. package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-BxxP_XF9.js → useLastLogLine-BNd5hYuW.js} +1 -1
  86. package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-BermyNU5.js → useReportContext-Cy5Qg_UR.js} +1 -1
  87. package/codeyam-cli/src/webserver/build/client/assets/{useToast-a_QN_W9_.js → useToast-5HR2j9ZE.js} +1 -1
  88. package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-if8kM_1Q.js → analysisRunner-D_1MSYeW.js} +1 -1
  89. package/codeyam-cli/src/webserver/build/server/assets/{index-CHymws6l.js → index-ckWaCf_v.js} +1 -1
  90. package/codeyam-cli/src/webserver/build/server/assets/{init-D3HkMDbI.js → init-ld124R4Z.js} +2 -2
  91. package/codeyam-cli/src/webserver/build/server/assets/{server-build-DTCzJQiH.js → server-build-DzzNZGv_.js} +125 -125
  92. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  93. package/codeyam-cli/src/webserver/build-info.json +5 -5
  94. package/codeyam-cli/src/webserver/idleDetector.js +41 -8
  95. package/codeyam-cli/src/webserver/idleDetector.js.map +1 -1
  96. package/codeyam-cli/src/webserver/scripts/journalCapture.ts +36 -0
  97. package/codeyam-cli/src/webserver/terminalServer.js +5 -5
  98. package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
  99. package/codeyam-cli/templates/codeyam-editor-reference.md +214 -0
  100. package/package.json +1 -1
  101. package/codeyam-cli/src/webserver/build/client/assets/editor._tab-DPw7NZHc.js +0 -1
  102. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DYqG1D_d.js +0 -58
  103. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-DggyRwOr.js +0 -41
  104. package/codeyam-cli/src/webserver/build/client/assets/globals-DRvOjyO3.css +0 -1
  105. package/codeyam-cli/src/webserver/build/client/assets/manifest-f4212c17.js +0 -1
  106. package/codeyam-cli/src/webserver/build/client/assets/root-F-k2uYj5.js +0 -67
@@ -1,10 +1,10 @@
1
1
  {
2
- "buildTimestamp": "2026-03-18T14:58:22.078Z",
3
- "buildTime": 1773845902078,
4
- "gitCommit": "4dda2c78ef15ac678fb9a0e8f4d270c514f30f81",
2
+ "buildTimestamp": "2026-03-19T01:18:46.592Z",
3
+ "buildTime": 1773883126592,
4
+ "gitCommit": "27da20c7d41586bf9567c2e2ac63312ba9fb9057",
5
5
  "nodeVersion": "v20.20.1",
6
6
  "contentHash": "b046e014847d5b02d10d6795839ccd0d5117627cbd0be413260824610596a63d",
7
- "buildNumber": 1092,
8
- "semanticVersion": "0.1.1092",
9
- "version": "0.1.1092 (2026-03-18T14:58+b046e01)"
7
+ "buildNumber": 1104,
8
+ "semanticVersion": "0.1.1104",
9
+ "version": "0.1.1104 (2026-03-19T01:18+b046e01)"
10
10
  }
@@ -1,7 +1,7 @@
1
1
 
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
2
+ [3/19/2026, 1:18:46 AM] > codeyam-combo@1.0.0 mergeDependencies
3
+ [3/19/2026, 1:18:46 AM] > node ./scripts/mergePackageJsonFiles.cjs
4
4
 
5
5
 
6
- [3/18/2026, 2:58:22 PM] Merged dependencies into root package.json
6
+ [3/19/2026, 1:18:46 AM] Merged dependencies into root package.json
7
7
 
@@ -205,6 +205,8 @@ function checkbox(text) {
205
205
  * Prints seed-based scenarios, mock-based fallback, @ file prefix, externalApis, url requirement, and error checking.
206
206
  */
207
207
  function printAppScenarioInstructions(pageName, route) {
208
+ const root = process.cwd();
209
+ const hasSeedAdapter = !!detectSeedAdapter(root);
208
210
  checkbox('Check existing scenarios: `codeyam editor scenarios`');
209
211
  console.log(chalk.dim(' Review existing scenarios — reuse and update their data rather than'));
210
212
  console.log(chalk.dim(' creating duplicates. Re-register with the same name to update a scenario.'));
@@ -230,10 +232,18 @@ function printAppScenarioInstructions(pageName, route) {
230
232
  console.log(chalk.yellow(' Required fields: "type":"application", "url" (real route), "pageFilePath" (source file)'));
231
233
  console.log(chalk.yellow(' Do NOT include "componentName" — that would make it a component scenario'));
232
234
  console.log();
233
- checkbox('Choose the right data approach for scenarios:');
234
- console.log(chalk.dim(' With seed adapter: add "seed":{...} to populate the database for each state'));
235
- console.log(chalk.dim(' Without seed adapter: add "mockData":{"routes":{"/api/...":{"body":[...]}}} to mock API responses'));
236
- console.log(chalk.dim(' For external APIs (Stripe, weather, etc.): add "externalApis":{"GET https://...":{"body":[...],"status":200}}'));
235
+ if (hasSeedAdapter) {
236
+ checkbox(chalk.bold.red('REQUIRED: Every app scenario MUST include "seed" data without it the page will be empty!'));
237
+ console.log(chalk.yellow(' A seed adapter exists — you MUST include "seed":{...} in every app scenario registration.'));
238
+ console.log(chalk.yellow(' An app scenario without seed data will render an empty page (no database rows = nothing to show).'));
239
+ console.log(chalk.dim(' "seed" maps table names to arrays of rows: "seed":{"user":[{"id":1,"name":"Alice"}],"article":[...]}'));
240
+ console.log(chalk.dim(' For external APIs: also add "externalApis":{"GET https://...":{"body":[...],"status":200}}'));
241
+ }
242
+ else {
243
+ checkbox('Include data in every app scenario — without it the page will be empty:');
244
+ console.log(chalk.dim(' Use "mockData":{"routes":{"/api/...":{"body":[...]}}} to mock API responses'));
245
+ console.log(chalk.dim(' For external APIs: add "externalApis":{"GET https://...":{"body":[...],"status":200}}'));
246
+ }
237
247
  checkbox('For large seed/mock data, write JSON to a temp file and use @ prefix:');
238
248
  console.log(chalk.dim(' Write JSON to .codeyam/tmp/scenario.json then register with:'));
239
249
  console.log(chalk.dim(' codeyam editor register @.codeyam/tmp/scenario.json'));
@@ -320,7 +330,7 @@ function printComponentCaptureInstructions() {
320
330
  console.log(chalk.dim(' The route defines a `scenarios` object mapping scenario names to props,'));
321
331
  console.log(chalk.dim(' reads `?s=ScenarioName` from the URL, and renders the component with those props.'));
322
332
  console.log(chalk.dim(' Wrap the component in a capture container with id="codeyam-capture":'));
323
- console.log(chalk.dim(' <div id="codeyam-capture" style={{ display:"inline-block", padding:"20px" }}>'));
333
+ console.log(chalk.dim(' <div id="codeyam-capture" style={{ display:"inline-block" }}>'));
324
334
  console.log(chalk.dim(' <div style={{ width:"100%", maxWidth:"..." }}> ← match the app\'s container width'));
325
335
  console.log(chalk.dim(' e.g. card in a 3-col grid → maxWidth:"24rem", full-width component → omit maxWidth'));
326
336
  console.log(chalk.dim(' The screenshot captures just this wrapper, so the component fills the image.'));
@@ -800,6 +810,7 @@ function printCycleOverview(root, state) {
800
810
  console.log(chalk.green('Start now: ') + chalk.bold('codeyam editor 1'));
801
811
  console.log(chalk.dim(' If the user already described what they want, pass it: codeyam editor 1 --prompt "their message"'));
802
812
  }
813
+ console.log(chalk.dim('If stuck on CLI commands, scenarios, or debugging, read: .codeyam/docs/editor-reference.md'));
803
814
  console.log();
804
815
  }
805
816
  // ─── Step 1: Plan ─────────────────────────────────────────────────────
@@ -2651,6 +2662,13 @@ async function handleRegister(jsonArg) {
2651
2662
  if (data.captureError)
2652
2663
  parts.push(chalk.yellow(`captureError="${data.captureError}"`));
2653
2664
  console.log(prefix + parts.join(' '));
2665
+ // Warn when application scenario is missing seed data
2666
+ if (data.missingSeedWarning) {
2667
+ console.log(chalk.red.bold('WARNING: No seed data in this application scenario!'));
2668
+ console.log(chalk.yellow(' This scenario has type "application" but no "seed" data was provided.'));
2669
+ console.log(chalk.yellow(' The page will render with an empty database — nothing will be visible.'));
2670
+ console.log(chalk.yellow(' Re-register with "seed":{...} containing the database rows this page needs.'));
2671
+ }
2654
2672
  // Surface client errors prominently so they can't be missed
2655
2673
  if (data.clientErrors && data.clientErrors.length > 0) {
2656
2674
  console.log(chalk.red.bold(`⚠ WARNING: ${data.clientErrors.length} client error${data.clientErrors.length !== 1 ? 's' : ''} detected during capture:`));
@@ -2658,6 +2676,14 @@ async function handleRegister(jsonArg) {
2658
2676
  console.log(chalk.red(` → ${err}`));
2659
2677
  }
2660
2678
  console.log(chalk.yellow(' The screenshot may show an error screen instead of the actual component.'));
2679
+ // Provide actionable debugging hints for HTTP/API errors
2680
+ const hasApiResponseError = data.clientErrors.some((e) => e.includes('API response error:'));
2681
+ const hasHttpError = data.clientErrors.some((e) => e.includes('HTTP error:'));
2682
+ if (hasHttpError || hasApiResponseError) {
2683
+ console.log(chalk.yellow(' To debug: look at the "API response error" lines above — they show the exact API endpoint'));
2684
+ console.log(chalk.yellow(' that failed and what the server returned. Then check the scenario seed data to ensure'));
2685
+ console.log(chalk.yellow(' all IDs referenced in the URL exist in the seed, and that the route is correct.'));
2686
+ }
2661
2687
  console.log(chalk.yellow(' Fix the issue and re-register this scenario.'));
2662
2688
  }
2663
2689
  if (!res.ok) {
@@ -2971,24 +2997,56 @@ function printAuditGateFailures(data) {
2971
2997
  if (!s)
2972
2998
  return;
2973
2999
  const issues = [];
2974
- if (s.componentsMissing > 0)
3000
+ if (s.componentsMissing > 0) {
2975
3001
  issues.push(`${s.componentsMissing} component(s) missing scenarios`);
2976
- if (s.componentsWithErrors > 0)
3002
+ const missing = (data.components || []).filter((c) => c.status === 'missing');
3003
+ for (const c of missing) {
3004
+ issues.push(` → ${c.name}${c.filePath ? ` (${c.filePath})` : ''}`);
3005
+ }
3006
+ }
3007
+ if (s.componentsWithErrors > 0) {
2977
3008
  issues.push(`${s.componentsWithErrors} component(s) with client errors (browser API or runtime errors in captured scenarios)`);
2978
- if (s.functionsMissing > 0)
3009
+ const withErrors = (data.components || []).filter((c) => c.status === 'has_errors');
3010
+ for (const c of withErrors) {
3011
+ issues.push(` → ${c.name}${c.filePath ? ` (${c.filePath})` : ''}`);
3012
+ }
3013
+ }
3014
+ if (s.functionsMissing > 0) {
2979
3015
  issues.push(`${s.functionsMissing} function(s) missing test files`);
2980
- if (s.functionsFailing > 0)
3016
+ const missing = (data.functions || []).filter((f) => f.status === 'missing');
3017
+ for (const f of missing) {
3018
+ issues.push(` → ${f.name}${f.filePath ? ` (${f.filePath})` : ''}`);
3019
+ }
3020
+ }
3021
+ if (s.functionsFailing > 0) {
2981
3022
  issues.push(`${s.functionsFailing} function(s) with failing tests`);
2982
- if (s.functionsRunnerError > 0)
3023
+ const failing = (data.functions || []).filter((f) => f.status === 'failing');
3024
+ for (const f of failing) {
3025
+ issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
3026
+ }
3027
+ }
3028
+ if (s.functionsRunnerError > 0) {
2983
3029
  issues.push(`${s.functionsRunnerError} function(s) with test runner errors (the runner crashed — not a test failure)`);
2984
- if (s.functionsNameMismatch > 0)
3030
+ const runnerErrors = (data.functions || []).filter((f) => f.status === 'runner_error');
3031
+ for (const f of runnerErrors) {
3032
+ issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
3033
+ }
3034
+ }
3035
+ if (s.functionsNameMismatch > 0) {
2985
3036
  issues.push(`${s.functionsNameMismatch} function(s) with test name mismatch`);
3037
+ const mismatch = (data.functions || []).filter((f) => f.status === 'name_mismatch');
3038
+ for (const f of mismatch) {
3039
+ issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
3040
+ }
3041
+ }
2986
3042
  if (s.missingFromGlossary > 0)
2987
3043
  issues.push(`${s.missingFromGlossary} file(s) with scenarios not in glossary`);
2988
3044
  if (s.incompleteEntities > 0)
2989
3045
  issues.push(`${s.incompleteEntities} entity/entities need import analysis`);
2990
3046
  if (s.miscategorizedScenarios > 0)
2991
3047
  issues.push(`${s.miscategorizedScenarios} component(s) using page URLs instead of isolation routes`);
3048
+ if (s.scenariosNeedingRecapture > 0)
3049
+ issues.push(`${s.scenariosNeedingRecapture} scenario(s) need recapture (dependency tree changed)`);
2992
3050
  if (issues.length > 0) {
2993
3051
  console.error(chalk.yellow('\nAudit failures:'));
2994
3052
  for (const issue of issues) {
@@ -3064,6 +3122,11 @@ async function handleAudit() {
3064
3122
  console.log();
3065
3123
  // Components
3066
3124
  if (components.length > 0) {
3125
+ // Build name frequency map for disambiguation
3126
+ const componentNameCounts = new Map();
3127
+ for (const c of components) {
3128
+ componentNameCounts.set(c.name, (componentNameCounts.get(c.name) || 0) + 1);
3129
+ }
3067
3130
  console.log(chalk.bold('Components (scenarios):'));
3068
3131
  for (const c of components) {
3069
3132
  const icon = c.status === 'ok' ? chalk.green('✓') : chalk.red('✗');
@@ -3077,7 +3140,11 @@ async function handleAudit() {
3077
3140
  else {
3078
3141
  detail = chalk.red(' — no scenarios registered');
3079
3142
  }
3080
- console.log(` ${icon} ${c.name}${detail}`);
3143
+ // Show file path for failing components always, for OK only when name is ambiguous
3144
+ const isDuplicate = (componentNameCounts.get(c.name) || 0) > 1;
3145
+ const showPath = c.status !== 'ok' || isDuplicate;
3146
+ const pathSuffix = showPath && c.filePath ? chalk.dim(` (${c.filePath})`) : '';
3147
+ console.log(` ${icon} ${c.name}${pathSuffix}${detail}`);
3081
3148
  if (c.clientErrors && c.clientErrors.length > 0) {
3082
3149
  for (const err of c.clientErrors.slice(0, 3)) {
3083
3150
  console.log(chalk.red(` → ${err}`));
@@ -3179,6 +3246,32 @@ async function handleAudit() {
3179
3246
  console.log(chalk.yellow(' or re-register with an isolation URL.'));
3180
3247
  console.log();
3181
3248
  }
3249
+ // Scenarios needing recapture (entity or dependency tree changed)
3250
+ const scenariosNeedingRecapture = data.scenariosNeedingRecapture || [];
3251
+ if (scenariosNeedingRecapture.length > 0) {
3252
+ console.log(chalk.bold('Scenarios needing recapture (dependency tree changed):'));
3253
+ for (const s of scenariosNeedingRecapture) {
3254
+ const reason = s.status.status === 'impacted' && s.status.impactedBy?.length
3255
+ ? `impacted by: ${s.status.impactedBy.map((d) => `${d.name} [${d.changeType}]`).join(', ')}`
3256
+ : `${s.status.status}`;
3257
+ console.log(` ${chalk.red('✗')} ${s.scenarioName} ${chalk.dim(`(${s.entityName} — ${reason})`)}`);
3258
+ }
3259
+ console.log(chalk.yellow(' Re-register these scenarios to capture updated screenshots.'));
3260
+ console.log();
3261
+ }
3262
+ // Duplicate glossary names (warning, not a failure)
3263
+ const duplicateNames = data.duplicateNames || [];
3264
+ if (duplicateNames.length > 0) {
3265
+ console.log(chalk.bold('Duplicate names in glossary (confusing for audit):'));
3266
+ for (const dn of duplicateNames) {
3267
+ console.log(` ${chalk.yellow('⚠')} "${dn.name}" appears ${dn.filePaths.length} times:`);
3268
+ for (const fp of dn.filePaths) {
3269
+ console.log(` ${fp}`);
3270
+ }
3271
+ }
3272
+ console.log(chalk.yellow(' Fix: remove duplicate entries or rename them to be unique in .codeyam/glossary.json'));
3273
+ console.log();
3274
+ }
3182
3275
  // Summary
3183
3276
  const allOk = summary.allPassing;
3184
3277
  if (allOk) {
@@ -3214,6 +3307,9 @@ async function handleAudit() {
3214
3307
  if (summary.miscategorizedScenarios > 0) {
3215
3308
  parts.push(`${summary.miscategorizedScenarios} component${summary.miscategorizedScenarios !== 1 ? 's' : ''} using page URLs instead of isolation routes`);
3216
3309
  }
3310
+ if (summary.scenariosNeedingRecapture > 0) {
3311
+ parts.push(`${summary.scenariosNeedingRecapture} scenario${summary.scenariosNeedingRecapture !== 1 ? 's' : ''} need recapture`);
3312
+ }
3217
3313
  console.log(chalk.red.bold('Audit failed: ') + parts.join(', '));
3218
3314
  }
3219
3315
  console.log();