@cosyte/terminology 0.0.8 → 0.0.9
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/CHANGELOG.md +157 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -23,8 +23,165 @@ this file is maintained by hand (Changesets handles the version bump and publish
|
|
|
23
23
|
without evaluating a part expansion still has to report. Reading `d.system` is now a type error.
|
|
24
24
|
The rationale, and the other three sites, are under **Fixed** below.
|
|
25
25
|
|
|
26
|
+
- **The test suite no longer sets a global timeout, and its one repeated start-up tax is gone**
|
|
27
|
+
(`PARSER-TESTTIMEOUT-ASSERTS-AN-IDLE-BOX`). Development tooling only — `vitest.config.ts` and the
|
|
28
|
+
test suite. No source file, no build output and no part of the public surface is touched.
|
|
29
|
+
|
|
30
|
+
**The trim came first, and it was the larger win.** `test/scripts/phi-scan.test.ts` spawns the
|
|
31
|
+
scanner at twenty call sites, and the cost of each spawn was start-up, not scanning — the fixtures
|
|
32
|
+
are a few hundred bytes. Measured on a 12-CPU cgroup quota, warmed runs of each against the same
|
|
33
|
+
scanner and argv: a `tsx` start had a median around **470–500 ms** against **141–200 ms** for
|
|
34
|
+
`node` running the same TypeScript through its native type stripping — roughly 300 ms a spawn.
|
|
35
|
+
That roughly halved the file: a plain base run measured **13,925 ms** over 21 cases, and plain runs
|
|
36
|
+
after the change measured **5,657 ms and 6,853 ms** over 22. Both runners were checked to produce
|
|
37
|
+
byte-identical stdout and stderr and the same exit code, on a clean file and on a violator, before
|
|
38
|
+
the change; several cases assert on stderr exactly.
|
|
39
|
+
|
|
40
|
+
`pnpm phi-scan` still runs `tsx`, so one case still spawns it and asserts the two runners **agree**
|
|
41
|
+
on exit code, stdout and stderr — a parity assertion, so a divergence reds rather than letting the
|
|
42
|
+
sweep quietly test something the gate does not run. Node's type stripping is on by default from
|
|
43
|
+
**22.18** while `engines.node` is `>=22.0.0`; the CI matrix is 22 + 24 and both resolve above that,
|
|
44
|
+
but a developer on 22.0–22.17 would need a newer 22 to run the suite.
|
|
45
|
+
|
|
46
|
+
**`testTimeout: 10_000` and `hookTimeout: 10_000` are removed**; the shared `@cosyte/vitest-config`
|
|
47
|
+
sets no timeout at all. A global timeout asserts the **machine**, not the code: sized for the
|
|
48
|
+
slowest test in the repo and then inherited by every other test, so a genuinely hung fast test
|
|
49
|
+
looks merely slow instead of broken. `hookTimeout` was pure noise — Vitest's default hook timeout
|
|
50
|
+
is **exactly** 10,000 ms, so the literal restated it. Both defaults were established by measuring a
|
|
51
|
+
deliberately over-running test and hook, not by reading the documentation.
|
|
52
|
+
|
|
53
|
+
**Per-test, never global.** Every test whose cost is not fixed now declares its own budget beside
|
|
54
|
+
the work. The `attw-gate` cases that run a real `npm pack` have carried an explicit 60 s one all
|
|
55
|
+
along; three groups were added — the two 200,000-row bulk cases in
|
|
56
|
+
`test/rxnorm/term-types.test.ts`, the single `tsx`-parity case, and **all of `test/property/**`**,
|
|
57
|
+
whose runtime varies with the fast-check draw as well as with the box, since this package pins no
|
|
58
|
+
seed by design. With those declared, every remaining test peaked at **689 ms\*\*, a ~7x margin
|
|
59
|
+
against the 5 s default the config now inherits.
|
|
60
|
+
|
|
61
|
+
**The method is part of the claim.** Ten full runs on a contended box (12-CPU cgroup quota,
|
|
62
|
+
fourteen-worker fleet), of which **six were `vitest run --coverage`**. That is not optional: CI
|
|
63
|
+
gates on `pnpm test` _and_ `pnpm test:coverage`, and the instrumented run is materially slower,
|
|
64
|
+
roughly doubling the property-suite peaks. An earlier draft of this change measured only the plain
|
|
65
|
+
run, recorded 499 ms, and was refuted for it.
|
|
66
|
+
|
|
67
|
+
**Two things measurement corrected.** The argument-refusal cases in `attw-gate` look like they
|
|
68
|
+
belong with the slow ones and do not: the wrapper rejects the flag before invoking `attw`, so they
|
|
69
|
+
run no `npm pack` and finish in ~200 ms. And the case that actually approached the old ceiling —
|
|
70
|
+
**9,318 ms against 10,000 ms** under load, a 682 ms margin on correct code — was an `attw` case
|
|
71
|
+
that already had its own 60 s budget, so the global was never what stood between it and a false
|
|
72
|
+
red. The `attw` cost itself is genuine work (a real `npm pack` runs ~1,550 ms), so it is bounded
|
|
73
|
+
rather than trimmed. These figures describe one box on one day and are recorded so the next reader
|
|
74
|
+
re-measures rather than inherits them.
|
|
75
|
+
|
|
26
76
|
### Fixed
|
|
27
77
|
|
|
78
|
+
- **The publish gate's argument guard refused a fixed LIST of blinding spellings, and `-fjson` was
|
|
79
|
+
not on it — a value fused to a short flag hid the one sentence the gate reads, and it handed back a
|
|
80
|
+
pass over a tarball carrying no types** (`ATTW-GUARD-ALLOWLIST`). Development tooling only —
|
|
81
|
+
`scripts/attw.mjs` ships in no tarball, and the public surface, build output and runtime behaviour
|
|
82
|
+
are unchanged.
|
|
83
|
+
|
|
84
|
+
**The rules of the gate are stated once, in `scripts/attw.mjs`'s docblock. This entry points at it
|
|
85
|
+
rather than repeating them**, and `CLAUDE.md`'s paragraph now does the same. The guard was
|
|
86
|
+
described in several committed files at once and the copies drifted: `CLAUDE.md` claimed a refusal "by
|
|
87
|
+
option name, wholesale" that a fused short option walked past, and called `--config-path` refused
|
|
88
|
+
"by inference, not measurement" when the real-file half takes one command to measure.
|
|
89
|
+
|
|
90
|
+
**The remedy is an ALLOW-LIST, so no spelling is enumerated.** The gate forwards `--profile` and
|
|
91
|
+
`--no-definitely-typed` and refuses everything else, including options that blind nothing:
|
|
92
|
+
"harmless" is not a judgement a script can make from an option name. Measured on `7bdd5f5` against
|
|
93
|
+
this repo's pinned `@arethetypeswrong/cli@0.18.4`, on a fixture whose tarball carries no types —
|
|
94
|
+
`-fjson`, `-Pf json` and `-Pfjson` each exited **0** with the untyped sentence absent and a
|
|
95
|
+
non-empty transcript, so the empty-output net could not backstop them; `--help`, `-h`, `--version`
|
|
96
|
+
and `-V` did the same. `--config-path` naming a real file that sets `format` blinded identically,
|
|
97
|
+
while the nonexistent path the old test named blinds **nothing** — `readConfig()` swallows the
|
|
98
|
+
`ENOENT` and the sentence is still printed, so that test asserted a refusal over a case that could
|
|
99
|
+
not have hurt the gate. Both halves are pinned now.
|
|
100
|
+
|
|
101
|
+
**The preflight walks two promises it used to skip**, each measured to leave bare `attw` at exit 0:
|
|
102
|
+
`bin`, which `attw` does not look at at all, so a manifest could promise a command absent from the
|
|
103
|
+
tarball; and a path written without a leading `./`, which is legal and is the spelling npm's own
|
|
104
|
+
documentation uses, so `"main": "dist/index.js"` was dropped silently while the gate reported it
|
|
105
|
+
had checked. This package declares no `bin` — that half is pinned on a fixture that does, because
|
|
106
|
+
every sibling copies this file.
|
|
107
|
+
|
|
108
|
+
**A false explanation of a correct red is deleted rather than reworded.** The preflight used to
|
|
109
|
+
name the exit code `attw` "would have" produced. It reads the manifest and never the tarball, and
|
|
110
|
+
the tarball decides: `analysis.types` is `containsTypes()` in `@arethetypeswrong/core`, which is
|
|
111
|
+
`listFiles(directory).some(ts.hasTSFileExtension)` — any TypeScript-extension file in the packed
|
|
112
|
+
tarball, computed before an entrypoint is resolved. A package packing a whole `dist/` can lose
|
|
113
|
+
every declared declaration and still hand `attw` an undeclared chunk declaration, at which point it
|
|
114
|
+
exits 1 and the sentence is false. The failure now says what it checked and that it cannot speak
|
|
115
|
+
for `attw`.
|
|
116
|
+
|
|
117
|
+
**A limit found while grading this, filed rather than closed.** The `.attw.json` refusal names
|
|
118
|
+
`quiet` and `format`, but `readConfig()` sets an option value for **every** key except
|
|
119
|
+
`configPath`, `help` and `version` — so a committed config reaches options this gate does not name,
|
|
120
|
+
`definitelyTyped` pointed at a `.tgz` among them, which merges those types in and can make an
|
|
121
|
+
untyped tarball analyse as typed. It predates this change, and the allow-list closes only its argv
|
|
122
|
+
half — `--definitely-typed` on argv is now refused, where the deny-list forwarded it — while the
|
|
123
|
+
config route is untouched. Adding a key would rebuild, on the config side, the deny-list this
|
|
124
|
+
change retires on the argument side.
|
|
125
|
+
|
|
126
|
+
- **A symbolic link under a scan root read CLEAN on BOTH of the PHI scanner's enumerating routes, so
|
|
127
|
+
a link pointing at a file full of real identifiers passed the gate twice over**
|
|
128
|
+
(`PHI-SCAN-SYMLINK-BLIND-ON-BOTH-ROUTES`). Development tooling only — `scripts/phi-scan.ts` ships in
|
|
129
|
+
no tarball and the package's public surface is unchanged.
|
|
130
|
+
|
|
131
|
+
Reproduced on `80a8cc7` before any fix, with a synthetic name-bearing payload (a person name, a
|
|
132
|
+
DOB, a dashed SSN and an email at a non-test domain) placed outside the walk roots and a link to it
|
|
133
|
+
at `src/leak.ts`. `pnpm phi-scan` printed `OK — no hits` and exited **0**; `pnpm phi-scan --staged`,
|
|
134
|
+
after `git add`, printed `OK — no hits` and exited **0**. Naming the link's target explicitly on the
|
|
135
|
+
command line found both shapes and exited 1, so the payload was always detectable — the two routes
|
|
136
|
+
simply never looked at it.
|
|
137
|
+
|
|
138
|
+
The two blindnesses are separate mechanisms and needed separate fixes. The walk enumerates
|
|
139
|
+
`Dirent.isFile()`, which is an **lstat** answer, so a link is neither a file nor a directory and
|
|
140
|
+
fell out of the loop with no record that anything had been skipped — and `isDirectory()` answers
|
|
141
|
+
false for a linked directory too, so a whole subtree could disappear the same way. The `--staged`
|
|
142
|
+
route reads content with `git show :<path>`, and **git stores a symbolic link as its target path
|
|
143
|
+
under mode `120000`**, so it was handed the target's path text and scanned that. That second route
|
|
144
|
+
is this repo's `pre-commit` hook, which is exactly where the claim that `--staged` covers a link
|
|
145
|
+
would have been trusted.
|
|
146
|
+
|
|
147
|
+
**Neither route is made to follow the link.** Following would read bytes the enumeration does not
|
|
148
|
+
control — outside the repo, a loop, a device, a FIFO that blocks the gate forever — and git does not
|
|
149
|
+
carry those bytes anyway, so a hit on them would be a claim about something no commit contains.
|
|
150
|
+
Instead the enumeration is narrowed: an entry under a scan root that is not a regular file **refuses
|
|
151
|
+
the scan** (exit 2, the existing "could not complete" code), naming every offender rather than the
|
|
152
|
+
first. The walk classifies by `Dirent` (symbolic link, FIFO, socket, block device, character
|
|
153
|
+
device); `--staged` now reads `git diff --cached --raw -z` instead of `--name-only` so the
|
|
154
|
+
destination mode is visible, and refuses mode `120000` and `160000` (a gitlink) wherever that
|
|
155
|
+
route's own path scope reaches them. A `--raw` record that does not parse refuses as well, rather
|
|
156
|
+
than being skipped into a silently shortened list.
|
|
157
|
+
|
|
158
|
+
**`T` (typechange) is in the `--diff-filter`, and leaving it out made the mode check unreachable
|
|
159
|
+
whenever the file being replaced was already tracked.** Replacing a **tracked** regular file with a link is neither an add nor a
|
|
160
|
+
modify: git raises `:100644 120000 <sha> <sha> T`, so `--diff-filter=AM` deleted the record before
|
|
161
|
+
any mode could be read and the hook passed the link green. Measured on git 2.39.5: with `AM` the
|
|
162
|
+
raw output for that stage is empty. Typechange carries a single path, exactly like `A` and `M`, so
|
|
163
|
+
admitting it costs the record stride nothing — and it means the reverse typechange, a link replaced
|
|
164
|
+
by a real file, is now scanned as the ordinary file it became.
|
|
165
|
+
|
|
166
|
+
**A refusal names the entry's own repo-relative path and an engine-owned token for its kind, and
|
|
167
|
+
never the link target** — a target path is text off the working tree and can itself carry PHI. That
|
|
168
|
+
is asserted, not asserted-in-prose: the pinning payload and the target's own filename both carry a
|
|
169
|
+
synthetic person name, and every refusal message is checked to contain none of it.
|
|
170
|
+
|
|
171
|
+
**What this does not cover, stated narrowly, each measured.** Explicit-path mode already read
|
|
172
|
+
through a link and reported the target's hits; it is unchanged. The `--staged` path scope is
|
|
173
|
+
unchanged — still `test/fixtures/**` and `src/**.ts` — so a staged link outside it is still not
|
|
174
|
+
looked at; narrowing what a scope admits is not widening the scope. That scope also bounds the
|
|
175
|
+
gitlink half: a submodule staged at `test/fixtures/nested` is refused, while one at `src/nested` is
|
|
176
|
+
a directory name that fails the `.ts` suffix and is not looked at. `R` (rename) and `C` (copy) are
|
|
177
|
+
still **not** enumerated by `--staged` at all, so a staged rename that also appends PHI passes that
|
|
178
|
+
route — pre-existing, unchanged here, and admitting it needs the two-path record shape handled,
|
|
179
|
+
which is a scope decision rather than this one; CI's all-mode sweep does read the resulting
|
|
180
|
+
worktree file. A tracked file **absent from the worktree** is still caught at `git add` time only.
|
|
181
|
+
And the scanner still has no tolerance for a file that vanishes between enumeration and read, so an
|
|
182
|
+
untracked transient appearing under a walk root can still refuse a whole sweep; that is a different
|
|
183
|
+
defect, it fails closed, and it is not addressed here.
|
|
184
|
+
|
|
28
185
|
- **A loaded GEM map, complex map and RxNorm drug graph froze their wrapper and handed out plain
|
|
29
186
|
`Map`s inside it, so whoever held one could delete a diagnosis mapping, add a target the steward's
|
|
30
187
|
file never authored, or empty a medication's ingredient edges** (`TERMINOLOGY-INNER-MAPS-UNSEALED`).
|
package/dist/index.cjs
CHANGED
|
@@ -4776,7 +4776,7 @@ function approximateMatch(graph, query, options = {}) {
|
|
|
4776
4776
|
}
|
|
4777
4777
|
|
|
4778
4778
|
// src/index.ts
|
|
4779
|
-
var VERSION = "0.0.
|
|
4779
|
+
var VERSION = "0.0.9";
|
|
4780
4780
|
|
|
4781
4781
|
exports.COMPLEX_MAP_SOURCE_SYSTEM = COMPLEX_MAP_SOURCE_SYSTEM;
|
|
4782
4782
|
exports.DIAGNOSTIC_CODES = DIAGNOSTIC_CODES;
|