specsmith 0.17.0.dev644__tar.gz → 0.17.0.dev649__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 (336) hide show
  1. {specsmith-0.17.0.dev644/src/specsmith.egg-info → specsmith-0.17.0.dev649}/PKG-INFO +1 -1
  2. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/pyproject.toml +1 -1
  3. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/ci_manager.py +4 -1
  4. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/cli.py +36 -27
  5. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/config.py +21 -0
  6. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/differ.py +15 -9
  7. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/doctor.py +6 -3
  8. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/exporter.py +3 -0
  9. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/governance_logic.py +6 -3
  10. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/profiles.py +4 -2
  11. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/quality_report.py +4 -6
  12. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/updater.py +3 -3
  13. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/upgrader.py +4 -1
  14. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/validator.py +26 -20
  15. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/vcs_commands.py +9 -5
  16. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649/src/specsmith.egg-info}/PKG-INFO +1 -1
  17. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/LICENSE +0 -0
  18. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/README.md +0 -0
  19. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/setup.cfg +0 -0
  20. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/__init__.py +0 -0
  21. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/belief.py +0 -0
  22. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/certainty.py +0 -0
  23. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/failure_graph.py +0 -0
  24. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/py.typed +0 -0
  25. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/recovery.py +0 -0
  26. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/session.py +0 -0
  27. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/stress_tester.py +0 -0
  28. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/epistemic/trace.py +0 -0
  29. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/__init__.py +0 -0
  30. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/__main__.py +0 -0
  31. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/__init__.py +0 -0
  32. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/broker.py +0 -0
  33. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/chat_runner.py +0 -0
  34. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/cleanup.py +0 -0
  35. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/context_seed.py +0 -0
  36. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/core.py +0 -0
  37. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/dispatch/__init__.py +0 -0
  38. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/dispatch/_status.py +0 -0
  39. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/dispatch/dag.py +0 -0
  40. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/dispatch/dispatcher.py +0 -0
  41. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/dispatch/events.py +0 -0
  42. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/dispatch/result.py +0 -0
  43. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/endpoints.py +0 -0
  44. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/events.py +0 -0
  45. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/execution_profiles.py +0 -0
  46. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/fallback.py +0 -0
  47. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/hf_leaderboard.py +0 -0
  48. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/hf_sync.py +0 -0
  49. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/indexer.py +0 -0
  50. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/llm_client.py +0 -0
  51. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/mcp.py +0 -0
  52. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/memory.py +0 -0
  53. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/model_intelligence.py +0 -0
  54. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/model_profiles.py +0 -0
  55. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/model_router.py +0 -0
  56. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/orchestrator.py +0 -0
  57. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/permissions.py +0 -0
  58. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/profiles.py +0 -0
  59. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/provider_registry.py +0 -0
  60. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/repl.py +0 -0
  61. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/router.py +0 -0
  62. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/rules.py +0 -0
  63. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/runner.py +0 -0
  64. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/safety.py +0 -0
  65. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/spawner.py +0 -0
  66. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/suggester.py +0 -0
  67. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/teams.py +0 -0
  68. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/tools.py +0 -0
  69. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/verifier.py +0 -0
  70. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/agent/voice.py +0 -0
  71. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/approvals.py +0 -0
  72. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/architect.py +0 -0
  73. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/auditor.py +0 -0
  74. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/auth.py +0 -0
  75. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/block_export.py +0 -0
  76. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/channel.py +0 -0
  77. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/commands/__init__.py +0 -0
  78. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/commands/intelligence.py +0 -0
  79. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/commands/issues_policy.py +0 -0
  80. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/commands/reporting.py +0 -0
  81. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/compliance/__init__.py +0 -0
  82. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/compliance/_compat.py +0 -0
  83. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/compliance/checker.py +0 -0
  84. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/compliance/evidence.py +0 -0
  85. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/compliance/regulations.py +0 -0
  86. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/compliance/reporter.py +0 -0
  87. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/compressor.py +0 -0
  88. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/console_utils.py +0 -0
  89. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/context_orchestrator.py +0 -0
  90. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/context_window.py +0 -0
  91. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/credit_analyzer.py +0 -0
  92. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/credits.py +0 -0
  93. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/dashboard.py +0 -0
  94. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/__init__.py +0 -0
  95. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/base.py +0 -0
  96. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/citations.py +0 -0
  97. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/fpd.py +0 -0
  98. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/odp.py +0 -0
  99. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/patentsview.py +0 -0
  100. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/pfw.py +0 -0
  101. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/ppubs.py +0 -0
  102. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/datasources/ptab.py +0 -0
  103. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/drive.py +0 -0
  104. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/editor.py +0 -0
  105. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/epistemic/__init__.py +0 -0
  106. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/epistemic/belief.py +0 -0
  107. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/epistemic/certainty.py +0 -0
  108. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/epistemic/failure_graph.py +0 -0
  109. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/epistemic/recovery.py +0 -0
  110. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/epistemic/stress_tester.py +0 -0
  111. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/esdb/__init__.py +0 -0
  112. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/esdb/_license.py +0 -0
  113. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/esdb/bridge.py +0 -0
  114. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/esdb/sqlite_store.py +0 -0
  115. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/eval/__init__.py +0 -0
  116. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/eval/builtins.py +0 -0
  117. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/eval/runner.py +0 -0
  118. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/executor.py +0 -0
  119. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/governance_store.py +0 -0
  120. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/governance_yaml.py +0 -0
  121. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/governed_pr.py +0 -0
  122. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/__init__.py +0 -0
  123. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/app.py +0 -0
  124. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/main_window.py +0 -0
  125. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/session_tab.py +0 -0
  126. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/theme.py +0 -0
  127. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/widgets/__init__.py +0 -0
  128. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/widgets/chat_view.py +0 -0
  129. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/widgets/input_bar.py +0 -0
  130. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/widgets/provider_bar.py +0 -0
  131. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/widgets/token_meter.py +0 -0
  132. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/widgets/tool_panel.py +0 -0
  133. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/widgets/update_checker.py +0 -0
  134. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/gui/worker.py +0 -0
  135. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/history_search.py +0 -0
  136. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/importer.py +0 -0
  137. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/instinct.py +0 -0
  138. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/__init__.py +0 -0
  139. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/agent_skill.py +0 -0
  140. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/aider.py +0 -0
  141. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/base.py +0 -0
  142. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/claude_code.py +0 -0
  143. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/codity.py +0 -0
  144. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/copilot.py +0 -0
  145. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/cursor.py +0 -0
  146. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/gemini.py +0 -0
  147. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/integrations/windsurf.py +0 -0
  148. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/issue_reporter.py +0 -0
  149. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/languages.py +0 -0
  150. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/ledger.py +0 -0
  151. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/local_model.py +0 -0
  152. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/mcp_generator.py +0 -0
  153. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/mcp_server.py +0 -0
  154. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/__init__.py +0 -0
  155. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/m001_governance_yaml.py +0 -0
  156. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/m002_agents_slim.py +0 -0
  157. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/m003_compliance_init.py +0 -0
  158. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/m004_ledger_esdb.py +0 -0
  159. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/m005_agent_run_tool.py +0 -0
  160. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/m006_session_governance.py +0 -0
  161. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/m007_yaml_first.py +0 -0
  162. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/migrations/runner.py +0 -0
  163. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/ollama_cmds.py +0 -0
  164. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/patent.py +0 -0
  165. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/paths.py +0 -0
  166. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/phase.py +0 -0
  167. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/plugins.py +0 -0
  168. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/policy.py +0 -0
  169. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/project_metrics.py +0 -0
  170. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/rate_limits.py +0 -0
  171. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/recover.py +0 -0
  172. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/releaser.py +0 -0
  173. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/requirements.py +0 -0
  174. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/requirements_parser.py +0 -0
  175. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/retrieval.py +0 -0
  176. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/risk.py +0 -0
  177. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/safe_write.py +0 -0
  178. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/scaffolder.py +0 -0
  179. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/serve.py +0 -0
  180. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/session.py +0 -0
  181. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/session_init.py +0 -0
  182. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/session_store.py +0 -0
  183. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/__init__.py +0 -0
  184. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/ai_agents.py +0 -0
  185. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/cloud.py +0 -0
  186. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/corporate.py +0 -0
  187. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/cross_platform.py +0 -0
  188. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/data_engineering.py +0 -0
  189. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/devops.py +0 -0
  190. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/docs.py +0 -0
  191. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/embedded.py +0 -0
  192. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/governance.py +0 -0
  193. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/hardware.py +0 -0
  194. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/mobile.py +0 -0
  195. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/platform_engineering.py +0 -0
  196. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/productivity.py +0 -0
  197. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/software_engineering.py +0 -0
  198. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/specsmith_skills.py +0 -0
  199. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/ssh.py +0 -0
  200. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills/web_backend.py +0 -0
  201. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/skills_builder.py +0 -0
  202. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/sync.py +0 -0
  203. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/agents.md.j2 +0 -0
  204. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/community/bug_report.md.j2 +0 -0
  205. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/community/code_of_conduct.md.j2 +0 -0
  206. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/community/contributing.md.j2 +0 -0
  207. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/community/feature_request.md.j2 +0 -0
  208. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/community/license-Apache-2.0.j2 +0 -0
  209. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/community/license-MIT.j2 +0 -0
  210. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/community/pull_request_template.md.j2 +0 -0
  211. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/community/security.md.j2 +0 -0
  212. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/docs/architecture.md.j2 +0 -0
  213. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/docs/mkdocs.yml.j2 +0 -0
  214. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/docs/readthedocs.yaml.j2 +0 -0
  215. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/docs/requirements.md.j2 +0 -0
  216. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/docs/test-spec.md.j2 +0 -0
  217. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/editorconfig.j2 +0 -0
  218. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/gitattributes.j2 +0 -0
  219. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/gitignore.j2 +0 -0
  220. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/go/go.mod.j2 +0 -0
  221. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/go/main.go.j2 +0 -0
  222. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/belief-registry.md.j2 +0 -0
  223. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/context-budget.md.j2 +0 -0
  224. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/drift-metrics.md.j2 +0 -0
  225. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/epistemic-axioms.md.j2 +0 -0
  226. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/failure-modes.md.j2 +0 -0
  227. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/lifecycle.md.j2 +0 -0
  228. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/roles.md.j2 +0 -0
  229. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/rules.md.j2 +0 -0
  230. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/session-protocol.md.j2 +0 -0
  231. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/uncertainty-map.md.j2 +0 -0
  232. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/governance/verification.md.j2 +0 -0
  233. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/js/package.json.j2 +0 -0
  234. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/ledger.md.j2 +0 -0
  235. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/python/cli.py.j2 +0 -0
  236. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/python/init.py.j2 +0 -0
  237. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/python/pyproject.toml.j2 +0 -0
  238. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/readme.md.j2 +0 -0
  239. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/rust/Cargo.toml.j2 +0 -0
  240. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/rust/main.rs.j2 +0 -0
  241. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/scripts/exec.cmd.j2 +0 -0
  242. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/scripts/exec.sh.j2 +0 -0
  243. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/scripts/run.cmd.j2 +0 -0
  244. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/scripts/run.sh.j2 +0 -0
  245. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/scripts/setup.cmd.j2 +0 -0
  246. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/scripts/setup.sh.j2 +0 -0
  247. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/templates/workflows/release.yml.j2 +0 -0
  248. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/tool_installer.py +0 -0
  249. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/toolrules.py +0 -0
  250. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/tools.py +0 -0
  251. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/trace.py +0 -0
  252. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/transcripts.py +0 -0
  253. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/vcs/__init__.py +0 -0
  254. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/vcs/base.py +0 -0
  255. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/vcs/bitbucket.py +0 -0
  256. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/vcs/github.py +0 -0
  257. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/vcs/gitlab.py +0 -0
  258. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/wi_store.py +0 -0
  259. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/wireframes.py +0 -0
  260. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith/workspace.py +0 -0
  261. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith.egg-info/SOURCES.txt +0 -0
  262. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith.egg-info/dependency_links.txt +0 -0
  263. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith.egg-info/entry_points.txt +0 -0
  264. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith.egg-info/requires.txt +0 -0
  265. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/src/specsmith.egg-info/top_level.txt +0 -0
  266. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_CMD_001.py +0 -0
  267. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_agent_profiles.py +0 -0
  268. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_agent_run_feedback.py +0 -0
  269. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_agent_runner_ready.py +0 -0
  270. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_ai_client.py +0 -0
  271. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_ai_intelligence.py +0 -0
  272. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_architect_interview.py +0 -0
  273. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_architect_v2.py +0 -0
  274. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_architecture.py +0 -0
  275. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_auditor.py +0 -0
  276. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_channel.py +0 -0
  277. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_chat_diff_decision.py +0 -0
  278. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_chat_runner_openai_compat.py +0 -0
  279. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_chat_stdin_protocol.py +0 -0
  280. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_cleanup_cmd.py +0 -0
  281. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_cli.py +0 -0
  282. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_cli_regressions.py +0 -0
  283. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_cli_workflows_history_drive.py +0 -0
  284. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_compliance.py +0 -0
  285. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_compliance_governance.py +0 -0
  286. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_compressor.py +0 -0
  287. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_dispatch.py +0 -0
  288. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_e2e_nexus.py +0 -0
  289. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_endpoints_cli.py +0 -0
  290. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_endpoints_store.py +0 -0
  291. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_epistemic.py +0 -0
  292. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_esdb_backend_switch.py +0 -0
  293. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_esdb_enforcement.py +0 -0
  294. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_esdb_license.py +0 -0
  295. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_esdb_sqlite.py +0 -0
  296. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_esdb_verify_chain_cli.py +0 -0
  297. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_fallback_chain.py +0 -0
  298. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_golden_path.py +0 -0
  299. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_importer.py +0 -0
  300. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_init_modes.py +0 -0
  301. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_integrations.py +0 -0
  302. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_integrations_codity.py +0 -0
  303. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_intelligence.py +0 -0
  304. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_issue_policy_features.py +0 -0
  305. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_issue_reporter.py +0 -0
  306. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_issues_263_264.py +0 -0
  307. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_local_model.py +0 -0
  308. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_markdown_deprecation.py +0 -0
  309. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_mcp_client.py +0 -0
  310. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_mcp_server.py +0 -0
  311. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_migration_direction.py +0 -0
  312. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_model_router.py +0 -0
  313. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_new_modules.py +0 -0
  314. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_nexus.py +0 -0
  315. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_permissions.py +0 -0
  316. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_phase1_4_new.py +0 -0
  317. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_phase34_completion.py +0 -0
  318. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_project_metrics.py +0 -0
  319. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_quality_report.py +0 -0
  320. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_rate_limits.py +0 -0
  321. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_reporting_commands.py +0 -0
  322. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_req_248_262.py +0 -0
  323. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_req_358_359.py +0 -0
  324. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_scaffolder.py +0 -0
  325. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_schema_migrations.py +0 -0
  326. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_skill_marketplace.py +0 -0
  327. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_skills_mcp.py +0 -0
  328. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_smoke.py +0 -0
  329. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_suggester.py +0 -0
  330. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_tools.py +0 -0
  331. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_typing_guardrails.py +0 -0
  332. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_validator.py +0 -0
  333. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_vcs.py +0 -0
  334. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_warp_parity.py +0 -0
  335. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_warp_parity_followup.py +0 -0
  336. {specsmith-0.17.0.dev644 → specsmith-0.17.0.dev649}/tests/test_wi_lifecycle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.17.0.dev644
3
+ Version: 0.17.0.dev649
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "specsmith"
7
- version = "0.17.0.dev644"
7
+ version = "0.17.0.dev649"
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"
@@ -157,11 +157,14 @@ class CiManager:
157
157
 
158
158
  import yaml
159
159
 
160
+ from specsmith.config import _normalize_scaffold_raw
161
+
160
162
  raw = yaml.safe_load(scaffold_path.read_text(encoding="utf-8")) or {}
163
+ raw = _normalize_scaffold_raw(raw)
161
164
  try:
162
165
  config = ProjectConfig(**raw)
163
166
  except Exception as exc:
164
- raise RuntimeError(f"Invalid scaffold.yml: {exc}") from exc
167
+ raise RuntimeError(f"Invalid scaffold config: {exc}") from exc
165
168
 
166
169
  p_name = platform or _detect_platform(self.root)
167
170
  self._platform_name = p_name
@@ -1845,8 +1845,9 @@ def doctor(project_dir: str, onboarding: bool, as_json: bool) -> None:
1845
1845
  import subprocess
1846
1846
  import sys
1847
1847
 
1848
+ # Single import style (no from-import) avoids CodeQL py/import-and-import-from.
1849
+ import specsmith.esdb as _esdb_mod_dr
1848
1850
  from specsmith.auditor import run_audit
1849
- from specsmith.esdb import open_default_store
1850
1851
  from specsmith.phase import read_phase
1851
1852
 
1852
1853
  def _tool_version(cmd: str) -> tuple[bool, str]:
@@ -1896,7 +1897,7 @@ def doctor(project_dir: str, onboarding: bool, as_json: bool) -> None:
1896
1897
  chain_ok = False
1897
1898
  record_count = 0
1898
1899
  try:
1899
- with open_default_store(root, warn=False) as store: # type: ignore[attr-defined]
1900
+ with _esdb_mod_dr.open_default_store(root, warn=False) as store: # type: ignore[attr-defined]
1900
1901
  esdb_open = True
1901
1902
  record_count = int(store.record_count())
1902
1903
  chain_ok = store.chain_valid() is not False
@@ -1904,10 +1905,9 @@ def doctor(project_dir: str, onboarding: bool, as_json: bool) -> None:
1904
1905
  _add("esdb backend", False, f"open failed: {exc}")
1905
1906
  if esdb_open:
1906
1907
  # Re-read the module-level ESDB_BACKEND — open_default_store() updates
1907
- # the global in-place, so the locally-imported name is stale.
1908
- import specsmith.esdb as _esdb_mod
1909
-
1910
- _add("esdb backend", True, f"{_esdb_mod.ESDB_BACKEND} open")
1908
+ # the global in-place so we read it via the module object, not a
1909
+ # locally-imported name that would be stale. (#263)
1910
+ _add("esdb backend", True, f"{_esdb_mod_dr.ESDB_BACKEND} open")
1911
1911
  _add(
1912
1912
  "esdb chain",
1913
1913
  chain_ok,
@@ -2935,16 +2935,20 @@ main.add_command(test)
2935
2935
  @click.option("--project-dir", type=click.Path(exists=True), default=".")
2936
2936
  def migrate(new_type: str, project_dir: str) -> None:
2937
2937
  """Change the project type and regenerate type-dependent files."""
2938
+ from specsmith.config import _normalize_scaffold_raw
2939
+ from specsmith.paths import find_scaffold
2940
+
2938
2941
  root = Path(project_dir).resolve()
2939
- scaffold_path = root / "scaffold.yml"
2942
+ scaffold_path = find_scaffold(root)
2940
2943
 
2941
- if not scaffold_path.exists():
2942
- console.print("[red]No scaffold.yml found.[/red]")
2944
+ if not scaffold_path or not scaffold_path.exists():
2945
+ console.print("[red]No scaffold config found (docs/SPECSMITH.yml or scaffold.yml).[/red]")
2943
2946
  raise SystemExit(1)
2944
2947
 
2945
2948
  with open(scaffold_path) as f:
2946
2949
  raw = yaml.safe_load(f)
2947
2950
 
2951
+ raw = _normalize_scaffold_raw(raw or {})
2948
2952
  old_type = raw.get("type", "unknown")
2949
2953
  raw["type"] = new_type
2950
2954
 
@@ -3103,17 +3107,21 @@ def verify_release() -> None:
3103
3107
  help="Project root directory.",
3104
3108
  )
3105
3109
  def apply(project_dir: str) -> None:
3106
- """Regenerate CI and agent files from current scaffold.yml."""
3110
+ """Regenerate CI and agent files from current scaffold config."""
3111
+ from specsmith.config import _normalize_scaffold_raw
3112
+ from specsmith.paths import find_scaffold
3113
+
3107
3114
  root = Path(project_dir).resolve()
3108
- scaffold_path = root / "scaffold.yml"
3115
+ scaffold_path = find_scaffold(root)
3109
3116
 
3110
- if not scaffold_path.exists():
3111
- console.print("[red]No scaffold.yml found.[/red]")
3117
+ if not scaffold_path or not scaffold_path.exists():
3118
+ console.print("[red]No scaffold config found (docs/SPECSMITH.yml or scaffold.yml).[/red]")
3112
3119
  raise SystemExit(1)
3113
3120
 
3114
3121
  with open(scaffold_path) as f:
3115
3122
  raw = yaml.safe_load(f)
3116
3123
 
3124
+ raw = _normalize_scaffold_raw(raw or {})
3117
3125
  config = ProjectConfig(**raw)
3118
3126
  created: list[Path] = []
3119
3127
 
@@ -8032,19 +8040,21 @@ def tools_scan_cmd(project_dir: str, as_json: bool, fpga: bool) -> None:
8032
8040
 
8033
8041
  import yaml
8034
8042
 
8035
- from specsmith.config import ProjectConfig
8043
+ from specsmith.config import ProjectConfig, _normalize_scaffold_raw
8036
8044
  from specsmith.doctor import _check_tool
8045
+ from specsmith.paths import find_scaffold
8037
8046
 
8038
8047
  root = Path(project_dir).resolve()
8039
- scaffold_path = root / "scaffold.yml"
8048
+ scaffold_path = find_scaffold(root)
8040
8049
 
8041
8050
  checks: list[dict] = []
8042
8051
 
8043
8052
  # Standard project tools via doctor
8044
- if scaffold_path.exists():
8053
+ if scaffold_path and scaffold_path.exists():
8045
8054
  try:
8046
8055
  with open(scaffold_path) as f:
8047
8056
  raw = yaml.safe_load(f) or {}
8057
+ raw = _normalize_scaffold_raw(raw)
8048
8058
  config = ProjectConfig(**raw)
8049
8059
  from specsmith.tools import get_tools
8050
8060
 
@@ -8075,10 +8085,10 @@ def tools_scan_cmd(project_dir: str, as_json: bool, fpga: bool) -> None:
8075
8085
  )
8076
8086
  except Exception as e: # noqa: BLE001
8077
8087
  if not as_json:
8078
- console.print(f"[yellow]Could not read scaffold.yml: {e}[/yellow]")
8088
+ console.print(f"[yellow]Could not read scaffold config: {e}[/yellow]")
8079
8089
 
8080
8090
  # FPGA/HDL tools from scaffold.yml fpga_tools list
8081
- if fpga and scaffold_path.exists():
8091
+ if fpga and scaffold_path and scaffold_path.exists():
8082
8092
  try:
8083
8093
  with open(scaffold_path) as f:
8084
8094
  raw = yaml.safe_load(f) or {}
@@ -8143,7 +8153,9 @@ def tools_scan_cmd(project_dir: str, as_json: bool, fpga: bool) -> None:
8143
8153
  return
8144
8154
 
8145
8155
  if not checks:
8146
- console.print("[yellow]No tools found. Does scaffold.yml exist?[/yellow]")
8156
+ console.print(
8157
+ "[yellow]No tools found. Does docs/SPECSMITH.yml (or scaffold.yml) exist?[/yellow]"
8158
+ )
8147
8159
  return
8148
8160
 
8149
8161
  installed_count = sum(1 for c in checks if c["installed"])
@@ -11252,8 +11264,7 @@ def esdb_status_cmd(project_dir: str, as_json: bool) -> None:
11252
11264
  import json as _json
11253
11265
  import sys
11254
11266
 
11255
- import specsmith.esdb as _esdb_mod # used after open to read updated ESDB_BACKEND
11256
- from specsmith.esdb import CHRONO_AVAILABLE, open_default_store
11267
+ import specsmith.esdb as _esdb_mod # used after open to read updated ESDB_BACKEND (#263)
11257
11268
  from specsmith.esdb._license import check_license, resolve_license_path
11258
11269
  from specsmith.sync import auto_migrate_if_needed
11259
11270
 
@@ -11265,7 +11276,7 @@ def esdb_status_cmd(project_dir: str, as_json: bool) -> None:
11265
11276
  lic_status = check_license(warn=False) if lic_path else None
11266
11277
 
11267
11278
  # Open the appropriate store (no warning — we’ll report it ourselves)
11268
- store = open_default_store(root, warn=False)
11279
+ store = _esdb_mod.open_default_store(root, warn=False)
11269
11280
  # Re-read ESDB_BACKEND from the module — open_default_store() updates the
11270
11281
  # module-level global; the locally-imported name would be stale. (#263)
11271
11282
  active_backend = _esdb_mod.ESDB_BACKEND
@@ -11300,7 +11311,7 @@ def esdb_status_cmd(project_dir: str, as_json: bool) -> None:
11300
11311
  backend_label = f"{active_backend} (error: {exc})"
11301
11312
 
11302
11313
  license_info: dict[str, object]
11303
- if not CHRONO_AVAILABLE:
11314
+ if not _esdb_mod.CHRONO_AVAILABLE:
11304
11315
  license_info = {"chronomemory_installed": False, "active": False}
11305
11316
  elif lic_status is None:
11306
11317
  license_info = {
@@ -11372,7 +11383,7 @@ def esdb_status_cmd(project_dir: str, as_json: bool) -> None:
11372
11383
  if store_error:
11373
11384
  console.print(f" [red]\u2717[/red] Store error: {store_error}")
11374
11385
  # License line
11375
- if not CHRONO_AVAILABLE:
11386
+ if not _esdb_mod.CHRONO_AVAILABLE:
11376
11387
  console.print(
11377
11388
  " [dim]chronomemory not installed \u2014 run "
11378
11389
  "'pip install specsmith[esdb]' for ChronoStore[/dim]"
@@ -12240,14 +12251,12 @@ def cleanup_cmd(project_dir: str, apply_flag: bool, as_json: bool) -> None:
12240
12251
  removed: list[str] = []
12241
12252
  if apply_flag:
12242
12253
  for p in targets:
12243
- try:
12254
+ with contextlib.suppress(OSError): # best-effort; locked/missing files are skipped
12244
12255
  if p.is_dir():
12245
12256
  shutil.rmtree(p)
12246
12257
  else:
12247
12258
  p.unlink(missing_ok=True)
12248
12259
  removed.append(str(p.relative_to(root)))
12249
- except OSError:
12250
- pass
12251
12260
  with contextlib.suppress(Exception):
12252
12261
  from specsmith.ledger import add_entry
12253
12262
 
@@ -529,6 +529,27 @@ class ProjectConfig(BaseModel):
529
529
  return None
530
530
 
531
531
 
532
+ # ---------------------------------------------------------------------------
533
+ # Legacy key normalisation helper
534
+ # ---------------------------------------------------------------------------
535
+
536
+
537
+ def _normalize_scaffold_raw(raw: dict[str, Any]) -> dict[str, Any]:
538
+ """Normalise legacy scaffold YAML keys to the current schema.
539
+
540
+ Call this before ``ProjectConfig(**raw)`` whenever raw YAML is loaded from
541
+ disk so that projects created by older specsmith versions continue to parse
542
+ correctly after a key rename.
543
+
544
+ Migrations handled:
545
+ - ``project`` → ``name`` (renamed in specsmith ≤ 0.9)
546
+ """
547
+ if raw and "project" in raw and "name" not in raw:
548
+ raw = dict(raw)
549
+ raw["name"] = raw.pop("project")
550
+ return raw
551
+
552
+
532
553
  # Keys are str (ProjectType enum values) for compatibility now that config.type is str
533
554
  _TYPE_LABELS: dict[str, str] = {
534
555
  ProjectType.BACKEND_FRONTEND: "Python backend + web frontend",
@@ -10,7 +10,8 @@ from pathlib import Path
10
10
  import yaml
11
11
  from jinja2 import Environment, PackageLoader, select_autoescape
12
12
 
13
- from specsmith.config import ProjectConfig
13
+ from specsmith.config import ProjectConfig, _normalize_scaffold_raw
14
+ from specsmith.paths import find_scaffold
14
15
 
15
16
  _GOVERNANCE_FILES: list[tuple[str, str]] = [
16
17
  ("governance/rules.md.j2", "docs/governance/RULES.md"),
@@ -28,17 +29,18 @@ def run_diff(root: Path) -> list[tuple[str, str]]:
28
29
 
29
30
  Returns list of (relative_path, status) where status is 'match', 'differs', or 'missing'.
30
31
  """
31
- scaffold_path = root / "scaffold.yml"
32
- if not scaffold_path.exists():
33
- return [("scaffold.yml", "missing")]
32
+ scaffold_path = find_scaffold(root)
33
+ if not scaffold_path or not scaffold_path.exists():
34
+ return [("docs/SPECSMITH.yml", "missing")]
34
35
 
35
36
  with open(scaffold_path) as f:
36
37
  raw = yaml.safe_load(f)
37
38
 
39
+ raw = _normalize_scaffold_raw(raw or {})
38
40
  try:
39
41
  config = ProjectConfig(**raw)
40
42
  except Exception:
41
- return [("scaffold.yml", "invalid")]
43
+ return [(scaffold_path.name, "invalid")]
42
44
 
43
45
  env = Environment(
44
46
  loader=PackageLoader("specsmith", "templates"),
@@ -116,17 +118,21 @@ def run_diff_html(root: Path) -> str:
116
118
  """Generate an HTML diff report with side-by-side views."""
117
119
  import difflib
118
120
 
119
- scaffold_path = root / "scaffold.yml"
120
- if not scaffold_path.exists():
121
- return "<html><body><p>No scaffold.yml found.</p></body></html>"
121
+ scaffold_path = find_scaffold(root)
122
+ if not scaffold_path or not scaffold_path.exists():
123
+ return (
124
+ "<html><body><p>No scaffold config found"
125
+ " (docs/SPECSMITH.yml or scaffold.yml).</p></body></html>"
126
+ )
122
127
 
123
128
  with open(scaffold_path) as f:
124
129
  raw = yaml.safe_load(f)
125
130
 
131
+ raw = _normalize_scaffold_raw(raw or {})
126
132
  try:
127
133
  config = ProjectConfig(**raw)
128
134
  except Exception:
129
- return "<html><body><p>Invalid scaffold.yml.</p></body></html>"
135
+ return "<html><body><p>Invalid scaffold config.</p></body></html>"
130
136
 
131
137
  from specsmith.tools import get_tools
132
138
 
@@ -118,7 +118,10 @@ def run_doctor(root: Path) -> DoctorReport:
118
118
  2. File-based heuristics for embedded/hardware/mobile/cloud projects.
119
119
  3. Always-available base tools (git, python3) surfaced for every project.
120
120
  """
121
- scaffold_path = root / "scaffold.yml"
121
+ from specsmith.config import ProjectConfig, _normalize_scaffold_raw
122
+ from specsmith.paths import find_scaffold
123
+
124
+ scaffold_path = find_scaffold(root)
122
125
  report = DoctorReport()
123
126
 
124
127
  # Always check the absolute basics
@@ -126,15 +129,15 @@ def run_doctor(root: Path) -> DoctorReport:
126
129
  report.checks.append(_check_tool(exe, category, root=root))
127
130
 
128
131
  # Scaffold-driven checks
129
- if scaffold_path.exists():
132
+ if scaffold_path and scaffold_path.exists():
130
133
  import yaml
131
134
 
132
- from specsmith.config import ProjectConfig
133
135
  from specsmith.tools import get_tools
134
136
 
135
137
  try:
136
138
  with open(scaffold_path) as f:
137
139
  raw = yaml.safe_load(f)
140
+ raw = _normalize_scaffold_raw(raw or {})
138
141
  config = ProjectConfig(**raw)
139
142
  except Exception: # noqa: BLE001
140
143
  config = None
@@ -30,6 +30,9 @@ def run_export(root: Path) -> str:
30
30
 
31
31
  with open(scaffold_path) as f:
32
32
  raw = yaml.safe_load(f)
33
+ from specsmith.config import _normalize_scaffold_raw
34
+
35
+ raw = _normalize_scaffold_raw(raw or {})
33
36
  try:
34
37
  config = ProjectConfig(**raw)
35
38
  tools = get_tools(config)
@@ -83,11 +83,14 @@ def run_preflight(
83
83
  # docs/REQUIREMENTS.md is deprecated (REQ-373) but still used as a fallback
84
84
  # for keyword matching in infer_scope() when it exists. Explicit REQ-NNN IDs
85
85
  # in the utterance are always resolved from requirements.json regardless.
86
- _req_md = _safe_resolve(os.path.join(_root_str, "docs", "REQUIREMENTS.md"))
86
+ # Use os.path.realpath directly (not through _safe_resolve) so CodeQL's
87
+ # interprocedural taint analysis can confirm the sanitiser inline without
88
+ # having to track through a user-defined wrapper function.
89
+ _req_md = Path(os.path.realpath(os.path.join(_root_str, "docs", "REQUIREMENTS.md")))
87
90
  if not _req_md.is_file():
88
- _req_md = _safe_resolve(os.path.join(_root_str, "REQUIREMENTS.md")) # legacy
91
+ _req_md = Path(os.path.realpath(os.path.join(_root_str, "REQUIREMENTS.md"))) # legacy
89
92
  # infer_scope handles a non-existent path gracefully (returns empty scope)
90
- _repo_idx = _safe_resolve(os.path.join(_root_str, ".repo-index", "files.json"))
93
+ _repo_idx = Path(os.path.realpath(os.path.join(_root_str, ".repo-index", "files.json")))
91
94
  scope = infer_scope(
92
95
  utterance,
93
96
  _req_md,
@@ -306,8 +306,10 @@ def load_from_scaffold(project_dir: str) -> ExecutionProfile:
306
306
  except ImportError:
307
307
  return PROFILES[DEFAULT_PROFILE_NAME]
308
308
 
309
- scaffold = Path(project_dir) / "scaffold.yml"
310
- if not scaffold.exists():
309
+ from specsmith.paths import find_scaffold
310
+
311
+ scaffold = find_scaffold(Path(project_dir))
312
+ if not scaffold or not scaffold.exists():
311
313
  return PROFILES[DEFAULT_PROFILE_NAME]
312
314
 
313
315
  try:
@@ -210,7 +210,7 @@ def render_markdown(data: QualityReportData) -> str:
210
210
  "---",
211
211
  "",
212
212
  "*Generated by `specsmith quality-report`. "
213
- "Run `specsmith metrics report` for session-level detail.*",
213
+ + "Run `specsmith metrics report` for session-level detail.*",
214
214
  ]
215
215
 
216
216
  return "\n".join(lines)
@@ -364,7 +364,7 @@ def _read_project_name(root: Path) -> str:
364
364
  text = pyp.read_text(encoding="utf-8")
365
365
  # Match [project] section name field
366
366
  m = re.search(
367
- r'^\[project\].*?^name\s*=\s*["\']([^"\'\']+)["\']',
367
+ r'^\[project\].*?^name\s*=\s*["\']+)["\']',
368
368
  text,
369
369
  re.MULTILINE | re.DOTALL,
370
370
  )
@@ -372,7 +372,7 @@ def _read_project_name(root: Path) -> str:
372
372
  return m.group(1).strip()
373
373
  # Match [tool.poetry] name field
374
374
  m2 = re.search(
375
- r'^\[tool\.poetry\].*?^name\s*=\s*["\']([^"\'\']+)["\']',
375
+ r'^\[tool\.poetry\].*?^name\s*=\s*["\']+)["\']',
376
376
  text,
377
377
  re.MULTILINE | re.DOTALL,
378
378
  )
@@ -492,13 +492,11 @@ def _fill_github_issues(root: Path, data: QualityReportData) -> None:
492
492
  for issue in issues:
493
493
  created = issue.get("createdAt", "")
494
494
  if created:
495
- try:
495
+ with contextlib.suppress(ValueError): # malformed createdAt — skip
496
496
  dt = datetime.datetime.fromisoformat(created.replace("Z", "+00:00"))
497
497
  days = (now - dt).days
498
498
  if days > oldest_delta:
499
499
  oldest_delta = days
500
- except ValueError:
501
- pass
502
500
  data.oldest_open_issue_days = oldest_delta
503
501
  except Exception: # noqa: BLE001
504
502
  pass
@@ -214,14 +214,14 @@ def run_migration(root: Path, *, dry_run: bool = False) -> list[str]:
214
214
  raw["spec_version"] = __version__
215
215
  with open(scaffold_path, "w") as f:
216
216
  yaml.dump(raw, f, default_flow_style=False, sort_keys=False)
217
- actions.append("Updated scaffold.yml")
217
+ actions.append(f"Updated {scaffold_path.name}")
218
218
 
219
219
  # Regenerate governance templates
220
- from specsmith.config import ProjectConfig
220
+ from specsmith.config import ProjectConfig, _normalize_scaffold_raw
221
221
  from specsmith.upgrader import run_upgrade
222
222
 
223
223
  try:
224
- ProjectConfig(**raw) # Validate config
224
+ ProjectConfig(**_normalize_scaffold_raw(raw)) # Validate config
225
225
  if not dry_run:
226
226
  result = run_upgrade(root, target_version=__version__)
227
227
  for updated_file in result.updated_files:
@@ -125,10 +125,13 @@ def run_upgrade(
125
125
  with open(scaffold_path) as f:
126
126
  raw = yaml.safe_load(f)
127
127
 
128
+ from specsmith.config import _normalize_scaffold_raw
129
+
130
+ raw = _normalize_scaffold_raw(raw or {})
128
131
  try:
129
132
  config = ProjectConfig(**raw)
130
133
  except Exception as e:
131
- return UpgradeResult(message=f"Invalid scaffold.yml: {e}")
134
+ return UpgradeResult(message=f"Invalid scaffold config: {e}")
132
135
 
133
136
  new_version = target_version or __version__
134
137
  old_version = config.spec_version
@@ -84,20 +84,24 @@ _SLEEP_LOOP_CONTEXT = (
84
84
 
85
85
 
86
86
  def _check_scaffold_yml(root: Path) -> list[ValidationResult]:
87
- """Check that scaffold.yml exists and is valid YAML."""
87
+ """Check that the scaffold config exists and is valid YAML."""
88
+ from specsmith.config import _normalize_scaffold_raw
89
+ from specsmith.paths import find_scaffold
90
+
88
91
  results: list[ValidationResult] = []
89
- scaffold_path = root / "scaffold.yml"
92
+ scaffold_path = find_scaffold(root)
90
93
 
91
- if not scaffold_path.exists():
94
+ if not scaffold_path or not scaffold_path.exists():
92
95
  results.append(
93
96
  ValidationResult(
94
97
  name="scaffold-yml",
95
98
  passed=True,
96
- message="No scaffold.yml found (project may not have been created by specsmith)",
99
+ message="No scaffold config found (project may not have been created by specsmith)",
97
100
  )
98
101
  )
99
102
  return results
100
103
 
104
+ cfg_name = scaffold_path.name
101
105
  try:
102
106
  import yaml
103
107
 
@@ -108,31 +112,33 @@ def _check_scaffold_yml(root: Path) -> list[ValidationResult]:
108
112
  ValidationResult(
109
113
  name="scaffold-yml",
110
114
  passed=False,
111
- message="scaffold.yml is not a valid YAML mapping",
112
- )
113
- )
114
- elif "name" not in data or "type" not in data:
115
- results.append(
116
- ValidationResult(
117
- name="scaffold-yml",
118
- passed=False,
119
- message="scaffold.yml missing required fields: name, type",
115
+ message=f"{cfg_name} is not a valid YAML mapping",
120
116
  )
121
117
  )
122
118
  else:
123
- results.append(
124
- ValidationResult(
125
- name="scaffold-yml",
126
- passed=True,
127
- message=f"scaffold.yml valid: project={data['name']}, type={data['type']}",
119
+ data = _normalize_scaffold_raw(data)
120
+ if "name" not in data or "type" not in data:
121
+ results.append(
122
+ ValidationResult(
123
+ name="scaffold-yml",
124
+ passed=False,
125
+ message=f"{cfg_name} missing required fields: name, type",
126
+ )
127
+ )
128
+ else:
129
+ results.append(
130
+ ValidationResult(
131
+ name="scaffold-yml",
132
+ passed=True,
133
+ message=f"{cfg_name} valid: project={data['name']}, type={data['type']}",
134
+ )
128
135
  )
129
- )
130
136
  except Exception as e:
131
137
  results.append(
132
138
  ValidationResult(
133
139
  name="scaffold-yml",
134
140
  passed=False,
135
- message=f"scaffold.yml parse error: {e}",
141
+ message=f"{cfg_name} parse error: {e}",
136
142
  )
137
143
  )
138
144
 
@@ -145,8 +145,10 @@ def run_push(root: Path, *, force: bool = False) -> GitResult:
145
145
  return GitResult(success=False, message="Not on any branch")
146
146
 
147
147
  # Safety: check branching strategy
148
- scaffold_path = root / "scaffold.yml"
149
- if scaffold_path.exists() and not force:
148
+ from specsmith.paths import find_scaffold
149
+
150
+ scaffold_path = find_scaffold(root)
151
+ if scaffold_path and scaffold_path.exists() and not force:
150
152
  with open(scaffold_path) as f:
151
153
  raw = yaml.safe_load(f) or {}
152
154
  strategy = raw.get("branching_strategy", "gitflow")
@@ -215,7 +217,7 @@ def run_sync(root: Path) -> GitResult:
215
217
 
216
218
  # Check if governance files were in the pull.
217
219
  # Use ORIG_HEAD (set by git pull) rather than HEAD~1 — works even on first pull.
218
- gov_files = ["AGENTS.md", "LEDGER.md", "scaffold.yml", "docs/governance/"]
220
+ gov_files = ["AGENTS.md", "LEDGER.md", "scaffold.yml", "docs/SPECSMITH.yml", "docs/governance/"]
219
221
  warnings: list[str] = []
220
222
  diff_result = _run_git(root, ["diff", "--name-only", "ORIG_HEAD..HEAD"])
221
223
  if diff_result.success:
@@ -310,11 +312,13 @@ def create_pr(
310
312
  """Create a PR via platform CLI with governance context."""
311
313
  import yaml
312
314
 
313
- scaffold_path = root / "scaffold.yml"
315
+ from specsmith.paths import find_scaffold
316
+
317
+ scaffold_path = find_scaffold(root)
314
318
  platform = "github"
315
319
  base_branch = "develop"
316
320
 
317
- if scaffold_path.exists():
321
+ if scaffold_path and scaffold_path.exists():
318
322
  with open(scaffold_path) as f:
319
323
  raw = yaml.safe_load(f) or {}
320
324
  platform = raw.get("vcs_platform", "github")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: specsmith
3
- Version: 0.17.0.dev644
3
+ Version: 0.17.0.dev649
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