Transcripts

Transcripts provide a way to script interactions between Unison code and the Unison Codebase Manager ( UCM.) They are written as markdown documents containing fenced codeblocks that define the Unison code and UCM commands to be performed.

Components of a transcript

Transcript files are .md files that contain a series of interactions, called "stanzas". Stanzas are evaluated starting from the top of the file down.

When writing Unison code in a transcript, start a code block with triple backticks followed by "unison":

``` unison
myTerm = "Hello world"
```

Let's say you want to add this term to a Unison codebase. You can describe that in a fenced code block started by triple backticks followed by the word "ucm":

``` ucm
scratch/main> add myTerm
```

The scratch/main> is a prompt indicator that you'll use to separate the project/branch indicator on the left and the ucm commands on the right. The project and branch will be created automatically if they don't exist. scratch/main is the de facto standard for transcripts. To the right of the prompt, you can issue UCM commands to interact with the codebase.

To run a transcript when you start up the UCM, provide the transcript option and a path to the markdown file like so:

ucm transcript path/to/transcript.md

By default, transcripts are run against a new codebase each time. When a transcript is run it creates a temporary file to house the new codebase and deletes it upon finishing the run. Note that unlike the default behavior of initializing a new codebase with the UCM codebase-create argument, transcripts do not contain the base library. It's common to start your transcripts with a ``` ucm block which contains the command builtins.merge so that you have a minimal set of built-ins to work with (these are things like Nat and List).

``` ucm :hide
scratch/main> builtins.merge
```

If you would like your codebase to run against a codebase with the base library in scope, you can add a ucm block which issues a lib.install command for your desired base library.

Also… be prepared to grab a cup of tea 🫖 - installing base in a transcript adds a few seconds to the runtime of the transcript.

If a transcript can be successfully executed, the UCM will create an output file which captures the results of the interactions being described. The output of the transcript run will be written in a .output suffixed file with the same name and file path as the original.

👉
Did you know? Transcripts can help project maintainers triage and fix bugs! Simply write your reproduction as a transcript and attach the markdown file to your bug report.

Expecting failures

There are two ways to communicate that a stanza will fail, the :error tag or :bug tag. These tags are useful to communicate if an error is expected or unexpected when filing bug tickets.

Add the :error tag to a fenced code block to indicate that the UCM should expect a failure when running the enclosed block.

``` ucm :error
scratch/main> add failureExpected
```

error will enable the transcript runner to continue with subsequent stanzas in the script.

Add the :bug tag to the fenced codeblock if the Unison stanza should succeed, but doesn't.

``` ucm :bug
scratch/main> add shouldSucceed
```

If a stanza succeeds where you think it should fail, combine the two with :error :bug for reporting:

``` unison :error :bug
aTerm = "imagine this should fail but succeeds mysteriously"
```

Hiding output

If there's ever an interaction which is too noisy to be included in the .output file, you can append the :hide modifier to any stanza.

``` ucm :hide
scratch/main> builtins.merge
```

``` unison :hide
scratch/main> List.range 0 99
```

Stateful stanzas

In some circumstances, the stanzas of a transcript might entail a back-and-forth interaction between the UCM and a scratch file. An example of this would be if a bug surfaces upon updating an edited term, but not during the initial typechecking. To do this you need to "edit" the term, but by default, stanzas don't reflect "re-opened" unison terms.

If you need to save and edit terms to a transcript codebase, the UCM edit command will open your scratch.u file and render the terms to it. You can mimic the back-and-forth of editing terms by loading the file to bring it into the transcript codebase's scope.

``` unison
myTerm = "hi"
```

``` ucm
scratch/main> add myTerm
scratch/main> edit myTerm
```

At this point the scratch.u file contains ''myTerm'' at the top.

``` ucm
scratch/main> load scratch.u
```

``` unison
myTerm = "hi there!"
```

Transcript codebase options

By default, transcripts run against a fresh, ephemeral codebase each time, but a number of options exist for controlling the codebase that a transcript runs against and what happens to the resulting codebase.

CommandInput CodebaseOutput Codebase
ucm transcript \
./transcript.md
Fresh, temporary codebaseDeleted after run
ucm transcript \
./transcript.md \
--save-codebase
Fresh codebaseCreates a new, saved copy of the resulting codebase
ucm transcript \
./transcript.md \
--save-codebase-to ./aCodebase
Fresh codebaseUpdates the specified existing codebase. Use with caution!
ucm transcript.fork \
./transcript.md \
--codebase ./aCodebase
Copy of an existing codebase, given as argumentCreates a new codebase as output; original codebase unchanged
ucm transcript.in-place \
./transcript.md \
--codebase ./aCodebase
Existing codebaseModifies the specified codebase directly (in-place). Use with caution!

Want to undo unwanted changes to a codebase? Use the reflog and reset commands to reset the codebase state.