From c3b3f5a194d53147b7fdbea5ec2037ba4f4eb7a0 Mon Sep 17 00:00:00 2001 From: ArchieChelle Date: Thu, 25 Jun 2026 00:35:10 -0400 Subject: [PATCH 1/2] Add --url flag to applypilot run to inject a specific job URL --- src/applypilot/cli.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/src/applypilot/cli.py b/src/applypilot/cli.py index 6c8be912..2ffa0ba8 100644 --- a/src/applypilot/cli.py +++ b/src/applypilot/cli.py @@ -97,12 +97,30 @@ def run( "lenient: banned words ignored, LLM judge skipped (fastest, fewest API calls)." ), ), + url: Optional[str] = typer.Option( + None, "--url", + help="Inject a specific job URL and run enrich -> score -> tailor -> cover -> pdf on it (skips discover).", + ), ) -> None: """Run pipeline stages: discover, enrich, score, tailor, cover, pdf.""" _bootstrap() from applypilot.pipeline import run_pipeline + # --url: inject the job into the DB and skip discover + if url: + from applypilot.database import get_connection, store_jobs + conn = get_connection() + new, dup = store_jobs(conn, [{"url": url}], site="manual", strategy="manual") + if new: + console.print(f"[green]Added job URL to pipeline:[/green] {url}") + else: + console.print(f"[yellow]Job URL already in database:[/yellow] {url}") + if not stages: + stages = ["enrich", "score", "tailor", "cover", "pdf"] + else: + stages = [s for s in stages if s != "discover"] + stage_list = stages if stages else ["all"] # Validate stage names From f83e7197728b15f936e51a7baa9f713716aa1813 Mon Sep 17 00:00:00 2001 From: ArchieChelle Date: Thu, 25 Jun 2026 12:52:54 -0400 Subject: [PATCH 2/2] Fix tailor validation rejecting company in subtitle field The preserved-company check in validate_json_fields only looked at each experience entry's `header` field. The LLM reliably places the role in `header` and the company in `subtitle` (e.g. "First Family Trust | Dates"), so the check failed for every company on nearly every job, causing ~95% of tailored resumes to be rejected as FAILED_VALIDATION after exhausting all retries. Check the company name against both `header` and `subtitle` so legitimately formatted output passes. Co-Authored-By: Claude Opus 4.8 --- src/applypilot/scoring/validator.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/applypilot/scoring/validator.py b/src/applypilot/scoring/validator.py index abb8f89d..7e7b2558 100644 --- a/src/applypilot/scoring/validator.py +++ b/src/applypilot/scoring/validator.py @@ -138,8 +138,11 @@ def validate_json_fields(data: dict, profile: dict, mode: str = "normal") -> dic if isinstance(data["experience"], list): for company in preserved_companies: + # The LLM may place the company in either the header ("Title at + # Company") or the subtitle ("Company | Dates"), so check both. has_company = any( - company.lower() in str(e.get("header", "")).lower() + company.lower() + in f"{e.get('header', '')} {e.get('subtitle', '')}".lower() for e in data["experience"] ) if not has_company: