@yemi33/minions 0.1.2257 → 0.1.2259

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 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
- mutateJsonFileLocked(prPath, (prs) => {
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 idx = prs.findIndex(p => p.id === id);
13409
- if (idx >= 0) { prs.splice(idx, 1); found = true; }
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
- }, { defaultValue: [] });
13418
+ });
13412
13419
  }
13413
13420
  if (!found) return jsonReply(res, 404, { error: 'PR not found' });
13414
13421
  invalidateStatusCache();
@@ -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
- process.kill(safePid, 'SIGTERM');
1126
+ shared.killGracefully({ pid: safePid }, 5000);
1127
1127
  }
1128
1128
  } catch { /* may already be dead */ }
1129
1129
  }
@@ -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 || (process.env.MINIONS_PORT && parseInt(process.env.MINIONS_PORT, 10)) || 7331;
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
@@ -7003,6 +7003,13 @@ function upsertPullRequestRecord(prPath, entry, { project = null, itemId = null,
7003
7003
  mutatePullRequests(prPath, (prs) => {
7004
7004
  normalizePrRecords(prs, project);
7005
7005
  let target = findPrRecord(prs, normalizedEntry, project);
7006
+ // Issue #384: tombstoned records (userDeleted:true) must not be re-activated
7007
+ // by any poller path. Return skipped so reconcilePrs / shared-branch-reconcile
7008
+ // cannot resurrect a PR the user explicitly removed.
7009
+ if (target && target.userDeleted === true) {
7010
+ skipped = true;
7011
+ return prs;
7012
+ }
7006
7013
  if (!target && typeof beforeInsert === 'function' && beforeInsert(prs, normalizedEntry) === false) {
7007
7014
  skipped = true;
7008
7015
  return prs;
@@ -7845,8 +7852,8 @@ function mutateWorkItems(filePath, mutator) {
7845
7852
  if (wrote) {
7846
7853
  try { store._mirrorJsonFromSql(scope, filePath); } catch { /* mirror best-effort */ }
7847
7854
  try { require('./db-events').emitStateEvent('work_items'); } catch { /* optional */ }
7855
+ try { require('./queries').invalidateWorkItemsCache(); } catch { /* queries not loaded */ }
7848
7856
  }
7849
- try { require('./queries').invalidateWorkItemsCache(); } catch { /* queries not loaded */ }
7850
7857
  return result;
7851
7858
  }
7852
7859
 
@@ -7859,9 +7866,9 @@ function mutateWorkItems(filePath, mutator) {
7859
7866
  _skipSqlRouting: true,
7860
7867
  onWrote: () => {
7861
7868
  try { require('./db-events').emitStateEvent('work_items'); } catch { /* optional */ }
7869
+ try { require('./queries').invalidateWorkItemsCache(); } catch { /* queries not loaded */ }
7862
7870
  },
7863
7871
  });
7864
- try { require('./queries').invalidateWorkItemsCache(); } catch { /* queries not loaded */ }
7865
7872
  return result;
7866
7873
  }
7867
7874
 
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.2257",
3
+ "version": "0.1.2259",
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"