This is a follow-on from T394410: Move management of recommended Wikifunctions to use CommunityConfiguration.
Goal
Replace CommunityConfiguration's default string-array editor with a typed Wikifunctions lookup widget for both CC providers registered by WikiLambda:
- WikifunctionsSuggestions (client mode, any Function)
- AbstractWikiSuggestedWikifunctions (abstract mode, Functions returning Z89/HTML fragments only)
This is the deferred work from T394410: Move management of recommended Wikifunctions to use CommunityConfiguration that I explicitly scoped out of the initial migration. Assuming that migration now lands as-is (patches 211a6d428 and dc172779c), sysops have to type ZIDs into a plain text array with only a regex safety net, which is a known-bad UX.
Blocked by
Upstream; we need to add a runtime attributes entry to CC so extensions can register custom Vue controls. Without that interface, the only way to land this work is to upstream a Wikifunctions-specific control into CC itself — possible but architecturally worse.
Scope
Phased so each patch is atomic and independently reviewable:
Phase 1 — New shared ResourceLoader module
Add ext.wikilambda.functionLookup as a new Codex-backed RL module in extension.json, independent of ext.wikilambda.app. Contents:
- FunctionLookupControl.vue — Codex CdxMultiselectLookup-based component; props: modelValue (ZID array), schema; emits update:modelValue.
- functionLookupApi.js — minimal wrapper that calls apiUtils.newApi() (the existing mw.ForeignApi path used by ext.wikilambda.app) → wikilambdasearch_functions, passing search, optional output_type (Phase 2), and an AbortSignal.
- functionResultItem.vue — Codex menu-item rendering for labelled ZID rows.
Do NOT extract from the existing FunctionSelect.vue — its useMainStore() dependency drags in ~20 Pinia modules. A parallel ~200-line minimal component is cheaper than a refactor and keeps the VE dialog's contract unchanged.
One-time refactor: move apiUtils.newApi() out of ext.wikilambda.app/utils/ and into a shared location so the new module can consume it without pulling the app.
Phase 2 — Server: Z89-only search filter
ApiQueryFunctions.php:167-170 already accepts a single-ZID output_type parameter in the non-search API. Expose the same on the wikilambdasearch_functions search Action API as wikilambdasearch_functions_output_type, validated by the same regex.
Do NOT overload the existing renderable flag — keep its binary [Z6 ∪ Z89] semantics; add the richer output_type parameter alongside.
PHPUnit integration test: output_type=Z89 returns only Z89-returning functions.
Phase 3 — Schema integration
- SuggestedFunctionsSchema.php: add self::CONTROL => 'MediaWiki\\Extension\\WikiLambda\\Controls\\FunctionLookupControl' on the SuggestedFunctions property.
- AbstractSuggestedFunctionsSchema.php: add the same, plus a control option for the Z89 filter (exact key shape pinned down by whatever {T} ships): self::CONTROL => 'MediaWiki\\Extension\\WikiLambda\\Controls\\FunctionLookupControl', self::CONTROL_OPTIONS => [ 'outputType' => 'Z89' ],
- Register WikiLambda's attributes.CommunityConfiguration.Controls.WikifunctionsFunctionLookup entry in extension.json.
Acceptance criteria
- Sysops on a client-mode wiki editing Special:CommunityConfiguration see a Codex typeahead for the WikifunctionsSuggestions list; search queries hit the remote Wikifunctions repo via mw.ForeignApi using wgWikifunctionsBaseUrl.
- Sysops on abstract.wikipedia.org see the same typeahead, but results are filtered to Z89-returning functions only.
- The 5-entry and 10-entry caps continue to be enforced by the schema at save time.
- WikiLambdaClientModeOffline=true degrades to a read-only display of already-configured ZIDs (no search).
- Jest tests cover the new component. PHPUnit tests cover the new server parameter. Coverage thresholds respected.
Non-goals
- No change to the stored JSON shape on either MediaWiki:WikifunctionsSuggestions.json or MediaWiki:AbstractWikiSuggestedWikifunctions.json. The widget emits the same ZID-array the current editor does.
- No change to the abstract-mode schema DEFAULT list (the seeded values from T394410: Move management of recommended Wikifunctions to use CommunityConfiguration).
- No "type-narrowing to HTML-only" filter surfaced on the client-mode provider — remains "any Function".