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.
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/CHANGELOG.md +77 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/PKG-INFO +4 -3
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/README.md +3 -2
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/pyproject.toml +1 -1
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/__init__.py +4 -4
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/cli.py +18 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/scorer.py +79 -28
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/rewrite_terminal.py +3 -3
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/terminal.py +36 -14
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/wrapped_html.py +3 -3
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cli.py +2 -2
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_coverage_boost.py +6 -6
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/uv.lock +1 -1
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.editorconfig +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/dependabot.yml +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/workflows/ci.yml +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.github/workflows/publish.yml +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.gitignore +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.pre-commit-config.yaml +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.pre-commit-hooks.yaml +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.testmondata-shm +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/.testmondata-wal +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/CODE_OF_CONDUCT.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/CONTRIBUTING.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/LICENSE +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/SECURITY.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/Screenshot 2026-03-24 at 09.45.03.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/action.yml +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/demo.gif +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-128.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-16.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-256.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-32.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-48.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-512.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon-96.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/brand-icon.svg +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-128.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-16.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-256.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-32.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-48.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-512.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon-96.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-favicon.svg +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-128.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-16.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-256.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-32.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-48.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-512.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon-96.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/cli-icon.svg +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-128.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-16.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-256.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-32.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-48.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-512.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon-96.png +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/favicon.svg +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/icons/generate.sh +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/superpowers/specs/2026-03-24-v14-command-consolidation-design.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/docs/superpowers/specs/2026-03-25-v1.5-dashboard-design.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/scripts/generate_demo_data.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/aider.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/base.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/chatgpt.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/claude_chat.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/claude_code.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/cline.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/codex.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/cursor.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/filters.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/gemini.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/adapters/openclaw.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/handler.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/host.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/manifest.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/bridge/protocol.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/commands/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/commands/telemetry.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/commands/wrapped.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/config.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/agent.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/analyzer.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/compress.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/conversation.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/cost.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/dashboard.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/dedup.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/digest.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/distill.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/effectiveness.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/extractors.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/extractors_zh.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/insights.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/lang_detect.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/library.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/lint.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/merge_view.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/models.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/persona.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/pipeline.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/privacy.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/privacy_scan.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/prompt_dna.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/recommend.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/repetition.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/rewrite.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/segmenter.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/session_meta.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/session_quality.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/session_type.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/style.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/suggestions.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/templates.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/timeutil.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/trends.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/core/wrapped.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/demo.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/base.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/local_embed.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/ollama.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/openai_embed.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/embeddings/tfidf.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/mcp.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/mcp_main.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/agent_terminal.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/chartjs.min.js +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/compress_terminal.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/dashboard_terminal.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/distill_terminal.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/export.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/html_report.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/json_out.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/markdown.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/projects_terminal.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/repetition_terminal.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/sessions_terminal.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/output/wrapped_terminal.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/py.typed +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/sharing/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/sharing/client.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/sharing/clipboard.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/storage/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/storage/db.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/collector.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/consent.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/events.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/prompt.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/queue.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/src/reprompt/telemetry/sender.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/__init__.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/conftest.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/aider_chat_history.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/chatgpt_conversations.json +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/claude_chat_export.json +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/claude_session.jsonl +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/cline_task/api_conversation_history.json +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/export/default_export.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/export/full_export.md +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/gemini_session.json +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/fixtures/openclaw_session.jsonl +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_aider.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_chatgpt.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_claude.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_claude_chat.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_cline.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_gemini.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_adapter_openclaw.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_agent.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_agent_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_analyzer.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_e2e.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_handler.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_integration.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_manifest.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_bridge_protocol.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cli_deprecations.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cli_library_effectiveness.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_clipboard.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_codex_adapter.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compare_best_worst.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress_dna.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress_html.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_compress_insights.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_config.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_conversation.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_copy_flag.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cost.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_cursor_adapter.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_dashboard.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db_digest.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db_effectiveness.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db_session_quality.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_db_trends.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_dedup.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_demo.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_deprecated_commands.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_digest.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_digest_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_distill.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_distill_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_distill_weights.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_e2e.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_effectiveness.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_embeddings_local.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_embeddings_ollama.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_embeddings_openai.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_empty_state.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_export.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_export_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_export_snapshot.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_extractors.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_extractors_routing.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_extractors_zh.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_extractors_zh_e2e.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_html_report.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_import_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_import_e2e.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_init_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_insights.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_insights_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_insights_expanded.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_install_hook.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_lang_detect.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_library.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_lint.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_lint_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_markdown.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_mcp.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_merge_view.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_models.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_output.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_parse_conversation_base.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_parse_conversation_chatgpt.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_parse_conversation_claude.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_persona.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_pipeline.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy_e2e.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy_output.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_privacy_scan.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_projects.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_prompt_dna.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_public_api.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_recommend.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_repetition.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_repetition_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_repetition_output.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_rewrite.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_schema_version.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_score_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_scorer.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_segmenter.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_session_quality.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_session_type.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_sessions_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_sessions_output.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_share_e2e.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_sharing_client.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_source_filter.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_style.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_style_trends.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_suggestions.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_collector.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_consent.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_e2e.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_events.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_prompt.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_queue.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_telemetry_sender.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_template_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_templates.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_timeutil.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_trends.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_trends_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_use_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_cli.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_e2e.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_html.py +0 -0
- {reprompt_cli-2.0.1 → reprompt_cli-2.0.2}/tests/test_wrapped_output.py +0 -0
- {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.
|
|
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:
|
|
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:
|
|
186
|
+
rev: v2.0.1
|
|
186
187
|
hooks:
|
|
187
188
|
- id: reprompt-lint
|
|
188
189
|
```
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""reprompt — Discover, analyze, and evolve your best prompts from AI coding sessions."""
|
|
2
2
|
|
|
3
|
-
__version__ = "2.0.
|
|
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 >=
|
|
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.
|
|
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.
|
|
9
|
-
5.
|
|
8
|
+
4. Structure (0-15): role, constraints, examples, output format
|
|
9
|
+
5. Repetition (0-15): keyword reinforcement (Google Research)
|
|
10
10
|
|
|
11
|
-
|
|
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
|
|
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
|
|
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-
|
|
97
|
+
# ── Structure (0-15) ──
|
|
82
98
|
structure = 0.0
|
|
83
99
|
if dna.has_role_definition:
|
|
84
|
-
structure +=
|
|
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
|
-
"
|
|
107
|
+
"low",
|
|
108
|
+
points=3,
|
|
92
109
|
)
|
|
93
110
|
)
|
|
94
111
|
|
|
95
112
|
if dna.has_constraints:
|
|
96
|
-
structure +=
|
|
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 +=
|
|
126
|
+
structure += 2.0 + min(dna.example_count, 1) * 1.0
|
|
109
127
|
|
|
110
128
|
if dna.has_output_format:
|
|
111
|
-
structure +=
|
|
129
|
+
structure += 2.0
|
|
112
130
|
|
|
113
131
|
if dna.has_step_by_step:
|
|
114
|
-
structure +=
|
|
132
|
+
structure += 1.0
|
|
115
133
|
|
|
116
|
-
structure += min(dna.section_count,
|
|
117
|
-
structure = min(structure,
|
|
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
|
-
"
|
|
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
|
-
"
|
|
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-
|
|
204
|
+
# ── Clarity (0-25) ──
|
|
185
205
|
clarity = 0.0
|
|
186
206
|
|
|
187
207
|
# Opening quality
|
|
188
|
-
clarity +=
|
|
208
|
+
clarity += 9.0 * min(dna.opening_quality, 1.0)
|
|
189
209
|
|
|
190
210
|
# Low ambiguity
|
|
191
|
-
clarity +=
|
|
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
|
-
"
|
|
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 +=
|
|
225
|
+
clarity += 8.0
|
|
205
226
|
elif dna.word_count >= 10:
|
|
206
|
-
clarity +=
|
|
227
|
+
clarity += 5.0
|
|
207
228
|
elif dna.word_count >= 5:
|
|
208
|
-
clarity +=
|
|
229
|
+
clarity += 2.0
|
|
209
230
|
else:
|
|
210
231
|
suggestions.append(
|
|
211
232
|
Suggestion(
|
|
212
233
|
"clarity",
|
|
213
234
|
"DETAIL arXiv:2512.02246",
|
|
214
|
-
"
|
|
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,
|
|
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 >=
|
|
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
|
-
|
|
329
|
-
"
|
|
330
|
-
if total >=
|
|
331
|
-
else "
|
|
332
|
-
if total >=
|
|
333
|
-
else "
|
|
334
|
-
if total >=
|
|
335
|
-
else "
|
|
336
|
-
if total >=
|
|
337
|
-
else "
|
|
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(
|
|
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
|
-
("
|
|
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}]
|
|
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 >=
|
|
27
|
+
if score >= 60:
|
|
28
28
|
return "#00C853"
|
|
29
|
-
if score >=
|
|
29
|
+
if score >= 40:
|
|
30
30
|
return "#FFD700"
|
|
31
|
-
if score >=
|
|
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
|
|
25
|
-
assert "reprompt
|
|
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(
|
|
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(
|
|
39
|
-
assert _grade(
|
|
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(
|
|
45
|
-
assert _grade(
|
|
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(
|
|
51
|
+
assert _grade(24) == "F"
|
|
52
52
|
|
|
53
53
|
|
|
54
54
|
class TestLazyImports:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|