> ## Documentation Index
> Fetch the complete documentation index at: https://docs.canary.effectiveai.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Write your first guideline

> Write an underwriting guideline that uses a rater, gives questions to roles and refers submissions, then work one submission from application to bind.

This tutorial follows [Write your first rater](https://docs.canary.effectiveai.app/rsl/tutorial/first-rater.md). You write a
second RSL file, a **guideline**, for a synthetic staffing liability program of Example Mutual.
Then you work one submission by hand as an assistant, an underwriter and a manager.

A rater holds the filed math. A guideline holds the underwriting rules around it: who answers each
question, which submissions are eligible, and which submissions need a sign-off.

## The underwriting rules

The example program has a rating manual with four rules:

* The premium is \$2 for each \$1,000 of payroll.
* A firm with claims pays 1.5 times that premium.
* The basic limit is \$1,000,000. A higher limit, up to \$2,000,000, costs 1.1 times that premium.
* The program rates a payroll of \$1,000 or more.

Its underwriting guideline adds five rules:

* A professional employer organization (PEO) must be in operation for 3 years or more and be financially sound.
* An underwriter judges the loss experience and the financial soundness.
* A manager signs off a firm that is in operation for less than 3 years.
* A manager signs off a premium of \$10,000 or more.
* An underwriter quotes and binds.

A staffing firm that is 2 years old, with a \$2,500,000 payroll, a clean loss record and the basic
limit, gets a \$5,000 premium after the manager signs off. The rates, rules and citations are synthetic.

## Save the rater and check it

Create a folder for the program:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
mkdir staffing
cd staffing
```

Save the following rater as `rater.rsl`.

> [accordion] rater.rsl
>
> ```rsl staffing/rater.rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
> spec {
>     rsl: "0.4",
>     carrier: "Example Mutual",
>     state: PA,
>     product: "Staffing Liability",
>     version: "0.1.0",
>     effective_date: 2026-01-01
> }
>
> Sources = {
>     rules: Source = {
>         artifact: artifact("5b0e7c0e-6f0a-4c56-9d39-0d1f1a1c7e11"),
>         kind: pdf
>     }
> }
>
> Types = {
>     Experience = {
>         no_claims,
>         claims
>     }
> }
>
> Constants = {
>     rate_per_1000 [cite: rules:p1] = 2,
>     claims_factor [cite: rules:p2] = 1.5,
>     basic_limit [cite: rules:p3] = 1000000,
>     higher_limit_factor [cite: rules:p3] = 1.1
> }
>
> Records = {
>     Policy = {
>         inputs {
>             payroll: Num {precision: int} where self in [0, 100000000] [cite: rules:p1],
>             experience: Experience [cite: rules:p2],
>             limit: Num {precision: int} per quote where self in [1000000, 2000000] [cite: rules:p3]
>         },
>         step rating [cite: rules:p1] {
>             experience_factor: Num = if self.experience = @Experience.no_claims then 1 else claims_factor,
>             limit_factor: Num = if self.limit > basic_limit then higher_limit_factor else 1,
>             premium: Premium [cite: rules:p1] =
>                 round(self.payroll / 1000 * rate_per_1000 * self.experience_factor * self.limit_factor, 2, half_up)
>         }
>     } where self.payroll >= 1000 [code: "PAYROLL_BELOW_MINIMUM", message: "The payroll must be at least $1,000.", cite: rules:p1]
> }
>
> RatingOutcomes = {
>     premium: Policy.premium
> }
> ```

Check it:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc check rater.rsl
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
PASS rater.rsl (strict)
cost premium: 3 (each list of size 1: 3, 3: 3, 10: 3)
```

The rater asks for the payroll, the loss experience and the limit, and returns one `premium`. Its
coded rule, `PAYROLL_BELOW_MINIMUM`, refuses a payroll below \$1,000, the lowest payroll that the manual rates.

The mark `per quote` on `limit` makes the limit a **term**: each quote of one submission may set
its own limit. Every other input is a fact that all quotes of the submission share.
[Run a submission](https://docs.canary.effectiveai.app/rsl/how-to/run-a-submission.md#offer-quote-options) quotes two limits side by side.

## Write the guideline

Create `guideline.rsl` beside `rater.rsl`, and write it from top to bottom in the seven parts
below. The complete file follows the last part.

### Name the program and use the rater

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
spec {
    rsl: "0.4",
    carrier: "Example Mutual",
    state: PA,
    product: "Staffing Liability Underwriting Guideline",
    version: "0.1.0",
    effective_date: 2026-01-01
}

use ts = "rater.rsl"
```

A guideline starts with the same header as a rater. The `use` line links the rater in the same
folder under the short name `ts`. From here, the rater's record is `ts.Policy`.

### Declare the roles and the acts

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
Roles = { assistant < uw < manager }

Acts = { quote: @Role.uw, bind: @Role.uw }
```

`Roles` lists the roles from lowest to highest. A role does everything that the roles below it do,
so a manager also answers an underwriter's questions. `Acts` names the lowest role that quotes and
the lowest role that binds.

### Cite the guideline and declare its values

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
Sources = {
    guideline: Source = {
        artifact: artifact("0c1f6f43-1f55-4a55-8a53-7d1b6f0e2a22"),
        kind: pdf
    }
}

Types = {
    Operation = {
        staffing,
        peo
    }
}

Constants = {
    established_years [cite: guideline:p1] = 3,
    large_premium [cite: guideline:p2] = 10000
}
```

These sections work as they do in a rater. The guideline cites its own source document, and the
artifact ID here is a placeholder for the synthetic guideline.

### Ask the questions

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
Records = {
    Submission = {
        inputs {
            operation: Operation [cite: guideline:p1],
            years_in_operation: Num {precision: int} where self in [0, 300] [cite: guideline:p1],
            financially_sound: Bool by @Role.uw when self.operation = @Operation.peo [cite: guideline:p1],
            policy: ts.Policy,
            policy.experience by @Role.uw
        },
```

* `policy: ts.Policy` takes the rater's record as one input. The guideline then asks every question of the rater under `policy`.
* `by @Role.uw` gives a question to the underwriter. A question that lacks `by` is open to every role.
* `policy.experience by @Role.uw` gives one of the rater's questions to the underwriter, by its path.
* `when` asks for `financially_sound` only when the firm is a PEO.

### Read the rater's premium

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
        step premium [cite: guideline:p2] {
            premium: Premium = ts(self.policy).premium
        }
```

`ts(self.policy).premium` is the rater's `premium` outcome for this policy. A guideline reads a
rater through its inputs and its outcomes only, so the rater's inner calculations stay free to
change. A policy that breaks a coded rule of the rater makes the submission ineligible.

### Add the eligibility rule

Close the record with a `where` rule that has a code:

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
    } where self.operation != @Operation.peo or (self.years_in_operation >= established_years and self.financially_sound) [code: "PEO_NOT_ESTABLISHED", message: "A PEO must be in operation for at least 3 years and be financially sound.", cite: guideline:p1]
```

A submission that breaks this rule moves to the `Ineligible` stage and shows the code and the
message. The answers stay in the log, so a corrected answer makes the submission eligible again.
[Decline a submission](#decline-a-submission) shows the stage and the decision that follows it.

### Add the two referrals

Write the referrals after the rule, then close `Records` and name the outcome:

```rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
        refer new_venture when self.years_in_operation < established_years
            to @Role.manager because "The firm is in operation for less than 3 years." [cite: guideline:p1]
        refer large_account when self.premium >= large_premium
            to @Role.manager because "The premium is $10,000 or more." [cite: guideline:p2]
}

RatingOutcomes = {
    premium: Submission.premium
}
```

A referral has a name, a condition, the lowest role that signs it off, and the reason shown to
that role. While its condition holds, the submission waits for an answer of `Approved` or
`Declined` from that role.

### Check the guideline

Your file now matches this one:

> [accordion] guideline.rsl
>
> ```rsl staffing/guideline.rsl theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
> spec {
>     rsl: "0.4",
>     carrier: "Example Mutual",
>     state: PA,
>     product: "Staffing Liability Underwriting Guideline",
>     version: "0.1.0",
>     effective_date: 2026-01-01
> }
>
> use ts = "rater.rsl"
>
> Roles = { assistant < uw < manager }
>
> Acts = { quote: @Role.uw, bind: @Role.uw }
>
> Sources = {
>     guideline: Source = {
>         artifact: artifact("0c1f6f43-1f55-4a55-8a53-7d1b6f0e2a22"),
>         kind: pdf
>     }
> }
>
> Types = {
>     Operation = {
>         staffing,
>         peo
>     }
> }
>
> Constants = {
>     established_years [cite: guideline:p1] = 3,
>     large_premium [cite: guideline:p2] = 10000
> }
>
> Records = {
>     Submission = {
>         inputs {
>             operation: Operation [cite: guideline:p1],
>             years_in_operation: Num {precision: int} where self in [0, 300] [cite: guideline:p1],
>             financially_sound: Bool by @Role.uw when self.operation = @Operation.peo [cite: guideline:p1],
>             policy: ts.Policy,
>             policy.experience by @Role.uw
>         },
>         step premium [cite: guideline:p2] {
>             premium: Premium = ts(self.policy).premium
>         }
>     } where self.operation != @Operation.peo or (self.years_in_operation >= established_years and self.financially_sound) [code: "PEO_NOT_ESTABLISHED", message: "A PEO must be in operation for at least 3 years and be financially sound.", cite: guideline:p1]
>         refer new_venture when self.years_in_operation < established_years
>             to @Role.manager because "The firm is in operation for less than 3 years." [cite: guideline:p1]
>         refer large_account when self.premium >= large_premium
>             to @Role.manager because "The premium is $10,000 or more." [cite: guideline:p2]
> }
>
> RatingOutcomes = {
>     premium: Submission.premium
> }
> ```

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc check guideline.rsl
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
PASS guideline.rsl (strict)
cost premium: 1 + 3*|Submission.policy| (each list of size 1: 4, 3: 10, 10: 31)
cost new_venture: 1 (each list of size 1: 1, 3: 1, 10: 1)
cost large_account: 2 + 3*|Submission.policy| (each list of size 1: 5, 3: 11, 10: 32)
```

One check covers both files. The compiler links the rater into the guideline and checks them as
one program. Each referral is a calculated outcome, so the check reports a cost for it beside the
premium.

## Work a submission

`rslc submission` records one submission in a log file. Each command names who acts, as
`--as role:name`. Each command prints the entries it wrote and then the status of the submission.

### Open the log as the assistant

Save the applicant's answers as `application.json`:

```json staffing/application.json theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
{
  "operation": "staffing",
  "years_in_operation": 2,
  "policy": {
    "payroll": 2500000,
    "limit": 1000000
  }
}
```

Open a log for this guideline:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission open submission.jsonl --program guideline.rsl --as assistant:intake
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  1  assistant:intake  opened guideline.rsl (program 6c92e7971a32)
stage: Open
open (4):
  operation           input    any role
  years_in_operation  input    any role
  policy              input    any role
  policy.experience   input    @uw
```

The first line is entry 1 of the log. The characters after `program` start a hash of the guideline
and the rater, so the same files give the same characters.

The status lists four open questions with the lowest role that may answer each. The `policy` line
stands for the rater's questions that every role answers.

### Answer from the application

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission answer submission.jsonl --file application.json --as assistant:intake
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  2  assistant:intake  answered operation = "staffing" from application.json
  3  assistant:intake  answered policy.limit = 1000000 from application.json
  4  assistant:intake  answered policy.payroll = 2500000 from application.json
  5  assistant:intake  answered years_in_operation = 2 from application.json
stage: Open
open (2):
  policy.experience  input    @uw
  new_venture        signoff  @manager  because: The firm is in operation for less than 3 years.
                       reads years_in_operation = 2
referrals:
  new_venture  Open  @manager
```

The file answers four questions. The log records one entry for each answer and names the file as
its source. The firm is 2 years old, so the `new_venture` referral is open before the premium is known.

### Read the status

`status` prints the same block at any time and leaves the log as it is:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission status submission.jsonl
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
stage: Open
open (2):
  policy.experience  input    @uw
  new_venture        signoff  @manager  because: The firm is in operation for less than 3 years.
                       reads years_in_operation = 2
referrals:
  new_venture  Open  @manager
```

Each open line gives the question, its kind, the lowest role that may answer, and the reason for
a referral. An `input` takes an answer. A `signoff` takes `Approved` or `Declined`.

### See a refusal

Answer the underwriter's question as the assistant:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission answer submission.jsonl policy.experience=no_claims --as assistant:intake
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
refused NOT_AUTHORIZED: answering `policy.experience` needs role `uw` or a role above; `intake` is `assistant`
  candidates: uw, manager
stage: Open
open (2):
  policy.experience  input    @uw
  new_venture        signoff  @manager  because: The firm is in operation for less than 3 years.
                       reads years_in_operation = 2
referrals:
  new_venture  Open  @manager
```

The log refuses the command with the code `NOT_AUTHORIZED` and stays as it was. The `candidates`
line lists the roles that may answer. A refused command exits with code 2, and the refusal is kept
in `submission.refused.jsonl`, beside the log.

### Answer as the underwriter

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission answer submission.jsonl policy.experience=no_claims --because "Loss runs, five years" --as uw:alice
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  6  uw:alice  answered policy.experience = "no_claims" because "Loss runs, five years"
stage: Open
open (1):
  new_venture  signoff  @manager  because: The firm is in operation for less than 3 years.
                 reads years_in_operation = 2
referrals:
  new_venture  Open  @manager
outcomes known so far:
  premium = 5000
```

`--because` records the reason beside the answer. Every rating answer is in, so the premium is
known: 2,500 × \$2 is \$5,000. The stage stays `Open` while the referral waits for the manager.

### Sign off the referral as the manager

A sign-off is an answer to the referral's name:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission answer submission.jsonl new_venture=Approved --because "Experienced owners." --as manager:morgan
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  7  manager:morgan  signed off new_venture = Approved on years_in_operation = 2 because "Experienced owners."
stage: Quotable
referrals:
  new_venture  Approved  @manager
outcomes:
  premium = 5000
```

Every question has an answer and the referral is approved, so the stage is `Quotable`.

### Quote

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission quote submission.jsonl q1 --as uw:alice
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  8  uw:alice  quoted q1: 1 outcomes
stage: Quotable
quotes:
  q1  stands
referrals:
  new_venture  Approved  @manager
outcomes:
  premium = 5000
```

A quote is a log entry with a name. It keeps the outcomes of the moment, here a \$5,000 premium,
and it stands while the answers stay the same.

### Change an answer

The applicant reports a higher payroll. Record it as the underwriter:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission answer submission.jsonl policy.payroll=3000000 --as uw:alice
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  9  uw:alice  answered policy.payroll = 3000000
stage: Quotable
quotes:
  q1  lapsed (policy.payroll changed)
referrals:
  new_venture  Approved  @manager
outcomes:
  premium = 6000
```

The quote `q1` lapses, because a quote rests on every answer. The sign-off stands, because the
condition of `new_venture` reads only `years_in_operation`. The premium is now \$6,000.

Now change an answer that the referral reads:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission answer submission.jsonl years_in_operation=1 --as uw:alice
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
 10  uw:alice  answered years_in_operation = 1
stage: Open
quotes:
  q1  lapsed (policy.payroll, years_in_operation changed)
open (1):
  new_venture  signoff  @manager  because: The firm is in operation for less than 3 years.
                 reads years_in_operation = 1
referrals:
  new_venture  Open  @manager  (sign-off lapsed)
outcomes known so far:
  premium = 6000
```

The manager approved a firm that was 2 years old. The sign-off lapses with that answer, and the
referral is open again. The manager signs off the corrected submission:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission answer submission.jsonl new_venture=Approved --because "Still acceptable." --as manager:morgan
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
 11  manager:morgan  signed off new_venture = Approved on years_in_operation = 1 because "Still acceptable."
stage: Quotable
quotes:
  q1  lapsed (policy.payroll, years_in_operation, new_venture changed)
referrals:
  new_venture  Approved  @manager
outcomes:
  premium = 6000
```

### Quote again and bind

The quote `q1` stays in the log under its name, so the new quote takes a new name:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission quote submission.jsonl q2 --as uw:alice
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
 12  uw:alice  quoted q2: 1 outcomes
stage: Quotable
quotes:
  q1  lapsed (policy.payroll, years_in_operation, new_venture changed)
  q2  stands
referrals:
  new_venture  Approved  @manager
outcomes:
  premium = 6000
```

Bind the quote that stands:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission bind submission.jsonl q2 --as uw:alice
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
 13  uw:alice  bound q2
stage: Bound
quotes:
  q1  lapsed (policy.payroll, years_in_operation, new_venture changed)
  q2  bound
referrals:
  new_venture  Approved  @manager
outcomes:
  premium = 6000
```

The submission is `Bound` at a \$6,000 premium. `bind` takes a quote only while it stands, so a
bound premium always matches the answers in the log. A bound submission is final: the log refuses every later write.

### Read the log

`history` lists every entry with its number and its writer:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission history submission.jsonl
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  1  assistant:intake  opened guideline.rsl (program 6c92e7971a32)
  2  assistant:intake  answered operation = "staffing" from application.json
  3  assistant:intake  answered policy.limit = 1000000 from application.json
  4  assistant:intake  answered policy.payroll = 2500000 from application.json
  5  assistant:intake  answered years_in_operation = 2 from application.json
  6  uw:alice  answered policy.experience = "no_claims" because "Loss runs, five years"
  7  manager:morgan  signed off new_venture = Approved on years_in_operation = 2 because "Experienced owners."
  8  uw:alice  quoted q1: 1 outcomes
  9  uw:alice  answered policy.payroll = 3000000
 10  uw:alice  answered years_in_operation = 1
 11  manager:morgan  signed off new_venture = Approved on years_in_operation = 1 because "Still acceptable."
 12  uw:alice  quoted q2: 1 outcomes
 13  uw:alice  bound q2
```

The log file holds the same entries, one JSON object on each line. Open `submission.jsonl` in an
editor. Lines 7 and 8 hold the first sign-off and the first quote:

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
{"seq":7,"at":"2026-11-10T08:22:35+00:00","by":{"role":"manager","id":"morgan"},"event":{"type":"signed_off","referral":"new_venture","decision":"Approved","key":"22c4a4f9ca8540d093859f3c0e9d48bf361dec04f26f5349e6a6fc8a668c62a1","read":{"years_in_operation":2},"because":"Experienced owners."}}
{"seq":8,"at":"2026-11-10T08:22:35+00:00","by":{"role":"uw","id":"alice"},"event":{"type":"quoted","name":"q1","key":"6ea5d0af602638b382ea51e29a5cf94715f420325599af0819b26928736fd573","outcomes":{"premium":5000}}}
```

`at` holds the time of your run. `read` holds the answer that the manager saw at the sign-off.
Each `key` is a hash of the answers that the sign-off or the quote rests on. Commands only add
lines, and each status is computed from the lines.

## Decline a submission

A second applicant is a PEO that is 2 years old. Open a second log for it:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission open peo.jsonl --program guideline.rsl --as assistant:intake
```

Answer two questions from its application:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission answer peo.jsonl operation=peo years_in_operation=2 --as assistant:intake
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  2  assistant:intake  answered operation = "peo"
  3  assistant:intake  answered years_in_operation = 2
stage: Ineligible
declines:
  PEO_NOT_ESTABLISHED  A PEO must be in operation for at least 3 years and be financially sound.
  the account stays open: correct an answer, or decline it with `close declined`
```

The answers break the eligibility rule, so the stage is `Ineligible`. The log refuses a quote in
this stage. The submission stays open, because a wrong answer and a true one look the same to the
log. A person decides what follows:

* **Correct the answer.** An answer of 4 years returns the submission to the `Open` stage.
* **Decline the submission.** `close declined` records the decision.

The application is right, so the underwriter declines:

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc submission close peo.jsonl declined --because "A PEO in its second year" --as uw:alice
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
  4  uw:alice  closed (declined) on PEO_NOT_ESTABLISHED because "A PEO in its second year"
stage: Declined
declines:
  PEO_NOT_ESTABLISHED  A PEO must be in operation for at least 3 years and be financially sound.
```

`close declined` takes the role of the `quote` act, here `uw`, and it works only while a rule or a
sign-off declines. The entry names the code that the decision rests on. `Declined` is final, like `Bound`.

## Run the whole story as a script

A script file holds the same story, one step on each line, with the results it expects. Save this
one as `bind.script`.

> [accordion] bind.script
>
> ```text staffing/bind.script theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
> # A two-year-old staffing firm: the manager signs off the new venture, the underwriter quotes and binds.
> program "guideline.rsl"
> as assistant:intake
> open
> answer file "application.json"
> # The referral is known before the premium is.
> expect referral new_venture Open
> expect open policy.experience, new_venture
> refused NOT_AUTHORIZED: answer policy.experience = no_claims
> as uw:alice
> answer policy.experience = no_claims because "Loss runs, five years"
> expect outcome premium = 5000
> refused NOT_QUOTABLE: quote q1
> refused NOT_AUTHORIZED: answer new_venture = Approved
> as manager:morgan
> answer new_venture = Approved because "Experienced owners."
> as uw:alice
> expect stage Quotable
> quote q1
> expect quote q1 stands
> # More payroll: the quote q1 was for other answers, the sign-off still stands.
> answer policy.payroll = 3000000
> expect referral new_venture Approved
> expect quote q1 lapsed
> refused NOT_QUOTED: bind q1
> # A changed answer the referral reads makes the sign-off lapse.
> answer years_in_operation = 1
> expect referral new_venture Lapsed
> as manager:morgan
> answer new_venture = Approved because "Still acceptable."
> as uw:alice
> # A quote is kept: the new one takes a new name, and bind names it.
> refused NOT_QUOTABLE: quote q1
> quote q2
> bind q2
> expect stage Bound
> expect quote q2 bound
> expect outcome premium = 6000
> ```

```sh theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
rslc script bind.script
```

```text theme={"languages":{"custom":["languages/rsl.tmLanguage.json"]}}
PASS bind.script: 26 steps, 0 failed, 13 log entries, stage Bound
```

`rslc script` plays the steps on a log in memory and checks each `expect` line. A line that starts
with `refused` passes when the log refuses the step with that code. Keep the script beside the
guideline as its test, and run it after each change.

## Next steps

* [Run a submission](https://docs.canary.effectiveai.app/rsl/how-to/run-a-submission.md) covers each command, quote options, `--json` for a program, and writes that name the entry they read.
* [Raters and guidelines](https://docs.canary.effectiveai.app/rsl/explanation/raters-and-guidelines.md) explains what each file owns and why a sign-off lapses.
* [Submission log](https://docs.canary.effectiveai.app/rsl/reference/submission-log.md) lists every entry, stage, refusal code and script line.
* [Check messages for guidelines](https://docs.canary.effectiveai.app/rsl/reference/check-messages/guidelines.md) explains each message that `rslc check` gives a guideline.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.