@yemi33/minions 0.1.1568 → 0.1.1569
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 +5 -0
- package/engine/lifecycle.js +30 -1
- package/engine/shared.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
package/engine/lifecycle.js
CHANGED
|
@@ -892,6 +892,23 @@ function parseReviewVerdict(text) {
|
|
|
892
892
|
return null;
|
|
893
893
|
}
|
|
894
894
|
|
|
895
|
+
/**
|
|
896
|
+
* Detect "idempotent bailout" output from a review agent — the agent saw a
|
|
897
|
+
* prior review on the PR (or the same dispatchKey re-fired) and chose to bail
|
|
898
|
+
* rather than spam a duplicate comment.
|
|
899
|
+
*
|
|
900
|
+
* Such output is intentionally short and contains no VERDICT keyword. Treating
|
|
901
|
+
* it as a retryable failure burns _retryCount and eventually flips the WI to
|
|
902
|
+
* status=failed even though the original review was successfully posted (#1770).
|
|
903
|
+
*
|
|
904
|
+
* @param {string} text - Agent output / resultSummary
|
|
905
|
+
* @returns {boolean}
|
|
906
|
+
*/
|
|
907
|
+
function isReviewBailout(text) {
|
|
908
|
+
if (!text || typeof text !== 'string') return false;
|
|
909
|
+
return /bail(ing)?\s+out/i.test(text) || /already\s+posted/i.test(text);
|
|
910
|
+
}
|
|
911
|
+
|
|
895
912
|
async function updatePrAfterReview(agentId, pr, project, config, resultSummary) {
|
|
896
913
|
|
|
897
914
|
if (!pr?.id) return;
|
|
@@ -1657,9 +1674,18 @@ async function runPostCompletionHooks(dispatchItem, agentId, code, stdout, confi
|
|
|
1657
1674
|
// same pattern as plan-to-prd (#893): updateWorkItemStatus deletes _retryCount, so the check
|
|
1658
1675
|
// must read/increment it before that happens. Also sets skipDoneStatus so completedAt isn't
|
|
1659
1676
|
// written and then left dangling when status is reset to pending for retry.
|
|
1677
|
+
//
|
|
1678
|
+
// (#1770) Idempotent bailout: if the agent explicitly bailed because a review was
|
|
1679
|
+
// already posted (e.g. the WI got re-dispatched before lifecycle marked the first
|
|
1680
|
+
// run done), treat the run as success — fall through to mark DONE without retry.
|
|
1681
|
+
// Without this, the second run produces no VERDICT, _retryCount increments,
|
|
1682
|
+
// and after 3 such bailouts the WI flips to status=failed even though the
|
|
1683
|
+
// original review was posted on the first run.
|
|
1660
1684
|
if (effectiveSuccess && type === WORK_TYPE.REVIEW && meta?.item?.id) {
|
|
1661
1685
|
const verdict = parseReviewVerdict(resultSummary);
|
|
1662
|
-
if (!verdict) {
|
|
1686
|
+
if (!verdict && isReviewBailout(resultSummary)) {
|
|
1687
|
+
log('info', `Review ${meta.item.id} bailed out (review already posted) — treating as DONE without retry`);
|
|
1688
|
+
} else if (!verdict) {
|
|
1663
1689
|
skipDoneStatus = true;
|
|
1664
1690
|
const wiPath = resolveWorkItemPath(meta);
|
|
1665
1691
|
if (wiPath) {
|
|
@@ -1672,6 +1698,8 @@ async function runPostCompletionHooks(dispatchItem, agentId, code, stdout, confi
|
|
|
1672
1698
|
if (retries < ENGINE_DEFAULTS.maxRetries) {
|
|
1673
1699
|
w.status = WI_STATUS.PENDING;
|
|
1674
1700
|
w._retryCount = retries + 1;
|
|
1701
|
+
w._lastRetryAt = ts();
|
|
1702
|
+
w._lastRetryReason = 'no review verdict';
|
|
1675
1703
|
delete w.dispatched_at;
|
|
1676
1704
|
delete w.completedAt;
|
|
1677
1705
|
log('warn', `Review ${meta.item.id} completed without verdict — auto-retry ${retries + 1}/${ENGINE_DEFAULTS.maxRetries}`);
|
|
@@ -2162,6 +2190,7 @@ module.exports = {
|
|
|
2162
2190
|
updateMetrics,
|
|
2163
2191
|
parseAgentOutput,
|
|
2164
2192
|
parseReviewVerdict,
|
|
2193
|
+
isReviewBailout,
|
|
2165
2194
|
parseStructuredCompletion,
|
|
2166
2195
|
runPostCompletionHooks,
|
|
2167
2196
|
syncPrdFromPrs,
|
package/engine/shared.js
CHANGED
|
@@ -758,6 +758,7 @@ const ENGINE_DEFAULTS = {
|
|
|
758
758
|
evalMaxIterations: 3, // max review→fix cycles before escalating to human
|
|
759
759
|
evalMaxCost: null, // USD ceiling per work item across all eval iterations; null = no limit (gather baseline data first)
|
|
760
760
|
maxRetries: 3, // max dispatch retries before marking work item as failed
|
|
761
|
+
minRetryGapMs: 120000, // 2min — minimum gap between retry dispatches for the same work item; prevents tight retry loops when an idempotent agent (e.g. review bailing out on a duplicate) cannot produce the expected output (#1770)
|
|
761
762
|
pipelineApiRetries: 2, // max attempts for pipeline API calls
|
|
762
763
|
pipelineApiRetryDelay: 2000, // ms delay between pipeline API retries
|
|
763
764
|
versionCheckInterval: 3600000, // 1 hour — how often to check npm for updates (ms)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1569",
|
|
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"
|