@yemi33/minions 0.1.702 → 0.1.704
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/CHANGELOG.md +6 -0
- package/docs/pr-review-fix-loop.md +110 -0
- package/engine/shared.js +1 -0
- package/engine.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
# PR Review & Fix Loop
|
|
2
|
+
|
|
3
|
+
How the engine manages the lifecycle of a PR from creation through review, fix, and re-review.
|
|
4
|
+
|
|
5
|
+
## 1. Implement agent creates PR
|
|
6
|
+
|
|
7
|
+
- Agent pushes code, output contains PR URL
|
|
8
|
+
- `syncPrsFromOutput()` (lifecycle.js) extracts URL via regex, creates `pull-requests.json` entry, links to work item via `addPrLink()`
|
|
9
|
+
|
|
10
|
+
## 2. Engine discovers PR needs review
|
|
11
|
+
|
|
12
|
+
- `discoverFromPrs()` (engine.js) runs each tick (~60s)
|
|
13
|
+
- Gates: `status === 'active'` + `reviewStatus === 'pending'` + not reviewed since last push + not dispatched + not on cooldown
|
|
14
|
+
- Pre-dispatch: `checkLiveReviewStatus()` hits GitHub/ADO API to catch stale cached status
|
|
15
|
+
- Routes to reviewer via `resolveAgent('review')`, dispatches with `review.md` playbook
|
|
16
|
+
|
|
17
|
+
## 3. Review completes
|
|
18
|
+
|
|
19
|
+
- `updatePrAfterReview()` (lifecycle.js) re-checks live vote from platform (may have changed during execution)
|
|
20
|
+
- Sets `reviewStatus` to `approved` / `changes-requested` / `waiting`
|
|
21
|
+
- Stores `minionsReview: { reviewer, reviewedAt, note }`
|
|
22
|
+
- Creates feedback file for author agent
|
|
23
|
+
|
|
24
|
+
## 4. Fix dispatch (3 independent triggers, at most one per tick)
|
|
25
|
+
|
|
26
|
+
### A. Review feedback (`changes-requested`)
|
|
27
|
+
|
|
28
|
+
- Gate: `reviewStatus === 'changes-requested'` + `!awaitingReReview` + not dispatched + not on cooldown
|
|
29
|
+
- Routes to PR author via `_author_` routing token
|
|
30
|
+
- `review_note` = reviewer's feedback
|
|
31
|
+
- Sets `fixDispatched = true` — prevents trigger B from also firing this tick
|
|
32
|
+
|
|
33
|
+
### B. Human comments (`humanFeedback.pendingFix`)
|
|
34
|
+
|
|
35
|
+
- Gate: `pendingFix || coalescedFeedback` + `!awaitingReReview` + `!fixDispatched`
|
|
36
|
+
- Agent comments filtered out via `/\bMinions\s*\(/i` regex on comment body
|
|
37
|
+
- Coalesces multiple comments arriving during cooldown into single fix
|
|
38
|
+
- Routes to author
|
|
39
|
+
|
|
40
|
+
### C. Build failures (`buildStatus === 'failing'`)
|
|
41
|
+
|
|
42
|
+
- Gate: `buildFixAttempts < maxBuildFixAttempts` (default 3) + grace period expired
|
|
43
|
+
- **Grace period** (`_buildFixPushedAt`): after fix dispatches, waits `buildFixGracePeriod` (default 10min, configurable in `ENGINE_DEFAULTS`) for CI to run before re-dispatching. Cleared when poller detects build status transition (CI actually ran).
|
|
44
|
+
- **Error logs**: GitHub fetches annotations (failures only, not warnings) + Actions job log (always). ADO fetches build timeline + failed task logs. Both fetch up to 3 failing pipelines.
|
|
45
|
+
- **Escalation**: after 3 failed attempts, writes inbox alert, sets `buildFixEscalated = true`, stops auto-dispatch. Counter resets when build recovers.
|
|
46
|
+
|
|
47
|
+
## 5. Fix completes
|
|
48
|
+
|
|
49
|
+
- `updatePrAfterFix()` (lifecycle.js) sets `reviewStatus = 'waiting'` + `fixedAt = ts()`
|
|
50
|
+
- Clears `humanFeedback.pendingFix`
|
|
51
|
+
- `awaitingReReview` gate (`waiting` + `fixedAt`) blocks all fix dispatch until reviewer acts
|
|
52
|
+
|
|
53
|
+
## 6. Re-review cycle
|
|
54
|
+
|
|
55
|
+
- Poller (~3min): detects new commit (`head.sha` changed) → sets `lastPushedAt`
|
|
56
|
+
- Platform review state drives next action:
|
|
57
|
+
- Reviewer approves → `approved` → done
|
|
58
|
+
- Reviewer re-requests changes → `changes-requested` → triggers another fix
|
|
59
|
+
- No reviewer action yet → stays `waiting` → engine waits
|
|
60
|
+
|
|
61
|
+
## 7. Build fix cycle after fix push
|
|
62
|
+
|
|
63
|
+
- Fix agent pushes → `_buildFixPushedAt` stamped
|
|
64
|
+
- Poller detects new commit → CI starts → `buildStatus` transitions (`failing` → `running`)
|
|
65
|
+
- `_buildFixPushedAt` cleared on any transition
|
|
66
|
+
- If CI passes → `buildFixAttempts` reset, `buildErrorLog` cleared → done
|
|
67
|
+
- If CI fails again → fresh error logs fetched → new fix dispatches immediately (grace already cleared by transition)
|
|
68
|
+
|
|
69
|
+
## Race prevention
|
|
70
|
+
|
|
71
|
+
| Scenario | Guard |
|
|
72
|
+
|---|---|
|
|
73
|
+
| Simultaneous review + fix | `activePrIds` — skip PR if any dispatch in-flight |
|
|
74
|
+
| Duplicate fix (review + human) | `fixDispatched` flag — only one fix per PR per tick |
|
|
75
|
+
| Branch write conflict | `isBranchActive()` mutex |
|
|
76
|
+
| Fix while awaiting re-review | `awaitingReReview` (waiting + fixedAt) |
|
|
77
|
+
| Build fix before CI runs | `_buildFixPushedAt` grace period (10min) |
|
|
78
|
+
| Duplicate dispatch | `dispatchKey` dedup + cooldown |
|
|
79
|
+
| Stale review status | Pre-dispatch live API check |
|
|
80
|
+
| Orphan detection | Heartbeat timeout + output scan |
|
|
81
|
+
|
|
82
|
+
## Key files
|
|
83
|
+
|
|
84
|
+
| File | Functions |
|
|
85
|
+
|---|---|
|
|
86
|
+
| `engine.js` | `discoverFromPrs()` — discovery + dispatch logic |
|
|
87
|
+
| `engine/lifecycle.js` | `syncPrsFromOutput()`, `updatePrAfterReview()`, `updatePrAfterFix()` |
|
|
88
|
+
| `engine/github.js` | `pollPrStatus()`, `pollPrHumanComments()`, `fetchGhBuildErrorLog()` |
|
|
89
|
+
| `engine/ado.js` | `pollPrStatus()`, `pollPrHumanComments()`, `fetchAdoBuildErrorLog()` |
|
|
90
|
+
| `engine/dispatch.js` | `addToDispatch()` — dedup by work item ID and dispatchKey |
|
|
91
|
+
| `engine/cooldown.js` | `isBranchActive()`, cooldown management |
|
|
92
|
+
| `playbooks/review.md` | Reviewer playbook |
|
|
93
|
+
| `playbooks/fix.md` | Fix agent playbook |
|
|
94
|
+
|
|
95
|
+
## PR state fields
|
|
96
|
+
|
|
97
|
+
| Field | Set by | Purpose |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| `status` | Poller | `active` / `merged` / `abandoned` |
|
|
100
|
+
| `reviewStatus` | Poller + post-completion | `pending` / `approved` / `changes-requested` / `waiting` |
|
|
101
|
+
| `buildStatus` | Poller | `none` / `passing` / `failing` / `running` |
|
|
102
|
+
| `buildErrorLog` | Poller | Actual CI error output for fix agents |
|
|
103
|
+
| `buildFixAttempts` | Discovery (on dispatch) | Counter for escalation cap |
|
|
104
|
+
| `buildFixEscalated` | Discovery (on cap) | Stops auto-dispatch |
|
|
105
|
+
| `_buildFixPushedAt` | Discovery (on dispatch) | Grace period timestamp |
|
|
106
|
+
| `_buildFailNotified` | Discovery | Dedup for inbox alert |
|
|
107
|
+
| `lastPushedAt` | Poller (new commit) | Tracks latest push for re-review logic |
|
|
108
|
+
| `lastReviewedAt` | `updatePrAfterReview()` | Prevents re-dispatch if reviewed |
|
|
109
|
+
| `minionsReview` | Post-completion hooks | `{ reviewer, reviewedAt, note, fixedAt }` |
|
|
110
|
+
| `humanFeedback` | `pollPrHumanComments()` | `{ pendingFix, feedbackContent, lastProcessedCommentDate }` |
|
package/engine/shared.js
CHANGED
|
@@ -544,6 +544,7 @@ const ENGINE_DEFAULTS = {
|
|
|
544
544
|
lockRetries: 2, // retry lock acquisition this many times after initial timeout (total attempts = 1 + lockRetries)
|
|
545
545
|
lockRetryBackoffMs: 500, // base backoff between lock retries (doubles each attempt: 500ms, 1s, 2s, ...)
|
|
546
546
|
maxBuildFixAttempts: 3, // max consecutive auto-fix dispatch cycles per PR before escalation to human
|
|
547
|
+
buildFixGracePeriod: 600000, // 10min — wait for CI to run after build fix before re-dispatching
|
|
547
548
|
ccModel: 'sonnet', // model for Command Center and doc-chat (sonnet, haiku, opus)
|
|
548
549
|
ccEffort: null, // effort level for CC/doc-chat (null, 'low', 'medium', 'high')
|
|
549
550
|
};
|
package/engine.js
CHANGED
|
@@ -1604,7 +1604,7 @@ async function discoverFromPrs(config, project) {
|
|
|
1604
1604
|
// Grace period: after a build fix push, wait for CI to run before re-dispatching
|
|
1605
1605
|
// Skip if build hasn't transitioned since last fix (still showing the old failure)
|
|
1606
1606
|
if (pr._buildFixPushedAt && pr.buildStatus === 'failing') {
|
|
1607
|
-
const gracePeriodMs = config.engine?.buildFixGracePeriod ??
|
|
1607
|
+
const gracePeriodMs = config.engine?.buildFixGracePeriod ?? ENGINE_DEFAULTS.buildFixGracePeriod;
|
|
1608
1608
|
if (Date.now() - new Date(pr._buildFixPushedAt).getTime() < gracePeriodMs) continue;
|
|
1609
1609
|
}
|
|
1610
1610
|
if (pr.status === PR_STATUS.ACTIVE && pr.buildStatus === 'failing') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.704",
|
|
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"
|