@yemi33/minions 0.1.2079 → 0.1.2081

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.
@@ -474,6 +474,13 @@ let _knownDashboardStartId = null;
474
474
  // dashboardBuildId is the md5 of the assembled HTML — bumps automatically on
475
475
  // hot-reload + on cold restart with any /dashboard/** change.
476
476
  let _knownDashboardBuildId = null;
477
+ // Hard-reload trigger when the *engine* commit changes — `minions restart`
478
+ // after a `git pull` swaps engine code but doesn't touch any
479
+ // /dashboard/** asset, so `dashboardBuildId` stays the same and the
480
+ // existing buildId reload above never fires. Without this, the stale
481
+ // "Engine running v… — disk has v…" banner persists in already-open tabs
482
+ // until the (hourly by default) /api/version repoll catches up.
483
+ let _knownEngineRunningCommit = null;
477
484
  // /api/status ETag cache (W-mpehsyhv0017085a). The dashboard polls every 4 s
478
485
  // but the server-side cache only changes every 10–60 s. Sending If-None-Match
479
486
  // lets the server short-circuit ~60 %+ of polls into a 304 with no body —
@@ -755,6 +762,18 @@ async function refresh() {
755
762
  return;
756
763
  }
757
764
  if (buildId) _knownDashboardBuildId = buildId;
765
+ // Auto-reload when the engine's commit changed (engine code was updated
766
+ // and process restarted, e.g. via `minions restart` after `git pull`).
767
+ // dashboardBuildId only hashes HTML/JS/CSS assets, so engine-only code
768
+ // updates don't trigger that path — leaving stale "Engine running v… —
769
+ // disk has v…" banners until the hourly /api/version repoll.
770
+ const engineCommit = (data.version && data.version.runningCommit) || null;
771
+ if (engineCommit && _knownEngineRunningCommit && engineCommit !== _knownEngineRunningCommit) {
772
+ console.log('Engine code changed — reloading page');
773
+ location.reload();
774
+ return;
775
+ }
776
+ if (engineCommit) _knownEngineRunningCommit = engineCommit;
758
777
  // Successful poll — clear unreachable state. Placed AFTER the reload
759
778
  // guards above so a dashboard restart still triggers location.reload()
760
779
  // instead of just dismissing the banner.
@@ -299,11 +299,19 @@ function evaluateCondition(condition, ctx) {
299
299
 
300
300
  switch (cond.check) {
301
301
  case 'runSucceeded': {
302
- // True when the current/last run completed with all stages succeeded (none failed)
302
+ // P-bfa1e finding #21: tightened predicate.
303
+ // Previously this accepted PENDING as "succeeded" via `s.status === COMPLETED || s.status === PENDING`,
304
+ // which let `stopWhen`/`stop-pipeline` short-circuit fire while stages were still queued for the next
305
+ // dispatch cycle. A "succeeded" run is one where:
306
+ // 1. The run object exists (no run → nothing has succeeded).
307
+ // 2. At least one stage exists (vacuous-truth empty `.every()` would otherwise lie about success).
308
+ // 3. EVERY stage is COMPLETED — RUNNING/PENDING/WAITING_HUMAN/PAUSED/FAILED/STOPPED all fail the check.
309
+ // Any `stopWhen` or condition-stage `stop-pipeline` consumer wired to `runSucceeded` now sees `false`
310
+ // until the run is fully done, so it cannot prematurely terminate the pipeline.
303
311
  if (!run) return false;
304
- return Object.values(run.stages || {}).every(
305
- s => s.status === PIPELINE_STATUS.COMPLETED || s.status === PIPELINE_STATUS.PENDING
306
- );
312
+ const stages = Object.values(run.stages || {});
313
+ if (stages.length === 0) return false;
314
+ return stages.every(s => s && s.status === PIPELINE_STATUS.COMPLETED);
307
315
  }
308
316
  case 'noFailedItems': {
309
317
  // True when all work items created by the pipeline are done (not failed)
@@ -1156,6 +1164,23 @@ async function discoverPipelineWork(config) {
1156
1164
  // Condition stage signaled pipeline stop — complete the run immediately
1157
1165
  if (result._stopPipeline) {
1158
1166
  completeRun(pipeline.id, activeRun.runId, PIPELINE_STATUS.STOPPED);
1167
+ // P-bfa1e finding #24: the local `activeRun` reference still has
1168
+ // `status === RUNNING` because we captured it at L980 before any
1169
+ // completion writes. The post-loop `allComplete` block at L1138
1170
+ // guards with `activeRun.status !== PIPELINE_STATUS.STOPPED`
1171
+ // before re-calling `completeRun(..., COMPLETED)` — if we leave
1172
+ // the stale RUNNING status in place that guard fails and we
1173
+ // clobber the STOPPED status with COMPLETED. Refresh the local
1174
+ // reference from disk so downstream reads in this same tick see
1175
+ // STOPPED. `getActiveRun` excludes terminal runs, so fall back
1176
+ // to a defensive in-place status patch when the refresh comes
1177
+ // back empty.
1178
+ const refreshed = getActiveRun(pipeline.id);
1179
+ if (refreshed) {
1180
+ activeRun = refreshed;
1181
+ } else {
1182
+ activeRun.status = PIPELINE_STATUS.STOPPED;
1183
+ }
1159
1184
  allComplete = true;
1160
1185
  break;
1161
1186
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yemi33/minions",
3
- "version": "0.1.2079",
3
+ "version": "0.1.2081",
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"
@@ -46,7 +46,7 @@ Your runtime is the **Copilot CLI**, not Claude Code. Your installed skills live
46
46
  - `~/.copilot/skills/<name>/SKILL.md` — user-level skills (yours)
47
47
  - `~/.copilot/installed-plugins/<marketplace>/<plugin>/skills/<name>/SKILL.md` — plugin-provided skills (also yours)
48
48
 
49
- To invoke a skill, call your `skill` tool with the skill name (the directory name). The skill body then guides the next steps.
49
+ To invoke a skill, call your `skill` tool with the skill name (the directory name). The skill body then guides the next steps. **Both user-level and plugin-level skills are invokable the same way** — the `<location>` tag in the registry is metadata, not a permission gate. If the registry below lists a skill, you can load it.
50
50
 
51
51
  When asked "what skills do you have", answer from the registry below — do NOT grep/glob `.claude/skills/`. Those belong to a different runtime (Claude Code) and are not available to you, even if the directory exists in cwd or `$HOME`.
52
52