# Autonovel Export

> Autonovel Phase 4 — typeset and export the completed novel as PDF (via LaTeX), ePub (stdlib), and audiobook transcript chunks ready for an optional external TTS pipeline. Reads chapters/ch_*.md plus outline.md for the table of contents. Writes export/novel.pdf, export/novel.epub, export/audiobook/. Final phase — sets state.json phase to 'done'.

- **Type:** Skill
- **Install:** `agentstack add skill-duketwocan-autonovel-agent-skills-autonovel-export`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [DukeTwoCan](https://agentstack.voostack.com/s/duketwocan)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [DukeTwoCan](https://github.com/DukeTwoCan)
- **Source:** https://github.com/DukeTwoCan/autonovel-agent-skills/tree/main/skills/creative/autonovel-export

## Install

```sh
agentstack add skill-duketwocan-autonovel-agent-skills-autonovel-export
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Autonovel — Phase 4 (Export)

Typeset the completed novel and produce final deliverables.

## When to use this skill

- State.json shows `"phase": "export"` (set by consistency-pass when cycles exhausted)
- User says "export the novel" / "build the PDF" / "make the ePub"

## Prerequisites

```
!`cd "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG" && ls chapters/*.md | wc -l && cat state.json | python -c "import json,sys; s=json.load(sys.stdin); print(s.get('phase'), s.get('chapters_drafted'))"`
```

Need: all chapters drafted, state.json phase is "export" (or user explicitly overriding).

For PDF: use a local `xelatex`/`pdflatex` installation or the repository's
optional container toolchain. Check for a local engine:
```
!`which pdflatex || which xelatex || echo "no LaTeX engine found"`
```

If neither is found, look for `compose.tools.yaml` at the repository root and
use the container command in Step 3. If neither native LaTeX nor Docker is
available, skip PDF with a warning; ePub and transcript chunks still work.

## Workflow

### Step 0 — Unpaid foreshadow check

If `story_state/facts.json` does not exist, skip this step silently — the
novel predates the story-state ledger (Module A) and has no foreshadow
tracking. Otherwise run:
```
!`python3 ${HERMES_SKILL_DIR}/lib/story_state.py unpaid "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG/story_state/facts.json"`
```
If any items print, list them to the user with their setup chapters before
proceeding. Export continues regardless (a dangling thread may be
intentional / sequel-bait) — this is a warning, not a gate.

### Step 1 — Confirm title and author

Read `state.json` for novel_slug. Ask the user for the title (display title, may differ from slug) and author byline.

### Step 2 — Content-notes front matter (if applicable)

Read `profile` from `state.json` and read the normalized selected packs from
`genre_context/resolved.json`'s `selected_pack_ids`. Let Intimacy be selected
only when `"intimacy"` is in that list; do not re-resolve pack selection from
display tags. A non-empty `profile.content_tags` still implies Intimacy because
the resolver records `"intimacy"` in `selected_pack_ids` for that profile. If
`profile.rating` is `M` or `E`, or Intimacy is selected, build a content-notes
line:

`Rating: . Tags: . Content: .`

`` remains the original `profile.tags` display list with only the
`-tag` exclusion entries dropped. Do not replace it with normalized tags, pack
IDs, or only pack-resolving tags; unknown positive display tags remain visible.
This is exactly the export-labeling rule from
`${HERMES_SKILL_DIR}/../autonovel/genres/special/intimacy/guardrails.md`.
`` is `profile.content_tags` joined verbatim; include the
`Content: .` part ONLY when `profile.content_tags` is non-empty,
and drop that part entirely (line ends at `Tags: .`) when it is
empty. The line lands in each format through a concrete hook:

- **PDF** — the tex template has a `` placeholder on the
  copyright/colophon page. Fill it with the line in Step 3, exactly as you
  fill `` and ``.
- **ePub** — pass the Step 2 line to build_epub.py via its optional
  `--content-notes "Rating: . Tags: . Content: ."`
  flag in Step 4 (drop the `Content:` part when `content_tags` is empty). It
  becomes a front-matter page before chapter 1 plus `dc:description` metadata.
  Omit the flag when notes don't apply.
- **Audiobook** — write the line to
  `$AUTONOVEL_WORKSPACE/$NOVEL_SLUG/export/audiobook/000_content_notes.txt`
  (the `000` prefix sorts it first, so any TTS pipeline reads it as a
  preamble). Skip the file when notes don't apply.

When the rating is G or T and no intimacy pack is loaded, skip the ePub
flag and the audiobook file — but still fill the tex ``
placeholder in Step 3, with an empty string (an empty placeholder renders
nothing; a literal `` left unfilled would leak into the
PDF).

### Step 3 — Build the PDF (if LaTeX available)

Copy the template:
```
!`cp ${HERMES_SKILL_DIR}/templates/novel.tex.template "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG/export/novel.tex"`
```

Fill ``, ``, and `` placeholders
(`` gets the Step 2 line, or an empty string when content
notes don't apply).

Run the builder:
```
!`python3 ${HERMES_SKILL_DIR}/lib/build_tex.py --workspace "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG" --out "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG/export/novel.pdf"`
```

If it errors, read `references/typesetting-checklist.md` for common LaTeX issues (missing packages, Unicode in chapter text, etc.).

For the repository's containerized XeLaTeX path, set `AUTONOVEL_PROJECT` to
the absolute per-novel workspace path, then run from the repository root:

```
docker compose -f compose.tools.yaml build latex
docker compose -f compose.tools.yaml run --rm latex --workspace /novel --out /novel/export/novel.pdf
```

The project mount is writable so the PDF and intermediate TeX files land in
the novel's own `export/` directory. The repository mount is read-only.

### Step 4 — Build the ePub

```
!`python3 ${HERMES_SKILL_DIR}/lib/build_epub.py --workspace "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG" --out "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG/export/novel.epub" --title "" --author ""`
```

If Step 2 produced a content-notes line, append
`--content-notes "Rating: . Tags: . Content: ."`
to the command above (drop the `Content:` part when `profile.content_tags` is
empty — it matches the Step 2 line exactly).

### Step 5 — Audiobook chunks

For each chapter:
```
!`python3 ${HERMES_SKILL_DIR}/lib/chunk_audio.py --chapter "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG/chapters/ch_NN.md" --out-dir "$AUTONOVEL_WORKSPACE/$NOVEL_SLUG/export/audiobook/ch_NN"`
```

Chunks land as `.txt` files. If the user has a local TTS pipeline:
- They can shell out: `for chunk in chapters/ch_NN_chunk_*.txt; do my_tts  ${chunk%.txt}.mp3; done`
- The skill doesn't run TTS itself; chunking is the deliverable.

The optional `f5-tts` Compose profile uses the official
`ghcr.io/swivid/f5-tts:main` image. This integration is experimental and is
not part of the export acceptance gate. It requires an NVIDIA-compatible
Docker runtime plus a user-supplied reference recording and exact transcript;
AutoNovel bundles no voice. Set `AUTONOVEL_PROJECT` and
`F5_TTS_REFERENCE_DIR`, then invoke one chunk explicitly:

```
docker compose -f compose.tools.yaml --profile tts run --rm f5-tts \
  --model F5TTS_v1_Base \
  --ref_audio /reference/voice.wav \
  --ref_text "Exact transcript of the reference recording." \
  --gen_file /novel/export/audiobook/ch_01/ch_01_chunk_001.txt \
  --output_dir /novel/export/audiobook/rendered
```

Review generated audio before processing a full manuscript.

### Step 6 — Final state update

Set `state.json` `phase` to `"done"`. Commit. Report final stats: word count, chapter count, score history, file paths to PDF/ePub/audio chunks.

## Handoff

Pipeline complete. Suggest `autonovel-prose-review` if the user wants further polish on any specific chapters.

## See also

- `references/typesetting-checklist.md` — common LaTeX issues and fixes
- `templates/novel.tex.template` — the LaTeX template (edit to customize layout)

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [DukeTwoCan](https://github.com/DukeTwoCan)
- **Source:** [DukeTwoCan/autonovel-agent-skills](https://github.com/DukeTwoCan/autonovel-agent-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-duketwocan-autonovel-agent-skills-autonovel-export
- Seller: https://agentstack.voostack.com/s/duketwocan
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
