---
name: deeper-signals-roi
description: >
  Use this skill whenever a user wants to build, justify, or defend the business case for a
  selection, promotion, or assessment program. Triggers include: "build a business case for an
  assessment", "ROI for hiring assessments", "justify our assessment spend", "what is the value
  of better hiring", "make the case to my CFO or CHRO", "is this assessment worth it", "model
  the value of better selection", "cost of a bad hire", "what would better promotion decisions
  be worth", "value of reducing turnover through better selection", or any request to translate
  workforce data and assessment validity into an estimated dollar value and a value-per-dollar
  figure. Also triggers when a user wants a branded ROI or business case document for an
  assessment investment. Always use this skill when the user wants a structured value case for a
  selection or promotion program, even if they do not say "ROI". It models a process, never a
  candidate.
---

# Assessment Value and Business Case Builder

This skill builds a defensible business case for a selection or promotion assessment program and
delivers it as a compact Deeper Signals branded Word document (cover plus about three content
pages), produced by the booklet generator vendored in `booklet/`.

The model is lean and built from textbook utility analysis. Value comes from one defensible
idea: how much better a proposed process predicts performance than the current one. Two streams:

1. **Performance value (primary).** The Brogden-Cronbach-Gleser result in incremental form:
   `N x delta_r x SD_y x Z_x x T`, where `delta_r` is the GAIN in validity over the current
   process. Undiscounted (no NPV).
2. **Retention value (secondary, conditional).** Replacement cost avoided when better selection
   reduces voluntary turnover. Shown ONLY when the user supplies a turnover rate.

Do not re-derive formulas by hand; always use `scripts/roi_engine.py`. The full specification is
in `references/roi_model.md` and `references/utility_analysis_math.md`.

---

## Operating principles (non-negotiable)

1. **Run a short intake before building.** Never invent workforce numbers. Quick mode needs only
   four inputs (see below). Ask, do not assume.
2. **Value comes from the GAIN, not the level.** Always model the current process and the
   proposed battery, and base value on the difference. If the user cannot describe the current
   process, default it to an unstructured interview and say so (a stronger baseline lowers the
   estimate).
3. **Budget is the denominator.** Ask the planned annual investment. It drives the headline
   value-per-dollar figure.
4. **Require Conservative / Expected / Strong. Prohibit point estimates** in the impact table.
   The engine produces all three.
5. **Ban validity coefficients from the body.** Never print r, R, or rho in the opportunity,
   approach, or impact sections. Translate into plain language (a top-performer multiplier, a
   dollar figure). Coefficients appear only in the methodology section.
6. **Validity is combined, not summed** (multiple-R, uniform 0.2 intercorrelation, cap 0.60),
   for both the current and proposed batteries.
7. **No NPV.** Figures are undiscounted by design. State this in the methodology.
8. **Retention only when earned.** Compute and show the retention stream only if the user
   supplies a voluntary turnover rate. Cost per departure defaults to 0.50 of salary or the
   user's own figure.
9. **Always USD.** If the user gives non-USD figures, convert before building the inputs JSON and
   pass `currency_note` to record the rate.
10. **Compact and branded.** Target cover plus three content pages, never more than four content
    pages. No orphaned headings. Methodology is one page. See `references/document_structure.md`.
11. **Never evaluate a candidate.** No scoring, ranking, or hire / no-hire recommendation
    anywhere. The skill models a process.

---

## Modes and inputs

**Quick mode (4 inputs):** decisions per year, average salary, current vs proposed process,
annual budget. Everything else defaults (selection ratio 0.20, tenure 3 years, SD_y 0.40 of
salary). No retention stream (no turnover rate supplied).

**Refined mode:** adds selection ratio, expected tenure, voluntary turnover rate (this turns on
the retention stream), cost per departure, and role or population splits via multiple segments.

A **segment** is one decision population (for example external hiring, or leadership promotion).
The engine sums across segments. Set `decision_type` to "hiring" or "promotion" per segment.

---

## Required intake (collect before building)

Collect the following before producing anything. The user must supply the Required items. For
Recommended and Context items, if the user does not know, use the documented estimate, tell the
user in chat what you assumed, and record it in the methodology (the document already does this).
Never invent a Required item.

**Required (needed to generate the business case):**

1. **Organisation name** (for the document).
2. **Decision type and populations.** Is this for hiring, promotion or succession, or both, and
   should it be split into more than one population (for example graduate hiring and leadership
   promotion modeled separately)?
3. **Number of decisions per year**, for each population (how many hires and / or promotions
   annually).
4. **Average salary** for the role(s) in each population.
5. **Current process.** What is used today to make these decisions. If the user cannot describe
   it, the model defaults to an unstructured interview and says so (a stronger current process
   lowers the estimate, so this default is the value-maximising end and must be stated).
6. **Proposed assessment(s).** Which assessment(s) the user wants to use. Map plain terms to a
   method (see Step 1); confirm the mapping with the user.
7. **Annual budget.** The amount the user plans to invest per year in the assessments. This is
   the denominator for the value-per-dollar figure.

**Recommended (improves accuracy; estimated and stated if unknown):**

8. **Selectivity (selection ratio).** Roughly how many people are considered for each decision
   made (for example 1 in 5). Estimate if unknown: 1 in 5 (0.20).
9. **Expected tenure.** How long people typically stay in the role, in years. Estimate if
   unknown: 3 years.
10. **Cost to replace someone who leaves.** Estimate if unknown: 50% of salary. Used only when
    the retention figure is shown (see item 11).
11. **Voluntary turnover rate.** The annual percentage who leave voluntarily. This is the one
    item that is NOT silently estimated: the retention figure appears only when the user supplies
    a turnover rate. If the user does not know it, offer to include an estimated retention figure
    using a typical benchmark (clearly flagged as an estimate) and include it only if the user
    agrees, so the headline is never inflated by a guessed turnover number.

**Context (optional, for framing only):**

12. **Organisation size** (total headcount). Used only to frame the opportunity section and to
    sanity-check the number of decisions; not used in the calculation. Passed as `org_size`.
13. **Currency.** If figures are not in USD, convert to USD, set `currency_note` to record the
    rate, and proceed in USD throughout.

If the user pushes for a number without giving inputs, gather at least the Required items first;
do not produce a business case from assumptions alone.

---

## Document structure (fixed)

Cover, then: 1) The opportunity, 2) The proposed approach, 3) Estimated impact, 4) Methodology
and assumptions (one page), 5) About Deeper Signals (the fixed call to action), 6) the verbatim
disclaimer. Do not add an executive summary or extra sections. See
`references/document_structure.md`.

---

## Workflow

### Step 1: Intake

Gather the inputs for the chosen mode. Map the current and proposed processes to method names
from `references/validity_coefficients.md`. Use documented defaults for anything not provided and
note them.

**Mapping the assessment type.** The value reflects the specific methods chosen, so capture them
precisely. The engine recognises common plain terms (for example "a cognitive test", "an
aptitude test", or "a personality assessment") via aliases, and combining distinct methods
(personality plus cognitive plus a structured interview) recomputes the combined validity. Two
points of discipline:

- When a user names a broad category like "personality assessment", it anchors to a conservative
  representative coefficient (contextualized conscientiousness). Tell the user the mapping you
  used and offer to refine it (for example, to a specific Deeper Signals instrument with its own
  validation figure). If they give a locally validated value, use it.
- Combine only distinct methods. Do not stack several facets of one instrument as if they were
  independent (see `references/validity_coefficients.md`); model one personality assessment as a
  single method, then combine it with other distinct methods.

If a method name is not recognised, the engine raises a clear error rather than dropping it, so
resolve every method to a recognised name or alias before running.

### Step 2: Compute

Write the inputs JSON and run the engine:

```bash
python3 scripts/roi_engine.py /tmp/inputs.json /tmp/results.json
```

Inputs JSON schema (one or more segments):

```json
{
  "client_name": "[Client Co]",
  "org_size": 1200,
  "budget": 150000,
  "currency_note": null,
  "segments": [
    {
      "name": "External hiring",
      "decision_type": "hiring",
      "n": 50,
      "salary": 80000,
      "selection_ratio": 0.20,
      "tenure": 3,
      "current_methods": ["Unstructured interviews", "Job experience (years)"],
      "proposed_methods": ["Structured interviews", "Cognitive ability tests", "Conscientiousness (contextualized)"],
      "turnover_rate": 0.15,
      "cost_per_turnover": null
    }
  ]
}
```

`selection_ratio`, `tenure`, `current_methods`, `turnover_rate`, and `cost_per_turnover` are
optional. Omit `turnover_rate` to leave the retention stream out (quick mode). The engine returns
three scenarios (performance, retention, total, benefit-cost ratio) and per-segment detail
including the lay translations.

### Step 3: Build the content

```bash
python3 scripts/build_booklet_content.py /tmp/results.json /tmp/meta.json /tmp/content.json
```

`meta.json` fields (all optional): `client_name`, `date`, `title`, `subheading`,
`methods_label`. Defaults: title "Assessment ROI", subheading "Building the business case". Keep
a custom `title` short (it renders at 56pt). The builder enforces the no-coefficients-in-body
rule, the scenario table, the one-page methodology, the fixed call to action, the verbatim
disclaimer, and the value-per-dollar cover tagline.

To change which call-to-action variant is used, set `CTA_DEFAULT` ("A", "B", or "C") at the top
of `scripts/build_booklet_content.py`. See `references/positioning.md`.

### Step 4: Generate the document

The generator is a single self-contained bundle (the `docx` library compiled in; no
`node_modules` needed). Run from the skill root:

```bash
node booklet/scripts/generate_booklet.js \
  /tmp/content.json /mnt/user-data/outputs/assessment_business_case.docx booklet/assets

python3 booklet/scripts/embed_fonts.py \
  /mnt/user-data/outputs/assessment_business_case.docx booklet/assets/fonts
```

The only host requirement is Node.js. To rebuild the bundle from source after editing
`booklet/scripts/generate_booklet.src.js`:

```bash
esbuild booklet/scripts/generate_booklet.src.js --bundle --platform=node \
  --outfile=booklet/scripts/generate_booklet.js
```

### Step 5: QA and deliver

```bash
python3 /mnt/skills/public/docx/scripts/office/validate.py /mnt/user-data/outputs/assessment_business_case.docx
soffice --headless --convert-to pdf --outdir /tmp /mnt/user-data/outputs/assessment_business_case.docx
pdftoppm -jpeg -r 100 /tmp/assessment_business_case.pdf /tmp/preview
```

Confirm: the document is four pages or fewer, the cover tagline carries the value-per-dollar
figure, no validity coefficient appears in the body, the impact section shows three scenarios
(not a point estimate), the methodology is one page, the call to action and the verbatim
disclaimer are present, and there are no orphaned headings. Then call `present_files` on the
.docx.

---

## Content standards

- No em dashes or en dashes anywhere. Use commas, parentheses, or periods.
- No italics except statistical symbols.
- All money in US dollars.
- The disclaimer is verbatim (`STANDARD_DISCLAIMER` in the builder). It is jurisdiction-neutral;
  recommend the client have qualified employment counsel review any process before launch.
- The call to action is fixed and identical in every document.

---

## Reference files

- `references/roi_model.md`: the two-stream model, segments, inputs, defaults, and what changed.
- `references/utility_analysis_math.md`: exact Z_x, scenario conventions, lay translations, and
  the evidence basis for the retention band and cost default.
- `references/validity_coefficients.md`: the Sackett (2022) validity table and multiple-R logic.
- `references/document_structure.md`: section order, compactness rules, the scenario table.
- `references/positioning.md`: brand voice and the three call-to-action variants.
- `scripts/roi_engine.py`: the two-stream engine.
- `scripts/build_booklet_content.py`: builds the compact booklet content JSON.
- `booklet/`: the vendored Deeper Signals generator. `scripts/generate_booklet.js` is the
  self-contained bundle, `scripts/generate_booklet.src.js` is its readable source,
  `scripts/embed_fonts.py` embeds the brand fonts, and `assets/` holds fonts, logo, and gradient.
- `evals/`: test scenarios and a mechanical validation input.

This skill is self-contained: the generator and brand assets are vendored under `booklet/`, so
it produces a branded document with no external skill. Host requirements: Python 3 with numpy
(engine) and Node.js (generator). The QA step uses host tools and is optional.
