diff --git a/README.md b/README.md index 352763c..d7631f7 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ The project is under active development. Core blogging workflows are broadly ava - Persistent conversational AI with safe Markdown, streamed and cancellable responses, model/session/token tracking, bounded project-aware blog tools, and localized conversation management in the Chat workspace. Allowlisted render tools add persistent native cards, charts, forms, lists, metrics, mind maps, tables, and tabs without executing assistant-provided HTML or JavaScript. - SSH-agent-based SCP or rsync publishing. - Integrated Git workflow with repository initialization, Git LFS image tracking, status and diffs, branch/file history, commits, remotes, cancellable fetch/pull/push, and post-pull filesystem reconciliation; network actions respect airplane mode. -- Site, media, and translation validation plus `ruds://new-post` Blogmark capture and Lua transforms; captures open directly in the post editor and defer automatic translation until an explicit save or publish, which queues one task per still-missing language. bDS2 keeps its separate `bds2://` bookmarklet protocol. +- Site, media, and translation validation plus `ruds://new-post` Blogmark capture and Lua transforms; captures open directly in the post editor and defer automatic translation until an explicit manual save, which queues one task per still-missing language. Publishing never starts automatic translation. bDS2 keeps its separate `bds2://` bookmarklet protocol. RuDS uses no JavaScript application runtime and loads no CSS or JavaScript from CDNs. The preview is served by the Rust application and displayed by the operating-system webview. diff --git a/crates/bds-ui/src/app.rs b/crates/bds-ui/src/app.rs index 379e7e7..0ef924a 100644 --- a/crates/bds-ui/src/app.rs +++ b/crates/bds-ui/src/app.rs @@ -6048,7 +6048,6 @@ impl BdsApp { } } self.notify(ToastLevel::Success, &t(self.ui_locale, "editor.published")); - return self.schedule_post_auto_translation(post_id); } Err(e) => { self.notify_operation_failed("editor.publish", e); @@ -11921,6 +11920,21 @@ mod tests { ); } + #[test] + fn publish_does_not_enqueue_missing_translations() { + let (mut app, post_id, _tmp) = auto_translation_test_app(&[]); + + let _ = app.publish_post_editor(&post_id); + + assert_eq!(app.post_editors[&post_id].status, PostStatus::Published); + assert!( + app.task_manager + .snapshots() + .iter() + .all(|task| task.group_name.as_deref() != Some("AI")) + ); + } + #[test] fn later_manual_save_enqueues_no_translation_task_when_languages_exist() { let (mut app, post_id, _tmp) = auto_translation_test_app(&["de", "fr"]); diff --git a/specs/action_patterns.allium b/specs/action_patterns.allium index 8e3decd..0202eb2 100644 --- a/specs/action_patterns.allium +++ b/specs/action_patterns.allium @@ -113,9 +113,8 @@ rule CancelAiSuggestions { rule AutoTranslationChain { when: PostSaved(post_id) - -- Triggered only by explicit manual save or publish, never by - -- auto-save, unmount/tab-switch persistence, post creation, import, - -- or scripting. + -- Triggered only by explicit manual save, never by publish, auto-save, + -- unmount/tab-switch persistence, post creation, import, or scripting. let saved_post = post/Post{id: post_id} requires: active_endpoint_configured requires: not saved_post.do_not_translate diff --git a/specs/translation.allium b/specs/translation.allium index e5bade5..f58481f 100644 --- a/specs/translation.allium +++ b/specs/translation.allium @@ -196,7 +196,7 @@ invariant FtsIncludesTranslations { -- -- Two entry points share one translation primitive: -- 1. ScheduleAutoTranslation - reactive, fired only by an explicit manual --- save (or publish) in the post editor — never by post creation or +-- save in the post editor — never by publish, post creation, or -- auto-save. One background task per missing language produces a DRAFT -- translation, then cascades to the post's linked media. -- 2. FillMissingTranslations - batch maintenance action. Scans every @@ -215,8 +215,8 @@ surface AutoTranslationControlSurface { provides: -- Reactive trigger: emitted only when a post is updated with - -- auto_translate enabled (the editor's manual save/publish path); - -- post creation and auto-save never emit it. + -- auto_translate enabled (the editor's manual save path); publish, + -- post creation, and auto-save never emit it. PostSavedForAutoTranslation(post) -- Batch trigger: "fill missing translations" maintenance action. FillMissingTranslationsRequested(project)