Loading episodes…
0:00 0:00

One Artifact, Three Consumers

00:00
BACK TO HOME

One Artifact, Three Consumers

10xTeam May 22, 2026 6 min read

tags: [testing, scenarios, nl-testing, studio, design, artifacts, composability, dar-test] related:

  • packages/studio/server.js
  • packages/studio/public/studio.js
  • packages/testing/nl-runner.js
  • packages/studio/tests/scenarios.test.js status: current —

025 — One Artifact, Three Consumers


A scenario in DarJS looks like this:

{
  "name": "vente-produit",
  "actor": "owner",
  "steps": [
    { "action": "create", "model": "Product", "data": { "name": "Café Noir", "price": 3.50 },
      "nl": "create a product called Café Noir priced at 3.50" },
    { "action": "transition", "model": "Order", "to": "confirmed",
      "nl": "confirm the order" }
  ]
}

Three different systems read this file:

  1. dar test — the structural E2E runner. It reads action, model, data, and to. It makes HTTP requests, follows model transitions, and validates the database state at each step.

  2. The NL Playwright runner (executeNlStep). It reads the nl field. It parses each step as natural language, resolves the selector from the UI contracts index, and drives the browser.

  3. A business owner reading the Studio scenario panel. They read the name, the actor, and the nl labels. They see: “owner creates a product called Café Noir, then confirms the order.”

The same file. No conversion between consumers. Each one reads what it needs and ignores the rest.


How Most Test Formats Are Designed

Most test formats are designed for one consumer. Playwright tests are designed to be run by Playwright. Jest tests are designed to be run by Jest. Cypress tests run in the Cypress runner. They are not designed to be read by a business owner, or to be executed by an HTTP-based structural runner, or to serve as documentation.

This is reasonable. The primary job of a test is to be executed by the test runner. Secondary readability is a nice property, not a design goal.

The consequence is that when you need multiple consumers — a structural runner and a browser runner and human readability — you write multiple representations. A tests/ folder for the structural runner. A playwright/ folder for the browser tests. A separate spec document for stakeholders. Three files describing the same flow. Three places to update when the flow changes.


The nl Label as the Hinge

The nl field is the design decision that makes one artifact serve three consumers.

Without it, the JSON is purely structural. Machines can run it. Humans can read it with effort. But a business owner looking at { "action": "transition", "model": "Order", "to": "confirmed" } sees framework mechanics, not a business operation.

The nl label translates the mechanical step into intent. “confirm the order” is what the business owner means. { "action": "transition", "model": "Order", "to": "confirmed" } is what the framework does. Both are true. Both live in the same step.

For the structural runner, nl is an ignored field — it passes through without reading it.

For the NL Playwright runner, nl is the primary input — it drives the selector resolution and Playwright action.

For the human, nl is the readable description — the story of what the step does in plain language.

The cost of adding nl: one field per step, written once by the author who knows both the intent and the implementation.


Why This Matters for Agentic Workflows

An AI writing a scenario can trivially fill both the structural fields and the nl label. It knows the model structure (it may have just created the models). It knows what the business wants (that’s what it was asked to build). Writing both is not extra work — it’s the same knowledge expressed twice.

What the AI cannot do is maintain three separate files. If the model structure changes, the structural test needs updating, the Playwright test needs updating, the spec document needs updating. Three places to remember, three places to miss.

One file with both the structure and the language collapses the maintenance surface. When the model changes, one file changes. All three consumers get the update automatically.


The Studio Scenario Designer

The Studio scenario panel builds these files visually. A business owner who doesn’t know what "action": "transition" means can:

  1. Select a model from a dropdown — the step’s model field
  2. Select “transition” from the action dropdown — the step’s action field
  3. Select “confirmed” from a state dropdown — populated from the model’s actual workflow states
  4. Type “confirm the order” in the nl input — the step’s nl field

They’re filling a form. The JSON is an output they never see. The structural fields come from the UI (model knowledge, workflow knowledge). The nl label comes from them — the one input only a human with business context can provide.

The resulting file is immediately runnable by dar test and by the NL runner. The business owner described the workflow. The machines can execute it.


The Broader Pattern

The nl-plus-structure design is one instance of a general pattern: fields that serve different consumers at different layers of the stack.

A database schema has created_at (for the application), id (for foreign keys), and display_name (for the UI). All in one row. Each consumer reads the field it needs.

An HTTP response has a status code (for the client code), a body (for the application logic), and headers (for caching, authentication, content negotiation). One response, multiple consumers reading different parts.

The design question for any data artifact is: who reads this, what do they need, and can I include all of it without conflict?

For scenarios, the consumers are the structural runner, the NL runner, and the human. Their needs are action/model/data/to, nl, and nl. Two of three consumers want the same field. The overlap is the hinge — nl simultaneously serves the automation and the human.

When you design an artifact for one consumer, you get one use. When you design it for multiple consumers by identifying each consumer’s natural field, the same artifact pays off at every layer it touches.


Join the 10xdev Community

Subscribe and get 8+ free PDFs that contain detailed roadmaps with recommended learning periods for each programming language or field, along with links to free resources such as books, YouTube tutorials, and courses with certificates.

Audio Interrupted

We lost the audio stream. Retry with shorter sentences?