@codeyam/codeyam-cli 0.1.15 → 0.1.17

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 (62) 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 +132 -9
  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 +212 -10
  8. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
  9. package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js +137 -0
  10. package/codeyam-cli/src/utils/__tests__/editorCaptureScenarioSeeding.test.js.map +1 -0
  11. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +70 -0
  12. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -1
  13. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js +51 -1
  14. package/codeyam-cli/src/utils/__tests__/editorScenarios.test.js.map +1 -1
  15. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +20 -1
  16. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -1
  17. package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js +177 -0
  18. package/codeyam-cli/src/utils/__tests__/glossaryAdd.test.js.map +1 -0
  19. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js +57 -0
  20. package/codeyam-cli/src/utils/__tests__/scenarioCoverage.test.js.map +1 -1
  21. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js +41 -0
  22. package/codeyam-cli/src/utils/__tests__/scenariosManifest.test.js.map +1 -1
  23. package/codeyam-cli/src/utils/editorAudit.js +51 -11
  24. package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
  25. package/codeyam-cli/src/utils/editorScenarioSwitch.js +24 -2
  26. package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -1
  27. package/codeyam-cli/src/utils/editorScenarios.js +28 -1
  28. package/codeyam-cli/src/utils/editorScenarios.js.map +1 -1
  29. package/codeyam-cli/src/utils/entityChangeStatus.js +1 -1
  30. package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -1
  31. package/codeyam-cli/src/utils/glossaryAdd.js +74 -0
  32. package/codeyam-cli/src/utils/glossaryAdd.js.map +1 -0
  33. package/codeyam-cli/src/utils/install-skills.js +5 -0
  34. package/codeyam-cli/src/utils/install-skills.js.map +1 -1
  35. package/codeyam-cli/src/utils/scenarioCoverage.js +4 -1
  36. package/codeyam-cli/src/utils/scenarioCoverage.js.map +1 -1
  37. package/codeyam-cli/src/utils/scenariosManifest.js +6 -0
  38. package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -1
  39. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js +40 -0
  40. package/codeyam-cli/src/webserver/__tests__/clientErrors.test.js.map +1 -1
  41. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js +92 -21
  42. package/codeyam-cli/src/webserver/__tests__/idleDetector.test.js.map +1 -1
  43. package/codeyam-cli/src/webserver/app/lib/clientErrors.js +7 -1
  44. package/codeyam-cli/src/webserver/app/lib/clientErrors.js.map +1 -1
  45. package/codeyam-cli/src/webserver/build/client/assets/{editor.entity.(_sha)-B7xQ9Sjy.js → editor.entity.(_sha)-Bnx7yUP0.js} +14 -14
  46. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-oepecPae.js +41 -0
  47. package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.dev-CUobbQdQ.js → entity._sha.scenarios._scenarioId.dev-KTQuL0aj.js} +1 -1
  48. package/codeyam-cli/src/webserver/build/client/assets/{manifest-5d53342d.js → manifest-3157d6b8.js} +1 -1
  49. package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-DcJSnBCE.js → analysisRunner-BMmkgAkg.js} +1 -1
  50. package/codeyam-cli/src/webserver/build/server/assets/{index-CEaDhUiv.js → index-DxB0pOSt.js} +1 -1
  51. package/codeyam-cli/src/webserver/build/server/assets/{init-DA7guOrE.js → init-DLYLaqqP.js} +2 -2
  52. package/codeyam-cli/src/webserver/build/server/assets/{server-build-juyiY2m6.js → server-build-CcyitQLQ.js} +111 -111
  53. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  54. package/codeyam-cli/src/webserver/build-info.json +5 -5
  55. package/codeyam-cli/src/webserver/idleDetector.js +41 -8
  56. package/codeyam-cli/src/webserver/idleDetector.js.map +1 -1
  57. package/codeyam-cli/src/webserver/scripts/journalCapture.ts +36 -0
  58. package/codeyam-cli/src/webserver/terminalServer.js +4 -4
  59. package/codeyam-cli/src/webserver/terminalServer.js.map +1 -1
  60. package/codeyam-cli/templates/codeyam-editor-reference.md +214 -0
  61. package/package.json +1 -1
  62. package/codeyam-cli/src/webserver/build/client/assets/editorPreview-CxmrE6AF.js +0 -41
@@ -1,10 +1,10 @@
1
1
  {
2
- "buildTimestamp": "2026-03-18T20:56:41.501Z",
3
- "buildTime": 1773867401501,
4
- "gitCommit": "3328e60080cd05630588c6f1b139c2caffcb164a",
2
+ "buildTimestamp": "2026-03-19T11:57:18.299Z",
3
+ "buildTime": 1773921438299,
4
+ "gitCommit": "471e1bd5c0e64ab79e5aae1965797f9cc293303d",
5
5
  "nodeVersion": "v20.20.1",
6
6
  "contentHash": "b046e014847d5b02d10d6795839ccd0d5117627cbd0be413260824610596a63d",
7
- "buildNumber": 1100,
8
- "semanticVersion": "0.1.1100",
9
- "version": "0.1.1100 (2026-03-18T20:56+b046e01)"
7
+ "buildNumber": 1105,
8
+ "semanticVersion": "0.1.1105",
9
+ "version": "0.1.1105 (2026-03-19T11:57+b046e01)"
10
10
  }
@@ -1,7 +1,7 @@
1
1
 
2
- [3/18/2026, 8:56:41 PM] > codeyam-combo@1.0.0 mergeDependencies
3
- [3/18/2026, 8:56:41 PM] > node ./scripts/mergePackageJsonFiles.cjs
2
+ [3/19/2026, 11:57:18 AM] > codeyam-combo@1.0.0 mergeDependencies
3
+ [3/19/2026, 11:57:18 AM] > node ./scripts/mergePackageJsonFiles.cjs
4
4
 
5
5
 
6
- [3/18/2026, 8:56:41 PM] Merged dependencies into root package.json
6
+ [3/19/2026, 11:57:18 AM] Merged dependencies into root package.json
7
7
 
@@ -810,6 +810,7 @@ function printCycleOverview(root, state) {
810
810
  console.log(chalk.green('Start now: ') + chalk.bold('codeyam editor 1'));
811
811
  console.log(chalk.dim(' If the user already described what they want, pass it: codeyam editor 1 --prompt "their message"'));
812
812
  }
813
+ console.log(chalk.dim('If stuck on CLI commands, scenarios, or debugging, read: .codeyam/docs/editor-reference.md'));
813
814
  console.log();
814
815
  }
815
816
  // ─── Step 1: Plan ─────────────────────────────────────────────────────
@@ -2675,6 +2676,14 @@ async function handleRegister(jsonArg) {
2675
2676
  console.log(chalk.red(` → ${err}`));
2676
2677
  }
2677
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
+ }
2678
2687
  console.log(chalk.yellow(' Fix the issue and re-register this scenario.'));
2679
2688
  }
2680
2689
  if (!res.ok) {
@@ -2700,6 +2709,53 @@ async function handleRegister(jsonArg) {
2700
2709
  process.exit(1);
2701
2710
  }
2702
2711
  }
2712
+ // ─── Glossary-add subcommand ──────────────────────────────────────────
2713
+ /**
2714
+ * `codeyam editor glossary-add '{"name":"...", "filePath":"...", "description":"..."}'`
2715
+ *
2716
+ * Safely adds/updates entries in .codeyam/glossary.json via the CLI,
2717
+ * avoiding hand-editing that breaks on unicode characters.
2718
+ */
2719
+ async function handleGlossaryAdd(jsonArg) {
2720
+ if (!jsonArg) {
2721
+ console.error(chalk.red('Error: JSON argument required.'));
2722
+ console.error(chalk.dim(' Usage: codeyam editor glossary-add \'{"name":"DrinkCard","filePath":"app/components/DrinkCard.tsx","description":"Displays a drink item"}\''));
2723
+ console.error(chalk.dim(' For large payloads: codeyam editor glossary-add @.codeyam/tmp/entry.json'));
2724
+ process.exit(1);
2725
+ }
2726
+ const parsed = parseRegisterArg(jsonArg);
2727
+ if (parsed.error) {
2728
+ console.error(chalk.red(`Error: ${parsed.error}`));
2729
+ process.exit(1);
2730
+ }
2731
+ // Normalize to array
2732
+ const items = Array.isArray(parsed.body) ? parsed.body : [parsed.body];
2733
+ // Read existing glossary
2734
+ const root = getProjectRoot();
2735
+ const glossaryPath = path.join(root, '.codeyam', 'glossary.json');
2736
+ let existing = [];
2737
+ try {
2738
+ const raw = JSON.parse(fs.readFileSync(glossaryPath, 'utf8'));
2739
+ existing = sanitizeGlossaryEntries(raw);
2740
+ }
2741
+ catch {
2742
+ // Glossary doesn't exist yet or can't be parsed — start fresh
2743
+ }
2744
+ // Merge
2745
+ const { validateGlossaryEntry, mergeGlossaryEntries } = await import('../utils/glossaryAdd.js');
2746
+ const result = mergeGlossaryEntries(existing, items);
2747
+ // Report validation errors
2748
+ for (const err of result.errors) {
2749
+ console.error(chalk.red(`Error at index ${err.index}: ${err.message}`));
2750
+ }
2751
+ if (result.added === 0 && result.updated === 0 && result.errors.length > 0) {
2752
+ process.exit(1);
2753
+ }
2754
+ // Write back with utf8 encoding to safely handle unicode
2755
+ fs.mkdirSync(path.dirname(glossaryPath), { recursive: true });
2756
+ fs.writeFileSync(glossaryPath, JSON.stringify(result.entries, null, 2), 'utf8');
2757
+ console.log(`added=${result.added} updated=${result.updated} total=${result.entries.length}`);
2758
+ }
2703
2759
  // ─── Dependents subcommand ────────────────────────────────────────────
2704
2760
  /**
2705
2761
  * `codeyam editor dependents <EntityName>`
@@ -2988,22 +3044,62 @@ function printAuditGateFailures(data) {
2988
3044
  if (!s)
2989
3045
  return;
2990
3046
  const issues = [];
2991
- if (s.componentsMissing > 0)
3047
+ if (s.componentsMissing > 0) {
2992
3048
  issues.push(`${s.componentsMissing} component(s) missing scenarios`);
2993
- if (s.componentsWithErrors > 0)
3049
+ const missing = (data.components || []).filter((c) => c.status === 'missing');
3050
+ for (const c of missing) {
3051
+ issues.push(` → ${c.name}${c.filePath ? ` (${c.filePath})` : ''}`);
3052
+ }
3053
+ }
3054
+ if (s.componentsWithErrors > 0) {
2994
3055
  issues.push(`${s.componentsWithErrors} component(s) with client errors (browser API or runtime errors in captured scenarios)`);
2995
- if (s.functionsMissing > 0)
3056
+ const withErrors = (data.components || []).filter((c) => c.status === 'has_errors');
3057
+ for (const c of withErrors) {
3058
+ issues.push(` → ${c.name}${c.filePath ? ` (${c.filePath})` : ''}`);
3059
+ }
3060
+ }
3061
+ if (s.functionsMissing > 0) {
2996
3062
  issues.push(`${s.functionsMissing} function(s) missing test files`);
2997
- if (s.functionsFailing > 0)
3063
+ const missing = (data.functions || []).filter((f) => f.status === 'missing');
3064
+ for (const f of missing) {
3065
+ issues.push(` → ${f.name}${f.filePath ? ` (${f.filePath})` : ''}`);
3066
+ }
3067
+ }
3068
+ if (s.functionsFailing > 0) {
2998
3069
  issues.push(`${s.functionsFailing} function(s) with failing tests`);
2999
- if (s.functionsRunnerError > 0)
3070
+ const failing = (data.functions || []).filter((f) => f.status === 'failing');
3071
+ for (const f of failing) {
3072
+ issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
3073
+ }
3074
+ }
3075
+ if (s.functionsRunnerError > 0) {
3000
3076
  issues.push(`${s.functionsRunnerError} function(s) with test runner errors (the runner crashed — not a test failure)`);
3001
- if (s.functionsNameMismatch > 0)
3077
+ const runnerErrors = (data.functions || []).filter((f) => f.status === 'runner_error');
3078
+ for (const f of runnerErrors) {
3079
+ issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
3080
+ }
3081
+ }
3082
+ if (s.functionsNameMismatch > 0) {
3002
3083
  issues.push(`${s.functionsNameMismatch} function(s) with test name mismatch`);
3084
+ const mismatch = (data.functions || []).filter((f) => f.status === 'name_mismatch');
3085
+ for (const f of mismatch) {
3086
+ issues.push(` → ${f.name}${f.testFile ? ` (${f.testFile})` : ''}`);
3087
+ }
3088
+ }
3003
3089
  if (s.missingFromGlossary > 0)
3004
3090
  issues.push(`${s.missingFromGlossary} file(s) with scenarios not in glossary`);
3005
- if (s.incompleteEntities > 0)
3006
- issues.push(`${s.incompleteEntities} entity/entities need import analysis`);
3091
+ if (s.incompleteEntities > 0) {
3092
+ const preCount = s.preExistingIncompleteEntities || 0;
3093
+ if (preCount > 0 && preCount === s.incompleteEntities) {
3094
+ issues.push(`${s.incompleteEntities} entity/entities need import analysis (pre-existing — not caused by your current changes, but must be fixed before proceeding)`);
3095
+ }
3096
+ else if (preCount > 0) {
3097
+ issues.push(`${s.incompleteEntities} entity/entities need import analysis (${preCount} pre-existing — not from your changes)`);
3098
+ }
3099
+ else {
3100
+ issues.push(`${s.incompleteEntities} entity/entities need import analysis`);
3101
+ }
3102
+ }
3007
3103
  if (s.miscategorizedScenarios > 0)
3008
3104
  issues.push(`${s.miscategorizedScenarios} component(s) using page URLs instead of isolation routes`);
3009
3105
  if (s.scenariosNeedingRecapture > 0)
@@ -3083,6 +3179,11 @@ async function handleAudit() {
3083
3179
  console.log();
3084
3180
  // Components
3085
3181
  if (components.length > 0) {
3182
+ // Build name frequency map for disambiguation
3183
+ const componentNameCounts = new Map();
3184
+ for (const c of components) {
3185
+ componentNameCounts.set(c.name, (componentNameCounts.get(c.name) || 0) + 1);
3186
+ }
3086
3187
  console.log(chalk.bold('Components (scenarios):'));
3087
3188
  for (const c of components) {
3088
3189
  const icon = c.status === 'ok' ? chalk.green('✓') : chalk.red('✗');
@@ -3096,7 +3197,11 @@ async function handleAudit() {
3096
3197
  else {
3097
3198
  detail = chalk.red(' — no scenarios registered');
3098
3199
  }
3099
- console.log(` ${icon} ${c.name}${detail}`);
3200
+ // Show file path for failing components always, for OK only when name is ambiguous
3201
+ const isDuplicate = (componentNameCounts.get(c.name) || 0) > 1;
3202
+ const showPath = c.status !== 'ok' || isDuplicate;
3203
+ const pathSuffix = showPath && c.filePath ? chalk.dim(` (${c.filePath})`) : '';
3204
+ console.log(` ${icon} ${c.name}${pathSuffix}${detail}`);
3100
3205
  if (c.clientErrors && c.clientErrors.length > 0) {
3101
3206
  for (const err of c.clientErrors.slice(0, 3)) {
3102
3207
  console.log(chalk.red(` → ${err}`));
@@ -3211,6 +3316,19 @@ async function handleAudit() {
3211
3316
  console.log(chalk.yellow(' Re-register these scenarios to capture updated screenshots.'));
3212
3317
  console.log();
3213
3318
  }
3319
+ // Duplicate glossary names (warning, not a failure)
3320
+ const duplicateNames = data.duplicateNames || [];
3321
+ if (duplicateNames.length > 0) {
3322
+ console.log(chalk.bold('Duplicate names in glossary (confusing for audit):'));
3323
+ for (const dn of duplicateNames) {
3324
+ console.log(` ${chalk.yellow('⚠')} "${dn.name}" appears ${dn.filePaths.length} times:`);
3325
+ for (const fp of dn.filePaths) {
3326
+ console.log(` ${fp}`);
3327
+ }
3328
+ }
3329
+ console.log(chalk.yellow(' Fix: remove duplicate entries or rename them to be unique in .codeyam/glossary.json'));
3330
+ console.log();
3331
+ }
3214
3332
  // Summary
3215
3333
  const allOk = summary.allPassing;
3216
3334
  if (allOk) {
@@ -3971,6 +4089,11 @@ const editorCommand = {
3971
4089
  await handleRegister(argv.json || '');
3972
4090
  return;
3973
4091
  }
4092
+ // Subcommand: codeyam editor glossary-add '{"name":"...", ...}'
4093
+ if (argv.step === 'glossary-add') {
4094
+ await handleGlossaryAdd(argv.json || '');
4095
+ return;
4096
+ }
3974
4097
  // Subcommand: codeyam editor analyze-imports
3975
4098
  if (argv.step === 'analyze-imports') {
3976
4099
  await handleAnalyzeImports();