@peopl-health/nexus 5.10.0-dev.1056 → 5.10.0-dev.1058

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.
@@ -0,0 +1,10 @@
1
+ const runtimeConfig = require('../../config/runtimeConfig');
2
+
3
+ function patternConsultLive() {
4
+ // Default off until the PATTERN_CONSULT Airtable preset and the swapped clinical_routing prose exist; the Python authority defaults true because those already exist there.
5
+ return String(runtimeConfig.get('PATTERN_CONSULT_LIVE', 'false')).trim().toLowerCase() === 'true';
6
+ }
7
+
8
+ module.exports = {
9
+ patternConsultLive,
10
+ };
@@ -1,8 +1,10 @@
1
1
  const crypto = require('node:crypto');
2
2
 
3
+ const { patternConsultStore } = require('../models/patternConsultModel');
3
4
  const { readSymptomCases, readClusters, storeCluster } = require('../../fhir');
4
5
  const { ClusterImpression } = require('../../shared/dtos/ClusterImpression');
5
6
  const { ClusterHistoryRecord } = require('../../shared/dtos/ClusterHistoryRecord');
7
+ const { patternConsultLive } = require('../flags/patternConsultFlags');
6
8
 
7
9
  const HYPOTHESIS_TYPES = ['ae_profile', 'symptom_syndrome', 'disease_complication', 'relational_causal'];
8
10
  const CONFIDENCE_LEVELS = ['speculative', 'moderate', 'strong'];
@@ -95,10 +97,28 @@ async function handler(args = {}, context = {}) {
95
97
  if (!CONFIDENCE_LEVELS.includes(initialConfidence)) return fail(`invalid initial_confidence: '${initialConfidence}'. Must be one of ${CONFIDENCE_LEVELS.join(' | ')}.`, { initial_confidence: initialConfidence });
96
98
  if (!CLINICAL_SIGNIFICANCE.includes(clinicalSignificance)) return fail(`invalid clinical_significance: '${clinicalSignificance}'. Must be one of ${CLINICAL_SIGNIFICANCE.join(' | ')}.`, { clinical_significance: clinicalSignificance });
97
99
 
100
+ const consultationId = str(args?.consultation_id).trim() || null;
101
+
98
102
  if (requested.length < 2) return fail('cluster requires at least 2 member_case_ids (NCI symptom-cluster definition).', { member_case_ids: requested });
99
103
  const memberCaseIds = [...new Set(requested)];
100
104
  if (memberCaseIds.length < 2) return fail('after dedup, fewer than 2 unique member_case_ids remain');
101
105
 
106
+ if (patternConsultLive() && initialConfidence !== 'speculative') {
107
+ if (!consultationId) {
108
+ return fail('unanchored_hypothesis_must_start_speculative', {
109
+ initial_confidence: initialConfidence,
110
+ hint: 'open at speculative confidence, or anchor to a requestPatternConsult consultation_id',
111
+ });
112
+ }
113
+ const consult = await patternConsultStore().get(consultationId);
114
+ if (!consult || consult.patientCode !== runtime.patientCode) {
115
+ return fail('invalid_consultation_id', {
116
+ consultation_id: consultationId,
117
+ hint: 'anchor to a real requestPatternConsult consultation for this patient, or open at speculative confidence',
118
+ });
119
+ }
120
+ }
121
+
102
122
  const patientId = runtime.patientCode;
103
123
  const active = await readClusters({ patientId, label });
104
124
  const existing = active.find((c) => c.status === 'active');
@@ -119,7 +139,6 @@ async function handler(args = {}, context = {}) {
119
139
 
120
140
  const now = new Date().toISOString();
121
141
  const clusterId = `cluster_${crypto.randomUUID().replace(/-/g, '').slice(0, 12)}`;
122
- const consultationId = str(args?.consultation_id).trim() || null;
123
142
  const cluster = new ClusterImpression({
124
143
  clusterId,
125
144
  patientId,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peopl-health/nexus",
3
- "version": "5.10.0-dev.1056",
3
+ "version": "5.10.0-dev.1058",
4
4
  "description": "Core messaging and assistant library for WhatsApp communication platforms",
5
5
  "keywords": [
6
6
  "whatsapp",