diff --git a/.codex-plugin/plugin.json b/.codex-plugin/plugin.json index 612d3ad..4835c37 100644 --- a/.codex-plugin/plugin.json +++ b/.codex-plugin/plugin.json @@ -1,6 +1,6 @@ { "name": "propulsion", - "version": "1.0.1", + "version": "1.0.2", "description": "Propulsion workflow routing and skills for agentic coding.", "author": { "name": "Moon Pixels" @@ -41,7 +41,7 @@ ], "brandColor": "#FF4F00", "composerIcon": "./assets/propulsion_icon_square.png", - "logo": "./assets/banner.png", + "logo": "./assets/propulsion_icon_square.png", "screenshots": [] } } diff --git a/index.mjs b/index.mjs index 2006862..d4f3f13 100644 --- a/index.mjs +++ b/index.mjs @@ -22,13 +22,31 @@ async function PropulsionPlugin() { } }, 'experimental.chat.messages.transform': async (_input, output) => { - output.messages = [ - { - role: 'system', - content: getPropulsionBootstrapGuidance(), - }, - ...(output.messages ?? []), - ]; + const bootstrap = getPropulsionBootstrapGuidance(); + const firstUser = output.messages?.find( + (message) => message.info.role === 'user', + ); + + if (!firstUser?.parts?.length) { + return; + } + + if ( + firstUser.parts.some( + (part) => + part.type === 'text' && + part.text.includes(''), + ) + ) { + return; + } + + const ref = firstUser.parts[0]; + firstUser.parts.unshift({ + ...ref, + type: 'text', + text: bootstrap, + }); }, }; } diff --git a/package.json b/package.json index f361ecc..e306ede 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "propulsion", - "version": "1.0.1", + "version": "1.0.2", "main": "./index.mjs", "exports": "./index.mjs", "scripts": { diff --git a/skills/propulsion/SKILL.md b/skills/propulsion/SKILL.md index 83b91ca..d0afa65 100644 --- a/skills/propulsion/SKILL.md +++ b/skills/propulsion/SKILL.md @@ -1,7 +1,7 @@ --- name: propulsion # prettier-ignore -description: Manage software-work request routing into Propulsion before any downstream stage is entered. Use when starting a session with software work. +description: Execute structured AI software development from planning through execution. Use when implementing or updating code, debugging issues, or starting repo software work. --- # Propulsion diff --git a/tests/opencode-plugin.test.js b/tests/opencode-plugin.test.js index 9f413f7..7f09904 100644 --- a/tests/opencode-plugin.test.js +++ b/tests/opencode-plugin.test.js @@ -86,13 +86,33 @@ describe('OpenCode Propulsion bootstrap guidance', () => { ); }); - test('registers an OpenCode messages transform that prepends Propulsion guidance', async () => { + test('registers an OpenCode messages transform that injects Propulsion guidance into the first user message', async () => { const pluginPackage = (await import('../index.mjs')).default; const PropulsionPlugin = pluginPackage.server; const hooks = await PropulsionPlugin({}); + const userPart = { + id: 'part-user', + type: 'text', + text: 'Build the thing', + }; const output = { system: ['existing system prompt'], - messages: [{ role: 'user', content: 'Build the thing' }], + messages: [ + { + info: { role: 'assistant' }, + parts: [ + { + id: 'part-assistant', + type: 'text', + text: 'Ready', + }, + ], + }, + { + info: { role: 'user' }, + parts: [userPart], + }, + ], }; expect(hooks).toEqual( @@ -102,15 +122,19 @@ describe('OpenCode Propulsion bootstrap guidance', () => { ); expect(hooks).not.toHaveProperty('experimental.chat.system.transform'); + await hooks['experimental.chat.messages.transform']({}, output); await hooks['experimental.chat.messages.transform']({}, output); expect(output.system).toEqual(['existing system prompt']); - expect(output.messages).toEqual([ + expect(output.messages).toHaveLength(2); + expect(output.messages[0].info.role).toBe('assistant'); + expect(output.messages[1].parts).toEqual([ { - role: 'system', - content: getPropulsionBootstrapGuidance(), + ...userPart, + type: 'text', + text: getPropulsionBootstrapGuidance(), }, - { role: 'user', content: 'Build the thing' }, + userPart, ]); }); });