# PIF v0.2 conformance test suite

This directory holds the conformance test bundle for PIF v0.2. Implementers of PIF validators run the suite to prove that their tool agrees with the v0.2 schemas on every documented case.

A validator that disagrees on any case in `manifest.json` is **not v0.2-conformant**.

The v0.1 conformance suite remains at [`../../v0.1/conformance/`](../../v0.1/conformance/) and is unchanged. Run both via `npm run conformance:all`.

## What's tested in v0.2

Beyond the v0.1 conformance scope, v0.2 adds tests for:

- **Semi-closed CURIE pattern** (Round 4 design lock): closed namespace enum + open token pattern + `ext:` escape hatch. Tests cover case sensitivity, whitespace handling, multi-colon rejection, empty token rejection, length limit (128), uniqueItems, and unknown-namespace rejection.
- **Cumulative validation**: v0.1 documents validate against v0.2 schemas without modification. v0.1 free-text `missing_controls[].control` values continue to validate via the cumulative pattern.
- **`conditional_applicability`** boolean on `applicable_requirements[]` entries (new in v0.2): structural validation + cross-reference to `assumptions_made`.
- **`pif_corpus_version`** envelope field (new in v0.2): optional, free-form audit-trail string.
- **Tightened required array** for `pif_version: "0.2"` PreflightAssertion documents: `out_of_scope` and `clarifying_questions` must be present. v0.1 documents (`pif_version: "0.1"`) continue to validate without these fields via cumulative validation.
- **`ext:` namespace escape**: vendor-internal frameworks pass structural validation; corpus-layer recognition is implementation-specific.

## How to run

From the repository root:

```
npm install
npm run conformance:v02
```

Or both v0.1 and v0.2 at once:

```
npm run conformance:all
```

The harness exits `0` on full pass, `1` on any mismatch. CI consumes the exit code (see `.github/workflows/conformance.yml`).

A pass looks like:

```
  ok valid-wd-v02-curie-pharma (WorkflowDescription, expect valid)
  ok invalid-pa-v02-missing-out-of-scope (PreflightAssertion, expect invalid)
  ...
17 passed, 0 failed (17 cases)
```

## Case inventory

**7 valid cases:**

- `valid-wd-v02-curie-pharma` — WorkflowDescription using `regulatory_domains_self_declared` with `gxp:` tokens.
- `valid-pa-v02-rich` — PreflightAssertion exercising every v0.2 feature: CURIE `regulatory_domains_identified`, CURIE `missing_controls.control`, `conditional_applicability`, `pif_corpus_version`, tightened required array.
- `valid-pa-v01-against-v02-schema` — cumulative validation test: a v0.1 PA validates against the v0.2 schema.
- `valid-pa-v02-ext-namespace` — `ext:preclari_custom_framework_tier1` vendor extension passes structural validation.
- `valid-pa-v02-conditional-applicability-true` — `conditional_applicability: true` paired with the corresponding `assumptions_made` entry.
- `valid-pa-v02-missing-controls-v01-freetext` — transition mode: v0.1 free-text control name in a v0.2 document.
- `valid-pa-v02-no-corpus-version` — `pif_corpus_version` is optional.

**10 invalid cases:**

- `invalid-pa-v02-missing-out-of-scope` — required-array tightening: missing field in v0.2 PA.
- `invalid-pa-v02-missing-clarifying-questions` — same tightening.
- `invalid-wd-v02-unknown-namespace` — `made_up_framework:x`.
- `invalid-wd-v02-uppercase-namespace` — `GXP:GMP` (namespace must be lowercase).
- `invalid-wd-v02-multi-colon` — `gamp5:appendix:m4`.
- `invalid-wd-v02-whitespace` — `gxp:has space`.
- `invalid-wd-v02-empty-token` — `gxp:`.
- `invalid-wd-v02-duplicate-curies` — `uniqueItems: true` violated.
- `invalid-wd-v02-curie-too-long` — `maxLength: 128` exceeded.
- `invalid-pa-v02-bad-conditional-applicability-type` — string instead of boolean.

## Adding a new case

Same procedure as v0.1: minimal fixture + manifest entry + run the harness. See [`../../v0.1/conformance/README.md`](../../v0.1/conformance/README.md) for the full guide.

## Reference harness

The harness at `run-conformance.ts` is a near-copy of the v0.1 harness — same ajv-based shape, same exit-code contract. Other-language ports of the v0.1 harness need only change the schema-loading paths to support v0.2 as well.
