mirror of
https://github.com/multica-ai/multica.git
synced 2026-07-05 13:29:44 +02:00
fix(squad): trim stall guidance prompts
Co-authored-by: multica-agent <github@multica.ai>
This commit is contained in:
@@ -611,7 +611,7 @@ func buildMetaSkillContent(provider string, ctx TaskContextForEnv) string {
|
||||
b.WriteString("7. **If you reply, post it as a comment — this step is mandatory when you reply.** Text in your terminal or run logs is NOT delivered to the user. ")
|
||||
b.WriteString(BuildCommentReplyInstructions(provider, ctx.IssueID, ctx.TriggerCommentID))
|
||||
b.WriteString("8. Before exiting: only if this run produced a fact that clears the high bar (important AND likely to be re-read by future runs on this same issue, e.g. a new PR URL or deploy URL), or you noticed a metadata key from entry that is now stale, pin or clear it via `multica issue metadata set`/`delete`. Most runs write nothing here — that is the expected outcome, not a gap. When in doubt, do not write. See the `## Issue Metadata` section above for the full bar.\n")
|
||||
fmt.Fprintf(&b, "9. Do NOT change the issue status unless the comment explicitly asks for it — with one exception: if you did real work this turn and are stopping with the task NOT finished (you are blocked, waiting on someone, or only completed a partial/interim step and cannot continue right now), run `multica issue status %s blocked` and pin `blocked_reason` (and `waiting_on` when you are waiting on a specific person or event). Once your task ends nothing continues automatically, so an \"I'll continue later\" comment alone leaves the issue looking like it is still progressing when no session is running. Skip the status change only if your Agent Identity forbids issue status changes — then make the blocker explicit in your comment.\n\n", ctx.IssueID)
|
||||
fmt.Fprintf(&b, "9. Do NOT change the issue status unless the comment explicitly asks for it — except when you did real work and must stop before the task is finished. In that case, run `multica issue status %s blocked`, pin `blocked_reason` and `waiting_on` when relevant, and explain the blocker in your reply. Skip this only if your Agent Identity forbids status changes.\n\n", ctx.IssueID)
|
||||
} else {
|
||||
// Assignment-triggered: defer to agent Skills for workflow specifics.
|
||||
b.WriteString("You are responsible for managing the issue status throughout your work, unless your Agent Identity forbids issue status changes.\n\n")
|
||||
@@ -627,7 +627,7 @@ func buildMetaSkillContent(provider string, ctx TaskContextForEnv) string {
|
||||
}
|
||||
b.WriteString("7. Before exiting: only if this run produced a fact that clears the high bar (important AND likely to be re-read by future runs on this same issue, e.g. a new PR URL or deploy URL), or you noticed a metadata key from entry that is now stale, pin or clear it via `multica issue metadata set`/`delete`. Most runs write nothing here — that is the expected outcome, not a gap. When in doubt, do not write. See the `## Issue Metadata` section above for the full bar.\n")
|
||||
fmt.Fprintf(&b, "8. When done, run `multica issue status %s in_review` unless your Agent Identity forbids issue status changes; if it does, skip this step.\n", ctx.IssueID)
|
||||
fmt.Fprintf(&b, "9. If blocked, run `multica issue status %s blocked` unless your Agent Identity forbids issue status changes. The same applies when you stop with the task unfinished and nothing will continue it automatically — you only finished an interim/partial step, or you are waiting on input: treat that as blocked, set the status, and pin `blocked_reason` (and `waiting_on` when you are waiting on a specific person or event). Leaving the issue in `in_progress`/`in_review` while no session is running makes it look like work is still happening when it has actually stopped. Post a comment explaining the blocker unless your Agent Identity forbids issue comments.\n\n", ctx.IssueID)
|
||||
fmt.Fprintf(&b, "9. If blocked, or if you must stop with unfinished work and no automatic continuation, run `multica issue status %s blocked` unless your Agent Identity forbids status changes. Pin `blocked_reason` and `waiting_on` when relevant, and post a comment explaining the blocker unless issue comments are forbidden.\n\n", ctx.IssueID)
|
||||
}
|
||||
|
||||
// Sub-issue creation semantics — the only piece of the old Parent /
|
||||
|
||||
@@ -172,7 +172,7 @@ func TestBriefCarriesBlockedOnStallGuidance(t *testing.T) {
|
||||
})
|
||||
for _, want := range []string{
|
||||
"Do NOT change the issue status unless the comment explicitly asks for it",
|
||||
"stopping with the task NOT finished",
|
||||
"must stop before the task is finished",
|
||||
"multica issue status " + issueID + " blocked",
|
||||
"blocked_reason",
|
||||
} {
|
||||
@@ -185,8 +185,8 @@ func TestBriefCarriesBlockedOnStallGuidance(t *testing.T) {
|
||||
// task unfinished and nothing continuing automatically.
|
||||
assignment := buildMetaSkillContent("claude", TaskContextForEnv{IssueID: issueID})
|
||||
for _, want := range []string{
|
||||
"If blocked, run `multica issue status " + issueID + " blocked`",
|
||||
"The same applies when you stop with the task unfinished",
|
||||
"run `multica issue status " + issueID + " blocked`",
|
||||
"must stop with unfinished work",
|
||||
"blocked_reason",
|
||||
} {
|
||||
if !strings.Contains(assignment, want) {
|
||||
@@ -314,7 +314,8 @@ func TestAssignmentTriggeredProtocolHonorsAgentIdentity(t *testing.T) {
|
||||
"Complete the task within your Agent Identity boundaries.",
|
||||
"Do not investigate, implement, create issues, update issues, or delegate if your Agent Identity forbids that action",
|
||||
"When done, run `multica issue status " + issueID + " in_review` unless your Agent Identity forbids issue status changes; if it does, skip this step.",
|
||||
"If blocked, run `multica issue status " + issueID + " blocked` unless your Agent Identity forbids issue status changes.",
|
||||
"If blocked, or if you must stop with unfinished work and no automatic continuation",
|
||||
"run `multica issue status " + issueID + " blocked` unless your Agent Identity forbids status changes.",
|
||||
} {
|
||||
if !strings.Contains(out, want) {
|
||||
t.Errorf("assignment-triggered brief missing identity-bound workflow text %q\n---\n%s", want, out)
|
||||
|
||||
@@ -55,18 +55,11 @@ Your responsibilities, in order:
|
||||
- a delegated member posts an update or asks you a question;
|
||||
- a delegated member finishes and the issue moves forward;
|
||||
- someone @mentions you again on this issue.
|
||||
5. **Re-evaluate on each trigger.** When you wake up again, read the new
|
||||
activity and decide whether to delegate the next step, escalate to
|
||||
the human reporter, or close the loop. Before you settle on
|
||||
` + "`" + `no_action` + "`" + `, consult the **Current Execution State** snapshot
|
||||
below: a delegated agent's task ends the moment it stops producing
|
||||
output, so an interim "I'll continue later" report does NOT mean a
|
||||
session is still running. If no worker session is active and the issue
|
||||
is not actually done, the work has stalled — delegate the next step,
|
||||
mark the issue ` + "`" + `blocked` + "`" + `, or escalate to a human rather than
|
||||
silently recording ` + "`" + `no_action` + "`" + `. Record ` + "`" + `no_action` + "`" + ` and exit
|
||||
silently only when no action genuinely is needed (e.g. a worker is
|
||||
still running, or a member posted an update that requires no response).
|
||||
5. **Re-evaluate on each trigger.** Read the new activity and the
|
||||
**Current Execution State** snapshot. If no worker task is active and
|
||||
the issue is not done, delegate the next step, mark ` + "`" + `blocked` + "`" + `, or
|
||||
escalate; do not silently record ` + "`" + `no_action` + "`" + `. Use ` + "`" + `no_action` + "`" + `
|
||||
only when no follow-up is needed.
|
||||
|
||||
Hard rules:
|
||||
- EVERY delegation MUST use the full mention markdown syntax
|
||||
@@ -170,12 +163,11 @@ func buildSquadExecutionState(ctx context.Context, q *db.Queries, issueID pgtype
|
||||
|
||||
if len(workers) == 0 {
|
||||
sb.WriteString("**No worker task is currently active on this issue.** ")
|
||||
sb.WriteString("No delegated agent has an active queued, waiting, or running task right now. A worker's task ends the moment it stops producing output, so a recent comment that reads like work is still in progress (\"I'll continue later\", \"still verifying\", a partial/interim report) does NOT mean anything is active — nothing resumes automatically. ")
|
||||
sb.WriteString("Before you record `no_action`, confirm the issue is genuinely done or genuinely waiting on a human. If work remains, delegate the next step, or mark the issue `blocked` and escalate. An interim report with no active session is a stalled issue, not a progressing one.\n")
|
||||
sb.WriteString("Nothing will continue automatically unless you delegate a new step. Before `no_action`, confirm the issue is done or waiting on a human; otherwise delegate, mark `blocked`, or escalate.\n")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
fmt.Fprintf(&sb, "**%d worker task(s) currently active on this issue.** A delegated agent has queued, waiting, or running work:\n", len(workers))
|
||||
fmt.Fprintf(&sb, "**%d worker task(s) currently active on this issue:**\n", len(workers))
|
||||
for _, t := range workers {
|
||||
name := "a squad member"
|
||||
if ag, err := q.GetAgent(ctx, t.AgentID); err == nil {
|
||||
@@ -183,7 +175,7 @@ func buildSquadExecutionState(ctx context.Context, q *db.Queries, issueID pgtype
|
||||
}
|
||||
fmt.Fprintf(&sb, "- %s — status `%s`\n", name, t.Status)
|
||||
}
|
||||
sb.WriteString("\nYou usually do NOT need to delegate the same work again while a worker task is in flight — recording `no_action` and waiting for it to finish is appropriate. Re-delegate only if the active work is clearly wrong or stuck, or hand off a genuinely independent next step.\n")
|
||||
sb.WriteString("\nUsually wait for active worker tasks to finish. Re-delegate only if the active work is wrong/stuck or you have an independent next step.\n")
|
||||
return sb.String()
|
||||
}
|
||||
|
||||
|
||||
@@ -431,7 +431,7 @@ func TestBuildSquadLeaderBriefing_ExecutionState(t *testing.T) {
|
||||
insertActiveTask(t, worker, issueID, false)
|
||||
out = buildSquadLeaderBriefing(ctx, testHandler.Queries, squad, issueID)
|
||||
for _, want := range []string{
|
||||
"worker task(s) currently active on this issue.",
|
||||
"worker task(s) currently active on this issue:",
|
||||
"Exec Worker",
|
||||
"status `running`",
|
||||
} {
|
||||
|
||||
Reference in New Issue
Block a user