# Career-Ops User Data Layer and System Layer Separation Explained

> Understand Career-Ops user data layer and system layer separation. Keep personal files safe from updates and ensure your core scripts auto-update.

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

---

**Career-Ops maintains a strict separation between the user data layer and system layer, ensuring personalizable files like [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) and [`config/profile.yml`](https://github.com/santifer/career-ops/blob/main/config/profile.yml) are never overwritten during updates while core scripts remain auto-updatable.**

The `santifer/career-ops` repository implements a dual-layer architecture designed to protect user customizations from system updates. This design distinguishes personal content from core infrastructure, allowing you to safely update the tooling without losing your CV, job tracking history, or custom configurations. Understanding this separation is essential for maintaining a stable, personalized job search workflow.

## The Two-Layer Architecture

Career-Ops explicitly documents this separation in [`AGENTS.md`](https://github.com/santifer/career-ops/blob/main/AGENTS.md)【/cache/repos/github.com/santifer/career-ops/main/AGENTS.md#L15-L22】, dividing the codebase into two distinct territories with different update behaviors.

### User Data Layer (Never Auto-Updated)

Files in this layer contain **personalizable content** specific to your job search and career profile. The system guarantees these files are **never overwritten** during updates, making them safe for persistent data storage.

Key paths in the user data layer include:

- [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) – Your master CV source of truth for all generation tasks
- [`config/profile.yml`](https://github.com/santifer/career-ops/blob/main/config/profile.yml) – Personal profile containing name, email, target roles, and salary targets
- [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) – Custom archetypes, narrative scripts, negotiation points, and proof points
- [`article-digest.md`](https://github.com/santifer/career-ops/blob/main/article-digest.md) – Optional detailed portfolio proof points
- [`portals.yml`](https://github.com/santifer/career-ops/blob/main/portals.yml) – Personal job portal search configuration
- `data/*` – Application tracker, pipeline inbox, scan history, and follow-ups
- `reports/*` – Generated evaluation reports
- `output/*` – Build artifacts including PDFs and LaTeX outputs
- `interview-prep/*` – Company-specific interview preparation notes

### System Layer (Auto-Updatable)

This layer contains **core infrastructure** maintained by the Career-Ops project. These files are **auto-updatable**—running `node update-system.mjs apply` or pulling new versions will overwrite their contents.

Key system layer components include:

- [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) – Shared evaluation logic and standard wording templates
- `*.mjs` scripts – Core scanners, PDF generators, liveness checks, and batch runners
- `templates/*` – CV HTML/LaTeX templates and state definitions
- `batch/*` – Batch processing scripts and execution helpers
- `dashboard/*` – UI dashboard source code
- [`AGENTS.md`](https://github.com/santifer/career-ops/blob/main/AGENTS.md), [`CLAUDE.md`](https://github.com/santifer/career-ops/blob/main/CLAUDE.md), `README*` – Project documentation and meta-information

## Working with the User Data Layer

To customize Career-Ops safely, modify only files residing in the user layer. For example, defining a custom archetype requires editing [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md):

```yaml

# modes/_profile.md

---
archetypes:
  - name: Data Engineer
    keywords: ["ETL", "SQL", "BigQuery", "Airflow"]
    score_weights:
      impact: 1.5
      relevance: 1.2
---

```

This configuration persists across updates because [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) resides in the user data layer.

## System Layer Implementation Patterns

System scripts execute from the system layer but read configuration from the user layer. The core `scan.mjs` script demonstrates this architecture:

```javascript
// scan.mjs – core zero-token scanner (System Layer)
import { fetchJobs } from "./providers/greenhouse.mjs";
// ...

```

When accessing your personal data, system scripts load user layer files:

```javascript
import fs from "fs";
import yaml from "js-yaml";

const profile = yaml.load(fs.readFileSync("config/profile.yml", "utf8"));
console.log(`Target roles: ${profile.roles.join(", ")}`);

```

This read-pattern allows the system to process your personal configuration without modifying the underlying data storage.

## Critical Rules for Layer Safety

Follow the implementation rule established in the codebase: **edit only** files in the user data layer when personalizing the system. **Never place** user-specific content in [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) or other system files, as updates will unconditionally overwrite these locations.

## Summary

- Career-Ops distinguishes **personalizable user data** from **auto-updatable system code** to prevent data loss during version updates.
- The **user data layer** includes [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md), [`config/profile.yml`](https://github.com/santifer/career-ops/blob/main/config/profile.yml), [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md), and directories like `data/` and `output/`—these files are never overwritten.
- The **system layer** includes [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md), `*.mjs` scripts, `templates/`, and documentation—updated automatically when upgrading Career-Ops.
- Store all custom archetypes, personal profiles, and job tracking data exclusively in the user layer to ensure persistence across system updates.

## Frequently Asked Questions

### What happens if I edit files in the System Layer?

If you modify system layer files such as [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) or `scan.mjs`, the next system update will overwrite your changes with the latest upstream versions. Always verify file paths against [`AGENTS.md`](https://github.com/santifer/career-ops/blob/main/AGENTS.md) before editing to confirm you are working within the user data layer.

### How do I update Career-Ops without losing my data?

Execute the system update command (typically `node update-system.mjs apply`) while keeping your working directory synchronized. Because your data lives in the user layer—specifically files like [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md), [`config/profile.yml`](https://github.com/santifer/career-ops/blob/main/config/profile.yml), and [`data/applications.md`](https://github.com/santifer/career-ops/blob/main/data/applications.md)—the update process modifies only system files, leaving your personal content untouched.

### Can I add new files to the User Data Layer?

Yes, you can create new files within user layer directories such as `interview-prep/` or `data/` to organize additional job search information. These locations are reserved for user data and are excluded from the auto-update mechanism, allowing you to extend the structure safely without conflict.

### Where should I store my job application tracking information?

Store application history, pipeline entries, and scan results in [`data/applications.md`](https://github.com/santifer/career-ops/blob/main/data/applications.md) or other files within the `data/` directory. This path is explicitly designated as part of the user data layer, ensuring your tracking information persists across Career-Ops version updates.