@yemi33/minions 0.1.1998 → 0.1.2000
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/dashboard/js/qa.js +509 -24
- package/dashboard/js/render-prs.js +23 -1
- package/dashboard/js/render-work-items.js +11 -1
- package/dashboard/pages/qa.html +53 -6
- package/dashboard/styles.css +149 -0
- package/dashboard.js +99 -1
- package/docs/completion-reports.md +33 -0
- package/docs/pr-comment-followup.md +206 -0
- package/engine/lifecycle.js +80 -0
- package/package.json +1 -1
- package/playbooks/fix.md +16 -1
- package/playbooks/review.md +14 -0
- package/playbooks/shared-rules.md +21 -0
- package/playbooks/templates/followup-dispatch.md +157 -0
package/engine/lifecycle.js
CHANGED
|
@@ -3360,6 +3360,74 @@ function extractDecompositionJson(stdout, runtimeName) {
|
|
|
3360
3360
|
return null;
|
|
3361
3361
|
}
|
|
3362
3362
|
|
|
3363
|
+
/**
|
|
3364
|
+
* PR follow-up audit (W-mpej3cox00099466).
|
|
3365
|
+
*
|
|
3366
|
+
* Parses the optional `followups` array on the agent's completion report,
|
|
3367
|
+
* logs each entry at `info` so operators can trace fan-out, and warns when
|
|
3368
|
+
* a claimed `wi_id` doesn't match any record in central or per-project
|
|
3369
|
+
* work-items.json. The mismatch warning catches dispatches that were reverted
|
|
3370
|
+
* (HTTP 409 from /api/work-items dedup), fingerprinted away by the standard
|
|
3371
|
+
* dedup window, or otherwise didn't actually land — situations where the
|
|
3372
|
+
* agent claimed a follow-up exists but the dashboard/engine has no record.
|
|
3373
|
+
*
|
|
3374
|
+
* Returns the array of well-formed followup entries; malformed entries (non-
|
|
3375
|
+
* object, missing `wi_id`) are logged and skipped. Failures inside the
|
|
3376
|
+
* existence check are non-fatal — they degrade to a warn.
|
|
3377
|
+
*/
|
|
3378
|
+
function processCompletionFollowups(completion, agentId, dispatchItem, config) {
|
|
3379
|
+
if (!completion || typeof completion !== 'object') return [];
|
|
3380
|
+
const raw = completion.followups;
|
|
3381
|
+
if (raw === undefined || raw === null) return [];
|
|
3382
|
+
if (!Array.isArray(raw)) {
|
|
3383
|
+
log('warn', `Followup audit: completion.followups must be an array; got ${typeof raw}`);
|
|
3384
|
+
return [];
|
|
3385
|
+
}
|
|
3386
|
+
if (raw.length === 0) return [];
|
|
3387
|
+
const wiId = dispatchItem?.meta?.item?.id || 'N/A';
|
|
3388
|
+
let existingIds = null;
|
|
3389
|
+
function loadExistingIds() {
|
|
3390
|
+
if (existingIds !== null) return existingIds;
|
|
3391
|
+
try {
|
|
3392
|
+
existingIds = new Set(queries.getWorkItems(config).map(w => w && w.id).filter(Boolean));
|
|
3393
|
+
} catch (err) {
|
|
3394
|
+
log('warn', `Followup audit: getWorkItems failed (${err.message}); skipping existence checks`);
|
|
3395
|
+
existingIds = new Set();
|
|
3396
|
+
}
|
|
3397
|
+
return existingIds;
|
|
3398
|
+
}
|
|
3399
|
+
const accepted = [];
|
|
3400
|
+
for (const entry of raw) {
|
|
3401
|
+
if (!entry || typeof entry !== 'object') {
|
|
3402
|
+
log('warn', `Followup audit (${agentId || 'unknown'} wi=${wiId}): skipping malformed entry (not an object)`);
|
|
3403
|
+
continue;
|
|
3404
|
+
}
|
|
3405
|
+
const followupWiId = typeof entry.wi_id === 'string' ? entry.wi_id.trim()
|
|
3406
|
+
: (typeof entry.wiId === 'string' ? entry.wiId.trim() : '');
|
|
3407
|
+
if (!followupWiId) {
|
|
3408
|
+
log('warn', `Followup audit (${agentId || 'unknown'} wi=${wiId}): skipping entry without wi_id`);
|
|
3409
|
+
continue;
|
|
3410
|
+
}
|
|
3411
|
+
const title = typeof entry.title === 'string' ? entry.title.trim() : '';
|
|
3412
|
+
const reason = typeof entry.reason === 'string' ? entry.reason.trim() : '';
|
|
3413
|
+
const parentCommentId = typeof entry.parent_comment_id === 'string'
|
|
3414
|
+
? entry.parent_comment_id.trim()
|
|
3415
|
+
: (typeof entry.parentCommentId === 'string' ? entry.parentCommentId.trim() : '');
|
|
3416
|
+
log('info', `Followup audit (${agentId || 'unknown'} wi=${wiId}): dispatched ${followupWiId}${title ? ` — ${title}` : ''}${parentCommentId ? ` (comment=${parentCommentId})` : ''}${reason ? ` — ${reason}` : ''}`);
|
|
3417
|
+
const allIds = loadExistingIds();
|
|
3418
|
+
if (allIds.size > 0 && !allIds.has(followupWiId)) {
|
|
3419
|
+
log('warn', `Followup audit (${agentId || 'unknown'} wi=${wiId}): claimed followup ${followupWiId} not found in any work-items.json — dispatch may have been deduped, reverted, or never landed`);
|
|
3420
|
+
}
|
|
3421
|
+
accepted.push({
|
|
3422
|
+
wi_id: followupWiId,
|
|
3423
|
+
title,
|
|
3424
|
+
reason,
|
|
3425
|
+
parent_comment_id: parentCommentId,
|
|
3426
|
+
});
|
|
3427
|
+
}
|
|
3428
|
+
return accepted;
|
|
3429
|
+
}
|
|
3430
|
+
|
|
3363
3431
|
/**
|
|
3364
3432
|
* Handle decomposition result — parse sub-items from agent output and create child work items.
|
|
3365
3433
|
* Called from runPostCompletionHooks when type === 'decompose'.
|
|
@@ -3538,6 +3606,17 @@ async function runPostCompletionHooks(dispatchItem, agentId, code, stdout, confi
|
|
|
3538
3606
|
if (structuredCompletion.summary) resultSummary = String(structuredCompletion.summary);
|
|
3539
3607
|
log('info', `Structured completion from ${agentId}: status=${structuredCompletion.status}, pr=${structuredCompletion.pr || 'N/A'}${structuredCompletion._source ? ` (${structuredCompletion._source})` : ''}`);
|
|
3540
3608
|
}
|
|
3609
|
+
// PR follow-up audit (W-mpej3cox00099466) — when the agent declares
|
|
3610
|
+
// `followups: [{wi_id, title, reason, parent_comment_id}]` in its completion
|
|
3611
|
+
// report, log each entry and verify the claimed WI ids actually landed in
|
|
3612
|
+
// some project's work-items.json. A mismatch (claimed wi_id with no matching
|
|
3613
|
+
// record) is logged at warn so operators can spot dispatches that were
|
|
3614
|
+
// reverted, fingerprinted-deduped, or otherwise didn't take.
|
|
3615
|
+
if (structuredCompletion) {
|
|
3616
|
+
try {
|
|
3617
|
+
processCompletionFollowups(structuredCompletion, agentId, dispatchItem, config);
|
|
3618
|
+
} catch (err) { log('warn', `Followup audit: ${err.message}`); }
|
|
3619
|
+
}
|
|
3541
3620
|
// F5 (W-mpeklod3000we69c): if the agent flagged an injection attempt in the
|
|
3542
3621
|
// structured completion, force the dispatch into a non-retryable failure
|
|
3543
3622
|
// with `FAILURE_CLASS.INJECTION_FLAGGED`. Inbox note + WI stamp are written
|
|
@@ -4303,4 +4382,5 @@ module.exports = {
|
|
|
4303
4382
|
isPrAttachmentRequired,
|
|
4304
4383
|
extractDecompositionJson,
|
|
4305
4384
|
handleDecompositionResult,
|
|
4385
|
+
processCompletionFollowups,
|
|
4306
4386
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2000",
|
|
4
4
|
"description": "Multi-agent AI dev team that runs from ~/.minions/ — five autonomous agents share a single engine, dashboard, and knowledge base",
|
|
5
5
|
"bin": {
|
|
6
6
|
"minions": "bin/minions.js"
|
package/playbooks/fix.md
CHANGED
|
@@ -35,6 +35,7 @@ Before editing, split the feedback into:
|
|
|
35
35
|
|
|
36
36
|
- **Blocking findings to fix:** verified correctness, safety, build/test failure, missing requested behavior, broken compatibility, or approval-blocking comments whose claim is valid on the current branch.
|
|
37
37
|
- **Findings to answer with rationale:** comments where the current approach is intentionally correct, the reviewer misunderstood the code, the issue is stale/already addressed, or the requested change would broaden the PR beyond its purpose.
|
|
38
|
+
- **Out-of-scope but legitimate follow-up requests:** asks for genuinely useful work that does **not** belong in this PR (a separate bug, a related-but-distinct feature, a refactor the reviewer explicitly said to "track separately"). Spin off a new Minions work item — see `## Follow-up Dispatch` below — and reply on the originating thread with the new WI id. This is a third option alongside "fix it" and "rebut it"; it does **not** loosen the don't-broaden-the-PR rule for in-PR work.
|
|
38
39
|
- **Non-blocking suggestions:** style, optional refactors, extra docs, or enhancements that are not required for approval. Do not implement these unless they are necessary to resolve a verified blocking issue.
|
|
39
40
|
|
|
40
41
|
## Health Check
|
|
@@ -55,7 +56,7 @@ Handle this like the PR author responding directly from a CLI:
|
|
|
55
56
|
- Fix it if the feedback is valid and improves correctness, safety, maintainability, or test coverage.
|
|
56
57
|
- If the current approach is intentionally correct, stale, already fixed, out of scope, or the requested change would be harmful, reply with specific rationale instead of silently changing code or ignoring the thread.
|
|
57
58
|
- Handle merge conflicts when needed, preserving the PR's intended changes while keeping the branch reviewable.
|
|
58
|
-
- Do not add unrelated cleanups or broaden the PR beyond the review feedback unless that is necessary to make the fix correct.
|
|
59
|
+
- Do not add unrelated cleanups or broaden the PR beyond the review feedback unless that is necessary to make the fix correct. For legitimate-but-out-of-scope asks, see `## Follow-up Dispatch` below — spin off a separate WI instead of broadening this PR.
|
|
59
60
|
|
|
60
61
|
## Validation
|
|
61
62
|
|
|
@@ -94,6 +95,20 @@ After pushing, respond to each review comment/thread:
|
|
|
94
95
|
- **GitHub**: Reply to each review comment, resolve conversations you've fixed
|
|
95
96
|
- **ADO**: Use `az` CLI first to reply to each thread and update status when supported; use ADO MCP only as a fallback when `az` is unavailable or insufficient. Set status to `fixed` or `closed` for fixes; leave `active` for rationale replies
|
|
96
97
|
|
|
98
|
+
## Follow-up Dispatch
|
|
99
|
+
|
|
100
|
+
When a comment asks for legitimate work that is **clearly out of scope** for this PR (separate bug, different feature, refactor the reviewer explicitly asked to "track separately"), spin off a new Minions work item via the dashboard API instead of broadening the PR or silently declining. Read the full contract — decision tree, exact curl shape, required `meta.pr_followup` fields, dedup behavior, and the mandatory comment-thread reply — at:
|
|
101
|
+
|
|
102
|
+
`{{team_root}}/playbooks/templates/followup-dispatch.md`
|
|
103
|
+
|
|
104
|
+
Key rules (full detail in the template):
|
|
105
|
+
|
|
106
|
+
- The follow-up is **additive**. You still fix the in-scope feedback in this PR and post the normal fix comment.
|
|
107
|
+
- Reply on the originating comment thread with the new WI id (e.g. `Tracked as follow-up: W-…`) and resolve that sub-thread.
|
|
108
|
+
- Always include `meta.pr_followup.parent_comment_id` — without it the server cannot dedup retries.
|
|
109
|
+
- Do not pick `agent`; let `routing.md` decide.
|
|
110
|
+
- Record every follow-up you dispatched in the `followups` array of your completion JSON.
|
|
111
|
+
|
|
97
112
|
## When to Stop
|
|
98
113
|
|
|
99
114
|
Your task is complete when each review finding has either been fixed or answered with rationale, the validation story is truthful and sufficient for review, the fix is pushed if code changed, the PR is commented, and addressed threads are resolved. Do NOT continue into unrelated improvements.
|
package/playbooks/review.md
CHANGED
|
@@ -98,6 +98,20 @@ After running the command, confirm it succeeded (check the command output for er
|
|
|
98
98
|
If you encounter merge conflicts (e.g., the PR shows conflicts):
|
|
99
99
|
1. Note the conflict in your review comment. Do NOT attempt to resolve — flag it for the author.
|
|
100
100
|
|
|
101
|
+
## Follow-up Dispatch
|
|
102
|
+
|
|
103
|
+
If, while reviewing, you spot substantial work that should be tracked separately rather than blocking this PR (a related-but-distinct bug, a feature gap that didn't ship in this diff, a refactor that's worth doing later), you may dispatch a follow-up Minions work item instead of pinning it as a blocking finding. Read the full contract — decision tree, exact curl shape, required `meta.pr_followup` fields, dedup behavior, and the mandatory comment-thread reply — at:
|
|
104
|
+
|
|
105
|
+
`{{team_root}}/playbooks/templates/followup-dispatch.md`
|
|
106
|
+
|
|
107
|
+
Key rules (full detail in the template):
|
|
108
|
+
|
|
109
|
+
- Use this for **legitimate out-of-scope follow-ups**, not for findings that should block the PR.
|
|
110
|
+
- The review verdict (`APPROVE` / `REQUEST_CHANGES`) is unchanged by the follow-up — pick the verdict based on the PR's own contents.
|
|
111
|
+
- Reply on the originating thread with the new WI id and resolve that sub-thread (do not leave it open).
|
|
112
|
+
- Always include `meta.pr_followup.parent_comment_id` so the server can dedup if you (or another agent) retries.
|
|
113
|
+
- Record every follow-up you dispatched in the `followups` array of your completion JSON.
|
|
114
|
+
|
|
101
115
|
## Do not run git checkout on the main working tree. Use `git diff` and `git show` only.
|
|
102
116
|
|
|
103
117
|
## When to Stop
|
|
@@ -92,6 +92,27 @@ The engine provides a completion report path in the prompt and in `MINIONS_COMPL
|
|
|
92
92
|
|
|
93
93
|
For the canonical schema — every field, the `failure_class` enum, `noop:true` semantics, `retryable` / `needs_rerun` shape, and the artifacts array — see `docs/completion-reports.md`. The JSON report is the primary signal; fenced `completion` blocks in stdout are accepted only as a fallback.
|
|
94
94
|
|
|
95
|
+
## Minions API access
|
|
96
|
+
|
|
97
|
+
The Minions dashboard runs at `http://localhost:7331` whenever the engine is up. Agents may call its HTTP endpoints when (and only when) the playbook explicitly authorizes it for a particular task — most dispatches do not need any API access, and uninvited writes to engine-managed state are still prohibited (see "Do NOT write to `agents/*/status.json`" above).
|
|
98
|
+
|
|
99
|
+
When a playbook authorizes an API call (e.g. follow-up work-item dispatch from `playbooks/templates/followup-dispatch.md`), use the standard `curl` shape:
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
curl -sS -X POST http://localhost:7331/api/<route> \
|
|
103
|
+
-H 'Content-Type: application/json' \
|
|
104
|
+
-H 'X-Minions-Agent: <your-agent-id>' \
|
|
105
|
+
-H 'X-Minions-Origin-Wi: <current-work-item-id>' \
|
|
106
|
+
-d '<json-payload>'
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Conventions:
|
|
110
|
+
|
|
111
|
+
- The full live route surface is available at `GET http://localhost:7331/api/routes` (the route registry includes method, path, and a one-line description for every handler).
|
|
112
|
+
- **Identification headers (for traceability, not auth).** Set `X-Minions-Agent` to your agent id and `X-Minions-Origin-Wi` to the work-item id you were dispatched against. Endpoints that persist these (e.g. `POST /api/work-items`) store them as `_originAgent` / `_originWi` for the dashboard timeline. Agents do **not** have a `X-CC-Turn-Id` — that header is reserved for Command Center turns.
|
|
113
|
+
- The dashboard binds to `127.0.0.1` only; no auth token is required for localhost calls.
|
|
114
|
+
- Treat HTTP 4xx as a contract violation: surface the response body in your completion summary instead of retrying blindly.
|
|
115
|
+
|
|
95
116
|
## Long-Running Commands
|
|
96
117
|
|
|
97
118
|
Builds, dependency installs, tests, and local servers can be quiet for long periods. Run the repo's normal CLI commands and let them finish; do not add artificial progress output, heartbeat loops, or command-specific workarounds just to keep Minions active.
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Follow-up Dispatch (PR-comment → new WI)
|
|
2
|
+
|
|
3
|
+
When a human leaves a PR comment that asks for work that is **legitimate but
|
|
4
|
+
outside the scope of the current PR** (a different bug, a related-but-separate
|
|
5
|
+
feature, a follow-up cleanup that doesn't belong in the current diff), do **not**
|
|
6
|
+
broaden the PR and do **not** silently rebut the comment. Spin off a new Minions
|
|
7
|
+
work item via the dashboard API and reply on the originating comment thread with
|
|
8
|
+
a link to it.
|
|
9
|
+
|
|
10
|
+
This carve-out only enables creating a **separate** work item. It does not
|
|
11
|
+
loosen the rule that the *current* PR should stay focused on the original
|
|
12
|
+
review feedback.
|
|
13
|
+
|
|
14
|
+
## Decision tree
|
|
15
|
+
|
|
16
|
+
For each human comment that asks for additional work, classify it before
|
|
17
|
+
editing:
|
|
18
|
+
|
|
19
|
+
1. **Fix in this PR** — the request is in scope (regression of the current
|
|
20
|
+
diff, a flaw in the new code, missing requested behavior the PR was already
|
|
21
|
+
supposed to cover). Fix it on this branch, push, reply on the thread.
|
|
22
|
+
2. **Answer with rationale** — the request is invalid, stale, already
|
|
23
|
+
addressed, or would harm the code. Post an evidence-backed rebuttal on the
|
|
24
|
+
thread; do **not** create a follow-up WI for it.
|
|
25
|
+
3. **Follow-up WI** — the request is legitimate but clearly out of scope for
|
|
26
|
+
the current PR (different file/system, different bug, distinct feature, a
|
|
27
|
+
refactor the reviewer explicitly asked you to "track separately" or "do in a
|
|
28
|
+
follow-up"). Create a new work item via the API (see below) and reply on the
|
|
29
|
+
originating thread with the new WI id.
|
|
30
|
+
|
|
31
|
+
If you are unsure between #1 and #3, prefer **#3 (follow-up)** so the current
|
|
32
|
+
PR stays small and reviewable. If you are unsure between #2 and #3, prefer #2
|
|
33
|
+
and explain your reasoning — don't manufacture work.
|
|
34
|
+
|
|
35
|
+
## The API call
|
|
36
|
+
|
|
37
|
+
The Minions dashboard runs on `http://localhost:7331`. Create a follow-up work
|
|
38
|
+
item with `POST /api/work-items`:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
curl -sS -X POST http://localhost:7331/api/work-items \
|
|
42
|
+
-H 'Content-Type: application/json' \
|
|
43
|
+
-H 'X-Minions-Agent: <your-agent-id>' \
|
|
44
|
+
-H 'X-Minions-Origin-Wi: <current-wi-id>' \
|
|
45
|
+
-d '{
|
|
46
|
+
"title": "Short imperative summary of the follow-up",
|
|
47
|
+
"type": "implement",
|
|
48
|
+
"priority": "medium",
|
|
49
|
+
"project": "<project-name>",
|
|
50
|
+
"description": "Why this is a follow-up, what should change, acceptance.\n\nOriginated from <reviewer> on PR #<N> (<url>): \"<verbatim quote of the ask>\"",
|
|
51
|
+
"references": [
|
|
52
|
+
{"url": "<originating-pr-url>", "label": "Originated from PR #<N> comment"}
|
|
53
|
+
],
|
|
54
|
+
"meta": {
|
|
55
|
+
"pr_followup": {
|
|
56
|
+
"parent_pr_url": "<originating-pr-url>",
|
|
57
|
+
"parent_pr_id": "<canonical PR id, e.g. github:owner/repo#123 or PR-123>",
|
|
58
|
+
"parent_comment_id": "<exact comment/thread id from the host API>",
|
|
59
|
+
"parent_comment_author": "<reviewer login>"
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}'
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Required fields and their conventions:
|
|
66
|
+
|
|
67
|
+
- **`title`** — short imperative ("Add foo to bar", "Fix off-by-one in baz").
|
|
68
|
+
- **`type`** — pick from the routing types (`implement`, `fix`, `test`,
|
|
69
|
+
`docs`, `ask`, `explore`, …). For new feature/fix work, `implement` is
|
|
70
|
+
almost always correct; use `fix` only when the follow-up is about an existing
|
|
71
|
+
PR's bug. Do **not** set `agent` — let `routing.md` pick.
|
|
72
|
+
- **`project`** — name of the same project the originating PR belongs to.
|
|
73
|
+
Required when more than one project is configured.
|
|
74
|
+
- **`description`** — explain *why* this is a follow-up and quote the exact
|
|
75
|
+
ask. Future readers should understand the scope without re-reading the PR
|
|
76
|
+
thread.
|
|
77
|
+
- **`references`** — at least one entry pointing back at the originating PR.
|
|
78
|
+
- **`meta.pr_followup`** — the four-field shape above. Used by the dashboard
|
|
79
|
+
for traceability chips and by the server for dedup (a second request with the
|
|
80
|
+
same `parent_comment_id` returns the existing WI id rather than creating a
|
|
81
|
+
duplicate).
|
|
82
|
+
|
|
83
|
+
Headers:
|
|
84
|
+
|
|
85
|
+
- **`X-Minions-Agent`** — your agent id (e.g. `lambert`, `ripley`,
|
|
86
|
+
`temp-mp3dop1v…`). Persisted as `_originAgent` on the new WI.
|
|
87
|
+
- **`X-Minions-Origin-Wi`** — the id of the work item you were dispatched
|
|
88
|
+
against (the one whose PR you are responding to). Persisted as `_originWi`.
|
|
89
|
+
|
|
90
|
+
Both headers are optional but strongly recommended — they let the dashboard
|
|
91
|
+
correlate the follow-up to the dispatch that created it.
|
|
92
|
+
|
|
93
|
+
## Server responses
|
|
94
|
+
|
|
95
|
+
| Status | Body | Meaning |
|
|
96
|
+
|---|---|---|
|
|
97
|
+
| 200 | `{ ok: true, id: "W-…" }` | New follow-up WI created. |
|
|
98
|
+
| 200 | `{ ok: true, id: "W-…", duplicate: true, duplicateOf: "W-…" }` | The standard title/type/project dedup window matched an in-flight WI. Same WI id is returned; reply on the comment thread with that id. |
|
|
99
|
+
| 409 | `{ error: "followup_already_dispatched", existingWiId: "W-…" }` | Another agent (or your previous attempt) already dispatched a follow-up for this exact `parent_comment_id`. Reply on the comment thread linking the existing WI; do not retry. |
|
|
100
|
+
| 400 | `{ error: "<message>" }` | Validation failed. Inspect the message: the most common cause is a malformed `meta.pr_followup` shape. Fix and retry. |
|
|
101
|
+
|
|
102
|
+
Treat 409 as a **success** for your purposes — the follow-up exists, you just
|
|
103
|
+
weren't the one who created it. Still post the reply on the comment thread with
|
|
104
|
+
the returned `existingWiId`.
|
|
105
|
+
|
|
106
|
+
## Mandatory post-dispatch step
|
|
107
|
+
|
|
108
|
+
After the API call returns a WI id (whether `id` from 200 or `existingWiId`
|
|
109
|
+
from 409), reply on the originating comment thread with a link back:
|
|
110
|
+
|
|
111
|
+
> Tracked as follow-up: **W-…** — see the Minions dashboard. Continuing with
|
|
112
|
+
> the in-place fix on this PR.
|
|
113
|
+
|
|
114
|
+
Then **resolve that sub-thread** (GitHub: "Resolve conversation"; ADO: set
|
|
115
|
+
status to `closed`) even if other review threads on the PR are still open. The
|
|
116
|
+
follow-up WI is the durable artifact; the comment thread should not be left
|
|
117
|
+
hanging.
|
|
118
|
+
|
|
119
|
+
## Record the follow-up in your completion report
|
|
120
|
+
|
|
121
|
+
Add a `followups` array to your JSON completion report so the engine has an
|
|
122
|
+
auditable record of what you fanned out to:
|
|
123
|
+
|
|
124
|
+
```json
|
|
125
|
+
{
|
|
126
|
+
"status": "success",
|
|
127
|
+
"summary": "…",
|
|
128
|
+
"followups": [
|
|
129
|
+
{
|
|
130
|
+
"wi_id": "W-mp7abc…",
|
|
131
|
+
"title": "Add foo to bar",
|
|
132
|
+
"reason": "Out-of-scope ask from reviewer on PR #123 comment #4567890",
|
|
133
|
+
"parent_comment_id": "4567890"
|
|
134
|
+
}
|
|
135
|
+
]
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
The engine logs each entry at `info` and warns if the array references a WI id
|
|
140
|
+
that doesn't exist in any project's `work-items.json` (mismatch between what
|
|
141
|
+
you claim and what the API actually created — usually a sign that the dispatch
|
|
142
|
+
was reverted or the response was misread).
|
|
143
|
+
|
|
144
|
+
## Do NOT
|
|
145
|
+
|
|
146
|
+
- Do not pick `agent` for the follow-up; the routing layer assigns one based
|
|
147
|
+
on `type` + `project`.
|
|
148
|
+
- Do not set `X-CC-Turn-Id` (that header is for Command Center turns; agents
|
|
149
|
+
don't have a turn id). Use `X-Minions-Agent`/`X-Minions-Origin-Wi` instead.
|
|
150
|
+
- Do not skip the comment-thread reply — without it, the human has no signal
|
|
151
|
+
that their ask was tracked and the engine will keep re-routing the comment
|
|
152
|
+
as `pendingFix`.
|
|
153
|
+
- Do not spin off follow-ups for nits, style notes, or things you are about
|
|
154
|
+
to fix in this PR anyway. Reserve this for asks that genuinely belong in a
|
|
155
|
+
separate WI.
|
|
156
|
+
- Do not omit `meta.pr_followup.parent_comment_id`; without it the server
|
|
157
|
+
cannot dedup and you will create duplicates on every retry.
|