@yemi33/minions 0.1.1019 → 0.1.1021
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 +37 -0
- package/engine/github.js +35 -8
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,42 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.1021 (2026-04-16)
|
|
4
|
+
|
|
5
|
+
### Features
|
|
6
|
+
- route implement items to dedicated implement playbook (#1115)
|
|
7
|
+
|
|
8
|
+
### Fixes
|
|
9
|
+
- mark PR abandoned on 404 instead of silently retrying each tick
|
|
10
|
+
- replace undefined PROJECTS with config.projects in checkWatches (#1108)
|
|
11
|
+
- write permission for publish workflow
|
|
12
|
+
- run tests inline and post check runs for publish PRs
|
|
13
|
+
- add maxBuffer to all GitHub CLI spawns + paginate PR list (#1130)
|
|
14
|
+
- add required CI checks for PRs + update publish for auto-merge
|
|
15
|
+
- revert to PR merge now that stale status check is removed
|
|
16
|
+
- guard live review check against undefined vote/state values (#1132)
|
|
17
|
+
- push version bump directly to master instead of via PR
|
|
18
|
+
- add push-triggered CI for chore/publish branches
|
|
19
|
+
- publish workflow chore PRs failing to merge
|
|
20
|
+
- harden KB ordering
|
|
21
|
+
- harden audited state transitions
|
|
22
|
+
|
|
23
|
+
### Other
|
|
24
|
+
- chore: test publish after removing stale status check
|
|
25
|
+
- chore: trigger publish test
|
|
26
|
+
- chore: test publish workflow fix
|
|
27
|
+
- chore: trigger publish workflow test
|
|
28
|
+
|
|
29
|
+
## 0.1.1020 (2026-04-16)
|
|
30
|
+
|
|
31
|
+
### Features
|
|
32
|
+
- route implement items to dedicated implement playbook (#1115)
|
|
33
|
+
|
|
34
|
+
### Fixes
|
|
35
|
+
- add maxBuffer to all GitHub CLI spawns + paginate PR list (#1130)
|
|
36
|
+
- replace undefined PROJECTS with config.projects in checkWatches (#1108)
|
|
37
|
+
- write permission for publish workflow
|
|
38
|
+
- run tests inline and post check runs for publish PRs
|
|
39
|
+
|
|
3
40
|
## 0.1.1019 (2026-04-16)
|
|
4
41
|
|
|
5
42
|
### Features
|
package/engine/github.js
CHANGED
|
@@ -20,6 +20,11 @@ function engine() {
|
|
|
20
20
|
let _dispatch = null;
|
|
21
21
|
function dispatchModule() { if (!_dispatch) _dispatch = require('./dispatch'); return _dispatch; }
|
|
22
22
|
|
|
23
|
+
// ─── Constants ──────────────────────────────────────────────────────────────
|
|
24
|
+
|
|
25
|
+
// 10 MB — prevents maxBuffer exceeded errors on repos with many open PRs.
|
|
26
|
+
// Node.js default is 1 MB which overflows when GitHub API returns 100+ PR objects.
|
|
27
|
+
const GH_MAX_BUFFER = 10 * 1024 * 1024;
|
|
23
28
|
// ─── Helpers ────────────────────────────────────────────────────────────────
|
|
24
29
|
|
|
25
30
|
function isGitHub(project) {
|
|
@@ -83,11 +88,19 @@ const isGhThrottled = () => _ghThrottle.isThrottled();
|
|
|
83
88
|
/** Returns a snapshot of the current GitHub throttle state. */
|
|
84
89
|
const getGhThrottleState = () => _ghThrottle.getState();
|
|
85
90
|
|
|
86
|
-
/**
|
|
87
|
-
|
|
91
|
+
/** Sentinel returned by ghApi when the resource does not exist (HTTP 404). */
|
|
92
|
+
const GH_NOT_FOUND = Object.freeze({ _notFound: true });
|
|
93
|
+
|
|
94
|
+
/** Run a `gh api` call and parse JSON result. Returns null on failure, GH_NOT_FOUND on 404.
|
|
95
|
+
* @param {string} endpoint - API endpoint (e.g. '/pulls?state=open')
|
|
96
|
+
* @param {string} slug - owner/repo slug
|
|
97
|
+
* @param {object} [opts] - Options: { paginate: boolean, timeout: number }
|
|
98
|
+
*/
|
|
99
|
+
async function ghApi(endpoint, slug, opts = {}) {
|
|
88
100
|
try {
|
|
89
|
-
const
|
|
90
|
-
const
|
|
101
|
+
const paginateFlag = opts.paginate ? ' --paginate' : '';
|
|
102
|
+
const cmd = `gh api${paginateFlag} "repos/${slug}${endpoint}"`;
|
|
103
|
+
const result = await execAsync(cmd, { timeout: opts.timeout || 30000, encoding: 'utf-8', maxBuffer: GH_MAX_BUFFER });
|
|
91
104
|
const parsed = JSON.parse(result);
|
|
92
105
|
_ghThrottle.recordSuccess();
|
|
93
106
|
return parsed;
|
|
@@ -100,6 +113,10 @@ async function ghApi(endpoint, slug) {
|
|
|
100
113
|
const retryAfterMs = secMatch ? parseInt(secMatch[1], 10) * 1000 : 0;
|
|
101
114
|
_ghThrottle.recordThrottle(retryAfterMs);
|
|
102
115
|
}
|
|
116
|
+
if (/HTTP 404|Not Found/i.test(msg)) {
|
|
117
|
+
log('warn', `GitHub API error (${endpoint}): ${e.message}`);
|
|
118
|
+
return GH_NOT_FOUND;
|
|
119
|
+
}
|
|
103
120
|
log('warn', `GitHub API error (${endpoint}): ${e.message}`);
|
|
104
121
|
return null;
|
|
105
122
|
}
|
|
@@ -152,7 +169,7 @@ async function fetchGhBuildErrorLog(slug, failedRuns) {
|
|
|
152
169
|
// Always fetch job log — annotations alone often lack test failure details
|
|
153
170
|
try {
|
|
154
171
|
const cmd = `gh api "repos/${slug}/actions/jobs/${run.id}/logs" 2>&1`;
|
|
155
|
-
const result = await execAsync(cmd, { timeout: 15000, encoding: 'utf-8' });
|
|
172
|
+
const result = await execAsync(cmd, { timeout: 15000, encoding: 'utf-8', maxBuffer: GH_MAX_BUFFER });
|
|
156
173
|
if (result && !result.includes('Not Found')) {
|
|
157
174
|
logParts.push(`--- ${run.name || 'Check'} (log) ---\n${result}`);
|
|
158
175
|
}
|
|
@@ -295,6 +312,15 @@ async function pollPrStatus(config) {
|
|
|
295
312
|
const totalUpdated = await forEachActiveGhPr(config, async (project, pr, prNum, slug) => {
|
|
296
313
|
const prData = await ghApi(`/pulls/${prNum}`, slug);
|
|
297
314
|
if (!prData) return false;
|
|
315
|
+
if (prData === GH_NOT_FOUND) {
|
|
316
|
+
// PR no longer exists — mark abandoned so it stops being polled
|
|
317
|
+
if (pr.status !== PR_STATUS.ABANDONED) {
|
|
318
|
+
pr.status = PR_STATUS.ABANDONED;
|
|
319
|
+
log('info', `PR ${pr.id} returned 404 — marking abandoned`);
|
|
320
|
+
return true;
|
|
321
|
+
}
|
|
322
|
+
return false;
|
|
323
|
+
}
|
|
298
324
|
|
|
299
325
|
let updated = false;
|
|
300
326
|
|
|
@@ -471,7 +497,7 @@ async function pollPrStatus(config) {
|
|
|
471
497
|
if (autoComplete) {
|
|
472
498
|
try {
|
|
473
499
|
const mergeMethod = ['squash', 'merge', 'rebase'].includes(config.engine?.prMergeMethod) ? config.engine.prMergeMethod : 'squash';
|
|
474
|
-
await execAsync(`gh pr merge ${prNum} --${mergeMethod} --repo ${slug} --delete-branch`, { timeout: 30000, encoding: 'utf-8' });
|
|
500
|
+
await execAsync(`gh pr merge ${prNum} --${mergeMethod} --repo ${slug} --delete-branch`, { timeout: 30000, encoding: 'utf-8', maxBuffer: GH_MAX_BUFFER });
|
|
475
501
|
pr._autoCompleted = true;
|
|
476
502
|
log('info', `Auto-completed PR ${pr.id}: builds green + review approved → merged (${mergeMethod})`);
|
|
477
503
|
updated = true;
|
|
@@ -612,8 +638,8 @@ async function reconcilePrs(config) {
|
|
|
612
638
|
} catch { continue; }
|
|
613
639
|
}
|
|
614
640
|
|
|
615
|
-
// Fetch open PRs
|
|
616
|
-
const prsData = await ghApi('/pulls?state=open&per_page=100', slug);
|
|
641
|
+
// Fetch open PRs — paginate to handle repos with >100 open PRs
|
|
642
|
+
const prsData = await ghApi('/pulls?state=open&per_page=100', slug, { paginate: true, timeout: 60000 });
|
|
617
643
|
if (!prsData || !Array.isArray(prsData)) {
|
|
618
644
|
recordSlugFailure(slug);
|
|
619
645
|
continue;
|
|
@@ -760,4 +786,5 @@ module.exports = {
|
|
|
760
786
|
resetSlugBackoff,
|
|
761
787
|
_ghPollBackoff,
|
|
762
788
|
_ghThrottle, // exported for testing
|
|
789
|
+
GH_MAX_BUFFER, // exported for testing
|
|
763
790
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1021",
|
|
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"
|