@yemi33/minions 0.1.1558 → 0.1.1559
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/dashboard/js/render-other.js +1 -0
- package/dashboard/js/settings.js +1 -0
- package/engine/projects.js +49 -3
- package/minions.js +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -44,6 +44,7 @@ async function projectChipRemove(name) {
|
|
|
44
44
|
var parts = ['Removed "' + name + '"'];
|
|
45
45
|
if (d.cancelledItems) parts.push(d.cancelledItems + ' WI cancelled');
|
|
46
46
|
if (d.drainedDispatches) parts.push(d.drainedDispatches + ' dispatch drained');
|
|
47
|
+
if (d.archivedPlans?.length) parts.push(d.archivedPlans.length + ' plan/PRD archived');
|
|
47
48
|
if (d.archivedTo) parts.push('archived');
|
|
48
49
|
if (d.pipelineRefs?.length) parts.push('! pipelines still reference: ' + d.pipelineRefs.join(', '));
|
|
49
50
|
showToast('cmd-toast', parts.join(' — '), true);
|
package/dashboard/js/settings.js
CHANGED
|
@@ -424,6 +424,7 @@ async function removeProject(name) {
|
|
|
424
424
|
if (d.cancelledItems) parts.push(d.cancelledItems + ' WI cancelled');
|
|
425
425
|
if (d.drainedDispatches) parts.push(d.drainedDispatches + ' dispatch drained');
|
|
426
426
|
if (d.cleanedWorktrees) parts.push(d.cleanedWorktrees + ' worktree(s) cleaned');
|
|
427
|
+
if (d.archivedPlans?.length) parts.push(d.archivedPlans.length + ' plan/PRD archived');
|
|
427
428
|
if (d.archivedTo) parts.push('archived to ' + d.archivedTo);
|
|
428
429
|
if (d.pipelineRefs?.length) parts.push('! pipelines still reference: ' + d.pipelineRefs.join(', '));
|
|
429
430
|
showToast('cmd-toast', parts.join(' — '), true);
|
package/engine/projects.js
CHANGED
|
@@ -44,6 +44,7 @@ function removeProject(target, options = {}) {
|
|
|
44
44
|
drainedDispatches: 0, // includes active dispatches whose agent processes were killed
|
|
45
45
|
cleanedWorktrees: 0,
|
|
46
46
|
disabledSchedules: 0,
|
|
47
|
+
archivedPlans: [],
|
|
47
48
|
pipelineRefs: [],
|
|
48
49
|
archivedTo: null,
|
|
49
50
|
purgedDataDir: false,
|
|
@@ -110,7 +111,52 @@ function removeProject(target, options = {}) {
|
|
|
110
111
|
}
|
|
111
112
|
}
|
|
112
113
|
|
|
113
|
-
// 5.
|
|
114
|
+
// 5. Archive plans + PRDs targeting this project so they don't keep
|
|
115
|
+
// showing in the dashboard after removal. Three signals:
|
|
116
|
+
// a) PRD JSON `project` field matches → archive PRD + linked source plan
|
|
117
|
+
// b) plan .md content has `Project: <name>` (any markdown emphasis)
|
|
118
|
+
// c) plan .md filename contains the project name (case-insensitive)
|
|
119
|
+
// The .backup sidecar removal in archivePlan prevents engine restart
|
|
120
|
+
// from re-triggering plan completion (mirror of f28162b0 fix).
|
|
121
|
+
const plansDir = path.join(MINIONS_DIR, 'plans');
|
|
122
|
+
const plansArchive = path.join(plansDir, 'archive');
|
|
123
|
+
const prdDir = path.join(MINIONS_DIR, 'prd');
|
|
124
|
+
const escName = project.name.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
125
|
+
const projectLineRe = new RegExp('^[*_>\\s]{0,4}\\*{0,2}_{0,2}Project:?\\*{0,2}_{0,2}\\s*' + escName + '\\b', 'im');
|
|
126
|
+
const archivedSourcePlans = new Set();
|
|
127
|
+
try {
|
|
128
|
+
if (fs.existsSync(prdDir)) {
|
|
129
|
+
const { archivePlan } = require('./lifecycle');
|
|
130
|
+
for (const f of fs.readdirSync(prdDir).filter(f => f.endsWith('.json'))) {
|
|
131
|
+
try {
|
|
132
|
+
const prd = JSON.parse(fs.readFileSync(path.join(prdDir, f), 'utf8'));
|
|
133
|
+
if (prd?.project !== project.name) continue;
|
|
134
|
+
archivePlan(f, prd, [project], config);
|
|
135
|
+
summary.archivedPlans.push('prd/' + f);
|
|
136
|
+
if (prd.source_plan) archivedSourcePlans.add(prd.source_plan);
|
|
137
|
+
} catch { /* skip unreadable PRD */ }
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
} catch (e) { summary.warnings.push('archive PRDs: ' + e.message); }
|
|
141
|
+
try {
|
|
142
|
+
if (fs.existsSync(plansDir)) {
|
|
143
|
+
fs.mkdirSync(plansArchive, { recursive: true });
|
|
144
|
+
const lowerName = project.name.toLowerCase();
|
|
145
|
+
for (const f of fs.readdirSync(plansDir).filter(f => f.endsWith('.md'))) {
|
|
146
|
+
if (archivedSourcePlans.has(f)) continue; // already moved by archivePlan above
|
|
147
|
+
const fp = path.join(plansDir, f);
|
|
148
|
+
try {
|
|
149
|
+
const filenameMatch = f.toLowerCase().includes(lowerName);
|
|
150
|
+
const content = filenameMatch ? '' : fs.readFileSync(fp, 'utf8');
|
|
151
|
+
if (!filenameMatch && !projectLineRe.test(content)) continue;
|
|
152
|
+
fs.renameSync(fp, path.join(plansArchive, f));
|
|
153
|
+
summary.archivedPlans.push('plans/' + f);
|
|
154
|
+
} catch { /* skip unreadable plan */ }
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
} catch (e) { summary.warnings.push('archive plans: ' + e.message); }
|
|
158
|
+
|
|
159
|
+
// 6. Surface pipelines that reference this project so the user can review
|
|
114
160
|
// them. Don't auto-modify — user intent there is unclear.
|
|
115
161
|
try {
|
|
116
162
|
const { getPipelines } = require('./pipeline');
|
|
@@ -125,12 +171,12 @@ function removeProject(target, options = {}) {
|
|
|
125
171
|
}
|
|
126
172
|
} catch { /* pipelines optional */ }
|
|
127
173
|
|
|
128
|
-
//
|
|
174
|
+
// 7. Remove from config.json (and persist any schedule disables)
|
|
129
175
|
config.projects = (config.projects || []).filter(p => p.name !== project.name);
|
|
130
176
|
try { fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); }
|
|
131
177
|
catch (e) { return { ...summary, error: 'Failed to write config: ' + e.message }; }
|
|
132
178
|
|
|
133
|
-
//
|
|
179
|
+
// 8. Move (or purge) projects/<name>/ — preserves PR/work-item history by
|
|
134
180
|
// default so a re-add can pick up where it left off.
|
|
135
181
|
const dataDir = path.join(MINIONS_DIR, 'projects', project.name);
|
|
136
182
|
if (fs.existsSync(dataDir)) {
|
package/minions.js
CHANGED
|
@@ -221,6 +221,7 @@ function removeProject(target, options = {}) {
|
|
|
221
221
|
if (result.cancelledItems) lines.push(` cancelled ${result.cancelledItems} pending work item(s)`);
|
|
222
222
|
if (result.drainedDispatches) lines.push(` drained ${result.drainedDispatches} dispatch entr${result.drainedDispatches === 1 ? 'y' : 'ies'} (active agents killed)`);
|
|
223
223
|
if (result.cleanedWorktrees) lines.push(` cleaned ${result.cleanedWorktrees} worktree(s)`);
|
|
224
|
+
if (result.archivedPlans?.length) lines.push(` archived ${result.archivedPlans.length} plan/PRD file(s)`);
|
|
224
225
|
if (result.disabledSchedules) lines.push(` disabled ${result.disabledSchedules} schedule(s)`);
|
|
225
226
|
if (result.archivedTo) lines.push(` archived data → ${result.archivedTo}`);
|
|
226
227
|
if (result.purgedDataDir) lines.push(` purged data directory`);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1559",
|
|
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"
|