@yemi33/minions 0.1.2273 → 0.1.2274
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/slim/body.html
CHANGED
|
@@ -124,6 +124,17 @@
|
|
|
124
124
|
</div>
|
|
125
125
|
</div>
|
|
126
126
|
</div>
|
|
127
|
+
<!-- Pending work items sub-section: lists work items with
|
|
128
|
+
status === 'pending'. Populated by renderPendingWorkItems() in
|
|
129
|
+
status.js from the /api/work-items poll slice; hidden via the
|
|
130
|
+
`hidden` attribute when there are zero pending items. -->
|
|
131
|
+
<div class="pending-section" id="pending-section" hidden>
|
|
132
|
+
<div class="pending-head">
|
|
133
|
+
Pending Work Items
|
|
134
|
+
<span class="pending-count" id="pending-count"></span>
|
|
135
|
+
</div>
|
|
136
|
+
<div class="pending-list" id="pending-list"></div>
|
|
137
|
+
</div>
|
|
127
138
|
</div>
|
|
128
139
|
</div>
|
|
129
140
|
|
|
@@ -514,6 +514,7 @@
|
|
|
514
514
|
_slimSettle('/api/pull-requests', prev.pullRequests),
|
|
515
515
|
_slimSettle('/api/pinned', prev.pinned),
|
|
516
516
|
_slimSettle('/state/engine/watches.json', prev.watches),
|
|
517
|
+
_slimSettle('/api/work-items', prev.workItems),
|
|
517
518
|
]);
|
|
518
519
|
var data = results[0] || {};
|
|
519
520
|
data.dispatch = (results[1] && typeof results[1] === 'object') ? results[1] : {};
|
|
@@ -521,6 +522,7 @@
|
|
|
521
522
|
data.pullRequests = Array.isArray(results[3]) ? results[3] : [];
|
|
522
523
|
data.pinned = Array.isArray(results[4]) ? results[4] : [];
|
|
523
524
|
data.watches = Array.isArray(results[5]) ? results[5] : [];
|
|
525
|
+
data.workItems = Array.isArray(results[6]) ? results[6] : [];
|
|
524
526
|
applyStatus(data);
|
|
525
527
|
} catch (e) {
|
|
526
528
|
// Soft failure — leave previous values, surface in stamp
|
|
@@ -165,6 +165,11 @@
|
|
|
165
165
|
// ── Team member cards ──────────────────────────────────────
|
|
166
166
|
renderMembers(Array.isArray(data.agents) ? data.agents : []);
|
|
167
167
|
|
|
168
|
+
// ── Pending work items section ─────────────────────────────
|
|
169
|
+
// Surfaces WIs with status === 'pending' (W-mqtx516q). Sourced from the
|
|
170
|
+
// /api/work-items slice merged in by the slim poll (history.js).
|
|
171
|
+
renderPendingWorkItems(Array.isArray(data.workItems) ? data.workItems : []);
|
|
172
|
+
|
|
168
173
|
// ── Stamps + history ───────────────────────────────────────
|
|
169
174
|
var stamp = document.getElementById('cockpit-stamp');
|
|
170
175
|
if (stamp) stamp.textContent = 'updated ' + relTime(data.timestamp || Date.now());
|
|
@@ -174,3 +179,94 @@
|
|
|
174
179
|
if (hStamp) hStamp.textContent = relTime(data.timestamp || Date.now());
|
|
175
180
|
}
|
|
176
181
|
|
|
182
|
+
// ── Pending work items renderer ────────────────────────────────
|
|
183
|
+
// Lists every work item with status === 'pending' in a dedicated section
|
|
184
|
+
// under the cockpit (W-mqtx516q). The section is hidden via the `hidden`
|
|
185
|
+
// attribute when there are zero pending items. Each row shows id, title,
|
|
186
|
+
// project, type, and the engine's _pendingReason as a small badge when set.
|
|
187
|
+
// Everything goes through textContent (no innerHTML) to keep the SEC-03
|
|
188
|
+
// baseline clean. A JSON fingerprint of the visible fields skips the DOM
|
|
189
|
+
// rebuild when nothing changed between 5s polls.
|
|
190
|
+
var _lastPendingJson = null;
|
|
191
|
+
|
|
192
|
+
function renderPendingWorkItems(items) {
|
|
193
|
+
var section = document.getElementById('pending-section');
|
|
194
|
+
var list = document.getElementById('pending-list');
|
|
195
|
+
if (!section || !list) return;
|
|
196
|
+
|
|
197
|
+
var pending = (Array.isArray(items) ? items : []).filter(function(w) {
|
|
198
|
+
return w && w.status === 'pending';
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
var fingerprint = JSON.stringify(pending.map(function(w) {
|
|
202
|
+
return [w.id, w.title, w.project || w._source, w.type, w._pendingReason];
|
|
203
|
+
}));
|
|
204
|
+
if (fingerprint === _lastPendingJson) return;
|
|
205
|
+
_lastPendingJson = fingerprint;
|
|
206
|
+
|
|
207
|
+
if (!pending.length) {
|
|
208
|
+
section.setAttribute('hidden', '');
|
|
209
|
+
list.textContent = '';
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
section.removeAttribute('hidden');
|
|
213
|
+
|
|
214
|
+
var countEl = document.getElementById('pending-count');
|
|
215
|
+
if (countEl) countEl.textContent = String(pending.length);
|
|
216
|
+
|
|
217
|
+
list.textContent = '';
|
|
218
|
+
var frag = document.createDocumentFragment();
|
|
219
|
+
pending.forEach(function(w) {
|
|
220
|
+
var row = document.createElement('div');
|
|
221
|
+
row.className = 'pending-row';
|
|
222
|
+
|
|
223
|
+
// Top line: title + optional pending-reason badge.
|
|
224
|
+
var main = document.createElement('div');
|
|
225
|
+
main.className = 'pending-row-main';
|
|
226
|
+
|
|
227
|
+
var title = document.createElement('span');
|
|
228
|
+
title.className = 'pending-title';
|
|
229
|
+
title.textContent = w.title || w.id || '(untitled)';
|
|
230
|
+
title.title = (w.title || w.id || '') + (w.id ? ' (' + w.id + ')' : '');
|
|
231
|
+
main.appendChild(title);
|
|
232
|
+
|
|
233
|
+
if (w._pendingReason) {
|
|
234
|
+
var badge = document.createElement('span');
|
|
235
|
+
badge.className = 'pending-reason-badge';
|
|
236
|
+
badge.textContent = String(w._pendingReason).replace(/_/g, ' ');
|
|
237
|
+
badge.title = 'Pending reason: ' + w._pendingReason;
|
|
238
|
+
main.appendChild(badge);
|
|
239
|
+
}
|
|
240
|
+
row.appendChild(main);
|
|
241
|
+
|
|
242
|
+
// Meta line: id + project + type chips.
|
|
243
|
+
var meta = document.createElement('div');
|
|
244
|
+
meta.className = 'pending-row-meta';
|
|
245
|
+
|
|
246
|
+
var idEl = document.createElement('span');
|
|
247
|
+
idEl.className = 'pending-meta-id';
|
|
248
|
+
idEl.textContent = w.id || '';
|
|
249
|
+
meta.appendChild(idEl);
|
|
250
|
+
|
|
251
|
+
var project = w.project || w._source;
|
|
252
|
+
if (project) {
|
|
253
|
+
var projEl = document.createElement('span');
|
|
254
|
+
projEl.className = 'pending-meta-chip';
|
|
255
|
+
projEl.textContent = project;
|
|
256
|
+
meta.appendChild(projEl);
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
if (w.type) {
|
|
260
|
+
var typeEl = document.createElement('span');
|
|
261
|
+
typeEl.className = 'pending-meta-chip pending-meta-type';
|
|
262
|
+
typeEl.textContent = w.type;
|
|
263
|
+
meta.appendChild(typeEl);
|
|
264
|
+
}
|
|
265
|
+
row.appendChild(meta);
|
|
266
|
+
|
|
267
|
+
frag.appendChild(row);
|
|
268
|
+
});
|
|
269
|
+
list.appendChild(frag);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
|
|
@@ -1139,6 +1139,93 @@
|
|
|
1139
1139
|
.team-section { margin-bottom: 14px; }
|
|
1140
1140
|
.cockpit-section { padding-top: 14px; border-top: 1px solid var(--border); }
|
|
1141
1141
|
|
|
1142
|
+
/* Pending work items section (W-mqtx516q). Sits under the cockpit tiles;
|
|
1143
|
+
hidden via the `hidden` attribute when there are no pending WIs. */
|
|
1144
|
+
.pending-section {
|
|
1145
|
+
padding-top: 14px;
|
|
1146
|
+
margin-top: 14px;
|
|
1147
|
+
border-top: 1px solid var(--border);
|
|
1148
|
+
}
|
|
1149
|
+
.pending-section[hidden] { display: none; }
|
|
1150
|
+
.pending-head {
|
|
1151
|
+
font-size: var(--text-sm);
|
|
1152
|
+
font-weight: 600;
|
|
1153
|
+
color: var(--text);
|
|
1154
|
+
letter-spacing: 0.02em;
|
|
1155
|
+
text-transform: uppercase;
|
|
1156
|
+
margin-bottom: 8px;
|
|
1157
|
+
display: flex;
|
|
1158
|
+
align-items: center;
|
|
1159
|
+
gap: 6px;
|
|
1160
|
+
}
|
|
1161
|
+
.pending-count {
|
|
1162
|
+
font-size: var(--text-xs);
|
|
1163
|
+
font-weight: 600;
|
|
1164
|
+
color: var(--orange);
|
|
1165
|
+
background: rgba(214, 153, 34, 0.14);
|
|
1166
|
+
border-radius: 9px;
|
|
1167
|
+
padding: 0 7px;
|
|
1168
|
+
line-height: 16px;
|
|
1169
|
+
}
|
|
1170
|
+
.pending-list {
|
|
1171
|
+
display: flex;
|
|
1172
|
+
flex-direction: column;
|
|
1173
|
+
gap: 6px;
|
|
1174
|
+
}
|
|
1175
|
+
.pending-row {
|
|
1176
|
+
background: var(--surface2);
|
|
1177
|
+
border: 1px solid var(--border);
|
|
1178
|
+
border-left: 3px solid var(--orange);
|
|
1179
|
+
border-radius: var(--radius);
|
|
1180
|
+
padding: 7px 9px;
|
|
1181
|
+
}
|
|
1182
|
+
.pending-row-main {
|
|
1183
|
+
display: flex;
|
|
1184
|
+
align-items: center;
|
|
1185
|
+
gap: 6px;
|
|
1186
|
+
}
|
|
1187
|
+
.pending-title {
|
|
1188
|
+
font-size: var(--text-md);
|
|
1189
|
+
color: var(--text);
|
|
1190
|
+
overflow: hidden;
|
|
1191
|
+
text-overflow: ellipsis;
|
|
1192
|
+
white-space: nowrap;
|
|
1193
|
+
min-width: 0;
|
|
1194
|
+
flex: 1;
|
|
1195
|
+
}
|
|
1196
|
+
.pending-reason-badge {
|
|
1197
|
+
flex: none;
|
|
1198
|
+
font-size: var(--text-xs);
|
|
1199
|
+
color: var(--orange);
|
|
1200
|
+
border: 1px solid rgba(214, 153, 34, 0.5);
|
|
1201
|
+
border-radius: 6px;
|
|
1202
|
+
padding: 0 5px;
|
|
1203
|
+
line-height: 15px;
|
|
1204
|
+
white-space: nowrap;
|
|
1205
|
+
}
|
|
1206
|
+
.pending-row-meta {
|
|
1207
|
+
display: flex;
|
|
1208
|
+
align-items: center;
|
|
1209
|
+
flex-wrap: wrap;
|
|
1210
|
+
gap: 6px;
|
|
1211
|
+
margin-top: 4px;
|
|
1212
|
+
}
|
|
1213
|
+
.pending-meta-id {
|
|
1214
|
+
font-size: var(--text-xs);
|
|
1215
|
+
color: var(--muted);
|
|
1216
|
+
font-family: var(--mono, monospace);
|
|
1217
|
+
}
|
|
1218
|
+
.pending-meta-chip {
|
|
1219
|
+
font-size: var(--text-xs);
|
|
1220
|
+
color: var(--muted);
|
|
1221
|
+
background: var(--surface);
|
|
1222
|
+
border: 1px solid var(--border);
|
|
1223
|
+
border-radius: 6px;
|
|
1224
|
+
padding: 0 6px;
|
|
1225
|
+
line-height: 15px;
|
|
1226
|
+
}
|
|
1227
|
+
.pending-meta-type { color: var(--blue); }
|
|
1228
|
+
|
|
1142
1229
|
/* Square member cards. Auto-fill so the column count adapts to the
|
|
1143
1230
|
panel width; aspect-ratio keeps each card square regardless. */
|
|
1144
1231
|
.member-grid {
|
|
@@ -168,14 +168,19 @@ async function validateAcceptanceCriteria(workItem, opts = {}) {
|
|
|
168
168
|
model: _resolveModel(opts),
|
|
169
169
|
maxTurns: 1,
|
|
170
170
|
direct: true,
|
|
171
|
-
// Direct callLLM spawns the runtime CLI with
|
|
172
|
-
// _spawnProcess).
|
|
173
|
-
// Edit/Write/Bash
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
//
|
|
177
|
-
//
|
|
178
|
-
|
|
171
|
+
// No tools at all. Direct callLLM spawns the runtime CLI with
|
|
172
|
+
// cwd=MINIONS_DIR (engine/llm.js _spawnProcess). P-b5e2a481 (2026-06-01
|
|
173
|
+
// 23:44 UTC) removed write access (Edit/Write/Bash) after the validator
|
|
174
|
+
// "previewed" work by editing dashboard/js/refresh.js in MINIONS_DIR, but
|
|
175
|
+
// left Read/Grep/Glob in place. Those read tools made the model search the
|
|
176
|
+
// MINIONS_DIR codebase to "verify" whether the described code exists — but
|
|
177
|
+
// the cwd is always MINIONS_DIR, never the target project, so work items
|
|
178
|
+
// targeting other repos (e.g. Android in office/src) were searched against
|
|
179
|
+
// this Node.js codebase, found nothing, and were wrongly marked invalid.
|
|
180
|
+
// The pre-dispatch eval is a pure text-reasoning call ("is this clear,
|
|
181
|
+
// actionable, and testable?") and needs no filesystem access. Passing no
|
|
182
|
+
// allowedTools makes the runtime omit --allowedTools entirely so the model
|
|
183
|
+
// reasons only over the prompt text.
|
|
179
184
|
engineConfig: opts.engineConfig,
|
|
180
185
|
});
|
|
181
186
|
} catch (e) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2274",
|
|
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"
|