@yemi33/minions 0.1.2258 → 0.1.2260
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/dashboard.js +12 -5
- package/engine/dispatch.js +1 -1
- package/engine/pipeline.js +1 -1
- package/engine/queries.js +2 -0
- package/engine/shared.js +31 -6
- package/engine.js +2 -0
- package/package.json +1 -1
package/dashboard.js
CHANGED
|
@@ -13390,7 +13390,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
13390
13390
|
}
|
|
13391
13391
|
}},
|
|
13392
13392
|
|
|
13393
|
-
{ method: 'POST', path: '/api/pull-requests/delete', desc: 'Remove a PR from tracking', params: 'id, project?', handler: async (req, res) => {
|
|
13393
|
+
{ method: 'POST', path: '/api/pull-requests/delete', desc: 'Remove a PR from tracking (sets userDeleted tombstone so pollers do not re-add it)', params: 'id, project?', handler: async (req, res) => {
|
|
13394
13394
|
const body = await readBody(req);
|
|
13395
13395
|
const { id } = body;
|
|
13396
13396
|
if (!id) return jsonReply(res, 400, { error: 'id required' });
|
|
@@ -13403,12 +13403,19 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
13403
13403
|
let found = false;
|
|
13404
13404
|
for (const prPath of prPaths) {
|
|
13405
13405
|
if (found) break;
|
|
13406
|
-
|
|
13406
|
+
// Issue #384: use a tombstone (userDeleted:true) instead of splice so
|
|
13407
|
+
// the next poller cycle cannot re-add the PR. The entry stays in the
|
|
13408
|
+
// file but is filtered from API responses and skipped by pollers.
|
|
13409
|
+
shared.mutatePullRequests(prPath, (prs) => {
|
|
13407
13410
|
if (!Array.isArray(prs)) return prs;
|
|
13408
|
-
const
|
|
13409
|
-
if (
|
|
13411
|
+
const pr = prs.find(p => p.id === id);
|
|
13412
|
+
if (pr) {
|
|
13413
|
+
pr.userDeleted = true;
|
|
13414
|
+
pr.userDeletedAt = shared.ts();
|
|
13415
|
+
found = true;
|
|
13416
|
+
}
|
|
13410
13417
|
return prs;
|
|
13411
|
-
}
|
|
13418
|
+
});
|
|
13412
13419
|
}
|
|
13413
13420
|
if (!found) return jsonReply(res, 404, { error: 'PR not found' });
|
|
13414
13421
|
invalidateStatusCache();
|
package/engine/dispatch.js
CHANGED
|
@@ -1123,7 +1123,7 @@ function cleanDispatchEntries(matchFn) {
|
|
|
1123
1123
|
const { execFileSync } = require('child_process');
|
|
1124
1124
|
execFileSync('taskkill', ['/PID', String(safePid), '/F', '/T'], { stdio: 'pipe', timeout: 5000, windowsHide: true });
|
|
1125
1125
|
} else {
|
|
1126
|
-
|
|
1126
|
+
shared.killGracefully({ pid: safePid }, 5000);
|
|
1127
1127
|
}
|
|
1128
1128
|
} catch { /* may already be dead */ }
|
|
1129
1129
|
}
|
package/engine/pipeline.js
CHANGED
|
@@ -722,7 +722,7 @@ async function executeApiStage(stage, stageState, run) {
|
|
|
722
722
|
const timeoutMs = ENGINE_DEFAULTS.pipelineApiTimeoutMs;
|
|
723
723
|
|
|
724
724
|
for (const call of calls) {
|
|
725
|
-
const port = shared.readDashboardPortFile(MINIONS_DIR)?.port ||
|
|
725
|
+
const port = shared.readDashboardPortFile(MINIONS_DIR)?.port || 7331;
|
|
726
726
|
const url = `http://localhost:${port}${call.endpoint}`;
|
|
727
727
|
const body = typeof call.body === 'string' ? call.body : JSON.stringify(call.body || {});
|
|
728
728
|
|
package/engine/queries.js
CHANGED
|
@@ -981,6 +981,8 @@ function getPullRequests(config) {
|
|
|
981
981
|
const groupsById = new Map();
|
|
982
982
|
for (const pr of sqlPrs) {
|
|
983
983
|
if (!pr || !pr.id) continue;
|
|
984
|
+
// Issue #384: skip tombstoned records (user explicitly deleted)
|
|
985
|
+
if (pr.userDeleted === true) continue;
|
|
984
986
|
if (!groupsById.has(pr.id)) {
|
|
985
987
|
const g = [];
|
|
986
988
|
groupsById.set(pr.id, g);
|
package/engine/shared.js
CHANGED
|
@@ -5720,14 +5720,32 @@ function resolveProjectRootDir(localPath, minionsDir) {
|
|
|
5720
5720
|
* unaffected — it uses GH_TOKEN / the OS credential store, not files under the
|
|
5721
5721
|
* home — and the operator's real `~/.copilot` (interactive copilot) is untouched.
|
|
5722
5722
|
*
|
|
5723
|
-
* Placed
|
|
5724
|
-
*
|
|
5725
|
-
*
|
|
5726
|
-
*
|
|
5727
|
-
*
|
|
5723
|
+
* Placed OUTSIDE the repo so concurrent git branch switches in the working tree
|
|
5724
|
+
* can never delete or dirty it, on the MINIONS_DIR volume (copilot's session-store
|
|
5725
|
+
* can grow to GBs, so keep it off a possibly-full system drive). Stable path so
|
|
5726
|
+
* copilot session resume (`--resume`) stays consistent across spawns. Falls back
|
|
5727
|
+
* to the user home when no minionsDir is given.
|
|
5728
|
+
*
|
|
5729
|
+
* Base selection is cross-platform (W-copilot-home-posix-root): on Windows the
|
|
5730
|
+
* MINIONS_DIR drive root (`C:\`, `D:\`, or a UNC share root) is user-writable, so
|
|
5731
|
+
* we anchor there. On POSIX the filesystem root (`/`) is NOT user-writable — a
|
|
5732
|
+
* home placed there can never be created (`mkdir` EACCES), `ensureAgentCopilotHome`
|
|
5733
|
+
* fail-opens and returns the uncreatable path anyway, and every spawned
|
|
5734
|
+
* `copilot --acp` / copilot agent then inherits a `COPILOT_HOME` it can't use and
|
|
5735
|
+
* exits code 1 silently (surfaced in CC as "Load failed"). So when the drive root
|
|
5736
|
+
* is the bare POSIX root we fall back to the user home — repo-external, writable,
|
|
5737
|
+
* and on the user's own volume.
|
|
5728
5738
|
*/
|
|
5729
5739
|
function resolveAgentCopilotHome(minionsDir) {
|
|
5730
|
-
|
|
5740
|
+
let base;
|
|
5741
|
+
if (minionsDir) {
|
|
5742
|
+
const root = path.parse(path.resolve(String(minionsDir))).root;
|
|
5743
|
+
// The POSIX filesystem root ('/') is not user-writable; Windows drive/UNC
|
|
5744
|
+
// roots are. Anchor at the user home in the unwritable-root case.
|
|
5745
|
+
base = (root === '/' || root === path.sep) ? os.homedir() : root;
|
|
5746
|
+
} else {
|
|
5747
|
+
base = os.homedir();
|
|
5748
|
+
}
|
|
5731
5749
|
return path.join(base, '.minions-agent-copilot-home');
|
|
5732
5750
|
}
|
|
5733
5751
|
|
|
@@ -7003,6 +7021,13 @@ function upsertPullRequestRecord(prPath, entry, { project = null, itemId = null,
|
|
|
7003
7021
|
mutatePullRequests(prPath, (prs) => {
|
|
7004
7022
|
normalizePrRecords(prs, project);
|
|
7005
7023
|
let target = findPrRecord(prs, normalizedEntry, project);
|
|
7024
|
+
// Issue #384: tombstoned records (userDeleted:true) must not be re-activated
|
|
7025
|
+
// by any poller path. Return skipped so reconcilePrs / shared-branch-reconcile
|
|
7026
|
+
// cannot resurrect a PR the user explicitly removed.
|
|
7027
|
+
if (target && target.userDeleted === true) {
|
|
7028
|
+
skipped = true;
|
|
7029
|
+
return prs;
|
|
7030
|
+
}
|
|
7006
7031
|
if (!target && typeof beforeInsert === 'function' && beforeInsert(prs, normalizedEntry) === false) {
|
|
7007
7032
|
skipped = true;
|
|
7008
7033
|
return prs;
|
package/engine.js
CHANGED
|
@@ -6622,6 +6622,8 @@ async function discoverFromPrs(config, project) {
|
|
|
6622
6622
|
|
|
6623
6623
|
for (const pr of prs) {
|
|
6624
6624
|
if (pr.status !== PR_STATUS.ACTIVE) continue;
|
|
6625
|
+
// Issue #384: skip tombstoned PRs (user explicitly deleted via dashboard)
|
|
6626
|
+
if (pr.userDeleted === true) continue;
|
|
6625
6627
|
if (shared.isContextOnlyPrRecord(pr)) {
|
|
6626
6628
|
_logPrDispatchSkipOnce(pr, 'context-only');
|
|
6627
6629
|
continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2260",
|
|
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"
|