# CVSmia - User Guide

This page describes how to use CVSmia to build and save a tailored resume based on source data in [JSONResume](https://jsonresume.org/) format.

## Quick Example Flow With English Sample Data

This flow shows the simplest way to get started with the English sample resume that the app places in `Documents\Solsem Consulting\CVSmia`.

### 1. Start the app and check the tabs

On startup, the app opens in `Customizer`, and `Validation` is visible as its own tab from the start.

![Startup in English UI](images/usage-en-01-start.png)

### 2. Open the English sample resume

Press `Ctrl+O` or choose `Customizer -> Open`, then open `sampleresume_en.json`.

![Open English sample data](images/usage-en-02-open-dialog.png)

### 3. Review the source data in the left tree

After the file is loaded, the jsonresume sections appear in the left-hand `Sourcedata` tree. In the screenshot below, the root node is expanded so you can see the sections included in the sample data.

You can also type text into the filter field above `Sourcedata` and press `Filter` to show only matching nodes together with the surrounding tree context.

![Source data loaded](images/usage-en-03-source-loaded.png)

### 4. Build a first tailored resume

For a quick first test, hold `Ctrl` and click the root node `resume` in the left tree. This copies the full sample resume to the right side. In normal use, you can instead `Ctrl`-click or drag individual sections to build a more targeted version.

![Sample data copied to tailored resume](images/usage-en-04-tailored-from-sample.png)

### 5. Open the tailored resume in viewer

Once you have content in the right tree, open the viewer with `Ctrl+P` or the menu option that opens the viewer with data. The viewer shows the tailored resume in a print-friendly layout.

![Tailored resume opened in viewer](images/usage-en-05-viewer-open.png)

### 6. Print to PDF from viewer

When the viewer is open, press `Ctrl+P` in the browser and choose `Save as PDF` or a PDF printer such as `Microsoft Print to PDF`. The print dialog belongs to the browser, so the exact labels can vary slightly.

![Viewer ready for PDF print](images/usage-en-06-viewer-print-step.png)

After that, you can save the PDF to the folder you want, or continue removing, renaming, or saving JSON content from the right tree.

## Module Overview With Screenshots

The screenshots below show the remaining modules in the application. Some of them require a license before the tab becomes visible.

### 7. Validation

Use `Validation` when you want to check JSON against the schema, inspect errors by path/line, and edit the content before saving again.

![Validation module](images/usage-en-07-validation.png)

### 8. AI-Customizer

`AI-Customizer` is a dedicated workspace for selecting relevant resume content against a job ad with AI assistance. It combines source data on the left, the AI-tailored resume on the right, and the job-ad input below.

![AI-Customizer in English UI](images/usage-en-08-ai-customizer.png)

### 9. JsonResumeConverter

Use `JsonResumeConverter` when you want to load raw text or another source and convert it into jsonresume, with AI attempted first and a local fallback if needed.

![JsonResumeConverter in English UI](images/usage-en-09-converter.png)

### 10. Matcher

`Matcher` lets you load both a resume and a job description and run matching in its own module without changing the trees in `Customizer`.

![Matcher module in English UI](images/usage-en-10-matcher.png)

### 11. Cognitive

`Cognitive` is the module for language suggestions and rewriting. Use it when you want help improving or varying text content.

![Cognitive module in English UI](images/usage-en-11-cognitive.png)

## What is CVSmia?

CVSmia lets you:

- open source data (left tree),
- build a tailored resume by selecting content (right tree),
- save the result in an implemented export format (typically JSONResume, and Teamtailor when licensed),
- preview in viewer and validate against schema.

## Typical workflow

1. Open source data with `Ctrl+O`.
2. Optionally filter the source data with the text field above the left tree when you want to narrow large datasets.
3. Add content from left to right by drag-and-drop or `Ctrl+click`.
4. Edit right-tree nodes where allowed (`F2` rename, `Delete` remove).
5. Save with `Ctrl+S`.
6. Preview in viewer with `Ctrl+P` (with data) or `Ctrl+Shift+V` (viewer only).
7. Print to PDF from viewer with `Ctrl+P` in the browser.

## Validation

Use the Validation tab to:

- run validation,
- inspect errors (path/line/message),
- copy errors,
- edit JSON,
- save corrected content.

If you open an invalid file it is marked as pending in Validation until fixed and saved.

## Matcher

- The Matcher tab now includes a dedicated tree view with the JSONResume data used for matching.
- In the `Match` menu, you can choose `Open CV…` to load a CV and `Open JD…` to load a job description before running match.
- Loading from `Match` does not modify the `Customize` trees.
- Loading source data in `Customize` also does not update `Matcher` automatically.
- After each run, Matcher now shows recommended next steps, such as which requirement needs stronger coverage or which existing resume evidence should be highlighted.
- When licensed, `AI-Customizer` is shown as tab number 2.

## Shortcuts

- `Ctrl+O`: Open file
- `Ctrl+S`: Save tailored resume
- `Ctrl+P`: Open viewer with data
- `Ctrl+Shift+V`: Open viewer
- `Ctrl+Shift+O`: Read from GitHub (wherever that menu action exists)
- `Ctrl+,`: Settings
- `F1`: Open local help
- `Alt+F4`: Exit the app (consistent across module menus like `Customize`, `AI-Customizer`, `Validation`, `Converter`, `Cognitive`, and `Match`).
- `Delete`: Remove selected node in right tree
- `F2`: Rename selected editable node in right tree
- Module menus now use the same shortcuts for equivalent actions (for example `Open` = `Ctrl+O`, `Save` = `Ctrl+S`, `Open viewer with data` = `Ctrl+P` where available).

## Tips

- Keep one rich master resume in source data and make targeted variants in the right tree.
- Run validation before sharing/publishing.

## Machine-readable license manifest

- The app exposes supported license modules in `license-modules.json` in the application folder.
- The source file lives at `src/CVSmia.Licensing/license-modules.json`.
- The file uses the generic protocol format with `protocolVersion`, `application`, and `modules[].id`.
- The file is built from `src/CVSmia.Licensing/EnumAppModules.cs`, so update the enum and build the project when the supported module set changes.
- `None` is intentionally excluded from the manifest.

## Optional local telemetry

- Telemetry is off by default and must be enabled explicitly in `settings.json` or `appsettings.json` with `Settings:TelemetryEnabled = true`.
- When enabled, the app writes local events to `%APPDATA%\Solsem Consulting\CVSmia\telemetry.ndjson` unless `Settings:TelemetryStoragePath` is set.
- The current event set covers app startup and the startup license-check result.
- Raw customer and license identifiers are not written to this telemetry file.

## Startup license call-home

- Paid licenses can now be verified against SentinelCore during startup when `LicenseCallHome` is configured in `appsettings.json`.
- The same call-home flow is also used when a paid license is installed or reloaded from the app, so the active license is checked consistently against SentinelCore.
- The first rollout uses `ObserveOnly`. This means a valid local paid license still starts on network failure even if the lease cache is missing, but the event is logged clearly.
- Trial remains local through `trial.dat` and Registry. Trial does not call home.
- If a paid license file exists but is locally invalid, the app still does not fall back to trial.
- If SentinelCore rejects the paid license online, paid startup is rejected with no fallback to trial.
- On network failure, the app attempts to use a local lease cache in `%APPDATA%\Solsem Consulting\CVSmia`.

Configuration example:

```json
{
  "LicenseCallHome": {
    "Enabled": true,
    "Mode": "ObserveOnly",
    "BaseUrl": "https://sentinelcore.example.no/",
    "VerifyTimeoutSeconds": 5,
    "MetadataRefreshHours": 24,
    "LeaseCacheFileName": "sentinelcore-lease.json",
    "InstallationIdFileName": "installation-id.json"
  }
}
```

## GitHub as a Resume Source

- Use the `Read from GitHub` menu item when you want to load resume data from GitHub.
- The menu item is available in `Customize`, `JsonResumeConverter`, `AI-Customizer`, and `Matcher`.
- Before the menu item is enabled, configure GitHub in `Settings` with either a `Token` or `Username and password`.
- GitHub credentials are stored encrypted locally per user.
- When you select `Read from GitHub`, a GitHub browser dialog opens so you can browse accessible repositories, choose a branch, and navigate to the file you want.
- You no longer need to paste a raw GitHub URL manually.
- Regular local file loading via `Open` is still available as before.
- GitHub menu items stay disabled until the required GitHub credentials are configured.
- Token authentication is recommended for github.com.

## jsonresume conversion and AI

- `JsonResumeConverter` attempts AI conversion first.
- `JsonResumeConverter` uses the same AI settings as AI Customizer (`AiEnabled`, `AiProvider`, `AiModel`, `AiEndpoint`) from `settings.json`/`appsettings.json`.
- `JsonResumeConverter` uses the same provider resolver as AI Customizer; the selected provider/model in settings is used directly (including Gemini, Anthropic and Ollama), with local fallback on failure.
- `JsonResumeConverter` now follows the same AI integration pattern as AI Customizer: the panel calls a dedicated AI assistant service, while the converter module only handles AI-attempt + local fallback.
- `JsonResumeConverter` now shows in its title whether the current result came from AI or from local fallback.
- `Validation` always runs local schema validation first, then attempts an AI explanation in its own prompt mode (`ValidationAssistant`) when validation finds errors.
- If AI is disabled, the API key is missing, the selected provider is unsupported, or the AI call fails, `Validation` now shows a short status that local fallback is being used.
- `Validation` now also shows local fix suggestions in a dedicated `Suggestion` column for common issues such as missing fields, invalid dates, and type mismatches.
- The Validation summary area also highlights concrete suggestions worth fixing first.
- The app status bar now gives clearer next-step guidance after loading source data, matching, validation, save, and preview actions.
- OpenAI-compatible calls (payload, auth and response parsing) are moved to the shared `CVSmia.Ai` library, used by both AI Customizer providers and `JsonResumeConverter`.
- Prompt and instruction building remain module-specific: `JsonResumeConverter` uses its own prompt builder (`IJsonResumePromptBuilder`) and does not share domain instructions across modules.
- AI is used when a valid API key is available (`OPENAI_API_KEY` or stored key in `%APPDATA%\Solsem Consulting\CVSmia\ai-api-key.dat`).
- In AI Customizer, the `Customize (ask AI)` menu item is disabled when `AiEnabled` is off or when no stored API key exists.
- If AI capability is unavailable or the AI call fails, the module automatically falls back to the local heuristic converter.
- `AI-Customizer` and `AI Assisted CV Manipulator` now use the same standard messages as the other AI flows when AI is disabled, the API key is missing, or the selected provider is unsupported.
- If invalid JSONResume is opened in AI-Customizer (`Open source data`), the file is routed to the Validation module for review/fix.
- When Validation saves/fixes pending JSON, data is sent back to the same module it came from (Customize or AI-Customizer).
- AI-Customizer now has a dedicated menu option to load job-ad text directly into the job-ad text field.
- `Open JD` in AI-Customizer always loads raw text and does not route through the Validation module.
- Model instructions are externalized in `prompts/jsonresume-extract.no.json` using `systemInstruction` and `userTemplate`.

## Change AI instructions without rebuilding

You can change AI system instructions and prompt templates without recompiling:

- Install-level defaults: edit `ai-prompts.json` in the app folder (same location as `CVSmia.exe`).
- Per-user override: create/edit `%APPDATA%\Solsem Consulting\CVSmia\ai-prompts.override.json`.

When to use which:

- `ai-prompts.json`: change default behavior for the installation.
- `ai-assisted-cv-manipulator-instructions.json`: control which predefined instructions are shown in `AI Assisted CV Manipulator`.

## AI Assisted CV Manipulator

`AI Assisted CV Manipulator` is a dedicated module for free-form AI processing of CV data.

- This module requires its own paid license and is hidden unless the module entitlement is included.
- Paste CV data into the left text box.
- Use `Ctrl+O` or the `Open` menu item to load source data directly into the left text box.
- Enter your own instruction in the middle column or choose a predefined instruction from the dropdown.
- Click `Execute` to send both the instruction and the CV data to the selected AI model.
- The result is shown in the right text box.
- Use `Save to file` to save the content from the right text box.
- Use `Edit instructions` to open and save the JSON list that controls the dropdown directly from the module.

Predefined instructions are loaded from `ai-assisted-cv-manipulator-instructions.json` in the application folder. The shipped file uses resource keys, but you can also provide explicit `displayName` and `instruction` values directly in the JSON file if you want custom presets.
The default list includes summary, skills extraction, role profile, conversion to jsonresume, translation to English, translation to Norwegian Bokmal, and a quality check for missing information.
- `ai-prompts.override.json`: let one user override locally without changing installed files.

Important:

- Use valid JSON.
- Keep required tokens in templates:
  - matching template: `{{jobDescription}}` and `{{resumeElements}}`
  - customizer template: `{{jobAdText}}`, `{{maxSelections}}` and `{{minConfidencePercent}}`
  - validation template: `{{validationIssues}}` and `{{resumeJson}}`
- Tone-specific system instruction can also be overridden via `SystemInstructionByTone.ValidationAssistant`.
- If a file is missing or invalid, the app falls back to built-in defaults.

## AI Customizer confidence threshold

- AI Customizer now uses both max selections and a minimum confidence percent.
- `AiCustomizeMinConfidencePercent` (0-100, default 60) controls which AI picks are included.
- Items with a reported `confidence` below the threshold are filtered out before insertion.
- `confidence` is interpreted both as percent (0-100) and decimal (0-1), so values like `82` and `0.82` are treated the same.
- To receive confidence values, the prompt format must request `selected[].confidence`; the system instruction is now aligned to follow the output format from the user prompt.
- AI Customizer now uses a dedicated provider prompt mode (`CustomizerSelection`) so customizer output format is not overridden by the generic `matchedIds` template.
- After AI extraction, a summary is shown with how many nodes had `confidence` and how many did not.
- Hover over a node in the right tree (tailored CV) to view node-specific AI confidence when available.
- Nodes in the right tree are also color-coded by confidence (high = green, medium = yellow, low = red).
- Confidence color is applied to the node area itself (not the full row background).
- For truncated/incomplete AI JSON output, AI Customizer now avoids parsing the full response as JSON and goes directly to robust fallback extraction of `id`/`confidence` from loose text.
- For OpenAI/Azure OpenAI, AI Customizer now uses JSON mode (`response_format: json_object`) and a higher max token limit in customizer calls to reduce truncated responses.
- AI Customizer now applies a two-pass selection strategy for better precision when many nodes are suggested: pass 1 gathers a broad candidate set, pass 2 reranks only candidates and returns top `maxSelections`.
- Manual drag-and-drop is now supported both ways in AI Customizer: drag from left to right to add, and drag from right back to left to remove from `AI-customized CV`.
- In the right tree, the selected node can also be removed with the `Delete` key.
