specsmith 0.3.6.dev171__tar.gz → 0.3.6.dev173__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.dev171/src/specsmith.egg-info → specsmith-0.3.6.dev173}/PKG-INFO +1 -1
  2. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/pyproject.toml +1 -1
  3. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/runner.py +17 -11
  4. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/tools.py +49 -0
  5. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/cli.py +117 -0
  6. specsmith-0.3.6.dev173/src/specsmith/retrieval.py +118 -0
  7. specsmith-0.3.6.dev173/src/specsmith/wireframes.py +86 -0
  8. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173/src/specsmith.egg-info}/PKG-INFO +1 -1
  9. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith.egg-info/SOURCES.txt +2 -0
  10. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/LICENSE +0 -0
  11. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/README.md +0 -0
  12. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/setup.cfg +0 -0
  13. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/__init__.py +0 -0
  14. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/belief.py +0 -0
  15. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/certainty.py +0 -0
  16. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/failure_graph.py +0 -0
  17. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/py.typed +0 -0
  18. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/recovery.py +0 -0
  19. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/session.py +0 -0
  20. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/stress_tester.py +0 -0
  21. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/epistemic/trace.py +0 -0
  22. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/__init__.py +0 -0
  23. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/__main__.py +0 -0
  24. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/__init__.py +0 -0
  25. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/core.py +0 -0
  26. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/hooks.py +0 -0
  27. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/optimizer.py +0 -0
  28. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/profiles/epistemic-auditor.md +0 -0
  29. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/profiles/planner.md +0 -0
  30. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/profiles/verifier.md +0 -0
  31. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/providers/__init__.py +0 -0
  32. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/providers/anthropic.py +0 -0
  33. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/providers/gemini.py +0 -0
  34. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/providers/mistral.py +0 -0
  35. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/providers/ollama.py +0 -0
  36. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/providers/openai.py +0 -0
  37. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/agent/skills.py +0 -0
  38. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/architect.py +0 -0
  39. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/auditor.py +0 -0
  40. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/auth.py +0 -0
  41. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/commands/__init__.py +0 -0
  42. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/compressor.py +0 -0
  43. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/config.py +0 -0
  44. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/credit_analyzer.py +0 -0
  45. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/credits.py +0 -0
  46. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/differ.py +0 -0
  47. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/doctor.py +0 -0
  48. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/epistemic/__init__.py +0 -0
  49. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/epistemic/belief.py +0 -0
  50. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/epistemic/certainty.py +0 -0
  51. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/epistemic/failure_graph.py +0 -0
  52. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/epistemic/recovery.py +0 -0
  53. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/epistemic/stress_tester.py +0 -0
  54. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/executor.py +0 -0
  55. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/exporter.py +0 -0
  56. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/__init__.py +0 -0
  57. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/app.py +0 -0
  58. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/main_window.py +0 -0
  59. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/session_tab.py +0 -0
  60. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/theme.py +0 -0
  61. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/widgets/__init__.py +0 -0
  62. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/widgets/chat_view.py +0 -0
  63. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/widgets/input_bar.py +0 -0
  64. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  65. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/widgets/token_meter.py +0 -0
  66. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  67. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/widgets/update_checker.py +0 -0
  68. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/gui/worker.py +0 -0
  69. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/importer.py +0 -0
  70. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/__init__.py +0 -0
  71. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/aider.py +0 -0
  72. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/base.py +0 -0
  73. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/claude_code.py +0 -0
  74. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/copilot.py +0 -0
  75. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/cursor.py +0 -0
  76. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/gemini.py +0 -0
  77. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/warp.py +0 -0
  78. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/integrations/windsurf.py +0 -0
  79. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/languages.py +0 -0
  80. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/ledger.py +0 -0
  81. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/ollama_cmds.py +0 -0
  82. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/patent.py +0 -0
  83. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/phase.py +0 -0
  84. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/plugins.py +0 -0
  85. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/profiles.py +0 -0
  86. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/rate_limits.py +0 -0
  87. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/releaser.py +0 -0
  88. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/requirements.py +0 -0
  89. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/scaffolder.py +0 -0
  90. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/session.py +0 -0
  91. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/agents.md.j2 +0 -0
  92. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  93. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  94. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  95. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  96. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  97. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  98. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  99. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/community/security.md.j2 +0 -0
  100. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  101. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  102. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  103. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  104. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  105. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/docs/workflow.md.j2 +0 -0
  106. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/editorconfig.j2 +0 -0
  107. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/gitattributes.j2 +0 -0
  108. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/gitignore.j2 +0 -0
  109. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/go/go.mod.j2 +0 -0
  110. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/go/main.go.j2 +0 -0
  111. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  112. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  113. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  114. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  115. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  116. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  117. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  118. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  119. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  120. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/governance/workflow.md.j2 +0 -0
  121. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/js/package.json.j2 +0 -0
  122. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/ledger.md.j2 +0 -0
  123. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/python/cli.py.j2 +0 -0
  124. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/python/init.py.j2 +0 -0
  125. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  126. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/readme.md.j2 +0 -0
  127. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  128. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  129. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  130. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  131. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  132. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  133. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  134. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  135. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  136. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/tool_installer.py +0 -0
  137. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/toolrules.py +0 -0
  138. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/tools.py +0 -0
  139. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/trace.py +0 -0
  140. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/updater.py +0 -0
  141. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/upgrader.py +0 -0
  142. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/validator.py +0 -0
  143. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/vcs/__init__.py +0 -0
  144. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/vcs/base.py +0 -0
  145. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/vcs/bitbucket.py +0 -0
  146. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/vcs/github.py +0 -0
  147. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/vcs/gitlab.py +0 -0
  148. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/vcs_commands.py +0 -0
  149. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith/workspace.py +0 -0
  150. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith.egg-info/dependency_links.txt +0 -0
  151. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith.egg-info/entry_points.txt +0 -0
  152. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith.egg-info/requires.txt +0 -0
  153. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/src/specsmith.egg-info/top_level.txt +0 -0
  154. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_auditor.py +0 -0
  155. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_cli.py +0 -0
  156. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_compressor.py +0 -0
  157. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_epistemic.py +0 -0
  158. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_importer.py +0 -0
  159. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_integrations.py +0 -0
  160. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_optimizer.py +0 -0
  161. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_rate_limits.py +0 -0
  162. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_scaffolder.py +0 -0
  163. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_smoke.py +0 -0
  164. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_tools.py +0 -0
  165. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/tests/test_validator.py +0 -0
  166. {specsmith-0.3.6.dev171 → specsmith-0.3.6.dev173}/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.dev171
3
+ Version: 0.3.6.dev173
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.dev171"
7
+ version = "0.3.6.dev173"
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"
@@ -168,10 +168,12 @@ H13: All proposals must state their epistemic boundaries. Hidden assumptions are
168
168
 
169
169
  ⚠ LANGUAGE RULE (HARD CONSTRAINT — NEVER VIOLATE):
170
170
  Respond ONLY in English. Every single response must be in English.
171
- Never use Chinese (中文), Japanese (日本語), Korean (한국어), French, German, Spanish,
171
+ Never use Chinese (中文), Japanese (日本語), Korean (한국어), Thai (ไทย), French, German, Spanish,
172
172
  Arabic, or ANY other non-English language — not even a single word.
173
173
  This applies to ALL models including Qwen, DeepSeek, LLaMA, Mistral, and others
174
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.
175
177
 
176
178
  ## Project Governance
177
179
  {governance_text}
@@ -236,17 +238,21 @@ class AgentRunner:
236
238
  QUICK_COMMANDS = {
237
239
  "start": (
238
240
  "[RESPOND IN ENGLISH ONLY] "
239
- "Run session start protocol: sync, load AGENTS.md, read last LEDGER.md entries"
241
+ "Run session start protocol: sync, load AGENTS.md, read last LEDGER.md entries. "
242
+ "Translate any non-English context internally if needed, but respond only in English."
240
243
  ),
241
- "resume": "Resume from last LEDGER.md entry — summarize state and propose next task",
242
- "save": "Write a ledger entry summarizing this session's work",
243
- "audit": "Run specsmith audit --fix",
244
- "commit": "Run specsmith commit",
245
- "push": "Run specsmith push",
246
- "sync": "Run specsmith sync",
247
- "epistemic": "Run full epistemic audit",
248
- "stress": "Run stress-test on requirements",
249
- "status": "Show session status and credit spend",
244
+ "resume": (
245
+ "[RESPOND IN ENGLISH ONLY] Resume from last LEDGER.md entry"
246
+ " summarize state and propose next task"
247
+ ),
248
+ "save": "[RESPOND IN ENGLISH ONLY] Write a ledger entry summarizing this session's work",
249
+ "audit": "[RESPOND IN ENGLISH ONLY] Run specsmith audit --fix",
250
+ "commit": "[RESPOND IN ENGLISH ONLY] Run specsmith commit",
251
+ "push": "[RESPOND IN ENGLISH ONLY] Run specsmith push",
252
+ "sync": "[RESPOND IN ENGLISH ONLY] Run specsmith sync",
253
+ "epistemic": "[RESPOND IN ENGLISH ONLY] Run full epistemic audit",
254
+ "stress": "[RESPOND IN ENGLISH ONLY] Run stress-test on requirements",
255
+ "status": "[RESPOND IN ENGLISH ONLY] Show session status and credit spend",
250
256
  }
251
257
 
252
258
  def __init__(
@@ -34,6 +34,8 @@ _SUBPROCESS_ENV: dict[str, str] = {
34
34
  "NO_COLOR": "1", # Disables Rich colour / Windows console API path
35
35
  "FORCE_COLOR": "0", # Belt-and-suspenders: also suppress colour
36
36
  "PYTHONIOENCODING": "utf-8", # Ensure UTF-8 on pipes regardless of locale
37
+ "PYTHONUTF8": "1",
38
+ "PYTHONLEGACYWINDOWSSTDIO": "utf-8",
37
39
  }
38
40
 
39
41
 
@@ -58,6 +60,30 @@ def _run_specsmith(args: list[str], project_dir: str = ".") -> str:
58
60
  return f"[ERROR] {e}"
59
61
 
60
62
 
63
+ def _read_wireframe_handler(project_dir: str, wireframe_id: str) -> str:
64
+ """Read wireframe metadata or inline text/SVG content."""
65
+ try:
66
+ from specsmith.wireframes import read_wireframe
67
+
68
+ return read_wireframe(Path(project_dir).resolve(), wireframe_id)
69
+ except Exception as e: # noqa: BLE001
70
+ return f"[ERROR] {e}"
71
+
72
+
73
+ def _retrieve_context_handler(project_dir: str, query: str, limit: str = "5") -> str:
74
+ """Search the opt-in local retrieval index."""
75
+ try:
76
+ from specsmith.retrieval import search_index
77
+
78
+ try:
79
+ max_results = max(1, min(int(limit), 20))
80
+ except (TypeError, ValueError):
81
+ max_results = 5
82
+ return search_index(Path(project_dir).resolve(), query, limit=max_results)
83
+ except Exception as e: # noqa: BLE001
84
+ return f"[ERROR] {e}"
85
+
86
+
61
87
  def build_tool_registry(project_dir: str = ".") -> list[Tool]:
62
88
  """Build the full specsmith tool registry for the agentic client.
63
89
 
@@ -303,6 +329,29 @@ def build_tool_registry(project_dir: str = ".") -> list[Tool]:
303
329
  params=[],
304
330
  handler=lambda: _run_specsmith(["req", "trace"], pd),
305
331
  ),
332
+ Tool(
333
+ name="read_wireframe",
334
+ description=(
335
+ "Resolve and inspect a wireframe artifact under docs/wireframes. "
336
+ "Returns metadata and, for SVG/text assets, inline content snippets."
337
+ ),
338
+ params=[
339
+ ToolParam("wireframe_id", "Wireframe ID or filename, e.g. WF-UI-001"),
340
+ ],
341
+ handler=lambda wireframe_id: _read_wireframe_handler(pd, wireframe_id),
342
+ ),
343
+ Tool(
344
+ name="retrieve_context",
345
+ description=(
346
+ "Search the explicit local retrieval index (opt-in) for relevant project "
347
+ "context across docs, ledger, and indexed source files."
348
+ ),
349
+ params=[
350
+ ToolParam("query", "Search query"),
351
+ ToolParam("limit", "Max results (default 5)", required=False),
352
+ ],
353
+ handler=lambda query, limit="5": _retrieve_context_handler(pd, query, limit),
354
+ ),
306
355
  # ----------------------------------------------------------------
307
356
  # Session tools
308
357
  # ----------------------------------------------------------------
@@ -4240,5 +4240,122 @@ def tools_rules_cmd(project_dir: str, tool_key: str, list_all: bool) -> None:
4240
4240
  main.add_command(tools_group)
4241
4241
 
4242
4242
 
4243
+ # ---------------------------------------------------------------------------
4244
+ # Wireframes — UI wireframe artifact management
4245
+ # ---------------------------------------------------------------------------
4246
+
4247
+
4248
+ @main.group(name="wireframes")
4249
+ def wireframes_group() -> None:
4250
+ """Manage wireframe artifacts under docs/wireframes/."""
4251
+
4252
+
4253
+ @wireframes_group.command(name="list")
4254
+ @click.option("--project-dir", type=click.Path(exists=True), default=".")
4255
+ def wireframes_list_cmd(project_dir: str) -> None:
4256
+ """List wireframe files and their requirement references."""
4257
+ from specsmith.wireframes import list_wireframes
4258
+
4259
+ root = Path(project_dir).resolve()
4260
+ items = list_wireframes(root)
4261
+ if not items:
4262
+ console.print("[yellow]No wireframes found in docs/wireframes/.[/yellow]")
4263
+ console.print(" Create wireframe files there (SVG, PNG, PDF, etc.) and reference them")
4264
+ console.print(" from REQUIREMENTS.md via a `Wireframe` field in each requirement.")
4265
+ return
4266
+ console.print(f"[bold]Wireframes[/bold] ({len(items)})\n")
4267
+ for wf in items:
4268
+ refs_str = wf.get("refs", "")
4269
+ refs_note = f" ← {refs_str}" if refs_str else " [dim](unreferenced)[/dim]"
4270
+ console.print(f" [cyan]{wf['id']:20s}[/cyan] {wf['file']}{refs_note}")
4271
+
4272
+
4273
+ @wireframes_group.command(name="check")
4274
+ @click.option("--project-dir", type=click.Path(exists=True), default=".")
4275
+ def wireframes_check_cmd(project_dir: str) -> None:
4276
+ """Check for missing wireframe files referenced in REQUIREMENTS.md."""
4277
+ from specsmith.wireframes import check_wireframe_refs
4278
+
4279
+ root = Path(project_dir).resolve()
4280
+ missing = check_wireframe_refs(root)
4281
+ if not missing:
4282
+ console.print("[bold green]✓ All wireframe references are valid.[/bold green]")
4283
+ return
4284
+ console.print(f"[bold red]{len(missing)} missing wireframe reference(s):[/bold red]\n")
4285
+ for m in missing:
4286
+ console.print(f" [red]✗[/red] {m}")
4287
+ raise SystemExit(1)
4288
+
4289
+
4290
+ main.add_command(wireframes_group)
4291
+
4292
+
4293
+ # ---------------------------------------------------------------------------
4294
+ # Index — opt-in local retrieval index (RAG foundation)
4295
+ # ---------------------------------------------------------------------------
4296
+
4297
+
4298
+ @main.group(name="index")
4299
+ def index_group() -> None:
4300
+ """Manage the local retrieval index (explicit opt-in context retrieval).
4301
+
4302
+ This builds a keyword-searchable index of project docs and source files
4303
+ stored at .specsmith/retrieval-index.json. The agent tool `retrieve_context`
4304
+ queries this index — it is never searched automatically.
4305
+ """
4306
+
4307
+
4308
+ @index_group.command(name="build")
4309
+ @click.option("--project-dir", type=click.Path(exists=True), default=".")
4310
+ @click.option(
4311
+ "--include-ledger",
4312
+ is_flag=True,
4313
+ default=False,
4314
+ help="Also index LEDGER.md (often large — only useful for long-running projects).",
4315
+ )
4316
+ @click.option(
4317
+ "--external",
4318
+ default="",
4319
+ help="Path to an additional file or directory to include in the index.",
4320
+ )
4321
+ def index_build_cmd(project_dir: str, include_ledger: bool, external: str) -> None:
4322
+ """Build or refresh the local retrieval index.
4323
+
4324
+ Indexes governance docs (AGENTS.md, REQUIREMENTS.md, ARCHITECTURE.md, TEST_SPEC.md)
4325
+ and source files under src/, client/, server/, and shared/.
4326
+ Use --external to add external reference material.
4327
+ """
4328
+ from specsmith.retrieval import build_index
4329
+
4330
+ root = Path(project_dir).resolve()
4331
+ result = build_index(root, include_ledger=include_ledger, external=external)
4332
+ console.print(f"[green]✓[/green] {result}")
4333
+ console.print(
4334
+ "\n Agent tool: [bold]retrieve_context[/bold] now available in this project.\n"
4335
+ " Usage example: ask the agent 'search for requirements about authentication'."
4336
+ )
4337
+
4338
+
4339
+ @index_group.command(name="search")
4340
+ @click.argument("query")
4341
+ @click.option("--project-dir", type=click.Path(exists=True), default=".")
4342
+ @click.option("--limit", default=5, help="Maximum results to return (default: 5).")
4343
+ def index_search_cmd(query: str, project_dir: str, limit: int) -> None:
4344
+ """Search the local retrieval index.
4345
+
4346
+ QUERY: keyword search query
4347
+
4348
+ The index must be built first with `specsmith index build`.
4349
+ """
4350
+ from specsmith.retrieval import search_index
4351
+
4352
+ root = Path(project_dir).resolve()
4353
+ result = search_index(root, query, limit=limit)
4354
+ console.print(result)
4355
+
4356
+
4357
+ main.add_command(index_group)
4358
+
4359
+
4243
4360
  if __name__ == "__main__":
4244
4361
  main()
@@ -0,0 +1,118 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 BitConcepts, LLC. All rights reserved.
3
+ """Explicit opt-in local retrieval index (RAG foundation)."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import json
8
+ import re
9
+ from pathlib import Path
10
+
11
+ _INDEX_PATH = Path(".specsmith") / "retrieval-index.json"
12
+ _TEXT_EXTS = {
13
+ ".md",
14
+ ".txt",
15
+ ".py",
16
+ ".ts",
17
+ ".js",
18
+ ".json",
19
+ ".yaml",
20
+ ".yml",
21
+ ".toml",
22
+ ".go",
23
+ ".rs",
24
+ ".c",
25
+ ".cpp",
26
+ ".h",
27
+ ".java",
28
+ ".sh",
29
+ ".ps1",
30
+ ".cmd",
31
+ }
32
+ _SKIP_DIRS = {".git", "node_modules", "__pycache__", ".venv", "dist", "build", ".mypy_cache"}
33
+
34
+
35
+ def build_index(root: Path, *, include_ledger: bool = False, external: str = "") -> str:
36
+ """Build or refresh the local retrieval index."""
37
+ entries: list[dict[str, str]] = []
38
+ candidates: list[Path] = []
39
+
40
+ for rel in ["AGENTS.md", "docs/REQUIREMENTS.md", "docs/ARCHITECTURE.md", "docs/TEST_SPEC.md"]:
41
+ fp = root / rel
42
+ if fp.exists():
43
+ candidates.append(fp)
44
+ if include_ledger:
45
+ for rel in ["LEDGER.md", "docs/LEDGER.md"]:
46
+ fp = root / rel
47
+ if fp.exists():
48
+ candidates.append(fp)
49
+
50
+ ext_path = Path(external).resolve() if external else None
51
+ if ext_path and ext_path.exists():
52
+ if ext_path.is_file():
53
+ candidates.append(ext_path)
54
+ else:
55
+ for fp in ext_path.rglob("*"):
56
+ if fp.is_file() and fp.suffix.lower() in _TEXT_EXTS:
57
+ candidates.append(fp)
58
+
59
+ for src_dir in [root / "src", root / "client", root / "server", root / "shared"]:
60
+ if not src_dir.exists():
61
+ continue
62
+ for fp in src_dir.rglob("*"):
63
+ if (
64
+ fp.is_file()
65
+ and fp.suffix.lower() in _TEXT_EXTS
66
+ and not any(part in _SKIP_DIRS for part in fp.parts)
67
+ ):
68
+ candidates.append(fp)
69
+
70
+ for fp in sorted(set(candidates)):
71
+ try:
72
+ text = fp.read_text(encoding="utf-8", errors="ignore")
73
+ except Exception: # noqa: BLE001
74
+ continue
75
+ if not text.strip():
76
+ continue
77
+ entries.append(
78
+ {
79
+ "path": str(fp.relative_to(root)) if fp.is_relative_to(root) else str(fp),
80
+ "content": text[:12000],
81
+ }
82
+ )
83
+
84
+ index_path = root / _INDEX_PATH
85
+ index_path.parent.mkdir(parents=True, exist_ok=True)
86
+ index_path.write_text(json.dumps({"entries": entries}, indent=2), encoding="utf-8")
87
+ return f"Indexed {len(entries)} file(s) into {index_path.relative_to(root)}"
88
+
89
+
90
+ def search_index(root: Path, query: str, *, limit: int = 5) -> str:
91
+ """Search the local retrieval index with a simple keyword score."""
92
+ index_path = root / _INDEX_PATH
93
+ if not index_path.exists():
94
+ return "[NOT INDEXED] Run `specsmith index` first."
95
+
96
+ data = json.loads(index_path.read_text(encoding="utf-8"))
97
+ entries = data.get("entries", [])
98
+ tokens = [t for t in re.findall(r"[a-zA-Z0-9_\\-]+", query.lower()) if len(t) > 1]
99
+ if not tokens:
100
+ return "[ERROR] Query must include at least one keyword."
101
+
102
+ scored: list[tuple[int, dict[str, str]]] = []
103
+ for entry in entries:
104
+ hay = f"{entry.get('path', '')}\n{entry.get('content', '')}".lower()
105
+ score = sum(hay.count(tok) for tok in tokens)
106
+ if score > 0:
107
+ scored.append((score, entry))
108
+
109
+ if not scored:
110
+ return f"No indexed matches for '{query}'."
111
+
112
+ scored.sort(key=lambda item: (-item[0], item[1].get("path", "")))
113
+ lines = [f"Top {min(limit, len(scored))} result(s) for '{query}':"]
114
+ for score, entry in scored[:limit]:
115
+ content = entry.get("content", "").strip().replace("\r\n", "\n")
116
+ preview = "\n".join(content.splitlines()[:8])
117
+ lines.append(f"\n[{score}] {entry.get('path', '')}\n{preview}")
118
+ return "\n".join(lines)
@@ -0,0 +1,86 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 BitConcepts, LLC. All rights reserved.
3
+ """Wireframe artifact helpers for UI-oriented projects."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import re
8
+ from pathlib import Path
9
+
10
+ from specsmith.requirements import list_reqs
11
+
12
+ _WF_ID_RE = re.compile(r"^(WF-[A-Z0-9-]+)")
13
+
14
+
15
+ def _wireframes_dir(root: Path) -> Path:
16
+ return root / "docs" / "wireframes"
17
+
18
+
19
+ def list_wireframes(root: Path) -> list[dict[str, str]]:
20
+ """List wireframe files and any directly linked requirements."""
21
+ wf_dir = _wireframes_dir(root)
22
+ reqs = list_reqs(root)
23
+ refs: dict[str, list[str]] = {}
24
+ for req in reqs:
25
+ wf = req.get("wireframe", "").strip()
26
+ if wf:
27
+ refs.setdefault(Path(wf).name, []).append(req["id"])
28
+
29
+ items: list[dict[str, str]] = []
30
+ if not wf_dir.exists():
31
+ return items
32
+ for fp in sorted(p for p in wf_dir.iterdir() if p.is_file()):
33
+ match = _WF_ID_RE.match(fp.stem)
34
+ items.append(
35
+ {
36
+ "id": match.group(1) if match else fp.stem,
37
+ "file": str(fp.relative_to(root)),
38
+ "refs": ", ".join(refs.get(fp.name, [])),
39
+ }
40
+ )
41
+ return items
42
+
43
+
44
+ def check_wireframe_refs(root: Path) -> list[str]:
45
+ """Return missing wireframe references from REQUIREMENTS.md."""
46
+ missing: list[str] = []
47
+ for req in list_reqs(root):
48
+ wf = req.get("wireframe", "").strip()
49
+ if not wf:
50
+ continue
51
+ target = (root / wf).resolve()
52
+ if not target.exists():
53
+ missing.append(f"{req['id']} → {wf}")
54
+ return missing
55
+
56
+
57
+ def read_wireframe(root: Path, wireframe_id: str) -> str:
58
+ """Return metadata and best-effort content for a wireframe artifact."""
59
+ wf_dir = _wireframes_dir(root)
60
+ if not wf_dir.exists():
61
+ return "[NOT FOUND] docs/wireframes/"
62
+
63
+ needle = wireframe_id.lower()
64
+ candidates = [
65
+ fp
66
+ for fp in wf_dir.iterdir()
67
+ if fp.is_file() and (fp.name.lower() == needle or fp.stem.lower().startswith(needle))
68
+ ]
69
+ if not candidates:
70
+ return f"[NOT FOUND] {wireframe_id}"
71
+
72
+ target = candidates[0]
73
+ size = target.stat().st_size
74
+ rel = target.relative_to(root)
75
+ suffix = target.suffix.lower()
76
+ header = f"{rel} ({size:,} bytes)"
77
+ if suffix in {".svg", ".md", ".txt"}:
78
+ content = target.read_text(encoding="utf-8", errors="ignore")
79
+ if len(content) > 8000:
80
+ content = content[:8000] + "\n...(truncated)"
81
+ return f"{header}\n\n{content}"
82
+ return (
83
+ f"{header}\n\n"
84
+ "Binary wireframe asset. Use a vision-capable client or open the file directly. "
85
+ "For traceability, reference it from REQUIREMENTS.md via a `Wireframe` field."
86
+ )
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.3.6.dev171
3
+ Version: 0.3.6.dev173
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
@@ -35,6 +35,7 @@ src/specsmith/profiles.py
35
35
  src/specsmith/rate_limits.py
36
36
  src/specsmith/releaser.py
37
37
  src/specsmith/requirements.py
38
+ src/specsmith/retrieval.py
38
39
  src/specsmith/scaffolder.py
39
40
  src/specsmith/session.py
40
41
  src/specsmith/tool_installer.py
@@ -45,6 +46,7 @@ src/specsmith/updater.py
45
46
  src/specsmith/upgrader.py
46
47
  src/specsmith/validator.py
47
48
  src/specsmith/vcs_commands.py
49
+ src/specsmith/wireframes.py
48
50
  src/specsmith/workspace.py
49
51
  src/specsmith.egg-info/PKG-INFO
50
52
  src/specsmith.egg-info/SOURCES.txt