> ## Documentation Index
> Fetch the complete documentation index at: https://docs.starfort.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Write a Rule Package

> Fill in Layer A detectors, Layer B classification rules, and the Layer C label policy — in the right order — for Stratum grading (Starfort v1.4 docs)

Where [Manage Stratum policies](/en/v1.4/admin/stratum-policy) covers the structure and version discipline of Taxonomies and Rule Packages, this page covers a Rule Package's **content** — what to fill in first across the three layers, and how to design priorities, terminals, and suppression so rules don't fight each other.

A single document's classification passes through the three layers in order:

```mermaid theme={"dark"}
flowchart LR
    D["Document"] --> A["Layer A<br/>detector signals"]
    A --> B["Layer B<br/>classification rules → grade candidates"]
    B --> C["Layer C<br/>label policy → final grade"]
    C --> R1["Auto-finalized"]
    C --> R2["Gray zone<br/>(secondary review)"]
    C --> R3["Blocked"]
```

<Note>
  The YAML on this page is excerpted to illustrate structure. For real authoring, start from the **policy type template** `/aim` provides, and treat the template's schema as the authority on fields and validation. Templates support both JSON and YAML; the policy model is defined in YAML.
</Note>

## Before you start — Taxonomy first

Every grade reference in a Rule Package comes from the Taxonomy. Before writing, finalize the project's Taxonomy (grade set, ranks, verdict methods, thresholds) and decide which version the Rule Package will reference. Every detector's grade attribution and every grade a classification rule emits must be **a grade that exists in that Taxonomy version**.

## Layer A — detectors: what to detect

A detector is the smallest unit that detects a specific signal, and each one carries a grade attribution — which grade it contributes to. Their character differs by pipeline stage:

| Stage  | Detector                | Best suited for                                                                                                                               |
| ------ | ----------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| **L1** | Fingerprint             | Filled-in copies of registered [fingerprint templates](/en/v1.4/admin/fingerprint-templates) — high confidence, immediate grounds to finalize |
| **L1** | Exact match             | Exact matches against pre-registered real data                                                                                                |
| **L2** | Pattern                 | Structured identifiers with a fixed shape (SSNs, card numbers, and the like) — paired with validation rules                                   |
| **L2** | Keyword                 | Domain keywords — context-word proximity reinforces confidence                                                                                |
| **L3** | Semantic classification | Inferring a grade from the document's meaning, even without structured signals                                                                |
| **L4** | Clause-based judgment   | Judging boundary cases against policy clauses — counter-evidence included                                                                     |

```yaml theme={"dark"}
detectors:
  - id: det.pat_ssn
    kind: pattern
    grade_attribution: confidential
    regex: '(?<!\d)\d{3}[-.\s]?\d{2}[-.\s]?\d{4}(?!\d)'
    validator: ssn_area_group_check
    context_words: [ssn, social security]
    proximity_chars: 250
    confidence_tiers: { format: 0.75, context: 0.85, checksum: 0.95 }
    action: mask

  - id: det.fp_contract_application
    kind: fingerprint
    grade_attribution: confidential
    template_id: tmpl_contract_application
    match_threshold: 0.8
    action: review_only
```

Authoring guidance:

* **Get the grade attribution right on every detector.** The grade a detector contributes to is the starting point for Layer B combinations and Layer C aggregation.
* **Build pattern detectors in three tiers: format + validation + context.** Anchor digit boundaries in the regex (`(?<!\d)`, `(?!\d)`); use a `validator` — a checksum or validity check, such as rejecting SSN areas and groups the SSA never issues — as reinforcement that raises confidence; and use `context_words` + `proximity_chars` as a confidence ladder (`confidence_tiers`) that steps up when a context word is nearby. Distinguishing a format-only match from one that also passed context and validation, at different confidences, is what lets Layer B set threshold conditions.
* **`action` decides a detection's masking treatment.** Set items whose risk masking removes to `mask`, so they take part in re-grading the masked copy. Set items that stay risky even when redacted — credentials and the like — or signals that are merely evidence for a judgment, to `review_only` — a document left with non-maskable items keeps its grade, and external transfer stays blocked.
* **Fingerprint detectors reference registered forms.** The fingerprint template `template_id` points at must be registered in the project, and reference validity is verified when the Rule Package is activated.

L4 clause-based judgment defines grade criteria as natural-language clauses. Draw the boundary with include/exclude examples, and add **counter-evidence clauses** — "already publicly disclosed," for instance — pointing the other way:

```yaml theme={"dark"}
clauses:
  - clause_id: cl.confidential.underwriting_criteria
    grade: confidential
    title: Underwriting criteria
    markdown: |
      Content that exposes underwriting logic or threshold values is Confidential.
      - Includes: decision-criteria tables; internal manuals carrying threshold values.
      - Excludes: general discussion of criteria already publicly disclosed.
```

L4's judgment only ever acts as a "needs review" signal — it never directly blocks or masks on its own.

## Layer B — classification rules: signals into grade candidates

Classification rules combine detector signals and emit grade candidates:

| Element      | Role                                                                                                                                                     |
| ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `condition`  | The combination of detector signals — `signal` (matched or not), `compare` (count or confidence comparisons), `and` / `or` / `not` (negative conditions) |
| `emit`       | The grade candidate emitted when the condition holds                                                                                                     |
| `priority`   | Evaluation priority across rules                                                                                                                         |
| `terminal`   | Confirm — a strong rule that finalizes its grade immediately                                                                                             |
| `suppresses` | Suppress — when this rule fires, the named rules' candidates are voided                                                                                  |

```yaml theme={"dark"}
rules:
  - id: rule.confidential_application_form   # filled-in registered form — finalize immediately
    priority: 90
    condition: { op: signal, detector_id: det.fp_contract_application, test: matched }
    emit: { grade: confidential }
    terminal: true

  - id: rule.confidential_pii_verified       # verified unique identifier — with a confidence threshold
    priority: 80
    condition:
      op: and
      nodes:
        - { op: signal, detector_id: det.pat_ssn, test: matched }
        - { op: compare, detector_id: det.pat_ssn, field: confidence, cmp: ge, value: 0.85 }
    emit: { grade: confidential }

  - id: rule.general_masked_derivative       # negative condition — an already-redacted document suppresses the confidential candidate
    priority: 78
    condition:
      op: and
      nodes:
        - { op: signal, detector_id: det.pat_mask_artifacts, test: matched }
        - { op: not, node: { op: signal, detector_id: det.pat_ssn, test: matched } }
    emit: { grade: general }
    suppresses: [rule.confidential_pii_verified]
```

Design guidance:

* **Reserve `terminal` for evidence with near-certain confidence.** Fingerprint matches and exact matches — signals with almost no false-positive room — are the candidates. Overusing terminal robs the later stages (semantic classification, clause judgment) and the label policy of their chance to correct.
* **Set thresholds with `compare`.** The same detector yields different confidences for a format-only match versus one that also passed validation, so tighten a rule's firing condition by comparing `field: confidence` or `field: count`.
* **Encode counter-evidence with negative conditions.** As above: mask artifacts present and no live PII means a redacted derivative — emit General while voiding the Confidential candidate via `suppresses`. L4's counter-evidence clauses (already disclosed, confirmed public) can likewise be excluded from Confidential clause verdicts with a `not` condition.
* **Order `priority` by strength of evidence.** Put the confirm-class rules high; leave weak signals that can't stand alone as low-priority secondary candidates, useful for converging on the gray zone.

## Layer C — label policy: conflict resolution and external-transfer routing

The label policy finalizes the grade candidates Layer B emitted and decides external-transfer routing:

```yaml theme={"dark"}
label_policy:
  taxonomy_ref: my-company@1.0
  conflict_resolution: highest_rank
  manual_label_precedence: true
  routing:
    confidential: { low: 0.60, high: 0.85 }
    internal:     { low: 0.60, high: 0.85 }
```

* **`taxonomy_ref`** — the specific Taxonomy version this Rule Package references.
* **`conflict_resolution: highest_rank`** — when one document yields multiple grade candidates, finalize at the highest grade. A single sensitive section pulls the whole document's grade up, preventing under-classification.
* **`manual_label_precedence`** — a manually assigned grade is never silently overwritten by automatic classification.
* **`routing`** — per-grade confidence thresholds. At or above `high`, the verdict auto-finalizes; between `low` and `high`, it routes to the gray zone and on to human secondary review. Verdicts ineligible for external transfer are blocked.

The General grade isn't score-based — it's a **clearance gate**: only documents with no suspicious signals and a completed classification pass. When classification can't run to completion (analysis failure, timeout), the document is never demoted to General; it's handled fail-secure, on the safe side.

## Taxonomy referential integrity

* The Taxonomy version a Rule Package references is **pinned** by `taxonomy_ref`. Publishing a revised Taxonomy doesn't move existing Rule Packages — they keep running against the version they reference. To adopt the new grading scheme, publish a new Rule Package version with an updated `taxonomy_ref` and pin it.
* Whether every detector's grade attribution and every emitted grade exist in the referenced Taxonomy's grade set — and whether the fingerprint templates and versions that fingerprint detectors reference exist — is subject to schema validation and activation-time verification.

## Checklist

* Did you finalize the Taxonomy version first and pin it with `taxonomy_ref`?
* Does every detector carry a grade attribution, and does every emitted grade exist in that Taxonomy?
* Do your pattern detectors have digit boundaries, a `validator`, and a context-word confidence ladder?
* Did you avoid setting `mask` on items whose risk masking doesn't remove (credentials and the like)?
* Is `terminal` reserved for high-confidence evidence like fingerprints and exact matches?
* Is counter-evidence (redacted derivatives, prior disclosure) reflected via negative conditions and `suppresses`?
* Do the `routing` `low` / `high` thresholds draw the auto-finalize/gray-zone boundary where you intend?
* Are the [fingerprint templates](/en/v1.4/admin/fingerprint-templates) your fingerprint detectors reference registered, with valid versions?

<Tip>
  A finished Rule Package doesn't apply itself on save. **Pin** the new version to the Project Stratum before it's used for classification — for the version discipline, see [Manage Stratum policies](/en/v1.4/admin/stratum-policy).
</Tip>
