specsmith 0.20.1.dev749__tar.gz → 0.20.1.dev751__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 (372) hide show
  1. {specsmith-0.20.1.dev749/src/specsmith.egg-info → specsmith-0.20.1.dev751}/PKG-INFO +15 -1
  2. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/README.md +14 -0
  3. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/pyproject.toml +1 -1
  4. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/runner.py +12 -0
  5. specsmith-0.20.1.dev751/src/specsmith/agent/terminal_env.py +119 -0
  6. specsmith-0.20.1.dev751/src/specsmith/integrations/warp.py +179 -0
  7. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751/src/specsmith.egg-info}/PKG-INFO +15 -1
  8. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_integrations_warp.py +24 -0
  9. specsmith-0.20.1.dev751/tests/test_terminal_env.py +137 -0
  10. specsmith-0.20.1.dev749/src/specsmith/agent/terminal_env.py +0 -43
  11. specsmith-0.20.1.dev749/src/specsmith/integrations/warp.py +0 -84
  12. specsmith-0.20.1.dev749/tests/test_terminal_env.py +0 -58
  13. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/LICENSE +0 -0
  14. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/setup.cfg +0 -0
  15. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/__init__.py +0 -0
  16. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/belief.py +0 -0
  17. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/certainty.py +0 -0
  18. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/failure_graph.py +0 -0
  19. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/py.typed +0 -0
  20. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/recovery.py +0 -0
  21. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/session.py +0 -0
  22. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/stress_tester.py +0 -0
  23. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/epistemic/trace.py +0 -0
  24. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/__init__.py +0 -0
  25. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/__main__.py +0 -0
  26. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/__init__.py +0 -0
  27. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/broker.py +0 -0
  28. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/chat_runner.py +0 -0
  29. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/cleanup.py +0 -0
  30. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/context_seed.py +0 -0
  31. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/core.py +0 -0
  32. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/dispatch/__init__.py +0 -0
  33. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/dispatch/_status.py +0 -0
  34. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/dispatch/dag.py +0 -0
  35. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
  36. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/dispatch/events.py +0 -0
  37. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/dispatch/result.py +0 -0
  38. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/endpoints.py +0 -0
  39. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/events.py +0 -0
  40. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/execution_profiles.py +0 -0
  41. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/fallback.py +0 -0
  42. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/hf_leaderboard.py +0 -0
  43. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/hf_sync.py +0 -0
  44. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/indexer.py +0 -0
  45. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/llm_client.py +0 -0
  46. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/mcp.py +0 -0
  47. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/memory.py +0 -0
  48. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/model_intelligence.py +0 -0
  49. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/model_profiles.py +0 -0
  50. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/model_router.py +0 -0
  51. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/orchestrator.py +0 -0
  52. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/permissions.py +0 -0
  53. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/profiles.py +0 -0
  54. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/provider_registry.py +0 -0
  55. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/repl.py +0 -0
  56. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/router.py +0 -0
  57. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/rules.py +0 -0
  58. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/safety.py +0 -0
  59. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/spawner.py +0 -0
  60. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/suggester.py +0 -0
  61. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/teams.py +0 -0
  62. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/token_pricing.py +0 -0
  63. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/tools.py +0 -0
  64. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/verifier.py +0 -0
  65. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/agent/voice.py +0 -0
  66. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/approvals.py +0 -0
  67. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/architect.py +0 -0
  68. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/auditor.py +0 -0
  69. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/auth.py +0 -0
  70. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/block_export.py +0 -0
  71. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/channel.py +0 -0
  72. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/ci_manager.py +0 -0
  73. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/cli.py +0 -0
  74. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/commands/__init__.py +0 -0
  75. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/commands/intelligence.py +0 -0
  76. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/commands/issues_policy.py +0 -0
  77. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/commands/reporting.py +0 -0
  78. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/compliance/__init__.py +0 -0
  79. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/compliance/_compat.py +0 -0
  80. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/compliance/checker.py +0 -0
  81. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/compliance/evidence.py +0 -0
  82. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/compliance/regulations.py +0 -0
  83. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/compliance/reporter.py +0 -0
  84. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/compressor.py +0 -0
  85. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/config.py +0 -0
  86. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/console_utils.py +0 -0
  87. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/context_orchestrator.py +0 -0
  88. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/context_window.py +0 -0
  89. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/credit_analyzer.py +0 -0
  90. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/credits.py +0 -0
  91. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/dashboard.py +0 -0
  92. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/__init__.py +0 -0
  93. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/base.py +0 -0
  94. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/citations.py +0 -0
  95. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/fpd.py +0 -0
  96. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/odp.py +0 -0
  97. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/patentsview.py +0 -0
  98. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/pfw.py +0 -0
  99. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/ppubs.py +0 -0
  100. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/datasources/ptab.py +0 -0
  101. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/differ.py +0 -0
  102. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/doctor.py +0 -0
  103. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/drive.py +0 -0
  104. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/editor.py +0 -0
  105. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/efficiency.py +0 -0
  106. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/epistemic/__init__.py +0 -0
  107. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/epistemic/belief.py +0 -0
  108. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/epistemic/certainty.py +0 -0
  109. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/epistemic/failure_graph.py +0 -0
  110. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/epistemic/recovery.py +0 -0
  111. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/epistemic/stress_tester.py +0 -0
  112. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/esdb/__init__.py +0 -0
  113. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/esdb/_license.py +0 -0
  114. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/esdb/bridge.py +0 -0
  115. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/esdb/sqlite_store.py +0 -0
  116. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/esdb_sweep.py +0 -0
  117. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/esdb_writer.py +0 -0
  118. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/eval/__init__.py +0 -0
  119. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/eval/builtins.py +0 -0
  120. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/eval/runner.py +0 -0
  121. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/executor.py +0 -0
  122. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/exporter.py +0 -0
  123. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/governance_logic.py +0 -0
  124. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/governance_store.py +0 -0
  125. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/governance_yaml.py +0 -0
  126. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/governed_pr.py +0 -0
  127. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/__init__.py +0 -0
  128. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/app.py +0 -0
  129. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/main_window.py +0 -0
  130. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/session_tab.py +0 -0
  131. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/theme.py +0 -0
  132. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/widgets/__init__.py +0 -0
  133. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/widgets/chat_view.py +0 -0
  134. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/widgets/input_bar.py +0 -0
  135. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  136. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/widgets/token_meter.py +0 -0
  137. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  138. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/widgets/update_checker.py +0 -0
  139. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/gui/worker.py +0 -0
  140. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/history_search.py +0 -0
  141. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/importer.py +0 -0
  142. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/instinct.py +0 -0
  143. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/__init__.py +0 -0
  144. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/agent_skill.py +0 -0
  145. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/aider.py +0 -0
  146. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/base.py +0 -0
  147. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/claude_code.py +0 -0
  148. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/codity.py +0 -0
  149. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/copilot.py +0 -0
  150. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/cursor.py +0 -0
  151. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/gemini.py +0 -0
  152. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/integrations/windsurf.py +0 -0
  153. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/issue_reporter.py +0 -0
  154. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/languages.py +0 -0
  155. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/ledger.py +0 -0
  156. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/local_model.py +0 -0
  157. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/mcp_generator.py +0 -0
  158. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/mcp_server.py +0 -0
  159. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/__init__.py +0 -0
  160. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
  161. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m002_agents_slim.py +0 -0
  162. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m003_compliance_init.py +0 -0
  163. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
  164. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
  165. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m006_session_governance.py +0 -0
  166. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m007_yaml_first.py +0 -0
  167. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m008_esdb_full_coverage.py +0 -0
  168. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m009_esdb_first.py +0 -0
  169. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/m010_post_esdb_cleanup.py +0 -0
  170. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/migrations/runner.py +0 -0
  171. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/ollama_cmds.py +0 -0
  172. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/patent.py +0 -0
  173. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/paths.py +0 -0
  174. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/phase.py +0 -0
  175. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/plugins.py +0 -0
  176. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/policy.py +0 -0
  177. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/profiles.py +0 -0
  178. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/project_metrics.py +0 -0
  179. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/quality_report.py +0 -0
  180. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/rate_limits.py +0 -0
  181. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/recover.py +0 -0
  182. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/releaser.py +0 -0
  183. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/requirements.py +0 -0
  184. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/requirements_parser.py +0 -0
  185. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/retrieval.py +0 -0
  186. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/risk.py +0 -0
  187. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/safe_write.py +0 -0
  188. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/scaffolder.py +0 -0
  189. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/serve.py +0 -0
  190. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/session.py +0 -0
  191. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/session_init.py +0 -0
  192. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/session_store.py +0 -0
  193. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/__init__.py +0 -0
  194. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/ai_agents.py +0 -0
  195. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/cloud.py +0 -0
  196. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/corporate.py +0 -0
  197. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/cross_platform.py +0 -0
  198. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/data_engineering.py +0 -0
  199. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/devops.py +0 -0
  200. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/docs.py +0 -0
  201. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/embedded.py +0 -0
  202. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/governance.py +0 -0
  203. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/hardware.py +0 -0
  204. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/mobile.py +0 -0
  205. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/platform_engineering.py +0 -0
  206. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/productivity.py +0 -0
  207. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/software_engineering.py +0 -0
  208. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/specsmith_skills.py +0 -0
  209. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/ssh.py +0 -0
  210. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills/web_backend.py +0 -0
  211. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/skills_builder.py +0 -0
  212. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/sync.py +0 -0
  213. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/agents.md.j2 +0 -0
  214. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  215. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  216. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  217. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  218. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  219. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  220. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  221. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/community/security.md.j2 +0 -0
  222. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  223. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  224. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  225. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  226. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  227. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/editorconfig.j2 +0 -0
  228. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/gitattributes.j2 +0 -0
  229. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/gitignore.j2 +0 -0
  230. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/go/go.mod.j2 +0 -0
  231. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/go/main.go.j2 +0 -0
  232. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  233. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  234. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  235. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  236. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  237. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
  238. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  239. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  240. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
  241. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  242. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  243. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/js/package.json.j2 +0 -0
  244. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/ledger.md.j2 +0 -0
  245. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/python/cli.py.j2 +0 -0
  246. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/python/init.py.j2 +0 -0
  247. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  248. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/readme.md.j2 +0 -0
  249. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  250. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  251. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  252. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  253. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  254. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  255. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  256. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  257. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  258. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/tool_installer.py +0 -0
  259. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/toolrules.py +0 -0
  260. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/tools.py +0 -0
  261. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/trace.py +0 -0
  262. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/transcripts.py +0 -0
  263. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/updater.py +0 -0
  264. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/upgrader.py +0 -0
  265. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/validator.py +0 -0
  266. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/vcs/__init__.py +0 -0
  267. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/vcs/base.py +0 -0
  268. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/vcs/bitbucket.py +0 -0
  269. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/vcs/github.py +0 -0
  270. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/vcs/gitlab.py +0 -0
  271. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/vcs_commands.py +0 -0
  272. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/wi_store.py +0 -0
  273. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/wireframes.py +0 -0
  274. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith/workspace.py +0 -0
  275. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith.egg-info/SOURCES.txt +0 -0
  276. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith.egg-info/dependency_links.txt +0 -0
  277. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith.egg-info/entry_points.txt +0 -0
  278. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith.egg-info/requires.txt +0 -0
  279. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/src/specsmith.egg-info/top_level.txt +0 -0
  280. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_CMD_001.py +0 -0
  281. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_agent_profiles.py +0 -0
  282. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_agent_run_feedback.py +0 -0
  283. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_agent_runner_ready.py +0 -0
  284. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_ai_client.py +0 -0
  285. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_ai_intelligence.py +0 -0
  286. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_architect_interview.py +0 -0
  287. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_architect_v2.py +0 -0
  288. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_architecture.py +0 -0
  289. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_audit_governance.py +0 -0
  290. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_auditor.py +0 -0
  291. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_benchmark_harness.py +0 -0
  292. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_broker_scope.py +0 -0
  293. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_channel.py +0 -0
  294. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_chat_diff_decision.py +0 -0
  295. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_chat_runner_openai_compat.py +0 -0
  296. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_chat_stdin_protocol.py +0 -0
  297. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_cleanup_cmd.py +0 -0
  298. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_cli.py +0 -0
  299. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_cli_regressions.py +0 -0
  300. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_cli_workflows_history_drive.py +0 -0
  301. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_compliance.py +0 -0
  302. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_compliance_governance.py +0 -0
  303. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_compressor.py +0 -0
  304. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_deprecation_registry.py +0 -0
  305. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_dispatch.py +0 -0
  306. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_dual_write.py +0 -0
  307. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_e2e_nexus.py +0 -0
  308. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_efficiency.py +0 -0
  309. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_endpoints_cli.py +0 -0
  310. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_endpoints_store.py +0 -0
  311. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_epistemic.py +0 -0
  312. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_backend_switch.py +0 -0
  313. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_enforcement.py +0 -0
  314. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_integration.py +0 -0
  315. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_license.py +0 -0
  316. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_sqlite.py +0 -0
  317. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_status_integrity.py +0 -0
  318. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_status_output.py +0 -0
  319. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_sweep.py +0 -0
  320. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_verify_chain_cli.py +0 -0
  321. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_esdb_writer.py +0 -0
  322. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_fallback_chain.py +0 -0
  323. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_golden_path.py +0 -0
  324. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_importer.py +0 -0
  325. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_init_modes.py +0 -0
  326. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_integrations.py +0 -0
  327. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_integrations_codity.py +0 -0
  328. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_intelligence.py +0 -0
  329. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_issue_policy_features.py +0 -0
  330. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_issue_reporter.py +0 -0
  331. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_issues_263_264.py +0 -0
  332. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_local_model.py +0 -0
  333. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_markdown_deprecation.py +0 -0
  334. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_mcp_client.py +0 -0
  335. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_mcp_server.py +0 -0
  336. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_metrics_flush.py +0 -0
  337. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_migration_direction.py +0 -0
  338. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_model_router.py +0 -0
  339. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_new_modules.py +0 -0
  340. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_nexus.py +0 -0
  341. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_parallel_agents.py +0 -0
  342. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_permissions.py +0 -0
  343. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_phase1_4_new.py +0 -0
  344. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_phase34_completion.py +0 -0
  345. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_project_metrics.py +0 -0
  346. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_quality_report.py +0 -0
  347. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_rate_limits.py +0 -0
  348. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_releaser.py +0 -0
  349. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_repl.py +0 -0
  350. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_repl_extended.py +0 -0
  351. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_reporting_commands.py +0 -0
  352. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_req_248_262.py +0 -0
  353. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_req_358_359.py +0 -0
  354. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_resume_command.py +0 -0
  355. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_scaffolder.py +0 -0
  356. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_schema_migrations.py +0 -0
  357. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_skill_marketplace.py +0 -0
  358. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_skills_mcp.py +0 -0
  359. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_smoke.py +0 -0
  360. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_sqlite_parity.py +0 -0
  361. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_suggester.py +0 -0
  362. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_sync_reconcile.py +0 -0
  363. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_token_cost.py +0 -0
  364. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_tools.py +0 -0
  365. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_trace_vault_esdb.py +0 -0
  366. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_typing_guardrails.py +0 -0
  367. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_validator.py +0 -0
  368. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_vcs.py +0 -0
  369. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_warp_parity.py +0 -0
  370. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_warp_parity_followup.py +0 -0
  371. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_wi_lifecycle.py +0 -0
  372. {specsmith-0.20.1.dev749 → specsmith-0.20.1.dev751}/tests/test_wi_lifecycle_extended.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.20.1.dev749
3
+ Version: 0.20.1.dev751
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
@@ -1341,6 +1341,20 @@ oz agent run --mcp '{"specsmith-governance": {"command": "specsmith", "args": ["
1341
1341
  | `governance_req_list` | All requirements with status + test coverage, filterable |
1342
1342
  | `governance_trace_seal` | Create a cryptographic trace vault seal |
1343
1343
 
1344
+ ### Third-party CLI agent toolbar
1345
+
1346
+ For **specsmith** and **aider** (not yet natively supported by Warp), add this regex once in **Warp → Settings → Agents → Third party CLI agents → Commands that enable the toolbar**:
1347
+
1348
+ ```
1349
+ specsmith\s+run|aider
1350
+ ```
1351
+
1352
+ `claude`, `codex`, `gemini`, and `cursor` are already natively supported — no regex needed.
1353
+
1354
+ Once set, the toolbelt (Rich Input, attach code, File Explorer, Tab Configs, Remote Control) appears whenever `specsmith run` or `aider` is running. `specsmith run` also emits an OSC 9 desktop notification on session start — intercepted automatically by Warp, iTerm2, and Windows Terminal.
1355
+
1356
+ Run `specsmith integrate warp` to regenerate `.warp/SETUP.md` with the full per-REPL setup guide.
1357
+
1344
1358
  ### Repository Workflows (Ctrl+Shift+R)
1345
1359
 
1346
1360
  Clone this repo and open it in Warp — seven governance workflows appear automatically in
@@ -1263,6 +1263,20 @@ oz agent run --mcp '{"specsmith-governance": {"command": "specsmith", "args": ["
1263
1263
  | `governance_req_list` | All requirements with status + test coverage, filterable |
1264
1264
  | `governance_trace_seal` | Create a cryptographic trace vault seal |
1265
1265
 
1266
+ ### Third-party CLI agent toolbar
1267
+
1268
+ For **specsmith** and **aider** (not yet natively supported by Warp), add this regex once in **Warp → Settings → Agents → Third party CLI agents → Commands that enable the toolbar**:
1269
+
1270
+ ```
1271
+ specsmith\s+run|aider
1272
+ ```
1273
+
1274
+ `claude`, `codex`, `gemini`, and `cursor` are already natively supported — no regex needed.
1275
+
1276
+ Once set, the toolbelt (Rich Input, attach code, File Explorer, Tab Configs, Remote Control) appears whenever `specsmith run` or `aider` is running. `specsmith run` also emits an OSC 9 desktop notification on session start — intercepted automatically by Warp, iTerm2, and Windows Terminal.
1277
+
1278
+ Run `specsmith integrate warp` to regenerate `.warp/SETUP.md` with the full per-REPL setup guide.
1279
+
1266
1280
  ### Repository Workflows (Ctrl+Shift+R)
1267
1281
 
1268
1282
  Clone this repo and open it in Warp — seven governance workflows appear automatically in
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "specsmith"
7
- version = "0.20.1.dev749"
7
+ version = "0.20.1.dev751"
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"
@@ -306,6 +306,13 @@ class AgentRunner:
306
306
 
307
307
  # Host-terminal detection (REQ-444): when running inside Warp the
308
308
  # banner/ready frame advertises native integration. Read-only.
309
+ # Set SPECSMITH_RUN_ACTIVE so any child specsmith command (audit,
310
+ # preflight, checkpoint, etc.) can detect they are running inside
311
+ # the Nexus REPL and report context-aware governance notifications.
312
+ import os as _os_init
313
+
314
+ _os_init.environ.setdefault("SPECSMITH_RUN_ACTIVE", "1")
315
+
309
316
  from specsmith.agent.terminal_env import detect_terminal
310
317
 
311
318
  self.terminal = detect_terminal()
@@ -395,6 +402,11 @@ class AgentRunner:
395
402
  if self.terminal.is_warp:
396
403
  ver = f" {self.terminal.version}" if self.terminal.version else ""
397
404
  lines.insert(3, f" terminal: Warp{ver} \u2014 native integration active")
405
+ # Emit OSC 9 desktop notification so Warp surfaces a popup.
406
+ from specsmith.agent.terminal_env import emit_warp_notification
407
+
408
+ proj = Path(self.project_dir).name
409
+ emit_warp_notification(f"specsmith run | {proj} | governance active")
398
410
  for s in statuses:
399
411
  if s.available:
400
412
  lines.append(
@@ -0,0 +1,119 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
3
+ """Terminal-environment detection for specsmith (REQ-444).
4
+
5
+ Lets the interactive REPL (``specsmith run``) and standalone CLI commands
6
+ detect when they are running inside Warp and which CLI agent REPL is active.
7
+ Detection is based on:
8
+ * ``TERM_PROGRAM=WarpTerminal`` / any ``WARP_*`` env var — Warp host
9
+ * ``SPECSMITH_RUN_ACTIVE=1`` — set by ``specsmith run`` on REPL start
10
+ * ``AIDER_MODEL`` / ``AIDER_CONFIG`` — set by aider at session start
11
+ * ``CLAUDE_CODE_ENTRYPOINT`` — set by Claude Code CLI
12
+ * ``CODEX_CLI_SESSION`` — set by OpenAI Codex CLI
13
+ * ``GEMINI_CLI`` — set by Gemini CLI
14
+ * ``CURSOR_TRACE_ID`` — set by Cursor CLI
15
+
16
+ All detection is read-only and purely best-effort.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import os
22
+ import sys
23
+ from dataclasses import asdict, dataclass
24
+ from typing import TextIO
25
+
26
+ # ---------------------------------------------------------------------------
27
+ # Known CLI-agent env-var signals.
28
+ # Keys are canonical agent IDs; values are lists of env vars that
29
+ # confirm the agent is (or recently was) active in this shell session.
30
+ # Warp natively supports: claude, codex, gemini, cursor.
31
+ # specsmith and aider are NOT natively supported — users add them via the
32
+ # custom toolbar regex in Warp Settings → Agents → Third party CLI agents.
33
+ # ---------------------------------------------------------------------------
34
+ _AGENT_ENV_SIGNALS: dict[str, list[str]] = {
35
+ "specsmith": ["SPECSMITH_RUN_ACTIVE"],
36
+ "aider": ["AIDER_MODEL", "AIDER_CONFIG", "AIDER_CHAT_LANGUAGE"],
37
+ "claude": ["CLAUDE_CODE_ENTRYPOINT", "ANTHROPIC_CLAUDE_CODE_SESSION"],
38
+ "codex": ["CODEX_CLI_SESSION", "OPENAI_CODEX_CLI"],
39
+ "gemini": ["GEMINI_CLI", "GEMINI_CLI_SESSION"],
40
+ "cursor": ["CURSOR_TRACE_ID", "CURSOR_SESSION_ID"],
41
+ "copilot": ["GITHUB_COPILOT_CLI", "GH_COPILOT_SESSION"],
42
+ "windsurf": ["WINDSURF_SESSION", "CODEIUM_SESSION"],
43
+ }
44
+
45
+
46
+ @dataclass(frozen=True)
47
+ class TerminalInfo:
48
+ """Information about the host terminal and active CLI agent REPL."""
49
+
50
+ is_warp: bool
51
+ program: str
52
+ version: str
53
+ #: Canonical agent ID when a known CLI agent REPL is detected, else "".
54
+ #: Examples: ``"specsmith"``, ``"aider"``, ``"claude"``, ``"codex"``.
55
+ active_agent: str = ""
56
+
57
+ def as_dict(self) -> dict[str, object]:
58
+ """Return a flat dict suitable for the ``ready`` event frame."""
59
+ return asdict(self)
60
+
61
+
62
+ def detect_terminal(env: dict[str, str] | None = None) -> TerminalInfo:
63
+ """Detect the host terminal and active CLI agent from environment variables.
64
+
65
+ Warp sets ``TERM_PROGRAM=WarpTerminal`` (and ``TERM_PROGRAM_VERSION``).
66
+ As a fallback we also treat the presence of any ``WARP_*`` variable as a
67
+ Warp signal. Pass *env* to override ``os.environ`` (used by tests).
68
+ """
69
+ source = os.environ if env is None else env
70
+ program = (source.get("TERM_PROGRAM") or "").strip()
71
+ version = (source.get("TERM_PROGRAM_VERSION") or "").strip()
72
+ is_warp = program == "WarpTerminal" or any(k.startswith("WARP_") for k in source)
73
+ if is_warp and not program:
74
+ program = "WarpTerminal"
75
+
76
+ # Detect the active CLI-agent REPL by checking known signal env vars.
77
+ # First match wins; order matters (specsmith checked before generic agents).
78
+ active_agent = ""
79
+ for agent, signals in _AGENT_ENV_SIGNALS.items():
80
+ if any(source.get(sig) for sig in signals):
81
+ active_agent = agent
82
+ break
83
+
84
+ return TerminalInfo(
85
+ is_warp=is_warp,
86
+ program=program,
87
+ version=version,
88
+ active_agent=active_agent,
89
+ )
90
+
91
+
92
+ # ---------------------------------------------------------------------------
93
+ # OSC 9 terminal notification (Warp, iTerm2, Windows Terminal)
94
+ # ---------------------------------------------------------------------------
95
+
96
+
97
+ def emit_warp_notification(message: str, *, stream: TextIO | None = None) -> None:
98
+ """Emit an OSC 9 terminal notification that Warp (and compatible terminals)
99
+ surfaces as a desktop notification.
100
+
101
+ The escape sequence ``ESC ] 9 ; <message> BEL`` is the standard notification
102
+ protocol supported by Warp, iTerm2, and Windows Terminal. When *stream* is
103
+ ``None`` (the default), the function skips silently if stdout is not a TTY
104
+ (e.g. captured in tests or CI). Pass an explicit *stream* to override.
105
+
106
+ This is always safe to call — it is a no-op outside Warp and raises no
107
+ exceptions.
108
+ """
109
+ out = stream if stream is not None else sys.stdout
110
+ try:
111
+ # When using the default stdout and it's not a tty, skip silently
112
+ # to avoid polluting captured output in tests or piped commands.
113
+ if stream is None and hasattr(out, "isatty") and not out.isatty():
114
+ return
115
+ out.write(f"\033]9;{message}\007")
116
+ if hasattr(out, "flush"):
117
+ out.flush()
118
+ except Exception: # noqa: BLE001 # intentional: notification is best-effort
119
+ pass
@@ -0,0 +1,179 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
3
+ """Warp integration adapter (REQ-444).
4
+
5
+ Generates Warp-native artifacts so Warp's agent is governed by specsmith:
6
+
7
+ * ``.warp/specsmith-mcp.json`` — governance MCP server config
8
+ * ``.warp/launch_configs/specsmith-governed.yaml`` — launch config for a governed session
9
+ * ``.agents/skills/SKILL.md`` — governance skill (shared with agent-skill)
10
+
11
+ ``AGENTS.md`` is already the governance hub Warp reads as project Rules, so the
12
+ adapter does not duplicate it.
13
+
14
+ This adapter supersedes the pre-0.5.0 ``warp`` name that previously aliased to
15
+ the generic ``agent-skill`` adapter; the skill is still emitted here (by reusing
16
+ ``AgentSkillAdapter``), so existing setups keep their ``.agents/skills/SKILL.md``.
17
+ """
18
+
19
+ from __future__ import annotations
20
+
21
+ import json
22
+ from pathlib import Path
23
+
24
+ from specsmith.config import ProjectConfig
25
+ from specsmith.integrations.agent_skill import AgentSkillAdapter
26
+ from specsmith.integrations.base import AgentAdapter
27
+
28
+
29
+ class WarpAdapter(AgentAdapter):
30
+ """Generate Warp-native governance integration files."""
31
+
32
+ @property
33
+ def name(self) -> str:
34
+ return "warp"
35
+
36
+ @property
37
+ def description(self) -> str:
38
+ return "Warp native integration (MCP server config, launch config, governance skill)"
39
+
40
+ def generate(self, config: ProjectConfig, target: Path) -> list[Path]:
41
+ created: list[Path] = []
42
+ warp_dir = target / ".warp"
43
+ warp_dir.mkdir(parents=True, exist_ok=True)
44
+
45
+ # 1. MCP governance server config (shared builder with `mcp install-warp`).
46
+ from specsmith.mcp_server import build_warp_mcp_config
47
+
48
+ mcp_path = warp_dir / "specsmith-mcp.json"
49
+ mcp_path.write_text(
50
+ json.dumps(build_warp_mcp_config(), indent=2) + "\n",
51
+ encoding="utf-8",
52
+ )
53
+ created.append(mcp_path)
54
+
55
+ # 2. Launch config for a governed `specsmith run` session.
56
+ launch_dir = warp_dir / "launch_configs"
57
+ launch_dir.mkdir(parents=True, exist_ok=True)
58
+ launch_path = launch_dir / "specsmith-governed.yaml"
59
+ launch_path.write_text(self._render_launch_config(config, target), encoding="utf-8")
60
+ created.append(launch_path)
61
+
62
+ # 3. Governance skill (reuse the agent-skill adapter; .agents/skills/SKILL.md).
63
+ created.extend(AgentSkillAdapter().generate(config, target))
64
+
65
+ # 4. Third-party CLI agent toolbar setup guide.
66
+ setup_path = warp_dir / "SETUP.md"
67
+ setup_path.write_text(self._render_setup_guide(config), encoding="utf-8")
68
+ created.append(setup_path)
69
+
70
+ # Print the single most-important instruction so it appears immediately
71
+ # after `specsmith integrate warp` completes.
72
+ import sys
73
+
74
+ print(
75
+ "\n ↳ Warp toolbar (one-time, per machine):\n"
76
+ " Settings → Agents → Third party CLI agents\n"
77
+ " Commands that enable the toolbar → add regex:\n"
78
+ " specsmith\\s+run|aider\n"
79
+ " (claude, codex, gemini, cursor — already natively supported)\n"
80
+ "\n"
81
+ " Full setup guide: .warp/SETUP.md",
82
+ file=sys.stdout,
83
+ flush=True,
84
+ )
85
+
86
+ return created
87
+
88
+ def _render_setup_guide(self, config: ProjectConfig) -> str: # noqa: ARG002
89
+ """Render the .warp/SETUP.md toolbar + notification setup guide."""
90
+ return """\
91
+ # Warp — specsmith governance integration
92
+
93
+ ## Third-party CLI agent toolbar (one-time setup per machine)
94
+
95
+ Warp natively supports the toolbar for: **claude**, **codex**, **gemini**, **cursor**.
96
+ For **specsmith** and **aider** (not yet natively supported), add the following
97
+ regex to Warp → Settings → Agents → Third party CLI agents → Commands that enable the toolbar:
98
+
99
+ ```
100
+ specsmith\\s+run|aider
101
+ ```
102
+
103
+ Once saved, the Warp toolbelt appears automatically when either `specsmith run` or
104
+ `aider` is active in any pane, providing Rich Input (Ctrl+G), attach code as context,
105
+ File Explorer, Tab Configs, and Remote Control.
106
+
107
+ ## Desktop notifications
108
+
109
+ `specsmith run` emits OSC 9 desktop notifications when running inside Warp
110
+ (or any OSC-9-compatible terminal such as iTerm2 or Windows Terminal).
111
+ No extra setup is needed — Warp intercepts the escape sequence automatically.
112
+
113
+ Notification events:
114
+ - Session start: `specsmith run | <project> | governance active`
115
+
116
+ ## MCP governance server
117
+
118
+ Add `.warp/specsmith-mcp.json` to Warp → Settings → Agents → MCP servers so
119
+ Warp's Oz agent can call governance tools natively (preflight, audit, checkpoint,
120
+ req_list, phase, trace_seal) without shell roundtrips.
121
+
122
+ Paste the contents of `.warp/specsmith-mcp.json` or run:
123
+ ```bash
124
+ specsmith mcp install-warp
125
+ ```
126
+
127
+ ## Launch configuration
128
+
129
+ `.warp/launch_configs/specsmith-governed.yaml` opens a governed `specsmith run`
130
+ session. Copy it to your Warp launch configurations directory:
131
+ - macOS/Linux: `~/.warp/launch_configurations/`
132
+ - Windows: `%APPDATA%/warp/Warp/data/launch_configurations/`
133
+
134
+ ## Supported REPLs and their Warp status
135
+
136
+ | REPL | Toolbar | How |
137
+ |---|---|---|
138
+ | `specsmith run` | Custom regex | Add `specsmith\\s+run` to toolbar regex |
139
+ | `aider` | Custom regex | Add `aider` to toolbar regex |
140
+ | `claude` | Native | Built into Warp — no setup needed |
141
+ | `codex` | Native | Built into Warp — no setup needed |
142
+ | `gemini` | Native | Built into Warp — no setup needed |
143
+ | `cursor` | Native | Built into Warp — no setup needed |
144
+
145
+ ## Session protocol (all REPLs)
146
+
147
+ ```bash
148
+ # Session start
149
+ specsmith kill-session 2>/dev/null || true
150
+ specsmith audit --project-dir .
151
+ specsmith sync --project-dir .
152
+ specsmith checkpoint --project-dir . # output GOVERNANCE ANCHOR verbatim
153
+
154
+ # Before every code change
155
+ specsmith preflight "<describe the change>" --json
156
+
157
+ # Session end
158
+ specsmith save && specsmith kill-session
159
+ ```
160
+ """
161
+
162
+ def _render_launch_config(self, config: ProjectConfig, target: Path) -> str:
163
+ cwd = str(target).replace("\\", "/")
164
+ return f"""\
165
+ # specsmith governed session — Warp launch configuration.
166
+ # Copy to your Warp launch configurations directory to use it:
167
+ # macOS/Linux: ~/.warp/launch_configurations/
168
+ # Windows: %APPDATA%/warp/Warp/data/launch_configurations/
169
+ # The governance MCP server config lives in .warp/specsmith-mcp.json — add it
170
+ # under Warp Settings -> Agents -> MCP servers so Warp's agent is governed.
171
+ name: {config.name} — specsmith governed
172
+ windows:
173
+ - tabs:
174
+ - title: specsmith
175
+ layout:
176
+ cwd: "{cwd}"
177
+ commands:
178
+ - exec: specsmith run
179
+ """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.20.1.dev749
3
+ Version: 0.20.1.dev751
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
@@ -1341,6 +1341,20 @@ oz agent run --mcp '{"specsmith-governance": {"command": "specsmith", "args": ["
1341
1341
  | `governance_req_list` | All requirements with status + test coverage, filterable |
1342
1342
  | `governance_trace_seal` | Create a cryptographic trace vault seal |
1343
1343
 
1344
+ ### Third-party CLI agent toolbar
1345
+
1346
+ For **specsmith** and **aider** (not yet natively supported by Warp), add this regex once in **Warp → Settings → Agents → Third party CLI agents → Commands that enable the toolbar**:
1347
+
1348
+ ```
1349
+ specsmith\s+run|aider
1350
+ ```
1351
+
1352
+ `claude`, `codex`, `gemini`, and `cursor` are already natively supported — no regex needed.
1353
+
1354
+ Once set, the toolbelt (Rich Input, attach code, File Explorer, Tab Configs, Remote Control) appears whenever `specsmith run` or `aider` is running. `specsmith run` also emits an OSC 9 desktop notification on session start — intercepted automatically by Warp, iTerm2, and Windows Terminal.
1355
+
1356
+ Run `specsmith integrate warp` to regenerate `.warp/SETUP.md` with the full per-REPL setup guide.
1357
+
1344
1358
  ### Repository Workflows (Ctrl+Shift+R)
1345
1359
 
1346
1360
  Clone this repo and open it in Warp — seven governance workflows appear automatically in
@@ -79,6 +79,30 @@ class TestWarpAdapterGenerate:
79
79
  assert "test-project" in content
80
80
  assert "AGENTS.md" in content
81
81
 
82
+ def test_generates_setup_md(self, config: ProjectConfig, tmp_path: Path) -> None:
83
+ WarpAdapter().generate(config, tmp_path)
84
+ setup = tmp_path / ".warp" / "SETUP.md"
85
+ assert setup.exists()
86
+ content = setup.read_text(encoding="utf-8")
87
+ # Must document the toolbar regex for non-native REPLs.
88
+ assert "specsmith" in content
89
+ assert "aider" in content
90
+ # Must distinguish natively supported agents.
91
+ assert "claude" in content
92
+ assert "Native" in content
93
+
94
+ def test_setup_md_contains_toolbar_regex(self, config: ProjectConfig, tmp_path: Path) -> None:
95
+ WarpAdapter().generate(config, tmp_path)
96
+ setup = tmp_path / ".warp" / "SETUP.md"
97
+ content = setup.read_text(encoding="utf-8")
98
+ # The regex the user must paste into Warp settings.
99
+ assert r"specsmith\s+run|aider" in content
100
+
101
+ def test_generated_files_includes_setup_md(self, config: ProjectConfig, tmp_path: Path) -> None:
102
+ files = WarpAdapter().generate(config, tmp_path)
103
+ rel = {p.relative_to(tmp_path).as_posix() for p in files}
104
+ assert ".warp/SETUP.md" in rel
105
+
82
106
  def test_idempotent(self, config: ProjectConfig, tmp_path: Path) -> None:
83
107
  first = WarpAdapter().generate(config, tmp_path)
84
108
  first_contents = {p: p.read_text(encoding="utf-8") for p in first}
@@ -0,0 +1,137 @@
1
+ # SPDX-License-Identifier: MIT
2
+ # Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
3
+ """Tests for host-terminal detection (REQ-444)."""
4
+
5
+ from __future__ import annotations
6
+
7
+ import io
8
+
9
+ from specsmith.agent.terminal_env import TerminalInfo, detect_terminal, emit_warp_notification
10
+
11
+
12
+ class TestDetectTerminal:
13
+ def test_detects_warp_via_term_program(self) -> None:
14
+ info = detect_terminal(
15
+ {"TERM_PROGRAM": "WarpTerminal", "TERM_PROGRAM_VERSION": "0.2026.06.01"}
16
+ )
17
+ assert info.is_warp is True
18
+ assert info.program == "WarpTerminal"
19
+ assert info.version == "0.2026.06.01"
20
+
21
+ def test_detects_warp_via_warp_env_var(self) -> None:
22
+ info = detect_terminal({"WARP_HONOR_PS1": "0"})
23
+ assert info.is_warp is True
24
+ # Program is backfilled when only a WARP_* signal is present.
25
+ assert info.program == "WarpTerminal"
26
+
27
+ def test_non_warp_terminal(self) -> None:
28
+ info = detect_terminal({"TERM_PROGRAM": "iTerm.app"})
29
+ assert info.is_warp is False
30
+ assert info.program == "iTerm.app"
31
+ assert info.version == ""
32
+
33
+ def test_empty_env(self) -> None:
34
+ info = detect_terminal({})
35
+ assert info.is_warp is False
36
+ assert info.program == ""
37
+ assert info.version == ""
38
+
39
+ def test_as_dict_round_trip(self) -> None:
40
+ info = detect_terminal({"TERM_PROGRAM": "WarpTerminal"})
41
+ d = info.as_dict()
42
+ assert d == {
43
+ "is_warp": True,
44
+ "program": "WarpTerminal",
45
+ "version": "",
46
+ "active_agent": "",
47
+ }
48
+
49
+ def test_frozen_dataclass(self) -> None:
50
+ info = TerminalInfo(is_warp=False, program="x", version="1")
51
+ try:
52
+ info.is_warp = True # type: ignore[misc]
53
+ except AttributeError:
54
+ pass
55
+ else: # pragma: no cover - dataclass should be frozen
56
+ raise AssertionError("TerminalInfo should be frozen")
57
+
58
+
59
+ class TestActiveAgentDetection:
60
+ def test_detects_specsmith_repl(self) -> None:
61
+ info = detect_terminal({"SPECSMITH_RUN_ACTIVE": "1"})
62
+ assert info.active_agent == "specsmith"
63
+
64
+ def test_detects_aider_via_model(self) -> None:
65
+ info = detect_terminal({"AIDER_MODEL": "gpt-4o"})
66
+ assert info.active_agent == "aider"
67
+
68
+ def test_detects_aider_via_config(self) -> None:
69
+ info = detect_terminal({"AIDER_CONFIG": "/home/user/.aider.conf.yml"})
70
+ assert info.active_agent == "aider"
71
+
72
+ def test_detects_claude(self) -> None:
73
+ info = detect_terminal({"CLAUDE_CODE_ENTRYPOINT": "cli"})
74
+ assert info.active_agent == "claude"
75
+
76
+ def test_detects_codex(self) -> None:
77
+ info = detect_terminal({"CODEX_CLI_SESSION": "abc123"})
78
+ assert info.active_agent == "codex"
79
+
80
+ def test_detects_gemini(self) -> None:
81
+ info = detect_terminal({"GEMINI_CLI": "1"})
82
+ assert info.active_agent == "gemini"
83
+
84
+ def test_no_agent_in_plain_shell(self) -> None:
85
+ info = detect_terminal({"TERM_PROGRAM": "iTerm.app"})
86
+ assert info.active_agent == ""
87
+
88
+ def test_specsmith_wins_over_aider_when_both_present(self) -> None:
89
+ # SPECSMITH_RUN_ACTIVE is checked first in the signals dict.
90
+ info = detect_terminal({"SPECSMITH_RUN_ACTIVE": "1", "AIDER_MODEL": "gpt-4o"})
91
+ assert info.active_agent == "specsmith"
92
+
93
+ def test_active_agent_included_in_as_dict(self) -> None:
94
+ info = detect_terminal({"AIDER_MODEL": "claude-3-5-sonnet"})
95
+ assert info.as_dict()["active_agent"] == "aider"
96
+
97
+
98
+ class TestEmitWarpNotification:
99
+ def test_writes_osc9_sequence_to_explicit_stream(self) -> None:
100
+ buf = io.StringIO()
101
+ emit_warp_notification("hello warp", stream=buf)
102
+ assert buf.getvalue() == "\033]9;hello warp\007"
103
+
104
+ def test_message_is_included_verbatim(self) -> None:
105
+ buf = io.StringIO()
106
+ emit_warp_notification("specsmith run | myproj | governance active", stream=buf)
107
+ assert "specsmith run | myproj | governance active" in buf.getvalue()
108
+
109
+ def test_empty_message_still_writes_osc_frame(self) -> None:
110
+ buf = io.StringIO()
111
+ emit_warp_notification("", stream=buf)
112
+ # Should still write the OSC frame (empty body is valid)
113
+ assert "\033]9;" in buf.getvalue()
114
+
115
+ def test_no_exception_on_closed_stream(self) -> None:
116
+ buf = io.StringIO()
117
+ buf.close()
118
+ # Must not raise
119
+ emit_warp_notification("test", stream=buf)
120
+
121
+
122
+ class TestBannerReflectsTerminal:
123
+ def test_runner_reads_terminal(self, tmp_path, monkeypatch) -> None:
124
+ monkeypatch.setenv("TERM_PROGRAM", "WarpTerminal")
125
+ from specsmith.agent.runner import AgentRunner
126
+
127
+ runner = AgentRunner(project_dir=str(tmp_path), json_events=True)
128
+ assert runner.terminal.is_warp is True
129
+
130
+ def test_runner_sets_specsmith_run_active(self, tmp_path, monkeypatch) -> None:
131
+ import os
132
+
133
+ monkeypatch.delenv("SPECSMITH_RUN_ACTIVE", raising=False)
134
+ from specsmith.agent.runner import AgentRunner
135
+
136
+ AgentRunner(project_dir=str(tmp_path), json_events=True)
137
+ assert os.environ.get("SPECSMITH_RUN_ACTIVE") == "1"
@@ -1,43 +0,0 @@
1
- # SPDX-License-Identifier: MIT
2
- # Copyright (c) 2026 Layer1Labs Silicon, Inc. All rights reserved.
3
- """Terminal-environment detection for specsmith (REQ-444).
4
-
5
- Lets the interactive REPL (``specsmith run``) detect when it is running
6
- inside Warp so it can adapt its banner / ``ready`` frame. Detection is
7
- based on the standard ``TERM_PROGRAM`` signal Warp sets, plus any
8
- ``WARP_*`` environment variables, and is purely read-only.
9
- """
10
-
11
- from __future__ import annotations
12
-
13
- import os
14
- from dataclasses import asdict, dataclass
15
-
16
-
17
- @dataclass(frozen=True)
18
- class TerminalInfo:
19
- """Information about the host terminal."""
20
-
21
- is_warp: bool
22
- program: str
23
- version: str
24
-
25
- def as_dict(self) -> dict[str, object]:
26
- """Return a flat dict suitable for the ``ready`` event frame."""
27
- return asdict(self)
28
-
29
-
30
- def detect_terminal(env: dict[str, str] | None = None) -> TerminalInfo:
31
- """Detect the host terminal from environment variables.
32
-
33
- Warp sets ``TERM_PROGRAM=WarpTerminal`` (and ``TERM_PROGRAM_VERSION``).
34
- As a fallback we also treat the presence of any ``WARP_*`` variable as a
35
- Warp signal. Pass *env* to override ``os.environ`` (used by tests).
36
- """
37
- source = os.environ if env is None else env
38
- program = (source.get("TERM_PROGRAM") or "").strip()
39
- version = (source.get("TERM_PROGRAM_VERSION") or "").strip()
40
- is_warp = program == "WarpTerminal" or any(k.startswith("WARP_") for k in source)
41
- if is_warp and not program:
42
- program = "WarpTerminal"
43
- return TerminalInfo(is_warp=is_warp, program=program, version=version)