# How `/outcome` Records Application Results and Calibrates the Fit Framework

> Discover how the /outcome command records application results, archives materials, and calibrates the AI fit framework using job_search_tracker.csv and structured directories.

- Repository: [Mads Lorentzen/ai-job-search](https://github.com/MadsLorentzen/ai-job-search)
- Tags: internals
- Published: 2026-07-14

---

**The `/outcome` command writes application statuses to `job_search_tracker.csv`, archives submitted materials in structured directories, and passes finalized results to the `/setup` command, which extracts strong-fit and weak-fit signals to continuously recalibrate the AI scoring model.**

The `MadsLorentzen/ai-job-search` repository implements a feedback-driven workflow for job searching where the `/outcome` command serves as the critical bridge between completed applications and the AI-driven fit framework. By persisting results in both machine-readable CSV files and structured markdown documents, the system creates a data trail that automatically sharpens the accuracy of future job recommendations.

## The Three-Phase Recording Process

When you invoke `/outcome`, it executes a coordinated sequence that captures the full context of your application results. According to the command definition in [`/.claude/commands/outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main//.claude/commands/outcome.md), this process ensures that no data is lost between the final interview and the next scraping cycle.

### 1. Central Tracker Updates

The command immediately writes to `job_search_tracker.csv`, updating the row corresponding to your application with the current **status** (e.g., `interview`, `offer`, `hired`, `rejected`), a **fit_rating**, and dated notes. This CSV is the canonical source used by `/scrape` and `/rank` to prevent duplicate searches and to provide a quick overview of open versus closed applications.

The CSV schema includes specific columns: `date`, `company`, `sector`, `role`, `role_type`, `channel`, `status`, `contact_person`, `fit_rating`, `notes`, `cv_file`, `cover_letter_file`, and `source`.

### 2. Material Archiving

`/outcome` creates or updates a dedicated folder at `documents/applications/<company>_<role>/` to preserve the complete application context. Inside this directory, it stores:

- The submitted **CV draft** (`cv_draft.tex`) and **cover letter** (`cover_letter.tex`)
- The original **job posting** ([`job_posting.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/job_posting.md)), fetched automatically via WebFetch when available
- An [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) file that records the precise status, interview-stage check-boxes, and free-form notes

The format of [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) is defined in the **Outcome** section of [`documents/README.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/documents/README.md). This file uses a structured markdown format with sections for status tracking and interview progress.

### 3. Calibration Handoff to `/setup`

Rather than writing directly to the fit-scoring framework, `/outcome` follows a **read-before-write** architecture. When `/setup` runs (Path A), it scans every [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) whose status is **final** (specifically excluding `in_progress` entries). From these files, it extracts:

- **Strong-fit signals**: Role types and sectors that repeatedly lead to interviews or offers
- **Weak-fit signals**: Combinations that consistently result in rejection or no-response
- **User feedback**: Free-form notes that can be converted into STAR-candidate examples

This calibration data is merged into the **Job-Evaluation** skill file at [`/.claude/skills/job-application-assistant/04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main//.claude/skills/job-application-assistant/04-job-evaluation.md) under the "Calibration from Past Applications" heading.

## How Calibration Refines the Fit Framework

The separation of concerns between `/outcome` and `/setup` ensures the system remains **idempotent** and prevents race conditions. By keeping the calibration logic inside `/setup`, the framework ensures that data is only analyzed after it is fully persisted.

When `/setup` processes your application history, it identifies patterns such as:

- **Strong-fit signals**: ML Engineer roles at Technology companies (e.g., Acme, BigCorp) consistently reached at least the phone screen stage
- **Weak-fit signals**: Data Analyst positions at Finance sector companies often resulted in no response

These signals directly inform the scoring algorithm used by `/rank`, allowing the AI to weight future opportunities based on your proven success patterns rather than generic heuristics.

## Practical Workflow Examples

Trigger the outcome recording for a specific application using the command syntax:

```bash
/outcome acme ml engineer

```

During the interaction, the system updates your status based on your input:

```text
User: I had a phone screen on 2024-03-01, no news since.
Bot:  → records “interview” stage, adds date, updates status to in_progress.

```

The resulting [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) file follows this structured format:

```markdown

# Outcome: Acme — ML Engineer

**Status:** interview_only

## Interview stages reached

- [x] Phone screen (2024-03-01)
- [ ] Technical interview
- [ ] Case interview
- [ ] Final round
- [ ] Offer received

## Notes

- Recruiter said “good fit”, asked about cloud experience.
- Would improve by emphasizing production ML pipelines.

```

The corresponding CSV update adds a row with specific tracking data:

```csv
date,company,sector,role,role_type,channel,status,contact_person,fit_rating,notes,cv_file,cover_letter_file,source
2024-02-20,Acme,Technology,ML Engineer,Full‑time,LinkedIn,interview,John Doe,7,"Phone screen 2024-03-01",cv/main_acme.tex,cover_letters/cover_acme_ml_engineer.tex,https://acme.com/jobs/123

```

Finally, `/setup` inserts calibration insights into [`04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/04-job-evaluation.md):

```markdown

## Calibration from Past Applications

- **Strong‑fit signals**: ML Engineer roles at Tech companies (Acme, BigCorp) consistently reached at least the phone screen.
- **Weak‑fit signals**: Data Analyst positions at Finance sector often resulted in no response.

```

## Core Implementation Files

- **[`/.claude/commands/outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main//.claude/commands/outcome.md)**: Defines the step-by-step process for recording results, archiving materials, updating the CSV, and handing off calibration data.
- **[`documents/README.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/documents/README.md)**: Documents the folder structure, explains the purpose of each file ([`job_posting.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/job_posting.md), [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md), etc.), and specifies how `in_progress` entries are excluded from calibration.
- **[`/.claude/skills/job-application-assistant/04-job-evaluation.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main//.claude/skills/job-application-assistant/04-job-evaluation.md)**: Holds the fit-scoring framework; receives calibrated signals derived from finalized [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) files.
- **`job_search_tracker.csv`**: The central CSV used by `/scrape` and `/rank` to track application status and avoid duplicate effort.

## Summary

- **`/outcome`** persists raw application data to both `job_search_tracker.csv` and structured [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) files in `documents/applications/<company>_<role>/`.
- **`/setup`** consumes finalized outcome records to identify strong-fit and weak-fit signals, ensuring the calibration process remains idempotent and read-before-write.
- The system tracks specific interview stages, contact persons, and qualitative feedback to create a comprehensive data foundation for AI-driven recommendations.
- Only **finalized** statuses (excluding `in_progress`) trigger calibration updates, preventing premature adjustments to the fit-scoring model.

## Frequently Asked Questions

### What file format does `/outcome` use to store detailed results?

The command generates an [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) file using a structured markdown format defined in [`documents/README.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/documents/README.md). This file contains sections for status tracking, interview-stage check-boxes, and free-form notes, allowing both human readability and machine parsing by `/setup`.

### How does the system prevent duplicate job applications?

By updating `job_search_tracker.csv` with every status change, `/outcome` provides a central registry that `/scrape` and `/rank` reference to identify already-applied positions. The CSV includes specific columns for company, role, channel, and source URL to ensure precise deduplication.

### What is the difference between `/outcome` and `/setup` in the calibration process?

`/outcome` handles the **write** operations—archiving materials and updating the tracker—while `/setup` handles the **read** and **analysis** operations. This separation prevents race conditions and ensures that `/setup` only calibrates the fit-scoring framework using complete, finalized application data from [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) files.

### Which application statuses trigger the fit framework calibration?

Calibration only occurs when `/setup` encounters [`outcome.md`](https://github.com/MadsLorentzen/ai-job-search/blob/main/outcome.md) files with **final** statuses (such as `hired`, `rejected`, or `offer`). Entries marked `in_progress` are explicitly ignored during the calibration scan, ensuring that the fit-scoring model updates only based on concluded application cycles.