# The program builder

Build, test and publish programs in the panel: visually or in JSON, by recording, by picking on live pages and stored snapshots.

The program builder edits one program as two views of the same document: a step list and the
program's JSON, side by side. It records what you do in a real browser, picks fields on live and
stored pages, test-runs the draft and publishes it, without a builder-only format: what it saves
is the same [program JSON](https://docs.kaab.ist/concepts/programs-and-versions) the API stores.

## When to use it

Use the builder to create a program from a site you can see, to try a change against a real page
before publishing it, and to fix a program a proposal could not. If you keep programs as files in
a repository, edit them there and push them with the [CLI](https://docs.kaab.ist/guides/cli); the builder's **Export**
and **Import** move a definition between the two.

## The screen

Open it from a program's page with **Open builder**.

**The header** shows the program's name, a badge for the version you are editing (*draft vN*, or
*new draft*) and the save state: "Saved", "Unsaved changes", "Saving…", or "Saved locally: fix
lint errors to save the draft". On the right: undo, redo, **Export**, **Import**, **Save draft**
and **Publish**, which stays disabled until the draft lints clean. If someone publishes a version
while you edit, a warning says so.

**The left column** has four tabs:

- **Steps**: the program as cards, one per step, each with a drag handle, a summary and badges
  (*side effect*, *checkpoint*, the `expect`, the number of lint findings). A **+** between two
  cards adds a step from a menu grouped into Navigate, Interact, Wait, Data, Session & input,
  Control and Other. An open card shows the action's form and, under **Step settings**, the step's
  id, name, timeout, what to do on error, and the *Side effect*, *Optional* and *Retry* settings.
- **Inputs**: each input with its type, whether it is required or may be stored, its default,
  description and limits.
- **Options**: the starting and highest tier (the highest your plan allows is shown), credit, step
  and duration limits, region, locale, time zone, viewport, asset blocking, cache, session and
  proxy.
- **Policies**: strict mode, raw values, what to do on an expired session or a captcha, and when
  to keep screenshots.

**The right column** has five tabs: **JSON** (an editor of the whole program), **Lint** with the
number of findings, **Browser**, **Stored page** and **Test**. It widens for the browser tabs and
can take the full width.

## Steps, inputs, options and policies

Every action of the program language has a form: targets with their ranked candidates and a
uniqueness check against the page you have open, conditions built from parts (`all`, `any`, `not`,
landmarks), extract fields with types, parse settings, constraints and transforms. `when` and
`loop_until` show their blocks as lanes; `paginate` shows the fields it extracts on every page.

Whatever you change in one view shows in the other at once. JSON that does not parse is pointed out
by line, and the step list keeps showing the last valid version until it parses again.

Lint runs as you type. **Lint** lists each finding with its code, message and path, and clicking one
opens that step; "The program lints clean." when there is nothing. Errors block publishing;
warnings say what they mean. Undo and redo cover both views (`Ctrl+Z`, `Ctrl+Shift+Z`). Your work is
kept in the browser as you go, and saved to the server as the program's draft version after 30
seconds without an edit, whenever it lints.

## Recording and picking

**Browser** opens the page in a real browser in the cloud, going out through the same network as a
run of the program. In *Navigate* mode what you do is recorded as steps: the recorder proposes
checks (`expect`) to add, asks you to declare secret inputs for passwords (which are never
recorded) and offers to ask for one-time codes when the program runs. In *Pick* mode, a click fills
in the target or the field you asked to pick; **select similar** turns one item of a list into a
list field. See [picking and recording](https://docs.kaab.ist/panel/picking-and-recording).

**Stored page** does the same on a page a test run kept, with nothing on it running: extraction can
be tried there instantly in your browser, and on the server for the authoritative answer.

## Testing

**Test** runs the draft as it is now, for free, against your daily test quota: **Run all**, **Run to
here** (stop after the selected step) and **Run step** (from the last checkpoint before it). The
**Dry run** switch stops before the first step marked as a side effect. The tab also holds a
test value for each of the program's inputs.

The timeline shows each step's status, duration and badges (*healed*, *obstacle*); open a step to see
its screenshot and **Use this page in the picker**. When the run asks for a value, the timeline says
what it is waiting for and offers **Send**; when it needs a person, it offers a takeover; when it
succeeds, the data appears below.

## Staying signed in

A program that signs in can keep the session: end the sign-in with a **checkpoint** that saves a
session (`save_session`), and set **Options → Session** to that name with **Resume from the stored
session** on. Later runs start after the checkpoint while the session works. If the site has ended
it, the first page lands on its login form; the run notices and signs in again from the first step,
which saves the session anew. Declare the program's `login_page` landmark (a condition that holds
on the login form) so this works on sites whose login page has no telling URL.

## Publishing

**Publish** opens "Publish a new version": the lint result, what changed since the current version,
what a run costs and the tier it starts at, which fields still lack ground truth, a notes field,
and checkboxes to move other aliases (say, `production`) to the new version too. Each program page
lists its versions, their diffs and its aliases.

The same alias move from code:

### TypeScript

```ts
// `production` moves only when you say so: here it stays on version 1.
const aliased = await kaab.programs.aliases.set(program.id, "production", { version: 1 });
console.log(`aliases: ${JSON.stringify(aliased.aliases)}`);
```

## Worked example

Build a product program for a shop's product page:

1. **Programs → New program**, name it `shop-product`, choose **Blank**, and open the builder.
2. Add a **Go to URL** step with `https://shop.example.com/p/1`, then an **Extract** step.
3. In **Test**, press **Run all**. When it succeeds, open the `goto` step in the timeline and
   choose **Use this page in the picker**: the stored page opens in **Stored page**.
4. In the extract step, add a field `title` and press **Pick**, then click the heading on the
   stored page. Add `price`, pick the price, and set its type to money with locale `tr` and
   currency `TRY`. The field's sample shows `1.337,40 TL`.
5. **Run here** extracts in your browser: `title` is "Kulaklık Klasik 101" and `price` is
   1337.4 TRY. **Test on the server** gives the same answer.
6. **Publish**: lint is clean, every field has ground truth, and version 1 becomes `latest`.

To record a sign-in instead, open **Browser** on a login page such as
`https://portal.example.com/login`, choose **Record**, and sign in: the recorder suggests a secret `password` input and an "ask for it when the program runs"
step for the one-time code. **Run to here** on the step after the login stops there and shows the
dashboard's screenshot.

## Pitfalls

- **Publishing without ground truth.** A field you never confirmed on a page has nothing for the
  healer to compare with when the site changes. The publish dialog lists them.
- **Testing a side effect for real.** **Run all** performs side-effect steps; switch on **Dry run**
  until you mean it.
- **Lint errors stop the server save.** Your work stays in the browser ("Saved locally") until the
  draft lints; another device does not see it.
- **Editing while someone publishes.** Heed the warning and reload before you publish over their
  version.

## Reference

- [DSL reference](https://docs.kaab.ist/reference/dsl) and [lint codes](https://docs.kaab.ist/reference/dsl/lint)
- [Create a program version](https://docs.kaab.ist/reference/api/programs/create-program-version),
  [publish a version](https://docs.kaab.ist/reference/api/programs/publish-program-version),
  [set an alias](https://docs.kaab.ist/reference/api/programs/set-program-alias)
