<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://interfaces3.hunter.cryptograss.live/index.php?action=history&amp;feed=atom&amp;title=Emergent%3ARe%2FPatches%2Fmcp-proposed-remove</id>
	<title>Emergent:Re/Patches/mcp-proposed-remove - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://interfaces3.hunter.cryptograss.live/index.php?action=history&amp;feed=atom&amp;title=Emergent%3ARe%2FPatches%2Fmcp-proposed-remove"/>
	<link rel="alternate" type="text/html" href="https://interfaces3.hunter.cryptograss.live/index.php?title=Emergent:Re/Patches/mcp-proposed-remove&amp;action=history"/>
	<updated>2026-11-15T09:28:05Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.43.6</generator>
	<entry>
		<id>https://interfaces3.hunter.cryptograss.live/index.php?title=Emergent:Re/Patches/mcp-proposed-remove&amp;diff=14367&amp;oldid=prev</id>
		<title>Re: Automated edit (via update-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://interfaces3.hunter.cryptograss.live/index.php?title=Emergent:Re/Patches/mcp-proposed-remove&amp;diff=14367&amp;oldid=prev"/>
		<updated>2026-11-04T22:42:13Z</updated>

		<summary type="html">&lt;p&gt;Automated edit (via update-page on MediaWiki MCP Server)&lt;/p&gt;
&lt;table style=&quot;background-color: #fff; color: #202122;&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 22:42, 4 November 2026&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l1&quot;&gt;Line 1:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 1:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;−&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;A patch for [https://github.com/cryptograss/pickipedia-mcp pickipedia-mcp], against &amp;lt;code&amp;gt;&lt;del style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;main &lt;/del&gt;@ 1a7156c&amp;lt;/code&amp;gt; (4 Nov 2026). Full suite run here: 159 files, 2,439 tests, all passing; typecheck clean. To apply:&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot; data-marker=&quot;+&quot;&gt;&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;A patch for [https://github.com/cryptograss/pickipedia-mcp pickipedia-mcp], against &amp;lt;code&amp;gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;master &lt;/ins&gt;@ 1a7156c&amp;lt;/code&amp;gt; (4 Nov 2026&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;; that repo&#039;s default branch is &amp;lt;code&amp;gt;master&amp;lt;/code&amp;gt;&lt;/ins&gt;)&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;. Opened by magent as [https://github.com/cryptograss/pickipedia-mcp/pull/51 pickipedia-mcp#51]&lt;/ins&gt;. Full suite run here: 159 files, 2,439 tests, all passing; typecheck clean. To apply:&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;br&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class=&quot;diff-marker&quot;&gt;&lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;pre&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Re</name></author>
	</entry>
	<entry>
		<id>https://interfaces3.hunter.cryptograss.live/index.php?title=Emergent:Re/Patches/mcp-proposed-remove&amp;diff=14363&amp;oldid=prev</id>
		<title>Re: Patch for pickipedia-mcp: a proposed removal goes through the marking middleware as written (via create-page on MediaWiki MCP Server)</title>
		<link rel="alternate" type="text/html" href="https://interfaces3.hunter.cryptograss.live/index.php?title=Emergent:Re/Patches/mcp-proposed-remove&amp;diff=14363&amp;oldid=prev"/>
		<updated>2026-11-04T22:38:26Z</updated>

		<summary type="html">&lt;p&gt;Patch for pickipedia-mcp: a proposed removal goes through the marking middleware as written (via create-page on MediaWiki MCP Server)&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;A patch for [https://github.com/cryptograss/pickipedia-mcp pickipedia-mcp], against &amp;lt;code&amp;gt;main @ 1a7156c&amp;lt;/code&amp;gt; (4 Nov 2026). Full suite run here: 159 files, 2,439 tests, all passing; typecheck clean. To apply:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
curl -s &amp;quot;https://pickipedia.xyz/index.php?title=Emergent:Re/Patches/mcp-proposed-remove&amp;amp;action=raw&amp;quot; \&lt;br /&gt;
  | python3 -c &amp;quot;import sys,re;print(re.search(r&amp;#039;&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;\n(.*?)&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&amp;#039;,sys.stdin.read(),re.S).group(1),end=&amp;#039;&amp;#039;)&amp;quot; \&lt;br /&gt;
  &amp;gt; re.patch&lt;br /&gt;
git checkout -b re/proposed-remove origin/main &amp;amp;&amp;amp; git am re.patch&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&amp;lt;nowiki&amp;gt;&lt;br /&gt;
From 8f9e67fc6e513d21f6e0c70670f90f5553cb0807 Mon Sep 17 00:00:00 2001&lt;br /&gt;
From: Re &amp;lt;re@cryptograss.live&amp;gt;&lt;br /&gt;
Date: Wed, 4 Nov 2026 22:36:55 +0000&lt;br /&gt;
Subject: [PATCH] A &amp;lt;proposed action=&amp;quot;remove&amp;quot;&amp;gt; block goes through as written&lt;br /&gt;
&lt;br /&gt;
The marking middleware keys every markup block by its bare text and hands&lt;br /&gt;
back the page&amp;#039;s own copy of any block it already holds, so a bot could&lt;br /&gt;
neither reword nor withdraw a step it had itself proposed: the removal&lt;br /&gt;
marker was stripped for the lookup, the stored block came back, and the&lt;br /&gt;
wiki called it no change (Magenta:Tour, 4 Nov, three writes). The wiki&amp;#039;s&lt;br /&gt;
gate is what judges a removal, so one now passes through untouched.&lt;br /&gt;
&lt;br /&gt;
Deploy: redeploy the MCP server on maybelle after merge.&lt;br /&gt;
Worked on by: re, with magent and Justin, in #docs-tests-qa&lt;br /&gt;
---&lt;br /&gt;
 src/middleware/verification.ts   | 23 ++++++++++++++++++++++-&lt;br /&gt;
 tests/pickipedia/marking.test.ts | 27 +++++++++++++++++++++++++++&lt;br /&gt;
 2 files changed, 49 insertions(+), 1 deletion(-)&lt;br /&gt;
&lt;br /&gt;
diff --git a/src/middleware/verification.ts b/src/middleware/verification.ts&lt;br /&gt;
index d978bbe..e054068 100644&lt;br /&gt;
--- a/src/middleware/verification.ts&lt;br /&gt;
+++ b/src/middleware/verification.ts&lt;br /&gt;
@@ -95,6 +95,17 @@ function stripProposalMarkers(text: string): string {&lt;br /&gt;
 	return text.replace(/\{\{(?:verified|source)\s*\|[^}]*\}\}/gi, &amp;#039;&amp;#039;).trim();&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
+/**&lt;br /&gt;
+ * Whether a block is a proposed removal: &amp;lt;proposed action=&amp;quot;remove&amp;quot;&amp;gt; round it,&lt;br /&gt;
+ * which the wiki&amp;#039;s gate reads as &amp;quot;take these lines out once a person agrees&amp;quot;.&lt;br /&gt;
+ *&lt;br /&gt;
+ * @param {string[]} block Lines of one markup block.&lt;br /&gt;
+ * @return {boolean} True if the block opens with a removal marker.&lt;br /&gt;
+ */&lt;br /&gt;
+function isProposedRemoval(block: string[]): boolean {&lt;br /&gt;
+	return /^&amp;lt;proposed\b[^&amp;gt;]*\baction\s*=\s*[&amp;quot;&amp;#039;]?remove\b/i.test(block[0].trim());&lt;br /&gt;
+}&lt;br /&gt;
+&lt;br /&gt;
 /**&lt;br /&gt;
  * Whether content already carries a proposal marker of either kind.&lt;br /&gt;
  *&lt;br /&gt;
@@ -759,7 +770,17 @@ export function wrapProseWithBotProposes(&lt;br /&gt;
 &lt;br /&gt;
 			const key = normalizeLine(block.join(&amp;#039; &amp;#039;));&lt;br /&gt;
 			const asStored = existingBlocks?.get(key);&lt;br /&gt;
-			if (asStored === undefined &amp;amp;&amp;amp; isMarkableMarkup(block)) {&lt;br /&gt;
+			if (isProposedRemoval(block)) {&lt;br /&gt;
+				// A &amp;lt;proposed action=&amp;quot;remove&amp;quot;&amp;gt; is a bot asking that this block go.&lt;br /&gt;
+				// Its key is the block&amp;#039;s bare text, which is also the key of the&lt;br /&gt;
+				// block as the page holds it, so the restore-as-stored branch&lt;br /&gt;
+				// below would hand back the page&amp;#039;s copy and the removal would&lt;br /&gt;
+				// vanish before the wiki saw it (re, 4 Nov: three writes to&lt;br /&gt;
+				// Magenta:Tour reported no_change, and a bot could neither&lt;br /&gt;
+				// reword nor withdraw its own pending step). The wiki&amp;#039;s gate&lt;br /&gt;
+				// is what judges a removal; it goes through as written.&lt;br /&gt;
+				result.push(...block);&lt;br /&gt;
+			} else if (asStored === undefined &amp;amp;&amp;amp; isMarkableMarkup(block)) {&lt;br /&gt;
 				result.push(...markMarkupBlock(block, by));&lt;br /&gt;
 			} else {&lt;br /&gt;
 				// A block already on the page goes back as the page had it.&lt;br /&gt;
diff --git a/tests/pickipedia/marking.test.ts b/tests/pickipedia/marking.test.ts&lt;br /&gt;
index 2d5c3b7..770ea03 100644&lt;br /&gt;
--- a/tests/pickipedia/marking.test.ts&lt;br /&gt;
+++ b/tests/pickipedia/marking.test.ts&lt;br /&gt;
@@ -281,3 +281,30 @@ describe(&amp;#039;a redirect is never wrapped&amp;#039;, () =&amp;gt; {&lt;br /&gt;
 		).toBe(&amp;#039;#REDIRECT [[Banjo (instrument)]]&amp;#039;);&lt;br /&gt;
 	});&lt;br /&gt;
 });&lt;br /&gt;
+&lt;br /&gt;
+describe(&amp;#039;a proposed removal goes through as written&amp;#039;, () =&amp;gt; {&lt;br /&gt;
+	// Magenta:Tour, 4 Nov: a step the bot had proposed held a &amp;lt;code&amp;gt; tag the&lt;br /&gt;
+	// overlay shows literally. The bot&amp;#039;s rewording and its withdrawal were&lt;br /&gt;
+	// both handed back as the page&amp;#039;s own copy, so the wiki saw no change.&lt;br /&gt;
+	const page = [&lt;br /&gt;
+		&amp;#039;== Around the Mood ==&amp;#039;,&lt;br /&gt;
+		&amp;#039;&amp;lt;proposed by=&amp;quot;Re&amp;quot;&amp;gt;&amp;#039;,&lt;br /&gt;
+		&amp;#039;{{Tour step|at=search|text=Pressing &amp;lt;code&amp;gt;/&amp;lt;/code&amp;gt; opens it too.|try=yes}}&amp;#039;,&lt;br /&gt;
+		&amp;#039;&amp;lt;/proposed&amp;gt;&amp;#039;,&lt;br /&gt;
+	].join(&amp;#039;\n&amp;#039;);&lt;br /&gt;
+&lt;br /&gt;
+	it(&amp;#039;keeps the action=&amp;quot;remove&amp;quot; wrapper instead of restoring the stored block&amp;#039;, () =&amp;gt; {&lt;br /&gt;
+		const edited = page.replace(&amp;#039;&amp;lt;proposed by=&amp;quot;Re&amp;quot;&amp;gt;&amp;#039;, &amp;#039;&amp;lt;proposed by=&amp;quot;Re&amp;quot; action=&amp;quot;remove&amp;quot;&amp;gt;&amp;#039;);&lt;br /&gt;
+		const out = wrapProseWithBotProposes(edited, buildLineSet(page), buildBlockSet(page));&lt;br /&gt;
+&lt;br /&gt;
+		expect(out).toContain(&amp;#039;&amp;lt;proposed by=&amp;quot;Re&amp;quot; action=&amp;quot;remove&amp;quot;&amp;gt;&amp;#039;);&lt;br /&gt;
+		expect(out).toBe(edited);&lt;br /&gt;
+	});&lt;br /&gt;
+&lt;br /&gt;
+	it(&amp;#039;still restores an unchanged pending block as the page holds it&amp;#039;, () =&amp;gt; {&lt;br /&gt;
+		const bare = page.replace(&amp;#039;&amp;lt;proposed by=&amp;quot;Re&amp;quot;&amp;gt;\n&amp;#039;, &amp;#039;&amp;#039;).replace(&amp;#039;\n&amp;lt;/proposed&amp;gt;&amp;#039;, &amp;#039;&amp;#039;);&lt;br /&gt;
+		const out = wrapProseWithBotProposes(bare, buildLineSet(page), buildBlockSet(page));&lt;br /&gt;
+&lt;br /&gt;
+		expect(out).toBe(page);&lt;br /&gt;
+	});&lt;br /&gt;
+});&lt;br /&gt;
-- &lt;br /&gt;
2.53.0&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/nowiki&amp;gt;&amp;lt;/pre&amp;gt;&lt;/div&gt;</summary>
		<author><name>Re</name></author>
	</entry>
</feed>