Skip to content

Commit a4469d8

Browse files
Hanns Peterclaude
andcommitted
Release scriveno 3.6.0: multi-book identity, slug naming, series store
- Add optional book identity (title/subtitle/author/slug/series/book_number) to config.json, written by /scr:new-work and /scr:import with a WORK.md fallback so existing projects keep working - Add docs/naming-conventions.md and lib/slug.js as the canonical naming contract; the slug helper re-exports the injection-safe algorithm previously scoped to /scr:track - Keep canonical export and cover filenames as defaults and add self-describing {slug}-... copies when a book identity exists, ending silent collisions across a series - Platform-encode /scr:build-ebook's EPUB output (ebook-{platform}.epub) to match /scr:build-print, so per-platform store builds no longer overwrite one another - Sanitize the series store to ~/.scriveno/series/{series_slug}/ with a legacy-path migration shim, a derived books.json index, and optional series-tier STYLE-GUIDE/ART-DIRECTION/GLOSSARY/covers - Propagate series-tier voice, art direction, and glossary into the drafter, /scr:cover-art --series, and the translator, each with project-local fallback - Make /scr:manager --switch honest about cwd-based resolution; add per-language and per-edition cover slots; add orphaned illustration/header-prompt hygiene to /scr:reorder-units - Bump 3.5.0 -> 3.6.0 across the release-alignment file set; add slug-helper and series-naming contract tests (2151 tests green, policy clean) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
1 parent ef539f8 commit a4469d8

27 files changed

Lines changed: 947 additions & 42 deletions

CHANGELOG.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,20 @@
22

33
All notable package-level changes to `scriveno` are documented here.
44

5+
## 3.6.0 - 2026-06-26
6+
7+
Multi-book identity, slug-based naming, and a first-class series store.
8+
9+
- Added `docs/naming-conventions.md` as the canonical contract for book identity, the slug algorithm, the series store, and the deliverable filename grammar `{slug}[-{lang}][-{platform}][-v{n}].{ext}`. Every export, cover, and series command now cites it instead of hardcoding its own scheme.
10+
- Added `lib/slug.js`: a dependency-free, generic slug helper (`sanitizeSlug`, `buildDeliverableName`, plus a CLI) that re-exports the injection-safe algorithm previously scoped to `/scr:track`. The series directory and book identity now derive from it, closing a path-traversal and collision hazard.
11+
- Added optional book identity to `config.json` (`title`, `subtitle`, `author`, `slug`, `series`, `book_number`), written by `/scr:new-work` and `/scr:import`, with a documented WORK.md fallback so existing projects keep working unchanged.
12+
- Export and cover commands now keep their canonical literal output as the default and additionally write a self-describing `{slug}-...` copy when a book identity exists, so a multi-book writer's deliverables no longer collide on shared upload folders.
13+
- `/scr:build-ebook` now platform-encodes its EPUB output (`ebook-{platform}.epub`) to match `/scr:build-print`'s `print-{platform}.pdf`, so per-platform store builds no longer overwrite one another.
14+
- `/scr:series-bible` now stores the series under a sanitized `~/.scriveno/series/{series_slug}/` path with a legacy-path migration shim, a derived `books.json` index (`slug`, `book_number`, `title`, `path`), and optional series-tier shared surfaces (`STYLE-GUIDE.md`, `ART-DIRECTION.md`, `GLOSSARY.md`, `covers/`).
15+
- Series-tier consistency now propagates with project-local fallback: the drafter loads the series voice baseline, `/scr:cover-art --series` reads the series art direction, and the translator reads the series glossary.
16+
- `/scr:manager --switch` is now honest about Scriveno operating on the current working directory: it prints the exact `cd` to run instead of implying a persistent switch it never had.
17+
- Added per-language and per-edition cover slots (`build/{lang}/...`, `build/editions/{edition}/...`) and orphaned illustration/header-prompt hygiene to `/scr:reorder-units`.
18+
519
## 3.5.0 - 2026-06-22
620

721
Per-unit cycle command and opt-in autosave.

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
[![CI](https://github.com/aihxp/scriveno/actions/workflows/ci.yml/badge.svg)](https://github.com/aihxp/scriveno/actions/workflows/ci.yml)
44
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
5-
[![Version](https://img.shields.io/badge/version-3.5.0-blue)](CHANGELOG.md)
5+
[![Version](https://img.shields.io/badge/version-3.6.0-blue)](CHANGELOG.md)
66
[![npm](https://img.shields.io/npm/v/scriveno.svg)](https://www.npmjs.com/package/scriveno)
77
[![Downloads](https://img.shields.io/npm/dm/scriveno.svg)](https://www.npmjs.com/package/scriveno)
88
[![Status CLI](https://img.shields.io/badge/status%20CLI-scriveno%20status-blue)](docs/runtime-support.md#shared-auto-invoke-engine)
@@ -265,11 +265,11 @@ Scriveno currently ships installer targets for these AI tooling environments:
265265

266266
## Status
267267

268-
**Version:** 3.5.0
268+
**Version:** 3.6.0
269269

270270
Scriveno's core command surface is stable across 125 commands, 50 work types, and 11 installer targets. The current repo baseline includes shipped planning milestones through `v2.0 Publishing Cover Packaging`, plus the creative-context, record-store, neutral research layer, world/place/geography layers, prepublish editorial review, branching-next, runtime-sync, adaptive concierge, human-first writing-safeguard, authenticity-diagnostic, domain-grilling, installer-marker cleanup, cross-runtime agent metadata, bounded subagent spawning protocol, model adaptation guide, visible automation status, the shared `npx scriveno@latest status --project .` auto-invoke engine, route-intelligence lanes, safe apply reporting, runtime smoke checks, agent availability checks, route graph audits, workflow-reference guards, the full audit repair pass through `2.0.11`, the first-run proof surface in `2.5.0`, the executable `/scr:first-run` path, command profiles, context-health checks, `/scr:proof-unit`, hub-first command families, and interactive install profile selection. See [Quick Proof](docs/quick-proof.md) for the fastest proof path, [Shipped Assets](docs/shipped-assets.md) for the canonical asset inventory, and [Runtime Support](docs/runtime-support.md) for the runtime compatibility matrix.
271271

272-
Version `3.5.0` publishes Scriveno under the package name `scriveno`, so the current install command is `npx scriveno@latest`. The older `scriveno-cli` package name is historical and was unpublished during the rename, so npm cannot attach a deprecation notice to it while it has no active registry record. The older `scriven-cli` package remains on npm only as a deprecated legacy name that points users to `scriveno`. Do not treat either legacy package name as active unless a deliberate compatibility shim is republished. See [CHANGELOG](CHANGELOG.md) for the full list and [docs/release-notes.md](docs/release-notes.md) for the public-facing summary.
272+
Version `3.6.0` publishes Scriveno under the package name `scriveno`, so the current install command is `npx scriveno@latest`. The older `scriveno-cli` package name is historical and was unpublished during the rename, so npm cannot attach a deprecation notice to it while it has no active registry record. The older `scriven-cli` package remains on npm only as a deprecated legacy name that points users to `scriveno`. Do not treat either legacy package name as active unless a deliberate compatibility shim is republished. See [CHANGELOG](CHANGELOG.md) for the full list and [docs/release-notes.md](docs/release-notes.md) for the public-facing summary.
273273

274274
Package history is tracked in [CHANGELOG.md](CHANGELOG.md), and the public-facing summary for this release is in [docs/release-notes.md](docs/release-notes.md).
275275

agents/drafter.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ You will always receive these files loaded into your context (load in this exact
1616

1717
1. **STYLE-GUIDE.md** -- The voice DNA. This is the single most important file. Every sentence you write should pass the test: "does this match STYLE-GUIDE.md?" If you're unsure, re-read STYLE-GUIDE.md.
1818

19+
**Series voice baseline (optional).** When this book belongs to a series (`.manuscript/config.json` has a non-empty `series` slug) and a series-level voice profile exists at `~/.scriveno/series/{series_slug}/STYLE-GUIDE.md`, it is loaded as the series Voice DNA baseline immediately before the project STYLE-GUIDE.md. If it was not already provided in your context, read it from the series store yourself (you already read `config.json` in the rigor step below, so resolve `series_slug` from `config.series`). The project STYLE-GUIDE.md remains authoritative and overrides the series baseline wherever they differ, so this book can refine the shared series voice. This is what keeps Book 5 sounding like Book 1. If no series voice profile exists, behavior is unchanged. See `docs/naming-conventions.md` section 3.
20+
1921
2. **WRITING-RULES.md** (optional). Universal AI-tell don'ts and show-don't-tell triggers. Loaded if present in the project's `.manuscript/` directory or the installed Scriveno templates. STYLE-GUIDE.md wins where they conflict; WRITING-RULES.md is the floor, not the ceiling. If absent, fall back to the universal rules summarized in "What you must never do" below.
2022

2123
3. **Pitfall pack** (optional). Type-specific pitfalls keyed off `.manuscript/config.json`'s `work_type`. Resolution order: `.manuscript/PITFALLS.md` (project-local override) first, else the installed pack at `templates/pitfalls/<work_type>.md` (global `~/.scriveno/templates/pitfalls/` or project `.scriveno/templates/pitfalls/`). If neither exists, skip silently. Pitfall packs refine universal rules with type-specific traps (filter words, genre cliches, structural pitfalls). They cannot relax WRITING-RULES.md or override STYLE-GUIDE.md.

agents/translator.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ You will always receive these files loaded into your context:
2020

2121
3. **GLOSSARY-{lang}.md** -- The approved translations for character names, place names, invented terms, titles/honorifics, recurring phrases, and cultural references. Every term in this glossary MUST be used exactly as specified. No improvisation on approved terms.
2222

23+
**Series glossary (optional).** When the work belongs to a series (`.manuscript/config.json` has a non-empty `series` slug) and a series-level glossary exists at `~/.scriveno/series/{series_slug}/GLOSSARY.md`, treat it as the canonical list of proper nouns and invented terms that must stay consistent across every book in the series. The per-language `GLOSSARY-{lang}.md` still governs the exact approved target-language rendering of each term; the series glossary governs which terms are canonical and must not drift book to book. If a term is in the series glossary but has no `GLOSSARY-{lang}.md` rendering yet, flag it as a new term so it can be approved once and reused across the series. If no series glossary exists, behavior is unchanged. See `docs/naming-conventions.md` section 3.
24+
2325
4. **Translation memory excerpt** -- Relevant segments from translation-memory.json that match content in this unit. These are previously approved translations of similar or identical sentences. Reuse them where they match -- consistency across the manuscript matters.
2426

2527
5. **CHARACTERS.md excerpt** (or FIGURES.md for sacred works) -- Only the characters/figures relevant to this unit. Includes their voice anchors, speech patterns, and current emotional state. Each character must sound distinct in the target language, just as they do in the source.

commands/scr/back-matter.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,8 @@ Load the following project files:
7878
- The adapted cast surface for canonical `CHARACTERS.md`, when applicable -- for glossary extraction (names, roles, concepts, terms)
7979
- Drafted prose from `.manuscript/drafts/` (especially `.manuscript/drafts/body/`) -- for content extraction (glossary terms, endnotes, themes)
8080

81+
**Resolve book identity (config first, WORK.md fallback).** When an element needs the book title, author, or series (the "About the Author" bio, the colophon, any "Also by" listing, and the glossary/index headers), prefer the identity keys in `.manuscript/config.json` (`title`, `author`, and the series linkage `series` slug + `book_number`), and fall back to `.manuscript/WORK.md` only when a config key is absent or empty, per the reader fallback contract in `docs/naming-conventions.md` sections 2-3 (config `title`, else the first H1 in WORK.md; config `author`, else the WORK.md author field, else leave blank and do not invent one).
82+
8183
**Confirm the `back-matter` command is available** for the current work type by checking `CONSTRAINTS.json`. If the work type's group is in the `hidden` list, inform the writer and stop.
8284

8385
Check for adapted behavior:

commands/scr/build-ebook.md

Lines changed: 39 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,17 @@ You are a **manuscript build specialist** for EPUB output.
3030

3131
Load the following project files:
3232

33-
- `.manuscript/config.json` -- to get `work_type`, title, author, language, and project settings
33+
- `.manuscript/config.json` -- to get `work_type`, title, author, language, `slug`, and project settings
3434
- Scriveno's installed/shared `CONSTRAINTS.json` (global `~/.scriveno/data/CONSTRAINTS.json` or project `.scriveno/data/CONSTRAINTS.json`) -- to check `exports` section for format availability by work type group
3535

36+
**Resolve book identity (fallback contract):** when you need `title`, `author`, or `language`, prefer the `.manuscript/config.json` key and fall back to today's source per `docs/naming-conventions.md` section 2:
37+
38+
- `title`: config `title`, else the first H1 in `.manuscript/WORK.md`.
39+
- `author`: config `author`, else the WORK.md author field, else leave blank and do not invent one.
40+
- `language`: config `translation.source_language`, else `en`.
41+
42+
Carry the resolved `slug` (config `slug` if present and non-empty) forward for the slugged-copy step in STEP 4.
43+
3644
Resolve shared asset directories before checking templates:
3745

3846
- `SHARED_DATA_DIR`: first existing directory from `.scriveno/data`, `$HOME/.scriveno/data`, then `data` when running from the Scriveno source repository
@@ -370,10 +378,10 @@ First, copy the OPF stub for reference:
370378
cp "$EXPORT_TEMPLATE_DIR/scriveno-fixed-layout.opf" .manuscript/output/fixed-layout.opf
371379
```
372380

373-
Invoke Pandoc with the fixed-layout stylesheet:
381+
Invoke Pandoc with the fixed-layout stylesheet. The `{platform}` token is the platform slug resolved in STEP 1.8 (one of `kdp`, `ingram`, `apple`, `bn`, `d2d`, `kobo`, `google`, `smashwords`). Platform-encoding the canonical output mirrors `/scr:build-print`'s `print-{platform}.pdf` so per-platform EPUBs no longer collide:
374382
```bash
375383
pandoc .manuscript/output/assembled-manuscript.md \
376-
-o .manuscript/output/ebook-fixed-layout.epub \
384+
-o .manuscript/output/ebook-fixed-layout-{platform}.epub \
377385
--metadata-file=.manuscript/output/metadata.yaml \
378386
--epub-cover-image=.manuscript/build/ebook-cover.jpg \
379387
--css="$EXPORT_TEMPLATE_DIR/scriveno-fixed-layout-epub.css" \
@@ -384,16 +392,22 @@ pandoc .manuscript/output/assembled-manuscript.md \
384392

385393
Note: `--split-level=0` keeps facing pages together as single spine items.
386394

395+
**Slugged copy (additive):** when `.manuscript/config.json` has a non-empty `slug`, also write a self-describing copy alongside the canonical file per `docs/naming-conventions.md` sections 4-5. The canonical `ebook-fixed-layout-{platform}.epub` remains the stable contract; the slugged copy is the collision-safe artifact a writer collects for upload:
396+
```bash
397+
cp .manuscript/output/ebook-fixed-layout-{platform}.epub .manuscript/output/{slug}-fixed-layout-{platform}.epub
398+
```
399+
If `slug` is absent or empty, skip this copy.
400+
387401
After build, show:
388402
> **Note:** Fixed-layout EPUB generated. Merge the OPF metadata from `.manuscript/output/fixed-layout.opf` into the EPUB's `package.opf` before submitting to Apple Books.
389403
390404
Then proceed to STEP 5 (skip the standard Pandoc invocation below).
391405

392-
**If `--fixed-layout` is NOT enabled:** use the standard Pandoc invocation:
406+
**If `--fixed-layout` is NOT enabled:** use the standard Pandoc invocation. The `{platform}` token is the platform slug resolved in STEP 1.8 (one of `kdp`, `ingram`, `apple`, `bn`, `d2d`, `kobo`, `google`, `smashwords`). Platform-encoding the canonical output mirrors `/scr:build-print`'s `print-{platform}.pdf` so per-platform EPUBs no longer collide:
393407

394408
```bash
395409
pandoc .manuscript/output/assembled-manuscript.md \
396-
-o .manuscript/output/ebook.epub \
410+
-o .manuscript/output/ebook-{platform}.epub \
397411
--metadata-file=.manuscript/output/metadata.yaml \
398412
--epub-cover-image=.manuscript/build/ebook-cover.jpg \
399413
--css="$EXPORT_TEMPLATE_DIR/scriveno-epub.css" \
@@ -402,6 +416,12 @@ pandoc .manuscript/output/assembled-manuscript.md \
402416
--split-level=1
403417
```
404418

419+
**Slugged copy (additive):** when `.manuscript/config.json` has a non-empty `slug`, also write a self-describing copy alongside the canonical file per `docs/naming-conventions.md` sections 4-5. The canonical `ebook-{platform}.epub` remains the stable contract; the slugged copy is the collision-safe artifact a writer collects for upload:
420+
```bash
421+
cp .manuscript/output/ebook-{platform}.epub .manuscript/output/{slug}-{platform}.epub
422+
```
423+
If `slug` is absent or empty, skip this copy.
424+
405425
If `.manuscript/build/ebook-cover.jpg` does not exist, check `.manuscript/build/ebook-cover.png`. If neither exists, omit the `--epub-cover-image` flag and note:
406426
> **Note:** No ebook cover found at `.manuscript/build/ebook-cover.jpg` or `.png`. EPUB will be generated without a cover. To add a cover, place your front-cover-only RGB file at `.manuscript/build/ebook-cover.jpg` (or `.png`) and re-run this build command.
407427
@@ -417,26 +437,36 @@ If `--fixed-layout` is active:
417437

418438
Show:
419439
```
420-
OK EPUB built -> .manuscript/output/ebook-fixed-layout.epub ({file_size})
440+
OK EPUB built -> .manuscript/output/ebook-fixed-layout-{platform}.epub ({file_size})
421441
Platform: {selected platform label}
422442
```
423443

444+
When a non-empty `slug` produced a slugged copy, add a line reporting it:
445+
```
446+
Slugged copy -> .manuscript/output/{slug}-fixed-layout-{platform}.epub
447+
```
448+
424449
Get file size with:
425450
```bash
426-
ls -lh .manuscript/output/ebook-fixed-layout.epub | awk '{print $5}'
451+
ls -lh .manuscript/output/ebook-fixed-layout-{platform}.epub | awk '{print $5}'
427452
```
428453

429454
Otherwise:
430455

431456
Show:
432457
```
433-
OK EPUB built -> .manuscript/output/ebook.epub ({file_size})
458+
OK EPUB built -> .manuscript/output/ebook-{platform}.epub ({file_size})
434459
Platform: {selected platform label}
435460
```
436461

462+
When a non-empty `slug` produced a slugged copy, add a line reporting it:
463+
```
464+
Slugged copy -> .manuscript/output/{slug}-{platform}.epub
465+
```
466+
437467
Get file size with:
438468
```bash
439-
ls -lh .manuscript/output/ebook.epub | awk '{print $5}'
469+
ls -lh .manuscript/output/ebook-{platform}.epub | awk '{print $5}'
440470
```
441471

442472
## Response Contract

0 commit comments

Comments
 (0)