fix(team): notify lead on task create with startImmediately

Extract sendUserTaskStartNotification as reusable private method.
When a task is created via UI directly in "In Progress" column
(startImmediately=true), the controller's maybeNotifyAssignedOwner
skips the lead. Now createTask sends the notification to the lead
with full description, prompt, and task_get instructions.
This commit is contained in:
iliya 2026-03-25 15:03:44 +02:00
parent 58f3ccd4b4
commit bd90de8e81

View file

@ -877,6 +877,19 @@ export class TeamDataService {
...(shouldStart ? { startImmediately: true } : {}),
}) as TeamTask;
// Controller's maybeNotifyAssignedOwner skips the lead (owner === lead).
// For user-created tasks with startImmediately, ensure the lead also gets notified.
if (shouldStart) {
try {
const leadName = await this.resolveLeadName(teamName);
if (this.isLeadOwner(task.owner!, leadName)) {
await this.sendUserTaskStartNotification(teamName, task);
}
} catch {
/* best-effort */
}
}
return task;
}
@ -945,44 +958,52 @@ export class TeamDataService {
this.getController(teamName).tasks.startTask(taskId, 'user');
if (task.owner) {
try {
const parts = [
`**start working on task now** ${this.getTaskLabel(task)} "${task.subject}"`,
];
if (task.description?.trim()) {
parts.push(`\nDetails:\n${task.description.trim()}`);
}
if (task.prompt?.trim()) {
parts.push(`\nInstructions:\n${task.prompt.trim()}`);
}
parts.push(
'',
wrapAgentBlock(
[
`Begin work on this task immediately. Keep it moving until it is completed or clearly blocked. Do not leave it idle.`,
`To fetch the full task context (description, comments, attachments) use:`,
`task_get { teamName: "${teamName}", taskId: "${task.id}" }`,
`When done, update task status:`,
`task_complete { teamName: "${teamName}", taskId: "${task.id}" }`,
].join('\n')
)
);
await this.sendMessage(teamName, {
member: task.owner,
from: 'user',
text: parts.join('\n'),
taskRefs: task.descriptionTaskRefs,
summary: `Start working on ${this.getTaskLabel(task)}`,
source: 'system_notification',
});
} catch {
// Best-effort notification
}
await this.sendUserTaskStartNotification(teamName, task);
}
return { notifiedOwner: !!task.owner };
}
/**
* Send a task start notification from the user to the task owner.
* Includes description, prompt, and task_get/task_complete instructions.
* Used by startTaskByUser and createTask (startImmediately).
*/
private async sendUserTaskStartNotification(teamName: string, task: TeamTask): Promise<void> {
if (!task.owner) return;
try {
const parts = [`**start working on task now** ${this.getTaskLabel(task)} "${task.subject}"`];
if (task.description?.trim()) {
parts.push(`\nDetails:\n${task.description.trim()}`);
}
if (task.prompt?.trim()) {
parts.push(`\nInstructions:\n${task.prompt.trim()}`);
}
parts.push(
'',
wrapAgentBlock(
[
`Begin work on this task immediately. Keep it moving until it is completed or clearly blocked. Do not leave it idle.`,
`To fetch the full task context (description, comments, attachments) use:`,
`task_get { teamName: "${teamName}", taskId: "${task.id}" }`,
`When done, update task status:`,
`task_complete { teamName: "${teamName}", taskId: "${task.id}" }`,
].join('\n')
)
);
await this.sendMessage(teamName, {
member: task.owner,
from: 'user',
text: parts.join('\n'),
taskRefs: task.descriptionTaskRefs,
summary: `Start working on ${this.getTaskLabel(task)}`,
source: 'system_notification',
});
} catch {
// Best-effort notification
}
}
async updateTaskStatus(
teamName: string,
taskId: string,