# PRISM — Risk Intelligence Scoring Extension (Agent Instructions)

> Drop this file into your CLAUDE.md, .cursorrules, copilot-instructions.md, or agent system prompt to make your AI tool PRISM-compliant. This document is self-contained — no external files or downloads are required.

**Standard:** PRISM v1.0 | **Authors:** itsavibe.ai

> **Prerequisite:** This agent configuration implements the PRISM risk scoring extension. Your tool MUST already implement the VIBES data standard (see `vibes-agent.md`). PRISM stores its data on VIBES annotation records. For security attestation, see `verify-agent.md`. For agent learning and governance, see `evolve-agent.md`. For incident response and forensics (which uses PRISM scores as the default severity source), see `trace-agent.md`.

## Table of Contents

| § | Section | Anchor |
|---|---|---|
| 1 | What is PRISM? | [#1-what-is-prism](#1-what-is-prism) |
| 2 | Enabling PRISM | [#2-enabling-prism](#2-enabling-prism) |
| 3 | Severity Bands | [#3-severity-bands](#3-severity-bands) |
| 4 | Signal Vocabulary | [#4-signal-vocabulary](#4-signal-vocabulary) |
| 5 | Reference Scoring Algorithm | [#5-reference-scoring-algorithm](#5-reference-scoring-algorithm) |
| 6 | Storage Format | [#6-storage-format](#6-storage-format) |
| 7 | Agent Behavior | [#7-agent-behavior](#7-agent-behavior) |
| 8 | CI/CD Integration | [#8-cicd-integration](#8-cicd-integration) |

**Deep-load examples:**
- Just the signal vocabulary: `https://itsavibe.ai/prism-agent.md#4-signal-vocabulary`
- Just the CI/CD gating chapter: `https://itsavibe.ai/prism-agent.md#8-cicd-integration`

---

## 1. What is PRISM?

PRISM (Provenance & Risk Intelligence Scoring Model) quantifies the risk profile of an AI-generated change based on metadata available at annotation time. It combines audit signals — action types, scope, assurance levels, review status, temperature — into a single 0.0–1.0 score that CI/CD pipelines can act on.

PRISM is a **framework, not a fixed formula**. You MAY use the reference algorithm, customize its weights, or substitute an entirely different scoring function. The only normative requirement is the storage format — if you compute a risk score, you MUST store it using the fields defined in Section 5.

---

## 2. Enabling PRISM

PRISM is controlled by the `risk_scoring` object in `.ai-audit/config.json`. You MUST check this before computing scores.

```json
{
  "standard": "VIBES",
  "standard_version": "1.0",
  "assurance_level": "medium",
  "risk_scoring": {
    "enabled": true,
    "algorithm": "weighted_average",
    "weights": {
      "temperature": 0.15,
      "action_type": 0.15,
      "scope_lines": 0.15,
      "scope_files": 0.10,
      "assurance_gap": 0.10,
      "human_review_present": 0.15,
      "prompt_token_count": 0.10,
      "model_capability_tier": 0.10
    },
    "thresholds": {
      "low": 0.00,
      "medium": 0.30,
      "high": 0.60,
      "critical": 0.80
    },
    "review_rules": [
      {"condition": "temperature > 0.8 AND action_type == 'create' AND scope_lines > 100", "action": "require_review"},
      {"condition": "assurance_gap == 1.0", "action": "flag"}
    ]
  }
}
```

| Field | Type | Required | Default | Description |
|-------|------|----------|---------|-------------|
| `risk_scoring.enabled` | boolean | No | `false` | Enable PRISM computation |
| `risk_scoring.algorithm` | string | No | `"weighted_average"` | Scoring algorithm identifier |
| `risk_scoring.weights` | object | No | See Section 4 | Signal weight overrides (values will be normalized) |
| `risk_scoring.thresholds` | object | No | See Section 3 | Severity band boundaries |
| `risk_scoring.review_rules` | array | No | `[]` | Rule-based gating conditions (alternative to score thresholds) |

If `risk_scoring` is absent or `enabled` is `false`, you MUST NOT compute or store PRISM scores.

---

## 3. Severity Bands

PRISM scores map to four severity bands. Use configured thresholds if present, otherwise use these defaults:

| Band | Range | Meaning | Recommended Action |
|------|-------|---------|-------------------|
| **Low** | 0.00 – 0.29 | Routine change with minimal risk signals | Auto-merge permitted |
| **Medium** | 0.30 – 0.59 | Moderate risk — larger scope or assurance gap | Flag for review; require approval |
| **High** | 0.60 – 0.79 | Significant risk — complex change or missing review | Block merge; require senior review |
| **Critical** | 0.80 – 1.00 | Extreme risk — large unreviewed creation at high temperature | Block merge; escalate to security team |

---

## 4. Signal Vocabulary

Each signal produces a normalized value between 0.0 (lowest risk) and 1.0 (highest risk). You are not required to compute all signals — unavailable signals are omitted from the `risk_factors` array.

| Signal | Source | Normalization | Default Weight |
|--------|--------|---------------|----------------|
| `temperature` | Environment context | `min(temperature / 2.0, 1.0)` | 0.15 |
| `action_type` | Annotation record | `create` = 0.6, `modify` = 0.4, `delete` = 0.8, `review` = 0.1 | 0.15 |
| `scope_lines` | Annotation record | `(line_end - line_start + 1) / total_file_lines`, cap at 1.0 | 0.15 |
| `scope_files` | Session context | Files touched in session / baseline (default 20), cap at 1.0 | 0.10 |
| `assurance_gap` | Config + annotation | `low` = 1.0, `medium` = 0.5, `high` = 0.0 | 0.10 |
| `human_review_present` | Edge records | 0.0 if a `reviewed_by` edge exists, 1.0 if none | 0.15 |
| `prompt_token_count` | Prompt context | Token count / baseline (default 2000), cap at 1.0 | 0.10 |
| `model_capability_tier` | Environment context | Smaller/older models = higher risk. Implementation-defined. | 0.10 |

**Extensibility:** You MAY define additional custom signals. Custom signal names SHOULD use a namespace prefix (e.g., `custom:security_sensitive`, `org:compliance_tier`) to avoid collision with future standard signals.

---

## 5. Reference Scoring Algorithm

The reference algorithm computes PRISM as a weighted average of available signals:

```
PRISM = Σ(weight_i × value_i) / Σ(weight_i)    for all available signals
```

Signals that are unavailable (e.g., `prompt_token_count` at Low assurance) are excluded from both the numerator and denominator — their weight is redistributed proportionally.

### Example Computation

```
Signals:
  action_type        = 0.6   (create → high risk)     weight = 0.15
  scope_lines        = 0.85  (45 of 53 lines)         weight = 0.15
  human_review_present = 1.0 (no review edge)         weight = 0.15
  assurance_gap      = 0.5   (medium assurance)        weight = 0.10
  temperature        = 0.9   (near-max randomness)     weight = 0.15

PRISM = (0.6×0.15 + 0.85×0.15 + 1.0×0.15 + 0.5×0.10 + 0.9×0.15) / (0.15+0.15+0.15+0.10+0.15)
      = (0.09 + 0.1275 + 0.15 + 0.05 + 0.135) / 0.70
      = 0.5525 / 0.70
      = 0.789 → High severity band
```

### Alternative: Rule-Based Gating

Organizations MAY skip the scoring algorithm and define rule-based triggers instead. For example: "require review if `temperature > 0.8` AND `action_type == 'create'` AND `scope_lines > 100`". Check the `review_rules` array in config.

---

## 6. Storage Format

If you compute risk information, you MUST store it using these fields on line and function annotation records:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `risk_score` | number | No | Aggregate risk score, 0.0–1.0 |
| `risk_factors` | array | No | Array of signal assessments providing transparency into the score |

Each element in `risk_factors` is an object:

| Field | Type | Required | Description |
|-------|------|----------|-------------|
| `signal` | string | Yes | Signal name from the vocabulary |
| `value` | number | Yes | Normalized signal value, 0.0–1.0 |
| `weight` | number | Yes | Weight used in computation |
| `reason` | string | No | Human-readable explanation |

### Example Annotation with PRISM

```json
{"type":"line","file_path":"src/auth.py","line_start":1,"line_end":45,"environment_hash":"e7a3f1b2...","prompt_hash":"a1b2c3d4...","action":"create","timestamp":"2026-02-03T10:05:00Z","commit_hash":"abc123","session_id":"550e8400-...","assurance_level":"medium","risk_score":0.72,"risk_factors":[{"signal":"temperature","value":0.9,"weight":0.15,"reason":"Near-maximum randomness"},{"signal":"action_type","value":0.6,"weight":0.15},{"signal":"scope_lines","value":0.85,"weight":0.15,"reason":"45 of 53 lines (85%)"},{"signal":"assurance_gap","value":0.5,"weight":0.10},{"signal":"human_review_present","value":1.0,"weight":0.15,"reason":"No review edge found"}]}
```

---

## 7. Agent Behavior

### When to Compute

You MUST compute PRISM scores during the **post-generation hook** (see `vibes-agent.md` Section 7), after all other annotation fields have been populated.

Compute PRISM if and only if:
1. `.ai-audit/config.json` contains `"risk_scoring": {"enabled": true}`.
2. The annotation record has at least one signal available (e.g., `action` is always present).

### Computation Steps

For each line or function annotation record:

1. **Collect signals.** Read the annotation record, environment context, prompt context, edge records, and config to extract signal values. Use the normalization rules in Section 4.
2. **Read weights.** Use `risk_scoring.weights` from config if present, otherwise use defaults.
3. **Compute score.** Apply the configured algorithm (default: weighted average). Only include signals that have values — do not assume zero for missing signals.
4. **Check rules.** If `review_rules` are configured, evaluate each rule's condition against the signal values. Flag or block as specified.
5. **Store results.** Set `risk_score` and `risk_factors` on the annotation record before appending to `annotations.jsonl`.

### Minimum Implementation

A minimal PRISM implementation needs only:

1. Check if `risk_scoring.enabled` is `true` in config.
2. Compute `action_type` and `scope_lines` signals (always available).
3. Apply weighted average with those two signals.
4. Store `risk_score` and `risk_factors` on the annotation.

All other signals are optional enhancements.

---

## 8. CI/CD Integration

PRISM scores are most powerful when they drive automated pipeline decisions.

### Score-Based Gating (bash)

```bash
# Fail if any annotation has PRISM >= 0.8
MAX_PRISM=$(jq -rs '[.[] | select(.type == "line" and .risk_score != null) | .risk_score] | max // 0' .ai-audit/annotations.jsonl)
if (( $(echo "$MAX_PRISM >= 0.8" | bc -l) )); then
  echo "BLOCKED: Critical risk score ($MAX_PRISM). Requires senior review."
  exit 1
fi
```

### Factor-Based Gating (bash)

```bash
# Fail if any annotation has temperature signal > 0.9
HIGH_TEMP=$(jq -rs '[.[] | select(.risk_factors != null) | .risk_factors[] | select(.signal == "temperature" and .value > 0.9)] | length' .ai-audit/annotations.jsonl)
if [ "$HIGH_TEMP" -gt 0 ]; then
  echo "BLOCKED: $HIGH_TEMP annotations generated with near-max temperature."
  exit 1
fi
```

### DuckDB Query

```sql
SELECT file_path, line_start, line_end, risk_score, risk_factors
FROM read_json_auto('.ai-audit/annotations.jsonl')
WHERE type = 'line' AND risk_score >= 0.6
  AND commit_hash = '<COMMIT_SHA>'
ORDER BY risk_score DESC;
```

### vibecheck CLI

```bash
# Compute and display risk scores
vibecheck risk

# Fail CI if threshold exceeded
vibecheck risk --threshold 0.6 --ci

# JSON output for PR bots
vibecheck risk --format json

# Block critical merges
vibecheck risk --threshold 0.8 --ci --fail-on critical
```
