From a54caf974a1e0cf007b4e58bcb4b5366ff1e78bf Mon Sep 17 00:00:00 2001 From: Kalpesh1Sharma Date: Thu, 20 Aug 2026 23:49:59 +0530 Subject: [PATCH] Add evidence-first resume bullet rewriter --- .../.env.example | 1 + .../.gitignore | 6 + .../README.md | 359 +++++ .../impact-quantifying-bullet-rewriter/app.py | 1164 +++++++++++++++++ .../assets/evidence_first_review.png | Bin 0 -> 90415 bytes .../core/__init__.py | 0 .../core/evidence.py | 107 ++ .../core/models.py | 44 + .../core/rewriter.py | 267 ++++ .../requirements.txt | 5 + .../generate_sample_resume.py | 52 + .../sample_documents/sample_resume.docx | Bin 0 -> 35587 bytes .../superdocs/__init__.py | 0 .../superdocs/client.py | 278 ++++ .../superdocs/parser.py | 102 ++ .../superdocs/polling.py | 74 ++ .../tests/test_evidence.py | 66 + .../tests/test_rewriter.py | 99 ++ .../tests/test_superdocs_parser.py | 101 ++ 19 files changed, 2725 insertions(+) create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/.env.example create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/.gitignore create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/README.md create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/app.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/assets/evidence_first_review.png create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/__init__.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/evidence.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/models.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/rewriter.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/requirements.txt create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/sample_documents/generate_sample_resume.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/sample_documents/sample_resume.docx create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/__init__.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/client.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/parser.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/polling.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_evidence.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_rewriter.py create mode 100644 use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_superdocs_parser.py diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/.env.example b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/.env.example new file mode 100644 index 00000000..43c1b6f4 --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/.env.example @@ -0,0 +1 @@ +SUPERDOCS_API_KEY=your_superdocs_api_key_here diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/.gitignore b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/.gitignore new file mode 100644 index 00000000..c4720b1c --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/.gitignore @@ -0,0 +1,6 @@ +.env +.venv/ +__pycache__/ +*.pyc +.pytest_cache/ +outputs/* \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/README.md b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/README.md new file mode 100644 index 00000000..cbb6bbca --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/README.md @@ -0,0 +1,359 @@ +# Evidence-First Resume Bullet Rewriter + +Built by **Kalpesh Sharma** for the **SuperDocs Engineer Task**. + +An evidence-first resume editing workflow that strengthens resume bullets without inventing metrics, responsibilities, technologies, or experience. + +The core rule is simple: + +> If measurable impact is missing, ask for it instead of making it up. + +![Evidence-First Resume Bullet Rewriter](assets/evidence_first_review.png) + +## What it does + +The app takes a resume bullet and checks whether the information needed for a stronger outcome-oriented statement is actually supported. + +It can: + +- detect explicit quantitative evidence already present in a bullet +- preserve existing metrics +- ask the user for measurable impact when none is available +- reject unsupported claims such as fabricated leadership experience +- generate a conservative rewrite using only supplied evidence +- upload the source resume to SuperDocs +- show the proposed document edit before applying it +- require explicit human approval or rejection +- export the reviewed DOCX after approval + +## Example + +### Source + +```text +Automated invoice processing using Python. +``` + +The source contains no measurable result, so the app does **not** invent one. + +Instead it asks for evidence such as: + +```text +Reduced processing time from 3 hours to 45 minutes. +``` + +The resulting proposal becomes: + +```text +Automated invoice processing using Python, reducing processing time from 3 hours to 45 minutes. +``` + +The values `3 hours` and `45 minutes` came directly from the user. + +## Unsupported-claim protection + +If the source says: + +```text +Built Power BI dashboards for operational reporting. +``` + +and the user requests: + +```text +Make this say I led a five-person analytics team. +``` + +the request is rejected because the source contains no evidence of leadership responsibility. + +The app does not silently add the claim. + +## Workflow + +```text +Resume bullet + ↓ +Evidence detection + ↓ +Is measurable impact available? + │ + ├── No → ask the user + │ + └── Yes + ↓ +Supported-claim validation + ↓ +Evidence-grounded rewrite + ↓ +Upload source DOCX to SuperDocs + ↓ +SuperDocs proposed edit + ↓ +Human review + ↙ ↘ + Reject Approve + ↓ + Reviewed DOCX + ↓ + Export +``` + +## SuperDocs integration + +SuperDocs is used for the actual document-editing workflow. + +The app: + +1. uploads the resume DOCX into a SuperDocs session +2. sends a surgical edit instruction containing the exact source and replacement bullet +3. starts an asynchronous review with `ask_every_time` +4. polls until the job reaches an actionable state +5. parses the proposed changes +6. displays the before/after diff +7. sends the human approval or rejection decision +8. exports the reviewed DOCX + +The edit instruction explicitly tells SuperDocs not to modify unrelated resume content or introduce new claims. + +## Human review + +Nothing is applied automatically. + +The user sees the proposed SuperDocs change first and can choose: + +- **Approve proposed change** +- **Reject proposed change** + +Only an approved edit is allowed to become part of the reviewed document. + +## Graceful re-entry + +SuperDocs review jobs can take time. + +If a review has already reached `awaiting_approval`, the app reuses that existing job instead of starting another review request. + +This avoids unnecessary duplicate operations and makes the workflow safe to resume. + +## Pending-change parsing + +SuperDocs may return proposed changes as either: + +- a list +- a JSON-encoded string + +and current review jobs expose them through job metadata. + +The parser handles these forms explicitly and fails loudly if malformed content is returned instead of silently treating it as an empty successful diff. + +## Proof cases + +### Case 1 — missing metric + +Source: + +```text +Automated invoice processing using Python. +``` + +Result: + +```text +More evidence needed +``` + +No metric is invented. + +After the user provides: + +```text +Reduced processing time from 3 hours to 45 minutes. +``` + +the values are used in the proposed rewrite. + +### Case 2 — metric already exists + +Source: + +```text +Processed 500 invoices per month using Python. +``` + +Result: + +```text +Ready for review +``` + +`500 invoices` is preserved exactly. + +### Case 3 — unsupported experience + +Source: + +```text +Built Power BI dashboards for operational reporting. +``` + +Requested claim: + +```text +Make this say I led a five-person analytics team. +``` + +Result: + +```text +Unsupported request +``` + +No leadership claim is added. + +## Verified SuperDocs flow + +The complete workflow was tested with a synthetic resume. + +```text +Evidence detection PASS +Missing-metric gate PASS +Unsupported-claim gate PASS +SuperDocs upload PASS +Proposed edit PASS +Human approval PASS +Approved edit persisted PASS +DOCX export PASS +Unrelated bullets preserved PASS +``` + +The final exported resume changed only: + +```text +Automated invoice processing using Python. +``` + +to: + +```text +Automated invoice processing using Python, reducing processing time from 3 hours to 45 minutes. +``` + +The remaining resume bullets were unchanged. + +## Project structure + +```text +impact-quantifying-bullet-rewriter/ +│ +├── app.py +├── README.md +├── requirements.txt +├── .env.example +├── .gitignore +│ +├── assets/ +│ └── evidence_first_review.png +│ +├── core/ +│ ├── __init__.py +│ ├── evidence.py +│ ├── models.py +│ └── rewriter.py +│ +├── sample_documents/ +│ ├── generate_sample_resume.py +│ └── sample_resume.docx +│ +├── superdocs/ +│ ├── __init__.py +│ ├── client.py +│ ├── parser.py +│ └── polling.py +│ +└── tests/ + ├── test_evidence.py + ├── test_rewriter.py + └── test_superdocs_parser.py +``` + +## Setup + +Create a virtual environment if needed: + +```bash +python -m venv .venv +``` + +Activate it and install dependencies: + +```bash +pip install -r requirements.txt +``` + +Create a local `.env`: + +```text +SUPERDOCS_API_KEY=your_superdocs_api_key +``` + +Never commit the real `.env` file. + +## Generate the sample resume + +```bash +python sample_documents/generate_sample_resume.py +``` + +## Run tests + +```bash +python -m pytest -v +``` + +The test suite does not require a live SuperDocs API key. + +## Run the app + +```bash +streamlit run app.py +``` + +Then: + +1. analyse a resume bullet +2. provide missing evidence if requested +3. upload `sample_documents/sample_resume.docx` +4. open it in SuperDocs +5. start Review +6. inspect the proposed before/after change +7. approve or reject it +8. export the reviewed DOCX + +## Design principles + +### Evidence over invention + +A stronger-looking resume is not useful if its claims are false. + +Metrics are only used when they already exist in the source or are explicitly supplied by the user. + +### Surgical edits + +SuperDocs receives an exact source bullet and exact replacement bullet. + +The instruction explicitly prohibits unrelated edits. + +### Human accountability + +The system can propose a change. + +The human decides whether the document actually changes. + +### Graceful failure + +Missing evidence, unsupported claims, malformed pending changes, missing API configuration, failed jobs, and timeouts are surfaced rather than hidden. + +--- + +The goal of this build is not to make every resume bullet sound impressive. + +It is to make supported experience clearer **without crossing the line from rewriting into fabrication**. diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/app.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/app.py new file mode 100644 index 00000000..b44382a1 --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/app.py @@ -0,0 +1,1164 @@ +from __future__ import annotations + +import tempfile +import time +from pathlib import Path +from uuid import uuid4 + +import streamlit as st + +from core.rewriter import propose_rewrite +from superdocs.client import ( + SuperDocsClient, + SuperDocsError, +) +from superdocs.parser import ( + SuperDocsParseError, + pending_changes_from_job, +) +from superdocs.polling import ( + wait_until_action_needed, +) + + +st.set_page_config( + page_title="Evidence-First Resume Bullet Rewriter", + page_icon="📝", + layout="wide", +) + + +# ========================================================== +# STATE +# ========================================================== + + +def initialize_state() -> None: + defaults = { + "proposal": None, + "source_bullet": None, + "requested_claim": "", + "resume_session_id": None, + "resume_document_id": None, + "resume_filename": None, + "review_job_id": None, + "pending_changes": [], + "review_status": None, + "review_decision": None, + "reviewed_docx_bytes": None, + } + + for key, value in defaults.items(): + if key not in st.session_state: + st.session_state[key] = value + + +def reset_review_state() -> None: + st.session_state.review_job_id = None + st.session_state.pending_changes = [] + st.session_state.review_status = None + st.session_state.review_decision = None + st.session_state.reviewed_docx_bytes = None + + +initialize_state() + + +# ========================================================== +# SUPERDOCS HELPERS +# ========================================================== + + +def upload_resume_to_superdocs( + uploaded_file, +) -> None: + suffix = ( + Path(uploaded_file.name).suffix + or ".docx" + ) + + temp_path: Path | None = None + + try: + with tempfile.NamedTemporaryFile( + delete=False, + suffix=suffix, + ) as temp_file: + temp_file.write( + uploaded_file.getvalue() + ) + + temp_path = Path( + temp_file.name + ) + + client = SuperDocsClient() + + requested_session_id = ( + "resume-bullet-" + + uuid4().hex[:10] + ) + + upload = client.upload_document( + path=temp_path, + session_id=requested_session_id, + open_mode="replace", + ) + + st.session_state.resume_session_id = ( + upload.get("session_id") + or requested_session_id + ) + + st.session_state.resume_document_id = ( + upload.get("document_id") + ) + + st.session_state.resume_filename = ( + uploaded_file.name + ) + + reset_review_state() + + finally: + if temp_path is not None: + temp_path.unlink( + missing_ok=True + ) + + +def wait_until_completed( + *, + client: SuperDocsClient, + job_id: str, + timeout_seconds: int = 180, + poll_interval: float = 2.0, +) -> dict: + """ + Used after the human approval decision. + + Unlike wait_until_action_needed(), this keeps + polling past awaiting_approval until the job + actually completes. + """ + + started = time.monotonic() + + while True: + job = client.get_job( + job_id=job_id + ) + + status = job.get("status") + + if status == "completed": + return job + + if status == "failed": + raise SuperDocsError( + job.get( + "error", + "SuperDocs job failed.", + ) + ) + + if status == "cancelled": + raise SuperDocsError( + "SuperDocs job was cancelled." + ) + + elapsed = ( + time.monotonic() + - started + ) + + if elapsed >= timeout_seconds: + raise TimeoutError( + f"Job {job_id} did not complete " + f"within {timeout_seconds} seconds." + ) + + time.sleep( + poll_interval + ) + + +def build_review_instruction( + original: str, + proposed: str, +) -> str: + return f""" +Replace exactly this resume bullet: + +SOURCE BULLET: +{original} + +REPLACEMENT BULLET: +{proposed} + +Rules: +- Change only the source bullet shown above. +- Use the replacement wording exactly as supplied. +- Do not modify any other resume content. +- Do not add new metrics. +- Do not change existing metrics. +- Do not invent responsibilities. +- Do not invent leadership experience. +- Do not invent technologies. +- Do not make any other edits. +- If the exact source bullet cannot be found, do not substitute a different bullet. +""".strip() + + +def export_reviewed_resume() -> bytes: + session_id = ( + st.session_state.resume_session_id + ) + + if not session_id: + raise RuntimeError( + "No SuperDocs resume session exists." + ) + + source_name = ( + st.session_state.resume_filename + or "resume.docx" + ) + + output_name = ( + Path(source_name).stem + + "_reviewed.docx" + ) + + temp_path: Path | None = None + + try: + with tempfile.NamedTemporaryFile( + delete=False, + suffix=".docx", + ) as temp_file: + temp_path = Path( + temp_file.name + ) + + client = SuperDocsClient() + + client.export_document( + session_id=session_id, + output_path=temp_path, + filename=output_name, + file_format="docx", + ) + + return temp_path.read_bytes() + + finally: + if temp_path is not None: + temp_path.unlink( + missing_ok=True + ) + + +# ========================================================== +# HEADER +# ========================================================== + + +st.title( + "Evidence-First Resume Bullet Rewriter" +) + +st.caption( + "Strengthen resume bullets without inventing " + "metrics, experience, or responsibilities." +) + +st.info( + "This tool only uses evidence supplied in the " + "resume or by the user. If measurable impact " + "is missing, it asks instead of guessing." +) + + +# ========================================================== +# 1. SOURCE BULLET +# ========================================================== + + +st.subheader( + "1. Source bullet" +) + +source_bullet = st.text_area( + "Paste one resume bullet", + value=( + "Automated invoice processing " + "using Python." + ), + height=100, +) + + +# ========================================================== +# 2. OPTIONAL REQUEST +# ========================================================== + + +st.subheader( + "2. Optional instruction" +) + +requested_claim = st.text_input( + "Anything specific you want emphasized?", + placeholder=( + "Example: Emphasize my " + "leadership experience" + ), +) + + +if st.button( + "Analyse bullet", + type="primary", + use_container_width=True, +): + proposal = propose_rewrite( + source_bullet, + requested_claim=( + requested_claim + or None + ), + ) + + st.session_state.proposal = ( + proposal + ) + + st.session_state.source_bullet = ( + source_bullet + ) + + st.session_state.requested_claim = ( + requested_claim + ) + + reset_review_state() + + +proposal = ( + st.session_state.proposal +) + + +# ========================================================== +# 3. EVIDENCE CHECK +# ========================================================== + + +if proposal: + st.divider() + + st.subheader( + "3. Evidence check" + ) + + left, right = st.columns(2) + + with left: + st.markdown( + "**Source bullet**" + ) + + st.write( + proposal.original_bullet + ) + + with right: + st.markdown( + "**Status**" + ) + + if proposal.status == "ready": + st.success( + "Ready for review" + ) + + elif ( + proposal.status + == "needs_metric" + ): + st.warning( + "More evidence needed" + ) + + else: + st.error( + "Unsupported request" + ) + + if proposal.evidence_used: + st.markdown( + "**Evidence found**" + ) + + for evidence in ( + proposal.evidence_used + ): + st.code( + evidence + ) + + else: + st.caption( + "No explicit quantitative " + "evidence found." + ) + + + # ====================================================== + # MISSING METRIC + # ====================================================== + + if ( + proposal.status + == "needs_metric" + ): + st.markdown( + "### Missing evidence" + ) + + st.write( + proposal.reason + ) + + for question in ( + proposal.questions + ): + st.info( + question + ) + + supplied_metric = st.text_input( + "Add measurable evidence " + "you actually know", + placeholder=( + "Example: Reduced processing " + "time from 3 hours to " + "45 minutes" + ), + key="supplied_metric", + ) + + if st.button( + "Use this evidence", + use_container_width=True, + ): + updated = propose_rewrite( + st.session_state[ + "source_bullet" + ], + supplied_metric=( + supplied_metric + ), + requested_claim=( + st.session_state[ + "requested_claim" + ] + or None + ), + ) + + st.session_state.proposal = ( + updated + ) + + reset_review_state() + + st.rerun() + + + # ====================================================== + # UNSUPPORTED REQUEST + # ====================================================== + + elif ( + proposal.status + == "unsupported" + ): + st.error( + proposal.reason + ) + + st.markdown( + """ +The requested claim was **not added** +because it could not be supported by +the supplied resume evidence. +""" + ) + + + # ====================================================== + # READY + # ====================================================== + + elif ( + proposal.status + == "ready" + ): + st.subheader( + "4. Proposed rewrite" + ) + + before, after = ( + st.columns(2) + ) + + with before: + st.markdown( + "**Before**" + ) + + st.text_area( + "Original", + proposal.original_bullet, + height=120, + disabled=True, + label_visibility="collapsed", + key="before_text", + ) + + with after: + st.markdown( + "**After**" + ) + + st.text_area( + "Proposal", + ( + proposal.proposed_bullet + or "" + ), + height=120, + disabled=True, + label_visibility="collapsed", + key="after_text", + ) + + st.success( + "No unsupported metric or " + "experience was introduced." + ) + + st.caption( + proposal.reason + ) + + + # ================================================== + # 5. UPLOAD RESUME + # ================================================== + + st.divider() + + st.subheader( + "5. Open resume in SuperDocs" + ) + + st.write( + "Upload the DOCX that contains " + "the source bullet. The proposed " + "rewrite will not be applied until " + "you explicitly approve it." + ) + + uploaded_resume = ( + st.file_uploader( + "Upload resume DOCX", + type=["docx"], + key="resume_uploader", + ) + ) + + if ( + uploaded_resume + is not None + ): + st.caption( + "Selected: " + f"`{uploaded_resume.name}`" + ) + + if st.button( + "Open resume in SuperDocs", + type="primary", + key="upload_resume_button", + ): + try: + with st.spinner( + "Uploading resume " + "to SuperDocs..." + ): + upload_resume_to_superdocs( + uploaded_resume + ) + + st.success( + "Resume opened " + "successfully." + ) + + st.rerun() + + except Exception as exc: + st.error( + str(exc) + ) + + + # ================================================== + # 6. HUMAN REVIEW + # ================================================== + + if ( + st.session_state + .resume_session_id + ): + st.success( + "Resume is ready " + "in SuperDocs." + ) + + st.caption( + "Document: " + + str( + st.session_state + .resume_filename + ) + ) + + st.subheader( + "6. SuperDocs human review" + ) + + review_instruction = ( + build_review_instruction( + proposal.original_bullet, + ( + proposal + .proposed_bullet + or "" + ), + ) + ) + + with st.expander( + "Exact edit instruction" + ): + st.code( + review_instruction + ) + + if ( + not st.session_state + .pending_changes + and st.session_state + .review_status + not in { + "completed", + "rejected", + } + ): + button_label = ( + "Resume SuperDocs Review" + if ( + st.session_state.review_job_id + and st.session_state.review_status + == "awaiting_approval" + ) + else "Start SuperDocs Review" + ) + + if st.button( + button_label, + type="primary", + key="start_review_button", + ): + try: + client = SuperDocsClient() + + existing_job_id = ( + st.session_state + .review_job_id + ) + + with st.spinner( + "Loading the existing " + "SuperDocs review..." + if ( + existing_job_id + and st.session_state + .review_status + == "awaiting_approval" + ) + else ( + "SuperDocs is preparing " + "the proposed edit..." + ) + ): + if ( + existing_job_id + and st.session_state + .review_status + == "awaiting_approval" + ): + # Graceful re-entry: + # reuse the already-created job instead + # of starting another review request. + job_id = existing_job_id + job = client.get_job( + job_id=job_id + ) + + else: + started = ( + client.start_async_chat( + session_id=( + st.session_state + .resume_session_id + ), + message=( + review_instruction + ), + approval_mode=( + "ask_every_time" + ), + ) + ) + + job_id = started.get( + "job_id" + ) + + if not job_id: + raise RuntimeError( + "SuperDocs did not " + "return a job_id." + ) + + st.session_state[ + "review_job_id" + ] = job_id + + job = wait_until_action_needed( + client=client, + job_id=job_id, + timeout_seconds=180, + ) + + status = job.get( + "status" + ) + + st.session_state[ + "review_status" + ] = status + + metadata = ( + job.get("metadata") + or {} + ) + + if ( + status + == "awaiting_approval" + and isinstance( + metadata, + dict, + ) + and metadata.get( + "awaiting_kind" + ) + == "continue_prompt" + ): + raise RuntimeError( + "SuperDocs requested " + "continuation for a larger " + "operation. This demo expects " + "one small surgical edit." + ) + + changes = ( + pending_changes_from_job( + job + ) + ) + + st.session_state[ + "pending_changes" + ] = changes + + if ( + status + == "awaiting_approval" + and not changes + ): + raise RuntimeError( + "SuperDocs reached " + "awaiting_approval but " + "returned no proposed changes." + ) + + st.rerun() + + except ( + SuperDocsError, + SuperDocsParseError, + TimeoutError, + RuntimeError, + ) as exc: + st.error( + str(exc) + ) + + + # ============================================== + # SHOW PROPOSED CHANGES + # ============================================== + + pending_changes = ( + st.session_state + .pending_changes + ) + + if pending_changes: + st.warning( + "SuperDocs has proposed " + "a change. Nothing has " + "been applied yet." + ) + + for index, change in enumerate( + pending_changes, + start=1, + ): + with st.container( + border=True + ): + st.markdown( + f"### Proposed " + f"change {index}" + ) + + operation = ( + change.get( + "operation" + ) + ) + + explanation = ( + change.get( + "ai_explanation" + ) + ) + + if operation: + st.caption( + "Operation: " + + str( + operation + ) + ) + + if explanation: + st.write( + "**Explanation:** " + + str( + explanation + ) + ) + + before_html = ( + change.get( + "old_html" + ) + or change.get( + "before_html" + ) + or change.get( + "before" + ) + or "" + ) + + after_html = ( + change.get( + "new_html" + ) + or change.get( + "after_html" + ) + or change.get( + "after" + ) + or "" + ) + + left_change, right_change = ( + st.columns(2) + ) + + with left_change: + st.markdown( + "**Before**" + ) + + st.code( + before_html + or "(empty)", + language="html", + ) + + with right_change: + st.markdown( + "**After**" + ) + + st.code( + after_html + or "(empty)", + language="html", + ) + + approve_col, reject_col = ( + st.columns(2) + ) + + with approve_col: + if st.button( + "Approve proposed change", + type="primary", + use_container_width=True, + key="approve_change", + ): + try: + client = ( + SuperDocsClient() + ) + + with st.spinner( + "Applying approved " + "change..." + ): + decisions = [ + { + "change_id": change["change_id"], + "approved": True, + } + for change in pending_changes + ] + + client.approve_changes( + session_id=( + st.session_state + .resume_session_id + ), + job_id=( + st.session_state + .review_job_id + ), + changes=decisions, + approved=True, + ) + + wait_until_completed( + client=client, + job_id=( + st.session_state + .review_job_id + ), + timeout_seconds=180, + ) + + st.session_state[ + "pending_changes" + ] = [] + + st.session_state[ + "review_status" + ] = "completed" + + st.session_state[ + "review_decision" + ] = "approved" + + st.success( + "Change approved " + "and applied." + ) + + st.rerun() + + except Exception as exc: + st.error( + str(exc) + ) + + with reject_col: + if st.button( + "Reject proposed change", + use_container_width=True, + key="reject_change", + ): + try: + client = ( + SuperDocsClient() + ) + + with st.spinner( + "Rejecting proposed " + "change..." + ): + decisions = [ + { + "change_id": change["change_id"], + "approved": False, + } + for change in pending_changes + ] + + client.approve_changes( + session_id=( + st.session_state + .resume_session_id + ), + job_id=( + st.session_state + .review_job_id + ), + changes=decisions, + approved=False, + ) + + st.session_state[ + "pending_changes" + ] = [] + + st.session_state[ + "review_status" + ] = "rejected" + + st.session_state[ + "review_decision" + ] = "rejected" + + st.rerun() + + except Exception as exc: + st.error( + str(exc) + ) + + + # ============================================== + # APPROVED + # ============================================== + + if ( + st.session_state + .review_decision + == "approved" + ): + st.success( + "Human approval complete. " + "The reviewed document " + "can now be exported." + ) + + st.subheader( + "7. Export reviewed DOCX" + ) + + if st.button( + "Prepare reviewed DOCX", + type="primary", + key="prepare_export", + ): + try: + with st.spinner( + "Exporting reviewed " + "resume..." + ): + ( + st.session_state[ + "reviewed_docx_bytes" + ] + ) = ( + export_reviewed_resume() + ) + + st.rerun() + + except Exception as exc: + st.error( + str(exc) + ) + + if ( + st.session_state + .reviewed_docx_bytes + ): + source_name = ( + st.session_state + .resume_filename + or "resume.docx" + ) + + output_name = ( + Path(source_name).stem + + "_reviewed.docx" + ) + + st.download_button( + "Download reviewed DOCX", + data=( + st.session_state + .reviewed_docx_bytes + ), + file_name=( + output_name + ), + mime=( + "application/vnd." + "openxmlformats-" + "officedocument." + "wordprocessingml." + "document" + ), + use_container_width=True, + key="download_reviewed_docx", + ) + + + # ============================================== + # REJECTED + # ============================================== + + elif ( + st.session_state + .review_decision + == "rejected" + ): + st.warning( + "The proposed change was " + "rejected. The resume was " + "not intentionally changed " + "by this review." + ) + + if st.button( + "Reset review", + key="reset_review", + ): + reset_review_state() + st.rerun() \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/assets/evidence_first_review.png b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/assets/evidence_first_review.png new file mode 100644 index 0000000000000000000000000000000000000000..dcf9493cb5f5693cc44f8c97f641a0479c948269 GIT binary patch literal 90415 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⋘wnY2+VAIdw#eY`Pwg)W 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

bue->)Pg<_w)5*>)k#V<>5hRY~< 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 AtpET3 literal 0 HcmV?d00001 diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/__init__.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/evidence.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/evidence.py new file mode 100644 index 00000000..356610eb --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/evidence.py @@ -0,0 +1,107 @@ +import re + +from core.models import BulletAnalysis, EvidenceItem + + +PATTERNS: list[tuple[str, re.Pattern[str]]] = [ + ( + "percentage", + re.compile(r"\b\d+(?:\.\d+)?\s*%"), + ), + ( + "currency", + re.compile( + r"(?:₹|\$|€|£)\s?\d[\d,]*(?:\.\d+)?" + r"|\b\d[\d,]*(?:\.\d+)?\s?(?:USD|INR|EUR|GBP)\b", + re.IGNORECASE, + ), + ), + ( + "duration", + re.compile( + r"\b\d+(?:\.\d+)?\s*" + r"(?:seconds?|secs?|minutes?|mins?|hours?|hrs?|days?|weeks?|months?)\b", + re.IGNORECASE, + ), + ), + ( + "volume", + re.compile( + r"\b\d[\d,]*(?:\.\d+)?\s+" + r"(?:" + r"invoices?|records?|reports?|files?|documents?|tickets?|" + r"customers?|clients?|users?|transactions?|orders?|requests?|" + r"dashboards?|pipelines?|models?|queries?|jobs?|cases?" + r")\b", + re.IGNORECASE, + ), + ), +] + + +def _overlaps( + start: int, + end: int, + occupied: list[tuple[int, int]], +) -> bool: + return any(start < existing_end and end > existing_start for existing_start, existing_end in occupied) + + +def extract_evidence(text: str) -> list[EvidenceItem]: + """ + Extract explicit quantitative evidence from a resume bullet. + + Important: + This function only detects evidence that is literally present + in the supplied text. It never infers or invents metrics. + """ + if not text or not text.strip(): + return [] + + evidence: list[EvidenceItem] = [] + occupied: list[tuple[int, int]] = [] + + for kind, pattern in PATTERNS: + for match in pattern.finditer(text): + start, end = match.span() + + if _overlaps(start, end, occupied): + continue + + evidence.append( + EvidenceItem( + text=match.group(0), + kind=kind, # type: ignore[arg-type] + start=start, + end=end, + ) + ) + occupied.append((start, end)) + + evidence.sort(key=lambda item: item.start) + return evidence + + +def analyze_bullet(text: str) -> BulletAnalysis: + cleaned = text.strip() + evidence = extract_evidence(cleaned) + + missing: list[str] = [] + + if not evidence: + missing.append("quantified impact") + + return BulletAnalysis( + original_bullet=cleaned, + evidence=evidence, + has_quantified_evidence=bool(evidence), + missing_evidence=missing, + ) + + +def metric_question() -> str: + return ( + "Do you know a measurable result for this work, such as time saved, " + "processing-time reduction, volume handled, error reduction, " + "revenue generated, or cost saved?" + ) \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/models.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/models.py new file mode 100644 index 00000000..20d53cd1 --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/models.py @@ -0,0 +1,44 @@ +from dataclasses import dataclass, field +from typing import Literal + + +EvidenceKind = Literal[ + "percentage", + "currency", + "duration", + "volume", + "number", +] + + +@dataclass(frozen=True) +class EvidenceItem: + text: str + kind: EvidenceKind + start: int + end: int + + +@dataclass +class BulletAnalysis: + original_bullet: str + evidence: list[EvidenceItem] = field(default_factory=list) + has_quantified_evidence: bool = False + missing_evidence: list[str] = field(default_factory=list) + + +RewriteStatus = Literal[ + "ready", + "needs_metric", + "unsupported", +] + + +@dataclass +class RewriteProposal: + original_bullet: str + proposed_bullet: str | None + status: RewriteStatus + reason: str + evidence_used: list[str] = field(default_factory=list) + questions: list[str] = field(default_factory=list) \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/rewriter.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/rewriter.py new file mode 100644 index 00000000..907b58f1 --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/core/rewriter.py @@ -0,0 +1,267 @@ +from __future__ import annotations + +import re + +from core.evidence import analyze_bullet, extract_evidence, metric_question +from core.models import RewriteProposal + + +LEADERSHIP_REQUEST_TERMS = ( + "led", + "lead ", + "managed", + "supervised", + "mentored", + "team lead", + "leadership", +) + +LEADERSHIP_SOURCE_TERMS = ( + "led", + "managed", + "supervised", + "mentored", + "team lead", + "direct reports", +) + + +def _clean(text: str) -> str: + return " ".join(text.strip().split()) + + +def _ensure_period(text: str) -> str: + text = text.strip() + + if not text: + return text + + if text[-1] not in ".!?": + return text + "." + + return text + + +def _contains_any(text: str, terms: tuple[str, ...]) -> bool: + lowered = text.lower() + return any(term in lowered for term in terms) + + +def request_is_supported( + source_bullet: str, + requested_claim: str, +) -> tuple[bool, str]: + """ + Check whether a requested claim is supported by the source bullet. + + This deliberately handles only claim families we can validate + deterministically. Unsupported high-risk additions are rejected + rather than guessed. + """ + source = _clean(source_bullet) + request = _clean(requested_claim) + + if not request: + return True, "No additional claim requested." + + requests_leadership = _contains_any( + request, + LEADERSHIP_REQUEST_TERMS, + ) + + if requests_leadership: + source_supports_leadership = _contains_any( + source, + LEADERSHIP_SOURCE_TERMS, + ) + + if not source_supports_leadership: + return ( + False, + "The requested leadership claim is not supported by " + "the supplied resume evidence.", + ) + + return True, "Requested claim is supported by the supplied evidence." + + +def strengthen_structure(bullet: str) -> str: + """ + Apply only conservative wording cleanup. + + No new facts, metrics, technologies, responsibilities, + or outcomes are introduced here. + """ + cleaned = _clean(bullet) + + replacements = ( + ( + r"(?i)^was responsible for processing\s+", + "Processed ", + ), + ( + r"(?i)^responsible for processing\s+", + "Processed ", + ), + ( + r"(?i)^was responsible for creating\s+", + "Created ", + ), + ( + r"(?i)^responsible for creating\s+", + "Created ", + ), + ( + r"(?i)^was responsible for developing\s+", + "Developed ", + ), + ( + r"(?i)^responsible for developing\s+", + "Developed ", + ), + ) + + for pattern, replacement in replacements: + if re.search(pattern, cleaned): + cleaned = re.sub( + pattern, + replacement, + cleaned, + count=1, + ) + break + + return _ensure_period(cleaned) + + +def _metric_to_result_clause(metric_text: str) -> str: + """ + Convert a user-supplied result into a clause that can be appended + without changing its factual content. + """ + metric = _clean(metric_text).rstrip(".") + + conversions = ( + (r"(?i)^reduced\s+", "reducing "), + (r"(?i)^saved\s+", "saving "), + (r"(?i)^increased\s+", "increasing "), + (r"(?i)^improved\s+", "improving "), + (r"(?i)^decreased\s+", "decreasing "), + (r"(?i)^cut\s+", "cutting "), + ) + + for pattern, replacement in conversions: + if re.search(pattern, metric): + return re.sub( + pattern, + replacement, + metric, + count=1, + ) + + if metric: + return metric[0].lower() + metric[1:] + + return metric + + +def propose_rewrite( + bullet: str, + supplied_metric: str | None = None, + requested_claim: str | None = None, +) -> RewriteProposal: + """ + Produce an evidence-first rewrite proposal. + + Rules: + 1. Never invent quantitative impact. + 2. Never add unsupported leadership claims. + 3. User-supplied metrics must contain explicit quantitative evidence. + 4. All evidence used is returned for traceability. + """ + source = _clean(bullet) + + if not source: + return RewriteProposal( + original_bullet="", + proposed_bullet=None, + status="unsupported", + reason="A source bullet is required before a rewrite can be proposed.", + ) + + if requested_claim: + supported, reason = request_is_supported( + source, + requested_claim, + ) + + if not supported: + return RewriteProposal( + original_bullet=source, + proposed_bullet=None, + status="unsupported", + reason=reason, + ) + + source_analysis = analyze_bullet(source) + evidence_used = [ + item.text + for item in source_analysis.evidence + ] + + metric = _clean(supplied_metric or "") + + if not source_analysis.has_quantified_evidence and not metric: + return RewriteProposal( + original_bullet=source, + proposed_bullet=None, + status="needs_metric", + reason=( + "The source bullet does not contain a measurable result. " + "No metric will be invented." + ), + evidence_used=evidence_used, + questions=[metric_question()], + ) + + if metric: + metric_evidence = extract_evidence(metric) + + if not metric_evidence: + return RewriteProposal( + original_bullet=source, + proposed_bullet=None, + status="needs_metric", + reason=( + "The supplied impact statement does not contain an " + "explicit measurable result." + ), + evidence_used=evidence_used, + questions=[metric_question()], + ) + + evidence_used.extend( + item.text + for item in metric_evidence + ) + + rewritten = strengthen_structure(source).rstrip(".") + + if metric: + metric_clause = _metric_to_result_clause(metric) + + if metric_clause.lower() not in rewritten.lower(): + rewritten = f"{rewritten}, {metric_clause}" + + rewritten = _ensure_period(rewritten) + + return RewriteProposal( + original_bullet=source, + proposed_bullet=rewritten, + status="ready", + reason=( + "Rewrite uses only facts and measurable evidence supplied " + "by the resume or the user." + ), + evidence_used=list(dict.fromkeys(evidence_used)), + ) \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/requirements.txt b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/requirements.txt new file mode 100644 index 00000000..b6cd845a --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/requirements.txt @@ -0,0 +1,5 @@ +streamlit +python-docx +pytest +requests +python-dotenv \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/sample_documents/generate_sample_resume.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/sample_documents/generate_sample_resume.py new file mode 100644 index 00000000..751f7f30 --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/sample_documents/generate_sample_resume.py @@ -0,0 +1,52 @@ +from pathlib import Path + +from docx import Document + + +OUTPUT_DIR = Path(__file__).parent +OUTPUT_PATH = OUTPUT_DIR / "sample_resume.docx" + + +def build_resume() -> None: + document = Document() + + document.add_heading("Alex Morgan", level=0) + document.add_paragraph( + "Data Analyst | Python | SQL | Power BI" + ) + + document.add_heading("Experience", level=1) + + document.add_heading( + "Operations Data Analyst — Example Industries", + level=2, + ) + document.add_paragraph( + "January 2024 — Present" + ) + + bullets = [ + "Automated invoice processing using Python.", + "Processed 500 invoices per month using Python.", + "Built Power BI dashboards for operational reporting.", + "Was responsible for processing 1,200 records per week.", + "Reduced report preparation time from 3 hours to 45 minutes.", + ] + + for bullet in bullets: + paragraph = document.add_paragraph( + style="List Bullet" + ) + paragraph.add_run(bullet) + + document.add_heading("Skills", level=1) + document.add_paragraph( + "Python, SQL, Power BI, Excel" + ) + + document.save(OUTPUT_PATH) + print(f"Created: {OUTPUT_PATH}") + + +if __name__ == "__main__": + build_resume() \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/sample_documents/sample_resume.docx b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/sample_documents/sample_resume.docx new file mode 100644 index 0000000000000000000000000000000000000000..589700922fd0cddbb1ead15001224785cfb63a75 GIT binary patch literal 35587 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�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 literal 0 HcmV?d00001 diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/__init__.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/client.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/client.py new file mode 100644 index 00000000..0fb8428c --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/client.py @@ -0,0 +1,278 @@ +from __future__ import annotations + +import os +from pathlib import Path +from typing import Any + +import requests +from dotenv import load_dotenv + + +load_dotenv() + + +class SuperDocsError(RuntimeError): + pass + + +class SuperDocsClient: + BASE_URL = "https://api.superdocs.app" + + def __init__( + self, + api_key: str | None = None, + timeout: int = 180, + ) -> None: + self.api_key = ( + api_key + or os.getenv("SUPERDOCS_API_KEY") + ) + + self.timeout = timeout + + if not self.api_key: + raise SuperDocsError( + "SUPERDOCS_API_KEY is missing. " + "Add it to your local .env file." + ) + + @property + def auth_headers(self) -> dict[str, str]: + return { + "Authorization": + f"Bearer {self.api_key}", + } + + @property + def json_headers(self) -> dict[str, str]: + return { + **self.auth_headers, + "Content-Type": "application/json", + } + + def upload_document( + self, + *, + path: str | Path, + session_id: str, + open_mode: str = "replace", + ) -> dict[str, Any]: + path = Path(path) + + if not path.exists(): + raise FileNotFoundError( + path + ) + + with path.open("rb") as file_handle: + response = requests.post( + ( + f"{self.BASE_URL}" + "/v1/documents/upload" + ), + headers=self.auth_headers, + files={ + "file": ( + path.name, + file_handle, + ) + }, + data={ + "session_id": + session_id, + + "open_mode": + open_mode, + }, + timeout=self.timeout, + ) + + if not response.ok: + raise SuperDocsError( + ( + f"Upload failed for " + f"{path.name}. " + f"HTTP " + f"{response.status_code}: " + f"{response.text}" + ) + ) + + return response.json() + + def chat( + self, + *, + session_id: str, + message: str, + document_id: str | None = None, + ) -> dict[str, Any]: + payload: dict[str, Any] = { + "session_id": session_id, + "message": message, + } + + if document_id is not None: + payload["document_id"] = document_id + + response = requests.post( + f"{self.BASE_URL}/v1/chat", + headers=self.json_headers, + json=payload, + timeout=self.timeout, + ) + + if not response.ok: + raise SuperDocsError( + "Chat request failed. " + f"HTTP {response.status_code}: " + f"{response.text}" + ) + + return response.json() + + def start_async_chat( + self, + *, + session_id: str, + message: str, + approval_mode: str = "ask_every_time", + ) -> dict[str, Any]: + response = requests.post( + f"{self.BASE_URL}/v1/chat/async", + headers=self.json_headers, + json={ + "session_id": session_id, + "message": message, + "approval_mode": approval_mode, + }, + timeout=self.timeout, + ) + + if not response.ok: + raise SuperDocsError( + "Failed to start Review request. " + f"HTTP {response.status_code}: " + f"{response.text}" + ) + + return response.json() + + def get_job( + self, + *, + job_id: str, + ) -> dict[str, Any]: + response = requests.get( + f"{self.BASE_URL}/v1/jobs/{job_id}", + headers=self.auth_headers, + timeout=self.timeout, + ) + + if not response.ok: + raise SuperDocsError( + "Failed to read job status. " + f"HTTP {response.status_code}: " + f"{response.text}" + ) + + return response.json() + + def approve_changes( + self, + *, + session_id: str, + job_id: str, + changes: list[dict[str, Any]], + approved: bool, + ) -> dict[str, Any]: + response = requests.post( + ( + f"{self.BASE_URL}/v1/chat/" + f"{session_id}/approve" + ), + headers=self.json_headers, + json={ + "job_id": job_id, + "approved": approved, + "changes": changes, + }, + timeout=self.timeout, + ) + + if not response.ok: + raise SuperDocsError( + "Failed to submit approval decision. " + f"HTTP {response.status_code}: " + f"{response.text}" + ) + + return response.json() + + def continue_job( + self, + *, + session_id: str, + job_id: str, + should_continue: bool, + ) -> dict[str, Any]: + response = requests.post( + ( + f"{self.BASE_URL}/v1/chat/" + f"{session_id}/continue" + ), + headers=self.json_headers, + json={ + "job_id": job_id, + "continue": should_continue, + }, + timeout=self.timeout, + ) + + if not response.ok: + raise SuperDocsError( + "Failed to continue job. " + f"HTTP {response.status_code}: " + f"{response.text}" + ) + + return response.json() + + def export_document( + self, + *, + session_id: str, + output_path: str | Path, + filename: str, + file_format: str = "docx", + ) -> Path: + output_path = Path(output_path) + + response = requests.post( + f"{self.BASE_URL}/v1/documents/export", + headers=self.json_headers, + json={ + "session_id": session_id, + "format": file_format, + "filename": filename, + }, + timeout=self.timeout, + ) + + if not response.ok: + raise SuperDocsError( + "Document export failed. " + f"HTTP {response.status_code}: " + f"{response.text}" + ) + + output_path.parent.mkdir( + parents=True, + exist_ok=True, + ) + + output_path.write_bytes( + response.content + ) + + return output_path \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/parser.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/parser.py new file mode 100644 index 00000000..050e6719 --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/parser.py @@ -0,0 +1,102 @@ +from __future__ import annotations + +import json +from typing import Any + + +class SuperDocsParseError(ValueError): + pass + + +def parse_pending_changes( + value: Any, +) -> list[dict[str, Any]]: + """ + SuperDocs pending changes may arrive either: + - already as a list + - as a JSON-encoded string + + Never silently treat malformed content as an + empty successful diff. + """ + + if isinstance(value, str): + try: + value = json.loads(value) + except json.JSONDecodeError as exc: + raise SuperDocsParseError( + "pending_changes was a string " + "but was not valid JSON." + ) from exc + + if value is None: + return [] + + if not isinstance(value, list): + raise SuperDocsParseError( + "pending_changes must be a list " + "or a JSON-encoded list." + ) + + changes: list[dict[str, Any]] = [] + + for item in value: + if not isinstance(item, dict): + raise SuperDocsParseError( + "Every proposed change must be an object." + ) + + changes.append(item) + + return changes + + +def pending_changes_from_job( + job: dict[str, Any], +) -> list[dict[str, Any]]: + """ + Extract proposed changes from a SuperDocs job. + + Current Review jobs expose pending_changes inside + job["metadata"], but fallback locations are supported + for graceful compatibility. + """ + + metadata = job.get("metadata") + + if isinstance(metadata, dict): + value = metadata.get( + "pending_changes" + ) + + if value is not None: + return parse_pending_changes( + value + ) + + for key in ( + "pending_changes", + "result", + "data", + "output", + ): + value = job.get(key) + + if key in { + "result", + "data", + "output", + }: + if isinstance(value, dict): + value = value.get( + "pending_changes" + ) + else: + continue + + if value is not None: + return parse_pending_changes( + value + ) + + return [] \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/polling.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/polling.py new file mode 100644 index 00000000..4cd6c211 --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/superdocs/polling.py @@ -0,0 +1,74 @@ +from __future__ import annotations + +import time +from typing import Any + +from superdocs.client import ( + SuperDocsClient, + SuperDocsError, +) + + +def wait_until_action_needed( + *, + client: SuperDocsClient, + job_id: str, + timeout_seconds: int = 180, + poll_interval: float = 2.0, +) -> dict[str, Any]: + started = time.monotonic() + last_status = None + + while True: + job = client.get_job( + job_id=job_id + ) + + status = job.get("status") + + if status != last_status: + print( + f" Job status: {status}" + ) + last_status = status + + if status in { + "awaiting_approval", + "completed", + }: + return job + + if status == "failed": + raise SuperDocsError( + job.get( + "error", + "SuperDocs job failed.", + ) + ) + + if status == "cancelled": + raise SuperDocsError( + "SuperDocs job was cancelled." + ) + + elapsed = ( + time.monotonic() + - started + ) + + if elapsed >= timeout_seconds: + raise TimeoutError( + f"Job {job_id} did not reach " + f"an actionable state within " + f"{timeout_seconds} seconds." + ) + + if elapsed >= 30: + print( + f" Still processing... " + f"{int(elapsed)}s elapsed" + ) + + time.sleep( + poll_interval + ) \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_evidence.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_evidence.py new file mode 100644 index 00000000..7ea612cf --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_evidence.py @@ -0,0 +1,66 @@ +from core.evidence import analyze_bullet, extract_evidence, metric_question + + +def test_detects_volume_metric(): + bullet = "Processed 500 invoices per month using Python." + + analysis = analyze_bullet(bullet) + + assert analysis.has_quantified_evidence is True + assert any(item.text == "500 invoices" for item in analysis.evidence) + + +def test_missing_metric_is_reported(): + bullet = "Automated invoice processing using Python." + + analysis = analyze_bullet(bullet) + + assert analysis.has_quantified_evidence is False + assert "quantified impact" in analysis.missing_evidence + + +def test_detects_percentage(): + evidence = extract_evidence( + "Reduced processing time by 40% using Python automation." + ) + + assert any( + item.kind == "percentage" and item.text == "40%" + for item in evidence + ) + + +def test_detects_currency(): + evidence = extract_evidence( + "Reduced annual operating costs by $25,000." + ) + + assert any( + item.kind == "currency" and item.text == "$25,000" + for item in evidence + ) + + +def test_detects_duration_metrics(): + evidence = extract_evidence( + "Reduced processing time from 3 hours to 45 minutes." + ) + + values = [item.text for item in evidence] + + assert "3 hours" in values + assert "45 minutes" in values + + +def test_empty_bullet_has_no_evidence(): + analysis = analyze_bullet("") + + assert analysis.has_quantified_evidence is False + assert analysis.evidence == [] + + +def test_metric_question_does_not_suggest_fake_number(): + question = metric_question() + + assert "Do you know" in question + assert "measurable result" in question \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_rewriter.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_rewriter.py new file mode 100644 index 00000000..e087298d --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_rewriter.py @@ -0,0 +1,99 @@ +from core.rewriter import ( + propose_rewrite, + request_is_supported, + strengthen_structure, +) + + +def test_missing_metric_requires_user_input(): + proposal = propose_rewrite( + "Automated invoice processing using Python." + ) + + assert proposal.status == "needs_metric" + assert proposal.proposed_bullet is None + assert proposal.questions + assert "No metric will be invented" in proposal.reason + + +def test_existing_metric_allows_rewrite(): + proposal = propose_rewrite( + "Processed 500 invoices per month using Python." + ) + + assert proposal.status == "ready" + assert proposal.proposed_bullet is not None + assert "500 invoices" in proposal.proposed_bullet + assert "500 invoices" in proposal.evidence_used + + +def test_user_supplied_metric_is_used_exactly(): + proposal = propose_rewrite( + "Automated invoice processing using Python.", + supplied_metric=( + "Reduced processing time from 3 hours to 45 minutes." + ), + ) + + assert proposal.status == "ready" + assert proposal.proposed_bullet is not None + assert "3 hours" in proposal.proposed_bullet + assert "45 minutes" in proposal.proposed_bullet + + assert "3 hours" in proposal.evidence_used + assert "45 minutes" in proposal.evidence_used + + +def test_non_quantified_user_answer_is_not_accepted(): + proposal = propose_rewrite( + "Automated invoice processing using Python.", + supplied_metric="It became much faster.", + ) + + assert proposal.status == "needs_metric" + assert proposal.proposed_bullet is None + + +def test_unsupported_leadership_claim_is_rejected(): + proposal = propose_rewrite( + "Built Power BI dashboards for operational reporting.", + requested_claim="Make this say I led a five-person analytics team.", + ) + + assert proposal.status == "unsupported" + assert proposal.proposed_bullet is None + assert "leadership claim" in proposal.reason + + +def test_supported_leadership_language_passes_gate(): + supported, reason = request_is_supported( + "Led the analytics team and built Power BI dashboards.", + "Emphasize that I led the analytics team.", + ) + + assert supported is True + assert "supported" in reason + + +def test_conservative_structure_cleanup(): + result = strengthen_structure( + "Was responsible for processing 500 invoices per month using Python." + ) + + assert result == ( + "Processed 500 invoices per month using Python." + ) + + +def test_rewrite_does_not_add_unknown_metric(): + proposal = propose_rewrite( + "Processed 500 invoices per month using Python." + ) + + assert proposal.status == "ready" + + result = proposal.proposed_bullet or "" + + assert "40%" not in result + assert "50%" not in result + assert "$" not in result \ No newline at end of file diff --git a/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_superdocs_parser.py b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_superdocs_parser.py new file mode 100644 index 00000000..0889dbfd --- /dev/null +++ b/use-cases/Kalpesh1Sharma/impact-quantifying-bullet-rewriter/tests/test_superdocs_parser.py @@ -0,0 +1,101 @@ +import pytest + +from superdocs.parser import ( + SuperDocsParseError, + parse_pending_changes, +) + + +def test_pending_changes_accepts_list(): + changes = [ + { + "change_id": "change-1", + "operation": "replace", + } + ] + + assert ( + parse_pending_changes(changes) + == changes + ) + + +def test_pending_changes_parses_json_encoded_string(): + raw = """ + [ + { + "change_id": "change-1", + "operation": "replace" + } + ] + """ + + result = parse_pending_changes( + raw + ) + + assert len(result) == 1 + + assert ( + result[0]["change_id"] + == "change-1" + ) + + +def test_bad_json_does_not_become_empty_changes(): + with pytest.raises( + SuperDocsParseError + ): + parse_pending_changes( + "[broken" + ) + +from superdocs.parser import ( + pending_changes_from_job, +) + + +def test_pending_changes_found_inside_job_metadata(): + job = { + "status": "awaiting_approval", + "metadata": { + "pending_changes": [ + { + "operation": "replace", + "old_html": "

Before

", + "new_html": "

After

", + } + ] + }, + } + + changes = pending_changes_from_job( + job + ) + + assert len(changes) == 1 + assert ( + changes[0]["operation"] + == "replace" + ) + + +def test_metadata_pending_changes_can_be_json_string(): + job = { + "status": "awaiting_approval", + "metadata": { + "pending_changes": ( + '[{"operation":"replace"}]' + ) + }, + } + + changes = pending_changes_from_job( + job + ) + + assert len(changes) == 1 + assert ( + changes[0]["operation"] + == "replace" + ) \ No newline at end of file