@yemi33/minions 0.1.2301 → 0.1.2302
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 +42 -3
- package/engine/shared.js +42 -0
- package/package.json +1 -1
- package/prompts/cc-system.md +21 -0
package/dashboard.js
CHANGED
|
@@ -4263,12 +4263,25 @@ function _resetPreambleCache() {
|
|
|
4263
4263
|
_preambleCacheTs = 0;
|
|
4264
4264
|
}
|
|
4265
4265
|
|
|
4266
|
+
// Compact one-word-ish label for a project's effective dispatch checkout mode,
|
|
4267
|
+
// for CC state surfaces (preamble + refresh). 'worktree' | 'live' |
|
|
4268
|
+
// 'hybrid (live-validation: <type>)' so CC can see at a glance whether a project
|
|
4269
|
+
// authors in isolated worktrees, runs in-place on the operator tree, or splits
|
|
4270
|
+
// the two (coding → worktree, validation type → live). See resolveCheckoutMode.
|
|
4271
|
+
function _projectCheckoutModeLabel(p) {
|
|
4272
|
+
const mode = shared.resolveCheckoutMode(p);
|
|
4273
|
+
if (mode === 'live' && p && p.liveValidation && p.liveValidation.type) {
|
|
4274
|
+
return `hybrid (live-validation: ${p.liveValidation.type})`;
|
|
4275
|
+
}
|
|
4276
|
+
return mode;
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4266
4279
|
function buildCCStatePreamble() {
|
|
4267
4280
|
const now = Date.now();
|
|
4268
4281
|
if (_preambleCache && now - _preambleCacheTs < PREAMBLE_TTL) return _preambleCache;
|
|
4269
4282
|
// Lightweight snapshot — just enough to orient. Use tools for details.
|
|
4270
4283
|
const agents = getAgents().map(a => `- ${a.name} (${a.id}): ${a.status}${a.currentTask ? ' — ' + a.currentTask.slice(0, 60) : ''}`).join('\n');
|
|
4271
|
-
const projects = PROJECTS.map(p => `- ${p.name}: ${p.localPath}`).join('\n');
|
|
4284
|
+
const projects = PROJECTS.map(p => `- ${p.name}: ${p.localPath} [${_projectCheckoutModeLabel(p)}]`).join('\n');
|
|
4272
4285
|
|
|
4273
4286
|
const dq = getDispatchQueue();
|
|
4274
4287
|
const active = (dq.active || []).map(d => `- ${d.agentName || d.agent}: ${(d.task || '').slice(0, 50)}`).join('\n') || '(none)';
|
|
@@ -4340,7 +4353,7 @@ function buildCCStateRefresh() {
|
|
|
4340
4353
|
// Agent roster carries the current task too — without it a resumed session
|
|
4341
4354
|
// sees only that an agent is "busy", never *what* it is busy with.
|
|
4342
4355
|
const agents = getAgents().map(a => `- ${a.name}: ${a.status}${a.currentTask ? ' — ' + a.currentTask.slice(0, 50) : ''}`).join('\n');
|
|
4343
|
-
const projects = PROJECTS.map(p => `- ${p.name} (${p.repo || p.localPath})`).join('\n');
|
|
4356
|
+
const projects = PROJECTS.map(p => `- ${p.name} (${p.repo || p.localPath}) [${_projectCheckoutModeLabel(p)}]`).join('\n');
|
|
4344
4357
|
|
|
4345
4358
|
// MCP servers — just names + source for orientation
|
|
4346
4359
|
let mcpLine = '(none discovered)';
|
|
@@ -11337,6 +11350,31 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
11337
11350
|
}
|
|
11338
11351
|
// Drop the legacy field so a migrated project never carries both.
|
|
11339
11352
|
delete proj.worktreeMode;
|
|
11353
|
+
// Defensive cleanup: liveValidation is only honored under
|
|
11354
|
+
// checkoutMode:'live'. If this update moves the project OFF live,
|
|
11355
|
+
// drop any stale hybrid block so resolveCheckoutMode doesn't have to
|
|
11356
|
+
// warn-and-ignore an orphaned liveValidation on every resolve.
|
|
11357
|
+
if (shared.resolveCheckoutMode(proj) !== 'live') {
|
|
11358
|
+
delete proj.liveValidation;
|
|
11359
|
+
}
|
|
11360
|
+
}
|
|
11361
|
+
// Hybrid live-validation block (per-project). Only meaningful when the
|
|
11362
|
+
// resolved checkout mode is 'live' — runs AFTER the checkoutMode block
|
|
11363
|
+
// above so resolveCheckoutMode(proj) reflects the intended final mode.
|
|
11364
|
+
// Empty string / null clears the override; any other value flows
|
|
11365
|
+
// through shared.validateLiveValidation which throws HTTP 400 on
|
|
11366
|
+
// malformed input or when checkoutMode !== 'live'. Absent key leaves
|
|
11367
|
+
// any existing block untouched (so a Settings save that omits the
|
|
11368
|
+
// field never silently drops a configured hybrid project).
|
|
11369
|
+
if (Object.prototype.hasOwnProperty.call(update, 'liveValidation')) {
|
|
11370
|
+
const rawLv = update.liveValidation;
|
|
11371
|
+
if (rawLv === '' || rawLv === null || rawLv === undefined) {
|
|
11372
|
+
delete proj.liveValidation;
|
|
11373
|
+
} else {
|
|
11374
|
+
const validatedLv = shared.validateLiveValidation(rawLv, { checkoutMode: shared.resolveCheckoutMode(proj) });
|
|
11375
|
+
if (validatedLv === undefined) delete proj.liveValidation;
|
|
11376
|
+
else proj.liveValidation = validatedLv;
|
|
11377
|
+
}
|
|
11340
11378
|
}
|
|
11341
11379
|
}
|
|
11342
11380
|
}
|
|
@@ -14301,7 +14339,7 @@ What would you like to discuss or change? When you're happy, say "approve" and I
|
|
|
14301
14339
|
|
|
14302
14340
|
// Settings
|
|
14303
14341
|
{ method: 'GET', path: '/api/settings', desc: 'Return current engine + claude + routing config', handler: handleSettingsRead },
|
|
14304
|
-
{ method: 'POST', path: '/api/settings', desc: 'Update engine + claude + agent + projects config', params: 'engine?, claude?, agents?, projects?', handler: handleSettingsUpdate },
|
|
14342
|
+
{ method: 'POST', path: '/api/settings', desc: 'Update engine + claude + agent + projects config', params: 'engine?, claude?, agents?, projects? (per-project: checkoutMode, liveValidation, mainBranch, workSources)', handler: handleSettingsUpdate },
|
|
14305
14343
|
{ method: 'POST', path: '/api/settings/routing', desc: 'Update routing.md', params: 'content', handler: handleSettingsRouting },
|
|
14306
14344
|
{ method: 'POST', path: '/api/settings/reset', desc: 'Reset engine + claude + agent settings to defaults', handler: handleSettingsReset },
|
|
14307
14345
|
|
|
@@ -14512,6 +14550,7 @@ module.exports = {
|
|
|
14512
14550
|
_resolveScheduleProjectValue: resolveScheduleProjectValue,
|
|
14513
14551
|
_collectArchivedWorkItems: collectArchivedWorkItems,
|
|
14514
14552
|
buildCCStatePreamble,
|
|
14553
|
+
_projectCheckoutModeLabel,
|
|
14515
14554
|
buildCCStateRefresh,
|
|
14516
14555
|
_resetRefreshCache,
|
|
14517
14556
|
_routesAsMeta,
|
package/engine/shared.js
CHANGED
|
@@ -2757,6 +2757,47 @@ function validateCheckoutMode(value) {
|
|
|
2757
2757
|
return value;
|
|
2758
2758
|
}
|
|
2759
2759
|
|
|
2760
|
+
// Validate + normalize a per-project `liveValidation` block (hybrid mode).
|
|
2761
|
+
// Hybrid = checkoutMode:'live' + liveValidation:{ type, autoDispatch }: coding
|
|
2762
|
+
// work items author in isolated worktrees (escaping the live cap) while only
|
|
2763
|
+
// work items whose type === liveValidation.type run in-place on the live
|
|
2764
|
+
// checkout. See resolveCheckoutMode (which routes per work-item type) and
|
|
2765
|
+
// docs/live-checkout-mode.md.
|
|
2766
|
+
//
|
|
2767
|
+
// Returns:
|
|
2768
|
+
// - undefined → caller should clear the field (empty / null / '' input)
|
|
2769
|
+
// - { type, autoDispatch? } normalized object on success
|
|
2770
|
+
// Throws HTTP 400 (via _httpError) on malformed input, or when the effective
|
|
2771
|
+
// checkout mode is not 'live' (liveValidation is meaningless without it — it is
|
|
2772
|
+
// silently ignored at resolve time, so we refuse to persist a misconfiguration).
|
|
2773
|
+
//
|
|
2774
|
+
// `opts.checkoutMode` is the project's effective (resolved) checkout mode; pass
|
|
2775
|
+
// shared.resolveCheckoutMode(project) AFTER any checkoutMode update has been
|
|
2776
|
+
// applied so the gate sees the intended final mode.
|
|
2777
|
+
function validateLiveValidation(value, opts) {
|
|
2778
|
+
if (value === undefined || value === null || value === '') return undefined;
|
|
2779
|
+
if (typeof value !== 'object' || Array.isArray(value)) {
|
|
2780
|
+
throw _httpError(400, 'Invalid liveValidation: must be an object { type, autoDispatch }.');
|
|
2781
|
+
}
|
|
2782
|
+
const checkoutMode = opts && opts.checkoutMode;
|
|
2783
|
+
if (checkoutMode !== CHECKOUT_MODES.LIVE) {
|
|
2784
|
+
throw _httpError(400, 'liveValidation requires checkoutMode "live" (hybrid mode). Set checkoutMode to "live" first, or clear liveValidation.');
|
|
2785
|
+
}
|
|
2786
|
+
const type = typeof value.type === 'string' ? value.type.trim() : '';
|
|
2787
|
+
if (!type) {
|
|
2788
|
+
throw _httpError(400, 'Invalid liveValidation: "type" is required and must be a non-empty string — the work-item type that runs on the live checkout (e.g. "build-and-test").');
|
|
2789
|
+
}
|
|
2790
|
+
const out = { type };
|
|
2791
|
+
// autoDispatch (optional): when true, lifecycle auto-creates a validation WI
|
|
2792
|
+
// of `type` after each coding WI completes with a PR (engine/lifecycle.js
|
|
2793
|
+
// autoDispatchLiveValidationWi). Coerce to a strict boolean; absent leaves it
|
|
2794
|
+
// off so the operator opts in explicitly.
|
|
2795
|
+
if (Object.prototype.hasOwnProperty.call(value, 'autoDispatch')) {
|
|
2796
|
+
out.autoDispatch = !!value.autoDispatch;
|
|
2797
|
+
}
|
|
2798
|
+
return out;
|
|
2799
|
+
}
|
|
2800
|
+
|
|
2760
2801
|
// ── Engine Defaults ─────────────────────────────────────────────────────────
|
|
2761
2802
|
// Single source of truth for engine configuration defaults.
|
|
2762
2803
|
// Used by: engine.js, minions.js (init). config.template.json only has the project schema.
|
|
@@ -9192,6 +9233,7 @@ module.exports = {
|
|
|
9192
9233
|
validateProjectPath,
|
|
9193
9234
|
CHECKOUT_MODES,
|
|
9194
9235
|
validateCheckoutMode,
|
|
9236
|
+
validateLiveValidation,
|
|
9195
9237
|
resolveCheckoutMode,
|
|
9196
9238
|
isLiveCheckoutProject,
|
|
9197
9239
|
resolveLiveCheckoutAutoReset,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@yemi33/minions",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2302",
|
|
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"
|
package/prompts/cc-system.md
CHANGED
|
@@ -319,6 +319,27 @@ The `X-CC-Turn-Id` header is the audit trail — the handler stamps it onto the
|
|
|
319
319
|
|
|
320
320
|
**Errors:** if a `curl` returns 4xx/5xx, surface the error text in your reply so the user sees what went wrong. Don't retry blindly — usually the body explains the missing field.
|
|
321
321
|
|
|
322
|
+
## Project checkout modes (worktree / live / hybrid)
|
|
323
|
+
|
|
324
|
+
Every configured project has an effective **checkout mode** — surfaced in your state snapshot next to the project as `[worktree]`, `[live]`, or `[hybrid (live-validation: <type>)]`. It controls where dispatched agents run:
|
|
325
|
+
|
|
326
|
+
- **`worktree`** (default) — each dispatch gets its own isolated `git worktree`. Agents run fully in parallel; nothing touches the operator's working tree. Use for normal repos.
|
|
327
|
+
- **`live`** — agents run **in-place** inside the project's `localPath` (no worktree). The engine caps this to **one mutating dispatch at a time** per project and **refuses on a dirty tree**. Use only when worktrees are unworkable (e.g. Android `repo`, submodules, deep Windows paths, emulators that bind the real checkout).
|
|
328
|
+
- **`hybrid`** — `live` **plus** a `liveValidation: { type, autoDispatch }` block. Coding work items (`implement`/`fix`/`docs`/`decompose`) author in **isolated worktrees** (full parallelism), while **only** work items whose type matches `liveValidation.type` (e.g. `build-and-test`) run **in-place on the live checkout**. This is the best of both: parallel code authoring + a real on-disk build/validation that can't run in a worktree.
|
|
329
|
+
|
|
330
|
+
**When to recommend hybrid:** the project's build/test/validation genuinely cannot run in an isolated worktree (it needs the real checkout — submodules, a `repo`-managed tree, an emulator/dev-server bound to `localPath`, deep-path tooling), **but** you still want coding agents to work in parallel rather than serialize through the single live checkout. If the *whole* workflow must run on the real tree, use plain `live`. If nothing needs the real tree, stay on `worktree`.
|
|
331
|
+
|
|
332
|
+
**Configuring it** (via the projects array on `POST /api/settings` — never hand-edit `config.json`):
|
|
333
|
+
```bash
|
|
334
|
+
# Switch a project to hybrid mode (live checkout + deferred build-and-test validation)
|
|
335
|
+
curl -s -X POST http://localhost:{{dashboard_port}}/api/settings \
|
|
336
|
+
-H 'Content-Type: application/json' -H 'X-CC-Turn-Id: {{cc_turn_id}}' \
|
|
337
|
+
-d '{"projects":[{"name":"<project>","checkoutMode":"live","liveValidation":{"type":"build-and-test","autoDispatch":true}}]}'
|
|
338
|
+
# Clear hybrid (back to plain live): pass "liveValidation": null
|
|
339
|
+
# Clear live entirely (back to worktree): pass "checkoutMode": "worktree" (also clear liveValidation)
|
|
340
|
+
```
|
|
341
|
+
The server validates: `liveValidation` requires `checkoutMode:"live"` (400 otherwise) and a non-empty `type`. With `autoDispatch:true`, the engine auto-creates a `<type>` validation WI on the live checkout after each coding WI completes with a PR. **Always confirm the mode switch with the user before applying it** — it changes how every future dispatch on that project runs.
|
|
342
|
+
|
|
322
343
|
## GitHub auth
|
|
323
344
|
|
|
324
345
|
We have multiple authed `gh` accounts (`yemi33`, `yemishin_microsoft`) covering three repo scopes (`yemi33/minions`, `yemishin_microsoft/minions`, `opg-microsoft/minions`).
|