Changelog¶
All notable changes to mklang are documented here. The format follows Keep a Changelog.
Two version lines are tracked separately:
- Spec version — the language, declared per-file via the
mklang:field (currently"0.3";"0.2"documents remain valid). - Package version — the reference interpreter / tooling, SemVer in
pyproject.toml(currently0.11.0).
[0.11.0] — 2026-07-18¶
Global vs local configuration separation (ADR 0023) — language stays 0.3.
Added¶
mklang doctor— diagnose the resolved setup: winning config file and layer (project / user / system / bundled), schema validation of the resolved config (stale keys surface as warnings), which.envfiles loaded, per-provider key status (active-provider gaps are errors,localexempt), tool backends (search/kb/mail), machine roots with counts, and the state paths. Exit 1 when the active provider cannot run.mklang init --usernow also copiesruntime.schema.jsonnext to the userruntime.yaml(parity with project mode; editor validation works in both).run --hitlwithout--checkpointsuspends into$XDG_STATE_HOME/mklang/checkpoints/instead of erroring; the suspension message prints the generated path.
Changed¶
.envnow layers per key: real environment > project.env> user~/.config/mklang/.env. Previously any project.envhid the user file entirely, even for keys it did not define.mklang-mcpresolves its config through the same chain as the CLI (project → user →/etc→ bundled) instead of pinning the checkout-relative bundled example — MCP clients no longer need an explicit--config.- The console workspace defaults to
./machinesonly when it exists, falling back to the XDG user machines dir seeded bymklang init --user.
Removed¶
- The dead
run:block (max_repair_per_gate,trace) from the example config and its schema: the runtime never read it — repair budgets live in each gate (repair: N, SPEC §7) and the trace is always part of the run result.mklang doctorflags it as a stale key in existing configs. - The legacy
~/.mklang/console/sessionsread fallback: sessions live only under the XDG state root (ADR 0021's migration window is over).
[0.10.0] — 2026-07-18¶
First-run experience (language stays 0.3).
Added¶
- Getting started guide — one linear install → init → key → console path, first in the docs nav.
mklang --version, and a getting-started nudge (exit 0) on baremklanginstead of a usage error.mklang initseedsmachines/with a commentedhello.mksample and itshello.test.yamlscenario script (keyless first run viamklang test).- Upfront provider key gate: runs, the console, and
lint --llmfail fast with the exact.envvariable to set instead of dying inside the provider SDK (localstays exempt). - Shell completions via argcomplete (
[completions]extra). - ADR 0021 phase 3 packaging:
scripts/install.sh(pipx +mklang init --user, with--uninstall) and an Arch Linux recipe inpackaging/arch/; the optional MCP user service is deferred (stdio-only server).
Changed¶
- README install/quickstart restructured: pipx path first, checkout/
uvworkflow kept as the from-checkout section. - Lean sdist: exclude media assets,
site/,demos/,dist/, and.github/from the source distribution (the AUR recipe builds from it).
[0.9.3] — 2026-07-17¶
Documentation-alignment patch (language stays 0.3).
Fixed¶
- Make the best-practices guide the documentation SSOT for current XDG host paths and console lifecycle behavior.
- Align the console session path with ADR 0021 while retaining the legacy path as a documented read fallback.
- Bring the README live-matrix status and roadmap history up to date through the 0.9.2 release, and mark ADR 0015's original path as superseded.
[0.9.2] — 2026-07-17¶
Console shutdown patch (language stays 0.3).
Fixed¶
- Shut down the console cleanly when
Ctrl+Cis pressed during an active run: request cooperative cancellation, release pending human prompts, close the provider client, and wait for the backing thread before returning to the shell. - Prevent late UI callbacks and session writes after console shutdown starts.
[0.9.1] — 2026-07-17¶
Release-pipeline patch (language stays 0.3).
Fixed¶
- Keep fatal CLI diagnostics on one stable line when stdout/stderr is not a TTY.
- Skip the console-session CLI test when the optional Textual extra is absent.
[0.9.0] — 2026-07-17¶
Feature release (language stays 0.3). Every local surface now works outside a repository checkout, preserves automation-safe output, and presents a responsive operational workspace in the terminal.
Added¶
- Responsive console and CLI presentation (ADR 0022). Rich human output with
stable piped JSON, shared diagnostics, responsive inspector/activity layout,
slash-command quoting/suggestions, operational status, cooperative stop, and
additive
run-finishedevents. - ADR 0021 phases 1–2. XDG host paths, bundled config fallback,
idempotent
mklang init, legacy console-session reads, and system/user/project machine discovery with source labels.
Fixed¶
- Connection errors now retry. Provider
_createloops treated only HTTPTRANSIENT_STATUSas retryable; SDK connection failures carry nostatus_code, so a network blip halted the run withprovider-erroron the first try.is_connection_error(matched by class name — the SDKs are lazy-imported) classifiesAPIConnectionError/APITimeoutErroras transient with the same exponential backoff, for both the Anthropic and OpenAI-compat adapters.
[0.8.2] — 2026-07-17¶
Package patch (language stays 0.3). Documentation growth (best practices §12–§13) plus a console glyph fix and a CI test guard.
Added¶
- Best practices §12–§13 — observability (trace vs live events vs process
logging) and filesystem taxonomy (host paths / workspace
.mk/ data tools / no bash in core). Cross-links from console security and patterns.
Fixed¶
- Console activity tree double expand icon. Run rows no longer prefix
▶in the label — Textual Tree already draws the ▶/▼ toggle. - CI: console render tests skip without
rich.test_console_render.pynow usespytest.importorskip("rich")like the other console tests, so the no-console-extra CI matrix collects cleanly.
[0.8.1] — 2026-07-17¶
Package patch (language stays 0.3). Console rendering safety, host wall-clock, and produce system-prompt assembly — surface/host polish only.
Added¶
- Host clock convention
context.now. When a machine declares top-levelnowand it is still empty after inputs, CLI / MCP / console fill a local ISO datetime with offset (same opt-in pattern astoday). Consoleagent.mkdeclaresnowand is instructed to REPLY wall-clock questions from the host values (no AUTHOR for the clock alone). - Produce system prompt assembly (
llm/prompts.py): sectioned system message fromstructure+execution; documented as Best practices §3 (system vs user). Consoleagent.mkputs sticky policy inexecutionand turn data inprompt.
Changed¶
- Console conversation rendering (chrome vs content). Agent replies render
as CommonMark in the log; user/HITL text and slash observations stay plain or
fenced (
json/yaml). Activity tree turn titles, machine names, and output previews use plain styledText(no Rich-markup injection). Helpers live inconsole/render.py; log usesmarkup=False. - Docs: SPEC §4–§6 non-normative notes (produce system/user assembly, host
clocks); Best practices §3; authoring faces table; console brain prompt
assembly; README faces/status; ADR 0016
nowchecklist.
[0.8.0] — 2026-07-17¶
Package feature release (language stays 0.3). Host tools gain a uniform stub
architecture; console anti-cutoff observations stay honest; time-sensitive
machines get a host today convention and richer search.
Fixed¶
- Console
run_machineobservation honesty (anti-cutoff chain). Produce truncation (ADR 0018) is propagated astruncated/finish_reasonplus a compacttracesummary; long results are clipped with an explicit…[truncated]marker andresult_truncated— no more silent 2k cuts that invited the brain to invent the missing tail.
Added¶
- Host convention
context.today. When a machine declares top-leveltodayand it is still empty after inputs, CLI / MCP / console fill the host ISO date (YYYY-MM-DD). Never invents undeclared keys. - Search recency fields (ADR 0016 addendum): optional tool inputs
days/topic; optionalpublished_dateon results (Tavily when provided). - Research / news patterns and
agent.mkinstruct grounding in notes/today and forbid filling gaps with pre-training knowledge; console docs document the observation shape. - Best practices guide (
docs/best-practices.md) — layer discipline, authoring checklist, recommended tool contracts, web/time/cutoff rules, anti-patterns, and what must stay host-side vs candidate language 0.4. - Host tool stub architecture (ADR 0020): shared JSON envelope
(
tool/stub/error) for I/O tools;search_kbandsend_replyuse structured observations; defaultsend_replyhassent: false(no fake delivery); fake backends viaMKLANG_KB_BACKEND/MKLANG_MAIL_BACKENDandconfigure_kb/configure_mail; modulestool_obs,kb,mail. news_searchscenario tests (examples/news_search.test.yaml) — happy path and search-unbound →no_search.- OpenAI-compatible produce defaults
max_tokens=4096when tier params omit it (parity with Anthropic; reduces silent length stops; still overridable / droppable per provider).
Changed¶
- Breaking (host observation shape only): builtin
search_kb/send_replyno longer return free-text[kb stub]…/[sent]…strings — they return ADR 0020 JSON. Scripted scenario tools are unaffected.searchaddstool+stubfields (additive).
[0.7.0] — 2026-07-17¶
Package feature release (language stays 0.3). Console becomes a full operational front door; host tools and runtime budgets close the agent loop.
Added¶
- Console M1–M3 (ADR 0015 Accepted). Agent-first Textual TUI
(
mklang[console]) whose brain is the bundled, user-swappableagent.mk: authoring loop (write → validate → repair), persistent sessions (--continue/--session), budget-exhaustion park//resume, live activity tree, F2 inspector, slash commands. Docs:docs/console.md. - Live engine events on the MCP transport (ADR 0019):
run/resumestreamon_eventasmklang.eventlogging notifications. - Web search tool (ADR 0016 Accepted): structured JSON
searchobservations; offline stub by default; opt-infake/tavilybackends;examples/research_web.mk+ scenario tests. - Output anti-cutoff (ADR 0018 Accepted):
Produced.truncated/finish_reason; trace + events;report|halton CLI (--on-truncate), MCP, console, scripttest. Truncatedparse: list→parse-list-truncated. - Context management Layer 0–1 (ADR 0017 Accepted): judge CONTEXT head+tail
marker; produce-prompt per-value cap; console
history_for_brain; compress patternexamples/research_compress.mk. - LLM-assisted lint (
mklang lint --llm, ADR 0010 Accepted): advisory only.
[0.6.0] — 2026-07-17¶
The language moves to 0.3 (additive; every 0.2 document remains valid) and the agent-facing surfaces land: MCP host, machine stdlib, discovery, authoring guide.
Added — language 0.3 (ADR 0014)¶
parse: list— a generative state can deposit a parsed JSON array (markdown fences tolerated) instead of text; unparseable output halts cleanly withstate-error: parse-list. This makes Plan-and-Execute a pure machine.- Raw whole-template
input:resolution — aninput:value that is exactly one{{path}}placeholder passes the raw context value (lists included) acrosscall:/tool:boundaries; mixed templates render as before. - Conformance cases
parse-list,parse-list-invalid,raw-input-passthrough; the JSON Schema (both copies) gains theparseenum;checkwarns when a 0.2 document uses the new face.
Added — surfaces¶
- MCP server surface (ADR 0011, now Accepted). Optional stdio MCP host —
extra
mklang[mcp], console scriptmklang-mcp— exposing exactly two tools:run(machine as inline.mksource or filesystem path,inputsmerged into the context, optionalcost_budget/hitl) andresume(opaque single-use checkpoint handle, HITL reply injection, new budget). Results return the same{status, error, result, usage, trace, at?}shape the CLI prints. Suspended runs hold their frames in a process-scoped in-memory session store; nothing is written to disk. Core install is unaffected (mcpis not a core dependency). - Public host seam
mklang.host—prepare_path/prepare_source(inline source loading is new) /build_output/set_path, with structuredPrepareErrorinstead of printed diagnostics. The CLI now wraps this seam, so CLI and MCP semantics cannot drift. - Agent authoring guide (
docs/authoring.md) — a compact recipe for writing a correct.mkwith thecheck/lintloop, distilled from SPEC with the real validator messages. - Machine stdlib (ADR 0012). Eight general-purpose architecture machines
bundled with the package —
std_cot,std_self_consistency,std_refine,std_tot,std_debate,std_map_reduce,std_cascade,std_plan_execute— uniform contract (taskin,answerout), each with scripted scenario tests. Present in every host registry with user-always-wins precedence (stdlib ←mklang.machinesentry-point plugins ← siblings ← target, shadowing warned); runnable by name from CLI and MCP (mklang run std_cot --set task="…"); inline MCP sources cancall: std_*. Run-by-name checkpoints record a null machine hash and resume cleanly. Catalog indocs/stdlib.md. - Discovery, check, durable resume (ADR 0013). MCP tools
list_machines/describe_machine(what may be commissioned, with full contracts),check(schema + semantics + lint as structured output, no provider needed), andcheckpoint_pathonrun/resumefor cross-process durable suspensions —resumeaccepts an in-memory handle or a checkpoint file, including files frommklang run --checkpoint; inline sources persist via a new optionalmachine_sourceenvelope key. CLI gains the symmetricmklang machinessubcommand (JSON;--diradds project machines).
Changed¶
- CI runs the unit suite with the
mcpextra (the MCP tests no longer skip silently) and checks/lints the bundled stdlib alongside the examples. - Unknown run-by-name targets fail with the list of bundled machine names instead of a raw errno message.
# noqaannotations removed across the codebase (the suppressed rule was never enabled); explanatory comments remain.
[0.5.4] — 2026-07-16¶
Release-readiness pass. The language stays 0.2 and runtime semantics are unchanged; this release makes the existing interpreter reproducibly distributable.
Added¶
- Trusted Publishing release workflow. A published GitHub Release now gates publication on the full offline suite, strict docs, artifact validation, a clean-wheel installation smoke, and the live provider matrix. The publish job consumes the already-tested artifacts and uses short-lived PyPI OIDC credentials.
- Enforceable live-matrix reporting.
scripts/gate_divergence.pycan require named providers, enforce a minimum agreement rate, write a summary artifact, and distinguishes a missing-key skip from a provider/runtime failure. - Release provenance tests. CI pins package metadata and
mklang.__version__to the same value and tests the required-provider gate offline.
Changed¶
- DeepSeek and OpenAI are the blocking release providers (three divergence runs,
agreement
1.0). Anthropic, Google, OpenRouter, xAI, and Mistral are attempted when credentials are configured and remain informational.
[0.5.3] — 2026-07-16¶
Third remediation pass (Follow-up 003): closes the residue Remediation 002
delivered without declaring. The language stays 0.2; no .mk needs changes.
Added¶
mklang test— deterministic machine testing without API keys (R3-1). A new subcommand runs a machine against a script of named scenarios with a scripted LLM (produce texts + judge picks) and scripted tools/hooks — fully deterministic, no provider or key. Per-scenario PASS/FAIL with a minimal diff (first mismatched key, expected vs actual); exit 0 iff all pass. The scripted LLM,hooks:/tools:bindings, and expectation matcher now live once insrc/mklang/scripttest.py, shared with the conformance runner (all 21 cases green through it, unchanged). Shipsexamples/triage.test.yaml(happy path + KB-empty escalation). Docs: README "Test your machine without API keys",docs/patterns.md,conformance/README.mdcross-reference. CI runsuv run mklang test examples/triage.mk --script examples/triage.test.yamlin the unit-test job (no API keys); the same scenarios are also covered bytests/test_scripttest.pyin the normal pytest run.- Static budget-feasibility check (R3-2).
mklang check/lintnow BFS the shortest path (in states) fromentryto a gateto: END.budgetbelow it is a guaranteedbudget-exhaustedhalt, reported as errorbudget-infeasible;budget < shortest + 2warns (no headroom for a single repair). Fan-out states count as 1 (branch counts are data-dependent), so the check is a lower bound — the message says so. SPEC §7 documents it next to the charging rule. Host pre-validation only; run semantics unchanged. - Dotted second-segment lint on inline context maps (R3-3, completes F7). When
a
{{root.key}}root resolves to an inline dict literal incontext:(ticket: {body: …}), the second segment is now validated against the map's keys, so{{ticket.bod}}is flagged. Skipped for state outputs and runtime roots (human/item/index) whose shape is unknowable; deeper than segment 2 stays out of scope. - Schema-copy identity test (R3-4). One test asserts
schema/mklang.schema.jsonand the packaged copysrc/mklang/data/mklang.schema.jsonare byte-identical, with a failure message naming the sync direction (reposchema/is the source). - ADR 0010 — LLM-assisted lint (R3-5, Proposed, design only). An opt-in
mklang lint --llmthat would generate synthetic outputs and measure gate-selection stability/overlap (reusinggate_divergence.py) to catch ambiguous prosewhenconditions. Documents cost model, determinism caveats, relation to the conformance suite, and why it is out of 0.5.x. No code.
[0.5.2] — 2026-07-16¶
Second remediation pass. The language stays 0.2; no .mk needs changes.
Changed (observable behavior)¶
- Default judge model now follows each state's tier (F1). Previously every
gate — including the highest-stakes gates on
reasoningstates (refund thresholds, legal matters, human escalation) — was judged by the cheapest (fast) model, silently deviating from SPEC §2.1. Gate judging now uses the state's own effective tier by default. This changes which model judges your gates. To restore the previous single-model behavior, set the providerjudge:key in the runtime config — it is now an explicit, opt-in global override, no longer the default (it ships commented out inconfig/runtime.example.yaml). The chosen judge model is recorded in the trace asjudge_modelon everygate_via: llmstep. Gate-divergence numbers collected before this change are not comparable with those after; re-runscripts/gate_divergence.py(now with a--judge-tierflag) to refresh them.
Fixed¶
- Strict judge-reply parsing (F2). The bare-number fallback no longer grabs
the first digit anywhere in the reply (a verbose judge's "Condition 1 fails…"
misread as choice 1). Parse order is now: strict JSON, then a whole-reply bare
number, then the last number in the reply (models conclude with the answer).
The last two are traced as
judge_parse(anomaly-adjacent, not a fallback). The judge system prompt now forbids extra numbers; SPEC §5 constrains conformant judges to terse instruct-style replies. samplebranch diversity (F3). Eachsample: Nbranch now sees its own{{index}}(0-based), so a prompt can say "you are branch {{index}}, take a different approach" (Tree-of-Thought, debate) instead of relying on temperature alone.{{index}}is now available in both fan-out forms;{{item}}remainsover-only.
Added¶
unresolved-interpolationlint rule (F7).mklang lintflags any{{path}}whose first segment nocontext:key / stateoutput:/ (inside a fan-out)item/indexprovides — the silent-typo bug ({{kb_answr}}→ empty string).item/indexreferenced outside a fan-out state are flagged too. First-segment only (dotted tails can't be checked statically); warning by default, error under--strict.--strictrejects unsupportedmklang:versions (F6). An unknown language version stays a warning by default but becomes a hard error (version-unsupported) undermklang check --strict/lint --strict/ the newrun --strict.0600checkpoints (F5). Checkpoint files (full blackboard as plaintext JSON) are written owner-only. SPEC §11 now lists checkpoints as an asset and documents the plaintext-at-rest surface (host-side mitigation; encryption is a v0.2 non-goal). The--checkpointhelp notes the plaintext content.- Conformance coverage for hook precedence and
toolstates (F8). The case format gains scriptedhooks:(boolean sequences) andtools:(list or{input-substring: output}map) bindings, plusexpect.error_prefix. New cases:hook-before-prose,hook-false-falls-through,tool-state-output-deposit,tool-unknown-halts,fanout-sample-index(F3),budget-fanout-charging(F4). Suite: 15 → 21 cases. - SPEC §7 now states the fan-out step-charging rule (
max(1, len(branches))) explicitly, with the map-reduce budget-sizing implication and a worked example;docs/patterns.mdand ROADMAP note the possible v0.3budget/branch_budgetsplit.
Deferred from Remediation 002, delivered in 0.5.3: author-facing scripted testing (
mklang test), budget-feasibility check, dotted-segment lint, schema-identity test, ADR 0010.
[0.5.1] — 2026-07-16¶
Fixed¶
- Judge silent clamp — out-of-range or 0-based
{"choice": k}replies are no longer clamped to a valid gate.parse_choicereturnsNonefor OOR; adapters raiseJudgeUnparseable; the engine does not re-clamp. Soft-fallback tootherwise(or hard-haltjudge-unparseable) is traced viajudge_fallback/judge_raw— never a mute misroute with onlygate_via: llm. - Showcase honesty (
triage.mk) —search_kbandsend_replyare realtool:states (host stubs); generative states no longer claim tool use or “confirm the send.” Same honesty pass onresearch.mk(no fakeweb_search). - README — dropped “no host code required”; documented that tools/hooks are host-supplied; centered conformance + portable spec as the differentiator.
Added¶
- Builtins / entry points:
search_kb,send_reply(deterministic stubs). - SPEC §5 — normative 1-based judge protocol; OOR = anomaly; documented
JUDGE_CONTEXT_CHARS(4000) truncation. - SPEC §11 Threat model (v0.2) — injection surface, partial mitigations, explicit non-goals (declare rather than deny).
- Reference produce temperature defaults documented (non-normative).
- Gate-divergence experiment —
scripts/gate_divergence.py+docs/experiments/gate-divergence.md(cross-provider agreement scaffold). - ADR 0004 honesty note: prose-gate reliability is empirical.
Changed¶
- Positioning: “writable by non-programmers” softened to prose-first / readable; production needs developer judgment for tools, hooks, and untrusted inputs.
[0.5.0] — 2026-07-16¶
Added¶
- Conformance suite (ADR 0009) —
conformance/cases/*.yaml: implementation-neutral cases (machine + scripted LLM + expected outcome) that pin the language semantics; any second interpreter must pass them with its own runner. Reference runner intests/test_conformance.py(15 cases). mklang lint—checkplus static analysis: dead gates afterotherwise, repair-only states, outputs nobody reads (terminal/judged states exempt), template roots nothing provides (--strictexits 1 on findings).- Provider adapters as entry-point plugins — group
mklang.providers(factory(ProviderConfig) -> LLM); builtinanthropic, unknown names fall back to the OpenAI-compatible adapter. Completes the plugin story (tools/hooks/providers). - Gated live smoke tests (
tests/test_live.py) — opt-in viaMKLANG_LIVE=1, provider-agnostic: they run the config'sactiveprovider (override withMKLANG_LIVE_PROVIDER) and skip when its key is missing. All providers, Anthropic included, share the same path — no provider-specific test code. - CI + docs site — extended GitHub Actions workflow (tests, ruff, schema +
semantic checks, lint, build, gated live smoke on main) and an mkdocs-material
site assembled from the repo's canonical markdown (
scripts/build-docs.sh, deployed to GitHub Pages).
Changed¶
- SPEC termination paragraph: the END-reachability validator is enforced (it already was — the prose still said "SHOULD").
- Packaging metadata: classifiers, corrected repository URLs, author contact.
[0.4.0] — 2026-07-16¶
Added¶
- Human-in-the-loop (ADR 0008) — with
--hitl(requires--checkpoint), a firedescalategate suspends at the handler state instead of just routing: the envelope recordsreason: "escalated"andhitl: true. Reply viamklang resume ck.json --set human.reply="…"— values land in the innermost frame's context so the handler can interpolate{{human.reply}}. Library API:run(..., escalate_suspend=True); mutateframes[-1]["ctx"]before resuming. Default off — escalate-as-routing (tier cascades) is unaffected; escalate toENDand fan-out branches never suspend. Language unchanged (spec stays 0.2).
[0.3.0] — 2026-07-16¶
Added¶
- Resumable runs / checkpoints (ADR 0007) — opt-in: with
--checkpoint PATH, budget exhaustion (budget-exhausted/cost-exhausted) suspends instead of halting and writes a JSON checkpoint (frames = blackboard + position + spend percalllevel, machine sha256). New subcommandmklang resume <checkpoint>(--max-tokens,--machine,--force) continues as if uninterrupted — golden round-trip tested, nestedcallincluded. NewRunResultstatus"suspended"withframes; library APIrun(..., suspendable=, resume=); CLI exit code 3. Fan-out branches never suspend. Language unchanged (spec stays 0.2).
Fixed¶
- Docs drift pass: SPEC pseudo-schema includes
hook/hooks:; comparison table and philosophy updated for host hooks; ADR 0002/0004 no longer refer to code-hooks as future-only; ROADMAP test count aligned (~70). - Stale
__version__inmklang/__init__.py(was pinned at 0.2.0).
[0.2.2] — 2026-07-16¶
Added¶
- Code-hook gates — optional
hook: <name>on a gate evaluates a host predicate(context, output) -> boolwithout the LLM (ADR 0006). Top-levelhooks:declarations; CLI builtins (auto_approve_ok, …); examplehook_gates.mk. Trace recordsgate_via: hook|llm|otherwise. - Tool / hook plugin registry — entry-point groups
mklang.toolsandmklang.hooks;load_tool_registry()/load_hook_registry()merge builtins with third-party plugins (later keys win). Documented in CONTRIBUTING / patterns.
Changed¶
- Default runtime provider is DeepSeek (
active: deepseekinconfig/runtime.example.yaml); README quickstart and status aligned. Live smoke re-verified on DeepSeek (expense_approval.mk→done).
[0.2.1] — 2026-07-16¶
Correctness hardening and multi-provider polish on top of the v0.2 core.
Fixed¶
- Sub-machine halt propagation — a
callwhose child halts (budget, fail, …) now halts the parent ascall-failed: <child-error>with nestedsub_trace, instead of continuing asdonewithresult=None. - Judge sees reasoning — when
reason: true, the private chain-of-thought is passed toLLM.judge(SPEC §4.5 / §6), not only recorded in the trace. - Anthropic adapter parity — transient retry with backoff, wrap API failures as
ProviderError, applytemperaturewhen thinking is off, structured JSON judge (sharedparse_choicewith OpenAI-compat). - Pre-run tier validation —
mklang runrejects machines that need a tier missing from the provider map; engine KeyError messages name the missing tier. - Shared
cost_budgetacrosscall— sub-machines inherit the remaining token budget (no unbounded child spend while the parent still looks under budget). - Judge unparseable is no longer silent — adapters raise
JudgeUnparseable; the engine soft-falls back only to an eligibleotherwise(trace:judge_fallback), else halts withjudge-unparseable. overmissing path / wrong type — hard error (empty list still OK per SPEC).- Fan-out branch
callhalt — preservessub_traceand child token usage. - Engine exception-safety (clean
halt, isolated fan-out branches); empty-eligibleno longer crashes;--setaccepts JSON (lists forover);load_registryskips malformed siblings;.envdiscovered from cwd.
Added¶
- Formal
toolstates — a state can invoke a host-registered callable so tool observations re-enter the context (real ReAct, not prose-simulated). Optional top-leveltools:block; built-in demo tools (calc,search). - Cost accounting — per-step token usage in the trace, a run total, and an
optional
cost_budget(haltcost-exhausted). - Error taxonomy —
refusal,provider-error,call-failed,judge-unparseablehalt reasons; typed adapter exceptions (CallFailed,JudgeUnparseable, …). - Structured-output judge — OpenAI-compatible and Anthropic adapters judge via
JSON
{"choice": N}with a regex fallback path inparse_choice. - Per-tier
paramsapplied to the model (effort / thinking / reasoning_effort), best-effort with drop-on-error; pre-run validation inmklang run; richermklang check(dead states, unproducedresult, catch-all warning, version advisory). - Schema bundled as package data;
mklang: "0.2"field; transient-error retry. - Apache-2.0
LICENSE,CONTRIBUTING.md, this changelog. - Quality: golden-trace and cookbook-conformance tests; Anthropic adapter unit tests
(params / refusal / usage / retry / judge). Live Anthropic e2e still deferred
(no
ANTHROPIC_API_KEYin the release environment). Live-tested path remains DeepSeek. - Docs: SPEC header aligned to 0.2; ROADMAP shipped items synced.
[0.2.0] — core v0.2 + reference interpreter¶
Added¶
- Language core v0.2:
reason(traced chain-of-thought),accumulate(list-append), fan-out (sample/over), sub-machinecall, top-levelresult. - Patterns cookbook (
SPEC.md §10) mapping CoT / ReAct / Reflexion / Self-consistency / Tree-of-Thought / Plan-Execute / Debate / Map-Reduce / Router / speculative cascade. - Reference interpreter (
src/mklang/): loader + validator,{{}}interpolation, multi-provider LLM adapters (native Anthropic + generic OpenAI-compatible), run loop, nested trace,mklang run/mklang checkCLI. Live-tested on DeepSeek. - JSON Schema
oneOf {generative | call}; examplesself_consistency,map_reduce(+summarize_doc),react.
[0.1] — language definition¶
Added¶
- The mklang concept: an LLM-driven state machine where each state has four faces
(
structure,prompt,execution,gates), gates are transitions, and the LLM is the runtime. Provider-agnostic capability tiers (fast/balanced/reasoning). SPEC.md, JSON Schema, multi-provider runtime config, examplestriage,research,expense_approval.