task description auto

This commit is contained in:
Ian Gulliver
2026-10-20 08:57:37 -07:00
parent 8f3226350e
commit d530ec5edc
20 changed files with 434 additions and 342 deletions
+7 -3
View File
@@ -101,9 +101,13 @@ func (m *Manager) takeBounce(ctx context.Context, l *live, final string) (bool,
func (m *Manager) taskGuidance(ctx context.Context, task api.Task) (string, error) {
g := guidance + fmt.Sprintf("\n- This task's ports are %d to %d; $PORT holds the first. Run dev servers and anything else that listens on these, so parallel tasks don't collide, and listen on 127.0.0.1. To show the human a running server, call byre's expose_port tool."+
"\n- This worktree starts with only what git tracks. Before other work in a new worktree, do any setup the project's AGENTS.md describes."+
"\n- This task's title is %q. Whoever created the task wrote it, and it may be the only statement of what they want.",
task.PortBase, task.PortBase+store.PortBlock-1, task.Title)
"\n- This worktree starts with only what git tracks. Before other work in a new worktree, do any setup the project's AGENTS.md describes.",
task.PortBase, task.PortBase+store.PortBlock-1)
if task.Title == "" {
g += "\n- This task has no title yet. First thing, before any other work, call set_task_title with a very short, distinct, to-the-point title (two to four words), and call it again whenever the work moves on."
} else {
g += fmt.Sprintf("\n- This task's title is %q. First thing, if it isn't very short (two to four words), distinct and to the point, call set_task_title with one that is, and call it again whenever the work moves on.", task.Title)
}
if task.TodoItem != nil {
g += fmt.Sprintf("\n- This task was started from the item %q in %s at the repo root. When the work is done, remove that item from %s in this worktree, so the removal lands in the same merge as the work.",
*task.TodoItem, todo.File, todo.File)
+1 -1
View File
@@ -742,7 +742,7 @@ func (m *Manager) startLive(ctx context.Context, sess api.AgentSession, task api
if err != nil {
return nil, err
}
tools := append([]mcp.Tool{m.askTool(l), m.cancelQuestionTool(l), m.setMergeTitleTool(l), m.stopMergeTool(l), m.mergeToMainTool(l), m.setTaskSummaryTool(l), m.searchClosedTool(l), m.exposePortTool(l), m.takeSnapshotTool(l), m.terminalReadTool(l), m.terminalTypeTool(l), m.bashTool(l), m.readKnowledgeTool()}, append(m.subtaskTools(l), m.clientTools(l)...)...)
tools := append([]mcp.Tool{m.askTool(l), m.cancelQuestionTool(l), m.setTaskTitleTool(l), m.setMergeTitleTool(l), m.stopMergeTool(l), m.mergeToMainTool(l), m.setTaskSummaryTool(l), m.searchClosedTool(l), m.exposePortTool(l), m.takeSnapshotTool(l), m.terminalReadTool(l), m.terminalTypeTool(l), m.bashTool(l), m.readKnowledgeTool()}, append(m.subtaskTools(l), m.clientTools(l)...)...)
lead := true
if sess.Role == api.Implementer {
g += longTitleGuidance(task)
+35
View File
@@ -638,6 +638,41 @@ func (m *Manager) setMergeTitle(ctx context.Context, l *live, raw json.RawMessag
return fmt.Sprintf("Merge commit title set to %q.", title), nil
}
func (m *Manager) setTaskTitleTool(l *live) mcp.Tool {
return mcp.Tool{
Name: "set_task_title",
Description: "Set this task's title, which names it in byre's task list and switcher. " +
"Keep it very short (two to four words), distinct from the project's other tasks, and to the point, for example \"webhook retries\". " +
"Until set_merge_title is called, the merge commit title follows it. It replaces any earlier title.",
InputSchema: json.RawMessage(`{
"type": "object",
"properties": {
"title": {"type": "string", "description": "One short line."}
},
"required": ["title"]
}`),
Handler: func(ctx context.Context, raw json.RawMessage) (string, error) {
args := setMergeTitleArgs{}
err := json.Unmarshal(raw, &args)
if err != nil {
return "", fmt.Errorf("malformed set_task_title call: %w", err)
}
title := strings.TrimSpace(args.Title)
if title == "" || strings.ContainsAny(title, "\r\n") {
return "", fmt.Errorf("%w: title must be one non-empty line", ErrInvalid)
}
err = m.store.SetTitle(ctx, l.taskID, title, agentActor)
if errors.Is(err, store.ErrNotFound) {
return "", fmt.Errorf("%w: this task is closed or merging", ErrConflict)
}
if err != nil {
return "", err
}
return fmt.Sprintf("Task title set to %q.", title), nil
},
}
}
type stopMergeArgs struct {
Reason string `json:"reason"`
}