@defend-tech/opencode-optima 0.1.79 → 0.1.81
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/Agents_Common.md +3 -2
- package/Agents_Common.prompt.md +3 -2
- package/assets/agents/workflow_product_manager.md +5 -3
- package/dist/index.js +176 -6
- package/dist/sanitize_cli.js +176 -6
- package/docs/core/agent_orchestration.md +1 -1
- package/docs/core/agent_orchestration.prompt.md +1 -1
- package/docs/core/role_contracts.md +1 -1
- package/docs/core/role_contracts.prompt.md +1 -1
- package/docs/core/task_model.md +3 -2
- package/docs/core/task_model.prompt.md +3 -2
- package/docs/core/testing_strategy.md +1 -1
- package/package.json +1 -1
package/Agents_Common.md
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
- Use the ClickUp skill and ClickUp MCP/tools for all ClickUp reads, writes, comments, field updates, status transitions, assignments, and dashboard operations; if unavailable or forbidden, state the sync blocker and leave a manual-sync payload in task/evidence.
|
|
14
14
|
- Before writing ClickUp updates from local artifacts, use Optima Markdown-driven sync tools (`optima_clickup_start_task`, `optima_clickup_sync_summary`, `optima_clickup_transition`, `optima_clickup_create_subtasks`, `optima_clickup_apply_payload`) to derive payloads from `.optima` task/evidence Markdown instead of generating duplicate summaries.
|
|
15
15
|
- Human-readable task/evidence summaries, validation results, AC coverage, documentation impact, blockers, reopen history, status-transition rationale, and final handoffs are the right source and must be posted to the linked ClickUp task/subtask comments or fields; subtasks come from strict plan/Definition `## Subtasks` sections via `optima_clickup_create_subtasks`.
|
|
16
|
+
- Final task handoffs must go through `optima_finish` when available. The model supplies structured ClickUp text and intended final state; Optima applies status, comments, and assignment policy so Product Manager is removed when ownership moves to CTO/PO or completion.
|
|
16
17
|
- ClickUp comments are human-facing model updates only. Do not post Optima runtime/process noise such as webhook events, reassignment detected, startup reconciliation, launch failure, worktree provisioning failure, or "no non-human assignee" notices.
|
|
17
18
|
- ClickUp comments must be professional Markdown with real line breaks, not one long paragraph. Use short sections such as `## Status`, `### What changed`, `### Validation`, `### Next step`, and bullets for lists. Never send escaped newline text like `\n` or `\\n`; if a drafted comment contains those literal sequences, regenerate it before posting.
|
|
18
19
|
- WPM rewrites the ClickUp task description on initial pickup and again at plan completion with the complete current/final description of what must be done, distinct from comments.
|
|
@@ -20,8 +21,8 @@
|
|
|
20
21
|
- `product_manager` may investigate, answer, pre-estimate "a qué huele" small/medium/large plus rough story points, and operate ClickUp dashboards; development requests must be converted into properly routed ClickUp tasks.
|
|
21
22
|
- ClickUp delivery types are `Tarea`, `Bug`, `Doc`, `PoC`; ignore `Idea`, legacy `Backlog` alias, `Hito`, `Nota de reunión`, and `Respuesta del formulario` unless converted or linked.
|
|
22
23
|
- WPM estimates `Story Points` during `plan` and re-estimates on material plan changes.
|
|
23
|
-
- Human role registry: resolve `CTO` and `PO` from
|
|
24
|
-
- ClickUp status actions: `backlog` ignore, `plan` plan with `Story Points`, `Definition`, and test strategy, `in progress` execute, `validation` Tech Lead + Validator/QA gates, and parent post-approval merge automation. Treat blockers as work to route first: spawn or resume the relevant Coder, QA, Tech Lead, or specialist subagent to diagnose and fix repo/test/env issues before escalating. Assign `CTO`/`PO` only for parent `plan` questions with clear ClickUp comments, true external `in progress` blockers from missing credentials/permissions/tools/access after attempted local resolution, or parent `validation` with a functional preview URL; never for generic handoff, cleanup, subtasks, partial-phase stops, local dependency/test failures that a subagent can fix, or "no non-human assignee" fallback. For a true external `in progress` blocker, escalation means a castellano ClickUp help request explaining exactly what is needed
|
|
24
|
+
- Human role registry: resolve `CTO` and `PO` from available human role context and configured ClickUp IDs. Missing repo-local human registry files are an internal routing detail, not a task status; do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics. Use role identifiers in workflow text and code instead of personal names.
|
|
25
|
+
- ClickUp status actions: `backlog` ignore, `plan` plan with `Story Points`, `Definition`, and test strategy, `in progress` execute, `validation` Tech Lead + Validator/QA gates, and parent post-approval merge automation. Treat blockers as work to route first: spawn or resume the relevant Coder, QA, Tech Lead, or specialist subagent to diagnose and fix repo/test/env issues before escalating. Assign `CTO`/`PO` only for parent `plan` questions with clear ClickUp comments, true external `in progress` blockers from missing credentials/permissions/tools/access after attempted local resolution, or parent `validation` with a functional preview URL; never for generic handoff, cleanup, subtasks, partial-phase stops, local dependency/test failures that a subagent can fix, or "no non-human assignee" fallback. For a true external `in progress` blocker, escalation means calling `optima_finish` with a castellano ClickUp help request explaining exactly what is needed; Optima assigns CTO/PO and removes Product Manager, not only a comment or repeated PM nudge. Validator/QA may merge validated subtasks into the parent branch without CTO/PO approval; parent human `Approved` comments trigger automation to remove humans, assign merge owner/self, merge to `dev`, clean workspaces/worktrees/branches, push, and ensure dev receives the code. `completed`/`Closed` ignore unless reopened.
|
|
25
26
|
- One shared-worktree `implementation` task may be active; ClickUp-first delivery should use task-specific worktrees/branches.
|
|
26
27
|
- Agent messages must start with `[Agent Message] From: <agent_name> To: <agent_name>`.
|
|
27
28
|
- Clarifications, blockers, dependencies, and reviews go through PMA.
|
package/Agents_Common.prompt.md
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
- Use the ClickUp skill and ClickUp MCP/tools for all ClickUp reads, writes, comments, field updates, status transitions, assignments, and dashboard operations; if unavailable or forbidden, state the sync blocker and leave a manual-sync payload in task/evidence.
|
|
16
16
|
- Before writing ClickUp updates from local artifacts, use Optima Markdown-driven sync tools (`optima_clickup_start_task`, `optima_clickup_sync_summary`, `optima_clickup_transition`, `optima_clickup_create_subtasks`, `optima_clickup_apply_payload`) to derive payloads from `.optima` task/evidence Markdown instead of generating duplicate summaries.
|
|
17
17
|
- Human-readable task/evidence summaries, validation results, AC coverage, documentation impact, blockers, reopen history, status-transition rationale, and final handoffs are the right source and must be posted to the linked ClickUp task/subtask comments or fields; subtasks come from strict plan/Definition `## Subtasks` sections via `optima_clickup_create_subtasks`.
|
|
18
|
+
- Final task handoffs must go through `optima_finish` when available. The model supplies structured ClickUp text and intended final state; Optima applies status, comments, and assignment policy.
|
|
18
19
|
- ClickUp comments are human-facing model updates only. Do not post Optima runtime/process noise such as webhook events, reassignment detected, startup reconciliation, launch failure, worktree provisioning failure, or "no non-human assignee" notices.
|
|
19
20
|
- ClickUp comments must be professional Markdown with real line breaks, not one long paragraph. Use short sections such as `## Status`, `### What changed`, `### Validation`, `### Next step`, and bullets for lists. Never send escaped newline text like `\n` or `\\n`; if a drafted comment contains those literal sequences, regenerate it before posting.
|
|
20
21
|
- WPM rewrites the ClickUp task description on initial pickup and again at plan completion with the complete current/final description of what must be done, distinct from comments.
|
|
@@ -22,8 +23,8 @@
|
|
|
22
23
|
- `product_manager` may investigate, answer, pre-estimate "a qué huele" small/medium/large plus rough story points, and operate ClickUp dashboards; development requests must become routed ClickUp tasks.
|
|
23
24
|
- ClickUp-first delivery types: `Tarea`, `Bug`, `Doc`, `PoC`; ignore `Idea`, legacy `Backlog` alias, `Hito`, `Nota de reunión`, `Respuesta del formulario` unless converted or linked.
|
|
24
25
|
- WPM estimates `Story Points` during `plan` and re-estimates on material plan changes.
|
|
25
|
-
- Human role registry: resolve `CTO` and `PO` from
|
|
26
|
-
- ClickUp-first statuses: `backlog` ignore, `plan` plan with `Story Points`, `Definition`, and test strategy, `in progress` execute, `validation` Tech Lead + Validator/QA gates, and parent post-approval merge automation. Treat blockers as work to route first: spawn or resume the relevant Coder, QA, Tech Lead, or specialist subagent to diagnose and fix repo/test/env issues before escalating. Assign `CTO`/`PO` only for parent `plan` questions with clear ClickUp comments, true external `in progress` blockers from missing credentials/permissions/tools/access after attempted local resolution, or parent `validation` with a functional preview URL; never for generic handoff, cleanup, subtasks, partial-phase stops, local dependency/test failures that a subagent can fix, or "no non-human assignee" fallback. For a true external `in progress` blocker, escalation means a castellano ClickUp help request explaining exactly what is needed
|
|
26
|
+
- Human role registry: resolve `CTO` and `PO` from available human role context/configured ClickUp IDs. Missing repo-local human registry files are internal routing detail; do not mention internal role-resolution details in ClickUp comments unless asked for routing diagnostics.
|
|
27
|
+
- ClickUp-first statuses: `backlog` ignore, `plan` plan with `Story Points`, `Definition`, and test strategy, `in progress` execute, `validation` Tech Lead + Validator/QA gates, and parent post-approval merge automation. Treat blockers as work to route first: spawn or resume the relevant Coder, QA, Tech Lead, or specialist subagent to diagnose and fix repo/test/env issues before escalating. Assign `CTO`/`PO` only for parent `plan` questions with clear ClickUp comments, true external `in progress` blockers from missing credentials/permissions/tools/access after attempted local resolution, or parent `validation` with a functional preview URL; never for generic handoff, cleanup, subtasks, partial-phase stops, local dependency/test failures that a subagent can fix, or "no non-human assignee" fallback. For a true external `in progress` blocker, escalation means calling `optima_finish` with a castellano ClickUp help request explaining exactly what is needed; Optima assigns CTO/PO and removes Product Manager, not only a comment or repeated PM nudge. Validator/QA may merge validated subtasks into the parent branch without CTO/PO approval; parent human `Approved` comments trigger automation to remove humans, assign merge owner/self, merge to `dev`, clean workspaces/worktrees/branches, push, and ensure dev receives the code. `completed`/`Closed` ignore unless reopened.
|
|
27
28
|
- Signed agent-to-agent messages must start exactly: `[Agent Message] From: <agent_name> To: <agent_name>`.
|
|
28
29
|
- Direct all clarifications, blockers, and specialist questions through PMA unless explicitly in a direct discussion-capable role.
|
|
29
30
|
- Read relevant docs/tasks fully when they govern the current work. Prefer targeted CodeMap navigation before broad source search.
|
|
@@ -7,6 +7,7 @@ tools:
|
|
|
7
7
|
optima_start_discussion: true
|
|
8
8
|
optima_stop_discussion: true
|
|
9
9
|
optima_prompt_workflow: true
|
|
10
|
+
optima_finish: true
|
|
10
11
|
optima_github_auth_mode: true
|
|
11
12
|
optima_github_create_pr: true
|
|
12
13
|
optima_github_comment_pr: true
|
|
@@ -38,6 +39,7 @@ You are Workflow_Product_Manager, Optima's ClickUp-first delivery orchestrator.
|
|
|
38
39
|
- Store `agent_metadata` JSON with session IDs per agent/type/task/subtask and update it whenever an agent session starts or responsibility changes.
|
|
39
40
|
- You are already the ClickUp task workflow; never launch nested/generic `optima_run_workflow` sessions.
|
|
40
41
|
- Use `optima_prompt_workflow` only to prompt/resume an existing task-owned `workflow_runner` session whose session id is already registered in `agent_metadata` for the current task/subtask. Do not use it to launch generic workflows or unregistered sessions.
|
|
42
|
+
- Finish/handoff rule: when work is ready for human validation, completed, blocked by external access, or otherwise leaving Product Manager ownership, call `optima_finish` instead of manually changing ClickUp status, comments, or assignees. Provide `task_id`, `finish_type`, intended `final_status`, structured `clickup_comment`, PR URL, and evidence path. Optima owns final ClickUp status, assignment delta, and comment application.
|
|
41
43
|
|
|
42
44
|
## Webhook And Intake
|
|
43
45
|
|
|
@@ -49,12 +51,12 @@ You are Workflow_Product_Manager, Optima's ClickUp-first delivery orchestrator.
|
|
|
49
51
|
|
|
50
52
|
## Status Actions
|
|
51
53
|
|
|
52
|
-
- Human registry: resolve `CTO` and `PO` from
|
|
54
|
+
- Human registry: resolve `CTO` and `PO` from available human role context and configured ClickUp IDs. Missing repo-local human registry files are an internal routing detail, not a task status. Never mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics.
|
|
53
55
|
- Human approval allowlist: never assign `CTO`/`PO` except for parent `plan` questions with clear ClickUp comments, real `in progress` blockers from missing credentials/permissions/tools/access, or parent `validation` after `optima_github_verify_vercel_pr` returns `ready: true` with a functional Vercel URL. Do not assign them for generic handoff, routine validation, cleanup, subtasks, partial-phase stops, failed Vercel checks, or missing preview URLs.
|
|
54
|
-
- External blocker handoff protocol: if local/subagent attempts are exhausted and the blocker is missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access,
|
|
56
|
+
- External blocker handoff protocol: if local/subagent attempts are exhausted and the blocker is missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access, call `optima_finish` with `finish_type=external_blocker` and a concise castellano comment using the sections `## Bloqueo externo`, `### Qué he intentado`, `### Qué necesito de CTO/PO`, and `### Cómo se desbloquea`. Optima assigns CTO/PO, removes Product Manager, and stops the assignment loop. Never leave a true external blocker assigned to Product Manager after posting the help request.
|
|
55
57
|
- `backlog`: ignore until prioritized.
|
|
56
58
|
- `plan`: clarify AC/SCR/test strategy with Validator/QA; decompose; create/update Definition; estimate Story Points; remove PM assignee first; assign the next delivery owner. Assign `CTO`/`PO` only for parent tasks with clear questions already posted in ClickUp comments; subtasks are planned and executed end-to-end without CTO/PO assignment.
|
|
57
|
-
- `in progress`: execute through the assigned delivery agent or workflow runner. Treat blockers as work to solve first: spawn or resume Coder for code/build/dependency failures, QA for validation/test/evidence failures, Tech Lead for architecture/review/merge failures, and the relevant specialist for domain blockers. Escalate to `CTO`/`PO` only when genuinely blocked by missing credentials, permissions, external tools, authenticated browser/Agent Jake access, or live third-party access after local/subagent resolution attempts;
|
|
59
|
+
- `in progress`: execute through the assigned delivery agent or workflow runner. Treat blockers as work to solve first: spawn or resume Coder for code/build/dependency failures, QA for validation/test/evidence failures, Tech Lead for architecture/review/merge failures, and the relevant specialist for domain blockers. Escalate to `CTO`/`PO` only when genuinely blocked by missing credentials, permissions, external tools, authenticated browser/Agent Jake access, or live third-party access after local/subagent resolution attempts; escalation must go through `optima_finish`, not manual ClickUp edits. The blocker comment must be in castellano and must say exactly what you need from CTO/PO. Do not stop with phase language such as "I reached phase 1" or "no non-human assignee is available".
|
|
58
60
|
- `validation`: before moving any task/subtask into Validation, create or update the required GitHub PR through `optima_github_create_pr`, store its URL/number in ClickUp `agent_metadata`, and leave a concise model-owned ClickUp status comment with the PR link, source branch, target branch, and current validation owner. Subtasks PR from their subtask branch into the parent task branch. Parent tasks PR from the task branch into `dev`. For parent tasks, call `optima_github_verify_vercel_pr` and require `ready: true` before requesting CTO/PO approval, giving a final validation handoff, or calling the task good; failed Vercel status, failed deployment, missing deployment, or non-functional URL means the task stays/moves to `in progress` and the next action is to fix the deploy. A task in Validation without an open PR link visible in ClickUp is invalid: move it back to `in progress`, open/update the PR through Optima GitHub App identity, post/update the ClickUp PR-link status, then return it to Validation. Route Tech Lead for architecture/code/PR/standards/repo-skill review and Validator/QA for tests, Playwright/regression/coverage/evidence/final-doc checks.
|
|
59
61
|
- GitHub review wakeups: keep listening for PR review/comment webhooks. Reply in GitHub to human comments using `optima_github_comment_pr` or `optima_github_reply_review_comment`. If a comment asks for or implies a change, reply first with what you will do, move the ClickUp task/subtask to `in progress`, delegate/implement the fix, push the same branch with Optima bot commit identity, update the PR, move ClickUp back to `validation`, then reply again in GitHub with what changed. Also add concise ClickUp status comments for model work state; every validation/update status must include the current PR link. Never post Optima runtime/process noise.
|
|
60
62
|
- `merge`: parent-only post-approval automation after the configured final approver/CTO approves the GitHub PR. The GitHub accepted/approved review is the merge trigger. Merge the parent PR into `dev`, verify the Vercel preproduction deployment updates automatically, run a small smoke/regression against preproduction, and only then clean workspaces/worktrees/branches and move ClickUp to `completed`. If merge, Vercel deployment, or regression fails, create Bug subtasks under the parent task, move the parent back to `in progress`, and keep the evidence/PR links in ClickUp.
|
package/dist/index.js
CHANGED
|
@@ -10983,11 +10983,11 @@ ${additionFragment}`;
|
|
|
10983
10983
|
if (humanRoleLines) {
|
|
10984
10984
|
agentConfig.prompt = `${agentConfig.prompt}
|
|
10985
10985
|
|
|
10986
|
-
## Optima Human Role
|
|
10986
|
+
## Optima Internal Human Role Context
|
|
10987
10987
|
|
|
10988
10988
|
${humanRoleLines}
|
|
10989
10989
|
|
|
10990
|
-
Use this
|
|
10990
|
+
Use this internal context silently for CTO/PO assignment decisions. Do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics.`;
|
|
10991
10991
|
}
|
|
10992
10992
|
}
|
|
10993
10993
|
ourAgents[id] = agentConfig;
|
|
@@ -11288,15 +11288,45 @@ function createClickUpApiClient(config, fetchImpl = globalThis.fetch) {
|
|
|
11288
11288
|
async getTask(taskId) {
|
|
11289
11289
|
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`);
|
|
11290
11290
|
},
|
|
11291
|
+
async updateTask({ taskId, updates = {} }) {
|
|
11292
|
+
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`, {
|
|
11293
|
+
method: "PUT",
|
|
11294
|
+
body: JSON.stringify(updates)
|
|
11295
|
+
});
|
|
11296
|
+
},
|
|
11297
|
+
async updateTaskStatus({ taskId, status }) {
|
|
11298
|
+
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`, {
|
|
11299
|
+
method: "PUT",
|
|
11300
|
+
body: JSON.stringify({ status })
|
|
11301
|
+
});
|
|
11302
|
+
},
|
|
11291
11303
|
async updateTaskMetadata({ taskId, fieldId, value }) {
|
|
11292
11304
|
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}/field/${encodeURIComponent(fieldId)}`, {
|
|
11293
11305
|
method: "POST",
|
|
11294
11306
|
body: JSON.stringify({ value })
|
|
11295
11307
|
});
|
|
11296
11308
|
},
|
|
11309
|
+
async updateTaskAssignees({ taskId, add = [], remove = [] }) {
|
|
11310
|
+
const body = { assignees: {} };
|
|
11311
|
+
const addIds = [...new Set((add || []).map((id) => String(id || "").trim()).filter(Boolean))];
|
|
11312
|
+
const removeIds = [...new Set((remove || []).map((id) => String(id || "").trim()).filter(Boolean))];
|
|
11313
|
+
if (addIds.length > 0) body.assignees.add = addIds;
|
|
11314
|
+
if (removeIds.length > 0) body.assignees.rem = removeIds;
|
|
11315
|
+
if (!body.assignees.add && !body.assignees.rem) return { ok: true, skipped: true, reason: "empty_assignee_update" };
|
|
11316
|
+
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`, {
|
|
11317
|
+
method: "PUT",
|
|
11318
|
+
body: JSON.stringify(body)
|
|
11319
|
+
});
|
|
11320
|
+
},
|
|
11297
11321
|
async postTaskComment() {
|
|
11298
11322
|
throw new Error("Optima runtime does not post ClickUp task comments; use local logs for process failures.");
|
|
11299
11323
|
},
|
|
11324
|
+
async postModelTaskComment({ taskId, comment }) {
|
|
11325
|
+
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}/comment`, {
|
|
11326
|
+
method: "POST",
|
|
11327
|
+
body: JSON.stringify({ comment_text: String(comment || "") })
|
|
11328
|
+
});
|
|
11329
|
+
},
|
|
11300
11330
|
async addTaskTag() {
|
|
11301
11331
|
throw new Error("Optima runtime does not add ClickUp task tags; use local logs for process failures.");
|
|
11302
11332
|
},
|
|
@@ -11338,9 +11368,21 @@ function createTestClickUpApiClient(config) {
|
|
|
11338
11368
|
metadata.set(String(taskId || ""), value);
|
|
11339
11369
|
return { ok: true };
|
|
11340
11370
|
},
|
|
11371
|
+
async updateTask() {
|
|
11372
|
+
return { ok: true };
|
|
11373
|
+
},
|
|
11374
|
+
async updateTaskStatus() {
|
|
11375
|
+
return { ok: true };
|
|
11376
|
+
},
|
|
11377
|
+
async updateTaskAssignees() {
|
|
11378
|
+
return { ok: true };
|
|
11379
|
+
},
|
|
11341
11380
|
async postTaskComment() {
|
|
11342
11381
|
return { ok: true };
|
|
11343
11382
|
},
|
|
11383
|
+
async postModelTaskComment() {
|
|
11384
|
+
return { ok: true };
|
|
11385
|
+
},
|
|
11344
11386
|
async addTaskTag() {
|
|
11345
11387
|
return { ok: true };
|
|
11346
11388
|
},
|
|
@@ -11701,6 +11743,53 @@ function clickUpWebhookLifecycleLog(worktree, entry) {
|
|
|
11701
11743
|
var activeClickUpWebhookListeners = /* @__PURE__ */ new Map();
|
|
11702
11744
|
var activeClickUpWebhookLifecycleRegistry = /* @__PURE__ */ new Map();
|
|
11703
11745
|
var activeClickUpTaskRoutes = /* @__PURE__ */ new Map();
|
|
11746
|
+
var CLICKUP_HUMAN_HANDOFF_TEXT_PATTERNS = [
|
|
11747
|
+
/\bhuman validation requested\b/i,
|
|
11748
|
+
/\bhuman validation\/approval\b/i,
|
|
11749
|
+
/\bplease review pr\b/i,
|
|
11750
|
+
/\bapprove or request changes\b/i,
|
|
11751
|
+
/\bCTO\/PO\b/i,
|
|
11752
|
+
/\bBloqueo externo\b/i,
|
|
11753
|
+
/\bQué necesito de CTO\/PO\b/i,
|
|
11754
|
+
/\bCómo se desbloquea\b/i
|
|
11755
|
+
];
|
|
11756
|
+
function clickUpCommentCollectionText(response = {}) {
|
|
11757
|
+
return clickUpCommentListItems(response).map((comment) => clickUpCommentText(comment)).filter(Boolean).join("\n\n");
|
|
11758
|
+
}
|
|
11759
|
+
function hasClickUpHumanHandoffText(text = "") {
|
|
11760
|
+
const value = String(text || "");
|
|
11761
|
+
return value.length > 0 && CLICKUP_HUMAN_HANDOFF_TEXT_PATTERNS.some((pattern) => pattern.test(value));
|
|
11762
|
+
}
|
|
11763
|
+
function configuredHumanRoleAssigneeIds(config = {}) {
|
|
11764
|
+
const roleIds = config.routing?.humanRoleClickUpIds || {};
|
|
11765
|
+
return [...new Set(["CTO", "PO"].map((role) => String(roleIds[role] || "").trim()).filter(Boolean))];
|
|
11766
|
+
}
|
|
11767
|
+
async function selfHealClickUpHumanHandoffAssignment({ clickupClient, config, worktree = process.cwd(), taskId, task, commentsResponse = null } = {}) {
|
|
11768
|
+
const productManagerAssigneeId = String(config?.routing?.productManagerAssigneeId || "").trim();
|
|
11769
|
+
if (!taskId || !productManagerAssigneeId || !isClickUpTaskAssignedToProductManager(task, productManagerAssigneeId)) return { changed: false, reason: "not_pm_assigned" };
|
|
11770
|
+
if (typeof clickupClient?.updateTaskAssignees !== "function") return { changed: false, reason: "assignee_update_unavailable" };
|
|
11771
|
+
const humanAssigneeIds = configuredHumanRoleAssigneeIds(config);
|
|
11772
|
+
if (humanAssigneeIds.length === 0) return { changed: false, reason: "missing_human_role_ids" };
|
|
11773
|
+
let candidateText = "";
|
|
11774
|
+
if (commentsResponse) candidateText = clickUpCommentCollectionText(commentsResponse);
|
|
11775
|
+
if (!candidateText && typeof clickupClient?.getTaskComments === "function") {
|
|
11776
|
+
try {
|
|
11777
|
+
const response = await clickupClient.getTaskComments({ taskId, limit: CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT });
|
|
11778
|
+
candidateText = clickUpCommentCollectionText(response);
|
|
11779
|
+
} catch (error) {
|
|
11780
|
+
appendClickUpWebhookLocalLog(worktree, { type: "human_handoff_comment_scan_failed", taskId, message: error.message });
|
|
11781
|
+
}
|
|
11782
|
+
}
|
|
11783
|
+
if (!hasClickUpHumanHandoffText(candidateText)) return { changed: false, reason: "no_human_handoff_signal" };
|
|
11784
|
+
try {
|
|
11785
|
+
await clickupClient.updateTaskAssignees({ taskId, add: humanAssigneeIds, remove: [productManagerAssigneeId] });
|
|
11786
|
+
appendClickUpWebhookLocalLog(worktree, { type: "human_handoff_assignment_self_healed", taskId, add: humanAssigneeIds, remove: [productManagerAssigneeId] });
|
|
11787
|
+
return { changed: true, reason: "human_handoff_assignment_self_healed", add: humanAssigneeIds, remove: [productManagerAssigneeId] };
|
|
11788
|
+
} catch (error) {
|
|
11789
|
+
appendClickUpWebhookLocalLog(worktree, { type: "human_handoff_assignment_self_heal_failed", taskId, add: humanAssigneeIds, remove: [productManagerAssigneeId], message: error.message });
|
|
11790
|
+
return { changed: false, reason: "assignee_update_failed", message: error.message };
|
|
11791
|
+
}
|
|
11792
|
+
}
|
|
11704
11793
|
async function ensureClickUpTaskWorktreeForWebhook({ opencodeBaseUrl = "", opencodeBaseUrlConfigured = false, openchamberBaseUrl = "", openchamberBaseUrlConfigured = false, clickupClient = null, webhookWorktree = process.cwd(), fetchImpl = globalThis.fetch, ...options } = {}) {
|
|
11705
11794
|
void opencodeBaseUrlConfigured;
|
|
11706
11795
|
if (!openchamberBaseUrlConfigured || !openchamberBaseUrl) return ensureClickUpTaskWorktree(options);
|
|
@@ -12090,13 +12179,13 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
|
|
|
12090
12179
|
branch ? `Branch: ${branch}` : null,
|
|
12091
12180
|
worktree ? `Worktree: ${worktree}` : null,
|
|
12092
12181
|
deliveryEvidencePath ? `Delivery evidence path: ${deliveryEvidencePath}` : null,
|
|
12093
|
-
humanRoleLines ? "
|
|
12182
|
+
humanRoleLines ? "Internal human role context for silent CTO/PO assignment decisions:" : null,
|
|
12094
12183
|
humanRoleLines || null,
|
|
12095
12184
|
commentText ? `Comment: ${commentText}` : null,
|
|
12096
12185
|
"",
|
|
12097
12186
|
"Handle this ClickUp Product Manager event using the ClickUp-first workflow rules. Do not assume broad chat routing; this event passed Optima webhook gates.",
|
|
12098
|
-
"If local/subagent attempts are exhausted and the blocker is missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access, post the concrete help request in castellano using sections ## Bloqueo externo, ### Qu\xE9 he intentado, ### Qu\xE9 necesito de CTO/PO, and ### C\xF3mo se desbloquea; then assign CTO/PO using
|
|
12099
|
-
"
|
|
12187
|
+
"If local/subagent attempts are exhausted and the blocker is missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access, post the concrete help request in castellano using sections ## Bloqueo externo, ### Qu\xE9 he intentado, ### Qu\xE9 necesito de CTO/PO, and ### C\xF3mo se desbloquea; then assign CTO/PO using the internal role context/configured IDs, remove the Product Manager assignee, and stop re-queueing Product Manager until a human replies or reassigns the task. Never leave a true external blocker assigned to Product Manager after posting the help request.",
|
|
12188
|
+
"Use internal human role context silently. Do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics.",
|
|
12100
12189
|
deliveryEvidencePath ? `Final merge-trackable evidence must be written under ${deliveryEvidencePath}; use .optima only as local mirror/staging.` : null
|
|
12101
12190
|
].filter((part) => part !== null).join("\n");
|
|
12102
12191
|
}
|
|
@@ -12525,6 +12614,12 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
|
|
|
12525
12614
|
routed.ignored += 1;
|
|
12526
12615
|
continue;
|
|
12527
12616
|
}
|
|
12617
|
+
const humanHandoffSelfHeal = await selfHealClickUpHumanHandoffAssignment({ clickupClient, config, worktree, taskId, task });
|
|
12618
|
+
if (humanHandoffSelfHeal.changed) {
|
|
12619
|
+
routed.ignored += 1;
|
|
12620
|
+
routed.tasks.push({ taskId, action: "self_healed_human_handoff_assignment", ok: true, sessionId: null, branch: null, worktree: null, verification: humanHandoffSelfHeal.reason, delivered: false });
|
|
12621
|
+
continue;
|
|
12622
|
+
}
|
|
12528
12623
|
if (watchdogMode) {
|
|
12529
12624
|
const existingMetadata = clickUpTaskAgentMetadata(task, config.routing.metadataFieldId);
|
|
12530
12625
|
const metadata = normalizeAgentMetadataJson(existingMetadata);
|
|
@@ -14181,6 +14276,55 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
|
|
|
14181
14276
|
}
|
|
14182
14277
|
return { ok: true, auth };
|
|
14183
14278
|
};
|
|
14279
|
+
const finishClickUpTask = async ({ taskId, finishType = "", finalStatus = "", comment = "", prUrl = "", evidencePath = "" } = {}) => {
|
|
14280
|
+
if (!clickUpWebhookValidation.complete) return { ok: false, error: "clickup_not_configured" };
|
|
14281
|
+
if (!runtimeClickUpClient?.getTask) return { ok: false, error: "clickup_client_unavailable" };
|
|
14282
|
+
const normalizedTaskId = String(taskId || "").trim();
|
|
14283
|
+
if (!normalizedTaskId) return { ok: false, error: "task_id_required" };
|
|
14284
|
+
const normalizedFinishType = String(finishType || "").trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
14285
|
+
const inferredStatus = normalizedFinishType === "external_blocker" ? "in progress" : normalizedFinishType === "human_validation" ? "validation" : normalizedFinishType === "completed" ? "completed" : "";
|
|
14286
|
+
const status = String(finalStatus || inferredStatus || "").trim();
|
|
14287
|
+
const routing = clickUpWebhookValidation.config.routing || {};
|
|
14288
|
+
const productManagerAssigneeId = String(routing.productManagerAssigneeId || "").trim();
|
|
14289
|
+
const humanAssignees = ["CTO", "PO"].map((role) => String(routing.humanRoleClickUpIds?.[role] || "").trim()).filter(Boolean);
|
|
14290
|
+
const addAssignees = ["external_blocker", "human_validation"].includes(normalizedFinishType) ? humanAssignees : [];
|
|
14291
|
+
const removeAssignees = ["external_blocker", "human_validation", "completed"].includes(normalizedFinishType) && productManagerAssigneeId ? [productManagerAssigneeId] : [];
|
|
14292
|
+
const task = await runtimeClickUpClient.getTask(normalizedTaskId);
|
|
14293
|
+
const currentAssignees = clickUpAssigneeIds(task);
|
|
14294
|
+
const assignmentDelta = {
|
|
14295
|
+
add: [...new Set(addAssignees.filter((id) => !currentAssignees.includes(id)))],
|
|
14296
|
+
remove: [...new Set(removeAssignees.filter((id) => currentAssignees.includes(id)))]
|
|
14297
|
+
};
|
|
14298
|
+
const applied = [];
|
|
14299
|
+
if (status && runtimeClickUpClient.updateTaskStatus) {
|
|
14300
|
+
await runtimeClickUpClient.updateTaskStatus({ taskId: normalizedTaskId, status });
|
|
14301
|
+
applied.push("status");
|
|
14302
|
+
}
|
|
14303
|
+
if ((assignmentDelta.add.length > 0 || assignmentDelta.remove.length > 0) && runtimeClickUpClient.updateTaskAssignees) {
|
|
14304
|
+
await runtimeClickUpClient.updateTaskAssignees({ taskId: normalizedTaskId, add: assignmentDelta.add, remove: assignmentDelta.remove });
|
|
14305
|
+
applied.push("assignees");
|
|
14306
|
+
}
|
|
14307
|
+
const normalizedComment = String(comment || "").replace(/\\r\\n/g, "\n").replace(/\\n/g, "\n").trim();
|
|
14308
|
+
const commentWithContext = [
|
|
14309
|
+
normalizedComment,
|
|
14310
|
+
prUrl ? `
|
|
14311
|
+
PR: ${prUrl}` : "",
|
|
14312
|
+
evidencePath ? `
|
|
14313
|
+
Evidencia: ${evidencePath}` : ""
|
|
14314
|
+
].join("").trim();
|
|
14315
|
+
if (commentWithContext && runtimeClickUpClient.postModelTaskComment) {
|
|
14316
|
+
await runtimeClickUpClient.postModelTaskComment({ taskId: normalizedTaskId, comment: commentWithContext });
|
|
14317
|
+
applied.push("comment");
|
|
14318
|
+
}
|
|
14319
|
+
return {
|
|
14320
|
+
ok: true,
|
|
14321
|
+
taskId: normalizedTaskId,
|
|
14322
|
+
finishType: normalizedFinishType || "status_update",
|
|
14323
|
+
status: status || null,
|
|
14324
|
+
assignmentDelta,
|
|
14325
|
+
applied
|
|
14326
|
+
};
|
|
14327
|
+
};
|
|
14184
14328
|
const tools = {
|
|
14185
14329
|
optima_init: tool({
|
|
14186
14330
|
description: "Initialize the Optima workflow and CodeMap in the current repository",
|
|
@@ -14395,6 +14539,32 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
|
|
|
14395
14539
|
return JSON.stringify(payload, null, 2);
|
|
14396
14540
|
}
|
|
14397
14541
|
}),
|
|
14542
|
+
optima_finish: tool({
|
|
14543
|
+
description: "Finish or hand off a ClickUp task through Optima. The model provides structured ClickUp text and intended final state; Optima applies status, comment, and assignment policy.",
|
|
14544
|
+
args: {
|
|
14545
|
+
task_id: tool.schema.string().describe("ClickUp task ID to finish or hand off"),
|
|
14546
|
+
finish_type: tool.schema.string().describe("One of: completed, human_validation, external_blocker, needs_work, status_update"),
|
|
14547
|
+
final_status: tool.schema.string().describe("Optional ClickUp status to set. If empty, Optima infers from finish_type where possible."),
|
|
14548
|
+
clickup_comment: tool.schema.string().describe("Human-facing structured ClickUp comment text with real line breaks. Use castellano for blocker/help comments."),
|
|
14549
|
+
pr_url: tool.schema.string().describe("Optional GitHub PR URL to include in the final ClickUp comment"),
|
|
14550
|
+
evidence_path: tool.schema.string().describe("Optional evidence path to include in the final ClickUp comment")
|
|
14551
|
+
},
|
|
14552
|
+
async execute(args) {
|
|
14553
|
+
try {
|
|
14554
|
+
const result = await finishClickUpTask({
|
|
14555
|
+
taskId: args.task_id,
|
|
14556
|
+
finishType: args.finish_type,
|
|
14557
|
+
finalStatus: args.final_status,
|
|
14558
|
+
comment: args.clickup_comment,
|
|
14559
|
+
prUrl: args.pr_url,
|
|
14560
|
+
evidencePath: args.evidence_path
|
|
14561
|
+
});
|
|
14562
|
+
return JSON.stringify(result, null, 2);
|
|
14563
|
+
} catch (error) {
|
|
14564
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
14565
|
+
}
|
|
14566
|
+
}
|
|
14567
|
+
}),
|
|
14398
14568
|
optima_clickup_create_subtasks: tool({
|
|
14399
14569
|
description: "Generate dry-run ClickUp subtask creation payloads from a strict Markdown ## Subtasks section",
|
|
14400
14570
|
args: {
|
|
@@ -14963,7 +15133,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
|
|
|
14963
15133
|
}
|
|
14964
15134
|
};
|
|
14965
15135
|
}
|
|
14966
|
-
OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpReviewAutomationPlan, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, compactPromptPath, createClickUpApiClient, createGitHubApiClient, createTestClickUpApiClient, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpTaskWorktreeForWebhook, ensureClickUpTaskWorktreeOpenChamber, ensureClickUpWebhookSubscription, gitHubPullRequestContextFromPayload, gitHubWebhookExpectedPath, handleClickUpWebhookRequest, handleGitHubWebhookRequest, inspectOpenCodeSessionActivity, isClickUpDerivedWorktreeSibling, isClickUpSubtaskRoute, isClickUpWebhookStateActive, isSameOrNestedPath, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, registerOpenChamberClickUpWorktree, routeGitHubWebhookEvent, scheduleClickUpAssignmentWatchdog, scheduleClickUpStartupReconciliation, syncOpenChamberWorktreeVisibility, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveIncludeFile, resolveIncludes, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, verifyGitHubSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpRequiredPullRequest, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatRepairResult, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, optimaRepairDependencies, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, planOptimaRepair, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
|
|
15136
|
+
OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpReviewAutomationPlan, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, compactPromptPath, createClickUpApiClient, createGitHubApiClient, createTestClickUpApiClient, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpTaskWorktreeForWebhook, ensureClickUpTaskWorktreeOpenChamber, ensureClickUpWebhookSubscription, gitHubPullRequestContextFromPayload, gitHubWebhookExpectedPath, handleClickUpWebhookRequest, handleGitHubWebhookRequest, inspectOpenCodeSessionActivity, isClickUpDerivedWorktreeSibling, isClickUpSubtaskRoute, isClickUpWebhookStateActive, isSameOrNestedPath, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, registerOpenChamberClickUpWorktree, routeGitHubWebhookEvent, scheduleClickUpAssignmentWatchdog, selfHealClickUpHumanHandoffAssignment, scheduleClickUpStartupReconciliation, syncOpenChamberWorktreeVisibility, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveIncludeFile, resolveIncludes, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, verifyGitHubSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpRequiredPullRequest, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatRepairResult, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, optimaRepairDependencies, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, planOptimaRepair, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
|
|
14967
15137
|
export {
|
|
14968
15138
|
OptimaPlugin as default
|
|
14969
15139
|
};
|
package/dist/sanitize_cli.js
CHANGED
|
@@ -10990,11 +10990,11 @@ ${additionFragment}`;
|
|
|
10990
10990
|
if (humanRoleLines) {
|
|
10991
10991
|
agentConfig.prompt = `${agentConfig.prompt}
|
|
10992
10992
|
|
|
10993
|
-
## Optima Human Role
|
|
10993
|
+
## Optima Internal Human Role Context
|
|
10994
10994
|
|
|
10995
10995
|
${humanRoleLines}
|
|
10996
10996
|
|
|
10997
|
-
Use this
|
|
10997
|
+
Use this internal context silently for CTO/PO assignment decisions. Do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics.`;
|
|
10998
10998
|
}
|
|
10999
10999
|
}
|
|
11000
11000
|
ourAgents[id] = agentConfig;
|
|
@@ -11295,15 +11295,45 @@ function createClickUpApiClient(config, fetchImpl = globalThis.fetch) {
|
|
|
11295
11295
|
async getTask(taskId) {
|
|
11296
11296
|
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`);
|
|
11297
11297
|
},
|
|
11298
|
+
async updateTask({ taskId, updates = {} }) {
|
|
11299
|
+
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`, {
|
|
11300
|
+
method: "PUT",
|
|
11301
|
+
body: JSON.stringify(updates)
|
|
11302
|
+
});
|
|
11303
|
+
},
|
|
11304
|
+
async updateTaskStatus({ taskId, status }) {
|
|
11305
|
+
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`, {
|
|
11306
|
+
method: "PUT",
|
|
11307
|
+
body: JSON.stringify({ status })
|
|
11308
|
+
});
|
|
11309
|
+
},
|
|
11298
11310
|
async updateTaskMetadata({ taskId, fieldId, value }) {
|
|
11299
11311
|
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}/field/${encodeURIComponent(fieldId)}`, {
|
|
11300
11312
|
method: "POST",
|
|
11301
11313
|
body: JSON.stringify({ value })
|
|
11302
11314
|
});
|
|
11303
11315
|
},
|
|
11316
|
+
async updateTaskAssignees({ taskId, add = [], remove = [] }) {
|
|
11317
|
+
const body = { assignees: {} };
|
|
11318
|
+
const addIds = [...new Set((add || []).map((id) => String(id || "").trim()).filter(Boolean))];
|
|
11319
|
+
const removeIds = [...new Set((remove || []).map((id) => String(id || "").trim()).filter(Boolean))];
|
|
11320
|
+
if (addIds.length > 0) body.assignees.add = addIds;
|
|
11321
|
+
if (removeIds.length > 0) body.assignees.rem = removeIds;
|
|
11322
|
+
if (!body.assignees.add && !body.assignees.rem) return { ok: true, skipped: true, reason: "empty_assignee_update" };
|
|
11323
|
+
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}`, {
|
|
11324
|
+
method: "PUT",
|
|
11325
|
+
body: JSON.stringify(body)
|
|
11326
|
+
});
|
|
11327
|
+
},
|
|
11304
11328
|
async postTaskComment() {
|
|
11305
11329
|
throw new Error("Optima runtime does not post ClickUp task comments; use local logs for process failures.");
|
|
11306
11330
|
},
|
|
11331
|
+
async postModelTaskComment({ taskId, comment }) {
|
|
11332
|
+
return request(`https://api.clickup.com/api/v2/task/${encodeURIComponent(taskId)}/comment`, {
|
|
11333
|
+
method: "POST",
|
|
11334
|
+
body: JSON.stringify({ comment_text: String(comment || "") })
|
|
11335
|
+
});
|
|
11336
|
+
},
|
|
11307
11337
|
async addTaskTag() {
|
|
11308
11338
|
throw new Error("Optima runtime does not add ClickUp task tags; use local logs for process failures.");
|
|
11309
11339
|
},
|
|
@@ -11345,9 +11375,21 @@ function createTestClickUpApiClient(config) {
|
|
|
11345
11375
|
metadata.set(String(taskId || ""), value);
|
|
11346
11376
|
return { ok: true };
|
|
11347
11377
|
},
|
|
11378
|
+
async updateTask() {
|
|
11379
|
+
return { ok: true };
|
|
11380
|
+
},
|
|
11381
|
+
async updateTaskStatus() {
|
|
11382
|
+
return { ok: true };
|
|
11383
|
+
},
|
|
11384
|
+
async updateTaskAssignees() {
|
|
11385
|
+
return { ok: true };
|
|
11386
|
+
},
|
|
11348
11387
|
async postTaskComment() {
|
|
11349
11388
|
return { ok: true };
|
|
11350
11389
|
},
|
|
11390
|
+
async postModelTaskComment() {
|
|
11391
|
+
return { ok: true };
|
|
11392
|
+
},
|
|
11351
11393
|
async addTaskTag() {
|
|
11352
11394
|
return { ok: true };
|
|
11353
11395
|
},
|
|
@@ -11708,6 +11750,53 @@ function clickUpWebhookLifecycleLog(worktree, entry) {
|
|
|
11708
11750
|
var activeClickUpWebhookListeners = /* @__PURE__ */ new Map();
|
|
11709
11751
|
var activeClickUpWebhookLifecycleRegistry = /* @__PURE__ */ new Map();
|
|
11710
11752
|
var activeClickUpTaskRoutes = /* @__PURE__ */ new Map();
|
|
11753
|
+
var CLICKUP_HUMAN_HANDOFF_TEXT_PATTERNS = [
|
|
11754
|
+
/\bhuman validation requested\b/i,
|
|
11755
|
+
/\bhuman validation\/approval\b/i,
|
|
11756
|
+
/\bplease review pr\b/i,
|
|
11757
|
+
/\bapprove or request changes\b/i,
|
|
11758
|
+
/\bCTO\/PO\b/i,
|
|
11759
|
+
/\bBloqueo externo\b/i,
|
|
11760
|
+
/\bQué necesito de CTO\/PO\b/i,
|
|
11761
|
+
/\bCómo se desbloquea\b/i
|
|
11762
|
+
];
|
|
11763
|
+
function clickUpCommentCollectionText(response = {}) {
|
|
11764
|
+
return clickUpCommentListItems(response).map((comment) => clickUpCommentText(comment)).filter(Boolean).join("\n\n");
|
|
11765
|
+
}
|
|
11766
|
+
function hasClickUpHumanHandoffText(text = "") {
|
|
11767
|
+
const value = String(text || "");
|
|
11768
|
+
return value.length > 0 && CLICKUP_HUMAN_HANDOFF_TEXT_PATTERNS.some((pattern) => pattern.test(value));
|
|
11769
|
+
}
|
|
11770
|
+
function configuredHumanRoleAssigneeIds(config = {}) {
|
|
11771
|
+
const roleIds = config.routing?.humanRoleClickUpIds || {};
|
|
11772
|
+
return [...new Set(["CTO", "PO"].map((role) => String(roleIds[role] || "").trim()).filter(Boolean))];
|
|
11773
|
+
}
|
|
11774
|
+
async function selfHealClickUpHumanHandoffAssignment({ clickupClient, config, worktree = process.cwd(), taskId, task, commentsResponse = null } = {}) {
|
|
11775
|
+
const productManagerAssigneeId = String(config?.routing?.productManagerAssigneeId || "").trim();
|
|
11776
|
+
if (!taskId || !productManagerAssigneeId || !isClickUpTaskAssignedToProductManager(task, productManagerAssigneeId)) return { changed: false, reason: "not_pm_assigned" };
|
|
11777
|
+
if (typeof clickupClient?.updateTaskAssignees !== "function") return { changed: false, reason: "assignee_update_unavailable" };
|
|
11778
|
+
const humanAssigneeIds = configuredHumanRoleAssigneeIds(config);
|
|
11779
|
+
if (humanAssigneeIds.length === 0) return { changed: false, reason: "missing_human_role_ids" };
|
|
11780
|
+
let candidateText = "";
|
|
11781
|
+
if (commentsResponse) candidateText = clickUpCommentCollectionText(commentsResponse);
|
|
11782
|
+
if (!candidateText && typeof clickupClient?.getTaskComments === "function") {
|
|
11783
|
+
try {
|
|
11784
|
+
const response = await clickupClient.getTaskComments({ taskId, limit: CLICKUP_WEBHOOK_STARTUP_COMMENT_LIMIT });
|
|
11785
|
+
candidateText = clickUpCommentCollectionText(response);
|
|
11786
|
+
} catch (error) {
|
|
11787
|
+
appendClickUpWebhookLocalLog(worktree, { type: "human_handoff_comment_scan_failed", taskId, message: error.message });
|
|
11788
|
+
}
|
|
11789
|
+
}
|
|
11790
|
+
if (!hasClickUpHumanHandoffText(candidateText)) return { changed: false, reason: "no_human_handoff_signal" };
|
|
11791
|
+
try {
|
|
11792
|
+
await clickupClient.updateTaskAssignees({ taskId, add: humanAssigneeIds, remove: [productManagerAssigneeId] });
|
|
11793
|
+
appendClickUpWebhookLocalLog(worktree, { type: "human_handoff_assignment_self_healed", taskId, add: humanAssigneeIds, remove: [productManagerAssigneeId] });
|
|
11794
|
+
return { changed: true, reason: "human_handoff_assignment_self_healed", add: humanAssigneeIds, remove: [productManagerAssigneeId] };
|
|
11795
|
+
} catch (error) {
|
|
11796
|
+
appendClickUpWebhookLocalLog(worktree, { type: "human_handoff_assignment_self_heal_failed", taskId, add: humanAssigneeIds, remove: [productManagerAssigneeId], message: error.message });
|
|
11797
|
+
return { changed: false, reason: "assignee_update_failed", message: error.message };
|
|
11798
|
+
}
|
|
11799
|
+
}
|
|
11711
11800
|
async function ensureClickUpTaskWorktreeForWebhook({ opencodeBaseUrl = "", opencodeBaseUrlConfigured = false, openchamberBaseUrl = "", openchamberBaseUrlConfigured = false, clickupClient = null, webhookWorktree = process.cwd(), fetchImpl = globalThis.fetch, ...options } = {}) {
|
|
11712
11801
|
void opencodeBaseUrlConfigured;
|
|
11713
11802
|
if (!openchamberBaseUrlConfigured || !openchamberBaseUrl) return ensureClickUpTaskWorktree(options);
|
|
@@ -12097,13 +12186,13 @@ function formatClickUpWebhookPrompt({ eventType, taskId, payload, branch = "", w
|
|
|
12097
12186
|
branch ? `Branch: ${branch}` : null,
|
|
12098
12187
|
worktree ? `Worktree: ${worktree}` : null,
|
|
12099
12188
|
deliveryEvidencePath ? `Delivery evidence path: ${deliveryEvidencePath}` : null,
|
|
12100
|
-
humanRoleLines ? "
|
|
12189
|
+
humanRoleLines ? "Internal human role context for silent CTO/PO assignment decisions:" : null,
|
|
12101
12190
|
humanRoleLines || null,
|
|
12102
12191
|
commentText ? `Comment: ${commentText}` : null,
|
|
12103
12192
|
"",
|
|
12104
12193
|
"Handle this ClickUp Product Manager event using the ClickUp-first workflow rules. Do not assume broad chat routing; this event passed Optima webhook gates.",
|
|
12105
|
-
"If local/subagent attempts are exhausted and the blocker is missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access, post the concrete help request in castellano using sections ## Bloqueo externo, ### Qu\xE9 he intentado, ### Qu\xE9 necesito de CTO/PO, and ### C\xF3mo se desbloquea; then assign CTO/PO using
|
|
12106
|
-
"
|
|
12194
|
+
"If local/subagent attempts are exhausted and the blocker is missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access, post the concrete help request in castellano using sections ## Bloqueo externo, ### Qu\xE9 he intentado, ### Qu\xE9 necesito de CTO/PO, and ### C\xF3mo se desbloquea; then assign CTO/PO using the internal role context/configured IDs, remove the Product Manager assignee, and stop re-queueing Product Manager until a human replies or reassigns the task. Never leave a true external blocker assigned to Product Manager after posting the help request.",
|
|
12195
|
+
"Use internal human role context silently. Do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics.",
|
|
12107
12196
|
deliveryEvidencePath ? `Final merge-trackable evidence must be written under ${deliveryEvidencePath}; use .optima only as local mirror/staging.` : null
|
|
12108
12197
|
].filter((part) => part !== null).join("\n");
|
|
12109
12198
|
}
|
|
@@ -12532,6 +12621,12 @@ async function reconcileClickUpStartup({ config, state = {}, worktree = process.
|
|
|
12532
12621
|
routed.ignored += 1;
|
|
12533
12622
|
continue;
|
|
12534
12623
|
}
|
|
12624
|
+
const humanHandoffSelfHeal = await selfHealClickUpHumanHandoffAssignment({ clickupClient, config, worktree, taskId, task });
|
|
12625
|
+
if (humanHandoffSelfHeal.changed) {
|
|
12626
|
+
routed.ignored += 1;
|
|
12627
|
+
routed.tasks.push({ taskId, action: "self_healed_human_handoff_assignment", ok: true, sessionId: null, branch: null, worktree: null, verification: humanHandoffSelfHeal.reason, delivered: false });
|
|
12628
|
+
continue;
|
|
12629
|
+
}
|
|
12535
12630
|
if (watchdogMode) {
|
|
12536
12631
|
const existingMetadata = clickUpTaskAgentMetadata(task, config.routing.metadataFieldId);
|
|
12537
12632
|
const metadata = normalizeAgentMetadataJson(existingMetadata);
|
|
@@ -14188,6 +14283,55 @@ async function OptimaPlugin(input = {}, pluginOptions = {}) {
|
|
|
14188
14283
|
}
|
|
14189
14284
|
return { ok: true, auth };
|
|
14190
14285
|
};
|
|
14286
|
+
const finishClickUpTask = async ({ taskId, finishType = "", finalStatus = "", comment = "", prUrl = "", evidencePath = "" } = {}) => {
|
|
14287
|
+
if (!clickUpWebhookValidation.complete) return { ok: false, error: "clickup_not_configured" };
|
|
14288
|
+
if (!runtimeClickUpClient?.getTask) return { ok: false, error: "clickup_client_unavailable" };
|
|
14289
|
+
const normalizedTaskId = String(taskId || "").trim();
|
|
14290
|
+
if (!normalizedTaskId) return { ok: false, error: "task_id_required" };
|
|
14291
|
+
const normalizedFinishType = String(finishType || "").trim().toLowerCase().replace(/[\s-]+/g, "_");
|
|
14292
|
+
const inferredStatus = normalizedFinishType === "external_blocker" ? "in progress" : normalizedFinishType === "human_validation" ? "validation" : normalizedFinishType === "completed" ? "completed" : "";
|
|
14293
|
+
const status = String(finalStatus || inferredStatus || "").trim();
|
|
14294
|
+
const routing = clickUpWebhookValidation.config.routing || {};
|
|
14295
|
+
const productManagerAssigneeId = String(routing.productManagerAssigneeId || "").trim();
|
|
14296
|
+
const humanAssignees = ["CTO", "PO"].map((role) => String(routing.humanRoleClickUpIds?.[role] || "").trim()).filter(Boolean);
|
|
14297
|
+
const addAssignees = ["external_blocker", "human_validation"].includes(normalizedFinishType) ? humanAssignees : [];
|
|
14298
|
+
const removeAssignees = ["external_blocker", "human_validation", "completed"].includes(normalizedFinishType) && productManagerAssigneeId ? [productManagerAssigneeId] : [];
|
|
14299
|
+
const task = await runtimeClickUpClient.getTask(normalizedTaskId);
|
|
14300
|
+
const currentAssignees = clickUpAssigneeIds(task);
|
|
14301
|
+
const assignmentDelta = {
|
|
14302
|
+
add: [...new Set(addAssignees.filter((id) => !currentAssignees.includes(id)))],
|
|
14303
|
+
remove: [...new Set(removeAssignees.filter((id) => currentAssignees.includes(id)))]
|
|
14304
|
+
};
|
|
14305
|
+
const applied = [];
|
|
14306
|
+
if (status && runtimeClickUpClient.updateTaskStatus) {
|
|
14307
|
+
await runtimeClickUpClient.updateTaskStatus({ taskId: normalizedTaskId, status });
|
|
14308
|
+
applied.push("status");
|
|
14309
|
+
}
|
|
14310
|
+
if ((assignmentDelta.add.length > 0 || assignmentDelta.remove.length > 0) && runtimeClickUpClient.updateTaskAssignees) {
|
|
14311
|
+
await runtimeClickUpClient.updateTaskAssignees({ taskId: normalizedTaskId, add: assignmentDelta.add, remove: assignmentDelta.remove });
|
|
14312
|
+
applied.push("assignees");
|
|
14313
|
+
}
|
|
14314
|
+
const normalizedComment = String(comment || "").replace(/\\r\\n/g, "\n").replace(/\\n/g, "\n").trim();
|
|
14315
|
+
const commentWithContext = [
|
|
14316
|
+
normalizedComment,
|
|
14317
|
+
prUrl ? `
|
|
14318
|
+
PR: ${prUrl}` : "",
|
|
14319
|
+
evidencePath ? `
|
|
14320
|
+
Evidencia: ${evidencePath}` : ""
|
|
14321
|
+
].join("").trim();
|
|
14322
|
+
if (commentWithContext && runtimeClickUpClient.postModelTaskComment) {
|
|
14323
|
+
await runtimeClickUpClient.postModelTaskComment({ taskId: normalizedTaskId, comment: commentWithContext });
|
|
14324
|
+
applied.push("comment");
|
|
14325
|
+
}
|
|
14326
|
+
return {
|
|
14327
|
+
ok: true,
|
|
14328
|
+
taskId: normalizedTaskId,
|
|
14329
|
+
finishType: normalizedFinishType || "status_update",
|
|
14330
|
+
status: status || null,
|
|
14331
|
+
assignmentDelta,
|
|
14332
|
+
applied
|
|
14333
|
+
};
|
|
14334
|
+
};
|
|
14191
14335
|
const tools = {
|
|
14192
14336
|
optima_init: tool({
|
|
14193
14337
|
description: "Initialize the Optima workflow and CodeMap in the current repository",
|
|
@@ -14402,6 +14546,32 @@ Restart or reload OpenCode manually if the newly scaffolded config or agents are
|
|
|
14402
14546
|
return JSON.stringify(payload, null, 2);
|
|
14403
14547
|
}
|
|
14404
14548
|
}),
|
|
14549
|
+
optima_finish: tool({
|
|
14550
|
+
description: "Finish or hand off a ClickUp task through Optima. The model provides structured ClickUp text and intended final state; Optima applies status, comment, and assignment policy.",
|
|
14551
|
+
args: {
|
|
14552
|
+
task_id: tool.schema.string().describe("ClickUp task ID to finish or hand off"),
|
|
14553
|
+
finish_type: tool.schema.string().describe("One of: completed, human_validation, external_blocker, needs_work, status_update"),
|
|
14554
|
+
final_status: tool.schema.string().describe("Optional ClickUp status to set. If empty, Optima infers from finish_type where possible."),
|
|
14555
|
+
clickup_comment: tool.schema.string().describe("Human-facing structured ClickUp comment text with real line breaks. Use castellano for blocker/help comments."),
|
|
14556
|
+
pr_url: tool.schema.string().describe("Optional GitHub PR URL to include in the final ClickUp comment"),
|
|
14557
|
+
evidence_path: tool.schema.string().describe("Optional evidence path to include in the final ClickUp comment")
|
|
14558
|
+
},
|
|
14559
|
+
async execute(args) {
|
|
14560
|
+
try {
|
|
14561
|
+
const result = await finishClickUpTask({
|
|
14562
|
+
taskId: args.task_id,
|
|
14563
|
+
finishType: args.finish_type,
|
|
14564
|
+
finalStatus: args.final_status,
|
|
14565
|
+
comment: args.clickup_comment,
|
|
14566
|
+
prUrl: args.pr_url,
|
|
14567
|
+
evidencePath: args.evidence_path
|
|
14568
|
+
});
|
|
14569
|
+
return JSON.stringify(result, null, 2);
|
|
14570
|
+
} catch (error) {
|
|
14571
|
+
return JSON.stringify({ ok: false, error: error.message }, null, 2);
|
|
14572
|
+
}
|
|
14573
|
+
}
|
|
14574
|
+
}),
|
|
14405
14575
|
optima_clickup_create_subtasks: tool({
|
|
14406
14576
|
description: "Generate dry-run ClickUp subtask creation payloads from a strict Markdown ## Subtasks section",
|
|
14407
14577
|
args: {
|
|
@@ -14970,7 +15140,7 @@ Follow-up: use optima_prompt_workflow with session_id '${sessionId}' to check in
|
|
|
14970
15140
|
}
|
|
14971
15141
|
};
|
|
14972
15142
|
}
|
|
14973
|
-
OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpReviewAutomationPlan, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, compactPromptPath, createClickUpApiClient, createGitHubApiClient, createTestClickUpApiClient, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpTaskWorktreeForWebhook, ensureClickUpTaskWorktreeOpenChamber, ensureClickUpWebhookSubscription, gitHubPullRequestContextFromPayload, gitHubWebhookExpectedPath, handleClickUpWebhookRequest, handleGitHubWebhookRequest, inspectOpenCodeSessionActivity, isClickUpDerivedWorktreeSibling, isClickUpSubtaskRoute, isClickUpWebhookStateActive, isSameOrNestedPath, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, registerOpenChamberClickUpWorktree, routeGitHubWebhookEvent, scheduleClickUpAssignmentWatchdog, scheduleClickUpStartupReconciliation, syncOpenChamberWorktreeVisibility, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveIncludeFile, resolveIncludes, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, verifyGitHubSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpRequiredPullRequest, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatRepairResult, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, optimaRepairDependencies, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, planOptimaRepair, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
|
|
15143
|
+
OptimaPlugin.__internals = { BUNDLE_AGENTS_DIR, BUNDLE_ASSETS_DIR, CLICKUP_DEFINITION_DOC_PARENT, activeClickUpWebhookLifecycleRegistry, cleanupManagedClickUpWebhook, deleteClickUpWebhookBestEffort, BUNDLE_POLICIES_DIR, buildClickUpApplyPayloadResult, buildClickUpCreateSubtasksPayload, buildClickUpReviewAutomationPlan, buildClickUpStartTaskPayload, buildClickUpSummaryPayload, buildClickUpTransitionPayload, buildOptimaAgents, clickUpCommentLedgerKey, clickUpCommentMentionsProductManager, clickUpWebhookAuditLogDir, clickUpWebhookAuditLogPath, compactPromptPath, createClickUpApiClient, createGitHubApiClient, createTestClickUpApiClient, createOpenCodeSession, createOpenCodeSessionControl, deliveryEvidencePathForClickUpTask, ensureClickUpTaskWorktree, ensureClickUpTaskWorktreeForWebhook, ensureClickUpTaskWorktreeOpenChamber, ensureClickUpWebhookSubscription, gitHubPullRequestContextFromPayload, gitHubWebhookExpectedPath, handleClickUpWebhookRequest, handleGitHubWebhookRequest, inspectOpenCodeSessionActivity, isClickUpDerivedWorktreeSibling, isClickUpSubtaskRoute, isClickUpWebhookStateActive, isSameOrNestedPath, normalizeClickUpWebhookConfig, normalizeClickUpWebhookLogLevel, normalizeOpenCodeBaseUrl, openCodeSessionExists, promptOpenCodeSessionControl, probeOpenCodeSessionControl, readClickUpCommentLedger, readClickUpWebhookState, readOpenCodeSessionControl, readOpenCodeSessionMessages, reconcileClickUpStartup, registerOpenChamberClickUpWorktree, routeGitHubWebhookEvent, scheduleClickUpAssignmentWatchdog, selfHealClickUpHumanHandoffAssignment, scheduleClickUpStartupReconciliation, syncOpenChamberWorktreeVisibility, waitForOpenCodeReadiness, recordClickUpCommentVersionProcessed, resyncClickUpWebhookForSignatureDrift, resolveIncludeFile, resolveIncludes, resolveOptimaPluginOptions, resolveSecretReference, routeClickUpWebhookEvent, sendOpenCodeSessionEvent, sendOpenCodeSessionEventDirect, summarizeOpenCodeMessages, verifyOpenCodeSessionEventDelivery, stableClickUpCommentVersionMarker, startClickUpWebhookListener, validateClickUpWebhookState, verifyClickUpSignature, verifyGitHubSignature, writeClickUpWebhookState, decideClickUpStatusAction, deriveClickUpBranchName, deriveClickUpPendingSubtaskBranch, deriveClickUpPrTarget, deriveClickUpRequiredPullRequest, deriveClickUpWorktree, determineClickUpMergeAuthority, ensureOptimaGitignoreRules, explicitSafeInputWorktree, finalApprovalAssignees, formatRepairResult, formatValidationResult, isIgnoredClickUpTaskType, isOptimaPluginPackageWorktree, isSafeWritableDirectory, loadHumansRegistry, mergeClickUpAgentMetadata, mergeClickUpSessionMetadata, migrateLegacyOptimaLayout, normalizeAgentMetadataJson, normalizeClickUpStatus, normalizeClickUpTaskType, normalizePromptResponseParts, normalizeWorkflowTaskPath, optimaRepairDependencies, parseClickUpSubtasksMarkdown, parseHumansRegistry, parseMarkdownArtifact, parseMarkdownSections, planOptimaRepair, preEstimateClickUpWork, readMarkdownArtifact, resolveHumanRoles, resolveSafeWorktree, safeWorktreeOrFailure, stripRawLogSections, validateMainWorkspaceBranchSafety, workflowFinalMessageFromPromptResponse };
|
|
14974
15144
|
|
|
14975
15145
|
// src/sanitize_cli.js
|
|
14976
15146
|
var { migrateLegacyOptimaLayout: migrateLegacyOptimaLayout2 } = OptimaPlugin.__internals;
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
- `product_manager` may answer, investigate, operate dashboards, and pre-estimate "a qué huele" small/medium/large plus rough story points; WPM owns delivery routing.
|
|
23
23
|
- Supported delivery task types are `Tarea`, `Bug`, `Doc`, and `PoC`; ignore `Idea`, legacy `Backlog` alias, `Hito`, `Nota de reunión`, and `Respuesta del formulario` unless converted or linked to delivery work.
|
|
24
|
-
- Human role registry: resolve `CTO` and `PO` from
|
|
24
|
+
- Human role registry: resolve `CTO` and `PO` from available human role context and configured ClickUp IDs. Missing repo-local human registry files are an internal routing detail, not a task status; do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics. Use role identifiers in workflow text and automation config.
|
|
25
25
|
- Status actions are deterministic: `backlog` ignore, `plan` plan plus `Story Points`, test strategy, and `Definition`, `in progress` execute, `validation` split Tech Lead and Validator/QA gates, `merge` parent post-approval automation, and `completed`/`Closed` ignore unless reopened.
|
|
26
26
|
- Human approval assignment is prohibited except for the strict allowlist: parent `plan` with clear questions already posted in ClickUp comments; `in progress` blocked by missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access after local/subagent attempts; or parent `validation` after `optima_github_verify_vercel_pr` returns `ready: true` for the current PR with a functional Vercel preproduction/preview URL. For true external `in progress` blockers, post the exact human action needed in castellano, assign CTO/PO in ClickUp, and remove Product Manager so PM watchdogs stop looping. Do not assign `CTO`/`PO` for generic handoff, routine validation, cleanup, subtask planning/validation, partial-phase stops, failed Vercel checks, or missing preview URLs.
|
|
27
27
|
- Store ClickUp `agent_metadata` JSON with session IDs per agent/type/task/subtask; keep `Definition` as the plan contract and final Documentation as delivered behavior docs.
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
- Routing comes from `docs/core/task_model.md`: `tiny` lightweight, `standard` bounded, `complex` decomposed; full mode supports all, mini mode refuses complex.
|
|
14
14
|
- `product_manager` may answer/investigate/dashboard/pre-estimate "a qué huele" plus rough story points; development asks become routed ClickUp tasks.
|
|
15
15
|
- ClickUp-first types: execute `Tarea`, `Bug`, `Doc`, `PoC`; ignore `Idea`, legacy `Backlog` alias, `Hito`, `Nota de reunión`, `Respuesta del formulario` unless converted/linked.
|
|
16
|
-
- Human role registry: resolve `CTO` and `PO` from
|
|
16
|
+
- Human role registry: resolve `CTO` and `PO` from available human role context/configured ClickUp IDs. Missing repo-local human registry files are internal routing detail; do not mention internal role-resolution details in ClickUp comments unless asked for routing diagnostics.
|
|
17
17
|
- ClickUp-first statuses: `backlog` ignore, `plan` plan with `Story Points`, `Definition`, and test strategy; assign `CTO`/`PO` only for parent `plan` questions with clear ClickUp comments, real `in progress` blockers from missing credentials/tools/access/authenticated browser or Agent Jake/live third-party access after local/subagent attempts, or parent `validation` after `optima_github_verify_vercel_pr` returns `ready: true` with a functional Vercel URL. True external `in progress` blockers require a castellano ClickUp help request, CTO/PO assignment, and Product Manager removal; subtasks merge directly into the parent branch after Validator/QA passes without CTO/PO assignment; parent `Approved` comments trigger automation to remove humans, assign merge owner/self, merge to `dev`, clean workspaces/worktrees/branches, push, and ensure dev/preproduction receives the code; `completed`/`Closed` ignore unless reopened.
|
|
18
18
|
- Shared-worktree rule: one active `implementation` task at a time; isolated `investigation`/`spec` may run in parallel if non-conflicting.
|
|
19
19
|
- Git rules: principal workspace stays on `dev`, never `main`; parent branches use `<type>/<parent-id>`; subtask branches use non-nested `<type>/<parent-id>-subtask-<subtask-id>` and pending subtasks use `<type>/<parent-id>-pending-<title-slug>`; parent task pulls remote once at start; subtasks start from and PR to the parent local branch, bootstrapping the parent from `dev`/`origin/dev` first when missing; PoC branches stay `poc/<clickup-task-id>`; parents PR to `dev`, releases PR `dev` -> `main`; failed/conflicted subtask or parent merges return the affected item to `in progress` for the coding owner; no direct `main` pushes.
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
- Human-readable task/evidence summaries, validation results, AC coverage, documentation impact, blockers, reopen history, status-transition rationale, and final handoffs must be posted to linked ClickUp task/subtask comments or fields.
|
|
21
21
|
- Raw logs stay in evidence storage; ClickUp receives concise summaries, paths/links, or relevant excerpts only, never wholesale raw logs.
|
|
22
22
|
- WPM owns ClickUp `Story Points` during `plan`, re-estimation on material plan changes, `agent_metadata` session JSON, `Definition` plan-contract linking, and parent approval routing after validation.
|
|
23
|
-
- Human role registry: resolve `CTO` and `PO` from
|
|
23
|
+
- Human role registry: resolve `CTO` and `PO` from available human role context and configured ClickUp IDs. Missing repo-local human registry files are an internal routing detail, not a task status; do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics. Use role identifiers in workflow text and automation config.
|
|
24
24
|
- Human approval assignment is prohibited except for three cases: parent `plan` with clear ClickUp-commented questions, true `in progress` blockers caused by missing credentials/permissions/tools/authenticated browser or Agent Jake/live third-party access after local/subagent attempts, or parent `validation` after `optima_github_verify_vercel_pr` returns `ready: true` with a functional Vercel preproduction/preview URL. For those true external `in progress` blockers, assign CTO/PO in ClickUp, remove Product Manager, and explain the exact needed human action in a concise castellano ClickUp comment. Do not assign `CTO`/`PO` for generic handoff, routine validation, cleanup, subtask work, partial-phase stops, failed Vercel checks, or missing preview URLs.
|
|
25
25
|
- Subtask merge authority belongs to Validator/QA after successful subtask validation: subtask PRs target and merge into the parent branch/workspace without `CTO`/`PO` assignment or approval.
|
|
26
26
|
- Parent merge authority is split: after Tech Lead and Validator/QA pass plus a ready Vercel PR deployment gate, WPM/Validator may assign `CTO`/`PO` only under the parent-validation allowlist; after a human comments `Approved`, automation removes human assignees, assigns itself or the merge owner, merges to `dev`, cleans workspaces/worktrees/branches, pushes to `dev`, and ensures the dev/preproduction environment contains the code.
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
- Sync human-readable task/evidence summaries, validation results, AC coverage, documentation impact, blockers, reopen history, status-transition rationale, and final handoffs to linked ClickUp task/subtask comments or fields.
|
|
15
15
|
- Keep raw logs in evidence storage; ClickUp receives concise summaries, paths/links, or relevant excerpts only, never wholesale raw logs.
|
|
16
16
|
- WPM owns `Story Points` during `plan`, re-estimation on material plan changes, `agent_metadata`, `Definition` plan-contract linking, and parent approval routing after validation.
|
|
17
|
-
- Human role registry: resolve `CTO` and `PO` from
|
|
17
|
+
- Human role registry: resolve `CTO` and `PO` from available human role context/configured ClickUp IDs. Missing repo-local human registry files are internal routing detail; do not mention internal role-resolution details in ClickUp comments unless asked for routing diagnostics.
|
|
18
18
|
- Human approval assignment is prohibited except for parent `plan` questions with clear ClickUp comments, true `in progress` blockers from missing credentials/tools/access/authenticated browser or Agent Jake/live third-party access after local/subagent attempts, or parent `validation` after `optima_github_verify_vercel_pr` returns `ready: true` with a functional Vercel URL. True external `in progress` blocker escalation means a concrete castellano help request, ClickUp assignment to CTO/PO, and Product Manager removal; never use it for generic handoff, cleanup, subtasks, phase stops, failed Vercel checks, or missing preview URLs.
|
|
19
19
|
- Validator/QA may merge validated subtask PRs into the parent branch/workspace without `CTO`/`PO` assignment or approval.
|
|
20
20
|
- Parent merge authority uses the validation allowlist only after a ready Vercel PR deployment gate: after a human comments `Approved`, automation removes human assignees, assigns merge owner/self, merges to `dev`, cleans workspaces/worktrees/branches, pushes, and ensures dev/preproduction receives the code.
|
package/docs/core/task_model.md
CHANGED
|
@@ -11,7 +11,8 @@
|
|
|
11
11
|
- Delivery task types: `Tarea`, `Bug`, `Doc`, `PoC`.
|
|
12
12
|
- Ignored task types: `Idea`, legacy `Backlog` alias, `Hito`, `Nota de reunión`, `Respuesta del formulario` unless converted or linked to delivery work; `Idea` is non-delivery.
|
|
13
13
|
- `product_manager` may pre-estimate "a qué huele" small/medium/large plus rough story points, but development requests must be converted to routed ClickUp work.
|
|
14
|
-
- Human role registry: resolve `CTO` and `PO` from
|
|
14
|
+
- Human role registry: resolve `CTO` and `PO` from available human role context and configured ClickUp IDs. Missing repo-local human registry files are an internal routing detail, not a task status; do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics. Use role identifiers in workflow text and automation config.
|
|
15
|
+
- Final task handoffs must use `optima_finish` when available: the model supplies structured ClickUp text and intended final state, while Optima applies status, comments, and assignment policy.
|
|
15
16
|
- Status-to-action mapping: `backlog` -> `ignore`, `plan` -> `plan`, `in progress` -> `execute`, `validation` -> `validate`, `merge` -> `merge`, `completed`/`Closed` -> `ignore` unless reopened. `plan` does not imply generic human approval assignment; `merge` is parent-only post-approval automation, while subtasks merge after successful Validator/QA validation without waiting for a human approval status.
|
|
16
17
|
- Branch-safe type slugs are lowercase ASCII: `tarea`, `bug`, `doc`, `poc`.
|
|
17
18
|
|
|
@@ -19,7 +20,7 @@
|
|
|
19
20
|
|
|
20
21
|
- Agents must not assign ClickUp tasks to `CTO` or `PO` except for the explicit cases below; generic handoff, routine validation, duplicate-assignee cleanup, or incomplete phase handoff are prohibited.
|
|
21
22
|
- **Parent planning questions:** only a parent task in `plan` may assign `CTO`/`PO`, and only after clear, concrete questions have been posted in ClickUp comments. Subtasks are planned and executed end-to-end without CTO/PO planning assignment.
|
|
22
|
-
- **Real in-progress blocker:** a task in `in progress` may assign/escalate to `CTO`/`PO` only when blocked by missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access after local/subagent attempts are exhausted. Escalation means
|
|
23
|
+
- **Real in-progress blocker:** a task in `in progress` may assign/escalate to `CTO`/`PO` only when blocked by missing credentials, permissions, authenticated browser/Agent Jake access, external tools, or live third-party access after local/subagent attempts are exhausted. Escalation means calling `optima_finish` with a concrete ClickUp help request in castellano explaining exactly what is needed; Optima assigns CTO/PO and removes the Product Manager assignee so watchdogs stop re-queueing PM until a human replies/reassigns. Agents must not stop at informal phase boundaries such as "I reached phase 1"; phases should have been subtasks, otherwise finish the accepted task.
|
|
23
24
|
- **Parent validation approval:** only a parent task in `validation` may assign `CTO`/`PO` for final validation, and only after `optima_github_verify_vercel_pr` returns `ready: true` for the current parent PR with a functional Vercel preproduction/preview URL. After a human comments `Approved`, automation reassigns to itself or the merge owner, removes human assignees, merges, cleans workspaces/worktrees/branches, pushes to `dev`, and ensures the dev/preproduction environment contains the code.
|
|
24
25
|
|
|
25
26
|
## Routing Rules
|
|
@@ -6,8 +6,9 @@
|
|
|
6
6
|
- Slices: `foundation`, `core`, `logic`, `ui`, `polish`, `qa`, `docs`.
|
|
7
7
|
- ClickUp-first delivery types: `Tarea`, `Bug`, `Doc`, `PoC`; ignored types: `Idea`, legacy `Backlog` alias, `Hito`, `Nota de reunión`, `Respuesta del formulario` unless converted/linked.
|
|
8
8
|
- Product Manager without workflow never develops; it may pre-estimate "a qué huele" small/medium/large plus rough story points and route development into ClickUp tasks.
|
|
9
|
-
- Human role registry: resolve `CTO` and `PO` from
|
|
10
|
-
-
|
|
9
|
+
- Human role registry: resolve `CTO` and `PO` from available human role context/configured ClickUp IDs. Missing repo-local human registry files are internal routing detail; do not mention internal role-resolution details in ClickUp comments unless asked for routing diagnostics.
|
|
10
|
+
- Final task handoffs must use `optima_finish` when available; Optima applies final status, comment, and assignments.
|
|
11
|
+
- ClickUp-first actions: `backlog` ignore, `plan` plan with `Story Points`, `Definition`, and test strategy; assign `CTO`/`PO` only for parent planning questions with clear ClickUp comments, real `in progress` blockers caused by missing credentials/tools/access/authenticated browser or Agent Jake/live third-party access after local/subagent attempts, or parent `validation` after `optima_github_verify_vercel_pr` returns `ready: true` with a functional Vercel URL. For true external `in progress` blockers, call `optima_finish` with a concrete castellano ClickUp help request explaining exactly what is needed; Optima assigns CTO/PO and removes Product Manager so PM watchdogs stop looping until a human replies/reassigns. Subtasks execute end-to-end and merge to the parent branch after Validator/QA passes without CTO/PO approval; parent `Approved` comments trigger automation to remove humans, assign merge owner/self, merge to `dev`, clean workspaces/worktrees/branches, push, and ensure dev/preproduction receives the code; `completed`/`Closed` ignore unless reopened.
|
|
11
12
|
- Routing: keep `tiny` to one slice and usually one specialist; keep `standard` bounded; decompose `complex` into slice-based subtasks.
|
|
12
13
|
- `complex + implementation` normally uses `workflow_runner` in full mode.
|
|
13
14
|
- WPM stores `agent_metadata`, re-estimates `Story Points` on material plan changes, and keeps `Definition` plan contract separate from final Documentation.
|
|
@@ -18,7 +18,7 @@ We adhere to a strict test pyramid strategy to ensure 100% reliability.
|
|
|
18
18
|
- **Planning Participation:** Validator/QA participates during `plan` for test strategy, required new coverage, Playwright needs, regression scope, and documentation-validation expectations.
|
|
19
19
|
- **Regression:** A full regression suite must be run by the Developer before handing over for technical review.
|
|
20
20
|
- **Split Validation:** Tech Lead reviews architecture, code, PR readiness, standards, and repo-skill use; Validator/QA verifies tests, Playwright flows, regression, required coverage, evidence, and final documentation freshness.
|
|
21
|
-
- **Human Role Registry:** Resolve `CTO` and `PO` from
|
|
21
|
+
- **Human Role Registry:** Resolve `CTO` and `PO` from available human role context and configured ClickUp IDs. Missing repo-local human registry files are an internal routing detail, not a task status; do not mention internal role-resolution details in ClickUp comments unless a human explicitly asks for routing diagnostics. Use role identifiers in workflow text and automation config.
|
|
22
22
|
- **Human Approval Allowlist:** Assign `CTO`/`PO` only for parent `plan` questions with clear ClickUp comments, real `in progress` blockers caused by missing credentials/permissions/tools/access/authenticated browser or Agent Jake/live third-party access after local/subagent attempts, or parent `validation` after `optima_github_verify_vercel_pr` returns `ready: true` with a functional Vercel URL. For true external `in progress` blockers, post the concrete help request in castellano, assign CTO/PO in ClickUp, and remove Product Manager. Never assign them for generic handoff, routine validation, cleanup, subtasks, partial-phase stops, failed Vercel checks, or missing preview URLs.
|
|
23
23
|
- **Merge Execution Gate:** Validator/QA may merge validated subtask PRs into the parent branch/workspace without human approval. Parent PRs to `dev` require Tech Lead and Validator/QA pass plus the parent-validation allowlist; after a human comments `Approved`, automation removes human assignees, assigns itself or the merge owner, merges, cleans workspaces/worktrees/branches, pushes to `dev`, and ensures the dev environment contains the code. Any conflicted or failed merge returns the affected task/subtask to `in progress` for the coding owner.
|
|
24
24
|
- **Documentation Gate:** Validator/QA must fail validation when final documentation is missing or outdated; `Definition` is only the plan contract, not the delivered documentation.
|