@cosyte/synth 0.0.1 → 0.0.3

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.
Files changed (3) hide show
  1. package/CHANGELOG.md +130 -0
  2. package/README.md +7 -2
  3. package/package.json +3 -1
package/CHANGELOG.md CHANGED
@@ -14,6 +14,13 @@ its public history at `0.0.x`, per the cosyte version ladder (`0.0.x` until firs
14
14
 
15
15
  ### Added
16
16
 
17
+ - **A brand image at the top of `README.md`.** The page opens with the Cosyte lockup, served as a
18
+ `<picture>` with a light and a dark source so it follows the reader's theme, and carrying alt text
19
+ that describes the mark for anyone reading with images off or a screen reader on. The block is
20
+ copied byte for byte out of the `hl7` README, which is the reference the suite mirrors, so the
21
+ repos that carry it stay one string rather than drifting into as many hand-typed variants. The
22
+ first 353 bytes of this README are now byte-identical to that file's, with the first divergence
23
+ inside the H1.
17
24
  - Project scaffold from the shared `@cosyte/*` parser template: the canonical toolchain (TypeScript
18
25
  ES2023 + strict rigor via `@cosyte/tsconfig`, ESLint 10 + type-checked `typescript-eslint` via
19
26
  `@cosyte/eslint-config`, Prettier via `@cosyte/prettier-config`, Vitest 4 + v8 coverage via
@@ -369,6 +376,87 @@ its public history at `0.0.x`, per the cosyte version ladder (`0.0.x` until firs
369
376
  instead of silently reopening the hole. `CHANGELOG.md` is excluded on purpose, as in every sibling
370
377
  copy: it ships inside the npm tarball, yet the same convention names it as a place identifiers
371
378
  belong. That contradiction is ecosystem-wide and is recorded, not decided here.
379
+ - **CI-REQUIRED-CHECKS: a gate on what the required test job SELECTS, not just that it ran.**
380
+ `scripts/check-test-selection.ts` (`pnpm check:test-selection`, also reached by `pnpm check`) plus
381
+ `.github/workflows/test-selection.yml` (job id, and therefore future check-run context,
382
+ `test-selection`). It compares the tracked test files that EXIST against the files
383
+ `vitest list --filesOnly` says vitest would RUN, and reds on any shortfall in its subject. Ported
384
+ in shape from `ncpdp` `27f9e89`; the **invocation rule ports verbatim** (this repo's `test` /
385
+ `test:coverage` bodies are spelled identically, confirmed before reuse, so
386
+ `ALLOWED_TEST_SCRIPT_BODIES` is the same closed exact-match set rather than a re-derivation), and
387
+ the **derived subjects are re-derived here**, because `ncpdp`'s ground its fuzz subject in a
388
+ workflow that hands a path straight to `vitest run` and **no workflow in this repo contains that
389
+ string at all** (ported verbatim it refuses). Three subjects instead:
390
+ 1. **The published surface**, from `package.json` `exports`. Each of the eight subpaths resolves to
391
+ a `dist/[<dir>/]index.<ext>` emitted from `src/[<dir>/]index.ts`; every tracked module under
392
+ scope naming one of those entry points must be selected, and every entry point must have at
393
+ least one selected module naming it. Keyed on a **resolved module path**, not a filename and not
394
+ a bare substring, so a rename moves nothing out of the subject; scope is a **deny-list** of
395
+ `src/`, `scripts/` and the repo root, so a move anywhere else does not either. **This is the
396
+ rule that reaches the synthetic-safety property layer**, which was named by nothing.
397
+ **The scope was an allow-list (`test/`) in the first version and the refuter broke it**:
398
+ relocating all six `synthetic-safety.property.test.ts` files into `internal/` took the whole
399
+ safety layer out of CI, `vitest list` selected zero of them, and the gate printed OK exit 0.
400
+ A move into one of the three denied locations still escapes and is stated in three places
401
+ rather than denied.
402
+ 2. **The fuzz path**, derived in two steps because that is how this repo spells it: the nightly
403
+ `Fuzz` workflow runs `pnpm test:fuzz`, whose body is a `vitest run <path>`. Redundant today
404
+ (that module also imports a published entry) and kept for its empty-set refusal, which is a
405
+ tripwire on the fuzz job disappearing **only if no other literal path is left behind anywhere in
406
+ a workflow**. The extraction is text and cannot tell a real `run:` from prose quoting one, so a
407
+ commented `vitest run test/hl7` suppresses the refusal; calling it unconditional would overstate
408
+ it.
409
+ 3. **The PHI scanner**, ported directly (`phi-scan` script plus `run-phi-scan: true` in `ci.yml`).
410
+
411
+ It prints a **denominator** on every run instead of a bare OK: of 39 tracked in-scope code modules,
412
+ **38 are watched by a name-independent rule, 1 by the `.test.`/`.spec.` filename shape alone
413
+ (`test/docs-content.test.ts`), and 0 by no rule at all**. The like-for-like figure in `ncpdp` is **4
414
+ of 27** in-scope modules; its own header quotes "4 of 24", counting only name-shaped files, which
415
+ flatters the ratio. Cite the comparable number, not the friendlier one.
416
+ Three self-tests re-prove it on every run, one resolving a genuinely narrowed config through real
417
+ vitest; **self-test A ignores the filename floor and requires a DERIVED rule to name each dropped
418
+ file**. Both A's drop targets one at a time, so the colliding direction is exercised in each; the
419
+ single difference is that `ncpdp`'s verdict counts the filename floor, which is why that one passed
420
+ with its derived rules neutered. (An earlier draft of this entry said `ncpdp`'s A "does not do" the
421
+ one-at-a-time part; a refuter corrected it, and A is not the backstop for the derived rules in either
422
+ repo, because emptying a subject empties A's targets with it. Self-test C is.)
423
+ **`test-selection` is deliberately NOT added to ruleset `19913330`**: a required context no
424
+ workflow has emitted on `main` leaves every future PR pending and unmergeable. Wire first, require
425
+ later.
426
+
427
+ **Every quantity above is re-derivable, not asserted.** The script header lists the command that
428
+ produces each one, because two of the three refuter passes found a false number or a false claim of
429
+ reach rather than a hole in the mechanism, both times from a sentence ported out of a sibling repo
430
+ and never re-measured here. All of them were re-measured against this repo, on the tree that ships.
431
+
432
+ Demonstrated red by seeding, one route at a time: a narrowed `include`; an `exclude` targeting
433
+ `**/synthetic-safety.property.test.ts`; an `exclude` dropping `test/property/`; positional filters
434
+ written both `vitest run <p>` and `vitest --run <p>`; `--shard=`, `--config=`; a body naming no
435
+ vitest at all (`pnpm run test:unit`, `node node_modules/vitest/vitest.mjs run`) **and a delegation
436
+ to this repo's own narrowing script, `pnpm run test:fuzz`**; renaming a safety suite to `.ts`,
437
+ `.spec.ts` and `_safety.ts`; **the colliding renames that were measured GREEN on `ncpdp`'s earlier
438
+ versions** (`_helpers.ts`, `test/_helpers/load-fixture.ts`, `test/_x/parse.ts`, and the cross-format
439
+ safety suite moved into `test/_helpers/fuzz-config.ts`); the PHI suite renamed to
440
+ `phi-scan-suite.ts`; the fuzz subject renamed out of shape; `run-phi-scan: false`; and
441
+ un-exporting `./astm` together with a narrowed include. Deleting the `Fuzz` workflow, deleting the
442
+ `test:fuzz` script, or deleting the `exports` map each make it **REFUSE to report** rather than pass
443
+ vacuously.
444
+
445
+ Red after the refuter pass, having been **green before it**: any suite relocated out of `test/`
446
+ (one safety suite, then all six at once, then the PHI suite, each into `internal/`), and a suite
447
+ renamed to `_safety.ts` whose import specifiers were rewritten to unicode escapes so the raw text
448
+ no longer looked like the path while the imports still resolved.
449
+
450
+ Green and stated as limits rather than denied: a config branching on `process.argv` (**2 of 39**
451
+ suites would have run); un-exporting `./astm` alone (**2** `test/astm` suites drop to the filename
452
+ floor, denominator 38 to 36); a suite moved into `src/`, `scripts/` or the repo root; and renaming
453
+ `test/docs-content.test.ts` out of shape.
454
+
455
+ - **The dual ESM/CJS release smoke now runs in a job.** `.github/workflows/smoke.yml` (job id `smoke`,
456
+ matrix contexts `smoke (22)` / `smoke (24)`), with `build` and `smoke` as steps of **one** job so a
457
+ future required context covers both. Same wiring `deid` used for the same defect, which is what
458
+ makes this a class rather than an incident. These contexts are also deliberately **not** added to
459
+ the ruleset yet.
372
460
 
373
461
  ### Changed
374
462
 
@@ -409,6 +497,48 @@ its public history at `0.0.x`, per the cosyte version ladder (`0.0.x` until firs
409
497
 
410
498
  ### Fixed
411
499
 
500
+ - **`README.md` said the package was not published to npm. It is.** The summary blockquote opened
501
+ with "pre-alpha (`0.0.x`), not yet published to npm", so the npm package page asserted that the
502
+ package did not exist on npm, directly under the version npm renders in its own header. A reader
503
+ could not tell which half was current. The line now says the package is published and points at
504
+ the npm package page for the version that is live. **No version number is written into the
505
+ correction, deliberately**: the registry is the source of truth, and a number copied onto a page
506
+ is a number that goes stale there (`npm view @cosyte/synth version` is the check).
507
+ - The closing line of the same blockquote, "the two remaining founder gates are the actual
508
+ `npm publish` and the repo public-flip", was **cut rather than reworded**. Both halves are now
509
+ false: the publish happened, and `cosyte/synth` is already a public repository (read back from
510
+ `gh repo view`). Rewording it would have left a measured falsehood standing in cleaner clothes.
511
+ - **Still standing, and deliberately not touched here.** `CLAUDE.md` carries the same "not yet
512
+ published" claim, and the `[Unreleased]` preamble in this file still says the first pre-alpha
513
+ release "will ship" the initial API surface, in the future tense, about a version that shipped.
514
+ Both belong to a cross-repo item spanning eight repos; fixing one repo's copy inside this change
515
+ would fragment it. `docs-content/intro.md` and `docs-content/installation.md` carry the "not yet
516
+ published to npm" claim too, and are left for the same sweep.
517
+ - **`scripts/smoke.mjs` ran in NO CI job.** It only ever ran on the meta-repo's local
518
+ `scripts/verify.sh` ladder, which a contributor is not obliged to run and CI never invokes, so no
519
+ required check covered the eight published subpaths and a green PR said nothing about whether they
520
+ load. Now wired (`.github/workflows/smoke.yml`).
521
+
522
+ **A correction, recorded rather than quietly dropped.** Earlier drafts of this entry and of two
523
+ other surfaces said the file had been _documented as a CI gate_, so that the docs asserted a
524
+ protection nothing provided. **That was false here**, and the third refuter pass caught it: every
525
+ surface describing this file said `run by verify.sh` (this file, `CLAUDE.md`, and the
526
+ release-hardening changeset), and its header said only "Run after `build`". The docs were accurate.
527
+ The sentence was **ported from `deid`, where it is true** (its own changelog records the line that
528
+ claimed CI and never ran), and it was ported without re-measuring it against this repo, which is
529
+ precisely the failure the test-selection gate's header warns about two entries up. The defect is
530
+ real and unchanged; only the indictment of the prior docs was wrong.
531
+
532
+ - **The smoke's subpath set was a hand-written array.** `SUBPATHS` listed the eight subpaths inline,
533
+ so dropping one would have left the gate printing OK over a subset. It is now derived from
534
+ `package.json` `exports` at run time, loads the export targets themselves rather than
535
+ reconstructing `dist/<name>/index.mjs` by hand (so an `exports` entry pointing at a path the build
536
+ does not emit fails here rather than in a consumer's install), and **REFUSES to report** if its
537
+ per-subpath probe map and that `exports` map disagree in either direction. There is no exclusion
538
+ list either: `./package.json` drops out because its target is structurally data, not because a key
539
+ was named. Demonstrated: deleting `"./astm"` from `exports` makes the smoke refuse. That refusal is
540
+ the interlock under `check:test-selection`, whose headline subject is derived from the same map.
541
+
412
542
  ### Security
413
543
 
414
544
  [Unreleased]: https://github.com/cosyte/synth/commits/main
package/README.md CHANGED
@@ -1,3 +1,8 @@
1
+ <picture>
2
+ <source media="(prefers-color-scheme: dark)" srcset="https://cosyte.com/tile/cosyte-lockup-tile-on-dark-1200x300.png">
3
+ <img alt="Cosyte: a plus mark set in two overlapping rounded squares, one solid and one outlined, beside the Cosyte wordmark" src="https://cosyte.com/tile/cosyte-lockup-tile-on-light-1200x300.png">
4
+ </picture>
5
+
1
6
  # @cosyte/synth
2
7
 
3
8
  > Deterministic, seedable **synthetic healthcare-fixture generator** for Node.js and TypeScript —
@@ -11,7 +16,8 @@ date, phone, and address from a **guaranteed-non-colliding synthetic source**. I
11
16
  **format/conformance generator, not a clinical simulator** — it does not model disease progression
12
17
  (that is Synthea).
13
18
 
14
- > **Status:** pre-alpha (`0.0.x`), not yet published to npm. The generator is **feature-complete**: the
19
+ > **Status:** pre-alpha (`0.0.x`), published to npm. The version shown on the npm package page is the
20
+ > one that is live; this page never repeats it. The generator is **feature-complete**: the
15
21
  > seeded-PRNG core, the synthetic-safety providers, and the round-trip harness; **spec-clean generation
16
22
  > across all six formats** — HL7 v2 (`ADT`/`ORU`/`ORM`/`SIU`/`VXU`), FHIR R4 / US Core (the full clinical
17
23
  > set + `collection`/`transaction`/`document` Bundles), C-CDA R2.1 (CCD + Referral Note), X12 005010
@@ -26,7 +32,6 @@ date, phone, and address from a **guaranteed-non-colliding synthetic source**. I
26
32
  > needing a private vendor corpus); the X12 **270** eligibility _request_ and NCPDP SCRIPT lifecycle
27
33
  > **responses** (both track the parsers' builder surfaces); **NCPDP SCRIPT / ASTM / DICOM** de-identify
28
34
  > pairing (no `@cosyte/deid` adapter, or not generated); and optional **Synthea** clinical-content ingestion.
29
- > The two remaining founder gates are the actual `npm publish` and the repo public-flip.
30
35
 
31
36
  ## Install
32
37
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cosyte/synth",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Deterministic, seedable synthetic healthcare-fixture generator for Node.js and TypeScript — spec-clean by construction, never real PHI.",
5
5
  "keywords": [
6
6
  "synth",
@@ -191,6 +191,8 @@
191
191
  "changeset": "changeset",
192
192
  "typecheck": "tsc --noEmit",
193
193
  "phi-scan": "tsx scripts/phi-scan.ts",
194
+ "check": "pnpm run check:test-selection",
195
+ "check:test-selection": "tsx scripts/check-test-selection.ts",
194
196
  "check:no-internal-refs": "bash scripts/check-no-internal-refs.sh",
195
197
  "lint": "eslint \"src/**/*.ts\" \"scripts/**/*.ts\" \"test/**/*.ts\" --max-warnings=0 --no-error-on-unmatched-pattern",
196
198
  "lint:fix": "eslint \"src/**/*.ts\" \"scripts/**/*.ts\" \"test/**/*.ts\" --fix --no-error-on-unmatched-pattern",