modwire 9.1.0__tar.gz → 9.2.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 (363) hide show
  1. {modwire-9.1.0 → modwire-9.2.0}/.dev/modwire.egg-info/SOURCES.txt +2 -0
  2. {modwire-9.1.0 → modwire-9.2.0}/PKG-INFO +33 -1
  3. {modwire-9.1.0 → modwire-9.2.0}/README.md +32 -0
  4. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/application.py +51 -12
  5. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/application.py +67 -20
  6. modwire-9.2.0/src/modwire/cli/cache/models/cache_outcome.py +44 -0
  7. modwire-9.2.0/src/modwire/cli/cache/models/cached_result.py +29 -0
  8. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/facade.py +7 -6
  9. {modwire-9.1.0 → modwire-9.2.0}/tests/application/test_07_cache.py +88 -1
  10. {modwire-9.1.0 → modwire-9.2.0}/.github/workflows/ci.yml +0 -0
  11. {modwire-9.1.0 → modwire-9.2.0}/.github/workflows/release.yml +0 -0
  12. {modwire-9.1.0 → modwire-9.2.0}/.gitignore +0 -0
  13. {modwire-9.1.0 → modwire-9.2.0}/AGENTS.md +0 -0
  14. {modwire-9.1.0 → modwire-9.2.0}/LICENSE +0 -0
  15. {modwire-9.1.0 → modwire-9.2.0}/MANIFEST.in +0 -0
  16. {modwire-9.1.0 → modwire-9.2.0}/Makefile +0 -0
  17. {modwire-9.1.0 → modwire-9.2.0}/docs/target-language-ownership.md +0 -0
  18. {modwire-9.1.0 → modwire-9.2.0}/pyproject.toml +0 -0
  19. {modwire-9.1.0 → modwire-9.2.0}/scripts/check_extractors.py +0 -0
  20. {modwire-9.1.0 → modwire-9.2.0}/scripts/generate_docs.py +0 -0
  21. {modwire-9.1.0 → modwire-9.2.0}/scripts/verify_consumer.py +0 -0
  22. {modwire-9.1.0 → modwire-9.2.0}/setup.cfg +0 -0
  23. {modwire-9.1.0 → modwire-9.2.0}/setup.py +0 -0
  24. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/__init__.py +0 -0
  25. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/__main__.py +0 -0
  26. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/__init__.py +0 -0
  27. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/__init__.py +0 -0
  28. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/application.py +0 -0
  29. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/domain.py +0 -0
  30. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/models/__init__.py +0 -0
  31. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/models/edge_rule_violation.py +0 -0
  32. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/models/flow_report.py +0 -0
  33. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/models/flow_violation.py +0 -0
  34. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/models/types.py +0 -0
  35. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/services/__init__.py +0 -0
  36. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/services/backward_flow_analyzer.py +0 -0
  37. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/services/boundaries_flow_analyzer.py +0 -0
  38. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/services/module_boundary_analyzer.py +0 -0
  39. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/services/no_cycles_flow_analyzer.py +0 -0
  40. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/boundaries/services/no_reentry_flow_analyzer.py +0 -0
  41. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/__init__.py +0 -0
  42. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/application.py +0 -0
  43. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/__init__.py +0 -0
  44. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/architecture_config.py +0 -0
  45. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/boundaries_config.py +0 -0
  46. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/boundary_rule.py +0 -0
  47. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/configuration_value.py +0 -0
  48. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/flow_realm.py +0 -0
  49. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/flow_rules.py +0 -0
  50. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/shape_config.py +0 -0
  51. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/shape_realm.py +0 -0
  52. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/shape_rules.py +0 -0
  53. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/config/models/tag_rule.py +0 -0
  54. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/facade.py +0 -0
  55. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/__init__.py +0 -0
  56. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/application.py +0 -0
  57. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/domain.py +0 -0
  58. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/__init__.py +0 -0
  59. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/callable_report_entry.py +0 -0
  60. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/callables_report.py +0 -0
  61. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/clusters_report.py +0 -0
  62. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/clusters_report_item.py +0 -0
  63. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/coherence_report.py +0 -0
  64. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/exports_report.py +0 -0
  65. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/exports_report_item.py +0 -0
  66. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/hotspots_report.py +0 -0
  67. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/hotspots_report_item.py +0 -0
  68. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/models/insight_report.py +0 -0
  69. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/services/__init__.py +0 -0
  70. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/services/callables_reporter.py +0 -0
  71. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/services/clusters_reporter.py +0 -0
  72. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/services/coherence_reporter.py +0 -0
  73. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/services/exports_reporter.py +0 -0
  74. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/services/hotspots_reporter.py +0 -0
  75. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/insights/services/insight_report_field_map.py +0 -0
  76. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/__init__.py +0 -0
  77. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/application.py +0 -0
  78. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/domain.py +0 -0
  79. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/models/__init__.py +0 -0
  80. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/models/architecture_map.py +0 -0
  81. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/models/architecture_realm.py +0 -0
  82. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/models/tag_map.py +0 -0
  83. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/models/tag_match.py +0 -0
  84. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/services/__init__.py +0 -0
  85. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/services/architecture_map_loader.py +0 -0
  86. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/map/services/tag_matcher.py +0 -0
  87. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/__init__.py +0 -0
  88. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/application.py +0 -0
  89. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/domain.py +0 -0
  90. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/__init__.py +0 -0
  91. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/architecture_group.py +0 -0
  92. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/map_report.py +0 -0
  93. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/report_catalog.py +0 -0
  94. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/report_descriptor.py +0 -0
  95. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/report_item.py +0 -0
  96. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/report_metadata.py +0 -0
  97. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/report_node.py +0 -0
  98. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/models/report_section.py +0 -0
  99. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/services/__init__.py +0 -0
  100. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/report/services/map_report_collector.py +0 -0
  101. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/__init__.py +0 -0
  102. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/application.py +0 -0
  103. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/domain.py +0 -0
  104. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/models/__init__.py +0 -0
  105. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/models/shape_realm_architecture_map.py +0 -0
  106. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/models/shape_report.py +0 -0
  107. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/models/shape_violation.py +0 -0
  108. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/__init__.py +0 -0
  109. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/abstract_class_resolver.py +0 -0
  110. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/callable_resolver.py +0 -0
  111. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/class_resolver.py +0 -0
  112. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/file_resolver.py +0 -0
  113. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/import_resolver.py +0 -0
  114. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/property_resolver.py +0 -0
  115. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/signature_resolver.py +0 -0
  116. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/architecture/shape/services/symbol_resolver.py +0 -0
  117. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/autowiring.py +0 -0
  118. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/__init__.py +0 -0
  119. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/__init__.py +0 -0
  120. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/domain.py +0 -0
  121. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/models/__init__.py +0 -0
  122. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/models/cache_entry.py +0 -0
  123. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/models/cache_key.py +0 -0
  124. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/models/cache_options.py +0 -0
  125. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/models/extraction_snapshot.py +0 -0
  126. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/models/source_entry.py +0 -0
  127. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/models/source_inventory.py +0 -0
  128. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/services/__init__.py +0 -0
  129. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/services/cache_codec.py +0 -0
  130. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/services/cache_identity.py +0 -0
  131. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/cache/services/filesystem_cache_storage.py +0 -0
  132. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/documentation/__init__.py +0 -0
  133. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/documentation/application.py +0 -0
  134. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/documentation/services/__init__.py +0 -0
  135. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/documentation/services/documentation_generator.py +0 -0
  136. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/initialization/__init__.py +0 -0
  137. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/initialization/application.py +0 -0
  138. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/initialization/models/__init__.py +0 -0
  139. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/initialization/models/initialization_result.py +0 -0
  140. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/initialization/services/__init__.py +0 -0
  141. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/initialization/services/initialization_service.py +0 -0
  142. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/__init__.py +0 -0
  143. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/application.py +0 -0
  144. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/domain.py +0 -0
  145. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/models/__init__.py +0 -0
  146. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/models/command_request.py +0 -0
  147. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/models/extractor_batch_input.py +0 -0
  148. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/models/extractor_command_input.py +0 -0
  149. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/models/extractor_source_input.py +0 -0
  150. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/models/report_pipeline_context.py +0 -0
  151. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/models/scan_policy.py +0 -0
  152. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/__init__.py +0 -0
  153. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/batch_source_reader.py +0 -0
  154. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/callables_insight.py +0 -0
  155. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/clusters_insight.py +0 -0
  156. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/coherence_insight.py +0 -0
  157. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/command_line.py +0 -0
  158. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/configuration_loader.py +0 -0
  159. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/extractor_command.py +0 -0
  160. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/flow_violations.py +0 -0
  161. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/hotspots_insight.py +0 -0
  162. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/map_tree.py +0 -0
  163. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/output_console.py +0 -0
  164. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/shape_violations.py +0 -0
  165. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/success.py +0 -0
  166. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/unknown_files_warning.py +0 -0
  167. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/pipeline/services/unused_exports_insight.py +0 -0
  168. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/__init__.py +0 -0
  169. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/application.py +0 -0
  170. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/models/__init__.py +0 -0
  171. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/models/defaults.py +0 -0
  172. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/models/init_asset.py +0 -0
  173. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/templates/AGENTS.md +0 -0
  174. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/templates/ARCHITECTURE.md +0 -0
  175. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/templates/INDEX.md +0 -0
  176. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/templates/MODWIRE.md +0 -0
  177. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/templates/RULES.md +0 -0
  178. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/templates/TESTING.md +0 -0
  179. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/templates/WORKFLOW.md +0 -0
  180. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/cli/resources/templates/architecture.yaml +0 -0
  181. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/__init__.py +0 -0
  182. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/dependency/__init__.py +0 -0
  183. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/dependency/application.py +0 -0
  184. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/dependency/domain.py +0 -0
  185. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/dependency/services/__init__.py +0 -0
  186. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/dependency/services/graph_builder.py +0 -0
  187. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/dependency/services/import_resolver.py +0 -0
  188. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/dependency/services/suffix_index.py +0 -0
  189. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/__init__.py +0 -0
  190. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/application.py +0 -0
  191. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/domain.py +0 -0
  192. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/models/__init__.py +0 -0
  193. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/models/batch_config.py +0 -0
  194. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/models/extraction_request.py +0 -0
  195. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/models/extractor_resource.py +0 -0
  196. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/models/extractor_runtime.py +0 -0
  197. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/models/python_call_context.py +0 -0
  198. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/__init__.py +0 -0
  199. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/php/build.php +0 -0
  200. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/php/build.py +0 -0
  201. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/php/composer.json +0 -0
  202. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/php/composer.lock +0 -0
  203. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/php/script.php +0 -0
  204. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/php/script.src.php +0 -0
  205. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/python/__init__.py +0 -0
  206. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/python/script.py +0 -0
  207. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/typescript/build.mjs +0 -0
  208. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/typescript/build.py +0 -0
  209. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/typescript/package-lock.json +0 -0
  210. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/typescript/package.json +0 -0
  211. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/typescript/script.js +0 -0
  212. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/typescript/script.ts +0 -0
  213. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/resources/typescript/tsconfig.json +0 -0
  214. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/services/__init__.py +0 -0
  215. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/services/php_extractor.py +0 -0
  216. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/services/python_call_reader.py +0 -0
  217. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/services/python_extractor.py +0 -0
  218. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/services/python_syntax_parser.py +0 -0
  219. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/extractors/services/type_script_extractor.py +0 -0
  220. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/extraction/facade.py +0 -0
  221. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/py.typed +0 -0
  222. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/__init__.py +0 -0
  223. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/__init__.py +0 -0
  224. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/application.py +0 -0
  225. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/domain.py +0 -0
  226. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/__init__.py +0 -0
  227. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/code_map.py +0 -0
  228. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/code_package.py +0 -0
  229. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/dependency_edge_result.py +0 -0
  230. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/dependency_graph.py +0 -0
  231. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/dependency_node_result.py +0 -0
  232. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/duplicate_identity_error.py +0 -0
  233. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/edge.py +0 -0
  234. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/edge_resolution.py +0 -0
  235. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/identity.py +0 -0
  236. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/node.py +0 -0
  237. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/query_builder.py +0 -0
  238. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/query_types.py +0 -0
  239. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/queryable_code_map.py +0 -0
  240. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_abstract_class.py +0 -0
  241. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_call.py +0 -0
  242. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_callable.py +0 -0
  243. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_callable_symbol.py +0 -0
  244. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_class.py +0 -0
  245. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_class_method.py +0 -0
  246. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_class_property.py +0 -0
  247. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_export.py +0 -0
  248. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_extraction.py +0 -0
  249. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_file.py +0 -0
  250. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_file_result.py +0 -0
  251. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_function.py +0 -0
  252. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_import.py +0 -0
  253. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_imported_symbol.py +0 -0
  254. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_interface.py +0 -0
  255. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_item_result.py +0 -0
  256. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_parameter.py +0 -0
  257. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_signature.py +0 -0
  258. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_symbol.py +0 -0
  259. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_type.py +0 -0
  260. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/source_value.py +0 -0
  261. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/models/types.py +0 -0
  262. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/services/__init__.py +0 -0
  263. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/services/glob_path_matcher.py +0 -0
  264. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/code/services/identity_resolver.py +0 -0
  265. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/values/__init__.py +0 -0
  266. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/values/models/__init__.py +0 -0
  267. {modwire-9.1.0 → modwire-9.2.0}/src/modwire/shared/values/models/value_model.py +0 -0
  268. {modwire-9.1.0 → modwire-9.2.0}/tests/__init__.py +0 -0
  269. {modwire-9.1.0 → modwire-9.2.0}/tests/application/__init__.py +0 -0
  270. {modwire-9.1.0 → modwire-9.2.0}/tests/application/base_test.py +0 -0
  271. {modwire-9.1.0 → modwire-9.2.0}/tests/application/test_01_attacks.py +0 -0
  272. {modwire-9.1.0 → modwire-9.2.0}/tests/application/test_06_happy_path.py +0 -0
  273. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/__init__.py +0 -0
  274. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/base_test.py +0 -0
  275. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/boundaries/__init__.py +0 -0
  276. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/boundaries/base_test.py +0 -0
  277. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/boundaries/test_01_attacks.py +0 -0
  278. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/boundaries/test_02_invariants.py +0 -0
  279. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/boundaries/test_03_public_api.py +0 -0
  280. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/boundaries/test_04_paths.py +0 -0
  281. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/config/__init__.py +0 -0
  282. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/config/test_01_attacks.py +0 -0
  283. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/config/test_02_invariants.py +0 -0
  284. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/insights/__init__.py +0 -0
  285. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/insights/base_test.py +0 -0
  286. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/insights/test_02_invariants.py +0 -0
  287. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/map/__init__.py +0 -0
  288. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/map/test_02_patterns.py +0 -0
  289. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/report/__init__.py +0 -0
  290. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/report/test_02_invariants.py +0 -0
  291. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/shape/__init__.py +0 -0
  292. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/shape/base_test.py +0 -0
  293. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/shape/test_01_limits.py +0 -0
  294. {modwire-9.1.0 → modwire-9.2.0}/tests/architecture/shape/test_02_invariants.py +0 -0
  295. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/__init__.py +0 -0
  296. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/base_test.py +0 -0
  297. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/documentation/__init__.py +0 -0
  298. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/documentation/test_02_invariants.py +0 -0
  299. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/initialization/__init__.py +0 -0
  300. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/initialization/test_01_attacks.py +0 -0
  301. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/initialization/test_02_invariants.py +0 -0
  302. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/initialization/test_03_interruption.py +0 -0
  303. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/initialization/test_04_cleanup.py +0 -0
  304. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/initialization/test_05_recovery.py +0 -0
  305. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/pipeline/__init__.py +0 -0
  306. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/pipeline/base_test.py +0 -0
  307. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/pipeline/test_01_attacks.py +0 -0
  308. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/pipeline/test_02_invariants.py +0 -0
  309. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/pipeline/test_03_interruption.py +0 -0
  310. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/pipeline/test_04_command_transport.py +0 -0
  311. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/pipeline/test_05_recovery.py +0 -0
  312. {modwire-9.1.0 → modwire-9.2.0}/tests/cli/pipeline/test_06_happy_path.py +0 -0
  313. {modwire-9.1.0 → modwire-9.2.0}/tests/conftest.py +0 -0
  314. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/__init__.py +0 -0
  315. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/base_test.py +0 -0
  316. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/big_projects/__init__.py +0 -0
  317. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/big_projects/project.py +0 -0
  318. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/big_projects/projects.json +0 -0
  319. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/big_projects/resolution_results.json +0 -0
  320. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/big_projects/results.json +0 -0
  321. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/big_projects/run.py +0 -0
  322. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/cache_benchmark/__init__.py +0 -0
  323. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/cache_benchmark/run.py +0 -0
  324. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/dependency/__init__.py +0 -0
  325. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/dependency/test_02_invariants.py +0 -0
  326. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/extractors/__init__.py +0 -0
  327. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/extractors/test_01_attacks.py +0 -0
  328. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/extractors/test_02_invariants.py +0 -0
  329. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/extractors/test_03_native_symbols.py +0 -0
  330. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/scan_benchmark/__init__.py +0 -0
  331. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/scan_benchmark/prepare.py +0 -0
  332. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/scan_benchmark/results.json +0 -0
  333. {modwire-9.1.0 → modwire-9.2.0}/tests/extraction/scan_benchmark/run.py +0 -0
  334. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/php/ignored/example_generated.php +0 -0
  335. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/php/src/example_application/example_actions/example_action.php +0 -0
  336. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/php/src/example_domain/example_model/example_record.php +0 -0
  337. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/php/src/example_domain/example_services/example_policy.php +0 -0
  338. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/php/src/example_interfaces/example_http/example_controller.php +0 -0
  339. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/python/ignored/example_generated.py +0 -0
  340. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/python/src/example_application/example_actions/example_action.py +0 -0
  341. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/python/src/example_domain/example_model/example_record.py +0 -0
  342. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/python/src/example_domain/example_services/example_policy.py +0 -0
  343. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/python/src/example_interfaces/example_http/example_controller.py +0 -0
  344. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/ignored/example_generated.ts +0 -0
  345. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/src/example_application/example_actions/example_action.ts +0 -0
  346. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/src/example_domain/example_model/example_record.ts +0 -0
  347. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/src/example_domain/example_model/example_view.tsx +0 -0
  348. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_audit.js +0 -0
  349. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_callables.ts +0 -0
  350. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/src/example_domain/example_services/example_policy.ts +0 -0
  351. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/src/example_interfaces/example_http/example_controller.ts +0 -0
  352. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/languages/typescript/src/example_interfaces/example_http/example_view.jsx +0 -0
  353. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/syntax/php/example_shapes.php +0 -0
  354. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/syntax/python/example_shapes.py +0 -0
  355. {modwire-9.1.0 → modwire-9.2.0}/tests/fixtures/syntax/typescript/example_shapes.ts +0 -0
  356. {modwire-9.1.0 → modwire-9.2.0}/tests/shared/__init__.py +0 -0
  357. {modwire-9.1.0 → modwire-9.2.0}/tests/shared/code/__init__.py +0 -0
  358. {modwire-9.1.0 → modwire-9.2.0}/tests/shared/code/test_02_invariants.py +0 -0
  359. {modwire-9.1.0 → modwire-9.2.0}/tests/support/__init__.py +0 -0
  360. {modwire-9.1.0 → modwire-9.2.0}/tests/support/base_test.py +0 -0
  361. {modwire-9.1.0 → modwire-9.2.0}/tests/support/code_map.py +0 -0
  362. {modwire-9.1.0 → modwire-9.2.0}/tests/support/service_test.py +0 -0
  363. {modwire-9.1.0 → modwire-9.2.0}/uv.lock +0 -0
@@ -119,6 +119,8 @@ src/modwire/cli/cache/models/__init__.py
119
119
  src/modwire/cli/cache/models/cache_entry.py
120
120
  src/modwire/cli/cache/models/cache_key.py
121
121
  src/modwire/cli/cache/models/cache_options.py
122
+ src/modwire/cli/cache/models/cache_outcome.py
123
+ src/modwire/cli/cache/models/cached_result.py
122
124
  src/modwire/cli/cache/models/extraction_snapshot.py
123
125
  src/modwire/cli/cache/models/source_entry.py
124
126
  src/modwire/cli/cache/models/source_inventory.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: modwire
3
- Version: 9.1.0
3
+ Version: 9.2.0
4
4
  Summary: Code extraction, architecture analysis and the Modwire CLI.
5
5
  Author: Tomasz Szpak
6
6
  License-Expression: MIT
@@ -52,6 +52,10 @@ Analyze a code map with a validated architecture configuration.
52
52
 
53
53
  Analyze a code map, reusing reports for an exact map and configuration identity.
54
54
 
55
+ ### `analyze_cached_with_diagnostics`
56
+
57
+ Analyze a code map and report the public outcome of report-cache reuse.
58
+
55
59
  ### `discover`
56
60
 
57
61
  Discover supported source languages beneath a root using the caller's scan policy.
@@ -72,10 +76,18 @@ Extract source files and return a queryable code map.
72
76
 
73
77
  Return a code map with content-addressed source and complete-manifest reuse.
74
78
 
79
+ ### `generate_map_cached_with_diagnostics`
80
+
81
+ Return a code map and public outcomes for extraction and complete-map reuse.
82
+
75
83
  ### `generate_queryable_map_cached`
76
84
 
77
85
  Return a queryable code map with content-addressed persistent reuse.
78
86
 
87
+ ### `generate_queryable_map_cached_with_diagnostics`
88
+
89
+ Return a queryable code map and public outcomes for every applicable cache stage.
90
+
79
91
  ### `clear_cache`
80
92
 
81
93
  Clear only the Modwire-owned directory for one cache namespace.
@@ -100,6 +112,26 @@ Run the native extractor transport for one supported language.
100
112
 
101
113
  Run the Modwire command line interface and return its process status.
102
114
 
115
+ ## `CacheStage`
116
+
117
+ Public stages reported by cached Modwire operations.
118
+
119
+ ## `CacheOutcome`
120
+
121
+ Content-safe lifecycle counts for one stage of a cached operation.
122
+
123
+ Extraction counts describe current source records. Code-map and report counts
124
+ describe one entry. Invalidated entries are also misses. Diagnostics include
125
+ the configured namespace but never cache keys, source identities, or content.
126
+
127
+ ## `CachedResult`
128
+
129
+ A cached operation value together with one outcome per applicable stage.
130
+
131
+ ### `outcome`
132
+
133
+ Return the outcome for one applicable cache stage.
134
+
103
135
  ## `CacheOptions`
104
136
 
105
137
  Generic persistent-cache settings supplied by a caller.
@@ -24,6 +24,10 @@ Analyze a code map with a validated architecture configuration.
24
24
 
25
25
  Analyze a code map, reusing reports for an exact map and configuration identity.
26
26
 
27
+ ### `analyze_cached_with_diagnostics`
28
+
29
+ Analyze a code map and report the public outcome of report-cache reuse.
30
+
27
31
  ### `discover`
28
32
 
29
33
  Discover supported source languages beneath a root using the caller's scan policy.
@@ -44,10 +48,18 @@ Extract source files and return a queryable code map.
44
48
 
45
49
  Return a code map with content-addressed source and complete-manifest reuse.
46
50
 
51
+ ### `generate_map_cached_with_diagnostics`
52
+
53
+ Return a code map and public outcomes for extraction and complete-map reuse.
54
+
47
55
  ### `generate_queryable_map_cached`
48
56
 
49
57
  Return a queryable code map with content-addressed persistent reuse.
50
58
 
59
+ ### `generate_queryable_map_cached_with_diagnostics`
60
+
61
+ Return a queryable code map and public outcomes for every applicable cache stage.
62
+
51
63
  ### `clear_cache`
52
64
 
53
65
  Clear only the Modwire-owned directory for one cache namespace.
@@ -72,6 +84,26 @@ Run the native extractor transport for one supported language.
72
84
 
73
85
  Run the Modwire command line interface and return its process status.
74
86
 
87
+ ## `CacheStage`
88
+
89
+ Public stages reported by cached Modwire operations.
90
+
91
+ ## `CacheOutcome`
92
+
93
+ Content-safe lifecycle counts for one stage of a cached operation.
94
+
95
+ Extraction counts describe current source records. Code-map and report counts
96
+ describe one entry. Invalidated entries are also misses. Diagnostics include
97
+ the configured namespace but never cache keys, source identities, or content.
98
+
99
+ ## `CachedResult`
100
+
101
+ A cached operation value together with one outcome per applicable stage.
102
+
103
+ ### `outcome`
104
+
105
+ Return the outcome for one applicable cache stage.
106
+
75
107
  ## `CacheOptions`
76
108
 
77
109
  Generic persistent-cache settings supplied by a caller.
@@ -11,13 +11,24 @@ from .architecture.facade import ArchitectureFacade
11
11
  from .architecture.report.models.report_catalog import ReportCatalog
12
12
  from .architecture.report.models.report_node import ReportNode
13
13
  from .cli.cache.models.cache_options import CacheOptions
14
+ from .cli.cache.models.cache_outcome import CacheOutcome, CacheStage
15
+ from .cli.cache.models.cached_result import CachedResult
14
16
  from .cli.facade import CliFacade
15
17
  from .cli.pipeline.models.scan_policy import ScanPolicy
16
18
  from .extraction.facade import ExtractionFacade
17
19
  from .shared.code.models.code_map import CodeMap
18
20
  from .shared.code.models.queryable_code_map import QueryableCodeMap
19
21
 
20
- __all__ = ["CacheOptions", "CodeMap", "ModwireApplication", "QueryableCodeMap", "ScanPolicy"]
22
+ __all__ = [
23
+ "CacheOptions",
24
+ "CacheOutcome",
25
+ "CacheStage",
26
+ "CachedResult",
27
+ "CodeMap",
28
+ "ModwireApplication",
29
+ "QueryableCodeMap",
30
+ "ScanPolicy",
31
+ ]
21
32
 
22
33
 
23
34
  @dataclass(frozen=True)
@@ -62,12 +73,20 @@ class ModwireApplication:
62
73
  ) -> tuple[ReportNode, ...]:
63
74
  """Analyze a code map, reusing reports for an exact map and configuration identity."""
64
75
 
76
+ return self.analyze_cached_with_diagnostics(code_map, config, options).value
77
+
78
+ def analyze_cached_with_diagnostics(
79
+ self, code_map: QueryableCodeMap, config: ArchitectureConfig, options: CacheOptions
80
+ ) -> CachedResult[tuple[ReportNode, ...]]:
81
+ """Analyze a code map and report the public outcome of report-cache reuse."""
82
+
65
83
  cached = self.cli.cached_reports(code_map.code_map, config, options)
66
- if cached is not None:
67
- return cached
84
+ if cached.value is not None:
85
+ return CachedResult(value=cached.value, outcomes=cached.outcomes)
68
86
  reports = self.architecture.analyze(code_map, config)
69
87
  self.cli.store_reports(code_map.code_map, config, reports, options)
70
- return reports
88
+ outcome = cached.outcome(CacheStage.REPORTS).model_copy(update={"computed": 1, "stored": 1})
89
+ return CachedResult(value=reports, outcomes=(outcome,))
71
90
 
72
91
  def discover(self, root: str, policy: ScanPolicy) -> tuple[str, ...]:
73
92
  """Discover supported source languages beneath a root using the caller's scan policy."""
@@ -97,21 +116,39 @@ class ModwireApplication:
97
116
  def generate_map_cached(self, language: str, root: str, policy: ScanPolicy, options: CacheOptions) -> CodeMap:
98
117
  """Return a code map with content-addressed source and complete-manifest reuse."""
99
118
 
119
+ return self.generate_map_cached_with_diagnostics(language, root, policy, options).value
120
+
121
+ def generate_map_cached_with_diagnostics(
122
+ self, language: str, root: str, policy: ScanPolicy, options: CacheOptions
123
+ ) -> CachedResult[CodeMap]:
124
+ """Return a code map and public outcomes for extraction and complete-map reuse."""
125
+
100
126
  request = self.extraction.request(language, str(root))
101
127
  snapshot = self.cli.extract_cached(request, policy, options)
102
- cached = self.cli.cached_code_map(snapshot, options)
103
- if cached is not None:
104
- return cached
105
- code_map = self.extraction.generate_map(language, snapshot.extraction)
106
- self.cli.store_code_map(snapshot, code_map, options)
107
- return code_map
128
+ cached = self.cli.cached_code_map(snapshot.value, options)
129
+ outcome = cached.outcome(CacheStage.CODE_MAP)
130
+ if cached.value is not None:
131
+ code_map = cached.value
132
+ else:
133
+ code_map = self.extraction.generate_map(language, snapshot.value.extraction)
134
+ self.cli.store_code_map(snapshot.value, code_map, options)
135
+ outcome = outcome.model_copy(update={"computed": 1, "stored": 1})
136
+ return CachedResult(value=code_map, outcomes=(*snapshot.outcomes, outcome))
108
137
 
109
138
  def generate_queryable_map_cached(
110
139
  self, language: str, root: str, policy: ScanPolicy, options: CacheOptions
111
140
  ) -> QueryableCodeMap:
112
141
  """Return a queryable code map with content-addressed persistent reuse."""
113
142
 
114
- return QueryableCodeMap(code_map=self.generate_map_cached(language, root, policy, options))
143
+ return self.generate_queryable_map_cached_with_diagnostics(language, root, policy, options).value
144
+
145
+ def generate_queryable_map_cached_with_diagnostics(
146
+ self, language: str, root: str, policy: ScanPolicy, options: CacheOptions
147
+ ) -> CachedResult[QueryableCodeMap]:
148
+ """Return a queryable code map and public outcomes for every applicable cache stage."""
149
+
150
+ cached = self.generate_map_cached_with_diagnostics(language, root, policy, options)
151
+ return CachedResult(value=QueryableCodeMap(code_map=cached.value), outcomes=cached.outcomes)
115
152
 
116
153
  def clear_cache(self, options: CacheOptions) -> None:
117
154
  """Clear only the Modwire-owned directory for one cache namespace."""
@@ -131,7 +168,9 @@ class ModwireApplication:
131
168
  def generate_documentation(self, readme: str, check: bool) -> int:
132
169
  """Generate this README from the published interface docstrings, or check that it is current."""
133
170
 
134
- return self.cli.generate_documentation(str(readme), (type(self), CacheOptions, ScanPolicy), check)
171
+ return self.cli.generate_documentation(
172
+ str(readme), (type(self), CacheStage, CacheOutcome, CachedResult, CacheOptions, ScanPolicy), check
173
+ )
135
174
 
136
175
  def run_extractor(self, language: str) -> int:
137
176
  """Run the native extractor transport for one supported language."""
@@ -18,11 +18,19 @@ from ..pipeline.models.scan_policy import ScanPolicy
18
18
  from .domain import CacheStorage
19
19
  from .models.cache_key import CacheKey
20
20
  from .models.cache_options import CacheOptions
21
+ from .models.cache_outcome import CacheOutcome, CacheStage
22
+ from .models.cached_result import CachedResult
21
23
  from .models.extraction_snapshot import ExtractionSnapshot
22
24
  from .services.cache_codec import CacheCodec
23
25
  from .services.cache_identity import CacheIdentity
24
26
 
25
27
 
28
+ @dataclass(frozen=True)
29
+ class _CacheRead:
30
+ value: object | None
31
+ invalidated: bool
32
+
33
+
26
34
  @injectable
27
35
  @dataclass(frozen=True)
28
36
  class CacheApplication:
@@ -40,21 +48,26 @@ class CacheApplication:
40
48
 
41
49
  def extract_cached(
42
50
  self, request: ExtractionRequest, policy: ScanPolicy, options: CacheOptions
43
- ) -> ExtractionSnapshot:
51
+ ) -> CachedResult[ExtractionSnapshot]:
44
52
  inventory = self.reader.inventory(request, policy)
45
53
  keys = {entry.source_id: self.identity.source(request, policy, entry) for entry in inventory.entries}
46
54
  files: dict[FileId, SourceFile] = {}
47
55
  misses: list[FileId] = []
56
+ hits = 0
57
+ invalidated = 0
48
58
  for entry in inventory.entries:
49
59
  key = keys[entry.source_id]
50
- value = self._read(options, key)
60
+ cached = self._read(options, key)
51
61
  try:
52
- source_file = SourceFile.model_validate(value)
62
+ source_file = SourceFile.model_validate(cached.value)
53
63
  if source_file.file_id != entry.source_id:
54
64
  raise ValueError("Cached source identity does not match its key.")
55
65
  files[entry.source_id] = source_file
66
+ hits += 1
56
67
  except (TypeError, ValueError, ValidationError):
57
- self.storage.delete(options, key)
68
+ if cached.value is not None and not cached.invalidated:
69
+ self.storage.delete(options, key)
70
+ invalidated += int(cached.invalidated or cached.value is not None)
58
71
  misses.append(entry.source_id)
59
72
 
60
73
  if misses or not inventory.entries:
@@ -98,16 +111,38 @@ class CacheApplication:
98
111
  },
99
112
  )
100
113
  self.prune(options)
101
- return ExtractionSnapshot(extraction=extraction, manifest=manifest)
114
+ return CachedResult(
115
+ value=ExtractionSnapshot(extraction=extraction, manifest=manifest),
116
+ outcomes=(
117
+ CacheOutcome(
118
+ stage=CacheStage.EXTRACTION,
119
+ namespace=options.namespace,
120
+ hits=hits,
121
+ misses=len(misses),
122
+ invalidated=invalidated,
123
+ computed=len(misses),
124
+ stored=len(misses),
125
+ ),
126
+ ),
127
+ )
102
128
 
103
- def code_map(self, snapshot: ExtractionSnapshot, options: CacheOptions) -> CodeMap | None:
129
+ def code_map(self, snapshot: ExtractionSnapshot, options: CacheOptions) -> CachedResult[CodeMap | None]:
104
130
  key = self.identity.code_map("", snapshot.manifest)
105
- value = self._read(options, key)
131
+ cached = self._read(options, key)
106
132
  try:
107
- return CodeMap.model_validate(value)
133
+ value = CodeMap.model_validate(cached.value)
134
+ outcome = CacheOutcome(stage=CacheStage.CODE_MAP, namespace=options.namespace, hits=1)
108
135
  except (TypeError, ValueError, ValidationError):
109
- self.storage.delete(options, key)
110
- return None
136
+ if cached.value is not None and not cached.invalidated:
137
+ self.storage.delete(options, key)
138
+ value = None
139
+ outcome = CacheOutcome(
140
+ stage=CacheStage.CODE_MAP,
141
+ namespace=options.namespace,
142
+ misses=1,
143
+ invalidated=int(cached.invalidated or cached.value is not None),
144
+ )
145
+ return CachedResult[CodeMap | None](value=value, outcomes=(outcome,))
111
146
 
112
147
  def store_code_map(self, snapshot: ExtractionSnapshot, code_map: CodeMap, options: CacheOptions) -> None:
113
148
  self._write(options, self.identity.code_map("", snapshot.manifest), code_map.model_dump(mode="json"))
@@ -115,17 +150,28 @@ class CacheApplication:
115
150
 
116
151
  def reports(
117
152
  self, code_map: CodeMap, config: ArchitectureConfig, options: CacheOptions
118
- ) -> tuple[ReportNode, ...] | None:
153
+ ) -> CachedResult[tuple[ReportNode, ...] | None]:
119
154
  key = self.identity.reports(code_map, config)
120
- value = self._read(options, key)
155
+ cached = self._read(options, key)
156
+ cached_value: object | None = cached.value
157
+ invalidated = cached.invalidated or cached_value is not None
121
158
  try:
122
- if not isinstance(value, list):
159
+ if not isinstance(cached_value, list):
123
160
  raise ValueError("Cached reports must be a list.")
124
- reports = tuple(self._report(item) for item in cast(list[object], value))
125
- return tuple(sorted(reports, key=lambda item: (item.metadata.order, item.metadata.id)))
161
+ reports = tuple(self._report(item) for item in cast(list[object], cached_value))
162
+ value = tuple(sorted(reports, key=lambda item: (item.metadata.order, item.metadata.id)))
163
+ outcome = CacheOutcome(stage=CacheStage.REPORTS, namespace=options.namespace, hits=1)
126
164
  except (AttributeError, ImportError, KeyError, TypeError, ValueError, ValidationError):
127
- self.storage.delete(options, key)
128
- return None
165
+ if cached_value is not None and not cached.invalidated:
166
+ self.storage.delete(options, key)
167
+ value = None
168
+ outcome = CacheOutcome(
169
+ stage=CacheStage.REPORTS,
170
+ namespace=options.namespace,
171
+ misses=1,
172
+ invalidated=int(invalidated),
173
+ )
174
+ return CachedResult[tuple[ReportNode, ...] | None](value=value, outcomes=(outcome,))
129
175
 
130
176
  def store_reports(
131
177
  self,
@@ -156,14 +202,15 @@ class CacheApplication:
156
202
  self.storage.delete(options, entry.key)
157
203
  total -= entry.size
158
204
 
159
- def _read(self, options: CacheOptions, key: CacheKey) -> object | None:
205
+ def _read(self, options: CacheOptions, key: CacheKey) -> _CacheRead:
160
206
  payload = self.storage.read(options, key)
161
207
  if payload is None:
162
- return None
208
+ return _CacheRead(value=None, invalidated=False)
163
209
  value = self.codec.decode(key, payload)
164
210
  if value is None:
165
211
  self.storage.delete(options, key)
166
- return value
212
+ return _CacheRead(value=None, invalidated=True)
213
+ return _CacheRead(value=value, invalidated=False)
167
214
 
168
215
  def _write(self, options: CacheOptions, key: CacheKey, value: object) -> None:
169
216
  self.storage.write(options, key, self.codec.encode(key, value))
@@ -0,0 +1,44 @@
1
+ from enum import StrEnum
2
+
3
+ from pydantic import field_validator
4
+
5
+ from ....shared.values.models.value_model import ValueModel
6
+
7
+
8
+ class CacheStage(StrEnum):
9
+ """Public stages reported by cached Modwire operations."""
10
+
11
+ EXTRACTION = "extraction"
12
+ CODE_MAP = "code-map"
13
+ REPORTS = "reports"
14
+
15
+
16
+ class CacheOutcome(ValueModel):
17
+ """Content-safe lifecycle counts for one stage of a cached operation.
18
+
19
+ Extraction counts describe current source records. Code-map and report counts
20
+ describe one entry. Invalidated entries are also misses. Diagnostics include
21
+ the configured namespace but never cache keys, source identities, or content.
22
+ """
23
+
24
+ stage: CacheStage
25
+ namespace: str
26
+ hits: int = 0
27
+ misses: int = 0
28
+ invalidated: int = 0
29
+ computed: int = 0
30
+ stored: int = 0
31
+
32
+ @field_validator("namespace")
33
+ @classmethod
34
+ def _non_empty_namespace(cls, value: str) -> str:
35
+ if not value.strip():
36
+ raise ValueError("Cache outcome namespace must not be empty.")
37
+ return value
38
+
39
+ @field_validator("hits", "misses", "invalidated", "computed", "stored")
40
+ @classmethod
41
+ def _non_negative_count(cls, value: int) -> int:
42
+ if value < 0:
43
+ raise ValueError("Cache outcome counts must not be negative.")
44
+ return value
@@ -0,0 +1,29 @@
1
+ from pydantic import field_validator
2
+
3
+ from ....shared.values.models.value_model import ValueModel
4
+ from .cache_outcome import CacheOutcome, CacheStage
5
+
6
+
7
+ class CachedResult[Result](ValueModel):
8
+ """A cached operation value together with one outcome per applicable stage."""
9
+
10
+ value: Result
11
+ outcomes: tuple[CacheOutcome, ...]
12
+
13
+ @field_validator("outcomes")
14
+ @classmethod
15
+ def _unique_non_empty_stages(cls, value: tuple[CacheOutcome, ...]) -> tuple[CacheOutcome, ...]:
16
+ if not value:
17
+ raise ValueError("A cached result requires at least one cache outcome.")
18
+ stages = tuple(outcome.stage for outcome in value)
19
+ if len(stages) != len(set(stages)):
20
+ raise ValueError("A cached result must contain at most one outcome per stage.")
21
+ return value
22
+
23
+ def outcome(self, stage: CacheStage) -> CacheOutcome:
24
+ """Return the outcome for one applicable cache stage."""
25
+
26
+ for outcome in self.outcomes:
27
+ if outcome.stage == stage:
28
+ return outcome
29
+ raise LookupError(f"Cache stage is not applicable to this result: {stage}")
@@ -14,6 +14,7 @@ from ..shared.code.models.queryable_code_map import QueryableCodeMap
14
14
  from ..shared.code.models.source_extraction import SourceExtraction
15
15
  from .cache.application import CacheApplication
16
16
  from .cache.models.cache_options import CacheOptions
17
+ from .cache.models.cached_result import CachedResult
17
18
  from .cache.models.extraction_snapshot import ExtractionSnapshot
18
19
  from .documentation.application import DocumentationApplication
19
20
  from .initialization.application import InitializationApplication
@@ -53,10 +54,10 @@ class CliFacade:
53
54
 
54
55
  def extract_cached(
55
56
  self, request: ExtractionRequest, policy: ScanPolicy, options: CacheOptions
56
- ) -> ExtractionSnapshot:
57
+ ) -> CachedResult[ExtractionSnapshot]:
57
58
  return self.cache.extract_cached(request, policy, options)
58
59
 
59
- def cached_code_map(self, snapshot: ExtractionSnapshot, options: CacheOptions) -> CodeMap | None:
60
+ def cached_code_map(self, snapshot: ExtractionSnapshot, options: CacheOptions) -> CachedResult[CodeMap | None]:
60
61
  return self.cache.code_map(snapshot, options)
61
62
 
62
63
  def store_code_map(self, snapshot: ExtractionSnapshot, code_map: CodeMap, options: CacheOptions) -> None:
@@ -64,7 +65,7 @@ class CliFacade:
64
65
 
65
66
  def cached_reports(
66
67
  self, code_map: CodeMap, config: ArchitectureConfig, options: CacheOptions
67
- ) -> tuple[ReportNode, ...] | None:
68
+ ) -> CachedResult[tuple[ReportNode, ...] | None]:
68
69
  return self.cache.reports(code_map, config, options)
69
70
 
70
71
  def store_reports(
@@ -127,13 +128,13 @@ class CliFacade:
127
128
  extraction = self.extract(extraction_request, policy)
128
129
  code_map = self.extraction.generate_queryable_map(request.language, extraction)
129
130
  return self.render(self.architecture.analyze(code_map, config), request.summary)
130
- snapshot = self.extract_cached(extraction_request, policy, cache_options)
131
- cached_code_map = self.cached_code_map(snapshot, cache_options)
131
+ snapshot = self.extract_cached(extraction_request, policy, cache_options).value
132
+ cached_code_map = self.cached_code_map(snapshot, cache_options).value
132
133
  if cached_code_map is None:
133
134
  cached_code_map = self.extraction.generate_map(request.language, snapshot.extraction)
134
135
  self.store_code_map(snapshot, cached_code_map, cache_options)
135
136
  code_map = QueryableCodeMap(code_map=cached_code_map)
136
- reports = self.cached_reports(cached_code_map, config, cache_options)
137
+ reports = self.cached_reports(cached_code_map, config, cache_options).value
137
138
  if reports is None:
138
139
  reports = self.architecture.analyze(code_map, config)
139
140
  self.store_reports(cached_code_map, config, reports, cache_options)
@@ -1,11 +1,98 @@
1
1
  from concurrent.futures import ThreadPoolExecutor
2
2
 
3
- from modwire.application import CacheOptions
3
+ from modwire.application import CacheOptions, CacheStage
4
4
 
5
5
  from .base_test import ApplicationTestCase
6
6
 
7
7
 
8
8
  class TestPersistentCache(ApplicationTestCase):
9
+ def test_public_map_diagnostics_distinguish_cold_and_warm_cache_stages(self) -> None:
10
+ root = self.project({"src/example.py": "def example_function():\n return 1\n"})
11
+ options = self.cache_options("example-diagnostics")
12
+
13
+ cold = self.application.generate_map_cached_with_diagnostics("python", root, self.scan_policy(), options)
14
+ warm = self.application.generate_map_cached_with_diagnostics("python", root, self.scan_policy(), options)
15
+
16
+ assert cold.value == warm.value
17
+ assert cold.outcome(CacheStage.EXTRACTION).to_dict() == {
18
+ "stage": "extraction",
19
+ "namespace": "example-diagnostics",
20
+ "hits": 0,
21
+ "misses": 1,
22
+ "invalidated": 0,
23
+ "computed": 1,
24
+ "stored": 1,
25
+ }
26
+ assert cold.outcome(CacheStage.CODE_MAP).to_dict() == {
27
+ "stage": "code-map",
28
+ "namespace": "example-diagnostics",
29
+ "hits": 0,
30
+ "misses": 1,
31
+ "invalidated": 0,
32
+ "computed": 1,
33
+ "stored": 1,
34
+ }
35
+ assert warm.outcome(CacheStage.EXTRACTION).hits == 1
36
+ assert warm.outcome(CacheStage.EXTRACTION).misses == 0
37
+ assert warm.outcome(CacheStage.CODE_MAP).hits == 1
38
+ assert warm.outcome(CacheStage.CODE_MAP).misses == 0
39
+
40
+ def test_public_map_diagnostics_report_partial_source_reuse(self) -> None:
41
+ root = self.project(
42
+ {
43
+ "src/example_first.py": "def example_first():\n return 1\n",
44
+ "src/example_second.py": "def example_second():\n return 2\n",
45
+ }
46
+ )
47
+ options = self.cache_options("example-partial-diagnostics")
48
+ self.application.generate_map_cached_with_diagnostics("python", root, self.scan_policy(), options)
49
+ (root / "src/example_second.py").write_text("def example_changed():\n return 2\n", encoding="utf-8")
50
+
51
+ changed = self.application.generate_map_cached_with_diagnostics("python", root, self.scan_policy(), options)
52
+
53
+ extraction = changed.outcome(CacheStage.EXTRACTION)
54
+ code_map = changed.outcome(CacheStage.CODE_MAP)
55
+ assert (extraction.hits, extraction.misses, extraction.computed, extraction.stored) == (1, 1, 1, 1)
56
+ assert extraction.invalidated == 0
57
+ assert (code_map.hits, code_map.misses, code_map.computed, code_map.stored) == (0, 1, 1, 1)
58
+
59
+ def test_public_map_diagnostics_report_invalidated_entries(self) -> None:
60
+ root = self.project({"src/example.py": "class ExampleValue:\n pass\n"})
61
+ options = self.cache_options("example-invalidated-diagnostics")
62
+ expected = self.application.generate_map_cached_with_diagnostics("python", root, self.scan_policy(), options)
63
+ for path in (self.workspace / "cache").rglob("*.cache"):
64
+ path.write_bytes(b"not-a-cache-entry")
65
+
66
+ recovered = self.application.generate_map_cached_with_diagnostics("python", root, self.scan_policy(), options)
67
+
68
+ assert recovered.value == expected.value
69
+ assert recovered.outcome(CacheStage.EXTRACTION).invalidated == 1
70
+ assert recovered.outcome(CacheStage.EXTRACTION).misses == 1
71
+ assert recovered.outcome(CacheStage.CODE_MAP).invalidated == 1
72
+ assert recovered.outcome(CacheStage.CODE_MAP).misses == 1
73
+
74
+ def test_public_report_diagnostics_distinguish_cold_and_warm_results(self) -> None:
75
+ root = self.project({"src/example.py": "def example_function():\n return 1\n"})
76
+ options = self.cache_options("example-report-diagnostics")
77
+ code_map = self.application.generate_queryable_map_cached("python", root, self.scan_policy(), options)
78
+ config = self.example_configuration()
79
+
80
+ cold = self.application.analyze_cached_with_diagnostics(code_map, config, options)
81
+ warm = self.application.analyze_cached_with_diagnostics(code_map, config, options)
82
+
83
+ assert cold.value == warm.value
84
+ assert cold.outcome(CacheStage.REPORTS).to_dict() == {
85
+ "stage": "reports",
86
+ "namespace": "example-report-diagnostics",
87
+ "hits": 0,
88
+ "misses": 1,
89
+ "invalidated": 0,
90
+ "computed": 1,
91
+ "stored": 1,
92
+ }
93
+ assert warm.outcome(CacheStage.REPORTS).hits == 1
94
+ assert warm.outcome(CacheStage.REPORTS).misses == 0
95
+
9
96
  def test_warm_code_map_matches_the_uncached_public_result(self) -> None:
10
97
  root = self.project({"src/example.py": "def example_function():\n return 1\n"})
11
98
  options = self.cache_options("example-warm")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes