EKOS — Enterprise Knowledge Operating System

Reproduce legacy ETL logic.
Verified, not guessed.

A Pentaho step, a SQL SELECT, a VIEW, and a stored procedure are all the same underlying idea — a transformation of data from sources to a sink. EKOS compiles all of them into one shared, evidence-backed representation, so an AI agent can explain what a legacy pipeline does and prove a migration didn't change its meaning.

Pentaho .ktr/.kjb+ SQL SELECT · VIEW · procedure Transformation IR Ledger ekos_transformation_explain / diff Claude / any agent
§ 01 / problem
Why this exists

1000+ repos. Four data platforms. One Pentaho job nobody wants to open.

A developer needs to reproduce an existing Pentaho job's business logic in a new pipeline — with one rule changed — across an estate spanning GitHub, PostgreSQL, Databricks, Synapse, an Informix database with no source repo, an outdated Confluence, and legacy Kettle ETL. Today that means manually reading .ktr/.kjb XML and hunting for tribal knowledge in Confluence.

  • TodayRead the XML by hand, guess at what a step means, hope Confluence still describes it.
  • MissingOne representation that a Pentaho step, a SQL query, and a stored procedure all compile into — so they can be compared.
  • EKOSCompiles every format into a shared Transformation IR once, evidenced, queryable, diffable.
§ 02 / architecture
The Transformation IR

Seven node kinds. Every format compiles into them.

Building a separate extraction path per format would produce N incompatible semantic models that can't be diffed against each other — which defeats the point. So everything maps into one intermediate representation first.

§ 03 / observe
Stage 1 — Parsing, deterministically

Parsing an XML file is still a fact. Labeling its business meaning isn't.

Two independent parsers compile into the same TransformNode enum — a Pentaho XML DOM walker (roxmltree) and a SQL AST walker (sqlparser-rs, Postgres/T-SQL/Databricks dialects). The same bytes always parse to the same graph, with zero judgment calls — that's what keeps this a deterministic compiler pass, not an LLM guess.

  • Stored procsEmbedded SQL statements become real IR fragments; surrounding control flow becomes Unmapped, honestly.
  • CoverageReported per file as a percentage — how much of a legacy job maps to real nodes vs. unresolved gaps.
crates/semantic/transform_ir.rs
pub enum TransformNode {
    Source { object_name: String, columns: Vec<String> },
    Filter { condition: String },
    Join { left: NodeId, right: NodeId,
           keys: Vec<(String, String)>, kind: JoinKind },
    Aggregate { group_by: Vec<String>, aggs: Vec<AggExpr> },
    Calculate { output: String, expr: String },
    Sink { object_name: String, columns: Vec<String> },
    // deliberate — never a silent drop
    Unmapped { raw: String, reason: String },
}
§ 04 / explain
Ask what a legacy job does

ekos_transformation_explain — every claim cites its source.

Point the tool at a pipeline's Sink and it walks the chain of real IR nodes feeding into it, root-first, rendering each into a plain-English step with the exact source fragment behind it. Unresolved steps are surfaced by name — ⚠ not understood — not silently omitted.

  • No XMLThe agent never opens the .ktr file — every fact comes through this one tool.
  • ReusesThe same graph-walking primitive already powering blast-radius analysis (RFC 0018) — no new traversal engine.
ekos_transformation_explain(id)
{ "node_type": "Filter",
  "summary": "filters rows where status = 'active'",
  "evidence": [{ "source": "load_customers.ktr",
                 "fragment": "status = 'active'",
                 "confidence": 1.0 }] }
§ 05 / diff
Prove the migration is safe

ekos_transformation_diff — exactly what changed, nothing more.

Draft the new pipeline, then diff its Sink against the original's. Sources, filters, joins, aggregates, and calculates are bucketed and compared as sets — not by position, since a pipeline can reorder independent steps without changing meaning.

ekos_transformation_diff(old_id, new_id) — one rule added
"sources": { added: [], removed: [] }   // unchanged
"sinks":   { added: [], removed: [] }   // unchanged
"filters": {
    removed: ["status = 'active'"]
    added:   ["status = 'active' AND region = 'EU'"]
}

Verified end to end against a real benchmark: a two-source, filtered, joined, calculated Pentaho job redrafted as SQL with one changed rule — 100% coverage, zero Unmapped nodes, and the diff isolated exactly the one rule that changed.

§ 06 / identity
The same table, three names

A hypothesis until confirmed — never a silent merge.

Informix cust_mstr, Postgres customers, Databricks gold.dim_customer — the same real-world entity, three different names, three different systems. ekos identity scan scores candidate matches on column overlap, naming-pattern similarity, and type compatibility, and writes each one as an unconfirmed relationship.

  • Never automaticEven a 0.95-confidence match stays unconfirmed until reviewed — a wrong silent merge corrupts every downstream answer.
  • Confirm/rejectekos_identity_review — the one write-capable MCP tool, scoped to exactly this relationship kind.
§ 07 / guarantees
Why an agent can trust it

Four guarantees no LLM summary gives you.

Hypothesis ≠ fact

A candidate cross-system match carries an explicit unconfirmed status — structurally distinguishable from an observed fact, never indistinguishable.

Evidence per step

Every claim in an explanation cites the exact source file and fragment it came from — nothing is asserted without a citation.

Unmapped is signal

What can't be parsed is recorded as "something is here, not yet understood" — never dropped, never presented as a complete answer.

Deterministic, append-only

The same source re-parsed twice gets the same id; a re-parse that changed is a new version, never an in-place rewrite.

Try it

Point an agent at the pipeline. Not the XML — the compiled logic.

terminal
# compile every .ktr/.kjb and SQL file once
$ ekos build && ekos recover && ekos resolve && ekos compile && ekos commit

# link the same entity across systems (optional)
$ ekos identity scan

# serve it to any MCP client over stdio
$ ekos mcp serve --workspace .
MCP toolAnswers
ekos_transformation_explainWhat does this legacy pipeline actually do, with evidence
ekos_transformation_diffDid my redraft preserve the original logic
ekos_identity_reviewConfirm/reject a cross-system identity match
EKOS · RFC 0027 (Transformation IR) + RFC 0028 (MCP tools) + RFC 0029 (Cross-system identity) · github.com/alexeyban/EKOS