specsmith 0.17.1.dev667__tar.gz → 0.17.1.dev684__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 (354) hide show
  1. {specsmith-0.17.1.dev667/src/specsmith.egg-info → specsmith-0.17.1.dev684}/PKG-INFO +1 -1
  2. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/pyproject.toml +1 -1
  3. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/context_seed.py +134 -3
  4. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/runner.py +42 -1
  5. specsmith-0.17.1.dev684/src/specsmith/agent/token_pricing.py +191 -0
  6. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/auditor.py +2 -1
  7. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/cli.py +292 -0
  8. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/_compat.py +89 -44
  9. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/context_orchestrator.py +75 -4
  10. specsmith-0.17.1.dev684/src/specsmith/efficiency.py +293 -0
  11. specsmith-0.17.1.dev684/src/specsmith/esdb_sweep.py +225 -0
  12. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb_writer.py +202 -2
  13. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/ledger.py +17 -0
  14. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/__init__.py +4 -0
  15. specsmith-0.17.1.dev684/src/specsmith/migrations/m009_esdb_first.py +257 -0
  16. specsmith-0.17.1.dev684/src/specsmith/migrations/m010_post_esdb_cleanup.py +241 -0
  17. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/project_metrics.py +7 -0
  18. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/serve.py +11 -0
  19. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/agents.md.j2 +33 -2
  20. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/trace.py +7 -0
  21. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs_commands.py +25 -1
  22. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684/src/specsmith.egg-info}/PKG-INFO +1 -1
  23. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/SOURCES.txt +13 -0
  24. specsmith-0.17.1.dev684/tests/test_benchmark_harness.py +688 -0
  25. specsmith-0.17.1.dev684/tests/test_dual_write.py +268 -0
  26. specsmith-0.17.1.dev684/tests/test_efficiency.py +246 -0
  27. specsmith-0.17.1.dev684/tests/test_esdb_sweep.py +267 -0
  28. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_nexus.py +8 -3
  29. specsmith-0.17.1.dev684/tests/test_parallel_agents.py +511 -0
  30. specsmith-0.17.1.dev684/tests/test_repl_extended.py +391 -0
  31. specsmith-0.17.1.dev684/tests/test_resume_command.py +188 -0
  32. specsmith-0.17.1.dev684/tests/test_token_cost.py +319 -0
  33. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/LICENSE +0 -0
  34. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/README.md +0 -0
  35. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/setup.cfg +0 -0
  36. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/__init__.py +0 -0
  37. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/belief.py +0 -0
  38. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/certainty.py +0 -0
  39. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/failure_graph.py +0 -0
  40. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/py.typed +0 -0
  41. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/recovery.py +0 -0
  42. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/session.py +0 -0
  43. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/stress_tester.py +0 -0
  44. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/epistemic/trace.py +0 -0
  45. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/__init__.py +0 -0
  46. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/__main__.py +0 -0
  47. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/__init__.py +0 -0
  48. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/broker.py +0 -0
  49. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/chat_runner.py +0 -0
  50. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/cleanup.py +0 -0
  51. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/core.py +0 -0
  52. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/__init__.py +0 -0
  53. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/_status.py +0 -0
  54. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/dag.py +0 -0
  55. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
  56. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/events.py +0 -0
  57. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/dispatch/result.py +0 -0
  58. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/endpoints.py +0 -0
  59. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/events.py +0 -0
  60. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/execution_profiles.py +0 -0
  61. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/fallback.py +0 -0
  62. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/hf_leaderboard.py +0 -0
  63. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/hf_sync.py +0 -0
  64. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/indexer.py +0 -0
  65. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/llm_client.py +0 -0
  66. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/mcp.py +0 -0
  67. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/memory.py +0 -0
  68. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/model_intelligence.py +0 -0
  69. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/model_profiles.py +0 -0
  70. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/model_router.py +0 -0
  71. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/orchestrator.py +0 -0
  72. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/permissions.py +0 -0
  73. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/profiles.py +0 -0
  74. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/provider_registry.py +0 -0
  75. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/repl.py +0 -0
  76. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/router.py +0 -0
  77. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/rules.py +0 -0
  78. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/safety.py +0 -0
  79. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/spawner.py +0 -0
  80. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/suggester.py +0 -0
  81. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/teams.py +0 -0
  82. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/tools.py +0 -0
  83. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/verifier.py +0 -0
  84. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/agent/voice.py +0 -0
  85. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/approvals.py +0 -0
  86. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/architect.py +0 -0
  87. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/auth.py +0 -0
  88. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/block_export.py +0 -0
  89. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/channel.py +0 -0
  90. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/ci_manager.py +0 -0
  91. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/commands/__init__.py +0 -0
  92. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/commands/intelligence.py +0 -0
  93. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/commands/issues_policy.py +0 -0
  94. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/commands/reporting.py +0 -0
  95. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/__init__.py +0 -0
  96. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/checker.py +0 -0
  97. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/evidence.py +0 -0
  98. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/regulations.py +0 -0
  99. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compliance/reporter.py +0 -0
  100. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/compressor.py +0 -0
  101. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/config.py +0 -0
  102. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/console_utils.py +0 -0
  103. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/context_window.py +0 -0
  104. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/credit_analyzer.py +0 -0
  105. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/credits.py +0 -0
  106. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/dashboard.py +0 -0
  107. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/__init__.py +0 -0
  108. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/base.py +0 -0
  109. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/citations.py +0 -0
  110. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/fpd.py +0 -0
  111. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/odp.py +0 -0
  112. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/patentsview.py +0 -0
  113. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/pfw.py +0 -0
  114. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/ppubs.py +0 -0
  115. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/datasources/ptab.py +0 -0
  116. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/differ.py +0 -0
  117. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/doctor.py +0 -0
  118. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/drive.py +0 -0
  119. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/editor.py +0 -0
  120. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/__init__.py +0 -0
  121. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/belief.py +0 -0
  122. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/certainty.py +0 -0
  123. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/failure_graph.py +0 -0
  124. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/recovery.py +0 -0
  125. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/epistemic/stress_tester.py +0 -0
  126. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb/__init__.py +0 -0
  127. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb/_license.py +0 -0
  128. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb/bridge.py +0 -0
  129. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/esdb/sqlite_store.py +0 -0
  130. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/eval/__init__.py +0 -0
  131. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/eval/builtins.py +0 -0
  132. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/eval/runner.py +0 -0
  133. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/executor.py +0 -0
  134. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/exporter.py +0 -0
  135. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/governance_logic.py +0 -0
  136. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/governance_store.py +0 -0
  137. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/governance_yaml.py +0 -0
  138. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/governed_pr.py +0 -0
  139. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/__init__.py +0 -0
  140. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/app.py +0 -0
  141. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/main_window.py +0 -0
  142. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/session_tab.py +0 -0
  143. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/theme.py +0 -0
  144. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/__init__.py +0 -0
  145. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/chat_view.py +0 -0
  146. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/input_bar.py +0 -0
  147. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  148. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/token_meter.py +0 -0
  149. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  150. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/widgets/update_checker.py +0 -0
  151. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/gui/worker.py +0 -0
  152. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/history_search.py +0 -0
  153. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/importer.py +0 -0
  154. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/instinct.py +0 -0
  155. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/__init__.py +0 -0
  156. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/agent_skill.py +0 -0
  157. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/aider.py +0 -0
  158. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/base.py +0 -0
  159. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/claude_code.py +0 -0
  160. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/codity.py +0 -0
  161. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/copilot.py +0 -0
  162. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/cursor.py +0 -0
  163. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/gemini.py +0 -0
  164. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/integrations/windsurf.py +0 -0
  165. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/issue_reporter.py +0 -0
  166. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/languages.py +0 -0
  167. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/local_model.py +0 -0
  168. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/mcp_generator.py +0 -0
  169. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/mcp_server.py +0 -0
  170. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
  171. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m002_agents_slim.py +0 -0
  172. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m003_compliance_init.py +0 -0
  173. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
  174. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
  175. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m006_session_governance.py +0 -0
  176. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m007_yaml_first.py +0 -0
  177. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/m008_esdb_full_coverage.py +0 -0
  178. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/migrations/runner.py +0 -0
  179. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/ollama_cmds.py +0 -0
  180. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/patent.py +0 -0
  181. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/paths.py +0 -0
  182. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/phase.py +0 -0
  183. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/plugins.py +0 -0
  184. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/policy.py +0 -0
  185. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/profiles.py +0 -0
  186. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/quality_report.py +0 -0
  187. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/rate_limits.py +0 -0
  188. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/recover.py +0 -0
  189. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/releaser.py +0 -0
  190. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/requirements.py +0 -0
  191. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/requirements_parser.py +0 -0
  192. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/retrieval.py +0 -0
  193. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/risk.py +0 -0
  194. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/safe_write.py +0 -0
  195. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/scaffolder.py +0 -0
  196. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/session.py +0 -0
  197. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/session_init.py +0 -0
  198. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/session_store.py +0 -0
  199. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/__init__.py +0 -0
  200. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/ai_agents.py +0 -0
  201. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/cloud.py +0 -0
  202. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/corporate.py +0 -0
  203. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/cross_platform.py +0 -0
  204. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/data_engineering.py +0 -0
  205. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/devops.py +0 -0
  206. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/docs.py +0 -0
  207. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/embedded.py +0 -0
  208. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/governance.py +0 -0
  209. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/hardware.py +0 -0
  210. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/mobile.py +0 -0
  211. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/platform_engineering.py +0 -0
  212. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/productivity.py +0 -0
  213. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/software_engineering.py +0 -0
  214. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/specsmith_skills.py +0 -0
  215. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/ssh.py +0 -0
  216. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills/web_backend.py +0 -0
  217. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/skills_builder.py +0 -0
  218. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/sync.py +0 -0
  219. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  220. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  221. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  222. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  223. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  224. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  225. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  226. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/community/security.md.j2 +0 -0
  227. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  228. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  229. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  230. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  231. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  232. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/editorconfig.j2 +0 -0
  233. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/gitattributes.j2 +0 -0
  234. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/gitignore.j2 +0 -0
  235. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/go/go.mod.j2 +0 -0
  236. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/go/main.go.j2 +0 -0
  237. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  238. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  239. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  240. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  241. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  242. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
  243. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  244. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  245. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
  246. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  247. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  248. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/js/package.json.j2 +0 -0
  249. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/ledger.md.j2 +0 -0
  250. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/python/cli.py.j2 +0 -0
  251. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/python/init.py.j2 +0 -0
  252. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  253. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/readme.md.j2 +0 -0
  254. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  255. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  256. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  257. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  258. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  259. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  260. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  261. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  262. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  263. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/tool_installer.py +0 -0
  264. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/toolrules.py +0 -0
  265. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/tools.py +0 -0
  266. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/transcripts.py +0 -0
  267. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/updater.py +0 -0
  268. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/upgrader.py +0 -0
  269. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/validator.py +0 -0
  270. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/__init__.py +0 -0
  271. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/base.py +0 -0
  272. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/bitbucket.py +0 -0
  273. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/github.py +0 -0
  274. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/vcs/gitlab.py +0 -0
  275. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/wi_store.py +0 -0
  276. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/wireframes.py +0 -0
  277. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith/workspace.py +0 -0
  278. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/dependency_links.txt +0 -0
  279. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/entry_points.txt +0 -0
  280. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/requires.txt +0 -0
  281. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/src/specsmith.egg-info/top_level.txt +0 -0
  282. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_CMD_001.py +0 -0
  283. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_agent_profiles.py +0 -0
  284. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_agent_run_feedback.py +0 -0
  285. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_agent_runner_ready.py +0 -0
  286. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_ai_client.py +0 -0
  287. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_ai_intelligence.py +0 -0
  288. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_architect_interview.py +0 -0
  289. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_architect_v2.py +0 -0
  290. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_architecture.py +0 -0
  291. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_auditor.py +0 -0
  292. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_channel.py +0 -0
  293. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_chat_diff_decision.py +0 -0
  294. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_chat_runner_openai_compat.py +0 -0
  295. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_chat_stdin_protocol.py +0 -0
  296. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_cleanup_cmd.py +0 -0
  297. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_cli.py +0 -0
  298. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_cli_regressions.py +0 -0
  299. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_cli_workflows_history_drive.py +0 -0
  300. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_compliance.py +0 -0
  301. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_compliance_governance.py +0 -0
  302. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_compressor.py +0 -0
  303. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_dispatch.py +0 -0
  304. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_e2e_nexus.py +0 -0
  305. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_endpoints_cli.py +0 -0
  306. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_endpoints_store.py +0 -0
  307. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_epistemic.py +0 -0
  308. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_backend_switch.py +0 -0
  309. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_enforcement.py +0 -0
  310. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_integration.py +0 -0
  311. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_license.py +0 -0
  312. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_sqlite.py +0 -0
  313. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_verify_chain_cli.py +0 -0
  314. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_esdb_writer.py +0 -0
  315. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_fallback_chain.py +0 -0
  316. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_golden_path.py +0 -0
  317. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_importer.py +0 -0
  318. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_init_modes.py +0 -0
  319. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_integrations.py +0 -0
  320. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_integrations_codity.py +0 -0
  321. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_intelligence.py +0 -0
  322. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_issue_policy_features.py +0 -0
  323. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_issue_reporter.py +0 -0
  324. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_issues_263_264.py +0 -0
  325. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_local_model.py +0 -0
  326. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_markdown_deprecation.py +0 -0
  327. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_mcp_client.py +0 -0
  328. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_mcp_server.py +0 -0
  329. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_migration_direction.py +0 -0
  330. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_model_router.py +0 -0
  331. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_new_modules.py +0 -0
  332. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_permissions.py +0 -0
  333. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_phase1_4_new.py +0 -0
  334. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_phase34_completion.py +0 -0
  335. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_project_metrics.py +0 -0
  336. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_quality_report.py +0 -0
  337. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_rate_limits.py +0 -0
  338. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_repl.py +0 -0
  339. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_reporting_commands.py +0 -0
  340. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_req_248_262.py +0 -0
  341. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_req_358_359.py +0 -0
  342. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_scaffolder.py +0 -0
  343. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_schema_migrations.py +0 -0
  344. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_skill_marketplace.py +0 -0
  345. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_skills_mcp.py +0 -0
  346. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_smoke.py +0 -0
  347. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_suggester.py +0 -0
  348. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_tools.py +0 -0
  349. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_typing_guardrails.py +0 -0
  350. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_validator.py +0 -0
  351. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_vcs.py +0 -0
  352. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_warp_parity.py +0 -0
  353. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/tests/test_warp_parity_followup.py +0 -0
  354. {specsmith-0.17.1.dev667 → specsmith-0.17.1.dev684}/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.dev667
3
+ Version: 0.17.1.dev684
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.dev667"
7
+ version = "0.17.1.dev684"
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"
@@ -27,7 +27,9 @@ left off (extended to cover full epistemic continuity).
27
27
  from __future__ import annotations
28
28
 
29
29
  import json
30
+ import uuid
30
31
  from collections.abc import Sequence
32
+ from datetime import datetime, timezone
31
33
  from pathlib import Path
32
34
  from typing import Any
33
35
 
@@ -62,6 +64,10 @@ def build_context_seed(
62
64
  records (failed approaches, stale decisions, low-confidence hypotheses) are
63
65
  excluded from the context window.
64
66
 
67
+ REQ-407: ESDB-first ledger snippet (falls back to LEDGER.md).
68
+ REQ-415: auto-tune seed parameters from EFF-CURRENT.
69
+ REQ-416: write context_usage record per build_context_seed() call.
70
+
65
71
  Args:
66
72
  project_dir: Project root containing ``.specsmith/``.
67
73
  char_budget: Maximum total characters across all seed turns.
@@ -75,9 +81,21 @@ def build_context_seed(
75
81
  Empty list if no prior context is available.
76
82
  """
77
83
  root = Path(project_dir).resolve()
84
+ session_id = uuid.uuid4().hex[:16].upper()
78
85
  turns: list[dict[str, Any]] = []
79
86
  used = 0
80
87
 
88
+ # Auto-tune parameters from EFF-CURRENT (REQ-415)
89
+ eff = _load_efficiency_params(root)
90
+ if eff.get("degraded"):
91
+ # Reduce budget when context is degraded to force tighter seeds
92
+ char_budget = int(char_budget * 0.75)
93
+ if eff.get("context_char_efficiency") is not None:
94
+ # Scale max_ledger based on fill efficiency: high fill → fewer ledger lines
95
+ fill_eff = float(eff["context_char_efficiency"])
96
+ if fill_eff > 0.9:
97
+ max_ledger = max(10, max_ledger // 2)
98
+
81
99
  # ── 1. Session state snapshot ─────────────────────────────────────
82
100
  session_summary = _load_session_summary(root)
83
101
  if session_summary:
@@ -95,7 +113,7 @@ def build_context_seed(
95
113
  turns.append(t)
96
114
  used += len(c)
97
115
 
98
- # ── 3. Recent LEDGER entries ─────────────────────────────────
116
+ # ── 3. Recent LEDGER entries — ESDB-first (REQ-407) ─────────────────
99
117
  ledger_block = _load_ledger_snippet(root, max_lines=max_ledger)
100
118
  if ledger_block and used + len(ledger_block) <= char_budget:
101
119
  turns.append(
@@ -106,7 +124,22 @@ def build_context_seed(
106
124
  )
107
125
  used += len(ledger_block)
108
126
 
109
- # ── 4. ESDB records relevance-based by kind (REQ-399) ──────────────
127
+ # ── 4. Efficiency degradation warning ────────────────────────────────
128
+ if eff.get("degraded"):
129
+ eq_score = eff.get("epistemic_quality_score", 0.0)
130
+ tpc = eff.get("tokens_per_correct_answer")
131
+ baseline = eff.get("baseline_tokens_per_pass")
132
+ warn_parts = ["[EFFICIENCY WARNING: context degraded"]
133
+ if tpc is not None and baseline is not None:
134
+ warn_parts.append(f"tokens/pass={tpc:.0f} vs baseline={baseline:.0f}")
135
+ if eq_score:
136
+ warn_parts.append(f"epistemic_quality={eq_score:.2f}")
137
+ warn_parts.append("— consider specsmith esdb sweep]")
138
+ warn_content = " ".join(warn_parts)
139
+ turns.append({"role": "system", "content": warn_content})
140
+ used += len(warn_content)
141
+
142
+ # ── 5. ESDB records — relevance-based by kind (REQ-399) ──────────────
110
143
  esdb_block = _load_esdb_by_kind(
111
144
  root,
112
145
  max_preflight=max_preflight,
@@ -123,6 +156,17 @@ def build_context_seed(
123
156
  ),
124
157
  }
125
158
  )
159
+ used += len(esdb_block)
160
+
161
+ # ── 6. Write context_usage record (REQ-416) ──────────────────────────
162
+ _write_context_usage(
163
+ root,
164
+ session_id=session_id,
165
+ seed_chars=used,
166
+ seed_fill_pct=round(used / max(1, char_budget) * 100.0, 1),
167
+ turns_count=len(turns),
168
+ degraded=bool(eff.get("degraded")),
169
+ )
126
170
 
127
171
  return turns
128
172
 
@@ -192,7 +236,34 @@ def _load_conversation_history(
192
236
 
193
237
 
194
238
  def _load_ledger_snippet(root: Path, *, max_lines: int) -> str:
195
- """Return the last ``max_lines`` of LEDGER.md, newest-first."""
239
+ """Return the last ``max_lines`` of ledger entries — ESDB-first (REQ-407).
240
+
241
+ Query order:
242
+ 1. ESDB ``ledger_event`` records (sorted by timestamp desc).
243
+ 2. Fall back to LEDGER.md file if ESDB has no ledger_event records.
244
+ """
245
+ # 1. Try ESDB first
246
+ try:
247
+ from specsmith.esdb import SqliteStore
248
+
249
+ sqlite_path = root / ".specsmith" / "esdb.sqlite3"
250
+ if sqlite_path.exists():
251
+ with SqliteStore(root) as store:
252
+ records = store.query(kind="ledger_event", status="active")
253
+ if records:
254
+ # Sort newest first by timestamp in data, then take last max_lines
255
+ def _ts(r: Any) -> str:
256
+ return str(r.data.get("timestamp") or "")
257
+
258
+ sorted_recs = sorted(records, key=_ts, reverse=True)[:max_lines]
259
+ lines_out = [
260
+ f"{r.data.get('timestamp', '')[:16]} — {r.label[:120]}" for r in sorted_recs
261
+ ]
262
+ return "\n".join(lines_out)
263
+ except Exception: # noqa: BLE001
264
+ pass
265
+
266
+ # 2. Fall back to LEDGER.md file
196
267
  try:
197
268
  candidates = [root / "LEDGER.md", root / "docs" / "LEDGER.md"]
198
269
  for path in candidates:
@@ -310,4 +381,64 @@ def _load_esdb_by_kind(
310
381
  return "\n".join(lines)
311
382
 
312
383
 
384
+ def _load_efficiency_params(root: Path) -> dict[str, Any]:
385
+ """Load EFF-CURRENT from ESDB and return its data dict (REQ-415).
386
+
387
+ Returns an empty dict on any error (best-effort).
388
+ """
389
+ try:
390
+ from specsmith.esdb import SqliteStore
391
+
392
+ sqlite_path = root / ".specsmith" / "esdb.sqlite3"
393
+ if not sqlite_path.exists():
394
+ return {}
395
+ with SqliteStore(root) as store:
396
+ rec = store.get("EFF-CURRENT")
397
+ if rec is None:
398
+ return {}
399
+ data = dict(rec.data)
400
+ # Flatten epistemic_quality score for convenience
401
+ eq = data.get("epistemic_quality")
402
+ if isinstance(eq, dict):
403
+ data["epistemic_quality_score"] = eq.get("score", 0.0)
404
+ return data
405
+ except Exception: # noqa: BLE001
406
+ return {}
407
+
408
+
409
+ def _write_context_usage(
410
+ root: Path,
411
+ *,
412
+ session_id: str,
413
+ seed_chars: int,
414
+ seed_fill_pct: float,
415
+ turns_count: int,
416
+ degraded: bool,
417
+ ) -> None:
418
+ """Write a context_usage record to ESDB (REQ-416, best-effort)."""
419
+ try:
420
+ from specsmith.esdb import SqliteRecord, open_default_store
421
+
422
+ rec_id = f"CTX-{session_id}"
423
+ record = SqliteRecord(
424
+ id=rec_id,
425
+ kind="context_usage",
426
+ status="active",
427
+ label=f"seed session={session_id} fill={seed_fill_pct:.1f}%",
428
+ confidence=1.0,
429
+ data={
430
+ "session_id": session_id,
431
+ "seed_chars": seed_chars,
432
+ "seed_fill_pct": seed_fill_pct,
433
+ "turns_count": turns_count,
434
+ "degraded_at_seed": degraded,
435
+ "timestamp": datetime.now(timezone.utc).isoformat(),
436
+ },
437
+ )
438
+ with open_default_store(root, warn=False) as store:
439
+ store.upsert(record)
440
+ except Exception: # noqa: BLE001
441
+ pass
442
+
443
+
313
444
  __all__ = ["build_context_seed"]
@@ -394,7 +394,9 @@ class AgentRunner:
394
394
  lines.append(f" {s.icon} {s.name:<10} \u2717 {s.note}")
395
395
  lines.append("")
396
396
  if active_count == 0:
397
- lines.append(" \u26a0 No provider available — commands will return no response.")
397
+ lines.append(
398
+ " \u26a0 No provider available \u2014 commands will return no response."
399
+ )
398
400
  else:
399
401
  # Show multi-model routing if the router is configured (REQ-389).
400
402
  if self._model_router is not None:
@@ -585,6 +587,28 @@ class AgentRunner:
585
587
  self._emit_event(type="system", message=hint)
586
588
  return None
587
589
 
590
+ if result is None:
591
+ # All providers failed — give the user an actionable explanation
592
+ # rather than silent emptiness.
593
+ import os as _os
594
+
595
+ host = _os.environ.get("OLLAMA_HOST", DEFAULT_OLLAMA_HOST).rstrip("/")
596
+ if _ollama_alive(host):
597
+ model = _pick_ollama_model(host)
598
+ hint = (
599
+ f"Ollama is running but returned no response "
600
+ f"(model: {model}). "
601
+ "Try: ollama run " + model
602
+ )
603
+ else:
604
+ hint = (
605
+ "No LLM provider available. Options:\n"
606
+ " • Start Ollama: ollama serve\n"
607
+ " • Set ANTHROPIC_API_KEY / OPENAI_API_KEY / GOOGLE_API_KEY"
608
+ )
609
+ self._emit_event(type="system", message=hint)
610
+ return None
611
+
588
612
  # Aggregate metrics into the session state (C1).
589
613
  # ``run_chat`` now reports tokens_in / tokens_out / cost_usd off the
590
614
  # provider response (Ollama prompt_eval_count + eval_count, OpenAI
@@ -604,6 +628,23 @@ class AgentRunner:
604
628
  )
605
629
  self._state.elapsed_minutes = round((time.time() - self._started_at) / 60.0, 2)
606
630
 
631
+ # Write token_metric to ESDB (REQ-410) — best-effort, never blocks.
632
+ if tokens_in or tokens_out:
633
+ try:
634
+ from specsmith.esdb_writer import write_token_metric
635
+
636
+ write_token_metric(
637
+ self.project_dir,
638
+ input_tokens=tokens_in,
639
+ output_tokens=tokens_out,
640
+ cost_usd=cost_usd,
641
+ model=str(getattr(result, "provider", "") if result else ""),
642
+ command_source=activity or "chat",
643
+ work_item_id=str(getattr(self._state, "active_work_item_id", "") or ""),
644
+ )
645
+ except Exception: # noqa: BLE001
646
+ pass
647
+
607
648
  if result is not None:
608
649
  self._history.append({"role": "user", "text": utterance})
609
650
  self._history.append({"role": "agent", "text": result.summary})
@@ -0,0 +1,191 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
3
+ """specsmith.agent.token_pricing — static per-token cost lookup.
4
+
5
+ Provides a single function :func:`cost_for_tokens` that returns the estimated
6
+ USD cost for a given (provider, model, input_tokens, output_tokens) tuple.
7
+
8
+ Design contract
9
+ ---------------
10
+ - ``ollama`` provider (and its aliases ``llamacpp``, ``vllm``, ``lmstudio``)
11
+ always returns **0.0** — local inference is free; this is intentional and
12
+ correct, not a bug or missing data.
13
+ - Known cloud models (OpenAI, Anthropic, Google) use a static pricing table
14
+ updated to Q2 2026 list prices.
15
+ - Unknown providers/models fall back to a conservative default rate so
16
+ ``cost_of_pass`` analysis degrades gracefully rather than crashing.
17
+
18
+ Pricing source
19
+ --------------
20
+ Q2 2026 provider pricing pages. All figures are in USD per 1 M tokens.
21
+ Update this table when provider pricing changes (bump the table version comment).
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ from typing import Any
27
+
28
+ # ---------------------------------------------------------------------------
29
+ # Pricing table — (input_usd_per_1M, output_usd_per_1M)
30
+ # Table version: 2026-Q2
31
+ # ---------------------------------------------------------------------------
32
+
33
+ #: Providers that are always zero-cost (local inference).
34
+ _FREE_PROVIDERS: frozenset[str] = frozenset({"ollama", "llamacpp", "vllm", "lmstudio", "local"})
35
+
36
+ #: Static pricing table. Keys are normalised model name substrings matched
37
+ #: from longest to shortest so that more-specific keys win over generic ones.
38
+ _PRICING_PER_1M: dict[str, tuple[float, float]] = {
39
+ # ── OpenAI GPT-4 family ────────────────────────────────────────────────
40
+ "gpt-4o-mini": (0.15, 0.60),
41
+ "gpt-4o": (2.50, 10.00),
42
+ "gpt-4.1-nano": (0.10, 0.40),
43
+ "gpt-4.1-mini": (0.40, 1.60),
44
+ "gpt-4.1": (2.00, 8.00),
45
+ "gpt-4-turbo": (10.00, 30.00),
46
+ # ── OpenAI GPT-5 family ────────────────────────────────────────────────
47
+ "gpt-5-nano": (0.50, 2.00),
48
+ "gpt-5-mini": (2.00, 8.00),
49
+ "gpt-5-pro": (50.00, 200.00),
50
+ "gpt-5.4-nano": (0.30, 1.20),
51
+ "gpt-5.4-mini": (1.00, 4.00),
52
+ "gpt-5.4-pro": (20.00, 80.00),
53
+ "gpt-5.4": (5.00, 20.00),
54
+ "gpt-5.5-pro": (15.00, 60.00),
55
+ "gpt-5.5": (3.00, 12.00),
56
+ "gpt-5.2-codex": (10.00, 40.00),
57
+ "gpt-5.2-pro": (40.00, 160.00),
58
+ "gpt-5.2": (10.00, 40.00),
59
+ "gpt-5.3-codex": (8.00, 32.00),
60
+ "gpt-5.1": (12.00, 48.00),
61
+ "gpt-5-codex": (15.00, 60.00),
62
+ "gpt-5": (15.00, 60.00),
63
+ # ── OpenAI reasoning ──────────────────────────────────────────────────
64
+ "o4-mini": (1.10, 4.40),
65
+ "o3-mini": (1.10, 4.40),
66
+ "o3": (10.00, 40.00),
67
+ "o1": (15.00, 60.00),
68
+ # ── Anthropic ─────────────────────────────────────────────────────────
69
+ "claude-haiku-4-5": (0.25, 1.25),
70
+ "claude-haiku": (0.25, 1.25),
71
+ "claude-sonnet-4-5": (3.00, 15.00),
72
+ "claude-sonnet-4-6": (3.00, 15.00),
73
+ "claude-sonnet": (3.00, 15.00),
74
+ "claude-opus-4-5": (15.00, 75.00),
75
+ "claude-opus-4-6": (15.00, 75.00),
76
+ "claude-opus": (15.00, 75.00),
77
+ # ── Google ────────────────────────────────────────────────────────────
78
+ "gemini-3.5-flash": (0.15, 0.60),
79
+ "gemini-3-flash": (0.35, 1.05),
80
+ "gemini-flash": (0.075, 0.30),
81
+ "gemini-3.1-pro": (1.25, 5.00),
82
+ "gemini-pro": (1.25, 5.00),
83
+ # ── Conservative fallback ─────────────────────────────────────────────
84
+ "unknown": (3.00, 15.00),
85
+ }
86
+
87
+
88
+ def _lookup_rates(model: str) -> tuple[float, float]:
89
+ """Return (input_usd_per_1M, output_usd_per_1M) for *model*.
90
+
91
+ Tries an exact key match first, then a longest-substring match, and
92
+ finally falls back to the ``"unknown"`` conservative default.
93
+ """
94
+ key = model.strip().lower()
95
+ if key in _PRICING_PER_1M:
96
+ return _PRICING_PER_1M[key]
97
+ # Longest-prefix / substring match so that "gpt-4o-mini-2026-04-09"
98
+ # still resolves to "gpt-4o-mini".
99
+ best_match = ""
100
+ for table_key in _PRICING_PER_1M:
101
+ if table_key in key and len(table_key) > len(best_match):
102
+ best_match = table_key
103
+ if best_match:
104
+ return _PRICING_PER_1M[best_match]
105
+ return _PRICING_PER_1M["unknown"]
106
+
107
+
108
+ def cost_for_tokens(
109
+ provider: str,
110
+ model: str,
111
+ input_tokens: int,
112
+ output_tokens: int,
113
+ ) -> float:
114
+ """Return estimated USD cost for a single LLM call.
115
+
116
+ Args:
117
+ provider: Provider name (e.g. ``"ollama"``, ``"openai"``, ``"anthropic"``).
118
+ model: Model name or slug (e.g. ``"gpt-4o"``, ``"qwen2.5-coder:14b"``).
119
+ input_tokens: Number of prompt/context tokens consumed.
120
+ output_tokens: Number of generated/completion tokens.
121
+
122
+ Returns:
123
+ Estimated cost in USD. Always ``0.0`` for local/free providers
124
+ (Ollama, llamacpp, vllm, lmstudio, local). Returns ``0.0`` when
125
+ both token counts are zero regardless of provider.
126
+
127
+ Examples::
128
+
129
+ >>> cost_for_tokens("ollama", "qwen2.5-coder:14b", 1000, 500)
130
+ 0.0
131
+ >>> cost_for_tokens("openai", "gpt-4o-mini", 1_000_000, 0)
132
+ 0.15
133
+ >>> cost_for_tokens("anthropic", "claude-haiku-4-5", 0, 1_000_000)
134
+ 1.25
135
+ """
136
+ if not provider and not model:
137
+ return 0.0
138
+ if (provider or "").strip().lower() in _FREE_PROVIDERS:
139
+ return 0.0
140
+ if input_tokens == 0 and output_tokens == 0:
141
+ return 0.0
142
+ inp_per_m, out_per_m = _lookup_rates(model)
143
+ return (input_tokens * inp_per_m + output_tokens * out_per_m) / 1_000_000
144
+
145
+
146
+ def cost_for_tokens_breakdown(
147
+ provider: str,
148
+ model: str,
149
+ input_tokens: int,
150
+ output_tokens: int,
151
+ ) -> tuple[float, float, float]:
152
+ """Return ``(input_cost_usd, output_cost_usd, total_cost_usd)``."""
153
+ if (provider or "").strip().lower() in _FREE_PROVIDERS:
154
+ return 0.0, 0.0, 0.0
155
+ inp_per_m, out_per_m = _lookup_rates(model)
156
+ inp_cost = input_tokens * inp_per_m / 1_000_000
157
+ out_cost = output_tokens * out_per_m / 1_000_000
158
+ return inp_cost, out_cost, inp_cost + out_cost
159
+
160
+
161
+ def tokens_per_correct_answer(
162
+ records: list[Any],
163
+ *,
164
+ token_attr: str = "tokens_total",
165
+ passed_attr: str = "passed",
166
+ ) -> float | None:
167
+ """Compute mean tokens consumed per correct (passing) answer.
168
+
169
+ Args:
170
+ records: Sequence of record objects (e.g. :class:`MetricsRecord` or
171
+ :class:`RunResult`) with numeric ``token_attr`` and bool
172
+ ``passed_attr`` attributes.
173
+ token_attr: Attribute name for total token count.
174
+ passed_attr: Attribute name for pass/fail boolean.
175
+
176
+ Returns:
177
+ Mean total tokens among passing records, or ``None`` if no passing
178
+ records exist.
179
+ """
180
+ passing = [r for r in records if getattr(r, passed_attr, False)]
181
+ if not passing:
182
+ return None
183
+ totals = [getattr(r, token_attr, 0) for r in passing]
184
+ return sum(totals) / len(totals)
185
+
186
+
187
+ __all__ = [
188
+ "cost_for_tokens",
189
+ "cost_for_tokens_breakdown",
190
+ "tokens_per_correct_answer",
191
+ ]
@@ -554,8 +554,9 @@ def check_ledger_health(root: Path) -> list[AuditResult]:
554
554
 
555
555
 
556
556
  # Default thresholds (used when no project type is detected)
557
+ # AGENTS.md: raised to 250 (template now generates ~202 lines with Parallel Agents section)
557
558
  _DEFAULT_THRESHOLDS: dict[str, int] = {
558
- "AGENTS.md": 200,
559
+ "AGENTS.md": 250,
559
560
  "docs/governance/RULES.md": 800,
560
561
  "docs/governance/SESSION-PROTOCOL.md": 400,
561
562
  "docs/governance/LIFECYCLE.md": 200,