Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: 2
updates:
- package-ecosystem: cargo
directory: /
schedule:
interval: weekly
day: monday
time: "06:00"
timezone: Europe/Rome
open-pull-requests-limit: 5
groups:
rust-patch-and-minor:
update-types:
- patch
- minor

- package-ecosystem: github-actions
directory: /
schedule:
interval: weekly
day: monday
time: "06:30"
timezone: Europe/Rome
open-pull-requests-limit: 5
17 changes: 14 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,20 @@ jobs:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
# Lifecycle integration tests under crates/bookforge-cli/tests/ require
# test/test.epub, which is gitignored. They will be skipped in CI; that
# is intentional. The remaining workspace tests still run.
# Lifecycle tests create synthetic EPUB fixtures and run in clean clones.
- run: cargo test --workspace --locked

test-windows:
name: test (windows-msvc)
runs-on: windows-2022
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
key: windows-msvc
- run: cargo test --workspace --locked

msrv:
Expand Down
44 changes: 44 additions & 0 deletions .github/workflows/security.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: Security

on:
pull_request:
push:
branches: [main]
schedule:
- cron: "41 4 * * 1"
workflow_dispatch:

permissions:
contents: read

jobs:
rustsec:
name: RustSec advisory audit
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: rustsec/audit-check@v2.0.0
with:
token: ${{ secrets.GITHUB_TOKEN }}

codeql:
name: CodeQL (Rust)
runs-on: ubuntu-22.04
permissions:
actions: read
contents: read
security-events: write
steps:
- uses: actions/checkout@v6
with:
persist-credentials: false
- uses: github/codeql-action/init@v4
with:
languages: rust
build-mode: none
queries: security-extended
- uses: github/codeql-action/analyze@v4
with:
category: /language:rust
31 changes: 31 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,36 @@
# Changelog

## Unreleased (2.4.0-dev)

BookForge main now carries a distinct development version so source builds
cannot be confused with the published v2.3.0 artifacts.

- Added cache-safe job reconfiguration through `bookforge reconfigure`, with
auditable overrides that apply when a stopped or dead paused job resumes.
- Added escalation-first handling for truncated batch responses and prominent
systemic-truncation alerts across CLI, watch, and dashboard surfaces.
- Fixed resume override handling, adaptive batch override propagation, stale
override cleanup, and dashboard wizard API-key retention.
- Bumped the batch translate prompts (plain, marker-safe, run-preserving, and
their compact variants) from v2 to v3 to teach models about a per-item
`retry_guidance` field; the batch prompt cache tag moved from `batch_v2`
to `batch_v3` so translations cached under the old prompt text are not
reused.

## v2.3.0 - 2026-07-05

BookForge v2.3.0 added source-EPUB reflow and cooperative job controls.

- Added `bookforge reflow`, including the opt-in `--aggressive` level, while
preserving the rule that source EPUBs are never silently rewritten during
translation.
- Added pause, resume, and stop controls to the engine, CLI, terminal watcher,
and browser dashboard, with completed segments checkpointed before parking.
- Made finalize-stage QA and double-check requests honor pause/stop controls;
stopped jobs remain resumable without retranslating completed segments.
- Hardened reflow boundaries around letterless paragraphs, inline whitespace,
dehyphenation, and class-based merge guards.

## v2.2.0 - 2026-07-04

BookForge v2.2.0 ships the v1.7 roadmap milestone: bilingual output.
Expand Down
19 changes: 12 additions & 7 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,13 +50,19 @@ usually won't move.
Before submitting:

```bash
cargo fmt
cargo clippy --all-targets --all-features
cargo test
cargo fmt --all --check
cargo clippy --all-targets --all-features -- -A clippy::too_many_arguments -D warnings
cargo test --workspace --locked
```

All three should pass cleanly. CI runs the same set.

On Windows, use the MSVC Rust host (`stable-x86_64-pc-windows-msvc`) and
install the Visual Studio Build Tools C++ workload. The GNU host requires a
separate MinGW toolchain including `dlltool.exe` and is not the contributor
baseline. Verify the active host with `rustc -vV` before diagnosing a project
build failure.

Add tests for any behaviour change, especially around:

- EPUB segmentation and rebuild (`bookforge-epub`).
Expand All @@ -65,10 +71,9 @@ Add tests for any behaviour change, especially around:
- Anything that touches the `ProgressSink` event schema or the JSONL
field set (these are semver-stable for v1.x; see ROADMAP §1.5).

Some lifecycle integration tests under `crates/bookforge-cli/tests/`
read `test/test.epub`, which is gitignored. They will be skipped or
fail on a fresh clone unless you drop your own fixture at that path.
A real-but-small public-domain EPUB works fine.
Lifecycle integration tests build synthetic EPUB fixtures and run in a fresh
clone. The separate pinned Standard Ebooks corpus is exercised by CI through
`scripts/corpus-smoke.sh`; local corpus downloads remain gitignored.

## Commit and PR style

Expand Down
55 changes: 43 additions & 12 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ console = "0.16"
indicatif = "0.18"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter", "fmt"] }
quick-xml = { version = "0.38", features = ["escape-html"] }
quick-xml = { version = "0.41", features = ["escape-html"] }
zip = "6.0"
rusqlite = { version = "0.37", features = ["bundled"] }
reqwest = { version = "0.12", features = ["json", "rustls-tls", "gzip", "brotli"], default-features = false }
Expand Down
13 changes: 7 additions & 6 deletions crates/bookforge-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "bookforge-cli"
version = "2.3.0"
version = "2.4.0-dev"
description = "CLI-first EPUB translation engine with deterministic structure rebuild and review loop."
readme = "../../README.md"
edition.workspace = true
Expand All @@ -16,11 +16,11 @@ path = "src/main.rs"
anyhow.workspace = true
async-stream = { version = "0.3", optional = true }
axum = { version = "0.8", optional = true, features = ["multipart"] }
bookforge-core = { version = "2.3.0", path = "../bookforge-core", features = ["cli"] }
bookforge-epub = { version = "2.3.0", path = "../bookforge-epub" }
bookforge-llm = { version = "2.3.0", path = "../bookforge-llm" }
bookforge-pdf = { version = "2.3.0", path = "../bookforge-pdf" }
bookforge-store = { version = "2.3.0", path = "../bookforge-store" }
bookforge-core = { version = "2.4.0-dev", path = "../bookforge-core", features = ["cli"] }
bookforge-epub = { version = "2.4.0-dev", path = "../bookforge-epub" }
bookforge-llm = { version = "2.4.0-dev", path = "../bookforge-llm" }
bookforge-pdf = { version = "2.4.0-dev", path = "../bookforge-pdf" }
bookforge-store = { version = "2.4.0-dev", path = "../bookforge-store" }
clap.workspace = true
console.workspace = true
futures-core = { version = "0.3", optional = true }
Expand Down Expand Up @@ -55,6 +55,7 @@ serve = [

[dev-dependencies]
assert_cmd = "2"
predicates = "3"
quick-xml.workspace = true
tempfile = "3"
tower = "0.5"
Expand Down
Loading
Loading