From feffa87e79de84a0a79ad2ee5064874e87c34a71 Mon Sep 17 00:00:00 2001 From: Brezn Date: Tue, 21 Apr 2026 13:56:16 -0600 Subject: [PATCH 1/2] Prefer SDK execution directive mapper in plugin outputs --- src/index.ts | 54 ++++++++++++++++++++++++++++++++-------------- test/index.test.ts | 3 ++- 2 files changed, 40 insertions(+), 17 deletions(-) diff --git a/src/index.ts b/src/index.ts index ffd6a41..b370c5c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,5 +1,6 @@ +import * as HeadsDownSDK from "@headsdown/sdk"; import { CalibrationTracker, ConfigStore, HeadsDownClient, ProposalStateStore } from "@headsdown/sdk"; -import type { Contract, ScheduleResolution } from "@headsdown/sdk"; +import type { Contract, ScheduleResolution, Verdict } from "@headsdown/sdk"; import { type Plugin, tool } from "@opencode-ai/plugin"; import { evaluateGate } from "./policy.js"; @@ -15,18 +16,27 @@ async function getAuthenticatedClient(): Promise { } } -function buildWrapUpInstruction( - guidance: - | { - active?: boolean; - selectedMode?: "auto" | "wrap_up" | "full_depth"; - remainingMinutes?: number | null; - reason?: string; - hints?: string[]; - } - | null - | undefined, -): string | null { +function resolveExecutionInstruction(input: { + contract?: Contract | null; + schedule?: ScheduleResolution | null; + verdict?: Pick | null; +}): string | null { + const describeExecutionDirective = ( + HeadsDownSDK as unknown as { + describeExecutionDirective?: (value: { + contract?: Contract | null; + schedule?: ScheduleResolution | null; + verdict?: Pick | null; + }) => { primaryDirective?: string }; + } + ).describeExecutionDirective; + + if (typeof describeExecutionDirective === "function") { + const directive = describeExecutionDirective(input); + return directive.primaryDirective ?? null; + } + + const guidance = input.verdict?.wrapUpGuidance ?? input.schedule?.wrapUpGuidance; if (!guidance || !guidance.active) { return null; } @@ -98,7 +108,10 @@ function formatAvailabilitySummary(contract: Contract | null, availability: Sche parts.push(`Wrap-Up guidance: ${timing} (${availability.wrapUpGuidance.selectedMode})`); } - const wrapUpInstruction = buildWrapUpInstruction(availability.wrapUpGuidance); + const wrapUpInstruction = resolveExecutionInstruction({ + contract, + schedule: availability, + }); if (wrapUpInstruction) { parts.push(`Wrap-Up instruction: ${wrapUpInstruction}`); } @@ -126,7 +139,10 @@ export const HeadsDownOpenCodePlugin: Plugin = async () => { async execute() { const client = await getAuthenticatedClient(); const { contract, schedule: availability } = await client.getAvailability(); - const wrapUpInstruction = buildWrapUpInstruction(availability.wrapUpGuidance); + const wrapUpInstruction = resolveExecutionInstruction({ + contract, + schedule: availability, + }); return JSON.stringify( { authenticated: true, @@ -187,7 +203,13 @@ export const HeadsDownOpenCodePlugin: Plugin = async () => { } } - const wrapUpInstruction = buildWrapUpInstruction(verdict.wrapUpGuidance); + const wrapUpInstruction = resolveExecutionInstruction({ + verdict: { + decision: verdict.decision, + reason: verdict.reason, + wrapUpGuidance: verdict.wrapUpGuidance, + }, + }); return JSON.stringify( { decision: verdict.decision, diff --git a/test/index.test.ts b/test/index.test.ts index 9581e1b..6634926 100644 --- a/test/index.test.ts +++ b/test/index.test.ts @@ -7,7 +7,7 @@ describe("OpenCode HeadsDown plugin source", () => { const source = await readFile(join(import.meta.dirname, "..", "src", "index.ts"), "utf8"); expect(source).toContain("Execution policy for this task"); - expect(source).toContain("buildWrapUpInstruction"); + expect(source).toContain("resolveExecutionInstruction"); expect(source).toContain("wrapUpInstruction"); }); @@ -16,5 +16,6 @@ describe("OpenCode HeadsDown plugin source", () => { expect(source).toContain("delivery_mode"); expect(source).toContain("deliveryMode: args.delivery_mode"); + expect(source).toContain("describeExecutionDirective"); }); }); From 4ef9e28172d1b948e42da4ff9034a1e8edfd3e6c Mon Sep 17 00:00:00 2001 From: Brezn Date: Tue, 21 Apr 2026 14:05:28 -0600 Subject: [PATCH 2/2] Bump @headsdown/sdk to 0.2.13 --- package-lock.json | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1dc6b25..1b722ff 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "license": "MIT", "dependencies": { - "@headsdown/sdk": "^0.2.12", + "@headsdown/sdk": "^0.2.13", "@opencode-ai/plugin": "^1.4.0" }, "devDependencies": { @@ -464,9 +464,9 @@ } }, "node_modules/@headsdown/sdk": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/@headsdown/sdk/-/sdk-0.2.12.tgz", - "integrity": "sha512-beJqMUPLRtVZhbDFY4fpjcJsRG3pDA3daiWxOenO5G04qMAU2PM80VF3oe1Ew7dtaa44M/wsOpnyQP6LcOwTYA==", + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/@headsdown/sdk/-/sdk-0.2.13.tgz", + "integrity": "sha512-B7KNkWnXF/gs2jOqvFUK66BFVe4CNvJfKSY/GCkfVQOySWzMHx9guadVdTOpysAgJUHF4OIHo0J9ipFHrOsSNw==", "license": "MIT", "engines": { "node": ">=18.0.0" diff --git a/package.json b/package.json index 471b13b..aae6c74 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "test": "vitest run" }, "dependencies": { - "@headsdown/sdk": "^0.2.12", + "@headsdown/sdk": "^0.2.13", "@opencode-ai/plugin": "^1.4.0" }, "devDependencies": {