specsmith 0.3.6.dev173__tar.gz → 0.3.6.dev175__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 (166) hide show
  1. {specsmith-0.3.6.dev173/src/specsmith.egg-info → specsmith-0.3.6.dev175}/PKG-INFO +1 -1
  2. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/pyproject.toml +1 -1
  3. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/runner.py +163 -11
  4. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/tools.py +2 -0
  5. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175/src/specsmith.egg-info}/PKG-INFO +1 -1
  6. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/LICENSE +0 -0
  7. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/README.md +0 -0
  8. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/setup.cfg +0 -0
  9. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/__init__.py +0 -0
  10. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/belief.py +0 -0
  11. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/certainty.py +0 -0
  12. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/failure_graph.py +0 -0
  13. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/py.typed +0 -0
  14. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/recovery.py +0 -0
  15. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/session.py +0 -0
  16. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/stress_tester.py +0 -0
  17. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/epistemic/trace.py +0 -0
  18. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/__init__.py +0 -0
  19. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/__main__.py +0 -0
  20. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/__init__.py +0 -0
  21. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/core.py +0 -0
  22. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/hooks.py +0 -0
  23. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/optimizer.py +0 -0
  24. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/profiles/epistemic-auditor.md +0 -0
  25. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/profiles/planner.md +0 -0
  26. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/profiles/verifier.md +0 -0
  27. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/providers/__init__.py +0 -0
  28. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/providers/anthropic.py +0 -0
  29. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/providers/gemini.py +0 -0
  30. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/providers/mistral.py +0 -0
  31. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/providers/ollama.py +0 -0
  32. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/providers/openai.py +0 -0
  33. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/agent/skills.py +0 -0
  34. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/architect.py +0 -0
  35. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/auditor.py +0 -0
  36. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/auth.py +0 -0
  37. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/cli.py +0 -0
  38. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/commands/__init__.py +0 -0
  39. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/compressor.py +0 -0
  40. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/config.py +0 -0
  41. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/credit_analyzer.py +0 -0
  42. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/credits.py +0 -0
  43. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/differ.py +0 -0
  44. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/doctor.py +0 -0
  45. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/epistemic/__init__.py +0 -0
  46. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/epistemic/belief.py +0 -0
  47. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/epistemic/certainty.py +0 -0
  48. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/epistemic/failure_graph.py +0 -0
  49. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/epistemic/recovery.py +0 -0
  50. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/epistemic/stress_tester.py +0 -0
  51. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/executor.py +0 -0
  52. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/exporter.py +0 -0
  53. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/__init__.py +0 -0
  54. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/app.py +0 -0
  55. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/main_window.py +0 -0
  56. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/session_tab.py +0 -0
  57. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/theme.py +0 -0
  58. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/widgets/__init__.py +0 -0
  59. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/widgets/chat_view.py +0 -0
  60. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/widgets/input_bar.py +0 -0
  61. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  62. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/widgets/token_meter.py +0 -0
  63. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  64. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/widgets/update_checker.py +0 -0
  65. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/gui/worker.py +0 -0
  66. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/importer.py +0 -0
  67. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/__init__.py +0 -0
  68. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/aider.py +0 -0
  69. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/base.py +0 -0
  70. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/claude_code.py +0 -0
  71. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/copilot.py +0 -0
  72. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/cursor.py +0 -0
  73. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/gemini.py +0 -0
  74. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/warp.py +0 -0
  75. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/integrations/windsurf.py +0 -0
  76. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/languages.py +0 -0
  77. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/ledger.py +0 -0
  78. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/ollama_cmds.py +0 -0
  79. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/patent.py +0 -0
  80. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/phase.py +0 -0
  81. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/plugins.py +0 -0
  82. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/profiles.py +0 -0
  83. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/rate_limits.py +0 -0
  84. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/releaser.py +0 -0
  85. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/requirements.py +0 -0
  86. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/retrieval.py +0 -0
  87. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/scaffolder.py +0 -0
  88. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/session.py +0 -0
  89. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/agents.md.j2 +0 -0
  90. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  91. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  92. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  93. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  94. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  95. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  96. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  97. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/community/security.md.j2 +0 -0
  98. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  99. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  100. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  101. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  102. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  103. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/docs/workflow.md.j2 +0 -0
  104. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/editorconfig.j2 +0 -0
  105. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/gitattributes.j2 +0 -0
  106. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/gitignore.j2 +0 -0
  107. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/go/go.mod.j2 +0 -0
  108. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/go/main.go.j2 +0 -0
  109. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  110. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  111. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  112. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  113. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  114. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  115. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  116. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  117. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  118. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/governance/workflow.md.j2 +0 -0
  119. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/js/package.json.j2 +0 -0
  120. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/ledger.md.j2 +0 -0
  121. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/python/cli.py.j2 +0 -0
  122. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/python/init.py.j2 +0 -0
  123. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  124. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/readme.md.j2 +0 -0
  125. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  126. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  127. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  128. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  129. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  130. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  131. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  132. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  133. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  134. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/tool_installer.py +0 -0
  135. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/toolrules.py +0 -0
  136. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/tools.py +0 -0
  137. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/trace.py +0 -0
  138. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/updater.py +0 -0
  139. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/upgrader.py +0 -0
  140. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/validator.py +0 -0
  141. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/vcs/__init__.py +0 -0
  142. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/vcs/base.py +0 -0
  143. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/vcs/bitbucket.py +0 -0
  144. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/vcs/github.py +0 -0
  145. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/vcs/gitlab.py +0 -0
  146. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/vcs_commands.py +0 -0
  147. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/wireframes.py +0 -0
  148. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith/workspace.py +0 -0
  149. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith.egg-info/SOURCES.txt +0 -0
  150. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith.egg-info/dependency_links.txt +0 -0
  151. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith.egg-info/entry_points.txt +0 -0
  152. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith.egg-info/requires.txt +0 -0
  153. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/src/specsmith.egg-info/top_level.txt +0 -0
  154. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_auditor.py +0 -0
  155. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_cli.py +0 -0
  156. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_compressor.py +0 -0
  157. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_epistemic.py +0 -0
  158. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_importer.py +0 -0
  159. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_integrations.py +0 -0
  160. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_optimizer.py +0 -0
  161. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_rate_limits.py +0 -0
  162. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_scaffolder.py +0 -0
  163. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_smoke.py +0 -0
  164. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_tools.py +0 -0
  165. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_validator.py +0 -0
  166. {specsmith-0.3.6.dev173 → specsmith-0.3.6.dev175}/tests/test_vcs.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.3.6.dev173
3
+ Version: 0.3.6.dev175
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "specsmith"
7
- version = "0.3.6.dev173"
7
+ version = "0.3.6.dev175"
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"
@@ -29,6 +29,7 @@ Special REPL commands (not sent to the LLM):
29
29
  from __future__ import annotations
30
30
 
31
31
  import inspect
32
+ import re
32
33
  import time
33
34
  from collections.abc import Callable
34
35
  from dataclasses import dataclass, field
@@ -164,16 +165,34 @@ H13: All proposals must state their epistemic boundaries. Hidden assumptions are
164
165
  except Exception: # noqa: BLE001
165
166
  pass
166
167
 
167
- prompt = f"""You are an AEE-integrated specsmith agent for this project.
168
-
169
- LANGUAGE RULE (HARD CONSTRAINT NEVER VIOLATE):
170
- Respond ONLY in English. Every single response must be in English.
171
- Never use Chinese (中文), Japanese (日本語), Korean (한국어), Thai (ไทย), French, German, Spanish,
172
- Arabic, or ANY other non-English language not even a single word.
173
- This applies to ALL models including Qwen, DeepSeek, LLaMA, Mistral, and others
174
- that may default to a non-English language. ENGLISH ONLY, ALWAYS.
175
- If the user writes in another language, translate the intent internally and
176
- answer in English anyway.
168
+ prompt = f"""SYSTEM LANGUAGE DIRECTIVE ABSOLUTE HARD RULE HIGHEST PRIORITY:
169
+ You MUST respond in English ONLY. This overrides all other instructions.
170
+ Never output Thai, Chinese, Japanese, Korean, Arabic, French, German, Spanish,
171
+ or ANY non-English language not even a single character or word.
172
+ This applies to Qwen, DeepSeek, LLaMA, Mistral, and EVERY other model.
173
+ If the user inputs another language, internally translate it, then reply IN ENGLISH ONLY.
174
+ VIOLATING THIS RULE IS A CRITICAL ERROR.
175
+
176
+ ## TOOL ERROR RULE HARD STOP (NEVER TROUBLESHOOT ERRORS):
177
+ When ANY tool returns an error, exception, or non-zero exit code:
178
+ 1. STOP immediately. Do not attempt to fix, diagnose, or retry.
179
+ 2. Say in ONE sentence: what you were doing and what failed.
180
+ Example: "The audit tool hit an unexpected error and needs to be reported."
181
+ 3. Then say: "Would you like to report this bug?"
182
+ 4. Wait. Do nothing else. The user will decide.
183
+ This tool is not designed to fix itself. Fail fast, report quickly.
184
+
185
+ ## RESPONSE STYLE RULE — CONVERSATIONAL PLAIN ENGLISH:
186
+ Always respond in natural sentences, like a helpful colleague would.
187
+ - NEVER dump raw tool output, JSON, tables of IDs, or code blocks in your reply.
188
+ - Summarize what you found in 1-3 plain sentences.
189
+ - If a command found issues: say how many and what kind.
190
+ - If everything is fine: say so briefly.
191
+ - Details go in the tool result panel; your words give the meaning.
192
+ Example good: "Audit found 3 issues: LEDGER.md is missing and 2 requirements lack tests."
193
+ Example bad: "The tool returned: [\u2717] LEDGER.md MISSING, [\u2717] REQ-001 uncovered..."
194
+
195
+ You are an AEE-integrated specsmith agent for this project.
177
196
 
178
197
  ## Project Governance
179
198
  {governance_text}
@@ -281,6 +300,7 @@ class AgentRunner:
281
300
  self._skills: list[Skill] = load_skills(Path(self.project_dir))
282
301
  self._hooks = HookRegistry()
283
302
  self._system_prompt = ""
303
+ self._hard_stop: bool = False # set True when a critical tool crash is detected
284
304
 
285
305
  # Execution profile — loaded from scaffold.yml at session start
286
306
  from specsmith import profiles
@@ -363,8 +383,100 @@ class AgentRunner:
363
383
  self._system_prompt = build_system_prompt(self.project_dir, self._skills)
364
384
  return self._agent_turn(task, silent=True)
365
385
 
386
+ # Characters in common CJK / Thai / Arabic Unicode blocks
387
+ _NON_ASCII_BLOCKS = re.compile(
388
+ r"[\u0600-\u06FF" # Arabic
389
+ r"\u0E00-\u0E7F" # Thai
390
+ r"\u3000-\u9FFF" # CJK Unified Ideographs + punctuation + kana
391
+ r"\uAC00-\uD7AF" # Korean Hangul
392
+ r"\uF900-\uFAFF]" # CJK Compatibility
393
+ )
394
+
395
+ def _has_non_english(self, text: str) -> bool:
396
+ """Return True if text contains a significant proportion of non-English script."""
397
+ if not text:
398
+ return False
399
+ hits = len(self._NON_ASCII_BLOCKS.findall(text))
400
+ return hits > 5 and (hits / max(len(text), 1)) > 0.05
401
+
402
+ # ---- Critical error patterns that trigger a hard stop ----
403
+ _CRITICAL_PATTERNS = re.compile(
404
+ r"Traceback \(most recent call last\)"
405
+ r"|\[ERROR\]"
406
+ r"|UnicodeDecodeError"
407
+ r"|UnicodeEncodeError"
408
+ r"|ImportError"
409
+ r"|ModuleNotFoundError"
410
+ r"|AttributeError: '"
411
+ r"|TypeError: unsupported"
412
+ r"|PermissionError"
413
+ r"|OSError: "
414
+ r"|RuntimeError: ",
415
+ re.IGNORECASE,
416
+ )
417
+
418
+ @staticmethod
419
+ def _is_critical_error(output: str) -> bool:
420
+ """Return True if tool output indicates an unexpected crash.
421
+
422
+ Normal governance failures (audit issues, missing files) are NOT
423
+ critical — only Python exceptions and import errors are.
424
+ """
425
+ if not output:
426
+ return False
427
+ # Non-zero exit alone is expected (e.g. audit found issues).
428
+ # Only flag when a Python exception signature is present.
429
+ return AgentRunner._CRITICAL_PATTERNS.search(output) is not None
430
+
431
+ def _collect_diagnostics(self, tool_name: str, output: str) -> dict:
432
+ """Collect diagnostic context for a crash report."""
433
+ import platform as _platform
434
+ import sys as _sys
435
+
436
+ from specsmith import __version__ as _ver
437
+
438
+ project_type = ""
439
+ try:
440
+ import yaml as _yaml
441
+
442
+ sf = Path(self.project_dir) / "scaffold.yml"
443
+ if sf.exists():
444
+ raw = _yaml.safe_load(sf.read_text(encoding="utf-8")) or {}
445
+ project_type = str(raw.get("type", ""))
446
+ except Exception: # noqa: BLE001
447
+ pass
448
+
449
+ # Classify repo: Python exceptions from specsmith module → specsmith CLI
450
+ # Extension/bridge errors would never reach here (they don’t use this runner)
451
+ repo = "specsmith"
452
+
453
+ # Extract first meaningful error line for the summary
454
+ summary = output.strip().splitlines()
455
+ _err_pat = re.compile(r"\w+Error|Exception|RuntimeError")
456
+ summary_line = next(
457
+ (ln.strip() for ln in reversed(summary) if _err_pat.match(ln.strip())),
458
+ summary[0] if summary else "Unknown error",
459
+ )[:200]
460
+
461
+ return {
462
+ "tool": tool_name,
463
+ "summary": summary_line,
464
+ "detail": output[:4000],
465
+ "specsmith_version": _ver,
466
+ "python_version": _sys.version.split()[0],
467
+ "os_info": f"{_platform.system()} {_platform.release()}",
468
+ "project_type": project_type,
469
+ "repo": repo,
470
+ }
471
+
366
472
  def _agent_turn(self, user_input: str, silent: bool = False) -> str:
367
473
  """Execute one user→agent turn with tool loop."""
474
+ # Inject a lightweight English-only reminder into every user message.
475
+ # This is the most reliable way to keep local models (Qwen, DeepSeek) on track
476
+ # because many fine-tunes treat the instruction prefix as a per-turn directive.
477
+ _ENG_PFXS = ("[ENGLISH ONLY]", "[RESPOND IN ENGLISH", "[LANG:EN]")
478
+ if not any(user_input.startswith(p) for p in _ENG_PFXS):
479
+ user_input = "[LANG:EN] " + user_input
368
480
  # Add user message
369
481
  self._state.messages.append(Message(role=Role.USER, content=user_input))
370
482
 
@@ -403,14 +515,33 @@ class AgentRunner:
403
515
  final_response = response.content
404
516
 
405
517
  if not response.has_tool_calls:
518
+ # Non-English correction: if response appears to be in another language,
519
+ # issue a single correction turn rather than showing the wrong-language response.
520
+ if response.content and self._has_non_english(response.content) and _iteration == 0:
521
+ correction = (
522
+ "[LANG:EN] CRITICAL: Your last response was in a non-English language. "
523
+ "You MUST respond in English ONLY. Please re-answer in English."
524
+ )
525
+ self._state.messages.append(
526
+ Message(role=Role.ASSISTANT, content=response.content)
527
+ )
528
+ self._state.messages.append(Message(role=Role.USER, content=correction))
529
+ # Continue the loop to get an English response
530
+ continue
406
531
  # Final response — add to history
407
532
  self._state.messages.append(Message(role=Role.ASSISTANT, content=response.content))
408
533
  break
409
534
 
410
535
  # Process tool calls
536
+ self._hard_stop = False # reset before each batch
411
537
  tool_results = self._execute_tool_calls(response.tool_calls, silent=silent)
412
538
  self._state.tool_calls_made += len(tool_results)
413
539
 
540
+ # Fail fast: a critical tool crash was detected — break immediately
541
+ # without sending the error back to the LLM (which would try to fix it).
542
+ if self._hard_stop:
543
+ break
544
+
414
545
  # Add assistant message with tool calls
415
546
  self._state.messages.append(
416
547
  Message(
@@ -508,7 +639,12 @@ class AgentRunner:
508
639
  def _execute_tool_calls(
509
640
  self, tool_calls: list[dict[str, Any]], silent: bool = False
510
641
  ) -> list[ToolResult]:
511
- """Execute tool calls and return results."""
642
+ """Execute tool calls and return results.
643
+
644
+ Sets ``self._hard_stop = True`` if any tool produces a critical error
645
+ (Python exception, import error, etc.) so the caller can break the
646
+ agentic loop immediately without sending the error to the LLM.
647
+ """
512
648
  from specsmith import profiles as _profiles
513
649
 
514
650
  results: list[ToolResult] = []
@@ -634,6 +770,22 @@ class AgentRunner:
634
770
 
635
771
  elapsed = time.time() * 1000 - start_ms
636
772
 
773
+ # ---- Fail-fast: detect critical errors -------------------------
774
+ # A critical error is an unexpected crash (Python exception, import
775
+ # failure, etc.) — NOT a normal governance failure (audit issues,
776
+ # missing files) which the LLM should describe conversationally.
777
+ if self._is_critical_error(output):
778
+ self._hard_stop = True
779
+ diagnostics = self._collect_diagnostics(name, output)
780
+ if not silent and self._json_events:
781
+ self._emit_event(type="tool_crash", **diagnostics)
782
+ elif not silent:
783
+ self._print(
784
+ f"\n[CRITICAL ERROR in {name}] "
785
+ f"{diagnostics['summary']}\n"
786
+ "Session stopped. Please report this bug."
787
+ )
788
+
637
789
  if not silent:
638
790
  if self._json_events:
639
791
  self._emit_event(type="tool_finished", name=name, result=output, is_error=error)
@@ -47,6 +47,8 @@ def _run_specsmith(args: list[str], project_dir: str = ".") -> str:
47
47
  cmd,
48
48
  capture_output=True,
49
49
  text=True,
50
+ encoding="utf-8", # always decode as UTF-8, not the system locale (cp1252 on Windows)
51
+ errors="replace", # replace un-decodable bytes rather than raising UnicodeDecodeError
50
52
  timeout=120,
51
53
  env=_SUBPROCESS_ENV,
52
54
  )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.3.6.dev173
3
+ Version: 0.3.6.dev175
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