code-agnostic 0.4.0__tar.gz → 0.5.0__tar.gz

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 (171) hide show
  1. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/PKG-INFO +1 -1
  2. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/__init__.py +1 -1
  3. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/agents/claude.py +1 -1
  4. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/agents/codex.py +2 -2
  5. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/agents/parser.py +2 -2
  6. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/apps_service.py +2 -2
  7. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/codex/config_repository.py +2 -2
  8. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/framework.py +2 -2
  9. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/schema.py +1 -1
  10. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/aliases.py +3 -1
  11. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/workspaces.py +2 -1
  12. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/helpers.py +9 -2
  13. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/options.py +17 -6
  14. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/executor.py +7 -7
  15. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/imports/adapters.py +6 -2
  16. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/imports/service.py +13 -10
  17. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/planner.py +57 -66
  18. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/project_artifacts.py +6 -2
  19. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/rules/compilers.py +2 -1
  20. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/rules/parser.py +2 -1
  21. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/skills/parser.py +6 -3
  22. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/status.py +4 -4
  23. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/tui/renderers.py +3 -1
  24. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/tui/sections.py +5 -1
  25. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/tui/tables.py +6 -5
  26. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic.egg-info/PKG-INFO +1 -1
  27. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/pyproject.toml +6 -1
  28. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/LICENSE +0 -0
  29. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/README.md +0 -0
  30. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/__main__.py +0 -0
  31. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/agents/__init__.py +0 -0
  32. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/agents/compilers.py +0 -0
  33. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/agents/copilot.py +0 -0
  34. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/agents/models.py +0 -0
  35. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/agents/opencode.py +0 -0
  36. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/__init__.py +0 -0
  37. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/app_id.py +0 -0
  38. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/claude/__init__.py +0 -0
  39. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/claude/config_repository.py +0 -0
  40. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/claude/mapper.py +0 -0
  41. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/claude/service.py +0 -0
  42. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/codex/__init__.py +0 -0
  43. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/codex/mapper.py +0 -0
  44. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/codex/schema.json +0 -0
  45. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/codex/schema_repository.py +0 -0
  46. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/codex/service.py +0 -0
  47. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/__init__.py +0 -0
  48. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/compiled_planning.py +0 -0
  49. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/interfaces/__init__.py +0 -0
  50. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/interfaces/mapper.py +0 -0
  51. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/interfaces/repositories.py +0 -0
  52. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/interfaces/service.py +0 -0
  53. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/loader.py +0 -0
  54. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/models.py +0 -0
  55. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/symlink_planning.py +0 -0
  56. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/common/utils.py +0 -0
  57. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/copilot/__init__.py +0 -0
  58. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/copilot/config_repository.py +0 -0
  59. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/copilot/mapper.py +0 -0
  60. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/copilot/service.py +0 -0
  61. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/cursor/__init__.py +0 -0
  62. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/cursor/config_repository.py +0 -0
  63. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/cursor/mapper.py +0 -0
  64. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/cursor/schema.json +0 -0
  65. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/cursor/schema_repository.py +0 -0
  66. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/cursor/service.py +0 -0
  67. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/opencode/__init__.py +0 -0
  68. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/opencode/config_repository.py +0 -0
  69. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/opencode/mapper.py +0 -0
  70. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/opencode/schema.json +0 -0
  71. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/opencode/schema_repository.py +0 -0
  72. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/apps/opencode/service.py +0 -0
  73. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/__init__.py +0 -0
  74. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/__init__.py +0 -0
  75. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/agents.py +0 -0
  76. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/apply.py +0 -0
  77. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/apps.py +0 -0
  78. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/explain_lossiness.py +0 -0
  79. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/import_.py +0 -0
  80. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/mcp.py +0 -0
  81. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/plan.py +0 -0
  82. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/projects.py +0 -0
  83. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/restore.py +0 -0
  84. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/rules.py +0 -0
  85. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/skills.py +0 -0
  86. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/status.py +0 -0
  87. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/cli/commands/validate.py +0 -0
  88. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/constants.py +0 -0
  89. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/core/__init__.py +0 -0
  90. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/core/project_repository.py +0 -0
  91. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/core/repository.py +0 -0
  92. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/core/workspace_repository.py +0 -0
  93. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/errors.py +0 -0
  94. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/generated_artifacts.py +0 -0
  95. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/git_exclude_service.py +0 -0
  96. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/imports/__init__.py +0 -0
  97. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/imports/filesystem.py +0 -0
  98. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/imports/models.py +0 -0
  99. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/lossiness.py +0 -0
  100. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/mcp_service.py +0 -0
  101. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/models.py +0 -0
  102. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/rules/__init__.py +0 -0
  103. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/rules/models.py +0 -0
  104. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/rules/repository.py +0 -0
  105. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/skills/__init__.py +0 -0
  106. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/skills/compilers.py +0 -0
  107. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/skills/install_sources.py +0 -0
  108. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/skills/models.py +0 -0
  109. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/spec/__init__.py +0 -0
  110. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/spec/loaders.py +0 -0
  111. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/spec/schemas/agent.v1.schema.json +0 -0
  112. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/spec/schemas/mcp.base.schema.json +0 -0
  113. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/spec/schemas/mcp.v1.schema.json +0 -0
  114. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/spec/schemas/rule.v1.schema.json +0 -0
  115. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/spec/schemas/skill.v1.schema.json +0 -0
  116. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/tui/__init__.py +0 -0
  117. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/tui/enums.py +0 -0
  118. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/tui/import_selector.py +0 -0
  119. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/utils.py +0 -0
  120. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/validation.py +0 -0
  121. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/workspace_artifacts.py +0 -0
  122. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic/workspaces.py +0 -0
  123. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic.egg-info/SOURCES.txt +0 -0
  124. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic.egg-info/dependency_links.txt +0 -0
  125. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic.egg-info/entry_points.txt +0 -0
  126. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic.egg-info/requires.txt +0 -0
  127. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/code_agnostic.egg-info/top_level.txt +0 -0
  128. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/setup.cfg +0 -0
  129. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_agents.py +0 -0
  130. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_aliases.py +0 -0
  131. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_apply_apps.py +0 -0
  132. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_apply_codex.py +0 -0
  133. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_apply_cursor.py +0 -0
  134. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_apply_mcp_cleanup.py +0 -0
  135. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_apply_target.py +0 -0
  136. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_apps.py +0 -0
  137. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_disable_cleanup.py +0 -0
  138. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_explain_lossiness.py +0 -0
  139. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_flags.py +0 -0
  140. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_git_exclude.py +0 -0
  141. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_import.py +0 -0
  142. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_import_interactive.py +0 -0
  143. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_mcp.py +0 -0
  144. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_module_organization.py +0 -0
  145. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_plan.py +0 -0
  146. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_projects.py +0 -0
  147. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_restore.py +0 -0
  148. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_rules.py +0 -0
  149. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_skills.py +0 -0
  150. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_status.py +0 -0
  151. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_validate.py +0 -0
  152. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_workspace_resolution.py +0 -0
  153. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_cli_workspaces.py +0 -0
  154. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_common_mcp_to_dto.py +0 -0
  155. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_common_repository.py +0 -0
  156. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_compiled_planning.py +0 -0
  157. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_dto_to_common_mcp.py +0 -0
  158. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_git_exclude_service.py +0 -0
  159. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_mcp_service.py +0 -0
  160. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_planner_executor.py +0 -0
  161. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_planner_rules.py +0 -0
  162. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_project_config_sync.py +0 -0
  163. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_skill_install_sources.py +0 -0
  164. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_symlink_planning.py +0 -0
  165. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_sync_plan_model.py +0 -0
  166. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_transactional_executor.py +0 -0
  167. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_utils.py +0 -0
  168. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_version.py +0 -0
  169. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_workspace_config_sync.py +0 -0
  170. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_workspace_repo_status.py +0 -0
  171. {code_agnostic-0.4.0 → code_agnostic-0.5.0}/tests/test_workspaces.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-agnostic
3
- Version: 0.4.0
3
+ Version: 0.5.0
4
4
  Summary: Centralized hub for LLM coding config: MCP, skills, rules, and agents.
5
5
  Requires-Python: >=3.10
6
6
  Description-Content-Type: text/markdown
@@ -1,3 +1,3 @@
1
1
  __all__ = ["__version__"]
2
2
 
3
- __version__ = "0.4.0"
3
+ __version__ = "0.5.0"
@@ -6,7 +6,7 @@ import re
6
6
  from pathlib import Path
7
7
  from typing import Any
8
8
 
9
- import yaml # type: ignore[import-untyped]
9
+ import yaml
10
10
 
11
11
  from code_agnostic.agents.models import Agent
12
12
 
@@ -7,9 +7,9 @@ from pathlib import Path
7
7
  from typing import Any
8
8
 
9
9
  try:
10
- import tomllib
10
+ import tomllib # type: ignore[import-not-found]
11
11
  except ModuleNotFoundError: # pragma: no cover
12
- import tomli as tomllib # type: ignore
12
+ import tomli as tomllib
13
13
 
14
14
  import tomlkit
15
15
 
@@ -83,7 +83,7 @@ def parse_agent(path: Path) -> Agent:
83
83
 
84
84
 
85
85
  def serialize_agent(agent: Agent, *, target_app: str | None = None) -> str:
86
- fm: dict = {}
86
+ fm: dict[str, Any] = {}
87
87
  if agent.metadata.name:
88
88
  fm["name"] = agent.metadata.name
89
89
  if agent.metadata.description:
@@ -105,7 +105,7 @@ def serialize_agent(agent: Agent, *, target_app: str | None = None) -> str:
105
105
  if nickname_candidates:
106
106
  fm["nickname_candidates"] = list(nickname_candidates)
107
107
 
108
- tools: dict = {}
108
+ tools: dict[str, Any] = {}
109
109
  if agent.metadata.tools.read is not True:
110
110
  tools["read"] = agent.metadata.tools.read
111
111
  if agent.metadata.tools.write is not True:
@@ -7,7 +7,6 @@ from code_agnostic.apps.common.framework import (
7
7
  list_registered_app_services,
8
8
  )
9
9
  from code_agnostic.apps.common.interfaces.service import IAppConfigService
10
- from code_agnostic.apps.common.interfaces.repositories import ISourceRepository
11
10
  from code_agnostic.apps.common.symlink_planning import (
12
11
  load_state_links,
13
12
  load_state_paths,
@@ -15,6 +14,7 @@ from code_agnostic.apps.common.symlink_planning import (
15
14
  plan_stale_group,
16
15
  )
17
16
  from code_agnostic.core.project_repository import ProjectConfigRepository
17
+ from code_agnostic.core.repository import CoreRepository
18
18
  from code_agnostic.core.workspace_repository import WorkspaceConfigRepository
19
19
  from code_agnostic.executor import SyncExecutor
20
20
  from code_agnostic.models import Action, AppStatusRow, AppSyncStatus, SyncPlan
@@ -24,7 +24,7 @@ from code_agnostic.utils import read_json_safe, write_json
24
24
 
25
25
 
26
26
  class AppsService:
27
- def __init__(self, core_repository: ISourceRepository) -> None:
27
+ def __init__(self, core_repository: CoreRepository) -> None:
28
28
  self.core_repository = core_repository
29
29
 
30
30
  @property
@@ -3,9 +3,9 @@ from pathlib import Path
3
3
  from typing import Any
4
4
 
5
5
  try:
6
- import tomllib
6
+ import tomllib # type: ignore[import-not-found]
7
7
  except ModuleNotFoundError: # pragma: no cover
8
- import tomli as tomllib # type: ignore
8
+ import tomli as tomllib
9
9
 
10
10
  import tomlkit
11
11
 
@@ -20,12 +20,12 @@ class AppServiceRegistryMeta(ABCMeta):
20
20
  bases: tuple[type, ...],
21
21
  namespace: dict[str, Any],
22
22
  **kwargs: Any,
23
- ):
23
+ ) -> "AppServiceRegistryMeta":
24
24
  cls = super().__new__(mcls, name, bases, namespace, **kwargs)
25
25
  app_id = getattr(cls, "APP_ID", None)
26
26
  is_abstract = bool(getattr(cls, "__abstractmethods__", False))
27
27
  if app_id is not None and not is_abstract:
28
- mcls._registry[app_id] = cast(type["RegisteredAppConfigService"], cls) # type: ignore[assignment]
28
+ mcls._registry[app_id] = cast(type["RegisteredAppConfigService"], cls)
29
29
  return cls
30
30
 
31
31
 
@@ -51,6 +51,6 @@ class JsonSchemaRepository(ISchemaRepository):
51
51
  now = time.time()
52
52
  if cached and now - cached[0] < self.ttl_seconds:
53
53
  return cached[1]
54
- schema = json.loads(path.read_text(encoding="utf-8"))
54
+ schema: dict[str, Any] = json.loads(path.read_text(encoding="utf-8"))
55
55
  _SCHEMA_CACHE[key] = (now, schema)
56
56
  return schema
@@ -14,7 +14,9 @@ class AliasedGroup(click.Group):
14
14
  def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command | None:
15
15
  return super().get_command(ctx, self.ALIASES.get(cmd_name, cmd_name))
16
16
 
17
- def resolve_command(self, ctx: click.Context, args: list[str]):
17
+ def resolve_command(
18
+ self, ctx: click.Context, args: list[str]
19
+ ) -> tuple[str | None, click.Command | None, list[str]]:
18
20
  if args and args[0] in self.ALIASES:
19
21
  args[0] = self.ALIASES[args[0]]
20
22
  return super().resolve_command(ctx, args)
@@ -1,6 +1,7 @@
1
1
  """Workspaces group commands."""
2
2
 
3
3
  from pathlib import Path
4
+ from typing import Any
4
5
 
5
6
  import click
6
7
  from rich.console import Console
@@ -63,7 +64,7 @@ def workspaces_list(obj: dict[str, str]) -> None:
63
64
  core = CoreRepository()
64
65
  workspace_service = WorkspaceService()
65
66
 
66
- overview: list[dict] = []
67
+ overview: list[dict[str, Any]] = []
67
68
  try:
68
69
  workspaces = core.load_workspaces()
69
70
  except SyncAppError as exc:
@@ -7,7 +7,12 @@ import click
7
7
  from code_agnostic.apps.apps_service import AppsService
8
8
  from code_agnostic.core.repository import CoreRepository
9
9
  from code_agnostic.errors import SyncAppError
10
- from code_agnostic.models import ActionStatus, EditorStatusRow, EditorSyncStatus
10
+ from code_agnostic.models import (
11
+ ActionStatus,
12
+ EditorStatusRow,
13
+ EditorSyncStatus,
14
+ SyncPlan,
15
+ )
11
16
 
12
17
 
13
18
  def _workspace_entries_by_name(core: CoreRepository) -> dict[str, dict[str, str]]:
@@ -64,7 +69,9 @@ def reject_symlinked_source_dir(path: Path, resource_type: str) -> None:
64
69
  )
65
70
 
66
71
 
67
- def status_row_for_app(app_name: str, plan, apps: AppsService) -> EditorStatusRow:
72
+ def status_row_for_app(
73
+ app_name: str, plan: SyncPlan, apps: AppsService
74
+ ) -> EditorStatusRow:
68
75
  if not apps.is_enabled(app_name):
69
76
  return EditorStatusRow(
70
77
  name=app_name,
@@ -1,6 +1,7 @@
1
1
  """Shared option decorators for CLI commands."""
2
2
 
3
3
  from collections.abc import Callable
4
+ from typing import Any
4
5
 
5
6
  import click
6
7
 
@@ -38,7 +39,9 @@ def _import_source_values() -> list[str]:
38
39
  ]
39
40
 
40
41
 
41
- def app_option(required: bool = False) -> Callable:
42
+ def app_option(
43
+ required: bool = False,
44
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
42
45
  return click.option(
43
46
  "-a",
44
47
  "--app",
@@ -49,7 +52,9 @@ def app_option(required: bool = False) -> Callable:
49
52
  )
50
53
 
51
54
 
52
- def manageable_app_option(required: bool = True) -> Callable:
55
+ def manageable_app_option(
56
+ required: bool = True,
57
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
53
58
  return click.option(
54
59
  "-a",
55
60
  "--app",
@@ -59,7 +64,9 @@ def manageable_app_option(required: bool = True) -> Callable:
59
64
  )
60
65
 
61
66
 
62
- def import_app_option(required: bool = True) -> Callable:
67
+ def import_app_option(
68
+ required: bool = True,
69
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
63
70
  return click.option(
64
71
  "-a",
65
72
  "--app",
@@ -69,7 +76,9 @@ def import_app_option(required: bool = True) -> Callable:
69
76
  )
70
77
 
71
78
 
72
- def workspace_option(required: bool = False) -> Callable:
79
+ def workspace_option(
80
+ required: bool = False,
81
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
73
82
  return click.option(
74
83
  "-w",
75
84
  "--workspace",
@@ -79,7 +88,9 @@ def workspace_option(required: bool = False) -> Callable:
79
88
  )
80
89
 
81
90
 
82
- def project_option(required: bool = False) -> Callable:
91
+ def project_option(
92
+ required: bool = False,
93
+ ) -> Callable[[Callable[..., Any]], Callable[..., Any]]:
83
94
  return click.option(
84
95
  "--project",
85
96
  required=required,
@@ -88,5 +99,5 @@ def project_option(required: bool = False) -> Callable:
88
99
  )
89
100
 
90
101
 
91
- def verbose_option() -> Callable:
102
+ def verbose_option() -> Callable[[Callable[..., Any]], Callable[..., Any]]:
92
103
  return click.option("-v", "--verbose", is_flag=True, default=False)
@@ -7,13 +7,13 @@ from pathlib import Path
7
7
  from typing import Any
8
8
  from typing import Protocol
9
9
 
10
- from code_agnostic.apps.common.interfaces.repositories import ISourceRepository
11
10
  from code_agnostic.constants import (
12
11
  SYNC_REVISIONS_DIRNAME,
13
12
  SYNC_STAGING_DIRNAME,
14
13
  SYNC_STATE_FILENAME,
15
14
  )
16
15
  from code_agnostic.core.project_repository import ProjectConfigRepository
16
+ from code_agnostic.core.repository import CoreRepository
17
17
  from code_agnostic.core.workspace_repository import WorkspaceConfigRepository
18
18
  from code_agnostic.models import Action, ActionKind, ActionStatus, SyncPlan
19
19
  from code_agnostic.utils import write_json
@@ -21,7 +21,7 @@ from code_agnostic.utils import write_json
21
21
 
22
22
  @dataclass
23
23
  class ExecutionContext:
24
- core: ISourceRepository
24
+ core: CoreRepository
25
25
 
26
26
 
27
27
  @dataclass(frozen=True)
@@ -189,7 +189,7 @@ class WriteRuleHandler:
189
189
 
190
190
 
191
191
  class SyncExecutor:
192
- def __init__(self, core: ISourceRepository) -> None:
192
+ def __init__(self, core: CoreRepository) -> None:
193
193
  self.context = ExecutionContext(core=core)
194
194
  self.handlers: dict[ActionKind, ActionHandler] = {
195
195
  ActionKind.WRITE_JSON: WriteJsonHandler(),
@@ -421,12 +421,12 @@ class SyncExecutor:
421
421
  if workspace is not None and project is not None:
422
422
  raise ValueError("Choose only one scope: workspace or project.")
423
423
 
424
- if workspace is None and project is None:
425
- root = self.context.core.root
426
- elif workspace is not None:
424
+ if workspace is not None:
427
425
  root = self.context.core.workspace_config_dir(workspace)
428
- else:
426
+ elif project is not None:
429
427
  root = self.context.core.project_config_dir(project)
428
+ else:
429
+ root = self.context.core.root
430
430
 
431
431
  revision_record = self._build_revision_record(
432
432
  root=root, workspace=workspace, project=project, revision_id="restore"
@@ -1,5 +1,6 @@
1
1
  from dataclasses import dataclass
2
2
  from pathlib import Path
3
+ from typing import Any, cast
3
4
 
4
5
  from code_agnostic.apps.app_id import AppId
5
6
  from code_agnostic.apps.codex.config_repository import CodexConfigRepository
@@ -24,8 +25,11 @@ class ImportAdapter:
24
25
  mapper: IAppMCPMapper
25
26
  config_repository: object
26
27
 
27
- def load_mcp_payload(self) -> dict:
28
- return self.config_repository.load_mcp_payload() # type: ignore[attr-defined]
28
+ def load_mcp_payload(self) -> dict[str, Any]:
29
+ return cast(
30
+ "dict[str, Any]",
31
+ self.config_repository.load_mcp_payload(), # type: ignore[attr-defined]
32
+ )
29
33
 
30
34
 
31
35
  def create_import_adapter(app: str, source_root: Path | None = None) -> ImportAdapter:
@@ -1,4 +1,5 @@
1
1
  from pathlib import Path
2
+ from typing import Any
2
3
 
3
4
  from code_agnostic.agents.codex import normalize_codex_agent_filename, parse_codex_agent
4
5
  from code_agnostic.agents.parser import serialize_agent
@@ -8,7 +9,7 @@ from code_agnostic.apps.common.models import MCPServerDTO
8
9
  from code_agnostic.apps.common.utils import common_mcp_to_dto, dto_to_common_mcp
9
10
  from code_agnostic.core.repository import CoreRepository
10
11
  from code_agnostic.errors import InvalidConfigSchemaError, InvalidJsonFormatError
11
- from code_agnostic.imports.adapters import create_import_adapter
12
+ from code_agnostic.imports.adapters import ImportAdapter, create_import_adapter
12
13
  from code_agnostic.imports.filesystem import (
13
14
  content_equal,
14
15
  copy_path,
@@ -261,7 +262,9 @@ class ImportService:
261
262
  unsupported.append(ImportSection.AGENTS)
262
263
  return unsupported
263
264
 
264
- def _plan_mcp(self, adapter, conflict_policy: ConflictPolicy):
265
+ def _plan_mcp(
266
+ self, adapter: ImportAdapter, conflict_policy: ConflictPolicy
267
+ ) -> tuple[list[ImportAction], list[str], list[str]]:
265
268
  actions: list[ImportAction] = []
266
269
  errors: list[str] = []
267
270
  skipped: list[str] = []
@@ -272,7 +275,7 @@ class ImportService:
272
275
  return actions, [str(exc)], skipped
273
276
 
274
277
  if not source_dto:
275
- source_config = adapter.config_repository.config_path
278
+ source_config = adapter.config_repository.config_path # type: ignore[attr-defined]
276
279
  if source_config.exists():
277
280
  skipped.append(
278
281
  f"No MCP servers found in source config: {source_config}"
@@ -368,7 +371,7 @@ class ImportService:
368
371
  else:
369
372
  skipped.append(f"MCP server skipped due to conflict: {name}")
370
373
 
371
- normalized_payload = {}
374
+ normalized_payload: dict[str, Any] = {}
372
375
  existing_schema = existing_payload.get("$schema")
373
376
  if isinstance(existing_schema, str) and existing_schema:
374
377
  normalized_payload["$schema"] = existing_schema
@@ -399,7 +402,7 @@ class ImportService:
399
402
  target_dir: Path,
400
403
  conflict_policy: ConflictPolicy,
401
404
  follow_symlinks: bool,
402
- ):
405
+ ) -> tuple[list[ImportAction], list[str], list[str]]:
403
406
  actions: list[ImportAction] = []
404
407
  errors: list[str] = []
405
408
  skipped: list[str] = []
@@ -518,10 +521,10 @@ class ImportService:
518
521
 
519
522
  def _plan_codex_agents(
520
523
  self,
521
- adapter,
524
+ adapter: ImportAdapter,
522
525
  conflict_policy: ConflictPolicy,
523
526
  follow_symlinks: bool,
524
- ):
527
+ ) -> tuple[list[ImportAction], list[str], list[str]]:
525
528
  actions: list[ImportAction] = []
526
529
  errors: list[str] = []
527
530
  skipped: list[str] = []
@@ -584,10 +587,10 @@ class ImportService:
584
587
 
585
588
  def _plan_copilot_agents(
586
589
  self,
587
- adapter,
590
+ adapter: ImportAdapter,
588
591
  conflict_policy: ConflictPolicy,
589
592
  follow_symlinks: bool,
590
- ):
593
+ ) -> tuple[list[ImportAction], list[str], list[str]]:
591
594
  actions: list[ImportAction] = []
592
595
  errors: list[str] = []
593
596
  skipped: list[str] = []
@@ -707,7 +710,7 @@ class ImportService:
707
710
  section: ImportSection,
708
711
  detail_name: str,
709
712
  target: Path,
710
- payload: dict,
713
+ payload: dict[str, Any],
711
714
  conflict_policy: ConflictPolicy,
712
715
  ) -> tuple[ImportAction, str | None, str | None]:
713
716
  existing_payload, existing_error = read_json_safe(target)
@@ -5,7 +5,6 @@ from code_agnostic.apps.common.compiled_planning import (
5
5
  plan_owned_compiled_text_action,
6
6
  )
7
7
  from code_agnostic.apps.common.framework import create_registered_app_service
8
- from code_agnostic.apps.common.interfaces.repositories import ISourceRepository
9
8
  from code_agnostic.apps.common.interfaces.service import IAppConfigService
10
9
  from code_agnostic.apps.common.symlink_planning import (
11
10
  load_state_links,
@@ -34,6 +33,7 @@ from code_agnostic.constants import (
34
33
  SKILLS_DIRNAME,
35
34
  )
36
35
  from code_agnostic.core.project_repository import ProjectConfigRepository
36
+ from code_agnostic.core.repository import CoreRepository
37
37
  from code_agnostic.core.workspace_repository import WorkspaceConfigRepository
38
38
  from code_agnostic.errors import MissingConfigFileError, SyncAppError
39
39
  from code_agnostic.git_exclude_service import GitExcludeService
@@ -44,11 +44,12 @@ from code_agnostic.project_artifacts import (
44
44
  project_skills_dir,
45
45
  )
46
46
  from code_agnostic.rules.compilers import OpenCodeRuleCompiler
47
+ from code_agnostic.rules.models import Rule
47
48
  from code_agnostic.rules.repository import RulesRepository
48
49
  from code_agnostic.workspaces import WorkspaceService
49
50
 
50
51
 
51
- def _compile_workspace_agents(rules) -> str:
52
+ def _compile_workspace_agents(rules: list[Rule]) -> str:
52
53
  compiler = OpenCodeRuleCompiler()
53
54
  sections = [compiler.compile(rule)[1] for rule in rules]
54
55
  return "\n\n".join(sections) + "\n"
@@ -143,16 +144,9 @@ def _set_workspace_opencode_instructions(
143
144
  else:
144
145
  payload["instructions"] = [str(workspace_agents_path)]
145
146
 
146
- validate_config = getattr(service, "validate_config", None)
147
- if callable(validate_config):
148
- validate_config(payload)
149
-
147
+ service.validate_config(payload)
150
148
  existing = service.repository.load_config()
151
- derive_status = getattr(service, "derive_status", None)
152
- if callable(derive_status):
153
- derived_status = derive_status(existing, payload)
154
- if isinstance(derived_status, ActionStatus):
155
- action.status = derived_status
149
+ action.status = service.derive_status(existing, payload)
156
150
  action.payload = payload
157
151
 
158
152
 
@@ -235,7 +229,7 @@ def _prepare_project_action(action: Action, *, project_name: str) -> Action:
235
229
  class SyncPlanner:
236
230
  def __init__(
237
231
  self,
238
- core: ISourceRepository,
232
+ core: CoreRepository,
239
233
  app_services: list[IAppConfigService],
240
234
  workspace_service: WorkspaceService | None = None,
241
235
  include_workspace: bool = True,
@@ -379,7 +373,7 @@ class SyncPlanner:
379
373
 
380
374
  for svc in self.app_services:
381
375
  meta = app_metadata(svc.app_id)
382
- if meta.project_dir_name is None or not hasattr(svc, "plan_skill_actions"):
376
+ if meta.project_dir_name is None:
383
377
  continue
384
378
 
385
379
  target_service = _create_workspace_project_service(
@@ -400,14 +394,15 @@ class SyncPlanner:
400
394
  desired_paths_by_scope.setdefault(scope, []).append(mcp_action.path)
401
395
 
402
396
  scope = f"project:{svc.app_id.value}:{project_name}:skills_dir"
403
- plan_skill_actions = getattr(target_service, "plan_skill_actions")
404
- skill_actions, desired_paths, skill_skipped = plan_skill_actions(
405
- skill_sources,
406
- project_skills_dir(svc.app_id, project_root),
407
- scope,
408
- svc.app_id.value,
409
- load_state_paths(managed_paths, scope),
410
- load_state_links(managed_links, scope),
397
+ skill_actions, desired_paths, skill_skipped = (
398
+ target_service.plan_skill_actions(
399
+ skill_sources,
400
+ project_skills_dir(svc.app_id, project_root),
401
+ scope,
402
+ svc.app_id.value,
403
+ load_state_paths(managed_paths, scope),
404
+ load_state_links(managed_links, scope),
405
+ )
411
406
  )
412
407
  for action in skill_actions:
413
408
  _prepare_project_action(action, project_name=project_name)
@@ -459,7 +454,7 @@ class SyncPlanner:
459
454
 
460
455
  return SyncPlan(actions=actions, errors=[], skipped=skipped)
461
456
 
462
- def _plan_single_workspace(self, workspace: dict) -> SyncPlan:
457
+ def _plan_single_workspace(self, workspace: dict[str, str]) -> SyncPlan:
463
458
  workspace_name = workspace["name"]
464
459
  workspace_path = Path(workspace["path"])
465
460
 
@@ -685,18 +680,17 @@ class SyncPlanner:
685
680
  desired_paths_by_scope.setdefault(scope, []).append(mcp_action.path)
686
681
  if skill_sources:
687
682
  scope = f"ws:{svc.app_id.value}:workspace_root_skills_dir"
688
- plan_skill_actions = getattr(
689
- workspace_target_service, "plan_skill_actions"
690
- )
691
- skill_actions, desired_paths, skill_skipped = plan_skill_actions(
692
- skill_sources,
693
- _workspace_skills_dir(
694
- svc.app_id, workspace_target_service.repository.root
695
- ),
696
- scope,
697
- "workspace",
698
- load_state_paths(managed_paths, scope),
699
- load_state_links(managed_links, scope),
683
+ skill_actions, desired_paths, skill_skipped = (
684
+ workspace_target_service.plan_skill_actions(
685
+ skill_sources,
686
+ _workspace_skills_dir(
687
+ svc.app_id, workspace_target_service.repository.root
688
+ ),
689
+ scope,
690
+ "workspace",
691
+ load_state_paths(managed_paths, scope),
692
+ load_state_links(managed_links, scope),
693
+ )
700
694
  )
701
695
  for a in skill_actions:
702
696
  _prepare_workspace_action(
@@ -710,16 +704,15 @@ class SyncPlanner:
710
704
  skipped.extend(skill_skipped)
711
705
  if agent_sources and meta.supports_import_agents:
712
706
  scope = f"ws:{svc.app_id.value}:workspace_root_agents_dir"
713
- plan_agent_actions = getattr(
714
- workspace_target_service, "plan_agent_actions"
715
- )
716
- agent_actions, desired_paths, agent_skipped = plan_agent_actions(
717
- agent_sources,
718
- getattr(workspace_target_service.repository, "agents_dir"),
719
- scope,
720
- "workspace",
721
- load_state_paths(managed_paths, scope),
722
- load_state_links(managed_links, scope),
707
+ agent_actions, desired_paths, agent_skipped = (
708
+ workspace_target_service.plan_agent_actions(
709
+ agent_sources,
710
+ workspace_target_service.repository.agents_dir,
711
+ scope,
712
+ "workspace",
713
+ load_state_paths(managed_paths, scope),
714
+ load_state_links(managed_links, scope),
715
+ )
723
716
  )
724
717
  for a in agent_actions:
725
718
  _prepare_workspace_action(
@@ -794,18 +787,17 @@ class SyncPlanner:
794
787
 
795
788
  if skill_sources:
796
789
  scope = f"ws:{svc.app_id.value}:repo_skills_dir"
797
- plan_skill_actions = getattr(
798
- repo_target_service, "plan_skill_actions"
799
- )
800
- skill_actions, desired_paths, skill_skipped = plan_skill_actions(
801
- skill_sources,
802
- _workspace_skills_dir(
803
- svc.app_id, repo_target_service.repository.root
804
- ),
805
- scope,
806
- "workspace",
807
- load_state_paths(managed_paths, scope),
808
- load_state_links(managed_links, scope),
790
+ skill_actions, desired_paths, skill_skipped = (
791
+ repo_target_service.plan_skill_actions(
792
+ skill_sources,
793
+ _workspace_skills_dir(
794
+ svc.app_id, repo_target_service.repository.root
795
+ ),
796
+ scope,
797
+ "workspace",
798
+ load_state_paths(managed_paths, scope),
799
+ load_state_links(managed_links, scope),
800
+ )
809
801
  )
810
802
  for a in skill_actions:
811
803
  _prepare_workspace_action(
@@ -820,16 +812,15 @@ class SyncPlanner:
820
812
 
821
813
  if agent_sources and meta.supports_import_agents:
822
814
  scope = f"ws:{svc.app_id.value}:repo_agents_dir"
823
- plan_agent_actions = getattr(
824
- repo_target_service, "plan_agent_actions"
825
- )
826
- agent_actions, desired_paths, agent_skipped = plan_agent_actions(
827
- agent_sources,
828
- getattr(repo_target_service.repository, "agents_dir"),
829
- scope,
830
- "workspace",
831
- load_state_paths(managed_paths, scope),
832
- load_state_links(managed_links, scope),
815
+ agent_actions, desired_paths, agent_skipped = (
816
+ repo_target_service.plan_agent_actions(
817
+ agent_sources,
818
+ repo_target_service.repository.agents_dir,
819
+ scope,
820
+ "workspace",
821
+ load_state_paths(managed_paths, scope),
822
+ load_state_links(managed_links, scope),
823
+ )
833
824
  )
834
825
  for a in agent_actions:
835
826
  _prepare_workspace_action(
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  from pathlib import Path
4
+ from typing import TYPE_CHECKING
4
5
 
5
6
  from code_agnostic.apps.app_id import AppId
6
7
  from code_agnostic.constants import (
@@ -13,12 +14,15 @@ from code_agnostic.constants import (
13
14
  SKILLS_DIRNAME,
14
15
  )
15
16
 
17
+ if TYPE_CHECKING:
18
+ from code_agnostic.core.repository import CoreRepository
16
19
 
17
- def load_project_entries(core) -> list[dict[str, str]]:
20
+
21
+ def load_project_entries(core: CoreRepository) -> list[dict[str, str]]:
18
22
  return core.load_projects()
19
23
 
20
24
 
21
- def project_config_dir(core, name: str) -> Path:
25
+ def project_config_dir(core: CoreRepository, name: str) -> Path:
22
26
  return core.project_config_dir(name)
23
27
 
24
28
 
@@ -3,6 +3,7 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  from abc import ABC, abstractmethod
6
+ from typing import Any
6
7
 
7
8
  import yaml
8
9
 
@@ -20,7 +21,7 @@ class CursorRuleCompiler(IRuleCompiler):
20
21
 
21
22
  def compile(self, rule: Rule) -> tuple[str, str]:
22
23
  filename = f"{rule.name}.mdc"
23
- fm: dict = {}
24
+ fm: dict[str, Any] = {}
24
25
  if rule.metadata.description:
25
26
  fm["description"] = rule.metadata.description
26
27
  if rule.metadata.globs: