@yemi33/minions 0.1.1894 → 0.1.1895
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/engine/cli.js +36 -4
- package/engine/shared.js +1 -1
- package/engine.js +0 -1
- package/package.json +1 -1
- package/playbooks/shared-rules.md +1 -1
package/engine/cli.js
CHANGED
|
@@ -1144,7 +1144,8 @@ const commands = {
|
|
|
1144
1144
|
const e = engine();
|
|
1145
1145
|
if (!title) {
|
|
1146
1146
|
console.log('Usage: node .minions/engine.js work "<title>" [options-json]');
|
|
1147
|
-
console.log('Options: {"type":"implement","priority":"high","agent":"dallas","description":"...","branch":"feature/..."}');
|
|
1147
|
+
console.log('Options: {"id":"W-customid","type":"implement","priority":"high","agent":"dallas","description":"...","branch":"feature/...","project":"minions"}');
|
|
1148
|
+
console.log(' id Optional caller-supplied work item ID. Defaults to a cuid-style W-<id>.');
|
|
1148
1149
|
return;
|
|
1149
1150
|
}
|
|
1150
1151
|
|
|
@@ -1157,7 +1158,7 @@ const commands = {
|
|
|
1157
1158
|
}
|
|
1158
1159
|
|
|
1159
1160
|
const config = getConfig();
|
|
1160
|
-
const { getProjects, projectWorkItemsPath, resolveProjectSource } = require('./shared');
|
|
1161
|
+
const { getProjects, projectWorkItemsPath, resolveProjectSource, uid, safeJsonArr } = require('./shared');
|
|
1161
1162
|
const projects = getProjects(config);
|
|
1162
1163
|
const target = opts.project ? resolveProjectSource(opts.project, projects, { allowCentral: false }) : null;
|
|
1163
1164
|
if (target?.error) {
|
|
@@ -1166,10 +1167,36 @@ const commands = {
|
|
|
1166
1167
|
}
|
|
1167
1168
|
const targetProject = target?.project || (projects.length > 0 ? projects[0] : null);
|
|
1168
1169
|
const wiPath = projectWorkItemsPath(targetProject);
|
|
1170
|
+
const archivePath = wiPath.replace(/\.json$/, '-archive.json');
|
|
1171
|
+
|
|
1172
|
+
// Caller-supplied id: validate and pre-check live + archive for collisions
|
|
1173
|
+
// BEFORE acquiring the work-items lock, so a rejection never mutates state.
|
|
1174
|
+
let requestedId = null;
|
|
1175
|
+
if (opts.id != null) {
|
|
1176
|
+
if (typeof opts.id !== 'string' || !opts.id.trim()) {
|
|
1177
|
+
console.log('Error: opts.id must be a non-empty string');
|
|
1178
|
+
process.exit(1);
|
|
1179
|
+
}
|
|
1180
|
+
requestedId = opts.id.trim();
|
|
1181
|
+
const liveItems = safeJsonArr(wiPath);
|
|
1182
|
+
const archivedItems = safeJsonArr(archivePath);
|
|
1183
|
+
if (liveItems.some(w => w?.id === requestedId) || archivedItems.some(w => w?.id === requestedId)) {
|
|
1184
|
+
console.log(`Error: work item id "${requestedId}" already exists in ${path.basename(wiPath)} or its archive`);
|
|
1185
|
+
process.exit(1);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1169
1189
|
let item;
|
|
1190
|
+
let collision = false;
|
|
1170
1191
|
mutateWorkItems(wiPath, items => {
|
|
1192
|
+
const id = requestedId || ('W-' + uid());
|
|
1193
|
+
// Re-check inside the lock to close the TOCTOU race against other writers.
|
|
1194
|
+
if (items.some(w => w?.id === id)) {
|
|
1195
|
+
collision = true;
|
|
1196
|
+
return items;
|
|
1197
|
+
}
|
|
1171
1198
|
item = {
|
|
1172
|
-
id
|
|
1199
|
+
id,
|
|
1173
1200
|
title: title,
|
|
1174
1201
|
type: opts.type || 'implement',
|
|
1175
1202
|
status: WI_STATUS.QUEUED,
|
|
@@ -1184,7 +1211,12 @@ const commands = {
|
|
|
1184
1211
|
items.push(item);
|
|
1185
1212
|
});
|
|
1186
1213
|
|
|
1187
|
-
|
|
1214
|
+
if (collision || !item) {
|
|
1215
|
+
console.log(`Error: work item id collision detected for "${requestedId || 'auto-generated'}"`);
|
|
1216
|
+
process.exit(1);
|
|
1217
|
+
}
|
|
1218
|
+
|
|
1219
|
+
console.log(`Queued work item: ${item.id} — ${item.title} (project: ${targetProject?.name || 'default'})`);
|
|
1188
1220
|
console.log(` Type: ${item.type} | Priority: ${item.priority} | Agent: ${item.agent || 'auto'}`);
|
|
1189
1221
|
},
|
|
1190
1222
|
|
package/engine/shared.js
CHANGED
|
@@ -1716,7 +1716,7 @@ const ESCALATION_POLICY = {
|
|
|
1716
1716
|
};
|
|
1717
1717
|
|
|
1718
1718
|
// Structured completion protocol — fields agents must produce in ```completion blocks
|
|
1719
|
-
const COMPLETION_FIELDS = ['status', 'summary', 'files_changed', 'tests', 'pr', '
|
|
1719
|
+
const COMPLETION_FIELDS = ['status', 'summary', 'files_changed', 'tests', 'pr', 'not_changed', 'failure_class', 'retryable', 'needs_rerun', 'verdict', 'artifacts'];
|
|
1720
1720
|
|
|
1721
1721
|
const DEFAULT_AGENT_METRICS = {
|
|
1722
1722
|
tasksCompleted: 0, tasksErrored: 0,
|
package/engine.js
CHANGED
|
@@ -1649,7 +1649,6 @@ async function spawnAgent(dispatchItem, config) {
|
|
|
1649
1649
|
errorReason = structuredCompletion
|
|
1650
1650
|
? String(
|
|
1651
1651
|
structuredCompletion.summary
|
|
1652
|
-
|| structuredCompletion.pending
|
|
1653
1652
|
|| structuredCompletion.failure_class
|
|
1654
1653
|
|| `Agent reported ${structuredCompletion.status || 'failure'}`
|
|
1655
1654
|
).slice(0, 300)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1895",
|
|
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"
|
|
@@ -67,7 +67,7 @@ Bias toward senior-engineer restraint:
|
|
|
67
67
|
The engine provides a completion report path in the prompt and in `MINIONS_COMPLETION_REPORT`. Before exiting, write JSON there with the actual outcome:
|
|
68
68
|
|
|
69
69
|
```json
|
|
70
|
-
{"status":"success","summary":"what changed and how it was validated","verdict":null,"pr":"PR id/url or N/A","failure_class":"N/A","retryable":false,"needs_rerun":false,"artifacts":[{"type":"note|plan|prd|pr|file","path":"relative/path/or/url","title":"short label"}]}
|
|
70
|
+
{"status":"success","summary":"what changed and how it was validated","verdict":null,"pr":"PR id/url or N/A","failure_class":"N/A","retryable":false,"needs_rerun":false,"not_changed":"adjacent X left alone; refactor Y declined as out of scope","artifacts":[{"type":"note|plan|prd|pr|file","path":"relative/path/or/url","title":"short label"}]}
|
|
71
71
|
```
|
|
72
72
|
|
|
73
73
|
For the canonical schema — every field, the `failure_class` enum, `noop:true` semantics, `retryable` / `needs_rerun` shape, and the artifacts array — see `docs/completion-reports.md`. The JSON report is the primary signal; fenced `completion` blocks in stdout are accepted only as a fallback.
|