reprompt-cli 2.0.1__tar.gz → 2.0.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 (302) hide show
  1. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/CHANGELOG.md +77 -0
  2. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/PKG-INFO +4 -3
  3. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/README.md +3 -2
  4. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/pyproject.toml +1 -1
  5. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/__init__.py +4 -4
  6. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/cli.py +18 -0
  7. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/scorer.py +79 -28
  8. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/rewrite_terminal.py +3 -3
  9. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/terminal.py +36 -14
  10. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/wrapped_html.py +3 -3
  11. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cli.py +2 -2
  12. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_coverage_boost.py +6 -6
  13. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/uv.lock +1 -1
  14. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.editorconfig +0 -0
  15. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  16. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  17. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  18. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  19. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  20. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/dependabot.yml +0 -0
  21. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/workflows/ci.yml +0 -0
  22. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/workflows/publish.yml +0 -0
  23. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.gitignore +0 -0
  24. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.pre-commit-config.yaml +0 -0
  25. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.pre-commit-hooks.yaml +0 -0
  26. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.testmondata-shm +0 -0
  27. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.testmondata-wal +0 -0
  28. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/CODE_OF_CONDUCT.md +0 -0
  29. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/CONTRIBUTING.md +0 -0
  30. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/LICENSE +0 -0
  31. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/SECURITY.md +0 -0
  32. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/Screenshot 2026-03-24 at 09.45.03.png +0 -0
  33. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/action.yml +0 -0
  34. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/demo.gif +0 -0
  35. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-128.png +0 -0
  36. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-16.png +0 -0
  37. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-256.png +0 -0
  38. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-32.png +0 -0
  39. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-48.png +0 -0
  40. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-512.png +0 -0
  41. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-96.png +0 -0
  42. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon.svg +0 -0
  43. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-128.png +0 -0
  44. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-16.png +0 -0
  45. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-256.png +0 -0
  46. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-32.png +0 -0
  47. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-48.png +0 -0
  48. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-512.png +0 -0
  49. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-96.png +0 -0
  50. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon.svg +0 -0
  51. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-128.png +0 -0
  52. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-16.png +0 -0
  53. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-256.png +0 -0
  54. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-32.png +0 -0
  55. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-48.png +0 -0
  56. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-512.png +0 -0
  57. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-96.png +0 -0
  58. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon.svg +0 -0
  59. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-128.png +0 -0
  60. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-16.png +0 -0
  61. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-256.png +0 -0
  62. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-32.png +0 -0
  63. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-48.png +0 -0
  64. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-512.png +0 -0
  65. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-96.png +0 -0
  66. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon.svg +0 -0
  67. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/generate.sh +0 -0
  68. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/superpowers/specs/2026-03-24-v14-command-consolidation-design.md +0 -0
  69. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/superpowers/specs/2026-03-25-v1.5-dashboard-design.md +0 -0
  70. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/scripts/generate_demo_data.py +0 -0
  71. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/__init__.py +0 -0
  72. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/aider.py +0 -0
  73. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/base.py +0 -0
  74. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/chatgpt.py +0 -0
  75. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/claude_chat.py +0 -0
  76. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/claude_code.py +0 -0
  77. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/cline.py +0 -0
  78. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/codex.py +0 -0
  79. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/cursor.py +0 -0
  80. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/filters.py +0 -0
  81. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/gemini.py +0 -0
  82. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/openclaw.py +0 -0
  83. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/__init__.py +0 -0
  84. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/handler.py +0 -0
  85. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/host.py +0 -0
  86. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/manifest.py +0 -0
  87. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/protocol.py +0 -0
  88. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/commands/__init__.py +0 -0
  89. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/commands/telemetry.py +0 -0
  90. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/commands/wrapped.py +0 -0
  91. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/config.py +0 -0
  92. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/__init__.py +0 -0
  93. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/agent.py +0 -0
  94. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/analyzer.py +0 -0
  95. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/compress.py +0 -0
  96. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/conversation.py +0 -0
  97. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/cost.py +0 -0
  98. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/dashboard.py +0 -0
  99. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/dedup.py +0 -0
  100. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/digest.py +0 -0
  101. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/distill.py +0 -0
  102. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/effectiveness.py +0 -0
  103. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/extractors.py +0 -0
  104. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/extractors_zh.py +0 -0
  105. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/insights.py +0 -0
  106. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/lang_detect.py +0 -0
  107. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/library.py +0 -0
  108. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/lint.py +0 -0
  109. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/merge_view.py +0 -0
  110. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/models.py +0 -0
  111. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/persona.py +0 -0
  112. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/pipeline.py +0 -0
  113. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/privacy.py +0 -0
  114. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/privacy_scan.py +0 -0
  115. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/prompt_dna.py +0 -0
  116. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/recommend.py +0 -0
  117. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/repetition.py +0 -0
  118. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/rewrite.py +0 -0
  119. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/segmenter.py +0 -0
  120. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/session_meta.py +0 -0
  121. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/session_quality.py +0 -0
  122. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/session_type.py +0 -0
  123. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/style.py +0 -0
  124. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/suggestions.py +0 -0
  125. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/templates.py +0 -0
  126. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/timeutil.py +0 -0
  127. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/trends.py +0 -0
  128. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/wrapped.py +0 -0
  129. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/demo.py +0 -0
  130. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/__init__.py +0 -0
  131. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/base.py +0 -0
  132. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/local_embed.py +0 -0
  133. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/ollama.py +0 -0
  134. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/openai_embed.py +0 -0
  135. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/tfidf.py +0 -0
  136. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/mcp.py +0 -0
  137. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/mcp_main.py +0 -0
  138. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/__init__.py +0 -0
  139. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/agent_terminal.py +0 -0
  140. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/chartjs.min.js +0 -0
  141. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/compress_terminal.py +0 -0
  142. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/dashboard_terminal.py +0 -0
  143. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/distill_terminal.py +0 -0
  144. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/export.py +0 -0
  145. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/html_report.py +0 -0
  146. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/json_out.py +0 -0
  147. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/markdown.py +0 -0
  148. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/projects_terminal.py +0 -0
  149. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/repetition_terminal.py +0 -0
  150. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/sessions_terminal.py +0 -0
  151. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/wrapped_terminal.py +0 -0
  152. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/py.typed +0 -0
  153. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/sharing/__init__.py +0 -0
  154. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/sharing/client.py +0 -0
  155. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/sharing/clipboard.py +0 -0
  156. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/storage/__init__.py +0 -0
  157. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/storage/db.py +0 -0
  158. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/__init__.py +0 -0
  159. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/collector.py +0 -0
  160. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/consent.py +0 -0
  161. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/events.py +0 -0
  162. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/prompt.py +0 -0
  163. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/queue.py +0 -0
  164. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/sender.py +0 -0
  165. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/__init__.py +0 -0
  166. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/conftest.py +0 -0
  167. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/aider_chat_history.md +0 -0
  168. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/chatgpt_conversations.json +0 -0
  169. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/claude_chat_export.json +0 -0
  170. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/claude_session.jsonl +0 -0
  171. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/cline_task/api_conversation_history.json +0 -0
  172. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/export/default_export.md +0 -0
  173. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/export/full_export.md +0 -0
  174. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/gemini_session.json +0 -0
  175. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/openclaw_session.jsonl +0 -0
  176. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_aider.py +0 -0
  177. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_chatgpt.py +0 -0
  178. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_claude.py +0 -0
  179. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_claude_chat.py +0 -0
  180. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_cline.py +0 -0
  181. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_gemini.py +0 -0
  182. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_openclaw.py +0 -0
  183. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_agent.py +0 -0
  184. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_agent_cli.py +0 -0
  185. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_analyzer.py +0 -0
  186. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_cli.py +0 -0
  187. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_e2e.py +0 -0
  188. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_handler.py +0 -0
  189. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_integration.py +0 -0
  190. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_manifest.py +0 -0
  191. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_protocol.py +0 -0
  192. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cli_deprecations.py +0 -0
  193. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cli_library_effectiveness.py +0 -0
  194. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_clipboard.py +0 -0
  195. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_codex_adapter.py +0 -0
  196. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compare_best_worst.py +0 -0
  197. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress.py +0 -0
  198. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress_cli.py +0 -0
  199. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress_dna.py +0 -0
  200. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress_html.py +0 -0
  201. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress_insights.py +0 -0
  202. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_config.py +0 -0
  203. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_conversation.py +0 -0
  204. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_copy_flag.py +0 -0
  205. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cost.py +0 -0
  206. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cursor_adapter.py +0 -0
  207. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_dashboard.py +0 -0
  208. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db.py +0 -0
  209. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db_digest.py +0 -0
  210. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db_effectiveness.py +0 -0
  211. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db_session_quality.py +0 -0
  212. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db_trends.py +0 -0
  213. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_dedup.py +0 -0
  214. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_demo.py +0 -0
  215. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_deprecated_commands.py +0 -0
  216. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_digest.py +0 -0
  217. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_digest_cli.py +0 -0
  218. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_distill.py +0 -0
  219. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_distill_cli.py +0 -0
  220. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_distill_weights.py +0 -0
  221. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_e2e.py +0 -0
  222. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_effectiveness.py +0 -0
  223. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_embeddings_local.py +0 -0
  224. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_embeddings_ollama.py +0 -0
  225. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_embeddings_openai.py +0 -0
  226. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_empty_state.py +0 -0
  227. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_export.py +0 -0
  228. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_export_cli.py +0 -0
  229. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_export_snapshot.py +0 -0
  230. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_extractors.py +0 -0
  231. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_extractors_routing.py +0 -0
  232. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_extractors_zh.py +0 -0
  233. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_extractors_zh_e2e.py +0 -0
  234. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_html_report.py +0 -0
  235. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_import_cli.py +0 -0
  236. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_import_e2e.py +0 -0
  237. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_init_cli.py +0 -0
  238. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_insights.py +0 -0
  239. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_insights_cli.py +0 -0
  240. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_insights_expanded.py +0 -0
  241. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_install_hook.py +0 -0
  242. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_lang_detect.py +0 -0
  243. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_library.py +0 -0
  244. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_lint.py +0 -0
  245. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_lint_cli.py +0 -0
  246. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_markdown.py +0 -0
  247. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_mcp.py +0 -0
  248. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_merge_view.py +0 -0
  249. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_models.py +0 -0
  250. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_output.py +0 -0
  251. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_parse_conversation_base.py +0 -0
  252. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_parse_conversation_chatgpt.py +0 -0
  253. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_parse_conversation_claude.py +0 -0
  254. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_persona.py +0 -0
  255. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_pipeline.py +0 -0
  256. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy.py +0 -0
  257. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy_cli.py +0 -0
  258. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy_e2e.py +0 -0
  259. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy_output.py +0 -0
  260. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy_scan.py +0 -0
  261. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_projects.py +0 -0
  262. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_prompt_dna.py +0 -0
  263. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_public_api.py +0 -0
  264. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_recommend.py +0 -0
  265. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_repetition.py +0 -0
  266. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_repetition_cli.py +0 -0
  267. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_repetition_output.py +0 -0
  268. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_rewrite.py +0 -0
  269. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_schema_version.py +0 -0
  270. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_score_cli.py +0 -0
  271. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_scorer.py +0 -0
  272. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_segmenter.py +0 -0
  273. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_session_quality.py +0 -0
  274. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_session_type.py +0 -0
  275. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_sessions_cli.py +0 -0
  276. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_sessions_output.py +0 -0
  277. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_share_e2e.py +0 -0
  278. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_sharing_client.py +0 -0
  279. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_source_filter.py +0 -0
  280. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_style.py +0 -0
  281. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_style_trends.py +0 -0
  282. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_suggestions.py +0 -0
  283. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_cli.py +0 -0
  284. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_collector.py +0 -0
  285. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_consent.py +0 -0
  286. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_e2e.py +0 -0
  287. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_events.py +0 -0
  288. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_prompt.py +0 -0
  289. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_queue.py +0 -0
  290. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_sender.py +0 -0
  291. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_template_cli.py +0 -0
  292. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_templates.py +0 -0
  293. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_timeutil.py +0 -0
  294. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_trends.py +0 -0
  295. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_trends_cli.py +0 -0
  296. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_use_cli.py +0 -0
  297. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped.py +0 -0
  298. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_cli.py +0 -0
  299. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_e2e.py +0 -0
  300. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_html.py +0 -0
  301. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_output.py +0 -0
  302. {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_share.py +0 -0
@@ -2,6 +2,83 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## [2.0.1] - 2026-03-31
6
+
7
+ ### Added
8
+ - **Project-level quality comparison** — `reprompt projects` aggregates session quality, efficiency, focus scores, and frustration signals per project. Supports `--source` filter, `--json`, `--copy`.
9
+ - Tests: 1670 → 1716
10
+
11
+ ## [2.0.0] - 2026-03-31
12
+
13
+ ### Changed
14
+ - **Major version bump** — the rewrite engine marks the shift from passive analysis (v1.x) to active prompt coaching (v2.0). reprompt now scores, rewrites, and optimizes your AI prompts automatically.
15
+
16
+ ## [1.10.0] - 2026-03-31
17
+
18
+ ### Added
19
+ - **Prompt rewrite engine** — `reprompt rewrite "prompt"` applies 4 rule-based transformations: filler removal (reuses compress engine), instruction front-loading (Stanford position bias), key requirement echo (Google repetition research), hedging cleanup (12 regex patterns). Shows before/after score delta and manual suggestions. No LLM needed, under 50ms.
20
+ - **`reprompt init` command** — generates `.reprompt.toml` config with all lint rules documented and commented defaults. `--force` to overwrite existing.
21
+ - Tests: 1597 → 1670
22
+
23
+ ## [1.9.1] - 2026-03-31
24
+
25
+ ### Added
26
+ - **Configurable lint rules** — `.reprompt.toml` or `[tool.reprompt.lint]` in `pyproject.toml`. Supports `score-threshold`, `min-length`, `short-prompt`, `vague-prompt`, `debug-needs-reference`, `file-extensions`. Config walks up from CWD. CLI flags override file config.
27
+ - Tests: 1567 → 1597
28
+
29
+ ## [1.9.0] - 2026-03-31
30
+
31
+ ### Added
32
+ - **Bidirectional bridge** — Native Messaging `sync_result` now returns insights (avg score, score trend, top coaching tip) back to the browser extension. New `get_insights` message type for full analysis including repetition data and pattern info.
33
+ - `get_recent_scores(limit)` DB method for trend computation.
34
+ - Tests: 1545 → 1567
35
+
36
+ ## [1.8.1] - 2026-03-31
37
+
38
+ ### Added
39
+ - **Cross-session repetition detection** — `reprompt repetition` detects recurring prompts across different AI sessions using TF-IDF + containment clustering (threshold 0.75). Shows repetition rate, recurring topics ranked by session count, and date ranges. Integrated into `reprompt insights` output.
40
+ - Tests: 1529 → 1545
41
+
42
+ ## [1.8.0] - 2026-03-31
43
+
44
+ ### Added
45
+ - **Session quality metrics** — `reprompt sessions` provides composite 0-100 session scoring combining prompt quality, efficiency, focus, and outcome. Frustration signal detection: abandonment, escalation, stall turns. Rich table and detail views.
46
+
47
+ ### Fixed
48
+ - **Pipeline type mismatch** — `parse_conversation()` returns `list[ConversationTurn]`, not `Conversation`. Pipeline now wraps turns correctly. Without this fix, session quality scoring silently failed.
49
+ - **Bridge shell injection** — quoted `sys.executable` in bridge wrapper script to prevent command injection when Python path contains spaces.
50
+ - **Unclamped scores** — efficiency and focus component scores now clamped to 0-100 range.
51
+ - Tests: 1497 → 1529
52
+
53
+ ## [1.7.1] - 2026-03-29
54
+
55
+ ### Added
56
+ - **Expanded privacy scanner** — 10 new detection patterns: SSH private keys (RSA/EC/DSA/OPENSSH/PKCS#8), PEM certificates, service tokens (Slack bot/user/app, Google API, npm), database connection strings (PostgreSQL, MySQL, MongoDB, Redis). 28 new tests. Closes #12.
57
+
58
+ ## [1.7.0] - 2026-03-28
59
+
60
+ ### Added
61
+ - **GitHub Action PR comments** — `comment-on-pr: true` posts quality report as PR comment with markdown table, collapsible violations, and score summary. Updates existing comment on re-push (no duplicates).
62
+ - **Token cost estimation** — `reprompt score` shows ~tokens and $cost. `reprompt insights` shows total prompt cost. `reprompt report` overview includes estimated cost. MCP `score_prompt` includes token count and cost.
63
+ - Locale-aware token counting: 1.3x words (EN), 1.5x chars (CJK).
64
+ - Price table: Claude Sonnet/Opus/Haiku, GPT-4o/mini, Gemini, DeepSeek. Auto-detect model from adapter source.
65
+ - Tests: 1497 → 1529
66
+
67
+ ## [1.6.2] - 2026-03-28
68
+
69
+ ### Fixed
70
+ - **Security: shell injection in GitHub Action** — inputs now passed via env vars, not string interpolation.
71
+ - **Bridge: 1MB message limit** — enforce Chrome Native Messaging size limit with proper JSON decode error handling.
72
+
73
+ ### Improved
74
+ - SQLite WAL mode + 10s timeout for concurrent access safety.
75
+ - MCP: all 6 tools wrapped in try/except with structured error responses; `check_privacy` uses SQL LIMIT.
76
+ - Dedup: skip O(n²) semantic layer when batch > 5000 prompts.
77
+ - ChatGPT adapter: warn on files > 200MB.
78
+ - First-run dashboard shows "Found N sessions (~M turns) across K tools".
79
+ - `purge --all` now requires confirmation.
80
+ - MCP server consolidated from 10 to 6 focused tools.
81
+
5
82
  ## [1.6.1] - 2026-03-28
6
83
 
7
84
  ### Fixed
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reprompt-cli
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: Discover, analyze, and optimize your prompts from AI coding sessions
5
5
  Project-URL: Homepage, https://github.com/reprompt-dev/reprompt
6
6
  Project-URL: Repository, https://github.com/reprompt-dev/reprompt
@@ -111,6 +111,7 @@ $ reprompt
111
111
  | `reprompt agent` | Agent workflow analysis -- error loops, tool patterns, session efficiency |
112
112
  | `reprompt sessions` | Session quality scores with frustration signal detection |
113
113
  | `reprompt repetition` | Cross-session repetition detection -- spot recurring prompts |
114
+ | `reprompt projects` | Per-project quality breakdown -- sessions, scores, frustration signals |
114
115
 
115
116
  ### Optimize
116
117
 
@@ -200,7 +201,7 @@ reprompt install-hook # adds post-session hook to Claude Code
200
201
 
201
202
  ### Browser extension
202
203
 
203
- Capture prompts from ChatGPT, Claude.ai, and Gemini directly in your browser:
204
+ Capture prompts from ChatGPT, Claude.ai, and Gemini directly in your browser. Live score badge shows prompt quality as you type.
204
205
 
205
206
  1. **Install the extension** from [Chrome Web Store](https://chromewebstore.google.com/detail/reprompt/ojdccpagaanchmkninlbgbgemdcjckhn) or [Firefox Add-ons](https://addons.mozilla.org/addon/reprompt-cli/)
206
207
  2. **Connect to the CLI:** `reprompt install-extension`
@@ -227,7 +228,7 @@ Captured prompts sync locally via Native Messaging -- nothing leaves your machin
227
228
  # .pre-commit-config.yaml
228
229
  repos:
229
230
  - repo: https://github.com/reprompt-dev/reprompt
230
- rev: v1.7.0
231
+ rev: v2.0.1
231
232
  hooks:
232
233
  - id: reprompt-lint
233
234
  ```
@@ -66,6 +66,7 @@ $ reprompt
66
66
  | `reprompt agent` | Agent workflow analysis -- error loops, tool patterns, session efficiency |
67
67
  | `reprompt sessions` | Session quality scores with frustration signal detection |
68
68
  | `reprompt repetition` | Cross-session repetition detection -- spot recurring prompts |
69
+ | `reprompt projects` | Per-project quality breakdown -- sessions, scores, frustration signals |
69
70
 
70
71
  ### Optimize
71
72
 
@@ -155,7 +156,7 @@ reprompt install-hook # adds post-session hook to Claude Code
155
156
 
156
157
  ### Browser extension
157
158
 
158
- Capture prompts from ChatGPT, Claude.ai, and Gemini directly in your browser:
159
+ Capture prompts from ChatGPT, Claude.ai, and Gemini directly in your browser. Live score badge shows prompt quality as you type.
159
160
 
160
161
  1. **Install the extension** from [Chrome Web Store](https://chromewebstore.google.com/detail/reprompt/ojdccpagaanchmkninlbgbgemdcjckhn) or [Firefox Add-ons](https://addons.mozilla.org/addon/reprompt-cli/)
161
162
  2. **Connect to the CLI:** `reprompt install-extension`
@@ -182,7 +183,7 @@ Captured prompts sync locally via Native Messaging -- nothing leaves your machin
182
183
  # .pre-commit-config.yaml
183
184
  repos:
184
185
  - repo: https://github.com/reprompt-dev/reprompt
185
- rev: v1.7.0
186
+ rev: v2.0.1
186
187
  hooks:
187
188
  - id: reprompt-lint
188
189
  ```
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "reprompt-cli"
3
- version = "2.0.1"
3
+ version = "2.0.2"
4
4
  description = "Discover, analyze, and optimize your prompts from AI coding sessions"
5
5
  readme = "README.md"
6
6
  license = { text = "MIT" }
@@ -1,6 +1,6 @@
1
1
  """reprompt — Discover, analyze, and evolve your best prompts from AI coding sessions."""
2
2
 
3
- __version__ = "2.0.1"
3
+ __version__ = "2.0.2"
4
4
 
5
5
  __all__ = [
6
6
  "__version__",
@@ -19,11 +19,11 @@ def _grade(total: float) -> str:
19
19
  """Map 0-100 score to letter grade."""
20
20
  if total >= 85:
21
21
  return "A"
22
- if total >= 70:
22
+ if total >= 60:
23
23
  return "B"
24
- if total >= 55:
25
- return "C"
26
24
  if total >= 40:
25
+ return "C"
26
+ if total >= 25:
27
27
  return "D"
28
28
  return "F"
29
29
 
@@ -982,9 +982,18 @@ def score(
982
982
  "paper": s.paper,
983
983
  "message": s.message,
984
984
  "impact": s.impact,
985
+ "points": s.points,
985
986
  }
986
987
  for s in breakdown.suggestions
987
988
  ],
989
+ "confirmations": [
990
+ {
991
+ "category": c.category,
992
+ "message": c.message,
993
+ "score": c.score,
994
+ }
995
+ for c in breakdown.confirmations
996
+ ],
988
997
  }
989
998
  typer.echo(json_mod.dumps(data, indent=2))
990
999
  else:
@@ -1004,9 +1013,18 @@ def score(
1004
1013
  "paper": s.paper,
1005
1014
  "message": s.message,
1006
1015
  "impact": s.impact,
1016
+ "points": s.points,
1007
1017
  }
1008
1018
  for s in breakdown.suggestions
1009
1019
  ],
1020
+ "confirmations": [
1021
+ {
1022
+ "category": c.category,
1023
+ "message": c.message,
1024
+ "score": c.score,
1025
+ }
1026
+ for c in breakdown.confirmations
1027
+ ],
1010
1028
  }
1011
1029
  typer.echo(render_score(data))
1012
1030
  from reprompt.core.suggestions import get_suggestion
@@ -2,13 +2,18 @@
2
2
  """Weighted prompt scoring engine with research-calibrated weights.
3
3
 
4
4
  Scores a PromptDNA feature vector on a 0-100 scale across five categories:
5
- 1. Structure (0-25): role, constraints, examples, output format
5
+ 1. Clarity (0-25): low ambiguity, good opening, reasonable length
6
6
  2. Context (0-25): code blocks, file refs, error messages, specificity
7
7
  3. Position (0-20): instruction placement (Lost in the Middle)
8
- 4. Repetition (0-15): keyword reinforcement (Google Research)
9
- 5. Clarity (0-15): low ambiguity, good opening, reasonable length
8
+ 4. Structure (0-15): role, constraints, examples, output format
9
+ 5. Repetition (0-15): keyword reinforcement (Google Research)
10
10
 
11
- Each weight is derived from published research findings:
11
+ Weight rationale: clarity and context are what normal developers can
12
+ improve immediately; structure and repetition are advanced techniques
13
+ that provide additional lift. This ensures a clear, specific prompt
14
+ scores 55-65 without requiring markdown or role definitions.
15
+
16
+ Research references:
12
17
  - Position weights from the U-curve in arXiv:2307.03172 (30% degradation)
13
18
  - Repetition weights from arXiv:2512.14982 (up to 76% improvement)
14
19
  - Specificity weights from DETAIL arXiv:2512.02246
@@ -53,6 +58,16 @@ class Suggestion:
53
58
  paper: str # short citation
54
59
  message: str
55
60
  impact: str # "high", "medium", "low"
61
+ points: int = 0 # expected score gain if applied
62
+
63
+
64
+ @dataclass
65
+ class Confirmation:
66
+ """Positive feedback for a detected feature."""
67
+
68
+ category: str
69
+ message: str
70
+ score: str # e.g. "20/20"
56
71
 
57
72
 
58
73
  @dataclass
@@ -62,13 +77,14 @@ class ScoreBreakdown:
62
77
  total: float = 0.0
63
78
 
64
79
  # Category scores (each out of their max)
65
- structure: float = 0.0 # max 25
80
+ structure: float = 0.0 # max 15
66
81
  context: float = 0.0 # max 25
67
82
  position: float = 0.0 # max 20
68
83
  repetition: float = 0.0 # max 15
69
- clarity: float = 0.0 # max 15
84
+ clarity: float = 0.0 # max 25
70
85
 
71
86
  suggestions: list[Suggestion] = field(default_factory=list)
87
+ confirmations: list[Confirmation] = field(default_factory=list)
72
88
 
73
89
 
74
90
  def score_prompt(dna: PromptDNA) -> ScoreBreakdown:
@@ -78,22 +94,23 @@ def score_prompt(dna: PromptDNA) -> ScoreBreakdown:
78
94
  """
79
95
  suggestions: list[Suggestion] = []
80
96
 
81
- # ── Structure (0-25) ──
97
+ # ── Structure (0-15) ──
82
98
  structure = 0.0
83
99
  if dna.has_role_definition:
84
- structure += 5.0
100
+ structure += 3.0
85
101
  else:
86
102
  suggestions.append(
87
103
  Suggestion(
88
104
  "structure",
89
105
  "Prompt Report",
90
106
  'Add a role definition (e.g., "You are a senior Python developer")',
91
- "medium",
107
+ "low",
108
+ points=3,
92
109
  )
93
110
  )
94
111
 
95
112
  if dna.has_constraints:
96
- structure += 4.0 + min(dna.constraint_count, 3) * 1.0
113
+ structure += 3.0 + min(dna.constraint_count, 2) * 1.0
97
114
  else:
98
115
  suggestions.append(
99
116
  Suggestion(
@@ -101,20 +118,21 @@ def score_prompt(dna: PromptDNA) -> ScoreBreakdown:
101
118
  "Prompt Report",
102
119
  'Add constraints (e.g., "Do not modify tests", "Must be backward-compatible")',
103
120
  "medium",
121
+ points=5,
104
122
  )
105
123
  )
106
124
 
107
125
  if dna.has_examples:
108
- structure += 4.0 + min(dna.example_count, 2) * 1.0
126
+ structure += 2.0 + min(dna.example_count, 1) * 1.0
109
127
 
110
128
  if dna.has_output_format:
111
- structure += 3.0
129
+ structure += 2.0
112
130
 
113
131
  if dna.has_step_by_step:
114
- structure += 2.0
132
+ structure += 1.0
115
133
 
116
- structure += min(dna.section_count, 3) * 1.0
117
- structure = min(structure, 25.0)
134
+ structure += min(dna.section_count, 2) * 1.0
135
+ structure = min(structure, 15.0)
118
136
 
119
137
  # ── Context (0-25) ──
120
138
  context = 0.0
@@ -130,6 +148,7 @@ def score_prompt(dna: PromptDNA) -> ScoreBreakdown:
130
148
  "DETAIL arXiv:2512.02246",
131
149
  "Add file path references — specificity improves output quality significantly",
132
150
  "high",
151
+ points=6,
133
152
  )
134
153
  )
135
154
 
@@ -142,6 +161,7 @@ def score_prompt(dna: PromptDNA) -> ScoreBreakdown:
142
161
  "DETAIL arXiv:2512.02246",
143
162
  "Include the actual error message — debug prompts with errors are 3.7x more effective", # noqa: E501
144
163
  "high",
164
+ points=6,
145
165
  )
146
166
  )
147
167
 
@@ -157,9 +177,9 @@ def score_prompt(dna: PromptDNA) -> ScoreBreakdown:
157
177
  Suggestion(
158
178
  "position",
159
179
  "Lost in the Middle arXiv:2307.03172",
160
- "Your key instruction is buried in the middle "
161
- "move it to the start or end for better attention (30% degradation in middle)",
180
+ "Move your key instruction to the start or end (30% degradation in middle)",
162
181
  "high",
182
+ points=10,
163
183
  )
164
184
  )
165
185
 
@@ -175,48 +195,78 @@ def score_prompt(dna: PromptDNA) -> ScoreBreakdown:
175
195
  Suggestion(
176
196
  "repetition",
177
197
  "Google Research arXiv:2512.14982",
178
- "Repeating your core requirement at the end of the prompt "
179
- "can improve accuracy by up to 76%",
198
+ "Repeat your core requirement at the end can improve accuracy up to 76%",
180
199
  "medium",
200
+ points=8,
181
201
  )
182
202
  )
183
203
 
184
- # ── Clarity (0-15) ──
204
+ # ── Clarity (0-25) ──
185
205
  clarity = 0.0
186
206
 
187
207
  # Opening quality
188
- clarity += 5.0 * min(dna.opening_quality, 1.0)
208
+ clarity += 9.0 * min(dna.opening_quality, 1.0)
189
209
 
190
210
  # Low ambiguity
191
- clarity += 5.0 * max(0.0, 1.0 - dna.ambiguity_score)
211
+ clarity += 8.0 * max(0.0, 1.0 - dna.ambiguity_score)
192
212
  if dna.ambiguity_score > 0.5:
193
213
  suggestions.append(
194
214
  Suggestion(
195
215
  "clarity",
196
216
  "DETAIL arXiv:2512.02246",
197
- "Prompt is vague — replace pronouns ('it', 'this') with specific names",
217
+ "Replace pronouns ('it', 'this') with specific names",
198
218
  "high",
219
+ points=4,
199
220
  )
200
221
  )
201
222
 
202
223
  # Reasonable length (not too short)
203
224
  if dna.word_count >= 20:
204
- clarity += 5.0
225
+ clarity += 8.0
205
226
  elif dna.word_count >= 10:
206
- clarity += 3.0
227
+ clarity += 5.0
207
228
  elif dna.word_count >= 5:
208
- clarity += 1.0
229
+ clarity += 2.0
209
230
  else:
210
231
  suggestions.append(
211
232
  Suggestion(
212
233
  "clarity",
213
234
  "DETAIL arXiv:2512.02246",
214
- "Prompt is very short — add context about what, where, and why",
235
+ "Add more context about what, where, and why",
215
236
  "high",
237
+ points=6,
216
238
  )
217
239
  )
218
240
 
219
- clarity = min(clarity, 15.0)
241
+ clarity = min(clarity, 25.0)
242
+
243
+ # ── Positive confirmations ──
244
+ confirmations: list[Confirmation] = []
245
+ if pos_score >= 0.8:
246
+ confirmations.append(
247
+ Confirmation("position", "Key instruction at the start — optimal placement",
248
+ f"{round(position)}/20")
249
+ )
250
+ if dna.has_file_references:
251
+ confirmations.append(
252
+ Confirmation("context", "File references detected — specificity matters",
253
+ f"{round(min(context, 25))}/25")
254
+ )
255
+ if dna.has_error_messages:
256
+ confirmations.append(
257
+ Confirmation("context", "Error context included — 3.7x more effective",
258
+ f"{round(min(context, 25))}/25")
259
+ )
260
+ if dna.has_constraints:
261
+ confirmations.append(
262
+ Confirmation("structure", "Constraints defined — clear boundaries set",
263
+ f"{round(structure)}/15")
264
+ )
265
+ if dna.opening_quality >= 0.4:
266
+ confirmations.append(
267
+ Confirmation("clarity", "Strong opening — starts with clear intent",
268
+ f"{round(clarity)}/25")
269
+ )
220
270
 
221
271
  # ── Total ──
222
272
  total = structure + context + position + repetition + clarity
@@ -230,4 +280,5 @@ def score_prompt(dna: PromptDNA) -> ScoreBreakdown:
230
280
  repetition=round(repetition, 1),
231
281
  clarity=round(clarity, 1),
232
282
  suggestions=suggestions,
283
+ confirmations=confirmations,
233
284
  )
@@ -60,10 +60,10 @@ def render_rewrite(result: RewriteResult) -> str:
60
60
  def _score_color(score: float) -> str:
61
61
  if score >= 85:
62
62
  return "bold magenta"
63
- if score >= 70:
63
+ if score >= 60:
64
64
  return "bold green"
65
- if score >= 55:
66
- return "bold yellow"
67
65
  if score >= 40:
66
+ return "bold yellow"
67
+ if score >= 25:
68
68
  return "yellow"
69
69
  return "bold red"
@@ -325,19 +325,32 @@ def render_score(breakdown: dict[str, Any]) -> str:
325
325
  console = Console(file=buf, force_terminal=True, width=80)
326
326
 
327
327
  total = breakdown["total"]
328
- grade = (
329
- "Excellent"
330
- if total >= 80
331
- else "Good"
332
- if total >= 60
333
- else "Fair"
334
- if total >= 40
335
- else "Poor"
336
- if total >= 20
337
- else "Very Poor"
328
+ tier = (
329
+ "EXPERT"
330
+ if total >= 85
331
+ else "STRONG"
332
+ if total >= 70
333
+ else "GOOD"
334
+ if total >= 50
335
+ else "BASIC"
336
+ if total >= 30
337
+ else "DRAFT"
338
+ )
339
+ tier_color = (
340
+ "bold magenta"
341
+ if total >= 85
342
+ else "bold green"
343
+ if total >= 70
344
+ else "bold cyan"
345
+ if total >= 50
346
+ else "bold yellow"
347
+ if total >= 30
348
+ else "dim"
338
349
  )
339
350
 
340
- console.print(f"\n[bold]Prompt DNA Score: {total:.0f}/100[/bold] ({grade})")
351
+ console.print(
352
+ f"\n[bold]Score: {total:.0f}/100[/bold] [{tier_color}]{tier}[/{tier_color}]"
353
+ )
341
354
  cost_info = breakdown.get("estimated_cost")
342
355
  if cost_info:
343
356
  console.print(
@@ -348,11 +361,11 @@ def render_score(breakdown: dict[str, Any]) -> str:
348
361
 
349
362
  # Category bars
350
363
  categories = [
351
- ("Structure", breakdown["structure"], 25),
364
+ ("Clarity", breakdown["clarity"], 25),
352
365
  ("Context", breakdown["context"], 25),
353
366
  ("Position", breakdown["position"], 20),
367
+ ("Structure", breakdown["structure"], 15),
354
368
  ("Repetition", breakdown["repetition"], 15),
355
- ("Clarity", breakdown["clarity"], 15),
356
369
  ]
357
370
  for name, cat_score, max_val in categories:
358
371
  pct = cat_score / max_val if max_val > 0 else 0
@@ -360,6 +373,13 @@ def render_score(breakdown: dict[str, Any]) -> str:
360
373
  bar = "\u2588" * filled + "\u2591" * (10 - filled)
361
374
  console.print(f" {name:<12} {bar} {cat_score:.0f}/{max_val}")
362
375
 
376
+ # Positive confirmations (what's already good)
377
+ confirmations = breakdown.get("confirmations", [])
378
+ if confirmations:
379
+ console.print(f"\n[bold green]Strengths ({len(confirmations)}):[/bold green]")
380
+ for c in confirmations:
381
+ console.print(f" [green]\u2713[/green] {c['message']} [dim]({c['score']})[/dim]")
382
+
363
383
  # Suggestions (sorted by impact: high → medium → low)
364
384
  suggestions = breakdown.get("suggestions", [])
365
385
  if suggestions:
@@ -368,8 +388,10 @@ def render_score(breakdown: dict[str, Any]) -> str:
368
388
  console.print(f"\n[bold]Suggestions ({len(suggestions)}):[/bold]")
369
389
  for s in suggestions:
370
390
  impact_color = {"high": "red", "medium": "yellow", "low": "dim"}.get(s["impact"], "dim")
391
+ pts = f" [bold](+{s['points']} pts)[/bold]" if s.get("points") else ""
371
392
  console.print(
372
- f" [{impact_color}]\u25a0[/{impact_color}] [dim][{s['paper']}][/dim] {s['message']}"
393
+ f" [{impact_color}]\u25a0[/{impact_color}] {s['message']}{pts}"
394
+ f" [dim]{s['paper']}[/dim]"
373
395
  )
374
396
 
375
397
  return buf.getvalue()
@@ -24,11 +24,11 @@ def _score_color(score: float) -> str:
24
24
  """Return a hex color based on the overall score percentage."""
25
25
  if score >= 85:
26
26
  return "#7C4DFF"
27
- if score >= 70:
27
+ if score >= 60:
28
28
  return "#00C853"
29
- if score >= 50:
29
+ if score >= 40:
30
30
  return "#FFD700"
31
- if score >= 30:
31
+ if score >= 25:
32
32
  return "#FF8C00"
33
33
  return "#FF4444"
34
34
 
@@ -21,8 +21,8 @@ def test_version():
21
21
  result = runner.invoke(app, ["--version"])
22
22
  assert result.exit_code == 0
23
23
  assert "reprompt" in result.output
24
- # Check version format (e.g. "reprompt 1.0.0")
25
- assert "reprompt 1." in result.output
24
+ # Check version format (e.g. "reprompt 2.0.1")
25
+ assert "reprompt " in result.output
26
26
 
27
27
 
28
28
  def test_status_empty(tmp_path, monkeypatch):
@@ -29,26 +29,26 @@ class TestGradeFunction:
29
29
  def test_grade_b(self):
30
30
  from reprompt import _grade
31
31
 
32
- assert _grade(70) == "B"
32
+ assert _grade(60) == "B"
33
33
  assert _grade(84) == "B"
34
34
 
35
35
  def test_grade_c(self):
36
36
  from reprompt import _grade
37
37
 
38
- assert _grade(55) == "C"
39
- assert _grade(69) == "C"
38
+ assert _grade(40) == "C"
39
+ assert _grade(59) == "C"
40
40
 
41
41
  def test_grade_d(self):
42
42
  from reprompt import _grade
43
43
 
44
- assert _grade(40) == "D"
45
- assert _grade(54) == "D"
44
+ assert _grade(25) == "D"
45
+ assert _grade(39) == "D"
46
46
 
47
47
  def test_grade_f(self):
48
48
  from reprompt import _grade
49
49
 
50
50
  assert _grade(0) == "F"
51
- assert _grade(39) == "F"
51
+ assert _grade(24) == "F"
52
52
 
53
53
 
54
54
  class TestLazyImports:
@@ -2210,7 +2210,7 @@ wheels = [
2210
2210
 
2211
2211
  [[package]]
2212
2212
  name = "reprompt-cli"
2213
- version = "2.0.0"
2213
+ version = "2.0.2"
2214
2214
  source = { editable = "." }
2215
2215
  dependencies = [
2216
2216
  { name = "pydantic-settings" },
File without changes
File without changes
File without changes