Created: 2026-06-26
Target: Ourin's PLUGIN/2.0M bridge / SSP PLUGIN compatibility / PLUGIN/1.0 behavior compatibility
Purpose: Implement UKADOC PLUGIN/2.0's request/response, PLUGIN Event, plugin descript, and legacy PLUGIN/1.0-derived behavior to practical compatibility level as a macOS native plugin bridge.
Reference Specifications
- UKADOC PLUGIN/2.0: https://ssp.shillest.net/ukadoc/manual/spec_plugin.html
- UKADOC PLUGIN Event: https://ssp.shillest.net/ukadoc/manual/list_plugin_event.html
- UKADOC Plugin descript.txt: https://ssp.shillest.net/ukadoc/manual/descript_plugin.html
- PLUGIN/1.0 Reference: http://usada.sakura.vg/contents/plugin.html
- Ourin Spec:
docs/SPEC_PLUGIN_2.0M_en-us.md - Ourin Event Spec:
docs/PLUGIN_EVENT_2.0M_SPEC_en-us.md
Completion Definition
Full plugin bridge implementation means meeting all of the following:
- Sending to plugins complies with PLUGIN/2.0 wire semantics.
Event/Reference*/Target/Script/ScriptOption/EventOptionresponses from plugins are bridged to ghosts per spec.- All events in UKADOC PLUGIN Event list have at least correct ID, GET/NOTIFY, and Reference ordering send paths.
descript.txtcharset/secondchangeinterval/otherghosttalkis wired into actual operation.property.get/property.setis delegated to plugins aspluginlist(...).extextended properties.- Both Shift_JIS/CP932 and UTF-8 plugins have no character encoding issues in request/response.
- PLUGIN/1.0 doesn't directly load Windows DLLs on macOS, but provides behavior compatibility for event names, menu invocation, and old descript-derived metadata.
Current Summary
Updated 2026-06-27: The runtime bridge items in this plan are implemented. Charset byte encode/decode, Target delivery, Event/Script fallback, ScriptOption, plugin-specific secondchangeinterval, otherghosttalk before/after, catalog/install/ghost/menu event wiring, pluginlist(...).ext property delegation, PLUGIN/1.0 metadata compatibility, DevTools console, choice/anchor plugin-origin one-shot hooks are connected. Regression validated via PluginEncodingTests, PluginTargetRoutingTests, PluginPropertyBridgeTests and existing matrix, plus full xcodebuild -project Ourin.xcodeproj -scheme Ourin test.
Implemented:
.plugin/.bundledetection andrequest/loadu/unloadcalls.PluginFrameGET/NOTIFY frame construction.PluginEventDispatcherper-plugin sequential dispatch.OurinPluginEventBridgeraiseplugin/notifypluginresponse bridge.EventOption: notify,ScriptOptionparse, basic__SYSTEM_ALL_GHOST__acceptance.OnChoiceSelect(Ex)/OnAnchorSelect(Ex)plugin-origin one-shot passthrough.- Actual byte encode/decode based on negotiated
Charset. Targetdelivery to specific ghost / all ghosts / baseware.notranslate/nobreakSakuraScript execution control.property.get/property.setplugin delegation.OnOtherGhostTalkactual talk pipeline connection andbefore/after.- Catalog notification wiring at startup / install.
- PLUGIN/1.0-derived plugin metadata / menu/message behavior compatibility.
Phase 0: Implementation Status Audit and Spec Sync
Purpose: Eliminate gaps between old docs and actual code, fix baseline for subsequent implementation.
Target:
docs/SPEC_PLUGIN_2.0M_en-us.mddocs/PLUGIN_EVENT_2.0M_SPEC_en-us.mddocs/PLUGIN_COMPAT_FIX_PROPOSAL.mdOurin/PluginEvent/*Ourin/PluginHost/*
Tasks:
- Retranscribe UKADOC event list to Ourin implementation table.
- Classify each event as
implemented/helper-only/not wired/not implemented. - Split existing docs "implemented" terminology into helper-only and runtime-wired.
Acceptance Criteria:
- Docs implementation status does not contradict what
rgconfirms in code. - Each unimplemented item maps to a Phase in this plan.
Phase 1: Wire charset at byte level
Purpose: Apply PLUGIN/2.0 Charset to actual request/response encode/decode.
Target:
Ourin/PluginHost/Plugin.swiftOurin/PluginHost/PluginProtocol.swiftOurin/PluginEvent/PluginEncodingNormalizer.swiftOurin/PluginEvent/PluginEventDispatcher.swiftOurinTests/OurinPluginEventBridgeTests.swift- New:
OurinTests/PluginEncodingTests.swift
Tasks:
- Make
Plugin.sendcharset-specifiable viaString.Encoding. - After
PluginRequestbuild, wire with negotiated charset to bytes. - Decode plugin response with response
Charsetor request charset, normalize to internal UTF-8String. - Retain
versionresponseCharsetper plugin, apply to next request. - Add Shift_JIS/CP932 round-trip fixture plugin or mock request function to tests.
Acceptance Criteria:
- Shift_JIS plugin doesn't have character corruption even with Japanese
Reference*sent. - Shift_JIS response
Script/Event/Reference*can be handled as UTF-8 internal strings. - UTF-8 plugin existing tests don't regress.
Phase 2: Complete Target routing
Purpose: Route Target-specified plugin responses to intended ghosts per spec.
Target:
Ourin/PluginEvent/OurinPluginEventBridge.swiftOurin/SHIORIEvents/EventBridge.swiftOurin/Ghost/GhostManager.swiftOurin/Ghost/GhostManager+System.swiftOurin/SSTP/BridgeToSHIORI.swift
Tasks:
- Evaluate
PluginTransportAction.targetnot just as string, but pass to delivery target resolver. - Add target resolver:
-
nil/ empty: prioritize calling ghost, else active ghost. -__SYSTEM_ALL_GHOST__: all running ghosts. - ghost name / ghost id / ghost path / owned SSTP id: matching ghost. -baseware/ourin: baseware processing. - Retain calling ghost in action context for
raiseplugin. - System event-derived responses in
PluginEventDispatcherfollow active ghost or target spec. - Don't run fallback script on target mismatch.
Acceptance Criteria:
- With 2 ghosts running,
Target-specified response reaches only that ghost. __SYSTEM_ALL_GHOST__reaches all ghosts.raisepluginresponse returns to calling ghost if target unspecified.
Phase 3: Tighten Event/Script response semantics
Purpose: Stabilize spec where Event fallback to default Script only if event doesn't respond.
Target:
Ourin/PluginEvent/OurinPluginEventBridge.swiftOurin/SHIORIEvents/EventBridge.swiftOurin/SHIORIEvents/EventID.swiftOurin/Ghost/GhostManager.swiftOurin/SakuraScriptEngine.swift
Tasks:
- Plugin response
Eventis GET to SHIORI if noEventOption: notify. - If GET response script is empty, use plugin response
Scriptas fallback. - With
EventOption: notify, don't look at response script, don't run plugin fallback. - Implement
ScriptOption: nobreakas "enqueue after current talk". - Propagate
ScriptOption: notranslateto SakuraScript execution context. - Enable
OnOtherGhostTalkreasons to carryplugin-script/plugin-event/notranslate.
Acceptance Criteria:
- With
Event + Scriptresponse and ghost GET response, default Script doesn't replay. - Only when ghost returns empty does default Script replay.
nobreakdoesn't interrupt playing talk.notranslatebypasses translate pipeline.
Phase 4: Wire all UKADOC PLUGIN Event send paths
Purpose: Connect all event IDs in list to runtime event sources.
Target:
Ourin/PluginEvent/PluginEventDispatcher.swiftOurin/OurinApp.swiftOurin/Ghost/GhostManager+System.swiftOurin/Ghost/GhostManager+Balloon.swiftOurin/NarInstall/*Ourin/HeadlineHost/*Ourin/Property/*
Per-event tasks:
version- Keep as is, re-validate after charset byte implementation.installedplugin- Send at startup, plugin reload, install/uninstall.installedghostname- Send at startup, ghost install/uninstall. -Reference0: ghost names. -Reference1: sakura names. -Reference2: kero names.installedballoonname- Send at startup, balloon install/uninstall.ghostpathlist- Send at startup, ghost path setting change.balloonpathlist- Send at startup, balloon path setting change.headlinepathlist- Send at startup, headline path setting change.pluginpathlist- Send at startup, plugin reload/install/uninstall.OnSecondChange- Respectsecondchangeintervalper plugin. Currently single batch timer; move to per-plugin timer or tick filter.OnOtherGhostTalk- Connect just before/after ghost talk.
- Respect
otherghosttalkfalse/0/true/1/after/before.
OnGhostBoot- Send when ghost boot complete.
0if window not yet built.
- Send when ghost boot complete.
OnGhostExit- Send NOTIFY when ghost exits.
OnGhostInfoUpdate- Send NOTIFY on ghost config/shell/info update.
OnMenuExec- Send GET when plugin menu executed.
OnInstallComplete- Send on NAR / ghost / shell / balloon / plugin / headline install complete.
OnChoiceSelect(Ex)/OnAnchorSelect(Ex)/ arbitrary choice event- Mark only choices from plugin response script/event, once, for plugin passthrough.
raiseplugin/notifypluginarbitrary name- Keep as is, wire Target context and charset.
property.get- Implement in Phase 5.
property.set- Implement in Phase 5.
Acceptance Criteria:
- Each event Reference order matches UKADOC.
[NOTIFY]events ignore response script.OnSecondChangerespects per-plugin interval.OnOtherGhostTalkdistinguishesbefore/after.
Phase 5: plugin extended property.get / property.set
Purpose: Delegate pluginlist(...).ext extended properties to plugin requests.
Target:
Ourin/Property/PluginPropertyProvider.swiftOurin/Property/PropertyManager.swiftOurin/PluginHost/PluginRegistry.swiftOurin/PluginEvent/PluginEventDispatcher.swiftOurinTests/PropertySystemTests.swift
Design:
- Treat
pluginlist(name).ext.fooorpluginlist.index(n).ext.fooas extended property. - get:
- Send
GET PLUGIN/2.0Mto target plugin ID: property.getReference0: foo- Adopt response value as property value, not
ValueorScript. - set:
- Send per-spec, not GET or NOTIFY, but request-response equivalent.
ID: property.setReference0: fooReference1: value- Treat status
204or200as success.
Acceptance Criteria:
pluginlist.index(0).ext.somekeyreturns pluginproperty.getresponse.PropertyManager.set("pluginlist.index(0).ext.somekey", value: "x")callsproperty.set.- 404/500 response becomes property get nil / set false.
Phase 6: PLUGIN/1.0 behavior compatibility
Purpose: Provide macOS-friendly handling of old plugin distributions, old metadata, old menu behavior without Windows DLL binary compatibility.
Target:
Ourin/PluginHost/PluginRegistry.swiftOurin/PluginHost/PluginProtocol.swiftOurin/PluginEvent/PluginEventDispatcher.swiftOurin/OwnerDrawMenu/*OurinTests/LegacyPluginRegistryTests.swift
Tasks:
- Clarify conditions for treating legacy metadata-only plugin directory as bridge target.
- Normalize old key aliases in
descript.txt. - Windows DLL plugins without native
.pluginare "unloadable but metadata visible"; show explicit error or disabled on menu execution. - Retain PLUGIN/1.0 menu / author / readme / charset keys in
PluginMeta. - If native replacement exists for same ID, prioritize native, don't double-register legacy.
Acceptance Criteria:
- Legacy plugin directory is distinguishable in Ourin UI.
- Native replacement prevents double-loading.
- Old descript charset/name/id/filename readable as metadata.
Phase 7: Menu / UI / DevTools bridge
Purpose: Make plugin bridge state and firing verifiable from UI.
Target:
Ourin/ContentView.swiftOurin/DevTools/*Ourin/OwnerDrawMenu/*Ourin/PluginHost/PluginRegistry.swift
Tasks:
- Show negotiated charset, package path, executable path, legacy/native state in Plugin DevTools.
- Add or enhance test console to send arbitrary
GET/NOTIFYrequest to any plugin. - Wire actual menu execution to
OnMenuExecdispatcher. - Prioritize
message.*.txtin plugin menu display text.
Acceptance Criteria:
- Manually verify
version/ arbitrary event / property.get from DevTools. - Plugin menu text switches via
message.japanese.txt/message.english.txt.
Phase 8: Test plugin fixtures
Purpose: Lock real plugin compatibility via unit and integration tests.
Target:
OurinTests/Fixtures/plugin/*- New fixture plugin source
OurinTests/PluginBridgeIntegrationTests.swift
Fixtures:
- UTF-8 echo plugin.
- Shift_JIS echo plugin.
Event + Script fallbackplugin.Targetplugin.property.get/setplugin.- Legacy metadata-only plugin.
Acceptance Criteria:
- CI or local
xcodebuild testcan load fixture plugins. - Validate byte charset, Target, fallback, property via actual plugin response.
Phase 9: Regression test matrix
Target Tests
OurinPluginEventBridgeTestsLegacyPluginRegistryTestsPropertySystemTestsSakuraScriptEngineTestsSSTPDispatcherTests- New
PluginEncodingTests - New
PluginTargetRoutingTests - New
PluginPropertyBridgeTests - New
PluginEventDispatchMatrixTests
Verification Command:
xcodebuild -project Ourin.xcodeproj -scheme Ourin test
Additionally, during target changes run individually:
xcodebuild -project Ourin.xcodeproj -scheme Ourin -only-testing:OurinTests/OurinPluginEventBridgeTests test
xcodebuild -project Ourin.xcodeproj -scheme Ourin -only-testing:OurinTests/PropertySystemTests test
xcodebuild -project Ourin.xcodeproj -scheme Ourin -only-testing:OurinTests/LegacyPluginRegistryTests test
Implementation Order
Recommended:
- Phase 0: docs/status audit.
- Phase 1: charset byte implementation.
- Phase 2: Target routing.
- Phase 3: Event/Script semantics.
- Phase 4: event wiring.
- Phase 5: property.get/set.
- Phase 6: PLUGIN/1.0 behavior compatibility.
- Phase 7: UI/DevTools.
- Phase 8/9: fixtures and test matrix expansion.
Rationale:
- Charset and Target are foundation for entire bridge; affect all subsequent events.
- Fixing Event/Script semantics first stabilizes OnMenuExec, raiseplugin, choice hook behavior.
- Property is independent but needs target plugin resolution from Phase 2.
Risks and Mitigations
| Risk | Impact | Mitigation |
|---|---|---|
| Shift_JIS plugin response decode failure | Japanese plugins break | Add byte fixture and CP932 fallback |
| Target routing sends script to wrong ghost | User experience / compatibility hit | Add multi-ghost routing tests |
nobreak breaks playback queue |
Talk playback regressions | Add SakuraScript playback tests |
OnOtherGhostTalk fires recursively |
plugin-event loop | Introduce reason flag and re-entry suppress token |
property.set has side effects |
Unexpected plugin state change | Send to explicit target plugin only |
| Legacy plugin misload | Crash/broken bundle | Separate loadability by native bundle presence |
Minimum Milestones
M1: bridge core complete
- Charset byte implementation.
- Target routing.
- Event/Script fallback tighten.
OurinPluginEventBridgeTests/PluginEncodingTests/PluginTargetRoutingTestspass.
M2: event matrix complete
- All UKADOC PLUGIN Event IDs wired to runtime sources.
OnSecondChangeper-plugin interval.OnOtherGhostTalkbefore/after.PluginEventDispatchMatrixTestspass.
M3: property and legacy compatibility
property.get/setplugin delegation.- PLUGIN/1.0 metadata-only compatibility.
- Native replacement priority and dedup.
M4: UI and operational verification
- DevTools shows request/response.
- Plugin menu text reflects
message.*.txt. - Full
xcodebuild ... testpasses.
Docs to Update After Completion
docs/SPEC_PLUGIN_2.0M_en-us.mddocs/SPEC_PLUGIN_2.0M_ja-jp.mddocs/PLUGIN_EVENT_2.0M_SPEC_en-us.mddocs/PLUGIN_EVENT_2.0M_SPEC_ja-jp.mddocs/PropertySystem_en-us.mddocs/PropertySystem_ja-jp.mddocs/SUPPORTED_SAKURA_SCRIPT.md
Checklist
- [x] Charset negotiated byte encode/decode
- [x] Target resolver
- [x] caller ghost context for
raiseplugin - [x]
__SYSTEM_ALL_GHOST__multi-ghost delivery - [x]
EventGET fallback semantics - [x]
EventOption: notify - [x]
ScriptOption: nobreak - [x]
ScriptOption: notranslate - [x] plugin-specific
secondchangeinterval - [x]
otherghosttalkbefore/after - [x]
installedghostname - [x]
installedballoonname - [x]
ghostpathlist - [x]
balloonpathlist - [x]
headlinepathlist - [x]
OnGhostBoot - [x]
OnGhostExit - [x]
OnGhostInfoUpdate - [x]
OnMenuExec - [x]
OnInstallComplete - [x] choice/anchor one-shot plugin-origin hook
- [x]
property.get - [x]
property.set - [x] PLUGIN/1.0 metadata-only compatibility
- [x] DevTools request console
- [x] fixture/plugin bridge regression suite
出典と編集について
Ourin / Furin Lab・contributors。文書はCC BY-SA 4.0(第三者の個別表記を除く)。Web版は見出し・リンクの整備とローカルパスの一般化を行っています。更新基準日: 2026-10-30。
元資料: docs/PLUGIN_BRIDGE_COMPLETION_PLAN_en-us.md
ソース SHA-256: d6de5d136440f58214bd2a29911e4d170881e9f80a73c85b496d55a48c691f09