diff --git a/README.md b/README.md index 628d0ec..168b4b1 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,10 @@ durability, acknowledgement, retry, privacy normalization, and AWR delivery. If the Wizard hook is absent or incompatible, the plugin records that capture is unavailable and continues without inventing a receipt. +Set `ORGX_SESSION_SUMMARY_AUTO_FLUSH=off` for a deliberately offline run. The +adapter and Wizard retain the capture without starting a delivery worker; +`orgx-wizard hooks flush` can replay it later with server acknowledgement. + ### V2 beta canary The production plugin stays on OpenCode's stable plugin contract. Set diff --git a/package-lock.json b/package-lock.json index c451cca..50ec16e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@useorgx/orgx-opencode-plugin", - "version": "0.1.0-alpha.10", + "version": "0.1.0-alpha.11", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@useorgx/orgx-opencode-plugin", - "version": "0.1.0-alpha.10", + "version": "0.1.0-alpha.11", "license": "MIT", "dependencies": { "@opencode-ai/sdk": "^1.18.2", diff --git a/package.json b/package.json index b175970..f20ea2d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@useorgx/orgx-opencode-plugin", - "version": "0.1.0-alpha.10", + "version": "0.1.0-alpha.11", "publishConfig": { "access": "public" }, diff --git a/plugin.manifest.json b/plugin.manifest.json index 7110812..9a5849b 100644 --- a/plugin.manifest.json +++ b/plugin.manifest.json @@ -1,6 +1,6 @@ { "plugin_name": "@useorgx/orgx-opencode-plugin", - "version": "0.1.0-alpha.10", + "version": "0.1.0-alpha.11", "manifest_fingerprint": "", "signature": "", "capabilities": [ diff --git a/src/sessionSummaryBridge.test.ts b/src/sessionSummaryBridge.test.ts index ceb17ef..16a45aa 100644 --- a/src/sessionSummaryBridge.test.ts +++ b/src/sessionSummaryBridge.test.ts @@ -105,6 +105,34 @@ describe('OpenCode session summary bridge', () => { } }); + it('keeps an offline run queued without starting fallback delivery', async () => { + const dir = mkdtempSync(join(tmpdir(), 'orgx-opencode-bridge-')); + const hookPath = join(dir, 'orgx-session-summary.mjs'); + await writeFile(hookPath, 'export async function main() {}\n', 'utf8'); + const spawnImpl = vi.fn(); + try { + const result = await bridgeOpenCodeSessionSummary({ + nativeEvent: 'session.idle', + payload: { properties: { sessionID: 'session-offline' } }, + directory: '/work/repo', + hookPath, + env: { + PATH: process.env.PATH, + ORGX_SESSION_SUMMARY_AUTO_FLUSH: 'off', + }, + importHook: async () => ({ + main: async () => ({ ok: true, queued: true, delivery_triggered: false }), + }), + spawnImpl, + }); + + expect(result.fallback_delivery_triggered).toBe(false); + expect(spawnImpl).not.toHaveBeenCalled(); + } finally { + rmSync(dir, { recursive: true, force: true }); + } + }); + it('reports the installed-hook dependency when unavailable', async () => { await expect( bridgeOpenCodeSessionSummary({ diff --git a/src/sessionSummaryBridge.ts b/src/sessionSummaryBridge.ts index 8e3de49..a235197 100644 --- a/src/sessionSummaryBridge.ts +++ b/src/sessionSummaryBridge.ts @@ -110,11 +110,16 @@ async function exists(path: string): Promise { } } +function autoFlushDisabled(value: string | undefined): boolean { + return ['off', 'false', '0'].includes(String(value ?? '').trim().toLowerCase()); +} + function triggerFlush( env: Env, spawnImpl: SpawnLike, queueDir?: string ): boolean { + if (autoFlushDisabled(env.ORGX_SESSION_SUMMARY_AUTO_FLUSH)) return false; try { const args = ['hooks', 'flush', '--background', '--limit=25']; if (queueDir) args.push(`--queue=${queueDir}`);