@nexalink/coding-contracts 0.3.0 → 0.4.1

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
@@ -1,6 +1,8 @@
1
1
  # `@nexalink/coding-contracts`
2
2
 
3
- Canonical TypeScript contracts for Nexalink CareCompass coding workflows.
3
+ Canonical TypeScript contracts for CareCompass by Nexalink, an embeddable SDK for AI-assisted medical-coding review. CareCompass is built for behavioral-health EHR and RCM platforms: suggestions are grounded in payer policies supplied and approved by the customer's team, and a qualified human reviewer makes the final coding decision.
4
+
5
+ This package supplies the types, validators, and schemas used by those workflows; it is not the hosted coding service. CareCompass does not submit claims or bill payers. Prior authorization and patient navigation are future directions, not the current product. Pilot scope and pricing are agreed directly with Nexalink.
4
6
 
5
7
  The package provides:
6
8
 
@@ -20,7 +22,7 @@ persist data, submit claims, or replace review by a qualified human coder.
20
22
  Pin an exact version so contract upgrades are deliberate:
21
23
 
22
24
  ```sh
23
- bun add @nexalink/coding-contracts@0.2.0 --exact
25
+ bun add @nexalink/coding-contracts@0.4.1 --exact
24
26
  ```
25
27
 
26
28
  The package supports both ES modules and CommonJS.
@@ -110,12 +112,12 @@ approved evidence set.
110
112
 
111
113
  | Category | Exports |
112
114
  | ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
113
- | Types | `RcmCodingInput`, `RcmCodingOutput`, `RcmSupportingReference`, `RcmModelPrompt`, `RcmRetrievalMetadata`, `RcmRuntimeEvent`, `RcmWorkflowCatalog` |
115
+ | Types | `RcmCodingInput`, `RcmCodingOutput`, `RcmSupportingReference`, `RcmModelPrompt`, `RcmRetrievalMetadata`, `RcmRuntimeEvent`, `RcmReviewerEvent`, `RcmWorkflowCatalog` |
114
116
  | Case models | `CodingCase`, `CodingCaseContext`, `CodingCasePayer`, `CodingCaseClinical`, `CodingServiceLine`, `CodingExtension`, `CodingBatch` |
115
117
  | Decision models | `CodingDecision`, `CodingDecisionLine`, `CodingEvidence`, `CodingRuleResult`, `CodingReviewerAction` |
116
118
  | Zod schemas | `rcmCodingInputSchema`, `rcmCodingOutputSchema`, `codingCaseSchema`, `codingDecisionSchema`, and one schema for each additional contract type |
117
119
  | Validation | `rcm*ValidationError` functions, `coding*ValidationError` functions, and `valid*` boolean helpers |
118
- | Workflow policy | `RCM_WORKFLOW_ID`, `RCM_MODEL_POLICY_ID`, `RCM_HUMAN_REVIEW_POLICY_ID`, `RCM_HUMAN_REVIEW_INSTRUCTION`, `RCM_OUTPUT_SCHEMA_NAME` |
120
+ | Workflow policy | `RCM_WORKFLOW_ID`, `PIN_TIME_WORKFLOW_ID`, `RCM_MODEL_POLICY_ID`, `RCM_HUMAN_REVIEW_POLICY_ID`, `RCM_HUMAN_REVIEW_INSTRUCTION`, `RCM_OUTPUT_SCHEMA_NAME` |
119
121
  | Schema versions | `RCM_INPUT_SCHEMA_VERSION`, `RCM_OUTPUT_SCHEMA_VERSION`, `RCM_REFERENCE_SCHEMA_VERSION`, `CODING_CASE_SCHEMA_VERSION`, `CODING_DECISION_SCHEMA_VERSION`, and the other contract wire-version constants |
120
122
  | Schema documents | `Rcm*SchemaJson`, `Coding*SchemaJson` values, JSON Schema package subpaths, `versions.json`, and `workflow-constants.json` |
121
123
 
@@ -2,8 +2,8 @@
2
2
  // GENERATED FILE. DO NOT EDIT.
3
3
  // Source: coding-contracts schemas/ (run: bun run contracts:gen)
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.validCodingEvidence = exports.codingEvidenceSchema = exports.CodingDecisionLineSchemaJson = exports.validCodingDecisionLine = exports.codingDecisionLineSchema = exports.CodingBatchSchemaJson = exports.validCodingBatch = exports.codingBatchSchema = exports.CodingCaseSchemaJson = exports.validCodingCase = exports.codingCaseSchema = exports.CodingExtensionSchemaJson = exports.validCodingExtension = exports.codingExtensionSchema = exports.CodingServiceLineSchemaJson = exports.validCodingServiceLine = exports.codingServiceLineSchema = exports.CodingCaseClinicalSchemaJson = exports.validCodingCaseClinical = exports.codingCaseClinicalSchema = exports.CodingCasePayerSchemaJson = exports.validCodingCasePayer = exports.codingCasePayerSchema = exports.CodingCaseContextSchemaJson = exports.validCodingCaseContext = exports.codingCaseContextSchema = exports.RCM_WORKFLOW_CATALOG_SCHEMA_VERSION = exports.RCM_RUNTIME_EVENT_SCHEMA_VERSION = exports.RCM_RETRIEVAL_SCHEMA_VERSION = exports.RCM_MODEL_PROMPT_SCHEMA_VERSION = exports.RCM_OUTPUT_SCHEMA_VERSION = exports.RCM_INPUT_SCHEMA_VERSION = exports.RCM_REFERENCE_SCHEMA_VERSION = exports.CODING_DECISION_SCHEMA_VERSION = exports.CODING_REVIEWER_ACTION_SCHEMA_VERSION = exports.CODING_RULE_RESULT_SCHEMA_VERSION = exports.CODING_EVIDENCE_SCHEMA_VERSION = exports.CODING_DECISION_LINE_SCHEMA_VERSION = exports.CODING_BATCH_SCHEMA_VERSION = exports.CODING_CASE_SCHEMA_VERSION = exports.CODING_EXTENSION_SCHEMA_VERSION = exports.CODING_SERVICE_LINE_SCHEMA_VERSION = exports.CODING_CASE_CLINICAL_SCHEMA_VERSION = exports.CODING_CASE_PAYER_SCHEMA_VERSION = exports.CODING_CASE_CONTEXT_SCHEMA_VERSION = exports.RCM_HUMAN_REVIEW_INSTRUCTION = exports.RCM_OUTPUT_SCHEMA_NAME = exports.RCM_HUMAN_REVIEW_POLICY_ID = exports.RCM_MODEL_POLICY_ID = exports.RCM_WORKFLOW_ID = void 0;
6
- exports.RcmWorkflowCatalogSchemaJson = exports.validRcmWorkflowCatalog = exports.rcmWorkflowCatalogSchema = exports.RcmRuntimeEventSchemaJson = exports.validRcmRuntimeEvent = exports.rcmRuntimeEventSchema = exports.RcmRetrievalMetadataSchemaJson = exports.validRcmRetrievalMetadata = exports.rcmRetrievalMetadataSchema = exports.RcmModelPromptSchemaJson = exports.validRcmModelPrompt = exports.rcmModelPromptSchema = exports.RcmCodingOutputSchemaJson = exports.validRcmCodingOutput = exports.rcmCodingOutputSchema = exports.RcmCodingInputSchemaJson = exports.validRcmCodingInput = exports.rcmCodingInputSchema = exports.RcmSupportingReferenceSchemaJson = exports.validRcmSupportingReference = exports.rcmSupportingReferenceSchema = exports.CodingDecisionSchemaJson = exports.validCodingDecision = exports.codingDecisionSchema = exports.CodingReviewerActionSchemaJson = exports.validCodingReviewerAction = exports.codingReviewerActionSchema = exports.CodingRuleResultSchemaJson = exports.validCodingRuleResult = exports.codingRuleResultSchema = exports.CodingEvidenceSchemaJson = void 0;
5
+ exports.CodingDecisionLineSchemaJson = exports.validCodingDecisionLine = exports.codingDecisionLineSchema = exports.CodingBatchSchemaJson = exports.validCodingBatch = exports.codingBatchSchema = exports.CodingCaseSchemaJson = exports.validCodingCase = exports.codingCaseSchema = exports.CodingExtensionSchemaJson = exports.validCodingExtension = exports.codingExtensionSchema = exports.CodingServiceLineSchemaJson = exports.validCodingServiceLine = exports.codingServiceLineSchema = exports.CodingCaseClinicalSchemaJson = exports.validCodingCaseClinical = exports.codingCaseClinicalSchema = exports.CodingCasePayerSchemaJson = exports.validCodingCasePayer = exports.codingCasePayerSchema = exports.CodingCaseContextSchemaJson = exports.validCodingCaseContext = exports.codingCaseContextSchema = exports.RCM_WORKFLOW_CATALOG_SCHEMA_VERSION = exports.RCM_RUNTIME_EVENT_SCHEMA_VERSION = exports.RCM_REVIEWER_EVENT_SCHEMA_VERSION = exports.RCM_RETRIEVAL_SCHEMA_VERSION = exports.RCM_MODEL_PROMPT_SCHEMA_VERSION = exports.RCM_OUTPUT_SCHEMA_VERSION = exports.RCM_INPUT_SCHEMA_VERSION = exports.RCM_REFERENCE_SCHEMA_VERSION = exports.CODING_DECISION_SCHEMA_VERSION = exports.CODING_REVIEWER_ACTION_SCHEMA_VERSION = exports.CODING_RULE_RESULT_SCHEMA_VERSION = exports.CODING_EVIDENCE_SCHEMA_VERSION = exports.CODING_DECISION_LINE_SCHEMA_VERSION = exports.CODING_BATCH_SCHEMA_VERSION = exports.CODING_CASE_SCHEMA_VERSION = exports.CODING_EXTENSION_SCHEMA_VERSION = exports.CODING_SERVICE_LINE_SCHEMA_VERSION = exports.CODING_CASE_CLINICAL_SCHEMA_VERSION = exports.CODING_CASE_PAYER_SCHEMA_VERSION = exports.CODING_CASE_CONTEXT_SCHEMA_VERSION = exports.PIN_TIME_WORKFLOW_ID = exports.RCM_HUMAN_REVIEW_INSTRUCTION = exports.RCM_OUTPUT_SCHEMA_NAME = exports.RCM_HUMAN_REVIEW_POLICY_ID = exports.RCM_MODEL_POLICY_ID = exports.RCM_WORKFLOW_ID = void 0;
6
+ exports.RcmWorkflowCatalogSchemaJson = exports.validRcmWorkflowCatalog = exports.rcmWorkflowCatalogSchema = exports.RcmRuntimeEventSchemaJson = exports.validRcmRuntimeEvent = exports.rcmRuntimeEventSchema = exports.RcmReviewerEventSchemaJson = exports.validRcmReviewerEvent = exports.rcmReviewerEventSchema = exports.RcmRetrievalMetadataSchemaJson = exports.validRcmRetrievalMetadata = exports.rcmRetrievalMetadataSchema = exports.RcmModelPromptSchemaJson = exports.validRcmModelPrompt = exports.rcmModelPromptSchema = exports.RcmCodingOutputSchemaJson = exports.validRcmCodingOutput = exports.rcmCodingOutputSchema = exports.RcmCodingInputSchemaJson = exports.validRcmCodingInput = exports.rcmCodingInputSchema = exports.RcmSupportingReferenceSchemaJson = exports.validRcmSupportingReference = exports.rcmSupportingReferenceSchema = exports.CodingDecisionSchemaJson = exports.validCodingDecision = exports.codingDecisionSchema = exports.CodingReviewerActionSchemaJson = exports.validCodingReviewerAction = exports.codingReviewerActionSchema = exports.CodingRuleResultSchemaJson = exports.validCodingRuleResult = exports.codingRuleResultSchema = exports.CodingEvidenceSchemaJson = exports.validCodingEvidence = exports.codingEvidenceSchema = void 0;
7
7
  exports.codingCaseContextValidationError = codingCaseContextValidationError;
8
8
  exports.codingCasePayerValidationError = codingCasePayerValidationError;
9
9
  exports.codingCaseClinicalValidationError = codingCaseClinicalValidationError;
@@ -21,6 +21,7 @@ exports.rcmCodingInputValidationError = rcmCodingInputValidationError;
21
21
  exports.rcmCodingOutputValidationError = rcmCodingOutputValidationError;
22
22
  exports.rcmModelPromptValidationError = rcmModelPromptValidationError;
23
23
  exports.rcmRetrievalMetadataValidationError = rcmRetrievalMetadataValidationError;
24
+ exports.rcmReviewerEventValidationError = rcmReviewerEventValidationError;
24
25
  exports.rcmRuntimeEventValidationError = rcmRuntimeEventValidationError;
25
26
  exports.rcmWorkflowCatalogValidationError = rcmWorkflowCatalogValidationError;
26
27
  const zod_1 = require("zod");
@@ -64,6 +65,7 @@ exports.RCM_MODEL_POLICY_ID = "carecompass-rcm-review-v1";
64
65
  exports.RCM_HUMAN_REVIEW_POLICY_ID = "qualified-coder-review-v1";
65
66
  exports.RCM_OUTPUT_SCHEMA_NAME = "carecompass_rcm_grounded_review";
66
67
  exports.RCM_HUMAN_REVIEW_INSTRUCTION = "Qualified human coder review is required before billing, coding, or claim submission.";
68
+ exports.PIN_TIME_WORKFLOW_ID = "monthly-pin-time-aggregation";
67
69
  // Schema wire versions (source: schemas/*.schema.json).
68
70
  exports.CODING_CASE_CONTEXT_SCHEMA_VERSION = "coding-case-context-v1";
69
71
  exports.CODING_CASE_PAYER_SCHEMA_VERSION = "coding-case-payer-v1";
@@ -82,6 +84,7 @@ exports.RCM_INPUT_SCHEMA_VERSION = "rcm-coding-input-v1";
82
84
  exports.RCM_OUTPUT_SCHEMA_VERSION = "rcm-grounded-human-review-v2";
83
85
  exports.RCM_MODEL_PROMPT_SCHEMA_VERSION = "rcm-model-prompt-v1";
84
86
  exports.RCM_RETRIEVAL_SCHEMA_VERSION = "rcm-retrieval-metadata-v1";
87
+ exports.RCM_REVIEWER_EVENT_SCHEMA_VERSION = "rcm-reviewer-event-v1";
85
88
  exports.RCM_RUNTIME_EVENT_SCHEMA_VERSION = "rcm-runtime-event-v1";
86
89
  exports.RCM_WORKFLOW_CATALOG_SCHEMA_VERSION = "rcm-workflow-catalog-v1";
87
90
  // --------------------------------------------------------------------
@@ -3199,7 +3202,7 @@ exports.CodingRuleResultSchemaJson = {
3199
3202
  },
3200
3203
  };
3201
3204
  // --------------------------------------------------------------------
3202
- // CodingReviewerAction (schema 1.0.0, wire coding-reviewer-action-v1)
3205
+ // CodingReviewerAction (schema 1.1.0, wire coding-reviewer-action-v1)
3203
3206
  // --------------------------------------------------------------------
3204
3207
  exports.codingReviewerActionSchema = zod_1.z
3205
3208
  .object({
@@ -3212,6 +3215,15 @@ exports.codingReviewerActionSchema = zod_1.z
3212
3215
  "escalated",
3213
3216
  ]),
3214
3217
  resolutionCode: zod_1.z.string().min(1).max(80).optional(),
3218
+ reviewOutcomeCategory: zod_1.z
3219
+ .enum([
3220
+ "unsupported_or_excessive",
3221
+ "missed_supported",
3222
+ "unchanged_supported",
3223
+ "missing_evidence",
3224
+ "escalation",
3225
+ ])
3226
+ .optional(),
3215
3227
  notes: zod_1.z
3216
3228
  .string()
3217
3229
  .min(1)
@@ -3235,6 +3247,7 @@ function codingReviewerActionValidationError(value) {
3235
3247
  "reviewerRole",
3236
3248
  "action",
3237
3249
  "resolutionCode",
3250
+ "reviewOutcomeCategory",
3238
3251
  "notes",
3239
3252
  "occurredAt",
3240
3253
  ].includes(key)))
@@ -3262,6 +3275,18 @@ function codingReviewerActionValidationError(value) {
3262
3275
  value_resolutionCode.length > 80)
3263
3276
  return "reviewer_action_resolution_code";
3264
3277
  }
3278
+ if (value["reviewOutcomeCategory"] !== undefined) {
3279
+ const value_reviewOutcomeCategory = value["reviewOutcomeCategory"];
3280
+ if (typeof value_reviewOutcomeCategory !== "string" ||
3281
+ ![
3282
+ "unsupported_or_excessive",
3283
+ "missed_supported",
3284
+ "unchanged_supported",
3285
+ "missing_evidence",
3286
+ "escalation",
3287
+ ].includes(value_reviewOutcomeCategory))
3288
+ return "reviewer_action_outcome_category";
3289
+ }
3265
3290
  if (value["notes"] !== undefined) {
3266
3291
  const value_notes = value["notes"];
3267
3292
  if (typeof value_notes !== "string" ||
@@ -3284,8 +3309,8 @@ exports.CodingReviewerActionSchemaJson = {
3284
3309
  $schema: "https://json-schema.org/draft/2020-12/schema",
3285
3310
  $id: "https://nexalink.care/contracts/coding-reviewer-action.schema.json",
3286
3311
  title: "CodingReviewerAction",
3287
- description: "Attributable human-review disposition appended to an otherwise immutable decision. A decision plus its reviewer actions remains replayable: original and reviewer versions are both preserved.",
3288
- version: "1.0.0",
3312
+ description: "Attributable human-review disposition appended to an otherwise immutable decision. A decision plus its reviewer actions remains replayable: original and reviewer versions are both preserved. Review outcome categories are reviewer-adjudicated observations and never inferred from payment, code, or reimbursement changes.",
3313
+ version: "1.1.0",
3289
3314
  type: "object",
3290
3315
  additionalProperties: false,
3291
3316
  required: ["reviewerId", "action", "occurredAt"],
@@ -3309,6 +3334,16 @@ exports.CodingReviewerActionSchemaJson = {
3309
3334
  minLength: 1,
3310
3335
  maxLength: 80,
3311
3336
  },
3337
+ reviewOutcomeCategory: {
3338
+ type: "string",
3339
+ enum: [
3340
+ "unsupported_or_excessive",
3341
+ "missed_supported",
3342
+ "unchanged_supported",
3343
+ "missing_evidence",
3344
+ "escalation",
3345
+ ],
3346
+ },
3312
3347
  notes: {
3313
3348
  type: "string",
3314
3349
  minLength: 1,
@@ -3500,7 +3535,7 @@ exports.codingDecisionSchema = zod_1.z
3500
3535
  });
3501
3536
  }
3502
3537
  });
3503
- function codingDecisionValidationError(value, options) {
3538
+ function codingDecisionValidationError(value) {
3504
3539
  if (!isRecord(value))
3505
3540
  return "coding_decision";
3506
3541
  if (![
@@ -5243,6 +5278,342 @@ exports.RcmRetrievalMetadataSchemaJson = {
5243
5278
  },
5244
5279
  };
5245
5280
  // --------------------------------------------------------------------
5281
+ // RcmReviewerEvent (schema 1.0.0, wire rcm-reviewer-event-v1)
5282
+ // --------------------------------------------------------------------
5283
+ exports.rcmReviewerEventSchema = zod_1.z
5284
+ .object({
5285
+ eventName: zod_1.z.enum([
5286
+ "review_opened",
5287
+ "decision_shown",
5288
+ "evidence_opened",
5289
+ "evidence_copied",
5290
+ "review_active_time",
5291
+ ]),
5292
+ occurredAt: zod_1.z
5293
+ .string()
5294
+ .regex(new RegExp("^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$"))
5295
+ .refine(isRfc3339DateTime)
5296
+ .max(64),
5297
+ tenantRef: zod_1.z
5298
+ .string()
5299
+ .regex(new RegExp("^[A-Za-z0-9_.:-]+$"))
5300
+ .min(1)
5301
+ .max(128),
5302
+ caseRef: zod_1.z.string().regex(new RegExp("^[A-Za-z0-9_.:-]+$")).min(1).max(128),
5303
+ reviewId: zod_1.z
5304
+ .string()
5305
+ .regex(new RegExp("^[A-Za-z0-9_.:-]+$"))
5306
+ .min(1)
5307
+ .max(128)
5308
+ .optional(),
5309
+ workflowId: zod_1.z.enum([
5310
+ "rcm-coding-assistance",
5311
+ "monthly-pin-time-aggregation",
5312
+ ]),
5313
+ packId: zod_1.z
5314
+ .string()
5315
+ .regex(new RegExp("^[A-Za-z0-9_.:-]+$"))
5316
+ .min(1)
5317
+ .max(80)
5318
+ .optional(),
5319
+ packVersion: zod_1.z
5320
+ .string()
5321
+ .regex(new RegExp("^[A-Za-z0-9_.:-]+$"))
5322
+ .min(1)
5323
+ .max(80)
5324
+ .optional(),
5325
+ environment: zod_1.z.enum(["development", "staging", "production"]).optional(),
5326
+ source: zod_1.z.enum(["portal", "embed"]),
5327
+ evidenceId: zod_1.z
5328
+ .string()
5329
+ .regex(new RegExp("^[A-Za-z0-9_.:-]{1,64}$"))
5330
+ .min(1)
5331
+ .max(64)
5332
+ .optional(),
5333
+ activeSeconds: zod_1.z.number().int().min(0).max(86400).optional(),
5334
+ idlePaused: zod_1.z.boolean().optional(),
5335
+ })
5336
+ .strict()
5337
+ .superRefine((value, ctx) => {
5338
+ const isEvidenceEvent = value["eventName"] === "evidence_opened" ||
5339
+ value["eventName"] === "evidence_copied";
5340
+ const isActiveTimeEvent = value["eventName"] === "review_active_time";
5341
+ if (isEvidenceEvent !== (value.evidenceId !== undefined) ||
5342
+ isActiveTimeEvent !== (value.activeSeconds !== undefined) ||
5343
+ (!isActiveTimeEvent && value.idlePaused !== undefined)) {
5344
+ ctx.addIssue({
5345
+ code: "custom",
5346
+ path: ["eventName"],
5347
+ message: "reviewer_event_shape",
5348
+ });
5349
+ }
5350
+ });
5351
+ function rcmReviewerEventValidationError(value) {
5352
+ if (!isRecord(value))
5353
+ return "reviewer_event";
5354
+ if (![
5355
+ "eventName",
5356
+ "occurredAt",
5357
+ "tenantRef",
5358
+ "caseRef",
5359
+ "workflowId",
5360
+ "source",
5361
+ ].every((key) => key in value))
5362
+ return "reviewer_event_keys";
5363
+ if (!Object.keys(value).every((key) => [
5364
+ "eventName",
5365
+ "occurredAt",
5366
+ "tenantRef",
5367
+ "caseRef",
5368
+ "reviewId",
5369
+ "workflowId",
5370
+ "packId",
5371
+ "packVersion",
5372
+ "environment",
5373
+ "source",
5374
+ "evidenceId",
5375
+ "activeSeconds",
5376
+ "idlePaused",
5377
+ ].includes(key)))
5378
+ return "reviewer_event_keys";
5379
+ const value_eventName = value["eventName"];
5380
+ if (typeof value_eventName !== "string" ||
5381
+ ![
5382
+ "review_opened",
5383
+ "decision_shown",
5384
+ "evidence_opened",
5385
+ "evidence_copied",
5386
+ "review_active_time",
5387
+ ].includes(value_eventName))
5388
+ return "reviewer_event_name";
5389
+ const value_occurredAt = value["occurredAt"];
5390
+ if (typeof value_occurredAt !== "string" ||
5391
+ value_occurredAt.length > 64 ||
5392
+ !new RegExp("^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$").test(value_occurredAt) ||
5393
+ !isRfc3339DateTime(value_occurredAt))
5394
+ return "reviewer_event_occurred_at";
5395
+ const value_tenantRef = value["tenantRef"];
5396
+ if (typeof value_tenantRef !== "string" ||
5397
+ value_tenantRef.length < 1 ||
5398
+ value_tenantRef.length > 128 ||
5399
+ !new RegExp("^[A-Za-z0-9_.:-]+$").test(value_tenantRef))
5400
+ return "reviewer_event_tenant_ref";
5401
+ const value_caseRef = value["caseRef"];
5402
+ if (typeof value_caseRef !== "string" ||
5403
+ value_caseRef.length < 1 ||
5404
+ value_caseRef.length > 128 ||
5405
+ !new RegExp("^[A-Za-z0-9_.:-]+$").test(value_caseRef))
5406
+ return "reviewer_event_case_ref";
5407
+ if (value["reviewId"] !== undefined) {
5408
+ const value_reviewId = value["reviewId"];
5409
+ if (typeof value_reviewId !== "string" ||
5410
+ value_reviewId.length < 1 ||
5411
+ value_reviewId.length > 128 ||
5412
+ !new RegExp("^[A-Za-z0-9_.:-]+$").test(value_reviewId))
5413
+ return "reviewer_event_review_id";
5414
+ }
5415
+ const value_workflowId = value["workflowId"];
5416
+ if (typeof value_workflowId !== "string" ||
5417
+ !["rcm-coding-assistance", "monthly-pin-time-aggregation"].includes(value_workflowId))
5418
+ return "reviewer_event_workflow_id";
5419
+ if (value["packId"] !== undefined) {
5420
+ const value_packId = value["packId"];
5421
+ if (typeof value_packId !== "string" ||
5422
+ value_packId.length < 1 ||
5423
+ value_packId.length > 80 ||
5424
+ !new RegExp("^[A-Za-z0-9_.:-]+$").test(value_packId))
5425
+ return "reviewer_event_pack_id";
5426
+ }
5427
+ if (value["packVersion"] !== undefined) {
5428
+ const value_packVersion = value["packVersion"];
5429
+ if (typeof value_packVersion !== "string" ||
5430
+ value_packVersion.length < 1 ||
5431
+ value_packVersion.length > 80 ||
5432
+ !new RegExp("^[A-Za-z0-9_.:-]+$").test(value_packVersion))
5433
+ return "reviewer_event_pack_version";
5434
+ }
5435
+ if (value["environment"] !== undefined) {
5436
+ const value_environment = value["environment"];
5437
+ if (typeof value_environment !== "string" ||
5438
+ !["development", "staging", "production"].includes(value_environment))
5439
+ return "reviewer_event_environment";
5440
+ }
5441
+ const value_source = value["source"];
5442
+ if (typeof value_source !== "string" ||
5443
+ !["portal", "embed"].includes(value_source))
5444
+ return "reviewer_event_source";
5445
+ if (value["evidenceId"] !== undefined) {
5446
+ const value_evidenceId = value["evidenceId"];
5447
+ if (typeof value_evidenceId !== "string" ||
5448
+ value_evidenceId.length < 1 ||
5449
+ value_evidenceId.length > 64 ||
5450
+ !new RegExp("^[A-Za-z0-9_.:-]{1,64}$").test(value_evidenceId))
5451
+ return "reviewer_event_evidence_id";
5452
+ }
5453
+ if (value["activeSeconds"] !== undefined) {
5454
+ const value_activeSeconds = value["activeSeconds"];
5455
+ if (typeof value_activeSeconds !== "number" ||
5456
+ Number.isNaN(value_activeSeconds) ||
5457
+ !Number.isInteger(value_activeSeconds) ||
5458
+ value_activeSeconds < 0 ||
5459
+ value_activeSeconds > 86400)
5460
+ return "reviewer_event_active_seconds";
5461
+ }
5462
+ if (value["idlePaused"] !== undefined) {
5463
+ const value_idlePaused = value["idlePaused"];
5464
+ if (typeof value_idlePaused !== "boolean")
5465
+ return "reviewer_event_idle_paused";
5466
+ }
5467
+ const eventName = value["eventName"];
5468
+ const isEvidenceEvent = eventName === "evidence_opened" || eventName === "evidence_copied";
5469
+ if (isEvidenceEvent !== (value["evidenceId"] !== undefined))
5470
+ return "reviewer_event_shape";
5471
+ const isActiveTimeEvent = eventName === "review_active_time";
5472
+ if (isActiveTimeEvent !== (value["activeSeconds"] !== undefined))
5473
+ return "reviewer_event_shape";
5474
+ if (!isActiveTimeEvent && value["idlePaused"] !== undefined)
5475
+ return "reviewer_event_shape";
5476
+ return null;
5477
+ }
5478
+ const validRcmReviewerEvent = (value) => rcmReviewerEventValidationError(value) === null;
5479
+ exports.validRcmReviewerEvent = validRcmReviewerEvent;
5480
+ exports.RcmReviewerEventSchemaJson = {
5481
+ $schema: "https://json-schema.org/draft/2020-12/schema",
5482
+ $id: "https://nexalink.care/contracts/rcm-reviewer-event.schema.json",
5483
+ title: "RcmReviewerEvent",
5484
+ description: "Tenant-scoped, PHI-free reviewer engagement event for CareCompass RCM workflows. Events carry only an opaque case reference, categorical engagement facts, and aggregate durations. They never carry prompts, model responses, document contents, patient or member identifiers, claim identifiers, or free text.",
5485
+ version: "1.0.0",
5486
+ type: "object",
5487
+ additionalProperties: false,
5488
+ required: [
5489
+ "eventName",
5490
+ "occurredAt",
5491
+ "tenantRef",
5492
+ "caseRef",
5493
+ "workflowId",
5494
+ "source",
5495
+ ],
5496
+ properties: {
5497
+ eventName: {
5498
+ type: "string",
5499
+ enum: [
5500
+ "review_opened",
5501
+ "decision_shown",
5502
+ "evidence_opened",
5503
+ "evidence_copied",
5504
+ "review_active_time",
5505
+ ],
5506
+ },
5507
+ occurredAt: {
5508
+ type: "string",
5509
+ pattern: "^\\d{4}-\\d{2}-\\d{2}T(?:[01]\\d|2[0-3]):[0-5]\\d:[0-5]\\d(?:\\.\\d+)?(?:Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)$",
5510
+ format: "date-time",
5511
+ maxLength: 64,
5512
+ },
5513
+ tenantRef: {
5514
+ type: "string",
5515
+ minLength: 1,
5516
+ maxLength: 128,
5517
+ pattern: "^[A-Za-z0-9_.:-]+$",
5518
+ },
5519
+ caseRef: {
5520
+ type: "string",
5521
+ minLength: 1,
5522
+ maxLength: 128,
5523
+ pattern: "^[A-Za-z0-9_.:-]+$",
5524
+ },
5525
+ reviewId: {
5526
+ type: "string",
5527
+ minLength: 1,
5528
+ maxLength: 128,
5529
+ pattern: "^[A-Za-z0-9_.:-]+$",
5530
+ },
5531
+ workflowId: {
5532
+ type: "string",
5533
+ enum: ["rcm-coding-assistance", "monthly-pin-time-aggregation"],
5534
+ },
5535
+ packId: {
5536
+ type: "string",
5537
+ minLength: 1,
5538
+ maxLength: 80,
5539
+ pattern: "^[A-Za-z0-9_.:-]+$",
5540
+ },
5541
+ packVersion: {
5542
+ type: "string",
5543
+ minLength: 1,
5544
+ maxLength: 80,
5545
+ pattern: "^[A-Za-z0-9_.:-]+$",
5546
+ },
5547
+ environment: {
5548
+ type: "string",
5549
+ enum: ["development", "staging", "production"],
5550
+ },
5551
+ source: {
5552
+ type: "string",
5553
+ enum: ["portal", "embed"],
5554
+ },
5555
+ evidenceId: {
5556
+ type: "string",
5557
+ minLength: 1,
5558
+ pattern: "^[A-Za-z0-9_.:-]{1,64}$",
5559
+ maxLength: 64,
5560
+ },
5561
+ activeSeconds: {
5562
+ type: "integer",
5563
+ minimum: 0,
5564
+ maximum: 86400,
5565
+ },
5566
+ idlePaused: {
5567
+ type: "boolean",
5568
+ },
5569
+ },
5570
+ allOf: [
5571
+ {
5572
+ if: {
5573
+ properties: {
5574
+ eventName: {
5575
+ enum: ["evidence_opened", "evidence_copied"],
5576
+ },
5577
+ },
5578
+ required: ["eventName"],
5579
+ },
5580
+ then: {
5581
+ required: ["evidenceId"],
5582
+ },
5583
+ else: {
5584
+ not: {
5585
+ required: ["evidenceId"],
5586
+ },
5587
+ },
5588
+ },
5589
+ {
5590
+ if: {
5591
+ properties: {
5592
+ eventName: {
5593
+ const: "review_active_time",
5594
+ },
5595
+ },
5596
+ required: ["eventName"],
5597
+ },
5598
+ then: {
5599
+ required: ["activeSeconds"],
5600
+ },
5601
+ else: {
5602
+ not: {
5603
+ anyOf: [
5604
+ {
5605
+ required: ["activeSeconds"],
5606
+ },
5607
+ {
5608
+ required: ["idlePaused"],
5609
+ },
5610
+ ],
5611
+ },
5612
+ },
5613
+ },
5614
+ ],
5615
+ };
5616
+ // --------------------------------------------------------------------
5246
5617
  // RcmRuntimeEvent (schema 1.0.0, wire rcm-runtime-event-v1)
5247
5618
  // --------------------------------------------------------------------
5248
5619
  exports.rcmRuntimeEventSchema = zod_1.z
@@ -5601,17 +5972,20 @@ exports.RcmRuntimeEventSchemaJson = {
5601
5972
  },
5602
5973
  };
5603
5974
  // --------------------------------------------------------------------
5604
- // RcmWorkflowCatalog (schema 1.0.0, wire rcm-workflow-catalog-v1)
5975
+ // RcmWorkflowCatalog (schema 1.1.0, wire rcm-workflow-catalog-v1)
5605
5976
  // --------------------------------------------------------------------
5606
5977
  exports.rcmWorkflowCatalogSchema = zod_1.z
5607
5978
  .object({
5608
- id: zod_1.z.enum(["rcm-coding-assistance"]),
5979
+ id: zod_1.z.enum(["rcm-coding-assistance", "monthly-pin-time-aggregation"]),
5609
5980
  name: zod_1.z.string().min(1).max(120),
5610
5981
  description: zod_1.z.string().min(1).max(400),
5611
5982
  environments: zod_1.z.array(zod_1.z.enum(["development", "production"])).min(1),
5612
5983
  modelPolicy: zod_1.z
5613
5984
  .object({
5614
- policyId: zod_1.z.literal("carecompass-rcm-review-v1"),
5985
+ policyId: zod_1.z.enum([
5986
+ "carecompass-rcm-review-v1",
5987
+ "carecompass-pin-time-policy-v1",
5988
+ ]),
5615
5989
  inferencePath: zod_1.z.string().max(64),
5616
5990
  maxNewTokens: zod_1.z.number().int().min(1).max(2048),
5617
5991
  temperature: zod_1.z.number().min(0).max(2),
@@ -5627,7 +6001,21 @@ exports.rcmWorkflowCatalogSchema = zod_1.z
5627
6001
  .strict(),
5628
6002
  outputSchemaVersion: zod_1.z.literal("rcm-grounded-human-review-v2"),
5629
6003
  })
5630
- .strict();
6004
+ .strict()
6005
+ .superRefine((value, ctx) => {
6006
+ const expectedPolicy = value.id === "rcm-coding-assistance"
6007
+ ? "carecompass-rcm-review-v1"
6008
+ : "carecompass-pin-time-policy-v1";
6009
+ if (value.modelPolicy.policyId !== expectedPolicy ||
6010
+ (value.id === "monthly-pin-time-aggregation" &&
6011
+ value.environments.some((environment) => environment !== "development"))) {
6012
+ ctx.addIssue({
6013
+ code: "custom",
6014
+ path: ["modelPolicy"],
6015
+ message: "workflow_policy_binding",
6016
+ });
6017
+ }
6018
+ });
5631
6019
  function rcmWorkflowCatalogValidationError(value) {
5632
6020
  if (!isRecord(value))
5633
6021
  return "workflow_catalog";
@@ -5653,7 +6041,7 @@ function rcmWorkflowCatalogValidationError(value) {
5653
6041
  return "workflow_catalog_keys";
5654
6042
  const value_id = value["id"];
5655
6043
  if (typeof value_id !== "string" ||
5656
- !["rcm-coding-assistance"].includes(value_id))
6044
+ !["rcm-coding-assistance", "monthly-pin-time-aggregation"].includes(value_id))
5657
6045
  return "workflow_id";
5658
6046
  const value_name = value["name"];
5659
6047
  if (typeof value_name !== "string" ||
@@ -5696,7 +6084,7 @@ function rcmWorkflowCatalogValidationError(value) {
5696
6084
  return "model_policy_keys";
5697
6085
  const value_modelPolicy_policyId = value_modelPolicy["policyId"];
5698
6086
  if (typeof value_modelPolicy_policyId !== "string" ||
5699
- value_modelPolicy_policyId !== "carecompass-rcm-review-v1")
6087
+ !["carecompass-rcm-review-v1", "carecompass-pin-time-policy-v1"].includes(value_modelPolicy_policyId))
5700
6088
  return "model_policy_id";
5701
6089
  const value_modelPolicy_inferencePath = value_modelPolicy["inferencePath"];
5702
6090
  if (typeof value_modelPolicy_inferencePath !== "string" ||
@@ -5742,6 +6130,15 @@ function rcmWorkflowCatalogValidationError(value) {
5742
6130
  if (typeof value_outputSchemaVersion !== "string" ||
5743
6131
  value_outputSchemaVersion !== "rcm-grounded-human-review-v2")
5744
6132
  return "workflow_output_schema_version";
6133
+ const policy = isRecord(value["modelPolicy"]) ? value["modelPolicy"] : {};
6134
+ const expectedPolicy = value["id"] === "rcm-coding-assistance"
6135
+ ? "carecompass-rcm-review-v1"
6136
+ : "carecompass-pin-time-policy-v1";
6137
+ if (policy["policyId"] !== expectedPolicy ||
6138
+ (value["id"] === "monthly-pin-time-aggregation" &&
6139
+ Array.isArray(value["environments"]) &&
6140
+ value["environments"].some((environment) => environment !== "development")))
6141
+ return "workflow_policy_binding";
5745
6142
  return null;
5746
6143
  }
5747
6144
  const validRcmWorkflowCatalog = (value) => rcmWorkflowCatalogValidationError(value) === null;
@@ -5750,8 +6147,8 @@ exports.RcmWorkflowCatalogSchemaJson = {
5750
6147
  $schema: "https://json-schema.org/draft/2020-12/schema",
5751
6148
  $id: "https://nexalink.care/contracts/rcm-workflow-catalog.schema.json",
5752
6149
  title: "RcmWorkflowCatalog",
5753
- description: "A single authorized workflow entry. The catalog pins the workflow identifier, model policy, human-review policy, and output schema version that the runtime and portal may offer for the RCM coding-assistance workflow. Customer configuration can never redefine these immutable server-side values.",
5754
- version: "1.0.0",
6150
+ description: "A single authorized workflow entry. The catalog pins the workflow identifier, model policy, human-review policy, and output schema version that the runtime and portal may offer for registered coding workflows (currently rcm-coding-assistance and monthly-pin-time-aggregation). Customer configuration can never redefine these immutable server-side values.",
6151
+ version: "1.1.0",
5755
6152
  type: "object",
5756
6153
  additionalProperties: false,
5757
6154
  required: [
@@ -5766,7 +6163,7 @@ exports.RcmWorkflowCatalogSchemaJson = {
5766
6163
  properties: {
5767
6164
  id: {
5768
6165
  type: "string",
5769
- enum: ["rcm-coding-assistance"],
6166
+ enum: ["rcm-coding-assistance", "monthly-pin-time-aggregation"],
5770
6167
  },
5771
6168
  name: {
5772
6169
  type: "string",
@@ -5800,7 +6197,7 @@ exports.RcmWorkflowCatalogSchemaJson = {
5800
6197
  properties: {
5801
6198
  policyId: {
5802
6199
  type: "string",
5803
- const: "carecompass-rcm-review-v1",
6200
+ enum: ["carecompass-rcm-review-v1", "carecompass-pin-time-policy-v1"],
5804
6201
  },
5805
6202
  inferencePath: {
5806
6203
  type: "string",
@@ -5846,4 +6243,51 @@ exports.RcmWorkflowCatalogSchemaJson = {
5846
6243
  const: "rcm-grounded-human-review-v2",
5847
6244
  },
5848
6245
  },
6246
+ allOf: [
6247
+ {
6248
+ if: {
6249
+ properties: {
6250
+ id: {
6251
+ const: "rcm-coding-assistance",
6252
+ },
6253
+ },
6254
+ },
6255
+ then: {
6256
+ properties: {
6257
+ modelPolicy: {
6258
+ properties: {
6259
+ policyId: {
6260
+ const: "carecompass-rcm-review-v1",
6261
+ },
6262
+ },
6263
+ },
6264
+ },
6265
+ },
6266
+ },
6267
+ {
6268
+ if: {
6269
+ properties: {
6270
+ id: {
6271
+ const: "monthly-pin-time-aggregation",
6272
+ },
6273
+ },
6274
+ },
6275
+ then: {
6276
+ properties: {
6277
+ modelPolicy: {
6278
+ properties: {
6279
+ policyId: {
6280
+ const: "carecompass-pin-time-policy-v1",
6281
+ },
6282
+ },
6283
+ },
6284
+ environments: {
6285
+ items: {
6286
+ const: "development",
6287
+ },
6288
+ },
6289
+ },
6290
+ },
6291
+ },
6292
+ ],
5849
6293
  };