sourcelock 0.1.0__py3-none-any.whl
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.
- hc_source/__init__.py +5 -0
- hc_source/adapters/__init__.py +500 -0
- hc_source/adapters/_demo.py +258 -0
- hc_source/adapters/_demo_fixture.json +25 -0
- hc_source/adapters/_leie_sample.csv +15 -0
- hc_source/adapters/codes.py +1232 -0
- hc_source/adapters/coverage.py +1569 -0
- hc_source/adapters/hcc.py +1450 -0
- hc_source/adapters/leie.py +1310 -0
- hc_source/adapters/provider.py +1159 -0
- hc_source/cache.py +664 -0
- hc_source/cli.py +959 -0
- hc_source/cli_manifest.py +207 -0
- hc_source/data/codes/hcpcs_2026q3.csv.gz +0 -0
- hc_source/data/codes/icd10cm_fy2026.csv.gz +0 -0
- hc_source/data/codes/icd10cm_fy2027.csv.gz +0 -0
- hc_source/data/codes/manifest.json +75 -0
- hc_source/data/codes/regenerate.py +291 -0
- hc_source/data/hcc/hcc_data.json.zlib +0 -0
- hc_source/doctor.py +472 -0
- hc_source/guard.py +877 -0
- hc_source/http.py +541 -0
- hc_source/interfaces.py +395 -0
- hc_source/lockfile.py +236 -0
- hc_source/manifest.py +422 -0
- hc_source/mcp_server.py +203 -0
- hc_source/npi.py +50 -0
- hc_source/receipts.py +74 -0
- hc_source/schemas.py +339 -0
- sourcelock-0.1.0.dist-info/METADATA +272 -0
- sourcelock-0.1.0.dist-info/RECORD +34 -0
- sourcelock-0.1.0.dist-info/WHEEL +4 -0
- sourcelock-0.1.0.dist-info/entry_points.txt +2 -0
- sourcelock-0.1.0.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
"""Reference adapter.
|
|
2
|
+
|
|
3
|
+
This is a complete, working adapter over a static JSON fixture shipped inside
|
|
4
|
+
the package. It exists to prove the interface end to end offline, and to be the
|
|
5
|
+
thing you copy when writing a real route. Read it top to bottom before writing
|
|
6
|
+
``hc_source/adapters/<route>.py``; see ADAPTER_GUIDE.md for the rules.
|
|
7
|
+
|
|
8
|
+
The only thing unusual about it is its transport: it reads a packaged file via
|
|
9
|
+
a ``file://`` URL instead of an HTTPS endpoint, so ``hc-source doctor`` is green
|
|
10
|
+
on a laptop with no network. Everything else -- contract, canaries, typed
|
|
11
|
+
params, guard, receipts -- is exactly what a real adapter does.
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
from __future__ import annotations
|
|
15
|
+
|
|
16
|
+
import hashlib
|
|
17
|
+
import json
|
|
18
|
+
import os
|
|
19
|
+
from datetime import date
|
|
20
|
+
from pathlib import Path
|
|
21
|
+
from typing import Any
|
|
22
|
+
|
|
23
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
24
|
+
|
|
25
|
+
from ..http import FetchResult, fetch_json
|
|
26
|
+
from ..interfaces import Canary, CanaryObservation, SourceAdapter, ToolResult, ToolSpec
|
|
27
|
+
from ..receipts import build_receipt
|
|
28
|
+
from ..schemas import SourceContract
|
|
29
|
+
|
|
30
|
+
SOURCE_ID = "demo"
|
|
31
|
+
TRANSFORM_VERSION = "1"
|
|
32
|
+
|
|
33
|
+
#: Environment override, used by the test suite to simulate upstream drift.
|
|
34
|
+
FIXTURE_ENV_VAR = "HC_SOURCE_DEMO_FIXTURE"
|
|
35
|
+
|
|
36
|
+
CONTRACT = SourceContract(
|
|
37
|
+
source_id=SOURCE_ID,
|
|
38
|
+
authority_url="file://<packaged>/hc_source/adapters/_demo_fixture.json",
|
|
39
|
+
fallback_url=None,
|
|
40
|
+
license_notes="Synthetic reference data. Public domain; not derived from any real source.",
|
|
41
|
+
cadence="never (static fixture)",
|
|
42
|
+
effective_date_semantics=(
|
|
43
|
+
"effective_from is the release publication date; effective_to is null while the "
|
|
44
|
+
"release is current."
|
|
45
|
+
),
|
|
46
|
+
invariants=[
|
|
47
|
+
"release_id is a year.month string that only moves forward",
|
|
48
|
+
"every record carries code, short_description, and effective_from",
|
|
49
|
+
"codes match ^DEMO[0-9]{3}$",
|
|
50
|
+
],
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
NON_CLAIMS = [
|
|
54
|
+
"DOES_NOT_PROVE_COVERAGE: presence of a code in this release says nothing about whether "
|
|
55
|
+
"any payer covers or pays for it.",
|
|
56
|
+
"DOES_NOT_PROVE_CURRENCY: this is the pinned release, which may lag the upstream publisher.",
|
|
57
|
+
]
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
def packaged_fixture_path() -> Path:
|
|
61
|
+
return Path(__file__).with_name("_demo_fixture.json")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def fixture_path() -> Path:
|
|
65
|
+
override = os.environ.get(FIXTURE_ENV_VAR)
|
|
66
|
+
return Path(override) if override else packaged_fixture_path()
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _load() -> tuple[FetchResult, dict[str, Any]]:
|
|
70
|
+
"""Read the release through the shared transport, so we get a hash for free."""
|
|
71
|
+
return fetch_json(fixture_path().as_uri())
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def _schema_hash(payload: dict[str, Any]) -> str:
|
|
75
|
+
"""Hash the declared shape only -- not the data -- so drift and schema change differ."""
|
|
76
|
+
shape = json.dumps(payload.get("schema", []), sort_keys=True, separators=(",", ":"))
|
|
77
|
+
return hashlib.sha256(shape.encode("utf-8")).hexdigest()
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def _as_date(value: Any) -> date | None:
|
|
81
|
+
return date.fromisoformat(value) if isinstance(value, str) else None
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
# --------------------------------------------------------------------------
|
|
85
|
+
# Typed public parameters
|
|
86
|
+
# --------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
class NoParams(BaseModel):
|
|
90
|
+
model_config = ConfigDict(extra="forbid")
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
class LookupCodeParams(BaseModel):
|
|
94
|
+
model_config = ConfigDict(extra="forbid")
|
|
95
|
+
|
|
96
|
+
code: str = Field(pattern=r"^DEMO[0-9]{3}$", description="Demo code, e.g. DEMO001.")
|
|
97
|
+
include_retired: bool = Field(
|
|
98
|
+
default=False, description="Return the record even if the release marks it retired."
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
# --------------------------------------------------------------------------
|
|
103
|
+
# Handlers
|
|
104
|
+
# --------------------------------------------------------------------------
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def _get_release(_: NoParams) -> ToolResult:
|
|
108
|
+
result, payload = _load()
|
|
109
|
+
data = {
|
|
110
|
+
"release_id": payload["release_id"],
|
|
111
|
+
"effective_from": payload.get("effective_from"),
|
|
112
|
+
"effective_to": payload.get("effective_to"),
|
|
113
|
+
"record_count": len(payload.get("records", [])),
|
|
114
|
+
"schema": payload.get("schema", []),
|
|
115
|
+
}
|
|
116
|
+
return ToolResult(
|
|
117
|
+
data=data,
|
|
118
|
+
receipt=build_receipt(
|
|
119
|
+
contract=CONTRACT,
|
|
120
|
+
route="demo.get_release",
|
|
121
|
+
fetch=result,
|
|
122
|
+
source_version=payload["release_id"],
|
|
123
|
+
transform_version=TRANSFORM_VERSION,
|
|
124
|
+
effective_from=_as_date(payload.get("effective_from")),
|
|
125
|
+
effective_to=_as_date(payload.get("effective_to")),
|
|
126
|
+
non_claims=NON_CLAIMS,
|
|
127
|
+
),
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
def _lookup_code(params: LookupCodeParams) -> ToolResult:
|
|
132
|
+
result, payload = _load()
|
|
133
|
+
warnings: list[str] = []
|
|
134
|
+
|
|
135
|
+
match = next((r for r in payload.get("records", []) if r.get("code") == params.code), None)
|
|
136
|
+
if match is not None and match.get("retired") and not params.include_retired:
|
|
137
|
+
warnings.append(
|
|
138
|
+
f"The requested code is retired in release {payload['release_id']}; "
|
|
139
|
+
"pass include_retired=true to see it."
|
|
140
|
+
)
|
|
141
|
+
match = None
|
|
142
|
+
elif match is None:
|
|
143
|
+
warnings.append(
|
|
144
|
+
f"The requested code was not found in release {payload['release_id']}."
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return ToolResult(
|
|
148
|
+
data=match,
|
|
149
|
+
receipt=build_receipt(
|
|
150
|
+
contract=CONTRACT,
|
|
151
|
+
route="demo.lookup_code",
|
|
152
|
+
fetch=result,
|
|
153
|
+
source_version=payload["release_id"],
|
|
154
|
+
transform_version=TRANSFORM_VERSION,
|
|
155
|
+
effective_from=_as_date(payload.get("effective_from")),
|
|
156
|
+
effective_to=_as_date(payload.get("effective_to")),
|
|
157
|
+
warnings=warnings,
|
|
158
|
+
non_claims=NON_CLAIMS,
|
|
159
|
+
),
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
# --------------------------------------------------------------------------
|
|
164
|
+
# Canaries
|
|
165
|
+
# --------------------------------------------------------------------------
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def _observe_release() -> CanaryObservation:
|
|
169
|
+
result, payload = _load()
|
|
170
|
+
return CanaryObservation(
|
|
171
|
+
value=str(payload["release_id"]),
|
|
172
|
+
schema_hash=_schema_hash(payload),
|
|
173
|
+
upstream_status=result.status,
|
|
174
|
+
note="release id and declared column set",
|
|
175
|
+
)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def _observe_record_count() -> CanaryObservation:
|
|
179
|
+
_, payload = _load()
|
|
180
|
+
return CanaryObservation(
|
|
181
|
+
value=str(len(payload.get("records", []))),
|
|
182
|
+
note="row count of the pinned release",
|
|
183
|
+
)
|
|
184
|
+
|
|
185
|
+
|
|
186
|
+
def _release_remediation(status, observed, expected) -> str:
|
|
187
|
+
from ..schemas import CanaryStatus
|
|
188
|
+
|
|
189
|
+
if status is CanaryStatus.SCHEMA_CHANGED:
|
|
190
|
+
return (
|
|
191
|
+
"The demo release kept its id but changed its column set. Review the new columns, "
|
|
192
|
+
"bump TRANSFORM_VERSION in hc_source/adapters/_demo.py if the mapping changed, then "
|
|
193
|
+
"re-pin with `hc-source lock init`."
|
|
194
|
+
)
|
|
195
|
+
if status is CanaryStatus.UNREACHABLE:
|
|
196
|
+
return (
|
|
197
|
+
"The demo fixture could not be read. Check HC_SOURCE_DEMO_FIXTURE if it is set, "
|
|
198
|
+
"otherwise reinstall the package; then run `hc-source doctor` again."
|
|
199
|
+
)
|
|
200
|
+
return (
|
|
201
|
+
f"The demo source published release {observed}; source-lock.json pins {expected}. "
|
|
202
|
+
"Review the diff, then re-pin with `hc-source lock init`."
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
|
|
206
|
+
class DemoAdapter(SourceAdapter):
|
|
207
|
+
source_id = SOURCE_ID
|
|
208
|
+
contract = CONTRACT
|
|
209
|
+
|
|
210
|
+
# Every canary here reads vendored data, so there is no network to be flaky
|
|
211
|
+
# and a retry would just repeat a deterministic answer.
|
|
212
|
+
canary_retries = 0
|
|
213
|
+
|
|
214
|
+
def canaries(self) -> list[Canary]:
|
|
215
|
+
return [
|
|
216
|
+
Canary(
|
|
217
|
+
canary_id="demo.release_id",
|
|
218
|
+
source_id=SOURCE_ID,
|
|
219
|
+
description="Release id and declared column set of the demo source.",
|
|
220
|
+
observe=_observe_release,
|
|
221
|
+
remediation=(
|
|
222
|
+
"The demo source moved. Review the change, then re-pin with "
|
|
223
|
+
"`hc-source lock init`."
|
|
224
|
+
),
|
|
225
|
+
remediation_for=_release_remediation,
|
|
226
|
+
),
|
|
227
|
+
Canary(
|
|
228
|
+
canary_id="demo.record_count",
|
|
229
|
+
source_id=SOURCE_ID,
|
|
230
|
+
description="Number of records in the demo release.",
|
|
231
|
+
observe=_observe_record_count,
|
|
232
|
+
remediation=(
|
|
233
|
+
"The demo release gained or lost rows. Confirm the change is real upstream, "
|
|
234
|
+
"then re-pin with `hc-source lock init`."
|
|
235
|
+
),
|
|
236
|
+
),
|
|
237
|
+
]
|
|
238
|
+
|
|
239
|
+
def tools(self) -> list[ToolSpec]:
|
|
240
|
+
return [
|
|
241
|
+
ToolSpec(
|
|
242
|
+
name="demo.get_release",
|
|
243
|
+
description="Return the pinned demo release: id, effective dates, and column set.",
|
|
244
|
+
params_model=NoParams,
|
|
245
|
+
handler=_get_release,
|
|
246
|
+
tags=("metadata",),
|
|
247
|
+
),
|
|
248
|
+
ToolSpec(
|
|
249
|
+
name="demo.lookup_code",
|
|
250
|
+
description="Look up one demo code in the pinned release.",
|
|
251
|
+
params_model=LookupCodeParams,
|
|
252
|
+
handler=_lookup_code,
|
|
253
|
+
tags=("lookup",),
|
|
254
|
+
),
|
|
255
|
+
]
|
|
256
|
+
|
|
257
|
+
|
|
258
|
+
ADAPTER = DemoAdapter()
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"source": "SourceLock demo source",
|
|
3
|
+
"release_id": "2026.07",
|
|
4
|
+
"effective_from": "2026-07-01",
|
|
5
|
+
"effective_to": null,
|
|
6
|
+
"schema": ["code", "short_description", "effective_from"],
|
|
7
|
+
"records": [
|
|
8
|
+
{
|
|
9
|
+
"code": "DEMO001",
|
|
10
|
+
"short_description": "Reference item one",
|
|
11
|
+
"effective_from": "2026-07-01"
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
"code": "DEMO002",
|
|
15
|
+
"short_description": "Reference item two",
|
|
16
|
+
"effective_from": "2026-07-01"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"code": "DEMO003",
|
|
20
|
+
"short_description": "Reference item three, retired",
|
|
21
|
+
"effective_from": "2026-01-01",
|
|
22
|
+
"retired": true
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
LASTNAME,FIRSTNAME,MIDNAME,BUSNAME,GENERAL,SPECIALTY,UPIN,NPI,DOB,ADDRESS,CITY,STATE,ZIP,EXCLTYPE,EXCLDATE,REINDATE,WAIVERDATE,WVRSTATE
|
|
2
|
+
"","","","#1 MARKETING SERVICE, INC","OTHER BUSINESS","SOBER HOME","","0000000000","","239 BRIGHTON BEACH AVENUE","BROOKLYN","NY","11235","1128a1","20200319","00000000","00000000",""
|
|
3
|
+
"","","","101 FIRST CARE PHARMACY INC","OTHER BUSINESS","PHARMACY","","1972902351","","C/O 609 W 191ST STREET, APT D","NEW YORK","NY","10040","1128b8","20220320","00000000","00000000",""
|
|
4
|
+
"ABAD-SANTOS","CRISELDA","CALAYAN","","PHYSICIAN (MD, DO)","PSYCHIATRY","","1760461826","00000000","8506 N ADIR DR","WEST HILLS","CA","91304","1128b4","20250120","00000000","00000000",""
|
|
5
|
+
"ABADI","JAMSHEED","S","","PHYSICIAN (MD, DO)","INTERNAL MEDICINE","C04537","1477537496","00000000","89 WEEKS ROAD","E WILLISTON PARK","NY","11596","1128b4","20140520","00000000","00000000",""
|
|
6
|
+
"FRASER","JEFFREY","LOREN","","PHYSICIAN (MD, DO)","FAMILY PRACTICE","","1790792380","00000000","1402 E 8TH ST","HICKMAN","NE","68372","1128a4","20210819","00000000","20230324","NC"
|
|
7
|
+
"MIRANDA","EDUARDO","SIRIA","","PHYSICIAN (MD, DO)","INTERNAL MEDICINE","","1285673012","00000000","8306 ESTATE DRIVE","LAREDO","TX","78045","1128a1","20150618","00000000","20150618","TX"
|
|
8
|
+
"WAHIB","SAMIR","","","PHYSICIAN (MD, DO)","GYN/OBS","","1851353866","00000000","2204 N SECTION ST","SULLIVAN","IN","47882","1128a1","20240118","00000000","20240227","IN"
|
|
9
|
+
"","","","ABSOLUTE MEDICAL SUPPLIES SERV","DME COMPANY","DME - GENERAL","","1588302186","","246 STADDEN ROAD, STE 105","TANNERSVILLE","PA","18372","1128Aa","20260624","00000000","00000000",""
|
|
10
|
+
"","","","ASSURE HOLDINGS CORP","PHYSICIAN PRACTICE (","SURGERY","","0000000000","","7887 E BELLEVIEW AVE, SUITE 50","DENVER","CO","80111","BRCH SA","20250320","00000000","00000000",""
|
|
11
|
+
"","","","CHARTER HOME HEALTH, LLC","OTHER BUSINESS","HOME HEALTH AGENCY","","1104927508","","2798 O'NEAL LANE, BUILDING C","BATON ROUGE","LA","70816","BRCH CIA","20200812","00000000","00000000",""
|
|
12
|
+
"BELGADO","PAULINO","G JR","","MEDICAL PRACTICE, MD","GENERAL PRACTICE/FP","B51476","0000000000","19010101","154 SEVENTH STREET","CLINTONVILLE","WI","54929","1156","19900703","00000000","00000000",""
|
|
13
|
+
"","","","JEWISH MEMORIAL HOSPITAL","HOSPITAL","","","0000000000","","BROADWAY AND 196TH ST","NEW YORK","NY","10040","1160","19830705","00000000","00000000",""
|
|
14
|
+
"","","","UPHILL MEDICAL ASSOCIATES","MEDICAL GROUP","","","0000000000","","C/O 31 CENTRE ST SOUTH, #7","ONTARIO L6W2X7","XX","00000","1128a1","20040908","00000000","00000000",""
|
|
15
|
+
"CAMPBELL","FREDDY","ELTON","","DME COMPANY","OWNER/OPERATOR","","0000000000","00000000","FCI COLEMAN MEDIUM","COLEMAN","FM","33521","1128a1","20090618","00000000","00000000",""
|