<!-- Sema documentation — Documents & Reports
     Sema is a new AI-native, neurosymbolic programming language most models
     have not been trained on. Full corpus: https://sema.49.12.246.95.sslip.io/llms-full.txt
     Install language support: https://sema.49.12.246.95.sslip.io/install-skill/ -->

# Documents & Reports

> Generate structured, auditable reports in Sema — a typed Report the model fills and a deterministic renderer, plus docs as a reflected artifact.

The last mile of most AI programs is a **document**: a report, a case summary, a
briefing. The tempting shortcut is to ask a model for Markdown and hope it comes
back well-formed — then patch it with regexes when it doesn't. Sema splits the
job cleanly: the model fills a **typed structure**, and rendering that structure
to Markdown is a **pure, deterministic function**. Layout is structural, not a
prompt convention.

This guide uses the [`std.document`](/stdlib/document/) module for the report IR
and anchors on the [`finops-ledger`](/reference/examples-api/finops-ledger/)
example for grounded, review-gated report generation.

## The pieces

| Concern | Construct | Where |
|---|---|---|
| Typed report IR | `Report` struct + `render` | [std.document](/stdlib/document/) |
| Model fills a typed value | `simulate def … by <model>` | [simulate & Models](/neurosymbolic/simulate/) |
| Grounding the output | `check semantics(…)` | [Contracts](/neurosymbolic/contracts/) |
| Docs from the program | `sema doc` (docstrings + reflection) | this guide, §"Docs as artifact" |

## A typed report

`std.document` defines a `Report` the model (or your code) fills, and a
deterministic `render(report, nl)` that emits Markdown. `nl` is the newline
separator — parametrizable so the same renderer emits a single-line form for
tests or real newlines for output.

```sema
struct Report:
    title: str
    context: str
    confidence: f64          # < 0 means "no confidence section"
    rationale: str
    takeaways: list[str]
    section_titles: list[str]
    sections_text: str
    conclusion: str
```

Rendering is a function, so what you build is what you get — no regex repair of
freeform LLM Markdown, and section placement is structural:

```sema
from std.document import Report, render

r = Report(
    title="Renewable Energy Findings",
    context="Auto-synthesized from 2 sources.",
    confidence=0.82,
    rationale="Confidence is a Beta-Bernoulli posterior over iteration evidence.",
    takeaways=["costs fell", "capacity grew"],
    section_titles=["Findings"],
    sections_text="Solar capacity grew [1]. Costs fell [2].",
    conclusion="Costs continue to decline as capacity scales.",
)
print(render(r, "\n"))
```

Set `confidence` below zero to omit the confidence section entirely — the
renderer treats it as a signal, not just a number.

:::tip
Because `render` is `!{}` (pure, no effects), you can call it in a `test` block
and assert on the exact Markdown. Use `render(r, "\n")` for real output and
`render(r, " ")` (a single-line form) when comparing strings in tests.
:::

## Letting a model fill the report

For a report whose *prose* comes from a model, don't ask the model for Markdown —
ask it for the typed fields. A `simulate def … by <model>` has the model
implement the body, decoded into your struct, with contracts on the result. The
`finops-ledger` example drafts a compliance case summary this way:

```sema
simulate def draft_suspicious_activity(
    decision: ReconciliationDecision,
    bank: BankLine,
    ledger: list[LedgerEntry],
) -> SuspiciousActivityDraft by anomaly_writer:
    sem "Draft a cautious case summary for a compliance analyst"
    sem "Do not claim criminality; state uncertainty and cite evidence references"
    budget tokens=768, time="3s"
    ensure len(result.reasons) >= 1
    ensure result.subject_counterparty_id != ""
    check semantics(
        "draft is grounded in the reconciliation decision and does not overstate certainty",
        decision,
        result,
        judge=report_grounder,
        alpha=0.01,
    )
```

Three things make this an *auditable* document rather than a hopeful one:

- **`ensure`** contracts are hard — a draft with no reasons raises
  `ContractViolation`.
- **`check semantics(…)`** is a soft, monitored guard: a judge model verifies the
  draft is *grounded* in the decision and doesn't overstate certainty, at a
  calibrated significance `alpha`.
- **`budget tokens=…, time=…`** caps what the draft may cost.

See [Contracts](/neurosymbolic/contracts/) for the full contract vocabulary and
[Schemas & Typed Decode](/neurosymbolic/schemas/) for how the model's output is
decoded into the struct.

## Gating a report before it leaves the building

A generated document usually needs a review gate before it becomes an artifact.
In `finops-ledger`, the export path requires a human approval record, sanitizes
the draft, and wraps the write in a semantic guard so a non-conforming draft is
quarantined instead of shipped:

```sema
@RegulatedExport
def export_after_approval(draft: SuspiciousActivityDraft, approval: AnalystApproval) -> None !{fs.write, net.connect, model.invoke}:
    safe = sanitize_draft(draft)
    report_path = validate f"out/regulatory/{approval.decision_id}.json":
        sem "Local regulated-report path derived from analyst approval"
        ensure path.is_relative_to(value, "out/regulatory")
        ensure not path.contains_parent_ref(value)
    expect semantics("regulated draft contains only approved evidence and no raw account number", safe, judge=policy_judge, alpha=0.01):
        write_report(report_path, safe)
        log.info("regulated export prepared")
        submit_report("https://regulator-gateway.internal:443/drafts", safe)
    except SemanticsViolation as violation:
        quarantine(safe, evidence=violation)
```

The `validate f"…"` block turns an interpolated path into a checked value — the
`ensure` guards keep the write inside `out/regulatory` and reject `..`
traversal — so the document's *destination* is as governed as its contents.

## Documentation as a reflected artifact

Your **program itself** is a document too. In Sema, documentation is generated by
reflection over the code, merged with prose you write inline as **docstrings** — a
triple-quoted string as the first statement of a module, `def`, `struct`, or
`enum` (as in Python). Unlike a comment, a docstring is a real value the runtime
can reflect:

```sema
"""Geometry helpers."""

def norm(x: f64, y: f64) -> f64 !{}:
    """
    The Euclidean norm of a 2-D vector: $\|v\|_2 = \sqrt{x^2 + y^2}$.

    > [!NOTE]
    > The result is always non-negative.

    ```sema
    n = norm(3.0, 4.0)   # -> 5.0
    ```
    """
    return math.sqrt(x * x + y * y)
```

`sema doc <project>` then emits Markdown that combines **reflection** (the exact
signature, params, return type, effect row, struct fields with their `sem`
descriptors, enum variants — always accurate because it *is* the code) with your
**docstring prose** (Markdown, LaTeX, `> [!NOTE]` admonitions, `sema` examples,
passed straight through). Docstrings are dedented like Python's
`inspect.cleandoc`, and being triple-quoted they are raw — LaTeX backslashes
survive untouched.

Two flags close the loop:

- `--html` renders a self-contained page (KaTeX-typeset math, admonitions, code
  blocks) with no build step — the "nice page".
- `--skills` emits each module's doc with skill frontmatter, so generated docs
  load as **model context** via `skills.load` (see
  [Tools, Skills & MCP](/guides/tools-and-mcp/)) — code that documents itself to
  humans *and* to the models that read it.

:::note
The API-reference pages on this site — including the
[std.document reference](/reference/examples-api/finops-ledger/) example gallery
entry — are produced by `sema doc`. The reflected signatures can't drift from the
code, because they *are* the code.
:::

## Run and verify

From the `sema/` directory:

```bash
sema check examples/finops-ledger
SEMA_STRICT=1 sema run examples/finops-ledger
sema assure examples/finops-ledger --grade gold
sema doc examples/finops-ledger --html
```

`finops-ledger` is an `assure gold` project — the strongest grade, which
mutation-tests on top of running `test` blocks and fuzzing `ensure` properties.

## Variations

- **A single-page HTML report** — render a `Report`, write it with `fs.write`,
  then `sema doc --html` the module for the reflected companion page.
- **A briefing instead of a report** — the
  [`crisis-logistics`](/reference/examples-api/crisis-logistics/) example drafts a
  public safety `PublicBriefing` with the same `simulate def` + `check semantics`
  shape, then redacts and gates it before publication.
- **Test the exact Markdown** — because `render` is pure, put a golden string in a
  `test` block and let `sema assure` verify layout stability.

## See also

- [std.document](/stdlib/document/)
- [finops-ledger example (generated)](/reference/examples-api/finops-ledger/) ·
  [crisis-logistics example (generated)](/reference/examples-api/crisis-logistics/)
- [simulate & Models](/neurosymbolic/simulate/) · [Contracts](/neurosymbolic/contracts/) · [Schemas & Typed Decode](/neurosymbolic/schemas/)
