# verocase Reference Manual

`verocase` reads an assurance case written in
[Extended LTAC format](ltac-extended.txt)
and updates one or more Markdown or HTML documentation files with
automatically generated graphics, hyperlinks, and cross-references.
You edit the LTAC file for the argument structure and the document files
for the supporting detail; `verocase` keeps them in sync.

---

## LTAC Format

LTAC (Lightweight Text Assurance Case) is a plain-text format for
representing an assurance case argument.
We have extended LTAC to handle larger assurance cases
(e.g., by adding support for multiple packages, citations, and various
markings).

Each element occupies exactly one line, indented with two spaces per level.

### LTAC Element types

| Type | Purpose |
|---|---|
| `Claim` | A true-or-false statement that is asserted to hold |
| `Strategy` | An argument explaining how sub-claims or evidence collectively support the parent claim |
| `Evidence` | An artifact (document, test result, etc.) cited in support of a claim |
| `Context` | Background information or a scope constraint for the parent element |
| `Assumption` | A claim accepted as true without further argument at this point |
| `Justification` | A side-claim or rationale that supports a strategy or higher-level claim |
| `Relation` | Represents a relationship that would otherwise be implied by indentation; useful when you need to apply options to the relationship itself |
| `Link` | A citation of an element already defined earlier in the same package |

### LTAC Line syntax

```
INDENT - TYPE [^][IDENTIFIER]: statement text [{options}] [(ext_ref)]
```

- **`INDENT`**: two spaces per level; the root element of each package has no indentation.
- **`-`**: the bullet marker (only hyphens `-` are accepted).
- **`TYPE`**: one of the types in the table above, or `Link`.
- **`^`**: when present, marks this as a *citation* of an element declared elsewhere (another package).
- **`IDENTIFIER`**: optional; must be unique across the entire LTAC file (except for `Link` entries, which re-use an existing identifier).  Any characters except `:` and `^` are permitted.  If omitted, the identifier is inferred from the statement text (see [Identifiers](#identifiers)).
- **`: statement text`**: required; the colon separates the identifier (if any) from the descriptive text.  Text may contain colons.
- **`{options}`**: optional comma-separated list of modifier keywords (see [Options](#options) below).
- **`(ext_ref)`**: optional external reference in parentheses, such as a filename or URL.  Used as a hyperlink target in diagram output.

A `Link` line has a simpler form: just the type keyword and the identifier, with no colon or text:

```
    - Link ExistingId
```

A blank line ends the current package and begins the next one.

### LTAC Package structure

An LTAC file consists of one or more *packages* separated by blank lines.
Each package must begin with a `Claim` at indentation level 0 (no indent).
That top-level claim names the package; the package is identified by
the identifier of that claim.

All elements within a package form a tree, rooted at the top-level claim.
`Link` entries allow a previously defined element within the same package
to be referenced again without repeating it.

### Identifiers

Each identifier must be declared (without `^`) exactly once
across all packages.
Identifiers may contain letters, digits, hyphens, dots, and most other
printable characters, but not `:` or `^`.
Note that space is a legal character in identifiers.
There is no mandated identifier convention; meaningful names like
`AuthnClaim` are encouraged alongside traditional GSN-style names like `G1`.

If `IDENTIFIER` is omitted from an element line, verocase infers it from
the statement text by stripping characters that are illegal in identifiers
per the LTAC spec (`:`, `^`) or that the parser uses as delimiters and
would misread if the identifier were ever written back explicitly
(`{`, `}`, `(`, `)`).  For example:

```
- Claim: The system is safe
```

is treated as if it were written `- Claim The system is safe: The system is safe`,
so the element can be referenced in diagrams and via `Link`.
When verocase writes the LTAC file back out, it omits the identifier again
if it can still be recovered from the text: giving a clean round-trip.
If the statement is later changed (e.g. via `--restate`) so that the text
no longer matches the inferred identifier, the identifier is written out
explicitly to preserve it.

### Cross-package citations

An element in one package may cite a claim from another package using
the `^` prefix.  Cross-package citations have a distinct syntax: the
identifier is mandatory (it names the cited element), while `: text` is
optional:

```
- Claim ^OtherTop:
- Claim ^OtherTop: The other system is safe
```

The first form is a placeholder: the identifier is required but the text
may be left empty and filled in by `--sync`.  When text is present it
must match the declared element's text; `--sync` will correct it if not.

`^ID` resolves to the declared element with identifier `ID`
in any loaded package.

Cross-package citations are rendered as `asCited` in SACM notation
(double-bracket shape) and as away goals in GSN notation (subroutine shape).
In generated diagrams, clicking a citation navigates to the package
section in the document that includes that element's definition
(so you can see it in context).
Clicking on the element where it's defined will bring you to the
more detailed information about that element (if it exists).

### Reachability

All package roots in a multi-package LTAC file must be *reachable* from the
first element of the first package by following structural children,
citation declarations, and Link targets.
An unreachable package is an error.
(Single-package files are trivially reachable and skip this check.)

### Options

Options are listed inside curly braces near the end of a line
(before the reference if any).
They are ordered, case-insensitive, non-duplicative, and comma-separated.
You can use uppercase, but when written out they'll be converted
to lowercase.
If you want a statement to end in `{...}`, you can
disambiguate it by adding an empty `{}` after it.

```
- Claim C1: The system is safe {defeated}

- Claim C2: Residual risk is acceptable {needssupport}

- Claim C3: Meets criterion {72.3} {}
```

Each element may carry **at most one** assertion-status option (this
mirrors SACM's mutually exclusive `assertionDeclaration` attribute):

| Option | SACM assertionDeclaration |
|---|---|
| *(none)* | `asserted` (default) |
| `needssupport` | `needsSupport` |
| `assumed` | `assumed` |
| `axiomatic` | `axiomatic` |
| `defeated` | `defeated` |
| `asCited` | `asCited` |

Other options that may be combined with an assertion-status option:

| Option | Effect |
|---|---|
| `iscounter` | Sets `isCounter=true`; marks counter-evidence |
| `abstract` | Sets `isAbstract=true` |
| `metaclaim` | Sets `metaClaim=true` |

### External references

A parenthesized reference `(ref)` on an element is used as the click-target
URL for that element's node in diagram output. This is at the very end.
If you want a statement to end in `(...)`, you can
disambiguate it by adding an empty `()` after it.
Here are some examples:

```
- Claim C1: The system is safe (safety-analysis.md)

- Claim C2: Residual risk is acceptable (https://example.com/residual-risk.html)

- Claim C3: Meets criterion for safety (as discussed with stakeholders) ()
```

Resolution rules:

| `ref` form | `base_url` set? | Result |
|---|---|---|
| `http://…`, `https://…`, `file:///…` | either | used as-is |
| starts with `/` | either | used as-is |
| relative | no | used as-is |
| relative | yes | `dirname(base_url) + "/" + ref` |

Setting `base_url` to the GitHub URL of the output document therefore
resolves relative references like `hara.pdf` to the correct full URL
alongside the document.

### Permitted parent-child relationships

Not every combination is valid.  The following relationships are permitted
(`->` means "may have as a child"):

- `Claim` → `Claim`, `Strategy`, `Assumption`, `Justification`, `Evidence`
- `Strategy` → `Claim`, `Justification`, `Assumption`
- `Justification` → `Claim`, `Strategy`, `Evidence`
- Any element → `Context`, `Relation`

`Claim` and `Strategy` must not appear as direct children of `Evidence`,
`Context`, or `Assumption`.
Additionally, a claim supported by `Evidence` should not also be supported
by `Justification`, `Assumption`, or `Strategy`
(though `verocase` warns rather than refusing).

---

## Running verocase

### Synopsis

```
verocase [--config FILE] [--error] [--stats] [--strip]
         [--sync] [--rename OLD NEW] [--restate LABEL STATEMENT]
         [--detach ID] [--move ID DESTINATION]
         [--ltac FILENAME]
         [--validate | --stdout | --selftest
          | --fixmissing | --fixmisplaced | --start]
         [--select SELECTOR | --info ID | --descendants ID]
         [--empty] [--misplaced] [--leaves] [--packages]
         [--read-only] [--update-ltac]
         [files ...]
```

### Normal mode (default)

With no mode flag, `verocase` updates the listed document files in place.
It validates the LTAC, renders fresh content for all marked regions, and
writes the changes back atomically.
If no files are given, it tries the document auto-discovery sequence
(see [Auto-discovery](#auto-discovery)).

This is the intended day-to-day workflow: edit `case.ltac` and your
document files, then run `verocase` to resync everything.

### --validate

Validates the LTAC and, if document files are given (or auto-discovered),
checks that every declared LTAC element has a corresponding `element`
selector in the documents.
Produces no output and modifies no files.
Exit code is non-zero if any error was reported.
Useful in CI to confirm the assurance case is internally consistent.

### --select SELECTOR

Renders `SELECTOR` to stdout (after any main-mode operation completes).
Reads from the LTAC and config only; never opens document files.
Mutually exclusive with `--info` and `--descendants`.
May be combined with any main mode.
See [Selectors](#selectors) for the full list of selectors and their formats.

### --stdout

Processes document files the same way as normal mode but writes the
concatenated result to stdout instead of updating files in place.
Useful for previewing output or for piping into other tools.

### --selftest

Runs the built-in doctest suite and exits.
Exit code is 0 if all tests pass, 1 if any fail.

### --fixmissing

Re-renders all marked regions in the document files (the same way normal
mode does) and, for every declared LTAC element that has no corresponding
`element` selector, inserts a skeleton
`<!-- verocase element ID -->…<!-- end verocase -->` region near the
element's natural position in the document (immediately after its nearest
predecessor in LTAC depth-first order).  Falls back to appending at EOF
only when no predecessor has a document region yet (e.g., an empty document).

Also marks every leaf node (no supporting children) that lacks an
assertion-status option with `{needsSupport}` in the LTAC file.

Rewrites document files and the LTAC file in place.

`--fixmissing` is intended as a one-time scaffolding aid when bringing an
existing LTAC file into a new document.  After running it, review the
inserted regions and run `verocase` (normal mode) to continue.  Because
stubs are placed in LTAC order, a subsequent `--fixmisplaced` should not
be needed.

Use `--missing` (without `fix`) to *preview* which elements are missing
without modifying any file.

### --fixmisplaced

Moves element regions that appear in the wrong document order (relative
to LTAC depth-first order) to their correct positions.

Processes moves in LTAC order so that each move lands in the right place
even when multiple elements are misplaced.

Rewrites document files in place.

Use `--misplaced` (without `fix`) to *preview* which elements are
misplaced without modifying any file.

See [Full element content and the `stop` sentinel](#full-element-content-and-the-stop-sentinel)
for exactly what constitutes a "full region" and how to write document
sections that are never repositioned.

### --start

Creates a starter `case.ltac` and `case.md` in the current directory and
then populates them (equivalent to running `--fixmissing` on the new files).
Panics if any of the following files already exists:
`case.ltac`, `docs/case.ltac`, `case.md`, `case.markdown`, `case.html`,
`docs/case.md`, `docs/case.markdown`, `docs/case.html`.

After `--start`:
- `case.md` has its `warning` and `package *` regions filled in and
  skeleton `element` regions inserted in LTAC order for every node.
- `case.ltac` has `{needsSupport}` added to all leaf claims.

`--start` is intended as a quick on-ramp for new projects and tutorials.
Edit the generated files and run `verocase` (normal mode) to continue.

### Reporting options

Reporting options print information to stdout after the main operation completes.
They may be freely combined with each other and with any main mode.
Use `--read-only` alongside them if you want to suppress the default document-update pass.

Orphaned document regions (selector IDs not declared in the LTAC) are reported
as errors automatically whenever verocase processes a document — there is no
separate `--orphans` flag.

| Option | Description |
|---|---|
| `--empty` | List elements whose selector region exists but has no human-written prose after `<!-- end verocase -->`. |
| `--misplaced` | List elements whose selector region appears in the document in a different order than their declaration order in the LTAC.  Use `--fixmisplaced` to fix them. |
| `--leaves` | List leaf elements (no children in LTAC) with their options and references.  Leads with the `{needssupport}` subset. |
| `--packages` | List each package with element counts and the direct children of its root element. |

Multiple reporting options may be combined in a single run; each report is
separated by a blank line.

Example: report without modifying files:

```sh
verocase --read-only --empty --misplaced
```

### --ltac FILENAME

Specifies the LTAC file to load.
Overrides `ltac_file` in the config and the auto-discovery sequence.

### --help-validations

Prints the full list of LTAC structure and document validations that verocase
performs, then exits.  The regular `--help` output summarizes the most
important information; use this flag when you want to see exactly what
verocase checks.

### --help-config

Prints the full list of configuration keys recognised in the TOML config file,
then exits.  Equivalent to reading the [Configuration](#configuration) section
of this reference.

### --config FILE

Loads configuration from a TOML file.
See [Configuration](#configuration) for the full list of keys.
Unknown keys produce a warning and are ignored.

`verocase` also auto-discovers a config file if `--config` is not given:
it checks in order: `verocase.toml`, `docs/verocase.toml`, `case.toml`, `docs/case.toml`.

TOML support requires Python 3.11 or later (which includes `tomllib` in the
standard library), or the third-party `tomli` package (`pip install tomli`)
for older Python versions.  If neither is available and a config file is
found, `verocase` reports an error and continues with default settings.

### --error

Treats warnings as errors: any warning causes a non-zero exit code.
By default only serious errors (such as unclosed marked regions or
unresolvable LTAC files) cause a non-zero exit.

### --stats

Prints statistics about the LTAC structure (element counts by type, package
sizes, citations) and processed documents (region counts, empty regions).
May be combined with any mode.  Does not itself modify files; combine with
`--read-only` if you want statistics without triggering document rewrites.

### --strip

Regenerates document files with all selector regions emptied out (only
`warning` content is preserved).  Useful for reviewing document structure
without generated diagrams and boilerplate.  Combine with `--stdout` to write
the stripped result to stdout without modifying any files.

### --sync

Synchronizes citation statement text with declaration statement text in the
LTAC file.  If a `^ID: wrong text` citation does not match `ID: correct text`,
`--sync` rewrites the LTAC file so every citation and Link that carries
text uses the declaration's text instead.

Without `--sync`, a mismatch between a citation's text and its
declaration's text produces a warning suggesting the use of `--sync`.

`--sync` modifies the LTAC file (subject to the safe backup mechanism
described in [File handling](#file-handling)).

### --read-only

Suppresses the default document-update pass.  Loads and validates the LTAC
(and any document files given) without rewriting anything.  Useful for
combining with `--stats` or any reporting option without triggering document
rewrites.  Cannot be combined with any file-modifying mode (`--fixmissing`,
`--fixmisplaced`, `--start`, `--sync`, `--rename`, `--restate`, `--detach`,
`--move`, `--update-ltac`).

### --rename OLD NEW

Renames identifier `OLD` to `NEW` throughout the LTAC file and all
document files processed in the same run.
`OLD` must be a declared identifier; `NEW` must not yet exist.
May be given more than once on a single command line; mutations are applied
in the order given.

### --restate LABEL STATEMENT

Updates the statement text for `LABEL` to `STATEMENT` throughout the LTAC
file and all document files processed in the same run.
May be given more than once; mutations are applied in order.

---

## Selectors

A selector identifies what to render and in what format.
Selectors appear after `--select` on the command line or inside marked
regions in document files (see [Marked regions](#marked-regions)).

### Selector syntax

```
KIND [ID | *]
```

**`KIND`** is one of the values in the table below.
Shorthand kinds (`sacm`, `gsn`, `ltac`) are auto-expanded based on
the document format (markdown or HTML) and the `default_renderer` config key.

**`ID`** is the identifier of the element or package to render.
For selectors that accept `*`, all packages are rendered in order.

| Selector | `ID` | Description |
|---|---|---|
| `element ID` | required | Heading + cross-references for one element |
| `package [ID\|*]` | optional | Heading + diagram + index for one or all packages |
| `sacm [ID\|*]` | optional | SACM diagram (auto-detects markdown/HTML format) |
| `sacm/mermaid [ID\|*]` | optional | SACM Mermaid diagram (auto-detects format) |
| `sacm/mermaid/markdown [ID\|*]` | optional | SACM diagram as a fenced Mermaid block |
| `sacm/mermaid/html [ID\|*]` | optional | SACM diagram as `<pre class="mermaid">` |
| `gsn [ID\|*]` | optional | GSN diagram (auto-detects format) |
| `gsn/mermaid [ID\|*]` | optional | GSN Mermaid diagram (auto-detects format) |
| `gsn/mermaid/markdown [ID\|*]` | optional | GSN diagram as a fenced Mermaid block |
| `gsn/mermaid/html [ID\|*]` | optional | GSN diagram as `<pre class="mermaid">` |
| `ltac [ID\|*]` | optional | LTAC argument list (auto-detects format) |
| `ltac/markdown [ID\|*]` | optional | LTAC as an indented Markdown bullet list |
| `ltac/html [ID\|*]` | optional | LTAC as a nested HTML `<ul>` list |
| `ltac/txt [ID\|*]` | optional | LTAC as raw text (IDs, options, refs; no Markdown or HTML) |
| `info ID` | required | Full context for one element: ancestors, children, citation parents, counts |
| `statement ID` | required | Single-line statement: `Statement: …` |
| `warning` | none | Fixed "do not edit" comment pair |
| `stop` | none | Sentinel: ends the preceding element's full content; see below |
| `epilogue` | none | Like `stop`, and also causes `--fixmissing` to insert new stubs before this point; element selectors must not follow it; see below |

The shorthand expansions are:

| Written | Expands to (Markdown doc) | Expands to (HTML doc) |
|---|---|---|
| `sacm` | `sacm/mermaid/markdown` | `sacm/mermaid/html` |
| `sacm/mermaid` | `sacm/mermaid/markdown` | `sacm/mermaid/html` |
| `gsn` | `gsn/mermaid/markdown` | `gsn/mermaid/html` |
| `gsn/mermaid` | `gsn/mermaid/markdown` | `gsn/mermaid/html` |
| `ltac` | `ltac/markdown` | `ltac/html` |

Two CLI shortcuts exist for the most commonly used inspection selectors:

| Flag | Equivalent |
|---|---|
| `--info ID` | `--select "info ID"` |
| `--descendants ID` | `--select "ltac/txt ID"` |

---

## Configuration

Configuration is supplied in a TOML file, either via `--config FILE` or
auto-discovered from `verocase.toml`, `docs/verocase.toml`, `case.toml`, or `docs/case.toml`.
All keys are optional; unrecognized keys produce a warning.

| Key | Default | Description |
|---|---|---|
| `base_url` | `""` | Base URL for hyperlinks in `sacm/mermaid` and `gsn/mermaid` output.  Set to the GitHub URL of the rendered output document so that diagram node `click` targets resolve correctly. |
| `bottom_padding` | `true` | Adds an invisible `BottomPadding` node in Mermaid diagrams to prevent GitHub's floating diagram controls from obscuring the bottom row of nodes. |
| `default_renderer` | `"mermaid"` | Renderer used when expanding the `sacm` and `gsn` shorthand selectors.  Currently only `"mermaid"` is supported. |
| `default_representation` | `"sacm"` | Diagram notation used by the `package` selector.  Accepts `"sacm"` or `"gsn"`. |
| `document_files` | `[]` | List of document files to process; equivalent to listing them on the command line.  Command-line files take priority. |
| `element_level` | `3` | Markdown/HTML heading level (1-6) used by the `element` selector.  Can also be set per-document with `verocase-config`. |
| `element_selections` | `"referenced_by,supported_by,supports,ext_ref"` | Comma-separated list of sub-sections rendered inside each `element` region.  Valid values: `referenced_by`, `supported_by`, `supports`, `ext_ref`. |
| `ltac_file` | `""` | Path to the LTAC file; overridden by `--ltac`. |
| `markdown_base_url` | `""` | Base URL for hyperlinks in `ltac/markdown` and `ltac/html` output. |
| `max_backups` | `20` | Number of backup snapshots to keep in `.backups/` next to the LTAC file.  Each time verocase modifies any file it saves a complete snapshot (all modified files, the LTAC, and the config) in a timestamped subdirectory before making changes.  Older snapshots are silently rotated out.  Set to `0` to disable backups entirely.  Cannot be set per-document with `verocase-config`. |
| `max_mermaid_children` | `8` | Maximum number of visual children a node may have before the width-management transform splits the overflow into a synthetic `Connector`.  Set to `0` to disable the transform entirely. |
| `mermaid_js_url` | CDN URL | URL of the Mermaid JS script injected into HTML output.  Set to `""` to disable injection. |
| `narrowed_mermaid_children` | `6` | Number of children retained (left + right combined) when the width-management transform splits a wide node; the middle overflow becomes a `Connector`.  Must satisfy `narrowed_mermaid_children >= 2` and `narrowed_mermaid_children < max_mermaid_children` (when `max_mermaid_children > 0`).  Can also be set per-document with `verocase-config`. |
| `package_level` | `3` | Heading level (1-6) used by the `package` selector.  Can also be set per-document with `verocase-config`. |
| `package_selections` | `"representation,pkg_defines,pkg_citing,pkg_cited"` | Comma-separated list of sub-sections rendered inside each `package` region.  Valid values: `representation`, `pkg_defines`, `pkg_citing`, `pkg_cited`. |
| `pkg_header_prefix` | `"### "` | String prepended to each package header when rendering `*` with `ltac/*` selectors. |
| `pkg_header_suffix` | `"\n"` | String appended after each package header when rendering `*` with `ltac/*` selectors (a newline by default, producing a blank separator line). |
| `pkg_label` | `"Package "` | Word (with trailing space) used to identify packages in rendered output. |
| `warn_dubious_reference` | `true` | Warn when a node's reference field looks like a parenthetical comment (non-empty, no `.`, doesn't start with `#`).  Set to `false` to suppress these warnings.  Must be set in the config file; cannot be set per-document. |

---

## Document integration

### Marked regions

Anywhere in a Markdown or HTML document, the pair:

```
<!-- verocase SELECTOR -->
…stale content…
<!-- end verocase -->
```

marks a region whose content `verocase` replaces with freshly rendered
output for `SELECTOR`.
The opening and closing comment lines are preserved; only the content
between them is replaced.
If `SELECTOR` produces no output, the region is left empty.

Do *NOT* edit text within such regions! Your text will be replaced
then text time it's regenerated!

Marked regions may use any selector.
A common document structure might look like this:

```markdown
# Assurance case introduction

<!-- verocase warning -->
<!-- end verocase -->

## Introduction

Some introductory text

## Packages
<!-- verocase package * -->
<!-- end verocase -->

<!-- verocase element C1 -->
<!-- end verocase -->
... information about C1 ...

<!-- verocase element C2 -->
<!-- end verocase -->
... information about C2 ...
```

But you not limited to that. Other examples:

```markdown
<!-- verocase sacm/mermaid * -->
<!-- verocase gsn/mermaid * -->
<!-- verocase ltac/markdown * -->
<!-- verocase sacm/mermaid C1 -->
<!-- verocase statement C1 -->
```

### element and package selectors

The `element` and `package` selectors generate structured headings and
cross-reference sub-sections, providing a stable home for each piece of
the assurance case in the document.

**`<!-- verocase element ID -->`** generates:

- A heading at the level specified by `element_level` (default: `###`),
  using the element's type and identifier as its text, with a stable
  HTML anchor for deep-linking.
- Sub-sections controlled by `element_selections`:
  - `referenced_by`: lists packages that reference this element.
  - `supported_by`: lists the element's direct supporting children.
  - `supports`: lists what this element directly supports.

**`<!-- verocase package [ID|*] -->`** generates:

- A heading at the level specified by `package_level` (default: `###`),
  with a stable HTML anchor.
- Sub-sections controlled by `package_selections`:
  - `representation`: the default diagram (SACM or GSN per `default_representation`).
  - `pkg_defines`: lists elements defined in this package.
  - `pkg_citing`: lists elements from other packages cited here.
  - `pkg_cited`: lists elements from this package cited elsewhere.

`*` renders all packages in order.

`verocase` warns if a declared LTAC element has no corresponding `element`
selector in any processed document.  Use `--read-only --empty` to report
missing elements without modifying any file, or use
`--fixmissing` to scaffold them automatically.

### Full element content, `stop`, and `epilogue`

When `--fixmisplaced` moves an element it moves its **full content**, not just
the generated region.  Full content begins at `<!-- verocase element ID -->`
and extends through `<!-- end verocase -->` and then through all following prose
lines (including any embedded non-element selectors such as
`<!-- verocase info X -->` or `<!-- verocase ltac/markdown X -->`) until one
of these **terminators** appears:

| Terminator | Example |
|---|---|
| Another element selector | `<!-- verocase element NextID -->` |
| The `stop` sentinel | `<!-- verocase stop -->` |
| The `epilogue` sentinel | `<!-- verocase epilogue -->` |
| A per-document config line | `<!-- verocase-config element_level = 2 -->` |

**Why non-element selectors are included:** authors often place a
`<!-- verocase info X -->` or `<!-- verocase ltac/markdown X -->` block
immediately after an element's prose to provide supplemental context.
If those selectors were treated as terminators, `--fixmisplaced` would
silently sever them from the element they annotate and leave them stranded
at the original location.  Treating them as part of the element's full content
means they travel with it.

**Why `<!-- verocase-config -->` is a terminator:** config directives typically
set heading levels or other rendering parameters for the *next* element.  They
belong at the new location of the following element, not the end of the
preceding one.

#### `stop`: stable inter-element content

`stop` lets you write sections (introductions, transitions, contextual
asides) anywhere in the document that should never be repositioned.  The
content after `stop` is not part of any element's full content and will not be
moved by `--fixmisplaced`.  New stubs from `--fixmissing` may still be appended
after a `stop` if there is no `epilogue` to act as the fallback boundary.

`stop` can appear any number of times.  Each occurrence independently breaks
the preceding element's ownership; the next element selector after it begins a
fresh ownership region.

```markdown
<!-- verocase element SomeClaim -->
<!-- end verocase -->

Prose for SomeClaim…

<!-- verocase stop -->
<!-- end verocase -->

This transition paragraph stays here regardless of reorganization.

<!-- verocase element NextClaim -->
<!-- end verocase -->
```

#### `epilogue`: end of main element content

`epilogue` does everything `stop` does, and additionally:

1. **Directs `--fixmissing`:** when scaffolding missing element stubs, any
   element with no predecessor already in the document is placed *before* the
   `epilogue` marker rather than at the very end of the file.  Elements whose
   natural LTAC predecessor already has a region are still placed after that
   predecessor (smart placement takes priority).

2. **Forbids following element selectors:** verocase reports an error if a
   `<!-- verocase element ID -->` selector appears anywhere after an `epilogue`
   in the same document.  This catches accidental confusion between the main
   body and the epilogue.

Use `epilogue` once, at the point where the main element content ends and
stable end-of-document prose begins:

```markdown
<!-- verocase element LastClaim -->
<!-- end verocase -->

Prose for LastClaim…

<!-- verocase epilogue -->
<!-- end verocase -->

## Conclusions

This section is stable.  --fixmisplaced will never move it, and
--fixmissing inserts any new stubs above this point.
```

The starter document created by `--start` includes an `epilogue` before its
`## Notes` section to illustrate this pattern.

Both `stop` and `epilogue` take no ID argument.  Their generated content is a
fixed HTML comment; do not edit it.

### Per-document configuration

A document may override selected configuration keys for itself using
`verocase-config` directives:

```
<!-- verocase-config KEY = VALUE -->
```

The directive takes effect from that point in the document onward.
Currently supported keys:

| Key | Accepted values |
|---|---|
| `base_url` | any string (URL or empty) |
| `element_level` | `1`-`6` |
| `max_mermaid_children` | non-negative integer |
| `narrowed_mermaid_children` | non-negative integer |
| `package_level` | `1`-`6` |

Keys that affect LTAC parsing (such as `warn_dubious_reference`) cannot be
set per-document because LTAC is parsed before documents are read.
Set them in the `--config` TOML file instead.

Example: use level-2 headings for packages and level-3 for elements:

```markdown
<!-- verocase-config package_level = 2 -->
<!-- verocase-config element_level = 3 -->
```

Example: set `base_url` for GitHub click links in a specific document:

```markdown
<!-- verocase-config base_url = https://github.com/OWNER/REPO/blob/main/docs/case.md -->
```

Do **not** use `<!-- verocase config ... -->` (without the hyphen); that
syntax is recognized and produces a helpful error directing you to the
correct form.

### Anchor naming

Anchors for element and package headings are derived from the element type
and identifier only (statement text is excluded so that anchors remain
stable when statements change):

1. Form the string `TYPE ID` (e.g., `Claim C1`, `Package Requirements`).
2. Lowercase everything.
3. Remove characters that are not Unicode letters, digits, hyphens, or spaces.
4. Replace spaces with hyphens.
5. Collapse runs of hyphens; strip leading and trailing hyphens.

Examples:

| Type + Identifier | Anchor id |
|---|---|
| `Claim C1` | `claim-c1` |
| `Package Requirements` | `package-requirements` |
| `Strategy AR1` | `strategy-ar1` |

---

## Diagram output

### SACM/mermaid

The `sacm/mermaid` selector renders SACM notation using a Mermaid `flowchart BT`
(bottom-to-top) diagram.  Child elements appear below their parents;
arrows point upward toward the claim being supported.

#### SACM node shapes

| LTAC type | SACM concept | Mermaid shape |
|---|---|---|
| `Claim` | Claim | Rectangle `["…"]` |
| `Claim` with `assumed` | Claim (assertionDeclaration=assumed) | Rectangle, label appended with `<br>ASSUMED` |
| `Claim` with `needsSupport` | Claim (needsSupport) | Dashed rectangle (`abstractClaim` class) |
| `^`-prefixed Claim | Claim (asCited) | Double bracket `[["…"]]` |
| `Strategy` | ArgumentReasoning | Parallelogram `[/"…"/]` |
| `Evidence` | ArtifactReference | Cylinder `[("…")]`, label includes `↗` |
| `Context` | ArtifactReference (AssertedContext) | Cylinder `[("…")]`, label includes `↗` |
| `Assumption` | Claim (assumed) | Rectangle, label appended with `<br>ASSUMED` |
| `Justification` | Claim | Rectangle |

#### SACM inference arrows and sacmDots

SACM represents a single inference relationship as an `AssertedRelationship`.
When multiple children share the same parent, they all connect to a single
filled black dot (a *sacmDot*) that then connects to the parent.
This matches the SACM graphical notation from Annex C of the SACM specification.

```
    Child1 --- Dot1
    Child2 --- Dot1
    Dot1((" ")):::sacmDot --> Parent
```

`Context` children always use a separate context arrow (`--o`) and are
not grouped into a sacmDot.

When there is exactly one inferential child (and no metaClaim), the
unreified form is used: a direct arrow from child to parent with no dot.

#### Click links in SACM diagrams

Every identified node gets a `click` line.  The URL is:

- `base_url + "#" + fragment` when `base_url` is set (full absolute URL,
  required for GitHub rendering).
- `"#" + fragment` when `base_url` is empty (fragment-only link; works on
  platforms that resolve fragments within the same page, such as local HTML
  preview, GitLab, and Gitea).

The fragment used is:

| Node kind | Fragment |
|---|---|
| Citation (`^ID`) | `package-<id>` (the cited element's package heading) |
| Declaration | `<type>-<id>` (the element's own heading) |

### GSN/mermaid

The `gsn/mermaid` selector renders GSN notation using a Mermaid `flowchart TD`
(top-down) diagram.  Arrows point **downward** from each goal or strategy
to the elements that support it, matching standard GSN convention.

#### GSN node shapes

| LTAC type | GSN element | Mermaid shape |
|---|---|---|
| `Claim` | Goal | Rectangle `["…"]` |
| `Claim` with `needsSupport` | Undeveloped Goal | Dashed rectangle (`gsnUndev` class), label appended with `<br>◇` |
| `^`-prefixed Claim | Away Goal | Subroutine `[["…"]]` |
| `Strategy` | Strategy | Parallelogram `[/"…"/]` |
| `Evidence` | Solution | Circle `(("…"))` |
| `Context` | Context | Stadium `(["…"])` |
| `Assumption` | Assumption | Rounded rect with Ⓐ |
| `Justification` | Justification | Rounded rect with Ⓙ |

In GSN, each child gets its own direct arrow from the parent (no shared dot).
`Context`, `Assumption`, and `Justification` use the `--o` context arrow.

### ltac/markdown and ltac/html

`ltac/markdown` renders the argument tree as an indented Markdown bullet
list; `ltac/html` renders it as nested HTML `<ul>` lists.
Both add hyperlinks on each element label.  The URL for each element is
determined using `markdown_base_url` (default empty) by the same rules as
SACM/GSN click links.

When `*` is used, all packages are rendered in order, each preceded by a
configurable package header (`pkg_header_prefix` + identifier + `pkg_header_suffix`).

---

## Validations

The following checks always run when an LTAC file is loaded.
Errors cause a non-zero exit; warnings do not (unless `--error` is given).

**Fatal errors:**

- **Circular reasoning**: following children and citations must never form
  a loop.  The full cycle is reported, e.g., `C2 -> C4 -> C2`.

- **Unreachable package**: in a multi-package file, each package root must
  be reachable from the first element of the first package
  (following structural children, citation declarations, and Link targets).

- **Unresolved citation**: a `^ID` citation with no matching declaration.

- **Duplicate declaration**: an identifier declared (without `^`) more than once.

- **Anchor collision**: two identifiers that generate the same HTML anchor
  id (e.g., `Foo < 0` and `foo > 0` both produce `foo--0`).

**Warnings:**

- **Structural violation**: `Claim` or `Strategy` as a direct child of
  `Evidence`, `Context`, or `Assumption`.

- **Inconsistent type**: the same identifier used with different element types.

- **Inconsistent statement**: statement text that differs between the
  declaration and a citation or Link (use `--sync` to fix).

- **Multiple assertion statuses**: more than one of `needsSupport`,
  `assumed`, `axiomatic`, `defeated`, `asCited` on the same element.

- **Wrong citation package**: `^[PkgName] ID` where `PkgName` does not
  match the package that declares `ID`.

- **Cited but undeclared**: an identifier cited but never declared
  (distinct from "unresolved": the identifier may exist in an unloaded file).

**Additional checks when document files are processed:**

- A declared LTAC element with no corresponding `element` selector in any
  processed document (each element is expected to have a place for its
  supporting detail).

---

## Updating the LTAC file

By default, `verocase` treats the LTAC file as read-only.
Several options cause it to write an updated LTAC file.
All of them use the same safe backup mechanism (see [File handling](#file-handling)).

### --sync

Walks every citation and Link node in the LTAC tree.
If a node carries statement text that differs from the declaration's text,
the node's text is replaced with the declaration's text.
Reports the count of changed nodes and writes the file if any changes were made.

Example: if `- Claim ^C1: Old statement` is found but the declaration is
`- Claim C1: New statement`, `--sync` rewrites the citation to
`- Claim ^C1: New statement`.

### --rename OLD NEW

Renames identifier `OLD` to `NEW` in the LTAC forest and then rewrites the
LTAC file.
When document files are also processed in the same run, all `element` and
`package` selectors and `statement` selectors in those documents are updated
to use the new name.

After renaming, all validations are re-run; if any errors result, no files
are written.

### --restate LABEL STATEMENT

Changes the statement text of `LABEL` to `STATEMENT` in the LTAC forest and
rewrites the LTAC file.

### --detach ID

Replaces `ID`'s definition with a citation (`^ID`) at its current location
and moves its entire subtree to a new top-level package.
Panics if `ID` is not defined or is already a top-level package root.

Use `--detach` to break a large package into smaller ones.  After detaching,
the original package retains a `^ID` citation, preserving the argument
structure, while `ID` becomes the root of its own package.

### --move ID DESTINATION

Moves `ID`'s definition to be a child of `DESTINATION`.  `ID` may be anywhere
in the tree (top-level or nested).  If `^ID` is already a direct child of
`DESTINATION` it is replaced by the definition; otherwise the definition is
appended as the last child.  No citation is left at the original location;
to leave one behind, run `--detach ID` first, then `--move ID DESTINATION`.
Panics if `ID` or `DESTINATION` is not defined.

### Mutation ordering

`--rename`, `--restate`, `--detach`, and `--move` all share a single ordered
mutation queue and may be given more than once per invocation.
Mutations are applied in the order specified on the command line.  Order
matters: for example, `--detach C2 --move C2 C1` detaches `C2` first
(leaving `^C2` in place), then moves `C2` under `C1`.
The LTAC file is written once with all mutations applied.

---

## File handling

### Auto-discovery

If no `--ltac` option and no `ltac_file` config key are given, `verocase`
looks for `case.ltac` in the current directory, then `docs/case.ltac`.
If neither exists, it exits with an error.

Similarly, if no document files are given on the command line and no
`document_files` config key is set, it looks for any of the following
(in order): `case.md`, `case.markdown`, `case.html`,
`docs/case.md`, `docs/case.markdown`, `docs/case.html`.

Config file auto-discovery: `verocase.toml`, `docs/verocase.toml`, `case.toml`,
`docs/case.toml` (searched in that order).

### Safe file updates

All file writes are done atomically to prevent data loss:

1. The updated content for each file is written to a temporary file in the
   **same directory** as the target.
2. A complete timestamped snapshot of the current state (all files about to
   be modified, the LTAC file, and the config file if any) is saved under
   `.backups/` next to the LTAC file in a subdirectory named by the current
   time (e.g., `.backups/2026-03-17T142305.07/`).
3. The temporary files are moved into place as the final destinations.

If the updated content is identical to the original, the file is not
touched and no backup is created.

If a serious error occurs during processing, the files are left unchanged.

### The `.backups/` directory

`verocase` maintains a `.backups/` directory next to the LTAC file.
Each time any file is modified, a complete snapshot of the pre-change state
is saved in a new timestamped subdirectory.  Up to `max_backups` snapshots
are kept (default 20); older ones are automatically deleted.

To recover from an accidental edit inside a marked region, find the most
recent timestamped subdirectory in `.backups/` and copy the file back.

Set `max_backups = 0` in the config to disable backups entirely.

Add `.backups/` to `.gitignore` if you do not want snapshots tracked by git.

---

## Exit codes

| Code | Meaning |
|---|---|
| 0 | Success (no errors; any warnings were non-fatal) |
| 1 | One or more errors occurred, or warnings occurred with `--error` |

---

## See also

- [Extended LTAC format specification](ltac-extended.txt)
- [SACM notation in Mermaid: conventions](sacm-mermaid.md)
- [GSN notation in Mermaid: conventions](gsn-in-mermaid.md)
- [Design specification](design-spec.md)
- [README](../README.md)
