@codeyam/codeyam-cli 0.1.17 → 0.1.18

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 (28) 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 +123 -5
  4. package/codeyam-cli/src/commands/editor.js.map +1 -1
  5. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +160 -0
  6. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
  7. package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js +66 -0
  8. package/codeyam-cli/src/utils/__tests__/editorEntityHelpers.test.js.map +1 -1
  9. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js +213 -0
  10. package/codeyam-cli/src/utils/__tests__/entityChangeStatus.test.js.map +1 -1
  11. package/codeyam-cli/src/utils/editorAudit.js +44 -14
  12. package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
  13. package/codeyam-cli/src/utils/editorRecapture.js +109 -0
  14. package/codeyam-cli/src/utils/editorRecapture.js.map +1 -0
  15. package/codeyam-cli/src/utils/entityChangeStatus.js +30 -2
  16. package/codeyam-cli/src/utils/entityChangeStatus.js.map +1 -1
  17. package/codeyam-cli/src/utils/scenariosManifest.js +22 -0
  18. package/codeyam-cli/src/utils/scenariosManifest.js.map +1 -1
  19. package/codeyam-cli/src/webserver/build/client/assets/api.editor-recapture-stale-l0sNRNKZ.js +1 -0
  20. package/codeyam-cli/src/webserver/build/client/assets/manifest-b9d4d267.js +1 -0
  21. package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-BMmkgAkg.js → analysisRunner-CGwTN3V2.js} +1 -1
  22. package/codeyam-cli/src/webserver/build/server/assets/{index-DxB0pOSt.js → index-D4meMKy3.js} +1 -1
  23. package/codeyam-cli/src/webserver/build/server/assets/{init-DLYLaqqP.js → init-odGJ_c2-.js} +1 -1
  24. package/codeyam-cli/src/webserver/build/server/assets/{server-build-CcyitQLQ.js → server-build-TmPfF7pT.js} +123 -122
  25. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  26. package/codeyam-cli/src/webserver/build-info.json +5 -5
  27. package/package.json +1 -1
  28. package/codeyam-cli/src/webserver/build/client/assets/manifest-3157d6b8.js +0 -1
@@ -1,10 +1,10 @@
1
1
  {
2
- "buildTimestamp": "2026-03-19T11:57:18.299Z",
3
- "buildTime": 1773921438299,
4
- "gitCommit": "471e1bd5c0e64ab79e5aae1965797f9cc293303d",
2
+ "buildTimestamp": "2026-03-19T21:52:47.836Z",
3
+ "buildTime": 1773957167836,
4
+ "gitCommit": "40b059fe8e0f00686186b501bf7ad39e8cdbc22c",
5
5
  "nodeVersion": "v20.20.1",
6
6
  "contentHash": "b046e014847d5b02d10d6795839ccd0d5117627cbd0be413260824610596a63d",
7
- "buildNumber": 1105,
8
- "semanticVersion": "0.1.1105",
9
- "version": "0.1.1105 (2026-03-19T11:57+b046e01)"
7
+ "buildNumber": 1110,
8
+ "semanticVersion": "0.1.1110",
9
+ "version": "0.1.1110 (2026-03-19T21:52+b046e01)"
10
10
  }
@@ -1,7 +1,7 @@
1
1
 
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
2
+ [3/19/2026, 9:52:47 PM] > codeyam-combo@1.0.0 mergeDependencies
3
+ [3/19/2026, 9:52:47 PM] > node ./scripts/mergePackageJsonFiles.cjs
4
4
 
5
5
 
6
- [3/19/2026, 11:57:18 AM] Merged dependencies into root package.json
6
+ [3/19/2026, 9:52:47 PM] Merged dependencies into root package.json
7
7
 
@@ -1449,6 +1449,7 @@ function printStep12(root, feature) {
1449
1449
  checkbox('If `hasErrors` is true, fix them and re-capture affected scenarios');
1450
1450
  checkbox('Run `codeyam editor verify-images \'{"paths":["/"], "imageUrls":["url1"]}\'` with all page paths and image URLs');
1451
1451
  checkbox('Fix or remove any broken images before continuing');
1452
+ checkbox('Recapture stale scenarios: `codeyam editor recapture-stale`');
1452
1453
  checkbox('Run `codeyam editor audit` to verify completeness of scenarios and tests');
1453
1454
  checkbox('Do not proceed until all checks pass');
1454
1455
  stopGate(12);
@@ -2122,6 +2123,7 @@ function printStep14(root, feature) {
2122
2123
  console.log('Commit all changes for this feature.');
2123
2124
  console.log();
2124
2125
  console.log(chalk.bold('Checklist:'));
2126
+ checkbox('Ensure all screenshots are fresh: `codeyam editor recapture-stale`');
2125
2127
  checkbox(`Hide the results panel: \`codeyam editor hide-results\``);
2126
2128
  checkbox(`Git commit using the journal description: \`codeyam editor commit '{"message":"feat: <title>\\n\\n<journal description>"}'\``);
2127
2129
  console.log(chalk.dim(' The commit message body MUST match the journal description exactly'));
@@ -2951,6 +2953,7 @@ function handleChange(feature) {
2951
2953
  checkbox(`Navigate to key pages to verify changes: \`codeyam editor preview '{"path":"/your-route","dimension":"${dim}"}'\``);
2952
2954
  printDimensionGuidance(dim, dimNames);
2953
2955
  checkbox('Run `codeyam editor scenario-coverage` — all affected scenarios must be fresh');
2956
+ checkbox('Recapture stale scenarios: `codeyam editor recapture-stale`');
2954
2957
  checkbox('Run `codeyam editor audit` — all checks must pass');
2955
2958
  checkbox(`Check for client-side errors: \`codeyam editor client-errors\``);
2956
2959
  console.log(chalk.dim(' If `hasContent=false`, the preview is blank — fix the code before proceeding.'));
@@ -3186,11 +3189,18 @@ async function handleAudit() {
3186
3189
  }
3187
3190
  console.log(chalk.bold('Components (scenarios):'));
3188
3191
  for (const c of components) {
3189
- const icon = c.status === 'ok' ? chalk.green('✓') : chalk.red('✗');
3192
+ const icon = c.status === 'ok'
3193
+ ? chalk.green('✓')
3194
+ : c.status === 'needs_recapture'
3195
+ ? chalk.yellow('↻')
3196
+ : chalk.red('✗');
3190
3197
  let detail;
3191
3198
  if (c.status === 'has_errors') {
3192
3199
  detail = chalk.red(` — ${c.scenarioCount} scenario${c.scenarioCount !== 1 ? 's' : ''} but has client errors`);
3193
3200
  }
3201
+ else if (c.status === 'needs_recapture') {
3202
+ detail = chalk.yellow(` — ${c.scenarioCount} scenario${c.scenarioCount !== 1 ? 's' : ''}, needs recapture`);
3203
+ }
3194
3204
  else if (c.status === 'ok') {
3195
3205
  detail = chalk.dim(` (${c.scenarioCount} scenario${c.scenarioCount !== 1 ? 's' : ''})`);
3196
3206
  }
@@ -3199,7 +3209,7 @@ async function handleAudit() {
3199
3209
  }
3200
3210
  // Show file path for failing components always, for OK only when name is ambiguous
3201
3211
  const isDuplicate = (componentNameCounts.get(c.name) || 0) > 1;
3202
- const showPath = c.status !== 'ok' || isDuplicate;
3212
+ const showPath = (c.status !== 'ok' && c.status !== 'needs_recapture') || isDuplicate;
3203
3213
  const pathSuffix = showPath && c.filePath ? chalk.dim(` (${c.filePath})`) : '';
3204
3214
  console.log(` ${icon} ${c.name}${pathSuffix}${detail}`);
3205
3215
  if (c.clientErrors && c.clientErrors.length > 0) {
@@ -3313,7 +3323,7 @@ async function handleAudit() {
3313
3323
  : `${s.status.status}`;
3314
3324
  console.log(` ${chalk.red('✗')} ${s.scenarioName} ${chalk.dim(`(${s.entityName} — ${reason})`)}`);
3315
3325
  }
3316
- console.log(chalk.yellow(' Re-register these scenarios to capture updated screenshots.'));
3326
+ console.log(chalk.yellow(' Run: codeyam editor recapture-stale'));
3317
3327
  console.log();
3318
3328
  }
3319
3329
  // Duplicate glossary names (warning, not a failure)
@@ -3385,6 +3395,109 @@ async function handleAudit() {
3385
3395
  console.log(chalk.yellow('Warning: Could not build import graph. Run `codeyam editor analyze-imports` manually.'));
3386
3396
  }
3387
3397
  }
3398
+ // ─── Recapture-stale subcommand ────────────────────────────────────────
3399
+ /**
3400
+ * `codeyam editor recapture-stale`
3401
+ *
3402
+ * Identifies all scenarios whose entity (or dependency) has changed but
3403
+ * whose screenshot hasn't been recaptured this session, then recaptures
3404
+ * them in batch.
3405
+ */
3406
+ async function handleRecaptureStale() {
3407
+ const port = getServerPort();
3408
+ const url = `http://localhost:${port}/api/editor-recapture-stale`;
3409
+ console.log();
3410
+ console.log(chalk.bold.cyan('━━━ Recapture Stale Scenarios ━━━'));
3411
+ console.log();
3412
+ let res;
3413
+ try {
3414
+ res = await fetch(url, { method: 'POST' });
3415
+ }
3416
+ catch (err) {
3417
+ console.error(chalk.red('Error: Could not reach the CodeYam server. Is it running?'));
3418
+ console.error(chalk.dim(` ${err.message}`));
3419
+ process.exit(1);
3420
+ }
3421
+ if (!res.ok) {
3422
+ const body = await res.json().catch(() => null);
3423
+ console.error(chalk.red(`Error: Recapture endpoint returned ${res.status}`));
3424
+ if (body?.error)
3425
+ console.error(chalk.red(` ${body.error}`));
3426
+ process.exit(1);
3427
+ }
3428
+ // Handle JSON response (early returns like "no changes" / "all up to date")
3429
+ const contentType = res.headers.get('content-type') || '';
3430
+ if (contentType.includes('application/json')) {
3431
+ const data = await res.json();
3432
+ if (data.note) {
3433
+ console.log(chalk.dim(data.note));
3434
+ }
3435
+ else if (data.total === 0) {
3436
+ console.log(chalk.green('All scenarios are up to date.'));
3437
+ }
3438
+ console.log();
3439
+ return;
3440
+ }
3441
+ // Stream NDJSON progress events
3442
+ let total = 0;
3443
+ let recapturedCount = 0;
3444
+ let failedCount = 0;
3445
+ const reader = res.body?.getReader();
3446
+ if (!reader) {
3447
+ console.error(chalk.red('Error: No response body'));
3448
+ process.exit(1);
3449
+ }
3450
+ const decoder = new TextDecoder();
3451
+ let buffer = '';
3452
+ while (true) {
3453
+ const { done, value } = await reader.read();
3454
+ if (done)
3455
+ break;
3456
+ buffer += decoder.decode(value, { stream: true });
3457
+ const lines = buffer.split('\n');
3458
+ buffer = lines.pop() || ''; // Keep incomplete last line in buffer
3459
+ for (const line of lines) {
3460
+ if (!line.trim())
3461
+ continue;
3462
+ try {
3463
+ const event = JSON.parse(line);
3464
+ switch (event.type) {
3465
+ case 'start':
3466
+ total = event.total;
3467
+ console.log(`Found ${total} stale scenario(s). Recapturing...\n`);
3468
+ break;
3469
+ case 'capturing':
3470
+ process.stdout.write(chalk.dim(` … ${event.name}`));
3471
+ break;
3472
+ case 'success':
3473
+ // Clear the "capturing" line and print success
3474
+ process.stdout.write('\r\x1b[K');
3475
+ console.log(` ${chalk.green('✓')} ${event.name}`);
3476
+ recapturedCount++;
3477
+ break;
3478
+ case 'failure':
3479
+ process.stdout.write('\r\x1b[K');
3480
+ console.log(` ${chalk.red('✗')} ${event.name} — ${chalk.dim(event.error)}`);
3481
+ failedCount++;
3482
+ break;
3483
+ case 'done':
3484
+ // Final summary
3485
+ console.log();
3486
+ const color = failedCount > 0 ? chalk.yellow : chalk.green;
3487
+ console.log(color(`Recaptured ${recapturedCount}/${total} scenario(s).`));
3488
+ console.log();
3489
+ break;
3490
+ }
3491
+ }
3492
+ catch {
3493
+ // Skip unparseable lines
3494
+ }
3495
+ }
3496
+ }
3497
+ if (failedCount > 0) {
3498
+ process.exit(1);
3499
+ }
3500
+ }
3388
3501
  // ─── Scenarios subcommand ─────────────────────────────────────────────
3389
3502
  async function handleScenarios() {
3390
3503
  const port = getServerPort();
@@ -3995,8 +4108,8 @@ const editorCommand = {
3995
4108
  describe: 'Editor mode guided workflow',
3996
4109
  builder: (yargs) => {
3997
4110
  const stepDescription = IS_INTERNAL_BUILD
3998
- ? 'Step number (1-16) or subcommand (template, register, isolate, analyze-imports, dependents, audit, scenarios, scenario-coverage, change, sync, debug, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors)'
3999
- : 'Step number (1-16) or subcommand (template, register, isolate, analyze-imports, dependents, audit, scenarios, scenario-coverage, change, sync, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors)';
4111
+ ? 'Step number (1-16) or subcommand (template, register, isolate, analyze-imports, dependents, audit, scenarios, scenario-coverage, recapture-stale, change, sync, debug, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors)'
4112
+ : 'Step number (1-16) or subcommand (template, register, isolate, analyze-imports, dependents, audit, scenarios, scenario-coverage, recapture-stale, change, sync, preview, show-results, hide-results, commit, journal, journal-list, journal-update, dev-server, client-errors)';
4000
4113
  let builder = yargs
4001
4114
  .positional('step', {
4002
4115
  type: 'string',
@@ -4119,6 +4232,11 @@ const editorCommand = {
4119
4232
  await handleScenarioCoverage();
4120
4233
  return;
4121
4234
  }
4235
+ // Subcommand: codeyam editor recapture-stale
4236
+ if (argv.step === 'recapture-stale') {
4237
+ await handleRecaptureStale();
4238
+ return;
4239
+ }
4122
4240
  // Subcommand: codeyam editor change <feature>
4123
4241
  if (argv.step === 'change') {
4124
4242
  handleChange(argv.json || '');