正文
获取原文件SKILL.md
v0.2.1 发布合同(优先于历史版本说明)
本模块既有运行逻辑保持;本次与其他模块统一发布0.2.1,并执行原有回归。不得仅凭版本号推断新增临床能力。
详见 references/repair-v0.2.1.md。完整替换D001–D014并重新生成中间产物,不混用历史伪ID、清单或staging编号。测试通过不表示临床生产批准。
v0.2.0 修复合同(优先于旧版说明)
本地索引与上游文件做 SHA-256 绑定;独立重查有效期、源代码、Maps to/Maps to value 的完整集合和一对多基数。外部导入先检查逐请求授权收据/查询摘要/允许来源,再验证;查询含标识符则拒绝。无官方词表只能明确接受未映射用于 staging,不能宣称标准映射已验证。
具体运行界限见 references/repair-v0.2.md;任何自测通过都不等于临床生产批准。
Mission
D012 performs two distinct stages:
Clinical concept
↓
Terminology code
↓
OMOP Source Concept
↓ CONCEPT_RELATIONSHIP: Maps to
OMOP Standard Concept(s)
These stages must never be collapsed.
A LOINC, RxNorm, SNOMED CT, ICD-10-CM or local code is not automatically an OMOP concept_id.
Required upstream
Use only a finalized D011 manifest with:
overall_status = ready_for_terminology_mapping
D011 v0.1.1 or later is required because timeline events must carry:
conceptvaluedetailscoding
D012 never reads pre-D003 patient sources.
Core rules
- Never invent a terminology code.
- Never invent an OMOP
concept_id. - Never infer
concept_idfrom the numeric appearance of a code. - Verify every OMOP concept against a local vocabulary index.
- Map non-standard source concepts through
CONCEPT_RELATIONSHIP.relationship_id = "Maps to". - Preserve valid one-to-many
Maps torelationships. - Preserve
Maps to valueseparately. - The mapped Standard Concept's
domain_idcontrols downstream OMOP domain routing; do not assume it from the source fact type. - Unmapped concepts remain unresolved; they are not forced to concept_id 0 until D013 applies an explicit OMOP ETL policy.
- External terminology lookup is concept-only and explicitly authorized; bundled scripts never perform network calls.
Inputs
Required:
- D011
patient_timeline_manifest.json - D011
timeline_events.jsonl - a local OMOP vocabulary index built from user-supplied OHDSI vocabulary files
Optional:
- a local terminology alias bundle generated from licensed/official terminology sources
- externally resolved terminology results, imported after explicit authorization
Local OMOP vocabulary
Build an index from a user-supplied OHDSI vocabulary directory:
python "$SKILL_DIR/scripts/build_omop_vocab_index.py" \
--vocab-dir /path/to/athena-vocabulary \
--output /secure/path/omop_vocab_index.sqlite
Required files:
CONCEPT.csv
CONCEPT_RELATIONSHIP.csv
Optional:
VOCABULARY.csv
The index stores only vocabulary content supplied by the user. D012 does not distribute SNOMED CT, CPT4, or other restricted vocabulary content.
Local terminology aliases
An optional terminology_aliases.jsonl can resolve de-identified normalized names to verified terminology codes.
Example:
{
"alias": "example analyte",
"fact_type": "lab",
"system": "http://loinc.org",
"code": "XXXX-X",
"display": "Verified official display",
"version": "source-version",
"source": "local_official_export"
}
Do not create this bundle from model memory.
Workflow
1. Build the vocabulary index
python "$SKILL_DIR/scripts/build_omop_vocab_index.py" \
--vocab-dir /path/to/vocab \
--output ./secure/omop_vocab_index.sqlite
2. Prepare mapping
python "$SKILL_DIR/scripts/prepare_mapping.py" \
--d011-manifest /path/to/d011/patient_timeline_manifest.json \
--omop-index ./secure/omop_vocab_index.sqlite \
--aliases /optional/path/terminology_aliases.jsonl \
--output-root ./runs/haonan-d012
Outputs include:
mapping_requests.jsonlterminology_candidates.jsonlexternal_lookup_queue.jsonlagent_mapping_decisions.jsonlmapping_review_queue.csvterminology_omop_mapping_manifest.json
3. Resolve only unresolved terminology
Local exact verified candidates may be auto-selected when unique.
Ambiguous local candidates require a text-free decision:
{
"mapping_request_id": "mr_x",
"decision": "select_candidate",
"candidate_id": "tc_x",
"reason_codes": ["verified_local_exact_match"]
}
A user may explicitly authorize external terminology lookup for selected requests.
The external request contains only:
- request ID
- fact type
- de-identified concept query
- preferred terminology systems
It contains no patient ID, encounter ID, source document, date, or clinical narrative.
The bundled D012 scripts never send the request.
4. Import authorized external results
Write or obtain external_lookup_results.jsonl, then validate/import:
python "$SKILL_DIR/scripts/ingest_external_results.py" \
--run-dir /path/to/d012/pkg \
--results /path/to/external_lookup_results.jsonl
Every external result must identify its terminology source and version when available.
5. Finalize
python "$SKILL_DIR/scripts/finalize_mapping.py" \
--run-dir /path/to/d012/pkg
Outputs:
coded_timeline_events.jsonlmapping_ledger.jsonlomop_mapping_results.jsonlunresolved_mappings.jsonl
6. Validate
python "$SKILL_DIR/scripts/validate_mapping.py" \
--manifest /path/to/d012/pkg/terminology_omop_mapping_manifest.json
Mapping result semantics
Each selected terminology code is resolved to an OMOP source concept by:
(vocabulary_id, concept_code)
The source concept may be:
- Standard Concept (
standard_concept = S) → valid as its own standard mapping - non-standard → follow active
Maps torelationship(s) - classification/unsupported/unmapped → unresolved unless valid mapping exists
D012 preserves:
source_concept_id
standard_concept_ids[]
standard_domain_ids[]
maps_to_value_concept_ids[]
mapping_cardinality
vocabulary_snapshot
One-to-many is valid
If one source concept maps to two valid Standard Concepts, D012 keeps both:
mapping_cardinality = one_to_many
It does not arbitrarily pick one.
D013 decides how many OMOP rows are required by the target domain semantics.
External egress gate
Default:
network_egress_gate = BLOCKED
D012 may prepare a minimal queue, but no network call occurs.
Authorization applies per request, not per package.
Never send:
- patient identifiers
- encounter identifiers
- dates
- file names
- source prose
- provenance
- surrounding note context
Only the minimum de-identified clinical concept needed for terminology lookup may leave the local boundary.
Completion gate
ready_for_fhir_omop_transform requires:
- every mapping-required timeline event has a verified terminology result or an explicitly accepted unresolved status;
- every nonzero OMOP concept ID exists in the local vocabulary index;
- every source-to-standard mapping is either Standard-self or backed by active
Maps to; - one-to-many mappings are preserved;
Maps to valueis preserved separately;- no unresolved ambiguity is silently auto-selected;
- the vocabulary snapshot hash/version is recorded;
- no bundled script performed network access.
Safety
- zero automatic network;
- zero automatic installs;
- zero model downloads;
- no raw PHI;
- no credential collection;
- no vocabulary redistribution;
- no execution of input code;
- no terminology inference from model memory;
- no guessed OMOP concept IDs.
Handoff
D012 hands verified coded timeline events and mapping ledger to:
haonan-d013-fhir-omop-transformer