brainstorming
brainstorming
You MUST use this before any creative work - creating features, building components, adding functionality, modifying behavior, or planning anything new, in software or out of it (a talk, a business, a renovation).
nhi-cql-generatorGenerate CQL Library and FHIR ValueSet artifacts for Taiwan NHI (National Health Insurance) reimbursement rules from rule text. Use when user asks to create CQL/ValueSet for 健保給付規則, 藥品審查, NHI CQL, 健保代碼, or payment審查. This skill applies patterns learned from 50+ GT examples.
Independent GitHub snapshot · Automated classification · Original documentation governs
Generate CQL Library (.cql) and FHIR ValueSet (.json) files from Taiwan NHI reimbursement rules text.
This skill generates standardized clinical decision support artifacts for Taiwan's National Health Insurance system:
Critical: All patterns are learned from 50+ GT examples. Do NOT deviate from documented patterns.
Every generated CQL file depends on two shared libraries located in .github/skills/nhi-cql-generator/assets/:
FHIRHelpers.cql (version 4.0.1)
CDSConnectCommonsForFHIRv401.cql (version 2.1.0, aliased as C3F)
C3F.Confirmed(Conditions) - Filter confirmed conditionsC3F.Verified(Observations) - Filter verified observationsC3F.MostRecent(Observations) - Get most recent observationC3F.QuantityValue(Observation) - Extract quantity valueC3F.ObservationLookBack(Observations, LookBack) - Observations in time windowC3F.MostRecentProcedure(Procedures) - Get most recent procedureC3F.ActiveCondition(Conditions) - Filter active conditionsC3F.PeriodToInterval(Period) - Convert FHIR Period to CQL IntervalC3F. prefix (e.g., C3F.Confirmed([Condition: "code"]))IMPORTANT: When generating CQL artifacts, you MUST copy these two files to the output directory alongside the generated .cql files. Without them, the CQL will fail with error:
Could not load source for library CDSConnectCommonsForFHIRv401, version 2.1.0, namespace uri null.
library "[規則編號]" version '0.0.1'
'0.0.1'library "[規則編號]" version '0.0.1'
using FHIR version '4.0.1'
include "FHIRHelpers" version '4.0.1' called FHIRHelpers
include "CDSConnectCommonsForFHIRv401" version '2.1.0' called C3F
Never change: FHIR version, FHIRHelpers version, C3F version, or aliases.
After include statements, before codesystem declarations:
valueset "[中文名稱] valueset": '[ValueSet URL]'
URL Pattern: https://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.[sequential-number]
Examples:
valueset "17022B 呼氣一氧化氮監測(FeNO) valueset": 'https://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.6'valueset "糖尿病合併慢性腎病變 valueset": 'https://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.46'Use ONLY these codesystem URLs:
codesystem "ICD-10-CM": 'http://hl7.org/fhir/sid/icd-10-cm'
codesystem "ICD-10-PCS": 'http://www.cms.gov/Medicare/Coding/ICD10'
codesystem "LOINC": 'http://loinc.org'
codesystem "SCT": 'http://snomed.info/sct'
codesystem "TWMedicalServicePayment": 'https://twcore.mohw.gov.tw/ig/twcore/CodeSystem/medical-service-payment-tw'
codesystem "CONDVERSTATUS": 'http://terminology.hl7.org/CodeSystem/condition-ver-status'
codesystem "CONDCLINSTATUS": 'http://terminology.hl7.org/CodeSystem/condition-clinical'
codesystem "ActCode": 'http://terminology.hl7.org/CodeSystem/v3-ActCode'
context Patient
Always use Patient context.
Standard structure observed in all examples:
define "[適應症或條件名稱]":
exists ( C3F.Confirmed([Condition: "[valueset名稱]"]) )
define "MeetsInclusionCriteria":
"[主要適應症]"
define "InPopulation":
"MeetsInclusionCriteria"
define "Recommendation":
if "InPopulation" then '健保給付[點數]點'
else null
define "Rationale":
null
define "Links":
null
define "Suggestions":
null
define "Errors":
null
Direct Usage - Use C3F library functions directly without redefining them:
// ✅ Correct: Use C3F functions directly
define "適應症":
exists ( C3F.Confirmed([Condition: "適應症 valueset"]) )
define "Recent Observations":
C3F.ObservationLookBack([Observation: "code"], 1 year)
define "Lab Value":
C3F.QuantityValue( C3F.MostRecent([Observation: "code"]) )
Common C3F Functions:
C3F.Confirmed(Conditions) - Filters to confirmed conditions (verificationStatus = 'confirmed')C3F.Verified(Observations) - Filters to verified observations (status = 'final', 'corrected', or 'amended')C3F.ObservationLookBack(Observations, LookBack) - Observations within time windowC3F.MostRecent(Observations) - Most recent observation by effective dateC3F.QuantityValue(Observation) - Extract quantity value from observationC3F.MostRecentProcedure(Procedures) - Most recent procedureC3F.ActiveCondition(Conditions) - Active conditions (clinicalStatus = 'active', no abatement)C3F.PeriodToInterval(Period) - Convert FHIR Period to CQL IntervalNote: GT examples redundantly redefine these functions at the end of each file, but this is unnecessary duplication. Simply use C3F.FunctionName() directly.
exists ( C3F.Confirmed([Condition: "[valueset名稱]"]) )
exists ( C3F.Confirmed([Condition: "valueset1"])
union C3F.Confirmed([Condition: "valueset2"])
)
"condition1" and "condition2"
Count(C3F.ObservationLookBack([Observation: "[code]"], 1 year)) < 3
AgeInYears() >= 6 and AgeInYears() < 13
[Encounter: "[valueset]"] E
where ( E.serviceType ~ "[specialty code]" )
C3F.ProcedureLookBack([Procedure: "[code]"], 6 months)
define "Recommendation":
if "condition1" then if "condition2" then '說明A'
else '說明B'
else if "condition3" then '說明C'
else null
For rules with multiple適應症 with different頻率:
define "subpopulation 1":
if "InPopulation" is not true then null
else [specific condition for subpop1]
define "subpopulation 2":
if "InPopulation" is not true then null
else [specific condition for subpop2]
define "Recommendation":
if "subpopulation 1" then '健保給付[點數]點,[規範1]'
else if "subpopulation 2" then '健保給付[點數]點,[規範2]'
else null
When rules mention "脊髓損傷或病變", include ALL three categories:
| Category | ICD-10-CM | Examples |
|---|---|---|
| Trauma | S14., S24., S34., S44. | Spinal cord injury |
| Disease | G95., G82. | Spinal cord disorders, paraplegia |
| Degeneration | M43.3, M47.1, M50.0, M51.0 | Spondylolisthesis, myelopathy, disc disorders |
Critical: "病變" includes both functional disease (G-codes) AND degenerative structural changes (M-codes).
For "腦中風後遺症" or "中風導致之肢體偏癱":
| Scope | ICD-10-CM | Purpose |
|---|---|---|
| General stroke | I69.* | All stroke sequelae |
| Hemiplegia types | I69.33-I69.35 | Dominant/non-dominant/unspecified side |
| Specific sequelae | I69.3, I69.33, I69.34, I69.35, I69.39 | Cerebral infarction aftereffects |
Pattern: Use I69.* for broad inclusion, add specific I69.3X codes when hemiplegia is explicitly mentioned.
For "周邊神經病變":
For laboratory or measurement constraints:
define "低密度脂蛋白膽固醇異常":
exists (
[Observation: "LOINC code 18262-6"] O
where O.value as Quantity > 100 'mg/dL'
and O.status = 'final'
)
For rules specifying age ranges with measurement timing:
define "符合年齡條件":
( AgeInYears() >= 10 and AgeInYears() <= 17 )
or ( AgeInYears() >= 6 and AgeInYears() < 10 and "已測量過基線值" )
'...' for all strings// sparingly, written in Chinese when explaining業務邏輯define "氣喘":, define "懷孕糖尿病人、妊娠糖尿病人":)"variable" not "variable" = truePattern: [數字]{2,5}[字母] (e.g., 08111B, 12216C, 69041B, 83102K)
適應症 (Indications):
禁忌症 (Contraindications):
支付規範 (Payment Rules):
點數 (Points):
專科限制 (Specialty):
From text patterns like:
CRITICAL: Always filter by the specific NHI procedure code using TWMedicalServicePayment codesystem. NEVER use bare [Procedure] (this would match ALL procedures, not the one being regulated).
codesystem "TWMedicalServicePayment": 'https://twcore.mohw.gov.tw/ig/twcore/CodeSystem/medical-service-payment-tw'
code "[代號] 健保給付代碼": '[代號]' from "TWMedicalServicePayment" display '[項目名稱]'
// ✅ Correct: counts only THIS specific procedure
define "頻率符合":
Count(C3F.ProcedureLookBack([Procedure: "[代號] 健保給付代碼"], 1 year)) < N
// ❌ WRONG: counts ALL procedures in the patient's history
define "頻率符合":
Count(C3F.ProcedureLookBack([Procedure], 1 year)) < N
| Rule Text | CQL Encoding |
|---|---|
| "一年限申報三次" | Count(ObservationLookBack([Observation: ...], 1 year)) < 3 |
| "每四年限申報一次" | Count(ObservationLookBack([Observation: ...], 4 years)) < 1 |
| "每人以申報一次為原則" | Track across patient lifetime |
| "每次就診...每次治療應間隔至少一週" | Date diff checking |
| "一年限申報三次" | Count(C3F.ProcedureLookBack([Procedure: "[代號] 健保給付代碼"], 1 year)) < 3 |
| "每四年限申報一次" | Count(C3F.ProcedureLookBack([Procedure: "[代號] 健保給付代碼"], 4 years)) < 1 |
| "每人以申報一次為原則" | not exists(C3F.ProcedureLookBack([Procedure: "[代號] 健保給付代碼"], 100 years)) |
| "每週最多N次" | Count(C3F.ProcedureLookBack([Procedure: "[代號] 健保給付代碼"], 7 days)) < N |
| "每月限一次" | Count(C3F.ProcedureLookBack([Procedure: "[代號] 健保給付代碼"], 30 days)) < 1 |
When the rule says "限住院期間申報一次" or "同一就診申報一次", use Encounter reference instead of a time window. A time window (e.g., "1 year") would incorrectly block re-admission for a new event.
// 取得目前就醫 Encounter(最近一次進行中或完成的)
define "目前住院Encounter":
Last(
[Encounter] E
where E.status = 'in-progress' or E.status = 'finished'
sort by start of period
)
// 本次住院期間尚未申報過本項目
define "本次住院未申報過":
"目前住院Encounter" is not null
and not exists(
[Procedure: "[代號] 健保給付代碼"] P
where P.encounter.reference = 'Encounter/' + "目前住院Encounter".id
)
When rule says "同一治療期間至多N次", the ideal boundary is EpisodeOfCare. As a pragmatic approximation, use Encounter-reference for the per-visit part, and ProcedureLookBack with a reasonable lookback window for the total-count part:
define "本次就診未申報":
"目前住院Encounter" is not null
and not exists(
[Procedure: "[代號] 健保給付代碼"] P
where P.encounter.reference = 'Encounter/' + "目前住院Encounter".id
)
// 治療期間總次數:以 1 年作為最長治療期間的保守估計
define "治療期間總次數符合":
Count(C3F.ProcedureLookBack([Procedure: "[代號] 健保給付代碼"], 1 year)) < N
Note: The ideal approach for "同一治療期間" is to use
EpisodeOfCare, but this requires the FHIR server to populateEpisodeOfCareresources. The time-window approximation is the practical fallback.
Critical: Distinguish between pre-authorization criteria (事前資格檢查) and post-payment rules (事後支付規則).
These MUST be encoded as executable logic in MeetsInclusionCriteria:
Pattern: Contraindication ("禁忌症:...")
When a rule lists contraindications, create a separate contraindication ValueSet and check for absence:
// 1. Declare a separate contraindication valueset
valueset "[代號] 禁忌症": 'https://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.[n]'
// 2. Define the contraindication check
define "有禁忌症":
exists ( C3F.Confirmed([Condition: "[代號] 禁忌症"]) )
// 3. Incorporate into MeetsInclusionCriteria
define "MeetsInclusionCriteria":
"Has Indication" and not "有禁忌症"
// 4. Recommendation branches (always check indication first → then contraindication)
define "Recommendation":
if not "Has Indication" then null
else if "有禁忌症" then '不得申報。病患符合禁忌症:[詳細原因]。'
else '健保給付。...'
Important: The contraindication JSON file uses the same structure as the indication ValueSet. Give it a distinct OID number (e.g., indication = .9, contraindication = .200).
Pattern: Specialist Restriction ("限...專科醫師執行")
codesystem "SCT": 'http://snomed.info/sct'
code "Specialist code": '[SNOMED-code]' from "SCT" display '[specialist-type]'
define "performer_id":
Last(Split(First("RecentProcedure".performer).actor.reference, '/'))
define "Performer_ref":
[Practitioner] P where P.id = "performer_id"
define "Qualified_Practitioner":
exists ( "Performer_ref".qualification q
where q.code ~ "Specialist code" )
define "MeetsInclusionCriteria":
"[適應症]" and "Qualified_Practitioner"
Examples:
Pattern: Procedure Type Restriction
When rule specifies specific surgical procedures:
codesystem "ICD-10-PCS": 'http://www.cms.gov/Medicare/Coding/ICD10'
code "Procedure1 code": '[code]' from "ICD-10-PCS" display '[description]'
code "Procedure2 code": '[code]' from "ICD-10-PCS" display '[description]'
define "ApplicableProcedure":
C3F.MostRecentProcedure ( [Procedure: "Procedure1 code"]
union [Procedure: "Procedure2 code"]
)
define "MeetsInclusionCriteria":
"[適應症]" and exists("ApplicableProcedure")
Pattern: Encounter Specialty Check
For rules limiting to specific clinical departments:
code "Department specialty code": '[SNOMED-code]' from "SCT" display '[specialty]'
define "SpecialtyEncounter":
[Encounter] E where E.serviceType ~ "Department specialty code"
define "encounter check":
exists("SpecialtyEncounter")
define "Recommendation":
if "InPopulation" is not true then null
else if "encounter check" then '給付'
else '非[科別]申報,不予給付'
These should appear in Recommendation string but NOT in MeetsInclusionCriteria:
Examples:
Pattern:
define "Recommendation":
if "InPopulation" then '健保給付[點數]點,[描述],一般材料費得另加計百分之五十'
else null
| Phrase Pattern | Type | Action |
|---|---|---|
| 限...專科醫師執行 | Pre-auth | ✅ Convert to Practitioner.qualification check |
| 限...科別申報 | Pre-auth | ✅ Convert to Encounter.serviceType check |
| 限特定手術類型 | Pre-auth | ✅ Convert to Procedure code check |
| 材料費加計...% | Post-payment | ❌ Text only in Recommendation |
| 應事先申請 | Administrative | ❌ Text only in Recommendation |
| 需檢附報告 | Administrative | ❌ Text only in Recommendation |
Critical Rule: If the regulation affects whether payment is approved, it's pre-authorization → convert to CQL. If it only affects how much or when to pay, it's post-payment → text only.
Based on GT examples, use this complete structure:
{
"resourceType": "ValueSet",
"id": "2.16.840.1.113762.1.4.1287.[number]",
"meta": {
"versionId": "1",
"lastUpdated": "[timestamp]",
"profile": [
"http://hl7.org/fhir/StructureDefinition/shareablevalueset",
"http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/computable-valueset-cqfm",
"http://hl7.org/fhir/us/cqfmeasures/StructureDefinition/publishable-valueset-cqfm"
]
},
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/valueset-author",
"valueContactDetail": {
"name": "Industrial Technology Research Institute Author"
}
},
{
"url": "http://hl7.org/fhir/StructureDefinition/resource-lastReviewDate",
"valueDate": "[YYYY-MM-DD]"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/valueset-effectiveDate",
"valueDate": "[YYYY-MM-DD]"
}
],
"url": "http://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.[number]",
"identifier": [
{
"system": "urn:ietf:rfc:3986",
"value": "urn:oid:2.16.840.1.113762.1.4.1287.[number]"
}
],
"version": "[YYYYMMDD]",
"name": "[EnglishCamelCaseName]",
"title": "[English title or Chinese title]",
"status": "active",
"date": "[timestamp]",
"publisher": "Industrial Technology Research Institute Steward",
"description": "[規則編號,可多個用逗號分隔如 63007B, 63008B]",
"jurisdiction": [
{
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/data-absent-reason",
"valueCode": "unknown"
}
]
}
],
"purpose": "(Clinical Focus: ...),(Data Element Scope: ...),(Inclusion Criteria: ...),(Exclusion Criteria: ...)",
"compose": {
"include": [
{
"system": "[CodeSystem URL]",
"version": "2025",
"filter": [
{
"property": "concept",
"op": "[operator]",
"value": "[code]"
}
]
}
]
}
}
Pattern: 2.16.840.1.113762.1.4.1287.[sequential-number]
The ID is the full OID, not a custom name. File name matches the ID:
2.16.840.1.113762.1.4.1287.6.json"2.16.840.1.113762.1.4.1287.6"Critical: Use http:// (NOT https://) in url field:
"url": "http://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.[number]"
In CQL: Use https:// in valueset declarations:
valueset "name": 'https://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.[number]'
Use filter instead of explicit concept array:
Common operators:
"op": "descendent-of" - Include code and all descendants (most common)"op": "is-a" - Include code and descendants"op": "=" - Exact match single code"op": "in" - Multiple codes (comma-separated in value)Examples:
// All J45.* asthma codes
{"property": "concept", "op": "descendent-of", "value": "J45"}
// Specific codes
{"property": "concept", "op": "=", "value": "C79.81"}
// Multiple specific codes
{"property": "concept", "op": "in", "value": "E10.22,E13.22,E08.22"}
Choose operator based on code specificity and clinical intent:
| Operator | Use When | ICD-10 Code Pattern | Example |
|---|---|---|---|
= | Exact leaf code needed | 6-7 digits (e.g., G62.9, I69.398) | Single specific diagnosis |
is-a | Mid-level category | 4-5 digits (e.g., J45.5, E11.4) | Specific subtype with few children |
descendent-of | Broad family inclusion | 3-4 digits (e.g., J45, I69, G62) | All variants needed |
in | Multiple unrelated codes | Mixed | Enumerate disparate codes |
Code Granularity Guidelines:
Real Examples from GT:
// G62.9 (7 digits, leaf code) - use exact match
{"property": "concept", "op": "=", "value": "G62.9"}
// E11.4 (5 digits, mid-level) - use is-a
{"property": "concept", "op": "is-a", "value": "E11.4"}
// I69 (3 digits, broad family) - use descendent-of
{"property": "concept", "op": "descendent-of", "value": "I69"}
// Multiple unrelated codes - use in
{"property": "concept", "op": "in", "value": "M43.3,M47.1,M50.0,M51.0"}
Decision Logic:
=is-adescendent-ofinStandard 4-part structure (observed in all GT examples):
(Clinical Focus: [臨床焦點]),(Data Element Scope: [資料元素範圍]),(Inclusion Criteria: [納入條件]),(Exclusion Criteria: [排除條件,若無則寫 No])
Critical: ValueSet.url in JSON must exactly match the valueset declaration URL in CQL (except http vs https).
http://hl7.org/fhir/sid/icd-10-cm"2025"http://www.cms.gov/Medicare/Coding/ICD10 or https://twcore.mohw.gov.tw/ig/twcore/CodeSystem/medical-service-payment-twhttp://loinc.orghttp://snomed.info/sctFrom GT examples, one ValueSet may support multiple rules:
"description": "63007B, 63008B" - Modified radical mastectomy (single/bilateral)"description": "13030B,13031B,13032B" - Different H. pylori testsWhen rules share indications, use the same ValueSet ID.
Ask user for:
Extract and identify:
For each distinct code set identified:
2.16.840.1.113762.1.4.1287.[number].jsonhttp:// (NOT https)descendent-of for code families (e.g., J45 for all asthma)in for multiple specific codes= for single specific codesImportant:
2.16.840.1.113762.1.4.1287.6.json)http://https://Following exact structure:
Checklist:
Deliver to user:
[規則編號].cql (plain text)2.16.840.1.113762.1.4.1287.[number].json files.github/skills/nhi-cql-generator/assets/ to output directory:
FHIRHelpers.cqlCDSConnectCommonsForFHIRv401.cql| CQL ValueSet Declaration | ValueSet File | URL (CQL uses https, JSON uses http) |
|--------------------------|---------------|---------------------------------------|
| [中文名稱] valueset | 2.16.840.1.113762.1.4.1287.[N].json | https://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.[N] |
Critical: The CQL file will NOT execute without the dependency libraries in the same directory. Always include them in the output.
Input:
Output:
08111B.cql - With Von Willebrand disease codes2.16.840.1.113762.1.4.1287.1.json - ICD-10-CM codes with filter for VWD codesInput:
Output:
17022B.cql - With age check, frequency check, and pediatric specialty check2.16.840.1.113762.1.4.1287.6.json - Uses descendent-of filter for J45 (asthma)Input:
Output:
12216C.cql - With subpopulation 1 and 2, different frequency rules2.16.840.1.113762.1.4.1287.[N].json - HIV codes with appropriate filters2.16.840.1.113762.1.4.1287.[N+1].json - Dialysis dependency codesActivate when user mentions:
In ValueSet JSON (url field):
"url": "http://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.6"
Uses http:// (no 's')
In CQL (valueset declaration):
valueset "name": 'https://example.org/fhir/ValueSet/2.16.840.1.113762.1.4.1287.6'
Uses https:// (with 's')
This is intentional and follows GT examples exactly.
2.16.840.1.113762.1.4.1287.6.json17022B-indications.json