Changelog
0.3.1 — 2026-06-30
Competitive positioning and public-site upgrade.
- New
kynml.competitorsmodule with checked-in profiles for PyTorch Lightning, Keras, Ludwig, and ZenML. - New
kynml compare [--focus name] [--format table|markdown|json]command. - New Competitive Map docs page.
- Public homepage now includes a competitive map section and reflects the eight-command CLI surface.
0.3.0 — 2026-06-29
Phase 0/1 compiler upgrade: typed IR, shape inference, composition (params/import/sweep), reproducibility, formatter, and LSP diagnostics.
Breaking / Strictness
Shape inference runs at compile time (not at validate). Programs that previously passed kynml validate may now fail at kynml compile or kynml train if:
bceloss: the final dense layer does not have exactly 1 output unit. Previously accepted; now raisesKynMLShapeError.cross_entropyornllloss: the final dense layer has fewer than 2 output units. Previously accepted; now raisesKynMLShapeError.
Migration: ensure your last dense layer matches the loss. For bce use dense 1 sigmoid; for cross_entropy use dense N linear where N is your class count.
Programs using cross_entropy with a softmax or log_softmax activation on the final layer now emit a warning (not an error) at compile time. The warning is surfaced as a severity="warning" diagnostic in the LSP and printed to stderr by the CLI. This is not a breaking change, but the generated model will produce incorrect results — switch to dense N linear with cross_entropy.
Typed IR + Shape Inference
- New package
kynml/ir/:types.py,nodes.py,builder.py,infer.py,passes.py TypeShapeandDTypeprimitives — static tensor types with a dynamic batch axis (None)IRModule,IRGraph,IRTrain,IRDataset,IREvaluate,IRExport— frozen IR dataclasses- Layer IR ops:
InputOp,LinearOp,DropoutOp,BatchNorm1dOp lower_program(program) -> IRModule— pure structural translation from AST;inferred=Falseat this stageinfer_module(module) -> IRModule— threadsTypeShapethrough each graph op sequence; fillsLinearOp.in_featuresandBatchNorm1dOp.num_featuresautomatically; raisesKynMLShapeErroron mismatchesrun_passes(module) -> IRModule— pass registry (currently runsinfer_module)compile_to_ir(program, source_path, overrides) -> IRModuleinkynml/pipeline.py— canonical front door: compose → validate → lower → infer- New error type:
KynMLShapeError(subclass ofKynMLSemanticError)
Users no longer need to specify in_features anywhere. The parser, AST, and semantic validator are unchanged for existing programs.
Backend Seam
- New
kynml/codegen/base.py:BackendABC,EmitContext,get_backend(name) - New
kynml/codegen/pytorch_backend.py:PyTorchBackend— reads exclusively fromIRModule; assertsmodule.inferredat entry kynml/codegen/pytorch.pyis now a compatibility shim;generate_pytorch()andwrite_pytorch()have unchanged signatures and emitted-string contracts- Existing code importing
generate_pytorch/write_pytorchrequires no changes
Composition
- New
params:block —name = valuepairs; any block can reference values via$name - New
import "other.kyn"statements — mergesdatasetandmodelblocks; cycle detection; duplicate-name errors raiseKynMLSemanticError - New
sweep:block — each axis maps a param name to a list of values; grid expansion is Cartesian kynml/compose.py:apply_composition(),resolve_imports(),substitute_params()kynml/sweep.py:expand_sweep(),generate_sweep_runner()ParamRef,ParamsBlock,SweepBlockadded toast_nodes.pyProgramgainsparams,sweep, andimportsfields (all default toNone/[]— no breakage for existing programs)
Syntax examples:
params:
hidden = 64
lr = 0.001
sweep:
lr = [0.001, 0.01]
hidden = [32, 64]
import "shared/base.kyn"
model M:
input 4
dense $hidden relu
dense 1 linear
train:
optimizer = adam(lr=$lr)
epochs = 20
batch = $bs
CLI override: kynml compile model.kyn --out out.py --param lr=0.005 --param hidden=128
Reproducibility
seedanddeterministicfields added totrain:block- Generated scripts emit
CONFIG_HASH(sha256 of the.kynsource, computed at codegen time),SEED, and_set_seed()coveringrandom,numpy,torch, andtorch.cuda deterministic = trueadditionally setstorch.use_deterministic_algorithms(True)andtorch.backends.cudnn.deterministic = True- Every generated script writes
run_manifest.jsonafter training:kynml_version,config_hash,data_hash(sha256 of the dataset, computed at runtime),env(python/torch/numpy/platform versions),seed,metrics - New
kynml/repro/manifest.py:RunManifest,config_hash(),data_hash(),env_info(),write_manifest(),load_manifest() - New
kynml/lock.py:create_lock(),check_lock(),read_lock(),LockMismatchError— opt-in config-hash pinning for drift detection
train:
seed = 42
deterministic = true
Formatter (kynml fmt)
- New subcommand
kynml fmt <file> [--write | --check] --writeoverwrites the file in place;--checkexits with code 1 if the file would change (CI-friendly)- Without flags, prints formatted source to stdout
python -m kynml.format <file>— equivalent module entry pointfrom kynml.format.formatter import format_source, format_file— Python API- Idempotent:
format_source(format_source(x)) == format_source(x) - Rules: 4-space indentation, one blank line between blocks, no trailing whitespace, single trailing newline, canonical key order per block
LSP Diagnostics (kynml lsp)
- New subcommand
kynml lsp— starts an LSP server over stdio; requirespip install 'kynml[lsp]' python -m kynml.lsp— equivalent module entry pointfrom kynml.lsp.diagnostics import diagnose— pure diagnostics API, no pygls requireddiagnose(source) -> list[Diagnostic]— never raises; runs parse → validate → lower → infer; returnsDiagnosticTypedDicts withline,col,severity("error"|"warning"),message,code("parse"|"semantic"|"shape"|"warn")- Shape errors and activation-footgun warnings from the inference pass are included
CLI Additions
| New command | Description |
|---|---|
kynml sweep <file> [--out-dir dir] [--no-run] |
Expand sweep block, compile all combos, run orchestrator; writes sweep_results.json |
kynml fmt <file> [--write] [--check] |
Format .kyn in canonical form |
kynml lsp |
Start LSP server over stdio |
kynml compile and kynml train accept --param key=value (repeatable) to override params block defaults.
0.2.0 — 2026-06-29
20x expansion of the language surface, CONNECT integrations, and tooling layer.
Language
- New activations:
leaky_relu(→nn.LeakyReLU()),gelu(→nn.GELU()),softmax(→nn.Softmax(dim=1)),log_softmax(→nn.LogSoftmax(dim=1)) alongside existingrelu,sigmoid,tanh,linear - New losses:
huber(→nn.HuberLoss()),l1/mae(→nn.L1Loss()),nll(→nn.NLLLoss()) alongsidemse,bce,cross_entropy - New optimizers:
adamw(lr, weight_decay),rmsprop(lr, momentum)alongsideadam,sgd - New layer types:
dropout P,batchnorm [N]— dropout rate validated in[0, 1), batchnorm infers feature count from prior layer - Schedulers:
step(step_size, gamma),cosine(t_max),onecycle(max_lr)— emitted as fullbuild_scheduler()functions in the generated script - Early stopping:
early_stop(patience=N, mode="min"|"max")— tracks best epoch loss, breaks training loop on exhausted patience - Checkpointing:
checkpoint(every_n=N, path="...", async_save=true|false)— saves{epoch, model, optimizer}state dicts, auto-resumes on next run - Mixed precision:
precision = fp16 | bf16— emitstorch.amp.autocast+GradScalerwith CUDA-availability guard - Graph compilation:
compile = true— emitstorch.compile(model)(requires PyTorch ≥ 2.0) - DataLoader controls:
num_workers,pin_memory,prefetchondatasetblock map directly toDataLoaderkwargs - TorchScript export:
format = torchscriptviatorch.jit.script; alongside existingtorch(state dict) andonnx - ONNX opset:
opsetfield onexportblock (default 17)
CONNECT — Serving
- New sub-package
kynml.serving generate_service(program, model_path, out_dir)emits three files:app.py(FastAPI with/predictand/health),requirements.txt,Dockerfile- Optional extra:
pip install 'kynml[serving]'
CONNECT — MCP
- New sub-package
kynml.mcp python -m kynml.mcp.serverruns a stdio MCP server- Four tools:
kynml_validate,kynml_compile,kynml_train,kynml_predict - Optional extra:
pip install 'kynml[mcp]'
CONNECT — Integrations
- New sub-package
kynml.integrations kynml.integrations.huggingface.load_hf_dataset(dataset_id, split, target)— loads any HuggingFace Hub dataset as a pandas DataFramekynml.integrations.objectstore.load_remote(uri)— Parquet loading froms3://,r2://, or local.parquetpaths- Optional extras:
pip install 'kynml[hf]'and'kynml[objectstore]'
Codegen
- Multiclass detection:
cross_entropyloss automatically switches the generated script tolongtarget dtype andargmax-based metric evaluation - AMP fallback:
precision = fp16 | bf16generates a runtimetorch.cuda.is_available()guard - Async checkpointing:
async_save = truedispatches each checkpoint save on a daemon thread - Dataset path resolution: project root takes priority over
.kynfile directory; both are tried before raising
Test Suite
- 83 tests, all green
pyproject.toml
- New optional extras:
serving,mcp,hf,objectstore,all
0.1.0 — Initial Release
- PyTorch transpiler MVP
- CSV datasets,
normalize,split,shuffle - Dense models:
input,densewithrelu,sigmoid,tanh,linear - Losses:
mse,bce,cross_entropy - Optimizers:
adam,sgd - Scheduler: cosine annealing
- Metrics:
mae,mse,rmse,accuracy - Export:
torch(state dict),onnx - CLI:
validate,ast,compile,train - Static site on Cloudflare Pages at
kynml.kynetra.dev