# Input Pipeline Overview The input side of ResumeCustomizer prepares job-specific Markdown resumes by stitching together the base resume, a job-description Markdown file, and the shared instruction prompt, then invoking the Codex CLI inside a containerized watcher. ## Workflow Recap 1. Ensure `input/resume/` contains exactly one Markdown resume. 2. Drop a single job-description file (plain text or Markdown) into `input/ForCustomizing/inbox/`. 3. Start the watcher stack (`input/Docker/run-input-processor.sh up -d`). 4. The watcher normalizes the messy job description via Codex (using the baked-in normalizer prompt), stripping recruiter chatter while preserving every job-related detail, then combines the cleaned Markdown, the base resume, and the resolved customization prompt into a second Codex run that writes the generated resume to `ForCustomizing/outbox/YYYY/MM/DD/HHMM/-.md`. 5. Successful runs archive the job description under `ForCustomizing/processed/`, copy both the prompt and the cleaned job description into the same outbox folder, and leave the Codex output for human review. Failures move the job description into `ForCustomizing/failed/`. The human operator reviews the Codex output Markdown, makes any edits, and then manually hands it off to the output pipeline for document rendering. ## Container Stack The watcher lives in `input/Docker/`: - `Dockerfile` – builds a Node/Python base image, installs gosu, and prepares a non-root `codex` user. - `watch_and_customize.py` – polls the inbox, validates preconditions, resolves both templates (normalizer and customization), cleans the job description, builds prompts, runs Codex twice, and routes files. - `entrypoint.sh` – maps the container user to the caller’s UID/GID and ensures shared directories exist. - `run-input-processor.sh` – wrapper around `docker compose` that mounts your `~/.codex` directory and forwards CLI arguments. - `docker-compose.yml` – defines the container, volumes, environment variables, and restart policy (`no` so fatal errors halt the stack). ### Templates - baked normalizer prompt (`input/Docker/JobDescriptionNormalizerPrompt.md`) ships with the container; customize by editing the image. - `templates/ResumeCustomizerPrompt.md.example` ships with default resume-customization instructions. Copy it to `ResumeCustomizerPrompt.md` to override. - The `.gitignore` in `templates/` keeps local overrides out of version control. ### Key Environment Variables - `CODEX_COMMAND_TEMPLATE` – format string for the resume-customization Codex run (placeholders: `{prompt}`, `{output}`). - `CODEX_NORMALIZER_COMMAND_TEMPLATE` – optional override for the normalization Codex run (defaults to `CODEX_COMMAND_TEMPLATE`). - `POLL_INTERVAL_SECONDS` – watch loop delay (defaults to 5). - `CODEX_TIMEOUT_SECONDS` – wall-clock timeout for each Codex call (defaults to 600). - `CODEX_CONFIG_DIR` – host path to mount as `/home/codex/.codex` (defaults to `${HOME}/.codex` via the wrapper). ### Prerequisites - Docker Engine with the Compose plugin (`docker compose`) or the standalone `docker-compose` binary. - A working Codex CLI and credentials in `~/.codex`. The Docker build attempts `npm install --location=global codex-cli`; override or update as needed if packages change. ## Failure Modes - **Multiple resumes or job descriptions** – watcher exits immediately with a fatal configuration error. Fix the files and restart. - **Codex CLI missing or failing** – job description moves to `ForCustomizing/failed/`; inspect container logs, resolve, and requeue. - **Timeouts** – treat as failures; adjust `CODEX_TIMEOUT_SECONDS` if Codex regularly needs more time. For day-to-day operating guidelines, see `input/AGENTS.md`.