# User-Layer vs System-Layer Files in Career-Ops Data Contract Architecture: Complete Guide

> Understand user-layer vs system-layer files in Career-Ops Data Contract architecture. Learn how user data differs from core code for safe updates.

- Repository: [Santiago Fernández de Valderrama/career-ops](https://github.com/santifer/career-ops)
- Tags: deep-dive
- Published: 2026-08-20

---

**User-Layer files contain personal data and customizations that are never auto-updated, while System-Layer files contain core code and templates that can be safely replaced during upstream updates.**

The Career-Ops repository uses a strict **Data Contract architecture** defined in [`DATA_CONTRACT.md`](https://github.com/santifer/career-ops/blob/main/DATA_CONTRACT.md) to separate user-owned content from system-maintained infrastructure. This two-layer design ensures your personal configurations survive updates while the underlying tooling can evolve independently.

## What Are User-Layer Files?

User-Layer files hold **personal data, customizations, and artefacts you create**. According to the Career-Ops Data Contract, these files are explicitly "**NEVER auto-updated**"—update scripts are forbidden from reading, modifying, or deleting any file listed in this layer.

### User-Layer File Examples

| File | Purpose |
|------|---------|
| [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) | Your canonical CV in markdown |
| [`config/profile.yml`](https://github.com/santifer/career-ops/blob/main/config/profile.yml) | Identity, target roles, compensation expectations |
| [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) | Personal archetypes, narrative, negotiation scripts |
| [`modes/_custom.md`](https://github.com/santifer/career-ops/blob/main/modes/_custom.md) | Procedural house rules and output preferences |
| [`data/applications.md`](https://github.com/santifer/career-ops/blob/main/data/applications.md) | Job application tracker data |

The contract enforces a hard rule for this layer: "**If a file is in the User-Layer, no update process may read, modify, or delete it**".

### Working with User-Layer Files

```bash

# Add a custom archetype - this file will never be touched by updates

nano modes/_profile.md

```

Edit [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) to define your personal archetype blocks. Because this file is explicitly listed in the User-Layer table, the `update-system.mjs` script will skip it entirely during any update operation.

## What Are System-Layer Files?

System-Layer files contain **core code, templates, mode definitions, and infrastructure** that improves over time. These files are marked as "**safe to auto-update**" and can be replaced with newer versions from upstream without data loss.

### System-Layer File Examples

| File/Pattern | Purpose |
|--------------|---------|
| [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) | Core evaluation logic, scoring weights, global rules |
| `*.mjs` scripts (`scan.mjs`, `set-status.mjs`) | CLI utilities, scanners, data processors |
| `templates/*` | HTML/LaTeX templates for PDF generation |

Any file in this layer "**may be safely replaced**" during updates, allowing the Career-Ops maintainers to ship bug fixes, new scanning providers, and improved scoring rules.

### Updating System-Layer Files

```bash

# Pull latest upstream changes - system files get refreshed

git pull origin main

```

After this command, [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) (a System-Layer file) will reflect the latest upstream version while your User-Layer files remain untouched.

## How the Update System Respects the Contract

The `update-system.mjs` script implements layer-aware updates:

```bash

# Check if newer system version exists

node update-system.mjs check

# Apply update - replaces only System-Layer files

node update-system.mjs apply

```

The script consults [`DATA_CONTRACT.md`](https://github.com/santifer/career-ops/blob/main/DATA_CONTRACT.md) to determine which paths are user-owned versus system-owned before performing any file operations.

## Why the Split Matters

**Preserving user intent.** Personalization—archetypes, negotiation scripts, tracker data—lives in the User-Layer. A future `career-ops update` will never overwrite your bespoke configuration.

**Enabling evolution.** System-Layer files hold logic that can be honed by maintainers. Because they are auto-updatable, the tool benefits from improvements without requiring manual migration steps.

## Summary

- **User-Layer files** ([`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), [`modes/_custom.md`](https://github.com/santifer/career-ops/blob/main/modes/_custom.md), [`data/applications.md`](https://github.com/santifer/career-ops/blob/main/data/applications.md)) contain personal data and are **never touched by automatic updates**.

- **System-Layer files** ([`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md), `*.mjs` scripts, `templates/*`) contain core infrastructure and are **safe to replace** with upstream versions.

- The **Data Contract** in [`DATA_CONTRACT.md`](https://github.com/santifer/career-ops/blob/main/DATA_CONTRACT.md) defines both layers and enforces a hard boundary: User-Layer files cannot be read, modified, or deleted by any update process.

- The **`update-system.mjs`** script implements this contract, allowing selective updates that preserve user customizations.

## Frequently Asked Questions

### What happens if I edit a System-Layer file?

Your changes will be lost the next time you run `node update-system.mjs apply` or `git pull origin main`. Move permanent customizations to equivalent User-Layer files like [`modes/_custom.md`](https://github.com/santifer/career-ops/blob/main/modes/_custom.md).

### Can I convert a User-Layer file to System-Layer or vice versa?

The contract is maintained in [`DATA_CONTRACT.md`](https://github.com/santifer/career-ops/blob/main/DATA_CONTRACT.md). If you fork the repository, you can modify this file—but doing so voids the guarantee that upstream updates will respect your data boundaries.

### Where should I store my job application history?

Use [`data/applications.md`](https://github.com/santifer/career-ops/blob/main/data/applications.md), which is explicitly listed in the User-Layer. This ensures your tracking data persists across tool updates and is never overwritten by new releases.

### Does the update script verify the contract before running?

Yes. `update-system.mjs` parses [`DATA_CONTRACT.md`](https://github.com/santifer/career-ops/blob/main/DATA_CONTRACT.md) to build allowlists and denylists before touching any files. The script aborts if the contract file is missing or malformed.