@defend-tech/opencode-optima 0.1.53 → 0.1.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -9256,17 +9256,20 @@ function clickUpWebhookLocationCompatible(webhook = {}, config = {}) {
9256
9256
  }
9257
9257
  return true;
9258
9258
  }
9259
- async function findReusableClickUpWebhook(config, clickupClient = null) {
9259
+ async function findReusableClickUpWebhook(config, clickupClient = null, existingState = null) {
9260
9260
  if (!clickupClient?.listWebhooks) return null;
9261
9261
  const listed = await clickupClient.listWebhooks({ teamId: config.teamId });
9262
+ let secretlessMatch = null;
9262
9263
  for (const webhook of clickUpWebhookListItems(listed)) {
9263
9264
  const remote = normalizeClickUpWebhookApiResponse(webhook, config);
9264
9265
  if (remote.publicUrl !== config.webhook.publicUrl) continue;
9265
9266
  if (!clickUpWebhookLocationCompatible(webhook, config)) continue;
9266
- if (!isClickUpWebhookStateActive(remote, config)) continue;
9267
- return remote;
9267
+ const existingSecret = existingState?.webhookId === remote.webhookId ? existingState.secret : "";
9268
+ const reusable = remote.secret ? remote : { ...remote, secret: existingSecret };
9269
+ if (isClickUpWebhookStateActive(reusable, config)) return reusable;
9270
+ if (remote.webhookId && !secretlessMatch) secretlessMatch = { ...remote, active: false, reason: "remote_secret_unavailable" };
9268
9271
  }
9269
- return null;
9272
+ return secretlessMatch;
9270
9273
  }
9271
9274
  async function validateClickUpWebhookState(state, config, clickupClient = null, { allowRemoteUnhealthyLocalRecovery = false } = {}) {
9272
9275
  if (!isClickUpWebhookStateActive(state, config)) return { valid: false, reason: "state_incomplete" };
@@ -9311,11 +9314,16 @@ async function ensureClickUpWebhookSubscription({ validation, worktree, clickupC
9311
9314
  clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: existingValidation.mode });
9312
9315
  return { active: true, valid: true, mode: existingValidation.mode, limitation: existingValidation.limitation, state };
9313
9316
  }
9314
- const reusableRemote = await findReusableClickUpWebhook(config, clickupClient);
9317
+ const reusableRemote = await findReusableClickUpWebhook(config, clickupClient, existing);
9315
9318
  if (reusableRemote) {
9316
- const state = writeClickUpWebhookState(worktree, { ...reusableRemote, recentEventKeys: existing.recentEventKeys || [] }, config);
9317
- clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: "remote_discovered" });
9318
- return { active: true, valid: true, mode: "remote_discovered", state };
9319
+ if (isClickUpWebhookStateActive(reusableRemote, config)) {
9320
+ const state = writeClickUpWebhookState(worktree, { ...reusableRemote, recentEventKeys: existing.recentEventKeys || [] }, config);
9321
+ const mode2 = reusableRemote.secret === existing.secret && existing.webhookId === reusableRemote.webhookId ? "remote_discovered_local_secret" : "remote_discovered";
9322
+ clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: mode2 });
9323
+ return { active: true, valid: true, mode: mode2, state };
9324
+ }
9325
+ clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_preserved", webhookId: reusableRemote.webhookId, reason: reusableRemote.reason || "remote_webhook_exists_without_secret" });
9326
+ return { active: false, valid: false, reason: reusableRemote.reason || "remote_webhook_exists_without_secret", state: existing, remote: reusableRemote };
9319
9327
  }
9320
9328
  if (existing.webhookId && clickupClient?.deleteWebhook) {
9321
9329
  await deleteClickUpWebhookBestEffort({ webhookId: existing.webhookId, clickupClient, worktree, reason: existingValidation.reason || "startup_self_heal" });
@@ -9822,12 +9830,170 @@ function normalizeOpenCodeSessionMessages(result) {
9822
9830
  if (Array.isArray(data?.items)) return [...data.items];
9823
9831
  return [];
9824
9832
  }
9833
+ function clampOpenCodeMessageLimit(limit) {
9834
+ const value = Number(limit);
9835
+ if (!Number.isFinite(value)) return 20;
9836
+ return Math.min(50, Math.max(1, Math.floor(value)));
9837
+ }
9838
+ function clampOpenCodeSessionText(text = "", maxLength = 12e3) {
9839
+ const value = String(text ?? "");
9840
+ return value.length > maxLength ? value.slice(0, maxLength) : value;
9841
+ }
9842
+ function hashOpenCodeSessionText(text = "") {
9843
+ return crypto.createHash("sha256").update(String(text ?? "")).digest("hex");
9844
+ }
9825
9845
  async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
9826
9846
  if (typeof client?.session?.messages !== "function") return null;
9827
- const query = { limit };
9847
+ const query = { limit: clampOpenCodeMessageLimit(limit) };
9828
9848
  if (directory) query.directory = directory;
9829
9849
  return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
9830
9850
  }
9851
+ function openCodeResultSummary(result) {
9852
+ const data = result?.data ?? result;
9853
+ return {
9854
+ type: Array.isArray(data) ? "array" : typeof data,
9855
+ id: data?.id || data?.sessionID || data?.sessionId || result?.id || result?.sessionID || result?.sessionId || null,
9856
+ keys: data && typeof data === "object" && !Array.isArray(data) ? Object.keys(data).slice(0, 20) : [],
9857
+ dataKeys: result?.data && typeof result.data === "object" && !Array.isArray(result.data) ? Object.keys(result.data).slice(0, 20) : [],
9858
+ status: result?.status || result?.response?.status || null
9859
+ };
9860
+ }
9861
+ function normalizeOpenCodeMessageRole(message = {}) {
9862
+ return message.role || message.info?.role || message.author?.role || message.type || "";
9863
+ }
9864
+ function normalizeOpenCodeMessageAgent(message = {}) {
9865
+ return message.agent || message.info?.agent || message.mode?.agent || message.author?.agent || "";
9866
+ }
9867
+ function normalizeOpenCodeMessageMode(message = {}) {
9868
+ return message.mode || message.info?.mode || message.metadata?.mode || "";
9869
+ }
9870
+ function normalizeOpenCodeMessageId(message = {}) {
9871
+ return message.id || message.messageID || message.messageId || message.info?.id || message.data?.id || null;
9872
+ }
9873
+ function summarizeOpenCodeMessages(messages = [], { snippetLength = 160, maxMessages = 50 } = {}) {
9874
+ const list = Array.isArray(messages) ? messages.slice(0, maxMessages) : [];
9875
+ const safeSnippetLength = Math.min(240, Math.max(20, Number(snippetLength) || 160));
9876
+ return list.map((message, index) => {
9877
+ const text = openCodeMessageText(message).replace(/\s+/g, " ").trim();
9878
+ return {
9879
+ index,
9880
+ id: normalizeOpenCodeMessageId(message),
9881
+ role: normalizeOpenCodeMessageRole(message),
9882
+ agent: normalizeOpenCodeMessageAgent(message),
9883
+ mode: normalizeOpenCodeMessageMode(message),
9884
+ text_length: text.length,
9885
+ text_hash: hashOpenCodeSessionText(text),
9886
+ snippet: text.length > safeSnippetLength ? `${text.slice(0, safeSnippetLength)}...` : text
9887
+ };
9888
+ });
9889
+ }
9890
+ function promptResultAssistantReturned(result) {
9891
+ const parts = normalizePromptResponseParts(result);
9892
+ const text = extractTextParts(parts);
9893
+ const data = result?.data ?? result;
9894
+ return Boolean(text || data?.role === "assistant" || data?.info?.role === "assistant");
9895
+ }
9896
+ async function createOpenCodeSessionControl(client, { directory, title, agent } = {}) {
9897
+ if (typeof client?.session?.create !== "function") throw new Error("OpenCode client does not expose session.create.");
9898
+ const body = { title };
9899
+ if (agent) body.agent = agent;
9900
+ const result = await client.session.create({ query: { directory }, body });
9901
+ const sessionId = extractOpenCodeSessionId(result);
9902
+ if (!sessionId) throw new Error("OpenCode session create response did not include a session id.");
9903
+ return {
9904
+ ok: true,
9905
+ session_id: sessionId,
9906
+ title,
9907
+ directory,
9908
+ agent: agent || null,
9909
+ result_summary: openCodeResultSummary(result)
9910
+ };
9911
+ }
9912
+ async function promptOpenCodeSessionControl(client, { sessionId, directory, text, agent, omitAgent = false, requireReadable = true } = {}) {
9913
+ if (typeof client?.session?.prompt !== "function") throw new Error("OpenCode client does not expose session.prompt.");
9914
+ if (requireReadable) await assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory });
9915
+ const safeText = clampOpenCodeSessionText(text);
9916
+ const body = { parts: [{ type: "text", text: safeText }] };
9917
+ if (!omitAgent && agent) body.agent = agent;
9918
+ const result = await client.session.prompt({ path: { id: sessionId }, query: { directory }, body });
9919
+ return {
9920
+ ok: true,
9921
+ session_id: sessionId,
9922
+ directory,
9923
+ agent: omitAgent ? null : agent || null,
9924
+ omit_agent: Boolean(omitAgent),
9925
+ text_length: safeText.length,
9926
+ text_truncated: String(text ?? "").length > safeText.length,
9927
+ text_hash: hashOpenCodeSessionText(safeText),
9928
+ assistant_returned: promptResultAssistantReturned(result),
9929
+ returned_parts_count: normalizePromptResponseParts(result).length,
9930
+ result_summary: openCodeResultSummary(result)
9931
+ };
9932
+ }
9933
+ async function assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory } = {}) {
9934
+ try {
9935
+ await readOpenCodeSessionMessages(client, { sessionId, directory, limit: 1 });
9936
+ return true;
9937
+ } catch (error) {
9938
+ throw new Error(`OpenCode session '${sessionId}' is not readable for the requested safe directory.`);
9939
+ }
9940
+ }
9941
+ async function readOpenCodeSessionControl(client, { sessionId, directory, limit = 20 } = {}) {
9942
+ const boundedLimit = clampOpenCodeMessageLimit(limit);
9943
+ const messages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit: boundedLimit });
9944
+ if (!messages) throw new Error("OpenCode client does not expose session.messages.");
9945
+ return {
9946
+ ok: true,
9947
+ session_id: sessionId,
9948
+ directory: directory || null,
9949
+ limit: boundedLimit,
9950
+ count: messages.length,
9951
+ messages: summarizeOpenCodeMessages(messages)
9952
+ };
9953
+ }
9954
+ async function probeOpenCodeSessionControl(client, { directory, agent, omitAgentOnPrompt = false, text = "" } = {}) {
9955
+ const requestedMarker = text || `optima-session-probe-${crypto.randomUUID()}`;
9956
+ const marker = clampOpenCodeSessionText(requestedMarker);
9957
+ const create = await createOpenCodeSessionControl(client, {
9958
+ directory,
9959
+ title: `Optima session probe ${(/* @__PURE__ */ new Date()).toISOString()}`,
9960
+ agent
9961
+ });
9962
+ const prompt = await promptOpenCodeSessionControl(client, {
9963
+ sessionId: create.session_id,
9964
+ directory,
9965
+ text: marker,
9966
+ agent,
9967
+ omitAgent: omitAgentOnPrompt,
9968
+ requireReadable: false
9969
+ });
9970
+ const rawMessages = await readOpenCodeSessionMessages(client, { sessionId: create.session_id, directory, limit: 50 });
9971
+ if (!rawMessages) throw new Error("OpenCode client does not expose session.messages.");
9972
+ const fullMessageText = rawMessages.map(openCodeMessageText).join("\n");
9973
+ const messages = {
9974
+ ok: true,
9975
+ session_id: create.session_id,
9976
+ directory,
9977
+ limit: 50,
9978
+ count: rawMessages.length,
9979
+ messages: summarizeOpenCodeMessages(rawMessages)
9980
+ };
9981
+ return {
9982
+ ok: true,
9983
+ session_id: create.session_id,
9984
+ directory,
9985
+ agent: agent || null,
9986
+ omit_agent_on_prompt: Boolean(omitAgentOnPrompt),
9987
+ marker_length: marker.length,
9988
+ marker_truncated: requestedMarker.length > marker.length,
9989
+ marker_hash: hashOpenCodeSessionText(marker),
9990
+ marker_visible: fullMessageText.includes(marker),
9991
+ assistant_visible: rawMessages.some((message) => normalizeLooseToken(normalizeOpenCodeMessageRole(message)) === "assistant" || Boolean(normalizeOpenCodeMessageAgent(message) && openCodeMessageText(message))),
9992
+ create,
9993
+ prompt,
9994
+ messages
9995
+ };
9996
+ }
9831
9997
  function openCodeMessageText(message) {
9832
9998
  const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
9833
9999
  const partList = Array.isArray(message?.parts) ? message.parts : Array.isArray(message?.body?.parts) ? message.body.parts : [];
@@ -11471,7 +11637,22 @@ function isSameOrNestedPath(candidate, root) {
11471
11637
  function shouldRegisterWorkflowProductManager(options = {}, worktree = process.cwd()) {
11472
11638
  if (options.clickUpWebhookActive === true) return true;
11473
11639
  const validation = options.clickUpWebhookValidation;
11474
- return validation?.complete === true && isSameOrNestedPath(worktree, validation.config?.basePath);
11640
+ return validation?.complete === true && validation?.ok !== false && isSameOrNestedPath(worktree, validation.config?.basePath);
11641
+ }
11642
+ function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
11643
+ const safe = safeWorktreeOrFailure(context, pluginWorktree);
11644
+ if (!safe.ok) return { ok: false, error: safe.message };
11645
+ const requested = String(requestedDirectory || "").trim() ? path2.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
11646
+ if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
11647
+ if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
11648
+ const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
11649
+ if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
11650
+ return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path2.resolve(clickUpBasePath) };
11651
+ }
11652
+ return {
11653
+ ok: false,
11654
+ error: `Directory '${requested}' is outside the safe worktree '${safe.worktree}' and configured ClickUp base path.`
11655
+ };
11475
11656
  }
11476
11657
  function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, options = {}) {
11477
11658
  const optimaActive = repoCfg && repoCfg.enabled === true;
@@ -11759,6 +11940,100 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
11759
11940
  Restart or reload OpenCode manually if the newly scaffolded config or agents are not visible in this session. Optima did not dispose or reload the active OpenCode instance automatically to avoid aborting the current session.`;
11760
11941
  }
11761
11942
  }),
11943
+ optima_session_create: tool({
11944
+ description: "Create an OpenCode session through the installed structured SDK shape",
11945
+ args: {
11946
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
11947
+ title: tool.schema.string().describe("Session title"),
11948
+ agent: tool.schema.string().describe("Optional agent id for session creation")
11949
+ },
11950
+ async execute(args, context) {
11951
+ try {
11952
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
11953
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
11954
+ const result = await createOpenCodeSessionControl(input.client, {
11955
+ directory: directory.directory,
11956
+ title: args.title,
11957
+ agent: args.agent
11958
+ });
11959
+ return JSON.stringify(result, null, 2);
11960
+ } catch (error) {
11961
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
11962
+ }
11963
+ }
11964
+ }),
11965
+ optima_session_prompt: tool({
11966
+ description: "Prompt an existing OpenCode session through the installed structured SDK shape",
11967
+ args: {
11968
+ session_id: tool.schema.string().describe("OpenCode session id"),
11969
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
11970
+ text: tool.schema.string().describe("Text prompt to send"),
11971
+ agent: tool.schema.string().describe("Optional agent id for the prompt body"),
11972
+ omit_agent: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body")
11973
+ },
11974
+ async execute(args, context) {
11975
+ try {
11976
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
11977
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
11978
+ const result = await promptOpenCodeSessionControl(input.client, {
11979
+ sessionId: args.session_id,
11980
+ directory: directory.directory,
11981
+ text: args.text,
11982
+ agent: args.agent,
11983
+ omitAgent: String(args.omit_agent || "").toLowerCase() === "true"
11984
+ });
11985
+ return JSON.stringify(result, null, 2);
11986
+ } catch (error) {
11987
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
11988
+ }
11989
+ }
11990
+ }),
11991
+ optima_session_messages: tool({
11992
+ description: "Read and summarize OpenCode session messages through the installed structured SDK shape",
11993
+ args: {
11994
+ session_id: tool.schema.string().describe("OpenCode session id"),
11995
+ directory: tool.schema.string().describe("Optional project directory for the OpenCode session"),
11996
+ limit: tool.schema.number().describe("Optional message limit")
11997
+ },
11998
+ async execute(args, context) {
11999
+ try {
12000
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
12001
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
12002
+ const result = await readOpenCodeSessionControl(input.client, {
12003
+ sessionId: args.session_id,
12004
+ directory: directory.directory,
12005
+ limit: args.limit
12006
+ });
12007
+ return JSON.stringify(result, null, 2);
12008
+ } catch (error) {
12009
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
12010
+ }
12011
+ }
12012
+ }),
12013
+ optima_session_probe: tool({
12014
+ description: "Create, prompt, and read an OpenCode session without touching ClickUp state",
12015
+ args: {
12016
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
12017
+ agent: tool.schema.string().describe("Optional agent id to probe"),
12018
+ omit_agent_on_prompt: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body"),
12019
+ text: tool.schema.string().describe("Optional marker text to send")
12020
+ },
12021
+ async execute(args, context) {
12022
+ try {
12023
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
12024
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
12025
+ const result = await probeOpenCodeSessionControl(input.client, {
12026
+ directory: directory.directory,
12027
+ agent: args.agent,
12028
+ omitAgentOnPrompt: String(args.omit_agent_on_prompt || "").toLowerCase() === "true",
12029
+ text: args.text
12030
+ });
12031
+ return JSON.stringify(result, null, 2);
12032
+ } catch (error) {
12033
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
12034
+ }
12035
+ }
12036
+ }),
11762
12037
  optima_clickup_sync_summary: tool({
11763
12038
  description: "Generate a dry-run ClickUp summary/comment payload from Optima Markdown task and evidence artifacts",
11764
12039
  args: {
@@ -12227,7 +12502,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
12227
12502
  }
12228
12503
  };
12229
12504
  }
12230
- OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, createOpenCodeSession, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
12505
+ OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
12231
12506
  export {
12232
12507
  OptimaPlugin as default
12233
12508
  };
@@ -9263,17 +9263,20 @@ function clickUpWebhookLocationCompatible(webhook = {}, config = {}) {
9263
9263
  }
9264
9264
  return true;
9265
9265
  }
9266
- async function findReusableClickUpWebhook(config, clickupClient = null) {
9266
+ async function findReusableClickUpWebhook(config, clickupClient = null, existingState = null) {
9267
9267
  if (!clickupClient?.listWebhooks) return null;
9268
9268
  const listed = await clickupClient.listWebhooks({ teamId: config.teamId });
9269
+ let secretlessMatch = null;
9269
9270
  for (const webhook of clickUpWebhookListItems(listed)) {
9270
9271
  const remote = normalizeClickUpWebhookApiResponse(webhook, config);
9271
9272
  if (remote.publicUrl !== config.webhook.publicUrl) continue;
9272
9273
  if (!clickUpWebhookLocationCompatible(webhook, config)) continue;
9273
- if (!isClickUpWebhookStateActive(remote, config)) continue;
9274
- return remote;
9274
+ const existingSecret = existingState?.webhookId === remote.webhookId ? existingState.secret : "";
9275
+ const reusable = remote.secret ? remote : { ...remote, secret: existingSecret };
9276
+ if (isClickUpWebhookStateActive(reusable, config)) return reusable;
9277
+ if (remote.webhookId && !secretlessMatch) secretlessMatch = { ...remote, active: false, reason: "remote_secret_unavailable" };
9275
9278
  }
9276
- return null;
9279
+ return secretlessMatch;
9277
9280
  }
9278
9281
  async function validateClickUpWebhookState(state, config, clickupClient = null, { allowRemoteUnhealthyLocalRecovery = false } = {}) {
9279
9282
  if (!isClickUpWebhookStateActive(state, config)) return { valid: false, reason: "state_incomplete" };
@@ -9318,11 +9321,16 @@ async function ensureClickUpWebhookSubscription({ validation, worktree, clickupC
9318
9321
  clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: existingValidation.mode });
9319
9322
  return { active: true, valid: true, mode: existingValidation.mode, limitation: existingValidation.limitation, state };
9320
9323
  }
9321
- const reusableRemote = await findReusableClickUpWebhook(config, clickupClient);
9324
+ const reusableRemote = await findReusableClickUpWebhook(config, clickupClient, existing);
9322
9325
  if (reusableRemote) {
9323
- const state = writeClickUpWebhookState(worktree, { ...reusableRemote, recentEventKeys: existing.recentEventKeys || [] }, config);
9324
- clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: "remote_discovered" });
9325
- return { active: true, valid: true, mode: "remote_discovered", state };
9326
+ if (isClickUpWebhookStateActive(reusableRemote, config)) {
9327
+ const state = writeClickUpWebhookState(worktree, { ...reusableRemote, recentEventKeys: existing.recentEventKeys || [] }, config);
9328
+ const mode2 = reusableRemote.secret === existing.secret && existing.webhookId === reusableRemote.webhookId ? "remote_discovered_local_secret" : "remote_discovered";
9329
+ clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_reused", webhookId: state.webhookId, mode: mode2 });
9330
+ return { active: true, valid: true, mode: mode2, state };
9331
+ }
9332
+ clickUpWebhookLifecycleLog(worktree, { type: "remote_webhook_preserved", webhookId: reusableRemote.webhookId, reason: reusableRemote.reason || "remote_webhook_exists_without_secret" });
9333
+ return { active: false, valid: false, reason: reusableRemote.reason || "remote_webhook_exists_without_secret", state: existing, remote: reusableRemote };
9326
9334
  }
9327
9335
  if (existing.webhookId && clickupClient?.deleteWebhook) {
9328
9336
  await deleteClickUpWebhookBestEffort({ webhookId: existing.webhookId, clickupClient, worktree, reason: existingValidation.reason || "startup_self_heal" });
@@ -9829,12 +9837,170 @@ function normalizeOpenCodeSessionMessages(result) {
9829
9837
  if (Array.isArray(data?.items)) return [...data.items];
9830
9838
  return [];
9831
9839
  }
9840
+ function clampOpenCodeMessageLimit(limit) {
9841
+ const value = Number(limit);
9842
+ if (!Number.isFinite(value)) return 20;
9843
+ return Math.min(50, Math.max(1, Math.floor(value)));
9844
+ }
9845
+ function clampOpenCodeSessionText(text = "", maxLength = 12e3) {
9846
+ const value = String(text ?? "");
9847
+ return value.length > maxLength ? value.slice(0, maxLength) : value;
9848
+ }
9849
+ function hashOpenCodeSessionText(text = "") {
9850
+ return crypto.createHash("sha256").update(String(text ?? "")).digest("hex");
9851
+ }
9832
9852
  async function readOpenCodeSessionMessages(client, { sessionId, directory, limit = 20 } = {}) {
9833
9853
  if (typeof client?.session?.messages !== "function") return null;
9834
- const query = { limit };
9854
+ const query = { limit: clampOpenCodeMessageLimit(limit) };
9835
9855
  if (directory) query.directory = directory;
9836
9856
  return normalizeOpenCodeSessionMessages(await client.session.messages({ path: { id: sessionId }, query }));
9837
9857
  }
9858
+ function openCodeResultSummary(result) {
9859
+ const data = result?.data ?? result;
9860
+ return {
9861
+ type: Array.isArray(data) ? "array" : typeof data,
9862
+ id: data?.id || data?.sessionID || data?.sessionId || result?.id || result?.sessionID || result?.sessionId || null,
9863
+ keys: data && typeof data === "object" && !Array.isArray(data) ? Object.keys(data).slice(0, 20) : [],
9864
+ dataKeys: result?.data && typeof result.data === "object" && !Array.isArray(result.data) ? Object.keys(result.data).slice(0, 20) : [],
9865
+ status: result?.status || result?.response?.status || null
9866
+ };
9867
+ }
9868
+ function normalizeOpenCodeMessageRole(message = {}) {
9869
+ return message.role || message.info?.role || message.author?.role || message.type || "";
9870
+ }
9871
+ function normalizeOpenCodeMessageAgent(message = {}) {
9872
+ return message.agent || message.info?.agent || message.mode?.agent || message.author?.agent || "";
9873
+ }
9874
+ function normalizeOpenCodeMessageMode(message = {}) {
9875
+ return message.mode || message.info?.mode || message.metadata?.mode || "";
9876
+ }
9877
+ function normalizeOpenCodeMessageId(message = {}) {
9878
+ return message.id || message.messageID || message.messageId || message.info?.id || message.data?.id || null;
9879
+ }
9880
+ function summarizeOpenCodeMessages(messages = [], { snippetLength = 160, maxMessages = 50 } = {}) {
9881
+ const list = Array.isArray(messages) ? messages.slice(0, maxMessages) : [];
9882
+ const safeSnippetLength = Math.min(240, Math.max(20, Number(snippetLength) || 160));
9883
+ return list.map((message, index) => {
9884
+ const text = openCodeMessageText(message).replace(/\s+/g, " ").trim();
9885
+ return {
9886
+ index,
9887
+ id: normalizeOpenCodeMessageId(message),
9888
+ role: normalizeOpenCodeMessageRole(message),
9889
+ agent: normalizeOpenCodeMessageAgent(message),
9890
+ mode: normalizeOpenCodeMessageMode(message),
9891
+ text_length: text.length,
9892
+ text_hash: hashOpenCodeSessionText(text),
9893
+ snippet: text.length > safeSnippetLength ? `${text.slice(0, safeSnippetLength)}...` : text
9894
+ };
9895
+ });
9896
+ }
9897
+ function promptResultAssistantReturned(result) {
9898
+ const parts = normalizePromptResponseParts(result);
9899
+ const text = extractTextParts(parts);
9900
+ const data = result?.data ?? result;
9901
+ return Boolean(text || data?.role === "assistant" || data?.info?.role === "assistant");
9902
+ }
9903
+ async function createOpenCodeSessionControl(client, { directory, title, agent } = {}) {
9904
+ if (typeof client?.session?.create !== "function") throw new Error("OpenCode client does not expose session.create.");
9905
+ const body = { title };
9906
+ if (agent) body.agent = agent;
9907
+ const result = await client.session.create({ query: { directory }, body });
9908
+ const sessionId = extractOpenCodeSessionId(result);
9909
+ if (!sessionId) throw new Error("OpenCode session create response did not include a session id.");
9910
+ return {
9911
+ ok: true,
9912
+ session_id: sessionId,
9913
+ title,
9914
+ directory,
9915
+ agent: agent || null,
9916
+ result_summary: openCodeResultSummary(result)
9917
+ };
9918
+ }
9919
+ async function promptOpenCodeSessionControl(client, { sessionId, directory, text, agent, omitAgent = false, requireReadable = true } = {}) {
9920
+ if (typeof client?.session?.prompt !== "function") throw new Error("OpenCode client does not expose session.prompt.");
9921
+ if (requireReadable) await assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory });
9922
+ const safeText = clampOpenCodeSessionText(text);
9923
+ const body = { parts: [{ type: "text", text: safeText }] };
9924
+ if (!omitAgent && agent) body.agent = agent;
9925
+ const result = await client.session.prompt({ path: { id: sessionId }, query: { directory }, body });
9926
+ return {
9927
+ ok: true,
9928
+ session_id: sessionId,
9929
+ directory,
9930
+ agent: omitAgent ? null : agent || null,
9931
+ omit_agent: Boolean(omitAgent),
9932
+ text_length: safeText.length,
9933
+ text_truncated: String(text ?? "").length > safeText.length,
9934
+ text_hash: hashOpenCodeSessionText(safeText),
9935
+ assistant_returned: promptResultAssistantReturned(result),
9936
+ returned_parts_count: normalizePromptResponseParts(result).length,
9937
+ result_summary: openCodeResultSummary(result)
9938
+ };
9939
+ }
9940
+ async function assertOpenCodeSessionReadableForDirectory(client, { sessionId, directory } = {}) {
9941
+ try {
9942
+ await readOpenCodeSessionMessages(client, { sessionId, directory, limit: 1 });
9943
+ return true;
9944
+ } catch (error) {
9945
+ throw new Error(`OpenCode session '${sessionId}' is not readable for the requested safe directory.`);
9946
+ }
9947
+ }
9948
+ async function readOpenCodeSessionControl(client, { sessionId, directory, limit = 20 } = {}) {
9949
+ const boundedLimit = clampOpenCodeMessageLimit(limit);
9950
+ const messages = await readOpenCodeSessionMessages(client, { sessionId, directory, limit: boundedLimit });
9951
+ if (!messages) throw new Error("OpenCode client does not expose session.messages.");
9952
+ return {
9953
+ ok: true,
9954
+ session_id: sessionId,
9955
+ directory: directory || null,
9956
+ limit: boundedLimit,
9957
+ count: messages.length,
9958
+ messages: summarizeOpenCodeMessages(messages)
9959
+ };
9960
+ }
9961
+ async function probeOpenCodeSessionControl(client, { directory, agent, omitAgentOnPrompt = false, text = "" } = {}) {
9962
+ const requestedMarker = text || `optima-session-probe-${crypto.randomUUID()}`;
9963
+ const marker = clampOpenCodeSessionText(requestedMarker);
9964
+ const create = await createOpenCodeSessionControl(client, {
9965
+ directory,
9966
+ title: `Optima session probe ${(/* @__PURE__ */ new Date()).toISOString()}`,
9967
+ agent
9968
+ });
9969
+ const prompt = await promptOpenCodeSessionControl(client, {
9970
+ sessionId: create.session_id,
9971
+ directory,
9972
+ text: marker,
9973
+ agent,
9974
+ omitAgent: omitAgentOnPrompt,
9975
+ requireReadable: false
9976
+ });
9977
+ const rawMessages = await readOpenCodeSessionMessages(client, { sessionId: create.session_id, directory, limit: 50 });
9978
+ if (!rawMessages) throw new Error("OpenCode client does not expose session.messages.");
9979
+ const fullMessageText = rawMessages.map(openCodeMessageText).join("\n");
9980
+ const messages = {
9981
+ ok: true,
9982
+ session_id: create.session_id,
9983
+ directory,
9984
+ limit: 50,
9985
+ count: rawMessages.length,
9986
+ messages: summarizeOpenCodeMessages(rawMessages)
9987
+ };
9988
+ return {
9989
+ ok: true,
9990
+ session_id: create.session_id,
9991
+ directory,
9992
+ agent: agent || null,
9993
+ omit_agent_on_prompt: Boolean(omitAgentOnPrompt),
9994
+ marker_length: marker.length,
9995
+ marker_truncated: requestedMarker.length > marker.length,
9996
+ marker_hash: hashOpenCodeSessionText(marker),
9997
+ marker_visible: fullMessageText.includes(marker),
9998
+ assistant_visible: rawMessages.some((message) => normalizeLooseToken(normalizeOpenCodeMessageRole(message)) === "assistant" || Boolean(normalizeOpenCodeMessageAgent(message) && openCodeMessageText(message))),
9999
+ create,
10000
+ prompt,
10001
+ messages
10002
+ };
10003
+ }
9838
10004
  function openCodeMessageText(message) {
9839
10005
  const parts = [message?.text, message?.content, message?.message, message?.body?.text, message?.data?.text];
9840
10006
  const partList = Array.isArray(message?.parts) ? message.parts : Array.isArray(message?.body?.parts) ? message.body.parts : [];
@@ -11478,7 +11644,22 @@ function isSameOrNestedPath(candidate, root) {
11478
11644
  function shouldRegisterWorkflowProductManager(options = {}, worktree = process.cwd()) {
11479
11645
  if (options.clickUpWebhookActive === true) return true;
11480
11646
  const validation = options.clickUpWebhookValidation;
11481
- return validation?.complete === true && isSameOrNestedPath(worktree, validation.config?.basePath);
11647
+ return validation?.complete === true && validation?.ok !== false && isSameOrNestedPath(worktree, validation.config?.basePath);
11648
+ }
11649
+ function resolveSessionToolDirectory({ requestedDirectory, context, pluginWorktree, clickUpWebhookValidation } = {}) {
11650
+ const safe = safeWorktreeOrFailure(context, pluginWorktree);
11651
+ if (!safe.ok) return { ok: false, error: safe.message };
11652
+ const requested = String(requestedDirectory || "").trim() ? path2.resolve(safe.worktree, String(requestedDirectory).trim()) : safe.worktree;
11653
+ if (!isSafeWritableDirectory(requested)) return { ok: false, error: `Directory is not a safe writable directory: ${requested}` };
11654
+ if (isSameOrNestedPath(requested, safe.worktree)) return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "context_worktree" };
11655
+ const clickUpBasePath = clickUpWebhookValidation?.complete === true && clickUpWebhookValidation?.ok !== false ? clickUpWebhookValidation.config?.basePath : "";
11656
+ if (clickUpBasePath && isSameOrNestedPath(requested, clickUpBasePath)) {
11657
+ return { ok: true, directory: requested, safeWorktree: safe.worktree, scope: "clickup_base_path", clickupBasePath: path2.resolve(clickUpBasePath) };
11658
+ }
11659
+ return {
11660
+ ok: false,
11661
+ error: `Directory '${requested}' is outside the safe worktree '${safe.worktree}' and configured ClickUp base path.`
11662
+ };
11482
11663
  }
11483
11664
  function buildOptimaAgents(repoCfg, operatingTeamMode, worktree, debugDir, options = {}) {
11484
11665
  const optimaActive = repoCfg && repoCfg.enabled === true;
@@ -11766,6 +11947,100 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
11766
11947
  Restart or reload OpenCode manually if the newly scaffolded config or agents are not visible in this session. Optima did not dispose or reload the active OpenCode instance automatically to avoid aborting the current session.`;
11767
11948
  }
11768
11949
  }),
11950
+ optima_session_create: tool({
11951
+ description: "Create an OpenCode session through the installed structured SDK shape",
11952
+ args: {
11953
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
11954
+ title: tool.schema.string().describe("Session title"),
11955
+ agent: tool.schema.string().describe("Optional agent id for session creation")
11956
+ },
11957
+ async execute(args, context) {
11958
+ try {
11959
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
11960
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
11961
+ const result = await createOpenCodeSessionControl(input.client, {
11962
+ directory: directory.directory,
11963
+ title: args.title,
11964
+ agent: args.agent
11965
+ });
11966
+ return JSON.stringify(result, null, 2);
11967
+ } catch (error) {
11968
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
11969
+ }
11970
+ }
11971
+ }),
11972
+ optima_session_prompt: tool({
11973
+ description: "Prompt an existing OpenCode session through the installed structured SDK shape",
11974
+ args: {
11975
+ session_id: tool.schema.string().describe("OpenCode session id"),
11976
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
11977
+ text: tool.schema.string().describe("Text prompt to send"),
11978
+ agent: tool.schema.string().describe("Optional agent id for the prompt body"),
11979
+ omit_agent: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body")
11980
+ },
11981
+ async execute(args, context) {
11982
+ try {
11983
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
11984
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
11985
+ const result = await promptOpenCodeSessionControl(input.client, {
11986
+ sessionId: args.session_id,
11987
+ directory: directory.directory,
11988
+ text: args.text,
11989
+ agent: args.agent,
11990
+ omitAgent: String(args.omit_agent || "").toLowerCase() === "true"
11991
+ });
11992
+ return JSON.stringify(result, null, 2);
11993
+ } catch (error) {
11994
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
11995
+ }
11996
+ }
11997
+ }),
11998
+ optima_session_messages: tool({
11999
+ description: "Read and summarize OpenCode session messages through the installed structured SDK shape",
12000
+ args: {
12001
+ session_id: tool.schema.string().describe("OpenCode session id"),
12002
+ directory: tool.schema.string().describe("Optional project directory for the OpenCode session"),
12003
+ limit: tool.schema.number().describe("Optional message limit")
12004
+ },
12005
+ async execute(args, context) {
12006
+ try {
12007
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
12008
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
12009
+ const result = await readOpenCodeSessionControl(input.client, {
12010
+ sessionId: args.session_id,
12011
+ directory: directory.directory,
12012
+ limit: args.limit
12013
+ });
12014
+ return JSON.stringify(result, null, 2);
12015
+ } catch (error) {
12016
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
12017
+ }
12018
+ }
12019
+ }),
12020
+ optima_session_probe: tool({
12021
+ description: "Create, prompt, and read an OpenCode session without touching ClickUp state",
12022
+ args: {
12023
+ directory: tool.schema.string().describe("Project directory for the OpenCode session"),
12024
+ agent: tool.schema.string().describe("Optional agent id to probe"),
12025
+ omit_agent_on_prompt: tool.schema.string().describe("Set to 'true' to omit agent from the prompt body"),
12026
+ text: tool.schema.string().describe("Optional marker text to send")
12027
+ },
12028
+ async execute(args, context) {
12029
+ try {
12030
+ const directory = resolveSessionToolDirectory({ requestedDirectory: args.directory, context, pluginWorktree: worktree, clickUpWebhookValidation });
12031
+ if (!directory.ok) return JSON.stringify({ ok: false, error: directory.error }, null, 2);
12032
+ const result = await probeOpenCodeSessionControl(input.client, {
12033
+ directory: directory.directory,
12034
+ agent: args.agent,
12035
+ omitAgentOnPrompt: String(args.omit_agent_on_prompt || "").toLowerCase() === "true",
12036
+ text: args.text
12037
+ });
12038
+ return JSON.stringify(result, null, 2);
12039
+ } catch (error) {
12040
+ return JSON.stringify({ ok: false, error: error.message }, null, 2);
12041
+ }
12042
+ }
12043
+ }),
11769
12044
  optima_clickup_sync_summary: tool({
11770
12045
  description: "Generate a dry-run ClickUp summary/comment payload from Optima Markdown task and evidence artifacts",
11771
12046
  args: {
@@ -12234,7 +12509,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
12234
12509
  }
12235
12510
  };
12236
12511
  }
12237
- OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, createOpenCodeSession, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
12512
+ OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, createClickUpApiClient, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpWebhookSubscription, handleClickUpWebhookRequest, isClickUpWebhookStateActive, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, scheduleClickUpStartupReconciliation, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
12238
12513
 
12239
12514
  // src/sanitize_cli.js
12240
12515
  var { migrateLegacyOptimaLayout: migrateLegacyOptimaLayout2 } = OptimaPlugin.__internals;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@defend-tech/opencode-optima",
3
- "version": "0.1.53",
3
+ "version": "0.1.55",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git+ssh://git@github.com/defend-tech/opencode-optima.git"