---
title: Branded report template (agents deliver ready-made report pages)
---

# Branded report template (agents deliver ready-made report pages)

## What it is

When an Omniscio agent produces a **report deliverable** — research findings, a tool
roundup, recommendations, an audit, a comparison — it no longer designs an HTML page from
scratch. The product ships ONE standard **Aurora-branded report template**, renders it
server-side from plain data, and every locally-spawned session is automatically told to use it.

## Where to find it

### What the user sees

Reports published to Shares arrive **on-brand and consistent**: the Omniscio orb + the all-caps
OMNISCIO logotype, restrained aurora color, and a readable layout that leads with the answer.
An optional brief puts the verdict, next move, and takeaways before metadata. Supporting
sections are built from editorial blocks — headings, short paragraphs, lists, tables,
callouts, numbered rules — with tool cards for genuine roundups and ranked "Start Here"
picks. A sticky section nav, light/dark toggle (dark default), mobile-friendly layout,
clean printing, and reduced-motion support complete the shared shell.

The top bar carries the **report's own title** beside the logo, separated by a divider — it is how
the document names itself before the hero does, so it is worth setting. The bar scrolls away with
the page rather than pinning, so it never spends viewport height for the whole read; the section
nav below it is the one bar that stays pinned.
Use `docTitle` (short, plain text, no markup); omit it and it falls back to `brandSub`, then to
"Report".

**The "Start Here" picks jump to the tool they recommend.** Give each `topPicks` entry a `ref`
naming the exact `name` of the card it points at (or a section `id`) and that pick becomes a link:
clicking it scrolls to the card and rings it, so the reader can see where they were sent. Fill this
in — a pick's title is usually editorial ("IP Clearance (free)") and does NOT match the product name
on its card ("IP Clearance Before Sourcing"), so without `ref` a link is inferred only when the two
happen to be identical. A pick that resolves to nothing renders unlinked rather than guessing.

A curated **"Branded Research Report" Super Prompt** ships in the built-in catalog: launch it,
say what to research, and the session researches the topic and hands back a finished branded
report link.

## How it behaves

### Styles — read it, or present it

The template ships as a **catalog of named styles** rather than a single fixed page. There are two:

- **Aurora** — the Omniscio house style, dark by default, editorial body, sticky section nav. A
  page you READ: scroll it, search it, skim it, print it. The right answer unless you have a reason
  otherwise, and what you get if you ask for nothing.
- **Deck** — the same report as full-screen slides. One idea per slide, arrow keys, an overview
  index, a blank screen for when the room should be looking at you. Reach for it when someone will
  PRESENT the findings rather than read them.

**Deck takes no extra work and no different data.** It reads the same report object Aurora reads
and works out the slides from what is already there — a section becomes a chapter divider, a quote
block becomes a full-bleed quote, a numbered rule list becomes one slide per rule, a table stays a
table and splits across slides if it is long. So a report you have already written becomes a deck by
asking for one, and the same report can be both.

**You can also NAME the slide you want.** Inference is the default and it is usually right, but a
block may carry a `layout` when you have something specific in mind. Four to choose from, each
reading data the report already has:

| `layout` | What it gives you | Put it on a block with |
| --- | --- | --- |
| `bignum` | ONE figure at the size of the room, with its label and an optional line of context. | `stats` — the first entry is the figure. Use it when one number matters more than the rest; the stat GRID is for comparing several. |
| `compare` | Two panels of equal weight, side by side. | `kv` with exactly two entries — before and after, ours and theirs, the claim and what happened. |
| `timeline` | The entries hung off a rail, so the eye reads the ORDER first. | `kv` or `list`, two to six entries. Use it when the sequence is the point, not the items. |
| `matrix` | Four quadrants, with optional axis labels via `axes: ["Effort →", "← Impact"]`. | `kv` with exactly four entries — impact against effort, likelihood against cost. |

A `layout` is a hint about presentation, never a new schema: it is honoured only when the block
actually carries the data that structure needs, and a name that is unknown or does not fit falls
straight through to the inferred slide. So a typo can cost you the structure you wanted; it can
never cost you the slide. Give the block an `h` as well and it keeps its own heading — without one
it inherits the section's name, and the deck then drops the heading rather than printing the same
words twice.

It is navigable the way any presentation is: arrows, space, page up and down, Home and End, `F` for
fullscreen, `O` for the overview, `B` or `W` to blank the screen, a slide number then Enter to jump,
and `?` for the full list. On a phone you swipe. `Ctrl+P` prints one slide per page. A link ending
`#7` opens on slide 7.

Ask for a style with an optional `style` alongside your data. **Omit it and you get the default**, so
nothing written before the catalog existed needs to change. `GET /report-template/styles` lists
every style with a one-line note on when to reach for it, so an agent can pick at runtime instead of
reading source. An unrecognised name is refused, naming the valid ones — a typo never quietly
produces a report in a style you did not choose.

Re-publishing an existing report with its `updateToken` and a different `style` re-renders it in the
new look at the **same link**. Restyling something you already shared does not mint a new URL or
strand the one people have.

Adding a style is deliberately two mechanical steps — drop a self-contained HTML file carrying the
splice markers into `resources/report-template/styles/`, add one row to `REPORT_STYLES` — and a
build guard fails if you do one without the other. Which standard to use in the first place, and the
full add-a-style walkthrough, live in the agent-facing report-standards guide.

### The standard reading order

For a report, recommendation, or proposal, use **headline → verdict → next move →
takeaways → supporting detail**. Keep the headline short, the verdict to two sentences,
and aim for three one-sentence takeaways. Put the conclusion and any decision before
metadata. Never hide critical caveats inside a collapsed section.

`action` is readable next-step text, not an executable button. Omit it when nothing
needs doing. Brief values and section prose are **plain text**; HTML-looking strings
render literally. Existing rich-text fields and tool cards remain supported. Omitting
`brief` preserves the previous report layout.

### How to write the body — the house style

A report is a **document someone reads**, not a dashboard of summary tiles. It fails in
two opposite ways, and both are fatal: a wall of undifferentiated text, or real detail
crushed into one-line cards until the report says nothing.

- **Keep the detail.** Never compress an explanation into a card blurb to make it fit a
  shape. Long is fine; unreadable is not. Twenty rules with reasoning stay twenty rules
  with reasoning.
- **Break it up instead.** A heading every 150–250 words. Paragraphs of two to four
  sentences, one idea each. That — not deletion — is what makes length readable.
- **Use the block that matches the content.** Prose that is really a table reads as a
  wall of text; an argument crammed into cards reads as nothing at all.
- **Nothing important hides.** A reader should be able to scroll the whole report
  without clicking. `collapsible: true` is for an appendix, never for a finding, a
  decision, or a caveat.

### Section blocks

Each section carries `blocks` — an ordered list of typed blocks. The first recognised
key decides what a block is — `{"p": "…"}` — and the discriminator spelling works too:
`{"type": "p", "text": "…"}` (or `"kind"`) is normalised onto the same block, including
`{"type":"list","items":[…]}`, `{"type":"table","columns":[…],"rows":[…]}` and
`{"type":"callout","tone":"warn","title":"…","text":"…"}`. A shape neither form recognises
renders as a visible "Unrendered block" warning carrying your data, so it is never lost —
that warning is your signal to fix the block before anyone reads the report. Every value is plain text: it is escaped first, then a
small inline vocabulary is applied to the escaped string (`**bold**`, `*italic*`,
`` `code` ``, `[text](url)` with `http`/`https`/`mailto`/`#` hrefs only), so caller data
can never introduce a tag the template did not emit.

Emphasis also accepts its HTML spelling — `<strong>`, `<b>`, `<em>`, `<i>` and `<code>`
render the same as the markdown above, because the example REPORT writes emphasis that
way in the legacy `title` and card `desc` fields and authors reasonably carry it across.
Nothing else does: a `<span class="g">`, an `<img>`, a `<ul>`, or one of those five tags
carrying an attribute stays escaped and shows up as literal angle brackets on the page.
That is the signal the tag is unsupported — reach for the block type instead.

| Block | Shape | Use it for |
| --- | --- | --- |
| `lead` | `{ "lead": "…" }` | The opening line of a section, one size up |
| `h` / `h4` | `{ "h": "…" }` | A sub-heading (h3) / a minor heading |
| `p` | `{ "p": "…" }` or a bare string | A short paragraph |
| `list` | `{ "list": ["…"], "ordered": true }` | Enumerations; bold run-ins read well here |
| `kv` | `{ "kv": [["Term", "Meaning"]] }` | Term and definition |
| `table` | `{ "table": { "cols": [], "rows": [[]], "note": "" } }` | Tabular facts and measurements |
| `callout` | `{ "callout": { "kind": "info\|good\|warn\|stop", "title": "", "text": "" } }` | A caveat, a status, a warning |
| `rules` | `{ "rules": [{ "n": "01", "title": "", "body": [], "violation": "" }] }` | Numbered rules, invariants, findings, phases |
| `quote` | `{ "quote": { "text": "…", "cite": "…" } }` | A quotation |
| `stats` | `{ "stats": [["2.6%", "what it measures"]] }` | Headline figures inside the body |
| `code` | `{ "code": "…" }` | Literal text rendered verbatim |

A report that uses `blocks` renders in **document mode**: one narrow reading column and
a document-sized hero instead of the wide marketing splash.

### The pinned router

`nav` is worth filling in on any report with more than two sections. It builds a bar that
stays pinned under the toolbar as the reader scrolls, and it takes two forms from the same
list:

- **Wide screens** — a chip rail. The chip for the section you're in lights up and slides
  itself into view, so the bar always shows where you are.
- **Phones** — a single row: a dot, the current section's name, `4 / 9`, and a chevron.
  Tapping it opens a numbered list of every section with the current one marked.

A gradient **reading-progress line** runs along the bottom edge of the bar, so a long
report shows how much is left. With no `nav` entries the bar is removed entirely rather
than pinned as an empty band.

Give each entry an `id` that matches a section `id`:

```json
"nav": [{ "id": "why", "label": "Why" }, { "id": "rules", "label": "The 20 rules" }]
```

```json
{
  "docTitle": "Documentation taxonomy",
  "title": "One question per doc.",
  "brief": {
    "verdict": "Every document answers one question and names one real feature it serves.",
    "action": "Fix the roadmap board first, then land the shared schema.",
    "takeaways": ["Three vocabularies collapse into one tree.", "Nothing moves on disk."]
  },
  "nav": [{ "id": "why", "label": "Why" }],
  "sections": [
    {
      "id": "why",
      "icon": "database",
      "title": "Why this exists",
      "blocks": [
        { "lead": "A document nobody can place is a document nobody maintains." },
        { "p": "The link the whole system depends on exists on **0.6%** of nodes." },
        { "h": "Measured on the live corpus" },
        { "table": { "cols": ["Family", "Files", "Anchored"], "rows": [["Contracts", "1,327", "35"]] } },
        { "callout": { "kind": "warn", "text": "Figures were measured, not estimated." } },
        {
          "rules": [
            {
              "n": "01",
              "title": "A document answers exactly one question",
              "body": ["A document that answers two questions is two documents."],
              "violation": "A contract that explains how the code works."
            }
          ]
        }
      ]
    }
  ]
}
```

**Cards (`items`) still exist** and are right for a genuine roundup of comparable things
— one tool per card, one vendor per card, each with a cost badge and source link. They
are the wrong home for an argument, a rule, or an explanation.

### Guarantees

- The fill-in markers appear exactly once each — build-guarded, and the server-side renderer
  re-verifies them at render time, so a splice can never hit the wrong spot.
- Rendered data is escape-hardened: report data can never break out of the page's script
  element, no matter what strings it contains.
- The template is self-contained (embedded logo; only Google Fonts load externally) and safe
  for the Shares mobile sandbox (no bottom-pinned fixed elements).
- The render route reuses the canonical share-publish pipeline (same limits, expiry defaults,
  short-link and update-in-place semantics); the GET route is read-only with no parameters;
  errors are humanized.

Contract: report-template-contract. Tests: presentation (reading order, literal prose,
disclosure navigation, print-state restoration, and legacy compatibility), template integrity
(lint lane), the pure renderer (escape + marker re-verification), shim shape + port-agility, prompt-bundle gating, and a
live-server integration suite (auth, content, one-step render + publish).

## For agents

### How it works (agent mechanics)

- The template is a **bundled asset** shipped with the app (`resources/report-template/`),
  so it exists on every install and versions with the product — zero setup.
- **Preferred path — one-step render:** the agent builds ONLY the report data (a JSON object)
  and POSTs it to `http://127.0.0.1:19519/report-template/render` with the standard
  `AMC_CLI_TOKEN` bearer — body `{ data, title?, label?, expiresIn?, shortLink?, updateToken? }`.
  The **server** splices the data into the bundled template (the AI never touches the HTML
  shell, so a malformed page is impossible) and publishes the result to Shares through the
  same pipeline as `/share/publish`, returning the share URL in one step.
- **Manual path:** `GET http://127.0.0.1:19519/report-template` returns the raw template
  (`text/html`). Its example `const REPORT = {...}` object between the two marker comments
  (`REPORT-DATA-START` / `REPORT-DATA-END`) documents every field; an agent may replace only
  that block and publish the file itself. Optional blocks (brief, chips, stats, top picks, next
  steps, footer) may be omitted and the page still renders cleanly.
- Every non-SSH spawned session receives this guidance automatically via the standing
  `[ BRANDED REPORT TEMPLATE ]` instruction (same delivery as the Shares/convert/download
  capabilities); SSH sessions are excluded because they cannot reach the local server.

## Related

Reports rendered by this template are published through the same Shares pipeline that hosts other shared artifacts, so [INDEX.md](INDEX.md), the library index, is the way to find the neighbouring sharing and reporting pages if you want to follow a finished report out to where a reader opens it.
