# aradutta/career-ops architecture

> Architecture diagram of the GitHub repository aradutta/career-ops, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-17). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/aradutta/career-ops
- Repository: https://github.com/aradutta/career-ops

## Overview

1. **Repository role and deployment boundary**
   - This is a **local-first job-search orchestration system**, not a hosted app.
   - The main boundary is the user’s machine: it reads local CV/profile files, calls an AI coding CLI, writes reports/PDFs/tracker files, and optionally drives the browser for portal checks.
   - There are no backend servers in the repo; “integration” happens through local CLIs, browser automation, and filesystem artifacts.

2. **Primary control plane: AI coding CLI + skill/mode prompts**
   - The repo is organized around **agent instructions** rather than an application server.
   - Canonical behavior lives in `AGENTS.md`, with wrappers for different CLIs (`CLAUDE.md`, `OPENCODE.md`, `GEMINI.md`).
   - The `modes/` directory defines the task-specific workflows: evaluation, pipeline processing, scan, batch, PDF, cover letter, interview prep, tracker, etc.
   - The `.agents/skills/career-ops/SKILL.md` and matching skill folders are the unified entry points for multiple agent runtimes.

3. **User inputs and canonical source data**
   - The system centers on a few editable local inputs:
     - `cv.md` for the candidate’s resume content,
     - `config/profile.yml` for personal profile/preferences,
     - `templates/portals.example.yml` copied to `portals.yml` for portal/company scan targets.
   - Supporting reference material lives in `examples/`, `writing-samples/`, `jds/`, and `interview-prep/`.
   - This makes the repo data-driven: the agent reads these files and generates downstream artifacts from them.

4. **Job discovery / portal scanning subsystem**
   - `scan.mjs` and `scan-ats-full.mjs` are the discovery layer for job listings.
   - Providers under `providers/` implement ATS-specific adapters for Greenhouse, Lever, Ashby, Workable, Recruitee, SmartRecruiters, Workday, Solidjobs, and a local parser.
   - The scanner can operate in a “trust feed” mode or a `--verify` mode that uses **Playwright** to confirm listing liveness before entries enter the pipeline.
   - The output of this subsystem flows into pipeline/tracker data rather than directly into reports.

5. **Evaluation and recommendation pipeline**
   - The core workflow is: ingest job description or URL, classify the role, evaluate fit against `cv.md`, and generate a structured recommendation.
   - The README describes a **6-block evaluation** plus a legitimacy check; repository files suggest this is implemented as mode-driven prompt logic rather than a compiled service.
   - The evaluation output becomes the basis for downstream artifacts such as reports, tracker entries, and personalized resume/cover-letter generation.

6. **Document generation subsystem**
   - The repo supports ATS-oriented document output through template-driven generation.
   - `generate-latex.mjs`, `build-cv-latex.mjs`, `generate-pdf.mjs`, and `generate-cover-letter.mjs` coordinate PDF creation.
   - Templates live in `templates/` (`cv-template.html`, `cover-letter-template.html`, `cv-template.tex`), and fonts are bundled in `fonts/`.
   - The document pipeline is browser-render based, using **Playwright** to render HTML into PDF, with LaTeX also available for CV generation.

7. **Pipeline, tracker, and data integrity layer**
   - Persistent workflow state lives in filesystem data under `data/`, `reports/`, and `output/`.
   - Scripts like `tracker.mjs`, `merge-tracker.mjs`, `normalize-statuses.mjs`, `dedup-tracker.mjs`, `reserve-report-num.mjs`, and `tracker-links.mjs` indicate a canonical tracker with deduplication and status normalization.
   - The `templates/states.yml` file suggests a controlled status taxonomy.
   - This layer is the system of record for applications, not the job boards themselves.

8. **Batch and parallel processing subsystem**
   - `batch/` contains orchestration for processing many roles in parallel.
   - `batch/batch-runner.sh` and `batch/batch-prompt.md` indicate worker-style execution where multiple AI CLI instances can be used as sub-agents.
   - Related scripts like `verify-pipeline.mjs`, `test-all.mjs`, and `tracker-columns-tests.mjs` reinforce that batch jobs must preserve tracker consistency and output naming.

9. **Terminal dashboard subsystem**
   - `dashboard/` is a separate Go module, built as a **Bubble Tea** TUI.
   - It provides a visual browser over the pipeline with filtering, sorting, grouped/flat views, previews, and inline status changes.
   - Internals are split into `internal/data`, `internal/model`, `internal/theme`, and `internal/ui/screens`, which cleanly separates data shaping, UI state, theme, and screen logic.
   - This dashboard reads the same local pipeline data rather than maintaining its own datastore.

10. **Provider and parsing boundary**
   - The `providers/` layer isolates each ATS or portal format so the rest of the system can work against normalized job records.
   - `_http.mjs` and `_types.js` suggest a shared transport/schema foundation, with provider modules doing the site-specific extraction.
   - `providers/local-parser.mjs` and `data/parser-output/` indicate there is also a local parsing path for pasted or downloaded job text.

11. **Quality checks, health checks, and maintenance scripts**
   - The repo includes many “guardrail” scripts: `doctor.mjs`, `check-liveness.mjs`, `liveness-core.mjs`, `liveness-browser.mjs`, `validate-portals.mjs`, `cv-sync-check.mjs`, `role-matcher.mjs`, and others.
   - These scripts support repository hygiene, job-feed validity, CV/profile consistency, and matching/scoring logic.
   - CI workflows in `.github/workflows/` mirror these concerns with test, dependency review, code scanning, SBOM, stale cleanup, and release automation.

12. **Generated and ignored artifact zones**
   - `data/`, `reports/`, `output/`, `interview-prep/`, and parts of `batch/logs/` are runtime-generated or user-specific and mostly gitignored.
   - The repo is structured so source prompts/templates/config live in version control, while job-specific outputs are local artifacts.
   - That separation is important for the architecture diagram: source inputs on one side, generated evaluation/report/PDF/tracker artifacts on the other.

13. **External dependencies and runtime mix**
   - The system is intentionally polyglot:
     - **Node.js** for orchestration scripts, parsing, generation, and validation,
     - **Go** for the dashboard TUI,
     - **Playwright** for browser-based verification and PDF rendering.
   - AI provider access is via whichever coding CLI the user runs locally; the repo is designed to work with Claude Code, OpenCode, Gemini CLI, and similar tools.
   - External job portals and ATS platforms are treated as inputs, not owned services.

14. **How the main data flow fits together**
   - A typical flow is: user adds CV/profile + portal config → scanner or pasted JD produces normalized offer data → evaluation mode scores and summarizes the role → downstream generation creates PDF/cover letter and a tracker row → dashboard and tracker scripts let the user browse and maintain status.
   - The central architectural theme is a **filesystem-backed pipeline** driven by agent prompts and specialized scripts, with browser automation only at the edges.

Main entry points: [`gemini-eval.mjs`](https://github.com/aradutta/career-ops/blob/main/gemini-eval.mjs) (Evaluate), [`modes`](https://github.com/aradutta/career-ops/tree/main/modes) (Modes), [`data`](https://github.com/aradutta/career-ops/tree/main/data) (Data store), [`generate-pdf.mjs`](https://github.com/aradutta/career-ops/blob/main/generate-pdf.mjs) (Doc generation)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_control["Control plane"]
  node_agents["AGENTS.md<br/>agent policy<br/>[AGENTS.md]"]
  node_modes["Modes<br/>prompt workflows"]
  node_skills["Career skill<br/>agent skill<br/>[SKILL.md]"]
end

subgraph group_inputs["Source inputs"]
  node_profile["Profile<br/>candidate config"]
  node_cv["CV<br/>resume source"]
  node_portals["Portals config<br/>scan targets"]
  node_refs["Reference set<br/>supporting material"]
end

subgraph group_pipeline["Job pipeline"]
  node_scanner["Scanner<br/>job discovery<br/>[scan.mjs]"]
  node_fullscan["ATS scan<br/>job discovery<br/>[scan-ats-full.mjs]"]
  node_providers["Providers<br/>ATS adapters"]
  node_eval["Evaluate<br/>role scoring<br/>[gemini-eval.mjs]"]
  node_docgen["Doc generation<br/>document pipeline<br/>[generate-pdf.mjs]"]
  node_latex["LaTeX CV<br/>cv rendering<br/>[build-cv-latex.mjs]"]
  node_templates["Templates"]
  node_tracker[("Tracker<br/>system of record<br/>[tracker.mjs]")]
  node_batch["Batch<br/>parallel orchestration<br/>[batch-runner.sh]"]
end

subgraph group_ui["Dashboard"]
  node_dashboard["Dashboard<br/>TUI app<br/>[main.go]"]
end

subgraph group_ops["Maintenance"]
  node_checks["Checks<br/>validation scripts<br/>[doctor.mjs]"]
end

subgraph group_artifacts["Artifacts"]
  node_data[("Data store<br/>runtime data")]
  node_reports["Reports<br/>generated artifacts"]
  node_output["Output<br/>generated artifacts"]
end

node_agents -->|"defines workflows"| node_modes
node_skills -->|"shares policy"| node_agents
node_modes -->|"invokes scan"| node_scanner
node_modes -->|"invokes eval"| node_eval
node_modes -->|"invokes docs"| node_docgen
node_modes -->|"invokes batch"| node_batch
node_modes -.->|"operates UI"| node_dashboard
node_profile -->|"feeds profile"| node_eval
node_cv -->|"feeds CV"| node_eval
node_refs -.->|"calibrates prompts"| node_eval
node_portals -->|"targets scans"| node_scanner
node_scanner -->|"normalizes via"| node_providers
node_fullscan -->|"parses feeds"| node_providers
node_providers -->|"writes jobs"| node_data
node_scanner -->|"ingests jobs"| node_data
node_eval -->|"creates recommendations"| node_reports
node_eval -->|"updates pipeline"| node_tracker
node_docgen -->|"renders from"| node_templates
node_latex -->|"builds from"| node_templates
node_docgen -->|"emits documents"| node_reports
node_docgen -->|"writes artifacts"| node_output
node_batch -->|"fans out"| node_eval
node_batch -->|"syncs results"| node_tracker
node_tracker -->|"persists state"| node_data
node_dashboard -->|"reads state"| node_data
node_checks -.->|"validates store"| node_data
node_checks -.->|"verifies consistency"| node_tracker

click node_agents "https://github.com/aradutta/career-ops/blob/main/AGENTS.md"
click node_modes "https://github.com/aradutta/career-ops/tree/main/modes"
click node_skills "https://github.com/aradutta/career-ops/blob/main/.agents/skills/career-ops/SKILL.md"
click node_profile "https://github.com/aradutta/career-ops/blob/main/config/profile.example.yml"
click node_portals "https://github.com/aradutta/career-ops/blob/main/templates/portals.example.yml"
click node_refs "https://github.com/aradutta/career-ops/tree/main/examples"
click node_scanner "https://github.com/aradutta/career-ops/blob/main/scan.mjs"
click node_fullscan "https://github.com/aradutta/career-ops/blob/main/scan-ats-full.mjs"
click node_providers "https://github.com/aradutta/career-ops/tree/main/providers"
click node_eval "https://github.com/aradutta/career-ops/blob/main/gemini-eval.mjs"
click node_docgen "https://github.com/aradutta/career-ops/blob/main/generate-pdf.mjs"
click node_latex "https://github.com/aradutta/career-ops/blob/main/build-cv-latex.mjs"
click node_templates "https://github.com/aradutta/career-ops/tree/main/templates"
click node_tracker "https://github.com/aradutta/career-ops/blob/main/tracker.mjs"
click node_batch "https://github.com/aradutta/career-ops/blob/main/batch/batch-runner.sh"
click node_dashboard "https://github.com/aradutta/career-ops/blob/main/dashboard/main.go"
click node_checks "https://github.com/aradutta/career-ops/blob/main/doctor.mjs"
click node_data "https://github.com/aradutta/career-ops/tree/main/data"
click node_reports "https://github.com/aradutta/career-ops/tree/main/reports"
click node_output "https://github.com/aradutta/career-ops/tree/main/output"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_agents,node_modes,node_skills toneBlue
class node_profile,node_cv,node_portals,node_refs toneAmber
class node_scanner,node_fullscan,node_providers,node_eval,node_docgen,node_latex,node_templates,node_tracker,node_batch toneMint
class node_dashboard toneRose
class node_checks toneIndigo
class node_data,node_reports,node_output toneTeal
```

## Components

### Control plane

Agent instructions, skills, and task modes that define local CLI behavior.

- [AGENTS.md](https://github.com/aradutta/career-ops/blob/main/AGENTS.md): agent policy · Canonical instructions for AI coding CLI workflows. · `AGENTS.md`
- [Modes](https://github.com/aradutta/career-ops/tree/main/modes): prompt workflows · Task-specific prompt files for scan, pipeline, PDF, cover letter, interview prep, tracker, and related flows. · `modes`
- [Career skill](https://github.com/aradutta/career-ops/blob/main/.agents/skills/career-ops/SKILL.md): agent skill · Shared career-ops skill entry point reused across multiple agent runtimes. · `.agents/skills/career-ops/SKILL.md`

### Source inputs

Editable profile data and reference material consumed by the workflows.

- [Profile](https://github.com/aradutta/career-ops/blob/main/config/profile.example.yml): candidate config · Local personal profile and preferences used by prompts and scripts. · `config/profile.example.yml`
- **CV**: resume source · Primary resume content source for evaluation and document generation.
- [Portals config](https://github.com/aradutta/career-ops/blob/main/templates/portals.example.yml): scan targets · Example portal and company scan configuration copied into local use. · `templates/portals.example.yml`
- [Reference set](https://github.com/aradutta/career-ops/tree/main/examples): supporting material · Examples, writing samples, and job-description samples used to calibrate outputs. · `examples`

### Job pipeline

Discovery, evaluation, document generation, tracker management, and batch orchestration.

- [Scanner](https://github.com/aradutta/career-ops/blob/main/scan.mjs): job discovery · Entry scripts for ingesting job listings from feeds or URLs. · `scan.mjs`
- [ATS scan](https://github.com/aradutta/career-ops/blob/main/scan-ats-full.mjs): job discovery · Expanded scanning flow for ATS-specific discovery and normalization. · `scan-ats-full.mjs`
- [Providers](https://github.com/aradutta/career-ops/tree/main/providers): ATS adapters · Site-specific extractors that normalize jobs across ATS platforms. · `providers`
- [Evaluate](https://github.com/aradutta/career-ops/blob/main/gemini-eval.mjs): role scoring · Prompt-driven fit analysis and legitimacy checks against the candidate profile and CV. · `gemini-eval.mjs`
- [Doc generation](https://github.com/aradutta/career-ops/blob/main/generate-pdf.mjs): document pipeline · Orchestrates PDF, cover letter, and related document output. · `generate-pdf.mjs`
- [LaTeX CV](https://github.com/aradutta/career-ops/blob/main/build-cv-latex.mjs): cv rendering · Builds the CV PDF through the LaTeX generation path. · `build-cv-latex.mjs`
- [Templates](https://github.com/aradutta/career-ops/tree/main/templates): render templates · HTML, TeX, and state templates used by generation and tracker workflows. · `templates`
- [Tracker](https://github.com/aradutta/career-ops/blob/main/tracker.mjs): system of record · Canonical application state with deduplication, status normalization, and link management. · `tracker.mjs`
- [Batch](https://github.com/aradutta/career-ops/blob/main/batch/batch-runner.sh): parallel orchestration · Worker-style harness for running many role workflows in parallel. · `batch/batch-runner.sh`

### Dashboard

Go-based terminal UI for browsing the local pipeline state.

- [Dashboard](https://github.com/aradutta/career-ops/blob/main/dashboard/main.go): TUI app · Bubble Tea terminal browser for the shared pipeline and tracker data. · `dashboard/main.go`

### Maintenance

Validation, integrity, and repository hygiene scripts.

- [Checks](https://github.com/aradutta/career-ops/blob/main/doctor.mjs): validation scripts · Health, liveness, consistency, and policy checks across pipeline data and outputs. · `doctor.mjs`

### Artifacts

Filesystem-backed runtime outputs and working data.

- [Data store](https://github.com/aradutta/career-ops/tree/main/data): runtime data · Filesystem-backed job, parser, and tracker state used by the pipeline and dashboard. · `data`
- [Reports](https://github.com/aradutta/career-ops/tree/main/reports): generated artifacts · Generated reports and application summaries written locally. · `reports`
- [Output](https://github.com/aradutta/career-ops/tree/main/output): generated artifacts · General output directory for local artifacts produced by workflows. · `output`

## Connections

- AGENTS.md → Modes: defines workflows · The main agent policy delegates task-specific behavior to mode prompts.
- Career skill → AGENTS.md: shares policy · Shared skill instructions align multiple AI runtimes with the same repo rules.
- Modes → Scanner: invokes scan · Scan-related prompts drive the discovery scripts.
- Modes → Evaluate: invokes eval · Evaluation modes coordinate role scoring and recommendation generation.
- Modes → Doc generation: invokes docs · PDF and cover-letter modes orchestrate document generation.
- Modes → Batch: invokes batch · Batch modes launch parallel processing workflows.
- Modes → Dashboard: operates UI · Dashboard-related instructions help operators inspect local state.
- Profile → Evaluate: feeds profile · Candidate preferences and background are read during role evaluation.
- CV → Evaluate: feeds CV · Resume content is the primary basis for fit scoring and tailoring.
- Reference set → Evaluate: calibrates prompts · Examples and samples inform scoring, writing style, and output shaping.
- Portals config → Scanner: targets scans · Portal configuration tells the discovery layer what to inspect.
- Scanner → Providers: normalizes via · Scan entry points delegate site-specific extraction to ATS adapters.
- ATS scan → Providers: parses feeds · The full scan path uses the same provider boundary for ATS normalization.
- Providers → Data store: writes jobs · Normalized job records are stored in local pipeline data.
- Scanner → Data store: ingests jobs · Discovery results are persisted for later evaluation and tracking.
- Evaluate → Reports: creates recommendations · Role analysis produces structured outputs and report artifacts.
- Evaluate → Tracker: updates pipeline · Evaluated roles can become tracker entries with status and notes.
- Doc generation → Templates: renders from · PDF and cover-letter generation use the shared template set.
- LaTeX CV → Templates: builds from · LaTeX CV generation consumes the CV template assets.
- Doc generation → Reports: emits documents · Generated PDFs and supporting documents are written locally.
- Doc generation → Output: writes artifacts · Document generation also places outputs in the general artifact area.
- Batch → Evaluate: fans out · Batch runs distribute many role evaluations across worker processes.
- Batch → Tracker: syncs results · Parallel processing must keep tracker rows and statuses consistent.
- Tracker → Data store: persists state · Tracker state is maintained in filesystem-backed local data.
- Dashboard → Data store: reads state · The TUI browses the same local pipeline and tracker data.
- Checks → Data store: validates store · Health and consistency checks inspect pipeline data and outputs.
- Checks → Tracker: verifies consistency · Guardrail scripts enforce tracker normalization and integrity.
