@yemi33/minions 0.1.2422 → 0.1.2424
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.
|
@@ -369,6 +369,109 @@
|
|
|
369
369
|
.thesis p { margin: 0; color: var(--muted); }
|
|
370
370
|
.thesis strong { color: var(--text); }
|
|
371
371
|
|
|
372
|
+
.evolution-timeline {
|
|
373
|
+
display: grid;
|
|
374
|
+
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
375
|
+
gap: 16px;
|
|
376
|
+
margin: 0;
|
|
377
|
+
padding: 0;
|
|
378
|
+
list-style: none;
|
|
379
|
+
}
|
|
380
|
+
.evolution-stage {
|
|
381
|
+
position: relative;
|
|
382
|
+
display: flex;
|
|
383
|
+
min-width: 0;
|
|
384
|
+
}
|
|
385
|
+
.evolution-stage:not(:last-child)::after {
|
|
386
|
+
content: "\2192";
|
|
387
|
+
position: absolute;
|
|
388
|
+
top: 25px;
|
|
389
|
+
right: -14px;
|
|
390
|
+
z-index: 2;
|
|
391
|
+
display: grid;
|
|
392
|
+
width: 12px;
|
|
393
|
+
height: 24px;
|
|
394
|
+
place-items: center;
|
|
395
|
+
background: var(--bg);
|
|
396
|
+
color: var(--muted);
|
|
397
|
+
font-size: 0.88rem;
|
|
398
|
+
font-weight: 900;
|
|
399
|
+
}
|
|
400
|
+
.evolution-card {
|
|
401
|
+
position: relative;
|
|
402
|
+
width: 100%;
|
|
403
|
+
min-width: 0;
|
|
404
|
+
padding: 23px;
|
|
405
|
+
overflow-wrap: anywhere;
|
|
406
|
+
border: 1px solid var(--border);
|
|
407
|
+
border-radius: var(--radius-lg);
|
|
408
|
+
background: var(--surface-strong);
|
|
409
|
+
}
|
|
410
|
+
.evolution-card::before {
|
|
411
|
+
content: "";
|
|
412
|
+
position: absolute;
|
|
413
|
+
inset: 0 0 auto;
|
|
414
|
+
height: 3px;
|
|
415
|
+
border-radius: var(--radius-lg) var(--radius-lg) 0 0;
|
|
416
|
+
background: var(--blue);
|
|
417
|
+
}
|
|
418
|
+
.evolution-stage:nth-child(2) .evolution-card::before { background: var(--green); }
|
|
419
|
+
.evolution-stage:nth-child(3) .evolution-card::before { background: var(--purple); }
|
|
420
|
+
.evolution-stage:nth-child(4) .evolution-card::before { background: var(--yellow); }
|
|
421
|
+
.evolution-stage:nth-child(4) .evolution-card {
|
|
422
|
+
border-color: rgba(210, 153, 34, 0.42);
|
|
423
|
+
background: linear-gradient(145deg, rgba(210, 153, 34, 0.08), var(--surface-strong));
|
|
424
|
+
}
|
|
425
|
+
.evolution-meta {
|
|
426
|
+
display: flex;
|
|
427
|
+
align-items: center;
|
|
428
|
+
justify-content: space-between;
|
|
429
|
+
gap: 10px;
|
|
430
|
+
margin-bottom: 20px;
|
|
431
|
+
}
|
|
432
|
+
.evolution-index {
|
|
433
|
+
display: grid;
|
|
434
|
+
width: 34px;
|
|
435
|
+
height: 34px;
|
|
436
|
+
flex: 0 0 auto;
|
|
437
|
+
place-items: center;
|
|
438
|
+
border-radius: var(--radius-md);
|
|
439
|
+
background: rgba(88, 166, 255, 0.12);
|
|
440
|
+
color: var(--blue);
|
|
441
|
+
font-size: 0.76rem;
|
|
442
|
+
font-weight: 950;
|
|
443
|
+
}
|
|
444
|
+
.evolution-date {
|
|
445
|
+
color: var(--muted);
|
|
446
|
+
font-size: 0.72rem;
|
|
447
|
+
font-weight: 850;
|
|
448
|
+
letter-spacing: 0.08em;
|
|
449
|
+
text-align: right;
|
|
450
|
+
text-transform: uppercase;
|
|
451
|
+
}
|
|
452
|
+
.evolution-card h3 { margin-bottom: 13px; font-size: 1.12rem; }
|
|
453
|
+
.evolution-card > p { color: var(--muted); font-size: 0.86rem; }
|
|
454
|
+
.evolution-problem {
|
|
455
|
+
padding-bottom: 14px;
|
|
456
|
+
border-bottom: 1px solid var(--border);
|
|
457
|
+
}
|
|
458
|
+
.evolution-card strong { color: var(--text); }
|
|
459
|
+
.evolution-current {
|
|
460
|
+
margin: 18px 0 0;
|
|
461
|
+
padding: 13px 14px;
|
|
462
|
+
border-radius: var(--radius-md);
|
|
463
|
+
background: rgba(88, 166, 255, 0.07);
|
|
464
|
+
}
|
|
465
|
+
.evolution-stage:nth-child(2) .evolution-current { background: rgba(63, 185, 80, 0.07); }
|
|
466
|
+
.evolution-stage:nth-child(3) .evolution-current { background: rgba(188, 140, 255, 0.08); }
|
|
467
|
+
.evolution-stage:nth-child(4) .evolution-current { background: rgba(210, 153, 34, 0.09); }
|
|
468
|
+
.evolution-source {
|
|
469
|
+
margin: 18px 0 0;
|
|
470
|
+
color: var(--muted);
|
|
471
|
+
font-size: 0.78rem;
|
|
472
|
+
text-align: right;
|
|
473
|
+
}
|
|
474
|
+
|
|
372
475
|
.journey-shell {
|
|
373
476
|
--journey-progress: 0%;
|
|
374
477
|
position: relative;
|
|
@@ -854,6 +957,8 @@
|
|
|
854
957
|
.journey-panel { grid-template-columns: 1fr; }
|
|
855
958
|
.map-shell, .prompt-layout { grid-template-columns: 1fr; }
|
|
856
959
|
.map-details { min-height: 0; }
|
|
960
|
+
.evolution-timeline { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
|
961
|
+
.evolution-stage:not(:last-child)::after { display: none; }
|
|
857
962
|
.controls-grid { grid-template-columns: 1fr; }
|
|
858
963
|
}
|
|
859
964
|
|
|
@@ -894,6 +999,8 @@
|
|
|
894
999
|
.map-arrow-4 { transform: rotate(90deg); }
|
|
895
1000
|
.map-down { display: none; }
|
|
896
1001
|
.map-down-2, .map-down-3 { transform: none; }
|
|
1002
|
+
.evolution-timeline { grid-template-columns: 1fr; }
|
|
1003
|
+
.evolution-card { padding: 21px; }
|
|
897
1004
|
.mode-grid, .security-card, .bounds-grid, .surface-strip, .trouble-grid { grid-template-columns: 1fr; }
|
|
898
1005
|
.mode-note, .limitation { grid-column: auto; }
|
|
899
1006
|
.control-card dl { grid-template-columns: 1fr; gap: 2px; }
|
|
@@ -920,6 +1027,7 @@
|
|
|
920
1027
|
<span>Minions Memory</span>
|
|
921
1028
|
</a>
|
|
922
1029
|
<div class="nav-links">
|
|
1030
|
+
<a href="#memory-evolution">Evolution</a>
|
|
923
1031
|
<a href="#memory-journey">Journey</a>
|
|
924
1032
|
<a href="#architecture-map">System map</a>
|
|
925
1033
|
<a href="#prompt-assembly">Prompt</a>
|
|
@@ -987,6 +1095,69 @@
|
|
|
987
1095
|
</div>
|
|
988
1096
|
</section>
|
|
989
1097
|
|
|
1098
|
+
<section class="section" id="memory-evolution" aria-labelledby="evolution-heading">
|
|
1099
|
+
<div class="section-heading">
|
|
1100
|
+
<p class="eyebrow">Evolution, verified in repository history</p>
|
|
1101
|
+
<h2 id="evolution-heading">How memory grew with the problems it had to solve.</h2>
|
|
1102
|
+
<p>Each layer stayed useful after the next one arrived. The current system keeps readable files, adds focused retrieval, and falls back deliberately instead of treating older paths as obsolete.</p>
|
|
1103
|
+
</div>
|
|
1104
|
+
|
|
1105
|
+
<ol class="evolution-timeline" aria-label="Memory system evolution">
|
|
1106
|
+
<li class="evolution-stage" data-memory-era="shared">
|
|
1107
|
+
<article class="evolution-card" aria-labelledby="evolution-shared-title">
|
|
1108
|
+
<div class="evolution-meta">
|
|
1109
|
+
<span class="evolution-index" aria-hidden="true">01</span>
|
|
1110
|
+
<time class="evolution-date" datetime="2026-03">March 2026</time>
|
|
1111
|
+
</div>
|
|
1112
|
+
<h3 id="evolution-shared-title">Shared team memory</h3>
|
|
1113
|
+
<p class="evolution-problem"><strong>Problem solved:</strong> useful findings were scattered across individual task outputs.</p>
|
|
1114
|
+
<p>Inbox consolidation turned agent and human notes into a deduplicated, readable team digest in <span class="code-chip">notes.md</span>, while preserving source notes in the archive.</p>
|
|
1115
|
+
<p class="evolution-current"><strong>Current role:</strong> consolidation still maintains the team-readable record; the digest is also the team half of the legacy prompt path.</p>
|
|
1116
|
+
</article>
|
|
1117
|
+
</li>
|
|
1118
|
+
|
|
1119
|
+
<li class="evolution-stage" data-memory-era="personal">
|
|
1120
|
+
<article class="evolution-card" aria-labelledby="evolution-personal-title">
|
|
1121
|
+
<div class="evolution-meta">
|
|
1122
|
+
<span class="evolution-index" aria-hidden="true">02</span>
|
|
1123
|
+
<time class="evolution-date" datetime="2026-05">May 2026</time>
|
|
1124
|
+
</div>
|
|
1125
|
+
<h3 id="evolution-personal-title">Personal routing</h3>
|
|
1126
|
+
<p class="evolution-problem"><strong>Problem solved:</strong> one shared digest gave every specialist the same broad history.</p>
|
|
1127
|
+
<p>Consolidation began routing configured, non-temporary authors' findings into <span class="code-chip">knowledge/agents/<agent>.md</span>, using YAML identity with a filename fallback.</p>
|
|
1128
|
+
<p class="evolution-current"><strong>Current role:</strong> these notebooks remain readable and maintained, but broad prompt injection is now a fallback rather than the default recall strategy.</p>
|
|
1129
|
+
</article>
|
|
1130
|
+
</li>
|
|
1131
|
+
|
|
1132
|
+
<li class="evolution-stage" data-memory-era="retrieval">
|
|
1133
|
+
<article class="evolution-card" aria-labelledby="evolution-retrieval-title">
|
|
1134
|
+
<div class="evolution-meta">
|
|
1135
|
+
<span class="evolution-index" aria-hidden="true">03</span>
|
|
1136
|
+
<time class="evolution-date" datetime="2026-07">July 2026</time>
|
|
1137
|
+
</div>
|
|
1138
|
+
<h3 id="evolution-retrieval-title">Structured recall</h3>
|
|
1139
|
+
<p class="evolution-problem"><strong>Problem solved:</strong> growing team and personal files spent prompt space on history unrelated to the task.</p>
|
|
1140
|
+
<p>Migration 017 added scoped SQL records and FTS5 search. Retrieval now reranks task matches and builds a bounded <strong>Relevant Memory</strong> pack with provenance, then wraps it in an <span class="code-chip">UNTRUSTED-INPUT</span> fence.</p>
|
|
1141
|
+
<p class="evolution-current"><strong>Current default:</strong> retrieval is enabled with shadow mode off and may select up to 8 records within 8,192 bytes; pinned context remains first.</p>
|
|
1142
|
+
</article>
|
|
1143
|
+
</li>
|
|
1144
|
+
|
|
1145
|
+
<li class="evolution-stage" data-memory-era="current">
|
|
1146
|
+
<article class="evolution-card" aria-labelledby="evolution-current-title">
|
|
1147
|
+
<div class="evolution-meta">
|
|
1148
|
+
<span class="evolution-index" aria-hidden="true">04</span>
|
|
1149
|
+
<time class="evolution-date" datetime="2026-07">July 2026 to now</time>
|
|
1150
|
+
</div>
|
|
1151
|
+
<h3 id="evolution-current-title">Outcome capture and fallback</h3>
|
|
1152
|
+
<p class="evolution-problem"><strong>Problem solved:</strong> authored notes did not consistently preserve the normalized result of every task.</p>
|
|
1153
|
+
<p><strong>Opt-in</strong> <span class="code-chip">memoryEpisodicCapture</span> stores compact success, partial, or failure outcomes in SQL instead of intentionally collecting transcripts or chain-of-thought. It remains off by default; without a structured summary, a redacted, truncated stdout fallback can include transcript-like text.</p>
|
|
1154
|
+
<p class="evolution-current"><strong>Legacy fallback:</strong> when retrieval is off, shadowed, empty, or errors, prompt assembly uses bounded <span class="code-chip">notes.md</span> plus the assigned agent's notebook. Episode capture does not replace either file.</p>
|
|
1155
|
+
</article>
|
|
1156
|
+
</li>
|
|
1157
|
+
</ol>
|
|
1158
|
+
<p class="evolution-source">Milestone months follow the commits that introduced each capability; behavior labels describe the current implementation.</p>
|
|
1159
|
+
</section>
|
|
1160
|
+
|
|
990
1161
|
<section class="section" id="memory-journey" aria-labelledby="journey-heading">
|
|
991
1162
|
<div class="section-heading">
|
|
992
1163
|
<p class="eyebrow">End-to-end data flow</p>
|
|
@@ -18,15 +18,15 @@ The default `worktree` mode spawns each dispatch inside its own git worktree und
|
|
|
18
18
|
|
|
19
19
|
For these repos, the operator usually already has one canonical checkout that builds correctly. Live-checkout mode lets the agent dispatch into that checkout instead of cloning a side-by-side copy.
|
|
20
20
|
|
|
21
|
-
## Contract (
|
|
21
|
+
## Contract (seven guarantees)
|
|
22
22
|
|
|
23
|
-
Live mode is opinionated about what the engine will and will not do to the operator's tree. The contract has
|
|
23
|
+
Live mode is opinionated about what the engine will and will not do to the operator's tree. The contract has seven guarantees; the engine enforces them by recovering when explicitly configured, otherwise leaving blocked work pending or failing closed.
|
|
24
24
|
|
|
25
25
|
### 1. Per-project mutating-concurrency cap of 1
|
|
26
26
|
|
|
27
27
|
Only one worktree-requiring dispatch (fix / build-fix-complex / implement / review / test / verify / decompose / setup / docs) runs per live-mode project at a time. Read-only types (meeting / ask / explore / plan / plan-to-prd) are excluded from the cap because they never write to disk.
|
|
28
28
|
|
|
29
|
-
Implementation: `engine.js` builds a `liveProjectsInUse` set from the active dispatch list at every allocation pass and per-tick re-annotation; pending items whose project is already in the set are skipped with a `skipReason` and re-tried on the next tick.
|
|
29
|
+
Implementation: `engine.js` builds a `liveProjectsInUse` set from the active dispatch list at every allocation pass and per-tick re-annotation; pending items whose project is already in the set are skipped with a `skipReason` and re-tried on the next tick.
|
|
30
30
|
|
|
31
31
|
### 2. Dirty-tree policy
|
|
32
32
|
|
|
@@ -88,7 +88,7 @@ After the clean-tree check, `prepareLiveCheckout`:
|
|
|
88
88
|
- Succeeds → branch exists locally → plain `git checkout <branchName>` (no `--force`, no `-B`, no pull, no reset). The operator owns the checkout state; if they have local commits or a stale tip relative to `origin/<branchName>`, those are preserved.
|
|
89
89
|
- Fails → `git checkout -b <branchName>` (new branch from the **current HEAD**, not `origin/<mainRef>`).
|
|
90
90
|
|
|
91
|
-
**No `git fetch
|
|
91
|
+
**No implicit `git fetch`; branch from HEAD (issue #226).** By default, live mode does **not** run a pre-checkout `git fetch origin <mainRef>` and does **not** seed new branches from `origin/<mainRef>`; the only fetch exception is the explicit, safe [`liveCheckoutAutoFreshen`](#6b-opt-in-auto-freshen-livecheckoutautofreshen-w-mrdlcud2000e630e) opt-in. The operator's checked-out HEAD is otherwise the baseline. On a Scalar/GVFS-managed ADO repo, both fetch and `git checkout -b <branch> origin/<mainRef>` can trigger unauthenticated on-demand blob fetching, so branching from HEAD avoids that dependency. `mainRef` remains validated but does not seed the branch. **Worktree mode is unaffected** — it still branches from `origin/<mainRef>`.
|
|
92
92
|
|
|
93
93
|
PR-source live dispatches (`meta.branch` set) and shared-branch live dispatches (`meta.branchStrategy === 'shared-branch'`) flow through the same code path with no special case. If the operator already has a PR branch checked out at a different SHA than `origin/<branch>`, the engine will not fast-forward it — that is the intended contract (see Open Q5 in the source PRD). Resolve manually with `git pull --ff-only` or commit the local divergence first.
|
|
94
94
|
|
|
@@ -121,7 +121,7 @@ Like the blob-fetch case this is **structural, not transient** — it does *not*
|
|
|
121
121
|
|
|
122
122
|
Live mode shares one checkout per project. There is no pool to recycle, no quarantine directory, no per-WI subdirectory under the project root. The mutating-concurrency cap (Guarantee 1) is the only isolation mechanism: agents take turns in the same directory.
|
|
123
123
|
|
|
124
|
-
Pool short-circuits
|
|
124
|
+
Pool short-circuits in `engine.js` and `engine/cleanup.js` gate on `worktreePath` truthiness and `!liveMode`, so borrow / return / orphan-GC execute zero git commands for live projects.
|
|
125
125
|
|
|
126
126
|
### 5. Refuse on mid-operation / detached HEAD (engine never aborts the operator's in-progress op)
|
|
127
127
|
|
|
@@ -225,7 +225,7 @@ Live-mode agents run **in-place** in the operator's checkout, so when a dispatch
|
|
|
225
225
|
- **Fallback notify (only when a safe switch is impossible).** If git declines the plain checkout — most likely because the agent left uncommitted changes a checkout would overwrite — the refusal is **honored**: the tree is left exactly as the agent left it and a deduped `live-checkout-branch-<dispatchId>` inbox alert tells the operator how to switch back manually (`git -C <localPath> checkout <originalRef>`). The engine never forces the switch. An **unexpected** restore error (git missing, repo corruption, a GVFS blob fetch on the switch-back) now also writes this alert, so a non-refusal failure never silently strands the tree.
|
|
226
226
|
- **Terminal-failure alert.** When the dispatch ends in a non-success terminal state, a deduped `live-checkout-failed-<dispatchId>` inbox alert is written so the operator knows a live-mode run failed inside their own checkout (where any partial work is visible). This is independent of the restore and fires even when the restore itself succeeds.
|
|
227
227
|
|
|
228
|
-
|
|
228
|
+
**Restore itself** only switches branches and may auto-commit WIP on the engine's agent branch; it never resets, cleans, stashes, or passes `--force`. The configured pre-spawn auto-stash/auto-reset policies are the explicit exceptions described under Guarantee 2.
|
|
229
229
|
|
|
230
230
|
## Create-PR chip safety (CC-initiated, separate from the dispatch path)
|
|
231
231
|
|
|
@@ -290,6 +290,10 @@ Hybrid mode routes only selected canonical work-item types on the live checkout;
|
|
|
290
290
|
|
|
291
291
|
`type` may be a string or array, but every entry must be a live-capable canonical `WORK_TYPE`. `build-and-test` is a playbook alias and is normalized to `test` only for backward compatibility. `autoDispatch` must be boolean and requires `test` in the configured types; the generated WI has type `test`, carries structured `targetPr` / `pr_id` / URL-reference fields, targets the source PR branch, and renders the `build-and-test` playbook. Successful direct PR-backed `fix` and `build-fix-complex` dispatches, including human-feedback fixes, use the dispatch ID as their dedup key and do not add a nonexistent WI dependency.
|
|
292
292
|
|
|
293
|
+
#### Automatic validation deduplication
|
|
294
|
+
|
|
295
|
+
`autoDispatchLiveValidationWi` keeps at most one non-terminal validation for a source WI and for a canonical PR revision across the central and project SQL scopes. Generated WIs persist `meta.liveValidationPrId` and, when known, `meta.liveValidationHeadSha`; another completion for the same PR and head is suppressed, while a new head may create a fresh validation. Fix completions prefer verified remote-head evidence and otherwise use the tracked PR head. Legacy validation WIs without a stored head conservatively block duplicates until terminal. The comparison and insert run in one work-item-store transaction.
|
|
296
|
+
|
|
293
297
|
### Enabling auto-stash on dirty (config.json)
|
|
294
298
|
|
|
295
299
|
```jsonc
|
|
@@ -375,6 +379,7 @@ Live-checkout mode is deliberately small. These are NOT supported and will not b
|
|
|
375
379
|
| `engine.js` — `onAgentClose` live-mode restore wiring | Calls `restoreLiveCheckoutAtDispatchEnd` on every terminal result (P-d9e6b2c4). |
|
|
376
380
|
| `engine/cli.js` — orphan / reattach restore | Fires the dispatch-end restore (via `maybeRestoreLiveCheckoutFromRecord`) from the persisted record on the engine-restart completion path (P-d9e6b2c4; unified PL-live-checkout-reliability-hardening). |
|
|
377
381
|
| `engine/timeout.js` — `completeFromOutput` + orphan-sweep restore | Fires `maybeRestoreLiveCheckoutFromRecord` when a re-attached live dispatch is reaped post-restart — closes the gap where these paths had no restore wiring (PL-live-checkout-reliability-hardening). |
|
|
382
|
+
| `engine/lifecycle.js` — `autoDispatchLiveValidationWi` | Creates PR-targeted validation WIs and transactionally deduplicates them by source WI plus canonical PR identity/head across central and project scopes. |
|
|
378
383
|
| `engine.js` — dispatcher `liveProjectsInUse` set | Per-project mutating-concurrency cap (P-a3f9b205). |
|
|
379
384
|
| `engine.js` — worktree-pool / orphan-GC short-circuits | `worktreePath===null` no-ops in live mode (P-a3f9b206). |
|
|
380
385
|
| `engine/cleanup.js` — `runPeriodicWorktreeSweep` live filter | Excludes live-checkout projects from the registry-derived periodic worktree GC so the operator's primary checkout never enters the GC decision surface (PL-live-checkout-reliability-hardening). |
|
|
@@ -9,10 +9,10 @@ All dispatch decisions happen inside `engine.js#discoverFromPrs` once per discov
|
|
|
9
9
|
| # | Cause | Trigger (PR state) | Per-cause gate flag | Hard-stop kill-switch | Other gates |
|
|
10
10
|
|---|------------------------|---------------------------------------------------|----------------------------|-----------------------|-----------------------------------------------------------|
|
|
11
11
|
| 1 | Initial minion review | `reviewStatus === 'pending'` | `autoReviewPrs` | `autoFixPaused`* | `evalLoop`; provider polling enabled |
|
|
12
|
-
| 2 | Human-feedback fix | `humanFeedback.pendingFix`
|
|
12
|
+
| 2 | Human-feedback fix | `humanFeedback.pendingFix || hasCoalescedFeedback` | `autoFixHumanComments` | `autoFixPaused` | provider polling enabled; `!fixDispatched` |
|
|
13
13
|
| 3 | Minion re-review | `reviewStatus === 'waiting'` after fix push | `autoReReviewPrs` | `autoFixPaused`* | `evalLoop`; provider polling enabled |
|
|
14
|
-
| 4 | Minion review-feedback fix | `reviewStatus === 'changes-requested'` | `autoFixReviewFeedback` | `autoFixPaused` | `evalLoop`;
|
|
15
|
-
| 5 | Build-failure fix | `buildStatus === 'failing'` + grace expired | `autoFixBuilds` | `autoFixPaused` |
|
|
14
|
+
| 4 | Minion review-feedback fix | `reviewStatus === 'changes-requested'` | `autoFixReviewFeedback` | `autoFixPaused` | `evalLoop`; polling; `!awaitingReReview`; `!fixDispatched` |
|
|
15
|
+
| 5 | Build-failure fix | `buildStatus === 'failing'` + grace expired | `autoFixBuilds` | `autoFixPaused` | polling; `_buildFixPushedAt` grace; `!fixDispatched` |
|
|
16
16
|
| 6 | Merge-conflict fix | `_mergeConflict === true` + `status === 'active'` | `autoFixConflicts` | `autoFixPaused` | provider polling enabled; `!fixDispatched` in same pass |
|
|
17
17
|
|
|
18
18
|
\* `autoFixPaused` is the auto-**fix** kill-switch. It forces sites 2, 4, 5, and 6 off, but is **not** wired to suppress review dispatch (sites 1 and 3) — review verdicts stay fresh during a fix-storm incident. To halt review dispatch, clear `autoReviewPrs` / `autoReReviewPrs` directly, or set `pollingPaused: true` (which forces every per-PR auto-dispatch gate inert by zeroing `pollEnabled`).
|
|
@@ -29,19 +29,19 @@ A successful review dispatch that posts no `VERDICT:` comment and is not a recog
|
|
|
29
29
|
`discoverFromPrs()` evaluates PR review/fix triggers in a fixed order during each discovery pass:
|
|
30
30
|
|
|
31
31
|
1. Initial minion review (`reviewStatus === 'pending'`)
|
|
32
|
-
2. Human feedback (`humanFeedback.pendingFix` or
|
|
32
|
+
2. Human feedback (`humanFeedback.pendingFix` or `hasCoalescedFeedback`)
|
|
33
33
|
3. Minion re-review (`reviewStatus === 'waiting'` after a fix)
|
|
34
34
|
4. Minion review feedback (`changes-requested`)
|
|
35
35
|
5. Build failure (`buildStatus === 'failing'`)
|
|
36
36
|
6. Merge conflict (`_mergeConflict`)
|
|
37
37
|
|
|
38
|
-
When multiple problems coexist, earlier triggers get the first chance to enqueue work. The local `fixDispatched` flag is declared before the initial review trigger and set after first-review, human-feedback, review-feedback, and build-failure dispatches.
|
|
38
|
+
When multiple problems coexist, earlier triggers get the first chance to enqueue work. The local `fixDispatched` flag is declared before the initial review trigger and set after first-review, human-feedback, review-feedback, and build-failure dispatches. Each later trigger checks `!fixDispatched`, so those sites suppress all subsequent review/fix work for that PR in the same discovery pass. Re-review is the exception: it checks `!fixDispatched` before enqueueing but does not set the flag afterward. Consequently, a re-review may enqueue alongside a later build-failure fix or, when no build fix is queued, a merge-conflict fix in the same pass.
|
|
39
39
|
|
|
40
40
|
The engine does not cap review→fix cycles or build-fix attempts. Each trigger evaluates its own gates on every discovery pass; loops stop only when the underlying condition clears (reviewer approves, build passes, conflict resolves, human feedback handled). Operators who need to halt automation on a runaway PR have three escalating tools: (1) clear the relevant per-cause flag (`evalLoop`, `autoFixBuilds`, `autoFixConflicts`, `autoFixHumanComments`, `autoFixReviewFeedback`, `autoReviewPrs`, `autoReReviewPrs`); (2) flip the `autoFixPaused` master kill-switch to halt every auto-**fix** dispatch (sites B, C, D, and human-comment fix) at once while leaving review verdicts and polling fresh — Dashboard → Settings → Auto-fix & Review Loop or `POST /api/engine/auto-fix/pause`; (3) flip `pollingPaused` to halt PR polling entirely, which also forces every per-PR auto-dispatch gate inert. Per-PR per-cause noop pauses (`_noOpFixes[cause].paused`) are an orthogonal recovery surface — see §4E and `POST /api/pull-requests/clear-paused-cause`. See [docs/pr-auto-fix-dispatch.md](pr-auto-fix-dispatch.md) for the full site × gate × kill-switch reference table.
|
|
41
41
|
|
|
42
42
|
### A. Human comments (`humanFeedback.pendingFix`)
|
|
43
43
|
|
|
44
|
-
- Gate: `pendingFix ||
|
|
44
|
+
- Gate: `pendingFix || hasCoalescedFeedback` + not already dispatched/on cooldown
|
|
45
45
|
- Agent comments filtered out via `_isNonActionableComment()` (`engine/github.js`, `engine/ado.js`) — composes preview/bot body checks and the structural Minions-author check from `engine/comment-classifier.js`. The structural check matches the `<!-- minions:agent=<id> kind=<kind> -->` HTML marker on the body's first line (`hasMinionsMarker`); on GitHub it must combine with `viewerDidAuthor === true` (anti-spoof), on ADO with a `config.engine.minionsAdoIdentities` author match. Marker presence alone never classifies a comment as agent-authored on either platform.
|
|
46
46
|
- Coalesces multiple comments arriving during cooldown into single fix
|
|
47
47
|
- Routes to author
|
|
@@ -91,8 +91,8 @@ A "branch unchanged" no-op report for a `BUILD_FAILURE`-cause fix used to be con
|
|
|
91
91
|
## 5. Fix completes
|
|
92
92
|
|
|
93
93
|
- `updatePrAfterFix()` (lifecycle.js) sets `reviewStatus = 'waiting'` + `fixedAt = ts()`
|
|
94
|
-
- Clears `humanFeedback.pendingFix`
|
|
95
|
-
- `awaitingReReview`
|
|
94
|
+
- Clears `humanFeedback.pendingFix` only when it still identifies the completed dispatch's comment; newer feedback is preserved
|
|
95
|
+
- `awaitingReReview` (`waiting` + `fixedAt`) suppresses stale review-feedback fixes; fresh human feedback and independent build/conflict causes retain their own gates
|
|
96
96
|
|
|
97
97
|
## 6. Re-review cycle
|
|
98
98
|
|
|
@@ -115,7 +115,7 @@ A "branch unchanged" no-op report for a `BUILD_FAILURE`-cause fix used to be con
|
|
|
115
115
|
| Scenario | Guard |
|
|
116
116
|
|---|---|
|
|
117
117
|
| Simultaneous review + fix | `activePrIds` — skip PR if any dispatch in-flight |
|
|
118
|
-
|
|
|
118
|
+
| Same-pass review/fix fan-out | `fixDispatched` — initial review and successful fix sites suppress later work; re-review checks but does not set the flag, so it can co-dispatch with one later build/conflict fix |
|
|
119
119
|
| Branch write conflict | `isBranchActive()` mutex |
|
|
120
120
|
| Fix while awaiting re-review | `awaitingReReview` (waiting + fixedAt) |
|
|
121
121
|
| Build fix before CI runs | `_buildFixPushedAt` grace period (10min) |
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2424",
|
|
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"
|