# Changelog — `tdcv2` on npm

What changed for someone who runs `npm install tdcv2`.

Engine-wide changes — anything that alters what a config produces — live in
[the repository's CHANGELOG](../CHANGELOG.md) and are true of all five
implementations at the same version number. This file carries what is specific to
the npm package: its API surface, its command line, its landing page.

The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).

## [Unreleased]

## [0.3.6] — 2026-10-25

### Changed

- The engine changes shared by all five implementations — see the
  [engine changelog](../CHANGELOG.md#036--2026-10-25).

## [0.3.5] — 2026-10-17

### Changed

- The engine changes shared by all five implementations — see the
  [engine changelog](../CHANGELOG.md#035--2026-10-17).

## [0.3.4] — 2026-10-16

### Fixed

- **`tdcv2 init --locale` with no value wrote an `en` config without a word.** The flag parser
  read past the end of the line, took the missing value for "not given", and fell back to the
  default; `--data-path` did the same with the pack folder. The other four refuse the line, and so
  does this one now: `missing value for --locale`, exit 2, nothing written. Pinned in `cli.json`
  for both flags.

### Changed

- The engine changes shared by all five implementations — see the
  [engine changelog](../CHANGELOG.md#034--2026-10-16).

## [0.3.3] — 2026-09-29

### Added

- **`packRoots()` — the folders a run reads packs from.** `scanPacks([bundledPacksDir()])`
  sees only the bundled English packs, so a tool asking whether a person has a pack for
  `iban` got "no" for every other language, while the CLI rendered the pack they had
  installed. `scanPacks(packRoots({ configFile }))` is the registry that run gets: the bundled
  packs, then the global and the project config's `dataPaths`, then any given explicitly.
  `new TDC()` builds its list with the same call. Asked for by the agent building the MCP
  server.
- **`EXPR_FUNCTIONS`, `COMPUTE_TAGS` and `COMPUTE_ATTRIBUTES` in the public entry** — what the
  validator accepts in an expression and inside `<compute>`, for a tool that writes configs.

### Fixed

- **A pack's `locale` in `scanPacks()` is the locale a run finds it in.** It was copied from
  the file's `locale:` header alone, and 498 bundled packs carry none — `ru.person.lastName`
  among them — so the registry said they belonged to no locale while every run found them in
  `ru`, and a tool asking which locales carry a path advised installing packs already
  installed. It is now the locale the address starts with, and the header only for a pack
  outside every locale; 55 Nepali files whose header says `en` report `ne`, where they live
  and are found. Reported by the agent building the MCP server.
- **`tdcv2 pack add` no longer streams a progress bar into a pipe.** Off a terminal the live
  status line arrived whole — a carriage return and `ESC[K` per redraw, 21 of them on a 128 KB
  pack, hundreds on a large one — in whatever was reading the output, an agent's context
  included. Off a terminal it now says once `tdcv2: downloading fr (128 KB)…`, as the other
  four implementations always did, and keeps the live line for a terminal. Pinned in the
  shared CLI fixture; reported by the agent building the MCP server.

### Changed

- The engine changes shared by all five implementations — see the
  [engine changelog](../CHANGELOG.md#033--2026-09-29).

## [0.3.2] — 2026-09-22

### Changed

- Nothing for this package: the release fixes how the C# command line declares its
  runtime — see the [engine changelog](../CHANGELOG.md#032--2026-09-22).

## [0.3.1] — 2026-09-21

### Changed

- Engine and `tdcv2 pack` changes only, shared by all five implementations — see the
  [engine changelog](../CHANGELOG.md#031--2026-09-21).

## [0.3.0] — 2026-09-01

### Added

- **The language server reads the packs you actually installed.** `tdcv2 pack add sd` unpacks
  into a store and registers it in the project config's `dataPaths` — and the server never
  opened a config file. It scanned the bundled packs and two conventional folders, so an
  installed locale rendered perfectly from the command line and offered not one address in
  autocomplete. On a real store that is 222 invisible addresses per pack. Nobody reported it,
  because a missing suggestion looks exactly like a suggestion that does not apply.

  The roots now come through `loadConfig` — the same function `tdcv2`, `pack`, `init` and the
  Quick API call — and are re-scanned when one of their timestamps moves, so a pack installed
  while the editor is open appears without a restart.

- **Every attribute and every compute tag says what it does on hover.** Thirty-two of the
  eighty-six `<gen>` attributes had no text at all, and they were the new ones: `of`, `plus`,
  `expr`, `op`, `reset` and the whole statistical-distribution family. All forty-eight compute
  tags had none. The attribute was offered, accepted by the validator, and silent when you
  asked what it meant. `type=`'s own text had drifted the other way — it listed the generators
  by hand and stopped at `http`, so `pool`, `running`, `stat` and `formula` were missing from
  the one sentence that claims to list them all.

  A test now requires a doc for every name the validator accepts, and requires `type=` to name
  every generator the engine implements — the one hover text that enumerates something the
  engine owns, and so the one that can be checked rather than merely re-read.

- **The VS Code extension finds the server outside this repository.** It looks in four places
  — the configured `tdc.server.path`, the workspace's own `node_modules`, a resolvable
  `tdcv2` install, then a local build — and when there is none it says so, naming what still
  works (highlighting) and what does not (autocomplete, hover, diagnostics), instead of
  starting a client against a path that does not exist.

- **Parquet reports too**, on both the single-threaded and the parallel path — once per
  row group, summed across workers.

- **`--progress` counts a parallel run whole.** Every worker reports the rows it has
  written and the coordinator adds them up, so the percent is the file's — including the
  `uniq-scan` and `uniq-sort` phases, which the parallel path also splits across workers.

- **`--progress`, and `onProgress` on the library.** The command line writes
  `<output>.progress` beside the output — a small JSON object, rewritten in place
  about once a second, naming the phase and how far along it is. The library takes
  the same channel as a callback: `new TDC({ onProgress: ({ phase, done, total }) => ... })`.
  All five implementations now carry it, writing the same fields.

- **One vocabulary for the finished run, in all five implementations.** The object a run
  hands back now answers to the same names everywhere, spelled each language's own way.
  The reference already carried every name; it now proves so against the shared table.

  Nothing is renamed and nothing is deprecated: every existing name keep working exactly as before.
  This library is meant to be used BESIDE the generator, so a reader following an example
  written in another language should not have to translate the method names.

  Guarded by `fixtures/cross-language/api.json`, which all five test suites read. There was
  no guard on this surface before, which is why it drifted at all — each choice was
  reasonable in its own language and wrong for a reader crossing between them.

- **`toColumns()` — the run as columns, with numbers as numbers.** Present in all
  five implementations, spelled by each language's convention: `toColumns`,
  `to_columns`, `ToColumns`. `toArray()`
  hands back strings, so a caller wanting numbers parsed them again; a caller
  generating thousands of windows wrote the same `split(',')` and `Number()`
  every time.

  ```ts
  const { Sec, MV } = new TDC({ configString }).toColumns(); // Float64Array
  ```

  A column comes back as a `Float64Array` only when EVERY cell in it is a finite
  number, and as a plain array otherwise — so the type says which, and a caller
  reading a numeric column never has to check for a label hiding in it. The rule
  is all-or-nothing on purpose: a typed array cannot hold "no value", and filling
  the gaps with NaN would put a number nobody generated where a `parent=` filter
  had deliberately left nothing. Compound and pool sequences contribute one key
  per field, spelled `Name.field`.

  It is not a way to skip the number-to-string conversion — sequences hold their
  values as text, so this parses them. Measured on a 3,600-row window of six
  formula columns, the whole round trip is 0.54 ms against 22 ms of generation,
  2.4 per cent. This is for the ergonomics and for not building a 140 KB string
  per window.

## [0.2.2] — 2026-08-15

### Changed

- **The npm tarball is now checked the way a stranger receives it.** It was the one
  artefact this repository had never packed, installed and run — it kept working on the
  strength of a single `prepack` hook, which is luck holding rather than a check passing.
  `typescript/scripts/verify-tarball.mjs` builds from a clean clone, runs `npm pack`,
  installs the tarball into a directory of its own and uses both the library and the
  command line. Nothing about the package itself changed.

## [0.2.1] — 2026-08-11

Nothing changed in the npm package itself: no API was added, removed or renamed, the
command line takes the same arguments, and the landing page is unchanged. What this
version does change is what a config PRODUCES — `<gen type="pattern">` in particular —
and that is written up in [the repository's CHANGELOG](../CHANGELOG.md), where it is true
of all five implementations at once.

The line is here rather than absent because silence and "nothing to report" look the same
in a changelog, and only one of them is an answer.

## [0.1.4] — 2026-08-03

### Changed

- **One folder for downloaded packs, not three levels of near-duplicate names.**
  `tdcv2 pack add ru russia` used to leave `data/ru/packs/ru/…` and
  `data/russia/packs/countries/russia/…`, and appended a `dataPaths` entry per
  bundle — a hundred packs meant a hundred entries. Both extra levels belonged
  to the tooling rather than to the data: `<store>/<id>/` existed so removal
  could delete one folder, and `packs/` came out of the archive. They are gone.
  Every bundle now unpacks into ONE tree at its address path — `data/ru/…`,
  `data/countries/russia/…` — and the store is registered once.

  What each bundle owns is written down in `<store>/.tdcv2-installed.json`
  instead of implied by a folder name, so `pack remove` deletes exactly the
  paths that bundle brought and leaves the country beside it alone.

  A store from an earlier version is moved to the new shape in place, by the
  first `tdcv2 pack` command of any kind, which also replaces the per-bundle
  `dataPaths` entries with the store and says on stderr what it moved. Nothing
  has to be downloaded again. If a path in the new layout is already taken the
  move is refused whole, with the collisions named, rather than half-done.

### Fixed

- **`tdcv2 init --help` and `tdcv2 pack --help` printed an error instead of
  help.** The flag parser saw `--help` before anything thought to answer it, so
  both exited 2 with "unknown option". They now print the same usage text the
  four ports print, byte for byte, and `pack --help` answers before the pack
  store is resolved — which is the machine where somebody needs it.

- **The quick API's error handling, four defects.** This is the odd case where
  the reference was the worst of the five and the ports were right; each fix is
  theirs, carried back.

  Whether a pack was missing was decided by a lookup in a hardcoded table of
  locales and countries, so an address outside that table got the opposite
  answer to the one intended: `zz.person.lastName` was told "did you mean
  ar.person.lastName?" — proposing a different language, the exact outcome the
  message exists to avoid. It is a structural test now.

  A failure the address could not explain was rewritten into one about the
  address: an undeclared pack parameter raised TDC072 and the user was shown
  "unknown address common.internet.email — did you mean common.internet.email?".
  The engine's own diagnostic survives.

  Formatting a diagnostic read the project config unguarded, so a broken
  `tdcv2.config.json` replaced the real message — an error thrown from inside an
  error handler.

  The two halves of one message read two different lists, so a typo near a pack
  installed through the project's `dataPaths` got no suggestion.

- **The uninstalled-pack message no longer says `npx`.** All five now emit the
  same sentence.

## [0.1.3] — 2026-08-02

### Fixed

- **Pack parameters are checked in more places, and the check is right in two
  more.** A plain list of values now says it has no parameters instead of
  accepting one in silence, and a locale-relative address such as
  `person.lastName` is resolved against the active locale before it is checked —
  previously only absolute addresses like `common.internet.email` were. See the
  repository CHANGELOG; the behaviour is now the same in all five
  implementations.

## [0.1.2] — 2026-08-02

### Fixed

- **A missing pack says which pack, instead of proposing another language.** npm
  ships a starter set — `common`, `en`, `usa` — and the registry carries the
  other hundred-odd, so `tdc.lang.ru.person.lastName()` on a fresh install has no
  `ru` to draw from. It answered `unknown address "ru.person.lastName" (locale
"en"). Did you mean "en.person.lastName"?`, which offers English to someone who
  asked for Russian and reads as though the address were a typo. It now names the
  pack and the command that installs it.

## [0.1.1] — 2026-08-02

### Changed

- **The landing page shows both ways of using TDC.** npm renders the README out
  of the published tarball, so 0.1.0's page could only show what 0.1.0 shipped
  with. The page opens on a fork — reach for a value (`tdc.person.lastName()`) or
  describe a dataset (a config) — because these are two tools sharing one set of
  data and a reader has to see both.
- **Package metadata written for discovery**: a description that says what the
  thing does rather than what it is called, and 27 keywords covering the terms
  people search for.

### Fixed

- **`tdcv2 --version` reported a number that agreed only with itself.** The smoke
  test compared `VERSION` to a literal `'0.1.0'`, so `npm version` moved
  `package.json` while the test stayed green. It reads `package.json` now.
- **`tdcv2-lsp` could never start**: the language-server entry point had no
  `#!/usr/bin/env node`, and npm symlinks bins on POSIX.

## [0.1.0] — 2026-08-02

First release to npm. The engine, the CLI (`generate`, `init`, `pack`, `check`,
`format`), the language server, the library API and the one-value quick API, with
a starter set of data packs and the rest downloadable from the shared registry.
