# Output contract

> Badge line, LAWs voice contract, --emit modes (compact, json, context, md, html), evidence blocks, and footer pass-through rules.

- Repository: mvanhorn/last30days-skill
- GitHub: https://github.com/mvanhorn/last30days-skill
- Human docs: https://grok-wiki.com/public/docs/mvanhorn-last30days-skill-50b5421a8cca
- Complete Markdown: https://grok-wiki.com/public/docs/mvanhorn-last30days-skill-50b5421a8cca/llms-full.txt

## Source Files

- `skills/last30days/SKILL.md`
- `skills/last30days/scripts/lib/render.py`
- `skills/last30days/scripts/lib/html_render.py`
- `skills/last30days/scripts/last30days.py`
- `skills/last30days/scripts/lib/skill_meta.py`

---

---
title: "Output contract"
description: "Badge line, LAWs voice contract, --emit modes (compact, json, context, md, html), evidence blocks, and footer pass-through rules."
---

The last30days output contract spans three layers: Python rendering in `skills/last30days/scripts/lib/render.py` and `html_render.py`, the `--emit` router in `last30days.py`, and the hosting model’s synthesis rules in `SKILL.md` (badge, eight LAWs, evidence envelope, footer pass-through, invitation). Slash-command runs should use `--emit=compact` on stdout; saved artifacts and wire formats diverge by emit mode.

## Contract layers

```text
┌─────────────────────────────────────────────────────────────────┐
│ SKILL.md OUTPUT CONTRACT (LAWs 1–8, badge, synthesis shape)     │
│  → governs what the hosting model emits to the user             │
└────────────────────────────┬────────────────────────────────────┘
                             │ reads stdout / saves files
┌────────────────────────────▼────────────────────────────────────┐
│ last30days.py: emit_output() / emit_comparison_output()         │
│  --emit compact|md|json|context|html                            │
└────────────────────────────┬────────────────────────────────────┘
                             │
        ┌────────────────────┼────────────────────┐
        ▼                    ▼                    ▼
  render_compact      render_context      html_render.render_html
  (model scratchpad)  (abbreviated)       (shareable artifact)
```

| Layer | Owner | Primary consumer |
| --- | --- | --- |
| Badge + evidence + footer envelopes | `render.py` | Hosting model (compact/md stdout) |
| LAWs + invitation | `SKILL.md` | Hosting model (final chat response) |
| `--emit` routing | `last30days.py` | CLI, cron, skill Bash step |
| Saved `*-raw.md` | `render_full()` via `save_output()` | Durable debug / WebSearch appendix target |

## Badge line

The engine emits the mandatory first line in every compact, md, and HTML-prep path via `_render_badge()`:

```text
🌐 last30days v{VERSION} · synced {YYYY-MM-DD}

```

<ParamField body="VERSION" type="string">
Resolved from the nearest ancestor `.claude-plugin/plugin.json` `version` field; if missing (typical on per-harness skill installs), falls back to `SKILL.md` frontmatter via `skill_meta.read_skill_version()`. Returns `?` only when neither source yields a version.
</ParamField>

<ParamField body="synced date" type="string">
`date.today()` at render time (`YYYY-MM-DD`), not the research date range.
</ParamField>

<Note>
`SKILL.md` requires the hosting model to pass through the engine badge verbatim on line 1. Manual badge emission is a fallback when synthesizing without reusing engine stdout.
</Note>

**Placement by query type** (from `SKILL.md`):

| Query types | Line 1 | Line 3 (after blank line 2) |
| --- | --- | --- |
| GENERAL, NEWS, PROMPTING, RECOMMENDATIONS | Badge | `What I learned:` (prose label, not a title) |
| COMPARISON (`vs` / `versus`) | Badge | `# {A} vs {B} [vs {C}]: What the Community Says (/Last30Days)` |

## Voice contract (LAWs)

The eight LAWs in `SKILL.md` § OUTPUT CONTRACT override global formatting preferences inside `/last30days`. They apply at synthesis time; the engine enforces structure via HTML comments and warning blocks.

| LAW | Rule | Engine support |
| --- | --- | --- |
| **1** | No trailing `Sources:` / `References:` / link dumps; visible citation is the `🌐 Web:` footer line | Canonical boundary text; saved raw file holds WebSearch appendix |
| **2** | No invented title; body starts with `What I learned:` (COMPARISON uses required `# … vs …` title) | Badge as structural anchor |
| **3** | No em-dashes or en-dashes; use ` - ` | — |
| **4** | No `##` body headers except COMPARISON template sections and Python-pass-through blocks | Comparison scaffold emits allowed `## Head-to-Head` |
| **5** | Pass through emoji-tree footer verbatim | `<!-- PASS-THROUGH FOOTER -->` envelope |
| **6** | Do not emit raw ranked evidence clusters in user output | `<!-- EVIDENCE FOR SYNTHESIS -->` envelope |
| **7** | Reasoning-model hosts must pass `--plan` on named-entity topics | `## DEGRADED RUN WARNING` when `plan_source=deterministic` and flags missing |
| **8** | Inline `[name](url)` citations in narrative; footer links untouched | Evidence items carry URLs in compact output |

<LAW 6 failure signal>: User output containing `### 1.` followed by `(score N, M items, sources: …)` or `- Uncertainty: single-source` means evidence was dumped instead of synthesized.

## `--emit` modes

Default: `compact`. Choices are registered in `last30days.py` and routed through `emit_output()` / `emit_comparison_output()`.

| Mode | Stdout renderer | Typical use | Saved file when `--save-dir` set |
| --- | --- | --- | --- |
| `compact` | `render_compact()` | Primary skill path; model reads evidence + footer | `render_full()` → `{slug}-raw{suffix}.md` |
| `md` | `render_compact()` (identical to compact) | Debug/inspection only; **disallowed** as primary user-facing flow per `SKILL.md` | Same as compact: `render_full()` |
| `json` | `json.dumps(schema.to_dict(report))` | Scripting, watchlist, verify | `{slug}-raw{suffix}.json` (wire JSON) |
| `context` | `render_context()` or `render_comparison_multi_context()` | Token-efficient agent context | `render_full()` if saved as `.md` |
| `html` | `html_render.render_html()` | Shareable offline brief | `{slug}-raw-html{suffix}.html`; accepts `--synthesis-file` |

<Warning>
`--emit=md` and `--emit=compact` produce the same stdout (including evidence and footer envelopes). Do not treat `md` as a different user-facing format. The distinction matters for saved files: non-JSON/HTML saves always use `render_full()`, not compact stdout.
</Warning>

### `compact` / `md` stdout structure

`render_compact()` emits blocks in this order:

1. Badge + blank line
2. Debug header `# last30days vX: {topic}`
3. Model-facing safety blockquote (untrusted internet content)
4. Date range and active source list
5. Optional `## Freshness`, `## Warnings`
6. Optional `## DEGRADED RUN WARNING` (before evidence; LAW 7 backstop)
7. **Evidence envelope** (see below)
8. Optional `## Pre-Research Status` (after evidence closes)
9. Optional `## Head-to-Head` table scaffold (comparison topics)
10. **Pass-through footer** envelope
11. **Canonical boundary** (`# END OF last30days CANONICAL OUTPUT`)

`fun_level` (`low` / `medium` / `high`, from `FUN_LEVEL` env) adjusts Best Takes threshold and count inside the evidence envelope. Default cluster cap is 8 (4 per entity in comparison multi-render).

### `json`

Single-entity: full `Report` as dict via `schema.to_dict()`. Comparison: wrapper `{"comparison": true, "entities": [...], "reports": [{"entity", "report"}, ...]}`.

### `context`

Abbreviated cluster titles, representative items, safety note, optional freshness warning. No badge, evidence envelope, or emoji footer. Comparison context adds entity sections and resolved-entity summary when artifacts exist.

### `html`

Pipeline: `render_for_html()` → strip evidence / invitation / canonical boundary → promote prose labels → markdown-to-HTML → wrap engine footer → embed in styled template.

<Info>
HTML artifacts omit the evidence scratchpad, debug header, safety note, and invitation. Data-quality warnings go to **stderr** via `collect_html_warnings()`, not into the shareable file. Pass `--synthesis-file` with model-authored markdown (post-chat synthesis) for a populated brief body.
</Info>

## Evidence blocks

Raw research for the hosting model lives inside HTML comment boundaries:

```text
<!-- EVIDENCE FOR SYNTHESIS: read this, do not emit verbatim. ... -->
## Ranked Evidence Clusters
  ### N. {title} (score X, M items, sources: ...)
  ...
## Stats
## Best Takes          (fun_level-gated)
## Source Coverage
<!-- END EVIDENCE FOR SYNTHESIS -->
```

<Check>
LAW 6 scope: synthesize from this block into `What I learned:` prose (or COMPARISON template sections). Do **not** pass the envelope through to the user. Only the PASS-THROUGH FOOTER is verbatim in the final response (plus Python-emitted warning/scaffold blocks when present).
</Check>

Comparison multi-entity runs use one envelope with per-entity `## {label}` subsections, `#### Ranked Evidence Clusters`, and a shared `## Head-to-Head` scaffold after the envelope closes.

## Footer pass-through

The emoji-tree footer is wrapped for model copy-paste:

```text
<!-- PASS-THROUGH FOOTER: emit verbatim in the model response per LAW 5. -->
---
✅ All agents reported back!
├─ 🟠 Reddit: … │ …
├─ 🔵 X: … │ …
└─ 📎 Raw results saved to ~/…/slug-raw.md   (when --save-dir set)
---
<!-- END PASS-THROUGH FOOTER -->
```

Per-source lines are built from `_FOOTER_SOURCES` (Reddit, X, YouTube, TikTok, Instagram, Threads, Pinterest, HN, Bluesky, Truth Social, GitHub, Digg), plus Polymarket odds summaries and `🌐 Web:` publication names. Optional `🗣️ Top voices:` aggregates handles and subreddits.

<ParamField body="save_path" type="string | null">
Passed into `render_compact()` when `--save-dir` is set; `compute_save_path_display()` shows a `~/{relative}` path in the `📎 Raw results saved to` line.
</ParamField>

The canonical boundary after the footer explicitly scopes verbatim pass-through to the footer only and repeats LAW 1 / LAW 6 self-check strings.

## Final user-facing response shape

The engine does **not** emit the invitation block. The hosting model composes the chat response on top of compact stdout:

```text
[Badge — pass through line 1 from engine]

What I learned:                    ← model synthesis (LAW 2/4/8)
**Lead-in** - paragraph …
KEY PATTERNS from the research:    ← numbered list
1. …

[PASS-THROUGH FOOTER — verbatim]   ← LAW 5

---
I'm now an expert on {TOPIC}…       ← model invitation (SKILL.md templates)
```

| Block | Source | Pass through? |
| --- | --- | --- |
| Badge | Engine | Yes (line 1) |
| Evidence envelope | Engine | No (read only) |
| Head-to-Head scaffold | Engine (comparison) | Yes, fill cells |
| Emoji-tree footer | Engine | Yes (verbatim) |
| Invitation | Model | N/A (not in engine stdout) |
| Trailing `Sources:` | Model must omit | LAW 1 |

## Comparison and JSON/HTML notes

- **Comparison stdout**: `render_comparison_multi()` shares badge, one evidence envelope, Head-to-Head scaffold, single footer from the main report, and the same canonical boundary.
- **HTML footer**: `_wrap_engine_footer()` preserves the tree through markdown conversion; other HTML comments are stripped except `<!-- META: … -->` (date range and sources).
- **Zero-source runs**: If `_render_emoji_footer()` returns empty, `SKILL.md` allows skipping the footer and proceeding from KEY PATTERNS to the invitation.

## Verification signals

| Check | Command / test |
| --- | --- |
| Envelope order | `tests/test_render_v3.py` (`OutputEnvelopeTests`) |
| compact ≡ md stdout | `test_envelopes_appear_in_md_emit_mode` |
| HTML strips evidence | `tests/test_html_render.py` |
| Emit choices | `last30days.py` `--emit` argparse `choices=[...]` |

<Steps>
<Step title="Run compact research">
<code>python3 skills/last30days/scripts/last30days.py "topic" --emit=compact --save-dir="${LAST30DAYS_MEMORY_DIR:-$HOME/Documents/Last30Days}"</code>
</Step>
<Step title="Confirm stdout markers">
Stdout should start with the badge, contain exactly one `<!-- EVIDENCE FOR SYNTHESIS` / `<!-- END EVIDENCE FOR SYNTHESIS -->` pair, and one `<!-- PASS-THROUGH FOOTER` / `<!-- END PASS-THROUGH FOOTER -->` pair when sources returned data.
</Step>
<Step title="Synthesize per LAWs">
Transform evidence into `What I learned:` prose; copy the footer verbatim; end at the invitation with no trailing `Sources:` block.
</Step>
</Steps>

## Related pages

<CardGroup>
<Card title="Skill contract" href="/skill-contract">
SKILL.md runtime authority, engine invocation, and STEP 0 guards that precede output emission.
</Card>
<Card title="CLI reference" href="/cli-reference">
Full `--emit` flag listing, `--synthesis-file`, and direct CLI vs slash-command constraints.
</Card>
<Card title="HTML briefs" href="/html-briefs">
Shareable `--emit=html` artifacts, synthesis embedding, and save paths.
</Card>
<Card title="Comparison mode" href="/comparison-mode">
Multi-entity evidence layout, Head-to-Head scaffold, and comparison synthesis template.
</Card>
<Card title="Query types" href="/query-types">
QUERY_TYPE-specific placement rules for badge, titles, and invitation variants.
</Card>
</CardGroup>
