@yemi33/minions 0.1.1969 → 0.1.1971
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/engine/ado.js +39 -10
- package/engine/shared.js +10 -3
- package/package.json +1 -1
- package/playbooks/review.md +7 -1
- package/prompts/cc-system.md +1 -1
package/engine/ado.js
CHANGED
|
@@ -1103,8 +1103,21 @@ async function pollPrHumanComments(config) {
|
|
|
1103
1103
|
const authorName = (comment.author?.displayName || '').toLowerCase();
|
|
1104
1104
|
if (ignoredAuthors.some(a => authorName.includes(a))) continue;
|
|
1105
1105
|
if (/^#{1,3}\s*(Coverage|Build|Test|Deploy|Pipeline)\s*(Report|Status|Result|Summary)/i.test(content)) continue;
|
|
1106
|
-
// Detect agent comments (included in context, but don't trigger fix)
|
|
1107
|
-
|
|
1106
|
+
// Detect agent comments (included in context, but don't trigger fix).
|
|
1107
|
+
// W-mpbhnaim000q9ed3: also match the VERDICT-prefixed review body. The
|
|
1108
|
+
// `Review by Minions (...)` sign-off can be skipped by a review agent
|
|
1109
|
+
// (Ripley on PR ado:office/iss/constellation#5056697, 2026-05-18: posted
|
|
1110
|
+
// a 1100-char APPROVE body with no sign-off → engine treated it as
|
|
1111
|
+
// human feedback → fix-dispatch loop spammed "Skipping human-feedback
|
|
1112
|
+
// fix ... noop on the same head" once a minute for 9+ hours). The
|
|
1113
|
+
// VERDICT prefix is itself an engine-owned structured-output contract
|
|
1114
|
+
// (parseReviewVerdict, playbooks/review.md:69-72) — humans don't write
|
|
1115
|
+
// it as the first line of a comment. The `^` + /m anchor keeps quoted
|
|
1116
|
+
// verdict text inside a human reply from matching.
|
|
1117
|
+
const isAgent = /\bMinions\s*\(/i.test(content)
|
|
1118
|
+
|| /\bby\s+Minions\b/i.test(content)
|
|
1119
|
+
|| /\[minions\]/i.test(content)
|
|
1120
|
+
|| /^\s*VERDICT:\s*(APPROVE|REQUEST_CHANGES)\b/im.test(content);
|
|
1108
1121
|
|
|
1109
1122
|
const entry = {
|
|
1110
1123
|
threadId: thread.id,
|
|
@@ -1369,11 +1382,24 @@ async function checkLiveReviewStatus(pr, project) {
|
|
|
1369
1382
|
|
|
1370
1383
|
/**
|
|
1371
1384
|
* W-mp7b1g8q000fea45 — Reviewer vote reconciliation on verdict flip.
|
|
1385
|
+
* W-mpbhnaim000q9ed3 — Bug A: also cast +10 when current vote is 0 (not just <0).
|
|
1372
1386
|
*
|
|
1373
|
-
*
|
|
1374
|
-
*
|
|
1375
|
-
*
|
|
1376
|
-
*
|
|
1387
|
+
* Ensures the *authenticated reviewer's own* vote is positive (+10) when an agent
|
|
1388
|
+
* flips their verdict from request_changes → approved on a re-review. Mirrors the
|
|
1389
|
+
* existing target-branch re-approval pattern at engine/ado.js:837-852 (PUT
|
|
1390
|
+
* reviewers/{myId} {vote:10}). Covers both:
|
|
1391
|
+
* - prior negative vote (-5 wait-for-author, -10 rejected) → cleared to +10, and
|
|
1392
|
+
* - prior neutral vote (0 — never cast, or reset by another path and never
|
|
1393
|
+
* re-cast) → upgraded to +10 so the platform reflects the approved verdict.
|
|
1394
|
+
*
|
|
1395
|
+
* Without the neutral-vote upgrade, an agent flip to approved leaves the engine's
|
|
1396
|
+
* `reviewStatus` stuck at `changes-requested` because checkLiveReviewStatus keeps
|
|
1397
|
+
* seeing votes that don't carry an approval, and the next tick's reconciler
|
|
1398
|
+
* dispatches a redundant human-feedback fix (Ripley on PR 5056697, 2026-05-18:
|
|
1399
|
+
* `"Skipping human-feedback fix ... noop on the same head"` once a minute for 9+ hours).
|
|
1400
|
+
*
|
|
1401
|
+
* The function name remains `resetReviewerNegativeVote` for export-stability —
|
|
1402
|
+
* it is referenced in playbooks/review.md and called from lifecycle.js.
|
|
1377
1403
|
*
|
|
1378
1404
|
* IMPORTANT: only operates on the authenticated reviewer's own vote. Other
|
|
1379
1405
|
* reviewers' negative votes (humans, other minions on a different account) are
|
|
@@ -1385,7 +1411,7 @@ async function checkLiveReviewStatus(pr, project) {
|
|
|
1385
1411
|
* Otherwise returns:
|
|
1386
1412
|
* {
|
|
1387
1413
|
* attempted: boolean, // true if we found our reviewer entry and tried to PUT
|
|
1388
|
-
* changed: boolean, // true if the reviewer's vote was actually flipped
|
|
1414
|
+
* changed: boolean, // true if the reviewer's vote was actually flipped to +10
|
|
1389
1415
|
* fromVote: number|null,// the reviewer's prior vote (null if not a reviewer on the PR)
|
|
1390
1416
|
* toVote: number|null,// the vote after PUT (10 if changed, prior value otherwise)
|
|
1391
1417
|
* }
|
|
@@ -1421,16 +1447,19 @@ async function resetReviewerNegativeVote(pr, project) {
|
|
|
1421
1447
|
// is the normal GH path; on ADO we generally do vote, so this is rare.)
|
|
1422
1448
|
return { attempted: false, changed: false, fromVote: null, toVote: null };
|
|
1423
1449
|
}
|
|
1424
|
-
if (myVote
|
|
1425
|
-
// Already
|
|
1450
|
+
if (myVote > 0) {
|
|
1451
|
+
// Already positive — platform already matches the approved verdict.
|
|
1426
1452
|
return { attempted: false, changed: false, fromVote: myVote, toVote: myVote };
|
|
1427
1453
|
}
|
|
1454
|
+
// W-mpbhnaim000q9ed3: cover myVote === 0 too. A neutral vote on verdict flip
|
|
1455
|
+
// means the agent never cast (or someone reset to 0), so the platform doesn't
|
|
1456
|
+
// reflect approval yet; PUT +10 so reviewStatus reconciler stops looping.
|
|
1428
1457
|
await adoFetch(`${repoBase}/pullrequests/${prNum}/reviewers/${myId}?api-version=7.1`, token, {
|
|
1429
1458
|
method: 'PUT',
|
|
1430
1459
|
body: JSON.stringify({ vote: 10 }),
|
|
1431
1460
|
timeout: 4000,
|
|
1432
1461
|
});
|
|
1433
|
-
log('info', `PR ${pr.id}: reset reviewer vote ${myVote} → 10
|
|
1462
|
+
log('info', `PR ${pr.id}: reset reviewer vote ${myVote} → 10 on verdict flip`);
|
|
1434
1463
|
return { attempted: true, changed: true, fromVote: myVote, toVote: 10 };
|
|
1435
1464
|
} catch (e) {
|
|
1436
1465
|
log('warn', `Reviewer vote reset for ${pr?.id || 'unknown PR'}: ${e.message}`);
|
package/engine/shared.js
CHANGED
|
@@ -1959,9 +1959,15 @@ const WORK_TYPE = {
|
|
|
1959
1959
|
// and /api/work-items/retry) refuses to create or re-spawn a project-less WI
|
|
1960
1960
|
// of any type in this set when PROJECTS.length !== 1.
|
|
1961
1961
|
//
|
|
1962
|
-
// Complement of engine.js READ_ONLY_ROOT_TASK_TYPES
|
|
1963
|
-
//
|
|
1964
|
-
//
|
|
1962
|
+
// Complement of engine.js READ_ONLY_ROOT_TASK_TYPES. `docs` is included
|
|
1963
|
+
// (W-mpbgo1wv000gf75b): docs edits run as worktree-requiring dispatches
|
|
1964
|
+
// against the minions repo, so without a project the engine's
|
|
1965
|
+
// resolveProjectRootDir falls back to MINIONS_DIR's parent and can collapse
|
|
1966
|
+
// to a drive root on installs where MINIONS_DIR sits one level below the
|
|
1967
|
+
// filesystem root (e.g. `D:\squad` → `D:\`). Failing fast at HTTP-validate
|
|
1968
|
+
// time is preferable to letting a project-less docs WI land and loop on
|
|
1969
|
+
// WORKTREE_PREFLIGHT. Callers doing minions-repo docs work must pass
|
|
1970
|
+
// `project: "minions"` explicitly.
|
|
1965
1971
|
const WORKTREE_REQUIRING_TYPES = new Set([
|
|
1966
1972
|
WORK_TYPE.FIX,
|
|
1967
1973
|
WORK_TYPE.IMPLEMENT,
|
|
@@ -1970,6 +1976,7 @@ const WORKTREE_REQUIRING_TYPES = new Set([
|
|
|
1970
1976
|
WORK_TYPE.VERIFY,
|
|
1971
1977
|
WORK_TYPE.REVIEW,
|
|
1972
1978
|
WORK_TYPE.DECOMPOSE,
|
|
1979
|
+
WORK_TYPE.DOCS,
|
|
1973
1980
|
]);
|
|
1974
1981
|
|
|
1975
1982
|
const PLAN_STATUS = {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1971",
|
|
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/review.md
CHANGED
|
@@ -88,6 +88,8 @@ Minimum diff to ship: <one-line description of the smallest change that would fl
|
|
|
88
88
|
|
|
89
89
|
Non-blocking observations: None
|
|
90
90
|
- (default to `None`; if you list any, each must be tied to an existing diff line in the form `path:line — observation`)
|
|
91
|
+
|
|
92
|
+
Review by Minions ({{agent_name}} — {{agent_role}})
|
|
91
93
|
```
|
|
92
94
|
|
|
93
95
|
After running the command, confirm it succeeded (check the command output for errors). If it fails, retry once.
|
|
@@ -100,6 +102,10 @@ If you encounter merge conflicts (e.g., the PR shows conflicts):
|
|
|
100
102
|
|
|
101
103
|
## When to Stop
|
|
102
104
|
|
|
103
|
-
Your task is complete when your review comment
|
|
105
|
+
Your task is complete when your review comment has been posted successfully with BOTH:
|
|
106
|
+
- `VERDICT: APPROVE` or `VERDICT: REQUEST_CHANGES` on the first line, AND
|
|
107
|
+
- the `Review by Minions ({{agent_name}} — {{agent_role}})` sign-off on the last line of the body
|
|
108
|
+
|
|
109
|
+
and the completion report has `verdict: "approved"` or `verdict: "changes-requested"`. The sign-off is what lets the engine distinguish agent reviews from human PR comments on ADO; without it the engine will queue a redundant fix-dispatch loop (W-mpbhnaim000q9ed3, Ripley on PR 5056697).
|
|
104
110
|
|
|
105
111
|
Do NOT stop before posting the review. Do NOT continue reading unrelated files after posting.
|
package/prompts/cc-system.md
CHANGED
|
@@ -146,7 +146,7 @@ curl -s http://localhost:{{dashboard_port}}/api/status
|
|
|
146
146
|
|
|
147
147
|
**Required fields per endpoint** — the server returns `{ error: "..." }` if missing. Common cases:
|
|
148
148
|
- `POST /api/work-items`: `title` REQUIRED. `description` recommended. `project` REQUIRED when multiple projects are configured (server returns the list of known names if you guess wrong). `type` defaults to `implement`; valid values: `fix`, `implement`, `implement:large`, `explore`, `ask`, `review`, `test`, `verify`. Agent hint via `agent` (string) or `agents` (array).
|
|
149
|
-
- Exempt from the `project` requirement (these run rootless or via central paths): `ask`, `explore`, `plan`, `plan-to-prd`, `meeting
|
|
149
|
+
- Exempt from the `project` requirement (these run rootless or via central paths): `ask`, `explore`, `plan`, `plan-to-prd`, `meeting`. (`docs` is intentionally NOT exempt — it's write-capable and lands in `WORKTREE_REQUIRING_TYPES`, so it needs a real project worktree. For minions-repo docs work, pass `project: "minions"` explicitly.) Every other type needs a project worktree, so the server rejects project-less creates with `400 { error, knownProjects }` when ≠1 project is configured.
|
|
150
150
|
- **`meta.keep_processes: true`** — opt-in flag that lets the agent leave specific descendant PIDs running after it exits (default: engine reaps EVERYTHING the agent spawned). **Set this whenever the user's intent is to leave a process alive after the agent finishes** — e.g. "spin up the dev server and exit", "start the watcher and leave it running", "set up my dev env", "keep the emulator open", "launch the daemon for me", "boot the constellation host and disconnect". Don't set it for normal build/test/run-once tasks (`npm test`, `npm run build`, one-shot scripts) — those should be reaped. Also accepts optional `meta.keep_processes_ttl_minutes` (default 60, hard-cap 1440 = 24h). When you set this flag, also make the WI title/description say something like "leave the dev server running" so the agent knows to write `agents/<id>/keep-pids.json` before exiting (the playbook injects the contract automatically when the flag is on). Example: `-d '{"title":"Spin up Constellation dev env and leave server running","type":"implement","project":"constellation","description":"Run bun install + bun run dev. Leave the dev server (port 5173) and Constellation host (port 3001) running after you exit so the user can iterate.","meta":{"keep_processes":true,"keep_processes_ttl_minutes":240}}'`. Inspect / kill kept PIDs anytime via `GET /api/keep-processes` and `POST /api/keep-processes/kill`.
|
|
151
151
|
- **`skipPr: true`** — opt-in flag that tells the engine NOT to enforce the PR-attachment contract for this work item, so the WI can complete `done` without the missing-PR hard-fail. **Set this when the dispatch mutates state OUTSIDE any tracked git repo and therefore cannot produce a PR** — e.g. cleaning `~/.claude/skills/`, editing runtime config under `~/.config/`, resetting the dashboard cache, mutating engine JSON state files (`engine/*.json`) the engine itself owns, or local tooling installs. **Do NOT set it for any task that touches a tracked repo's source** — even one-line diffs in a real repo should produce a PR. Type-selection rule of thumb: prefer `type: "explore"` for genuinely read-only tasks (rootless, no worktree, no PR contract); use `skipPr: true` when the task is write-side mutation but the writes don't land in a git repo. Example: `-d '{"title":"Clean up duplicate skills in ~/.claude/skills","type":"implement","description":"Audit ~/.claude/skills/ and delete the 3 obsolete entries identified in NOTE-mp7gt4iw0004b879. Pure user-machine state outside any git repo, so no PR will be produced.","skipPr":true}'`.
|
|
152
152
|
- **`oneShot: true`** — opt-in flag for one-off human-initiated dispatches that should NOT enroll the discovered PR into the engine's automatic review/fix loop. The PR is still tracked (status + comments are polled normally) but `discoverFromPrs` skips it for review/fix dispatch. **Set this when the user's intent is "do this single action against an existing PR, then stop"** — e.g. "review PR #2533 once", "rebase PR #2540 once and exit", "post a fix-summary comment on PR #2519". Don't set it for normal feature/fix work where the PR should keep cycling through review/fix until merged. Example: `-d '{"title":"One-off review of PR #2533","type":"review","project":"minions","description":"Single review pass on github:yemi33/minions#2533. Do not re-dispatch on subsequent comments.","oneShot":true}'`.
|