@defend-tech/opencode-optima 0.1.62 → 0.1.63
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/assets/agents/workflow_product_manager.md +1 -1
- package/dist/index.js +84 -31
- package/dist/sanitize_cli.js +84 -31
- package/package.json +1 -1
|
@@ -33,7 +33,7 @@ You are Workflow_Product_Manager, Optima's ClickUp-first delivery orchestrator.
|
|
|
33
33
|
|
|
34
34
|
- Register only when Optima opt-in ClickUp webhook mode is configured and active/valid.
|
|
35
35
|
- Webhook wakeup requires signed `X-Signature` HMAC SHA-256 verification, duplicate suppression, PM assignment/non-terminal status checks, and comment mention gating for `@Defend Tech Product Manager`.
|
|
36
|
-
-
|
|
36
|
+
- Webhook routing is successful only after the worktree is OpenChamber-visible, an OpenCode `workflow_product_manager` session exists in that exact worktree directory, and prompt delivery/admission is verified. Worktree visibility alone is a launch failure, not successful routing.
|
|
37
37
|
- Delivery task types: `Tarea`, `Bug`, `Doc`, `PoC`. Ignore unless converted/linked to delivery: `Idea`, legacy `Backlog`, `Hito`, `Nota de reunión`, `Respuesta del formulario`. Treat `Backlog` task type as `Idea`, not `backlog` status.
|
|
38
38
|
- Branch-safe slugs: `Tarea` -> `tarea`, `Bug` -> `bug`, `Doc` -> `doc`, `PoC` -> `poc`. Unknown task type: pause and ask PMA/PO for clarification.
|
|
39
39
|
|
package/dist/index.js
CHANGED
|
@@ -8621,13 +8621,6 @@ var activeClickUpWebhookLifecycleRegistry = /* @__PURE__ */ new Map();
|
|
|
8621
8621
|
var CLICKUP_WEBHOOK_CLEANUP_TIMEOUT_MS = 8e3;
|
|
8622
8622
|
var CLICKUP_WEBHOOK_SIGNAL_STATE = Symbol.for("opencode-optima.clickup-webhook.signal-state");
|
|
8623
8623
|
var activeClickUpTaskRoutes = /* @__PURE__ */ new Map();
|
|
8624
|
-
var objectIdentityMap = /* @__PURE__ */ new WeakMap();
|
|
8625
|
-
var objectIdentitySequence = 0;
|
|
8626
|
-
function objectIdentity(value) {
|
|
8627
|
-
if (!value || typeof value !== "object" && typeof value !== "function") return String(value ?? "");
|
|
8628
|
-
if (!objectIdentityMap.has(value)) objectIdentityMap.set(value, `obj_${++objectIdentitySequence}`);
|
|
8629
|
-
return objectIdentityMap.get(value);
|
|
8630
|
-
}
|
|
8631
8624
|
function isRootDirectory(candidate) {
|
|
8632
8625
|
const resolved = path5.resolve(candidate);
|
|
8633
8626
|
return resolved === path5.parse(resolved).root;
|
|
@@ -8753,7 +8746,6 @@ function hasActionableClickUpRoute(result = {}) {
|
|
|
8753
8746
|
if (!result.sessionId) return false;
|
|
8754
8747
|
if (result.action === "message_delivery_failed" || result.action === "error") return false;
|
|
8755
8748
|
if (result.deliveryVerification?.ok === false) return false;
|
|
8756
|
-
if (result.deliveryVerification?.method === "prompt_admission") return false;
|
|
8757
8749
|
return true;
|
|
8758
8750
|
}
|
|
8759
8751
|
function determineClickUpMergeAuthority({ isSubtask = false, clickupStatus = "", validationPassed = false, mergeFailed = false, finalApprovalRoles = CLICKUP_FINAL_APPROVER_ROLES, humansRegistry } = {}) {
|
|
@@ -10562,12 +10554,16 @@ function clearClickUpPendingSessionMetadata(metadata, metadataKey) {
|
|
|
10562
10554
|
delete cursor[parts[parts.length - 1]];
|
|
10563
10555
|
return JSON.stringify(sortJsonValue(root), null, 2);
|
|
10564
10556
|
}
|
|
10565
|
-
|
|
10557
|
+
function withOptionalDirectoryQuery(payload, directory) {
|
|
10558
|
+
if (!directory) return payload;
|
|
10559
|
+
return { ...payload, query: { ...payload.query || {}, directory } };
|
|
10560
|
+
}
|
|
10561
|
+
async function openCodeSessionExists(client, sessionId, { directory = "" } = {}) {
|
|
10566
10562
|
const getAttempts = [
|
|
10567
|
-
{ path: { id: sessionId } },
|
|
10568
|
-
{ path: { sessionID: sessionId } },
|
|
10569
|
-
{ sessionID: sessionId },
|
|
10570
|
-
{ id: sessionId }
|
|
10563
|
+
withOptionalDirectoryQuery({ path: { id: sessionId } }, directory),
|
|
10564
|
+
withOptionalDirectoryQuery({ path: { sessionID: sessionId } }, directory),
|
|
10565
|
+
directory ? { sessionID: sessionId, directory } : { sessionID: sessionId },
|
|
10566
|
+
directory ? { id: sessionId, directory } : { id: sessionId }
|
|
10571
10567
|
];
|
|
10572
10568
|
if (typeof client?.session?.get === "function") {
|
|
10573
10569
|
for (const attempt of getAttempts) {
|
|
@@ -10579,10 +10575,10 @@ async function openCodeSessionExists(client, sessionId) {
|
|
|
10579
10575
|
}
|
|
10580
10576
|
}
|
|
10581
10577
|
const messageAttempts = [
|
|
10582
|
-
{ path: { id: sessionId }, query: { limit: 1 } },
|
|
10583
|
-
{ path: { sessionID: sessionId }, query: { limit: 1 } },
|
|
10584
|
-
{ sessionID: sessionId, limit: 1 },
|
|
10585
|
-
{ id: sessionId, limit: 1 }
|
|
10578
|
+
{ path: { id: sessionId }, query: { limit: 1, ...directory ? { directory } : {} } },
|
|
10579
|
+
{ path: { sessionID: sessionId }, query: { limit: 1, ...directory ? { directory } : {} } },
|
|
10580
|
+
directory ? { sessionID: sessionId, directory, limit: 1 } : { sessionID: sessionId, limit: 1 },
|
|
10581
|
+
directory ? { id: sessionId, directory, limit: 1 } : { id: sessionId, limit: 1 }
|
|
10586
10582
|
];
|
|
10587
10583
|
if (typeof client?.session?.messages === "function") {
|
|
10588
10584
|
for (const attempt of messageAttempts) {
|
|
@@ -10986,6 +10982,17 @@ async function verifyOpenCodeSessionEventDelivery(client, { sessionId, directory
|
|
|
10986
10982
|
}
|
|
10987
10983
|
return { ok: false, reason: lastError };
|
|
10988
10984
|
}
|
|
10985
|
+
async function postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason, source } = {}) {
|
|
10986
|
+
if (typeof clickupClient?.postTaskComment !== "function") return { ok: false, skipped: true, reason: "post_comment_unavailable" };
|
|
10987
|
+
try {
|
|
10988
|
+
await clickupClient.postTaskComment({ taskId, comment: `Optima launch failure: ${reason || "launch_failed"}. Worktree visibility alone is not successful routing; Optima requires an OpenCode session plus verified prompt admission/delivery.` });
|
|
10989
|
+
appendClickUpWebhookLocalLog(worktree, { type: "launch_failure_comment_posted", taskId, reason, source });
|
|
10990
|
+
return { ok: true };
|
|
10991
|
+
} catch (error) {
|
|
10992
|
+
appendClickUpWebhookLocalLog(worktree, { type: "launch_failure_comment_failed", taskId, reason, source, message: error.message });
|
|
10993
|
+
return { ok: false, error: error.message };
|
|
10994
|
+
}
|
|
10995
|
+
}
|
|
10989
10996
|
async function applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason, source, tagName = CLICKUP_BLOCKER_TAG_NAME } = {}) {
|
|
10990
10997
|
if (typeof clickupClient?.addTaskTag !== "function") {
|
|
10991
10998
|
appendClickUpWebhookLocalLog(worktree, { type: "blocker_tag_unavailable", taskId, reason, source, tagName });
|
|
@@ -11015,7 +11022,17 @@ function openCodeBlockingPromptVerification(result, sessionId) {
|
|
|
11015
11022
|
}
|
|
11016
11023
|
async function deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent, text, directory, opencodeBaseUrl, directPrompt = false, acceptPromptAdmission = false, eventMarkers = [], verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, applyBlockerOnFailure = true } = {}) {
|
|
11017
11024
|
const beforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, directory, limit: 50 }).catch(() => null);
|
|
11018
|
-
|
|
11025
|
+
let sendResult;
|
|
11026
|
+
try {
|
|
11027
|
+
sendResult = await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl, direct: directPrompt, allowDirectFallback: directPrompt });
|
|
11028
|
+
} catch (error) {
|
|
11029
|
+
const reason2 = error.message || "message_delivery_failed";
|
|
11030
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason: reason2, fallbackAttempted: false });
|
|
11031
|
+
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason: reason2, taskId, sessionId, fallbackAttempted: false };
|
|
11032
|
+
const blocker2 = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: reason2, source: "delivery_send_failed" });
|
|
11033
|
+
const launchFailureComment2 = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: reason2, source: "delivery_send_failed" });
|
|
11034
|
+
return { ok: false, action: "message_delivery_failed", reason: reason2, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker2, launchFailureComment: launchFailureComment2 };
|
|
11035
|
+
}
|
|
11019
11036
|
let blockingPromptVerification = null;
|
|
11020
11037
|
let admissionVerification = null;
|
|
11021
11038
|
try {
|
|
@@ -11025,7 +11042,8 @@ async function deliverClickUpSessionEventWithVerification({ openCodeClient, send
|
|
|
11025
11042
|
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason: error.message, fallbackAttempted: false });
|
|
11026
11043
|
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason: error.message, taskId, sessionId, fallbackAttempted: false };
|
|
11027
11044
|
const blocker2 = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: error.message, source: "delivery_admission_failed" });
|
|
11028
|
-
|
|
11045
|
+
const launchFailureComment2 = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: error.message, source: "delivery_admission_failed" });
|
|
11046
|
+
return { ok: false, action: "message_delivery_failed", reason: error.message, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker2, launchFailureComment: launchFailureComment2 };
|
|
11029
11047
|
}
|
|
11030
11048
|
if (blockingPromptVerification) return { ok: true, verification: blockingPromptVerification, admissionVerification: null, fallback: false };
|
|
11031
11049
|
if (admissionVerification && acceptPromptAdmission) {
|
|
@@ -11040,7 +11058,8 @@ async function deliverClickUpSessionEventWithVerification({ openCodeClient, send
|
|
|
11040
11058
|
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason, fallbackAttempted: false, httpFallbackDisabled: Boolean(opencodeBaseUrl) });
|
|
11041
11059
|
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: false };
|
|
11042
11060
|
const blocker = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason, source: "delivery_verification_failed" });
|
|
11043
|
-
|
|
11061
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason, source: "delivery_verification_failed" });
|
|
11062
|
+
return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker, launchFailureComment };
|
|
11044
11063
|
}
|
|
11045
11064
|
async function recoverClickUpPmSession({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, staleSessionId, sessionTitle, taskRoute, metadataWithRouting, config, prompt, eventMarkers = [], deliveryEvidencePath, evidencePath, eventKey, createSession, verifySessionEventDelivery } = {}) {
|
|
11046
11065
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_started", taskId, staleSessionId, worktree: taskRoute?.worktree });
|
|
@@ -11050,12 +11069,14 @@ async function recoverClickUpPmSession({ openCodeClient, sendSessionEvent, click
|
|
|
11050
11069
|
} catch (error) {
|
|
11051
11070
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_create_failed", taskId, staleSessionId, message: error.message });
|
|
11052
11071
|
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "replacement_session_create_failed", source: "pm_session_recovery" });
|
|
11053
|
-
|
|
11072
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "replacement_session_create_failed", source: "pm_session_recovery" });
|
|
11073
|
+
return { ok: false, action: "message_delivery_failed", reason: "replacement_session_create_failed", taskId, sessionId: staleSessionId, replacementAttempted: true, blockerTag, launchFailureComment, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath };
|
|
11054
11074
|
}
|
|
11055
11075
|
if (!String(replacementSessionId || "").startsWith("ses_")) {
|
|
11056
11076
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_create_invalid", taskId, staleSessionId, replacementSessionId });
|
|
11057
11077
|
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "replacement_session_create_failed", source: "pm_session_recovery" });
|
|
11058
|
-
|
|
11078
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "replacement_session_create_failed", source: "pm_session_recovery" });
|
|
11079
|
+
return { ok: false, action: "message_delivery_failed", reason: "replacement_session_create_failed", taskId, sessionId: staleSessionId, replacementAttempted: true, blockerTag, launchFailureComment, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath };
|
|
11059
11080
|
}
|
|
11060
11081
|
const replacementDelivery = await deliverClickUpSessionEventWithVerification({
|
|
11061
11082
|
openCodeClient,
|
|
@@ -11077,7 +11098,8 @@ async function recoverClickUpPmSession({ openCodeClient, sendSessionEvent, click
|
|
|
11077
11098
|
if (!replacementDelivery.ok) {
|
|
11078
11099
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_delivery_failed", taskId, staleSessionId, replacementSessionId, reason: replacementDelivery.reason });
|
|
11079
11100
|
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: replacementDelivery.reason || "replacement_delivery_failed", source: "pm_session_recovery" });
|
|
11080
|
-
|
|
11101
|
+
const launchFailureComment = replacementDelivery.launchFailureComment || await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: replacementDelivery.reason || "replacement_delivery_failed", source: "pm_session_recovery" });
|
|
11102
|
+
return { ...replacementDelivery, sessionId: staleSessionId, replacementSessionId, replacementAttempted: true, blockerTag, launchFailureComment, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath };
|
|
11081
11103
|
}
|
|
11082
11104
|
const replacementMetadata = clearClickUpPendingSessionMetadata(setClickUpSessionMetadata(metadataWithRouting, config.routing.metadataKey, replacementSessionId), config.routing.metadataKey);
|
|
11083
11105
|
await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: replacementMetadata });
|
|
@@ -11361,8 +11383,26 @@ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, w
|
|
|
11361
11383
|
if (!existingSessionId) {
|
|
11362
11384
|
let pendingSessionId = getNestedMetadataValue(metadata, clickUpPendingSessionKey(config.routing.metadataKey)) || state.pendingSessions?.[taskId];
|
|
11363
11385
|
if (!pendingSessionId) {
|
|
11364
|
-
|
|
11365
|
-
|
|
11386
|
+
try {
|
|
11387
|
+
pendingSessionId = await createSession(openCodeClient, { title: sessionTitle, directory: taskRoute.worktree, agent: config.routing.targetAgent });
|
|
11388
|
+
} catch (error) {
|
|
11389
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_create_failed", taskId, worktree: taskRoute.worktree, message: error.message });
|
|
11390
|
+
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "session_create_failed", source: "route_create_session" });
|
|
11391
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "session_create_failed", source: "route_create_session" });
|
|
11392
|
+
return finish({ ok: false, action: "error", reason: "session_create_failed", taskId, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, blockerTag, launchFailureComment });
|
|
11393
|
+
}
|
|
11394
|
+
if (!String(pendingSessionId || "").startsWith("ses_")) {
|
|
11395
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_create_invalid", taskId, worktree: taskRoute.worktree, sessionId: pendingSessionId || null });
|
|
11396
|
+
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "session_create_failed", source: "route_create_session" });
|
|
11397
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "session_create_failed", source: "route_create_session" });
|
|
11398
|
+
return finish({ ok: false, action: "error", reason: "session_create_failed", taskId, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, blockerTag, launchFailureComment });
|
|
11399
|
+
}
|
|
11400
|
+
if (!await sessionExists(openCodeClient, pendingSessionId, { directory: taskRoute.worktree })) {
|
|
11401
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_create_directory_unverified", taskId, worktree: taskRoute.worktree, sessionId: pendingSessionId });
|
|
11402
|
+
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "session_directory_unverified", source: "route_create_session" });
|
|
11403
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "session_directory_unverified", source: "route_create_session" });
|
|
11404
|
+
return finish({ ok: false, action: "error", reason: "session_directory_unverified", taskId, sessionId: pendingSessionId, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, blockerTag, launchFailureComment });
|
|
11405
|
+
}
|
|
11366
11406
|
if (saveState) {
|
|
11367
11407
|
saveState({
|
|
11368
11408
|
...state,
|
|
@@ -11378,7 +11418,20 @@ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, w
|
|
|
11378
11418
|
throw error;
|
|
11379
11419
|
}
|
|
11380
11420
|
const delivery = await deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId: pendingSessionId, agent: config.routing.targetAgent, text: prompt, directory: taskRoute.worktree, opencodeBaseUrl: config.opencode?.baseUrl, directPrompt: config.opencode?.promptDelivery === "http", acceptPromptAdmission: config.opencode?.acceptPromptAdmission === true, eventMarkers: [taskId, eventType], verifySessionEventDelivery });
|
|
11381
|
-
if (!delivery.ok)
|
|
11421
|
+
if (!delivery.ok) {
|
|
11422
|
+
const failedMetadata = clearClickUpPendingSessionMetadata(metadataWithRouting, config.routing.metadataKey);
|
|
11423
|
+
let pendingCleared = false;
|
|
11424
|
+
try {
|
|
11425
|
+
await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: failedMetadata });
|
|
11426
|
+
pendingCleared = true;
|
|
11427
|
+
} catch (error) {
|
|
11428
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pending_session_clear_failed", taskId, sessionId: pendingSessionId, message: error.message });
|
|
11429
|
+
}
|
|
11430
|
+
const { [taskId]: _failedPending, ...remainingPending2 } = stateToPersist.pendingSessions || {};
|
|
11431
|
+
stateToPersist = { ...stateToPersist, pendingSessions: remainingPending2 };
|
|
11432
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pending_session_delivery_failed", taskId, sessionId: pendingSessionId, reason: delivery.reason || "message_delivery_failed", pendingCleared });
|
|
11433
|
+
return finish({ ...delivery, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, pendingCleared });
|
|
11434
|
+
}
|
|
11382
11435
|
const nextMetadata = clearClickUpPendingSessionMetadata(setClickUpSessionMetadata(pendingMetadata, config.routing.metadataKey, pendingSessionId), config.routing.metadataKey);
|
|
11383
11436
|
await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: nextMetadata });
|
|
11384
11437
|
const { [taskId]: _completedPending, ...remainingPending } = stateToPersist.pendingSessions || {};
|
|
@@ -11386,7 +11439,7 @@ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, w
|
|
|
11386
11439
|
return finish({ ok: true, action: "created_session", taskId, sessionId: pendingSessionId, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, deliveryVerification: delivery.verification, deliveryAdmission: delivery.admissionVerification, deliveryFallback: delivery.fallback, deliveryAttempts: delivery.fallback ? 2 : 1 });
|
|
11387
11440
|
}
|
|
11388
11441
|
const sessionId = String(existingSessionId);
|
|
11389
|
-
if (await sessionExists(openCodeClient, sessionId)) {
|
|
11442
|
+
if (await sessionExists(openCodeClient, sessionId, { directory: taskRoute.worktree })) {
|
|
11390
11443
|
if (typeof clickupClient?.updateTaskMetadata === "function") await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: metadataWithRouting });
|
|
11391
11444
|
const delivery = await deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent: config.routing.targetAgent, text: prompt, directory: taskRoute.worktree, opencodeBaseUrl: config.opencode?.baseUrl, directPrompt: config.opencode?.promptDelivery === "http", acceptPromptAdmission: config.opencode?.acceptPromptAdmission === true, eventMarkers: [taskId, eventType], verifySessionEventDelivery, applyBlockerOnFailure: false });
|
|
11392
11445
|
if (!delivery.ok) {
|
|
@@ -11514,6 +11567,7 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
|
|
|
11514
11567
|
routed.undelivered += 1;
|
|
11515
11568
|
appendClickUpWebhookLocalLog(worktree, { type: "startup_reconciliation_task_undelivered", taskId, action: result?.action || "error", sessionId: routeSummary.sessionId, reason: result.reason || "startup_reconciliation_route_failed" });
|
|
11516
11569
|
if (!result.blockerTag) await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: result.reason || "startup_reconciliation_route_failed", source: "startup_reconciliation_task" });
|
|
11570
|
+
if (!result.launchFailureComment) await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: result.reason || "startup_reconciliation_route_failed", source: "startup_reconciliation_task" });
|
|
11517
11571
|
} else {
|
|
11518
11572
|
routed.undelivered += 1;
|
|
11519
11573
|
appendClickUpWebhookLocalLog(worktree, { type: "startup_reconciliation_task_undelivered", taskId, action: routeSummary.action, sessionId: routeSummary.sessionId, reason: "route_not_actionable" });
|
|
@@ -11621,14 +11675,13 @@ function clickUpListenerKey(config) {
|
|
|
11621
11675
|
}
|
|
11622
11676
|
function clickUpListenerFingerprint({ config, state, worktree, clickupClient, openCodeClient } = {}) {
|
|
11623
11677
|
return JSON.stringify({
|
|
11678
|
+
teamId: config?.teamId || "",
|
|
11624
11679
|
publicUrl: config?.webhook?.publicUrl || "",
|
|
11625
11680
|
path: clickUpWebhookExpectedPath(config),
|
|
11626
|
-
|
|
11681
|
+
location: config?.webhook?.location || {},
|
|
11627
11682
|
webhookId: state?.webhookId || "",
|
|
11628
11683
|
secret: state?.secret || "",
|
|
11629
|
-
events: config?.webhook?.events || []
|
|
11630
|
-
clickupClient: objectIdentity(clickupClient),
|
|
11631
|
-
openCodeClient: objectIdentity(openCodeClient)
|
|
11684
|
+
events: config?.webhook?.events || []
|
|
11632
11685
|
});
|
|
11633
11686
|
}
|
|
11634
11687
|
function startClickUpWebhookListener({ config, state, worktree, clickupClient, openCodeClient, listenerRegistry = activeClickUpWebhookListeners } = {}) {
|
package/dist/sanitize_cli.js
CHANGED
|
@@ -8628,13 +8628,6 @@ var activeClickUpWebhookLifecycleRegistry = /* @__PURE__ */ new Map();
|
|
|
8628
8628
|
var CLICKUP_WEBHOOK_CLEANUP_TIMEOUT_MS = 8e3;
|
|
8629
8629
|
var CLICKUP_WEBHOOK_SIGNAL_STATE = Symbol.for("opencode-optima.clickup-webhook.signal-state");
|
|
8630
8630
|
var activeClickUpTaskRoutes = /* @__PURE__ */ new Map();
|
|
8631
|
-
var objectIdentityMap = /* @__PURE__ */ new WeakMap();
|
|
8632
|
-
var objectIdentitySequence = 0;
|
|
8633
|
-
function objectIdentity(value) {
|
|
8634
|
-
if (!value || typeof value !== "object" && typeof value !== "function") return String(value ?? "");
|
|
8635
|
-
if (!objectIdentityMap.has(value)) objectIdentityMap.set(value, `obj_${++objectIdentitySequence}`);
|
|
8636
|
-
return objectIdentityMap.get(value);
|
|
8637
|
-
}
|
|
8638
8631
|
function isRootDirectory(candidate) {
|
|
8639
8632
|
const resolved = path5.resolve(candidate);
|
|
8640
8633
|
return resolved === path5.parse(resolved).root;
|
|
@@ -8760,7 +8753,6 @@ function hasActionableClickUpRoute(result = {}) {
|
|
|
8760
8753
|
if (!result.sessionId) return false;
|
|
8761
8754
|
if (result.action === "message_delivery_failed" || result.action === "error") return false;
|
|
8762
8755
|
if (result.deliveryVerification?.ok === false) return false;
|
|
8763
|
-
if (result.deliveryVerification?.method === "prompt_admission") return false;
|
|
8764
8756
|
return true;
|
|
8765
8757
|
}
|
|
8766
8758
|
function determineClickUpMergeAuthority({ isSubtask = false, clickupStatus = "", validationPassed = false, mergeFailed = false, finalApprovalRoles = CLICKUP_FINAL_APPROVER_ROLES, humansRegistry } = {}) {
|
|
@@ -10569,12 +10561,16 @@ function clearClickUpPendingSessionMetadata(metadata, metadataKey) {
|
|
|
10569
10561
|
delete cursor[parts[parts.length - 1]];
|
|
10570
10562
|
return JSON.stringify(sortJsonValue(root), null, 2);
|
|
10571
10563
|
}
|
|
10572
|
-
|
|
10564
|
+
function withOptionalDirectoryQuery(payload, directory) {
|
|
10565
|
+
if (!directory) return payload;
|
|
10566
|
+
return { ...payload, query: { ...payload.query || {}, directory } };
|
|
10567
|
+
}
|
|
10568
|
+
async function openCodeSessionExists(client, sessionId, { directory = "" } = {}) {
|
|
10573
10569
|
const getAttempts = [
|
|
10574
|
-
{ path: { id: sessionId } },
|
|
10575
|
-
{ path: { sessionID: sessionId } },
|
|
10576
|
-
{ sessionID: sessionId },
|
|
10577
|
-
{ id: sessionId }
|
|
10570
|
+
withOptionalDirectoryQuery({ path: { id: sessionId } }, directory),
|
|
10571
|
+
withOptionalDirectoryQuery({ path: { sessionID: sessionId } }, directory),
|
|
10572
|
+
directory ? { sessionID: sessionId, directory } : { sessionID: sessionId },
|
|
10573
|
+
directory ? { id: sessionId, directory } : { id: sessionId }
|
|
10578
10574
|
];
|
|
10579
10575
|
if (typeof client?.session?.get === "function") {
|
|
10580
10576
|
for (const attempt of getAttempts) {
|
|
@@ -10586,10 +10582,10 @@ async function openCodeSessionExists(client, sessionId) {
|
|
|
10586
10582
|
}
|
|
10587
10583
|
}
|
|
10588
10584
|
const messageAttempts = [
|
|
10589
|
-
{ path: { id: sessionId }, query: { limit: 1 } },
|
|
10590
|
-
{ path: { sessionID: sessionId }, query: { limit: 1 } },
|
|
10591
|
-
{ sessionID: sessionId, limit: 1 },
|
|
10592
|
-
{ id: sessionId, limit: 1 }
|
|
10585
|
+
{ path: { id: sessionId }, query: { limit: 1, ...directory ? { directory } : {} } },
|
|
10586
|
+
{ path: { sessionID: sessionId }, query: { limit: 1, ...directory ? { directory } : {} } },
|
|
10587
|
+
directory ? { sessionID: sessionId, directory, limit: 1 } : { sessionID: sessionId, limit: 1 },
|
|
10588
|
+
directory ? { id: sessionId, directory, limit: 1 } : { id: sessionId, limit: 1 }
|
|
10593
10589
|
];
|
|
10594
10590
|
if (typeof client?.session?.messages === "function") {
|
|
10595
10591
|
for (const attempt of messageAttempts) {
|
|
@@ -10993,6 +10989,17 @@ async function verifyOpenCodeSessionEventDelivery(client, { sessionId, directory
|
|
|
10993
10989
|
}
|
|
10994
10990
|
return { ok: false, reason: lastError };
|
|
10995
10991
|
}
|
|
10992
|
+
async function postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason, source } = {}) {
|
|
10993
|
+
if (typeof clickupClient?.postTaskComment !== "function") return { ok: false, skipped: true, reason: "post_comment_unavailable" };
|
|
10994
|
+
try {
|
|
10995
|
+
await clickupClient.postTaskComment({ taskId, comment: `Optima launch failure: ${reason || "launch_failed"}. Worktree visibility alone is not successful routing; Optima requires an OpenCode session plus verified prompt admission/delivery.` });
|
|
10996
|
+
appendClickUpWebhookLocalLog(worktree, { type: "launch_failure_comment_posted", taskId, reason, source });
|
|
10997
|
+
return { ok: true };
|
|
10998
|
+
} catch (error) {
|
|
10999
|
+
appendClickUpWebhookLocalLog(worktree, { type: "launch_failure_comment_failed", taskId, reason, source, message: error.message });
|
|
11000
|
+
return { ok: false, error: error.message };
|
|
11001
|
+
}
|
|
11002
|
+
}
|
|
10996
11003
|
async function applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason, source, tagName = CLICKUP_BLOCKER_TAG_NAME } = {}) {
|
|
10997
11004
|
if (typeof clickupClient?.addTaskTag !== "function") {
|
|
10998
11005
|
appendClickUpWebhookLocalLog(worktree, { type: "blocker_tag_unavailable", taskId, reason, source, tagName });
|
|
@@ -11022,7 +11029,17 @@ function openCodeBlockingPromptVerification(result, sessionId) {
|
|
|
11022
11029
|
}
|
|
11023
11030
|
async function deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent, text, directory, opencodeBaseUrl, directPrompt = false, acceptPromptAdmission = false, eventMarkers = [], verifySessionEventDelivery = verifyOpenCodeSessionEventDelivery, applyBlockerOnFailure = true } = {}) {
|
|
11024
11031
|
const beforeMessages = await readOpenCodeSessionMessages(openCodeClient, { sessionId, directory, limit: 50 }).catch(() => null);
|
|
11025
|
-
|
|
11032
|
+
let sendResult;
|
|
11033
|
+
try {
|
|
11034
|
+
sendResult = await sendSessionEvent(openCodeClient, { sessionId, agent, text, directory, opencodeBaseUrl, direct: directPrompt, allowDirectFallback: directPrompt });
|
|
11035
|
+
} catch (error) {
|
|
11036
|
+
const reason2 = error.message || "message_delivery_failed";
|
|
11037
|
+
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason: reason2, fallbackAttempted: false });
|
|
11038
|
+
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason: reason2, taskId, sessionId, fallbackAttempted: false };
|
|
11039
|
+
const blocker2 = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: reason2, source: "delivery_send_failed" });
|
|
11040
|
+
const launchFailureComment2 = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: reason2, source: "delivery_send_failed" });
|
|
11041
|
+
return { ok: false, action: "message_delivery_failed", reason: reason2, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker2, launchFailureComment: launchFailureComment2 };
|
|
11042
|
+
}
|
|
11026
11043
|
let blockingPromptVerification = null;
|
|
11027
11044
|
let admissionVerification = null;
|
|
11028
11045
|
try {
|
|
@@ -11032,7 +11049,8 @@ async function deliverClickUpSessionEventWithVerification({ openCodeClient, send
|
|
|
11032
11049
|
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason: error.message, fallbackAttempted: false });
|
|
11033
11050
|
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason: error.message, taskId, sessionId, fallbackAttempted: false };
|
|
11034
11051
|
const blocker2 = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: error.message, source: "delivery_admission_failed" });
|
|
11035
|
-
|
|
11052
|
+
const launchFailureComment2 = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: error.message, source: "delivery_admission_failed" });
|
|
11053
|
+
return { ok: false, action: "message_delivery_failed", reason: error.message, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker2, launchFailureComment: launchFailureComment2 };
|
|
11036
11054
|
}
|
|
11037
11055
|
if (blockingPromptVerification) return { ok: true, verification: blockingPromptVerification, admissionVerification: null, fallback: false };
|
|
11038
11056
|
if (admissionVerification && acceptPromptAdmission) {
|
|
@@ -11047,7 +11065,8 @@ async function deliverClickUpSessionEventWithVerification({ openCodeClient, send
|
|
|
11047
11065
|
appendClickUpWebhookLocalLog(worktree, { type: "message_delivery_failed", taskId, sessionId, reason, fallbackAttempted: false, httpFallbackDisabled: Boolean(opencodeBaseUrl) });
|
|
11048
11066
|
if (!applyBlockerOnFailure) return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: false };
|
|
11049
11067
|
const blocker = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason, source: "delivery_verification_failed" });
|
|
11050
|
-
|
|
11068
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason, source: "delivery_verification_failed" });
|
|
11069
|
+
return { ok: false, action: "message_delivery_failed", reason, taskId, sessionId, fallbackAttempted: false, blockerTag: blocker, launchFailureComment };
|
|
11051
11070
|
}
|
|
11052
11071
|
async function recoverClickUpPmSession({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, staleSessionId, sessionTitle, taskRoute, metadataWithRouting, config, prompt, eventMarkers = [], deliveryEvidencePath, evidencePath, eventKey, createSession, verifySessionEventDelivery } = {}) {
|
|
11053
11072
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_started", taskId, staleSessionId, worktree: taskRoute?.worktree });
|
|
@@ -11057,12 +11076,14 @@ async function recoverClickUpPmSession({ openCodeClient, sendSessionEvent, click
|
|
|
11057
11076
|
} catch (error) {
|
|
11058
11077
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_create_failed", taskId, staleSessionId, message: error.message });
|
|
11059
11078
|
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "replacement_session_create_failed", source: "pm_session_recovery" });
|
|
11060
|
-
|
|
11079
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "replacement_session_create_failed", source: "pm_session_recovery" });
|
|
11080
|
+
return { ok: false, action: "message_delivery_failed", reason: "replacement_session_create_failed", taskId, sessionId: staleSessionId, replacementAttempted: true, blockerTag, launchFailureComment, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath };
|
|
11061
11081
|
}
|
|
11062
11082
|
if (!String(replacementSessionId || "").startsWith("ses_")) {
|
|
11063
11083
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_create_invalid", taskId, staleSessionId, replacementSessionId });
|
|
11064
11084
|
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "replacement_session_create_failed", source: "pm_session_recovery" });
|
|
11065
|
-
|
|
11085
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "replacement_session_create_failed", source: "pm_session_recovery" });
|
|
11086
|
+
return { ok: false, action: "message_delivery_failed", reason: "replacement_session_create_failed", taskId, sessionId: staleSessionId, replacementAttempted: true, blockerTag, launchFailureComment, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath };
|
|
11066
11087
|
}
|
|
11067
11088
|
const replacementDelivery = await deliverClickUpSessionEventWithVerification({
|
|
11068
11089
|
openCodeClient,
|
|
@@ -11084,7 +11105,8 @@ async function recoverClickUpPmSession({ openCodeClient, sendSessionEvent, click
|
|
|
11084
11105
|
if (!replacementDelivery.ok) {
|
|
11085
11106
|
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_recovery_delivery_failed", taskId, staleSessionId, replacementSessionId, reason: replacementDelivery.reason });
|
|
11086
11107
|
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: replacementDelivery.reason || "replacement_delivery_failed", source: "pm_session_recovery" });
|
|
11087
|
-
|
|
11108
|
+
const launchFailureComment = replacementDelivery.launchFailureComment || await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: replacementDelivery.reason || "replacement_delivery_failed", source: "pm_session_recovery" });
|
|
11109
|
+
return { ...replacementDelivery, sessionId: staleSessionId, replacementSessionId, replacementAttempted: true, blockerTag, launchFailureComment, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath };
|
|
11088
11110
|
}
|
|
11089
11111
|
const replacementMetadata = clearClickUpPendingSessionMetadata(setClickUpSessionMetadata(metadataWithRouting, config.routing.metadataKey, replacementSessionId), config.routing.metadataKey);
|
|
11090
11112
|
await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: replacementMetadata });
|
|
@@ -11368,8 +11390,26 @@ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, w
|
|
|
11368
11390
|
if (!existingSessionId) {
|
|
11369
11391
|
let pendingSessionId = getNestedMetadataValue(metadata, clickUpPendingSessionKey(config.routing.metadataKey)) || state.pendingSessions?.[taskId];
|
|
11370
11392
|
if (!pendingSessionId) {
|
|
11371
|
-
|
|
11372
|
-
|
|
11393
|
+
try {
|
|
11394
|
+
pendingSessionId = await createSession(openCodeClient, { title: sessionTitle, directory: taskRoute.worktree, agent: config.routing.targetAgent });
|
|
11395
|
+
} catch (error) {
|
|
11396
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_create_failed", taskId, worktree: taskRoute.worktree, message: error.message });
|
|
11397
|
+
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "session_create_failed", source: "route_create_session" });
|
|
11398
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "session_create_failed", source: "route_create_session" });
|
|
11399
|
+
return finish({ ok: false, action: "error", reason: "session_create_failed", taskId, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, blockerTag, launchFailureComment });
|
|
11400
|
+
}
|
|
11401
|
+
if (!String(pendingSessionId || "").startsWith("ses_")) {
|
|
11402
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_create_invalid", taskId, worktree: taskRoute.worktree, sessionId: pendingSessionId || null });
|
|
11403
|
+
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "session_create_failed", source: "route_create_session" });
|
|
11404
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "session_create_failed", source: "route_create_session" });
|
|
11405
|
+
return finish({ ok: false, action: "error", reason: "session_create_failed", taskId, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, blockerTag, launchFailureComment });
|
|
11406
|
+
}
|
|
11407
|
+
if (!await sessionExists(openCodeClient, pendingSessionId, { directory: taskRoute.worktree })) {
|
|
11408
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pm_session_create_directory_unverified", taskId, worktree: taskRoute.worktree, sessionId: pendingSessionId });
|
|
11409
|
+
const blockerTag = await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: "session_directory_unverified", source: "route_create_session" });
|
|
11410
|
+
const launchFailureComment = await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: "session_directory_unverified", source: "route_create_session" });
|
|
11411
|
+
return finish({ ok: false, action: "error", reason: "session_directory_unverified", taskId, sessionId: pendingSessionId, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, blockerTag, launchFailureComment });
|
|
11412
|
+
}
|
|
11373
11413
|
if (saveState) {
|
|
11374
11414
|
saveState({
|
|
11375
11415
|
...state,
|
|
@@ -11385,7 +11425,20 @@ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, w
|
|
|
11385
11425
|
throw error;
|
|
11386
11426
|
}
|
|
11387
11427
|
const delivery = await deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId: pendingSessionId, agent: config.routing.targetAgent, text: prompt, directory: taskRoute.worktree, opencodeBaseUrl: config.opencode?.baseUrl, directPrompt: config.opencode?.promptDelivery === "http", acceptPromptAdmission: config.opencode?.acceptPromptAdmission === true, eventMarkers: [taskId, eventType], verifySessionEventDelivery });
|
|
11388
|
-
if (!delivery.ok)
|
|
11428
|
+
if (!delivery.ok) {
|
|
11429
|
+
const failedMetadata = clearClickUpPendingSessionMetadata(metadataWithRouting, config.routing.metadataKey);
|
|
11430
|
+
let pendingCleared = false;
|
|
11431
|
+
try {
|
|
11432
|
+
await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: failedMetadata });
|
|
11433
|
+
pendingCleared = true;
|
|
11434
|
+
} catch (error) {
|
|
11435
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pending_session_clear_failed", taskId, sessionId: pendingSessionId, message: error.message });
|
|
11436
|
+
}
|
|
11437
|
+
const { [taskId]: _failedPending, ...remainingPending2 } = stateToPersist.pendingSessions || {};
|
|
11438
|
+
stateToPersist = { ...stateToPersist, pendingSessions: remainingPending2 };
|
|
11439
|
+
appendClickUpWebhookLocalLog(worktree, { type: "pending_session_delivery_failed", taskId, sessionId: pendingSessionId, reason: delivery.reason || "message_delivery_failed", pendingCleared });
|
|
11440
|
+
return finish({ ...delivery, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, pendingCleared });
|
|
11441
|
+
}
|
|
11389
11442
|
const nextMetadata = clearClickUpPendingSessionMetadata(setClickUpSessionMetadata(pendingMetadata, config.routing.metadataKey, pendingSessionId), config.routing.metadataKey);
|
|
11390
11443
|
await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: nextMetadata });
|
|
11391
11444
|
const { [taskId]: _completedPending, ...remainingPending } = stateToPersist.pendingSessions || {};
|
|
@@ -11393,7 +11446,7 @@ async function routeClickUpWebhookEventUnlocked({ payload, config, state = {}, w
|
|
|
11393
11446
|
return finish({ ok: true, action: "created_session", taskId, sessionId: pendingSessionId, eventKey, branch: taskRoute.branch, worktree: taskRoute.worktree, deliveryEvidencePath, evidencePath: routingMetadata.evidence_path, deliveryVerification: delivery.verification, deliveryAdmission: delivery.admissionVerification, deliveryFallback: delivery.fallback, deliveryAttempts: delivery.fallback ? 2 : 1 });
|
|
11394
11447
|
}
|
|
11395
11448
|
const sessionId = String(existingSessionId);
|
|
11396
|
-
if (await sessionExists(openCodeClient, sessionId)) {
|
|
11449
|
+
if (await sessionExists(openCodeClient, sessionId, { directory: taskRoute.worktree })) {
|
|
11397
11450
|
if (typeof clickupClient?.updateTaskMetadata === "function") await clickupClient.updateTaskMetadata({ taskId, fieldId: config.routing.metadataFieldId, value: metadataWithRouting });
|
|
11398
11451
|
const delivery = await deliverClickUpSessionEventWithVerification({ openCodeClient, sendSessionEvent, clickupClient, worktree, taskId, sessionId, agent: config.routing.targetAgent, text: prompt, directory: taskRoute.worktree, opencodeBaseUrl: config.opencode?.baseUrl, directPrompt: config.opencode?.promptDelivery === "http", acceptPromptAdmission: config.opencode?.acceptPromptAdmission === true, eventMarkers: [taskId, eventType], verifySessionEventDelivery, applyBlockerOnFailure: false });
|
|
11399
11452
|
if (!delivery.ok) {
|
|
@@ -11521,6 +11574,7 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
|
|
|
11521
11574
|
routed.undelivered += 1;
|
|
11522
11575
|
appendClickUpWebhookLocalLog(worktree, { type: "startup_reconciliation_task_undelivered", taskId, action: result?.action || "error", sessionId: routeSummary.sessionId, reason: result.reason || "startup_reconciliation_route_failed" });
|
|
11523
11576
|
if (!result.blockerTag) await applyClickUpBlockerTag({ clickupClient, worktree, taskId, reason: result.reason || "startup_reconciliation_route_failed", source: "startup_reconciliation_task" });
|
|
11577
|
+
if (!result.launchFailureComment) await postClickUpLaunchFailureComment({ clickupClient, worktree, taskId, reason: result.reason || "startup_reconciliation_route_failed", source: "startup_reconciliation_task" });
|
|
11524
11578
|
} else {
|
|
11525
11579
|
routed.undelivered += 1;
|
|
11526
11580
|
appendClickUpWebhookLocalLog(worktree, { type: "startup_reconciliation_task_undelivered", taskId, action: routeSummary.action, sessionId: routeSummary.sessionId, reason: "route_not_actionable" });
|
|
@@ -11628,14 +11682,13 @@ function clickUpListenerKey(config) {
|
|
|
11628
11682
|
}
|
|
11629
11683
|
function clickUpListenerFingerprint({ config, state, worktree, clickupClient, openCodeClient } = {}) {
|
|
11630
11684
|
return JSON.stringify({
|
|
11685
|
+
teamId: config?.teamId || "",
|
|
11631
11686
|
publicUrl: config?.webhook?.publicUrl || "",
|
|
11632
11687
|
path: clickUpWebhookExpectedPath(config),
|
|
11633
|
-
|
|
11688
|
+
location: config?.webhook?.location || {},
|
|
11634
11689
|
webhookId: state?.webhookId || "",
|
|
11635
11690
|
secret: state?.secret || "",
|
|
11636
|
-
events: config?.webhook?.events || []
|
|
11637
|
-
clickupClient: objectIdentity(clickupClient),
|
|
11638
|
-
openCodeClient: objectIdentity(openCodeClient)
|
|
11691
|
+
events: config?.webhook?.events || []
|
|
11639
11692
|
});
|
|
11640
11693
|
}
|
|
11641
11694
|
function startClickUpWebhookListener({ config, state, worktree, clickupClient, openCodeClient, listenerRegistry = activeClickUpWebhookListeners } = {}) {
|