From 221a61fa9107e4438b606251434d6a298225d2b5 Mon Sep 17 00:00:00 2001 From: Adam Hainsworth-Potter Date: Mon, 4 May 2026 19:55:38 +0100 Subject: [PATCH] Fix Propulsion plugin loading --- .agents/plugins/marketplace.json | 2 +- .codex-plugin/plugin.json | 2 +- index.mjs | 14 +++++++++ package.json | 2 +- plugins/propulsion/.codex-plugin | 1 + plugins/propulsion/assets | 1 + plugins/propulsion/hooks | 1 + plugins/propulsion/skills | 1 + tests/opencode-plugin.test.js | 51 ++++++++++++++++++++++++++++++++ 9 files changed, 72 insertions(+), 3 deletions(-) create mode 120000 plugins/propulsion/.codex-plugin create mode 120000 plugins/propulsion/assets create mode 120000 plugins/propulsion/hooks create mode 120000 plugins/propulsion/skills diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json index b2412d9..855b046 100644 --- a/.agents/plugins/marketplace.json +++ b/.agents/plugins/marketplace.json @@ -9,7 +9,7 @@ "name": "propulsion", "source": { "source": "local", - "path": "./" + "path": "./plugins/propulsion" }, "policy": { "installation": "AVAILABLE", diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 461331f..612d3ad 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "propulsion", - "version": "1.0.0", + "version": "1.0.1", "description": "Propulsion workflow routing and skills for agentic coding.", "author": { "name": "Moon Pixels" diff --git a/index.mjs b/index.mjs index 5f25e26..2006862 100644 --- a/index.mjs +++ b/index.mjs @@ -1,12 +1,26 @@ import { createRequire } from 'node:module'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; const require = createRequire(import.meta.url); const { getPropulsionBootstrapGuidance, } = require('./lib/bootstrap-guidance.js'); +const PROPULSION_SKILLS_DIR = join( + dirname(fileURLToPath(import.meta.url)), + 'skills', +); async function PropulsionPlugin() { return { + config: async (config) => { + config.skills = config.skills || {}; + config.skills.paths = config.skills.paths || []; + + if (!config.skills.paths.includes(PROPULSION_SKILLS_DIR)) { + config.skills.paths.push(PROPULSION_SKILLS_DIR); + } + }, 'experimental.chat.messages.transform': async (_input, output) => { output.messages = [ { diff --git a/package.json b/package.json index 96a7c84..f361ecc 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "propulsion", - "version": "1.0.0", + "version": "1.0.1", "main": "./index.mjs", "exports": "./index.mjs", "scripts": { diff --git a/plugins/propulsion/.codex-plugin b/plugins/propulsion/.codex-plugin new file mode 120000 index 0000000..c3acab0 --- /dev/null +++ b/plugins/propulsion/.codex-plugin @@ -0,0 +1 @@ +../../.codex-plugin \ No newline at end of file diff --git a/plugins/propulsion/assets b/plugins/propulsion/assets new file mode 120000 index 0000000..41aef43 --- /dev/null +++ b/plugins/propulsion/assets @@ -0,0 +1 @@ +../../assets \ No newline at end of file diff --git a/plugins/propulsion/hooks b/plugins/propulsion/hooks new file mode 120000 index 0000000..2777e15 --- /dev/null +++ b/plugins/propulsion/hooks @@ -0,0 +1 @@ +../../hooks \ No newline at end of file diff --git a/plugins/propulsion/skills b/plugins/propulsion/skills new file mode 120000 index 0000000..5dcab58 --- /dev/null +++ b/plugins/propulsion/skills @@ -0,0 +1 @@ +../../skills \ No newline at end of file diff --git a/tests/opencode-plugin.test.js b/tests/opencode-plugin.test.js index a76c886..9f413f7 100644 --- a/tests/opencode-plugin.test.js +++ b/tests/opencode-plugin.test.js @@ -1,5 +1,7 @@ import { describe, expect, test } from 'bun:test'; import { readFile } from 'node:fs/promises'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; import { getPropulsionBootstrapGuidance } from '../lib/bootstrap-guidance.js'; @@ -21,6 +23,55 @@ describe('OpenCode Propulsion bootstrap guidance', () => { ).toBe(true); }); + test('publishes Propulsion through a non-empty Codex marketplace plugin path', async () => { + const marketplace = JSON.parse( + await readFile('.agents/plugins/marketplace.json', 'utf8'), + ); + const plugin = marketplace.plugins.find( + ({ name }) => name === 'propulsion', + ); + + expect(plugin.source).toEqual({ + source: 'local', + path: './plugins/propulsion', + }); + + const pluginManifest = JSON.parse( + await readFile( + 'plugins/propulsion/.codex-plugin/plugin.json', + 'utf8', + ), + ); + + expect(pluginManifest.name).toBe('propulsion'); + }); + + test('registers bundled skills with OpenCode config', async () => { + const pluginPackage = (await import('../index.mjs')).default; + const PropulsionPlugin = pluginPackage.server; + const hooks = await PropulsionPlugin({}); + const config = {}; + const skillsDir = join( + dirname(fileURLToPath(import.meta.url)), + '..', + 'skills', + ); + + expect(hooks).toEqual( + expect.objectContaining({ + config: expect.any(Function), + }), + ); + + await hooks.config(config); + await hooks.config(config); + + expect(config.skills.paths).toEqual([skillsDir]); + await expect( + readFile(join(skillsDir, 'debug', 'SKILL.md'), 'utf8'), + ).resolves.toContain('# Debug'); + }); + test('provides high-priority Propulsion routing guidance', () => { const guidance = getPropulsionBootstrapGuidance();