@yemi33/minions 0.1.1903 → 0.1.1904
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 +4 -15
- package/docs/deprecated.json +1 -10
- package/engine/cli.js +2 -13
- package/engine/shared.js +2 -83
- package/minions.js +2 -5
- package/package.json +1 -1
package/dashboard.js
CHANGED
|
@@ -73,19 +73,9 @@ function ensureConfiguredProjectStateFiles() {
|
|
|
73
73
|
const root = p.localPath ? path.resolve(p.localPath) : null;
|
|
74
74
|
if (!root || !fs.existsSync(root)) continue;
|
|
75
75
|
try {
|
|
76
|
-
|
|
77
|
-
if (state.migrated.length > 0 || state.removedLegacy.length > 0 || state.legacyDirRemoved) {
|
|
78
|
-
const parts = [];
|
|
79
|
-
if (state.migrated.length > 0) parts.push(`merged ${state.migrated.join(', ')}`);
|
|
80
|
-
if (state.removedLegacy.length > 0) parts.push(`removed ${state.removedLegacy.join(', ')}`);
|
|
81
|
-
if (state.legacyDirRemoved) parts.push(`removed legacy .minions dir`);
|
|
82
|
-
console.log(`[dashboard] migrated project state for "${p.name}" → projects/${p.name} (${parts.join('; ')})`);
|
|
83
|
-
}
|
|
84
|
-
if (state.legacyDirRemoveError) {
|
|
85
|
-
console.warn(`[dashboard] failed to remove legacy .minions dir for "${p.name}": ${state.legacyDirRemoveError}`);
|
|
86
|
-
}
|
|
76
|
+
shared.ensureProjectStateFiles(p);
|
|
87
77
|
} catch (e) {
|
|
88
|
-
console.warn(`[dashboard] project state
|
|
78
|
+
console.warn(`[dashboard] project state setup failed for "${p.name}": ${e.message}`);
|
|
89
79
|
}
|
|
90
80
|
}
|
|
91
81
|
}
|
|
@@ -5716,9 +5706,8 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
5716
5706
|
prUrlBase: detected.prUrlBase,
|
|
5717
5707
|
});
|
|
5718
5708
|
|
|
5719
|
-
// Create centralized project state
|
|
5720
|
-
|
|
5721
|
-
shared.ensureProjectStateFiles(project, { migrateLegacy: true, removeLegacy: true });
|
|
5709
|
+
// Create centralized project state files.
|
|
5710
|
+
shared.ensureProjectStateFiles(project);
|
|
5722
5711
|
|
|
5723
5712
|
let duplicate = false;
|
|
5724
5713
|
mutateDashboardConfig(config => {
|
package/docs/deprecated.json
CHANGED
|
@@ -1,10 +1 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"id": "project-local-minions-state",
|
|
4
|
-
"summary": "Project-local .minions directories are migrated to central projects/<name>/ state and removed",
|
|
5
|
-
"deprecated": "2026-05-06",
|
|
6
|
-
"reason": "Project repos should not receive Minions runtime state because .minions can leak into source repositories.",
|
|
7
|
-
"locations": ["engine/shared.js ensureProjectStateFiles legacy migration", "dashboard.js handleProjectsAdd/dashboard startup", "minions.js addProject/scanAndAdd", "engine/cli.js start migration", "bin/minions.js user-scoped init root"],
|
|
8
|
-
"cleanup": "Remove legacyProjectStateDir/legacyProjectStatePath migration/deletion after existing project-local .minions directories have been migrated."
|
|
9
|
-
}
|
|
10
|
-
]
|
|
1
|
+
[]
|
package/engine/cli.js
CHANGED
|
@@ -468,20 +468,9 @@ const commands = {
|
|
|
468
468
|
console.log(` WARNING: ${p.name} path not found: ${p.localPath}`);
|
|
469
469
|
} else {
|
|
470
470
|
try {
|
|
471
|
-
|
|
472
|
-
if (state.migrated.length > 0 || state.removedLegacy.length > 0 || state.legacyDirRemoved) {
|
|
473
|
-
const parts = [];
|
|
474
|
-
if (state.migrated.length > 0) parts.push(`merged ${state.migrated.join(', ')}`);
|
|
475
|
-
if (state.removedLegacy.length > 0) parts.push(`removed ${state.removedLegacy.join(', ')}`);
|
|
476
|
-
if (state.legacyDirRemoved) parts.push(`removed legacy .minions dir`);
|
|
477
|
-
e.log('info', `Migrated project state for "${p.name}" → projects/${p.name} (${parts.join('; ')})`);
|
|
478
|
-
}
|
|
479
|
-
if (state.legacyDirRemoveError) {
|
|
480
|
-
e.log('warn', `Failed to remove legacy .minions dir for "${p.name}": ${state.legacyDirRemoveError}`);
|
|
481
|
-
console.log(` WARNING: legacy .minions dir for "${p.name}" could not be removed: ${state.legacyDirRemoveError}`);
|
|
482
|
-
}
|
|
471
|
+
shared.ensureProjectStateFiles(p);
|
|
483
472
|
} catch (err) {
|
|
484
|
-
e.log('warn', `Project state
|
|
473
|
+
e.log('warn', `Project state setup failed for "${p.name}": ${err.message}`);
|
|
485
474
|
}
|
|
486
475
|
console.log(` Project: ${p.name} (${root})`);
|
|
487
476
|
}
|
package/engine/shared.js
CHANGED
|
@@ -1967,9 +1967,6 @@ function resolveProjectSource(source, projectsOrConfig, options = {}) {
|
|
|
1967
1967
|
projectStateDir(project),
|
|
1968
1968
|
projectWorkItemsPath(project),
|
|
1969
1969
|
projectPrPath(project),
|
|
1970
|
-
legacyProjectStateDir(project),
|
|
1971
|
-
legacyProjectStatePath(project, 'work-items.json'),
|
|
1972
|
-
legacyProjectStatePath(project, 'pull-requests.json'),
|
|
1973
1970
|
].filter(Boolean);
|
|
1974
1971
|
if (candidates.some(candidate => _sameSourcePath(value, candidate, minionsDir))) {
|
|
1975
1972
|
return _projectSourceDescriptor(project, value, explicit, minionsDir);
|
|
@@ -2023,36 +2020,6 @@ function projectPrPath(project) {
|
|
|
2023
2020
|
return path.join(projectStateDir(project), 'pull-requests.json');
|
|
2024
2021
|
}
|
|
2025
2022
|
|
|
2026
|
-
function legacyProjectStateDir(project) {
|
|
2027
|
-
if (!project?.localPath) return null;
|
|
2028
|
-
return path.join(path.resolve(project.localPath), '.minions');
|
|
2029
|
-
}
|
|
2030
|
-
|
|
2031
|
-
function legacyProjectStatePath(project, fileName) {
|
|
2032
|
-
const dir = legacyProjectStateDir(project);
|
|
2033
|
-
return dir ? path.join(dir, fileName) : null;
|
|
2034
|
-
}
|
|
2035
|
-
|
|
2036
|
-
function projectStateRecordKey(record) {
|
|
2037
|
-
if (record && typeof record === 'object') {
|
|
2038
|
-
const id = record.id ?? record.prId ?? record.workItemId ?? record.url ?? record.number;
|
|
2039
|
-
if (id !== undefined && id !== null && String(id).trim()) return String(id);
|
|
2040
|
-
}
|
|
2041
|
-
try { return JSON.stringify(record); } catch { return String(record); }
|
|
2042
|
-
}
|
|
2043
|
-
|
|
2044
|
-
function mergeProjectStateArrays(current, legacy) {
|
|
2045
|
-
const merged = Array.isArray(current) ? current.slice() : [];
|
|
2046
|
-
const seen = new Set(merged.map(projectStateRecordKey));
|
|
2047
|
-
for (const entry of Array.isArray(legacy) ? legacy : []) {
|
|
2048
|
-
const key = projectStateRecordKey(entry);
|
|
2049
|
-
if (seen.has(key)) continue;
|
|
2050
|
-
merged.push(entry);
|
|
2051
|
-
seen.add(key);
|
|
2052
|
-
}
|
|
2053
|
-
return merged;
|
|
2054
|
-
}
|
|
2055
|
-
|
|
2056
2023
|
function sameResolvedPath(a, b) {
|
|
2057
2024
|
if (!a || !b) return false;
|
|
2058
2025
|
try {
|
|
@@ -2064,64 +2031,20 @@ function sameResolvedPath(a, b) {
|
|
|
2064
2031
|
}
|
|
2065
2032
|
}
|
|
2066
2033
|
|
|
2067
|
-
function
|
|
2068
|
-
const dir = legacyProjectStateDir(project);
|
|
2069
|
-
if (!dir) return { removed: false, error: null };
|
|
2070
|
-
if (sameResolvedPath(dir, MINIONS_DIR)) return { removed: false, error: null };
|
|
2071
|
-
if (!fs.existsSync(dir)) return { removed: false, error: null };
|
|
2072
|
-
try {
|
|
2073
|
-
fs.rmSync(dir, { recursive: true, force: true });
|
|
2074
|
-
return { removed: true, error: null };
|
|
2075
|
-
} catch (err) {
|
|
2076
|
-
return { removed: false, error: err && err.message ? err.message : String(err) };
|
|
2077
|
-
}
|
|
2078
|
-
}
|
|
2079
|
-
|
|
2080
|
-
function ensureProjectStateFiles(project, options = {}) {
|
|
2081
|
-
const migrateLegacy = options.migrateLegacy !== false;
|
|
2082
|
-
const removeLegacy = options.removeLegacy === true;
|
|
2034
|
+
function ensureProjectStateFiles(project) {
|
|
2083
2035
|
const files = [
|
|
2084
2036
|
{ name: 'pull-requests.json', centralPath: projectPrPath(project) },
|
|
2085
2037
|
{ name: 'work-items.json', centralPath: projectWorkItemsPath(project) },
|
|
2086
2038
|
];
|
|
2087
|
-
const result = { created: []
|
|
2039
|
+
const result = { created: [] };
|
|
2088
2040
|
|
|
2089
2041
|
projectStateDirEnsure(project);
|
|
2090
2042
|
for (const file of files) {
|
|
2091
|
-
const legacyPath = legacyProjectStatePath(project, file.name);
|
|
2092
|
-
const hasLegacyState = legacyPath && (fs.existsSync(legacyPath) || fs.existsSync(legacyPath + '.backup'));
|
|
2093
|
-
const legacyData = migrateLegacy && hasLegacyState ? safeJson(legacyPath) : null;
|
|
2094
|
-
|
|
2095
|
-
if (Array.isArray(legacyData)) {
|
|
2096
|
-
let changed = false;
|
|
2097
|
-
mutateJsonFileLocked(file.centralPath, current => {
|
|
2098
|
-
const merged = mergeProjectStateArrays(Array.isArray(current) ? current : [], legacyData);
|
|
2099
|
-
changed = JSON.stringify(merged) !== JSON.stringify(current);
|
|
2100
|
-
return merged;
|
|
2101
|
-
}, { defaultValue: [], skipWriteIfUnchanged: true });
|
|
2102
|
-
if (changed && legacyData.length > 0) result.migrated.push(file.name);
|
|
2103
|
-
if (removeLegacy) {
|
|
2104
|
-
try {
|
|
2105
|
-
fs.unlinkSync(legacyPath);
|
|
2106
|
-
result.removedLegacy.push(file.name);
|
|
2107
|
-
} catch (err) {
|
|
2108
|
-
if (!err || err.code !== 'ENOENT') throw err;
|
|
2109
|
-
}
|
|
2110
|
-
safeUnlink(legacyPath + '.backup');
|
|
2111
|
-
}
|
|
2112
|
-
}
|
|
2113
|
-
|
|
2114
2043
|
if (!fs.existsSync(file.centralPath)) {
|
|
2115
2044
|
mutateJsonFileLocked(file.centralPath, data => Array.isArray(data) ? data : [], { defaultValue: [] });
|
|
2116
2045
|
result.created.push(file.name);
|
|
2117
2046
|
}
|
|
2118
2047
|
}
|
|
2119
|
-
|
|
2120
|
-
if (removeLegacy) {
|
|
2121
|
-
const res = removeLegacyProjectStateDir(project);
|
|
2122
|
-
result.legacyDirRemoved = res.removed;
|
|
2123
|
-
result.legacyDirRemoveError = res.error;
|
|
2124
|
-
}
|
|
2125
2048
|
return result;
|
|
2126
2049
|
}
|
|
2127
2050
|
|
|
@@ -3620,12 +3543,8 @@ module.exports = {
|
|
|
3620
3543
|
projectStateDirEnsure,
|
|
3621
3544
|
projectWorkItemsPath,
|
|
3622
3545
|
projectPrPath,
|
|
3623
|
-
legacyProjectStateDir,
|
|
3624
|
-
legacyProjectStatePath,
|
|
3625
3546
|
ensureProjectStateFiles,
|
|
3626
3547
|
sameResolvedPath,
|
|
3627
|
-
projectStateRecordKey, // exported for testing
|
|
3628
|
-
mergeProjectStateArrays, // exported for testing
|
|
3629
3548
|
realPathForComparison, // exported for testing
|
|
3630
3549
|
prPathComparisonCandidates, // exported for testing
|
|
3631
3550
|
resolveProjectForPrPath, // exported for testing
|
package/minions.js
CHANGED
|
@@ -135,14 +135,11 @@ async function addProject(targetDir) {
|
|
|
135
135
|
name, description, localPath: target, repoHost, repositoryId, org, project, repoName, mainBranch,
|
|
136
136
|
prUrlBase: detected.prUrlBase,
|
|
137
137
|
});
|
|
138
|
-
|
|
138
|
+
shared.ensureProjectStateFiles(projectEntry);
|
|
139
139
|
config.projects.push(projectEntry);
|
|
140
140
|
saveConfig(config);
|
|
141
141
|
|
|
142
142
|
console.log(`\n Linked "${name}" (${target})`);
|
|
143
|
-
if (state.migrated.length > 0 || state.removedLegacy.length > 0) {
|
|
144
|
-
console.log(` Migrated project state to ${shared.projectStateDir(projectEntry)}`);
|
|
145
|
-
}
|
|
146
143
|
console.log(` Total projects: ${config.projects.length}`);
|
|
147
144
|
console.log(`\n Start the minions from anywhere:`);
|
|
148
145
|
console.log(` node ${MINIONS_HOME}/engine.js # Engine`);
|
|
@@ -359,7 +356,7 @@ async function scanAndAdd({ root, depth } = {}) {
|
|
|
359
356
|
repoHost: repo.host, repositoryId: repo.repositoryId, org: repo.org, project: repo.project,
|
|
360
357
|
repoName: repo.repoName, mainBranch: repo.mainBranch, prUrlBase: repo.prUrlBase,
|
|
361
358
|
});
|
|
362
|
-
shared.ensureProjectStateFiles(projectEntry
|
|
359
|
+
shared.ensureProjectStateFiles(projectEntry);
|
|
363
360
|
config.projects.push(projectEntry);
|
|
364
361
|
console.log(` + ${name} (${repo.path})`);
|
|
365
362
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1904",
|
|
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"
|