"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.AuthoringGuideResources = void 0;
const OVERVIEW_URI = 'mabl-author://overview';
const SELECTOR_FIELDS_URI = 'mabl-author://selector-fields';
const SAVE_TOOL_MECHANICS_URI = 'mabl-author://save-tool-mechanics';
const AUTHORING_PATTERNS_URI = 'mabl-author://authoring-patterns';
const OVERVIEW_CONTENT = `# Hand-authoring mabl tests

You are writing test JSON yourself instead of having the cloud agent author
it. This is the right path when you know what the flow should look like and
want a deterministic test built from rules rather than from a trainer's live
page rendering. You pay for that by not having live xpath / bounding_*
fingerprints — you have to lean on \`locator\` + \`description\` and the
visual resolver to find elements at run time.

## Entry-point decision

| You want…                                                                  | Use                                                                                                                            |
| -------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| The cloud agent to render the page and capture trainer-quality selectors   | \`create_mabl_test_cloud\`                                                                                                     |
| To record on a real page yourself                                          | The mabl trainer (record in the mabl web app)                                                                                  |
| To create or edit test JSON directly because you know the structure        | This guide — \`mabl_create_test\` / \`mabl_create_flow\` for new tests; \`mabl_save_flow_steps\` / \`mabl_save_test_steps\` for edits |

If you don't have a \`test_id\` + \`flow_id\` to overwrite yet, call
\`mabl_create_test\` (for a new test, with optional \`initial_flow.steps\`
in the same call) or \`mabl_create_flow\` (for a new reusable flow).
Both pre-validate the steps before any side effects.

---

## Test structure

Before writing individual steps, think about how to group them. A sequence of
clicks that adds an item to a cart, or eight field-fills plus a submit click
that completes a form, is one conceptual action — not eight unrelated atoms.
Wrap conceptual actions in \`StepGroup\` with an \`intent.description\` that
names the goal in plain language. Failure analysis, run summaries, and future
readers all consume that intent text; without it they only see the mechanics.

See \`mabl-author://authoring-patterns\` for the full rationale, examples,
and the step-group vs reusable-flow split.

---

## The findTarget shape decision

**Always author new findTargets in the wrapped form**:
\`findTarget: {selector: {uuid, locator, description}}\`. The runtime's
canonical read path is \`findTarget.selector.locator\` and
\`findTarget.selector.description\` — flat \`findTarget.locator\` and
\`findTarget.description\` are rejected by the validator because they
silently fail at run time.

The schema also accepts three **legacy unwrapped shapes** kept only for
backwards-compatible read paths on older flows. The validator emits a
\`semantic.findtarget_unwrapped\` warning whenever a step uses one;
strict mode promotes that warning to an error so agent-authored output is
forced to the wrapped form exclusively.

| Shape                                                                                              | Status                                                          | Notes                                                                                                                          |
| -------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **Wrapped** \`{selector: {uuid, locator, description}}\`                                           | **Canonical** for new authoring                                  | Locator + description drive the modern resolver. Optional \`find_prompt\` aliases \`description\`.                            |
| Wrapped trainer-shape \`{selector: {uuid, xpath, id, class_name, ...}}\`                           | Legacy read path. Only appears on flows captured by the trainer | Attribute fields require \`xpath\` as the structural anchor for the legacy attribute-scoring resolver.                          |
| Unwrapped legacy SimpleElementSelector \`{uuid, xpath, id, class_name, ...}\` (no \`selector\` key) | Legacy read path. Warned (warning → error under strict mode)     | Older trainer captures saved this shape directly under \`findTarget\`. Do not author new finds this way.                       |
| Custom CSS \`{css_query: "..."}\` (paired with \`find_first\`/\`find_last\`/\`find_all\`)      | Legacy raw-CSS path. Warned                                     | Resolved by the legacy query path. No new-shape resolution.                                                                    |
| Custom XPath \`{xpath: "..."}\` (paired with \`find_first\`/\`find_last\`/\`find_all\`)        | Legacy raw-XPath path. Warned                                   | Resolved by the legacy query path. No new-shape resolution.                                                                    |

**The structural trap to avoid.** Because the SimpleElementSelector branch
lists \`locator\` and \`description\` as optional fields, an earlier shape
of the schema would accept \`{uuid, locator, description}\` flat under
\`findTarget\`. That shape silently fails at run time — the runtime reads
\`findTarget.selector.locator\` and finds nothing. The validator now
rejects flat \`findTarget.locator\` and flat \`findTarget.description\`
outright, with a redirect to the wrapped form.

Inside the wrapped form, the schema enforces a clean split between
**pure new-shape** (just \`{uuid, locator, description}\` and optionally
\`find_prompt\` — no attribute fields) and **trainer-shape**
(\`xpath\` plus any of \`id\`, \`class_name\`, \`name\`, \`tag_name\`,
\`data_*\`, \`aria_*\`, \`bounding_*\`, etc.). The middle ground —
attribute fields populated without \`xpath\` — is rejected because the
legacy resolver has no structural anchor to score against.

**If you're authoring blind (no browser session), stay in pure new-shape.**
Don't paste in \`id\` or \`class_name\` values you copied from source code
without also recording the corresponding \`xpath\`. The schema will reject
it, and even if it didn't, the legacy resolver has nothing to anchor on.

### Worked example: a single Click step

\`\`\`json
{
  "Click": {
    "find": {
      "findType": "find_one",
      "findTarget": {
        "selector": {
          "uuid": "login-submit",
          "locator": "button:has-text(\\"Log in\\")",
          "description": "Primary 'Log in' submit button on the login form"
        }
      }
    },
    "description": "Submit the login form"
  }
}
\`\`\`

For \`locator\` syntax, \`description\` good/bad examples, and \`uuid\`
reuse semantics see \`mabl-author://selector-fields\`.

## Variable conventions

Test variables substitute at run time. Reference them inside string fields
with \`{{@...}}\`. The canonical namespaces below are universal — they are
not workspace-dependent. The runtime populates them automatically for
every browser (or API) test.

Canonical system variables (use these in new authoring):

| Variable                                       | Source                                                                                                   |
| ---------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
| \`{{@web.defaults.url}}\`                      | Environment URL on the application                                                                       |
| \`{{@web.defaults.credentials.username}}\`     | \`credentialsId\` passed to \`run_mabl_test_cloud\`                                                      |
| \`{{@web.defaults.credentials.password}}\`     | \`credentialsId\` passed to \`run_mabl_test_cloud\`                                                      |
| \`{{@web.defaults.test_run_id}}\`              | Current test run id (populated by the runtime)                                                           |
| \`{{@api.url}}\`                               | Environment URL — API test equivalent of \`web.defaults.url\`                                            |
| \`{{@api.credentials.username}}\`              | API test equivalent of \`web.defaults.credentials.username\`                                             |
| \`{{@api.credentials.password}}\`              | API test equivalent of \`web.defaults.credentials.password\`                                             |
| \`{{@flow.<name>}}\`                           | Reusable-flow parameter (caller-supplied via \`EvaluateFlow.config.parameters\`, else \`default_value\`) |
| \`{{@user.<name>}}\`                           | User-defined test variable                                                                               |

### Faker generators for per-run values

Faker variables produce fresh values on every run without hardcoding. Use
them for anything that should not collide across runs:

| Pattern                          | Produces                                            |
| -------------------------------- | --------------------------------------------------- |
| \`{{fake.internet.email}}\`      | Throwaway email address                             |
| \`{{fake.name.firstName}}\`      | Person first name                                   |
| \`{{fake.name.lastName}}\`       | Person last name                                    |
| \`{{fake.uuid}}\`                | Random UUID                                         |
| \`{{alnum:N}}\`                  | Random alphanumeric string of length N              |

### Capture-early discipline

When a step creates server-side state — an order, a record, a confirmation
number, anything with a generated id — capture the generated value into a
\`{{@user.<name>}}\` variable on the step that produces it. Downstream
assertions and interactions reference the captured variable, not the
literal value you saw the first time. Literals work on the first authoring
pass and fail on the second replay when the data has changed.

Anti-patterns:

- Hardcoded emails, usernames, or passwords for sign-up flows — use
  \`{{fake.internet.email}}\` or \`{{alnum:N}}\` instead.
- Hardcoded order numbers, timestamps, or generated ids in assertions —
  capture-then-assert against the captured variable.
- Hardcoded dates that are only valid on the day the test was written —
  compute a relative date at run time (\`RunJavaScript\` step writing into a
  user variable) or use a faker pattern.

Humanized aliases (accepted, but the trainer rewrites them to the
canonical form on save; the runtime also has fallback canonicalization,
so legacy authoring still resolves):

| Alias                              | Canonical equivalent                              |
| ---------------------------------- | ------------------------------------------------- |
| \`{{@app.url}}\`                   | \`{{@web.defaults.url}}\`                         |
| \`{{@app.defaults.username}}\`     | \`{{@web.defaults.credentials.username}}\`        |
| \`{{@app.defaults.password}}\`     | \`{{@web.defaults.credentials.password}}\`        |

Recommendation: author in the canonical \`web.defaults.*\` form. That is
what the trainer persists, what existing tests use, and what the cloud
MCP save tools may auto-canonicalize to in the future.

The system-default variable names above are the same in every workspace —
do not read an existing test to discover them. To learn what
**user-defined** variables (\`{{@user.<name>}}\`) a workspace has, call
\`get_mabl_tests\` on a passing test and read its
\`annotatedStepDescriptions\` — it reveals the \`{{@user....}}\` and
\`{{@flow....}}\` patterns that workspace actually uses.

## The validate -> save -> run loop

\`\`\`
1. mabl_get_schema_resource(uri: "mabl-schema://step/<Type>")        # per-step shape
2. Compose steps[] as plain objects
3. mabl_validate(steps, testType: "browser")                         # pure structural check
4. mabl_save_flow_steps(flow_id, test_id, mode: "whole", steps[])    # or mabl_save_test_steps
5. run_mabl_test_cloud(testId, workspaceId, envId, appId,
                       credentialsId, browsers: ["chrome"])
6. get_latest_test_runs(testId)                                      # poll until terminal
7. analyze_failure(runId, testOrPlan: "test")                        # on failure
\`\`\`

For which save tool to use, when \`test_id\` is required on a save, and
what the common save-error codes mean, see
\`mabl-author://save-tool-mechanics\`.

## Common failures and what they tell you

| Symptom                                                                          | Likely cause                                                                                | Action                                                                                                                       |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| \`mabl_validate\` rejects with \`xpath\` required                                | Attribute fields (\`id\`, \`class_name\`, etc.) mixed into a wrapped selector without \`xpath\` | Add \`xpath\`, or remove the attribute fields to keep it pure new-shape                                                      |
| \`mabl_validate\` rejects "at least one of xpath/locator/description"            | Empty descriptor                                                                            | Add a \`locator\` and/or \`description\`                                                                                     |
| Runtime "Did not find element expected to be present" on the first step          | Locator didn't resolve and the description-driven visual fallback didn't engage             | Verify the locator with a quick page inspection; tighten or simplify; ensure your account is on a runtime that supports the new-shape resolver |
| Runtime "invalid email format" during sign-in                                    | Credential variable didn't resolve — the placeholder string was sent as-is                  | Use \`{{@app.defaults.username}}\` / \`{{@app.defaults.password}}\`; verify \`credentialsId\` was passed to \`run_mabl_test_cloud\` |
| Save returns \`wrong_authoring_boundary\` or \`shared_flow_requires_acknowledgement\` | Reusable-flow handling                                                                  | See \`mabl-author://save-tool-mechanics\`                                                                                    |

When the symptom doesn't match anything above, fall back to
\`analyze_failure(runId, testOrPlan: "test")\` for the AI failure
analysis — it has access to the run log and screenshots, which this
guide does not.

## See also

- \`mabl-author://authoring-patterns\` — patterns for structuring a test
  well, starting with step grouping
- \`mabl-author://selector-fields\` — \`locator\` / \`description\` /
  \`uuid\` field details
- \`mabl-author://save-tool-mechanics\` — when to use which save tool,
  when to call \`mabl_create_test\` / \`mabl_create_flow\` instead, and
  save-error codes
- \`mabl_get_schema_resource\` — progressive-disclosure JSON Schema for
  the test envelope, step index, or a single step type
- \`mabl_list_examples\` / \`mabl_get_example\` — worked example bodies
  per step type
- \`mabl_get_flow_steps\` / \`mabl_get_test_steps\` — read existing flows
  or tests as a starting point
`;
const SELECTOR_FIELDS_CONTENT = `# Selector field reference

Notes on the three fields that drive the new-shape resolver inside a
wrapped \`findTarget.selector\` descriptor.

## \`locator\`

A Playwright locator string. Accepts:

- Bare CSS: \`"button.primary"\`
- Explicit-prefix: \`"xpath=//button"\`, \`"css=button"\`
- Auto-detected XPath: \`"//button"\`
- Semantic primitives: \`"role=button[name=\\"Save\\"]"\`, \`"text=Submit"\`,
  \`"id=submit-btn"\`
- Chains via \`>>\`: \`"foo >> nth=2"\`
- Pseudo-classes: \`:has-text("x")\`, \`:visible\`, \`:nth-match\`

Variable references (standard \`{{@...}}\` syntax) are resolved before
the locator hits Playwright.

Pick the most stable identifier available: data-test-id > role= > id >
unique CSS class > generic XPath. Must resolve to exactly one element;
express narrowing inside the locator string rather than across multiple
find calls.

## \`description\`

A natural-language statement of what the element *is*, what it *does*,
and (optionally) how it looks or where it sits on the page. Drives the
description-driven visual resolver when the locator fails.

Combine purpose with whatever stable cues — color, position, layout,
nearby text — actually help find the element. Visual descriptors are
good, even great, when paired with purpose; the failure mode is leaning
on look ALONE.

- Excellent: "blue Add to Cart button below the product image" — purpose
  + color + position
- Excellent: "primary submit button on the checkout form" — purpose +
  location
- Excellent: "search input above the tests list that filters as the
  user types" — purpose + position + behavior
- Weak: "blue button on the right" — visual only, no purpose
- Bad: "the element at coordinates 684, 507" — coordinates change with
  any layout shift
- Bad: "the button with class .btn-submit" — just restates the locator

If the page redesigns one of the cues away (colors change, layout
shifts), the purpose part of the description keeps it anchored.

## \`uuid\`

A stable identifier you generate. The runtime keys captured fingerprints
(heal attempts, learned timeouts, confidence scores) to it.

**Reuse the same uuid for the same logical element across re-authors.**
Re-authoring with a new uuid loses the accumulated heal data and resets
confidence.

For pure-new-shape descriptors that have never been captured, any unique
string works (\`"login-email"\`, \`"tests-search-input"\`, etc.). Don't
use a real UUID format unless you have one from a prior capture.

## See also

- \`mabl_get_schema_resource(uri: "mabl-schema://step/<Type>")\` — full
  per-step JSON Schema
- \`mabl_get_example(id: ...)\` — worked example bodies
`;
const SAVE_TOOL_MECHANICS_CONTENT = `# Save tool mechanics

The mechanics that matter when picking which create or save tool to use,
and what each tool's failure modes mean. Per-parameter docs live in the
tools' input schemas — this guide covers what those don't.

## \`mabl_validate\` is structural-only

\`mabl_validate\` is pure logic — it does not touch the API and does not
check whether locators resolve on a live page. A green validate
guarantees \`mabl_save_*\` will accept the payload at the structural
layer; it does *not* guarantee the run passes.

## \`mabl_save_flow_steps\`: single-flow edits

Use for edits scoped to one flow.

For **structural (non-reusable) flows**, pass \`test_id\` so the test
rebinds to the new flow variant in the same call. Without it, the next
test run still executes the old variant.

For **reusable flows** (referenced by multiple tests),
\`acknowledge_shared: true\` is required. Without it the save returns
\`shared_flow_requires_acknowledgement\` plus a sample of impacted tests
so you can review blast radius before re-saving.

## \`mabl_save_test_steps\`: cross-flow edits

Use for edits that span multiple flows on a test.

\`mode: "whole"\` replaces the steps of one or more flows wholesale.
\`mode: "edits"\` applies a batch of replace / insert_after / delete /
move ops to the current state. Use "edits" for surgical changes on long
flows; "whole" for rewrites of flows under ~50 steps.

Edits that land on a step inside a reusable flow are refused with
\`wrong_authoring_boundary\` plus a redirect hint pointing at
\`mabl_save_flow_steps\`. The refusal is on purpose — reusable flows have
higher concurrent-modification risk and should be saved through the
single-flow path with explicit acknowledgement.

## When you don't have a test_id yet

Call \`mabl_create_test\` to create a new test envelope. Pass
\`initial_flow.steps\` to create the test and its first structural flow
in one round-trip; omit \`initial_flow\` to create an empty test (then
add flows via \`mabl_save_test_steps\` or attach existing ones).

For a standalone reusable flow that other tests will include, call
\`mabl_create_flow\` instead.

## Common save errors

| Error code                                  | Meaning                                                                | Action                                                                                                       |
| ------------------------------------------- | ---------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| \`pre_validation_failed\`                   | Steps failed \`mabl_validate\` (which save_* runs internally as a gate) | Call \`mabl_validate\` directly to see the suggestions                                                       |
| \`wrong_authoring_boundary\`                | Edit landed inside a reusable flow via \`mabl_save_test_steps\`        | Switch to \`mabl_save_flow_steps\` with \`acknowledge_shared: true\`                                         |
| \`shared_flow_requires_acknowledgement\`    | Saving a reusable flow without \`acknowledge_shared: true\`            | Review impacted-test sample in the response, then re-save with \`acknowledge_shared: true\`                  |
`;
const AUTHORING_PATTERNS_CONTENT = `# Authoring patterns

Reference for writing tests that are clear to read and easy to debug. Each
pattern is grounded in what a downstream consumer — a future author, the
failure-analysis tool, an agent reading the run — needs from the test.

## Group conceptually related steps with intents

A test's *shape* should mirror its goal. The 4 clicks that add an item to a
cart, the 8 fields that fill out a checkout form, the login sequence — each
is one conceptual action, not a list of unrelated atoms. Wrap conceptual
actions in \`StepGroup\` and label them with \`intent.description\`.

### Why

- **Readability.** A reader scanning the test sees the goals (\"Log in\",
  \"Add item to cart\", \"Submit checkout\") before drilling into mechanics.
- **Run-time analysis.** mabl's failure analysis and result reporting consume
  \`intent.description\` to summarize what the test was trying to do at the
  point of failure. Without intents, the analysis only sees
  \"Click on .btn-submit\" and has to infer the purpose.
- **Editability.** Grouped steps move and rename together. A redesign that
  changes *how* you add an item shouldn't ripple through unrelated step
  indices in the test.

### What to group

Group a sequence of steps when:

- They serve one user-visible goal you could describe in one sentence.
- They appear together — interleaving them with unrelated assertions or
  navigation would be unnatural.

Don't group:

- A single step. The wrapper adds noise without earning its keep.
- Steps that span two unrelated goals (e.g. \"Log in\" and \"Add to cart\"
  in the same group). Split into two groups, each with its own intent.

### Shape

\`\`\`json
{
  \"StepGroup\": {
    \"intent\": {
      \"description\": \"Add a Margherita pizza to the cart\"
    },
    \"steps\": [
      { \"Click\": { \"find\": { ... }, \"description\": \"Open the menu\" } },
      { \"Click\": { \"find\": { ... }, \"description\": \"Pick Margherita pizza\" } },
      { \"Click\": { \"find\": { ... }, \"description\": \"Choose size large\" } },
      { \"Click\": { \"find\": { ... }, \"description\": \"Add to cart\" } }
    ]
  }
}
\`\`\`

The group's \`intent.description\` is the **what** the user is trying to
accomplish; each child step's \`description\` is the **how**. \`StepGroup\`
is recursive — groups can nest, but only do that when the inner sub-goal is
itself worth naming.

### Step group vs reusable flow

| Use…                                          | When…                                                                                                                                                                                                                                  |
| --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Inline \`StepGroup\`                          | The action only appears in this one test                                                                                                                                                                                               |
| Reusable flow (invoked via \`EvaluateFlow\`)  | The sequence implements general functionality multiple tests are likely to use — login, signup, common setup/teardown, shared business workflows like \"add item to cart.\" Extract upfront when it looks reusable, even if only the current test references it today; anticipated reuse counts, not just observed reuse. Call \`mabl_search_flows\` first to check whether a suitable reusable flow already exists. |
| Reusable flow with parameters                 | The reusable sequence's inputs (URLs, IDs, values) vary per call site — declare \`parameters\` on the flow, reference inside as \`{{@flow.<name>}}\`, callers pass via \`EvaluateFlow.config.parameters\`. See \"Reusable flow parameters\" below.        |

Reusable flows carry their own purpose at the flow level (the flow's
\`description\`). The \`StepGroup\` pattern brings the same readability win
to non-reusable sub-tasks without forcing a flow extraction. Extracting
early doesn't lock you into a single hard-coded call site — see
\"Reusable flow parameters\" below for how to keep an extracted flow
flexible across callers.

### Reusable flow parameters

Reusable flows can declare formal parameters. This is the preferred way to
pass per-call-site data into a flow — better than having each caller set a
workspace variable before invoking the flow.

**Declare** on the flow itself:

\`\`\`json
{
  "parameters": [
    { "name": "widget_count", "default_value": "5" },
    { "name": "widget_label" }
  ]
}
\`\`\`

Each entry has a \`name\` and an optional \`default_value\`. The \`name\` is
the bare parameter name (no namespace prefix); the runtime binds it under
the \`flow.\` namespace at execution time.

**Reference** inside the flow's steps with \`{{@flow.<name>}}\`:

\`\`\`json
{ "EnterText": { "find": { ... }, "text": "{{@flow.widget_label}}" } }
\`\`\`

**Pass** values from the caller via \`EvaluateFlow.config.parameters\` —
a name → string map keyed by the same \`name\` you declared:

\`\`\`json
{
  "EvaluateFlow": {
    "flow": { "invariant_id": "<flow_invariant_id>" },
    "config": { "parameters": { "widget_count": "12", "widget_label": "Wrench" } }
  }
}
\`\`\`

Resolution order at run time: caller-provided value > \`default_value\` >
undefined.

#### Why prefer parameters over caller-set workspace variables

The antipattern: caller sets \`user.foo\` via a \`CreateVariable\` step,
then invokes a flow that reads \`{{@user.foo}}\`. This works, but:

- The flow has no signature — readers can't tell what data it expects
  without scanning every step for \`{{@user.*}}\` references.
- Callers can't tell what they need to set before invocation; mistakes
  surface as runtime failures, not authoring-time errors.
- The variable leaks into the test's global namespace for the rest of
  the run.

Declared parameters fix all three: the flow's contract is explicit,
callers see what to pass, and the binding lives in a scoped \`flow.\`
namespace that doesn't leak.

## Wait steps

Most steps already wait. Interaction steps (\`Click\`, \`EnterText\`,
\`Hover\`, etc.) poll for their target element with a built-in ~30-second
timeout before acting; \`AssertElement\` polls before validating. You only
need an explicit wait when the *next* step would race a slower transition —
a page navigation, a modal open, an async content load — before its target
is ready.

| You want to wait for…                              | Use                                                                                            |
| -------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
| An element to appear                               | \`WaitUntil\` with a find descriptor for the appearing element                                 |
| A page transition to settle before the next step   | Often unnecessary — let the next step's built-in polling cover it                              |
| An element to disappear                            | Not supported by \`WaitUntil\`. Assert on a post-disappearance state element instead           |
| A fixed duration                                   | **Last resort.** \`Wait\` (fixed sleep) slows every replay by its full duration                |

Anti-patterns:

- \"Just-in-case\" waits between steps on the same static page. Every saved
  fixed wait slows replay forever.
- A fixed \`Wait\` to absorb an animation. Wait on the post-animation state
  element instead.
- \`WaitUntil\` to wait for disappearance. It doesn't. Use an \`Assert*\` step
  describing the page's post-disappearance state.

## Assertion quality

- **One concept per assertion.** Each \`Assert*\` step verifies a single
  outcome. Folding multiple checks into one assertion makes failures
  harder to diagnose — you lose which sub-check failed.
- **Prefer business-outcome assertions over element-presence.**
  \"Order-confirmation number visible after submit\" is more valuable than
  \"submit button visible.\" Element-presence catches broken pages but
  misses broken outcomes; outcome assertions catch both.
- **Assert against captured variables, not hardcoded literals.** For any
  value that changes per run — order numbers, confirmation codes,
  generated emails, timestamps — capture into a \`{{@user.<name>}}\`
  variable first, then assert against the variable. Hardcoded literals
  pass once and fail forever after. (See \`mabl-author://overview\` >
  Variable conventions for the capture-early discipline.)
- **End each conceptual group with an assertion verifying its outcome.**
  A StepGroup that adds an item to a cart ends with an assertion that the
  item is in the cart. Without it, the group's \`intent.description\` is
  the only signal that anything was supposed to happen, and failure
  analysis has nothing to anchor to.

## See also

- \`mabl-author://overview\` — entry point: shape decision, variable
  conventions, validate -> save -> run loop, failure triage
- \`mabl-author://selector-fields\` — \`locator\` / \`description\` /
  \`uuid\` details for the steps inside a group
- \`mabl_get_schema_resource(uri: \"mabl-schema://step/StepGroup\")\` —
  full StepGroup schema
- \`mabl_get_schema_resource(uri: \"mabl-schema://step/EvaluateFlow\")\` —
  full EvaluateFlow schema (the reusable-flow invocation step)
`;
const RESOURCES = [
    {
        uri: OVERVIEW_URI,
        description: 'Entry point: when to hand-author, the findTarget shape decision, variable conventions, the validate -> save -> run loop, and a failure-triage table.',
        content: OVERVIEW_CONTENT,
    },
    {
        uri: SELECTOR_FIELDS_URI,
        description: 'Field reference for `locator`, `description`, and `uuid` inside a wrapped findTarget.selector.',
        content: SELECTOR_FIELDS_CONTENT,
    },
    {
        uri: SAVE_TOOL_MECHANICS_URI,
        description: 'When to use mabl_save_flow_steps vs mabl_save_test_steps, when to call mabl_create_test or mabl_create_flow instead, and what each save-error code means.',
        content: SAVE_TOOL_MECHANICS_CONTENT,
    },
    {
        uri: AUTHORING_PATTERNS_URI,
        description: 'Patterns for structuring a test well, starting with grouping conceptually related steps using StepGroup + intent.description.',
        content: AUTHORING_PATTERNS_CONTENT,
    },
];
const RESOURCE_BY_URI = new Map(RESOURCES.map((resource) => [resource.uri, resource]));
class AuthoringGuideResources {
    resolve(uri) {
        return RESOURCE_BY_URI.get(uri);
    }
    list() {
        return RESOURCES.map(({ uri, description }) => ({ uri, description }));
    }
}
exports.AuthoringGuideResources = AuthoringGuideResources;
