**Steps to replicate the issue** (include links if applicable):
* Navigate to Special:Undelete and enter a title of page that has been deleted
* Scroll down to the Page history section
* Click on any of the timestamps to view the selected revision
* Below the textarea that appears, click "Show preview"
**What happens?**:
Nothing happens. The page reloads as-is and no preview (i.e. rendered content) is displayed.
**What should have happened instead?**:
The preview should appear.
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
* Since 1.46-wmf.24
* It might have to do with the fact that since that version the syntax highlighter appears on the Special:Undelete page
**Other information** (browser name/version, screenshots, etc.):
The "Show changes" button works properly.
PatchDemos to demonstrate that issue started in wmf.24 (you need to log in to the `Patch Demo` account):
* wmf.23 (works): https://2c7ff3f548.catalyst.wmcloud.org/w/index.php?title=Special:Undelete&target=Test×tamp=20261015163516
* wmf.24 (broken): https://1ba9add6ed.catalyst.wmcloud.org/w/index.php?title=Special:Undelete&target=Test×tamp=20261015163904
## Summary
Since [[ https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1347796 | this change ]] has rolled out to production wikis, edits to articles on those wikis are causing the "page image" to be dropped. The article keeps its lead image in the wikitext, but the page image API, the page summary API (link previews, apps) and the `og:image` tag (link previews on social media and in chat apps) no longer return one.
The impact of this bug will continue to grow as more pages get edited.
Some example pages that should have page images but no longer do because they were recently edited:
- Napoleon (last edit 2026-10-15 14:59 UTC): https://en.wikipedia.org/w/api.php?action=query&prop=pageimages%7Cpageprops&titles=Napoleon&format=json&formatversion=2 · https://en.wikipedia.org/api/rest_v1/page/summary/Napoleon · https://en.wikipedia.org/wiki/Napoleon (no `og:image` meta tag)
- Mona Lisa (last edit 09:06 UTC): https://en.wikipedia.org/w/api.php?action=query&prop=pageimages%7Cpageprops&titles=Mona_Lisa&format=json&formatversion=2
- The Beatles (10:57 UTC) and Zendaya (10:55 UTC): https://en.wikipedia.org/w/api.php?action=query&prop=pageimages%7Cpageprops&titles=The_Beatles%7CZendaya&format=json&formatversion=2
An empty `array` or `aligned` environment passes the TeX check, but its MathML contains an `merror` (Math master):
```lang=latex
\begin{array}{c}\end{array}
\begin{aligned}\end{aligned}
```
```lang=xml
<merror><mtext>Not implemented MediaWiki\Extension\Math\WikiTexVC\Nodes\TexNode for array</mtext></merror>
```
An empty `matrix` renders fine, and so does an `array` with content (`\begin{array}{c}x\end{array}`).
**Found on English Wikipedia**
Input `fd684bb5977e49dc610a73561beb915c`:
```lang=latex
\frac{ \begin{array}{c} \end{array} }{ A := A^{[0]} \;\;\; C := \text{NONE} } \text{ (Restart)}
```
It is the only one of the 672,902 valid enwiki inputs whose MathML contains an `merror`, so `EnWikiFormulaeTest` fails on it once the reference is refreshed (T439313).
**Expected**
An empty `mtable`, like the empty `matrix`.
== Background
When I visit a Collections page, there is a vue warning in the console:
```
vue.js:2263 [Vue warn]: Invalid prop: custom validator check failed for prop "size".
at <CdxIcon icon="<path d=\"M11.835 3.505a6.7 6.7 0 011.46.603l2.362-1.18 1.414 1.415-1.18 2.361a6.7 6.7 0 01.603 1.46L19 9v2l-2.506.835a6.7 6.7 0 01-.603 1.46l1.18 2.362-1.414 1.414-2.362-1.18a6.7 6.7 0 01-1.46.603L11 19H9l-.836-2.506a6.7 6.7 0 01-1.46-.603l-2.361 1.18-1.414-1.414 1.18-2.362a6.7 6.7 0 01-.604-1.46L1 11V9l2.505-.836a6.7 6.7 0 01.603-1.46l-1.18-2.361 1.415-1.414 2.361 1.18a6.7 6.7 0 011.46-.604L9 1h2zM10 7a3 3 0 100 6 3 3 0 000-6\"/>" size="large" >
at <CdxButton ref="settingsButton" class="readinglists-nav-bar-settings-button" weight="quiet" ... >
at <Anonymous key=2 is-custom-list=true onCreateCollection=fn<onCreateCollection> >
at <Anonymous listId=9 isCustomListsEnabled=true onVnodeUnmounted=fn<onVnodeUnmounted> ... >
at <RouterView key="/Admin/9/Countries" >
at <App>
```
"large" is not a valid cdx-icon size:
https://doc.wikimedia.org/codex/latest/components/demos/icon.html#icon-sizes
---
== Requirements
//Add technical requirements and performance or accessibility considerations.//
=== Acceptance criteria for done
[] There should be no vue warning in the browser console when viewing a collection.
=== QA strategy
- **Risky change?** //List whether this change has an increased potential to cause bug, regressions, or controversy.//
- **QA by:** //Who should QA this task?//
- **QA in:** //Which environment? Patchdemo, beta, production...//
- **Test steps:** //Add if needed.//
=== Rollback plan
//Describe the rollback plan in production for this task if something goes wrong.//
//This task was created by Version 1.2.0 of the Reader Experience team task template using [[ https://phabulous.toolforge.org/ | phabulous ]].//
This is a tracking task to organize and gather the range of interventions we think can equip volunteers with what they need to detect and deter AI-related issues.
Where "AI-related" issues refers to both behavioral issues (e.g. [sealioning](https://en.wikipedia.org/wiki/Sealioning), [stonewalling](https://en.wikipedia.org/wiki/Stonewalling), etc.) and content issues (e.g. hallucinated references, non-neutral POV, etc.).
**Steps to replicate the issue** (include links if applicable):
*Enable mobile site
* Visit https://en.wikipedia.beta.wmcloud.org/wiki/Special:ReadingLists/Jdlrobson/collections
* Click "desktop view"
**What happens?**:
I see the page that is intended for mobile view in Vector 2022 as well as dropdown
{F108572848}
**What should have happened instead?**:
Ideally we would have a responsive experience rather than two separate experiences here.
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
**Other information** (browser name/version, screenshots, etc.):
One of the outcomes of {T437414} is an updated `postEdit` hook that exposes revision ID (of the edit that was published) and the editing interface that was used.
Currently, when a mentee asks their mentor that is not counted in any experiment using editSaved to send `edit_saved` events. If "Ask your mentor a question" integrates the new `postEdit` hook, then those questions (edits published on mentor's talk page) //will// be included in editSaved tracking.
This will enable us to count those interactions in **Average contributor engagement count**.
## Implementation notes
May need to rely on `fireHookOnPageReload` if the hook fires too close to a page reload (if there is one), because we know there's some event loss with events sent too close to a navigation change.
## AC
[ ] When a question is posted on a mentor's talk page via the "Ask your mentor a question" button on Homepage (soon to be Home page), a `postEdit` hook fires with the revision ID of the published question and identifying itself as `ask_a_mentor` (for example)
If the maintainers of a tool opt out (`defaults.alerts.notify: false`) while an alert of the tool is firing, they still get the "resolved" email when the alert stops firing.
Arguably, this might be what some users expect: receiving the "resolved" emails for alerts they were already notified about, but no new email for alerts firing in the future.
**Issue:**
Currently, the ja and ar sample semantic search cards do not have a highlighted sentence.
{F108571527}
Since those are examples of what a good result looks like for this feature, it is important that we show the highlight.
Due to time constraints, we decided not to have the highlight in the upcoming experiment (see thread: https://wikimedia.slack.com/archives/C0BB6A2NS6A/p1792006742030009). This ticket is a reminder to update that in the following experiment, as per the same thread.
The old URL will at some point stop working for non-full-res pix
See https://phabricator.wikimedia.org/T436620
We will also have to update the CSP for donor portal, transitionally adding thumb.wm.o to the clauses that have upload.wm.o , then later removing upload
With the deluge of security reports the #product_safety_and_integrity now receives, and the routine triaging that the #security-team performs at least once each week during our clinic, we should have a better way to track issue triaging and monitoring assignments, as #security-team members are often not //directly assigned// security tasks but are still responsible for them in certain ways. The standard for tracking other work in this way has typically been to create user- boards, so let's do that for member of the #security-team. And maybe standardize on a "clinic" column or something.
# @sbassett - #user-sbassett - {icon check-circle color=green} **done**
# @reedy - #user-reedy - {icon check-circle color=green} **done**
# @mstyles - #user-mstyles - {icon exclamation-triangle color=yellow} **in progress**
# @mmartorana - #user-mmartorana- {icon exclamation-triangle color=yellow} **in progress**
# @rscout - #user-rscout - {icon exclamation-triangle color=yellow} **in progress**
# @aranyap - #user-aranyap - {icon exclamation-triangle color=yellow} **in progress**
# @catrope - #user-catrope - {icon exclamation-triangle color=yellow} **in progress**
# @asanford-wmf - #user-asanford - {icon exclamation-triangle color=yellow} **in progress**
We might just need to add these to the phpdoc comment
Civi\WMFQueueMessage\DonationMessage
audit_file_gateway
checksum
contact_hash
contact_id
contribution_id
employer_id
exchange_rate
frequency_unit
gateway_session_id
invoice_id
original_fee_amount
original_net_amount
original_total_amount
payment_service_id
pending_id
response
settled_gross
sms_opt_in
url_country
user_ip
utm_key
utm_source
Civi\WMFQueueMessage\DonationModifyMessage
can_retry
contribution_status_id:name
gross_currency
is_suspected_fraud
reason
Civi\WMFQueueMessage\RecurDonationMessage
audit_file_gateway
billing_email
cancel_date
cancel_reason
checksum
contact_hash
contact_id
contribution_id
contribution_status_id:name
create_date
damaged_id
_deadlock_retried
employer_id
exchange_rate
failure_retry_date
financial_type_id
fiscal_number
frequency_interval
frequency_unit
gateway_session_id
gross_currency
invoice_id
is_autorescue
is_successful_autorescue
original_fee_amount
original_net_amount
original_total_amount
payment_instrument_id
payment_processor_id
payment_service_id
payment_token_id
pending_id
processor_contact_id
rescue_reference
response
restrictions
settled_gross
sms_opt_in
start_date
supplemental_address_1
txn_type
url_country
user_ip
utm_key
utm_source
Civi\WMFQueueMessage\RecurringModifyMessage
amount
campaign
cancel_reason
checksum
contact_id
contribution_recur_id
currency
duration
is_from_save_flow
medium
next_sched_contribution_date
source
source_enqueued_time
source_host
source_name
source_run_id
source_type
source_version
txn_type
Civi\WMFQueueMessage\RefundMessage
amount
backend_processor
backend_processor_parent_id
backend_processor_refund_id
currency
date
gateway
gateway_refund_id
gross
gross_currency
order_id
original_currency
original_fee_amount
original_net_amount
original_total_amount
payment_method
payment_service_refund_id
raw_status
reason
settled_currency
settled_date
settled_fee_amount
settled_net_amount
settled_total_amount
source_enqueued_time
source_host
source_name
source_run_id
source_type
source_version
status
WikiTexVC renders the TeX tie `~` as `<mspace width="0.5em">`.
@Jacobolus listed it as far too wide on [[https://en.wikipedia.org/w/index.php?diff=1368777449 | MathFormattingBugs]] (row `x~y`, added 2026-08-11).
Rendering on master: {F108568853}
In native and mathjax, `x~y` is visibly wider than `x\ y`. In mathml (server SVG) they look the same.
* Now `~` is 0.5 em (8 px at 16 px font size), but the row asks for a medium space of "3 or 4 math units", like `\:` in LaTeX. One math unit is 1/18 em, so that is 0.17 or 0.22 em (2.7 or 3.6 px).
* The 0.5em came with I33a751eb5ae62a45c7bc3941ff49f30fa436b00c ("Fix tilde spacing", T315978). That change fixed the escaping of the no-break space and gave no reason for the width.
* MathJax 4.1.0 renders `~` as `<mtext>` with a no-break space: [[https://archive.softwareheritage.org/swh:1:cnt:0dc9c1b9d75e51da3f0b700e6e3286b5f8072d72;origin=https://github.com/mathjax/MathJax-src;anchor=swh:1:rev:60ed165d2305b078e3d0fdaefa95366fde844cff;path=/ts/input/tex/base/BaseMethods.ts;lines=171-174 | BaseMethods.ts, Tilde]].
* WikiTexVC renders the control space `\ ` as `<mtext> </mtext>` (`Literal::toMMLTree()`). Only `~` gets the fixed 0.5em mspace.
* In the client-side SVG font, the no-break space is 0.332 em (5.3 px). That is narrower than now but still wider than the row asks for. It matches MathJax and `\ `.
* 45,829 of the 4,176,968 distinct inputs of all wikis (1.10 %) contain an unescaped `~` ([[https://doi.org/10.5281/zenodo.23394019 | 10.5281/zenodo.23394019]], `wmf_texvc_inputs.json`).
* mhchem adds `~` on its own: `MhchemTexify` writes a space between two entities as `~` (`entitySkip`). For example, `\ce{Ar^{0} \to Ar^{+1}}` gets a `~` before `\to`. 7,024 of the 61,589 `\ce` inputs in the same dataset (11.4 %) get such a `~` without containing one, so each of these gaps shrinks too.
follow up to {T439515}
Since the operator does not seem to cost much resources, I'd argue it would be useful to run it on production too, just so we work with the most important metrics. Ideally the reports really wouldn't differ, but if they would, it would be good to know.
On local it will be useful to test interacting with the report objects.
{F108569489}
PRs:
- [] https://github.com/wbstack/charts/pull/232
==== Error ====
* mwversion: 1.47.0-wmf.24
* timestamp: 2026-10-15T14:50:33.246Z
* phpversion: `8.3.35`
* reqId: `dc77d0ee-d523-41e6-8723-7434894fd6a3`
* [[ https://logstash.wikimedia.org/app/dashboards#/view/AXFV7JE83bOlOASGccsT?_g=(time:(from:'2026-10-14T14:50:33.246Z',to:'2026-10-15T15:04:55.865Z'))&_a=(query:(query_string:(query:'reqId:%22dc77d0ee-d523-41e6-8723-7434894fd6a3%22'))) | Find reqId in Logstash ]]
```name=normalized_message,lines=10
[{reqId}] {exception_url} RuntimeException: Broken variant table: sh-cyrl,sh-latn
```
| Frame | Location | Call
| -- | -- | --
| from | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Language/LanguageConverter.php#678 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Language/LanguageConverter.php(678) ]] |
| #0 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Language/Converters/ShConverter.php#121 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Language/Converters/ShConverter.php(121) ]] | MediaWiki\Language\LanguageConverter->translateWithoutRomanNumbers(string, string)
| #1 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Language/LanguageConverter.php#752 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Language/LanguageConverter.php(752) ]] | MediaWiki\Language\Converters\ShConverter->translate(string, string)
| #2 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/OutputTransform/Stages/ParsoidLanguageConverter.php#216 | /srv/mediawiki/php-1.47.0-wmf.24/includes/OutputTransform/Stages/ParsoidLanguageConverter.php(216) ]] | MediaWiki\Language\LanguageConverter->convertSplitTitle(MediaWiki\Title\Title, string)
| #3 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/OutputTransform/OutputTransformPipeline.php#79 | /srv/mediawiki/php-1.47.0-wmf.24/includes/OutputTransform/OutputTransformPipeline.php(79) ]] | MediaWiki\OutputTransform\Stages\ParsoidLanguageConverter->transform(MediaWiki\Parser\ParserOutput, MediaWiki\Parser\ParserOptions, array)
| #4 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Parser/ParserOutput.php#456 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Parser/ParserOutput.php(456) ]] | MediaWiki\OutputTransform\OutputTransformPipeline->run(MediaWiki\Parser\ParserOutput, MediaWiki\Parser\ParserOptions, array)
| #5 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/FileRepo/File/LocalFile.php#2677 | /srv/mediawiki/php-1.47.0-wmf.24/includes/FileRepo/File/LocalFile.php(2677) ]] | MediaWiki\Parser\ParserOutput->runOutputPipeline(MediaWiki\Parser\ParserOptions, array)
| #6 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CommonsMetadata/+blame/refs/heads/wmf/1.47.0-wmf.24/src/DataCollector.php#268 | /srv/mediawiki/php-1.47.0-wmf.24/extensions/CommonsMetadata/src/DataCollector.php(268) ]] | MediaWiki\FileRepo\File\LocalFile->getDescriptionText(MediaWiki\Languages\LanguageEn)
| #7 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CommonsMetadata/+blame/refs/heads/wmf/1.47.0-wmf.24/src/DataCollector.php#101 | /srv/mediawiki/php-1.47.0-wmf.24/extensions/CommonsMetadata/src/DataCollector.php(101) ]] | CommonsMetadata\DataCollector->getDescriptionText(MediaWiki\FileRepo\File\LocalFile, MediaWiki\Languages\LanguageEn)
| #8 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CommonsMetadata/+blame/refs/heads/wmf/1.47.0-wmf.24/src/HookHandler.php#99 | /srv/mediawiki/php-1.47.0-wmf.24/extensions/CommonsMetadata/src/HookHandler.php(99) ]] | CommonsMetadata\DataCollector->collect(array, MediaWiki\FileRepo\File\LocalFile)
| #9 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/HookContainer/HookContainer.php#127 | /srv/mediawiki/php-1.47.0-wmf.24/includes/HookContainer/HookContainer.php(127) ]] | CommonsMetadata\HookHandler->onGetExtendedMetadata(array, MediaWiki\FileRepo\File\LocalFile, MediaWiki\Context\DerivativeContext, bool, null)
| #10 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/HookContainer/HookRunner.php#2059 | /srv/mediawiki/php-1.47.0-wmf.24/includes/HookContainer/HookRunner.php(2059) ]] | MediaWiki\HookContainer\HookContainer->run(string, array)
| #11 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Media/FormatMetadata.php#1480 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Media/FormatMetadata.php(1480) ]] | MediaWiki\HookContainer\HookRunner->onGetExtendedMetadata(array, MediaWiki\FileRepo\File\LocalFile, MediaWiki\Context\DerivativeContext, bool, null)
| #12 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Media/FormatMetadata.php#1390 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Media/FormatMetadata.php(1390) ]] | MediaWiki\Media\FormatMetadata->getExtendedMetadataFromHook(MediaWiki\FileRepo\File\LocalFile, array, null)
| #13 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/libs/ObjectCache/WANObjectCache.php#1719 | /srv/mediawiki/php-1.47.0-wmf.24/includes/libs/ObjectCache/WANObjectCache.php(1719) ]] | MediaWiki\Media\FormatMetadata->MediaWiki\Media\{closure}(bool, int, array, null, array)
| #14 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/libs/ObjectCache/WANObjectCache.php#1533 | /srv/mediawiki/php-1.47.0-wmf.24/includes/libs/ObjectCache/WANObjectCache.php(1533) ]] | Wikimedia\ObjectCache\WANObjectCache->fetchOrRegenerate(string, int, Closure, array, array)
| #15 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Media/FormatMetadata.php#1385 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Media/FormatMetadata.php(1385) ]] | Wikimedia\ObjectCache\WANObjectCache->getWithSetCallback(string, int, Closure, array)
| #16 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CommonsMetadata/+blame/refs/heads/wmf/1.47.0-wmf.24/src/Hooks/SkinAfterBottomScriptsHandler.php#34 | /srv/mediawiki/php-1.47.0-wmf.24/extensions/CommonsMetadata/src/Hooks/SkinAfterBottomScriptsHandler.php(34) ]] | MediaWiki\Media\FormatMetadata->fetchExtendedMetadata(MediaWiki\FileRepo\File\LocalFile)
| #17 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CommonsMetadata/+blame/refs/heads/wmf/1.47.0-wmf.24/src/HookHandler.php#264 | /srv/mediawiki/php-1.47.0-wmf.24/extensions/CommonsMetadata/src/HookHandler.php(264) ]] | CommonsMetadata\Hooks\SkinAfterBottomScriptsHandler->getSchemaElement(MediaWiki\Title\Title, MediaWiki\FileRepo\File\LocalFile)
| #18 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/extensions/CommonsMetadata/+blame/refs/heads/wmf/1.47.0-wmf.24/src/HookHandler.php#243 | /srv/mediawiki/php-1.47.0-wmf.24/extensions/CommonsMetadata/src/HookHandler.php(243) ]] | CommonsMetadata\HookHandler->doSkinAfterBottomScripts(MediaWiki\FileRepo\LocalRepo, CommonsMetadata\Hooks\SkinAfterBottomScriptsHandler, MediaWiki\Title\Title)
| #19 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/HookContainer/HookContainer.php#127 | /srv/mediawiki/php-1.47.0-wmf.24/includes/HookContainer/HookContainer.php(127) ]] | CommonsMetadata\HookHandler->onSkinAfterBottomScripts(MediaWiki\Skins\Vector\SkinVector22, string)
| #20 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/HookContainer/HookRunner.php#4044 | /srv/mediawiki/php-1.47.0-wmf.24/includes/HookContainer/HookRunner.php(4044) ]] | MediaWiki\HookContainer\HookContainer->run(string, array)
| #21 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Output/OutputPage.php#3930 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Output/OutputPage.php(3930) ]] | MediaWiki\HookContainer\HookRunner->onSkinAfterBottomScripts(MediaWiki\Skins\Vector\SkinVector22, string)
| #22 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Output/OutputPage.php#5102 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Output/OutputPage.php(5102) ]] | MediaWiki\Output\OutputPage->getBottomScripts()
| #23 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Skin/Skin.php#682 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Skin/Skin.php(682) ]] | MediaWiki\Output\OutputPage->tailElement(MediaWiki\Skins\Vector\SkinVector22)
| #24 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Output/OutputPage.php#3194 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Output/OutputPage.php(3194) ]] | MediaWiki\Skin\Skin->outputPageFinal(MediaWiki\Output\OutputPage)
| #25 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/Actions/ActionEntryPoint.php#162 | /srv/mediawiki/php-1.47.0-wmf.24/includes/Actions/ActionEntryPoint.php(162) ]] | MediaWiki\Output\OutputPage->output(bool)
| #26 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/includes/MediaWikiEntryPoint.php#181 | /srv/mediawiki/php-1.47.0-wmf.24/includes/MediaWikiEntryPoint.php(181) ]] | MediaWiki\Actions\ActionEntryPoint->execute()
| #27 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/mediawiki/core/+blame/refs/heads/wmf/1.47.0-wmf.24/index.php#44 | /srv/mediawiki/php-1.47.0-wmf.24/index.php(44) ]] | MediaWiki\MediaWikiEntryPoint->run()
| #28 | [[ https://gerrit.wikimedia.org/r/plugins/gitiles/operations/mediawiki-config/+blame/refs/heads/master/w/index.php#3 | /srv/mediawiki/w/index.php(3) ]] | require(string)
| #29 | {main} |
==== Notes ====
This started when group 2 wikis got promoted. 618 occurrences so far.
It causes image pages to not be rendered: https://sh.wikipedia.org/wiki/Datoteka:Otplinjac.jpg
## WMDE Analytics Request
**This task was generated using the [WMDE Analytics](https://phabricator.wikimedia.org/project/profile/5408) request form. Please use the task templates linked on our project page to create tasks for the team. Thank you!**
### Why (Context & Decision)
//What problem are you trying to solve, and what decision will this analysis inform? Briefly explain the organisational or strategic context, why this matters now, and what action will be taken based on the outcome.//
The Wikidata Integration Team needs to better understand the usage of Wikidata powered templates beyond simply how many pages they're being used on. We want to expand the approach to this particular usage of Wikidata on Wikipedia to also look at the number of edits related to these templates as well as the number of editors that are making said edits.
### What (Scope & Output)
//Describe the specific question(s), metrics, segments, or deliverables (e.g., dashboard, deep dive, experiment analysis), including any relevant definitions or constraints.//
[] SparkSQL queries that calculate the number of edits that involve Wikidata powered templates
[] SparkSQL queries that use the generated data from the above queries to derive the number of users adding and editing Wikidata powered templates
- Broken down based on new editors
- Potentially: Include activity level of Wikidata powered template usage
- Potentially: Looking into total edits in the period by users and breaking down if they're a Wikidata template user or not
[] Airflow DAG to run the above queries (potentially two)
### By When (Timing & Priority)
//Provide a clear deadline, any key milestones (e.g. launch, leadership review), and note if timing is flexible or fixed.//
DD.MM.YYYY
---
**Information below this point is filled out by the analyst.**
### Sub Tasks
//A breakdown of the steps to complete this task.//
#### Data Pipeline Creation
[] Define metric(s) to be derived from the new / updated data pipeline
[] Define output table columns with stakeholder(s)
[] Create process diagrams in query documentation to map out complex flows
[] Write job queries or code
[] Test job queries or code
[] Write Airflow DAG
[] Test and deploy Airflow DAG
[] Create Superset dashboard
#### Finishing Up
[] Required documentation is written
* The task is moved to Delivered with the stakeholder being assigned and CCed in a comment
### Data
//The tables that will be referenced in this task and the sample sizes from them that will be used.//
- link_to_table
To make it easier to take over the project/dashboard and prepare for the new Zuul CI, let's create a skill file with all the knowledge.
WIP
There’s no precedent for adoption measurement in Striker.
To confirm first with WMF Legal that what follows is aligned with the WMF Privacy Policy.
What we want to report:
* Number of weekly ("active") users and tools for a given "view" (e.g. "alerts", "logs"), aggregated per week.
* Number of "returning users" who have visited this week //and// in the past X weeks.
* More?
Two tables:
* **`UserVisit`**:
** `week`: e.g. `2026-01`
** `view`: small, fixed set of constants (`tool_main`, `alerts`, `logs`)
** `source`: how the person got to that page (`toolpage`, `email`, etc.); `other` if no data
** `user_key`: `salted_hmac("striker.adoption.user", str(user.pk), secret=settings.ADOPTION_HMAC_KEY, algorithm="sha256").hexdigest()`
* **`ToolVisit`**:
** `week`
** `view`
** `tool_key`: `salted_hmac("striker.adoption.tool", str(tool.name), secret=settings.ADOPTION_HMAC_KEY, algorithm="sha256").hexdigest()`
How long the metrics we want to measure imply retaining rows in those tables:
* weekly distinct users and tools, by source: window = one week
* "returning users" who have also visited in the past X weeks: window = X + 1 weeks
* more?
Security considerations:
- The separation in two tables that share no key reduces the possibility of correlating individuals to their tools.
- The corresponding rows are deleted (by a daily cleanup process in Striker) as soon as their aggregation window has passed.
- The `ADOPTION_HMAC_KEY` can be occasionally rotated (between full weeks, e.g. right after the last aggregation of a quarter). It would cause a dip in measured "returning users," because the previous month’s visitors will get a new `user_key`.
#### Source determination
* Links we control (from Toolsadmin or emails) should carry an `?src=…` query parameter.
* When a request comes with `?src=…`, Striker records the visit and immediately redirects to the same URL without `?src=…`, so the address bar is not polluted with it (page refreshes, bookmarks, and copy-pasted links don’t keep the original `src`).
* A request without `?src=…` counts as a new `other` visit if the browser session hasn’t recorded that view/tool combination in the last 30 minutes.
* [[ https://phabricator.wikimedia.org/P96683 | Example code (Phab paste) ]]
This task is a follow-up on https://phabricator.wikimedia.org/T438410#12434235
**(1)** `readinglists-nav-bar-links` - "All items" and "Collections" should be bolded
>>! In T438410#12434235, @Sneha wrote:
> Thanks @Etonkovidova yes both navigation items should be bolded. On beta it is bolding when the text is black but is not bolding when its blue.
On `enwiki beta` the links "All items" and "Collections" should be dsiplayed bolded
|{F108563454}| {F108563617}
**(2)** clickable areas for `readinglists-special-nav-link` should be increased
{F108563792}
**(3) **pending @sneha confirmation that those issues need to be fixed
- the last item on mobile Reading list doesn't have the horizontal line
- "Sorted by most recent: label doesn't need a dot;
- and it is placed a little too high over the first card
|[[ https://www.figma.com/design/Q3pYKI7RRMdRRgkQp2RiTf/Web--Reading-List-Collections?node-id=3332-140737&t=LPyczffndTIUjaN9-0 | figma design ]]|`enwiki beta`
|---|---|
|{F106481452}|{F108565016}
The Data Engineering / Data Platform team is building the pipelines (T434047) which read Maniphest task metadata and transactions via the Conduit API (maniphest.search, maniphest.gettasktransactions, user.search) to make Phabricator activity available in the Data Lake. We need a dedicated bot account + Conduit API token for this, rather than a personal token.
Per https://www.mediawiki.org/wiki/Phabricator/Bots :
- **Name:** devmetrics-bot
- **Purpose:** Read-only collection of public Maniphest tasks and their transactions via Conduit for the Data Engineering developer-activity pipelines (T434047). Runs as a scheduled (Airflow) job in a k8s pod.
- **Email:** devmetrics-bot@wikimedia.org
- **Responsible user / organisation:** Data Platform Engineering (ex: @Antoine_Quhen)
Notes:
- The account only needs to see **public** tasks. No elevated visibility required.
- The token will be stored as a k8s Secret via operations/deployment-charts (or its secret counterpart) (not in puppet-private) and injected as the PHABRICATOR_TOKEN env var; please hand it over via a restricted paste as usual.
- The client self-identifies with User-Agent "data-engineering-team-bot wmf-developer-activity-pipelines" and paces requests at ≥1 req/s per the Robot policy.
Already added here: https://wikitech.wikimedia.org/wiki/Phabricator/Conduit_API_Tokens
While reviewing T418562, we found out that there is a confusing bit of legacy noise "nodb". A single string param "nodb" won't have any effect on the `Factory` or the `Model` it creates
I removed it to make the codebase less confusing:
PR: https://github.com/wbstack/api/pull/1297
At the moment there is a directory for frontend, but not for backend. The root directory contains both backend files and general files (documentation, developer configs, CI settings etc.). This can make it hard to navigate.
## Acceptance criteria
1. All files related to backend are in one directory and all related to frontend are in one.
2. Any references to moved files, such as in documentation and scripts, are updated.
== Background
To kick off the migration to Pinia, we will add a basic store with limited data and actions, as defined below.
---
== Requirements
=== Technical requirements
This initial patch will focus on metadata about the currently viewed list. The following will be moved from Entries.vue into the new store:
- List title and description
- Whether info about the list is being fetched (`loadingInfo`)
- `isDefaultList` and `isAllListItems` (note that these will be removed in favor of a single ref that stores the current view in a future task)
- `fetchListInfo()` - the function that gets the metadata
- Current error message
- `handleError()` - the function that sets the error message
Any component that uses these refs/actions will be updated to get them from the store.
Note that we can discuss the shape of the store in code review (e.g. single file vs multiple files, data structure).
=== Acceptance criteria
- [] The refs and actions above have been moved to a new Pinia store
- [] Components have been updated to use the store
- [] Jest unit tests are set up to work with Pinia
=== QA strategy
- **Risky change?** The refs and actions being migrated are important but straightforward, so I'd say there's a medium risk of regressions.
- **QA by:** Engineers, QA Engineer
- **QA in:** Patchdemo during code review, beta wikipedia
- **Test steps:** Visit Special:ReadingLists, a collection page, and /collections and look for regressions
=== Communication criteria
n/a
=== Rollback plan
Revert the patch
//This task was created by Version 1.2.0 of the Reader Experience team task template using [[ https://phabulous.toolforge.org/ | phabulous ]].//
== Background
As we've added more and more to the Vue app on Special:ReadingLists as part of the custom lists project, we're reaching the limit of what we can do by maintaining state within components. The main component for the app, Entries.vue, is large and handles most fetching and state management. Getting that state into subcomponents is messy, and the function that fetches items in the currently viewed list is large and difficult to maintain.
The Reader Experience engineers agree that Pinia would help us better organize our code to improve ease of maintenance and reduce risk of regressions. Since we're mid-project, we don't want to pause for a full migration. Instead, we will add a small store at first and gradually add to it as we work on custom lists. That work will be handled in subtasks.
=== User story
As one of the many developers working on Special:ReadingLists, I want to easily find and work with the appropriate code as I'm completing feature tasks and bug fixes.
As a maintainer of the ReadingLists extension, I want updating and debugging the code to be fast and intuitive.
As a maintainer of the ReadingLists extension, I want to use standard and recommended technology used in the Wikiverse and beyond.
---
== Requirements
=== Acceptance criteria for done
[] The app on Special:ReadingLists uses Pinia for state management
[] Unit tests are updated to work with PInia
[] There are no UI/UX regressions
=== QA strategy
QA will be done in subtasks.
//This task was created by Version 1.2.0 of the Reader Experience team task template using [[ https://phabulous.toolforge.org/ | phabulous ]].//
After packaging, the functional tests are now shipped with the debian package, so there's no way to run them easily (we had a run.sh template that used the http user/pass)
MediaWiki includes a “skip link”, which only shows up when it is focused via tab, near the beginning of the document tab order; it can be used to skip past various toolbars etc. to move focus straight to the actual content. WMDE’s fundraising banners currently cover up this skip link, making it invisible to sighted keyboard users (it might still show up via screenreaders, I haven’t tested that); furthermore, if you follow the link anyway (without closing the banner), then the page will jump such that the beginning of the content is covered up by the banner. It would be good to improve this. (From a cursory look through some WMF banners, they generally seem to handle this better: following the link will scroll the banner out of view. But that might be due to a generally different banner paradigm.)
{F108555074}
This task will track the #decommission of server wikikube-worker1152.eqiad.wmnet.
With the launch of updates to the decom cookbook, the majority of these steps can be handled by the service owners directly. The DC Ops team only gets involved once the system has been fully removed from service and powered down by the decommission cookbook.
wikikube-worker1152.eqiad.wmnet
**Steps for service owner:**
[] - all system services confirmed offline from production use
[] - set all icinga checks to maint mode/disabled while reclaim/decommmission takes place. (likely done by script)
[] - remove system from all lvs/pybal active configuration
[] - any service group puppet/hiera/dsh config removed
[] - login to cumin host and run the decom cookbook: cookbook sre.hosts.decommission <host fqdn> -t <phab task>. This does: bootloader wipe, host power down, netbox update to decommissioning status, puppet node clean, puppet node deactivate, debmonitor removal, and run homer.
[] - remove all remaining puppet references and all host entries in the puppet repo
[] - reassign task from service owner to no owner and ensure the site project (ops-sitename depending on site of server) is assigned.
**End service owner steps / Begin DC-Ops team steps:**
[] - system disks removed (by onsite)
[] - determine system age, under 5 years are reclaimed to spare, over 5 years are decommissioned.
[] - IF DECOM: system unracked and decommissioned (by onsite), update netbox with result and set state to offline
[] - IF DECOM: mgmt dns entries removed.
[] - IF RECLAIM: set netbox state to 'inventory' and hostname to asset tag
Create helpers that REST handlers can use to easily and efficiently run paginated database queries, including generating cursors for the next (and previous) page, and reading that cursor back in for the next query.
Create helpers that REST handlers can use to easily and consistently generate a pagination envelope (and the appropriate schema for that envelope). The decision on the exact shape of the envelope is T440445, but work on the helpers is not blocked in that.
This ticket tracks several pieces needed to make it easy for endpoint implementations (handlers) to support pagination.
Update the ML services chart so that it checks and ensures that each service has gpu affinity rules
**Steps to replicate the issue** (include links if applicable):
* I accidentally uploaded invalid yaml to `profile::kubernetes::deployment_server::deploy_service::service_catalog`
* one time I messed up indentation https://gerrit.wikimedia.org/r/c/operations/puppet/+/1355542
* another time I used a non-existing stage: https://gerrit.wikimedia.org/r/c/operations/puppet/+/1355531
* Visit https://spiderpig.wikimedia.org/service/deploy
* Select the service you want to deploy
**What happens?**:
* Instead of selecting a service to deploy, an error message is displayed in the dropdown menu
**What should have happened instead?**:
* The error message should be shown but deployments should still be possible
* Maybe it's possible to validate the yaml and use an older version if the new one is invalid?
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
**Other information** (browser name/version, screenshots, etc.):
Error messages visible in scap:
{F108547999}
{F108547998}
thanks also to @brouberol reporting this issue
**Steps to replicate the issue** (include links if applicable):
* Add a non-wikikube service like airflow with the `dse-k8s` `cluster_group` to the `deploy_service:.service_catalog`, see [hiera](https://gerrit.wikimedia.org/r/plugins/gitiles/operations/puppet/+/refs/heads/production/hieradata/role/common/deployment_server/kubernetes.yaml#647)
* Use https://spiderpig.wikimedia.org/service/deploy and choose "airflow"
* Click "Deploy service"
**What happens?**:
* The jobs fails with
```
FileNotFoundError: [Errno 2] No such file or directory: '/srv/deployment-charts/helmfile.d/services/airflow-test-k8s'
10:49:45 deploy-service failed: <FileNotFoundError> [Errno 2] No such file or directory: '/srv/deployment-charts/helmfile.d/services/airflow-test-k8s' (scap version: 4.298.0) (duration: 00m 00s)
```
* see error log: https://spiderpig.wikimedia.org/jobs/3007
**What should have happened instead?**:
* The deployment should use the helmfile in `/srv/deployment-charts/helmfile.d/dse-k8s-services/airflow-test-k8s` and not from /srv/deployment-charts/helmfile.d/**services**.
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
**Other information** (browser name/version, screenshots, etc.):
Today we tried to switch some partners who are part of the Bundle to Unavailable in /admin. This resulted in an internal server error.
**Steps to replicate the issue** (include links if applicable):
* Log in to an existing account on the English Wikipedia that did not have the CodeMirror syntax highlighter enabled yesterday
* Edit a section of a page
*
**What happens?**:
* Observe that the CodeMirror syntax highlighter is enabled
**Additional verification of issue**
* Go to Preferences - Editing and observe that "Enable syntax highlighting for wikitext" is selected, even though the editor did not select it.
**What should have happened instead?**:
* The CodeMirror syntax highlighter should not be enabled for existing editors who have not selected it in their Preferences.
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
**Other information** (browser name/version, screenshots, etc.):
This issue is new as of 15 October 2026 on the English Wikipedia.
**Steps to replicate the issue** (include links if applicable):
* Go to https://en.wikipedia.org/w/index.php?title=Template:Korea_Wikimedia_Association/Desktop_menu/styles.css&oldid=1285273319
* Click on Page information
* See that there is a "missing end tag" Linter error
* Look at line 56 to see that the only div tag on the page is in an HTML comment (/* <div class="dropdown"> ...)
**What happens?**:
**What should have happened instead?**:
No Linter error should be reported on this page.
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
**Other information** (browser name/version, screenshots, etc.):
This Linter error appeared on 15 October 2026. There were no Linter errors in Template space on the English Wikipedia yesterday.
Some results from our investigation seems to be wrong.
Q981894 has 122 statements https://www.wikidata.org/w/index.php?title=Q981894&action=info but we see a log line complaining about 418 usages being bundled:
> Wikibase INFO: Exceeded entity usage aspect bundling for aspect C {"count":418,"aspect":"C","entity_id":"Q981894","wiki":"eswiki"}
https://es.wikipedia.org/w/index.php?curid=7524658
Major suspicion is that we aren't counting the usages correctly.
The patch to look at: https://gerrit.wikimedia.org/r/c/mediawiki/extensions/Wikibase/+/1352357
- Might be hard to produce locally
- More research needed for further refinement
- Timebox: 4 days
## Description
# Go to https://www.wikifunctions.org/view/en/Z10004
# Click on "Details"
# get fresh results button is rendered: it shouldn't
{F108537352}
---
## Completion checklist
* [ ] Before closing this task, review one by one the checklist available here: https://www.mediawiki.org/wiki/Abstract_Wikipedia_team/Definition_of_Done#Front-end_Task/Bug_Completion_Checklist
**Feature summary**
User should have a list of own thanks available, meaning including an edit revision it was given for.
**Use case(s) and Benefits**
Thanks giver could revisit a list of given thanks edits (like thanks recipient can already review related edits in the notifications obtained).
E.g. user who was not aware of Favorites Commons feature (gadget) and just discovered it, could start making the list based on history of own thanks for uploads.
To ease debugging of metricsinfra alertmanager from prod we should deploy amtool configuration:
* `/etc/prometheus/amtool-metricsinfra-http.yml` contains user/password for basic auth
* a `amtool-metricsinfra` wrapper that calls `amtool --alertmanager.url https://metricsinfra-alertmanager-rw.wmcloud.org --http.config.file /etc/prometheus/amtool-metricsinfra-http.yml`
This way we can `amtool-metricsinfra` to interact with alertmanager metricsinfra the same way we do with `amtool` for alertmanager prod
Since I'm going on sabbatical, let's make it easier for the rest of the team to maintain the performance servers/tests if something happens.
Acceptance criteria:
* Setup a skill and reference files that holds the knowledge of the synthetic tests and servers
- The name of your repository: https://gitlab.wikimedia.org/repos/product-safety-and-integrity/wmf-security-skills
- The purpose of your repository: Claude Code / AI skills for PSI / Security usage
- The username(s) of the owner(s) and maintainer(s) of your repository: @kostajh @ASanford-WMF @sbassett
- Phabricator project where administrators should report any tasks related to your repository: n/a
## Please check the box to agree and acknowledge the following:
- [x] All owners and maintainers have GitLab 2fa enabled and are using strong passwords
- [x] Private repositories are only for restricted information, not confidential information
- [x] Accept the risks associated with private repositories, e.g.:
- Configuration changes – Any repository owner may change the visibility of your repository
- Forks – Anyone with the ability to fork your repo may change settings on their fork and expose information
- Forge vulnerabilities – GitLab may have an unknown vulnerability that may leak information contained within or metadata about this repository
This task will track the #decommission of server clouddb1013.eqiad.wmnet
With the launch of updates to the decom cookbook, the majority of these steps can be handled by the service owners directly. The DC Ops team only gets involved once the system has been fully removed from service and powered down by the decommission cookbook.
clouddb1013
**Steps for service owner:**
[] - all system services confirmed offline from production use
[x] - set all icinga checks to maint mode/disabled while reclaim/decommmission takes place. (likely done by script)
[x] - remove system from all lvs/pybal active configuration
[] - any service group puppet/hiera/dsh config removed
[] - login to cumin host and run the decom cookbook: cookbook sre.hosts.decommission <host fqdn> -t <phab task>. This does: bootloader wipe, host power down, netbox update to decommissioning status, puppet node clean, puppet node deactivate, debmonitor removal, and run homer.
[] - remove all remaining puppet references and all host entries in the puppet repo
[] - reassign task from service owner to no owner and ensure the site project (ops-sitename depending on site of server) is assigned.
**End service owner steps / Begin DC-Ops team steps:**
[] - system disks removed (by onsite)
[] - determine system age, under 5 years are reclaimed to spare, over 5 years are decommissioned.
[] - IF DECOM: system unracked and decommissioned (by onsite), update netbox with result and set state to offline
[] - IF DECOM: mgmt dns entries removed.
[] - IF RECLAIM: set netbox state to 'inventory' and hostname to asset tag
The return type of `OpenIDConnect::getClaim` is set to `?string`; however, the two methods that are being called in that method (`OpenIDConnectClient::getVerifiedClaims` and `OpenIDConnectClient::requestUserInfo`) both return more than just strings and nulls. (As the OIDC spec has multiple claims
Now, normally, this //shouldn't// be an issue (I think), as all claims/attributes being retrieved by `getClaim` should be strings (or null). So you could definitely make the argument that typing it as `?string` is 'good enough'.
However, if you are dealing with a OpenID Provider which does not follow the specification, this typing does becomes problematic. For example, my institution's OP sometimes returns a list of e-mails instead of a single string when querying the user info endpoint.
Ideally, my institution would follow the OIDC spec, but sadly I've been told that 'this is intended behavior'. So, I have to fix that mess on my side.
Now, I can easily write an email-processor callable which handles this edge-case, but the typing of `getClaim` results in an error before the email processor is even called. Removing the return-value typing of `getClaim` does work fine as a workaround. However, this requires us to manually patch the plugin code every update.
Seeing as //technically// `getClaim` should be able to return more than just strings, I believe I could be helped immensely if the return-typing would be relaxed. Alternatively, moving the emailProcessor call to `getClaim` would also fix my problem, but personally I wouldn't call that the 'cleanest' of solutions.
I fully admit that my problems stem from an out-of-spec provider, so I would be fine with this issue being closed as a non-issue (for this plugin). That would strengthen my case to my instition's identity-management team...
This task will track the #decommission of server db1156.eqiad.wmnet
With the launch of updates to the decom cookbook, the majority of these steps can be handled by the service owners directly. The DC Ops team only gets involved once the system has been fully removed from service and powered down by the decommission cookbook.
db1156
**Steps for service owner:**
[] - all system services confirmed offline from production use
[] - set all icinga checks to maint mode/disabled while reclaim/decommmission takes place. (likely done by script)
[] - remove system from all lvs/pybal active configuration
[] - any service group puppet/hiera/dsh config removed
[] - login to cumin host and run the decom cookbook: cookbook sre.hosts.decommission <host fqdn> -t <phab task>. This does: bootloader wipe, host power down, netbox update to decommissioning status, puppet node clean, puppet node deactivate, debmonitor removal, and run homer.
[] - remove all remaining puppet references and all host entries in the puppet repo
[] - reassign task from service owner to no owner and ensure the site project (ops-sitename depending on site of server) is assigned.
**End service owner steps / Begin DC-Ops team steps:**
[] - system disks removed (by onsite)
[] - determine system age, under 5 years are reclaimed to spare, over 5 years are decommissioned.
[] - IF DECOM: system unracked and decommissioned (by onsite), update netbox with result and set state to offline
[] - IF DECOM: mgmt dns entries removed.
[] - IF RECLAIM: set netbox state to 'inventory' and hostname to asset tag
The LDAP server used by Striker is getting an upgrade, see parent task: {T331699}.
We should make sure this does not break the Striker LDAP integration.
The [fundraising-banners](https://github.com/wmde/fundraising-banners/) development environment is somewhat annoying to work with due to three combined issues:
1. Building / compiling a banner is somewhat slow; building all channels more so.
2. On startup, every banner has to be built before the dev enviroment can be shown; this is slow due to 1.
3. When switching branches (or rebasing), the dev server often crashes and it’s necessary to fully restart it, which is slow due to 1 and 2.
It would be good if we could find ways to improve this. (This task represents an action item from the 2026-10-15 retrospective.) Some initial thoughts:
* The build used in the dev environment seems to be very similar to the build we actually deploy on wiki; it seems to be quite “heavyweight”, with lots of transformations happening. Can we use a simpler, lighter build for the dev environment, and reserve the expensive transpiling for the production build?
* Instead of building all the banners upfront, can we rearrange the dev environment so it only displays the configured banner channels (without building them), and then just builds the one banner you asked for when you open it?
The `download_ntriples_scholarly_articles` step in [[ https://airflow-wikidata.wikimedia.org/dags/wdqs_wikidata_data_reload/grid?tab=logs&task_id=download_ntriples_scholarly_articles&dag_run_id=manual__2026-10-13T20%3A43%3A30.250330%2B00%3A00 | the latest run ]] fails with the following error:
```
The Pod has an Event: Multi-Attach error for volume "pvc-b44d419f-21d5-477f-90df-a05e27b781db" Volume is already used by pod(s) download-ntriples-wikidata-main-4mgak43 from None
```
Before this run we dropped the usage of TopoLVM for the temp storage, in favor of network storage.
While network storage (`ceph-csi-rdb`) does support mounting from multiple pods, they need to be on the same node. This is similar to TopoLVM. However, since dropping TopoLVM, means dropping the node-affinity, the pods might run on different nodes.
Thus, the easiest solution would be to use separate temp PVCs for the `main` and `scholarly` indexes.
Alternatively we can use `topolvm-balanced` which is supported by more nodes.
**Steps to replicate the issue** (include links if applicable):
v2 bug: ?x rdfs:label ?l FILTER(LANG(?l) = "en") sometimes returns another language’s label tagged as English. For Q588351, v2 gave “boardercross” (the French label) as English, and the same query returned the right value minutes earlier.
**What happens?**:
Wrong language label returned, occasionally.
**What should have happened instead?**:
Correct language label, all the time.
Hello, we have had some cases recently where Community Growth staff needed to understand contribution and editor numbers across wikis/languages, split by country over time. Naturally the `wmf.geoeditors_monthly` and `wmf.geoeditors_edits_monthly` tables are a good fit for this analysis. On these two tables, we have a column dedicated to each of the metrics for the two tables for `_namespace_zero` editors and edits. While this is appropriate for most wikis, for Commons this isn't particularly meaningful. I was wondering if it would be worthwhile to have a column on these tables for "namespace -2" edits/editors (i.e. the one for Media namespace, which I understand would be more 'meaningful' for Commons)? Is there perhaps a reason why that wasn't originally done, i.e. would we say that for Commons its not misleading to just reference the overall figure, regardless of namespace being edited? Note: I am open to not changing anything on these table, I am mostly wondering if this warrants further consideration.
CloudVirtDown page runbook is https://wikitech.wikimedia.org/wiki/Portal:Cloud_VPS/Admin/Runbooks/NodeDown which redirects to https://wikitech.wikimedia.org/wiki/Portal:Cloud_VPS/Admin/Runbooks/NodeDownForLong
The wikitech page suggests using the drain cookbook, however it requires the host to be up for drain to work (discovered in T375223)
This task tracks improving the runbook and cookbook to handle the hardware failure case, i.e. evacuate the host of all VMs from nova and make sure the old VMs don't come back when the cloudvirt comes back online
##Feature summary
VisualEditor should create content-based reference names even if a reference contains multiple templates or a (citation) template and plain text.
##Use cases
While references like `<ref>{{Cite journal |last=name...}}</ref>` will create a content-based name (if configured), the same reference is treated as a basic reference with a fallback name like `"Reference-1"` if the reference contains additional content, e.g. `<ref>{{Cite journal |last=name...}} some comment</ref>` or `<ref>{{Cite journal |last=name...}} {{Retracted}}</ref>`.
##Solution
Always check the first template within a reference to see if some autoname configuration can be applied to generate a content-based name.
##Edge cases not covered by this approach
We won't do additional API calls to check if any other templates within the reference could be used for content-based ref name creation. Something like `<ref>{{Retracted}} {{Cite journal |last=name...}}</ref>` would likely still result in a fallback name given that `{{Retracted}}` probably won't included template parameters that are configured to be used for auto ref names. Most references should be covered by the solution above considering that the citation template is usually the first template used within references.
It looks like something has changed in the new Speechoid version (0.2.0) which means the lexicons can't sync. When you enter any word you get the error message about lexicons being out of sync. If you press the sync button it fails with the following:
```lines=10
[baecd018d6d995396ef2b1dc] /wiki/Special:EditLexicon MediaWiki\Wikispeech\SpeechoidConnectorException: Multiple lexicon matches language[
{
"components": [
{
"call": "tokenise",
"module": "tokeniser"
}
],
"config_file": "wikispeech_server/conf/voice_config_basic.json",
"lang": "sv",
"name": "basic_sv"
},
{
"components": [
{
"call": "textproc",
"mapper": {
"from": "sv-se_ws-sampa-braxen",
"to": "sv-se_matcha_ipa_from_ws"
},
"module": "adapters.textproc_adapter",
"name": "sv_se_1"
},
{
"call": "lexLookup",
"lexicon": "sv_se_braxen_lex:sv-se.braxen",
"module": "adapters.lexicon_client"
}
],
"config_file": "wikispeech_server/conf/voice_config_piper_mvp2.json",
"default": true,
"lang": "sv",
"name": "piper_textproc_sv"
},
{
"components": [
{
"call": "textproc",
"mapper": {
"from": "sv-se_ws-sampa-braxen",
"to": "sv-se_matcha_ipa_from_ws"
},
"module": "adapters.textproc_adapter",
"name": "sv_se_1"
},
{
"call": "lexLookup",
"lexicon": "sv_se_braxen_lex:sv-se.braxen",
"module": "adapters.lexicon_client"
}
],
"config_file": "wikispeech_server/conf/voice_config_matcha_mvp2.json",
"default": false,
"lang": "sv",
"name": "matcha_textproc_sv"
}
]
Backtrace:
from /var/www/html/w/extensions/Wikispeech/includes/SpeechoidConnector.php(372)
#0 /var/www/html/w/extensions/Wikispeech/includes/Lexicon/LexiconSpeechoidStorage.php(62): MediaWiki\Wikispeech\SpeechoidConnector->findLexiconByLanguage()
#1 /var/www/html/w/extensions/Wikispeech/includes/Lexicon/LexiconSpeechoidStorage.php(91): MediaWiki\Wikispeech\Lexicon\LexiconSpeechoidStorage->findLexiconNameByLanguage()
#2 /var/www/html/w/extensions/Wikispeech/includes/Lexicon/LexiconHandler.php(168): MediaWiki\Wikispeech\Lexicon\LexiconSpeechoidStorage->getEntry()
#3 /var/www/html/w/extensions/Wikispeech/includes/Lexicon/ConfiguredLexiconStorage.php(141): MediaWiki\Wikispeech\Lexicon\LexiconHandler->syncEntryItem()
#4 /var/www/html/w/extensions/Wikispeech/includes/Specials/SpecialEditLexicon.php(252): MediaWiki\Wikispeech\Lexicon\ConfiguredLexiconStorage->syncEntryItem()
#5 /var/www/html/w/includes/HTMLForm/HTMLForm.php(833): MediaWiki\Wikispeech\Specials\SpecialEditLexicon->syncSubmit()
#6 /var/www/html/w/includes/HTMLForm/HTMLForm.php(682): MediaWiki\HTMLForm\HTMLForm->trySubmit()
#7 /var/www/html/w/includes/HTMLForm/HTMLForm.php(730): MediaWiki\HTMLForm\HTMLForm->tryAuthorizedSubmit()
#8 /var/www/html/w/extensions/Wikispeech/includes/Specials/SpecialEditLexicon.php(146): MediaWiki\HTMLForm\HTMLForm->show()
#9 /var/www/html/w/includes/SpecialPage/SpecialPage.php(727): MediaWiki\Wikispeech\Specials\SpecialEditLexicon->execute()
#10 /var/www/html/w/includes/SpecialPage/SpecialPageFactory.php(1727): MediaWiki\SpecialPage\SpecialPage->run()
#11 /var/www/html/w/includes/Actions/ActionEntryPoint.php(505): MediaWiki\SpecialPage\SpecialPageFactory->executePath()
#12 /var/www/html/w/includes/Actions/ActionEntryPoint.php(145): MediaWiki\Actions\ActionEntryPoint->performRequest()
#13 /var/www/html/w/includes/MediaWikiEntryPoint.php(180): MediaWiki\Actions\ActionEntryPoint->execute()
#14 /var/www/html/w/index.php(44): MediaWiki\MediaWikiEntryPoint->run()
#15 {main}
```
Me and @Volans are going through cloud pages and runbooks, as part of that work I looked at ToolforgeKubernetesNodeNotReady and its history.
As far as I can tell the page was moved from toolschecker and has a fixed threshold of five nodes not ready, given that we have higher level page ToolforgeWebHighErrorRate I am for:
* move ToolforgeKubernetesNodeNotReady to be percent-based and exclude cordoned nodes from the count
* set it as `critical` instead of `page`, during an incident if too many nodes are not ready it will show up in the alerts dashboard anyways
* ditch the `absent()` alert since pint will catch the failure of the metric not being there
The `TitleBlacklist` logging channel has been enabled at `INFO` level by @Krinkle with https://gerrit.wikimedia.org/r/c/operations/mediawiki-config/+/1354557 (linked to T85428).
Since the logging bucket has been enabled, the logging system receives 40-50k messages per minutes **on top** of the usual 20k/minutes baseline and I guess it might put pressure on the logging storage system?
Example of redacted messages:
```
INFO: AntiSpoof could not normalize "<XXXXX>" Usernames cannot contain characters from different writing systems.
INFO: AntiSpoof could not normalize "<XXXX>" Usernames cannot contain the character "<YYYYY>" because it is an unknown character.
```
I note the message might need to converted to use a template message with placeholder and pass the values as context variables.
The [[ https://datahub.wikimedia.org/dataset/urn:li:dataset:(urn:li:dataPlatform:hive,wmf_traffic.webrequest_v2,PROD)/Columns?highlightedPath=&is_lineage_mode=false&schemaFilter= | webrequest_v2 ]] table is a smaller, faster and easier to maintain refactor of [[ https://datahub.wikimedia.org/dataset/urn:li:dataset:(urn:li:dataPlatform:hive,wmf.webrequest,PROD)/Columns?is_lineage_mode=false | webrequest ]].
It is also the main output table for the [[ https://wikitech.wikimedia.org/wiki/KAPOW | KAPOW ]] bot detection system.
In principle, all current uses of webrequest should migrate to either v2, or some other intermediate data product derived from it. As I write this, we are not doing a big push for this migration yet, but we have heard initial feedback from early adopters that we want to organize.
Each child ticket tracks the migration of a distinct table or pipeline, and //their// children track the blockers we're encountering along the way, so we can prioritize the blockers with higher leverage.
This ticket is done when:
- There are no more direct uses of webrequest (other than v2 itself), or
- All remaining direct uses are approved exceptions with a known migration date
We currently use [stylelint-webpack-plugin](https://github.com/webpack/stylelint-webpack-plugin) in the banners repo, but its README advises that it was merged into [lint-webpack-plugin](https://github.com/webpack/lint-webpack-plugin) (see [migration instructions](https://github.com/webpack/stylelint-webpack-plugin#migrating-to-lint-webpack-plugin)). We should probably migrate sooner or later.
This ticket collects the issues blocking the migration of the [[ https://datahub.wikimedia.org/dataset/urn:li:dataset:(urn:li:dataPlatform:hive,discovery.webrequest_metrics,PROD)/Columns?highlightedPath&is_lineage_mode=false&schemaFilter= | discovery.webrequest_metrics ]] pipeline to [[ https://datahub.wikimedia.org/dataset/urn:li:dataset:(urn:li:dataPlatform:hive,wmf_traffic.webrequest_v2,PROD)/Columns?highlightedPath&is_lineage_mode=false&schemaFilter= | webrequest_v2 ]].
The Search team uses that table in a [[ https://superset.wikimedia.org/superset/dashboard/search/?native_filters_key=p8AvpYN1ZqhOtPvTH9JmqciWmaRLKBR-1x8FJO-yN98Ovu4UgFKB-kZXRRhaZ7QO | dashboard ]] to track the fraction of pageviews that came through search ([[ https://wikimedia.slack.com/archives/CLKDS4MG9/p1791898567065449 | Slack thread ]]).
By migrating to webrequest_v2, they hope to take advantage of KAPOW scores for a more reliable pageviews metric. Unfortunately they can't switch to other pageviews data products, because they have specific requests that they need to filter for the dashboard.
When the child tickets are resolved, Search should be able to adapt their pipeline to run on webrequest_v2 instead of webrequest.
= Summary =
FactDiff is a planned Toolforge tool. It finds facts that different language editions of the same Wikipedia article state with **different dates or numbers**. It presents them as a worklist that editors can act on: for each conflict it shows both sentences, their citations and edit links to both wikis. It runs on open-weight LLMs hosted by WMF on LiftWing (Project Hummingbird).
NOTE: This is a work in progress. The design is not final, and I'm posting early to get feedback before release.
= Problem =
Language editions are written independently, so facts drift apart, and usually at least one edition is wrong, out of date or using a different definition. Some examples from early test runs (October 2026):
| Article | Fact | Values found |
| ------- | ---- | ------------ |
| Danube | Length | 2,850 km (en), 2,857 km (de), 2,888 km (es) |
| Eiffel Tower | Height of the top floor | 276 m (en), 279.11 m (fr), 300 m (es) |
| Golden Gate Bridge | End of construction | 19 April 1937 (en), 26 May 1937 (fr) |
Today these are found only when someone happens to read two editions side by side. Readers of the wrong edition never find out, and no editor-facing tool turns them into fixable tasks.
= Proposed solution =
You enter an article (or a category, for a batch worklist) on your home wiki and the languages to compare with. FactDiff lists each conflict with:
- the fact and the value each edition gives
- both sentences, each with its citations or an "uncited" marker, to help judge which edition is right
- "edit section" links on both wikis
Results can be exported as a wikitable to paste on a WikiProject page, or as CSV.
**Tech flow (current plan):**
- Read each edition's Parsoid HTML and split it into sentences and infobox rows that contain numbers. Digits in any script are normalised (Devanagari, Bengali, Arabic-Indic, …).
- Pair sentences across languages using the Wikidata items they link to, which act as language-neutral anchors. The lead and infobox are always compared as a whole.
- Ask an open-weight LLM on LiftWing (`llm-qwen36-27b`) to list facts that both editions state with conflicting values.
- Post-check: drop any finding whose values don't appear digit for digit in their sentences, and any difference that is only one of precision ("1943" vs "3 February 1943").
- Stateless Flask app on the Toolforge build service. No user data is stored.
= Related work =
- **InfoGap** (Samir et al., EMNLP 2024): research method that aligns facts across en/ru/fr biographies to find gaps and inconsistencies. Research code.
- **WikiGap**: Chrome extension built on InfoGap that shows facts from fr/zh/ru editions inside English articles, for readers. Uses GPT-4o.
- **WikiCompare**: browser plugin that adds information missing from the current page, taken from other language editions, for readers.
- **Wikiwand Fact Check**: paid feature of a third-party reader that shows where editions disagree and checks claims against the web.
- **CLAIRE**: research LLM agent that finds inconsistencies within English Wikipedia.
- **AI Source Verifier** (User:Alaexis): checks whether a cited source supports a claim. Related, but a different problem.
= What's different =
As far as I could find, no existing tool combines these:
- **Built for editors, around fixing.** Each finding shows both sentences with their citations and edit links on both wikis, rather than showing readers what they are missing.
- **Hosted by Wikimedia and free.** It runs on Toolforge with nothing to install and no API key.
- **Open models on WMF infrastructure.** It uses LiftWing, not a commercial AI service.
- **Any Wikipedia language pair**, not a fixed set of languages.
- **WikiProject worklists**: category batch mode and wikitable export.
If you know of a tool I missed, please comment.
= Feedback wanted =
# Which language pairs or topic areas would be most useful to start with?
# Would the worklist export fit how your WikiProject tracks cleanup? In what format?
# Would showing the Wikidata value next to each conflict, as a tie-breaker, be useful?
# (ML team) Is using the public LiftWing LLM endpoint from Toolforge OK for this kind of batch use, and are there load limits I should respect?
The api returns its own error responses in the format {error:message} but could return a more informative response problem+json following the spec here:
https://www.rfc-editor.org/info/rfc7807/
With the latest move to Chromium to 155, the Proton tests are failing:
https://gerrit.wikimedia.org/r/c/mediawiki/services/chromium-render/+/1355407
https://integration.wikimedia.org/ci/job/chromium-render-pipeline-test/234/console
**Steps to replicate the issue** (include links if applicable):
goto API-Spielwiese in german wiktionary
start the following request
(Reason is to get the info which of the words "Brote" or "Broten already exists in the wiki; both words exist)
https://de.wiktionary.org/w/api.php?action=parse&format=json&text=%5B%5BBrote%5D%5D%5B%5BBroten%5D%5D&prop=links&contentmodel=wikitext&formatversion=2
**What happens?**:
following JSON is returned:
{
"parse": {
"title": "API",
"pageid": 49495,
"links": [
{
"ns": 0,
"title": "Brote",
"exists": false
},
{
"ns": 0,
"title": "Broten",
"exists": false
}
]
}
}
**What should have happened instead?**:
correct would be:
{
"parse": {
"title": "API",
"pageid": 0,
"links": [
{
"ns": 0,
"title": "Brote",
"exists": true
},
{
"ns": 0,
"title": "Broten",
"exists": true
}
]
}
}
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
**Other information** (browser name/version, screenshots, etc.):
**Steps to replicate the issue** (include links if applicable):
* In desktop view, click edit source and edit something
* In another tab, switch to mobile view
* Save that edit
**What happens?**:
The edit gets tagged mobile edit and advanced mobile edit even if it was completely made in the normal source editor
**What should have happened instead?**:
The edit should have no tags
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
1.45.3
**Other information** (browser name/version, screenshots, etc.):
## Summary
Our LLMs run as KServe InferenceServices with custom model servers that reimplement features vLLM already supports, such as streaming, thinking, tool calling, and structured outputs. This adds a lot of code to maintain. It also breaks easily when vLLM changes, and we have to build our own images for it.
In T433580 we decided to move LLMs to KServe's LLMInferenceService, which runs vLLM's own server with one shared image. T433973 added it to our charts on all clusters, and T439659 tested Qwen3-14B on it in staging.
This task tracks the migration. Plain LLMs move as they are. Models with business logic are split: the LLM runs as an LLMInferenceService, and the business logic moves to a separate CPU or small GPU service that calls it.
## Technical notes
Models to migrate (assign yourself and create a subtask if needed):
Plain LLMs:
- llm-qwen3-14b
- llm-qwen36-27b
- llm-qwen38-27b
With business logic:
- llm-gpt-oss-safeguard-20b
- cope-b-a4b
Steps for each model:
1. Deploy the LLMInferenceService next to the old service with the same model and vLLM settings.
2. Compare old and new with the same requests (features from T439659), and with vllm-bench (benchmarks/README.md) for latency and throughput.
3. Move clients over, then remove the old service and the code it no longer needs.
Changes for clients (T439659):
- Plain LLMs offer only /chat/completions endpoints, with no :predict endpoints.
- Thinking is on by default.
- tool_choice "none" needs --exclude-tools-when-tool-choice-none.
Check with SREs:
- the vLLM dashboard (T429597) and the error-rate alert cover the new services (they have no Istio sidecar).
Smart routing and KEDA autoscaling are tracked separately in T436650 and are not part of this task.
## Acceptance criteria
[] Each listed model runs as an LLMInferenceService in production, or we recorded why not.
[] Business logic runs in a separate service, with the same API for clients.
[] Behavior and benchmark comparisons are recorded for each model, with no regression in latency or throughput.
[] Monitoring and alerts cover the new services.
[] Old services, images and code are removed.
When editing a page in the wikitext editor, there are two details panes below the edit box. One pane lists the wikidata entity usages tracked on the page, the other shows the template transclusions which were used. This task is about resolving an inconsistency between the behavior of these two panes: the template transclusions are updated dynamically according to the content in the editor, but the wikidata entity usages are taken from the database records for the last saved version of the page.
Behavior is the same regardless of using the realtime preview or the manual "show preview" button.
Recommendation of this task is to make the wikidata entity usage dynamic, by reading it from the EditPage ParserOutput.
Time estimation: 4-5 days
== Example ==
While initially editing a page:
{F108494055}
After saving the page and opening in the editor:
{F108494074}
Blanking the content without saving:
{F108494108}
**Steps to replicate the issue** (include links if applicable):
* `{{#invoke:User:SD0001/TemplateStyles|main|...}}`
**What happens?**:
* Link generated to [[User:SD0001/TemplateStyles]]
**What should have happened instead?**:
Link should be generated for [[Module:User:SD0001/TemplateStyles]], since #invoke strictly treats titles as being in module namespace.
== Common information
* **description**: Rule: PDU sensor over limit Faults:
#1: Sensor 12.33
** 0.33 over limit
Previous Measurement: 12.34
Limit: 12
#2: Sensor 12.02
** 0.02 over limit
Previous Measurement: 12.03
Limit: 12
https://wikitech.wikimedia.org/wiki/Network_monitoring#LibreNMS_alerts
* **summary**: Alert for device ps1-a4-eqiad.mgmt.eqiad.wmnet - PDU sensor over limit
* **timestamp**: 2026-10-15 02:58:48
* **alertname**: PDU sensor over limit
* **instance**: ps1-a4-eqiad.mgmt.eqiad.wmnet
* **scope**: network
* **severity**: task
* **source**: librenms
* **team**: dcops
== Firing alerts
---
* **description**: Rule: PDU sensor over limit Faults:
#1: Sensor 12.33
** 0.33 over limit
Previous Measurement: 12.34
Limit: 12
#2: Sensor 12.02
** 0.02 over limit
Previous Measurement: 12.03
Limit: 12
https://wikitech.wikimedia.org/wiki/Network_monitoring#LibreNMS_alerts
* **summary**: Alert for device ps1-a4-eqiad.mgmt.eqiad.wmnet - PDU sensor over limit
* **timestamp**: 2026-10-15 02:58:48
* **alertname**: PDU sensor over limit
* **instance**: ps1-a4-eqiad.mgmt.eqiad.wmnet
* **scope**: network
* **severity**: task
* **source**: librenms
* **team**: dcops
* [Source](https://librenms.wikimedia.org/device/device=40/alerts)
This task is a subtask for Outreachy 33: Claim-Source Verification Library
== Background
As we improve our connections between CiviCRM and MediaWiki we have begun storing in a global user preference a donor status preference. In future we want to allow fundraising to query via a private API which users recently consented to linking their donor accounts, but currently there is no way to identify users who have changed their preferences since a certain date.
I can currently retrieve all users that have updated the preference via the following query:
```
select gu_name ,gp_value from global_preferences join globaluser on gp_user = gu_id where gp_property = 'wikimedia-donor' AND gp_value != ''
```
However I can't filter this by date for all wikis.
I spoke to Amir about having a timestamp for every preference but that seems overkill, and for the goals of donor identification it would be acceptable to have a single field we can reference that helps us limit the poll of users as it grows.
It's proposed we add a gu_touched field that acts as an equivalent to the user_touched field for local users.
@catrope pointed me at `CentralAuth::queryAttached` which could be utilized for this purpose - perhaps with modifications forwarding the user_touched value across all projects to a new table or the existing centralauth globaluser today.
=== User story
As a developer I need a way to query global preferences since a certain date.
== Requirements
[] It should be possible to utilize in a maintenance script that runs against all wikis not knowing which wikis they are active on.
[] It should be possible for a maintenance script to query preferences updated between two dates and get a list of global user IDs for those users.
=== Acceptance criteria for done
[] //Add clear acceptance criteria. Separate out items to implement and items to QA if needed.//
=== QA strategy
- **Risky change?** //List whether this change has an increased potential to cause bug, regressions, or controversy.//
- **QA by:** //Who should QA this task?//
- **QA in:** //Which environment? Patchdemo, beta, production...//
- **Test steps:** //Add if needed.//
=== Communication criteria
//Add if this needs an announcement or discussion.//
=== Rollback plan
//Describe the rollback plan in production for this task if something goes wrong.//
See also: {T427943}
=== Behavior
1. Log in
2. Copy a paragraph of text from ChatGPT (web) using client's copy button
3. Paste text into a VE edit session (main namespace)
**❌ Actual**
3. Paste Check activates
**✅ Expected**
3. LLM Paste Check activates
=== References
- Screenrecording:
-- https://youtu.be/tbZCXDt4UcA?si=VTt0FkJWp8yTXAvi&t=99
- HTML output (attached):
-- {F108411503}
**Steps to replicate the issue** (include links if applicable):
* Visit https://en.wikipedia.beta.wmcloud.org/wiki/Special:ReadingLists and create one list and add an item to it.
* Switch to Hindu e.g. https://en.wikipedia.beta.wmcloud.org/wiki/Special:ReadingLists/Jdlrobson/collections?uselang=hi
**What happens?**:
Numbers are not localized{F108410655}
**What should have happened instead?**:
Numbers should be localized
e.g. `mw.language.convertNumber(0)`
```
mw.language.convertNumber(0)
'०'
mw.language.convertNumber(1)
'१
```
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
**Other information** (browser name/version, screenshots, etc.):
== Background
We want to refine the design of the collections picker that we started in {T438393}.
=== User story
//Add at least one user story.//
=== Design requirements
1. Line is missing above "create collection" at large resolution.
| Beta {F108369590} | Design {F108369663}
2. The link above collection should not be full width at low resolution
| Beta {F108370435} | Design {F108370469}
3. Create collection should not be underlined
3. The article title should be cropped if longer than 2 lines
| Beta {F108369821} {F108370076} | Design {F108370217}
4. The collection title should be cropped if longer than 2 lines
| Beta {F108370076} | Design {F108370217}
5. The height of each row on minerva is small for tapping. There should be 12 px space above and below the text.
| Beta {F108370435} | Design {F108370469}
== Requirements
NOTE: to be filled out once received answers to questions
=== Acceptance criteria for done
[] //Add clear acceptance criteria. Separate out items to implement and items to QA if needed.//
=== QA strategy
- **Risky change?** //List whether this change has an increased potential to cause bug, regressions, or controversy.//
- **QA by:** //Who should QA this task?//
- **QA in:** //Which environment? Patchdemo, beta, production...//
- **Test steps:** //Add if needed.//
=== Communication criteria
//Add if this needs an announcement or discussion.//
=== Rollback plan
//Describe the rollback plan in production for this task if something goes wrong.//
//This task was created by Version 1.2.0 of the Reader Experience team task template using [[ https://phabulous.toolforge.org/ | phabulous ]].//
=== Behavior
1. Copy some text from a website
2. Open VE where Paste Check and LLM Paste Check are avail. by default (all wikis)
3. Ensure you have "access" to both features on the account you're using
4. Paste the text you copied in "1." into the VE edit session you initiated in "2."
**❌ Actual**
5. Paste check appears in a **collapsed** state:
{F108398923}
**✅ Expected**
5. Paste check appears in an **expanded** state
## Summary
The `analytics/refinery` and `analytics/refinery/source` repositories mix reusable library code with business logic, which makes deployment (especially of SQL) slow and cumbersome, and our standalone Python repositories each re-implement the same CI/CD. As we move this code to GitLab, this RFC gathers input on how to structure our repositories so that developers can test, release, and deploy with less friction; the decision itself will be taken in a follow-up.
## Technical notes
### Current state
- **analytics/refinery** (since 2014) holds ~330 HQL files across dozens of unrelated pipelines in `hql/` (orchestrated from airflow-dags), a small Python library (`python/refinery`), scripts (`bin/`), deployed JARs (`artifacts/`), and static data. Deploying SQL to HDFS rides along with the refinery deployment process, and SQL changes get no automated linting or checks.
- **analytics/refinery/source** is a Maven multi-module project (`refinery-core`, `refinery-hive`, `refinery-spark`, `refinery-job`, `refinery-job-lite`, `refinery-tools`, ...) that contains both reusable libraries and job-specific Java/Scala code.
- **Standalone Python repositories** owned by the team each implement their own CI/CD for testing, linting, package building, and publishing to the GitLab Package Registry. There are also the PySpark Conda environments which could also be considered a part of this group.
- **dbt + Airflow** have made writing and scheduling new SQL pipelines much easier, but legacy HQL is expected to stay for a long time; it is not yet clear whether any of it can be translated to dbt-style SQL. Any new layout must give legacy HQL a good long-term home, not a temporary one.
The current state of stuff in `analytics/refinery` repos could be broken down into two broad categories, like so:
| | Libraries | Business logic (jobs) |
|---|---|---|
| Examples | `refinery-core`/`-spark`/`-hive` jars, `python/refinery` | ~330 files in `hql/`, job-specific Spark code, `static_data` |
| Lifecycle | Versioned, released on purpose, others depend on them | Deployed continuously when merged, nobody imports them |
| Deploy target | GitLab Package Registry (Maven, PyPI) | HDFS (via Blunderbuss) |
| Cost of a mistake | Breaks consumers, so semver plus a changelog | Breaks one pipeline; roll back with a revert |
### Problems we want to solve
- **Slow, cumbersome deployment** — business logic (especially SQL) cannot be deployed continuously; small changes wait on a release process built for libraries.
- **No clear boundaries** — library code and business logic share repositories and release cycles, and ownership is fuzzy.
- **Missing automated checks** — SQL changes get no linting or validation on review.
- **Duplicated CI/CD** — each standalone Python repository maintains its own copy of the same pipelines.
### Options
The options below are a starting point, not an exhaustive list. Please add options, pros, and cons in the comments.
#### Option A — Unified monorepo (libraries + business logic)
One repository holds library code (Java/Scala, Python) and business logic (HQL, job code, static data), and optionally the standalone Python packages. A shared GitLab CI/CD scaffolding knows how to test, build, release, and deploy each path: libraries are versioned and published to the GitLab Package Registry, while business logic is deployed (e.g. to HDFS via Blunderbuss) on merge.
Pros:
- One place to look for, change, and onboard to all team code.
- Atomic changes across a library and the jobs that use it, tested together in one MR before anything is released.
- CI/CD conventions and tooling are defined once; standalone Python repositories no longer duplicate pipelines (if folded in).
- One migration effort instead of several.
Cons:
- The CI/CD scaffolding is a significant up-front and ongoing engineering investment: path-based change detection, a dependency graph between components (a library change must also test its dependents), per-component versioning and tag namespacing, and multiple toolchains (Maven/JVM, Python, SQL) in one pipeline.
- Path-based change detection is easy to get subtly wrong (e.g. pipelines on new branches or on the default branch after a merge), which can cause skipped tests or unwanted deployments.
- A larger repository with coarser permissions and more merge contention.
- Without clear internal boundaries and conventions, it can recreate refinery's "everything in one place" problem at a larger scale.
#### Option B — Split by lifecycle
Library code goes into library repositories that are versioned and published to the GitLab Package Registry. Business logic goes into job repositories that deploy continuously on merge. Shared GitLab CI/CD components (test, lint, build, publish, deploy) remove duplication across all repositories, including the standalone Python ones.
Pros:
- Each repository's CI/CD is simple and standard; release (libraries) and continuous deployment (jobs) never interfere.
- Clear ownership, small blast radius, fast pipelines.
- Shared CI/CD components give consistency without monorepo tooling.
Cons:
- More repositories to create, permission, and maintain.
- A change to a library and a job that uses it needs two MRs and a library release in between.
- Risk of version drift between jobs and the libraries they depend on.
#### Option C — Business-logic monorepo, libraries separate
All business logic (HQL, job code in any language, static data) lives in one repository that deploys on merge. Libraries live in their own versioned repositories, as in Option B.
Pros:
- One continuous-deployment pipeline for all business logic, regardless of language.
- Libraries keep a deliberate, semver-based release cycle.
- Less CI/CD complexity than Option A, because the monorepo has a single lifecycle (deploy on merge).
Cons:
- Still needs path-scoped CI within the business-logic repository for multiple languages.
- Library changes that affect jobs still span repositories.
- Boundary questions remain (e.g. is job-specific Scala code a library or business logic?).
#### Option D — Move as-is, refactor later (baseline)
Copy refinery and refinery/source to GitLab unchanged and restructure afterwards.
Pros:
- Least effort; unblocks the GitLab migration quickly.
Cons:
- Fixes none of the problems above.
- CI/CD built for the old layout must be rebuilt when we restructure.
### Questions for any option
- How should jobs consume libraries: pinned released versions, or built from the same commit?
- How are components versioned and tagged, and what triggers a release versus a deployment?
- What are the deploy targets per component type (HDFS via Blunderbuss, GitLab Package Registry, conda environments, ...)?
- Where does the boundary between "library" and "business logic" lie for existing code (e.g. `refinery-job`)?
- Should dbt-jobs and the standalone Python repositories be part of this layout, or stay separate?
- Do we need to preserve git history when moving code?
## Acceptance criteria
- [ ] Stakeholders ([TODO: reviewers]) have weighed in on the options and the open questions.
- [ ] Trade-offs, risks, and missing details for each option are captured in the discussion thread.
- [ ] Enough input is gathered to take the decision in a follow-up task or meeting.
While trying to do {T441169}.
```
zabe@deploy1003:~$ mwscript extensions/WikimediaMaintenance/maintenance/addWiki.php --wiki=mlwikivoyage
[...]
Warning: Skipping potentially shared domain "virtual-campaignevents"
[extension-tables] Creating tables for enabled extensions... Creating transcode table...done.
...skipping schema change (Adding transcode_state field to table transcode).
[...]
...skipping update to table ce_invitation_list_articles in shared virtual domain.
Wikimedia\Rdbms\DBQueryError from line 1232 of /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/libs/Rdbms/Database/Database.php: Error 1142: DROP command denied to user 'wikiadmin2023'@'10.64.16.93' for table `wikishared`.`ce_worklist_articles`
Function: MediaWiki\Extension\CampaignEvents\Hooks\Handlers\SchemaChangesHandler::migrateAndDropWorklistArticlesTable
Query: DROP TABLE `ce_worklist_articles` CASCADE
#0 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/libs/Rdbms/Database/Database.php(1216): Wikimedia\Rdbms\Database->getQueryException('DROP command de...', 1142, 'DROP TABLE `ce_...', 'MediaWiki\\Exten...')
#1 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/libs/Rdbms/Database/Database.php(1190): Wikimedia\Rdbms\Database->getQueryExceptionAndLog('DROP command de...', 1142, 'DROP TABLE `ce_...', 'MediaWiki\\Exten...')
#2 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/libs/Rdbms/Database/Database.php(645): Wikimedia\Rdbms\Database->reportQueryError('DROP command de...', 1142, 'DROP TABLE `ce_...', 'MediaWiki\\Exten...', false)
#3 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/libs/Rdbms/Database/Database.php(3028): Wikimedia\Rdbms\Database->query(Object(Wikimedia\Rdbms\Query), 'MediaWiki\\Exten...')
#4 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/libs/Rdbms/Database/DBConnRef.php(129): Wikimedia\Rdbms\Database->dropTable('ce_worklist_art...', 'MediaWiki\\Exten...')
#5 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/libs/Rdbms/Database/DBConnRef.php(928): Wikimedia\Rdbms\DBConnRef->__call('dropTable', Array)
#6 /srv/mediawiki-staging/php-1.47.0-wmf.24/extensions/CampaignEvents/src/Hooks/Handlers/SchemaChangesHandler.php(188): Wikimedia\Rdbms\DBConnRef->dropTable('ce_worklist_art...', 'MediaWiki\\Exten...')
#7 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/Installer/DatabaseUpdater.php(586): MediaWiki\Extension\CampaignEvents\Hooks\Handlers\SchemaChangesHandler->migrateAndDropWorklistArticlesTable(Object(MediaWiki\Installer\MysqlUpdater))
#8 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/Installer/DatabaseUpdater.php(544): MediaWiki\Installer\DatabaseUpdater->runUpdates(Array, true, true)
#9 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/Installer/Task/ExtensionTablesTask.php(45): MediaWiki\Installer\DatabaseUpdater->doUpdates(Array)
#10 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/Installer/Task/TaskRunner.php(155): MediaWiki\Installer\Task\ExtensionTablesTask->execute()
#11 /srv/mediawiki-staging/php-1.47.0-wmf.24/includes/Installer/Task/TaskRunner.php(52): MediaWiki\Installer\Task\TaskRunner->runTask(Object(MediaWiki\Installer\Task\ExtensionTablesTask))
#12 /srv/mediawiki-staging/php-1.47.0-wmf.24/maintenance/installPreConfigured.php(82): MediaWiki\Installer\Task\TaskRunner->execute()
#13 /srv/mediawiki-staging/php-1.47.0-wmf.24/extensions/WikimediaMaintenance/maintenance/addWiki.php(63): InstallPreConfigured->execute()
#14 /srv/mediawiki-staging/php-1.47.0-wmf.24/maintenance/includes/MaintenanceRunner.php(695): AddWiki->execute()
#15 /srv/mediawiki-staging/php-1.47.0-wmf.24/maintenance/run.php(54): MediaWiki\Maintenance\MaintenanceRunner->run()
#16 /srv/mediawiki-staging/multiversion/MWScript.php(219): require_once('/srv/mediawiki-...')
#17 {main}
zabe@deploy1003:~$
```
== Common information
* **dashboard**: https://grafana.wikimedia.org/d/g-AaZRFWk/systemd-status
* **description**: sync-gitlab-group-with-ldap.service on gitlab1004:9100
* **runbook**: https://wikitech.wikimedia.org/wiki/Monitoring/check_systemd_state
* **summary**: sync-gitlab-group-with-ldap.service on gitlab1004:9100
* **alertname**: SystemdUnitFailed
* **instance**: gitlab1004:9100
* **name**: sync-gitlab-group-with-ldap.service
* **prometheus**: ops
* **severity**: critical
* **site**: eqiad
* **source**: prometheus
* **team**: collaboration-services
== Firing alerts
---
* **dashboard**: https://grafana.wikimedia.org/d/g-AaZRFWk/systemd-status
* **description**: sync-gitlab-group-with-ldap.service on gitlab1004:9100
* **runbook**: https://wikitech.wikimedia.org/wiki/Monitoring/check_systemd_state
* **summary**: sync-gitlab-group-with-ldap.service on gitlab1004:9100
* **alertname**: SystemdUnitFailed
* **instance**: gitlab1004:9100
* **name**: sync-gitlab-group-with-ldap.service
* **prometheus**: ops
* **severity**: critical
* **site**: eqiad
* **source**: prometheus
* **team**: collaboration-services
* [Source](https://prometheus-eqiad.wikimedia.org/ops/graph?g0.expr=%28instance_name%3Anode_systemd_unit_state_failed%3Acount1+%2A+on+%28instance%2C+name%29+group_left+%28team%29+systemd_unit_owner%29+%3D%3D+1+or+ignoring+%28team%29+%28instance_name%3Anode_systemd_unit_state_failed%3Acount1+%2A+on+%28instance%29+group_left+%28team%29+role_owner%29+%3D%3D+1&g0.tab=1)
####Background
- Release date: Dec 1
- 15 Days- Dec 16
####The Task
[] Validate only the KRs noted in Epic
[] Share with PM For hypothesis closeouts before December 20
This is a tracking task for hyptheses under the ST6.4 key result. For more details, check the T432486 parent and [[ https://meta.wikimedia.org/wiki/FY2026-2027#ST6 | FY2026-2027#ST6 ]] on Meta-Wiki.
>>! **Hypothesis**:
> If we reduce non-pageview workloads without increasing pageview latency, and if we make pageview workloads faster, we will increase net capacity for logged-in users by 10%.
This generally works in one of two ways:
* Increase effective capacity through reducing non-pageview workloads. Such as by improving CDN caching of MediaWiki API responses, Special pages (Special:HideBanners), or action=raw; which frees up capacity for pageviews.
* Increase effective capacity through making MediaWiki serve pageviews faster. Such as through improvements to MediaWiki performance (T302623) and PHP engine performance ([[ https://wikitech.wikimedia.org/wiki/User:Krinkle/MediaWiki_infra_optimizations_(2026) | wikitech:User:Krinkle/MediaWiki_infra_optimizations ]]).
TASK AUTO-GENERATED by Nagios/Icinga RAID event handler
A degraded RAID (md) [[ https://icinga.wikimedia.org/cgi-bin/icinga/extinfo.cgi?type=2&host=wikikube-worker2285&service=MD RAID | was detected ]] on host `wikikube-worker2285`. An automatic snapshot of the current RAID status is attached below.
Please **sync with the service owner** to find the appropriate time window before actually replacing any failed hardware.
```
CRITICAL: State: degraded, Active: 1, Working: 1, Failed: 1, Spare: 0
$ sudo /usr/local/lib/nagios/plugins/get-raid-status-md
Personalities : [raid1] [linear] [multipath] [raid0] [raid6] [raid5] [raid4] [raid10]
md0 : active raid1 sda2[0] sdb2[1](F)
937267200 blocks super 1.2 [2/1] [U_]
bitmap: 4/7 pages [16KB], 65536KB chunk
unused devices: <none>
```
####Background
Last year, we had an issue where the Year in Review announcement was not showing to Android users, and doing an early data check helped us catch that & fix it. We want to do a similar check this year to make sure A) The announcement is displaying, B) Entry points are showing to the correct people and C) There are no blockers in the account creation funnel
####Task
[] Analyst pull 3-day indicators & share with team, highlight if any display issues may be happening. Split by Android/iOS for all metrics
- 0.1 - Full page announcement was displayed to 95% of DAU
- 0.2 - At least X% of DAU were identified as data-rich and received data-rich entry points & personalized experience if logged-in
- Data-rich user = 3 or more articles in their reading history AND reading 2 or more distinct calendar days
- 0.3 - At least 1% of logged-out users who see the announcement successfully create an account through the feature [Baseline: 1.2% of android impressions of reading challenge announcement created an account]
[[ https://docs.google.com/document/d/16ja4jg7Uzm1iVmbPHogmKXo-ltsZRJ2sw3koZNxUkDM/edit?tab=t.0 | Metric review Notes doc ]]
**Background**
When contributors land on the dashboard, it is not always clear where to start. Some click through several tasks before realizing they don't have the rights to work on them.
**Proposed changes**
**1. Welcome strip**
- Add a strip at the top of the dashboard titled "Grow [Language] Wikipedia".
- It has three options: Complete a task, Track progress, Get help.
- Clicking an option takes the contributor to that section and highlights it.
**2. Quick tour**
- The tour opens when a contributor first lands on the dashboard, and can be opened again by clicking on one of the options from the welcome strip.
- Each section is highlighted in turn, with a popup next to it that shows one point at a time.
- Contributors can go back, go next, or close the tour at any time.
- On the last popup, Next ends the tour.
Tour content:
Essential tasks
- Essential tasks help you set up the foundations your language wiki needs to grow, develop, and move to the next stage.
- Some tasks require additional permissions, such as administrator rights, while others can be completed by regular editors.
- Each task comes with step-by-step guidance to help you along the way.
- Start with a beginner-level task that you have permission to complete.
Get help from the community
- As you work on essential tasks, you may have questions or need some help. There are different ways to connect with the Wikimedia community.
- Use the CapX platform to find and connect with mentors who speak your language or have skills you're looking for.
- Ask questions through Wikimedia mailing lists, Telegram groups, or other community channels.
Track your wiki's progress
- Keep an eye on your wiki's health and progress to understand how it's developing and where to focus your efforts.
- Understand your roadmap and see how many more articles or administrators your wiki needs to reach the next stage.
- Follow your wiki's trends over time to see whether you need to adjust your priorities or focus on different areas.
**3. Task order**
- Tasks the contributor has the rights to do appear first.
- Within that group, Beginner tasks appear before Intermediate ones.
- Tasks the contributor does not have the rights for move to the end, also ordered Beginner first.
- Locked tasks show the missing rights with a lock icon and the message "Get the required rights to start this task."
**Acceptance criteria**
- The welcome strip appears at the top of the dashboard with the wiki's name.
- Each strip option scrolls to and highlights its section.
- The tour shows the content above, one point per popup, next to the highlighted section.
- The tour opens on first visit and can be reopened from the strip.
- Tasks are ordered by rights first, then by level.
- Locked tasks show which rights are missing.
**Design Mockups**
Link: https://claude.ai/artifact/EfnCpQCMuoeYzHotfGMjLm
Screenshots
{F108388827}
Source
{F108388425}
== Background
During sprint 8 we discovered that we were building create/rename collection using outdated designs. This task captures the work to update them.
Current design:
{F108402650}
{F108402753}
=== User story
//Add at least one user story.//
=== Design requirements
//Add design requirements or link to design files.//
# current design
* progressive blue button in bottom right
* cancel button
* no close icon in top right
# updated design
* progressive blue button in bottom right
* no cancel button
* close icon in top right
https://figma.com/design/Q3pYKI7RRMdRRgkQp2RiTf/Web--Reading-List-Collections?node-id=3182-118441&p=f&focus-id=3182-118752&view=focus&m=dev
https://www.figma.com/design/Q3pYKI7RRMdRRgkQp2RiTf/Web--Reading-List-Collections?node-id=3182-118441&p=f&focus-id=3314-125474&view=focus&m=dev
== Requirements
[] Design is updated from old to new
=== Acceptance criteria for done
[] //Add clear acceptance criteria. Separate out items to implement and items to QA if needed.//
=== QA strategy
- **Risky change?** //List whether this change has an increased potential to cause bug, regressions, or controversy.//
- **QA by:** //Who should QA this task?//
- **QA in:** //Which environment? Patchdemo, beta, production...//
- **Test steps:** //Add if needed.//
=== Communication criteria
//Add if this needs an announcement or discussion.//
=== Rollback plan
//Describe the rollback plan in production for this task if something goes wrong.//
//This task was created by Version 1.2.0 of the Reader Experience team task template using [[ https://phabulous.toolforge.org/ | phabulous ]].//
####User story
As a contributor who returns to Home, I want new modules to be introduced in a consistent way, so that I notice what's new and why it's relevant to me without the page feeling unpredictable, spammy, or cluttered.
####Background
Home is meant to expose users to relevant new features as they progress on the wikis. Conditional modules appear as a user's account state changes, new modules launch after users already know the page, and other teams can register their own modules through the PersonalDashboard framework.
Without a shared pattern, each module will invent its own introduction, and Home will feel inconsistent and noisy. This task defines one pattern that all modules follow.
**Moments to consider:**
- Newly unlocked for a user: a conditional module appears because the user progressed and "unlocked" a new feature / module.
- Newly launched module: a module ships to Home for users who already know the page.
####Open questions
- Should teaser/locked states be allowed?
- Should we avoid more than one module being introduced at the same time? (For example, for an experienced editor visiting Home for the first time, should they see multiple intros?)
####Acceptance Criteria:
[] Recommended introduction treatment (e.g. "New" label, inline explainer, highlight, notification, or nothing)
[] Dismissal: how long the "new" treatment lasts, and what the second visit looks like.
[] Copy guidance for explaining why a module appeared ("You can now…").
[] Guidance written for other teams registering modules (published
== Common information
* **summary**: Abstract Wikipedia preview completeness SLO is below 98% target
* **title**: (ticket) mediawiki-wikilambda abstract-preview-completeness SLO error budget burn rate is too fast.
* **alertname**: SLOBudgetBurn
* **recorder**: thanos-rule@main
* **revision**: 1
* **severity**: task
* **sloth_id**: mediawiki-wikilambda-abstract-preview-completeness
* **sloth_service**: mediawiki-wikilambda
* **sloth_severity**: ticket
* **sloth_slo**: abstract-preview-completeness
* **source**: thanos
* **team**: abstract-wikipedia
== Firing alerts
---
* **summary**: Abstract Wikipedia preview completeness SLO is below 98% target
* **title**: (ticket) mediawiki-wikilambda abstract-preview-completeness SLO error budget burn rate is too fast.
* **alertname**: SLOBudgetBurn
* **recorder**: thanos-rule@main
* **revision**: 1
* **severity**: task
* **sloth_id**: mediawiki-wikilambda-abstract-preview-completeness
* **sloth_service**: mediawiki-wikilambda
* **sloth_severity**: ticket
* **sloth_slo**: abstract-preview-completeness
* **source**: thanos
* **team**: abstract-wikipedia
* [Source](https://thanos.wikimedia.org/graph?g0.expr=%28max+without+%28sloth_window%29+%28slo%3Asli_error%3Aratio_rate2h%7Brevision%3D%221%22%2Csloth_id%3D%22mediawiki-wikilambda-abstract-preview-completeness%22%2Csloth_service%3D%22mediawiki-wikilambda%22%2Csloth_slo%3D%22abstract-preview-completeness%22%7D+%3E+%283+%2A+0.02%29%29+and+max+without+%28sloth_window%29+%28slo%3Asli_error%3Aratio_rate1d%7Brevision%3D%221%22%2Csloth_id%3D%22mediawiki-wikilambda-abstract-preview-completeness%22%2Csloth_service%3D%22mediawiki-wikilambda%22%2Csloth_slo%3D%22abstract-preview-completeness%22%7D+%3E+%283+%2A+0.02%29%29%29+or+%28max+without+%28sloth_window%29+%28slo%3Asli_error%3Aratio_rate6h%7Brevision%3D%221%22%2Csloth_id%3D%22mediawiki-wikilambda-abstract-preview-completeness%22%2Csloth_service%3D%22mediawiki-wikilambda%22%2Csloth_slo%3D%22abstract-preview-completeness%22%7D+%3E+%281+%2A+0.02%29%29+and+max+without+%28sloth_window%29+%28slo%3Asli_error%3Aratio_rate3d%7Brevision%3D%221%22%2Csloth_id%3D%22mediawiki-wikilambda-abstract-preview-completeness%22%2Csloth_service%3D%22mediawiki-wikilambda%22%2Csloth_slo%3D%22abstract-preview-completeness%22%7D+%3E+%281+%2A+0.02%29%29%29&g0.tab=1)
**Steps to replicate the issue** (include links if applicable):
* Visit https://en.wikipedia.org/?banner=B2627_101413_en6C_m_p1_lg_bkg_cnt&force=1 on desktop and close the banner
* call `mw.loader.require('ext.wikimediaCustomizations.donor').recentlyDonated()`
**What happens?**:
returns true
**What should have happened instead?**:
should return false.
When inspecting the cookie it is important to check the `reason` field and confirm that it matches `'donate'`.
**Software version** (on `Special:Version` page; skip for WMF-hosted wikis like Wikipedia):
**Other information** (browser name/version, screenshots, etc.):
In T402650 we sent a survey to all Wikipedia Library users. We don't anticipate doing this again for at least some time, so we can remove related code and translatable strings for now.
The Data Lake - to - Postgres data transfers currently occur twice a day, at 04:00 and 12:00 UTC ([[ https://gitlab.wikimedia.org/repos/data-engineering/airflow-dags/-/blob/main/main/dags/datalake_to_postgres/datalake_to_postgres_dag.py?ref_type=heads#L33 | source code ]]
Make this schedule more frequent so that the transfer occurs once every 4 hours.
The debug logs contain one wrong statement, and some noisy debug logs from urllib3.
#### Definition of done
* Fix incorrect wording in the debug logs: on the first cycle after a restart, the debug log says that an alert "is still firing, last notified at", but it should say that an alert is assumed to be already notified
* Set the urllib3 loggers to the INFO level, so that they don't log a line for every request and every new connection
#### Impact
* Debug logs are shorter, and more accurate
Default values are defined in `alerts/config.py`, but some are also repeated in notifier.py and in the Helm chart `values.yaml`.
#### Definition of done
* Defaults are defined only once in `alerts/config.py`
#### Impact
* Defaults only need to be changed in one place, smaller risk of forgetting one
notifier.py receives the `active_at` of each alert and the `for:` durations of the rules, and computes the fired time from those. This calculation should be done in prometheus.py instead, so that the notifier receives a single value and is less coupled to the alert source.
#### Definition of done
* `notifier.py` receives a single value (`fired_at`) instead of two (`active_at` and `durations`)
#### Impact
* Less coupling between notifier.py and the alert source
Hey @Papaul - per our call earlier, can you check out dbprov2004 for any possible issues with either the PSU not having enough wattage or iDrac settings that are incorrect? During the CODFW outage, when the host lost one of the redundant power supplies, the other power supply wasn't able to handle the power draw, and shut itself down. And when the power was restored, it didn't auto-recover.
Thanks,
Willy
### Description
Most languages will never achieve full translation support. However, Search results should still favor the user's selected language. Results in their language should be prioritized, but English should always be available as a fallback option, particularly in cases where no translation is expected to exist (eg: endpoint names).
### Conditions of acceptance
[] When searching, results that match in the user's selected language are presented first.
[] Fallback results in English are always included if available, but presented after, and are marked as such.
[] If there are no results in their language, users are presented with the option to "Search in all languages" (translated to the selected language, if available)
[] When clicked, the search is executed again and results for matches in any/all languages are returned.
### Implementation details
The prototype site demonstrates the (roughly) desired behavior: https://wikifrodo.netlify.app/es
Test new AI features in Userlytics
Assess their performance
Write up recommendations, tips, and guidance to pass on to Design
### Description
Users rely heavily on search to find relevant content. To ensure they can always find what they're looking for, every content page should be included in the search results so that they can more easily discover and navigate across different topics.
### Conditions of acceptance
[] Short form content is discoverable through search.
[] Focus on content blocks, including those that result in links to external pages.
[] Navigation items are excluded.
[] Long form content is discoverable through search.
[] Full markdown file can be searched.
[] Content results are listed after any available API endpoint results.
[] A header is presented to differentiate content from API endpoints (consult with Design/Sarai)
Newcomers' questions coming through the Help panel or Mentorship should be formatted as in this change:
https://www.wikidata.org/w/index.php?title=Wikidata:Project_chat&diff=prev&oldid=2556561586
Specifically: remove link and timestamp from subheading.
Several projects deprecate links in subheadings.
Times are superfluous.
Patch: https://gerrit.wikimedia.org/r/c/mediawiki/core/+/1328371/7/sql/mysql/patch-user_editcount.sql
I can do it myself if DBA approves.
== Common information
* **summary**: Project deployment-prep instance deployment-deploy04 is down
* **alertname**: InstanceDown
* **instance**: deployment-deploy04
* **job**: node
* **project**: deployment-prep
* **severity**: warning
== Firing alerts
---
* **summary**: Project deployment-prep instance deployment-deploy04 is down
* **alertname**: InstanceDown
* **instance**: deployment-deploy04
* **job**: node
* **project**: deployment-prep
* **severity**: warning
* [Source](https://prometheus.wmcloud.org/graph?g0.expr=up%7Bjob%3D%22node%22%7D+%3D%3D+0&g0.tab=1)
If one of the configured Prometheus hosts answers with valid JSON, but with an unexpected shape (e.g. `{}`), the whole poll cycle fails, and no tool gets any email even if the other host answers correctly. The error is logged at every cycle, but the emails just stop.
Possible situations where this might happen:
* a host returns an error body as JSON with HTTP 200
* a single alert has missing or unexpected fields
#### Definition of done
* a response that cannot be parsed counts as a failed host, and the alerts of the other hosts are still notified
* a single alert that cannot be parsed is skipped, and the other alerts of the same cycle are still notified
* no resolved emails are sent while a host returns alerts that cannot be parsed, because a skipped alert could still be firing
* both cases are logged with a traceback to help debugging
#### Impact
* An unexpected response from one of the Prometheus hosts no longer stops the alert emails of every tool