@codeyam/codeyam-cli 0.1.25 → 0.1.27

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 (47) 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/__tests__/editor.statePersistence.test.js +55 -0
  4. package/codeyam-cli/src/commands/__tests__/editor.statePersistence.test.js.map +1 -0
  5. package/codeyam-cli/src/commands/editor.js +61 -8
  6. package/codeyam-cli/src/commands/editor.js.map +1 -1
  7. package/codeyam-cli/src/data/techStacks.js +1 -1
  8. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js +10 -0
  9. package/codeyam-cli/src/utils/__tests__/editorAudit.test.js.map +1 -1
  10. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js +120 -0
  11. package/codeyam-cli/src/utils/__tests__/editorScenarioSwitch.test.js.map +1 -1
  12. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js +84 -0
  13. package/codeyam-cli/src/utils/__tests__/editorSeedAdapter.test.js.map +1 -1
  14. package/codeyam-cli/src/utils/__tests__/testRunner.test.js +0 -1
  15. package/codeyam-cli/src/utils/__tests__/testRunner.test.js.map +1 -1
  16. package/codeyam-cli/src/utils/editorAudit.js +22 -5
  17. package/codeyam-cli/src/utils/editorAudit.js.map +1 -1
  18. package/codeyam-cli/src/utils/editorScenarioSwitch.js +27 -12
  19. package/codeyam-cli/src/utils/editorScenarioSwitch.js.map +1 -1
  20. package/codeyam-cli/src/utils/editorSeedAdapter.js +27 -14
  21. package/codeyam-cli/src/utils/editorSeedAdapter.js.map +1 -1
  22. package/codeyam-cli/src/utils/testRunner.js +1 -7
  23. package/codeyam-cli/src/utils/testRunner.js.map +1 -1
  24. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-CRxPi2BB.js +96 -0
  25. package/codeyam-cli/src/webserver/build/client/assets/globals-BsGHu8WX.css +1 -0
  26. package/codeyam-cli/src/webserver/build/client/assets/{manifest-7e749098.js → manifest-9032538f.js} +1 -1
  27. package/codeyam-cli/src/webserver/build/client/assets/{root-DGtly3mb.js → root-dKFRTYcy.js} +5 -5
  28. package/codeyam-cli/src/webserver/build/server/assets/{analysisRunner-CO8xocj3.js → analysisRunner-OLsM110H.js} +1 -1
  29. package/codeyam-cli/src/webserver/build/server/assets/{index-QKPqlUgg.js → index-WHdB6WTN.js} +1 -1
  30. package/codeyam-cli/src/webserver/build/server/assets/{init-DlspChIk.js → init-DbSiZoE6.js} +1 -1
  31. package/codeyam-cli/src/webserver/build/server/assets/{server-build-ChzicV-B.js → server-build-DZbLY6O_.js} +135 -134
  32. package/codeyam-cli/src/webserver/build/server/index.js +1 -1
  33. package/codeyam-cli/src/webserver/build-info.json +5 -5
  34. package/codeyam-cli/templates/expo-react-native/MOBILE_SETUP.md +54 -5
  35. package/codeyam-cli/templates/expo-react-native/app/_layout.tsx +4 -2
  36. package/codeyam-cli/templates/expo-react-native/app/index.tsx +36 -0
  37. package/codeyam-cli/templates/expo-react-native/babel.config.js +1 -0
  38. package/codeyam-cli/templates/expo-react-native/gitignore +2 -0
  39. package/codeyam-cli/templates/expo-react-native/package.json +23 -18
  40. package/codeyam-cli/templates/expo-react-native/patches/expo-modules-autolinking+3.0.24.patch +29 -0
  41. package/codeyam-cli/templates/seed-adapters/supabase.ts +91 -8
  42. package/package.json +1 -1
  43. package/codeyam-cli/src/webserver/build/client/assets/editor.entity.(_sha)-DLM1-ZMt.js +0 -96
  44. package/codeyam-cli/src/webserver/build/client/assets/globals-9EkC9j9I.css +0 -1
  45. package/codeyam-cli/templates/expo-react-native/app/(tabs)/_layout.tsx +0 -33
  46. package/codeyam-cli/templates/expo-react-native/app/(tabs)/index.tsx +0 -12
  47. package/codeyam-cli/templates/expo-react-native/app/(tabs)/settings.tsx +0 -12
@@ -1,10 +1,10 @@
1
1
  {
2
- "buildTimestamp": "2026-03-27T13:51:55.725Z",
3
- "buildTime": 1774619515725,
4
- "gitCommit": "cefcc7c0aa462f7267e8912e66de352da511a931",
2
+ "buildTimestamp": "2026-03-28T18:03:51.730Z",
3
+ "buildTime": 1774721031730,
4
+ "gitCommit": "3d7e1f0d118b714119562b24234d8e7ae6832002",
5
5
  "nodeVersion": "v20.20.1",
6
6
  "contentHash": "c92230c027acb71cab56d2a696876a6a52206bfadd59fbc31a512b00a7ee8826",
7
- "buildNumber": 1256,
8
- "semanticVersion": "0.1.1256",
9
- "version": "0.1.1256 (2026-03-27T13:51+c92230c)"
7
+ "buildNumber": 1271,
8
+ "semanticVersion": "0.1.1271",
9
+ "version": "0.1.1271 (2026-03-28T18:03+c92230c)"
10
10
  }
@@ -1,7 +1,7 @@
1
1
 
2
- [3/27/2026, 1:51:55 PM] > codeyam-combo@1.0.0 mergeDependencies
3
- [3/27/2026, 1:51:55 PM] > node ./scripts/mergePackageJsonFiles.cjs
2
+ [3/28/2026, 6:03:51 PM] > codeyam-combo@1.0.0 mergeDependencies
3
+ [3/28/2026, 6:03:51 PM] > node ./scripts/mergePackageJsonFiles.cjs
4
4
 
5
5
 
6
- [3/27/2026, 1:51:55 PM] Merged dependencies into root package.json
6
+ [3/28/2026, 6:03:51 PM] Merged dependencies into root package.json
7
7
 
@@ -0,0 +1,55 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ /**
4
+ * Structural test: every writeState() call in editor.ts must preserve
5
+ * `techStackId` and `appFormats` from the previous state.
6
+ *
7
+ * Bug: Steps 4-18 dropped techStackId from writeState calls, causing
8
+ * getTechStackContext() to fall back to Next.js defaults. This broke
9
+ * `codeyam editor isolate` for Expo projects — it created Next.js-style
10
+ * subdirectories instead of Expo flat files.
11
+ */
12
+ describe('editor state persistence', () => {
13
+ const editorSource = fs.readFileSync(path.join(__dirname, '..', 'editor.ts'), 'utf8');
14
+ // Find all writeState blocks in the source.
15
+ // Each writeState call spans multiple lines like:
16
+ // writeState(root, {
17
+ // feature,
18
+ // step: N,
19
+ // ...
20
+ // });
21
+ const writeStateBlocks = [];
22
+ const lines = editorSource.split('\n');
23
+ for (let i = 0; i < lines.length; i++) {
24
+ if (lines[i].includes('writeState(root,')) {
25
+ // Collect lines until we find the closing `});`
26
+ let block = '';
27
+ for (let j = i; j < lines.length; j++) {
28
+ block += lines[j] + '\n';
29
+ if (lines[j].match(/^\s*\}\);/))
30
+ break;
31
+ }
32
+ writeStateBlocks.push({ lineNumber: i + 1, block });
33
+ }
34
+ }
35
+ it('should find writeState calls in editor.ts', () => {
36
+ expect(writeStateBlocks.length).toBeGreaterThan(10);
37
+ });
38
+ // Filter to only writeState blocks that set a step number (printStep functions).
39
+ // Exclude the handleTemplate/migration-survey writeState that sets step: 0.
40
+ const stepWriteStates = writeStateBlocks.filter(({ block }) => block.match(/step:\s*\d+/) && !block.match(/step:\s*0/));
41
+ it('should find step writeState calls', () => {
42
+ expect(stepWriteStates.length).toBeGreaterThanOrEqual(18);
43
+ });
44
+ for (const { lineNumber, block } of stepWriteStates) {
45
+ const stepMatch = block.match(/step:\s*(\d+)/);
46
+ const stepNum = stepMatch ? stepMatch[1] : '?';
47
+ it(`step ${stepNum} writeState (line ${lineNumber}) should preserve techStackId`, () => {
48
+ expect(block).toContain('techStackId');
49
+ });
50
+ it(`step ${stepNum} writeState (line ${lineNumber}) should preserve appFormats`, () => {
51
+ expect(block).toContain('appFormats');
52
+ });
53
+ }
54
+ });
55
+ //# sourceMappingURL=editor.statePersistence.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.statePersistence.test.js","sourceRoot":"","sources":["../../../../../src/commands/__tests__/editor.statePersistence.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;;;;;;GAQG;AACH,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,MAAM,YAAY,GAAG,EAAE,CAAC,YAAY,CAClC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,WAAW,CAAC,EACvC,MAAM,CACP,CAAC;IAEF,4CAA4C;IAC5C,kDAAkD;IAClD,uBAAuB;IACvB,eAAe;IACf,eAAe;IACf,UAAU;IACV,QAAQ;IACR,MAAM,gBAAgB,GAA4C,EAAE,CAAC;IACrE,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;YAC1C,gDAAgD;YAChD,IAAI,KAAK,GAAG,EAAE,CAAC;YACf,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;gBACtC,KAAK,IAAI,KAAK,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBACzB,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAC;oBAAE,MAAM;YACzC,CAAC;YACD,gBAAgB,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QACtD,CAAC;IACH,CAAC;IAED,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACnD,MAAM,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC,eAAe,CAAC,EAAE,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;IAEH,iFAAiF;IACjF,4EAA4E;IAC5E,MAAM,eAAe,GAAG,gBAAgB,CAAC,MAAM,CAC7C,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,WAAW,CAAC,CACvE,CAAC;IAEF,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;QAC3C,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,sBAAsB,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;IAEH,KAAK,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,IAAI,eAAe,EAAE,CAAC;QACpD,MAAM,SAAS,GAAG,KAAK,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;QAC/C,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QAE/C,EAAE,CAAC,QAAQ,OAAO,qBAAqB,UAAU,+BAA+B,EAAE,GAAG,EAAE;YACrF,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC;QACzC,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,QAAQ,OAAO,qBAAqB,UAAU,8BAA8B,EAAE,GAAG,EAAE;YACpF,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,YAAY,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC;AACH,CAAC,CAAC,CAAC"}
@@ -305,6 +305,10 @@ function printAppScenarioInstructions(pageName, route) {
305
305
  console.log(chalk.dim(' Example: "Page - Full Data", "Page - Empty State", "Page - Error State"'));
306
306
  }
307
307
  console.log();
308
+ checkbox('Ensure every page file used in app scenarios has a glossary entry with its filePath:');
309
+ console.log(chalk.dim(' The register command validates pageFilePath against the glossary — add missing pages now.'));
310
+ console.log(chalk.dim(' Example: {"name":"CounterScreen","filePath":"app/(tabs)/index.tsx","type":"page","description":"Main counter page"}'));
311
+ console.log();
308
312
  checkbox('Register each scenario with type "application", the real page URL, and pageFilePath:');
309
313
  console.log(chalk.dim(` codeyam editor register '{"name":"${pageName || 'Page'} - Full Data",`));
310
314
  console.log(chalk.dim(` "type":"application","url":"${route || '/'}","pageFilePath":"src/path/to/Page.tsx",...}'`));
@@ -402,9 +406,15 @@ function printExtractionPlanInstructions() {
402
406
  function printComponentCaptureInstructions(root) {
403
407
  const ctx = root ? getTechStackContext(root) : undefined;
404
408
  const isExpo = ctx?.isExpo ?? false;
405
- checkbox('Create isolation route dirs: `codeyam editor isolate ComponentA ComponentB ...`');
406
- console.log(chalk.dim(` This creates app/isolated-components/layout.tsx (with production ${isExpo ? '__DEV__' : 'notFound()'} guard) and`));
407
- console.log(chalk.dim(' a directory per component. List ALL components that need isolation routes.'));
409
+ checkbox('Set up isolation routes: `codeyam editor isolate ComponentA ComponentB ...`');
410
+ if (isExpo) {
411
+ console.log(chalk.dim(' This creates app/isolated-components/_layout.tsx (with __DEV__ guard).'));
412
+ console.log(chalk.dim(' You then create a flat .tsx file per component (NOT subdirectories — Expo Router uses flat files).'));
413
+ }
414
+ else {
415
+ console.log(chalk.dim(` This creates app/isolated-components/layout.tsx (with notFound() guard) and`));
416
+ console.log(chalk.dim(' a directory per component. List ALL components that need isolation routes.'));
417
+ }
408
418
  checkbox('For each visual component:');
409
419
  console.log(chalk.dim(' 1. Read the source AND find where it is used in the app to understand:'));
410
420
  console.log(chalk.dim(' — Props/interface'));
@@ -805,8 +815,8 @@ function printSetup(root) {
805
815
  console.log(chalk.bold('Tech Stack Selection:'));
806
816
  console.log(chalk.dim(' Based on the selected formats, present ONLY the matching tech stacks.'));
807
817
  console.log(chalk.dim(' A stack matches if ANY of the user\'s selected formats appears in its "Supports" list.'));
808
- console.log(chalk.dim(' Show ALL matching stacks even if there is only one. Mark the recommended option.'));
809
- console.log(chalk.dim(' Use AskUserQuestion to let the user pick one.'));
818
+ console.log(chalk.dim(' If only ONE stack matches, confirm it directly (e.g. "Expo + React Native is the only stack for mobile apps — using that.").'));
819
+ console.log(chalk.dim(' If MULTIPLE stacks match, use AskUserQuestion to let the user pick one.'));
810
820
  console.log();
811
821
  console.log(chalk.bold(' Available Tech Stacks:'));
812
822
  for (const stack of TECH_STACKS) {
@@ -1249,6 +1259,8 @@ function printStep4(root, feature) {
1249
1259
  label: STEP_LABELS[4],
1250
1260
  startedAt: isResuming ? prevState.startedAt : now,
1251
1261
  featureStartedAt: prevState?.featureStartedAt || now,
1262
+ appFormats: prevState?.appFormats,
1263
+ techStackId: prevState?.techStackId,
1252
1264
  });
1253
1265
  logEvent(root, 'step', { step: 4, label: 'Verify Prototype', feature });
1254
1266
  stepHeader(4, 'Verify Prototype', feature);
@@ -1305,6 +1317,8 @@ function printStep5(root, feature) {
1305
1317
  label: STEP_LABELS[5],
1306
1318
  startedAt: isResuming ? prevState.startedAt : now,
1307
1319
  featureStartedAt: prevState?.featureStartedAt || now,
1320
+ appFormats: prevState?.appFormats,
1321
+ techStackId: prevState?.techStackId,
1308
1322
  });
1309
1323
  logEvent(root, 'step', { step: 5, label: 'Confirm', feature });
1310
1324
  stepHeader(5, 'Confirm', feature);
@@ -1364,6 +1378,8 @@ function printStep6(root, feature) {
1364
1378
  label: STEP_LABELS[6],
1365
1379
  startedAt: isResuming ? prevState.startedAt : now,
1366
1380
  featureStartedAt: prevState?.featureStartedAt || now,
1381
+ appFormats: prevState?.appFormats,
1382
+ techStackId: prevState?.techStackId,
1367
1383
  });
1368
1384
  logEvent(root, 'step', { step: 6, label: 'Deconstruct', feature });
1369
1385
  stepHeader(6, 'Deconstruct', feature);
@@ -1389,6 +1405,8 @@ function printStep7(root, feature) {
1389
1405
  label: STEP_LABELS[7],
1390
1406
  startedAt: isResuming ? prevState.startedAt : now,
1391
1407
  featureStartedAt: prevState?.featureStartedAt || now,
1408
+ appFormats: prevState?.appFormats,
1409
+ techStackId: prevState?.techStackId,
1392
1410
  });
1393
1411
  logEvent(root, 'step', { step: 7, label: 'Extract', feature });
1394
1412
  stepHeader(7, 'Extract', feature);
@@ -1409,6 +1427,7 @@ function printStep7(root, feature) {
1409
1427
  console.log(chalk.dim(' Cover: typical inputs, edge cases, empty/null inputs, error conditions'));
1410
1428
  console.log(chalk.dim(' Aim for 3-8 test cases per function depending on complexity'));
1411
1429
  console.log(chalk.dim(' Hooks count as functions — useDrinks, useAuth, etc. all need test files'));
1430
+ console.log(chalk.dim(' Wrap all tests in a describe("FunctionName", ...) block — the audit matches on this name'));
1412
1431
  if (ctx.isExpo) {
1413
1432
  checkbox('Place test files next to source but OUTSIDE `app/` (Expo Router treats all files in app/ as routes): `lib/storage.ts` → `lib/storage.test.ts`, `app/hooks/useCounter.ts` → `__tests__/hooks/useCounter.test.ts`');
1414
1433
  }
@@ -1446,6 +1465,8 @@ function printStep8(root, feature) {
1446
1465
  label: STEP_LABELS[8],
1447
1466
  startedAt: isResuming ? prevState.startedAt : now,
1448
1467
  featureStartedAt: prevState?.featureStartedAt || now,
1468
+ appFormats: prevState?.appFormats,
1469
+ techStackId: prevState?.techStackId,
1449
1470
  });
1450
1471
  logEvent(root, 'step', { step: 8, label: 'Glossary', feature });
1451
1472
  stepHeader(8, 'Glossary', feature);
@@ -1472,6 +1493,8 @@ function printStep9(root, feature) {
1472
1493
  label: STEP_LABELS[9],
1473
1494
  startedAt: isResuming ? prevState.startedAt : now,
1474
1495
  featureStartedAt: prevState?.featureStartedAt || now,
1496
+ appFormats: prevState?.appFormats,
1497
+ techStackId: prevState?.techStackId,
1475
1498
  });
1476
1499
  logEvent(root, 'step', { step: 9, label: 'Analyze', feature });
1477
1500
  stepHeader(9, 'Analyze and Verify', feature);
@@ -1522,6 +1545,8 @@ function printStep10(root, feature) {
1522
1545
  label: STEP_LABELS[10],
1523
1546
  startedAt: isResuming ? prevState.startedAt : now,
1524
1547
  featureStartedAt: prevState?.featureStartedAt || now,
1548
+ appFormats: prevState?.appFormats,
1549
+ techStackId: prevState?.techStackId,
1525
1550
  });
1526
1551
  logEvent(root, 'step', { step: 10, label: 'App Scenarios', feature });
1527
1552
  stepHeader(10, 'App Scenarios', feature);
@@ -1586,6 +1611,8 @@ function printStep11(root, feature) {
1586
1611
  label: STEP_LABELS[11],
1587
1612
  startedAt: isResuming ? prevState.startedAt : now,
1588
1613
  featureStartedAt: prevState?.featureStartedAt || now,
1614
+ appFormats: prevState?.appFormats,
1615
+ techStackId: prevState?.techStackId,
1589
1616
  });
1590
1617
  logEvent(root, 'step', { step: 11, label: 'User Scenarios', feature });
1591
1618
  stepHeader(11, 'User Scenarios', feature);
@@ -1632,6 +1659,8 @@ function printStep12(root, feature) {
1632
1659
  label: STEP_LABELS[12],
1633
1660
  startedAt: isResuming ? prevState.startedAt : now,
1634
1661
  featureStartedAt: prevState?.featureStartedAt || now,
1662
+ appFormats: prevState?.appFormats,
1663
+ techStackId: prevState?.techStackId,
1635
1664
  });
1636
1665
  logEvent(root, 'step', { step: 12, label: 'Verify', feature });
1637
1666
  stepHeader(12, 'Verify', feature);
@@ -1678,6 +1707,8 @@ function printStep13(root, feature) {
1678
1707
  label: STEP_LABELS[13],
1679
1708
  startedAt: isResuming ? prevState.startedAt : now,
1680
1709
  featureStartedAt: prevState?.featureStartedAt || now,
1710
+ appFormats: prevState?.appFormats,
1711
+ techStackId: prevState?.techStackId,
1681
1712
  });
1682
1713
  logEvent(root, 'step', { step: 13, label: 'Journal', feature });
1683
1714
  stepHeader(13, 'Journal', feature);
@@ -1711,6 +1742,8 @@ function printStep14(root, feature) {
1711
1742
  label: STEP_LABELS[14],
1712
1743
  startedAt: isResuming ? prevState.startedAt : now,
1713
1744
  featureStartedAt: prevState?.featureStartedAt || now,
1745
+ appFormats: prevState?.appFormats,
1746
+ techStackId: prevState?.techStackId,
1714
1747
  });
1715
1748
  logEvent(root, 'step', { step: 14, label: 'Review', feature });
1716
1749
  stepHeader(14, 'Review', feature);
@@ -1744,6 +1777,8 @@ function printStep15(root, feature) {
1744
1777
  label: STEP_LABELS[15],
1745
1778
  startedAt: isResuming ? prevState.startedAt : now,
1746
1779
  featureStartedAt: prevState?.featureStartedAt || now,
1780
+ appFormats: prevState?.appFormats,
1781
+ techStackId: prevState?.techStackId,
1747
1782
  });
1748
1783
  logEvent(root, 'step', { step: 15, label: 'Present', feature });
1749
1784
  stepHeader(15, 'Present', feature);
@@ -2393,6 +2428,8 @@ function printStep16(root, feature) {
2393
2428
  label: STEP_LABELS[16],
2394
2429
  startedAt: isResuming ? prevState.startedAt : now,
2395
2430
  featureStartedAt: prevState?.featureStartedAt || now,
2431
+ appFormats: prevState?.appFormats,
2432
+ techStackId: prevState?.techStackId,
2396
2433
  });
2397
2434
  logEvent(root, 'step', { step: 16, label: 'Commit', feature });
2398
2435
  stepHeader(16, 'Commit', feature);
@@ -2419,6 +2456,8 @@ function printStep17(root, feature) {
2419
2456
  label: STEP_LABELS[17],
2420
2457
  startedAt: isResuming ? prevState.startedAt : now,
2421
2458
  featureStartedAt: prevState?.featureStartedAt || now,
2459
+ appFormats: prevState?.appFormats,
2460
+ techStackId: prevState?.techStackId,
2422
2461
  });
2423
2462
  logEvent(root, 'step', { step: 17, label: 'Finalize', feature });
2424
2463
  stepHeader(17, 'Finalize', feature);
@@ -2444,6 +2483,8 @@ function printStep18(root, feature) {
2444
2483
  label: STEP_LABELS[18],
2445
2484
  startedAt: isResuming ? prevState.startedAt : now,
2446
2485
  featureStartedAt: prevState?.featureStartedAt || now,
2486
+ appFormats: prevState?.appFormats,
2487
+ techStackId: prevState?.techStackId,
2447
2488
  });
2448
2489
  logEvent(root, 'step', { step: 18, label: 'Push', feature });
2449
2490
  stepHeader(18, 'Push', feature);
@@ -2884,8 +2925,13 @@ function handleIsolate(componentNames) {
2884
2925
  process.exit(1);
2885
2926
  }
2886
2927
  const isolateDir = path.join(root, 'app', 'isolated-components');
2887
- // Create layout.tsx with production guard if missing
2928
+ // Create the framework-appropriate layout guard if missing.
2929
+ // Clean up wrong-framework layout from a previous CLI version.
2888
2930
  const layoutPath = path.join(isolateDir, ctx.isExpo ? '_layout.tsx' : 'layout.tsx');
2931
+ const wrongLayoutPath = path.join(isolateDir, ctx.isExpo ? 'layout.tsx' : '_layout.tsx');
2932
+ if (fs.existsSync(wrongLayoutPath)) {
2933
+ fs.unlinkSync(wrongLayoutPath);
2934
+ }
2889
2935
  if (!fs.existsSync(layoutPath)) {
2890
2936
  fs.mkdirSync(isolateDir, { recursive: true });
2891
2937
  if (ctx.isExpo) {
@@ -2938,7 +2984,13 @@ function handleIsolate(componentNames) {
2938
2984
  }
2939
2985
  }
2940
2986
  if (created.length > 0) {
2941
- console.log(chalk.green(`Created ${created.length} isolation route(s): ${created.join(', ')}`));
2987
+ if (ctx.isExpo) {
2988
+ console.log(chalk.green(`Ready for ${created.length} isolation route(s): ${created.map((n) => `app/isolated-components/${n}.tsx`).join(', ')}`));
2989
+ console.log(chalk.dim(' Create each file with useLocalSearchParams, a scenarios map, and nativeID="codeyam-capture"'));
2990
+ }
2991
+ else {
2992
+ console.log(chalk.green(`Created ${created.length} isolation route dir(s): ${created.join(', ')}`));
2993
+ }
2942
2994
  }
2943
2995
  if (existed.length > 0) {
2944
2996
  console.log(chalk.dim(`Already existed: ${existed.join(', ')}`));
@@ -3954,7 +4006,8 @@ async function handleAudit(options) {
3954
4006
  if (f.errorMessage) {
3955
4007
  detail += `\n ${chalk.red(f.errorMessage)}`;
3956
4008
  detail += `\n ${chalk.yellow('Note: This is NOT a test failure — the test runner itself could not execute.')}`;
3957
- detail += `\n ${chalk.yellow('Try running the test manually: npx vitest run ' + f.testFile)}`;
4009
+ const ctx = getTechStackContext(process.cwd());
4010
+ detail += `\n ${chalk.yellow('Try running the test manually: ' + ctx.testRunCommand + ' ' + f.testFile)}`;
3958
4011
  }
3959
4012
  break;
3960
4013
  case 'failing':