@codyswann/lisa 2.122.0 → 2.123.0

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 (71) hide show
  1. package/dist/configs/eslint/expo.d.ts +10 -1
  2. package/dist/configs/eslint/expo.d.ts.map +1 -1
  3. package/dist/configs/eslint/expo.js +19 -18
  4. package/dist/configs/eslint/expo.js.map +1 -1
  5. package/dist/configs/jest/expo.d.ts +10 -1
  6. package/dist/configs/jest/expo.d.ts.map +1 -1
  7. package/dist/configs/jest/expo.js +18 -13
  8. package/dist/configs/jest/expo.js.map +1 -1
  9. package/expo/copy-overwrite/eslint.config.ts +6 -0
  10. package/expo/copy-overwrite/jest.config.ts +10 -0
  11. package/expo/copy-overwrite/knip.json +24 -2
  12. package/expo/create-only/jest.config.react-native-mock.js +22 -0
  13. package/expo/package-lisa/package.lisa.json +37 -36
  14. package/package.json +1 -1
  15. package/plugins/lisa/.claude-plugin/plugin.json +1 -1
  16. package/plugins/lisa/.codex-plugin/plugin.json +1 -1
  17. package/plugins/lisa-agy/plugin.json +1 -1
  18. package/plugins/lisa-cdk/.claude-plugin/plugin.json +1 -1
  19. package/plugins/lisa-cdk/.codex-plugin/plugin.json +1 -1
  20. package/plugins/lisa-cdk-agy/plugin.json +1 -1
  21. package/plugins/lisa-cdk-copilot/.claude-plugin/plugin.json +1 -1
  22. package/plugins/lisa-cdk-cursor/.claude-plugin/plugin.json +1 -1
  23. package/plugins/lisa-copilot/.claude-plugin/plugin.json +1 -1
  24. package/plugins/lisa-cursor/.claude-plugin/plugin.json +1 -1
  25. package/plugins/lisa-expo/.claude-plugin/plugin.json +1 -1
  26. package/plugins/lisa-expo/.codex-plugin/plugin.json +1 -1
  27. package/plugins/lisa-expo/skills/directory-structure/SKILL.md +32 -20
  28. package/plugins/lisa-expo/skills/directory-structure/scripts/validate_structure.py +15 -6
  29. package/plugins/lisa-expo-agy/plugin.json +1 -1
  30. package/plugins/lisa-expo-agy/skills/directory-structure/SKILL.md +32 -20
  31. package/plugins/lisa-expo-agy/skills/directory-structure/scripts/validate_structure.py +15 -6
  32. package/plugins/lisa-expo-copilot/.claude-plugin/plugin.json +1 -1
  33. package/plugins/lisa-expo-copilot/skills/directory-structure/SKILL.md +32 -20
  34. package/plugins/lisa-expo-copilot/skills/directory-structure/scripts/validate_structure.py +15 -6
  35. package/plugins/lisa-expo-cursor/.claude-plugin/plugin.json +1 -1
  36. package/plugins/lisa-expo-cursor/skills/directory-structure/SKILL.md +32 -20
  37. package/plugins/lisa-expo-cursor/skills/directory-structure/scripts/validate_structure.py +15 -6
  38. package/plugins/lisa-harper-fabric/.claude-plugin/plugin.json +1 -1
  39. package/plugins/lisa-harper-fabric/.codex-plugin/plugin.json +1 -1
  40. package/plugins/lisa-harper-fabric-agy/plugin.json +1 -1
  41. package/plugins/lisa-harper-fabric-copilot/.claude-plugin/plugin.json +1 -1
  42. package/plugins/lisa-harper-fabric-cursor/.claude-plugin/plugin.json +1 -1
  43. package/plugins/lisa-nestjs/.claude-plugin/plugin.json +1 -1
  44. package/plugins/lisa-nestjs/.codex-plugin/plugin.json +1 -1
  45. package/plugins/lisa-nestjs-agy/plugin.json +1 -1
  46. package/plugins/lisa-nestjs-copilot/.claude-plugin/plugin.json +1 -1
  47. package/plugins/lisa-nestjs-cursor/.claude-plugin/plugin.json +1 -1
  48. package/plugins/lisa-openclaw/.claude-plugin/plugin.json +1 -1
  49. package/plugins/lisa-openclaw/.codex-plugin/plugin.json +1 -1
  50. package/plugins/lisa-openclaw-agy/plugin.json +1 -1
  51. package/plugins/lisa-openclaw-copilot/.claude-plugin/plugin.json +1 -1
  52. package/plugins/lisa-openclaw-cursor/.claude-plugin/plugin.json +1 -1
  53. package/plugins/lisa-rails/.claude-plugin/plugin.json +1 -1
  54. package/plugins/lisa-rails/.codex-plugin/plugin.json +1 -1
  55. package/plugins/lisa-rails-agy/plugin.json +1 -1
  56. package/plugins/lisa-rails-copilot/.claude-plugin/plugin.json +1 -1
  57. package/plugins/lisa-rails-cursor/.claude-plugin/plugin.json +1 -1
  58. package/plugins/lisa-typescript/.claude-plugin/plugin.json +1 -1
  59. package/plugins/lisa-typescript/.codex-plugin/plugin.json +1 -1
  60. package/plugins/lisa-typescript-agy/plugin.json +1 -1
  61. package/plugins/lisa-typescript-copilot/.claude-plugin/plugin.json +1 -1
  62. package/plugins/lisa-typescript-cursor/.claude-plugin/plugin.json +1 -1
  63. package/plugins/lisa-wiki/.claude-plugin/plugin.json +1 -1
  64. package/plugins/lisa-wiki/.codex-plugin/plugin.json +1 -1
  65. package/plugins/lisa-wiki-agy/plugin.json +1 -1
  66. package/plugins/lisa-wiki-copilot/.claude-plugin/plugin.json +1 -1
  67. package/plugins/lisa-wiki-cursor/.claude-plugin/plugin.json +1 -1
  68. package/plugins/src/expo/skills/directory-structure/SKILL.md +32 -20
  69. package/plugins/src/expo/skills/directory-structure/scripts/validate_structure.py +15 -6
  70. package/typescript/copy-overwrite/.prettierignore +1 -0
  71. package/typescript/copy-overwrite/eslint.ignore.config.json +2 -0
@@ -20,28 +20,40 @@ This skill ensures all new code follows the documented directory structure stand
20
20
 
21
21
  ## Root Directory Structure
22
22
 
23
+ Expo SDK 55+/56 adopts the `/src` convention: all **application source** lives
24
+ under `src/`, while config, assets, tests, and tooling stay at the project root.
25
+ Older projects keep source at the root. The structure below shows the `/src`
26
+ layout; for a root-layout project, read `src/<dir>` as `<dir>`. The `@/*`
27
+ TypeScript path alias points at `./src/*` (or `./*` for root layout), so imports
28
+ are identical either way. The validator and lint/coverage configs auto-detect a
29
+ `src/` directory.
30
+
23
31
  ```
24
32
  <project-root>/
25
- ├── app/ # Expo Router - THIN WRAPPERS ONLY
26
- ├── features/ # Feature modules - PRIMARY CODE LOCATION
27
- ├── components/ # Shared components
28
- │ ├── ui/ # GlueStack UI primitives
29
- │ ├── icons/ # Icon components
30
- │ ├── custom/ # Custom UI components
31
- └── [ComponentName]/ # Feature-agnostic components
32
- ├── hooks/ # Global hooks (with __tests__/)
33
- ├── providers/ # Global React context providers (with __tests__/)
34
- ├── stores/ # Global state - Apollo reactive variables (with __tests__/)
35
- ├── utils/ # Utility functions (with __tests__/)
36
- ├── types/ # Global TypeScript types
37
- ├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
38
- ├── config/ # Configuration files
39
- ├── constants/ # Global constants
40
- ├── assets/ # Static assets (fonts/, icons/, css/)
41
- ├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/)
42
- ├── scripts/ # Build and development scripts
43
- ├── docs/ # Documentation
44
- └── projects/ # Project-specific files (archive/)
33
+ ├── src/ # APPLICATION SOURCE (SDK 55+/56 /src convention)
34
+ ├── app/ # Expo Router - THIN WRAPPERS ONLY
35
+ ├── features/ # Feature modules - PRIMARY CODE LOCATION
36
+ │ ├── components/ # Shared components
37
+ ├── ui/ # GlueStack UI primitives
38
+ ├── icons/ # Icon components
39
+ │ ├── custom/ # Custom UI components
40
+ │ │ └── [ComponentName]/ # Feature-agnostic components
41
+ ├── hooks/ # Global hooks (with __tests__/)
42
+ ├── providers/ # Global React context providers (with __tests__/)
43
+ ├── stores/ # Global state - Apollo reactive variables (with __tests__/)
44
+ ├── utils/ # Utility functions (with __tests__/)
45
+ ├── lib/ # Utility libraries / integrations
46
+ ├── types/ # Global TypeScript types
47
+ ├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
48
+ ├── config/ # Configuration files
49
+ │ └── constants/ # Global constants
50
+ ├── assets/ # Static assets (fonts/, icons/, css/) — STAYS AT ROOT
51
+ ├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/) — STAYS AT ROOT
52
+ ├── scripts/ # Build and development scripts — STAYS AT ROOT
53
+ ├── public/ # Public web assets — STAYS AT ROOT
54
+ ├── __mocks__/ # Jest manual mocks — STAYS AT ROOT
55
+ ├── docs/ # Documentation — STAYS AT ROOT
56
+ └── projects/ # Project-specific files (archive/) — STAYS AT ROOT
45
57
  ```
46
58
 
47
59
  ## Feature Module Structure
@@ -298,8 +298,12 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
298
298
  """Validate file and directory naming conventions."""
299
299
  results = []
300
300
 
301
+ # Source lives under src/ for projects on the Expo SDK 55+/56 /src
302
+ # convention; fall back to the project root otherwise.
303
+ source_root = root / 'src' if (root / 'src').is_dir() else root
304
+
301
305
  # Feature directory names should be kebab-case
302
- features_dir = root / 'features'
306
+ features_dir = source_root / 'features'
303
307
  if features_dir.exists():
304
308
  kebab_pattern = re.compile(r'^[a-z][a-z0-9]*(-[a-z0-9]+)*$')
305
309
  for item in features_dir.iterdir():
@@ -308,7 +312,7 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
308
312
  results.append(ValidationResult(
309
313
  passed=False,
310
314
  message=f"Feature directory not in kebab-case",
311
- file_path=f"features/{item.name}",
315
+ file_path=str(item.relative_to(root)),
312
316
  suggestion=f"Rename to kebab-case (e.g., 'my-feature')"
313
317
  ))
314
318
 
@@ -330,7 +334,7 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
330
334
  ))
331
335
 
332
336
  # Check components directory (skip special subdirectories)
333
- components_dir = root / 'components'
337
+ components_dir = source_root / 'components'
334
338
  if components_dir.exists():
335
339
  for item in components_dir.iterdir():
336
340
  # Skip special directories that are allowed to be lowercase
@@ -361,22 +365,27 @@ def run_validation(path: Path) -> ValidationReport:
361
365
  report = ValidationReport()
362
366
  root = find_project_root(path)
363
367
 
368
+ # Source lives under src/ for projects on the Expo SDK 55+/56 /src
369
+ # convention; fall back to the project root otherwise. relative_to(root)
370
+ # is still used for display so reported paths read as src/...
371
+ source_root = root / 'src' if (root / 'src').is_dir() else root
372
+
364
373
  print(f"Validating directory structure from: {root}\n")
365
374
 
366
375
  # Run all validations
367
376
  report.errors.extend(validate_test_file_placement(root))
368
377
  report.errors.extend(validate_naming_conventions(root))
369
- report.errors.extend(validate_app_directory(root / 'app', root))
378
+ report.errors.extend(validate_app_directory(source_root / 'app', root))
370
379
 
371
380
  # Validate features
372
- features_dir = root / 'features'
381
+ features_dir = source_root / 'features'
373
382
  if features_dir.exists():
374
383
  for feature in features_dir.iterdir():
375
384
  if feature.is_dir() and not feature.name.startswith('.'):
376
385
  report.errors.extend(validate_feature_structure(feature, root))
377
386
 
378
387
  # Validate global components
379
- components_dir = root / 'components'
388
+ components_dir = source_root / 'components'
380
389
  if components_dir.exists():
381
390
  for item in components_dir.iterdir():
382
391
  # Skip ui/, icons/, custom/ as they have different structure
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -20,28 +20,40 @@ This skill ensures all new code follows the documented directory structure stand
20
20
 
21
21
  ## Root Directory Structure
22
22
 
23
+ Expo SDK 55+/56 adopts the `/src` convention: all **application source** lives
24
+ under `src/`, while config, assets, tests, and tooling stay at the project root.
25
+ Older projects keep source at the root. The structure below shows the `/src`
26
+ layout; for a root-layout project, read `src/<dir>` as `<dir>`. The `@/*`
27
+ TypeScript path alias points at `./src/*` (or `./*` for root layout), so imports
28
+ are identical either way. The validator and lint/coverage configs auto-detect a
29
+ `src/` directory.
30
+
23
31
  ```
24
32
  <project-root>/
25
- ├── app/ # Expo Router - THIN WRAPPERS ONLY
26
- ├── features/ # Feature modules - PRIMARY CODE LOCATION
27
- ├── components/ # Shared components
28
- │ ├── ui/ # GlueStack UI primitives
29
- │ ├── icons/ # Icon components
30
- │ ├── custom/ # Custom UI components
31
- └── [ComponentName]/ # Feature-agnostic components
32
- ├── hooks/ # Global hooks (with __tests__/)
33
- ├── providers/ # Global React context providers (with __tests__/)
34
- ├── stores/ # Global state - Apollo reactive variables (with __tests__/)
35
- ├── utils/ # Utility functions (with __tests__/)
36
- ├── types/ # Global TypeScript types
37
- ├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
38
- ├── config/ # Configuration files
39
- ├── constants/ # Global constants
40
- ├── assets/ # Static assets (fonts/, icons/, css/)
41
- ├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/)
42
- ├── scripts/ # Build and development scripts
43
- ├── docs/ # Documentation
44
- └── projects/ # Project-specific files (archive/)
33
+ ├── src/ # APPLICATION SOURCE (SDK 55+/56 /src convention)
34
+ ├── app/ # Expo Router - THIN WRAPPERS ONLY
35
+ ├── features/ # Feature modules - PRIMARY CODE LOCATION
36
+ │ ├── components/ # Shared components
37
+ ├── ui/ # GlueStack UI primitives
38
+ ├── icons/ # Icon components
39
+ │ ├── custom/ # Custom UI components
40
+ │ │ └── [ComponentName]/ # Feature-agnostic components
41
+ ├── hooks/ # Global hooks (with __tests__/)
42
+ ├── providers/ # Global React context providers (with __tests__/)
43
+ ├── stores/ # Global state - Apollo reactive variables (with __tests__/)
44
+ ├── utils/ # Utility functions (with __tests__/)
45
+ ├── lib/ # Utility libraries / integrations
46
+ ├── types/ # Global TypeScript types
47
+ ├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
48
+ ├── config/ # Configuration files
49
+ │ └── constants/ # Global constants
50
+ ├── assets/ # Static assets (fonts/, icons/, css/) — STAYS AT ROOT
51
+ ├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/) — STAYS AT ROOT
52
+ ├── scripts/ # Build and development scripts — STAYS AT ROOT
53
+ ├── public/ # Public web assets — STAYS AT ROOT
54
+ ├── __mocks__/ # Jest manual mocks — STAYS AT ROOT
55
+ ├── docs/ # Documentation — STAYS AT ROOT
56
+ └── projects/ # Project-specific files (archive/) — STAYS AT ROOT
45
57
  ```
46
58
 
47
59
  ## Feature Module Structure
@@ -298,8 +298,12 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
298
298
  """Validate file and directory naming conventions."""
299
299
  results = []
300
300
 
301
+ # Source lives under src/ for projects on the Expo SDK 55+/56 /src
302
+ # convention; fall back to the project root otherwise.
303
+ source_root = root / 'src' if (root / 'src').is_dir() else root
304
+
301
305
  # Feature directory names should be kebab-case
302
- features_dir = root / 'features'
306
+ features_dir = source_root / 'features'
303
307
  if features_dir.exists():
304
308
  kebab_pattern = re.compile(r'^[a-z][a-z0-9]*(-[a-z0-9]+)*$')
305
309
  for item in features_dir.iterdir():
@@ -308,7 +312,7 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
308
312
  results.append(ValidationResult(
309
313
  passed=False,
310
314
  message=f"Feature directory not in kebab-case",
311
- file_path=f"features/{item.name}",
315
+ file_path=str(item.relative_to(root)),
312
316
  suggestion=f"Rename to kebab-case (e.g., 'my-feature')"
313
317
  ))
314
318
 
@@ -330,7 +334,7 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
330
334
  ))
331
335
 
332
336
  # Check components directory (skip special subdirectories)
333
- components_dir = root / 'components'
337
+ components_dir = source_root / 'components'
334
338
  if components_dir.exists():
335
339
  for item in components_dir.iterdir():
336
340
  # Skip special directories that are allowed to be lowercase
@@ -361,22 +365,27 @@ def run_validation(path: Path) -> ValidationReport:
361
365
  report = ValidationReport()
362
366
  root = find_project_root(path)
363
367
 
368
+ # Source lives under src/ for projects on the Expo SDK 55+/56 /src
369
+ # convention; fall back to the project root otherwise. relative_to(root)
370
+ # is still used for display so reported paths read as src/...
371
+ source_root = root / 'src' if (root / 'src').is_dir() else root
372
+
364
373
  print(f"Validating directory structure from: {root}\n")
365
374
 
366
375
  # Run all validations
367
376
  report.errors.extend(validate_test_file_placement(root))
368
377
  report.errors.extend(validate_naming_conventions(root))
369
- report.errors.extend(validate_app_directory(root / 'app', root))
378
+ report.errors.extend(validate_app_directory(source_root / 'app', root))
370
379
 
371
380
  # Validate features
372
- features_dir = root / 'features'
381
+ features_dir = source_root / 'features'
373
382
  if features_dir.exists():
374
383
  for feature in features_dir.iterdir():
375
384
  if feature.is_dir() and not feature.name.startswith('.'):
376
385
  report.errors.extend(validate_feature_structure(feature, root))
377
386
 
378
387
  # Validate global components
379
- components_dir = root / 'components'
388
+ components_dir = source_root / 'components'
380
389
  if components_dir.exists():
381
390
  for item in components_dir.iterdir():
382
391
  # Skip ui/, icons/, custom/ as they have different structure
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -20,28 +20,40 @@ This skill ensures all new code follows the documented directory structure stand
20
20
 
21
21
  ## Root Directory Structure
22
22
 
23
+ Expo SDK 55+/56 adopts the `/src` convention: all **application source** lives
24
+ under `src/`, while config, assets, tests, and tooling stay at the project root.
25
+ Older projects keep source at the root. The structure below shows the `/src`
26
+ layout; for a root-layout project, read `src/<dir>` as `<dir>`. The `@/*`
27
+ TypeScript path alias points at `./src/*` (or `./*` for root layout), so imports
28
+ are identical either way. The validator and lint/coverage configs auto-detect a
29
+ `src/` directory.
30
+
23
31
  ```
24
32
  <project-root>/
25
- ├── app/ # Expo Router - THIN WRAPPERS ONLY
26
- ├── features/ # Feature modules - PRIMARY CODE LOCATION
27
- ├── components/ # Shared components
28
- │ ├── ui/ # GlueStack UI primitives
29
- │ ├── icons/ # Icon components
30
- │ ├── custom/ # Custom UI components
31
- └── [ComponentName]/ # Feature-agnostic components
32
- ├── hooks/ # Global hooks (with __tests__/)
33
- ├── providers/ # Global React context providers (with __tests__/)
34
- ├── stores/ # Global state - Apollo reactive variables (with __tests__/)
35
- ├── utils/ # Utility functions (with __tests__/)
36
- ├── types/ # Global TypeScript types
37
- ├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
38
- ├── config/ # Configuration files
39
- ├── constants/ # Global constants
40
- ├── assets/ # Static assets (fonts/, icons/, css/)
41
- ├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/)
42
- ├── scripts/ # Build and development scripts
43
- ├── docs/ # Documentation
44
- └── projects/ # Project-specific files (archive/)
33
+ ├── src/ # APPLICATION SOURCE (SDK 55+/56 /src convention)
34
+ ├── app/ # Expo Router - THIN WRAPPERS ONLY
35
+ ├── features/ # Feature modules - PRIMARY CODE LOCATION
36
+ │ ├── components/ # Shared components
37
+ ├── ui/ # GlueStack UI primitives
38
+ ├── icons/ # Icon components
39
+ │ ├── custom/ # Custom UI components
40
+ │ │ └── [ComponentName]/ # Feature-agnostic components
41
+ ├── hooks/ # Global hooks (with __tests__/)
42
+ ├── providers/ # Global React context providers (with __tests__/)
43
+ ├── stores/ # Global state - Apollo reactive variables (with __tests__/)
44
+ ├── utils/ # Utility functions (with __tests__/)
45
+ ├── lib/ # Utility libraries / integrations
46
+ ├── types/ # Global TypeScript types
47
+ ├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
48
+ ├── config/ # Configuration files
49
+ │ └── constants/ # Global constants
50
+ ├── assets/ # Static assets (fonts/, icons/, css/) — STAYS AT ROOT
51
+ ├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/) — STAYS AT ROOT
52
+ ├── scripts/ # Build and development scripts — STAYS AT ROOT
53
+ ├── public/ # Public web assets — STAYS AT ROOT
54
+ ├── __mocks__/ # Jest manual mocks — STAYS AT ROOT
55
+ ├── docs/ # Documentation — STAYS AT ROOT
56
+ └── projects/ # Project-specific files (archive/) — STAYS AT ROOT
45
57
  ```
46
58
 
47
59
  ## Feature Module Structure
@@ -298,8 +298,12 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
298
298
  """Validate file and directory naming conventions."""
299
299
  results = []
300
300
 
301
+ # Source lives under src/ for projects on the Expo SDK 55+/56 /src
302
+ # convention; fall back to the project root otherwise.
303
+ source_root = root / 'src' if (root / 'src').is_dir() else root
304
+
301
305
  # Feature directory names should be kebab-case
302
- features_dir = root / 'features'
306
+ features_dir = source_root / 'features'
303
307
  if features_dir.exists():
304
308
  kebab_pattern = re.compile(r'^[a-z][a-z0-9]*(-[a-z0-9]+)*$')
305
309
  for item in features_dir.iterdir():
@@ -308,7 +312,7 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
308
312
  results.append(ValidationResult(
309
313
  passed=False,
310
314
  message=f"Feature directory not in kebab-case",
311
- file_path=f"features/{item.name}",
315
+ file_path=str(item.relative_to(root)),
312
316
  suggestion=f"Rename to kebab-case (e.g., 'my-feature')"
313
317
  ))
314
318
 
@@ -330,7 +334,7 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
330
334
  ))
331
335
 
332
336
  # Check components directory (skip special subdirectories)
333
- components_dir = root / 'components'
337
+ components_dir = source_root / 'components'
334
338
  if components_dir.exists():
335
339
  for item in components_dir.iterdir():
336
340
  # Skip special directories that are allowed to be lowercase
@@ -361,22 +365,27 @@ def run_validation(path: Path) -> ValidationReport:
361
365
  report = ValidationReport()
362
366
  root = find_project_root(path)
363
367
 
368
+ # Source lives under src/ for projects on the Expo SDK 55+/56 /src
369
+ # convention; fall back to the project root otherwise. relative_to(root)
370
+ # is still used for display so reported paths read as src/...
371
+ source_root = root / 'src' if (root / 'src').is_dir() else root
372
+
364
373
  print(f"Validating directory structure from: {root}\n")
365
374
 
366
375
  # Run all validations
367
376
  report.errors.extend(validate_test_file_placement(root))
368
377
  report.errors.extend(validate_naming_conventions(root))
369
- report.errors.extend(validate_app_directory(root / 'app', root))
378
+ report.errors.extend(validate_app_directory(source_root / 'app', root))
370
379
 
371
380
  # Validate features
372
- features_dir = root / 'features'
381
+ features_dir = source_root / 'features'
373
382
  if features_dir.exists():
374
383
  for feature in features_dir.iterdir():
375
384
  if feature.is_dir() and not feature.name.startswith('.'):
376
385
  report.errors.extend(validate_feature_structure(feature, root))
377
386
 
378
387
  # Validate global components
379
- components_dir = root / 'components'
388
+ components_dir = source_root / 'components'
380
389
  if components_dir.exists():
381
390
  for item in components_dir.iterdir():
382
391
  # Skip ui/, icons/, custom/ as they have different structure
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-expo",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "Expo/React Native-specific skills, agents, rules, and MCP servers",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -20,28 +20,40 @@ This skill ensures all new code follows the documented directory structure stand
20
20
 
21
21
  ## Root Directory Structure
22
22
 
23
+ Expo SDK 55+/56 adopts the `/src` convention: all **application source** lives
24
+ under `src/`, while config, assets, tests, and tooling stay at the project root.
25
+ Older projects keep source at the root. The structure below shows the `/src`
26
+ layout; for a root-layout project, read `src/<dir>` as `<dir>`. The `@/*`
27
+ TypeScript path alias points at `./src/*` (or `./*` for root layout), so imports
28
+ are identical either way. The validator and lint/coverage configs auto-detect a
29
+ `src/` directory.
30
+
23
31
  ```
24
32
  <project-root>/
25
- ├── app/ # Expo Router - THIN WRAPPERS ONLY
26
- ├── features/ # Feature modules - PRIMARY CODE LOCATION
27
- ├── components/ # Shared components
28
- │ ├── ui/ # GlueStack UI primitives
29
- │ ├── icons/ # Icon components
30
- │ ├── custom/ # Custom UI components
31
- └── [ComponentName]/ # Feature-agnostic components
32
- ├── hooks/ # Global hooks (with __tests__/)
33
- ├── providers/ # Global React context providers (with __tests__/)
34
- ├── stores/ # Global state - Apollo reactive variables (with __tests__/)
35
- ├── utils/ # Utility functions (with __tests__/)
36
- ├── types/ # Global TypeScript types
37
- ├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
38
- ├── config/ # Configuration files
39
- ├── constants/ # Global constants
40
- ├── assets/ # Static assets (fonts/, icons/, css/)
41
- ├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/)
42
- ├── scripts/ # Build and development scripts
43
- ├── docs/ # Documentation
44
- └── projects/ # Project-specific files (archive/)
33
+ ├── src/ # APPLICATION SOURCE (SDK 55+/56 /src convention)
34
+ ├── app/ # Expo Router - THIN WRAPPERS ONLY
35
+ ├── features/ # Feature modules - PRIMARY CODE LOCATION
36
+ │ ├── components/ # Shared components
37
+ ├── ui/ # GlueStack UI primitives
38
+ ├── icons/ # Icon components
39
+ │ ├── custom/ # Custom UI components
40
+ │ │ └── [ComponentName]/ # Feature-agnostic components
41
+ ├── hooks/ # Global hooks (with __tests__/)
42
+ ├── providers/ # Global React context providers (with __tests__/)
43
+ ├── stores/ # Global state - Apollo reactive variables (with __tests__/)
44
+ ├── utils/ # Utility functions (with __tests__/)
45
+ ├── lib/ # Utility libraries / integrations
46
+ ├── types/ # Global TypeScript types
47
+ ├── generated/ # Auto-generated GraphQL types (DO NOT EDIT)
48
+ ├── config/ # Configuration files
49
+ │ └── constants/ # Global constants
50
+ ├── assets/ # Static assets (fonts/, icons/, css/) — STAYS AT ROOT
51
+ ├── e2e/ # End-to-end tests (fixtures/, pages/, tests/, utils/) — STAYS AT ROOT
52
+ ├── scripts/ # Build and development scripts — STAYS AT ROOT
53
+ ├── public/ # Public web assets — STAYS AT ROOT
54
+ ├── __mocks__/ # Jest manual mocks — STAYS AT ROOT
55
+ ├── docs/ # Documentation — STAYS AT ROOT
56
+ └── projects/ # Project-specific files (archive/) — STAYS AT ROOT
45
57
  ```
46
58
 
47
59
  ## Feature Module Structure
@@ -298,8 +298,12 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
298
298
  """Validate file and directory naming conventions."""
299
299
  results = []
300
300
 
301
+ # Source lives under src/ for projects on the Expo SDK 55+/56 /src
302
+ # convention; fall back to the project root otherwise.
303
+ source_root = root / 'src' if (root / 'src').is_dir() else root
304
+
301
305
  # Feature directory names should be kebab-case
302
- features_dir = root / 'features'
306
+ features_dir = source_root / 'features'
303
307
  if features_dir.exists():
304
308
  kebab_pattern = re.compile(r'^[a-z][a-z0-9]*(-[a-z0-9]+)*$')
305
309
  for item in features_dir.iterdir():
@@ -308,7 +312,7 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
308
312
  results.append(ValidationResult(
309
313
  passed=False,
310
314
  message=f"Feature directory not in kebab-case",
311
- file_path=f"features/{item.name}",
315
+ file_path=str(item.relative_to(root)),
312
316
  suggestion=f"Rename to kebab-case (e.g., 'my-feature')"
313
317
  ))
314
318
 
@@ -330,7 +334,7 @@ def validate_naming_conventions(root: Path) -> List[ValidationResult]:
330
334
  ))
331
335
 
332
336
  # Check components directory (skip special subdirectories)
333
- components_dir = root / 'components'
337
+ components_dir = source_root / 'components'
334
338
  if components_dir.exists():
335
339
  for item in components_dir.iterdir():
336
340
  # Skip special directories that are allowed to be lowercase
@@ -361,22 +365,27 @@ def run_validation(path: Path) -> ValidationReport:
361
365
  report = ValidationReport()
362
366
  root = find_project_root(path)
363
367
 
368
+ # Source lives under src/ for projects on the Expo SDK 55+/56 /src
369
+ # convention; fall back to the project root otherwise. relative_to(root)
370
+ # is still used for display so reported paths read as src/...
371
+ source_root = root / 'src' if (root / 'src').is_dir() else root
372
+
364
373
  print(f"Validating directory structure from: {root}\n")
365
374
 
366
375
  # Run all validations
367
376
  report.errors.extend(validate_test_file_placement(root))
368
377
  report.errors.extend(validate_naming_conventions(root))
369
- report.errors.extend(validate_app_directory(root / 'app', root))
378
+ report.errors.extend(validate_app_directory(source_root / 'app', root))
370
379
 
371
380
  # Validate features
372
- features_dir = root / 'features'
381
+ features_dir = source_root / 'features'
373
382
  if features_dir.exists():
374
383
  for feature in features_dir.iterdir():
375
384
  if feature.is_dir() and not feature.name.startswith('.'):
376
385
  report.errors.extend(validate_feature_structure(feature, root))
377
386
 
378
387
  # Validate global components
379
- components_dir = root / 'components'
388
+ components_dir = source_root / 'components'
380
389
  if components_dir.exists():
381
390
  for item in components_dir.iterdir():
382
391
  # Skip ui/, icons/, custom/ as they have different structure
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "Harper/Fabric-specific Lisa rules for TypeScript component apps.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-harper-fabric",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "Harper/Fabric-specific rules for TypeScript component apps",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "NestJS-specific skills and migration write-protection hooks.",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lisa-nestjs",
3
- "version": "2.122.0",
3
+ "version": "2.123.0",
4
4
  "description": "NestJS-specific skills (GraphQL, TypeORM) and hooks (migration write-protection)",
5
5
  "author": {
6
6
  "name": "Cody Swann"