Skip to content

refactor: replace resume-ops API integration with CLI-based approach#644

Open
Rat-S wants to merge 3 commits into
santifer:mainfrom
Rat-S:refactor/cli-resume-ops-integration
Open

refactor: replace resume-ops API integration with CLI-based approach#644
Rat-S wants to merge 3 commits into
santifer:mainfrom
Rat-S:refactor/cli-resume-ops-integration

Conversation

@Rat-S
Copy link
Copy Markdown

@Rat-S Rat-S commented May 13, 2026

Summary

Replaced the API-based resume-ops integration with a direct CLI invocation approach for improved reliability and simplicity.

Changes

Validation

  • npm run doctor: Environment setup issues only (missing cv.md, profile.yml — pre-existing)
  • node verify-pipeline.mjs: Passed
  • node cv-sync-check.mjs: Environment setup issues only (missing cv.md, profile.yml — pre-existing)

Related

N/A

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced resume-ops CLI workflow for tailoring resumes with theme customization and JSON export capabilities.
  • Documentation

    • Added comprehensive guide covering setup, configuration, and application tracking integration for the resume-ops workflow.
  • Chores

    • Updated dependencies with jsonresume-theme-stackoverflow, puppeteer, and resumed.
    • Modified .gitignore to exclude generated workspace and temporary files.

Review Change Stack

deadrat added 3 commits May 13, 2026 12:51
- Replaced API-based resume-ops integration with direct CLI invocation in resume-ops.mjs
- Removed start-resume-ops.mjs (no longer needed with CLI approach)
- Updated package.json scripts to reflect CLI-based workflow
- Updated modes/resume-ops.md documentation for CLI integration
@github-actions
Copy link
Copy Markdown
Contributor

Welcome to career-ops, @Rat-S! Thanks for your first PR.

A few things to know:

  • Tests will run automatically — check the status below
  • Make sure you've linked a related issue (required for features)
  • Read CONTRIBUTING.md if you haven't

We'll review your PR soon. Join our Discord if you have questions.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

📝 Walkthrough

Walkthrough

This PR introduces a complete resume-ops feature: a CLI-driven workflow for tailored resume generation. The implementation adds npm script integration, a Node.js wrapper that orchestrates invocation of an underlying uv-based tool, comprehensive documentation, test fixtures, and artifact exclusion rules to maintain a clean repository.

Changes

Resume-Ops Feature

Layer / File(s) Summary
Feature documentation and mode guide
modes/resume-ops.md
Documents the complete resume-ops pipeline: JD preparation (text or URL extraction), local setup prerequisites, JSON resume generation from source files when needed, tailoring invocation with output paths and optional theme selection, application tracking integration, JSON-to-Career-Ops field mapping, and safety/ethics constraints on content generation.
npm script and dependency setup
package.json
Adds new npm script resume-ops mapping to node resume-ops.mjs, and introduces three new dependencies: jsonresume-theme-stackoverflow, puppeteer, and resumed for resume rendering and PDF generation.
resume-ops Node.js CLI wrapper
resume-ops.mjs
Implements argument parsing for resume file, job description (supports file or inline text), and output path with optional theme flag. Validates inputs, handles temporary file creation for inline JD text, ensures output directory exists, spawns the uv-based resume-ops CLI with resolved PDF and JSON output paths, inherits stdio for live interaction, and manages cleanup and error handling.
Test fixture and build artifact exclusions
scratch/test-jd.txt, .gitignore
Provides a sample Senior Product Manager job description for testing the workflow. Updates .gitignore to exclude the scratch/ directory, resume-ops/ output directory, and resume-ops.log logfile from version control.

Sequence Diagram

sequenceDiagram
  participant User
  participant npm
  participant resume-ops.mjs
  participant uv
  participant FileSystem
  User->>npm: npm run resume-ops --resume=cv.json --jd=job.txt --output=output.pdf
  npm->>resume-ops.mjs: node resume-ops.mjs [args]
  resume-ops.mjs->>FileSystem: validate resume file exists
  resume-ops.mjs->>FileSystem: resolve JD (file or write temp text)
  resume-ops.mjs->>FileSystem: ensure output directory exists
  resume-ops.mjs->>uv: spawn uv run resume-ops --output output.pdf --output-json output.json
  uv->>FileSystem: generate PDF and JSON resume
  FileSystem-->>uv: output files
  uv-->>resume-ops.mjs: exit code
  resume-ops.mjs->>FileSystem: cleanup temp JD if created
  resume-ops.mjs-->>User: resolved promise or error
Loading

Estimated Code Review Effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Suggested Labels

🔴 core-architecture, 🔧 scripts

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: replacing API-based integration with a CLI-based approach for resume-ops, as shown across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@modes/resume-ops.md`:
- Around line 21-23: The fenced code block containing the node command (```bash
... ``` around the node resume-ops.mjs invocation) lacks blank lines before and
after; to satisfy MD031 add a single blank line immediately above the opening
```bash and a single blank line immediately below the closing ``` so the code
block is separated from surrounding text.

In `@resume-ops.mjs`:
- Line 8: Add a preflight check that verifies RESUME_OPS_DIR exists and is a
directory before attempting to spawn processes; locate the RESUME_OPS_DIR
constant and the code that calls spawn (the spawn invocation around the
resume-ops usage) and, before calling spawn, use fs.existsSync or
fs.statSync/fs.accessSync to confirm the path exists and is a directory, and if
not throw or log a clear, actionable error (e.g., "resume-ops directory not
found: RESUME_OPS_DIR — ensure sibling resume-ops is present") so the script
fails fast with a helpful message.
- Around line 44-61: Validate that params.output/outputPath ends with a .pdf
before deriving jsonPath: check outputPath with /\.pdf$/i and if it does not
match, stop and surface a clear error (e.g., console.error or
processLogger.error + process.exit(1)) asking for a PDF output path, otherwise
compute jsonPath = outputPath.replace(/\.pdf$/i, '.json') and push
'--output-json' to cliArgs; update the code around outputPath, jsonPath, cliArgs
and the params.output handling accordingly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro

Run ID: 686a6b26-69a3-4d5f-816a-c73d2362a414

📥 Commits

Reviewing files that changed from the base of the PR and between d692647 and ff60a61.

📒 Files selected for processing (5)
  • .gitignore
  • modes/resume-ops.md
  • package.json
  • resume-ops.mjs
  • scratch/test-jd.txt

Comment thread modes/resume-ops.md
Comment on lines +21 to +23
```bash
node resume-ops.mjs --resume resume-ops/.local/master-resume.json --jd "{JD_TEXT}" --output output/cv-{candidate}-{company}-{YYYY-MM-DD}.pdf
```
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix fenced code block spacing for markdownlint compliance.

Line 21 and Line 23 need blank lines around the fenced code block to satisfy MD031.

🧰 Tools
🪛 markdownlint-cli2 (0.22.1)

[warning] 21-21: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


[warning] 23-23: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@modes/resume-ops.md` around lines 21 - 23, The fenced code block containing
the node command (```bash ... ``` around the node resume-ops.mjs invocation)
lacks blank lines before and after; to satisfy MD031 add a single blank line
immediately above the opening ```bash and a single blank line immediately below
the closing ``` so the code block is separated from surrounding text.

Comment thread resume-ops.mjs
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const RESUME_OPS_DIR = path.resolve(__dirname, '..', 'resume-ops');
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add an explicit preflight check for RESUME_OPS_DIR before spawning.

If the sibling resume-ops directory is missing, execution fails late with a spawn error instead of a clear setup message. Fail fast with an actionable error before spawn.

Proposed fix
 const __dirname = path.dirname(fileURLToPath(import.meta.url));
 const RESUME_OPS_DIR = path.resolve(__dirname, '..', 'resume-ops');
 
 async function main() {
+  if (!fs.existsSync(RESUME_OPS_DIR)) {
+    console.error(`❌ Required directory not found: ${RESUME_OPS_DIR}`);
+    console.error('   Expected a sibling `resume-ops` checkout. Run setup first (e.g., `uv sync`).');
+    process.exit(1);
+  }
+
   const args = process.argv.slice(2);
As per coding guidelines `**/*.mjs`: Ensure scripts handle missing data/ directories gracefully.

Also applies to: 69-74

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@resume-ops.mjs` at line 8, Add a preflight check that verifies RESUME_OPS_DIR
exists and is a directory before attempting to spawn processes; locate the
RESUME_OPS_DIR constant and the code that calls spawn (the spawn invocation
around the resume-ops usage) and, before calling spawn, use fs.existsSync or
fs.statSync/fs.accessSync to confirm the path exists and is a directory, and if
not throw or log a clear, actionable error (e.g., "resume-ops directory not
found: RESUME_OPS_DIR — ensure sibling resume-ops is present") so the script
fails fast with a helpful message.

Comment thread resume-ops.mjs
Comment on lines +44 to +61
const outputPath = path.resolve(params.output);
fs.mkdirSync(path.dirname(outputPath), { recursive: true });

// Build CLI arguments for resume-ops
const cliArgs = [
'run', 'resume-ops',
'--resume', resumePath,
'--jd', jdPath,
'--output', outputPath,
];

if (params.theme) {
cliArgs.push('--theme', params.theme);
}

// Also request the intermediate tailored JSON alongside the PDF
const jsonPath = outputPath.replace(/\.pdf$/i, '.json');
cliArgs.push('--output-json', jsonPath);
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Validate that --output is a PDF path before deriving --output-json.

Without a .pdf suffix, jsonPath can collapse to the same path as outputPath, which can produce conflicting outputs.

Proposed fix
   const outputPath = path.resolve(params.output);
+  if (!/\.pdf$/i.test(outputPath)) {
+    console.error('❌ --output must be a .pdf path');
+    process.exit(1);
+  }
   fs.mkdirSync(path.dirname(outputPath), { recursive: true });
As per coding guidelines `**/*.mjs`: Ensure scripts handle missing data/ directories gracefully.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const outputPath = path.resolve(params.output);
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
// Build CLI arguments for resume-ops
const cliArgs = [
'run', 'resume-ops',
'--resume', resumePath,
'--jd', jdPath,
'--output', outputPath,
];
if (params.theme) {
cliArgs.push('--theme', params.theme);
}
// Also request the intermediate tailored JSON alongside the PDF
const jsonPath = outputPath.replace(/\.pdf$/i, '.json');
cliArgs.push('--output-json', jsonPath);
const outputPath = path.resolve(params.output);
if (!/\.pdf$/i.test(outputPath)) {
console.error('❌ --output must be a .pdf path');
process.exit(1);
}
fs.mkdirSync(path.dirname(outputPath), { recursive: true });
// Build CLI arguments for resume-ops
const cliArgs = [
'run', 'resume-ops',
'--resume', resumePath,
'--jd', jdPath,
'--output', outputPath,
];
if (params.theme) {
cliArgs.push('--theme', params.theme);
}
// Also request the intermediate tailored JSON alongside the PDF
const jsonPath = outputPath.replace(/\.pdf$/i, '.json');
cliArgs.push('--output-json', jsonPath);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@resume-ops.mjs` around lines 44 - 61, Validate that params.output/outputPath
ends with a .pdf before deriving jsonPath: check outputPath with /\.pdf$/i and
if it does not match, stop and surface a clear error (e.g., console.error or
processLogger.error + process.exit(1)) asking for a PDF output path, otherwise
compute jsonPath = outputPath.replace(/\.pdf$/i, '.json') and push
'--output-json' to cliArgs; update the code around outputPath, jsonPath, cliArgs
and the params.output handling accordingly.

@Rat-S
Copy link
Copy Markdown
Author

Rat-S commented May 13, 2026

Related issues #635 / and #557 .

It's a PR to cancel and replace #640

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant