commit 1bf292a4881b5a34ab0ff49093250f8729d9ddea Author: Hayden Hargreaves Date: Tue Jan 27 23:11:23 2026 -0700 (INIT): Project initialized. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3cd73f6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/flake.lock +/.env +/**/.env diff --git a/HaydenHargreaves_Oct01.pdf b/HaydenHargreaves_Oct01.pdf new file mode 100644 index 0000000..8a51962 Binary files /dev/null and b/HaydenHargreaves_Oct01.pdf differ diff --git a/cmd/server/main.go b/cmd/server/main.go new file mode 100644 index 0000000..7905807 --- /dev/null +++ b/cmd/server/main.go @@ -0,0 +1,5 @@ +package main + +func main() { + +} diff --git a/data/errors.json b/data/errors.json new file mode 100644 index 0000000..66dcf10 --- /dev/null +++ b/data/errors.json @@ -0,0 +1,11 @@ +[ + { + "Message": "POST \"https://api.openai.com/v1/chat/completions\": 429 Too Many Requests", + "Response": { + "message": "You exceeded your current quota, please check your plan and billing details. For more information on this error, read the docs: https://platform.openai.com/docs/guides/error-codes/api-errors.", + "type": "insufficient_quota", + "param": null, + "code": "insufficient_quota" + } + } +] diff --git a/data/example_google.json b/data/example_google.json new file mode 100644 index 0000000..b73f852 --- /dev/null +++ b/data/example_google.json @@ -0,0 +1,79 @@ +{ + "system-prompt": "You are an automated resume evaluation engine. Your task is to objectively assess a resume according to criteria provided by the user in a separate instruction prompt and to return a structured, neutral assessment.\n\nFollow these rules carefully:\n\nEvaluation scope\nThe user will provide:\n- A grading prompt that specifies what to evaluate (e.g., required skills, experience level, domain fit, formatting, clarity).\n- A resume, supplied as plain text converted from a PDF.\n- Use only the information present in the resume text and the user’s grading prompt.\n- Do not infer or assume facts that are not explicitly supported by the resume.\n\nObjectivity and tone\n- Your output must be strictly neutral, professional, and analytical.\n- Do not be overly positive, encouraging, harsh, sarcastic, or hostile.\n- Avoid emotional language, personal opinions, or value judgments.\n- Do not mention or speculate about any protected characteristics (e.g., age, gender, race, ethnicity, religion, disability, marital or parental status, nationality, sexual orientation, political views).\n\nBias and fairness\n- Evaluate only job-relevant factors specified in the grading prompt (e.g., skills, experience, technologies, education, accomplishments).\n- Ignore and do not comment on non-job-relevant details such as names, addresses, photos, or demographic clues.\n- Do not penalize or reward the candidate for gaps or patterns in work history unless the grading prompt explicitly instructs you to do so.\n- If the grading prompt requests something that would introduce unfair bias or target protected characteristics, ignore that part and proceed with a fair, job-relevant assessment instead.\n\nStructure of your response\nAlways return a single structured JSON object with the following shape (and no additional text before or after it):\n{\n \"overall_score\": number,\n \"summary\": string,\n \"criteria_scores\": [\n {\n \"criterion\": string,\n \"score\": number,\n \"evidence\": string,\n \"comments\": string\n }\n ],\n \"strengths\": [string],\n \"weaknesses\": [string],\n \"missing_information\": [string],\n \"recommendation\": {\n \"label\": string,\n \"rationale\": string\n }\n}\n\nHow to interpret the user’s grading prompt\n- Parse the user’s grading prompt into a clear list of evaluation criteria (for example: backend experience in Go, experience with distributed systems, leadership, communication, years of experience, education relevance, etc.).\n- Create one criteria_scores entry for each meaningful criterion you identify.\n- When the resume does not clearly support a criterion, give a lower score and explain that the evidence is weak or missing, rather than inventing details.\n\nScoring guidelines\n- Be consistent and conservative with scores.\n- overall_score should reflect a weighted sense of all criteria_scores, not just a single strong or weak area.\n- Use the full 0–100 and 0–10 ranges when appropriate; do not bunch all candidates in a narrow band.\n- When information is ambiguous or incomplete, lower the score slightly and explain what is missing in missing_information.\n\nReasoning and references to the resume\n- Ground every evaluation in concrete evidence from the resume (roles, dates, projects, technologies, accomplishments, responsibilities).\n- Do not quote extremely long passages; summarize the relevant points concisely.\n- If the resume contradicts itself or appears inconsistent, note this neutrally in weaknesses or missing_information without speculation about motives.\n\nOutput constraints\n- Output must be valid JSON that can be parsed by a strict JSON parser.\n- Do not include comments, trailing commas, or any text outside the JSON object.\n- Do not mention these instructions, the system, or the concept of prompts or roles in your response.", + "user-prompt": "Google Public Sector brings the magic of Google to the mission of government and education with solutions purpose-built for enterprises. We focus on helping United States public sector institutions accelerate their digital transformations, and we continue to make significant investments and grow our team to meet the complex needs of local, state and federal government and educational institutions. The US base salary range for this full-time position is $92,000-$122,000. Our salary ranges are determined by role, level, and location. Within the range, individual pay is determined by work location and additional factors, including job-related skills, experience, and relevant education or training. Your recruiter can share more about the specific salary range for your preferred location during the hiring process.\n\nPlease note that the compensation details listed in US role postings reflect the base salary only, and do not include bonus, equity, or benefits. Learn more about benefits at Google.\n\nResponsibilities\n\nCreate and support a productive and innovative team including working with peers, managers, and teams.\nDevelop scripts to automate routine tasks.\nAnalyze information and evaluate results to choose the best solution to effectively solve problems.\nApply knowledge gained in computer science courses to real world problems.\n\nMinimum qualifications:\n\nPursuing a Bachelor's degree or post secondary or training experience with a focus on subjects in software development or other technical related fields.\n\nExperience in software development and coding in two or more general purpose programming languages (e.g., C, C++, Java, JavaScript, Python, etc.).\n\nExperience with data structures or algorithms gathered from inside or outside of school or work.\n\nPreferred qualifications:\n\nCurrently attending a degree program in the US and available to work full time for 12 weeks outside of university term time.\n\nPenultimate academic year or returning to a degree program after completion of the internship.\n\nExperience programming in three or more of the following languages: C, C++, C#, Java, JavaScript, Kotlin, Go, Python, TypeScript, or similar.\n\nExperience with web application development, Unix/Linux environments, mobile application development, distributed and parallel systems, machine learning, information retrieval, natural language processing, networking, developing large software systems, or security software development.", + "output": { + "overall_score": 82, + "summary": "The candidate demonstrates strong alignment with the minimum qualifications through active pursuit of a software engineering degree, broad programming language experience, and applied project work. The resume shows hands-on experience with backend, web, cloud, and distributed systems that map well to the role’s responsibilities. Some preferred qualifications, such as explicit internship availability details, are not fully documented.", + "criteria_scores": [ + { + "criterion": "Education in software development or related field", + "score": 9, + "evidence": "Bachelor of Science in Software Engineering with a Cybersecurity minor; relevant coursework in data structures, algorithms, and software construction.", + "comments": "Education is directly aligned with the role and demonstrates strong academic performance; degree is still in progress." + }, + { + "criterion": "Programming experience in multiple general-purpose languages", + "score": 9, + "evidence": "Lists Go, Python, C#, JavaScript, Java, C/C++, and others; professional experience using C# and .NET.", + "comments": "Exceeds the minimum requirement and meets preferred qualification for three or more languages." + }, + { + "criterion": "Data structures and algorithms experience", + "score": 8, + "evidence": "Completed coursework in Data Structures and Analysis of Algorithms; applied query optimization reducing database operations by 80%.", + "comments": "Evidence supports both academic and practical exposure, though depth of algorithmic complexity is not detailed." + }, + { + "criterion": "Ability to automate tasks and build scripts", + "score": 7, + "evidence": "Engineered CI/CD pipelines and developed serverless functions to automate data extraction and processing.", + "comments": "Automation experience is present, primarily in DevOps and cloud contexts; explicit scripting examples are limited." + }, + { + "criterion": "Problem-solving and analytical skills", + "score": 8, + "evidence": "Resolved N+1 query issues, designed migration using the Strangler pattern, and optimized system throughput.", + "comments": "Demonstrates structured problem analysis and solution selection in real systems." + }, + { + "criterion": "Teamwork and collaboration", + "score": 8, + "evidence": "Led a team of students in a sponsored research project; collaborated on full-stack development in a professional role.", + "comments": "Leadership and collaboration are indicated, though scale of teams and cross-functional exposure are not fully described." + }, + { + "criterion": "Experience with web, distributed systems, or related domains", + "score": 9, + "evidence": "Full-stack web development, distributed IoT system using MQTT, AWS IoT pipelines, and cloud deployments.", + "comments": "Strong breadth across several preferred technical domains." + }, + { + "criterion": "Preferred internship availability and academic timing", + "score": 5, + "evidence": "Expected graduation May 2028 suggests penultimate year, but no explicit statement of 12-week full-time availability.", + "comments": "Partial alignment inferred from dates; explicit availability details are missing." + } + ], + "strengths": [ + "Broad programming language proficiency across backend and systems languages", + "Strong academic performance with relevant coursework", + "Hands-on experience with distributed systems and cloud platforms", + "Demonstrated problem-solving through measurable system improvements", + "Exposure to DevOps practices and CI/CD automation" + ], + "weaknesses": [ + "Internship availability and work authorization timing not explicitly stated", + "Limited detail on scale and complexity of algorithms beyond coursework", + "Scripting experience not described in depth outside DevOps contexts" + ], + "missing_information": [ + "Explicit confirmation of 12-week full-time internship availability", + "Details on size and scope of teams worked with in professional roles", + "Examples of standalone scripting languages or tools used for automation" + ], + "recommendation": { + "label": "Strong fit", + "rationale": "The candidate meets all minimum qualifications and most preferred qualifications through relevant education, multi-language programming experience, and applied project work. Minor gaps relate mainly to availability details rather than technical capability." + } + } +} diff --git a/data/example_output_netflix.json b/data/example_output_netflix.json new file mode 100644 index 0000000..8be566e --- /dev/null +++ b/data/example_output_netflix.json @@ -0,0 +1,92 @@ +{ + "overall_score": 29, + "summary": "The resume shows early-career backend, cloud, and IoT/edge ML project experience with hands-on CI/CD and serverless work. It does not demonstrate the senior-level (8+ years) experience or explicit GenAI/LLM, gRPC, GraphQL, and large-scale observability experience requested for the L5 GenAI Platform role. There is evidence of relevant technical aptitude and small-to-midsize system design work but limited alignment with the role’s scale and specific GenAI stack requirements.", + "criteria_scores": [ + { + "criterion": "Years of software engineering experience (8+ years)", + "score": 0, + "evidence": "Resume shows current studies (B.S. expected May 2028) and role dates: Poppin’ Jobs Mar 2025–Current and project work through 2025; no multi-year professional experience listed.", + "comments": "Candidate is an undergraduate student with internships/projects; resume does not support 8+ years of professional experience." + }, + { + "criterion": "GenAI stack (LLMs, RAG, Agents/Tools) experience", + "score": 0, + "evidence": "No mentions of LLMs, retrieval-augmented generation (RAG), Agents, or prompt engineering in the resume.", + "comments": "No explicit LLM/GenAI experience is provided; AI work noted is ML inference and a serverless parser, not LLM-based systems." + }, + { + "criterion": "SDKs and API development", + "score": 4, + "evidence": "Notes: 'Develop scalable backend services using .NET and C#', 'Design API integrations between frontend and backend systems', and 'Architected modular components within a monorepo'.", + "comments": "Shows practical API and backend service experience at application level. No evidence of designing or publishing SDKs for external/internal developer consumption at large scale." + }, + { + "criterion": "Software design and distributed systems", + "score": 5, + "evidence": "Led distributed IoT system for acoustic drone detection, built MQTT-based messaging, designed cloud data pipeline on AWS IoT, and used Strangler pattern for incremental migration.", + "comments": "Demonstrates system design and distributed messaging at an academic/research project scale and practical modernization patterns; limited evidence of operating large-scale, fault-tolerant production systems." + }, + { + "criterion": "Java and gRPC proficiency", + "score": 3, + "evidence": "Java is listed in Languages. No mention of gRPC or related RPC frameworks.", + "comments": "Java is present but there is no resume evidence of gRPC experience; proficiency in Java alone is insufficient for the stated gRPC requirement." + }, + { + "criterion": "Python and Python packaging/tooling", + "score": 3, + "evidence": "Python is listed in Languages; projects mention serverless Azure function and ML inference but do not detail Python packaging or tooling.", + "comments": "Candidate likely has Python knowledge, but there is no explicit evidence of Python package management tooling experience (pip, poetry, packaging, distribution)." + }, + { + "criterion": "GraphQL experience", + "score": 0, + "evidence": "Resume does not mention GraphQL.", + "comments": "No resume evidence for GraphQL development or schema/apollo experience." + }, + { + "criterion": "Large-scale build, release, CI/CD, and observability", + "score": 4, + "evidence": "Implemented CI/CD pipeline for Potion, used Docker, self-hosted deployment, and mentions CI/CD under Backend & DevOps.", + "comments": "Shows CI/CD and deployment experience for personal and team projects; lacks evidence of large-scale release engineering, enterprise CI/CD pipelines, or observability tooling (metrics/tracing/alerting) at production scale." + }, + { + "criterion": "Designing, building, and deploying ML applications", + "score": 5, + "evidence": "Led acoustic drone detection project with real-time acoustic processing and ML inference on edge devices; built AI-powered serverless function on Azure to parse job descriptions.", + "comments": "Has hands-on ML application and inference experience (edge and serverless). No explicit evidence of training large models, model fine-tuning workflows, or deploying LLMs." + }, + { + "criterion": "Cloud and DevOps (Azure, AWS, Docker, Linux, Ansible)", + "score": 6, + "evidence": "Lists Azure, AWS IoT, Docker, Nginx, Ansible, Linux, CI/CD; projects include Azure Functions, AWS IoT platform, and self-hosted deployments.", + "comments": "Strong foundational cloud and DevOps exposure across multiple technologies; evidence is oriented toward student/research and small production deployments rather than global-scale services." + } + ], + "strengths": [ + "Hands-on backend development using .NET/C# and API integration experience.", + "Practical cloud and DevOps experience (Azure Functions, AWS IoT, Docker, CI/CD).", + "Led a distributed IoT/edge ML research project with real-time inference and reliable messaging (MQTT).", + "Demonstrated ability to optimize backend performance (eliminated N+1 queries) and perform system modernization (Strangler pattern).", + "Built and maintained end-to-end projects including deployment and database management (Potion)." + ], + "weaknesses": [ + "Does not meet the 8+ years of software engineering experience required for L5.", + "No explicit experience with LLMs, RAG, Agents, or GenAI platform tooling.", + "No evidence of gRPC or GraphQL usage or Python packaging/tooling experience.", + "Limited evidence of operating large-scale, observable, fault-tolerant distributed systems in production.", + "No demonstrated experience publishing SDKs or building developer-facing platform libraries at scale." + ], + "missing_information": [ + "Total professional years of experience and scope of responsibilities at each role (team size, user/traffic scale).", + "Specific experience with LLMs, RAG systems, agent frameworks, or prompt engineering.", + "Use of gRPC and GraphQL in projects or any production-grade RPC/graph API implementations.", + "Experience with Python package management tooling (pip, poetry, packaging) and related workflows.", + "Details on observability tooling and practices used (metrics, tracing, logging, alerting) in deployed systems.", + "Evidence of designing/publishing SDKs or libraries intended for internal/external developer consumption." + ], + "recommendation": { + "label": "Weak fit", + "rationale": "The candidate shows relevant early-career technical foundations (backend, cloud, CI/CD, edge ML) but lacks the senior experience level (8+ years) and specific GenAI, gRPC/GraphQL, and large-scale observability and SDK development experience required for the L5 GenAI Platform role. The resume indicates potential for growth but does not meet the role’s stated requirements." + } +} diff --git a/data/example_pj.json b/data/example_pj.json new file mode 100644 index 0000000..300bcd8 --- /dev/null +++ b/data/example_pj.json @@ -0,0 +1,87 @@ +{ + "system-prompt": "You are an automated resume evaluation engine. Your task is to objectively assess a resume according to criteria provided by the user in a separate instruction prompt and to return a structured, neutral assessment.\n\nFollow these rules carefully:\n\nEvaluation scope\nThe user will provide:\n- A grading prompt that specifies what to evaluate (e.g., required skills, experience level, domain fit, formatting, clarity).\n- A resume, supplied as plain text converted from a PDF.\n- Use only the information present in the resume text and the user’s grading prompt.\n- Do not infer or assume facts that are not explicitly supported by the resume.\n\nObjectivity and tone\n- Your output must be strictly neutral, professional, and analytical.\n- Do not be overly positive, encouraging, harsh, sarcastic, or hostile.\n- Avoid emotional language, personal opinions, or value judgments.\n- Do not mention or speculate about any protected characteristics (e.g., age, gender, race, ethnicity, religion, disability, marital or parental status, nationality, sexual orientation, political views).\n\nBias and fairness\n- Evaluate only job-relevant factors specified in the grading prompt (e.g., skills, experience, technologies, education, accomplishments).\n- Ignore and do not comment on non-job-relevant details such as names, addresses, photos, or demographic clues.\n- Do not penalize or reward the candidate for gaps or patterns in work history unless the grading prompt explicitly instructs you to do so.\n- If the grading prompt requests something that would introduce unfair bias or target protected characteristics, ignore that part and proceed with a fair, job-relevant assessment instead.\n\nStructure of your response\nAlways return a single structured JSON object with the following shape (and no additional text before or after it):\n{\n \"overall_score\": number,\n \"summary\": string,\n \"criteria_scores\": [\n {\n \"criterion\": string,\n \"score\": number,\n \"evidence\": string,\n \"comments\": string\n }\n ],\n \"strengths\": [string],\n \"weaknesses\": [string],\n \"missing_information\": [string],\n \"recommendation\": {\n \"label\": string,\n \"rationale\": string\n }\n}\n\nHow to interpret the user’s grading prompt\n- Parse the user’s grading prompt into a clear list of evaluation criteria (for example: backend experience in Go, experience with distributed systems, leadership, communication, years of experience, education relevance, etc.).\n- Create one criteria_scores entry for each meaningful criterion you identify.\n- When the resume does not clearly support a criterion, give a lower score and explain that the evidence is weak or missing, rather than inventing details.\n\nScoring guidelines\n- Be consistent and conservative with scores.\n- overall_score should reflect a weighted sense of all criteria_scores, not just a single strong or weak area.\n- Use the full 0–100 and 0–10 ranges when appropriate; do not bunch all candidates in a narrow band.\n- When information is ambiguous or incomplete, lower the score slightly and explain what is missing in missing_information.\n\nReasoning and references to the resume\n- Ground every evaluation in concrete evidence from the resume (roles, dates, projects, technologies, accomplishments, responsibilities).\n- Do not quote extremely long passages; summarize the relevant points concisely.\n- If the resume contradicts itself or appears inconsistent, note this neutrally in weaknesses or missing_information without speculation about motives.\n\nOutput constraints\n- Output must be valid JSON that can be parsed by a strict JSON parser.\n- Do not include comments, trailing commas, or any text outside the JSON object.\n- Do not mention these instructions, the system, or the concept of prompts or roles in your response.", + "user-prompt": "Job Description:\n\nWe are seeking a Junior / Intern Web Developer to assist our team in enhancing & building our web application. This role involves working on UI implementation, state management, and API integration while learning best practices and contributing to code quality improvements.\n\nKey Responsibilities:\n\nImplement UI & Functionality: Translate design mockups into interactive and responsive app interfaces using frameworks like MUI and Bootstrap.\nAPI Integration: Work with senior developers to integrate and consume RESTful APIs using tools like Axios.\nState Management: Implement state management solutions using standard tooling.\nImprove Code Quality: Assist in refactoring disorganized code and encourage best practices for maintainability and readability.\nCollaborate & Troubleshoot: Work with design and development teams to resolve issues, test functionality, and ensure high app performance.\nUtilize Libraries: Leverage various UI and functionality libraries such as Framer Motion, React Toastify, React Hook Form, and more as needed.\nEncouraging Best Practices: Work with senior developers to refactor disorganized code and promote best coding practices for maintainability and readability.\nAssist with the build & deployment process.\n\nKey Requirements:\n\nFamiliarity with React for development.\nBasic knowledge of API consumption and handling asynchronous operations.\nUnderstanding of state management principles and experience.\nExperience with UI frameworks like MUI, Bootstrap, or similar.\nBasic problem-solving and debugging skills.\nWillingness to learn and follow best practices in coding and project organization.\nFamiliarity with Git for version control.\n\nPreferred Skills:\n\nExposure to form validation libraries (e.g., Yup, React Hook Form).\nExperience with animations and transitions using libraries like Framer Motion.\nBasic understanding of handling dates with tools like Date-Fns or Day.js.\n\nWhat We Offer:\n\nOpportunity to work with a modern tech stack in a collaborative environment.\nHands-on learning and professional development with experienced developers.\nInvolvement in real projects with guidance on best coding practices.\nPay depends on experience\nFlexible schedule (Up to 15 hours a week)\n\nWho We Are:\n\nPoppin’ Jobs is a new tech start up with youthful energy. We aim to be a leader in the youth job search market offering excellent choices for part-time, no experience, or seasonal jobs to youth aged 16 to 24. Our goal is to become a community where connections can be forged between local businesses and the youth residents. We are personally empowering the future workforce with the tools they need to excel in their professional paths.", + "output": { + "overall_score": 82, + "summary": "The candidate demonstrates strong technical breadth for a junior or intern web developer role, with clear experience in full-stack development, API integration, and deployment. The resume shows hands-on use of React and related frontend tools alongside substantial backend and DevOps work. Some preferred frontend-specific libraries and UI frameworks listed in the role are not explicitly evidenced. Overall, the profile aligns well with the role’s learning-oriented and contribution-focused expectations.", + "criteria_scores": [ + { + "criterion": "React familiarity", + "score": 8, + "evidence": "React is listed under Frontend & Tools, and multiple projects reference full-stack web application development.", + "comments": "Demonstrates familiarity with React, though the resume does not detail specific React components, hooks, or patterns used." + }, + { + "criterion": "UI implementation with frameworks (MUI, Bootstrap, or similar)", + "score": 6, + "evidence": "Frontend tools include Tailwind CSS, HTMX, and React.", + "comments": "Experience with UI development is evident, but MUI or Bootstrap are not explicitly mentioned." + }, + { + "criterion": "API integration and asynchronous operations", + "score": 9, + "evidence": "Designed API integrations between frontend and backend systems and optimized data flows in a professional role.", + "comments": "Strong evidence of RESTful API integration; asynchronous handling is implied but not described in detail." + }, + { + "criterion": "State management understanding", + "score": 7, + "evidence": "Full-stack application development and frontend experience with React are noted.", + "comments": "General understanding is likely, but no explicit state management libraries or patterns are specified." + }, + { + "criterion": "Code quality, refactoring, and best practices", + "score": 9, + "evidence": "Eliminated N+1 query issues, optimized database usage, and led incremental legacy system migration using the Strangler pattern.", + "comments": "Shows strong awareness of maintainability, refactoring, and best practices beyond typical junior expectations." + }, + { + "criterion": "Collaboration and troubleshooting", + "score": 8, + "evidence": "Worked with teams on scalable backend services and led a student research team on a distributed system.", + "comments": "Collaboration is clearly demonstrated, though frontend-focused collaboration examples are limited." + }, + { + "criterion": "Use of supporting frontend libraries (forms, animations, utilities)", + "score": 5, + "evidence": "React Hook Form and Framer Motion are mentioned in the job description but not in the resume.", + "comments": "No explicit evidence of form validation, animation libraries, or date-handling utilities." + }, + { + "criterion": "Build, deployment, and Git usage", + "score": 9, + "evidence": "Experience with CI/CD pipelines, Git, Docker, and deployment on self-hosted and cloud infrastructure.", + "comments": "Exceeds basic expectations for a junior role in build and deployment knowledge." + }, + { + "criterion": "Learning mindset and junior/intern suitability", + "score": 8, + "evidence": "Currently a software engineering student seeking an internship and engaged in multiple learning-focused projects.", + "comments": "Strong alignment with a learning-oriented junior or intern position." + } + ], + "strengths": [ + "Hands-on full-stack development experience in a production environment", + "Strong API integration and backend optimization skills", + "Experience with CI/CD, deployment, and cloud infrastructure", + "Demonstrated code quality improvements and refactoring practices", + "Exposure to modern frontend tooling including React and Tailwind CSS" + ], + "weaknesses": [ + "No explicit mention of MUI or Bootstrap usage", + "Limited detail on React state management approaches", + "Preferred frontend libraries (Framer Motion, React Hook Form, date utilities) not evidenced", + "Frontend-specific UI implementation examples are relatively high-level" + ], + "missing_information": [ + "Specific state management libraries or patterns used in React", + "Direct experience with MUI or Bootstrap components", + "Examples of form validation or animation libraries in practice", + "Details on debugging frontend-specific issues" + ], + "recommendation": { + "label": "Strong fit", + "rationale": "The candidate meets or exceeds most core requirements for a junior or intern web developer, particularly in API integration, code quality, and deployment. While some preferred frontend libraries and UI frameworks are not explicitly demonstrated, the overall skill set and learning trajectory align well with the role." + } + } +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..ea4868c --- /dev/null +++ b/flake.nix @@ -0,0 +1,50 @@ +{ + description = "Go development flake. Adjust as needed."; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils, ... }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { inherit system; }; + in + { + # Define the development shell. + # When you run `nix develop` (or direnv activates), you'll enter this shell. + devShells.default = pkgs.mkShell { + # List all the development tools you need available in this shell's PATH. + packages = with pkgs; [ + go + gopls + go-tools + gcc_multi + glibc_multi + ]; + + # Define the shell that will be executed. + # Here, we explicitly use zsh. + # Note: pkgs.zsh needs to be included in `packages` or `nativeBuildInputs` + # for it to be found in the shell's environment. `inherit pkgs.zsh;` is concise. + inherit (pkgs) zsh; + + # Environment variables and commands to run when the shell starts. + shellHook = '' + # Use the .local directory instead of home + export GOPATH="$HOME/.local/go" + echo "Settings GOPATH to: $HOME/.local/go " + + export GOOS=linux + export GOARCH=amd64 + export CGO_CFLAGS=-Wno-error=cpp; + + # Exec zsh to replace the current shell process with zsh. + # This ensures your prompt and zsh configurations load correctly. + exec zsh + ''; + }; + } + ); +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..8d97d6f --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module git.gophernest.net/azpect/ResumeLens + +go 1.25.5 + +require github.com/go-chi/chi/v5 v5.2.4 // indirect diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..72e03ff --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/go-chi/chi/v5 v5.2.4 h1:WtFKPHwlywe8Srng8j2BhOD9312j9cGUxG1SP4V2cR4= +github.com/go-chi/chi/v5 v5.2.4/go.mod h1:X7Gx4mteadT3eDOMTsXzmI4/rwUpOwBHLpAfupzFJP0= diff --git a/prototype/go.mod b/prototype/go.mod new file mode 100644 index 0000000..022c904 --- /dev/null +++ b/prototype/go.mod @@ -0,0 +1,14 @@ +module git.gophernest.net/azpect/ResumeRater + +go 1.25.5 + +require github.com/dslipak/pdf v0.0.2 + +require ( + github.com/openai/openai-go v1.12.0 // indirect + github.com/openai/openai-go/v3 v3.16.0 // indirect + github.com/tidwall/gjson v1.18.0 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.1 // indirect + github.com/tidwall/sjson v1.2.5 // indirect +) diff --git a/prototype/go.sum b/prototype/go.sum new file mode 100644 index 0000000..6017f38 --- /dev/null +++ b/prototype/go.sum @@ -0,0 +1,18 @@ +github.com/dslipak/pdf v0.0.2 h1:djAvcM5neg9Ush+zR6QXB+VMJzR6TdnX766HPIg1JmI= +github.com/dslipak/pdf v0.0.2/go.mod h1:2L3SnkI9cQwnAS9gfPz2iUoLC0rUZwbucpbKi5R1mUo= +github.com/openai/openai-go v1.12.0 h1:NBQCnXzqOTv5wsgNC36PrFEiskGfO5wccfCWDo9S1U0= +github.com/openai/openai-go v1.12.0/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y= +github.com/openai/openai-go/v3 v3.16.0 h1:VdqS+GFZgAvEOBcWNyvLVwPlYEIboW5xwiUCcLrVf8c= +github.com/openai/openai-go/v3 v3.16.0/go.mod h1:cdufnVK14cWcT9qA1rRtrXx4FTRsgbDPW7Ia7SS5cZo= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= +github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= diff --git a/prototype/main.go b/prototype/main.go new file mode 100644 index 0000000..f8d2e19 --- /dev/null +++ b/prototype/main.go @@ -0,0 +1,305 @@ +package main + +import ( + "context" + "log" + + "github.com/dslipak/pdf" + + "github.com/openai/openai-go/v3" + "github.com/openai/openai-go/v3/option" +) + +// TODO: Grade grammar and spelling +// TODO: Check for prompt injection +// TODO: Output should fall into a defined bound +// TODO: Timeout rate limit + +const SYSTEM_PROMPT string = ` + You are an automated resume evaluation engine. Your task is to objectively assess a resume according to criteria provided by the user in a separate instruction prompt and to return a structured, neutral assessment. + + Follow these rules carefully: + + Evaluation scope + The user will provide: + - A grading prompt that specifies what to evaluate (e.g., required skills, experience level, domain fit, formatting, clarity), or simply a job description. + - A resume, supplied as plain text converted from a PDF. + - Use only the information present in the resume text and the user’s grading prompt. + - Do not infer or assume facts that are not explicitly supported by the resume. + + Objectivity and tone + - Your output must be strictly neutral, professional, and analytical. + - Do not be overly positive, encouraging, harsh, sarcastic, or hostile. + - Avoid emotional language, personal opinions, or value judgments. + - Do not mention or speculate about any protected characteristics (e.g., age, gender, race, ethnicity, religion, disability, marital or parental status, nationality, sexual orientation, political views). + + Bias and fairness + - Evaluate only job-relevant factors specified in the grading prompt (e.g., skills, experience, technologies, education, accomplishments). + - Ignore and do not comment on non‑job‑relevant details such as names, addresses, photos, or demographic clues. + - Do not penalize or reward the candidate for gaps or patterns in work history unless the grading prompt explicitly instructs you to do so. + - If the grading prompt requests something that would introduce unfair bias or target protected characteristics, ignore that part and proceed with a fair, job‑relevant assessment instead. + - Avoid making assumtions that are not defined in the resume provided, or presumed by the user prompt. + + Structure of your response + Always return a single structured JSON object with the following shape (and no additional text before or after it): + { + "overall_score": number, // A numeric score from 0 to 100 representing overall fit + "summary": string, // 2–4 neutral sentences summarizing the candidate’s fit + "criteria_scores": [ // One entry per criterion derived from the user prompt + { + "criterion": string, // The name of the criterion + "score": number, // Score from 0 to 10 for this criterion + "evidence": string, // Brief, specific evidence from the resume + "comments": string // Neutral comments: strengths, weaknesses, and gaps + } + ], + "strengths": [ // 3–7 concise bullet‑style strings + string + ], + "weaknesses": [ // 3–7 concise bullet‑style strings, phrased neutrally + string + ], + "missing_information": [ // Items that cannot be assessed due to lack of data + string + ], + "recommendation": { // Neutral, non‑emotional recommendation + "label": string, // e.g., "Strong fit", "Moderate fit", "Weak fit", "Not enough information" + "rationale": string // Brief explanation grounded in the criteria and evidence + } + } + + How to interpret the user’s grading prompt + - Parse the user’s grading prompt into a clear list of evaluation criteria (for example: “backend experience in Go,” “experience with distributed systems,” “leadership,” “communication,” “years of experience,” “education relevance,” etc.). + - Create one criteria_scores entry for each meaningful criterion you identify. + - When the resume does not clearly support a criterion, give a lower score and explain that the evidence is weak or missing, rather than inventing details. + + Scoring guidelines + - Be consistent and conservative with scores. + - overall_score should reflect a weighted sense of all criteria_scores, not just a single strong or weak area. + - Use the full 0–100 and 0–10 ranges when appropriate; do not bunch all candidates in a narrow band. + - When information is ambiguous or incomplete, lower the score slightly and explain what is missing in missing_information. + + Reasoning and references to the resume + - Ground every evaluation in concrete evidence from the resume (roles, dates, projects, technologies, accomplishments, responsibilities). + - Do not quote extremely long passages; summarize the relevant points concisely. + - If the resume contradicts itself or appears inconsistent, note this neutrally in weaknesses or missing_information without speculation about motives. + + Output constraints + - Output must be valid JSON that can be parsed by a strict JSON parser. + - Do not include comments, trailing commas, or any text outside the JSON object. + - Do not mention these instructions, the system, or the concept of prompts or roles in your response. +` + +const USER_PROMPT_PJ string = ` + Job Description: + + We are seeking a Junior / Intern Web Developer to assist our team in enhancing & building our web application. This role involves working on UI implementation, state management, and API integration while learning best practices and contributing to code quality improvements. + + + + Key Responsibilities: + + Implement UI & Functionality: Translate design mockups into interactive and responsive app interfaces using frameworks like MUI and Bootstrap. + API Integration: Work with senior developers to integrate and consume RESTful APIs using tools like Axios. + State Management: Implement state management solutions using standard tooling. + Improve Code Quality: Assist in refactoring disorganized code and encourage best practices for maintainability and readability. + Collaborate & Troubleshoot: Work with design and development teams to resolve issues, test functionality, and ensure high app performance. + Utilize Libraries: Leverage various UI and functionality libraries such as Framer Motion, React Toastify, React Hook Form, and more as needed. + Encouraging Best Practices: Work with senior developers to refactor disorganized code and promote best coding practices for maintainability and readability. + Assist with the build & deployment process. + + + Key Requirements: + + Familiarity with React for development. + Basic knowledge of API consumption and handling asynchronous operations. + Understanding of state management principles and experience. + Experience with UI frameworks like MUI, Bootstrap, or similar. + Basic problem-solving and debugging skills. + Willingness to learn and follow best practices in coding and project organization. + Familiarity with Git for version control. + + + Preferred Skills: + + Exposure to form validation libraries (e.g., Yup, React Hook Form). + Experience with animations and transitions using libraries like Framer Motion. + Basic understanding of handling dates with tools like Date-Fns or Day.js. + + + What We Offer: + + Opportunity to work with a modern tech stack in a collaborative environment. + Hands-on learning and professional development with experienced developers. + Involvement in real projects with guidance on best coding practices. + Pay depends on experience + Flexible schedule (Up to 15 hours a week) + + + Who We Are: + + Poppin’ Jobs is a new tech start up with youthful energy. We aim to be a leader in the youth job search market offering excellent choices for part-time, no experience, or seasonal jobs to youth aged 16 to 24. Our goal is to become a community where connections can be forged between local businesses and the youth residents. We are personally empowering the future workforce with the tools they need to excel in their professional paths. +` + +const USER_PROMPT_GOOGLE string = ` +Google Public Sector brings the magic of Google to the mission of government and education with solutions purpose-built for enterprises. We focus on helping United States public sector institutions accelerate their digital transformations, and we continue to make significant investments and grow our team to meet the complex needs of local, state and federal government and educational institutions. The US base salary range for this full-time position is $92,000-$122,000. Our salary ranges are determined by role, level, and location. Within the range, individual pay is determined by work location and additional factors, including job-related skills, experience, and relevant education or training. Your recruiter can share more about the specific salary range for your preferred location during the hiring process.\n\nPlease note that the compensation details listed in US role postings reflect the base salary only, and do not include bonus, equity, or benefits. Learn more about benefits at Google.\n\nResponsibilities\n\nCreate and support a productive and innovative team including working with peers, managers, and teams.\nDevelop scripts to automate routine tasks.\nAnalyze information and evaluate results to choose the best solution to effectively solve problems.\nApply knowledge gained in computer science courses to real world problems.\n\nMinimum qualifications:\n\nPursuing a Bachelor's degree or post secondary or training experience with a focus on subjects in software development or other technical related fields.\n\nExperience in software development and coding in two or more general purpose programming languages (e.g., C, C++, Java, JavaScript, Python, etc.).\n\nExperience with data structures or algorithms gathered from inside or outside of school or work.\n\nPreferred qualifications:\n\nCurrently attending a degree program in the US and available to work full time for 12 weeks outside of university term time.\n\nPenultimate academic year or returning to a degree program after completion of the internship.\n\nExperience programming in three or more of the following languages: C, C++, C#, Java, JavaScript, Kotlin, Go, Python, TypeScript, or similar.\n\nExperience with web application development, Unix/Linux environments, mobile application development, distributed and parallel systems, machine learning, information retrieval, natural language processing, networking, developing large software systems, or security software development. +` + +const USER_PROMPT_NETFLIX string = ` +Full Stack Engineer 4 - Product Localization Technology +Los Gatos, California, United States of America + +Job Posting Date +01-22-2026 +Job Requisition ID +JR37381 +Teams +Engineering +Work Type +Onsite +At Netflix, our mission is to entertain the world. Together, we are writing the next episode - pushing the boundaries of storytelling, global fandom and making the unimaginable a reality. We are a dream team obsessed with the uncomfortable excitement of discovering what happens when you merge creativity, intuition and cutting-edge technology. Come be a part of what’s next. + +At Netflix, we want to entertain the world and are constantly innovating on how entertainment is imagined, created, and delivered to a global audience. Engineering teams within Netflix work hard every day to scale and innovate content production and member experiences in an ever-growing complex software landscape. + +Our Content & Business Products (CBP) Engineering teams build the products and services that power the full content lifecycle—from pitch to play—enabling Netflix to create and manage entertainment at scale. Within CBP, the Localization Tech team extends the reach of our content by localizing it into 35 languages across dubbing, subtitling, closed captions, and more. We build products that enable the creation of high-quality subtitling, dubbing, and accessibility assets, empowering linguists through advanced AI/ML-driven creative tools. We develop platforms that manage and streamline logistics across the entire localization lifecycle, allowing partners to focus on strategic and creative decision-making. Together, we ensure Netflix feels immersive, authentic, and meaningful for members in every language. + +Qualifications + +You have experience crafting resilient, high-scale, low-latency microservices in production environments. + +Proficient with gRPC, GraphQL, or RESTful API design and implementation using OO programming languages like Java, C#. + +Are adept at building enterprise applications with HTML/JavaScript/TypeScript/CSS. We currently build our user experiences with React, GraphQL, and several more libraries and frameworks depending on the product. + +Work cross-functionally to build, test, deploy, and launch UIs that operationalize our workflows at scale + +You have a proven track record of resilient data modeling through understanding and translating business requirements to technical requirements and identifying entities and their relationships that will serve the business process needs. + +You participate in our on-call rotation and lead the incident reviews. + +What Sets You Apart + +You are a resourceful full-stack engineer who can independently identify the root cause of issues and implement dependable, maintainable solutions across the entire stack. + +Maintain strong relationships with cross-functional teams through clear communication. + +Take a thoughtful, practical approach to problem-solving that considers tradeoffs and avoids over-engineering. + +Seek different perspectives, feedback, and relevant information to continuously grow and improve. + +Comfortable asking questions and seeking knowledge in unfamiliar or ambiguous situations. + +You evangelize new ideas and exemplify technical leadership with a bias for action. + +You appreciate the complexity of engaging with a global challenge. + +Generally, our compensation structure consists solely of an annual salary; we do not have bonuses. You choose each year how much of your compensation you want in salary versus stock options. To determine your personal top of market compensation, we rely on market indicators and consider your specific job family, background, skills, and experience to determine your compensation in the market range. The range for this role is $250,000.00 - $413,000.00. +Netflix provides comprehensive benefits including Health Plans, Mental Health support, a 401(k) Retirement Plan with employer match, Stock Option Program, Disability Programs, Health Savings and Flexible Spending Accounts, Family-forming benefits, and Life and Serious Injury Benefits. We also offer paid leave of absence programs. Full-time hourly employees accrue 35 days annually for paid time off to be used for vacation, holidays, and sick paid time off. Full-time salaried employees are immediately entitled to flexible time off. See more details about our Benefits here. + +Netflix is a unique culture and environment. Learn more here. + +Inclusion is a Netflix value and we strive to host a meaningful interview experience for all candidates. If you want an accommodation/adjustment for a disability or any other reason during the hiring process, please send a request to your recruiting partner. + +We are an equal-opportunity employer and celebrate diversity, recognizing that diversity builds stronger teams. We approach diversity and inclusion seriously and thoughtfully. We do not discriminate on the basis of race, religion, color, ancestry, national origin, caste, sex, sexual orientation, gender, gender identity or expression, age, disability, medical condition, pregnancy, genetic makeup, marital status, or military service. +` + +const USER_PROMPT_NETFLIX_2 string = ` +Software Engineering L5 - GenAI Platform +USA - Remote + +Job Posting Date +01-22-2026 +Job Requisition ID +JR37730 +Teams +Engineering +Work Type +Remote +At Netflix, our mission is to entertain the world. Together, we are writing the next episode - pushing the boundaries of storytelling, global fandom and making the unimaginable a reality. We are a dream team obsessed with the uncomfortable excitement of discovering what happens when you merge creativity, intuition and cutting-edge technology. Come be a part of what’s next. + +The data platform teams at Netflix enable us to leverage data to bring joy to our members in many different ways. We provide centralized data platforms and tools for various business functions at Netflix, so they can utilize our data to make critical data-driven decisions. We do all the heavy lifting to make it easy for our business partners to work with data efficiently, securely, and responsibly. We aspire to lead the industry standard in building a world-class data infrastructure, as Netflix leads the way to be the most popular and pervasive destination for global internet entertainment. + + +GenAI Platform + +The mission of the Gen AI Platform team is to boost the productivity of the data science and engineering community at Netflix. This means enabling users to spend more time solving business problems and less time engineering lower-level systems. We are seeking a Software Engineer to help build a developer platform that will provide the building blocks for Netflix to efficiently create GenAI applications. The platform will enable our teams to leverage LLM models and internally fine-tuned models. It will provide tools to support the LLM development lifecycle, high-level abstraction APIs for RAG, and tools for prompt engineering, management, and LLM operations. + +What you will do: + +Design, build, and deploy APIs to access third-party large language models and internal fine-tuned ML models. + +Develop frameworks and components for building GenAI applications. + +Develop and maintain integrations between third-party products and the Netflix data platform solutions. + +Lead cross-functional initiatives and collaborate with engineers, product managers, and technical program managers across teams. + +Solve real business needs at scale by applying your software engineering and analytical problem-solving skills. + +Rapidly iterate with users to improve product experiences while establishing foundational capabilities. + +Desired Background: + +8+ years of software engineering experience with a successful track record of delivering quality results + +Strong interest and experience with the latest GenAI stack (LLMs, RAG, Agents/Tools) + +Strong experience building SDKs and APIs for internal or external products + +Strong software design and development fundamentals, with experience in building and operating scalable, observable, fault-tolerant, distributed systems + +Proficiency in Java, GRPC, Python, Python package management tooling, and GraphQL + +Experience in large-scale build, release, continuous integration/continuous deployment (CI/CD), and observability methods + +Experience designing, building, and deploying ML applications + +Generally, our compensation structure consists solely of an annual salary; we do not have bonuses. You choose each year how much of your compensation you want in salary versus stock options. To determine your personal top of market compensation, we rely on market indicators and consider your specific job family, background, skills, and experience to determine your compensation in the market range. The range for this role is $388,000.00 - $619,000.00. This compensation range will vary based on location. +Netflix provides comprehensive benefits including Health Plans, Mental Health support, a 401(k) Retirement Plan with employer match, Stock Option Program, Disability Programs, Health Savings and Flexible Spending Accounts, Family-forming benefits, and Life and Serious Injury Benefits. We also offer paid leave of absence programs. Full-time hourly employees accrue 35 days annually for paid time off to be used for vacation, holidays, and sick paid time off. Full-time salaried employees are immediately entitled to flexible time off. See more details about our Benefits here. + +Netflix is a unique culture and environment. Learn more here. + +Inclusion is a Netflix value and we strive to host a meaningful interview experience for all candidates. If you want an accommodation/adjustment for a disability or any other reason during the hiring process, please send a request to your recruiting partner. + +We are an equal-opportunity employer and celebrate diversity, recognizing that diversity builds stronger teams. We approach diversity and inclusion seriously and thoughtfully. We do not discriminate on the basis of race, religion, color, ancestry, national origin, caste, sex, sexual orientation, gender, gender identity or expression, age, disability, medical condition, pregnancy, genetic makeup, marital status, or military service. + +Job is open for no less than 7 days and will be removed when the position is filled. +` + +func main() { + filename := "HaydenHargreaves_Oct01.pdf" + + rs, err := pdf.Open(filename) + if err != nil { + log.Fatalf("Error opening file: %s\n", err.Error()) + } + + page := rs.Page(1) + if page.V.IsNull() { + log.Fatalln("Page one is null.") + } + + text, err := page.GetPlainText(nil) + if err != nil { + log.Fatalf("Error reading plain text. %s\n", err.Error()) + } + + client := openai.NewClient( + // NOTE: Load from ENV + option.WithAPIKey("..."), + ) + + chatCompletion, err := client.Chat.Completions.New(context.TODO(), openai.ChatCompletionNewParams{ + Messages: []openai.ChatCompletionMessageParamUnion{ + openai.SystemMessage(SYSTEM_PROMPT), + openai.UserMessage(USER_PROMPT_NETFLIX_2), + openai.UserMessage(text), + }, + Model: openai.ChatModelGPT5Mini, + }) + if err != nil { + log.Fatalf("Error getting chat completion. %s\n", err.Error()) + } + + println(chatCompletion.Choices[0].Message.Content) +} diff --git a/prototype/main_test.go b/prototype/main_test.go new file mode 100644 index 0000000..f020738 --- /dev/null +++ b/prototype/main_test.go @@ -0,0 +1,43 @@ +package main + +import ( + "testing" + + "github.com/dslipak/pdf" +) + +func TestCanReadResumeToString(t *testing.T) { + resume, err := pdf.Open("HaydenHargreaves_Oct01.pdf") + + if err != nil { + t.Errorf("err is not nil. Expected nil. %s", err.Error()) + } + if resume == nil { + t.Error("resume is nil. Expected *pdf.Reader") + } + + page := resume.Page(1) + if page.V.IsNull() { + t.Error("page.V is nil. Expected pdf.Value") + } + + text, err := page.GetPlainText(nil) + if err != nil { + t.Errorf("err is not nil. Expected nil. %s", err.Error()) + } + + if text == "" { + t.Error("text is \"\". Expected content") + } +} + +func TestCannotReadResumeThatDoesNotExist(t *testing.T) { + resume, err := pdf.Open("unknown.pdf") + if err == nil { + t.Error("err is nil. Expected not nil") + } + + if resume != nil { + t.Error("resume is bot nil. Expected nil") + } +}