<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.okc.jayshapiro.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jay</id>
	<title>Pwani 2050 Commons - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.okc.jayshapiro.com/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Jay"/>
	<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/wiki/Special:Contributions/Jay"/>
	<updated>2026-09-17T04:06:15Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.9</generator>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=Blue_economy&amp;diff=113</id>
		<title>Blue economy</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=Blue_economy&amp;diff=113"/>
		<updated>2026-09-17T04:05:33Z</updated>

		<summary type="html">&lt;p&gt;Jay: With the author&amp;#039;s assistant: Explain that the &amp;quot;blue economy&amp;quot; is actually about ocean based/adjacent economic activities of some sort&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Seeded|source=the Pwani 2050 topic schema (no source document yet)|date=2026-09-17}}&lt;br /&gt;
{{Infobox topic&lt;br /&gt;
| name = Blue economy&lt;br /&gt;
| kind = sector&lt;br /&gt;
| pillar = Blue economy, ports and logistics&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Blue economy&#039;&#039;&#039; (Kiswahili: &#039;&#039;Uchumi wa bahari&#039;&#039;): economic activity that is based on or adjacent to the ocean, including fisheries, aquaculture, marine conservation, and coastal and marine resources.&lt;br /&gt;
&lt;br /&gt;
== What this page is for ==&lt;br /&gt;
A hub for everything the plan says and the community knows about blue economy on the coast. Link the organisations, projects, datasets and places that belong here, and record each stakeholder&#039;s position on contested questions so they can be read side by side.&lt;br /&gt;
&lt;br /&gt;
== Coverage the plan expects ==&lt;br /&gt;
* artisanal fisheries&lt;br /&gt;
* aquaculture and mariculture&lt;br /&gt;
* fish landing sites and cold chain&lt;br /&gt;
* marine protected areas&lt;br /&gt;
* mangroves and blue carbon&lt;br /&gt;
* seaweed farming&lt;br /&gt;
* deep sea fishing licensing&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
No sources yet.&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=112</id>
		<title>MediaWiki:Gadget-AuthorAssistant.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=112"/>
		<updated>2026-09-17T04:00:33Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* The author&#039;s assistant (PRD 5.7, ADR D9).&lt;br /&gt;
   Drafts a change to the current page from your instruction and the sources you name, shows the&lt;br /&gt;
   diff, and saves only when you click, through your own session under your own name. The service&lt;br /&gt;
   at /assistant/ holds no credential; it confirms who you are from this session and drafts. */&lt;br /&gt;
$( function () {&lt;br /&gt;
	var ns = mw.config.get( &#039;wgNamespaceNumber&#039; );&lt;br /&gt;
	var title = mw.config.get( &#039;wgPageName&#039; ).replace( /_/g, &#039; &#039; );&lt;br /&gt;
	var action = mw.config.get( &#039;wgAction&#039; );&lt;br /&gt;
	// On a view page the assistant saves as you; on the source editor it puts the draft into the&lt;br /&gt;
	// editor so you save with the normal form. In the visual editor, switch to source editing first.&lt;br /&gt;
	var editing = ( action === &#039;edit&#039; || action === &#039;submit&#039; ) &amp;amp;&amp;amp; $( &#039;#wpTextbox1&#039; ).length &amp;gt; 0;&lt;br /&gt;
	if ( ( ns !== 0 &amp;amp;&amp;amp; ns !== 6 ) || ( action !== &#039;view&#039; &amp;amp;&amp;amp; !editing ) || !mw.config.get( &#039;wgUserName&#039; ) ) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	var api = new mw.Api();&lt;br /&gt;
	var root = $( &#039;&amp;lt;div id=&amp;quot;okc-assistant&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var panel = $( &#039;&amp;lt;div class=&amp;quot;okc-panel&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var openBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-open&amp;quot;&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; );&lt;br /&gt;
	var instruction = $( &#039;&amp;lt;textarea rows=&amp;quot;4&amp;quot; placeholder=&amp;quot;What should change on this page? For example: add these two sources under the Sources heading, or fill in the population from the source below.&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var urls = $( &#039;&amp;lt;input type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Optional: web addresses to draw on, separated by spaces&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var draftBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( &#039;Draft the change&#039; );&lt;br /&gt;
	var status = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var result = $( &#039;&amp;lt;div&amp;gt;&#039; ).hide();&lt;br /&gt;
	var explanation = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var warn = $( &#039;&amp;lt;div class=&amp;quot;okc-warn&amp;quot;&amp;gt;&#039; ).hide();&lt;br /&gt;
	var diff = $( &#039;&amp;lt;div class=&amp;quot;okc-diff&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var saveBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( editing ? &#039;Put this in the editor&#039; : &#039;Save this as my edit&#039; );&lt;br /&gt;
	var discardBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-secondary&amp;quot; style=&amp;quot;margin-left:8px&amp;quot;&amp;gt;&#039; ).text( &#039;Discard&#039; );&lt;br /&gt;
	var proposal = null;&lt;br /&gt;
&lt;br /&gt;
	panel.append(&lt;br /&gt;
		$( &#039;&amp;lt;h3&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; ),&lt;br /&gt;
		$( &#039;&amp;lt;p&amp;gt;&#039; ).text( &#039;Tell it what to change. You will see the diff before anything is saved, and the edit will be yours: your name, your responsibility, still needing a reviewer’s approval.&#039; ),&lt;br /&gt;
		instruction, urls, draftBtn, status,&lt;br /&gt;
		result.append( explanation, warn, diff, saveBtn, discardBtn,&lt;br /&gt;
			$( &#039;&amp;lt;p class=&amp;quot;okc-note&amp;quot;&amp;gt;&#039; ).text( &#039;The edit summary will say the assistant helped and name any sources used.&#039; ) )&lt;br /&gt;
	);&lt;br /&gt;
	root.append( panel, openBtn );&lt;br /&gt;
	$( &#039;body&#039; ).append( root );&lt;br /&gt;
&lt;br /&gt;
	// In the visual editor the assistant works on the saved page and saves as you, then reopens&lt;br /&gt;
	// the editor on the new revision. Unsaved visual edits would be lost, so it refuses while there are any.&lt;br /&gt;
	function veUnsaved() {&lt;br /&gt;
		try {&lt;br /&gt;
			return $( &#039;html&#039; ).hasClass( &#039;ve-active&#039; ) &amp;amp;&amp;amp; ve.init.target.getSurface().getModel().hasBeenModified();&lt;br /&gt;
		} catch ( e ) { return false; }&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	openBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		root.toggleClass( &#039;okc-is-open&#039; );&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) &amp;amp;&amp;amp; $( &#039;html&#039; ).hasClass( &#039;ve-active&#039; ) ) {&lt;br /&gt;
			status.text( veUnsaved()&lt;br /&gt;
				? &#039;You have unsaved changes in the visual editor. Save or discard them first; the assistant works on the saved page.&#039;&lt;br /&gt;
				: &#039;In the visual editor the assistant works on the saved page and saves the result as your edit, then reopens the editor.&#039; );&lt;br /&gt;
		}&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) ) {&lt;br /&gt;
			fetch( &#039;/assistant/whoami&#039;, { credentials: &#039;same-origin&#039; } ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { status.text( r.status === 404 ? &#039;The assistant is switched off on this instance.&#039; : &#039;Please log in to use the assistant.&#039; ); draftBtn.prop( &#039;disabled&#039;, true ); }&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	draftBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		var text = instruction.val().trim();&lt;br /&gt;
		if ( !text ) { status.text( &#039;Say what should change.&#039; ); return; }&lt;br /&gt;
		if ( veUnsaved() ) { status.text( &#039;You have unsaved changes in the visual editor. Save or discard them first; the assistant works on the saved page.&#039; ); return; }&lt;br /&gt;
		status.text( &#039;Reading the page and drafting…&#039; );&lt;br /&gt;
		draftBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		result.hide();&lt;br /&gt;
		var current = editing&lt;br /&gt;
			? $.Deferred().resolve( { wikitext: $( &#039;#wpTextbox1&#039; ).val(), revid: undefined } ).promise()&lt;br /&gt;
			: api.get( { action: &#039;query&#039;, prop: &#039;revisions&#039;, rvprop: &#039;content|ids&#039;, rvslots: &#039;main&#039;, titles: title, formatversion: 2 } ).then( function ( data ) {&lt;br /&gt;
				var page = data.query.pages[ 0 ];&lt;br /&gt;
				var rev = page.revisions &amp;amp;&amp;amp; page.revisions[ 0 ];&lt;br /&gt;
				return { wikitext: rev ? rev.slots.main.content : &#039;&#039;, revid: rev ? rev.revid : undefined };&lt;br /&gt;
			} );&lt;br /&gt;
		current.then( function ( cur ) {&lt;br /&gt;
			var wikitext = cur.wikitext;&lt;br /&gt;
			var rev = { revid: cur.revid };&lt;br /&gt;
			return fetch( &#039;/assistant/draft&#039;, {&lt;br /&gt;
				method: &#039;POST&#039;, credentials: &#039;same-origin&#039;,&lt;br /&gt;
				headers: { &#039;content-type&#039;: &#039;application/json&#039; },&lt;br /&gt;
				body: JSON.stringify( { title: title, wikitext: wikitext, instruction: text, urls: urls.val().split( /\s+/ ).filter( Boolean ) } )&lt;br /&gt;
			} ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { return r.json().then( function ( e ) { throw new Error( e.detail || r.status ); } ); }&lt;br /&gt;
				return r.json();&lt;br /&gt;
			} ).then( function ( d ) {&lt;br /&gt;
				proposal = { wikitext: d.wikitext, summary: d.summary, baserevid: rev ? rev.revid : undefined };&lt;br /&gt;
				// nothing to save when the assistant proposed no change (it asked a question instead)&lt;br /&gt;
				saveBtn.prop( &#039;disabled&#039;, d.wikitext.trim() === wikitext.trim() );&lt;br /&gt;
				explanation.text( d.explanation );&lt;br /&gt;
				if ( d.warning ) { warn.text( d.warning ).show(); } else { warn.hide(); }&lt;br /&gt;
				return api.post( { action: &#039;compare&#039;, fromslots: &#039;main&#039;, &#039;fromtext-main&#039;: wikitext, &#039;fromcontentmodel-main&#039;: &#039;wikitext&#039;, toslots: &#039;main&#039;, &#039;totext-main&#039;: d.wikitext, &#039;tocontentmodel-main&#039;: &#039;wikitext&#039;, prop: &#039;diff&#039;, formatversion: 2 } ).then( function ( c ) {&lt;br /&gt;
					var body = c.compare.body || c.compare[ &#039;*&#039; ] || &#039;&#039;;&lt;br /&gt;
					diff.html( body ? &#039;&amp;lt;table class=&amp;quot;diff&amp;quot;&amp;gt;&amp;lt;colgroup&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;/colgroup&amp;gt;&#039; + body + &#039;&amp;lt;/table&amp;gt;&#039; : &#039;&amp;lt;p&amp;gt;No difference.&amp;lt;/p&amp;gt;&#039; );&lt;br /&gt;
					status.text( d.sources.length ? &#039;Sources used: &#039; + d.sources.join( &#039;, &#039; ) : &#039;Drafted.&#039; );&lt;br /&gt;
					result.show();&lt;br /&gt;
				} );&lt;br /&gt;
			} );&lt;br /&gt;
		} ).catch( function ( e ) {&lt;br /&gt;
			status.text( &#039;The assistant could not draft that: &#039; + ( e &amp;amp;&amp;amp; e.message ? e.message : e ) );&lt;br /&gt;
		} ).always( function () { draftBtn.prop( &#039;disabled&#039;, false ); } );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	saveBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		if ( !proposal ) { return; }&lt;br /&gt;
		if ( editing ) {&lt;br /&gt;
			$( &#039;#wpTextbox1&#039; ).val( proposal.wikitext );&lt;br /&gt;
			var summary = $( &#039;#wpSummary&#039; );&lt;br /&gt;
			if ( summary.length &amp;amp;&amp;amp; !summary.val() ) { summary.val( proposal.summary ); }&lt;br /&gt;
			status.text( &#039;The draft is in the editor. Review it and save with the normal button; the edit will be yours.&#039; );&lt;br /&gt;
			result.hide();&lt;br /&gt;
			root.removeClass( &#039;okc-is-open&#039; );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		saveBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		status.text( &#039;Saving as &#039; + mw.config.get( &#039;wgUserName&#039; ) + &#039;…&#039; );&lt;br /&gt;
		api.postWithToken( &#039;csrf&#039;, { action: &#039;edit&#039;, title: title, text: proposal.wikitext, summary: proposal.summary, baserevid: proposal.baserevid, formatversion: 2 } ).then( function () {&lt;br /&gt;
			if ( $( &#039;html&#039; ).hasClass( &#039;ve-active&#039; ) ) {&lt;br /&gt;
				location.href = mw.util.getUrl( title, { veaction: &#039;edit&#039; } );&lt;br /&gt;
			} else {&lt;br /&gt;
				location.reload();&lt;br /&gt;
			}&lt;br /&gt;
		}, function ( code, e ) {&lt;br /&gt;
			status.text( &#039;Save failed: &#039; + ( e &amp;amp;&amp;amp; e.error ? e.error.info : code ) );&lt;br /&gt;
			saveBtn.prop( &#039;disabled&#039;, false );&lt;br /&gt;
		} );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	discardBtn.on( &#039;click&#039;, function () { proposal = null; result.hide(); status.text( &#039;Discarded. Nothing was saved.&#039; ); } );&lt;br /&gt;
} );&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=111</id>
		<title>MediaWiki:Gadget-AuthorAssistant.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=111"/>
		<updated>2026-09-17T03:58:35Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* The author&#039;s assistant (PRD 5.7, ADR D9).&lt;br /&gt;
   Drafts a change to the current page from your instruction and the sources you name, shows the&lt;br /&gt;
   diff, and saves only when you click, through your own session under your own name. The service&lt;br /&gt;
   at /assistant/ holds no credential; it confirms who you are from this session and drafts. */&lt;br /&gt;
$( function () {&lt;br /&gt;
	var ns = mw.config.get( &#039;wgNamespaceNumber&#039; );&lt;br /&gt;
	var title = mw.config.get( &#039;wgPageName&#039; ).replace( /_/g, &#039; &#039; );&lt;br /&gt;
	var action = mw.config.get( &#039;wgAction&#039; );&lt;br /&gt;
	// On a view page the assistant saves as you; on the source editor it puts the draft into the&lt;br /&gt;
	// editor so you save with the normal form. In the visual editor, switch to source editing first.&lt;br /&gt;
	var editing = ( action === &#039;edit&#039; || action === &#039;submit&#039; ) &amp;amp;&amp;amp; $( &#039;#wpTextbox1&#039; ).length &amp;gt; 0;&lt;br /&gt;
	if ( ( ns !== 0 &amp;amp;&amp;amp; ns !== 6 ) || ( action !== &#039;view&#039; &amp;amp;&amp;amp; !editing ) || !mw.config.get( &#039;wgUserName&#039; ) ) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	var api = new mw.Api();&lt;br /&gt;
	var root = $( &#039;&amp;lt;div id=&amp;quot;okc-assistant&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var panel = $( &#039;&amp;lt;div class=&amp;quot;okc-panel&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var openBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-open&amp;quot;&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; );&lt;br /&gt;
	var instruction = $( &#039;&amp;lt;textarea rows=&amp;quot;4&amp;quot; placeholder=&amp;quot;What should change on this page? For example: add these two sources under the Sources heading, or fill in the population from the source below.&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var urls = $( &#039;&amp;lt;input type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Optional: web addresses to draw on, separated by spaces&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var draftBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( &#039;Draft the change&#039; );&lt;br /&gt;
	var status = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var result = $( &#039;&amp;lt;div&amp;gt;&#039; ).hide();&lt;br /&gt;
	var explanation = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var warn = $( &#039;&amp;lt;div class=&amp;quot;okc-warn&amp;quot;&amp;gt;&#039; ).hide();&lt;br /&gt;
	var diff = $( &#039;&amp;lt;div class=&amp;quot;okc-diff&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var saveBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( editing ? &#039;Put this in the editor&#039; : &#039;Save this as my edit&#039; );&lt;br /&gt;
	var discardBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-secondary&amp;quot; style=&amp;quot;margin-left:8px&amp;quot;&amp;gt;&#039; ).text( &#039;Discard&#039; );&lt;br /&gt;
	var proposal = null;&lt;br /&gt;
&lt;br /&gt;
	panel.append(&lt;br /&gt;
		$( &#039;&amp;lt;h3&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; ),&lt;br /&gt;
		$( &#039;&amp;lt;p&amp;gt;&#039; ).text( &#039;Tell it what to change. You will see the diff before anything is saved, and the edit will be yours: your name, your responsibility, still needing a reviewer’s approval.&#039; ),&lt;br /&gt;
		instruction, urls, draftBtn, status,&lt;br /&gt;
		result.append( explanation, warn, diff, saveBtn, discardBtn,&lt;br /&gt;
			$( &#039;&amp;lt;p class=&amp;quot;okc-note&amp;quot;&amp;gt;&#039; ).text( &#039;The edit summary will say the assistant helped and name any sources used.&#039; ) )&lt;br /&gt;
	);&lt;br /&gt;
	root.append( panel, openBtn );&lt;br /&gt;
	$( &#039;body&#039; ).append( root );&lt;br /&gt;
&lt;br /&gt;
	// In the visual editor the assistant works on the saved page and saves as you, then reopens&lt;br /&gt;
	// the editor on the new revision. Unsaved visual edits would be lost, so it refuses while there are any.&lt;br /&gt;
	function veUnsaved() {&lt;br /&gt;
		try {&lt;br /&gt;
			return $( &#039;html&#039; ).hasClass( &#039;ve-active&#039; ) &amp;amp;&amp;amp; ve.init.target.getSurface().getModel().hasBeenModified();&lt;br /&gt;
		} catch ( e ) { return false; }&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	openBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		root.toggleClass( &#039;okc-is-open&#039; );&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) &amp;amp;&amp;amp; $( &#039;html&#039; ).hasClass( &#039;ve-active&#039; ) ) {&lt;br /&gt;
			status.text( veUnsaved()&lt;br /&gt;
				? &#039;You have unsaved changes in the visual editor. Save or discard them first; the assistant works on the saved page.&#039;&lt;br /&gt;
				: &#039;In the visual editor the assistant works on the saved page and saves the result as your edit, then reopens the editor.&#039; );&lt;br /&gt;
		}&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) ) {&lt;br /&gt;
			fetch( &#039;/assistant/whoami&#039;, { credentials: &#039;same-origin&#039; } ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { status.text( r.status === 404 ? &#039;The assistant is switched off on this instance.&#039; : &#039;Please log in to use the assistant.&#039; ); draftBtn.prop( &#039;disabled&#039;, true ); }&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	draftBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		var text = instruction.val().trim();&lt;br /&gt;
		if ( !text ) { status.text( &#039;Say what should change.&#039; ); return; }&lt;br /&gt;
		if ( veUnsaved() ) { status.text( &#039;You have unsaved changes in the visual editor. Save or discard them first; the assistant works on the saved page.&#039; ); return; }&lt;br /&gt;
		status.text( &#039;Reading the page and drafting…&#039; );&lt;br /&gt;
		draftBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		result.hide();&lt;br /&gt;
		var current = editing&lt;br /&gt;
			? $.Deferred().resolve( { wikitext: $( &#039;#wpTextbox1&#039; ).val(), revid: undefined } ).promise()&lt;br /&gt;
			: api.get( { action: &#039;query&#039;, prop: &#039;revisions&#039;, rvprop: &#039;content|ids&#039;, rvslots: &#039;main&#039;, titles: title, formatversion: 2 } ).then( function ( data ) {&lt;br /&gt;
				var page = data.query.pages[ 0 ];&lt;br /&gt;
				var rev = page.revisions &amp;amp;&amp;amp; page.revisions[ 0 ];&lt;br /&gt;
				return { wikitext: rev ? rev.slots.main.content : &#039;&#039;, revid: rev ? rev.revid : undefined };&lt;br /&gt;
			} );&lt;br /&gt;
		current.then( function ( cur ) {&lt;br /&gt;
			var wikitext = cur.wikitext;&lt;br /&gt;
			var rev = { revid: cur.revid };&lt;br /&gt;
			return fetch( &#039;/assistant/draft&#039;, {&lt;br /&gt;
				method: &#039;POST&#039;, credentials: &#039;same-origin&#039;,&lt;br /&gt;
				headers: { &#039;content-type&#039;: &#039;application/json&#039; },&lt;br /&gt;
				body: JSON.stringify( { title: title, wikitext: wikitext, instruction: text, urls: urls.val().split( /\s+/ ).filter( Boolean ) } )&lt;br /&gt;
			} ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { return r.json().then( function ( e ) { throw new Error( e.detail || r.status ); } ); }&lt;br /&gt;
				return r.json();&lt;br /&gt;
			} ).then( function ( d ) {&lt;br /&gt;
				proposal = { wikitext: d.wikitext, summary: d.summary, baserevid: rev ? rev.revid : undefined };&lt;br /&gt;
				explanation.text( d.explanation );&lt;br /&gt;
				if ( d.warning ) { warn.text( d.warning ).show(); } else { warn.hide(); }&lt;br /&gt;
				return api.post( { action: &#039;compare&#039;, fromslots: &#039;main&#039;, &#039;fromtext-main&#039;: wikitext, &#039;fromcontentmodel-main&#039;: &#039;wikitext&#039;, toslots: &#039;main&#039;, &#039;totext-main&#039;: d.wikitext, &#039;tocontentmodel-main&#039;: &#039;wikitext&#039;, prop: &#039;diff&#039;, formatversion: 2 } ).then( function ( c ) {&lt;br /&gt;
					var body = c.compare.body || c.compare[ &#039;*&#039; ] || &#039;&#039;;&lt;br /&gt;
					diff.html( body ? &#039;&amp;lt;table class=&amp;quot;diff&amp;quot;&amp;gt;&amp;lt;colgroup&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;/colgroup&amp;gt;&#039; + body + &#039;&amp;lt;/table&amp;gt;&#039; : &#039;&amp;lt;p&amp;gt;No difference.&amp;lt;/p&amp;gt;&#039; );&lt;br /&gt;
					status.text( d.sources.length ? &#039;Sources used: &#039; + d.sources.join( &#039;, &#039; ) : &#039;Drafted.&#039; );&lt;br /&gt;
					result.show();&lt;br /&gt;
				} );&lt;br /&gt;
			} );&lt;br /&gt;
		} ).catch( function ( e ) {&lt;br /&gt;
			status.text( &#039;The assistant could not draft that: &#039; + ( e &amp;amp;&amp;amp; e.message ? e.message : e ) );&lt;br /&gt;
		} ).always( function () { draftBtn.prop( &#039;disabled&#039;, false ); } );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	saveBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		if ( !proposal ) { return; }&lt;br /&gt;
		if ( editing ) {&lt;br /&gt;
			$( &#039;#wpTextbox1&#039; ).val( proposal.wikitext );&lt;br /&gt;
			var summary = $( &#039;#wpSummary&#039; );&lt;br /&gt;
			if ( summary.length &amp;amp;&amp;amp; !summary.val() ) { summary.val( proposal.summary ); }&lt;br /&gt;
			status.text( &#039;The draft is in the editor. Review it and save with the normal button; the edit will be yours.&#039; );&lt;br /&gt;
			result.hide();&lt;br /&gt;
			root.removeClass( &#039;okc-is-open&#039; );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		saveBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		status.text( &#039;Saving as &#039; + mw.config.get( &#039;wgUserName&#039; ) + &#039;…&#039; );&lt;br /&gt;
		api.postWithToken( &#039;csrf&#039;, { action: &#039;edit&#039;, title: title, text: proposal.wikitext, summary: proposal.summary, baserevid: proposal.baserevid, formatversion: 2 } ).then( function () {&lt;br /&gt;
			if ( $( &#039;html&#039; ).hasClass( &#039;ve-active&#039; ) ) {&lt;br /&gt;
				location.href = mw.util.getUrl( title, { veaction: &#039;edit&#039; } );&lt;br /&gt;
			} else {&lt;br /&gt;
				location.reload();&lt;br /&gt;
			}&lt;br /&gt;
		}, function ( code, e ) {&lt;br /&gt;
			status.text( &#039;Save failed: &#039; + ( e &amp;amp;&amp;amp; e.error ? e.error.info : code ) );&lt;br /&gt;
			saveBtn.prop( &#039;disabled&#039;, false );&lt;br /&gt;
		} );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	discardBtn.on( &#039;click&#039;, function () { proposal = null; result.hide(); status.text( &#039;Discarded. Nothing was saved.&#039; ); } );&lt;br /&gt;
} );&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.css&amp;diff=110</id>
		<title>MediaWiki:Gadget-AuthorAssistant.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.css&amp;diff=110"/>
		<updated>2026-09-17T03:58:34Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* The author&#039;s assistant panel (PRD 5.7). */&lt;br /&gt;
#okc-assistant { position: fixed; right: 16px; bottom: 16px; z-index: 1000; font-size: 14px; }&lt;br /&gt;
#okc-assistant .okc-open { background: #0c6a8c; color: #fff; border: 0; border-radius: 999px; padding: 9px 16px; font-weight: 600; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.15); }&lt;br /&gt;
#okc-assistant .okc-panel { display: none; width: min(560px, calc(100vw - 32px)); max-height: 80vh; overflow: auto; background: #fff; color: #1d2a30; border: 1px solid #dfe6e8; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,.18); padding: 14px 16px; margin-bottom: 8px; }&lt;br /&gt;
#okc-assistant.okc-is-open .okc-panel { display: block; }&lt;br /&gt;
#okc-assistant h3 { margin: 0 0 6px; font-size: 16px; }&lt;br /&gt;
#okc-assistant p { margin: 0 0 8px; color: #4d5c63; }&lt;br /&gt;
#okc-assistant textarea, #okc-assistant input[type=text] { width: 100%; box-sizing: border-box; font: inherit; padding: 8px; border: 1px solid #dfe6e8; border-radius: 8px; margin-bottom: 8px; }&lt;br /&gt;
#okc-assistant button.okc-primary { background: #0c6a8c; color: #fff; border: 0; border-radius: 8px; padding: 8px 14px; font-weight: 600; cursor: pointer; }&lt;br /&gt;
#okc-assistant button.okc-secondary { background: #f3f3f3; color: #1d2a30; border: 1px solid #dfe6e8; border-radius: 8px; padding: 8px 14px; cursor: pointer; }&lt;br /&gt;
#okc-assistant .okc-diff { margin: 10px 0; max-height: 40vh; overflow: auto; border: 1px solid #dfe6e8; border-radius: 8px; padding: 6px; font-size: 13px; }&lt;br /&gt;
#okc-assistant .okc-diff table.diff { width: 100%; }&lt;br /&gt;
#okc-assistant .okc-warn { background: #f3e9cd; border-radius: 8px; padding: 8px 10px; margin: 8px 0; }&lt;br /&gt;
#okc-assistant .okc-note { font-size: 12px; color: #4d5c63; margin-top: 8px; }&lt;br /&gt;
#okc-assistant button:disabled { opacity: .5; cursor: default; }&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=109</id>
		<title>MediaWiki:Gadget-AuthorAssistant.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=109"/>
		<updated>2026-09-17T03:52:04Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* The author&#039;s assistant (PRD 5.7, ADR D9).&lt;br /&gt;
   Drafts a change to the current page from your instruction and the sources you name, shows the&lt;br /&gt;
   diff, and saves only when you click, through your own session under your own name. The service&lt;br /&gt;
   at /assistant/ holds no credential; it confirms who you are from this session and drafts. */&lt;br /&gt;
$( function () {&lt;br /&gt;
	var ns = mw.config.get( &#039;wgNamespaceNumber&#039; );&lt;br /&gt;
	var title = mw.config.get( &#039;wgPageName&#039; ).replace( /_/g, &#039; &#039; );&lt;br /&gt;
	var action = mw.config.get( &#039;wgAction&#039; );&lt;br /&gt;
	// On a view page the assistant saves as you; on the source editor it puts the draft into the&lt;br /&gt;
	// editor so you save with the normal form. In the visual editor, switch to source editing first.&lt;br /&gt;
	var editing = ( action === &#039;edit&#039; || action === &#039;submit&#039; ) &amp;amp;&amp;amp; $( &#039;#wpTextbox1&#039; ).length &amp;gt; 0;&lt;br /&gt;
	if ( ( ns !== 0 &amp;amp;&amp;amp; ns !== 6 ) || ( action !== &#039;view&#039; &amp;amp;&amp;amp; !editing ) || !mw.config.get( &#039;wgUserName&#039; ) ) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	var api = new mw.Api();&lt;br /&gt;
	var root = $( &#039;&amp;lt;div id=&amp;quot;okc-assistant&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var panel = $( &#039;&amp;lt;div class=&amp;quot;okc-panel&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var openBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-open&amp;quot;&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; );&lt;br /&gt;
	var instruction = $( &#039;&amp;lt;textarea rows=&amp;quot;4&amp;quot; placeholder=&amp;quot;What should change on this page? For example: add these two sources under the Sources heading, or fill in the population from the source below.&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var urls = $( &#039;&amp;lt;input type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Optional: web addresses to draw on, separated by spaces&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var draftBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( &#039;Draft the change&#039; );&lt;br /&gt;
	var status = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var result = $( &#039;&amp;lt;div&amp;gt;&#039; ).hide();&lt;br /&gt;
	var explanation = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var warn = $( &#039;&amp;lt;div class=&amp;quot;okc-warn&amp;quot;&amp;gt;&#039; ).hide();&lt;br /&gt;
	var diff = $( &#039;&amp;lt;div class=&amp;quot;okc-diff&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var saveBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( editing ? &#039;Put this in the editor&#039; : &#039;Save this as my edit&#039; );&lt;br /&gt;
	var discardBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-secondary&amp;quot; style=&amp;quot;margin-left:8px&amp;quot;&amp;gt;&#039; ).text( &#039;Discard&#039; );&lt;br /&gt;
	var proposal = null;&lt;br /&gt;
&lt;br /&gt;
	panel.append(&lt;br /&gt;
		$( &#039;&amp;lt;h3&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; ),&lt;br /&gt;
		$( &#039;&amp;lt;p&amp;gt;&#039; ).text( &#039;Tell it what to change. You will see the diff before anything is saved, and the edit will be yours: your name, your responsibility, still needing a reviewer’s approval.&#039; ),&lt;br /&gt;
		instruction, urls, draftBtn, status,&lt;br /&gt;
		result.append( explanation, warn, diff, saveBtn, discardBtn,&lt;br /&gt;
			$( &#039;&amp;lt;p class=&amp;quot;okc-note&amp;quot;&amp;gt;&#039; ).text( &#039;The edit summary will say the assistant helped and name any sources used.&#039; ) )&lt;br /&gt;
	);&lt;br /&gt;
	root.append( panel, openBtn );&lt;br /&gt;
	$( &#039;body&#039; ).append( root );&lt;br /&gt;
&lt;br /&gt;
	openBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		root.toggleClass( &#039;okc-is-open&#039; );&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) &amp;amp;&amp;amp; $( &#039;html&#039; ).hasClass( &#039;ve-active&#039; ) ) {&lt;br /&gt;
			status.text( &#039;You are in the visual editor. The assistant drafts wikitext, so use it from the Read view (it saves as your edit) or switch to source editing with the pencil menu (it puts the draft in the editor).&#039; );&lt;br /&gt;
			draftBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		draftBtn.prop( &#039;disabled&#039;, false );&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) ) {&lt;br /&gt;
			fetch( &#039;/assistant/whoami&#039;, { credentials: &#039;same-origin&#039; } ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { status.text( r.status === 404 ? &#039;The assistant is switched off on this instance.&#039; : &#039;Please log in to use the assistant.&#039; ); draftBtn.prop( &#039;disabled&#039;, true ); }&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	draftBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		var text = instruction.val().trim();&lt;br /&gt;
		if ( !text ) { status.text( &#039;Say what should change.&#039; ); return; }&lt;br /&gt;
		status.text( &#039;Reading the page and drafting…&#039; );&lt;br /&gt;
		draftBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		result.hide();&lt;br /&gt;
		var current = editing&lt;br /&gt;
			? $.Deferred().resolve( { wikitext: $( &#039;#wpTextbox1&#039; ).val(), revid: undefined } ).promise()&lt;br /&gt;
			: api.get( { action: &#039;query&#039;, prop: &#039;revisions&#039;, rvprop: &#039;content|ids&#039;, rvslots: &#039;main&#039;, titles: title, formatversion: 2 } ).then( function ( data ) {&lt;br /&gt;
				var page = data.query.pages[ 0 ];&lt;br /&gt;
				var rev = page.revisions &amp;amp;&amp;amp; page.revisions[ 0 ];&lt;br /&gt;
				return { wikitext: rev ? rev.slots.main.content : &#039;&#039;, revid: rev ? rev.revid : undefined };&lt;br /&gt;
			} );&lt;br /&gt;
		current.then( function ( cur ) {&lt;br /&gt;
			var wikitext = cur.wikitext;&lt;br /&gt;
			var rev = { revid: cur.revid };&lt;br /&gt;
			return fetch( &#039;/assistant/draft&#039;, {&lt;br /&gt;
				method: &#039;POST&#039;, credentials: &#039;same-origin&#039;,&lt;br /&gt;
				headers: { &#039;content-type&#039;: &#039;application/json&#039; },&lt;br /&gt;
				body: JSON.stringify( { title: title, wikitext: wikitext, instruction: text, urls: urls.val().split( /\s+/ ).filter( Boolean ) } )&lt;br /&gt;
			} ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { return r.json().then( function ( e ) { throw new Error( e.detail || r.status ); } ); }&lt;br /&gt;
				return r.json();&lt;br /&gt;
			} ).then( function ( d ) {&lt;br /&gt;
				proposal = { wikitext: d.wikitext, summary: d.summary, baserevid: rev ? rev.revid : undefined };&lt;br /&gt;
				explanation.text( d.explanation );&lt;br /&gt;
				if ( d.warning ) { warn.text( d.warning ).show(); } else { warn.hide(); }&lt;br /&gt;
				return api.post( { action: &#039;compare&#039;, fromslots: &#039;main&#039;, &#039;fromtext-main&#039;: wikitext, &#039;fromcontentmodel-main&#039;: &#039;wikitext&#039;, toslots: &#039;main&#039;, &#039;totext-main&#039;: d.wikitext, &#039;tocontentmodel-main&#039;: &#039;wikitext&#039;, prop: &#039;diff&#039;, formatversion: 2 } ).then( function ( c ) {&lt;br /&gt;
					var body = c.compare.body || c.compare[ &#039;*&#039; ] || &#039;&#039;;&lt;br /&gt;
					diff.html( body ? &#039;&amp;lt;table class=&amp;quot;diff&amp;quot;&amp;gt;&amp;lt;colgroup&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;/colgroup&amp;gt;&#039; + body + &#039;&amp;lt;/table&amp;gt;&#039; : &#039;&amp;lt;p&amp;gt;No difference.&amp;lt;/p&amp;gt;&#039; );&lt;br /&gt;
					status.text( d.sources.length ? &#039;Sources used: &#039; + d.sources.join( &#039;, &#039; ) : &#039;Drafted.&#039; );&lt;br /&gt;
					result.show();&lt;br /&gt;
				} );&lt;br /&gt;
			} );&lt;br /&gt;
		} ).catch( function ( e ) {&lt;br /&gt;
			status.text( &#039;The assistant could not draft that: &#039; + ( e &amp;amp;&amp;amp; e.message ? e.message : e ) );&lt;br /&gt;
		} ).always( function () { draftBtn.prop( &#039;disabled&#039;, false ); } );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	saveBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		if ( !proposal ) { return; }&lt;br /&gt;
		if ( editing ) {&lt;br /&gt;
			$( &#039;#wpTextbox1&#039; ).val( proposal.wikitext );&lt;br /&gt;
			var summary = $( &#039;#wpSummary&#039; );&lt;br /&gt;
			if ( summary.length &amp;amp;&amp;amp; !summary.val() ) { summary.val( proposal.summary ); }&lt;br /&gt;
			status.text( &#039;The draft is in the editor. Review it and save with the normal button; the edit will be yours.&#039; );&lt;br /&gt;
			result.hide();&lt;br /&gt;
			root.removeClass( &#039;okc-is-open&#039; );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		saveBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		status.text( &#039;Saving as &#039; + mw.config.get( &#039;wgUserName&#039; ) + &#039;…&#039; );&lt;br /&gt;
		api.postWithToken( &#039;csrf&#039;, { action: &#039;edit&#039;, title: title, text: proposal.wikitext, summary: proposal.summary, baserevid: proposal.baserevid, formatversion: 2 } ).then( function () {&lt;br /&gt;
			location.reload();&lt;br /&gt;
		}, function ( code, e ) {&lt;br /&gt;
			status.text( &#039;Save failed: &#039; + ( e &amp;amp;&amp;amp; e.error ? e.error.info : code ) );&lt;br /&gt;
			saveBtn.prop( &#039;disabled&#039;, false );&lt;br /&gt;
		} );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	discardBtn.on( &#039;click&#039;, function () { proposal = null; result.hide(); status.text( &#039;Discarded. Nothing was saved.&#039; ); } );&lt;br /&gt;
} );&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=99</id>
		<title>MediaWiki:Gadget-AuthorAssistant.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=99"/>
		<updated>2026-09-17T03:45:57Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* The author&#039;s assistant (PRD 5.7, ADR D9).&lt;br /&gt;
   Drafts a change to the current page from your instruction and the sources you name, shows the&lt;br /&gt;
   diff, and saves only when you click, through your own session under your own name. The service&lt;br /&gt;
   at /assistant/ holds no credential; it confirms who you are from this session and drafts. */&lt;br /&gt;
$( function () {&lt;br /&gt;
	var ns = mw.config.get( &#039;wgNamespaceNumber&#039; );&lt;br /&gt;
	var title = mw.config.get( &#039;wgPageName&#039; ).replace( /_/g, &#039; &#039; );&lt;br /&gt;
	var action = mw.config.get( &#039;wgAction&#039; );&lt;br /&gt;
	// On a view page the assistant saves as you; on the source editor it puts the draft into the&lt;br /&gt;
	// editor so you save with the normal form. In the visual editor, switch to source editing first.&lt;br /&gt;
	var editing = ( action === &#039;edit&#039; || action === &#039;submit&#039; ) &amp;amp;&amp;amp; $( &#039;#wpTextbox1&#039; ).length &amp;gt; 0;&lt;br /&gt;
	if ( ( ns !== 0 &amp;amp;&amp;amp; ns !== 6 ) || ( action !== &#039;view&#039; &amp;amp;&amp;amp; !editing ) || !mw.config.get( &#039;wgUserName&#039; ) ) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	var api = new mw.Api();&lt;br /&gt;
	var root = $( &#039;&amp;lt;div id=&amp;quot;okc-assistant&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var panel = $( &#039;&amp;lt;div class=&amp;quot;okc-panel&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var openBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-open&amp;quot;&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; );&lt;br /&gt;
	var instruction = $( &#039;&amp;lt;textarea rows=&amp;quot;4&amp;quot; placeholder=&amp;quot;What should change on this page? For example: add these two sources under the Sources heading, or fill in the population from the source below.&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var urls = $( &#039;&amp;lt;input type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Optional: web addresses to draw on, separated by spaces&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var draftBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( &#039;Draft the change&#039; );&lt;br /&gt;
	var status = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var result = $( &#039;&amp;lt;div&amp;gt;&#039; ).hide();&lt;br /&gt;
	var explanation = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var warn = $( &#039;&amp;lt;div class=&amp;quot;okc-warn&amp;quot;&amp;gt;&#039; ).hide();&lt;br /&gt;
	var diff = $( &#039;&amp;lt;div class=&amp;quot;okc-diff&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var saveBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( editing ? &#039;Put this in the editor&#039; : &#039;Save this as my edit&#039; );&lt;br /&gt;
	var discardBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-secondary&amp;quot; style=&amp;quot;margin-left:8px&amp;quot;&amp;gt;&#039; ).text( &#039;Discard&#039; );&lt;br /&gt;
	var proposal = null;&lt;br /&gt;
&lt;br /&gt;
	panel.append(&lt;br /&gt;
		$( &#039;&amp;lt;h3&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; ),&lt;br /&gt;
		$( &#039;&amp;lt;p&amp;gt;&#039; ).text( &#039;Tell it what to change. You will see the diff before anything is saved, and the edit will be yours: your name, your responsibility, still needing a reviewer’s approval.&#039; ),&lt;br /&gt;
		instruction, urls, draftBtn, status,&lt;br /&gt;
		result.append( explanation, warn, diff, saveBtn, discardBtn,&lt;br /&gt;
			$( &#039;&amp;lt;p class=&amp;quot;okc-note&amp;quot;&amp;gt;&#039; ).text( &#039;The edit summary will say the assistant helped and name any sources used.&#039; ) )&lt;br /&gt;
	);&lt;br /&gt;
	root.append( panel, openBtn );&lt;br /&gt;
	$( &#039;body&#039; ).append( root );&lt;br /&gt;
&lt;br /&gt;
	openBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		root.toggleClass( &#039;okc-is-open&#039; );&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) ) {&lt;br /&gt;
			fetch( &#039;/assistant/whoami&#039;, { credentials: &#039;same-origin&#039; } ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { status.text( r.status === 404 ? &#039;The assistant is switched off on this instance.&#039; : &#039;Please log in to use the assistant.&#039; ); draftBtn.prop( &#039;disabled&#039;, true ); }&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	draftBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		var text = instruction.val().trim();&lt;br /&gt;
		if ( !text ) { status.text( &#039;Say what should change.&#039; ); return; }&lt;br /&gt;
		status.text( &#039;Reading the page and drafting…&#039; );&lt;br /&gt;
		draftBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		result.hide();&lt;br /&gt;
		var current = editing&lt;br /&gt;
			? $.Deferred().resolve( { wikitext: $( &#039;#wpTextbox1&#039; ).val(), revid: undefined } ).promise()&lt;br /&gt;
			: api.get( { action: &#039;query&#039;, prop: &#039;revisions&#039;, rvprop: &#039;content|ids&#039;, rvslots: &#039;main&#039;, titles: title, formatversion: 2 } ).then( function ( data ) {&lt;br /&gt;
				var page = data.query.pages[ 0 ];&lt;br /&gt;
				var rev = page.revisions &amp;amp;&amp;amp; page.revisions[ 0 ];&lt;br /&gt;
				return { wikitext: rev ? rev.slots.main.content : &#039;&#039;, revid: rev ? rev.revid : undefined };&lt;br /&gt;
			} );&lt;br /&gt;
		current.then( function ( cur ) {&lt;br /&gt;
			var wikitext = cur.wikitext;&lt;br /&gt;
			var rev = { revid: cur.revid };&lt;br /&gt;
			return fetch( &#039;/assistant/draft&#039;, {&lt;br /&gt;
				method: &#039;POST&#039;, credentials: &#039;same-origin&#039;,&lt;br /&gt;
				headers: { &#039;content-type&#039;: &#039;application/json&#039; },&lt;br /&gt;
				body: JSON.stringify( { title: title, wikitext: wikitext, instruction: text, urls: urls.val().split( /\s+/ ).filter( Boolean ) } )&lt;br /&gt;
			} ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { return r.json().then( function ( e ) { throw new Error( e.detail || r.status ); } ); }&lt;br /&gt;
				return r.json();&lt;br /&gt;
			} ).then( function ( d ) {&lt;br /&gt;
				proposal = { wikitext: d.wikitext, summary: d.summary, baserevid: rev ? rev.revid : undefined };&lt;br /&gt;
				explanation.text( d.explanation );&lt;br /&gt;
				if ( d.warning ) { warn.text( d.warning ).show(); } else { warn.hide(); }&lt;br /&gt;
				return api.post( { action: &#039;compare&#039;, fromslots: &#039;main&#039;, &#039;fromtext-main&#039;: wikitext, &#039;fromcontentmodel-main&#039;: &#039;wikitext&#039;, toslots: &#039;main&#039;, &#039;totext-main&#039;: d.wikitext, &#039;tocontentmodel-main&#039;: &#039;wikitext&#039;, prop: &#039;diff&#039;, formatversion: 2 } ).then( function ( c ) {&lt;br /&gt;
					var body = c.compare.body || c.compare[ &#039;*&#039; ] || &#039;&#039;;&lt;br /&gt;
					diff.html( body ? &#039;&amp;lt;table class=&amp;quot;diff&amp;quot;&amp;gt;&amp;lt;colgroup&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;/colgroup&amp;gt;&#039; + body + &#039;&amp;lt;/table&amp;gt;&#039; : &#039;&amp;lt;p&amp;gt;No difference.&amp;lt;/p&amp;gt;&#039; );&lt;br /&gt;
					status.text( d.sources.length ? &#039;Sources used: &#039; + d.sources.join( &#039;, &#039; ) : &#039;Drafted.&#039; );&lt;br /&gt;
					result.show();&lt;br /&gt;
				} );&lt;br /&gt;
			} );&lt;br /&gt;
		} ).catch( function ( e ) {&lt;br /&gt;
			status.text( &#039;The assistant could not draft that: &#039; + ( e &amp;amp;&amp;amp; e.message ? e.message : e ) );&lt;br /&gt;
		} ).always( function () { draftBtn.prop( &#039;disabled&#039;, false ); } );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	saveBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		if ( !proposal ) { return; }&lt;br /&gt;
		if ( editing ) {&lt;br /&gt;
			$( &#039;#wpTextbox1&#039; ).val( proposal.wikitext );&lt;br /&gt;
			var summary = $( &#039;#wpSummary&#039; );&lt;br /&gt;
			if ( summary.length &amp;amp;&amp;amp; !summary.val() ) { summary.val( proposal.summary ); }&lt;br /&gt;
			status.text( &#039;The draft is in the editor. Review it and save with the normal button; the edit will be yours.&#039; );&lt;br /&gt;
			result.hide();&lt;br /&gt;
			root.removeClass( &#039;okc-is-open&#039; );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		saveBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		status.text( &#039;Saving as &#039; + mw.config.get( &#039;wgUserName&#039; ) + &#039;…&#039; );&lt;br /&gt;
		api.postWithToken( &#039;csrf&#039;, { action: &#039;edit&#039;, title: title, text: proposal.wikitext, summary: proposal.summary, baserevid: proposal.baserevid, formatversion: 2 } ).then( function () {&lt;br /&gt;
			location.reload();&lt;br /&gt;
		}, function ( code, e ) {&lt;br /&gt;
			status.text( &#039;Save failed: &#039; + ( e &amp;amp;&amp;amp; e.error ? e.error.info : code ) );&lt;br /&gt;
			saveBtn.prop( &#039;disabled&#039;, false );&lt;br /&gt;
		} );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	discardBtn.on( &#039;click&#039;, function () { proposal = null; result.hide(); status.text( &#039;Discarded. Nothing was saved.&#039; ); } );&lt;br /&gt;
} );&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadgets-definition&amp;diff=98</id>
		<title>MediaWiki:Gadgets-definition</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadgets-definition&amp;diff=98"/>
		<updated>2026-09-17T03:32:31Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Authoring ==&lt;br /&gt;
* AuthorAssistant[ResourceLoader|rights=edit|default|dependencies=mediawiki.api,mediawiki.util]|AuthorAssistant.js|AuthorAssistant.css&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=97</id>
		<title>MediaWiki:Gadget-AuthorAssistant.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=97"/>
		<updated>2026-09-17T03:32:30Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* The author&#039;s assistant (PRD 5.7, ADR D9).&lt;br /&gt;
   Drafts a change to the current page from your instruction and the sources you name, shows the&lt;br /&gt;
   diff, and saves only when you click, through your own session under your own name. The service&lt;br /&gt;
   at /assistant/ holds no credential; it confirms who you are from this session and drafts. */&lt;br /&gt;
( function () {&lt;br /&gt;
	var ns = mw.config.get( &#039;wgNamespaceNumber&#039; );&lt;br /&gt;
	var title = mw.config.get( &#039;wgPageName&#039; ).replace( /_/g, &#039; &#039; );&lt;br /&gt;
	var action = mw.config.get( &#039;wgAction&#039; );&lt;br /&gt;
	// On a view page the assistant saves as you; on the source editor it puts the draft into the&lt;br /&gt;
	// editor so you save with the normal form. In the visual editor, switch to source editing first.&lt;br /&gt;
	var editing = ( action === &#039;edit&#039; || action === &#039;submit&#039; ) &amp;amp;&amp;amp; $( &#039;#wpTextbox1&#039; ).length &amp;gt; 0;&lt;br /&gt;
	if ( ( ns !== 0 &amp;amp;&amp;amp; ns !== 6 ) || ( action !== &#039;view&#039; &amp;amp;&amp;amp; !editing ) || !mw.config.get( &#039;wgUserName&#039; ) ) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	var api = new mw.Api();&lt;br /&gt;
	var root = $( &#039;&amp;lt;div id=&amp;quot;okc-assistant&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var panel = $( &#039;&amp;lt;div class=&amp;quot;okc-panel&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var openBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-open&amp;quot;&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; );&lt;br /&gt;
	var instruction = $( &#039;&amp;lt;textarea rows=&amp;quot;4&amp;quot; placeholder=&amp;quot;What should change on this page? For example: add these two sources under the Sources heading, or fill in the population from the source below.&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var urls = $( &#039;&amp;lt;input type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Optional: web addresses to draw on, separated by spaces&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var draftBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( &#039;Draft the change&#039; );&lt;br /&gt;
	var status = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var result = $( &#039;&amp;lt;div&amp;gt;&#039; ).hide();&lt;br /&gt;
	var explanation = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var warn = $( &#039;&amp;lt;div class=&amp;quot;okc-warn&amp;quot;&amp;gt;&#039; ).hide();&lt;br /&gt;
	var diff = $( &#039;&amp;lt;div class=&amp;quot;okc-diff&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var saveBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( editing ? &#039;Put this in the editor&#039; : &#039;Save this as my edit&#039; );&lt;br /&gt;
	var discardBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-secondary&amp;quot; style=&amp;quot;margin-left:8px&amp;quot;&amp;gt;&#039; ).text( &#039;Discard&#039; );&lt;br /&gt;
	var proposal = null;&lt;br /&gt;
&lt;br /&gt;
	panel.append(&lt;br /&gt;
		$( &#039;&amp;lt;h3&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; ),&lt;br /&gt;
		$( &#039;&amp;lt;p&amp;gt;&#039; ).text( &#039;Tell it what to change. You will see the diff before anything is saved, and the edit will be yours: your name, your responsibility, still needing a reviewer’s approval.&#039; ),&lt;br /&gt;
		instruction, urls, draftBtn, status,&lt;br /&gt;
		result.append( explanation, warn, diff, saveBtn, discardBtn,&lt;br /&gt;
			$( &#039;&amp;lt;p class=&amp;quot;okc-note&amp;quot;&amp;gt;&#039; ).text( &#039;The edit summary will say the assistant helped and name any sources used.&#039; ) )&lt;br /&gt;
	);&lt;br /&gt;
	root.append( panel, openBtn );&lt;br /&gt;
	$( &#039;body&#039; ).append( root );&lt;br /&gt;
&lt;br /&gt;
	openBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		root.toggleClass( &#039;okc-is-open&#039; );&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) ) {&lt;br /&gt;
			fetch( &#039;/assistant/whoami&#039;, { credentials: &#039;same-origin&#039; } ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { status.text( r.status === 404 ? &#039;The assistant is switched off on this instance.&#039; : &#039;Please log in to use the assistant.&#039; ); draftBtn.prop( &#039;disabled&#039;, true ); }&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	draftBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		var text = instruction.val().trim();&lt;br /&gt;
		if ( !text ) { status.text( &#039;Say what should change.&#039; ); return; }&lt;br /&gt;
		status.text( &#039;Reading the page and drafting…&#039; );&lt;br /&gt;
		draftBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		result.hide();&lt;br /&gt;
		var current = editing&lt;br /&gt;
			? $.Deferred().resolve( { wikitext: $( &#039;#wpTextbox1&#039; ).val(), revid: undefined } ).promise()&lt;br /&gt;
			: api.get( { action: &#039;query&#039;, prop: &#039;revisions&#039;, rvprop: &#039;content|ids&#039;, rvslots: &#039;main&#039;, titles: title, formatversion: 2 } ).then( function ( data ) {&lt;br /&gt;
				var page = data.query.pages[ 0 ];&lt;br /&gt;
				var rev = page.revisions &amp;amp;&amp;amp; page.revisions[ 0 ];&lt;br /&gt;
				return { wikitext: rev ? rev.slots.main.content : &#039;&#039;, revid: rev ? rev.revid : undefined };&lt;br /&gt;
			} );&lt;br /&gt;
		current.then( function ( cur ) {&lt;br /&gt;
			var wikitext = cur.wikitext;&lt;br /&gt;
			var rev = { revid: cur.revid };&lt;br /&gt;
			return fetch( &#039;/assistant/draft&#039;, {&lt;br /&gt;
				method: &#039;POST&#039;, credentials: &#039;same-origin&#039;,&lt;br /&gt;
				headers: { &#039;content-type&#039;: &#039;application/json&#039; },&lt;br /&gt;
				body: JSON.stringify( { title: title, wikitext: wikitext, instruction: text, urls: urls.val().split( /\s+/ ).filter( Boolean ) } )&lt;br /&gt;
			} ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { return r.json().then( function ( e ) { throw new Error( e.detail || r.status ); } ); }&lt;br /&gt;
				return r.json();&lt;br /&gt;
			} ).then( function ( d ) {&lt;br /&gt;
				proposal = { wikitext: d.wikitext, summary: d.summary, baserevid: rev ? rev.revid : undefined };&lt;br /&gt;
				explanation.text( d.explanation );&lt;br /&gt;
				if ( d.warning ) { warn.text( d.warning ).show(); } else { warn.hide(); }&lt;br /&gt;
				return api.post( { action: &#039;compare&#039;, fromslots: &#039;main&#039;, &#039;fromtext-main&#039;: wikitext, &#039;fromcontentmodel-main&#039;: &#039;wikitext&#039;, toslots: &#039;main&#039;, &#039;totext-main&#039;: d.wikitext, &#039;tocontentmodel-main&#039;: &#039;wikitext&#039;, prop: &#039;diff&#039;, formatversion: 2 } ).then( function ( c ) {&lt;br /&gt;
					var body = c.compare.body || c.compare[ &#039;*&#039; ] || &#039;&#039;;&lt;br /&gt;
					diff.html( body ? &#039;&amp;lt;table class=&amp;quot;diff&amp;quot;&amp;gt;&amp;lt;colgroup&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;/colgroup&amp;gt;&#039; + body + &#039;&amp;lt;/table&amp;gt;&#039; : &#039;&amp;lt;p&amp;gt;No difference.&amp;lt;/p&amp;gt;&#039; );&lt;br /&gt;
					status.text( d.sources.length ? &#039;Sources used: &#039; + d.sources.join( &#039;, &#039; ) : &#039;Drafted.&#039; );&lt;br /&gt;
					result.show();&lt;br /&gt;
				} );&lt;br /&gt;
			} );&lt;br /&gt;
		} ).catch( function ( e ) {&lt;br /&gt;
			status.text( &#039;The assistant could not draft that: &#039; + ( e &amp;amp;&amp;amp; e.message ? e.message : e ) );&lt;br /&gt;
		} ).always( function () { draftBtn.prop( &#039;disabled&#039;, false ); } );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	saveBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		if ( !proposal ) { return; }&lt;br /&gt;
		if ( editing ) {&lt;br /&gt;
			$( &#039;#wpTextbox1&#039; ).val( proposal.wikitext );&lt;br /&gt;
			var summary = $( &#039;#wpSummary&#039; );&lt;br /&gt;
			if ( summary.length &amp;amp;&amp;amp; !summary.val() ) { summary.val( proposal.summary ); }&lt;br /&gt;
			status.text( &#039;The draft is in the editor. Review it and save with the normal button; the edit will be yours.&#039; );&lt;br /&gt;
			result.hide();&lt;br /&gt;
			root.removeClass( &#039;okc-is-open&#039; );&lt;br /&gt;
			return;&lt;br /&gt;
		}&lt;br /&gt;
		saveBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		status.text( &#039;Saving as &#039; + mw.config.get( &#039;wgUserName&#039; ) + &#039;…&#039; );&lt;br /&gt;
		api.postWithToken( &#039;csrf&#039;, { action: &#039;edit&#039;, title: title, text: proposal.wikitext, summary: proposal.summary, baserevid: proposal.baserevid, formatversion: 2 } ).then( function () {&lt;br /&gt;
			location.reload();&lt;br /&gt;
		}, function ( code, e ) {&lt;br /&gt;
			status.text( &#039;Save failed: &#039; + ( e &amp;amp;&amp;amp; e.error ? e.error.info : code ) );&lt;br /&gt;
			saveBtn.prop( &#039;disabled&#039;, false );&lt;br /&gt;
		} );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	discardBtn.on( &#039;click&#039;, function () { proposal = null; result.hide(); status.text( &#039;Discarded. Nothing was saved.&#039; ); } );&lt;br /&gt;
}() );&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadgets-definition&amp;diff=96</id>
		<title>MediaWiki:Gadgets-definition</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadgets-definition&amp;diff=96"/>
		<updated>2026-09-17T03:10:34Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* AuthorAssistant[ResourceLoader|rights=edit|default|dependencies=mediawiki.api,mediawiki.util]|AuthorAssistant.js|AuthorAssistant.css&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=95</id>
		<title>MediaWiki:Gadget-AuthorAssistant.js</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.js&amp;diff=95"/>
		<updated>2026-09-17T03:10:33Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* The author&#039;s assistant (PRD 5.7, ADR D9).&lt;br /&gt;
   Drafts a change to the current page from your instruction and the sources you name, shows the&lt;br /&gt;
   diff, and saves only when you click, through your own session under your own name. The service&lt;br /&gt;
   at /assistant/ holds no credential; it confirms who you are from this session and drafts. */&lt;br /&gt;
( function () {&lt;br /&gt;
	var ns = mw.config.get( &#039;wgNamespaceNumber&#039; );&lt;br /&gt;
	var title = mw.config.get( &#039;wgPageName&#039; ).replace( /_/g, &#039; &#039; );&lt;br /&gt;
	var action = mw.config.get( &#039;wgAction&#039; );&lt;br /&gt;
	if ( ( ns !== 0 &amp;amp;&amp;amp; ns !== 6 ) || action !== &#039;view&#039; || !mw.config.get( &#039;wgUserName&#039; ) ) {&lt;br /&gt;
		return;&lt;br /&gt;
	}&lt;br /&gt;
	var api = new mw.Api();&lt;br /&gt;
	var root = $( &#039;&amp;lt;div id=&amp;quot;okc-assistant&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var panel = $( &#039;&amp;lt;div class=&amp;quot;okc-panel&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var openBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-open&amp;quot;&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; );&lt;br /&gt;
	var instruction = $( &#039;&amp;lt;textarea rows=&amp;quot;4&amp;quot; placeholder=&amp;quot;What should change on this page? For example: add these two sources under the Sources heading, or fill in the population from the source below.&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var urls = $( &#039;&amp;lt;input type=&amp;quot;text&amp;quot; placeholder=&amp;quot;Optional: web addresses to draw on, separated by spaces&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var draftBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( &#039;Draft the change&#039; );&lt;br /&gt;
	var status = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var result = $( &#039;&amp;lt;div&amp;gt;&#039; ).hide();&lt;br /&gt;
	var explanation = $( &#039;&amp;lt;p&amp;gt;&#039; );&lt;br /&gt;
	var warn = $( &#039;&amp;lt;div class=&amp;quot;okc-warn&amp;quot;&amp;gt;&#039; ).hide();&lt;br /&gt;
	var diff = $( &#039;&amp;lt;div class=&amp;quot;okc-diff&amp;quot;&amp;gt;&#039; );&lt;br /&gt;
	var saveBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-primary&amp;quot;&amp;gt;&#039; ).text( &#039;Save this as my edit&#039; );&lt;br /&gt;
	var discardBtn = $( &#039;&amp;lt;button class=&amp;quot;okc-secondary&amp;quot; style=&amp;quot;margin-left:8px&amp;quot;&amp;gt;&#039; ).text( &#039;Discard&#039; );&lt;br /&gt;
	var proposal = null;&lt;br /&gt;
&lt;br /&gt;
	panel.append(&lt;br /&gt;
		$( &#039;&amp;lt;h3&amp;gt;&#039; ).text( &#039;Author’s assistant&#039; ),&lt;br /&gt;
		$( &#039;&amp;lt;p&amp;gt;&#039; ).text( &#039;Tell it what to change. You will see the diff before anything is saved, and the edit will be yours: your name, your responsibility, still needing a reviewer’s approval.&#039; ),&lt;br /&gt;
		instruction, urls, draftBtn, status,&lt;br /&gt;
		result.append( explanation, warn, diff, saveBtn, discardBtn,&lt;br /&gt;
			$( &#039;&amp;lt;p class=&amp;quot;okc-note&amp;quot;&amp;gt;&#039; ).text( &#039;The edit summary will say the assistant helped and name any sources used.&#039; ) )&lt;br /&gt;
	);&lt;br /&gt;
	root.append( panel, openBtn );&lt;br /&gt;
	$( &#039;body&#039; ).append( root );&lt;br /&gt;
&lt;br /&gt;
	openBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		root.toggleClass( &#039;okc-is-open&#039; );&lt;br /&gt;
		if ( root.hasClass( &#039;okc-is-open&#039; ) ) {&lt;br /&gt;
			fetch( &#039;/assistant/whoami&#039;, { credentials: &#039;same-origin&#039; } ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { status.text( r.status === 404 ? &#039;The assistant is switched off on this instance.&#039; : &#039;Please log in to use the assistant.&#039; ); draftBtn.prop( &#039;disabled&#039;, true ); }&lt;br /&gt;
			} );&lt;br /&gt;
		}&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	draftBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		var text = instruction.val().trim();&lt;br /&gt;
		if ( !text ) { status.text( &#039;Say what should change.&#039; ); return; }&lt;br /&gt;
		status.text( &#039;Reading the page and drafting…&#039; );&lt;br /&gt;
		draftBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		result.hide();&lt;br /&gt;
		api.get( { action: &#039;query&#039;, prop: &#039;revisions&#039;, rvprop: &#039;content|ids&#039;, rvslots: &#039;main&#039;, titles: title, formatversion: 2 } ).then( function ( data ) {&lt;br /&gt;
			var page = data.query.pages[ 0 ];&lt;br /&gt;
			var rev = page.revisions &amp;amp;&amp;amp; page.revisions[ 0 ];&lt;br /&gt;
			var wikitext = rev ? rev.slots.main.content : &#039;&#039;;&lt;br /&gt;
			return fetch( &#039;/assistant/draft&#039;, {&lt;br /&gt;
				method: &#039;POST&#039;, credentials: &#039;same-origin&#039;,&lt;br /&gt;
				headers: { &#039;content-type&#039;: &#039;application/json&#039; },&lt;br /&gt;
				body: JSON.stringify( { title: title, wikitext: wikitext, instruction: text, urls: urls.val().split( /\s+/ ).filter( Boolean ) } )&lt;br /&gt;
			} ).then( function ( r ) {&lt;br /&gt;
				if ( !r.ok ) { return r.json().then( function ( e ) { throw new Error( e.detail || r.status ); } ); }&lt;br /&gt;
				return r.json();&lt;br /&gt;
			} ).then( function ( d ) {&lt;br /&gt;
				proposal = { wikitext: d.wikitext, summary: d.summary, baserevid: rev ? rev.revid : undefined };&lt;br /&gt;
				explanation.text( d.explanation );&lt;br /&gt;
				if ( d.warning ) { warn.text( d.warning ).show(); } else { warn.hide(); }&lt;br /&gt;
				return api.post( { action: &#039;compare&#039;, fromtitle: title, totext: d.wikitext, toslots: &#039;main&#039;, &#039;totext-main&#039;: d.wikitext, &#039;tocontentmodel-main&#039;: &#039;wikitext&#039;, prop: &#039;diff&#039;, formatversion: 2 } ).then( function ( c ) {&lt;br /&gt;
					var body = c.compare.body || c.compare[ &#039;*&#039; ] || &#039;&#039;;&lt;br /&gt;
					diff.html( body ? &#039;&amp;lt;table class=&amp;quot;diff&amp;quot;&amp;gt;&amp;lt;colgroup&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-marker&amp;quot;&amp;gt;&amp;lt;col class=&amp;quot;diff-content&amp;quot;&amp;gt;&amp;lt;/colgroup&amp;gt;&#039; + body + &#039;&amp;lt;/table&amp;gt;&#039; : &#039;&amp;lt;p&amp;gt;No difference.&amp;lt;/p&amp;gt;&#039; );&lt;br /&gt;
					status.text( d.sources.length ? &#039;Sources used: &#039; + d.sources.join( &#039;, &#039; ) : &#039;Drafted.&#039; );&lt;br /&gt;
					result.show();&lt;br /&gt;
				} );&lt;br /&gt;
			} );&lt;br /&gt;
		} ).catch( function ( e ) {&lt;br /&gt;
			status.text( &#039;The assistant could not draft that: &#039; + ( e &amp;amp;&amp;amp; e.message ? e.message : e ) );&lt;br /&gt;
		} ).always( function () { draftBtn.prop( &#039;disabled&#039;, false ); } );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	saveBtn.on( &#039;click&#039;, function () {&lt;br /&gt;
		if ( !proposal ) { return; }&lt;br /&gt;
		saveBtn.prop( &#039;disabled&#039;, true );&lt;br /&gt;
		status.text( &#039;Saving as &#039; + mw.config.get( &#039;wgUserName&#039; ) + &#039;…&#039; );&lt;br /&gt;
		api.postWithToken( &#039;csrf&#039;, { action: &#039;edit&#039;, title: title, text: proposal.wikitext, summary: proposal.summary, baserevid: proposal.baserevid, formatversion: 2 } ).then( function () {&lt;br /&gt;
			location.reload();&lt;br /&gt;
		}, function ( code, e ) {&lt;br /&gt;
			status.text( &#039;Save failed: &#039; + ( e &amp;amp;&amp;amp; e.error ? e.error.info : code ) );&lt;br /&gt;
			saveBtn.prop( &#039;disabled&#039;, false );&lt;br /&gt;
		} );&lt;br /&gt;
	} );&lt;br /&gt;
&lt;br /&gt;
	discardBtn.on( &#039;click&#039;, function () { proposal = null; result.hide(); status.text( &#039;Discarded. Nothing was saved.&#039; ); } );&lt;br /&gt;
}() );&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.css&amp;diff=94</id>
		<title>MediaWiki:Gadget-AuthorAssistant.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant.css&amp;diff=94"/>
		<updated>2026-09-17T03:10:33Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* The author&#039;s assistant panel (PRD 5.7). */&lt;br /&gt;
#okc-assistant { position: fixed; right: 16px; bottom: 16px; z-index: 1000; font-size: 14px; }&lt;br /&gt;
#okc-assistant .okc-open { background: #0c6a8c; color: #fff; border: 0; border-radius: 999px; padding: 9px 16px; font-weight: 600; cursor: pointer; box-shadow: 0 2px 8px rgba(0,0,0,.15); }&lt;br /&gt;
#okc-assistant .okc-panel { display: none; width: min(560px, calc(100vw - 32px)); max-height: 80vh; overflow: auto; background: #fff; color: #1d2a30; border: 1px solid #dfe6e8; border-radius: 12px; box-shadow: 0 8px 30px rgba(0,0,0,.18); padding: 14px 16px; margin-bottom: 8px; }&lt;br /&gt;
#okc-assistant.okc-is-open .okc-panel { display: block; }&lt;br /&gt;
#okc-assistant h3 { margin: 0 0 6px; font-size: 16px; }&lt;br /&gt;
#okc-assistant p { margin: 0 0 8px; color: #4d5c63; }&lt;br /&gt;
#okc-assistant textarea, #okc-assistant input[type=text] { width: 100%; box-sizing: border-box; font: inherit; padding: 8px; border: 1px solid #dfe6e8; border-radius: 8px; margin-bottom: 8px; }&lt;br /&gt;
#okc-assistant button.okc-primary { background: #0c6a8c; color: #fff; border: 0; border-radius: 8px; padding: 8px 14px; font-weight: 600; cursor: pointer; }&lt;br /&gt;
#okc-assistant button.okc-secondary { background: #f3f3f3; color: #1d2a30; border: 1px solid #dfe6e8; border-radius: 8px; padding: 8px 14px; cursor: pointer; }&lt;br /&gt;
#okc-assistant .okc-diff { margin: 10px 0; max-height: 40vh; overflow: auto; border: 1px solid #dfe6e8; border-radius: 8px; padding: 6px; font-size: 13px; }&lt;br /&gt;
#okc-assistant .okc-diff table.diff { width: 100%; }&lt;br /&gt;
#okc-assistant .okc-warn { background: #f3e9cd; border-radius: 8px; padding: 8px 10px; margin: 8px 0; }&lt;br /&gt;
#okc-assistant .okc-note { font-size: 12px; color: #4d5c63; margin-top: 8px; }&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant&amp;diff=93</id>
		<title>MediaWiki:Gadget-AuthorAssistant</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Gadget-AuthorAssistant&amp;diff=93"/>
		<updated>2026-09-17T03:10:32Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;The author&#039;s assistant: drafts a change to the page you have open from your instruction and the sources you give it, shows you the diff, and saves only when you click, under your own name.&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Sidebar&amp;diff=92</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Sidebar&amp;diff=92"/>
		<updated>2026-09-17T02:58:28Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** Special:PendingChanges|Pages awaiting review&lt;br /&gt;
** Category:Machine-seeded stubs|Stubs to claim&lt;br /&gt;
** Special:Upload|Contribute a file&lt;br /&gt;
** Special:RecentChanges|recentchanges-url|recentchanges&lt;br /&gt;
** Help:Authoring|Help for authors&lt;br /&gt;
** https://okc.jayshapiro.com/ask/|Ask the Librarian&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Sidebar&amp;diff=91</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Sidebar&amp;diff=91"/>
		<updated>2026-09-17T02:39:13Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** Special:PendingChanges|Pages awaiting review&lt;br /&gt;
** Category:Machine-seeded stubs|Stubs to claim&lt;br /&gt;
** Special:Upload|Contribute a file&lt;br /&gt;
** Special:RecentChanges|recentchanges-url|recentchanges&lt;br /&gt;
** Help:Authoring|Help for authors&lt;br /&gt;
** https://okc.jayshapiro.com/ask/|Ask the library&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=Energy&amp;diff=90</id>
		<title>Energy</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=Energy&amp;diff=90"/>
		<updated>2026-09-17T02:18:53Z</updated>

		<summary type="html">&lt;p&gt;Jay: /* Sources */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{Seeded|source=the Pwani 2050 topic schema (no source document yet)|date=2026-09-17}}&lt;br /&gt;
{{Infobox topic&lt;br /&gt;
| name = Energy&lt;br /&gt;
| kind = sector&lt;br /&gt;
| pillar = Energy, water and housing&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Energy&#039;&#039;&#039; (Kiswahili: &#039;&#039;Nishati&#039;&#039;): Generation, transmission, distribution and access, including renewables.&lt;br /&gt;
&lt;br /&gt;
== What this page is for ==&lt;br /&gt;
A hub for everything the plan says and the community knows about energy on the coast. Link the organisations, projects, datasets and places that belong here, and record each stakeholder&#039;s position on contested questions so they can be read side by side.&lt;br /&gt;
&lt;br /&gt;
== Coverage the plan expects ==&lt;br /&gt;
* grid access and reliability&lt;br /&gt;
* solar and wind projects&lt;br /&gt;
* LNG and thermal generation&lt;br /&gt;
* energy for industry&lt;br /&gt;
* household energy and cooking fuels&lt;br /&gt;
&lt;br /&gt;
== Sources ==&lt;br /&gt;
This is where we will add sources for the Energy sector.&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Sidebar&amp;diff=83</id>
		<title>MediaWiki:Sidebar</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Sidebar&amp;diff=83"/>
		<updated>2026-09-17T00:49:09Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* navigation&lt;br /&gt;
** mainpage|mainpage-description&lt;br /&gt;
** Special:PendingChanges|Pages awaiting review&lt;br /&gt;
** Category:Machine-seeded stubs|Stubs to claim&lt;br /&gt;
** Special:Upload|Contribute a file&lt;br /&gt;
** Special:RecentChanges|recentchanges-url|recentchanges&lt;br /&gt;
** Help:Authoring|Help for authors&lt;br /&gt;
* SEARCH&lt;br /&gt;
* TOOLBOX&lt;br /&gt;
* LANGUAGES&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Licenses&amp;diff=82</id>
		<title>MediaWiki:Licenses</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Licenses&amp;diff=82"/>
		<updated>2026-09-17T00:49:08Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* Free licences&lt;br /&gt;
** CC BY-SA 4.0|Creative Commons Attribution-ShareAlike 4.0 (the commons default)&lt;br /&gt;
** CC BY 4.0|Creative Commons Attribution 4.0&lt;br /&gt;
** CC0|Public domain dedication (CC0)&lt;br /&gt;
* Other&lt;br /&gt;
** Government work|Kenyan government publication (open for reuse)&lt;br /&gt;
** Copyright with permission|Copyrighted, uploaded with the owner&#039;s permission for this commons&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
	<entry>
		<id>https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Citizen.css&amp;diff=81</id>
		<title>MediaWiki:Citizen.css</title>
		<link rel="alternate" type="text/html" href="https://wiki.okc.jayshapiro.com/index.php?title=MediaWiki:Citizen.css&amp;diff=81"/>
		<updated>2026-09-17T00:49:08Z</updated>

		<summary type="html">&lt;p&gt;Jay: Machine-seeded from the topic schema; no approved revision&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;/* Pwani 2050 theme for the Citizen skin. Colours from the Pwani 2050 logo: ocean #0c6a8c, teal #3fbbc3, gold #c9a24a. */&lt;br /&gt;
:root {&lt;br /&gt;
  --color-primary__h: 196;&lt;br /&gt;
  --color-primary__s: 84%;&lt;br /&gt;
  --color-primary__l: 30%;&lt;br /&gt;
}&lt;br /&gt;
.okc-seeded { border-radius: 8px; }&lt;br /&gt;
.okc-infobox { border-radius: 8px; }&lt;br /&gt;
.okc-position { border-left: 4px solid #3fbbc3; }&lt;/div&gt;</summary>
		<author><name>Jay</name></author>
	</entry>
</feed>