# How Career-Ops Implements a CV Source of Truth Using cv.md and article-digest.md for Proof Points

> Learn how Career-Ops implements a CV source of truth using cv.md and article-digest.md for dynamic proof points at runtime. Discover a robust approach to managing your professional experience.

- Repository: [Santiago Fernández de Valderrama/career-ops](https://github.com/santifer/career-ops)
- Tags: how-to-guide
- Published: 2026-06-10

---

**Career-Ops treats [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) as the canonical experience record while using [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) as an override layer for detailed metrics, ensuring all proof points are read dynamically at runtime rather than hard-coded.**

The Career-Ops repository (santifer/career-ops) establishes a robust **CV source of truth** by splitting canonical experience data from detailed proof points across two markdown files. This architecture ensures that metrics, project outcomes, and publications remain current while maintaining a stable base résumé structure.

## The Two-File Architecture for CV Source of Truth

The system divides candidate information into complementary roles: one file serves as the immutable baseline, while the other provides rich, updatable evidence.

### cv.md: The Canonical Experience Record

The **[`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md)** file at the project root acts as the primary **CV source of truth**. It contains the base list of roles, responsibilities, and static metrics that define the candidate’s professional history. When any evaluation mode starts, it reads this file first to establish the foundational narrative. According to the source code in [`modes/pdf.md`](https://github.com/santifer/career-ops/blob/main/modes/pdf.md), the PDF generation mode explicitly begins with the instruction: "Read [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) as the source of truth"【/cache/repos/github.com/santifer/career-ops/main/modes/pdf.md#L1-L6】.

### article-digest.md: The Detailed Proof Points Layer

The optional **[`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md)** file carries the *detailed proof points*—specific metrics, project outcomes, and publications that may update more frequently than the base CV. This file exists to supplement the canonical record with granular, evidence-based data. When present, it takes precedence over [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) for any overlapping metrics, functioning as an override layer rather than a replacement.

## Precedence Rules and the Hard-Coding Prohibition

The **sources of truth** are formally declared in [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md), which establishes strict governance rules for how evaluation code must handle these files.

### The Override Hierarchy

The documentation states that **[`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) overrides [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md)** when a metric appears in both locations【/cache/repos/github.com/santifer/career-ops/main/modes/_shared.md#L11-L22】. This precedence rule ensures that the most detailed, up-to-date numbers always surface in generated outputs, while the base CV remains stable.

### The Runtime Reading Mandate

All evaluation code is **required to read numbers at runtime** instead of embedding static values. The shared mode rules explicitly prohibit hard-coding: metrics must be extracted dynamically during each evaluation to ensure the CV source of truth remains authoritative and current【/cache/repos/github.com/santifer/career-ops/main/modes/_shared.md#L21-L22】.

## Runtime Evaluation Flow in Career-Ops Modes

Every evaluation mode follows a consistent pipeline: load the base CV, check for the digest file, and merge data according to the precedence rules.

### PDF Generation Mode (pdf.md)

The PDF mode demonstrates the standard loading sequence. It begins by reading [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) as the source of truth, then proceeds to detect role archetypes and rewrite the Professional Summary by injecting job description keywords while preserving existing metrics【/cache/repos/github.com/santifer/career-ops/main/modes/pdf.md#L1-L6】. If [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) exists, the system pulls richer proof points from it during this process.

### Offer Evaluation Mode (oferta.md)

When scoring a job description, the engine maps each requirement to exact lines in [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) while respecting the proof-point hierarchy. The mode instructions specify: "Read [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md). Create a table with each JD requirement mapped to exact lines in the CV"【/cache/repos/github.com/santifer/career-ops/main/modes/oferta.md#L25-L27】. If [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) is available, the system reads it first and uses its numbers for proof points, falling back to [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) only when the digest lacks specific metrics.

## Implementation: Dynamic Proof Point Retrieval

The following pattern illustrates how evaluation modes implement the CV source of truth protocol in practice:

```javascript
// Evaluation modes read files at runtime per _shared.md rules
const cv = await readFile('cv.md');                     // base CV source of truth
let digest = '';

if (await exists('article-digest.md')) {
  digest = await readFile('article-digest.md');        // detailed proof points
}

// Extraction prefers article-digest.md over cv.md per precedence rules
const metric = extractMetric(digest) || extractMetric(cv);

```

The pipeline executes in four distinct steps:

1. **Load [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md)** → Establish the base list of roles and static metrics.
2. **Load [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md)** (if present) → Import updated metrics and case studies.
3. **Prefer [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md)** → Use digest values for any metric-level proof point, falling back to [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) only when necessary.
4. **Never embed metrics** → Ensure all numbers are read dynamically during each evaluation run.

## Summary

- **Dual-file architecture**: [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) provides the canonical experience record, while [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) supplies detailed, updatable proof points.
- **Precedence rule**: [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) overrides [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) when the same metric appears in both files, as defined in [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md).
- **Hard-coding prohibition**: All evaluation code must read metrics at runtime; static embedding is forbidden.
- **Consistent pipeline**: Both PDF and Offer modes begin with [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) as the source of truth, then layer in [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) data when available.
- **Source files**: Key implementation details reside in [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) (rules), [`modes/pdf.md`](https://github.com/santifer/career-ops/blob/main/modes/pdf.md) (generation), and [`modes/oferta.md`](https://github.com/santifer/career-ops/blob/main/modes/oferta.md) (evaluation).

## Frequently Asked Questions

### What happens if a metric exists in both cv.md and article-digest.md?

The value in [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) takes precedence. According to [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md), the system documentation explicitly lists this override rule under "Sources of Truth" to ensure the most current metrics surface in generated outputs.

### Why does Career-Ops prohibit hard-coding metrics?

Hard-coding violates the CV source of truth principle. By requiring runtime reading, the system ensures that every evaluation reflects the latest data from the candidate's files, preventing stale or divergent metrics from appearing in cover letters or PDFs.

### How do the evaluation modes load these files?

Both PDF and Offer modes follow a standardized sequence: they first read [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) as the base source of truth, then check for [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) and load it if present. The Offer mode specifically maps job description requirements to exact lines in [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) while pulling updated numbers from the digest file.

### Where is the precedence rule documented?

The precedence rule is documented in [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) alongside the formal definition of sources of truth. This file also contains the prohibition against hard-coding, establishing the governance model for all Career-Ops evaluation modes.