Lambe 0.4.0: drop XML, bare pipeline ops, MCP surface fixes#1
Merged
Conversation
Breaking:
- Remove XML input/output support. The xmlToNative projection silently
collapsed repeated sibling elements (last-wins map semantics) and dropped
attributes entirely, producing wrong query results with no indication.
Rather than ship a footgun, XML is dropped pending a proper projection
design. The rumil XML parser itself is unchanged and remains spec-
compliant.
MCP surface:
- Add output_format parameter to lambe_query so agents can request
yaml/toml/csv/tsv/hcl output, matching the --to CLI flag.
- Expose csv, tsv in all three MCP format enums (library already supported
them; MCP surface was the gap).
- Rewrite tool descriptions and instructions to document common pitfalls:
&& / || for boolean logic, bracket syntax for hyphenated keys, pipeline
ops requiring a leading |, group_by returning [{key, values}].
- MCP server now reports its actual version via build-time-generated
lib/src/_version.dart (was hardcoded 0.1.0).
Quality gates:
- tool/gen_version.dart reads pubspec.yaml and writes lib/src/_version.dart.
Release workflow runs it before compile.
- test/doc_examples_test.dart extracts every lambe expression from AI.md
code blocks/tables and from every Dart string literal in mcp_server.dart,
then parses and evaluates each against a fixture. Catches phantom
features in docs (e.g., LLM-drafted examples advertising unimplemented
syntax) at CI time.
Bug fixes:
- Remove phantom `..` (recursive descent) from docs. The operator was
advertised in AI.md and MCP instructions as a Markdown pattern but was
never implemented.
- Fix broken AI.md example: filter(has("resources") == false) required
filter((. | has("resources")) == false) since has is a pipeline op.
Tests: 525 pass (491 + 34 extracted doc examples).
Admit _pipeOp into _atom so has("k"), length, keys, filter(...), map(...)
and every other pipe op can appear as standalone expressions.
Semantically equivalent to ". | op" — the evaluator already treats ops as
LamExpr subtypes; the parser was the only thing blocking it. Placed last
in the _atom alternation so existing constructs (object shorthand
{length}, field access .length, string interpolation "\(length)") keep
their prior meaning.
Unblocks shapes agents and users reach for naturally:
has("users") ≡ . | has("users")
length ≡ . | length
.users | map(has("email")) ≡ .users | map(. | has("email"))
.lists | filter(length > 2) ≡ .lists | filter(. | length > 2)
MCP instruction block updated: the "pipeline ops must follow |"
prohibition is gone (it was never true at the evaluator level, now not
true at the parser level either). The AI.md workaround
filter((. | has("resources")) == false) reverts to the cleaner
filter(has("resources") == false).
Housekeeping pass on the prior commit's code:
- drop the // ---- Tool: X ---- section banners from mcp_server.dart
(not used elsewhere in the codebase)
- trim inline "what this does" comments in doc_examples_test.dart; add
/// docs to every private helper per repo convention
- update the _atom grammar comment in parser.dart to reflect the new
alternatives
Tests: 547 pass (525 + 22 new bare-op tests).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
xmlToNativeprojection silently collapsed repeated sibling elements (last-wins map semantics) and dropped attributes entirely, producing wrong query results. Rather than ship a footgun, XML is removed pending a proper projection design (auto-arrayify siblings, preserve attributes). The rumil XML parser itself is unchanged and spec-compliant..input.has("k"),length,keys,sum,filter(...),map(...)— standalone or insidemap/filter. Equivalent to. | op. One-line parser change; 22 new tests.pubspec.yamlvia build-time-generatedlib/src/_version.dart(was hardcoded0.1.0). CSV and TSV exposed in all threeformatenums (library already supported them). Newoutput_formatparameter onlambe_queryfor yaml/toml/csv/tsv/hcl output, matching the--toCLI flag. Tool descriptions rewritten to document real pitfalls (&&/||, bracket syntax for hyphenated keys,group_byshape).test/doc_examples_test.dartextracts everylam '...'fromAI.mdand every embedded query from the MCP server's Dart string literals (34 expressions), and asserts each parses. Prevents phantom-feature drift where LLM-drafted examples advertise syntax the parser doesn't implement...(recursive descent) removed from docs. It was advertised as a Markdown query operator but was never implemented.filter(has("resources") == false)example — which now works on its own merits thanks to the bare-op change.Breaking
Format.xml,OutputFormat.xml, and XML extension detection (.xml,.pom,.csproj,.svg) removed from the library.--format xml/--to xmlCLI flags and the:to xmlREPL command no longer accepted.Non-breaking additions
lambeVersionexported frompackage:lambe/lambe.dart.output_formatparameter on thelambe_queryMCP tool.csv,tsvin all three MCPformatenums.tool/gen_version.dart+ release workflow step.Test plan
dart analyze lib bin test tool— no issuesdart test— 547 pass (was 491 on main; added 22 bare-op tests + 34 doc-example tests)Out of scope
Format.delimitedto unify CSV/TSV under the delimited parser (deferred — the currentcsv/tsvsplit preserves a useful dialect-detection escape hatch).