Adding a Synth Distribution
Audience: Pulse internals contributors adding a new synthetic-data
distribution kind to the internal/synth/ package — Normal, Uniform,
Categorical, ZipfMandelbrot, etc.
The synth surface generates .pulse cohorts from either a declared
schema (pulse synth from-schema) or a profile sampled from an
existing cohort (pulse synth from-profile). Distributions plug into
both code paths via the AllDistributions() registry in internal/synth.
1. Implement in internal/synth/
Add the distribution implementation in internal/synth/ (the public synth package is an alias facade; re-declare a new Dist* constant there if embedders should spell it). Each distribution
satisfies the package’s distribution interface (per-field RNG +
parameter validation + JSON marshalling). Register it in the
AllDistributions() slice (internal/synth) so the generator surface enumerates
it.
2. Capability declaration
Add a row to internal/descriptor/capabilities_distributions.go so the manifest
exposes the new distribution to LLM clients.
TestManifestDistributionsComplete enforces a capability row per
registered distribution kind.
3. Write the atomic skill and list it
Create skills/op-synth-<kebab>.md covering the parameter shape, the
distribution’s family (continuous, discrete, heavy-tailed,
categorical-like), and any sampling caveats;
TestSkillsCoverAllSynthDistributions enforces the file exists at that stem.
Add the kind’s name to the “Distribution registry” list in
skills/synthetic-data.md, and — if it changes reconstruction, correlation
or model participation — the focused skills/synth-*.md skill that owns that
topic (synth-marginals, synth-correlations, synth-models).
4. Update CLAUDE.md
There is no registered-synth-distribution count or list in CLAUDE.md to update —
CLAUDE.md never hardcodes registered counts; the manifest is the source of
truth. The Update Demand operator row (.claude/reference/update-demand.md)
requires instead the atomic skill skills/op-synth-<kebab>.md, the capability declaration in
internal/descriptor/capabilities_distributions.go. Edit CLAUDE.md only if the
operator introduces a contract it states directly, and mind
TestClaudeMdSizeBudget — long-form prose belongs in .claude/reference/.
5. Run the gates
go test ./internal/skills/ -run TestSkillsCoverAllSynthDistributions
go test ./internal/descriptor/ -run TestManifestDistributionsComplete
go test ./internal/synth/...
The Update Demand row for synth distributions covers all of these in one PR; see The Update Demand.