# Career-Ops System Defaults vs. User Customization: _shared.md and _profile.md Explained

> Understand the difference between Career Ops system defaults in _shared.md and user customizations in _profile.md. Learn how these files control scoring and tool behavior.

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

---

**In the `santifer/career-ops` project, [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) ships auto-updatable system defaults that control core scoring and tool behavior, whereas [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) holds static user customizations that the engine loads second to override any conflicting baseline values.**

Career-Ops cleanly separates immutable framework logic from personal career data. Understanding the distinction between **system defaults** and **user customization** in [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) and [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md) files is essential to upgrading safely without losing your preferences. Each file has a strict update policy and load order that prevents accidental overwrites while guaranteeing your settings always win.

## The Role of modes/_shared.md as System Defaults

### Core Logic and Scoring Matrices

[`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) houses the foundation of the application. It contains the **scoring matrix** (blocks A–F and the global score), **posting legitimacy tiers**, **archetype detection** tables, global NEVER/ALWAYS rules, and **tool definitions** such as WebSearch and Playwright. Because this logic may evolve with each release, the file is designed to be regenerated by the project’s update mechanism.

### Auto-Updatable by Design

[`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) is explicitly marked as auto-updatable. The system context header warns: “**THIS FILE IS AUTO-UPDATABLE. Don't put personal data here**.” Users should never edit this file for personal preferences because any update to the repository will overwrite those changes.

## The Role of modes/_profile.md as User Customization

### Candidate-Specific Career Data

[`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) stores the details that tailor the system to an individual. It holds **target role lists**, **adaptive framing tables**, **exit narrative**, cross-cutting advantage statements, portfolio links, **compensation targets**, **negotiation scripts**, and location policy. All of these fields map directly to how the application represents your career narrative.

### Static and User-Controlled

[`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md) is created once from [`modes/_profile.template.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.template.md) and then manually edited by you. The header clearly states: “**THIS FILE IS YOURS. It will NEVER be auto-updated**.” The updater never touches this path, so your customizations survive upgrades indefinitely.

## How Career-Ops Loads and Merges the Files

### Explicit Override Sequence

As implemented in `santifer/career-ops`, the engine reads [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) first to establish baseline defaults. It then reads [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) second. Any overlapping keys or conflicting settings are overridden by the user’s values. This predictable load order guarantees that personal preferences always win when the core rules change.

### Reading Both Files in Node.js

You can inspect the merge logic by loading both files at runtime:

```javascript
import { readFile } from 'fs/promises';
import path from 'path';

async function loadContext() {
  const shared = await readFile(
    path.resolve('modes/_shared.md'), 'utf8');
  const profile = await readFile(
    path.resolve('modes/_profile.md'), 'utf8');

  // Simple merge: profile values overwrite shared defaults
  const context = { shared, profile };
  return context;
}

```

### Pseudo-Logic for the Merge Engine

The evaluation engine behaves conceptually like this:

```javascript
// Pseudo-code from the evaluation engine
const defaults = parseMarkdown(sharedFile);
let config = { ...defaults };

if (fs.existsSync('modes/_profile.md')) {
  const overrides = parseMarkdown('modes/_profile.md');
  config = deepMerge(config, overrides); // user values win
}

```

### Adding a Custom Archetype

To override the built-in archetype list, define your own rows in [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md):

```markdown

# In modes/_profile.md

## Your Target Roles

| Archetype | Thematic axes | What they buy |
|-----------|---------------|---------------|
| **Data Engineering** | Pipelines, ETL, warehousing | Engineers who build reliable data platforms |

```

After saving, the next evaluation uses your “Data Engineering” entry instead of the default list from [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md).

## Where to Place Customizations in Career-Ops

### Do Not Use _shared.md for Personal Data

All personal archetypes, narrative framing, location policy, and compensation targets belong exclusively in [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md). Editing [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) risks complete data loss during the next update cycle.

### Related Files in the Merge Stack

Several other paths participate in the final context. [`config/profile.yml`](https://github.com/santifer/career-ops/blob/main/config/profile.yml) stores candidate identity metadata such as name, email, and location. [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) serves as the canonical curriculum vitae referenced by both defaults and customizations. However, the primary boundary between system defaults and user customization still rests on the [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) versus [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md) distinction.

## Why the Separation Matters

- **Reliability:** System defaults stay in sync with new releases, ensuring new features and bug-fixes are automatically available.
- **Safety:** User customizations survive upgrades because the updater never touches [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md).
- **Predictability:** The explicit load order ([`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) → [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md)) guarantees that personal preferences always win, avoiding surprising behavior when core rules change.

## Summary

- [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) contains auto-updatable system defaults including scoring rules, archetype detection, and tool configurations.
- [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) holds static user customizations such as target roles, narrative framing, and negotiation scripts.
- The engine loads [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) first and [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md) second, so overlapping user values override system baselines.
- Personal data should never be added to [`_shared.md`](https://github.com/santifer/career-ops/blob/main/_shared.md) because updates will overwrite it.
- Career-Ops references [`config/profile.yml`](https://github.com/santifer/career-ops/blob/main/config/profile.yml) for identity metadata and [`cv.md`](https://github.com/santifer/career-ops/blob/main/cv.md) for the canonical CV, but the core override logic depends on the two `modes` files.

## Frequently Asked Questions

### What happens if I edit _shared.md instead of _profile.md?

Any changes you make to [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) will be lost the next time the project auto-updates. The updater regenerates this file from the repository defaults, so you should treat it as read-only framework logic.

### How does Career-Ops resolve conflicting settings between the two files?

The engine always reads [`modes/_shared.md`](https://github.com/santifer/career-ops/blob/main/modes/_shared.md) first to build a baseline configuration. It then reads [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) and performs a deep merge where user values overwrite matching keys from the shared defaults. This ensures your personal settings take precedence.

### Can I restore _profile.md if I break my customizations?

Yes. Because [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md) is created once from [`modes/_profile.template.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.template.md), you can always return to the original template and copy it to create a fresh [`_profile.md`](https://github.com/santifer/career-ops/blob/main/_profile.md). Your broken file will never be overwritten by an updater, so restoration is entirely manual and under your control.

### What file should I edit to add a custom archetype or negotiation script?

Add all custom archetypes, adaptive framing tables, compensation targets, and negotiation scripts to [`modes/_profile.md`](https://github.com/santifer/career-ops/blob/main/modes/_profile.md). This is the sole location for personalizations, and the engine will prefer these entries over the built-in system defaults.