elva-cli 1.1.0rc2__tar.gz → 1.2.0__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 (222) hide show
  1. elva_cli-1.2.0/.github/ISSUE_TEMPLATE/bug_report.yml +27 -0
  2. elva_cli-1.2.0/.github/ISSUE_TEMPLATE/config.yml +5 -0
  3. elva_cli-1.2.0/.github/ISSUE_TEMPLATE/feature_request.yml +19 -0
  4. elva_cli-1.2.0/.github/pull_request_template.md +14 -0
  5. elva_cli-1.2.0/.github/workflows/ci.yml +57 -0
  6. elva_cli-1.2.0/.github/workflows/installer.yml +76 -0
  7. elva_cli-1.2.0/.github/workflows/release.yml +160 -0
  8. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/.gitignore +6 -0
  9. elva_cli-1.2.0/AGENTS.md +23 -0
  10. elva_cli-1.2.0/CHANGELOG.md +105 -0
  11. elva_cli-1.2.0/CLAUDE.md +6 -0
  12. elva_cli-1.2.0/CONTRIBUTING.md +79 -0
  13. elva_cli-1.2.0/PKG-INFO +145 -0
  14. elva_cli-1.2.0/README.md +111 -0
  15. elva_cli-1.2.0/RELEASING.md +66 -0
  16. elva_cli-1.2.0/SECURITY.md +11 -0
  17. elva_cli-1.2.0/docs/README.md +17 -0
  18. elva_cli-1.2.0/docs/agent-interface.md +67 -0
  19. elva_cli-1.2.0/docs/agent-workflow.md +108 -0
  20. elva_cli-1.2.0/docs/ai-plans.md +81 -0
  21. elva_cli-1.1.0rc2/PKG-INFO → elva_cli-1.2.0/docs/commands.md +163 -309
  22. elva_cli-1.2.0/docs/contracts.md +101 -0
  23. elva_cli-1.2.0/docs/email-signup.md +67 -0
  24. elva_cli-1.2.0/docs/exit-codes.md +184 -0
  25. elva_cli-1.2.0/docs/local-source.md +80 -0
  26. elva_cli-1.2.0/docs/privacy.md +40 -0
  27. elva_cli-1.2.0/docs/repository-readiness.md +33 -0
  28. elva_cli-1.2.0/docs/troubleshooting.md +23 -0
  29. elva_cli-1.2.0/examples/customer-orders/README.md +12 -0
  30. elva_cli-1.2.0/examples/customer-orders/artifact.json +47 -0
  31. elva_cli-1.2.0/llms.txt +19 -0
  32. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/pyproject.toml +5 -2
  33. elva_cli-1.2.0/scripts/smoke_wheel.py +116 -0
  34. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/_version.py +2 -2
  35. elva_cli-1.2.0/src/elva_cli/assets/agent-artifact.schema.json +564 -0
  36. elva_cli-1.2.0/src/elva_cli/assets/elva-mcp/SKILL.md +99 -0
  37. elva_cli-1.2.0/src/elva_cli/assets/elva-mcp/agents/openai.yaml +6 -0
  38. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/auth/models.py +7 -1
  39. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/auth/session.py +25 -9
  40. elva_cli-1.2.0/src/elva_cli/commands/agent.py +255 -0
  41. elva_cli-1.2.0/src/elva_cli/commands/apply.py +26 -0
  42. elva_cli-1.2.0/src/elva_cli/commands/auth.py +159 -0
  43. elva_cli-1.2.0/src/elva_cli/commands/contract.py +263 -0
  44. elva_cli-1.2.0/src/elva_cli/commands/insights.py +102 -0
  45. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/commands/mcp.py +111 -0
  46. elva_cli-1.2.0/src/elva_cli/commands/plan.py +34 -0
  47. elva_cli-1.2.0/src/elva_cli/commands/prompt.py +232 -0
  48. elva_cli-1.2.0/src/elva_cli/commands/repo.py +158 -0
  49. elva_cli-1.2.0/src/elva_cli/commands/schema.py +85 -0
  50. elva_cli-1.2.0/src/elva_cli/core/agent_artifact.py +252 -0
  51. elva_cli-1.2.0/src/elva_cli/core/agent_setup.py +51 -0
  52. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/api/http.py +19 -4
  53. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/api/targets.py +10 -9
  54. elva_cli-1.2.0/src/elva_cli/core/api/timeout.py +27 -0
  55. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/collections.py +9 -3
  56. elva_cli-1.2.0/src/elva_cli/core/services/agent_artifact.py +30 -0
  57. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/auth.py +5 -2
  58. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/auth_result.py +21 -0
  59. elva_cli-1.2.0/src/elva_cli/core/services/contract.py +281 -0
  60. elva_cli-1.2.0/src/elva_cli/core/services/contract_result.py +27 -0
  61. elva_cli-1.2.0/src/elva_cli/core/services/email_auth.py +290 -0
  62. elva_cli-1.2.0/src/elva_cli/core/services/insights.py +113 -0
  63. elva_cli-1.2.0/src/elva_cli/core/services/insights_result.py +19 -0
  64. elva_cli-1.2.0/src/elva_cli/core/services/local_source.py +112 -0
  65. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/mcp.py +2 -14
  66. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/mcp_common.py +19 -3
  67. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/mcp_create.py +25 -4
  68. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/mcp_publish.py +16 -3
  69. elva_cli-1.2.0/src/elva_cli/core/services/plan.py +206 -0
  70. elva_cli-1.2.0/src/elva_cli/core/services/plan_result.py +14 -0
  71. elva_cli-1.2.0/src/elva_cli/core/services/repo.py +397 -0
  72. elva_cli-1.2.0/src/elva_cli/core/services/repo_result.py +60 -0
  73. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/whoami.py +5 -1
  74. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/workspace_list.py +10 -3
  75. elva_cli-1.2.0/src/elva_cli/core/source_snapshot.py +319 -0
  76. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/main.py +82 -3
  77. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/registry.py +9 -0
  78. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/settings/models.py +4 -2
  79. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/settings/writer.py +6 -1
  80. elva_cli-1.2.0/src/elva_cli/ui/input.py +18 -0
  81. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/__init__.py +4 -0
  82. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/auth.py +17 -0
  83. elva_cli-1.2.0/src/elva_cli/ui/renderables/contract.py +58 -0
  84. elva_cli-1.2.0/src/elva_cli/ui/renderables/insights.py +47 -0
  85. elva_cli-1.2.0/src/elva_cli/ui/renderables/plan.py +31 -0
  86. elva_cli-1.2.0/src/elva_cli/ui/renderables/repo.py +69 -0
  87. elva_cli-1.2.0/tests/__init__.py +0 -0
  88. elva_cli-1.2.0/tests/cli/__init__.py +0 -0
  89. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/conftest.py +11 -0
  90. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_auth_register_command.py +3 -3
  91. elva_cli-1.2.0/tests/cli/test_insights_contract.py +433 -0
  92. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_never_blocks.py +6 -0
  93. elva_cli-1.2.0/tests/cli/test_regressions.py +136 -0
  94. elva_cli-1.2.0/tests/cli/test_repo.py +435 -0
  95. elva_cli-1.2.0/tests/conftest.py +32 -0
  96. elva_cli-1.2.0/tests/fixtures/agent-artifact.json +47 -0
  97. elva_cli-1.2.0/tests/isolation/sitecustomize.py +27 -0
  98. elva_cli-1.2.0/tests/unit/test_agent_artifact.py +213 -0
  99. elva_cli-1.2.0/tests/unit/test_cli_validation_regressions.py +131 -0
  100. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_collections_flow.py +4 -4
  101. elva_cli-1.2.0/tests/unit/test_email_auth.py +271 -0
  102. elva_cli-1.2.0/tests/unit/test_insights_contract.py +61 -0
  103. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_login_flow.py +7 -5
  104. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_mcp_create_flow.py +4 -4
  105. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_mcp_flow.py +6 -6
  106. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_mcp_logs_flow.py +3 -3
  107. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_mcp_publish_flow.py +4 -4
  108. elva_cli-1.2.0/tests/unit/test_plan.py +144 -0
  109. elva_cli-1.2.0/tests/unit/test_prompt_workflow.py +171 -0
  110. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_register_flow.py +6 -4
  111. elva_cli-1.2.0/tests/unit/test_repo.py +42 -0
  112. elva_cli-1.2.0/tests/unit/test_source_snapshot.py +268 -0
  113. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_targets.py +28 -5
  114. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_workspace_list.py +18 -0
  115. elva_cli-1.1.0rc2/CHANGELOG.md +0 -40
  116. elva_cli-1.1.0rc2/README.md +0 -733
  117. elva_cli-1.1.0rc2/src/elva_cli/commands/auth.py +0 -51
  118. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/__init__.py +0 -0
  119. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/__main__.py +0 -0
  120. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/auth/__init__.py +0 -0
  121. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/auth/store.py +0 -0
  122. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/commands/__init__.py +0 -0
  123. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/commands/collection.py +0 -0
  124. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/commands/config.py +0 -0
  125. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/commands/import_.py +0 -0
  126. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/commands/whoami.py +0 -0
  127. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/commands/workspace.py +0 -0
  128. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/context.py +0 -0
  129. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/__init__.py +0 -0
  130. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/api/__init__.py +0 -0
  131. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/api/collections.py +0 -0
  132. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/api/identity.py +0 -0
  133. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/openapi_ops.py +0 -0
  134. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/__init__.py +0 -0
  135. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/config.py +0 -0
  136. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/import_postman.py +0 -0
  137. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/import_result.py +0 -0
  138. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/import_spec.py +0 -0
  139. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/mcp_create_result.py +0 -0
  140. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/mcp_logs.py +0 -0
  141. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/mcp_logs_result.py +0 -0
  142. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/mcp_result.py +0 -0
  143. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/postman_result.py +0 -0
  144. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/whoami_result.py +0 -0
  145. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/workspace_list_result.py +0 -0
  146. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/workspace_switch.py +0 -0
  147. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/services/workspace_switch_result.py +0 -0
  148. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/spec/__init__.py +0 -0
  149. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/spec/detect.py +0 -0
  150. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/spec/fetch.py +0 -0
  151. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/core/spec/normalize.py +0 -0
  152. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/errors.py +0 -0
  153. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/logging.py +0 -0
  154. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/safe_text.py +0 -0
  155. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/settings/__init__.py +0 -0
  156. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/settings/loader.py +0 -0
  157. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/settings/paths.py +0 -0
  158. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/telemetry.py +0 -0
  159. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/__init__.py +0 -0
  160. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/console.py +0 -0
  161. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/output.py +0 -0
  162. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/prompts.py +0 -0
  163. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/base.py +0 -0
  164. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/collection.py +0 -0
  165. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/config.py +0 -0
  166. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/import_spec.py +0 -0
  167. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/mcp.py +0 -0
  168. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/mcp_create.py +0 -0
  169. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/mcp_logs.py +0 -0
  170. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/postman.py +0 -0
  171. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/whoami.py +0 -0
  172. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/renderables/workspace.py +0 -0
  173. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/secrets.py +0 -0
  174. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/theme.py +0 -0
  175. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/ui/views/__init__.py +0 -0
  176. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/src/elva_cli/update.py +0 -0
  177. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_auth_logout_command.py +0 -0
  178. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_cli_exit_codes.py +0 -0
  179. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_collection_command.py +0 -0
  180. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_config_command.py +0 -0
  181. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_config_write.py +0 -0
  182. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_import_command.py +0 -0
  183. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_import_postman_command.py +0 -0
  184. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_lazy_imports.py +0 -0
  185. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_mcp_command.py +0 -0
  186. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_mcp_create_command.py +0 -0
  187. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_mcp_logs_command.py +0 -0
  188. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_mcp_publish_command.py +0 -0
  189. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_output_streams.py +0 -0
  190. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_whoami_command.py +0 -0
  191. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/cli/test_workspace_switch_command.py +0 -0
  192. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_boundary.py +0 -0
  193. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_collection_endpoints.py +0 -0
  194. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_collection_endpoints_flow.py +0 -0
  195. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_collection_show.py +0 -0
  196. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_context.py +0 -0
  197. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_credentials.py +0 -0
  198. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_error_boundary.py +0 -0
  199. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_errors.py +0 -0
  200. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_exit_codes.py +0 -0
  201. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_http.py +0 -0
  202. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_import_flow.py +0 -0
  203. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_interactivity.py +0 -0
  204. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_logout_flow.py +0 -0
  205. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_mcp_create_operations.py +0 -0
  206. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_openapi_ops.py +0 -0
  207. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_output.py +0 -0
  208. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_postman_flow.py +0 -0
  209. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_prompts.py +0 -0
  210. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_refresh_client.py +0 -0
  211. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_safe_output.py +0 -0
  212. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_secret_input.py +0 -0
  213. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_secrets.py +0 -0
  214. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_session.py +0 -0
  215. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_settings_loader.py +0 -0
  216. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_settings_writer.py +0 -0
  217. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_spec_detect.py +0 -0
  218. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_spec_fetch.py +0 -0
  219. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_token_store.py +0 -0
  220. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_whoami_flow.py +0 -0
  221. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_workspace_render.py +0 -0
  222. {elva_cli-1.1.0rc2 → elva_cli-1.2.0}/tests/unit/test_workspace_switch.py +0 -0
@@ -0,0 +1,27 @@
1
+ name: Bug report
2
+ description: Report a reproducible CLI problem
3
+ body:
4
+ - type: input
5
+ id: version
6
+ attributes:
7
+ label: CLI version and installation method
8
+ validations:
9
+ required: true
10
+ - type: input
11
+ id: environment
12
+ attributes:
13
+ label: OS, shell and Python version
14
+ - type: textarea
15
+ id: reproduction
16
+ attributes:
17
+ label: Synthetic reproduction
18
+ description: Include commands and redacted errors. Do not include tokens, verification codes or customer data.
19
+ validations:
20
+ required: true
21
+ - type: textarea
22
+ id: result
23
+ attributes:
24
+ label: Expected and actual results
25
+ description: Include exit code and JSON status when available.
26
+ validations:
27
+ required: true
@@ -0,0 +1,5 @@
1
+ blank_issues_enabled: true
2
+ contact_links:
3
+ - name: Private security reporting
4
+ url: https://github.com/Theneo-Inc/theneo-elva-cli/blob/main/SECURITY.md
5
+ about: Read the private reporting instructions before disclosing a vulnerability.
@@ -0,0 +1,19 @@
1
+ name: Feature request
2
+ description: Describe a developer or agent workflow need
3
+ body:
4
+ - type: textarea
5
+ id: problem
6
+ attributes:
7
+ label: Workflow and problem
8
+ validations:
9
+ required: true
10
+ - type: textarea
11
+ id: outcome
12
+ attributes:
13
+ label: Desired outcome
14
+ validations:
15
+ required: true
16
+ - type: textarea
17
+ id: constraints
18
+ attributes:
19
+ label: Constraints and current workaround
@@ -0,0 +1,14 @@
1
+ ## Change
2
+
3
+ Describe the user-visible problem and resulting behavior.
4
+
5
+ ## Validation
6
+
7
+ State checks run and gaps. Distinguish fixtures, real services, packaged CLI and
8
+ native-agent validation.
9
+
10
+ ## Compatibility and docs
11
+
12
+ For public behavior changes, note help/docs, JSON/exit codes, backend requirements,
13
+ and changes to source uploads, credentials, drafts or publication. Omit inapplicable
14
+ sections. Do not include secrets or customer data.
@@ -0,0 +1,57 @@
1
+ name: ci
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ concurrency:
12
+ group: ci-${{ github.ref }}
13
+ cancel-in-progress: true
14
+
15
+ jobs:
16
+ wheel-and-minimum-typer:
17
+ runs-on: ubuntu-latest
18
+ steps:
19
+ - uses: actions/checkout@v4
20
+ with:
21
+ fetch-depth: 0
22
+ - uses: astral-sh/setup-uv@v5
23
+ with:
24
+ python-version: "3.11"
25
+ - run: uv build
26
+ - run: |
27
+ uv venv /tmp/wheel
28
+ uv pip install --python /tmp/wheel/bin/python dist/*.whl typer==0.27.1
29
+ /tmp/wheel/bin/python scripts/smoke_wheel.py
30
+
31
+ lint:
32
+ runs-on: ubuntu-latest
33
+ steps:
34
+ - uses: actions/checkout@v4
35
+ - uses: astral-sh/setup-uv@v5
36
+ with:
37
+ enable-cache: true
38
+ - run: uv sync --extra dev
39
+ - run: uv run ruff check .
40
+ - run: uv run ruff format --check .
41
+ - run: uv run mypy
42
+
43
+ test:
44
+ runs-on: ${{ matrix.os }}
45
+ strategy:
46
+ fail-fast: false
47
+ matrix:
48
+ os: [ubuntu-latest, macos-latest, windows-latest]
49
+ python: ["3.11", "3.12", "3.13"]
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - uses: astral-sh/setup-uv@v5
53
+ with:
54
+ enable-cache: true
55
+ python-version: ${{ matrix.python }}
56
+ - run: uv sync --extra dev
57
+ - run: uv run pytest
@@ -0,0 +1,76 @@
1
+ name: installer
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ paths: ["install/**", ".github/workflows/installer.yml"]
7
+ pull_request:
8
+ paths: ["install/**", ".github/workflows/installer.yml"]
9
+ workflow_dispatch:
10
+
11
+ permissions:
12
+ contents: read
13
+
14
+ concurrency:
15
+ group: installer-${{ github.ref }}
16
+ cancel-in-progress: false
17
+
18
+ jobs:
19
+ check:
20
+ runs-on: ubuntu-latest
21
+ timeout-minutes: 10
22
+ steps:
23
+ - uses: actions/checkout@v4
24
+ - uses: actions/setup-node@v4
25
+ with:
26
+ node-version: "22"
27
+ - run: npm install --global firebase-tools@15.32.1
28
+ - name: Prepare installer
29
+ run: |
30
+ sh -n install/install.sh
31
+ mkdir -p install/public
32
+ cp install/install.sh install/public/install.sh
33
+ - name: Test hosting
34
+ run: >-
35
+ firebase emulators:exec
36
+ --project demo-elva-cli-install
37
+ --config install/firebase.json
38
+ --only hosting
39
+ "sh install/test-hosting.sh"
40
+
41
+ deploy:
42
+ if: github.ref == 'refs/heads/main' && github.event_name != 'pull_request'
43
+ needs: check
44
+ runs-on: ubuntu-latest
45
+ timeout-minutes: 10
46
+ environment: installer
47
+ permissions:
48
+ contents: read
49
+ id-token: write
50
+ steps:
51
+ - uses: actions/checkout@v4
52
+ - uses: actions/setup-node@v4
53
+ with:
54
+ node-version: "22"
55
+ - run: npm install --global firebase-tools@15.32.1
56
+ - name: Prepare installer
57
+ run: |
58
+ mkdir -p install/public
59
+ cp install/install.sh install/public/install.sh
60
+ - uses: google-github-actions/auth@v3
61
+ with:
62
+ workload_identity_provider: ${{ vars.ELVA_INSTALLER_WIF_PROVIDER }}
63
+ service_account: ${{ vars.ELVA_INSTALLER_DEPLOY_SA }}
64
+ - name: Deploy installer
65
+ run: >-
66
+ firebase deploy
67
+ --project elva-marketing-prod
68
+ --config install/firebase.json
69
+ --only hosting
70
+ --non-interactive
71
+ - name: Verify published script
72
+ run: |
73
+ curl --fail --silent --show-error --retry 5 --retry-all-errors \
74
+ 'https://elva-cli-install.web.app/?revision=${{ github.sha }}' \
75
+ -o /tmp/published-install.sh
76
+ cmp install/install.sh /tmp/published-install.sh
@@ -0,0 +1,160 @@
1
+ name: release
2
+
3
+ on:
4
+ push:
5
+ tags: ["v*"]
6
+ workflow_dispatch:
7
+
8
+ permissions:
9
+ contents: read
10
+
11
+ jobs:
12
+ build:
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - uses: actions/checkout@v4
16
+ with:
17
+ fetch-depth: 0
18
+
19
+ - uses: astral-sh/setup-uv@v5
20
+
21
+ - run: uv build
22
+
23
+ - name: Reject unpublishable versions
24
+ run: |
25
+ version=$(ls dist/*.whl | head -1 | sed -E 's/.*elva_cli-(.+)-py3.*/\1/')
26
+ echo "built version: $version"
27
+ case "$version" in
28
+ *+*) echo "::error::'$version' has a PEP 440 local segment; PyPI will reject it. Build from an exact tag." ; exit 1 ;;
29
+ *dev*) echo "::error::'$version' is a dev version; the tag is missing or HEAD is past it." ; exit 1 ;;
30
+ esac
31
+
32
+ - run: uvx twine check dist/*
33
+
34
+ - name: Smoke test the wheel in a clean environment
35
+ run: |
36
+ python3 -m venv /tmp/smoke
37
+ /tmp/smoke/bin/pip install --quiet dist/*.whl
38
+ /tmp/smoke/bin/python scripts/smoke_wheel.py
39
+
40
+ - uses: actions/upload-artifact@v4
41
+ with:
42
+ name: dist
43
+ path: dist/
44
+
45
+ testpypi:
46
+ if: github.event_name == 'workflow_dispatch'
47
+ needs: build
48
+ runs-on: ubuntu-latest
49
+ environment: testpypi
50
+ permissions:
51
+ id-token: write
52
+ steps:
53
+ - uses: actions/download-artifact@v4
54
+ with:
55
+ name: dist
56
+ path: dist/
57
+ - uses: pypa/gh-action-pypi-publish@release/v1
58
+ with:
59
+ repository-url: https://test.pypi.org/legacy/
60
+
61
+ pypi:
62
+ if: startsWith(github.ref, 'refs/tags/v')
63
+ needs: build
64
+ runs-on: ubuntu-latest
65
+ environment: pypi
66
+ permissions:
67
+ id-token: write
68
+ steps:
69
+ - uses: actions/download-artifact@v4
70
+ with:
71
+ name: dist
72
+ path: dist/
73
+ - uses: pypa/gh-action-pypi-publish@release/v1
74
+
75
+ binaries:
76
+ if: startsWith(github.ref, 'refs/tags/v')
77
+ needs: build
78
+ strategy:
79
+ fail-fast: false
80
+ matrix:
81
+ include:
82
+ - { runner: ubuntu-latest, asset: elva-linux-x86_64 }
83
+ - { runner: ubuntu-24.04-arm, asset: elva-linux-aarch64 }
84
+ - { runner: macos-15-intel, asset: elva-darwin-x86_64 }
85
+ - { runner: macos-latest, asset: elva-darwin-arm64 }
86
+ runs-on: ${{ matrix.runner }}
87
+ steps:
88
+ - uses: actions/download-artifact@v4
89
+ with:
90
+ name: dist
91
+ path: dist/
92
+
93
+ - uses: dtolnay/rust-toolchain@stable
94
+
95
+ - name: Build ${{ matrix.asset }}
96
+ env:
97
+ PYAPP_EXEC_SPEC: elva_cli.main:main
98
+ PYAPP_PYTHON_VERSION: "3.12"
99
+ PYAPP_DISTRIBUTION_EMBED: "1"
100
+ run: |
101
+ export PYAPP_PROJECT_PATH="$PWD/$(ls dist/*.whl | head -1)"
102
+ echo "embedding $PYAPP_PROJECT_PATH"
103
+ cargo install pyapp --force --locked --root out
104
+ mv out/bin/pyapp "${{ matrix.asset }}"
105
+ chmod +x "${{ matrix.asset }}"
106
+
107
+ - name: It runs, and reports the version we built
108
+ run: |
109
+ set +e
110
+ got="$(./${{ matrix.asset }} --version 2>&1)"
111
+ rc=$?
112
+ set -e
113
+ echo "$got"
114
+ if [ $rc -ne 0 ]; then
115
+ echo "::error::${{ matrix.asset }} exited $rc"
116
+ exit 1
117
+ fi
118
+ version="$(ls dist/*.whl | head -1 | sed -E 's/.*elva_cli-(.+)-py3.*/\1/')"
119
+ case "$got" in
120
+ "elva $version "*) ;;
121
+ *) echo "::error::expected version $version, got: $got"; exit 1 ;;
122
+ esac
123
+
124
+ - uses: actions/upload-artifact@v4
125
+ with:
126
+ name: ${{ matrix.asset }}
127
+ path: ${{ matrix.asset }}
128
+
129
+ publish-binaries:
130
+ if: startsWith(github.ref, 'refs/tags/v')
131
+ needs: binaries
132
+ runs-on: ubuntu-latest
133
+ permissions:
134
+ contents: write
135
+ steps:
136
+ - uses: actions/download-artifact@v4
137
+ with:
138
+ pattern: elva-*
139
+ path: bin/
140
+ merge-multiple: true
141
+
142
+ - name: Checksums
143
+ working-directory: bin
144
+ run: |
145
+ chmod +x elva-*
146
+ sha256sum elva-* > SHA256SUMS
147
+ cat SHA256SUMS
148
+
149
+ - name: Upload to the release
150
+ env:
151
+ GH_TOKEN: ${{ github.token }}
152
+ run: |
153
+ case "$GITHUB_REF_NAME" in
154
+ *-*) prerelease="--prerelease" ;;
155
+ *) prerelease="" ;;
156
+ esac
157
+ gh release view "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" >/dev/null 2>&1 \
158
+ || gh release create "$GITHUB_REF_NAME" --repo "$GITHUB_REPOSITORY" \
159
+ --title "$GITHUB_REF_NAME" --generate-notes $prerelease
160
+ gh release upload "$GITHUB_REF_NAME" bin/* --repo "$GITHUB_REPOSITORY" --clobber
@@ -221,3 +221,9 @@ __marimo__/
221
221
  .venv/
222
222
  src/elva_cli/_version.py
223
223
  .ruff_cache/
224
+
225
+ /install/public/
226
+ /install/.firebase/
227
+ firebase-debug.log*
228
+ ui-debug.log*
229
+ gha-creds-*.json
@@ -0,0 +1,23 @@
1
+ # Working on Elva CLI
2
+
3
+ This file guides changes to the CLI source. Agents consuming Elva should use the
4
+ [canonical skill](src/elva_cli/assets/elva-mcp/SKILL.md), installed by `elva agent setup`,
5
+ and the [agent interface](docs/agent-interface.md).
6
+
7
+ ## Preserve behavior
8
+
9
+ Keep terminal I/O at the command/UI boundary and expensive imports lazy. Every
10
+ interactive input needs an unattended equivalent. Preserve stable JSON fields,
11
+ exit codes, retry IDs, and draft/publication separation. The existing-agent path
12
+ sends generated API artifacts; never silently switch it to source upload or Elva AI.
13
+ Use synthetic data and isolated profiles. Real services, email and publication
14
+ must stay within the user's authorized scope. Do not commit secrets or private data.
15
+
16
+ ## Validate and document
17
+
18
+ Follow [CONTRIBUTING.md](CONTRIBUTING.md). Run relevant tests; complete checks are
19
+ `ruff check .`, `ruff format --check .`, `mypy`, and `pytest`. Check changed examples
20
+ and links. Align `uv.lock` after dependency changes. Update help, guides and changelog
21
+ for public behavior changes. Keep the bundled skill canonical and include required
22
+ assets in distributions. Do not edit generated `_version.py`. Report actual checks
23
+ and distinguish fixtures from production, runtime and native-agent validation.
@@ -0,0 +1,105 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ### Repository documentation
6
+ - Add an agent-first quickstart, shareable skill link, recovery/privacy guides,
7
+ contributor instructions, offline example and issue/PR templates.
8
+ - Restore features onto current main, retaining standalone installer support.
9
+
10
+ ### Email-only CLI onboarding
11
+
12
+ - Add `auth signup` / `auth register` with email-only verification, automatic account
13
+ and default workspace setup, `auth verify --code-stdin`, and `auth resume`.
14
+ - Preserve a generated API artifact locally with `--continue-artifact`; return its
15
+ next command after login without source upload or another signup form.
16
+ - Bind signup proof and newly saved credentials to their API origin, recover lost
17
+ responses, keep codes out of arguments/output, and acknowledge durable storage.
18
+ - Teach the bundled agent skill to complete onboarding with authorized email access.
19
+
20
+
21
+ ### Existing-agent API artifacts
22
+
23
+ - Add `agent setup`, `agent schema`, `agent validate`, and `agent create`.
24
+ - Bundle discoverable Claude Code/Codex instructions for generating an API definition locally.
25
+ - Import only sanitized API artifacts; create resumable collection/contract/MCP drafts without Elva AI or GitHub.
26
+ - Require the matching artifact-plan backend before release.
27
+
28
+ ### Prompt from a local checkout
29
+ - Add root `--prompt` to scan raw source with Elva AI, generate OpenAPI collections,
30
+ select customer endpoints/fields, and create a reviewed draft contract and MCP.
31
+ - No GitHub connection or manually authored specification is required.
32
+ - Add audience/API URL follow-ups, bounded filtered uploads, independent ignore
33
+ rules, secret redaction, auth options, `--plan-only` and `--resume` recovery.
34
+ - Preserve source collections on planning retries and keep draft publication governed.
35
+
36
+ ### Workspace defaults, API insights and contracts
37
+ - Select the default Elva workspace automatically when no selection is configured,
38
+ including accounts with several workspaces. Mark that default in `workspace list`.
39
+ - Add `insights checks`, `insights review`, and `insights show`, with JSON output
40
+ and an optional overall-score gate for CI.
41
+ - Add `contract list/show/create/update/sync/approve/reject/publish/delete`.
42
+ Creation is draft-only; publication is explicit and reports partial results.
43
+ - Support PAT workspace discovery and scoped collection/contract reads and
44
+ lifecycle actions with the matching backend, preserving membership and roles.
45
+
46
+ ### GitHub repository sync
47
+ - Add `repo list`, `repo connect`, `repo sync`, and `repo status` using Elva's
48
+ existing linked GitHub account and scan pipeline.
49
+ - Support remote branch selection, explicit AI extraction, workspace scoping,
50
+ resumable bounded waits, JSON results, and collection change summaries.
51
+ - Preserve reconnect settings, refuse unscoped backends before mutations, and
52
+ report partial connection, failed scans and skipped collection sync accurately.
53
+ - Require the matching workspace-scoped repository backend before CLI rollout.
54
+
55
+ ### CLI validation fixes
56
+ - Support Windows source snapshots without POSIX-only open flags, retaining regular-file
57
+ and file-identity checks, and read installed skills consistently as UTF-8 on repeat setup.
58
+ - Isolate interactive tests from all CI provider flags and make newline, permission and
59
+ oversized-input test cases portable across the supported OS/Python matrix.
60
+ - Return complete MCP endpoints, including the workspace component, consistently
61
+ from create, show, and publish; drafts have no connection URL.
62
+ - Preserve Ctrl-C exit status 130, honor `timeout` / `ELVA_TIMEOUT` in every HTTP
63
+ transport, and reject non-finite timeouts before changing config files.
64
+ - Report denied access as `ELVA_FORBIDDEN` (exit 3) without deleting credentials.
65
+ - Require Typer 0.27.1 or newer, matching the vendored Click API the CLI uses.
66
+ - Correct the endpoints-to-MCP pipeline and distinguish source docs from PyPI 0.5.0.
67
+ - Isolate test profiles on macOS as well as Linux/Windows; smoke-test wheel commands.
68
+
69
+
70
+ ### Added
71
+ - **Identify as a first-class refresh client (ELVA-200).** Every request now
72
+ sends `X-Elva-Client: cli` and a `User-Agent: elva-cli/<version>`. The refresh
73
+ and CLI-login exchanges carry the marker so the backend routes them on the
74
+ body-token path and, once its compatibility flag is turned off, does not
75
+ reject the CLI as an unmarked client.
76
+ - **Refresh-and-retry on 401.** An idempotent request (GET/HEAD) that returns
77
+ 401 on a token that looked valid now forces one refresh and retries once.
78
+ Non-idempotent requests (the spec upload) are never auto-replayed.
79
+ - **Backoff on transient refresh failures.** A refresh that hits 429/5xx or a
80
+ network error is retried with backoff (1s/2s/4s) before surfacing as a
81
+ transient `ApiError` (exit 5); it never forces a re-login.
82
+
83
+ ### Changed
84
+ - Refresh continues to happen proactively ~60s before the access token expires
85
+ and to persist the rotated token atomically (temp file + rename, 0600) before
86
+ the response is used — unchanged, but now covered by explicit tests.
87
+ - **`elva import spec --url` now fetches through Elva and uploads like a file.**
88
+ The URL is fetched via Elva's `fetch-file` proxy (the same path the web app
89
+ uses, so a spec host only Elva can reach still works), a JSON spec is stored
90
+ as YAML to match a web-app import instead of one minified line, and `--name`
91
+ now defaults from the fetched spec's `info.title`. `--dry-run --url` reports
92
+ the real title/version/endpoint count/size, and a spec URL that 404s or times
93
+ out is now a usage error (exit 2) rather than a late server rejection. Local
94
+ `.json` files are converted to YAML on import for the same consistency.
95
+
96
+ ### Compatibility
97
+ This version works with **both** the flagged and the unflagged backend:
98
+ - While the backend keeps `AUTH_ALLOW_BODY_REFRESH_TOKEN` on, unmarked body
99
+ refreshes still work, so **older CLI versions keep working** too.
100
+ - Once the backend turns that flag off (this CLI version being the minimum
101
+ supported), the server rejects unmarked and legacy ("family-less") refresh
102
+ tokens with `401 REFRESH_TOKEN_LEGACY`. This CLI maps that to
103
+ *"Your session has expired. Run `elva auth login` to sign in again."*
104
+ (exit code 3). **Older CLI versions stop working at that point** and users
105
+ must upgrade and re-login once.
@@ -0,0 +1,6 @@
1
+ # Elva CLI development
2
+
3
+ Follow [AGENTS.md](AGENTS.md) when changing this repository. To create an MCP from
4
+ another API repository, use the [Elva skill](src/elva_cli/assets/elva-mcp/SKILL.md)
5
+ and [agent interface](docs/agent-interface.md). This file does not install that skill
6
+ into another project; use `elva agent setup`.
@@ -0,0 +1,79 @@
1
+ # Contributing to Elva CLI
2
+
3
+ Use GitHub issues for reproducible bugs and feature requests. Report vulnerabilities
4
+ privately using [SECURITY.md](SECURITY.md).
5
+
6
+ ## Setup
7
+
8
+ Use Python 3.11 or newer. Clone the repository and check out the intended branch:
9
+
10
+ ```bash
11
+ git clone https://github.com/Theneo-Inc/theneo-elva-cli.git
12
+ cd theneo-elva-cli
13
+ python3 -m venv .venv
14
+ source .venv/bin/activate
15
+ python -m pip install -e ".[dev]"
16
+ elva --version
17
+ elva --help
18
+ ```
19
+
20
+ In PowerShell, use `py -m venv .venv` and `.venv\Scripts\Activate.ps1`.
21
+ Alternatively, run `uv sync --locked --extra dev` and `uv run elva --help`.
22
+ When changing dependencies, run `uv lock`, review its diff and commit `uv.lock`
23
+ with `pyproject.toml`. Verify freshness with `uv lock --check`.
24
+
25
+ ## Checks
26
+
27
+ Run focused tests while editing, then the complete checks before merging:
28
+
29
+ ```bash
30
+ ruff check .
31
+ ruff format --check .
32
+ mypy
33
+ pytest
34
+ ```
35
+
36
+ Plain `mypy` checks source and tests; `mypy src` does not match CI. CI also defines
37
+ Linux/macOS/Windows coverage for Python 3.11–3.13 and a clean-wheel/minimum-Typer
38
+ check. Record actual results; a configured matrix is not evidence that it passed.
39
+
40
+ Tests use synthetic data and isolated CLI profiles. Preserve that isolation.
41
+ Use real services, email, source upload or publication only in the user's authorized
42
+ scope and environment. Never include tokens or customer data in fixtures.
43
+
44
+ ## Architecture
45
+
46
+ - `commands/`: Typer options and command orchestration.
47
+ - `core/services/`: service calls and typed results.
48
+ - `core/api/`: HTTP transport and API target resolution.
49
+ - `core/spec/`: API format detection and normalization.
50
+ - `core/agent_*.py`: artifact validation and skill installation.
51
+ - `auth/`: credentials, browser/email sessions and refresh.
52
+ - `settings/`: profiles, configuration and precedence.
53
+ - `ui/`: terminal output and prompts.
54
+ - `assets/elva-mcp/`: canonical installed skill.
55
+
56
+ These paths are under `src/elva_cli/`. Keep terminal I/O at the command/UI boundary
57
+ and expensive imports lazy. Every interactive input needs an unattended equivalent.
58
+ Preserve exit codes, JSON contracts, retry IDs and the distinction between drafts
59
+ and publication. Keep Python and backend artifact schemas aligned.
60
+
61
+ ## Documentation and PRs
62
+
63
+ Keep the README focused on onboarding and detailed commands in `docs/`. Update help,
64
+ the relevant guide and changelog for public behavior changes. Maintain one canonical
65
+ skill in `src/elva_cli/assets/elva-mcp/`.
66
+
67
+ Validate examples offline and check relative links:
68
+
69
+ ```bash
70
+ elva --json agent validate --from examples/customer-orders/artifact.json
71
+ ```
72
+
73
+ The example is synthetic. Local validation, resource creation, publication, live
74
+ runtime access and native agent discovery are separate checks.
75
+
76
+ PRs should describe the problem, resulting behavior, validation and any backend
77
+ compatibility requirements. Do not edit generated `src/elva_cli/_version.py`.
78
+ See [AGENTS.md](AGENTS.md), [RELEASING.md](RELEASING.md) and
79
+ [repository readiness](docs/repository-readiness.md).