specsmith 0.6.0.dev232__tar.gz → 0.6.0.dev234__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 (186) hide show
  1. {specsmith-0.6.0.dev232/src/specsmith.egg-info → specsmith-0.6.0.dev234}/PKG-INFO +6 -1
  2. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/pyproject.toml +12 -1
  3. specsmith-0.6.0.dev234/src/specsmith/agent/voice.py +135 -0
  4. specsmith-0.6.0.dev234/src/specsmith/block_export.py +106 -0
  5. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/cli.py +295 -87
  6. specsmith-0.6.0.dev234/src/specsmith/cloud_serve.py +150 -0
  7. specsmith-0.6.0.dev234/src/specsmith/drive.py +126 -0
  8. specsmith-0.6.0.dev234/src/specsmith/history_search.py +159 -0
  9. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/serve.py +58 -4
  10. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234/src/specsmith.egg-info}/PKG-INFO +6 -1
  11. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith.egg-info/SOURCES.txt +8 -1
  12. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith.egg-info/requires.txt +7 -0
  13. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_phase34_completion.py +14 -18
  14. specsmith-0.6.0.dev234/tests/test_warp_parity.py +421 -0
  15. specsmith-0.6.0.dev234/tests/test_warp_parity_followup.py +368 -0
  16. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/LICENSE +0 -0
  17. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/README.md +0 -0
  18. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/setup.cfg +0 -0
  19. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/__init__.py +0 -0
  20. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/belief.py +0 -0
  21. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/certainty.py +0 -0
  22. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/failure_graph.py +0 -0
  23. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/py.typed +0 -0
  24. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/recovery.py +0 -0
  25. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/session.py +0 -0
  26. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/stress_tester.py +0 -0
  27. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/epistemic/trace.py +0 -0
  28. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/__init__.py +0 -0
  29. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/__main__.py +0 -0
  30. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/__init__.py +0 -0
  31. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/broker.py +0 -0
  32. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/chat_runner.py +0 -0
  33. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/cleanup.py +0 -0
  34. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/events.py +0 -0
  35. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/indexer.py +0 -0
  36. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/mcp.py +0 -0
  37. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/memory.py +0 -0
  38. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/orchestrator.py +0 -0
  39. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/repl.py +0 -0
  40. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/router.py +0 -0
  41. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/rules.py +0 -0
  42. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/safety.py +0 -0
  43. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/suggester.py +0 -0
  44. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/tools.py +0 -0
  45. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/agent/verifier.py +0 -0
  46. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/architect.py +0 -0
  47. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/auditor.py +0 -0
  48. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/auth.py +0 -0
  49. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/commands/__init__.py +0 -0
  50. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/compressor.py +0 -0
  51. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/config.py +0 -0
  52. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/console_utils.py +0 -0
  53. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/credit_analyzer.py +0 -0
  54. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/credits.py +0 -0
  55. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/differ.py +0 -0
  56. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/doctor.py +0 -0
  57. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/epistemic/__init__.py +0 -0
  58. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/epistemic/belief.py +0 -0
  59. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/epistemic/certainty.py +0 -0
  60. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/epistemic/failure_graph.py +0 -0
  61. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/epistemic/recovery.py +0 -0
  62. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/epistemic/stress_tester.py +0 -0
  63. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/executor.py +0 -0
  64. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/exporter.py +0 -0
  65. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/__init__.py +0 -0
  66. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/app.py +0 -0
  67. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/main_window.py +0 -0
  68. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/session_tab.py +0 -0
  69. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/theme.py +0 -0
  70. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/widgets/__init__.py +0 -0
  71. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/widgets/chat_view.py +0 -0
  72. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/widgets/input_bar.py +0 -0
  73. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  74. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/widgets/token_meter.py +0 -0
  75. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  76. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/widgets/update_checker.py +0 -0
  77. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/gui/worker.py +0 -0
  78. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/importer.py +0 -0
  79. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/__init__.py +0 -0
  80. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/agent_skill.py +0 -0
  81. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/aider.py +0 -0
  82. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/base.py +0 -0
  83. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/claude_code.py +0 -0
  84. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/copilot.py +0 -0
  85. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/cursor.py +0 -0
  86. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/gemini.py +0 -0
  87. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/integrations/windsurf.py +0 -0
  88. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/languages.py +0 -0
  89. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/ledger.py +0 -0
  90. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/patent.py +0 -0
  91. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/phase.py +0 -0
  92. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/plugins.py +0 -0
  93. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/profiles.py +0 -0
  94. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/rate_limits.py +0 -0
  95. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/releaser.py +0 -0
  96. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/requirements.py +0 -0
  97. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/requirements_parser.py +0 -0
  98. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/retrieval.py +0 -0
  99. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/scaffolder.py +0 -0
  100. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/session.py +0 -0
  101. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/skills.py +0 -0
  102. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/agents.md.j2 +0 -0
  103. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  104. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  105. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  106. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  107. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  108. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  109. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  110. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/community/security.md.j2 +0 -0
  111. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  112. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  113. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  114. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  115. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  116. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/editorconfig.j2 +0 -0
  117. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/gitattributes.j2 +0 -0
  118. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/gitignore.j2 +0 -0
  119. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/go/go.mod.j2 +0 -0
  120. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/go/main.go.j2 +0 -0
  121. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  122. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  123. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  124. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  125. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  126. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
  127. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  128. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  129. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
  130. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  131. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  132. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/js/package.json.j2 +0 -0
  133. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/ledger.md.j2 +0 -0
  134. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/python/cli.py.j2 +0 -0
  135. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/python/init.py.j2 +0 -0
  136. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  137. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/readme.md.j2 +0 -0
  138. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  139. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  140. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  141. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  142. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  143. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  144. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  145. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  146. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  147. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/tool_installer.py +0 -0
  148. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/toolrules.py +0 -0
  149. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/tools.py +0 -0
  150. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/trace.py +0 -0
  151. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/updater.py +0 -0
  152. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/upgrader.py +0 -0
  153. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/validator.py +0 -0
  154. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/vcs/__init__.py +0 -0
  155. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/vcs/base.py +0 -0
  156. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/vcs/bitbucket.py +0 -0
  157. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/vcs/github.py +0 -0
  158. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/vcs/gitlab.py +0 -0
  159. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/vcs_commands.py +0 -0
  160. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/wireframes.py +0 -0
  161. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith/workspace.py +0 -0
  162. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith.egg-info/dependency_links.txt +0 -0
  163. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith.egg-info/entry_points.txt +0 -0
  164. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/src/specsmith.egg-info/top_level.txt +0 -0
  165. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_CMD_001.py +0 -0
  166. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_auditor.py +0 -0
  167. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_chat_diff_decision.py +0 -0
  168. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_chat_stdin_protocol.py +0 -0
  169. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_cli.py +0 -0
  170. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_cli_workflows_history_drive.py +0 -0
  171. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_compressor.py +0 -0
  172. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_e2e_nexus.py +0 -0
  173. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_epistemic.py +0 -0
  174. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_importer.py +0 -0
  175. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_integrations.py +0 -0
  176. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_mcp_client.py +0 -0
  177. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_nexus.py +0 -0
  178. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_phase1_4_new.py +0 -0
  179. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_rate_limits.py +0 -0
  180. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_scaffolder.py +0 -0
  181. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_skill_marketplace.py +0 -0
  182. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_smoke.py +0 -0
  183. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_suggester.py +0 -0
  184. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_tools.py +0 -0
  185. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_validator.py +0 -0
  186. {specsmith-0.6.0.dev232 → specsmith-0.6.0.dev234}/tests/test_vcs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.6.0.dev232
3
+ Version: 0.6.0.dev234
4
4
  Summary: Applied Epistemic Engineering toolkit — AEE agent sessions, execution profiles, FPGA/HDL governance, tool installer, 50+ CLI commands.
5
5
  Author: BitConcepts
6
6
  License-Expression: MIT
@@ -53,6 +53,11 @@ Provides-Extra: gui
53
53
  Requires-Dist: PySide6>=6.6; extra == "gui"
54
54
  Provides-Extra: ag2
55
55
  Requires-Dist: ag2[ollama]; extra == "ag2"
56
+ Provides-Extra: history-semantic
57
+ Requires-Dist: sentence-transformers>=2.2; extra == "history-semantic"
58
+ Requires-Dist: numpy>=1.24; extra == "history-semantic"
59
+ Provides-Extra: voice
60
+ Requires-Dist: whisper-cpp-python>=0.2; extra == "voice"
56
61
  Provides-Extra: agent
57
62
  Requires-Dist: anthropic>=0.56; extra == "agent"
58
63
  Requires-Dist: openai>=1.0; extra == "agent"
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "specsmith"
7
- version = "0.6.0.dev232"
7
+ version = "0.6.0.dev234"
8
8
  description = "Applied Epistemic Engineering toolkit — AEE agent sessions, execution profiles, FPGA/HDL governance, tool installer, 50+ CLI commands."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -67,6 +67,11 @@ mistral = ["openai>=1.0"] # Mistral uses the openai SDK pointed at api.mistral.
67
67
  gui = ["PySide6>=6.6"]
68
68
  # AG2 agent shell (Planner/Builder/Verifier over Ollama)
69
69
  ag2 = ["ag2[ollama]"]
70
+ # Optional semantic backend for `specsmith history search --semantic` (REQ-135).
71
+ # Falls back gracefully to keyword matching if these are not installed.
72
+ history-semantic = ["sentence-transformers>=2.2", "numpy>=1.24"]
73
+ # Optional whisper-cpp wrapper for the voice agent input (REQ-141).
74
+ voice = ["whisper-cpp-python>=0.2"]
70
75
  # Install all optional LLM providers
71
76
  agent = ["anthropic>=0.56", "openai>=1.0"]
72
77
  # Convenience bundle: everything
@@ -138,6 +143,12 @@ module = [
138
143
  "yaml.*",
139
144
  "keyring", # optional OS credential store; stubs not published
140
145
  "keyring.*",
146
+ "numpy", # optional [history-semantic] extra (REQ-135)
147
+ "numpy.*",
148
+ "sentence_transformers", # optional [history-semantic] extra (REQ-135)
149
+ "sentence_transformers.*",
150
+ "whisper_cpp_python", # optional [voice] extra (REQ-141)
151
+ "whisper_cpp_python.*",
141
152
  ]
142
153
  ignore_missing_imports = true
143
154
 
@@ -0,0 +1,135 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 BitConcepts, LLC. All rights reserved.
3
+ """Voice transcription wrapper (REQ-141).
4
+
5
+ Wraps the optional ``whisper_cpp_python`` library so the rest of specsmith
6
+ can call ``transcribe(path)`` without caring whether the extra is
7
+ installed. When the library is missing, ``transcribe`` raises
8
+ ``VoiceUnavailableError`` with a friendly install hint so the caller can
9
+ surface it to the user.
10
+
11
+ The wrapper supports three modes:
12
+
13
+ * **real** -- ``whisper_cpp_python`` is installed and a model file is
14
+ available (auto-located under ``~/.specsmith/voice/`` or pointed to via
15
+ ``SPECSMITH_VOICE_MODEL``). Real audio decoding.
16
+ * **stub** -- ``SPECSMITH_VOICE_STUB=<text>`` is set. Returns the literal
17
+ text without touching the audio file. Used by tests and CI so we don't
18
+ need to ship a 500MB model file.
19
+ * **unavailable** -- neither of the above. ``transcribe`` raises.
20
+
21
+ The CLI exposes this as ``specsmith voice transcribe <wav>``.
22
+ """
23
+
24
+ from __future__ import annotations
25
+
26
+ import os
27
+ from dataclasses import dataclass
28
+ from pathlib import Path
29
+
30
+
31
+ class VoiceUnavailableError(RuntimeError):
32
+ """Raised when whisper-cpp is not installed and no stub is set."""
33
+
34
+
35
+ @dataclass
36
+ class TranscribeResult:
37
+ text: str
38
+ backend: str # 'whisper-cpp', 'stub', 'unavailable'
39
+ model: str = ""
40
+ duration_s: float = 0.0
41
+
42
+ def to_dict(self) -> dict[str, object]:
43
+ return {
44
+ "text": self.text,
45
+ "backend": self.backend,
46
+ "model": self.model,
47
+ "duration_s": round(self.duration_s, 3),
48
+ }
49
+
50
+
51
+ def default_model_dir() -> Path:
52
+ return Path.home() / ".specsmith" / "voice"
53
+
54
+
55
+ def _resolve_model_path() -> Path | None:
56
+ """Return the on-disk model path, or None if no model is configured."""
57
+ env = os.environ.get("SPECSMITH_VOICE_MODEL", "").strip()
58
+ if env:
59
+ p = Path(env)
60
+ if p.is_file():
61
+ return p
62
+ # Auto-locate the smallest .bin under ~/.specsmith/voice/
63
+ voice_dir = default_model_dir()
64
+ if voice_dir.is_dir():
65
+ candidates = sorted(voice_dir.glob("*.bin"), key=lambda x: x.stat().st_size)
66
+ if candidates:
67
+ return candidates[0]
68
+ return None
69
+
70
+
71
+ def is_available() -> bool:
72
+ """Cheap probe: True iff transcription would succeed without raising."""
73
+ if os.environ.get("SPECSMITH_VOICE_STUB", "").strip():
74
+ return True
75
+ try:
76
+ import whisper_cpp_python # noqa: F401 (presence-only check)
77
+ except Exception: # noqa: BLE001
78
+ return False
79
+ return _resolve_model_path() is not None
80
+
81
+
82
+ def transcribe(path: Path) -> TranscribeResult:
83
+ """Transcribe a wav/flac/mp3 file to text.
84
+
85
+ Order of resolution:
86
+ 1. If ``SPECSMITH_VOICE_STUB`` is set, return its value verbatim. This
87
+ lets tests run without a model file.
88
+ 2. Otherwise import ``whisper_cpp_python`` and run a real transcription.
89
+ 3. If neither is available, raise :class:`VoiceUnavailableError` with
90
+ an actionable message.
91
+ """
92
+ import time as _time
93
+
94
+ if not path.exists():
95
+ raise FileNotFoundError(f"audio file not found: {path}")
96
+
97
+ stub = os.environ.get("SPECSMITH_VOICE_STUB", "").strip()
98
+ if stub:
99
+ return TranscribeResult(text=stub, backend="stub")
100
+
101
+ try:
102
+ import whisper_cpp_python
103
+ except Exception as exc: # noqa: BLE001
104
+ raise VoiceUnavailableError(
105
+ "whisper-cpp-python is not installed. Run "
106
+ "`pipx inject specsmith whisper-cpp-python` "
107
+ "(or `pip install specsmith[voice]`)."
108
+ ) from exc
109
+
110
+ model_path = _resolve_model_path()
111
+ if model_path is None:
112
+ raise VoiceUnavailableError(
113
+ "No whisper model found. Set SPECSMITH_VOICE_MODEL or place a "
114
+ f".bin model under {default_model_dir()}."
115
+ )
116
+
117
+ start = _time.perf_counter()
118
+ whisper = whisper_cpp_python.Whisper(model_path=str(model_path))
119
+ out = whisper.transcribe(str(path))
120
+ text = out.get("text") if isinstance(out, dict) else str(out)
121
+ return TranscribeResult(
122
+ text=str(text or "").strip(),
123
+ backend="whisper-cpp",
124
+ model=model_path.name,
125
+ duration_s=_time.perf_counter() - start,
126
+ )
127
+
128
+
129
+ __all__ = [
130
+ "TranscribeResult",
131
+ "VoiceUnavailableError",
132
+ "default_model_dir",
133
+ "is_available",
134
+ "transcribe",
135
+ ]
@@ -0,0 +1,106 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 BitConcepts, LLC. All rights reserved.
3
+ """Per-block share/export for `specsmith chat` (REQ-134).
4
+
5
+ Reads ``.specsmith/sessions/<session_id>/events.jsonl`` (the chat replay log
6
+ or, fallback, ``turns.jsonl``) and slices a single block out as a
7
+ self-contained Markdown / JSON / HTML snippet.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import html
13
+ import json
14
+ from pathlib import Path
15
+ from typing import Any
16
+
17
+
18
+ def _events_path(project_dir: Path, session_id: str) -> Path | None:
19
+ base = project_dir / ".specsmith" / "sessions" / session_id
20
+ candidates = [
21
+ base / "events.jsonl",
22
+ base / "turns.jsonl",
23
+ ]
24
+ for c in candidates:
25
+ if c.is_file():
26
+ return c
27
+ return None
28
+
29
+
30
+ def _read_events(events_path: Path) -> list[dict[str, Any]]:
31
+ out: list[dict[str, Any]] = []
32
+ for line in events_path.read_text(encoding="utf-8").splitlines():
33
+ line = line.strip()
34
+ if not line:
35
+ continue
36
+ try:
37
+ obj = json.loads(line)
38
+ except ValueError:
39
+ continue
40
+ if isinstance(obj, dict):
41
+ out.append(obj)
42
+ return out
43
+
44
+
45
+ def slice_block(events: list[dict[str, Any]], block_id: str) -> list[dict[str, Any]]:
46
+ """Return all events tagged with ``block_id``, plus the bracketing
47
+ block_start/block_complete events that defined it.
48
+ """
49
+ out: list[dict[str, Any]] = []
50
+ for evt in events:
51
+ if evt.get("block_id") == block_id or evt.get("id") == block_id:
52
+ out.append(evt)
53
+ return out
54
+
55
+
56
+ def export_block(
57
+ project_dir: Path,
58
+ session_id: str,
59
+ block_id: str,
60
+ *,
61
+ fmt: str = "md",
62
+ ) -> str:
63
+ """Export the events for ``block_id`` as a string in ``fmt``.
64
+
65
+ Raises FileNotFoundError if no session log exists.
66
+ Raises KeyError if the block is not found.
67
+ """
68
+ events_path = _events_path(project_dir, session_id)
69
+ if events_path is None:
70
+ raise FileNotFoundError(f"No session log for {session_id} in {project_dir}")
71
+ events = _read_events(events_path)
72
+ matching = slice_block(events, block_id)
73
+ if not matching:
74
+ raise KeyError(f"block_id {block_id} not found in session {session_id}")
75
+ if fmt == "json":
76
+ return json.dumps(matching, indent=2)
77
+ if fmt == "html":
78
+ rows = "".join(
79
+ f"<li><pre>{html.escape(json.dumps(evt, indent=2))}</pre></li>" for evt in matching
80
+ )
81
+ return (
82
+ f"<!DOCTYPE html><html><head><meta charset='utf-8'>"
83
+ f"<title>specsmith block {html.escape(block_id)}</title></head>"
84
+ f"<body><h1>Block {html.escape(block_id)}</h1>"
85
+ f"<p>session {html.escape(session_id)}</p><ol>{rows}</ol></body></html>"
86
+ )
87
+ # default: markdown
88
+ lines: list[str] = [
89
+ f"# Block `{block_id}`",
90
+ f"_session_: `{session_id}`",
91
+ "",
92
+ ]
93
+ for evt in matching:
94
+ kind = str(evt.get("type", "event"))
95
+ lines.append(f"## {kind}")
96
+ if "text" in evt:
97
+ lines.append(str(evt["text"]))
98
+ else:
99
+ lines.append("```json")
100
+ lines.append(json.dumps(evt, indent=2))
101
+ lines.append("```")
102
+ lines.append("")
103
+ return "\n".join(lines)
104
+
105
+
106
+ __all__ = ["export_block", "slice_block"]