specsmith 0.17.1.dev684__tar.gz → 0.18.0.dev686__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 (359) hide show
  1. {specsmith-0.17.1.dev684/src/specsmith.egg-info → specsmith-0.18.0.dev686}/PKG-INFO +1 -1
  2. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/pyproject.toml +1 -1
  3. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/__init__.py +1 -1
  4. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/runner.py +5 -4
  5. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/auditor.py +8 -1
  6. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/cli.py +142 -171
  7. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/compliance/evidence.py +11 -7
  8. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/compliance/regulations.py +2 -1
  9. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/config.py +2 -2
  10. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/context_orchestrator.py +27 -8
  11. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/esdb_writer.py +184 -118
  12. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/governance_logic.py +14 -7
  13. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/phase.py +15 -24
  14. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/project_metrics.py +6 -0
  15. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/retrieval.py +49 -5
  16. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/session_store.py +7 -0
  17. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/sync.py +8 -0
  18. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/trace.py +89 -29
  19. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/wi_store.py +10 -0
  20. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686/src/specsmith.egg-info}/PKG-INFO +1 -1
  21. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith.egg-info/SOURCES.txt +5 -0
  22. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_cli.py +29 -3
  23. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_compliance.py +24 -18
  24. specsmith-0.18.0.dev686/tests/test_deprecation_registry.py +90 -0
  25. specsmith-0.18.0.dev686/tests/test_esdb_status_integrity.py +130 -0
  26. specsmith-0.18.0.dev686/tests/test_esdb_status_output.py +89 -0
  27. specsmith-0.18.0.dev686/tests/test_sqlite_parity.py +124 -0
  28. specsmith-0.18.0.dev686/tests/test_trace_vault_esdb.py +87 -0
  29. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/LICENSE +0 -0
  30. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/README.md +0 -0
  31. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/setup.cfg +0 -0
  32. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/__init__.py +0 -0
  33. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/belief.py +0 -0
  34. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/certainty.py +0 -0
  35. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/failure_graph.py +0 -0
  36. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/py.typed +0 -0
  37. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/recovery.py +0 -0
  38. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/session.py +0 -0
  39. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/stress_tester.py +0 -0
  40. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/epistemic/trace.py +0 -0
  41. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/__main__.py +0 -0
  42. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/__init__.py +0 -0
  43. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/broker.py +0 -0
  44. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/chat_runner.py +0 -0
  45. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/cleanup.py +0 -0
  46. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/context_seed.py +0 -0
  47. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/core.py +0 -0
  48. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/dispatch/__init__.py +0 -0
  49. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/dispatch/_status.py +0 -0
  50. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/dispatch/dag.py +0 -0
  51. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
  52. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/dispatch/events.py +0 -0
  53. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/dispatch/result.py +0 -0
  54. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/endpoints.py +0 -0
  55. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/events.py +0 -0
  56. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/execution_profiles.py +0 -0
  57. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/fallback.py +0 -0
  58. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/hf_leaderboard.py +0 -0
  59. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/hf_sync.py +0 -0
  60. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/indexer.py +0 -0
  61. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/llm_client.py +0 -0
  62. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/mcp.py +0 -0
  63. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/memory.py +0 -0
  64. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/model_intelligence.py +0 -0
  65. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/model_profiles.py +0 -0
  66. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/model_router.py +0 -0
  67. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/orchestrator.py +0 -0
  68. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/permissions.py +0 -0
  69. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/profiles.py +0 -0
  70. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/provider_registry.py +0 -0
  71. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/repl.py +0 -0
  72. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/router.py +0 -0
  73. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/rules.py +0 -0
  74. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/safety.py +0 -0
  75. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/spawner.py +0 -0
  76. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/suggester.py +0 -0
  77. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/teams.py +0 -0
  78. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/token_pricing.py +0 -0
  79. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/tools.py +0 -0
  80. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/verifier.py +0 -0
  81. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/agent/voice.py +0 -0
  82. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/approvals.py +0 -0
  83. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/architect.py +0 -0
  84. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/auth.py +0 -0
  85. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/block_export.py +0 -0
  86. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/channel.py +0 -0
  87. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/ci_manager.py +0 -0
  88. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/commands/__init__.py +0 -0
  89. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/commands/intelligence.py +0 -0
  90. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/commands/issues_policy.py +0 -0
  91. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/commands/reporting.py +0 -0
  92. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/compliance/__init__.py +0 -0
  93. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/compliance/_compat.py +0 -0
  94. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/compliance/checker.py +0 -0
  95. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/compliance/reporter.py +0 -0
  96. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/compressor.py +0 -0
  97. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/console_utils.py +0 -0
  98. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/context_window.py +0 -0
  99. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/credit_analyzer.py +0 -0
  100. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/credits.py +0 -0
  101. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/dashboard.py +0 -0
  102. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/__init__.py +0 -0
  103. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/base.py +0 -0
  104. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/citations.py +0 -0
  105. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/fpd.py +0 -0
  106. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/odp.py +0 -0
  107. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/patentsview.py +0 -0
  108. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/pfw.py +0 -0
  109. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/ppubs.py +0 -0
  110. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/datasources/ptab.py +0 -0
  111. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/differ.py +0 -0
  112. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/doctor.py +0 -0
  113. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/drive.py +0 -0
  114. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/editor.py +0 -0
  115. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/efficiency.py +0 -0
  116. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/epistemic/__init__.py +0 -0
  117. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/epistemic/belief.py +0 -0
  118. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/epistemic/certainty.py +0 -0
  119. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/epistemic/failure_graph.py +0 -0
  120. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/epistemic/recovery.py +0 -0
  121. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/epistemic/stress_tester.py +0 -0
  122. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/esdb/__init__.py +0 -0
  123. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/esdb/_license.py +0 -0
  124. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/esdb/bridge.py +0 -0
  125. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/esdb/sqlite_store.py +0 -0
  126. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/esdb_sweep.py +0 -0
  127. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/eval/__init__.py +0 -0
  128. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/eval/builtins.py +0 -0
  129. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/eval/runner.py +0 -0
  130. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/executor.py +0 -0
  131. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/exporter.py +0 -0
  132. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/governance_store.py +0 -0
  133. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/governance_yaml.py +0 -0
  134. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/governed_pr.py +0 -0
  135. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/__init__.py +0 -0
  136. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/app.py +0 -0
  137. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/main_window.py +0 -0
  138. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/session_tab.py +0 -0
  139. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/theme.py +0 -0
  140. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/widgets/__init__.py +0 -0
  141. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/widgets/chat_view.py +0 -0
  142. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/widgets/input_bar.py +0 -0
  143. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  144. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/widgets/token_meter.py +0 -0
  145. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  146. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/widgets/update_checker.py +0 -0
  147. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/gui/worker.py +0 -0
  148. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/history_search.py +0 -0
  149. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/importer.py +0 -0
  150. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/instinct.py +0 -0
  151. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/__init__.py +0 -0
  152. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/agent_skill.py +0 -0
  153. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/aider.py +0 -0
  154. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/base.py +0 -0
  155. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/claude_code.py +0 -0
  156. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/codity.py +0 -0
  157. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/copilot.py +0 -0
  158. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/cursor.py +0 -0
  159. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/gemini.py +0 -0
  160. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/integrations/windsurf.py +0 -0
  161. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/issue_reporter.py +0 -0
  162. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/languages.py +0 -0
  163. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/ledger.py +0 -0
  164. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/local_model.py +0 -0
  165. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/mcp_generator.py +0 -0
  166. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/mcp_server.py +0 -0
  167. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/__init__.py +0 -0
  168. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
  169. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m002_agents_slim.py +0 -0
  170. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m003_compliance_init.py +0 -0
  171. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
  172. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
  173. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m006_session_governance.py +0 -0
  174. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m007_yaml_first.py +0 -0
  175. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m008_esdb_full_coverage.py +0 -0
  176. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m009_esdb_first.py +0 -0
  177. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/m010_post_esdb_cleanup.py +0 -0
  178. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/migrations/runner.py +0 -0
  179. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/ollama_cmds.py +0 -0
  180. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/patent.py +0 -0
  181. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/paths.py +0 -0
  182. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/plugins.py +0 -0
  183. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/policy.py +0 -0
  184. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/profiles.py +0 -0
  185. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/quality_report.py +0 -0
  186. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/rate_limits.py +0 -0
  187. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/recover.py +0 -0
  188. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/releaser.py +0 -0
  189. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/requirements.py +0 -0
  190. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/requirements_parser.py +0 -0
  191. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/risk.py +0 -0
  192. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/safe_write.py +0 -0
  193. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/scaffolder.py +0 -0
  194. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/serve.py +0 -0
  195. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/session.py +0 -0
  196. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/session_init.py +0 -0
  197. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/__init__.py +0 -0
  198. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/ai_agents.py +0 -0
  199. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/cloud.py +0 -0
  200. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/corporate.py +0 -0
  201. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/cross_platform.py +0 -0
  202. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/data_engineering.py +0 -0
  203. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/devops.py +0 -0
  204. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/docs.py +0 -0
  205. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/embedded.py +0 -0
  206. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/governance.py +0 -0
  207. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/hardware.py +0 -0
  208. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/mobile.py +0 -0
  209. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/platform_engineering.py +0 -0
  210. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/productivity.py +0 -0
  211. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/software_engineering.py +0 -0
  212. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/specsmith_skills.py +0 -0
  213. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/ssh.py +0 -0
  214. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills/web_backend.py +0 -0
  215. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/skills_builder.py +0 -0
  216. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/agents.md.j2 +0 -0
  217. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  218. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  219. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  220. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  221. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  222. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  223. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  224. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/community/security.md.j2 +0 -0
  225. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  226. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  227. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  228. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  229. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  230. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/editorconfig.j2 +0 -0
  231. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/gitattributes.j2 +0 -0
  232. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/gitignore.j2 +0 -0
  233. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/go/go.mod.j2 +0 -0
  234. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/go/main.go.j2 +0 -0
  235. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  236. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  237. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  238. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  239. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  240. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
  241. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  242. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  243. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
  244. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  245. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  246. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/js/package.json.j2 +0 -0
  247. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/ledger.md.j2 +0 -0
  248. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/python/cli.py.j2 +0 -0
  249. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/python/init.py.j2 +0 -0
  250. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  251. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/readme.md.j2 +0 -0
  252. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  253. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  254. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  255. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  256. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  257. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  258. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  259. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  260. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  261. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/tool_installer.py +0 -0
  262. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/toolrules.py +0 -0
  263. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/tools.py +0 -0
  264. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/transcripts.py +0 -0
  265. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/updater.py +0 -0
  266. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/upgrader.py +0 -0
  267. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/validator.py +0 -0
  268. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/vcs/__init__.py +0 -0
  269. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/vcs/base.py +0 -0
  270. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/vcs/bitbucket.py +0 -0
  271. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/vcs/github.py +0 -0
  272. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/vcs/gitlab.py +0 -0
  273. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/vcs_commands.py +0 -0
  274. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/wireframes.py +0 -0
  275. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith/workspace.py +0 -0
  276. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith.egg-info/dependency_links.txt +0 -0
  277. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith.egg-info/entry_points.txt +0 -0
  278. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith.egg-info/requires.txt +0 -0
  279. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/src/specsmith.egg-info/top_level.txt +0 -0
  280. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_CMD_001.py +0 -0
  281. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_agent_profiles.py +0 -0
  282. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_agent_run_feedback.py +0 -0
  283. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_agent_runner_ready.py +0 -0
  284. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_ai_client.py +0 -0
  285. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_ai_intelligence.py +0 -0
  286. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_architect_interview.py +0 -0
  287. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_architect_v2.py +0 -0
  288. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_architecture.py +0 -0
  289. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_auditor.py +0 -0
  290. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_benchmark_harness.py +0 -0
  291. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_channel.py +0 -0
  292. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_chat_diff_decision.py +0 -0
  293. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_chat_runner_openai_compat.py +0 -0
  294. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_chat_stdin_protocol.py +0 -0
  295. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_cleanup_cmd.py +0 -0
  296. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_cli_regressions.py +0 -0
  297. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_cli_workflows_history_drive.py +0 -0
  298. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_compliance_governance.py +0 -0
  299. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_compressor.py +0 -0
  300. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_dispatch.py +0 -0
  301. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_dual_write.py +0 -0
  302. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_e2e_nexus.py +0 -0
  303. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_efficiency.py +0 -0
  304. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_endpoints_cli.py +0 -0
  305. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_endpoints_store.py +0 -0
  306. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_epistemic.py +0 -0
  307. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_esdb_backend_switch.py +0 -0
  308. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_esdb_enforcement.py +0 -0
  309. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_esdb_integration.py +0 -0
  310. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_esdb_license.py +0 -0
  311. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_esdb_sqlite.py +0 -0
  312. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_esdb_sweep.py +0 -0
  313. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_esdb_verify_chain_cli.py +0 -0
  314. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_esdb_writer.py +0 -0
  315. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_fallback_chain.py +0 -0
  316. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_golden_path.py +0 -0
  317. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_importer.py +0 -0
  318. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_init_modes.py +0 -0
  319. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_integrations.py +0 -0
  320. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_integrations_codity.py +0 -0
  321. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_intelligence.py +0 -0
  322. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_issue_policy_features.py +0 -0
  323. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_issue_reporter.py +0 -0
  324. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_issues_263_264.py +0 -0
  325. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_local_model.py +0 -0
  326. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_markdown_deprecation.py +0 -0
  327. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_mcp_client.py +0 -0
  328. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_mcp_server.py +0 -0
  329. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_migration_direction.py +0 -0
  330. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_model_router.py +0 -0
  331. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_new_modules.py +0 -0
  332. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_nexus.py +0 -0
  333. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_parallel_agents.py +0 -0
  334. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_permissions.py +0 -0
  335. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_phase1_4_new.py +0 -0
  336. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_phase34_completion.py +0 -0
  337. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_project_metrics.py +0 -0
  338. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_quality_report.py +0 -0
  339. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_rate_limits.py +0 -0
  340. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_repl.py +0 -0
  341. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_repl_extended.py +0 -0
  342. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_reporting_commands.py +0 -0
  343. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_req_248_262.py +0 -0
  344. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_req_358_359.py +0 -0
  345. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_resume_command.py +0 -0
  346. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_scaffolder.py +0 -0
  347. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_schema_migrations.py +0 -0
  348. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_skill_marketplace.py +0 -0
  349. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_skills_mcp.py +0 -0
  350. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_smoke.py +0 -0
  351. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_suggester.py +0 -0
  352. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_token_cost.py +0 -0
  353. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_tools.py +0 -0
  354. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_typing_guardrails.py +0 -0
  355. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_validator.py +0 -0
  356. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_vcs.py +0 -0
  357. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_warp_parity.py +0 -0
  358. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_warp_parity_followup.py +0 -0
  359. {specsmith-0.17.1.dev684 → specsmith-0.18.0.dev686}/tests/test_wi_lifecycle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.17.1.dev684
3
+ Version: 0.18.0.dev686
4
4
  Summary: AEE governance toolkit for AI-assisted development — session preflight gates, multi-agent dispatch, requirements↔test traceability, ESDB persistence, MCP server, and skills for Warp, Cursor, Claude Code, Copilot, Windsurf, and Aider.
5
5
  Author: Layer1Labs Silicon, Inc.
6
6
  License-Expression: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "specsmith"
7
- version = "0.17.1.dev684"
7
+ version = "0.18.0.dev686"
8
8
  description = "AEE governance toolkit for AI-assisted development — session preflight gates, multi-agent dispatch, requirements↔test traceability, ESDB persistence, MCP server, and skills for Warp, Cursor, Claude Code, Copilot, Windsurf, and Aider."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -8,4 +8,4 @@ from importlib.metadata import version as _pkg_version
8
8
  try:
9
9
  __version__: str = _pkg_version("specsmith")
10
10
  except PackageNotFoundError: # running from source without install
11
- __version__ = "0.17.1" # fallback: keep in sync with pyproject.toml
11
+ __version__ = "0.18.0" # fallback: keep in sync with pyproject.toml
@@ -798,10 +798,11 @@ class AgentRunner:
798
798
  def _seal_profile_pin(self, profile_id: str) -> None:
799
799
  """Append a TraceVault decision seal recording the ``/agent`` pin (G4).
800
800
 
801
- Wrapped in best-effort try/except so an unwriteable
802
- ``.specsmith/trace.jsonl`` (read-only fs, missing project root, etc.)
803
- never breaks the chat loop. The seal type is ``decision`` because
804
- a profile pin is an explicit governance choice the user made.
801
+ Wrapped in best-effort try/except so an unwriteable ESDB store
802
+ (read-only fs, missing project root, etc.) never breaks the chat loop.
803
+ The seal is persisted as an ESDB ``seal_record`` (REQ-420). The seal
804
+ type is ``decision`` because a profile pin is an explicit governance
805
+ choice the user made.
805
806
  """
806
807
  try:
807
808
  from specsmith.trace import SealType, TraceVault
@@ -930,7 +930,14 @@ def check_type_mismatch(root: Path) -> list[AuditResult]:
930
930
 
931
931
 
932
932
  def check_trace_chain_integrity(root: Path) -> list[AuditResult]:
933
- """Check trace vault chain integrity if it exists."""
933
+ """Check trace vault chain integrity if it exists.
934
+
935
+ DEPRECATED(REQ-421): this verifies the legacy ``epistemic.trace`` flat-file
936
+ vault (``.specsmith/trace.jsonl``). The current trace vault is ESDB-only
937
+ (``specsmith.trace``; REQ-420). Retained so legacy projects that still carry
938
+ a trace.jsonl keep getting an integrity signal; remove at teardown.
939
+ See docs/DEPRECATIONS.md.
940
+ """
934
941
  trace_path = root / ".specsmith" / "trace.jsonl"
935
942
  if not trace_path.exists():
936
943
  return [] # No trace vault configured — skip silently
@@ -771,174 +771,81 @@ def preflight_cmd(
771
771
  ) -> None:
772
772
  """Classify a natural-language utterance under Specsmith governance (REQ-085).
773
773
 
774
- Reads REQUIREMENTS.md and ``.repo-index/files.json`` from PROJECT-DIR,
775
- classifies intent (read-only ask / change / release / destructive),
776
- infers scope, and emits a JSON object describing the preflight decision.
777
- Read-only asks accept by default; destructive intents require
778
- clarification; changes with no matching scope return needs_clarification.
774
+ REQ-418: this command delegates to ``governance_logic.run_preflight`` so the
775
+ CLI decision matches the in-process broker explicit ``REQ-NNN`` references
776
+ and ``.specsmith/requirements.json`` are honored, the REQ-098 floor is applied
777
+ once, and the work item / ESDB ``preflight_decision`` record are persisted
778
+ (unless ``--predict-only``). The command then layers on presentation-only
779
+ extras (``predicted_refinement``, ``stress_warnings``, ``narration``) and the
780
+ REQ-093/099 LEDGER.md events, and exits 0/2/3 per the decision (REQ-092).
779
781
  """
780
782
  import json as _json
781
- import uuid
782
783
 
783
- from specsmith.agent.broker import (
784
- Intent,
785
- PreflightDecision,
786
- classify_intent,
787
- infer_scope,
788
- narrate_plan,
789
- )
784
+ from specsmith.governance_logic import run_preflight
790
785
 
791
786
  root = Path(project_dir).resolve()
792
- intent = classify_intent(utterance)
793
- scope = infer_scope(
787
+ # REQ-418: delegate the decision to the authoritative broker so explicit
788
+ # REQ-NNN ids and .specsmith/requirements.json drive the result. run_preflight
789
+ # also applies the REQ-098 floor, allocates/persists the work item (unless
790
+ # predict_only), writes the ESDB preflight_decision record, and attaches the
791
+ # ai_disclosure + REG-004 escalation fields. Do NOT re-apply the floor here.
792
+ payload = run_preflight(
794
793
  utterance,
795
- root / "REQUIREMENTS.md",
796
- repo_index_path=root / ".repo-index" / "files.json",
794
+ str(root),
795
+ predict_only=predict_only,
796
+ escalate_threshold=escalate_threshold,
797
797
  )
798
+ decision_str = str(payload.get("decision", ""))
799
+ work_item_id = str(payload.get("work_item_id", ""))
800
+ requirement_ids = list(payload.get("requirement_ids", []))
801
+ confidence_target = float(payload.get("confidence_target", 0.0))
798
802
 
799
- requirement_ids = [r.req_id for r in scope.matched_requirements]
800
-
801
- # REQ-088: resolve test_case_ids from machine state by joining
802
- # `requirement_ids` against `.specsmith/testcases.json` (or `TESTS.md`
803
- # when the JSON is unavailable). Never invent ids.
804
- test_case_ids: list[str] = []
805
- if requirement_ids:
806
- testcases_json = root / ".specsmith" / "testcases.json"
807
- if testcases_json.is_file():
808
- try:
809
- records = _json.loads(testcases_json.read_text(encoding="utf-8"))
810
- except (OSError, ValueError):
811
- records = []
812
- req_set = set(requirement_ids)
813
- for record in records:
814
- if (
815
- isinstance(record, dict)
816
- and record.get("requirement_id") in req_set
817
- and isinstance(record.get("id"), str)
818
- ):
819
- test_case_ids.append(record["id"])
820
- else:
821
- tests_md = root / "TESTS.md"
822
- if tests_md.is_file():
823
- import re as _re
824
-
825
- text = tests_md.read_text(encoding="utf-8")
826
- # Match each test block: a `TEST-NNN` id paired with a
827
- # `REQ-NNN` requirement-id reference within the same block.
828
- req_set = set(requirement_ids)
829
- for block in _re.split(r"\n## ", text):
830
- test_match = _re.search(r"\*\*ID:\*\*\s+(TEST-\d+)", block)
831
- req_match = _re.search(r"\*\*Requirement ID:\*\*\s+(REQ-\d+)", block)
832
- if test_match and req_match and req_match.group(1) in req_set:
833
- test_case_ids.append(test_match.group(1))
834
-
835
- # Heuristic decision policy. Specsmith governance owns the contract; the
836
- # CLI implementation is intentionally simple and deterministic so the
837
- # broker (and tests) can rely on it without an LLM.
838
- decision_str = "accepted"
839
- instruction = ""
840
- confidence_target = 0.7
841
-
842
- if intent == Intent.READ_ONLY_ASK:
843
- decision_str = "accepted"
844
- instruction = "Read-only ask; no governance changes required."
845
- elif intent == Intent.DESTRUCTIVE:
846
- decision_str = "needs_clarification"
847
- instruction = (
848
- "Destructive operation detected. "
849
- "Confirm explicitly which paths or resources should be removed."
850
- )
851
- confidence_target = 0.9
852
- elif intent == Intent.RELEASE:
853
- decision_str = "needs_clarification"
854
- instruction = (
855
- "Release operations require explicit confirmation. "
856
- "Specify the target version and channel."
857
- )
858
- confidence_target = 0.9
859
- else: # CHANGE
860
- if scope.is_known:
861
- decision_str = "accepted"
862
- instruction = (
863
- "Change request matched existing governance scope. Proceed under "
864
- "Specsmith verification."
865
- )
866
- confidence_target = max(0.7, scope.confidence)
867
- else:
868
- decision_str = "needs_clarification"
869
- instruction = (
870
- "This change does not match an existing requirement. "
871
- "Could you say in one sentence which behavior you expect?"
872
- )
873
- confidence_target = 0.7
874
-
875
- # REQ-098: respect epistemic.confidence_threshold from .specsmith/config.yml
876
- # as a floor for confidence_target (heuristic default still applies when
877
- # the configured value is lower or the file is missing).
878
- config_threshold = _read_confidence_threshold_floor(root)
879
- if config_threshold is not None and config_threshold > confidence_target:
880
- confidence_target = config_threshold
881
-
882
- work_item_id = f"WI-{uuid.uuid4().hex[:8].upper()}" if decision_str == "accepted" else ""
883
-
884
- # REQ-117: predict-only mode does not allocate a work_item_id and does
885
- # not write a ledger event; instead it adds a `predicted_refinement`
886
- # field for IDE autocomplete.
803
+ # REQ-117: predict-only adds a `predicted_refinement` hint for IDE autocomplete.
804
+ # run_preflight already withholds the work item and the ESDB/ledger writes here.
887
805
  if predict_only:
888
- work_item_id = ""
889
-
890
- payload = {
891
- "decision": decision_str,
892
- "work_item_id": work_item_id,
893
- "requirement_ids": requirement_ids,
894
- "test_case_ids": test_case_ids,
895
- "confidence_target": round(confidence_target, 3),
896
- "instruction": instruction,
897
- "intent": intent.value,
898
- }
899
- if predict_only:
900
- if not scope.is_known and intent == Intent.CHANGE:
806
+ if decision_str == "needs_clarification":
901
807
  payload["predicted_refinement"] = (
902
- f"{utterance} (please name the component or file you want to change)"
808
+ f"{utterance} (please name the component, file, or REQ id to change)"
903
809
  )
904
- elif intent == Intent.DESTRUCTIVE:
905
- payload["predicted_refinement"] = f"{utterance} (specify the exact paths or resources)"
906
810
  else:
907
811
  payload["predicted_refinement"] = utterance
908
812
 
909
- # REQ-100: optional stress-test bridge over matched requirements. The flag
910
- # defaults off so unrelated tests stay green.
911
- if stress and scope.matched_requirements:
912
- warnings = _stress_test_warnings(root, scope.matched_requirements)
913
- if warnings:
914
- payload["stress_warnings"] = warnings
915
-
916
- if verbose:
917
- decision_obj = PreflightDecision.from_json(payload)
918
- payload["narration"] = narrate_plan(intent, scope, decision_obj, verbose=True)
919
- if payload.get("stress_warnings"):
920
- payload["narration"] += "\nNote: stress-test surfaced one or more critical failures."
921
-
922
- # REG-009: AI disclosure metadata (FTC Operation AI Comply, Utah SB149 2024).
923
- # Every governed output must disclose the AI system producing it.
924
- import os as _os
925
-
926
- payload["ai_disclosure"] = {
927
- "governed_by": "specsmith",
928
- "governance_gated": True,
929
- "provider": _os.environ.get("SPECSMITH_PROVIDER", "local/heuristic"),
930
- "model": _os.environ.get("SPECSMITH_MODEL", "deterministic-broker"),
931
- "spec_version": __version__,
932
- }
813
+ # REQ-100 (--stress) and --verbose (narration) need the broker's scope/intent
814
+ # view. Re-derive it best-effort; failures never affect the decision payload.
815
+ if stress or verbose:
816
+ try:
817
+ from specsmith.agent.broker import (
818
+ PreflightDecision,
819
+ classify_intent,
820
+ infer_scope,
821
+ narrate_plan,
822
+ )
933
823
 
934
- # REG-004: human escalation — if a threshold is set and confidence < threshold,
935
- # surface an explicit escalation notice in the payload.
936
- if escalate_threshold is not None and confidence_target < escalate_threshold:
937
- payload["escalation_required"] = True
938
- payload["escalation_reason"] = (
939
- f"Confidence {confidence_target:.3f} is below escalation threshold "
940
- f"{escalate_threshold:.3f}. Human review required before execution."
941
- )
824
+ intent = classify_intent(utterance)
825
+ # Mirror run_preflight's requirements-path resolution (REQ-418 parity):
826
+ # prefer docs/REQUIREMENTS.md, fall back to the project-root file so the
827
+ # stress/verbose scope view matches the authoritative decision's scope.
828
+ req_md = root / "docs" / "REQUIREMENTS.md"
829
+ if not req_md.is_file():
830
+ req_md = root / "REQUIREMENTS.md"
831
+ scope = infer_scope(
832
+ utterance,
833
+ req_md,
834
+ repo_index_path=root / ".repo-index" / "files.json",
835
+ )
836
+ if stress and scope.matched_requirements:
837
+ warnings = _stress_test_warnings(root, scope.matched_requirements)
838
+ if warnings:
839
+ payload["stress_warnings"] = warnings
840
+ if verbose:
841
+ decision_obj = PreflightDecision.from_json(payload)
842
+ payload["narration"] = narrate_plan(intent, scope, decision_obj, verbose=True)
843
+ if payload.get("stress_warnings"):
844
+ payload["narration"] += (
845
+ "\nNote: stress-test surfaced one or more critical failures."
846
+ )
847
+ except Exception: # noqa: BLE001 - presentation extras are best-effort
848
+ pass
942
849
 
943
850
  # Bypass rich's renderer to keep the JSON intact (same pattern as clean).
944
851
  click.echo(_json.dumps(payload, indent=2))
@@ -11592,39 +11499,99 @@ def esdb_status_cmd(project_dir: str, as_json: bool) -> None:
11592
11499
  raise SystemExit(1)
11593
11500
  return
11594
11501
 
11595
- icon = "[green]\u25cf[/green]"
11596
- console.print(f"{icon} ESDB \u2014 {backend_label}")
11597
- console.print(f" Records: {record_count}")
11598
- for kind, count in counts.items():
11599
- console.print(f" {kind}: {count}")
11502
+ # REQ-417: report the actual chain-verification result, not a hardcoded label.
11503
+ integrity_label = "Integrity OK" if chain_ok else "Integrity FAILED"
11600
11504
  chain_icon = "[green]\u2714[/green]" if chain_ok else "[red]\u2717[/red]"
11601
- console.print(f" {chain_icon} Integrity OK")
11505
+
11506
+ # Issue #263 / REQ-419: build both a colored (Rich markup) and a plain ASCII
11507
+ # rendering. The Rich render is attempted first for healthy consoles; on the
11508
+ # Windows legacy console it can raise a spurious KeyboardInterrupt (which Click
11509
+ # turns into Abort/exit 1), so ANY failure falls back to a resilient plain-text
11510
+ # stdout writer that mirrors the --json branch and never aborts.
11511
+ markup_lines: list[str] = [
11512
+ f"[green]\u25cf[/green] ESDB \u2014 {backend_label}",
11513
+ f" Records: {record_count}",
11514
+ ]
11515
+ plain_lines: list[str] = [
11516
+ f"ESDB - {backend_label}",
11517
+ f" Records: {record_count}",
11518
+ ]
11519
+ for kind, count in counts.items():
11520
+ markup_lines.append(f" {kind}: {count}")
11521
+ plain_lines.append(f" {kind}: {count}")
11522
+ markup_lines.append(f" {chain_icon} {integrity_label}")
11523
+ plain_lines.append(f" {integrity_label}")
11602
11524
  if store_error:
11603
- console.print(f" [red]\u2717[/red] Store error: {store_error}")
11525
+ markup_lines.append(f" [red]\u2717[/red] Store error: {store_error}")
11526
+ plain_lines.append(f" Store error: {store_error}")
11604
11527
  # License line
11605
11528
  if not sys.modules["specsmith.esdb"].CHRONO_AVAILABLE:
11606
- console.print(
11529
+ markup_lines.append(
11607
11530
  " [dim]chronomemory not installed \u2014 run "
11608
11531
  "'pip install specsmith[esdb]' for ChronoStore[/dim]"
11609
11532
  )
11533
+ plain_lines.append(
11534
+ " chronomemory not installed - run 'pip install specsmith[esdb]' for ChronoStore"
11535
+ )
11610
11536
  elif lic_status and lic_status.valid:
11611
- console.print(
11537
+ markup_lines.append(
11612
11538
  f" [green]\u2714[/green] License: {lic_status.customer} "
11613
11539
  f"(expires {lic_status.expires_at})"
11614
11540
  )
11541
+ plain_lines.append(f" License: {lic_status.customer} (expires {lic_status.expires_at})")
11615
11542
  else:
11616
11543
  reason = lic_status.reason if lic_status else "no license file"
11617
- console.print(f" [yellow]\u26a0[/yellow] ESDB license: {reason}")
11618
- console.print(
11544
+ markup_lines.append(f" [yellow]\u26a0[/yellow] ESDB license: {reason}")
11545
+ markup_lines.append(
11619
11546
  " [dim]Use 'specsmith esdb enable --key-file <path>' to activate ChronoStore.[/dim]"
11620
11547
  )
11548
+ plain_lines.append(f" ESDB license: {reason}")
11549
+ plain_lines.append(
11550
+ " Use 'specsmith esdb enable --key-file <path>' to activate ChronoStore."
11551
+ )
11621
11552
  if auto_counts:
11622
- console.print(
11553
+ markup_lines.append(
11623
11554
  " [cyan]\u27f3[/cyan] Auto-migrated from legacy JSON: "
11624
11555
  f"{auto_counts.get('requirements', 0)} requirements + "
11625
11556
  f"{auto_counts.get('testcases', 0)} testcases "
11626
11557
  f"({auto_counts.get('skipped', 0)} skipped)"
11627
11558
  )
11559
+ plain_lines.append(
11560
+ " Auto-migrated from legacy JSON: "
11561
+ f"{auto_counts.get('requirements', 0)} requirements + "
11562
+ f"{auto_counts.get('testcases', 0)} testcases "
11563
+ f"({auto_counts.get('skipped', 0)} skipped)"
11564
+ )
11565
+
11566
+ def _emit_plain() -> None:
11567
+ """Resiliently write the plain-text status block (mirrors the --json branch)."""
11568
+ plain_text = "\n".join(plain_lines)
11569
+ try:
11570
+ sys.stdout.write(plain_text + "\n")
11571
+ sys.stdout.flush()
11572
+ except Exception as out_exc: # noqa: BLE001
11573
+ try:
11574
+ sys.stderr.write(
11575
+ _json.dumps(
11576
+ {
11577
+ "ok": False,
11578
+ "error": "esdb status: stdout write failed",
11579
+ "reason": str(out_exc),
11580
+ "backend": active_backend,
11581
+ "record_count": record_count,
11582
+ }
11583
+ )
11584
+ + "\n"
11585
+ )
11586
+ sys.stderr.flush()
11587
+ except Exception: # noqa: BLE001
11588
+ pass
11589
+ raise SystemExit(1) from out_exc
11590
+
11591
+ try:
11592
+ console.print("\n".join(markup_lines))
11593
+ except (KeyboardInterrupt, Exception): # noqa: BLE001
11594
+ _emit_plain()
11628
11595
 
11629
11596
 
11630
11597
  @esdb_group.command(name="verify-chain")
@@ -11888,12 +11855,13 @@ def esdb_migrate_cmd(project_dir: str, as_json: bool) -> None:
11888
11855
  @click.option("--project-dir", type=click.Path(exists=True), default=".")
11889
11856
  @click.option("--json", "as_json", is_flag=True, default=False)
11890
11857
  def esdb_replay_cmd(project_dir: str, as_json: bool) -> None:
11891
- """Replay the trace vault WAL and verify SHA-256 hash chain integrity.
11858
+ """Replay the trace vault and verify SHA-256 hash chain integrity.
11892
11859
 
11893
- Reads .specsmith/trace.jsonl and walks every seal entry, recomputing
11894
- each entry_hash from its stored content_hash + prev_hash and comparing
11895
- to the stored value. Any mismatch indicates tampering or corruption.
11896
- Also reports ledger.jsonl entry count as a secondary consistency signal.
11860
+ Reads seal records from the ESDB (``seal_record`` kind; REQ-420) and walks
11861
+ every seal entry, recomputing each entry_hash from its stored content_hash +
11862
+ prev_hash and comparing to the stored value. Any mismatch indicates tampering
11863
+ or corruption. Also reports ledger.jsonl entry count as a secondary
11864
+ consistency signal.
11897
11865
  """
11898
11866
  import json as _json
11899
11867
 
@@ -14002,9 +13970,12 @@ def resume_cmd(
14002
13970
  with contextlib.suppress(Exception):
14003
13971
  bridge = EsdbBridge(str(root))
14004
13972
  status = bridge.status()
13973
+ # REQ-417: the leading ESDB indicator must reflect the real chain state,
13974
+ # not a hardcoded green check.
14005
13975
  chain_icon = "\u2713" if status.chain_valid else "\u2717"
13976
+ chain_color = "green" if status.chain_valid else "red"
14006
13977
  console.print(
14007
- f" [green]\u2713[/green] ESDB: {status.backend} "
13978
+ f" [{chain_color}]{chain_icon}[/{chain_color}] ESDB: {status.backend} "
14008
13979
  f"({status.record_count} records, chain {chain_icon})"
14009
13980
  )
14010
13981
 
@@ -163,17 +163,21 @@ class EvidenceCollector:
163
163
  )
164
164
  )
165
165
 
166
- # Trace vault
167
- trace = self.root / ".specsmith" / "trace.jsonl"
166
+ # Trace vault (REQ-420: seals are ESDB ``seal_record`` entries, no
167
+ # longer a .specsmith/trace.jsonl flat file).
168
+ from specsmith.trace import count_seal_records
169
+
170
+ seal_count = count_seal_records(self.root)
168
171
  items.append(
169
172
  EvidenceItem(
170
173
  control_id="Art.12",
171
174
  regulation_id="*",
172
- description="SHA-256 chained trace vault (decision seals)",
173
- source=".specsmith/trace.jsonl",
174
- source_type="file",
175
- confidence=0.9 if trace.exists() else 0.1,
176
- present=trace.exists(),
175
+ description="SHA-256 chained trace vault (decision seals, ESDB seal_record)",
176
+ source="ESDB seal_record (.specsmith/esdb.sqlite3 | .chronomemory/)",
177
+ source_type="esdb",
178
+ confidence=0.9 if seal_count > 0 else 0.1,
179
+ present=seal_count > 0,
180
+ detail=f"{seal_count} seal(s) in ESDB",
177
181
  )
178
182
  )
179
183
 
@@ -127,7 +127,8 @@ _EU_AI_ACT = Regulation(
127
127
  category="logging",
128
128
  specsmith_controls=[
129
129
  "specsmith trace (SHA-256 chain)",
130
- ".specsmith/trace.jsonl",
130
+ # DEPRECATED(REQ-421): legacy trace.jsonl replaced by ESDB seal_record.
131
+ "ESDB seal_record (.specsmith/esdb.sqlite3 | .chronomemory/)",
131
132
  "ChronoStore WAL (.chronomemory/events.wal)",
132
133
  ".specsmith/ledger.jsonl",
133
134
  "specsmith trace verify",
@@ -141,7 +141,7 @@ class ProjectConfig(BaseModel):
141
141
  ),
142
142
  )
143
143
  language: str = Field(default="python", description="Primary language/runtime")
144
- spec_version: str = Field(default="0.17.1", description="Spec version to scaffold from")
144
+ spec_version: str = Field(default="0.18.0", description="Spec version to scaffold from")
145
145
  description: str = Field(default="", description="Short project description")
146
146
 
147
147
  # Options
@@ -451,7 +451,7 @@ class ProjectConfig(BaseModel):
451
451
  )
452
452
  enable_trace_vault: bool = Field(
453
453
  default=False,
454
- description="Enable cryptographic trace vault (.specsmith/trace.jsonl)",
454
+ description="Enable cryptographic trace vault (ESDB seal_record; REQ-420)",
455
455
  )
456
456
 
457
457
  @property
@@ -360,18 +360,37 @@ class ContextOrchestrator:
360
360
  return 0
361
361
 
362
362
  def _count_critical_records(self) -> int:
363
- """Count records that qualify as critical (must be protected)."""
363
+ """Count records that qualify as critical (must be protected).
364
+
365
+ REQ-422: parity across backends — prefer the ChronoStore WAL when present,
366
+ otherwise count active high-confidence records from the free SQLite ESDB
367
+ backend so the protection path behaves identically without ChronoStore.
368
+ """
369
+ # --- ChronoStore first (commercial backend) -------------------------
364
370
  wal = self.root / ".chronomemory" / "events.wal"
365
- if not wal.exists():
366
- return 0
371
+ if wal.exists():
372
+ try:
373
+ from chronomemory import ChronoStore
374
+
375
+ with ChronoStore(self.root) as store:
376
+ return sum(
377
+ 1
378
+ for r in store.query()
379
+ if r.confidence >= CRITICAL_CONFIDENCE and r.status == "active"
380
+ )
381
+ except Exception: # noqa: BLE001
382
+ pass # fall through to SqliteStore
383
+
384
+ # --- Fall back to SqliteStore (free default backend) ----------------
367
385
  try:
368
- from chronomemory import ChronoStore
386
+ from specsmith.esdb import SqliteStore
369
387
 
370
- with ChronoStore(self.root) as store:
388
+ sqlite_path = self.root / ".specsmith" / "esdb.sqlite3"
389
+ if not sqlite_path.exists():
390
+ return 0
391
+ with SqliteStore(self.root) as store:
371
392
  return sum(
372
- 1
373
- for r in store.query()
374
- if r.confidence >= CRITICAL_CONFIDENCE and r.status == "active"
393
+ 1 for r in store.query(status="active") if r.confidence >= CRITICAL_CONFIDENCE
375
394
  )
376
395
  except Exception: # noqa: BLE001
377
396
  return 0