specsmith 0.12.0.dev493__tar.gz → 0.12.0.dev494__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 (289) hide show
  1. {specsmith-0.12.0.dev493/src/specsmith.egg-info → specsmith-0.12.0.dev494}/PKG-INFO +1 -1
  2. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/pyproject.toml +1 -1
  3. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/cli.py +100 -27
  4. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/mcp_server.py +61 -11
  5. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494/src/specsmith.egg-info}/PKG-INFO +1 -1
  6. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_mcp_server.py +78 -3
  7. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/LICENSE +0 -0
  8. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/README.md +0 -0
  9. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/setup.cfg +0 -0
  10. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/__init__.py +0 -0
  11. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/belief.py +0 -0
  12. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/certainty.py +0 -0
  13. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/failure_graph.py +0 -0
  14. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/py.typed +0 -0
  15. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/recovery.py +0 -0
  16. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/session.py +0 -0
  17. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/stress_tester.py +0 -0
  18. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/epistemic/trace.py +0 -0
  19. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/__init__.py +0 -0
  20. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/__main__.py +0 -0
  21. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/__init__.py +0 -0
  22. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/broker.py +0 -0
  23. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/chat_runner.py +0 -0
  24. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/cleanup.py +0 -0
  25. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/context_seed.py +0 -0
  26. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/core.py +0 -0
  27. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/dispatch/__init__.py +0 -0
  28. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/dispatch/_status.py +0 -0
  29. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/dispatch/dag.py +0 -0
  30. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
  31. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/dispatch/events.py +0 -0
  32. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/dispatch/result.py +0 -0
  33. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/endpoints.py +0 -0
  34. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/events.py +0 -0
  35. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/execution_profiles.py +0 -0
  36. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/fallback.py +0 -0
  37. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/hf_leaderboard.py +0 -0
  38. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/hf_sync.py +0 -0
  39. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/indexer.py +0 -0
  40. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/llm_client.py +0 -0
  41. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/mcp.py +0 -0
  42. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/memory.py +0 -0
  43. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/model_intelligence.py +0 -0
  44. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/model_profiles.py +0 -0
  45. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/orchestrator.py +0 -0
  46. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/permissions.py +0 -0
  47. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/profiles.py +0 -0
  48. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/provider_registry.py +0 -0
  49. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/repl.py +0 -0
  50. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/router.py +0 -0
  51. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/rules.py +0 -0
  52. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/runner.py +0 -0
  53. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/safety.py +0 -0
  54. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/spawner.py +0 -0
  55. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/suggester.py +0 -0
  56. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/teams.py +0 -0
  57. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/tools.py +0 -0
  58. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/verifier.py +0 -0
  59. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/agent/voice.py +0 -0
  60. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/architect.py +0 -0
  61. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/auditor.py +0 -0
  62. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/auth.py +0 -0
  63. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/block_export.py +0 -0
  64. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/channel.py +0 -0
  65. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/ci_manager.py +0 -0
  66. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/commands/__init__.py +0 -0
  67. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/commands/intelligence.py +0 -0
  68. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/compliance/__init__.py +0 -0
  69. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/compliance/_compat.py +0 -0
  70. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/compliance/checker.py +0 -0
  71. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/compliance/evidence.py +0 -0
  72. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/compliance/regulations.py +0 -0
  73. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/compliance/reporter.py +0 -0
  74. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/compressor.py +0 -0
  75. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/config.py +0 -0
  76. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/console_utils.py +0 -0
  77. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/context_orchestrator.py +0 -0
  78. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/context_window.py +0 -0
  79. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/credit_analyzer.py +0 -0
  80. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/credits.py +0 -0
  81. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/__init__.py +0 -0
  82. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/base.py +0 -0
  83. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/citations.py +0 -0
  84. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/fpd.py +0 -0
  85. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/odp.py +0 -0
  86. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/patentsview.py +0 -0
  87. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/pfw.py +0 -0
  88. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/ppubs.py +0 -0
  89. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/datasources/ptab.py +0 -0
  90. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/differ.py +0 -0
  91. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/doctor.py +0 -0
  92. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/drive.py +0 -0
  93. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/editor.py +0 -0
  94. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/epistemic/__init__.py +0 -0
  95. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/epistemic/belief.py +0 -0
  96. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/epistemic/certainty.py +0 -0
  97. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/epistemic/failure_graph.py +0 -0
  98. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/epistemic/recovery.py +0 -0
  99. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/epistemic/stress_tester.py +0 -0
  100. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/esdb/__init__.py +0 -0
  101. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/esdb/bridge.py +0 -0
  102. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/eval/__init__.py +0 -0
  103. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/eval/builtins.py +0 -0
  104. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/eval/runner.py +0 -0
  105. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/executor.py +0 -0
  106. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/exporter.py +0 -0
  107. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/governance_logic.py +0 -0
  108. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/governance_store.py +0 -0
  109. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/governance_yaml.py +0 -0
  110. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/__init__.py +0 -0
  111. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/app.py +0 -0
  112. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/main_window.py +0 -0
  113. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/session_tab.py +0 -0
  114. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/theme.py +0 -0
  115. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/widgets/__init__.py +0 -0
  116. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/widgets/chat_view.py +0 -0
  117. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/widgets/input_bar.py +0 -0
  118. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  119. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/widgets/token_meter.py +0 -0
  120. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  121. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/widgets/update_checker.py +0 -0
  122. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/gui/worker.py +0 -0
  123. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/history_search.py +0 -0
  124. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/importer.py +0 -0
  125. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/instinct.py +0 -0
  126. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/__init__.py +0 -0
  127. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/agent_skill.py +0 -0
  128. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/aider.py +0 -0
  129. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/base.py +0 -0
  130. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/claude_code.py +0 -0
  131. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/codity.py +0 -0
  132. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/copilot.py +0 -0
  133. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/cursor.py +0 -0
  134. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/gemini.py +0 -0
  135. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/integrations/windsurf.py +0 -0
  136. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/issue_reporter.py +0 -0
  137. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/languages.py +0 -0
  138. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/ledger.py +0 -0
  139. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/mcp_generator.py +0 -0
  140. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/migrations/__init__.py +0 -0
  141. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
  142. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/migrations/m002_agents_slim.py +0 -0
  143. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/migrations/m003_compliance_init.py +0 -0
  144. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
  145. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
  146. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/migrations/m006_session_governance.py +0 -0
  147. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/migrations/runner.py +0 -0
  148. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/ollama_cmds.py +0 -0
  149. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/patent.py +0 -0
  150. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/paths.py +0 -0
  151. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/phase.py +0 -0
  152. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/plugins.py +0 -0
  153. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/profiles.py +0 -0
  154. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/rate_limits.py +0 -0
  155. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/releaser.py +0 -0
  156. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/requirements.py +0 -0
  157. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/requirements_parser.py +0 -0
  158. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/retrieval.py +0 -0
  159. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/safe_write.py +0 -0
  160. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/scaffolder.py +0 -0
  161. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/serve.py +0 -0
  162. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/session.py +0 -0
  163. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/session_init.py +0 -0
  164. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/session_store.py +0 -0
  165. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/__init__.py +0 -0
  166. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/cloud.py +0 -0
  167. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/corporate.py +0 -0
  168. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/cross_platform.py +0 -0
  169. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/devops.py +0 -0
  170. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/docs.py +0 -0
  171. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/embedded.py +0 -0
  172. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/governance.py +0 -0
  173. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/hardware.py +0 -0
  174. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/mobile.py +0 -0
  175. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/productivity.py +0 -0
  176. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/specsmith_skills.py +0 -0
  177. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills/ssh.py +0 -0
  178. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/skills_builder.py +0 -0
  179. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/sync.py +0 -0
  180. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/agents.md.j2 +0 -0
  181. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  182. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  183. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  184. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  185. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  186. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  187. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  188. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/community/security.md.j2 +0 -0
  189. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  190. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  191. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  192. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  193. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  194. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/editorconfig.j2 +0 -0
  195. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/gitattributes.j2 +0 -0
  196. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/gitignore.j2 +0 -0
  197. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/go/go.mod.j2 +0 -0
  198. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/go/main.go.j2 +0 -0
  199. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  200. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  201. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  202. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  203. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  204. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
  205. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  206. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  207. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
  208. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  209. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  210. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/js/package.json.j2 +0 -0
  211. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/ledger.md.j2 +0 -0
  212. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/python/cli.py.j2 +0 -0
  213. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/python/init.py.j2 +0 -0
  214. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  215. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/readme.md.j2 +0 -0
  216. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  217. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  218. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  219. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  220. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  221. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  222. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  223. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  224. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  225. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/tool_installer.py +0 -0
  226. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/toolrules.py +0 -0
  227. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/tools.py +0 -0
  228. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/trace.py +0 -0
  229. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/updater.py +0 -0
  230. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/upgrader.py +0 -0
  231. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/validator.py +0 -0
  232. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/vcs/__init__.py +0 -0
  233. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/vcs/base.py +0 -0
  234. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/vcs/bitbucket.py +0 -0
  235. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/vcs/github.py +0 -0
  236. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/vcs/gitlab.py +0 -0
  237. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/vcs_commands.py +0 -0
  238. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/wireframes.py +0 -0
  239. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith/workspace.py +0 -0
  240. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith.egg-info/SOURCES.txt +0 -0
  241. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith.egg-info/dependency_links.txt +0 -0
  242. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith.egg-info/entry_points.txt +0 -0
  243. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith.egg-info/requires.txt +0 -0
  244. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/src/specsmith.egg-info/top_level.txt +0 -0
  245. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_CMD_001.py +0 -0
  246. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_agent_profiles.py +0 -0
  247. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_agent_run_feedback.py +0 -0
  248. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_agent_runner_ready.py +0 -0
  249. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_ai_client.py +0 -0
  250. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_ai_intelligence.py +0 -0
  251. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_auditor.py +0 -0
  252. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_channel.py +0 -0
  253. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_chat_diff_decision.py +0 -0
  254. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_chat_runner_openai_compat.py +0 -0
  255. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_chat_stdin_protocol.py +0 -0
  256. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_cli.py +0 -0
  257. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_cli_workflows_history_drive.py +0 -0
  258. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_compliance.py +0 -0
  259. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_compressor.py +0 -0
  260. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_dispatch.py +0 -0
  261. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_e2e_nexus.py +0 -0
  262. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_endpoints_cli.py +0 -0
  263. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_endpoints_store.py +0 -0
  264. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_epistemic.py +0 -0
  265. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_fallback_chain.py +0 -0
  266. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_importer.py +0 -0
  267. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_integrations.py +0 -0
  268. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_integrations_codity.py +0 -0
  269. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_intelligence.py +0 -0
  270. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_issue_reporter.py +0 -0
  271. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_mcp_client.py +0 -0
  272. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_new_modules.py +0 -0
  273. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_nexus.py +0 -0
  274. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_permissions.py +0 -0
  275. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_phase1_4_new.py +0 -0
  276. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_phase34_completion.py +0 -0
  277. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_rate_limits.py +0 -0
  278. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_req_248_262.py +0 -0
  279. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_req_358_359.py +0 -0
  280. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_scaffolder.py +0 -0
  281. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_skill_marketplace.py +0 -0
  282. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_skills_mcp.py +0 -0
  283. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_smoke.py +0 -0
  284. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_suggester.py +0 -0
  285. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_tools.py +0 -0
  286. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_validator.py +0 -0
  287. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_vcs.py +0 -0
  288. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_warp_parity.py +0 -0
  289. {specsmith-0.12.0.dev493 → specsmith-0.12.0.dev494}/tests/test_warp_parity_followup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.12.0.dev493
3
+ Version: 0.12.0.dev494
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.12.0.dev493"
7
+ version = "0.12.0.dev494"
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"
@@ -3207,32 +3207,61 @@ def checkpoint_cmd(project_dir: str, as_json: bool) -> None:
3207
3207
 
3208
3208
  # ── Human-readable anchor block ───────────────────────────────────────────
3209
3209
  # Designed to be compact and survive context summarization.
3210
- hbar = "\u2550" * 57 # ═══…
3210
+ _w = 57 # interior width — must match len(hbar)
3211
+ hbar = "\u2550" * _w # ═══…
3211
3212
  vbar = "\u2551" # ║
3212
3213
  health_icon = "\u2713" if health_ok else "\u2717"
3213
3214
  esdb_icon = "\u2713" if esdb_ok else "\u2717"
3214
3215
  wi_str = ", ".join(recent_wis) if recent_wis else "none seen"
3215
3216
 
3217
+ def _arow(rich: str, plain: str, wide: int = 0) -> str:
3218
+ """Format one anchor box row: ║ <content padded to _w terminal cols> ║.
3219
+
3220
+ ``plain`` is the markup-free string used for width calculation.
3221
+ ``wide`` is the count of 2-wide (full-width/emoji) characters in ``plain``
3222
+ that add an extra terminal column beyond their Python ``len()``.
3223
+ """
3224
+ pad = " " * max(0, _w - len(plain) - wide)
3225
+ return f"[bold cyan]{vbar}[/bold cyan]{rich}{pad}[bold cyan]{vbar}[/bold cyan]"
3226
+
3216
3227
  console.print(f"[bold cyan]\u2554{hbar}\u2557[/bold cyan]")
3217
- console.print(f"[bold cyan]{vbar}[/bold cyan] GOVERNANCE ANCHOR {ts}")
3218
- console.print(f"[bold cyan]{vbar}[/bold cyan] Project : [bold]{project_name}[/bold]")
3219
- console.print(
3220
- f"[bold cyan]{vbar}[/bold cyan] Phase : {phase_emoji} {phase_label} ({phase_pct}%)"
3228
+
3229
+ r1 = f" GOVERNANCE ANCHOR {ts}"
3230
+ console.print(_arow(r1, r1))
3231
+
3232
+ r2_plain = f" Project : {project_name}"
3233
+ console.print(_arow(f" Project : [bold]{project_name}[/bold]", r2_plain))
3234
+
3235
+ r3_plain = f" Phase : {phase_emoji} {phase_label} ({phase_pct}%)"
3236
+ console.print(_arow(r3_plain, r3_plain, wide=1 if phase_emoji else 0))
3237
+
3238
+ r4_plain = (
3239
+ f" Health : {health_icon} clean"
3240
+ if health_ok
3241
+ else f" Health : {health_icon} {audit_failed} issues"
3221
3242
  )
3222
- health_str = (
3223
- f"[green]{health_icon} clean[/green]"
3243
+ r4_rich = (
3244
+ f" Health : [green]{health_icon} clean[/green]"
3224
3245
  if health_ok
3225
- else f"[red]{health_icon} {audit_failed} issues[/red]"
3246
+ else f" Health : [red]{health_icon} {audit_failed} issues[/red]"
3226
3247
  )
3227
- console.print(f"[bold cyan]{vbar}[/bold cyan] Health : {health_str}")
3228
- console.print(
3229
- f"[bold cyan]{vbar}[/bold cyan] REQs : {req_count} TESTs: {test_count}"
3248
+ console.print(_arow(r4_rich, r4_plain))
3249
+
3250
+ r5 = (
3251
+ f" REQs : {req_count} TESTs: {test_count}"
3230
3252
  f" ESDB: {esdb_records} records ({esdb_icon} chain)"
3231
3253
  )
3232
- console.print(f"[bold cyan]{vbar}[/bold cyan] WIs : {wi_str}")
3254
+ console.print(_arow(r5, r5))
3255
+
3256
+ r6 = f" WIs : {wi_str}"
3257
+ console.print(_arow(r6, r6))
3258
+
3233
3259
  if last_preflight:
3234
- pf_short = last_preflight[:55]
3235
- console.print(f"[bold cyan]{vbar}[/bold cyan] Preflight: {pf_short}")
3260
+ _pf_max = _w - len(" Preflight: ") # 45 — was incorrectly 55
3261
+ pf_short = last_preflight[:_pf_max]
3262
+ r7 = f" Preflight: {pf_short}"
3263
+ console.print(_arow(r7, r7))
3264
+
3236
3265
  console.print(f"[bold cyan]\u255a{hbar}\u255d[/bold cyan]")
3237
3266
  console.print(
3238
3267
  "[dim]Include this block verbatim in any context summary "
@@ -9021,13 +9050,23 @@ def mcp_list_cmd(project_dir: str, as_json: bool) -> None:
9021
9050
 
9022
9051
  @mcp_group.command(name="serve")
9023
9052
  @click.option("--project-dir", type=click.Path(), default=".", show_default=True)
9024
- def mcp_serve_cmd(project_dir: str) -> None:
9053
+ @click.option(
9054
+ "--project-dirs",
9055
+ default="",
9056
+ help=(
9057
+ "Additional project directories to register (comma-separated absolute paths). "
9058
+ "All registered projects are accessible to any tool call via their "
9059
+ "absolute path as the project_dir argument."
9060
+ ),
9061
+ )
9062
+ def mcp_serve_cmd(project_dir: str, project_dirs: str) -> None:
9025
9063
  """Start the native governance MCP stdio server (REQ-363).
9026
9064
 
9027
9065
  Implements MCP 2024-11-05 over stdin/stdout (JSON-RPC 2.0).
9028
- Exposes six governance tools to any MCP client:
9066
+ Exposes seven governance tools to any MCP client:
9029
9067
 
9030
9068
  \b
9069
+ governance_project_list List all registered projects
9031
9070
  governance_audit Run governance audit
9032
9071
  governance_checkpoint Emit GOVERNANCE ANCHOR JSON
9033
9072
  governance_preflight Preflight a change intent
@@ -9036,9 +9075,17 @@ def mcp_serve_cmd(project_dir: str) -> None:
9036
9075
  governance_trace_seal Seal a milestone/decision
9037
9076
 
9038
9077
  \b
9039
- Warp config (Settings → Agents → MCP servers)::
9078
+ Single-project Warp config (Settings → Agents → MCP servers)::
9040
9079
 
9041
- {"specsmith-governance": {"command": "specsmith", "args": ["mcp", "serve"]}}
9080
+ {"specsmith-governance": {"command": "specsmith",
9081
+ "args": ["mcp", "serve", "--project-dir", "/path/to/project"]}}
9082
+
9083
+ \b
9084
+ Multi-project Warp config::
9085
+
9086
+ {"specsmith-governance": {"command": "specsmith",
9087
+ "args": ["mcp", "serve", "--project-dir", "/path/to/proj1",
9088
+ "--project-dirs", "/path/to/proj2,/path/to/proj3"]}}
9042
9089
 
9043
9090
  \b
9044
9091
  Or pass inline to oz (use ``specsmith mcp install-warp`` for the full snippet)::
@@ -9047,17 +9094,26 @@ def mcp_serve_cmd(project_dir: str) -> None:
9047
9094
  """
9048
9095
  from specsmith.mcp_server import run_server
9049
9096
 
9050
- run_server(project_dir=project_dir)
9097
+ extra = [p.strip() for p in project_dirs.split(",") if p.strip()] if project_dirs else []
9098
+ run_server(project_dir=project_dir, extra_project_dirs=extra)
9051
9099
 
9052
9100
 
9053
9101
  @mcp_group.command(name="install-warp")
9054
9102
  @click.option("--project-dir", type=click.Path(), default=".", show_default=True)
9103
+ @click.option(
9104
+ "--project-dirs",
9105
+ default="",
9106
+ help="Additional project dirs (comma-separated) to include in the multi-project config.",
9107
+ )
9055
9108
  @click.option("--json", "as_json", is_flag=True, default=False, help="Emit JSON config only.")
9056
- def mcp_install_warp_cmd(project_dir: str, as_json: bool) -> None:
9109
+ def mcp_install_warp_cmd(project_dir: str, project_dirs: str, as_json: bool) -> None:
9057
9110
  """Print the Warp MCP config snippet for the governance server (REQ-363).
9058
9111
 
9059
9112
  Copy the output into Warp Settings → Agents → MCP servers, or pass it
9060
9113
  to ``oz agent run --mcp '<json>'`` for a one-off cloud agent run.
9114
+
9115
+ For multi-project setups pass ``--project-dirs`` with comma-separated
9116
+ absolute paths; one server instance will serve all projects.
9061
9117
  """
9062
9118
  import json as _json
9063
9119
  import shutil
@@ -9068,10 +9124,17 @@ def mcp_install_warp_cmd(project_dir: str, as_json: bool) -> None:
9068
9124
  specsmith_exe = shutil.which("specsmith") or str(
9069
9125
  Path(sys.executable).parent / ("specsmith.exe" if sys.platform == "win32" else "specsmith")
9070
9126
  )
9127
+ default_dir = str(Path(project_dir).resolve())
9128
+ args: list[str] = ["mcp", "serve", "--project-dir", default_dir]
9129
+
9130
+ extra_dirs = [p.strip() for p in project_dirs.split(",") if p.strip()] if project_dirs else []
9131
+ if extra_dirs:
9132
+ args += ["--project-dirs", ",".join(extra_dirs)]
9133
+
9071
9134
  config = {
9072
9135
  "specsmith-governance": {
9073
9136
  "command": specsmith_exe,
9074
- "args": ["mcp", "serve", "--project-dir", str(Path(project_dir).resolve())],
9137
+ "args": args,
9075
9138
  }
9076
9139
  }
9077
9140
 
@@ -9085,12 +9148,22 @@ def mcp_install_warp_cmd(project_dir: str, as_json: bool) -> None:
9085
9148
  "or pass inline to [bold]oz agent run --mcp '<json>'[/bold]:\n"
9086
9149
  )
9087
9150
  console.print(_json.dumps(config, indent=2))
9088
- console.print(
9089
- "\n[dim]After adding, Warp/Oz can call governance_audit, governance_preflight,\n"
9090
- "governance_checkpoint, governance_phase, governance_req_list, and\n"
9091
- "governance_trace_seal as structured MCP tool calls.\n"
9092
- "\nVerify with: specsmith mcp serve (then send an initialize message).[/dim]"
9093
- )
9151
+ if extra_dirs:
9152
+ console.print(
9153
+ f"\n[dim]Serving {1 + len(extra_dirs)} projects. "
9154
+ "Call [bold]governance_project_list[/bold] to see all registered paths,\n"
9155
+ "then pass any path as [bold]project_dir[/bold] to target a specific project.[/dim]"
9156
+ )
9157
+ else:
9158
+ console.print(
9159
+ "\n[dim]After adding, Warp/Oz can call governance_project_list, "
9160
+ "governance_audit, governance_preflight,\n"
9161
+ "governance_checkpoint, governance_phase, governance_req_list, and\n"
9162
+ "governance_trace_seal as structured MCP tool calls.\n"
9163
+ "\nFor multiple projects add --project-dirs /path/a,/path/b to serve them "
9164
+ "all from one server instance.\n"
9165
+ "\nVerify with: specsmith mcp serve (then send an initialize message).[/dim]"
9166
+ )
9094
9167
 
9095
9168
 
9096
9169
  main.add_command(mcp_group)
@@ -35,7 +35,6 @@ No external dependencies — stdlib only + existing specsmith modules.
35
35
 
36
36
  from __future__ import annotations
37
37
 
38
- import contextlib
39
38
  import json
40
39
  import sys
41
40
  import time
@@ -50,7 +49,30 @@ MCP_PROTOCOL_VERSION = "2024-11-05"
50
49
  SERVER_NAME = "specsmith-governance"
51
50
  SERVER_VERSION = "0.12.0"
52
51
 
52
+ # ---------------------------------------------------------------------------
53
+ # Multi-project state — populated by run_server() at startup
54
+ # ---------------------------------------------------------------------------
55
+
56
+ # Default project dir used when a tool call omits ``project_dir``.
57
+ _DEFAULT_PROJECT_DIR: str = "."
58
+
59
+ # All registered project directories (absolute paths), default first.
60
+ _REGISTERED_PROJECTS: list[str] = []
61
+
53
62
  _TOOLS: list[dict[str, Any]] = [
63
+ {
64
+ "name": "governance_project_list",
65
+ "description": (
66
+ "List all project directories registered in this MCP server instance. "
67
+ "Use the returned paths as the `project_dir` argument for other tools "
68
+ "when working with multiple simultaneous projects."
69
+ ),
70
+ "inputSchema": {
71
+ "type": "object",
72
+ "properties": {},
73
+ "required": [],
74
+ },
75
+ },
54
76
  {
55
77
  "name": "governance_audit",
56
78
  "description": (
@@ -195,10 +217,25 @@ _TOOLS: list[dict[str, Any]] = [
195
217
 
196
218
 
197
219
  def _resolve_root(args: dict[str, Any]) -> Path:
198
- raw = args.get("project_dir", ".")
220
+ """Resolve project_dir from args, falling back to the server default.
221
+
222
+ If ``project_dir`` is not in *args* (or is empty), we use
223
+ ``_DEFAULT_PROJECT_DIR`` so callers don't have to repeat the path on
224
+ every tool call when only one project is active.
225
+ """
226
+ raw = args.get("project_dir") or _DEFAULT_PROJECT_DIR
199
227
  return Path(str(raw)).resolve()
200
228
 
201
229
 
230
+ def _handle_governance_project_list(args: dict[str, Any]) -> dict[str, Any]: # noqa: ARG001
231
+ """Return the list of projects registered in this server instance."""
232
+ return {
233
+ "default_project": _DEFAULT_PROJECT_DIR,
234
+ "projects": _REGISTERED_PROJECTS,
235
+ "count": len(_REGISTERED_PROJECTS),
236
+ }
237
+
238
+
202
239
  def _handle_governance_audit(args: dict[str, Any]) -> dict[str, Any]:
203
240
  """Run the governance audit and return structured results."""
204
241
  root = _resolve_root(args)
@@ -487,6 +524,7 @@ def _handle_governance_trace_seal(args: dict[str, Any]) -> dict[str, Any]:
487
524
  # ---------------------------------------------------------------------------
488
525
 
489
526
  _HANDLERS = {
527
+ "governance_project_list": _handle_governance_project_list,
490
528
  "governance_audit": _handle_governance_audit,
491
529
  "governance_checkpoint": _handle_governance_checkpoint,
492
530
  "governance_preflight": _handle_governance_preflight,
@@ -576,20 +614,32 @@ def _handle_request(msg: dict[str, Any]) -> dict[str, Any] | None:
576
614
  return None
577
615
 
578
616
 
579
- def run_server(project_dir: str = ".") -> None:
617
+ def run_server(
618
+ project_dir: str = ".",
619
+ extra_project_dirs: list[str] | None = None,
620
+ ) -> None:
580
621
  """Start the MCP stdio server. Blocks until stdin closes.
581
622
 
582
623
  Reads newline-delimited JSON-RPC 2.0 messages from stdin and
583
624
  writes responses to stdout. Stderr is used for diagnostic messages.
584
- The ``project_dir`` is injected into every tool call that doesn't
585
- supply its own ``project_dir`` argument.
586
- """
587
- import os
588
625
 
589
- # Set working directory so relative paths in tool calls resolve correctly
590
- if project_dir and project_dir != ".":
591
- with contextlib.suppress(OSError):
592
- os.chdir(project_dir)
626
+ ``project_dir`` becomes the default for tool calls that omit
627
+ ``project_dir``. ``extra_project_dirs`` registers additional projects
628
+ accessible via ``governance_project_list`` and addressable by any tool
629
+ using their absolute path as ``project_dir``.
630
+
631
+ The server no longer calls ``os.chdir()``; all paths are resolved
632
+ absolutely, so the server can serve multiple projects from one process.
633
+ """
634
+ global _DEFAULT_PROJECT_DIR, _REGISTERED_PROJECTS
635
+
636
+ # Register projects — always use absolute paths
637
+ _DEFAULT_PROJECT_DIR = str(Path(project_dir).resolve())
638
+ _REGISTERED_PROJECTS = [_DEFAULT_PROJECT_DIR]
639
+ for extra in extra_project_dirs or []:
640
+ abs_extra = str(Path(extra).resolve())
641
+ if abs_extra not in _REGISTERED_PROJECTS:
642
+ _REGISTERED_PROJECTS.append(abs_extra)
593
643
 
594
644
  for raw_line in sys.stdin:
595
645
  raw_line = raw_line.strip()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.12.0.dev493
3
+ Version: 0.12.0.dev494
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
@@ -78,12 +78,13 @@ class TestMcpProtocol:
78
78
  assert result["serverInfo"]["name"] == "specsmith-governance"
79
79
  assert "tools" in result["capabilities"]
80
80
 
81
- def test_tools_list_returns_six_tools(self) -> None:
81
+ def test_tools_list_returns_seven_tools(self) -> None:
82
82
  resp = _send_rpc(_make_rpc("tools/list", {}, req_id=2))
83
83
  tools = resp["result"]["tools"]
84
- assert len(tools) == 6
84
+ assert len(tools) == 7
85
85
  names = {t["name"] for t in tools}
86
86
  assert names == {
87
+ "governance_project_list",
87
88
  "governance_audit",
88
89
  "governance_checkpoint",
89
90
  "governance_preflight",
@@ -311,6 +312,80 @@ class TestGovernanceReqList:
311
312
  assert resp["result"]["isError"] is False
312
313
 
313
314
 
315
+ class TestGovernanceProjectList:
316
+ def test_returns_default_project(self, tmp_path: Path) -> None:
317
+ from specsmith.mcp_server import _handle_governance_project_list, run_server
318
+
319
+ # Prime server state with a known directory
320
+ run_server.__func__ if hasattr(run_server, "__func__") else run_server # noqa: B018
321
+ import specsmith.mcp_server as _mod
322
+
323
+ _mod._DEFAULT_PROJECT_DIR = str(tmp_path)
324
+ _mod._REGISTERED_PROJECTS = [str(tmp_path)]
325
+
326
+ result = _handle_governance_project_list({})
327
+ assert result["default_project"] == str(tmp_path)
328
+ assert str(tmp_path) in result["projects"]
329
+ assert result["count"] >= 1
330
+
331
+ def test_via_tools_call(self, tmp_path: Path) -> None:
332
+ import specsmith.mcp_server as _mod
333
+
334
+ _mod._DEFAULT_PROJECT_DIR = str(tmp_path)
335
+ _mod._REGISTERED_PROJECTS = [str(tmp_path)]
336
+
337
+ resp = _send_rpc(
338
+ _make_rpc(
339
+ "tools/call",
340
+ {"name": "governance_project_list", "arguments": {}},
341
+ req_id=30,
342
+ )
343
+ )
344
+ assert resp["result"]["isError"] is False
345
+ content = json.loads(resp["result"]["content"][0]["text"])
346
+ assert "projects" in content
347
+ assert "count" in content
348
+
349
+ def test_extra_projects_registered(self, tmp_path: Path) -> None:
350
+ """run_server registers extra_project_dirs and they appear in project_list."""
351
+ import io
352
+
353
+ import specsmith.mcp_server as _mod
354
+ from specsmith.mcp_server import run_server
355
+
356
+ extra = tmp_path / "extra"
357
+ extra.mkdir()
358
+
359
+ # Patch stdin to EOF immediately so run_server exits
360
+ old_stdin = sys.stdin
361
+ sys.stdin = io.StringIO("")
362
+ try:
363
+ run_server(project_dir=str(tmp_path), extra_project_dirs=[str(extra)])
364
+ finally:
365
+ sys.stdin = old_stdin
366
+
367
+ assert str(tmp_path.resolve()) == _mod._DEFAULT_PROJECT_DIR
368
+ assert str(extra.resolve()) in _mod._REGISTERED_PROJECTS
369
+ assert _mod._REGISTERED_PROJECTS[0] == str(tmp_path.resolve())
370
+
371
+ def test_no_chdir_called(self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None:
372
+ """run_server must NOT call os.chdir — paths are resolved absolutely."""
373
+ import io
374
+
375
+ from specsmith.mcp_server import run_server
376
+
377
+ chdir_calls: list[str] = []
378
+ monkeypatch.setattr("os.chdir", lambda p: chdir_calls.append(str(p)))
379
+ old_stdin = sys.stdin
380
+ sys.stdin = io.StringIO("")
381
+ try:
382
+ run_server(project_dir=str(tmp_path))
383
+ finally:
384
+ sys.stdin = old_stdin
385
+
386
+ assert chdir_calls == [], "run_server must not call os.chdir"
387
+
388
+
314
389
  class TestGovernanceTraceSeal:
315
390
  def test_missing_description_returns_error(self, tmp_path: Path) -> None:
316
391
  from specsmith.mcp_server import _handle_governance_trace_seal
@@ -458,4 +533,4 @@ class TestMcpServeCli:
458
533
  tools_resp = json.loads(lines[-1])
459
534
  assert "result" in tools_resp
460
535
  tools = tools_resp["result"]["tools"]
461
- assert len(tools) == 6
536
+ assert len(tools) == 7