raise-cli 2.2.1__tar.gz → 2.2.2__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 (264) hide show
  1. {raise_cli-2.2.1 → raise_cli-2.2.2}/.gitignore +5 -0
  2. {raise_cli-2.2.1 → raise_cli-2.2.2}/PKG-INFO +3 -3
  3. {raise_cli-2.2.1 → raise_cli-2.2.2}/README.md +2 -2
  4. {raise_cli-2.2.1 → raise_cli-2.2.2}/pyproject.toml +1 -1
  5. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/__init__.py +1 -1
  6. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/declarative/adapter.py +4 -1
  7. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/mcp_jira.py +14 -0
  8. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/models.py +3 -2
  9. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/artifacts/renderer.py +1 -3
  10. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/adapters.py +6 -2
  11. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/artifact.py +10 -2
  12. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/backlog.py +5 -1
  13. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/doctor.py +11 -4
  14. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/graph.py +5 -1
  15. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/init.py +18 -9
  16. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/pattern.py +1 -3
  17. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/session.py +57 -1
  18. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/skill.py +1 -3
  19. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/skill_set.py +3 -1
  20. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/main.py +7 -0
  21. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/compat.py +29 -0
  22. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/config/paths.py +6 -2
  23. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/builder.py +16 -11
  24. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/checks/environment.py +3 -1
  25. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/checks/project.py +4 -4
  26. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/fix.py +3 -1
  27. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/registry.py +3 -1
  28. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/report.py +4 -4
  29. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/runner.py +3 -1
  30. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/builtin/coverage.py +15 -2
  31. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/builtin/lint.py +12 -2
  32. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/builtin/tests.py +12 -2
  33. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/builtin/types.py +12 -2
  34. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/backlog.py +2 -2
  35. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/mcp/bridge.py +20 -4
  36. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/memory/writer.py +11 -0
  37. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/bootstrap.py +10 -2
  38. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/instructions.py +14 -28
  39. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/profile.py +1 -3
  40. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/publish/check.py +1 -1
  41. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/session/close.py +6 -4
  42. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/session/state.py +23 -4
  43. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills/scaffold.py +3 -1
  44. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills/schema.py +2 -1
  45. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills/skillsets.py +8 -9
  46. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/__init__.py +3 -6
  47. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-debug/SKILL.md +1 -1
  48. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-close/SKILL.md +6 -4
  49. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-start/SKILL.md +3 -4
  50. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-session-close/SKILL.md +5 -1
  51. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-session-start/SKILL.md +3 -2
  52. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-implement/SKILL.md +17 -4
  53. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-plan/SKILL.md +1 -1
  54. raise_cli-2.2.1/src/raise_cli/skills_base/rai-architecture-review/SKILL.md +0 -137
  55. raise_cli-2.2.1/src/raise_cli/skills_base/rai-quality-review/SKILL.md +0 -189
  56. {raise_cli-2.2.1 → raise_cli-2.2.2}/LICENSE +0 -0
  57. {raise_cli-2.2.1 → raise_cli-2.2.2}/NOTICE +0 -0
  58. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/__main__.py +0 -0
  59. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/__init__.py +0 -0
  60. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/declarative/__init__.py +0 -0
  61. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/declarative/discovery.py +0 -0
  62. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/declarative/expressions.py +0 -0
  63. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/declarative/reference/__init__.py +0 -0
  64. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/declarative/reference/github.yaml +0 -0
  65. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/declarative/schema.py +0 -0
  66. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/filesystem.py +0 -0
  67. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/mcp_bridge.py +0 -0
  68. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/mcp_confluence.py +0 -0
  69. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/protocols.py +0 -0
  70. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/registry.py +0 -0
  71. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/adapters/sync.py +0 -0
  72. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/agents/__init__.py +0 -0
  73. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/agents/antigravity.yaml +0 -0
  74. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/agents/claude.yaml +0 -0
  75. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/agents/copilot.yaml +0 -0
  76. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/agents/copilot_plugin.py +0 -0
  77. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/agents/cursor.yaml +0 -0
  78. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/agents/roo.yaml +0 -0
  79. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/agents/windsurf.yaml +0 -0
  80. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/artifacts/__init__.py +0 -0
  81. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/artifacts/models.py +0 -0
  82. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/artifacts/reader.py +0 -0
  83. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/artifacts/story_design.py +0 -0
  84. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/artifacts/writer.py +0 -0
  85. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/backlog/__init__.py +0 -0
  86. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/backlog/sync.py +0 -0
  87. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/__init__.py +0 -0
  88. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/__init__.py +0 -0
  89. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/_resolve.py +0 -0
  90. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/base.py +0 -0
  91. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/discover.py +0 -0
  92. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/docs.py +0 -0
  93. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/gate.py +0 -0
  94. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/info.py +0 -0
  95. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/journal.py +0 -0
  96. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/mcp.py +0 -0
  97. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/memory.py +0 -0
  98. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/profile.py +0 -0
  99. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/publish.py +0 -0
  100. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/release.py +0 -0
  101. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/commands/signal.py +0 -0
  102. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/cli/error_handler.py +0 -0
  103. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/config/__init__.py +0 -0
  104. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/config/agent_plugin.py +0 -0
  105. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/config/agent_registry.py +0 -0
  106. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/config/agents.py +0 -0
  107. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/config/ide.py +0 -0
  108. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/config/settings.py +0 -0
  109. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/__init__.py +0 -0
  110. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/analyzers/__init__.py +0 -0
  111. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/analyzers/models.py +0 -0
  112. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/analyzers/protocol.py +0 -0
  113. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/analyzers/python.py +0 -0
  114. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/diff.py +0 -0
  115. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/extractors/__init__.py +0 -0
  116. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/context/extractors/skills.py +0 -0
  117. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/core/__init__.py +0 -0
  118. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/core/files.py +0 -0
  119. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/core/text.py +0 -0
  120. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/core/tools.py +0 -0
  121. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/discovery/__init__.py +0 -0
  122. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/discovery/analyzer.py +0 -0
  123. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/discovery/drift.py +0 -0
  124. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/discovery/scanner.py +0 -0
  125. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/__init__.py +0 -0
  126. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/checks/__init__.py +0 -0
  127. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/models.py +0 -0
  128. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/doctor/protocol.py +0 -0
  129. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/engines/__init__.py +0 -0
  130. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/exceptions.py +0 -0
  131. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/__init__.py +0 -0
  132. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/builtin/__init__.py +0 -0
  133. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/models.py +0 -0
  134. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/protocol.py +0 -0
  135. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/gates/registry.py +0 -0
  136. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/__init__.py +0 -0
  137. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/extractor.py +0 -0
  138. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/models.py +0 -0
  139. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/__init__.py +0 -0
  140. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/_convert.py +0 -0
  141. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/adr.py +0 -0
  142. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/constitution.py +0 -0
  143. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/epic.py +0 -0
  144. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/glossary.py +0 -0
  145. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/guardrails.py +0 -0
  146. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/prd.py +0 -0
  147. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/roadmap.py +0 -0
  148. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/governance/parsers/vision.py +0 -0
  149. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/graph/__init__.py +0 -0
  150. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/graph/backends/__init__.py +0 -0
  151. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/graph/backends/api.py +0 -0
  152. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/graph/backends/dual.py +0 -0
  153. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/graph/backends/pending.py +0 -0
  154. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/handlers/__init__.py +0 -0
  155. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/__init__.py +0 -0
  156. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/builtin/__init__.py +0 -0
  157. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/builtin/backlog.py +0 -0
  158. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/builtin/gate_bridge.py +0 -0
  159. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/builtin/jira_sync.py +0 -0
  160. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/builtin/memory.py +0 -0
  161. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/builtin/telemetry.py +0 -0
  162. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/emitter.py +0 -0
  163. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/events.py +0 -0
  164. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/protocol.py +0 -0
  165. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/hooks/registry.py +0 -0
  166. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/mcp/__init__.py +0 -0
  167. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/mcp/models.py +0 -0
  168. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/mcp/registry.py +0 -0
  169. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/mcp/schema.py +0 -0
  170. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/memory/__init__.py +0 -0
  171. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/memory/loader.py +0 -0
  172. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/memory/migration.py +0 -0
  173. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/memory/models.py +0 -0
  174. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/__init__.py +0 -0
  175. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/claudemd.py +0 -0
  176. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/conventions.py +0 -0
  177. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/detection.py +0 -0
  178. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/governance.py +0 -0
  179. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/manifest.py +0 -0
  180. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/memory_md.py +0 -0
  181. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/migration.py +0 -0
  182. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/skill_conflict.py +0 -0
  183. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/skill_manifest.py +0 -0
  184. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/skills.py +0 -0
  185. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/onboarding/workflows.py +0 -0
  186. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/output/__init__.py +0 -0
  187. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/output/console.py +0 -0
  188. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/output/formatters/__init__.py +0 -0
  189. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/output/formatters/adapters.py +0 -0
  190. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/output/formatters/discover.py +0 -0
  191. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/output/formatters/skill.py +0 -0
  192. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/publish/__init__.py +0 -0
  193. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/publish/changelog.py +0 -0
  194. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/publish/version.py +0 -0
  195. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/__init__.py +0 -0
  196. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/framework/__init__.py +0 -0
  197. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/framework/methodology.yaml +0 -0
  198. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/__init__.py +0 -0
  199. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/architecture/__init__.py +0 -0
  200. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/architecture/domain-model.md +0 -0
  201. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/architecture/system-context.md +0 -0
  202. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/architecture/system-design.md +0 -0
  203. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/backlog.md +0 -0
  204. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/guardrails.md +0 -0
  205. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/prd.md +0 -0
  206. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/governance/vision.md +0 -0
  207. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/identity/__init__.py +0 -0
  208. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/identity/core.md +0 -0
  209. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/identity/perspective.md +0 -0
  210. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/memory/__init__.py +0 -0
  211. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/rai_base/memory/patterns-base.jsonl +0 -0
  212. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/schemas/__init__.py +0 -0
  213. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/schemas/journal.py +0 -0
  214. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/schemas/session_state.py +0 -0
  215. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/session/__init__.py +0 -0
  216. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/session/bundle.py +0 -0
  217. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/session/journal.py +0 -0
  218. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/session/resolver.py +0 -0
  219. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills/__init__.py +0 -0
  220. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills/locator.py +0 -0
  221. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills/name_checker.py +0 -0
  222. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills/parser.py +0 -0
  223. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills/validator.py +0 -0
  224. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/contract-template.md +0 -0
  225. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/preamble.md +0 -0
  226. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-discover/SKILL.md +0 -0
  227. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-discover-document/SKILL.md +0 -0
  228. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-discover-scan/SKILL.md +0 -0
  229. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-discover-start/SKILL.md +0 -0
  230. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-discover-validate/SKILL.md +0 -0
  231. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-docs-update/SKILL.md +0 -0
  232. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-doctor/SKILL.md +0 -0
  233. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-close/templates/retrospective.md +0 -0
  234. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-design/SKILL.md +0 -0
  235. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-design/templates/design.md +0 -0
  236. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-design/templates/scope.md +0 -0
  237. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-plan/SKILL.md +0 -0
  238. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-plan/_references/sequencing-strategies.md +0 -0
  239. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-plan/templates/plan-section.md +0 -0
  240. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-run/SKILL.md +0 -0
  241. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-epic-start/templates/brief.md +0 -0
  242. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-mcp-add/SKILL.md +0 -0
  243. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-mcp-remove/SKILL.md +0 -0
  244. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-mcp-status/SKILL.md +0 -0
  245. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-problem-shape/SKILL.md +0 -0
  246. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-project-create/SKILL.md +0 -0
  247. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-project-onboard/SKILL.md +0 -0
  248. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-research/SKILL.md +0 -0
  249. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-research/references/research-prompt-template.md +0 -0
  250. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-close/SKILL.md +0 -0
  251. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-design/SKILL.md +0 -0
  252. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-design/references/tech-design-story-v2.md +0 -0
  253. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-review/SKILL.md +0 -0
  254. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-run/SKILL.md +0 -0
  255. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-start/SKILL.md +0 -0
  256. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-story-start/templates/story.md +0 -0
  257. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/skills_base/rai-welcome/SKILL.md +0 -0
  258. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/telemetry/__init__.py +0 -0
  259. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/telemetry/schemas.py +0 -0
  260. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/telemetry/writer.py +0 -0
  261. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/tier/__init__.py +0 -0
  262. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/tier/context.py +0 -0
  263. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/viz/__init__.py +0 -0
  264. {raise_cli-2.2.1 → raise_cli-2.2.2}/src/raise_cli/viz/generator.py +0 -0
@@ -109,3 +109,8 @@ site/node_modules/
109
109
  site/dist/
110
110
  site/.astro/
111
111
  site/.wrangler/
112
+
113
+ # Issue analysis artifacts (PDFs, images — binary, no git value)
114
+ dev/issues/**/*.pdf
115
+ dev/issues/**/*.png
116
+ dev/issues/**/*.jpg
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: raise-cli
3
- Version: 2.2.1
3
+ Version: 2.2.2
4
4
  Summary: RaiSE CLI - Reliable AI Software Engineering governance framework
5
5
  Project-URL: Homepage, https://raiseframework.ai
6
6
  Project-URL: Documentation, https://docs.raiseframework.ai
@@ -130,7 +130,7 @@ pipx install raise-cli
130
130
  ```bash
131
131
  # 1. Clone and checkout the development branch
132
132
  git clone https://github.com/humansys/raise.git
133
- cd raise-commons
133
+ cd raise
134
134
  git checkout dev
135
135
 
136
136
  # 2. Create venv and install in development mode
@@ -334,7 +334,7 @@ rai session close --state-file /tmp/session-output.yaml --project "$(pwd)"
334
334
  ## Repository Structure
335
335
 
336
336
  ```
337
- raise-commons/
337
+ raise/
338
338
  ├── .claude/skills/ # Claude Code skills (37 skills)
339
339
 
340
340
  ├── framework/ # Public textbook (concepts, reference)
@@ -72,7 +72,7 @@ pipx install raise-cli
72
72
  ```bash
73
73
  # 1. Clone and checkout the development branch
74
74
  git clone https://github.com/humansys/raise.git
75
- cd raise-commons
75
+ cd raise
76
76
  git checkout dev
77
77
 
78
78
  # 2. Create venv and install in development mode
@@ -276,7 +276,7 @@ rai session close --state-file /tmp/session-output.yaml --project "$(pwd)"
276
276
  ## Repository Structure
277
277
 
278
278
  ```
279
- raise-commons/
279
+ raise/
280
280
  ├── .claude/skills/ # Claude Code skills (37 skills)
281
281
 
282
282
  ├── framework/ # Public textbook (concepts, reference)
@@ -7,7 +7,7 @@ raise-server = { workspace = true }
7
7
 
8
8
  [project]
9
9
  name = "raise-cli"
10
- version = "2.2.1"
10
+ version = "2.2.2"
11
11
  description = "RaiSE CLI - Reliable AI Software Engineering governance framework"
12
12
  authors = [
13
13
  {name = "Emilio Osorio", email = "emilio@humansys.ai"}
@@ -17,7 +17,7 @@ from raise_cli.exceptions import (
17
17
  ValidationError,
18
18
  )
19
19
 
20
- __version__ = "2.2.1"
20
+ __version__ = "2.2.2"
21
21
  __author__ = "Emilio Osorio"
22
22
  __license__ = "MIT"
23
23
 
@@ -102,7 +102,10 @@ class DeclarativeMcpAdapter:
102
102
  """Dispatch a protocol method call to the configured MCP tool."""
103
103
  mapping = self._get_method(method_name)
104
104
  args = self._evaluator.evaluate_args(mapping.args, context)
105
- return await self._bridge.call(mapping.tool, args)
105
+ result = await self._bridge.call(mapping.tool, args)
106
+ if result.is_error:
107
+ raise McpBridgeError(result.error_message)
108
+ return result
106
109
 
107
110
  def _parse_single(
108
111
  self, method_name: str, result: McpToolResult, context: dict[str, Any]
@@ -126,12 +126,16 @@ class McpJiraAdapter:
126
126
  args["additional_fields"] = json.dumps(issue.metadata)
127
127
 
128
128
  result = await self._bridge.call("jira_create_issue", args)
129
+ if result.is_error:
130
+ raise McpBridgeError(result.error_message)
129
131
  return self._parse_issue_ref(result)
130
132
 
131
133
  async def get_issue(self, key: str) -> IssueDetail:
132
134
  result = await self._bridge.call(
133
135
  "jira_get_issue", {"issue_key": key, "fields": "*all"}
134
136
  )
137
+ if result.is_error:
138
+ raise McpBridgeError(result.error_message)
135
139
  return self._parse_issue_detail(result)
136
140
 
137
141
  async def update_issue(self, key: str, fields: dict[str, Any]) -> IssueRef:
@@ -139,6 +143,8 @@ class McpJiraAdapter:
139
143
  "jira_update_issue",
140
144
  {"issue_key": key, "fields": json.dumps(fields)},
141
145
  )
146
+ if result.is_error:
147
+ raise McpBridgeError(result.error_message)
142
148
  return self._parse_issue_ref(result)
143
149
 
144
150
  async def transition_issue(self, key: str, status: str) -> IssueRef:
@@ -147,6 +153,8 @@ class McpJiraAdapter:
147
153
  "jira_transition_issue",
148
154
  {"issue_key": key, "transition_id": tid},
149
155
  )
156
+ if result.is_error:
157
+ raise McpBridgeError(result.error_message)
150
158
  ref = self._parse_issue_ref(result)
151
159
  # MCP transition tool returns no data — use the key we already have
152
160
  if not ref.key:
@@ -204,6 +212,8 @@ class McpJiraAdapter:
204
212
  "jira_add_comment",
205
213
  {"issue_key": key, "body": body},
206
214
  )
215
+ if result.is_error:
216
+ raise McpBridgeError(result.error_message)
207
217
  comment_id = result.data.get("id", "")
208
218
  url = result.data.get("self", "")
209
219
  return CommentRef(id=str(comment_id), url=str(url))
@@ -214,6 +224,8 @@ class McpJiraAdapter:
214
224
  "jira_get_issue",
215
225
  {"issue_key": key, "comment_limit": limit},
216
226
  )
227
+ if result.is_error:
228
+ raise McpBridgeError(result.error_message)
217
229
  return self._parse_comments(result)
218
230
 
219
231
  # ----- Query -----
@@ -225,6 +237,8 @@ class McpJiraAdapter:
225
237
  "jira_search",
226
238
  {"jql": clean_query, "limit": limit},
227
239
  )
240
+ if result.is_error:
241
+ raise McpBridgeError(result.error_message)
228
242
  return self._parse_search_results(result)
229
243
 
230
244
  # ----- Lifecycle -----
@@ -7,7 +7,6 @@ of adapters regardless of their concrete implementation.
7
7
  Architecture: ADR-033 (Open-core adapter architecture), ADR-034 (Governance extensibility)
8
8
  """
9
9
 
10
-
11
10
  from enum import StrEnum
12
11
  from typing import Any
13
12
 
@@ -172,7 +171,9 @@ class BacklogLink(BaseModel):
172
171
  """Link from one backlog item to another."""
173
172
 
174
173
  target: str = Field(..., description="Target issue key")
175
- link_type: str = Field(..., description="Relationship type (blocks, depends_on, relates_to)")
174
+ link_type: str = Field(
175
+ ..., description="Relationship type (blocks, depends_on, relates_to)"
176
+ )
176
177
 
177
178
 
178
179
  class BacklogComment(BaseModel):
@@ -74,9 +74,7 @@ def _get_template(project_root: Path | None = None) -> str:
74
74
  )
75
75
 
76
76
 
77
- def render_artifact(
78
- artifact: SkillArtifact, project_root: Path | None = None
79
- ) -> str:
77
+ def render_artifact(artifact: SkillArtifact, project_root: Path | None = None) -> str:
80
78
  """Render a typed artifact to Markdown.
81
79
 
82
80
  Uses the template from ``.raise/templates/artifacts/`` if available,
@@ -277,10 +277,14 @@ def _check_jira_config(project_root: Path) -> dict[str, Any]:
277
277
  env_results: list[dict[str, Any]] = []
278
278
  for var_name, description in _JIRA_ENV_VARS:
279
279
  if var_name == "JIRA_API_TOKEN":
280
- is_set = bool(os.environ.get("JIRA_API_TOKEN") or os.environ.get("JIRA_TOKEN"))
280
+ is_set = bool(
281
+ os.environ.get("JIRA_API_TOKEN") or os.environ.get("JIRA_TOKEN")
282
+ )
281
283
  else:
282
284
  is_set = bool(os.environ.get(var_name))
283
- env_results.append({"name": var_name, "set": is_set, "description": description})
285
+ env_results.append(
286
+ {"name": var_name, "set": is_set, "description": description}
287
+ )
284
288
 
285
289
  all_env_set = all(e["set"] for e in env_results)
286
290
  return {
@@ -121,7 +121,11 @@ def _resolve_all_artifacts(fmt: str) -> list[Path] | None:
121
121
 
122
122
  if not artifacts_dir.is_dir():
123
123
  if fmt == "json":
124
- typer.echo(json.dumps({"results": [], "all_passed": True, "message": "No artifacts found"}))
124
+ typer.echo(
125
+ json.dumps(
126
+ {"results": [], "all_passed": True, "message": "No artifacts found"}
127
+ )
128
+ )
125
129
  else:
126
130
  console.print("No artifacts found in .raise/artifacts/")
127
131
  raise typer.Exit(0)
@@ -129,7 +133,11 @@ def _resolve_all_artifacts(fmt: str) -> list[Path] | None:
129
133
  paths = sorted(artifacts_dir.glob("*.yaml"))
130
134
  if not paths:
131
135
  if fmt == "json":
132
- typer.echo(json.dumps({"results": [], "all_passed": True, "message": "No artifacts found"}))
136
+ typer.echo(
137
+ json.dumps(
138
+ {"results": [], "all_passed": True, "message": "No artifacts found"}
139
+ )
140
+ )
133
141
  else:
134
142
  console.print("No artifacts found in .raise/artifacts/")
135
143
  raise typer.Exit(0)
@@ -308,7 +308,11 @@ def sync(
308
308
  pm = resolve_adapter(adapter)
309
309
 
310
310
  # Derive adapter name for display
311
- adapter_name = adapter or type(pm).__name__.lower().replace("pmadapter", "").replace("adapter", "") or "unknown"
311
+ adapter_name = (
312
+ adapter
313
+ or type(pm).__name__.lower().replace("pmadapter", "").replace("adapter", "")
314
+ or "unknown"
315
+ )
312
316
 
313
317
  output_path = Path.cwd() / "governance" / "backlog.md"
314
318
 
@@ -53,7 +53,9 @@ def doctor(
53
53
  ] = False,
54
54
  online: Annotated[
55
55
  bool,
56
- typer.Option("--online", help="Include online checks (MCP, adapter connectivity)"),
56
+ typer.Option(
57
+ "--online", help="Include online checks (MCP, adapter connectivity)"
58
+ ),
57
59
  ] = False,
58
60
  category: Annotated[
59
61
  str | None,
@@ -104,7 +106,9 @@ def doctor(
104
106
  else:
105
107
  out = Console()
106
108
  if not results:
107
- out.print("No checks registered. Install raise-cli with extras for diagnostics.")
109
+ out.print(
110
+ "No checks registered. Install raise-cli with extras for diagnostics."
111
+ )
108
112
  return
109
113
 
110
114
  for r in results:
@@ -134,7 +138,9 @@ def doctor(
134
138
  out = Console()
135
139
  outcomes = run_fixes(fixable, Path.cwd())
136
140
  for fix_id, success in outcomes:
137
- status_label = "[green]fixed[/green]" if success else "[red]failed[/red]"
141
+ status_label = (
142
+ "[green]fixed[/green]" if success else "[red]failed[/red]"
143
+ )
138
144
  out.print(f" fix: {fix_id} -- {status_label}")
139
145
 
140
146
  if errors > 0:
@@ -144,7 +150,8 @@ def doctor(
144
150
  @doctor_app.command()
145
151
  def report(
146
152
  send: Annotated[
147
- bool, typer.Option("--send", help="Open email client with report"),
153
+ bool,
154
+ typer.Option("--send", help="Open email client with report"),
148
155
  ] = False,
149
156
  ) -> None:
150
157
  """Generate diagnostic report, optionally send via email."""
@@ -518,7 +518,11 @@ def build(
518
518
 
519
519
  # Build unified graph
520
520
  builder = GraphBuilder()
521
- graph = builder.build()
521
+ try:
522
+ graph = builder.build()
523
+ except ValueError as exc:
524
+ cli_error(str(exc), exit_code=1)
525
+ return # unreachable — cli_error raises
522
526
 
523
527
  # Count nodes by type
524
528
  node_counts: dict[str, int] = {}
@@ -203,7 +203,10 @@ def _get_project_message(
203
203
  if bootstrap_result is not None:
204
204
  if bootstrap_result.already_existed:
205
205
  # Check if base patterns were synced even though everything else existed
206
- if bootstrap_result.patterns_added > 0 or bootstrap_result.patterns_updated > 0:
206
+ if (
207
+ bootstrap_result.patterns_added > 0
208
+ or bootstrap_result.patterns_updated > 0
209
+ ):
207
210
  parts: list[str] = []
208
211
  if bootstrap_result.patterns_added > 0:
209
212
  parts.append(f"{bootstrap_result.patterns_added} new")
@@ -229,10 +232,15 @@ def _get_project_message(
229
232
 
230
233
  _base = _res_files("raise_cli.rai_base")
231
234
  _src = _base / "memory" / "patterns-base.jsonl"
232
- _count = len([
233
- ln for ln in _src.read_text(encoding="utf-8").strip().splitlines()
234
- if ln.strip()
235
- ])
235
+ _count = len(
236
+ [
237
+ ln
238
+ for ln in _src.read_text(encoding="utf-8")
239
+ .strip()
240
+ .splitlines()
241
+ if ln.strip()
242
+ ]
243
+ )
236
244
  lines.append(
237
245
  "[bold]Created:[/bold] .raise/rai/memory/ "
238
246
  f"[dim]— {_count} base patterns[/dim]"
@@ -283,15 +291,16 @@ def _get_project_message(
283
291
  bootstrap_msg = (
284
292
  f" Bootstrapped Rai base v{bootstrap_result.base_version}\n"
285
293
  )
286
- elif bootstrap_result.patterns_added > 0 or bootstrap_result.patterns_updated > 0:
294
+ elif (
295
+ bootstrap_result.patterns_added > 0
296
+ or bootstrap_result.patterns_updated > 0
297
+ ):
287
298
  parts_ri: list[str] = []
288
299
  if bootstrap_result.patterns_added > 0:
289
300
  parts_ri.append(f"{bootstrap_result.patterns_added} new")
290
301
  if bootstrap_result.patterns_updated > 0:
291
302
  parts_ri.append(f"{bootstrap_result.patterns_updated} updated")
292
- bootstrap_msg = (
293
- f" Synced base patterns: {', '.join(parts_ri)}\n"
294
- )
303
+ bootstrap_msg = f" Synced base patterns: {', '.join(parts_ri)}\n"
295
304
  skills_msg = ""
296
305
  if skills_result is not None and not skills_result.already_existed:
297
306
  skills_msg = (
@@ -320,9 +320,7 @@ def promote_pattern(
320
320
  f.write(json.dumps(dict(target)) + "\n")
321
321
 
322
322
  # Rewrite personal file without the promoted pattern (atomic: temp + rename)
323
- tmp_fd, tmp_path = tempfile.mkstemp(
324
- dir=personal_file.parent, suffix=".tmp"
325
- )
323
+ tmp_fd, tmp_path = tempfile.mkstemp(dir=personal_file.parent, suffix=".tmp")
326
324
  try:
327
325
  with open(tmp_fd, "w", encoding="utf-8") as tmp_f:
328
326
  for line in remaining:
@@ -16,7 +16,10 @@ Example:
16
16
  from __future__ import annotations
17
17
 
18
18
  from pathlib import Path
19
- from typing import Annotated
19
+ from typing import TYPE_CHECKING, Annotated
20
+
21
+ if TYPE_CHECKING:
22
+ from raise_cli.onboarding.skills import SkillScaffoldResult
20
23
 
21
24
  import typer
22
25
 
@@ -47,6 +50,55 @@ from raise_cli.session.state import (
47
50
  migrate_flat_to_session,
48
51
  )
49
52
 
53
+
54
+ def _maybe_sync_skills(project_path: Path) -> SkillScaffoldResult | None:
55
+ """Auto-sync skills if CLI version is newer than last deployed version.
56
+
57
+ Compares raise_cli.__version__ against .raise/manifests/skills.json.
58
+ If CLI is newer, runs scaffold_skills for each detected agent.
59
+
60
+ Returns:
61
+ SkillScaffoldResult if sync happened, None if skipped.
62
+ """
63
+ from raise_cli.onboarding.skill_manifest import load_skill_manifest
64
+
65
+ manifest = load_skill_manifest(project_path)
66
+ if manifest is None:
67
+ return None
68
+
69
+ from raise_cli import __version__ as cli_version
70
+
71
+ if manifest.raise_cli_version == cli_version:
72
+ return None
73
+
74
+ # Version mismatch — sync skills
75
+ from raise_cli.config.agent_registry import load_registry
76
+ from raise_cli.onboarding.skills import scaffold_skills
77
+
78
+ registry = load_registry(project_root=project_path)
79
+ agent_types = registry.detect_agents(project_path)
80
+ result: SkillScaffoldResult | None = None
81
+
82
+ for agent_type in agent_types:
83
+ config = registry.get_config(agent_type)
84
+ plugin = registry.get_plugin(agent_type)
85
+ result = scaffold_skills(project_path, agent_config=config, plugin=plugin)
86
+
87
+ # Report what happened
88
+ if result is not None:
89
+ parts: list[str] = []
90
+ if result.skills_updated:
91
+ parts.append(f"{len(result.skills_updated)} updated")
92
+ if result.skills_installed:
93
+ parts.append(f"{len(result.skills_installed)} new")
94
+ if parts:
95
+ typer.echo(
96
+ f"Skills synced to {cli_version} ({', '.join(parts)})"
97
+ )
98
+
99
+ return result
100
+
101
+
50
102
  session_app = typer.Typer(
51
103
  name="session",
52
104
  help="Manage working sessions",
@@ -172,6 +224,10 @@ def start(
172
224
  typer.echo(f"Warning: {validation.summary()}")
173
225
  typer.echo("Run `raise memory validate` to fix data quality issues.\n")
174
226
 
227
+ # Auto-sync skills if CLI was upgraded (RAISE-509)
228
+ if project is not None:
229
+ _maybe_sync_skills(Path(project))
230
+
175
231
  # Increment session count
176
232
  updated = increment_session(profile, project_path=project)
177
233
 
@@ -342,9 +342,7 @@ def sync_cmd(
342
342
  _print_sync_table(result)
343
343
 
344
344
  has_updates = bool(
345
- result.skills_updated
346
- or result.skills_installed
347
- or result.skills_conflicted
345
+ result.skills_updated or result.skills_installed or result.skills_conflicted
348
346
  )
349
347
  if has_updates:
350
348
  raise typer.Exit(code=1)
@@ -142,4 +142,6 @@ def diff_command(
142
142
 
143
143
  total = len(diff.added) + len(diff.modified) + len(diff.unchanged)
144
144
  added, modified = len(diff.added), len(diff.modified)
145
- console.print(f"\n[bold]Total:[/bold] {total} skills ({added} added, {modified} modified)")
145
+ console.print(
146
+ f"\n[bold]Total:[/bold] {total} skills ({added} added, {modified} modified)"
147
+ )
@@ -139,6 +139,13 @@ def main(
139
139
  global _current_output_format # noqa: PLW0603
140
140
  _current_output_format = format.value # type: ignore[assignment]
141
141
 
142
+ # Check for co-installed legacy packages (RAISE-482)
143
+ from raise_cli.compat import check_legacy_packages
144
+
145
+ legacy_warning = check_legacy_packages()
146
+ if legacy_warning:
147
+ console.print(f"[yellow]Warning:[/yellow] {legacy_warning}")
148
+
142
149
  # Calculate verbosity from flags
143
150
  verbosity = -1 if quiet else min(verbose, 3)
144
151
 
@@ -9,6 +9,7 @@ All platform guards live here. Import from compat, not from fcntl/msvcrt.
9
9
  from __future__ import annotations
10
10
 
11
11
  import sys
12
+ from importlib.metadata import PackageNotFoundError, version
12
13
  from pathlib import Path
13
14
  from typing import IO
14
15
 
@@ -64,3 +65,31 @@ def secure_permissions(path: Path) -> None:
64
65
  """
65
66
  if not IS_WINDOWS:
66
67
  path.chmod(0o600)
68
+
69
+
70
+ _LEGACY_PACKAGES = ("rai-cli", "rai-core")
71
+
72
+
73
+ def check_legacy_packages() -> str | None:
74
+ """Detect co-installed legacy packages from pre-rename era.
75
+
76
+ Returns a warning message with uninstall instructions if legacy
77
+ packages are found, or None if the environment is clean.
78
+ """
79
+ found: list[str] = []
80
+ for pkg in _LEGACY_PACKAGES:
81
+ try:
82
+ ver = version(pkg)
83
+ found.append(f"{pkg}=={ver}")
84
+ except PackageNotFoundError:
85
+ continue
86
+
87
+ if not found:
88
+ return None
89
+
90
+ names = " ".join(pkg.split("==")[0] for pkg in found)
91
+ return (
92
+ f"Legacy packages detected: {', '.join(found)}. "
93
+ f"These conflict with raise-cli and cause stale entry point warnings. "
94
+ f"Remove them with: pip uninstall -y {names}"
95
+ )
@@ -268,7 +268,9 @@ def get_session_dir(session_id: str, project_root: Path | None = None) -> Path:
268
268
  sessions_base = (get_personal_dir(project_root) / SESSIONS_DIR).resolve()
269
269
  session_path = (sessions_base / session_id).resolve()
270
270
  if not session_path.is_relative_to(sessions_base):
271
- raise ValueError(f"Invalid session_id — path traversal detected: {session_id!r}")
271
+ raise ValueError(
272
+ f"Invalid session_id — path traversal detected: {session_id!r}"
273
+ )
272
274
  return session_path
273
275
 
274
276
 
@@ -336,7 +338,9 @@ def _get_xdg_dir(env_var: str, fallback: str) -> Path:
336
338
  Path to the rai subdirectory within the XDG directory.
337
339
  """
338
340
  xdg_value = os.environ.get(env_var)
339
- base = _sanitize_env_path(xdg_value, env_var) if xdg_value else Path.home() / fallback
341
+ base = (
342
+ _sanitize_env_path(xdg_value, env_var) if xdg_value else Path.home() / fallback
343
+ )
340
344
  return base / "rai"
341
345
 
342
346
 
@@ -9,7 +9,6 @@ Architecture: ADR-019 Unified Context Graph Architecture
9
9
  from __future__ import annotations
10
10
 
11
11
  import json
12
- import logging
13
12
  from datetime import UTC, datetime
14
13
  from pathlib import Path
15
14
  from typing import TYPE_CHECKING, Any, cast
@@ -85,18 +84,24 @@ class GraphBuilder:
85
84
  # Must run before add_concept() so graph gets enriched copies
86
85
  self.load_code_structure(all_nodes)
87
86
 
88
- # Warn on duplicate node IDs before adding (silent overwrites lose data)
87
+ # Fail on duplicate node IDs silent overwrites lose data (RAISE-510)
89
88
  seen_ids: dict[str, str] = {}
89
+ duplicates: list[str] = []
90
90
  for node in all_nodes:
91
91
  if node.id in seen_ids:
92
- logging.warning(
93
- "Duplicate node ID '%s' — '%s' will overwrite '%s'",
94
- node.id,
95
- node.source_file or "unknown",
96
- seen_ids[node.id],
92
+ duplicates.append(
93
+ f" Duplicate node ID '{node.id}' — "
94
+ f"'{node.source_file or 'unknown'}' collides with "
95
+ f"'{seen_ids[node.id]}'"
97
96
  )
98
97
  seen_ids[node.id] = node.source_file or "unknown"
99
98
 
99
+ if duplicates:
100
+ raise ValueError(
101
+ "Duplicate node IDs detected — fix source data before building:\n"
102
+ + "\n".join(duplicates)
103
+ )
104
+
100
105
  # Add nodes to graph
101
106
  for node in all_nodes:
102
107
  graph.add_concept(node)
@@ -300,9 +305,7 @@ class GraphBuilder:
300
305
  return []
301
306
 
302
307
  try:
303
- raw: Any = json.loads(
304
- validated_file.read_text(encoding="utf-8")
305
- )
308
+ raw: Any = json.loads(validated_file.read_text(encoding="utf-8"))
306
309
  # Accept both {"components": [...]} wrapper and bare [...] array
307
310
  if isinstance(raw, list):
308
311
  components_list: list[dict[str, Any]] = raw # type: ignore[assignment]
@@ -840,7 +843,9 @@ class GraphBuilder:
840
843
  """
841
844
  # Synthesize content from bounded contexts
842
845
  bcs: list[Any] = frontmatter.get("bounded_contexts", [])
843
- bc_names: list[str] = [bc.get("name", "unknown") if isinstance(bc, dict) else str(bc) for bc in bcs]
846
+ bc_names: list[str] = [
847
+ bc.get("name", "unknown") if isinstance(bc, dict) else str(bc) for bc in bcs
848
+ ]
844
849
  bc_summary = ", ".join(bc_names) if bc_names else "none defined"
845
850
 
846
851
  shared: dict[str, Any] = frontmatter.get("shared_kernel", {})
@@ -28,7 +28,9 @@ class EnvironmentCheck:
28
28
 
29
29
  check_id: ClassVar[str] = "environment"
30
30
  category: ClassVar[str] = "environment"
31
- description: ClassVar[str] = "Python version, raise-cli version, OS, installed extras"
31
+ description: ClassVar[str] = (
32
+ "Python version, raise-cli version, OS, installed extras"
33
+ )
32
34
  requires_online: ClassVar[bool] = False
33
35
 
34
36
  def evaluate(self, context: DoctorContext) -> list[CheckResult]:
@@ -25,9 +25,7 @@ class ProjectCheck:
25
25
 
26
26
  check_id: ClassVar[str] = "project"
27
27
  category: ClassVar[str] = "project"
28
- description: ClassVar[str] = (
29
- ".raise/ structure, manifest, graph staleness, config"
30
- )
28
+ description: ClassVar[str] = ".raise/ structure, manifest, graph staleness, config"
31
29
  requires_online: ClassVar[bool] = False
32
30
 
33
31
  _GRAPH_STALENESS_DAYS: ClassVar[int] = 7
@@ -116,7 +114,9 @@ class ProjectCheck:
116
114
  graph_files = [graph_index]
117
115
  # Also check for additional graph files in the directory
118
116
  graph_dir = graph_index.parent
119
- graph_files.extend(f for f in graph_dir.rglob("*") if f.is_file() and f != graph_index)
117
+ graph_files.extend(
118
+ f for f in graph_dir.rglob("*") if f.is_file() and f != graph_index
119
+ )
120
120
  if not graph_files:
121
121
  return CheckResult(
122
122
  check_id="project-graph",
@@ -21,7 +21,9 @@ from raise_cli.doctor.models import CheckResult
21
21
  FIX_REGISTRY: dict[str, Callable[[Path], bool]] = {}
22
22
 
23
23
 
24
- def register_fix(fix_id: str) -> Callable[[Callable[[Path], bool]], Callable[[Path], bool]]:
24
+ def register_fix(
25
+ fix_id: str,
26
+ ) -> Callable[[Callable[[Path], bool]], Callable[[Path], bool]]:
25
27
  """Decorator to register a fix function by ID."""
26
28
 
27
29
  def decorator(fn: Callable[[Path], bool]) -> Callable[[Path], bool]:
@@ -83,7 +83,9 @@ class CheckRegistry:
83
83
  continue
84
84
 
85
85
  self._checks.append(instance)
86
- logger.debug("Loaded doctor check '%s' (category=%s)", ep.name, instance.category)
86
+ logger.debug(
87
+ "Loaded doctor check '%s' (category=%s)", ep.name, instance.category
88
+ )
87
89
 
88
90
  def register(self, check: DoctorCheck | Any) -> None:
89
91
  """Manually register a check instance (useful for testing)."""