@smile-digital-health/crl 5.1.1 → 5.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -6,36 +6,38 @@ Clinical Reasoning Language (CRL) provides a structured way to model clinical de
6
6
 
7
7
  ## Overview
8
8
 
9
- See the [User Guide](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/packages/crl/USER_GUIDE.md) for a comprehensive introduction to the CRL language, syntax, and authoring best practices. For the **CLI and MCP tool reference** (emit, validate, the MCP tools — for both CRL and CEL), see [TOOLING.md](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/packages/crl/TOOLING.md).
9
+ See the [User Guide](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/packages/crl/USER_GUIDE.md) for a comprehensive introduction to the CRL language, syntax, and authoring best practices. For the **CLI and MCP tool reference** (emit, validate, the MCP tools — for both CRL and CEL), see [TOOLING.md](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/packages/crl/TOOLING.md).
10
10
 
11
11
  CRL is a domain-specific language designed for expressing clinical practice guidelines in a structured and machine-readable format. The language is implemented in TypeScript and provides a comprehensive set of tools for processing CRL documents.
12
12
 
13
13
  For the authoring reference over MCP, call `authoring_kit({})` to discover guidance,
14
14
  or `authoring_kit({view:"full",format:"markdown"})` for the complete audited Markdown.
15
15
  The response is the same document as the release's `authoring-kit.md`; the agent can
16
- read or save it. JSON remains the default. See the [kit guide](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/docs/authoring-kit.md).
16
+ read or save it. JSON remains the default. See the [kit guide](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/docs/authoring-kit.md).
17
17
 
18
18
  ## Metadata annotations
19
19
 
20
- CRL concepts can carry typed metadata via an `@tag` convention on `meta` lines (e.g. `@description`, `@ke-feedback`, `@kg-concept`) — for descriptions, knowledge-engineer feedback, plain-language logic, external-store hints, and extraction provenance. See the [metadata model](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/packages/crl/spec/metadata-model.md) and the canonical [tag registry](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/packages/crl/spec/metadata-registry.json). *(Draft: the convention parses today; Validator enforcement is forthcoming.)*
20
+ CRL concepts can carry typed metadata via an `@tag` convention on `meta` lines (e.g. `@description`, `@ke-feedback`, `@kg-concept`) — for descriptions, knowledge-engineer feedback, plain-language logic, external-store hints, and extraction provenance. See the [metadata model](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/packages/crl/spec/metadata-model.md) and the canonical [tag registry](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/packages/crl/spec/metadata-registry.json). *(Draft: the convention parses today; Validator enforcement is forthcoming.)*
21
21
 
22
22
  ## Installation
23
23
 
24
24
  The package is publicly available from npm; installation does not require an npm account or token.
25
25
 
26
26
  ```bash
27
- npm install @smile-digital-health/crl@5.1.1
27
+ npm install @smile-digital-health/crl@5.2.0
28
28
  ```
29
29
 
30
- For a dependency that accepts compatible CRL5 updates:
30
+ Pin the version so generated-artifact migrations are adopted deliberately:
31
31
 
32
32
  ```json
33
33
  "dependencies": {
34
- "@smile-digital-health/crl": "^5.1.0"
34
+ "@smile-digital-health/crl": "5.2.0"
35
35
  }
36
36
  ```
37
37
 
38
- CRL5.1 changes the public authoring-kit npm and MCP APIs. When upgrading from 5.0.0, update kit calls as described in the [5.1.0 release notes](https://github.com/alphora/clinical-reasoning-language/releases/tag/v5.1.0); the CRL/CEL language and emitted CQL/FHIR are unchanged from 5.0.0. A `^5` dependency permits 5.1.0. Content from before the CRL5 language transition may also need language migration using the current authoring kit.
38
+ CRL 5.2 renames generated retrieval libraries from `LocalPrimitives`/`ExternalPrimitives` to `LocalElements`/`ExternalElements`, including CQL includes and FHIR Library identities. Regenerate CQL and FHIR together and replace the previous generated-file inventory, preserving independently authored files. Re-emission does not automatically delete obsolete artifacts. See the [5.2.0 migration notes](https://github.com/alphora/clinical-reasoning-language/releases/tag/v5.2.0). A `^5` or `^5.1.0` dependency can acquire this update automatically; use an exact version pin when upgrades require coordinated artifact replacement.
39
+
40
+ CRL/CEL syntax is unchanged by 5.2. When upgrading from 5.0.0, also update the authoring-kit npm/MCP calls described in the [5.1.0 release notes](https://github.com/alphora/clinical-reasoning-language/releases/tag/v5.1.0). Content from before the CRL5 language transition may need language migration using the current authoring kit.
39
41
 
40
42
  ### For Package Maintainers
41
43
 
@@ -165,7 +167,7 @@ The FSH-to-CRL transformer converts FHIR Shorthand (FSH) files into Clinical Rea
165
167
  - **Deduplication and Suffixing**: Terminology blocks are unique by identifier and body. If a duplicate identifier is encountered with a different body, a numeric suffix (e.g., `_2`) is added to the identifier. If both identifier and body are the same, the block is not duplicated.
166
168
  - **Extraction Logic**: For `medicationCodeableConcept`, the transformer uses `system`, `code`, and `identifier` from the FSH object. For `dynamicValue.expression.expression` (where `path = "code.coding"`), the transformer uses `system` and `code` from the CQL code expression string and `identifier` from the corresponding description.
167
169
 
168
- For more details, see the [User Guide](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/packages/crl/USER_GUIDE.md) and the technical mapping documentation.
170
+ For more details, see the [User Guide](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/packages/crl/USER_GUIDE.md) and the technical mapping documentation.
169
171
 
170
172
  ## CLI Tool Usage
171
173
 
@@ -193,7 +195,7 @@ crl-emit --path <root.crl> --out-dir <project-root> --target fhir-def
193
195
 
194
196
  Output lands at `<project-root>/src/fhir/<ResourceType>/<id>.json`. CQL emit (the existing `--target cql` / default behavior) lands at `<project-root>/src/cql/<library-name>.cql`. Library content references the CQL file via the relative path `../../cql/<library-name>.cql`.
195
197
 
196
- For semantic rules, layout details, deliberate spec deviations, and the MCP `emit_crl` tool, see [`USER_GUIDE.md` §"Emitting FHIR Definition resources"](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/packages/crl/USER_GUIDE.md#emitting-fhir-definition-resources).
198
+ For semantic rules, layout details, deliberate spec deviations, and the MCP `emit_crl` tool, see [`USER_GUIDE.md` §"Emitting FHIR Definition resources"](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/packages/crl/USER_GUIDE.md#emitting-fhir-definition-resources).
197
199
 
198
200
  ## API Usage & Reference
199
201
 
@@ -495,7 +497,7 @@ Note: This project uses a custom AST implementation that uses ANTLR's visitor pa
495
497
  >
496
498
  > The authoritative release checklist and instructions are maintained in a single location:
497
499
  >
498
- > **[.github/PULL_REQUEST_TEMPLATE/release.md](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/.github/PULL_REQUEST_TEMPLATE/release.md)**
500
+ > **[.github/PULL_REQUEST_TEMPLATE/release.md](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/.github/PULL_REQUEST_TEMPLATE/release.md)**
499
501
  >
500
502
  > Always follow the steps in this file when preparing a new release. This ensures consistency and reduces maintenance overhead. If you need to update the release process, update the PR template only.
501
503
 
@@ -509,7 +511,7 @@ Note: This project uses a custom AST implementation that uses ANTLR's visitor pa
509
511
  - **Generated Files:** Auto-generated files (e.g., ANTLR outputs, grammar-driven types) are ignored by git and should never be edited manually. Always use the provided scripts to regenerate them.
510
512
  - **Documentation:** Keep all documentation referencing the release checklist up-to-date by linking to the PR template.
511
513
 
512
- For more details, see the [release PR template](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/.github/PULL_REQUEST_TEMPLATE/release.md) and the automation scripts in `.github/scripts/`.
514
+ For more details, see the [release PR template](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/.github/PULL_REQUEST_TEMPLATE/release.md) and the automation scripts in `.github/scripts/`.
513
515
 
514
516
  ### Error Handling Strategy
515
517
 
@@ -552,7 +554,7 @@ We provide a Visual Studio Code extension for CRL files:
552
554
  - Comment support
553
555
  - Language basics for a better editing experience
554
556
 
555
- For installation instructions and full details, see [crl-vscode/README.md](https://github.com/alphora/clinical-reasoning-language/blob/v5.1.1/packages/crl-vscode/README.md)
557
+ For installation instructions and full details, see [crl-vscode/README.md](https://github.com/alphora/clinical-reasoning-language/blob/v5.2.0/packages/crl-vscode/README.md)
556
558
 
557
559
  ## License
558
560
 
@@ -218,16 +218,16 @@ export interface ActivityBecause extends ASTNode {
218
218
  rationale: string;
219
219
  location: Location;
220
220
  }
221
- export type InterfaceSourceLayer = "LocalPrimitives" | "ExternalPrimitives" | "Inferences";
221
+ export type InterfaceSourceLayer = "LocalElements" | "ExternalElements" | "Inferences";
222
222
  export interface ValueElement {
223
223
  path: string;
224
224
  location: Location;
225
225
  }
226
226
  export type RecordUnionTerm = {
227
- kind: "local-primitives";
227
+ kind: "local-elements";
228
228
  define: string;
229
229
  } | {
230
- kind: "external-primitives";
230
+ kind: "external-elements";
231
231
  define: string;
232
232
  } | {
233
233
  kind: "constructed";
@@ -284,7 +284,7 @@ export interface Concept extends ASTNode {
284
284
  __pureQuestion?: true;
285
285
  __pureQuestionRead?: true;
286
286
  __reductionLocalUnion?: string;
287
- __bothRepFoldInLocalPrimitives?: string;
287
+ __bothRepFoldInLocalElements?: string;
288
288
  __recordUnionTerms?: readonly RecordUnionTerm[];
289
289
  __bothRepMerge?: "union" | "recency-value" | "record-union";
290
290
  __effectiveDescriptor?: unknown;
@@ -1,7 +1,7 @@
1
1
  {
2
- "auditedRevision": "18799337ec6b91e91a4b1577c0e31a7f1b575714",
3
- "auditedSchemaVersion": "2.0",
4
- "auditedContentHash": "e9870c0042e7cb2e76a66d10b0edc72056786e0a53ccb73dc417544c8753c8b2",
5
- "scope": "Unified kit schema 2.0: canonical content unchanged; Markdown MCP retrieval and JSON compatibility reviewed from 451be38f1fc33723cfe44eec12c1add689c5c52b. Prior 301-file survey and explicit clinical/native evidence limitations retained. Transport owning tests and both real MCP entry points verified; see evidence ledger.",
2
+ "auditedRevision": "34d591eeab7fae22485546add54efe41106d756d",
3
+ "auditedSchemaVersion": "2.1",
4
+ "auditedContentHash": "28bf5d87e4802bd3da9a6e4b5798414a805ccecd740ecede8c6b977553809336",
5
+ "scope": "Kit schema 2.1 naming-only maintenance from 5e105580a3390bedcbf7874ddb37e9f5f7d6279d through 34d591eeab7fae22485546add54efe41106d756d. All project retrieval-layer identities and authored split fixtures use Elements. Consumer kit content and tags are unchanged; affected evidence records were refreshed. Verified: 4,855 core tests (32 skipped), core MCP, 32 extension MCP tests, 116 Bleph native cases, four returned-QR rounds, 11 bounded BMI cases, and exact emission parity. Prior semantic and native limitations remain; see the evidence ledger.",
6
6
  "evidence": "packages/crl/src/authoring-kit/tests/coverage.md"
7
7
  }
@@ -18,25 +18,29 @@ const conceptTypes_1 = require("../grammar/conceptTypes");
18
18
  const conceptValueTypes_1 = require("../grammar/conceptValueTypes");
19
19
  const spawn_1 = require("../results/spawn");
20
20
  const reference_1 = require("./reference");
21
- const SCHEMA_VERSION = "2.0";
21
+ const SCHEMA_VERSION = "2.1";
22
22
  const FEEDBACK_URL = "https://github.com/alphora/clinical-reasoning-language/issues/new";
23
23
  const SUMMARY = "Local decision support: express clinical intent through coded answers, supported source representations and explicit computed publications. Author decision/criterion structure for distinct criteria, named terminology for coded answer choices, and presentations for question wording. Validate and compare CRE predictions with emitted CQL/FHIR and native $apply. Supported age, request, qualification, threshold and finite-code BMI forms are in scope; broader #320 limitations are listed separately.";
24
24
  const FORCE_MODEL = {
25
- summary: "A rule whose force VARIES by clause carries explicit `clauses` (a single rule may carry both a default and " +
26
- "an invariant clause — do not collapse them); a rule without `clauses` is uniformly its stated force (the " +
27
- "validator-enforced grammar/mechanics rules). The force tells the agent how hard to bind. It exists so an " +
25
+ summary: "Every rule carries nonempty explicit `clauses`; each clause states its force. A rule may mix forces: " +
26
+ "do not collapse them into a rule-wide default. Read clauses with their rule prose and applicability. " +
27
+ "Prose still describes language semantics and tool behavior; a force level does not make those facts " +
28
+ "overridable. Use the explicit clauses to determine force. If prose appears to introduce a different obligation, report the ambiguity instead of guessing its force. " +
29
+ "Invariant anchors identify manual source or verification obligations; resolving an anchor does not prove " +
30
+ "the obligation was performed. The force tells the agent how hard to bind. It exists so an " +
28
31
  "agent that mechanically enforces an authoring PREFERENCE does not revert a human KE's deliberate, " +
29
32
  "faithful refactor. The force is operator-governed content, not agent-editable.",
30
33
  levels: [
31
34
  {
32
35
  level: "validator-enforced",
33
- meaning: "The grammar/validator rejects it (e.g. qualifier-required, guard-on-single-action). The agent need " +
34
- "not police; the tool does.",
36
+ meaning: "The grammar/validator reports the stated condition within its documented scope and preconditions. " +
37
+ "An error rejects the input; an explicitly described warning leaves it legal. A warning is not a " +
38
+ "rejection; absence of a diagnostic outside the checked scope is not proof of correctness.",
35
39
  },
36
40
  {
37
41
  level: "invariant",
38
- meaning: "A FIDELITY-TO-SOURCE constraint (an ADD or a HOLLOW vs the policy narrative). Always enforced, on ANY " +
39
- "author's output, human or agent. Every invariant carries a `test` that RESOLVES to a real check — never " +
42
+ meaning: "An obligation that applies regardless of author: either source fidelity (avoid an ADD or HOLLOW " +
43
+ "against the source) or per-policy verification and artifact integrity. Every invariant carries a `test` that RESOLVES to a real check — never " +
40
44
  '"looks wrong," and never a dangling/typo\'d anchor (a `test` pointing at nothing IS the K4 fake-green ' +
41
45
  "this guards against; the force-model test asserts every invariant's `test` resolves). The anchor names " +
42
46
  "the adjudication MODE: a `judgeLens.composition:<check>` (a §2/§3 source-fidelity judge call with no " +
@@ -240,13 +244,39 @@ const RULES = [
240
244
  rule: "Name a concept as a clinical concept. Put the question's wording in a separate presentation declaration with required question text and optional question description. Presentation has no separate short label. Check generated questionnaires and population through emit_results; a green CRE run does not establish the questionnaire behavior.",
241
245
  why: "A prompt should name the determination the reviewer can answer. A computed condition and the records feeding it are different surfaces.",
242
246
  ref: "docs/CRL-NORTH-STAR.md §4; #317; #318",
247
+ clauses: [
248
+ {
249
+ "text": "Name concepts for the clinical determinations they represent; put question wording in a presentation rather than turning the concept name into a question.",
250
+ "force": "default"
251
+ },
252
+ {
253
+ "text": "The concept-presentation rule defines presentation validation: only concepts declaring code is may have a presentation; its question text must be nonempty, description is optional, and label/short fields are rejected. Missing presentation on a coded concept is legal and warns even if unreached; the question fallback is the concept name with no description.",
254
+ "force": "validator-enforced"
255
+ },
256
+ {
257
+ "text": "Check generated question text and populated answers against the intended determination. CRE success alone does not verify Questionnaire behavior.",
258
+ "force": "invariant",
259
+ "test": "verifyLoop:native-outcome-verification"
260
+ }
261
+ ],
243
262
  },
244
263
  {
245
264
  id: "decision-qualifiers",
246
265
  applicability: "All CRL authoring",
247
266
  category: "decision-shape",
248
- rule: "A multi-branch decision must declare a qualifier: `first:` (ordered, first match wins — requires a trailing `otherwise`), `all:` (every matching branch fires), or `any:` (over actions only — offer alternatives). A `then:` body is closed by `end.`. A single-member block takes no qualifier. Every later branch of `first:`, including `otherwise`, receives null-propagating priority exclusions for prior guards. The author writes no condition on `otherwise`; the emitted action is guarded. Compound priors automatically get named CQL defines. `priority-exclusion-inexpressible` means an unresolved reference: correct its name/library qualification, not its guard shape. Earlier unknown prevents a later disposition; `all:` has no ordered exclusions.",
267
+ rule: "A multi-branch decision must declare a qualifier: `first:` (ordered, first match wins — top-level requires trailing `otherwise`; nested may omit it), `all:` (every matching branch fires), or `any:` (over actions only — offer alternatives). A `then:` body is closed by `end.`. A single-member block takes no qualifier. Every later branch of `first:`, including `otherwise`, receives null-propagating priority exclusions for prior guards. The author writes no condition on `otherwise`; the emitted action is guarded. Compound priors automatically get named CQL defines. `priority-exclusion-inexpressible` means an unresolved reference: correct its name/library qualification, not its guard shape. Earlier unknown prevents a later disposition; `all:` has no ordered exclusions.",
249
268
  ref: "docs/decision-shapes.md; validator rules qualifier-required / otherwise-required / any-over-branches / first-over-actions",
269
+ clauses: [
270
+ {
271
+ "text": "Multi-member blocks require a qualifier: first/all over branches, any/all over actions. A top-level first requires trailing otherwise; nested first may omit it. A singleton takes no qualifier. A then block closes with end. Otherwise is unconditioned, last, restricted to first, and cannot be the only branch.",
272
+ "force": "validator-enforced"
273
+ },
274
+ {
275
+ "text": "Verify the authored ordering: first priority exclusions preserve an earlier unknown instead of reaching a later disposition; all has no ordered exclusions. Inspect emitted conditions and executed paths rather than treating successful parsing as proof of precedence. Resolve priority-exclusion-inexpressible by correcting the referenced name/library qualification; do not change guard meaning to hide an unresolved reference.",
276
+ "force": "invariant",
277
+ "test": "verifyLoop:native-outcome-verification"
278
+ }
279
+ ],
250
280
  },
251
281
  {
252
282
  id: "decision-composition",
@@ -306,6 +336,17 @@ const RULES = [
306
336
  category: "guards",
307
337
  rule: "Per-action only when / unless guards are unsupported for selected publications: validation reports publication-unsupported-context and FHIR emit reports publication-action-guard-unsupported. Use branch conditions when that expresses the source intent. If the source requires a guarded action menu, report the missing publication capability; do not fall back to legacy Scalar answers. CRE legacy unknown coercion is not an intended pause contract.",
308
338
  ref: "docs/decision-shapes.md; validator rule guard-on-single-action",
339
+ clauses: [
340
+ {
341
+ "text": "A per-action guard on a single action is always rejected as guard-on-single-action. For an admitted selected publication resolved in the prepared source context, per-action only when/unless guards report publication-unsupported-context. FHIR emission separately reports publication-action-guard-unsupported. This does not certify legacy/unadmitted operands or unresolved package references.",
342
+ "force": "validator-enforced"
343
+ },
344
+ {
345
+ "text": "Use branch conditions only when they preserve source intent. If a guarded action menu is required, report the missing capability instead of substituting a legacy Scalar answer or accepting its unknown coercion.",
346
+ "force": "invariant",
347
+ "test": "judgeLens.composition:hollowed-criteria"
348
+ }
349
+ ],
309
350
  },
310
351
  {
311
352
  id: "branch-guards",
@@ -353,6 +394,18 @@ const RULES = [
353
394
  category: "decision-shape",
354
395
  rule: "A combined when (A or B) expresses alternatives within one Boolean condition. Ordered sibling when A / when B branches express precedence, including when data is missing. With selected Boolean A unknown and B true, the combined condition is true but first: sibling branches pause at A. Do not split or merge them merely for presentation or DNF size. Use a compound guard when either alternative can establish the rule without resolving the other; use ordered siblings when the earlier determination must be resolved first or branches route differently. Under all:, two satisfied sibling branches can each fire, while one combined OR branch fires its body once. Preserve authored clinical intent and test missing-data cases as well as fully known inputs.",
355
396
  ref: "docs/decision-shapes.md §3; #224",
397
+ clauses: [
398
+ {
399
+ "text": "Preserve source alternatives and precedence: a combined OR and ordered sibling branches are not interchangeable, especially with missing inputs. Do not split or merge merely for presentation or expression size.",
400
+ "force": "invariant",
401
+ "test": "judgeLens.composition:hollowed-criteria"
402
+ },
403
+ {
404
+ "text": "Verify relevant unknown and known cases: unknown A with true B satisfies combined OR, but first sibling branches pause at A; under all, satisfied siblings may each fire while one combined OR branch fires once.",
405
+ "force": "invariant",
406
+ "test": "verifyLoop:native-outcome-verification"
407
+ }
408
+ ],
356
409
  },
357
410
  {
358
411
  id: "dispositions",
@@ -432,9 +485,29 @@ const RULES = [
432
485
  id: "configure-dispositions",
433
486
  applicability: "Authoring authorization or coverage determinations, including before project configuration exists",
434
487
  category: "dispositions",
435
- rule: "A medical-policy deployment MUST configure its disposition vocabulary in the content project's `package.json` under `crl.dispositions`: a `mode` (`standalone` | `embedded`) and `options` mapping each PAS category (`certify` / `not-certify` / `pended`) to keyed reasons/flavors — `{ label, code? }`. The activity name a policy recommends is `\"<category>.<key>\"` (e.g. `recommend activity \"not-certify.EIU\"`), authored as a plain local `activity` block (`request CPGCommunicationRequest`); the `code` on an option is a PAS review-decision-reason code in full-PAS (Approve/Deny) intent, or the larger system's own code in embedded (Met/Unmet) intent. Once configured `options` resolves to a nonempty vocabulary it is the CLOSED valid set: the validator rejects any recommended activity not in it, any determination not `CPGCommunicationRequest`, and (per `disposition-mode`) a non-final leaf under `standalone`. `options: {}` yields an `empty-vocabulary` warning and leaves these checks inactive; resolve configuration diagnostics before relying on enforcement. Default vocabulary (if unconfigured): `certify.Approve` / `not-certify.Deny`.",
488
+ rule: "Configure a medical-policy deployment's disposition vocabulary in the content project's `package.json` under `crl.dispositions`: a `mode` (`standalone` | `embedded`) and `options` mapping each PAS category (`certify` / `not-certify` / `pended`) to keyed reasons/flavors — `{ label, code? }`. The activity name a policy recommends is `\"<category>.<key>\"` (e.g. `recommend activity \"not-certify.EIU\"`), authored as a plain local `activity` block (`request CPGCommunicationRequest`); the `code` on an option is a PAS review-decision-reason code in full-PAS (Approve/Deny) intent, or the larger system's own code in embedded (Met/Unmet) intent. Once configured `options` resolves to a nonempty vocabulary it is the CLOSED valid set: the validator rejects any recommended activity not in it, any determination not `CPGCommunicationRequest`, and (per `disposition-mode`) a non-final leaf under `standalone`. `options: {}` yields an `empty-vocabulary` warning and leaves these checks inactive; resolve configuration diagnostics before relying on enforcement. Default vocabulary (if unconfigured): `certify.Approve` / `not-certify.Deny`.",
436
489
  why: "The determination vocabulary is per-deployment (one payer per content project) — Approve/Deny for a standalone full-PA deployment, Met/Unmet for one that is part of a larger adjudication. Making it CONFIG (not hard-coded in the language or the kit) is what lets a deployment relabel or add a flavor without re-authoring policies, and keeps the universal kit customer-agnostic. This rule is GUIDANCE — the validator does NOT error on a MISSING config (an unconfigured project keeps today's behavior); it is the nudge to configure so the closed-set + request-type + finality checks turn on.",
437
490
  ref: "crl.dispositions; #134",
491
+ clauses: [
492
+ {
493
+ "text": "Configure the deployment disposition vocabulary and standalone/embedded mode in package.json crl.dispositions. Missing configuration is not rejected; unconfigured defaults are certify.Approve and not-certify.Deny. Resolve empty-vocabulary warnings before relying on config-gated checks.",
494
+ "force": "default"
495
+ },
496
+ {
497
+ "text": "A configured, nonempty resolved vocabulary gates disposition-not-configured, disposition-request-type and standalone disposition-non-final-leaf diagnostics. Missing configuration or an empty resolved vocabulary does not enable those checks.",
498
+ "force": "validator-enforced"
499
+ },
500
+ {
501
+ "text": "Check every recommended determination against the deployment vocabulary, including when configuration does not enable automatic validation.",
502
+ "force": "invariant",
503
+ "test": "verifyLoop:configured-membership"
504
+ },
505
+ {
506
+ "text": "A coverage determination communicates its conclusion through CPGCommunicationRequest, rather than ordering a service.",
507
+ "force": "invariant",
508
+ "test": "verifyLoop:communicated-not-ordered"
509
+ }
510
+ ],
438
511
  },
439
512
  {
440
513
  id: "disposition-mode",
@@ -443,6 +516,18 @@ const RULES = [
443
516
  rule: "`crl.dispositions.mode` is first-class and gates FINALITY only. `standalone` — our decision IS the whole coverage adjudication; every determination leaf must be FINAL (certify / not-certify). `embedded` — our decision is a SUB-determination feeding a larger cross-company adjudication; a non-final `pended` (PAS A4) leaf is legitimate (a refer-up / need-info contribution). In BOTH modes our decision still issues EXACTLY ONE determination on completion; a needed-unknown pause emits none (mutual-exclusivity is not relaxed by mode — do NOT read `embedded` as permission to emit two determinations across a parent + sub).",
444
517
  why: "The customer described two operating modes: Smile as the whole PA (Approve/Deny final) vs Smile as part of a larger system (Met/Unmet contributions that the larger tree finalizes). Only finality differs — a contribution may be non-final; it is still one contribution per run. Making mode explicit lets the same policy CRL run either way per deployment, and lets the validator enforce standalone-finality without guessing.",
445
518
  ref: "crl.dispositions.mode",
519
+ clauses: [
520
+ {
521
+ "text": "Standalone determinations must be final; embedded determinations may contribute a non-final pended result. Mode governs finality, not whether multiple conclusions are allowed.",
522
+ "force": "invariant",
523
+ "test": "verifyLoop:finality-by-mode"
524
+ },
525
+ {
526
+ "text": "Across the complete executed closure, a completed coverage determination produces exactly one conclusion; a needed-unknown pause produces none. Check delegated and sibling emission paths in both modes.",
527
+ "force": "invariant",
528
+ "test": "verifyLoop:mutual-exclusivity-spans-closure"
529
+ }
530
+ ],
446
531
  },
447
532
  {
448
533
  id: "minimalism",
@@ -450,6 +535,17 @@ const RULES = [
450
535
  category: "minimalism",
451
536
  rule: "Declare the MINIMAL set that captures the clinical intent and let the emitter do the heavy lifting. Do not over-specify properties the emitter can derive. Minimalism is over EMITTER-DERIVABLE detail, NOT over FIDELITY: a branch guard that keeps each distinct criterion VISIBLE (an inline atom in the applicability expression and dependency `input[]`, or a named criterion as one identifier `condition[]` resolving to a transparent define with its atoms in `input[]`) is NOT 'over-specified' relative to a `defined as` composite that hides them in one opaque boolean — semantic fidelity (same-fact vs distinct-criteria; see decision-composition) governs over node-count.",
452
537
  ref: "docs/CRL-NORTH-STAR.md §4.0",
538
+ clauses: [
539
+ {
540
+ "text": "Omit emitter-derivable detail where doing so preserves the authored meaning; prefer the minimal faithful declaration.",
541
+ "force": "default"
542
+ },
543
+ {
544
+ "text": "Retain each distinct source criterion as an auditable decision operand. A smaller opaque Boolean composite is not a faithful substitute merely because it has fewer nodes.",
545
+ "force": "invariant",
546
+ "test": "judgeLens.composition:hollowed-criteria"
547
+ }
548
+ ],
453
549
  },
454
550
  {
455
551
  id: "library-scoping",
@@ -458,6 +554,21 @@ const RULES = [
458
554
  rule: 'A document may start with one # header, followed by its required library "Name". declaration and optional library metadata, then includes before statements. Library and include declarations do not accept version clauses. Use logical CRL library and declaration names, not generated CQL filenames. Validate multifile content with validate_crl(path); inline code has no sibling context. The nearest package.json defines the project, and nested packages are separate projects. A qualified local sibling reference such as "Shared"."Choices" resolves without include, as in named-answer-reference.crl and named-answer-terms.crl. Installed packages must expose CRL files through package.json crl.libraries and be discoverable under the project\'s top-level node_modules (including scoped packages); nested dependency installations are not scanned. Each referencing CRL library must explicitly include a package library by its declared CRL name. Being installed, discovered or transitively included by another library does not grant reference visibility.',
459
555
  why: 'Discovery, reference visibility and physical CQL routing are distinct. Explicit include resolves an installed package before a same-named local library; without that include, a local qualified reference resolves locally. Avoid ambiguous ownership names. Packages cannot fall back to consumer-local libraries. Include aliases are unsupported: use declared names. Fix missing imports, cycles and emitted-name collision diagnostics in the source/package configuration, not generated CQL. Criteria are library-local; a concept and criterion cannot share a name within one library, and including another library does not make its criteria exportable.',
460
556
  ref: "imports/tests/preparePublicationContext.test.ts; imports/tests/registry.test.ts; imports/tests/criterionMultifile.test.ts; docs/decision-shapes.md",
557
+ clauses: [
558
+ {
559
+ "text": "CRL requires a library declaration before statements and places includes before statements. Library/include version clauses and include aliases are unsupported. Project-path validation checks import visibility: a referenced installed package library needs an explicit include in the referencing library; discovery or transitive inclusion alone does not grant visibility. Inline validation has no sibling project context. Criteria are library-local; same-library concept/criterion name collisions are rejected.",
560
+ "force": "validator-enforced"
561
+ },
562
+ {
563
+ "text": "Use logical CRL names, validate multifile content by path, and avoid ambiguous ownership names. Installed packages should expose crl.libraries through discoverable top-level node_modules; nested package roots are separate projects.",
564
+ "force": "default"
565
+ },
566
+ {
567
+ "text": "Verify emitted references resolve to the intended local or package owner. Inspect import/cycle/identity diagnostics; repair source or configuration rather than generated CQL. Package code must not acquire unintended consumer-local dependencies.",
568
+ "force": "invariant",
569
+ "test": "verifyLoop:native-outcome-verification"
570
+ }
571
+ ],
461
572
  },
462
573
  {
463
574
  id: "cel-cases",
@@ -483,6 +594,17 @@ const RULES = [
483
594
  category: "cel",
484
595
  rule: "Use distinct fact names for distinct resources in a case. Referencing the same emitting fact twice with different dates or intents does not create new resource identities and can invalidate the case. Different names can also collide after identity normalization. Patient references do not create extra Patients; an ambient Encounter participates in identity checks. Reusing a fact in separate cases is supported. Inspect diagnostics and the returned case/resource manifest; do not assume every referenced fact emitted a resource or that a warning skipped the whole case.",
485
596
  ref: "cel/validator/tests/identityDiagnostics.test.ts; emit_cel",
597
+ clauses: [
598
+ {
599
+ "text": "Collisions in actual emitted resource paths, within a case or with a previously emitted case in the same run, report id-collision as an error and prevent the colliding case from emitting. Different fact names can collide after normalization; repeated Patient references are exempt, and the ambient Encounter participates. Reusing a fact across separate cases is legal when their emitted paths remain distinct.",
600
+ "force": "validator-enforced"
601
+ },
602
+ {
603
+ "text": "Check identity diagnostics and the complete case/resource manifest, including normalization collisions, Patient references and ambient Encounter participation. Confirm that the intended resources actually emitted; do not infer resource presence or whole-case rejection from a warning.",
604
+ "force": "invariant",
605
+ "test": "verifyLoop:artifact-integrity"
606
+ }
607
+ ],
486
608
  },
487
609
  {
488
610
  id: "cel-quantity",
@@ -490,6 +612,17 @@ const RULES = [
490
612
  category: "cel",
491
613
  rule: "For a concept-linked Quantity answer, use a unit-bearing CEL literal, for example value is 90 'kg'. A bare number or whitespace-only unit is rejected. Unit presence validation does not certify UCUM spelling or dimensional compatibility; the producer and native execution must support the intended units. A numeric literal is not a CodeableConcept answer. Do not infer support for integer or other publication types from legacy numeric-validator tests.",
492
614
  ref: "cel/validator/tests/numericValueRules.test.ts; quantity-declaration; quantity-answer",
615
+ clauses: [
616
+ {
617
+ "text": "For a numeric/Quantity literal whose qualified defined by reference resolves to a concept with exactly one declared value type, Quantity requires a unit-bearing literal: bare numbers and whitespace-only units are rejected. A numeric literal targeting CodeableConcept is a value-type mismatch. This numeric check does not cover bare FHIR-type facts or unresolved/multiple-value-type targets; absence of a diagnostic there does not certify the value. Legacy integer/decimal targets have separate unitless rules, not proof of new publication support.",
618
+ "force": "validator-enforced"
619
+ },
620
+ {
621
+ "text": "Verify units are supported by the intended producer and native execution. Unit-presence validation alone does not establish UCUM or dimensional correctness; legacy numeric tests do not establish other publication-type support.",
622
+ "force": "invariant",
623
+ "test": "verifyLoop:native-outcome-verification"
624
+ }
625
+ ],
493
626
  },
494
627
  {
495
628
  id: "emit-output-root",
@@ -497,6 +630,17 @@ const RULES = [
497
630
  category: "process",
498
631
  rule: "ONE OUTPUT ROOT for the writing emit tools. MCP `emit_cql` returns CQL inline and never writes. Normally omit MCP `out` / `outRoot`, CLI `--out-dir` (`--out` for crl-emit-results): the nearest package.json defines the project root. `emit_crl` (target fhir-def) writes `<root>/src/cql/` and `<root>/src/fhir/<ResourceType>/<id>.json`; target cql writes `<root>/src/cql/`. `emit_cel` writes `<root>/tests/data/fhir/patient/<compartmentId>/<lowercase-type>/<id>.json`; `emit_results` writes under `<root>/tests/results/fhir/patient/<compartmentId>/`. An explicit output argument replaces ROOT, retaining that entire layout. Never pass a leaf such as src or tests/data/fhir as the root: src would become src/src/cql. Omission WRITES for emit_crl and emit_cel; use an explicit scratch root for inspection. A scratch tree mirrors the project layout. For both-representation content use closure emit_crl, not the single-library emit_cql tool. Consume returned paths and manifests; tools own placement. `emit_cel` replaces its patient data tree and `emit_results` prunes its generated outputs; `emit_crl` does not prune stale files, so a renamed definition can leave an obsolete CQL/FHIR file. Inspect the definition tree before publishing it.",
499
632
  ref: "packages/crl/TOOLING.md — the ROOT",
633
+ clauses: [
634
+ {
635
+ "text": "Normally omit output-root arguments to use the nearest project package.json. Use an explicit scratch root for inspection and closure emit_crl for both-representation content; consume returned paths instead of constructing output paths.",
636
+ "force": "default"
637
+ },
638
+ {
639
+ "text": "Verify that the selected root and complete returned paths are intended before publishing. Select a root above the documented generated layout, not a leaf that duplicates src or tests/data/fhir below itself. Account for CEL/results replacement and pruning, and inspect CRL definition trees for stale files after renames.",
640
+ "force": "invariant",
641
+ "test": "verifyLoop:artifact-integrity"
642
+ }
643
+ ],
500
644
  },
501
645
  {
502
646
  id: "written-equals-executed",
@@ -504,6 +648,18 @@ const RULES = [
504
648
  category: "process",
505
649
  rule: "CRL owes you written == executed. It optimizes clarity, not fewer keystrokes. The emitter translates CRL into CQL/FHIR; it does not invent a CRL expression the author could and should have written. Report a mismatch when a determination behaves differently from its source, even if the tool reports success. Target-language plumbing that CRL cannot express, such as the FHIR structural floor, belongs to emit. It must not manufacture a determination value. An unanswered pure question pauses because nothing supplies its value; that behavior follows from its declaration and must agree in the CRE. Explicitness is useful where the form exists; do not replace a faithful model merely to obtain a green run.",
506
650
  ref: "docs/CRL-NORTH-STAR.md §0 and §4.0",
651
+ clauses: [
652
+ {
653
+ "text": "The computable representation must preserve source criteria and outcomes. Do not introduce or remove a determination merely to obtain a green run; report written/executed mismatches.",
654
+ "force": "invariant",
655
+ "test": "judgeLens.composition:dropped-or-added-criterion"
656
+ },
657
+ {
658
+ "text": "Verify emitted behavior against authored intent, including unanswered questions. Compiler-owned structural plumbing must not manufacture determination values; CRE alone does not prove native agreement.",
659
+ "force": "invariant",
660
+ "test": "verifyLoop:native-outcome-verification"
661
+ }
662
+ ],
507
663
  },
508
664
  {
509
665
  id: "terminology-forms",
@@ -511,13 +667,48 @@ const RULES = [
511
667
  category: "concept-model",
512
668
  rule: "A terminology has three forms. Pure `valueset is` is a reference: when its final path segment is a FHIR id (1-64 letters, digits, dot or hyphen), the emitted placeholder uses that declared canonical, and deployment supplies the real membership there. CURRENT LIMIT: a canonical without that id-legal tail, including a URN OID, falls back to a policy slug canonical. This does not satisfy the fixed-canonical deployment model; inspect emitted identity and report the mismatch rather than assuming the swap works. `system is` plus `code is` entries instantiates membership. Mixed `valueset is` plus codes emits ONE policy-owned ValueSet identity and includes the authored external canonical by reference alongside its explicit codes; CQL references that same policy-owned identity. Do not assume a named reference contains a usable dropdown: instantiate the offered codes or deploy the real terminology. `value from is` binds offered answer values, never source retrieves. With value domain is answer options and in qualifying, that offered finite set also supplies the interpreted domain and concept-local exceptions; representation-local `coded from` selects which source records participate. They may name the same terminology when those roles genuinely coincide. A terminology code may carry optional `display is`; each finite answer ValueSet member requires its display. Displays are authored, never inferred. Example instantiated terminology:\n\n```crl\nterminology \"Example Choices\":\n- system is `http://example.org/CodeSystem/choices`.\n- code is `a` display is `Choice A`.\n- code is `b` display is `Choice B`.\n```\n\nA coded question without `value from is` still warns `answer-options-missing`. #313 remains open: this release adds displays but does not fix the titled codeless-reference defect.",
513
669
  ref: "docs/CRL-NORTH-STAR.md; #313; #316",
670
+ clauses: [
671
+ {
672
+ "text": "Choose reference, instantiated or mixed terminology to express the intended membership. Use value from is for offered answer values and representation-local coded from for source retrieval; share a terminology only when those roles coincide.",
673
+ "force": "default"
674
+ },
675
+ {
676
+ "text": "Finite answer ValueSet members require authored displays at the answer use site. A missing value from is on a coded question warns rather than failing.",
677
+ "force": "validator-enforced"
678
+ },
679
+ {
680
+ "text": "Inspect emitted ValueSet/CodeSystem identities and actual membership, including mixed/reference forms. Deploy real membership for an opaque reference before relying on it. Report the documented non-id-tail canonical fallback instead of assuming its identity or dropdown is correct.",
681
+ "force": "invariant",
682
+ "test": "verifyLoop:native-outcome-verification"
683
+ }
684
+ ],
514
685
  },
515
686
  {
516
687
  id: "verify-loop",
517
688
  applicability: "All CRL authoring",
518
689
  category: "process",
519
- rule: "Verify with the MCP tools in order: validate_crl(path) clean → validate_cel(path) clean → run_decision(path) with every case's `result is` passing. validate_cel and run_decision need FILES under a project root (a package.json) — they do not accept inline code. For a COMPOUND-GUARD branch, cite the run_decision `conditionTrace` (the per-operand truth-table) as the audit surface, and confirm the DROP-ONE battery (see cel-cases) — a satisfying case alone does not prove each conjunct is load-bearing.",
690
+ rule: "Verify with the MCP tools in order: validate_crl(path) clean → validate_cel(path) clean → run_decision(path) with every case's `result is` passing. validate_cel and run_decision need FILES under a project root (a package.json) — they do not accept inline code. For a COMPOUND-GUARD branch, cite the run_decision `conditionTrace` (the per-operand truth-table) as the audit surface, and demonstrate that each conjunct is load-bearing; the DROP-ONE battery (see cel-cases) is recommended, and equivalent proof is acceptable. A satisfying case alone is insufficient.",
520
691
  ref: "verifyLoop",
692
+ clauses: [
693
+ {
694
+ "text": "Validate CRL and CEL, compare supported CRE predictions with independent native activity/pause expectations, and record unsupported or unexecuted cases as unverified. Establish that each distinct criterion is consequential and relevant unknown behavior is correct; equivalent proof methods are acceptable.",
695
+ "force": "invariant",
696
+ "test": "verifyLoop:native-outcome-verification"
697
+ },
698
+ {
699
+ "text": "Prefer file-based CRL validation to supply project context. For compound guards, the conditionTrace and a drop-one battery are a recommended way to demonstrate that each conjunct matters.",
700
+ "force": "default"
701
+ },
702
+ {
703
+ "text": "The validate_cel and run_decision MCP tools require a file path under a project root and reject inline code. This restriction does not apply to validate_crl, which also accepts inline CRL.",
704
+ "force": "validator-enforced"
705
+ },
706
+ {
707
+ "text": "Check the executed path as well as the disposition; a matching activity name alone can hide a wrong fall-through or delegation route.",
708
+ "force": "invariant",
709
+ "test": "verifyLoop:assert-path"
710
+ }
711
+ ],
521
712
  },
522
713
  {
523
714
  id: "emitted-trees-are-ours",
@@ -525,6 +716,13 @@ const RULES = [
525
716
  category: "process",
526
717
  rule: "Emitted trees are producer-owned. `emit_cel` wipes `<root>/tests/data/fhir/patient/` and repopulates it; one suite owns that project tree, with no sibling-suite protection. `emit_results` prunes unclaimed Questionnaire/QuestionnaireResponse files in its results tree by default (`prune: false` retains them). Keep authored files elsewhere. Symlinks and removal failures are reported. Each tool writes a manifest with case → compartmentDir → paths and hashes. Re-hashing listed files proves integrity, not completeness: compare the complete path set too. A renamed case otherwise leaves plausible stale data which a downstream mirror copies and certifies. Use each tool's manifest and returned paths.",
527
718
  ref: "verifyLoop",
719
+ clauses: [
720
+ {
721
+ "text": "Keep authored files outside producer-owned data/results trees. Compare the complete expected path/resource set with returned manifests as well as file hashes; inspect pruning, retention, symlink and removal diagnostics. Integrity of listed files alone does not prove completeness or absence of stale output.",
722
+ "force": "invariant",
723
+ "test": "verifyLoop:artifact-integrity"
724
+ }
725
+ ],
528
726
  },
529
727
  {
530
728
  id: "produce-results",
@@ -532,6 +730,17 @@ const RULES = [
532
730
  category: "process",
533
731
  rule: "Questionnaires are generated by `$apply`, never emitted from CRL: no Questionnaire appears in the CRL definition emit. After validation and CRE checks, call `emit_results(celPath, crlPath, useCase)` (useCase selects result-driver behavior, not kit content); it owns result placement, so never place `$apply` output yourself. Enable `crl.enableResults` in VS Code User settings and restart the MCP client. An absent setting preserves an existing opt-in; explicit false removes it. A JRE 17+ and the CRL-maintained complete CLI engine " + spawn_1.ENGINE_JAR_SOURCE.buildId + " are required. The tool gives the download command when missing, discovers <home>/" + spawn_1.ENGINE_JAR_SOURCE.cacheRelativePath + ", and verifies the pinned hash; normal use needs no manual hashing, extraction, or classpath. The original Maven jar is not the corrected default. `jarPath` and `jarSha256` are overrides. Read every case state: generated / no-questionnaire / populate-degraded / failed / timeout / not-run. An absent file alone is not evidence that the policy asked nothing. generated means a Questionnaire was returned, not that the intended activity or pause was verified; compare those outcomes against each case oracle. Written MV pairs have stable per-case identities and omit QuestionnaireResponse.authored to avoid run-time churn. They are MV review artifacts; do not resubmit these normalized files unchanged as interactive responses. The results tree is producer-owned; use returned paths/manifests and keep hand-authored Q/QR elsewhere.",
534
732
  ref: "verifyLoop",
733
+ clauses: [
734
+ {
735
+ "text": "Use emit_results after validation and CRE checks, enabling it through crl.enableResults in VS Code User settings and restarting the MCP client, and using the maintained verified engine. Consume returned paths and manifests; use explicit jar overrides only for a deliberate alternate engine.",
736
+ "force": "default"
737
+ },
738
+ {
739
+ "text": "Inspect every results case state and compare actual activity/path and answer states with independent expectations. Generated means a Questionnaire was returned, not that the expected conclusion or pause was proved. Failed extraction, degradation, timeout or missing output is not evidence of a clinical pause. Keep result files under producer control: use returned paths/manifests rather than manually placing $apply output or hand-authored Q/QR in its generated tree. MV-normalized Q/QR files omit interactive metadata and must not be resubmitted unchanged as session responses.",
740
+ "force": "invariant",
741
+ "test": "verifyLoop:native-outcome-verification"
742
+ }
743
+ ],
535
744
  },
536
745
  {
537
746
  id: "review-flags",
@@ -774,6 +983,16 @@ const VERIFY_LOOP_BASE = {
774
983
  "Age publication requires independent runtime evidence for its pattern-specific recalculation, same-day assertion and unknown-input behavior. A legacy age fixture is not proof of the new publication contract.",
775
984
  };
776
985
  const METHODOLOGY_REQUIREMENTS = [
986
+ {
987
+ "id": "native-outcome-verification",
988
+ "applicability": "All CRL authoring",
989
+ "text": "Manual verification obligation: validate and emit the intended artifact closure, then compare native $apply activity identities, paths and relevant question/answer states with independently specified case expectations. Verify source/terminology ownership, membership, units and input prerequisites relevant to the case. Check known and missing-input cases and evidence that distinct criteria remain consequential; drop-one is one acceptable method, not a mandatory battery. A pause requires an identified unanswered question and no activity, with setup/extraction/evaluation errors excluded. When execution or a required capability is unavailable, record the affected cases as unverified with the blocking gap and owner/issue; this permits continued authoring but does not discharge runtime acceptance. CRE and successful emission are separate evidence tiers; neither proves native behavior or clinical fidelity."
990
+ },
991
+ {
992
+ "id": "artifact-integrity",
993
+ "applicability": "All CRL authoring",
994
+ "text": "Manual artifact check: keep authored files outside producer-owned trees; inspect tool diagnostics, returned paths and manifests. Compare the complete intended case/resource/path set as well as listed file hashes. Check for identity collisions, omitted resources, stale definitions and pruning/removal failures. Confirm that alternate output roots retain the documented layout. Hash equality alone proves neither completeness nor runtime or clinical correctness."
995
+ },
777
996
  {
778
997
  id: "assert-path",
779
998
  applicability: "All CRL authoring",
@@ -1027,7 +1246,7 @@ function getAuthoringKit() {
1027
1246
  const content = {
1028
1247
  introduction: {
1029
1248
  goal: "Help the KE create a comprehensive and correct computable representation of source material at L1 (narrative), L2 (semi-structured recommendations), or both, using CRL and emitted CQL/FHIR. L2 organizes clinical scenarios, decisions and actions; it is not a required pre-existing intermediate step. Preserve criteria, alternatives, exceptions and outcomes, and validate source coverage separately from execution. Knowledge levels: Boxwala et al. (2011), https://pmc.ncbi.nlm.nih.gov/articles/PMC3241169/. Kit format is a means to this goal, not a language requirement.",
1030
- reading: "Read applicability before applying guidance. The index is complete and unfiltered. Search results are discovery summaries, not complete instructions; retrieve their entry IDs. Entry includes prerequisites. Rule ref fields are human-readable source notes (documents, issues, validator names), not retrieval IDs; use index IDs and requires for tool navigation. Read counterexamples as warnings, never positive templates. Introductory coverage and verification evidence are separate axes.",
1249
+ reading: "Read applicability before applying guidance. The index is complete and unfiltered. Search results are discovery summaries, not complete instructions; retrieve their entry IDs and read the force clauses before acting. Entry includes prerequisites. Rule ref fields are human-readable source notes (documents, issues, validator names), not retrieval IDs; use index IDs and requires for tool navigation. Read counterexamples as warnings, never positive templates. Introductory coverage and verification evidence are separate axes.",
1031
1250
  navigation: 'authoring_kit({view:"entry",id:"rule:named-answer-options"}); authoring_kit({view:"full"}) exports everything.',
1032
1251
  auditMeaning: "contentMatchesAudit compares content only. auditedRevision is the last reviewed source revision, not the build revision or proof that subsequent implementation changes were audited. Development retrieval remains available with contentMatchesAudit:false; release acceptance requires matching audited content.",
1033
1252
  },