Skip to content

--config cannot emit tdbin outputs — codecs go stale under --watch #65

Description

@MelbourneDeveloper

Problem

--config FILE is the intended "one schema, many outputs" entry point, but its outputs are restricted to converters.LANGUAGES:

// dist/generation-config.js
const languageValue = (value) => converters.LANGUAGES.some((language) => language === value);
const parseOutput = ([language, path]) =>
    !languageValue(language)
        ? err({ message: `unsupported output language '${language}'` })
        : 

tdbin is not a converter language, so there is no way to say "also emit the codec module here" in a config file. tdbin generation has to be driven as separate encode/decode shell-outs, outside the config, outside --watch.

That splits one logical generation step into two mechanisms with two failure modes, and --watch regenerates only half of it — leaving codecs silently stale against the types they encode. Given that the whole point of the LAYOUT_HASH constant is to catch layout drift, having the tooling cause drift on every watched edit is a bad default.

Ask

Make tdbin a first-class config output. Something like:

{
  "source": "docs/models/live-ipc.td",
  "outputs": {
    "rust": "crates/deslop-core/src/wire_generated.rs",
    "typescript": "clients/vscode/src/types/wire-generated.ts"
  },
  "tdbin": {
    "rust": { "path": "crates/deslop-core/src/wire_codec.rs", "mode": "codec-only" },
    "typescript": { "path": "clients/vscode/src/types/wire-codec.ts" }
  }
}

Requirements:

  1. --watch regenerates types and codecs from the same parse, so they can never disagree.
  2. mode: "codec-only" maps to today's decode behaviour (impls against externally-emitted types); a "full" mode maps to encode.
  3. Config-driven runs apply the same emitted-type configuration to both (see the companion issue on codec/config divergence).
  4. Deterministic output ordering and the provenance header from Generated output: provenance header (source SHA + version) + built-in --check + deterministic ordering #41 apply to codec files too — a codec module that reorders between runs makes every regeneration a diff.
  5. Non-zero exit if the emitted LAYOUT_HASH set changed relative to the file on disk, so CI can gate wire-format changes. This is the tdbin analogue of the --check mode requested in Generated output: provenance header (source SHA + version) + built-in --check + deterministic ordering #41, and it is what actually makes the format's schema-evolution guarantees enforceable rather than aspirational.

Context

Deslop generates Rust + TypeScript from one .td file today via a wrapper script that invokes the CLI once per target and post-processes each. Adding tdbin should add a line to a config file, not a third bespoke code path.

Related: #41 (provenance header, --check, deterministic ordering).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions