Repository navigation
feature: allow a watch or group to append to the inherited AI Change Summary prompt - #4294
Merged
dgtlmoon merged 3 commits intoAug 20, 2026
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Closes #4251.
Adds a per-watch and per-group radio choosing whether the AI Change Summary prompt replaces the prompt it inherits (today's behaviour, still the default) or is appended to it.
The reporter's case: they only want to add one line to the global prompt, but the only way to do that today is to paste the whole global prompt into the watch and edit it. That copy then goes stale the moment the global prompt is edited.
Behaviour
get_effective_summary_prompt()now builds the prompt from the bottom of the cascade upward — hardcoded fallback → global default → tag → watch — and each level with a value either replaces what it inherited or appends to it, per its ownllm_change_summary_mode.replaceWATCHWATCHappendWATCHGLOBAL+WATCHreplaceTAGappendWATCHTAG+WATCHappendTAGappendWATCHGLOBAL+TAG+WATCHappendTAGreplaceWATCHWATCHA watch in append mode appends to whatever it would otherwise have inherited, so a group prompt stays authoritative for its watches. Levels are joined with a blank line.
Nothing changes for existing installs.
replaceis the default at every level, and with every level onreplacethe new code reduces to the original first-non-empty-wins cascade. Watches stored before this change have no mode key at all and are treated asreplace— there is a test pinning exactly that.Because the mode feeds
get_effective_summary_prompt(), and that result is already part of the summary cache key, toggling the mode invalidates cached summaries automatically rather than silently serving one generated under the other mode. Also covered by a test.Scope
llm_change_summaryonly.llm_intenthas no global default to append to, and the issue and its screenshot are about the summary prompt.llm_change_summary_modeis added to the OpenAPI spec, otherwise it would come back from aGET /api/v1/watch/<uuid>and then be rejected by the unknown-field validator on thePUTround trip.One thing I deliberately left alone: the existing Modify default prompt button pastes the inherited prompt into the textarea, which is a replace-mode workflow and would duplicate the prompt if clicked while append is selected. Hiding it in append mode needs JavaScript in a template shared by watch and tag edit, so I left it out rather than grow the diff — happy to add it if you'd like.
Testing
New tests, all passing:
tests/llm/test_evaluator.py::TestSummaryPromptAppendMode— 9 unit tests over the cascade: append onto global, onto the hardcoded fallback, onto a tag; the tag+watch chain; append with empty text; a missing mode key behaving asreplace; and the cache key changing with the mode.tests/test_llm_change_summary.py— 3 integration tests: append mode saved through the watch edit form and applied; a pre-[feature] Per-site appending to the global LLM prompt, instead of only overwriting it #4251 form submission (no mode field) still replacing; the radio rendering on the edit page.tests/test_llm_group_overrides.py— 2 tests: the radio rendering on the tag edit page, and a group in append mode adding to the global prompt.Suite runs on this branch (Linux container):
tests/llm/ tests/unit/ tests/test_llm_change_summary.py tests/test_llm_group_overrides.py— 375 passedtests/test_api.py tests/test_api_openapi.py tests/test_api_tags.py— 25 passedtests/restock/ tests/test_notification.py— 11 passed, 1 failedThe one failure is
tests/restock/test_restock.py::test_restock_detection, which fails identically on unmodified master in the same environment — unrelated to this change.CI gates run locally:
ruff check . --select E9,F63,F7,F82,INTclean, OpenAPI spec validates, and the template i18n fragmentation check stays at the baseline of 44 with no new violations. The new UI strings are wrapped in_l()/_(); I have not regenerated the translation catalog, to keep this diff free of.mo/.potchurn (#4108).