scriveno 2.5.0 → 2.7.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -4
- package/agents/voice-checker.md +10 -0
- package/commands/scr/autopilot-publish.md +1 -1
- package/commands/scr/autopilot-translate.md +5 -6
- package/commands/scr/autopilot.md +10 -6
- package/commands/scr/beta-reader.md +6 -3
- package/commands/scr/build-ebook.md +1 -1
- package/commands/scr/build-print.md +2 -2
- package/commands/scr/continuity-check.md +1 -0
- package/commands/scr/copy-edit.md +1 -0
- package/commands/scr/dialogue-audit.md +1 -0
- package/commands/scr/discussion-questions.md +1 -0
- package/commands/scr/draft.md +5 -4
- package/commands/scr/editor-review.md +1 -0
- package/commands/scr/export.md +1 -1
- package/commands/scr/help.md +1 -1
- package/commands/scr/line-edit.md +1 -0
- package/commands/scr/manuscript-stats.md +7 -7
- package/commands/scr/map-manuscript.md +1 -0
- package/commands/scr/multi-publish.md +3 -2
- package/commands/scr/new-character.md +1 -0
- package/commands/scr/new-work.md +1 -1
- package/commands/scr/next.md +1 -0
- package/commands/scr/originality-check.md +1 -0
- package/commands/scr/outline.md +2 -2
- package/commands/scr/pacing-analysis.md +1 -0
- package/commands/scr/pause-work.md +1 -1
- package/commands/scr/polish.md +1 -0
- package/commands/scr/progress.md +15 -10
- package/commands/scr/quick-write.md +4 -1
- package/commands/scr/resume-work.md +1 -1
- package/commands/scr/save.md +7 -4
- package/commands/scr/scan.md +17 -3
- package/commands/scr/sensitivity-review.md +1 -0
- package/commands/scr/submit.md +2 -1
- package/commands/scr/synopsis.md +1 -0
- package/commands/scr/theme-tracker.md +1 -0
- package/commands/scr/timeline.md +1 -0
- package/commands/scr/track.md +2 -0
- package/commands/scr/translate.md +1 -1
- package/commands/scr/voice-check.md +1 -0
- package/data/CONSTRAINTS.json +6 -1
- package/data/export-templates/scriveno-book.typst +2 -2
- package/data/export-templates/scriveno-chapbook.typst +1 -1
- package/data/export-templates/scriveno-picturebook.typst +9 -0
- package/data/export-templates/scriveno-stageplay.typst +14 -4
- package/docs/architecture.md +6 -3
- package/docs/auto-invoke-policy.md +4 -3
- package/docs/command-reference.md +29 -24
- package/docs/configuration.md +28 -3
- package/docs/context-protocol.md +2 -1
- package/docs/contributing.md +2 -2
- package/docs/creative-context.md +1 -1
- package/docs/drafter-quality.md +1 -1
- package/docs/history-protocol.md +1 -1
- package/docs/progress-protocol.md +132 -0
- package/docs/release-notes.md +54 -0
- package/docs/route-graph.md +1 -1
- package/docs/shipped-assets.md +4 -2
- package/docs/translation.md +7 -11
- package/docs/voice-dna.md +3 -3
- package/lib/auto-invoke-engine.js +95 -0
- package/lib/track-safety.js +72 -0
- package/package.json +1 -1
- package/templates/PROGRESS.md +56 -0
- package/templates/config.json +1 -1
package/docs/drafter-quality.md
CHANGED
|
@@ -104,7 +104,7 @@ Rough guidance for matching settings to model class. The writer's experience wit
|
|
|
104
104
|
| Mid-tier (Sonnet 4.x, GPT-4 mini, Haiku 4.x) | Day-to-day drafting, most novels and screenplays | `standard` | `standard` |
|
|
105
105
|
| Budget (Haiku, GPT-3.5, local 7-13B) | Bulk drafting of short scenes, repetitive structural work | `strict` | `minimal` |
|
|
106
106
|
|
|
107
|
-
If voice fidelity drops below the writer's `voice.drift_threshold
|
|
107
|
+
If voice fidelity drops below the writer's `voice.drift_threshold` (a voice-checker score below 70 at the default 0.3, where drift is `(100 - score) / 100`), the first lever is `rigor: strict`. The second is to step up a model tier. The third is to recalibrate STYLE-GUIDE.md via `/scr:voice-test`.
|
|
108
108
|
|
|
109
109
|
## Token economy
|
|
110
110
|
|
package/docs/history-protocol.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# HISTORY.log Protocol
|
|
2
2
|
|
|
3
|
-
`.manuscript/HISTORY.log` is the project's append-only chronological record of Scriveno commands that mutate state. It is
|
|
3
|
+
`.manuscript/HISTORY.log` is the project's append-only chronological record of Scriveno commands that mutate state. It is part of the context-integrity layer alongside `STATE.md` (structured snapshot), `RECORD.md` (established content), `.manuscript/CONTEXT.md` (one-page bootstrap), and `.manuscript/PROGRESS.md` (per-unit progress ledger). Where STATE.md records *what is true now* and CONTEXT.md narrates *where you are*, HISTORY.log records *how you got here, in order*.
|
|
4
4
|
|
|
5
5
|
This document is the single source of truth for the line format. Every command that appends to HISTORY.log must follow this contract.
|
|
6
6
|
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# Progress ledger protocol
|
|
2
|
+
|
|
3
|
+
This is the canonical contract for `.manuscript/PROGRESS.md`, Scriveno's openable per-unit progress ledger, and for how every command derives and renders unit status. The goal is one consistent answer to the question a writer asks most often: *what is done, what is in progress, what is untouched, and where are we in the journey?*
|
|
4
|
+
|
|
5
|
+
It is part of the trust layer, alongside the other derived and recorded surfaces:
|
|
6
|
+
|
|
7
|
+
- `STATE.md` -- structured workflow snapshot (aggregate counters, current position)
|
|
8
|
+
- `RECORD.md` -- compact established-content store
|
|
9
|
+
- `.manuscript/CONTEXT.md` -- one-page narrative bootstrap (synthesis, read first by a fresh session)
|
|
10
|
+
- `.manuscript/PROGRESS.md` -- per-unit progress ledger (the file you open to see every unit's status)
|
|
11
|
+
- `.manuscript/HISTORY.log` -- append-only audit trail
|
|
12
|
+
|
|
13
|
+
`STATE.md` answers "how many units are drafted." `PROGRESS.md` answers "which ones, and what state is each in." They never disagree because both are reconciled against disk, and `/scr:scan` is the trust check.
|
|
14
|
+
|
|
15
|
+
## What PROGRESS.md is for
|
|
16
|
+
|
|
17
|
+
`STATE.md` holds aggregate counts (`Units drafted: 4 of 5`). That tells the writer how far along they are but not *which* unit is where. `PROGRESS.md` is the deliverable-level view: a single human-readable file the writer can open to see every unit with its status (done / in progress / untouched), the macro pipeline position, recent activity, and the next step. It is the writing-domain analog of a requirements checklist.
|
|
18
|
+
|
|
19
|
+
The template lives at `templates/PROGRESS.md`. The file is **derived**: never hand-edited, always rebuilt from disk. Like `CONTEXT.md`, it is not created at `/scr:new-work`; it is generated the first time a unit-status-changing command or a save/pause/resume runs.
|
|
20
|
+
|
|
21
|
+
## The three status buckets
|
|
22
|
+
|
|
23
|
+
Every unit resolves to exactly one headline status. Derive it from disk first, then reconcile with `STATE.md`:
|
|
24
|
+
|
|
25
|
+
| Bucket | Marker | Disk condition |
|
|
26
|
+
|--------|--------|----------------|
|
|
27
|
+
| **Untouched** | `[ ]` | No plan file and no draft file for the unit. Not yet worked. |
|
|
28
|
+
| **In progress** | `[~]` | Started but not finished: a plan exists without a draft, a draft exists without a clean review, a review has open editor notes, or revisions are pending. |
|
|
29
|
+
| **Done** | `[x]` | The unit needs no more work this pass: it is submitted, or (for flows that stop at review) reviewed with no open notes. |
|
|
30
|
+
|
|
31
|
+
The headline bucket sits next to a finer **stage** so the writer sees both the rollup and the precise position.
|
|
32
|
+
|
|
33
|
+
## Per-unit stage derivation (disk-first)
|
|
34
|
+
|
|
35
|
+
Match each outline unit to its files by unit number. Use the same evidence `/scr:scan` uses (see `commands/scr/scan.md`, checks 1-3):
|
|
36
|
+
|
|
37
|
+
- **untouched** -- no `.manuscript/plans/{N}-*-PLAN.md` (or legacy `.manuscript/{N}-*-PLAN.md`) and no `.manuscript/drafts/body/{N}-*-DRAFT.md`
|
|
38
|
+
- **discussed** -- a `{N}-CONTEXT.md` exists but no plan or draft yet
|
|
39
|
+
- **planned** -- a plan file exists, no draft file
|
|
40
|
+
- **drafted** -- a draft file exists, no review report
|
|
41
|
+
- **reviewed** -- a `.manuscript/reviews/{N}-REVIEW.md` (or legacy `{N}-EDITOR-NOTES.md`) exists; treat as *reviewed with open notes* (in progress) when the review or `STATE.md` lists unresolved items, otherwise *reviewed clean*
|
|
42
|
+
- **submitted** -- `STATE.md` marks the unit submitted
|
|
43
|
+
|
|
44
|
+
Map stages to buckets: `untouched` -> untouched; `discussed`, `planned`, `drafted`, `reviewed-with-open-notes`, `revisions-pending` -> in progress; `reviewed-clean` (when the flow stops at review) and `submitted` -> done.
|
|
45
|
+
|
|
46
|
+
Word count per unit comes from the unit's draft file(s); show `--` for units with no draft.
|
|
47
|
+
|
|
48
|
+
## Pipeline position
|
|
49
|
+
|
|
50
|
+
The macro writing lifecycle is the default map (same chain `/scr:next` walks):
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
seed > voice > outline > discuss > plan > draft > review > revise > publish > translate
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Compute the current stage as the first incomplete step across the whole project, render it as `Stage {index} of {total}: {Name}`, and show the track with the current stage bracketed, for example:
|
|
57
|
+
|
|
58
|
+
```
|
|
59
|
+
seed > voice > outline > discuss > plan > [draft] > review > revise > publish > translate
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Translate is only relevant when the project has target languages configured; keep it in the track for orientation but never treat its absence as incomplete for a single-language project.
|
|
63
|
+
|
|
64
|
+
## The deliverable progress bar
|
|
65
|
+
|
|
66
|
+
Render a 10-cell bar over the done fraction using block characters (`U+2588` filled, `U+2591` empty), followed by counts and percent:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
████████░░ 4/5 scenes done (80%)
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
The denominator is the total unit count from `OUTLINE.md`. Percent is `round(done / total * 100)`. Use the work type's plural unit label (scenes, chapters, surahs, procedures, poems, and so on) from `CONSTRAINTS.json`; never hard-code "chapter."
|
|
73
|
+
|
|
74
|
+
## Ledger table shape
|
|
75
|
+
|
|
76
|
+
Group rows by the work type's mid level (act, part, sequence) when the outline has one, with a per-group rollup in the heading. Within a group, one row per atomic unit:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
### Act I -- Disruption (2/2 done)
|
|
80
|
+
|
|
81
|
+
| # | Title | Stage | Status | Words |
|
|
82
|
+
|---|-------|-------|--------|-------|
|
|
83
|
+
| 1 | The Letter | submitted | [x] | 1,020 |
|
|
84
|
+
| 2 | The Workshop | reviewed | [x] | 1,010 |
|
|
85
|
+
|
|
86
|
+
### Act II -- Decision (0/1 done, 1 in progress)
|
|
87
|
+
|
|
88
|
+
| # | Title | Stage | Status | Words |
|
|
89
|
+
|---|-------|-------|--------|-------|
|
|
90
|
+
| 3 | The Pier | drafted | [~] | 890 |
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
For work types without a mid level (short story, poetry collection), use a single flat table.
|
|
94
|
+
|
|
95
|
+
## Who regenerates PROGRESS.md
|
|
96
|
+
|
|
97
|
+
The ledger is a Level 2 safe local helper (see `docs/auto-invoke-policy.md`). It is rebuilt by the commands that change unit status or refresh derived state, never by a read-only command:
|
|
98
|
+
|
|
99
|
+
- `/scr:draft` -- after a unit is drafted and STATE.md is updated
|
|
100
|
+
- `/scr:editor-review` -- after a unit is marked reviewed
|
|
101
|
+
- `/scr:submit` -- after a unit is marked submitted
|
|
102
|
+
- `/scr:autopilot` -- after every unit, as part of the mandatory state update (so the file advances visibly during a run)
|
|
103
|
+
- `/scr:save`, `/scr:pause-work`, `/scr:resume-work` -- alongside `CONTEXT.md` regeneration, from the shared field set in `/scr:save` step 7
|
|
104
|
+
- `/scr:scan --fix` -- when the ledger is missing or stale
|
|
105
|
+
|
|
106
|
+
`/scr:progress` is read-only: it renders this picture live from disk and points the writer at `PROGRESS.md`, but it does not write the file. When the live view is ahead of the saved file (units changed since the last refresh), `/scr:progress` says so and suggests `/scr:save`.
|
|
107
|
+
|
|
108
|
+
## Token reference
|
|
109
|
+
|
|
110
|
+
A regenerator fills these tokens in `templates/PROGRESS.md`:
|
|
111
|
+
|
|
112
|
+
| Token | Source |
|
|
113
|
+
|-------|--------|
|
|
114
|
+
| `{{LAST_UPDATED}}` | ISO 8601 timestamp of this regeneration |
|
|
115
|
+
| `{{LAST_COMMAND}}` | the command that triggered the rebuild |
|
|
116
|
+
| `{{TITLE}}`, `{{WORK_TYPE}}` | `config.json` |
|
|
117
|
+
| `{{UNIT_LABEL}}`, `{{UNIT_LABEL_PLURAL}}` | `CONSTRAINTS.json` hierarchy for the work type |
|
|
118
|
+
| `{{PROGRESS_BAR}}`, `{{DONE_PERCENT}}` | computed from the done fraction |
|
|
119
|
+
| `{{DONE_COUNT}}`, `{{IN_PROGRESS_COUNT}}`, `{{UNTOUCHED_COUNT}}`, `{{TOTAL_COUNT}}` | per-unit derivation above |
|
|
120
|
+
| `{{WORD_COUNT}}` | sum of draft word counts |
|
|
121
|
+
| `{{STAGE_INDEX}}`, `{{STAGE_TOTAL}}`, `{{STAGE_NAME}}`, `{{LIFECYCLE_TRACK}}` | pipeline position above |
|
|
122
|
+
| `{{LEDGER_TABLE}}` | grouped ledger rows above |
|
|
123
|
+
| `{{RECENT_ACTIONS}}` | last 3-5 lines of `HISTORY.log` (or STATE.md Last actions) as rows |
|
|
124
|
+
| `{{NEXT_STEP}}` | the suggestion `/scr:next` would emit |
|
|
125
|
+
| `{{LAST_SCAN}}`, `{{LAST_SCAN_VERDICT}}` | `STATE.md` if recorded, else `never run` / `unknown` |
|
|
126
|
+
|
|
127
|
+
## When this protocol does not apply
|
|
128
|
+
|
|
129
|
+
- **Read-only views** (`/scr:progress`, `/scr:manuscript-stats`, `/scr:outline`) consume and render the derivation but do not write `PROGRESS.md`.
|
|
130
|
+
- **First-write commands** (`/scr:new-work`, `/scr:import`) -- no units exist yet; the ledger is generated on the first status-changing command or save.
|
|
131
|
+
|
|
132
|
+
The protocol is a hint, not a hard gate. A command that cannot parse the outline cleanly should fall back to the aggregate `STATE.md` counts and say so, rather than emit a wrong per-unit ledger.
|
package/docs/release-notes.md
CHANGED
|
@@ -2,6 +2,60 @@
|
|
|
2
2
|
|
|
3
3
|
This document is the public-facing summary of what changed between package releases. For package history, see the root [CHANGELOG](../CHANGELOG.md).
|
|
4
4
|
|
|
5
|
+
## 2.7.1 - 2026-05-30
|
|
6
|
+
|
|
7
|
+
### What changed
|
|
8
|
+
|
|
9
|
+
- `scriveno status` now prints the progress ledger directly (a `Progress:` line with bar, done / in progress / untouched, and pipeline position), so the deliverable view is visible from the bundled CLI, not only to runtimes that load the engine module.
|
|
10
|
+
- Documentation-integrity pass: corrected the context-integrity layer description (now five files), added `PROGRESS.md` to the scan trust-file lists and the architecture template tree, and refreshed stale version and count references across the docs.
|
|
11
|
+
|
|
12
|
+
### Why it matters
|
|
13
|
+
|
|
14
|
+
It closes the loop on the 2.7.0 progress ledger: the numbers are surfaced everywhere a writer looks, and the documentation matches the shipped behavior.
|
|
15
|
+
|
|
16
|
+
## 2.7.0 - 2026-05-30
|
|
17
|
+
|
|
18
|
+
### What changed
|
|
19
|
+
|
|
20
|
+
- Added a per-unit progress ledger: `.manuscript/PROGRESS.md` shows every unit as done / in progress / untouched, with a deliverable progress bar and pipeline position, and `/scr:progress` now leads with that view and points at the ledger file.
|
|
21
|
+
- `/scr:draft` and `/scr:autopilot` now narrate progress against the whole manuscript (unit N of total, percent).
|
|
22
|
+
- `lib/auto-invoke-engine.js` exposes `computeProgressLedger` so the ledger numbers are deterministic across runtimes; `docs/progress-protocol.md` documents the contract.
|
|
23
|
+
|
|
24
|
+
### Why it matters
|
|
25
|
+
|
|
26
|
+
Writers asked for one place to see what is done, in progress, and untouched without re-deriving it each time. The ledger is that file, and because it is derived from disk it cannot silently drift from the real state of the manuscript.
|
|
27
|
+
|
|
28
|
+
### Affected areas
|
|
29
|
+
|
|
30
|
+
- progress, draft, autopilot, outline, manuscript-stats, and scan commands
|
|
31
|
+
- the shared auto-invoke engine (computeProgressLedger)
|
|
32
|
+
- the trust-layer docs and templates
|
|
33
|
+
|
|
34
|
+
## 2.6.0 - 2026-05-29
|
|
35
|
+
|
|
36
|
+
### What changed
|
|
37
|
+
|
|
38
|
+
- Fixed a Pandoc-variable mismatch so RTL, CJK, and non-Latin fonts now reach the print and PDF path; added RTL support to the picturebook and stageplay templates (all four interior templates verified with `dir=rtl`).
|
|
39
|
+
- Made the voice-drift gate functional: `agents/voice-checker.md` now defines `drift = (100 - score) / 100`, so the default `voice.drift_threshold` of 0.3 means a re-draft is offered below a voice score of 70.
|
|
40
|
+
- Kept `/scr:autopilot-publish` fully unattended and advisory; a severe voice failure is surfaced loudly rather than halting the run.
|
|
41
|
+
- Corrected `/scr:quick-write` and `/scr:beta-reader` framing to match what they actually do.
|
|
42
|
+
- Marked the translation and illustration API tables as future targets, not shipped behavior.
|
|
43
|
+
- Audited and fixed documentation drift across the suite: command reference usage lines, the configuration baseline, the architecture file tree, voice-dna part numbering, the missing speech work type, and stale counts.
|
|
44
|
+
- Added `lib/track-safety.js` with adversarial tests, and `argument-hint` to 17 commands.
|
|
45
|
+
|
|
46
|
+
### Why it matters
|
|
47
|
+
|
|
48
|
+
This release closes the gap between what Scriveno documented and what it shipped. The export fix makes RTL and non-Latin print output actually work, the voice gate is now a real computed check instead of a phantom threshold, and the documentation no longer claims integrations or behavior that the prompt system does not provide.
|
|
49
|
+
|
|
50
|
+
### Affected areas
|
|
51
|
+
|
|
52
|
+
- export and print templates (RTL, CJK, fonts)
|
|
53
|
+
- voice-checker drift mapping and autopilot gates
|
|
54
|
+
- translation and illustration honesty
|
|
55
|
+
- documentation suite (command reference, configuration, architecture, voice-dna, README)
|
|
56
|
+
- track-safety helper and command argument hints
|
|
57
|
+
- package metadata and release-alignment tests
|
|
58
|
+
|
|
5
59
|
## 2.5.0 - 2026-05-16
|
|
6
60
|
|
|
7
61
|
### What changed
|
package/docs/route-graph.md
CHANGED
|
@@ -13,7 +13,7 @@ The text report summarizes command count, graph edges, agent-capable routes, loc
|
|
|
13
13
|
|
|
14
14
|
## Current Shape
|
|
15
15
|
|
|
16
|
-
As of `2.
|
|
16
|
+
As of `2.7.1`, the route graph contains:
|
|
17
17
|
|
|
18
18
|
- 113 commands
|
|
19
19
|
- intent-order edges from `command_intents`
|
package/docs/shipped-assets.md
CHANGED
|
@@ -27,14 +27,16 @@ A contributor adding `templates/pitfalls/<work_type>.md` is automatically picked
|
|
|
27
27
|
|
|
28
28
|
## Context Integrity Assets Shipped Since 2.0.0
|
|
29
29
|
|
|
30
|
-
These files ship in `templates/` and `docs/` and provide the
|
|
30
|
+
These files ship in `templates/` and `docs/` and provide the context-integrity set for session-aware AI work:
|
|
31
31
|
|
|
32
32
|
- `templates/CONTEXT.md` -- one-page session bootstrap scaffold copied into every project. Auto-regenerated on `/scr:save`, `/scr:pause-work`, `/scr:resume-work`. Read first by `/scr:next` and `/scr:resume-work` for orientation, with stale-detection + STATE.md fallback.
|
|
33
|
+
- `templates/PROGRESS.md` -- per-unit progress ledger scaffold: the openable file showing every unit as done / in progress / untouched, plus a deliverable progress bar and pipeline position. Derived from disk; auto-regenerated on `/scr:draft`, `/scr:editor-review`, `/scr:submit`, `/scr:autopilot`, `/scr:save`, `/scr:pause-work`, `/scr:resume-work`, and `/scr:scan --fix`. Rendered live by `/scr:progress`.
|
|
33
34
|
- `templates/RECORD.md` -- compact established-content store copied into every project. It tracks what the work has established, including open threads, promises, payoffs, continuity facts, movement, and next-unit obligations. It is deliberately neutral so sacred, academic, technical, poetry, script, visual, and prose projects can all use the same filename.
|
|
34
35
|
- `docs/context-protocol.md` -- canonical contract for the CONTEXT.md preference rule. The 12 high-impact commands that opt into the protocol reference this doc.
|
|
36
|
+
- `docs/progress-protocol.md` -- canonical contract for the `.manuscript/PROGRESS.md` per-unit ledger: status derivation from disk, the done / in progress / untouched buckets, pipeline position, the progress bar, and the regeneration points.
|
|
35
37
|
- `docs/history-protocol.md` -- canonical line-format spec for `.manuscript/HISTORY.log`, the append-only audit trail. Pipe-delimited, UTC ISO timestamps, committed to git.
|
|
36
38
|
|
|
37
|
-
`STATE.md` (workflow data) + `RECORD.md` (established content) + `CONTEXT.md` (narrative bootstrap) + `HISTORY.log` (audit trail) together form the integrity layer. `/scr:scan` is the trust check that interrogates whether the recorded state still matches disk.
|
|
39
|
+
`STATE.md` (workflow data) + `RECORD.md` (established content) + `CONTEXT.md` (narrative bootstrap) + `PROGRESS.md` (per-unit ledger) + `HISTORY.log` (audit trail) together form the integrity layer. `/scr:scan` is the trust check that interrogates whether the recorded state still matches disk.
|
|
38
40
|
|
|
39
41
|
## Runtime Sync Asset Shipped Today
|
|
40
42
|
|
package/docs/translation.md
CHANGED
|
@@ -2,17 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
Scriveno translates your manuscript into any language while preserving your voice. The translation pipeline handles glossary management, translation memory, cultural adaptation, quality verification, and multi-language publishing -- from setup to finished translated editions.
|
|
4
4
|
|
|
5
|
-
This guide covers the full pipeline:
|
|
5
|
+
This guide covers the full pipeline: how translation works, translating your manuscript, managing terminology, verifying quality, and publishing in multiple languages.
|
|
6
6
|
|
|
7
|
-
## Translation
|
|
7
|
+
## Translation approach
|
|
8
8
|
|
|
9
|
-
Scriveno
|
|
9
|
+
Scriveno translates through the in-context translator agent (`agents/translator.md`), not an external translation API. The agent itself handles literary nuance, sacred-text registers, and cultural adaptation that machine-translation services miss. It applies your voice profile, maintains glossary compliance, and can do formal or dynamic equivalence translation. Every unit is translated by the translator agent in fresh context with your STYLE-GUIDE.md loaded.
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
**Google Cloud Translation** -- Broad language coverage with 130+ languages. Required for Arabic, Hebrew, Hindi, Swahili, and other languages DeepL does not cover. Best choice for RTL scripts and languages with limited DeepL support.
|
|
14
|
-
|
|
15
|
-
**AI Agent (Claude/GPT)** -- The AI agent itself handles literary nuance, sacred text translation, and cultural adaptation that machine translation APIs miss. It applies your voice profile, maintains glossary compliance, and can do formal/dynamic equivalence translation. This is Scriveno's default for literary content -- every unit is translated by the translator agent with your STYLE-GUIDE.md loaded.
|
|
11
|
+
DeepL and Google Cloud Translation are documented as possible future integration targets, not current behavior. Scriveno does not call either service today; if an automated machine-translation path is added later, this guide will describe how it plugs in.
|
|
16
12
|
|
|
17
13
|
The translator agent works unit by unit in fresh context (just like the drafter), ensuring consistent quality and glossary compliance across the entire manuscript.
|
|
18
14
|
|
|
@@ -171,7 +167,7 @@ The TMX export produces industry-standard Translation Memory eXchange format com
|
|
|
171
167
|
|
|
172
168
|
## Cultural Adaptation
|
|
173
169
|
|
|
174
|
-
|
|
170
|
+
Translation handles words. Cultural adaptation handles meaning. Scriveno flags culturally sensitive content that needs deliberate attention beyond a faithful unit-by-unit rendering.
|
|
175
171
|
|
|
176
172
|
```
|
|
177
173
|
/scr:cultural-adaptation fr
|
|
@@ -247,8 +243,8 @@ Scriveno handles right-to-left and CJK (Chinese, Japanese, Korean) scripts throu
|
|
|
247
243
|
|
|
248
244
|
RTL languages (Arabic, Hebrew, Persian, Urdu) receive special handling:
|
|
249
245
|
|
|
250
|
-
- **Text direction** -- Export commands
|
|
251
|
-
- **Template adjustments** -- The Typst book template reverses inside/outside margins for RTL binding
|
|
246
|
+
- **Text direction** -- Export commands pass the Pandoc `dir` variable (`dir=rtl`); the Typst interior templates read that `dir` variable to orient text
|
|
247
|
+
- **Template adjustments** -- The Typst interior templates honor RTL: the book template reverses inside/outside margins for RTL binding, and the stageplay template flips its binding margin and page-number alignment. The chapbook and picturebook templates set text direction from the `dir` variable.
|
|
252
248
|
- **Font requirements** -- RTL exports need fonts with Arabic/Hebrew glyph support. Scriveno uses system-available fonts by default; specify custom fonts in `.manuscript/config.json`
|
|
253
249
|
- **Punctuation** -- Quotation marks use the appropriate convention (e.g., French-style guillemets for Arabic)
|
|
254
250
|
|
package/docs/voice-dna.md
CHANGED
|
@@ -138,7 +138,7 @@ This section governs the speed and flow of narrative.
|
|
|
138
138
|
- **Between chapters** -- Cliffhangers, echoes, or clean breaks
|
|
139
139
|
- **Time jumps** -- How they're signaled, how frequent, how handled
|
|
140
140
|
|
|
141
|
-
### Part
|
|
141
|
+
### Part 8: Reference Influences
|
|
142
142
|
|
|
143
143
|
This section captures the authors, works, and passages that anchor your voice.
|
|
144
144
|
|
|
@@ -210,7 +210,7 @@ The 10 registers are:
|
|
|
210
210
|
| **Parabolic** | Allegorical, story-within-story | "The kingdom of heaven is like..." concrete daily-life imagery |
|
|
211
211
|
| **Didactic** | Instructional, systematic, expository | Topic-by-topic structure, teacher-student dynamic, Q&A format |
|
|
212
212
|
|
|
213
|
-
Each unit's plan file specifies which register to use. Your STYLE-GUIDE.md Part 8
|
|
213
|
+
Each unit's plan file specifies which register to use. Your STYLE-GUIDE.md "Sacred voice registers" part (Part 8 in the shipped template) describes how YOU handle each register -- the drafter always defers to your personalized register style over the generic descriptions.
|
|
214
214
|
|
|
215
215
|
If no register is specified in a plan file, the drafter defaults to narrative-historical.
|
|
216
216
|
|
|
@@ -276,7 +276,7 @@ See [docs/drafter-quality.md](drafter-quality.md) for the full system, including
|
|
|
276
276
|
### Too many metaphors / not enough metaphors
|
|
277
277
|
|
|
278
278
|
**Symptom:** Prose is either overwritten or too bare.
|
|
279
|
-
**Fix:** Adjust metaphor density in STYLE-GUIDE.md Part
|
|
279
|
+
**Fix:** Adjust metaphor density in STYLE-GUIDE.md Part 3 (vocabulary and figurative language). "Sparse" means one metaphor per page at most. "Dense" means multiple per paragraph. Find your natural density by looking at your existing writing.
|
|
280
280
|
|
|
281
281
|
### AI-sounding hedging
|
|
282
282
|
|
|
@@ -820,6 +820,7 @@ function analyzeProject(projectRoot = process.cwd(), options = {}) {
|
|
|
820
820
|
commandUnit: config.command_unit || 'unit',
|
|
821
821
|
workType: config.work_type || '',
|
|
822
822
|
counts: { drafts: 0, plans: 0, reviews: 0 },
|
|
823
|
+
progress: computeProgressLedger(manuscriptDir),
|
|
823
824
|
signals,
|
|
824
825
|
recommendation,
|
|
825
826
|
automation,
|
|
@@ -871,6 +872,7 @@ function analyzeProject(projectRoot = process.cwd(), options = {}) {
|
|
|
871
872
|
commandUnit: config.command_unit || 'unit',
|
|
872
873
|
workType: config.work_type || '',
|
|
873
874
|
counts,
|
|
875
|
+
progress: computeProgressLedger(manuscriptDir),
|
|
874
876
|
signals,
|
|
875
877
|
recommendation,
|
|
876
878
|
automation,
|
|
@@ -879,12 +881,17 @@ function analyzeProject(projectRoot = process.cwd(), options = {}) {
|
|
|
879
881
|
|
|
880
882
|
function formatProactiveChecks(analysis) {
|
|
881
883
|
const { signals } = analysis;
|
|
884
|
+
const progress = analysis.progress || {};
|
|
882
885
|
const stateLine = signals.hasProject
|
|
883
886
|
? ` State: ${signals.hasState ? 'fresh' : 'missing, suggest /scr:scan'}`
|
|
884
887
|
: ' Project: missing, suggest /scr:new-work';
|
|
888
|
+
const progressLine = progress.total
|
|
889
|
+
? ` Progress: ${progress.bar} ${progress.done}/${progress.total} done (${progress.percent}%), ${progress.inProgress} in progress, ${progress.untouched} untouched`
|
|
890
|
+
: ' Progress: no units yet';
|
|
885
891
|
return [
|
|
886
892
|
'Proactive checks:',
|
|
887
893
|
stateLine,
|
|
894
|
+
progressLine,
|
|
888
895
|
` Readiness: ${signals.readiness?.state || 'none'}${signals.readiness?.missing?.length ? `, missing ${signals.readiness.missing.join(', ')}` : ''}`,
|
|
889
896
|
` Session: ${signals.context.state}${signals.context.suggest ? `, suggest ${signals.context.suggest}` : ''}`,
|
|
890
897
|
` Plans: ${signals.plan?.state || 'none'}${signals.plan?.suggest ? `, suggest ${signals.plan.suggest}` : ''}`,
|
|
@@ -1377,6 +1384,93 @@ if (require.main === module) {
|
|
|
1377
1384
|
}
|
|
1378
1385
|
}
|
|
1379
1386
|
|
|
1387
|
+
// Progress ledger: deterministic deliverable-progress computation from disk.
|
|
1388
|
+
// See docs/progress-protocol.md. Additive helper used by /scr:progress and any
|
|
1389
|
+
// runtime that loads this module, so the ledger is consistent across hosts.
|
|
1390
|
+
function ledgerUnitNumbers(dir, suffixRegex) {
|
|
1391
|
+
const found = new Set();
|
|
1392
|
+
let entries;
|
|
1393
|
+
try {
|
|
1394
|
+
entries = fs.readdirSync(dir);
|
|
1395
|
+
} catch (err) {
|
|
1396
|
+
return found;
|
|
1397
|
+
}
|
|
1398
|
+
for (const name of entries) {
|
|
1399
|
+
const match = name.match(suffixRegex);
|
|
1400
|
+
if (match) {
|
|
1401
|
+
found.add(parseInt(match[1], 10));
|
|
1402
|
+
}
|
|
1403
|
+
}
|
|
1404
|
+
return found;
|
|
1405
|
+
}
|
|
1406
|
+
|
|
1407
|
+
function ledgerOutlineUnitCount(manuscriptDir) {
|
|
1408
|
+
let text;
|
|
1409
|
+
try {
|
|
1410
|
+
text = fs.readFileSync(path.join(manuscriptDir, 'OUTLINE.md'), 'utf8');
|
|
1411
|
+
} catch (err) {
|
|
1412
|
+
return 0;
|
|
1413
|
+
}
|
|
1414
|
+
const tableRows = text.match(/^\|\s*\d+\s*\|/gm);
|
|
1415
|
+
if (tableRows && tableRows.length) {
|
|
1416
|
+
return tableRows.length;
|
|
1417
|
+
}
|
|
1418
|
+
const numberedLines = text.match(/^\s*\d+[.)]\s+\S/gm);
|
|
1419
|
+
return numberedLines ? numberedLines.length : 0;
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
function ledgerBar(done, total, width) {
|
|
1423
|
+
const cells = width || 10;
|
|
1424
|
+
const filled = total > 0 ? Math.round((done / total) * cells) : 0;
|
|
1425
|
+
const clamped = Math.max(0, Math.min(cells, filled));
|
|
1426
|
+
return '█'.repeat(clamped) + '░'.repeat(cells - clamped);
|
|
1427
|
+
}
|
|
1428
|
+
|
|
1429
|
+
// Returns deliverable progress for a project's .manuscript directory: total
|
|
1430
|
+
// units, per-stage counts, the done / in-progress / untouched buckets, a
|
|
1431
|
+
// percent, a rendered bar, and the unit-number sets. Derived purely from disk
|
|
1432
|
+
// (plan/draft/review files reconciled with the OUTLINE unit count).
|
|
1433
|
+
function computeProgressLedger(manuscriptDir) {
|
|
1434
|
+
const drafted = ledgerUnitNumbers(
|
|
1435
|
+
path.join(manuscriptDir, 'drafts', 'body'),
|
|
1436
|
+
/^(\d+)\D.*DRAFT\.md$/i
|
|
1437
|
+
);
|
|
1438
|
+
const planned = ledgerUnitNumbers(path.join(manuscriptDir, 'plans'), /^(\d+)\D.*PLAN\.md$/i);
|
|
1439
|
+
for (const unit of ledgerUnitNumbers(manuscriptDir, /^(\d+)\D.*PLAN\.md$/i)) {
|
|
1440
|
+
planned.add(unit);
|
|
1441
|
+
}
|
|
1442
|
+
const reviewed = ledgerUnitNumbers(path.join(manuscriptDir, 'reviews'), /^(\d+)\D.*REVIEW\.md$/i);
|
|
1443
|
+
for (const unit of ledgerUnitNumbers(manuscriptDir, /^(\d+)\D.*EDITOR-NOTES\.md$/i)) {
|
|
1444
|
+
reviewed.add(unit);
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
const worked = new Set([...planned, ...drafted, ...reviewed]);
|
|
1448
|
+
const maxWorked = worked.size ? Math.max(...worked) : 0;
|
|
1449
|
+
const total = Math.max(ledgerOutlineUnitCount(manuscriptDir), worked.size, maxWorked);
|
|
1450
|
+
|
|
1451
|
+
const done = reviewed.size;
|
|
1452
|
+
const inProgress = [...worked].filter((unit) => !reviewed.has(unit)).length;
|
|
1453
|
+
const untouched = Math.max(0, total - worked.size);
|
|
1454
|
+
const percent = total > 0 ? Math.round((done / total) * 100) : 0;
|
|
1455
|
+
|
|
1456
|
+
return {
|
|
1457
|
+
total,
|
|
1458
|
+
drafted: drafted.size,
|
|
1459
|
+
planned: planned.size,
|
|
1460
|
+
reviewed: reviewed.size,
|
|
1461
|
+
done,
|
|
1462
|
+
inProgress,
|
|
1463
|
+
untouched,
|
|
1464
|
+
percent,
|
|
1465
|
+
bar: ledgerBar(done, total, 10),
|
|
1466
|
+
units: {
|
|
1467
|
+
drafted: [...drafted].sort((a, b) => a - b),
|
|
1468
|
+
planned: [...planned].sort((a, b) => a - b),
|
|
1469
|
+
reviewed: [...reviewed].sort((a, b) => a - b),
|
|
1470
|
+
},
|
|
1471
|
+
};
|
|
1472
|
+
}
|
|
1473
|
+
|
|
1380
1474
|
module.exports = {
|
|
1381
1475
|
AGENT_ROUTE_POLICIES,
|
|
1382
1476
|
CATEGORY_ROUTE_POLICIES,
|
|
@@ -1404,4 +1498,5 @@ module.exports = {
|
|
|
1404
1498
|
inspectRuntimeSmoke,
|
|
1405
1499
|
listRuntimeAgentSupport,
|
|
1406
1500
|
parseCliArgs,
|
|
1501
|
+
computeProgressLedger,
|
|
1407
1502
|
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
// lib/track-safety.js
|
|
2
|
+
// Canonical, dependency-free slug + branch derivation for /scr:track (D-01).
|
|
3
|
+
//
|
|
4
|
+
// The track.md prompt instructs the agent to slugify a writer-provided track
|
|
5
|
+
// label before it ever touches a git or shell command. This module is the
|
|
6
|
+
// single source of truth for that algorithm. The installer copies lib/ into the
|
|
7
|
+
// writer's data dir, so it ships as <data-dir>/lib/track-safety.js and a runtime
|
|
8
|
+
// can derive a guaranteed-safe slug deterministically instead of relying on the
|
|
9
|
+
// model to apply the rules by hand:
|
|
10
|
+
//
|
|
11
|
+
// node <data-dir>/lib/track-safety.js "Editor's Suggestions"
|
|
12
|
+
// -> {"slug":"editors-suggestions","branch":"track/editors-suggestions"}
|
|
13
|
+
//
|
|
14
|
+
// Safety property: a sanitized slug contains only [a-z0-9-]. It can never carry
|
|
15
|
+
// a shell metacharacter, quote, whitespace, path separator, or command
|
|
16
|
+
// substitution, so interpolating `track/<slug>` into a git command line is safe.
|
|
17
|
+
|
|
18
|
+
'use strict';
|
|
19
|
+
|
|
20
|
+
// A slug is shell-safe iff it is a non-empty run of lowercase alphanumerics and
|
|
21
|
+
// hyphens with no leading/trailing hyphen.
|
|
22
|
+
const SLUG_SAFE = /^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/;
|
|
23
|
+
const FALLBACK_SLUG = 'untitled';
|
|
24
|
+
|
|
25
|
+
// Apply the D-01 rules: lowercase, whitespace/underscores to hyphen, strip
|
|
26
|
+
// everything that is not [a-z0-9-], collapse hyphen runs, trim edge hyphens.
|
|
27
|
+
// Returns FALLBACK_SLUG when the label has no usable characters (e.g. "***",
|
|
28
|
+
// "日本", "") so the caller never produces an empty branch name.
|
|
29
|
+
function sanitizeTrackSlug(label) {
|
|
30
|
+
const slug = String(label == null ? '' : label)
|
|
31
|
+
.toLowerCase()
|
|
32
|
+
.replace(/[\s_]+/g, '-')
|
|
33
|
+
.replace(/[^a-z0-9-]+/g, '')
|
|
34
|
+
.replace(/-+/g, '-')
|
|
35
|
+
.replace(/^-+|-+$/g, '');
|
|
36
|
+
return slug.length > 0 ? slug : FALLBACK_SLUG;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function isShellSafeSlug(slug) {
|
|
40
|
+
return typeof slug === 'string' && SLUG_SAFE.test(slug);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// Resolve a collision-free branch name. `existingBranches` is the set of branch
|
|
44
|
+
// names already present in the repo (e.g. parsed from `git branch`). Mirrors
|
|
45
|
+
// track.md create-step 6: append -2, -3, ... to the slug until the branch name
|
|
46
|
+
// is free.
|
|
47
|
+
function resolveTrackBranch(label, existingBranches = []) {
|
|
48
|
+
const taken = new Set(existingBranches);
|
|
49
|
+
const baseSlug = sanitizeTrackSlug(label);
|
|
50
|
+
let slug = baseSlug;
|
|
51
|
+
let n = 2;
|
|
52
|
+
while (taken.has(`track/${slug}`)) {
|
|
53
|
+
slug = `${baseSlug}-${n}`;
|
|
54
|
+
n += 1;
|
|
55
|
+
}
|
|
56
|
+
return { slug, branch: `track/${slug}` };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
module.exports = {
|
|
60
|
+
sanitizeTrackSlug,
|
|
61
|
+
isShellSafeSlug,
|
|
62
|
+
resolveTrackBranch,
|
|
63
|
+
FALLBACK_SLUG,
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
if (require.main === module) {
|
|
67
|
+
const label = process.argv[2] || '';
|
|
68
|
+
const existing = process.argv[3]
|
|
69
|
+
? process.argv[3].split(',').map((s) => s.trim()).filter(Boolean)
|
|
70
|
+
: [];
|
|
71
|
+
process.stdout.write(JSON.stringify(resolveTrackBranch(label, existing)) + '\n');
|
|
72
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
creative_pillar: continuity
|
|
3
|
+
always_load_for: [progress]
|
|
4
|
+
authority: derived
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Progress ledger
|
|
8
|
+
|
|
9
|
+
This file is auto-regenerated by Scriveno. It is the one place to open and see every {{UNIT_LABEL}} at a glance: what is done, what is in progress, and what is untouched. Do not hand-edit -- it is rebuilt from disk whenever the project's unit status changes (on `/scr:draft`, `/scr:editor-review`, `/scr:submit`, `/scr:autopilot`, `/scr:save`, `/scr:pause-work`, `/scr:resume-work`, and `/scr:scan --fix`).
|
|
10
|
+
|
|
11
|
+
If this file is missing, stale, or disagrees with the live view from `/scr:progress`, run `/scr:save` (or `/scr:scan --fix`) to rebuild it. `/scr:progress` always renders the current picture from disk; this file is the saved snapshot you can open any time.
|
|
12
|
+
|
|
13
|
+
**Updated:** {{LAST_UPDATED}}
|
|
14
|
+
**Updated by:** {{LAST_COMMAND}}
|
|
15
|
+
**Project:** {{TITLE}} ({{WORK_TYPE}})
|
|
16
|
+
|
|
17
|
+
## Deliverable progress
|
|
18
|
+
|
|
19
|
+
{{PROGRESS_BAR}} {{DONE_COUNT}}/{{TOTAL_COUNT}} {{UNIT_LABEL_PLURAL}} done ({{DONE_PERCENT}}%)
|
|
20
|
+
|
|
21
|
+
- **Done:** {{DONE_COUNT}}
|
|
22
|
+
- **In progress:** {{IN_PROGRESS_COUNT}}
|
|
23
|
+
- **Untouched:** {{UNTOUCHED_COUNT}}
|
|
24
|
+
- **Words:** {{WORD_COUNT}}
|
|
25
|
+
|
|
26
|
+
## Pipeline position
|
|
27
|
+
|
|
28
|
+
Stage {{STAGE_INDEX}} of {{STAGE_TOTAL}}: {{STAGE_NAME}}
|
|
29
|
+
|
|
30
|
+
`{{LIFECYCLE_TRACK}}`
|
|
31
|
+
|
|
32
|
+
## {{UNIT_LABEL}} ledger
|
|
33
|
+
|
|
34
|
+
Status key: `[x]` done `[~]` in progress `[ ]` untouched
|
|
35
|
+
|
|
36
|
+
{{LEDGER_TABLE}}
|
|
37
|
+
|
|
38
|
+
## Recent activity
|
|
39
|
+
|
|
40
|
+
The last few recorded actions, newest first. Full history lives in `.manuscript/HISTORY.log`.
|
|
41
|
+
|
|
42
|
+
{{RECENT_ACTIONS}}
|
|
43
|
+
|
|
44
|
+
## What's next
|
|
45
|
+
|
|
46
|
+
{{NEXT_STEP}}
|
|
47
|
+
|
|
48
|
+
## Trust check
|
|
49
|
+
|
|
50
|
+
The status above is derived from disk: plan files in `.manuscript/plans/`, drafts in `.manuscript/drafts/body/`, and reviews in `.manuscript/reviews/`, reconciled with `.manuscript/STATE.md`. The numbers are claims, not facts -- run `/scr:scan` to confirm they still match disk.
|
|
51
|
+
|
|
52
|
+
**Last `/scr:scan` run:** {{LAST_SCAN}}
|
|
53
|
+
**Last drift verdict:** {{LAST_SCAN_VERDICT}}
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
*Derived ledger. See `docs/progress-protocol.md` for how status is computed. This file is the saved snapshot; `/scr:progress` renders the same picture live.*
|
package/templates/config.json
CHANGED