@yemi33/minions 0.1.2447 → 0.1.2449
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/bin/cli-api-client.js +1 -1
- package/bin/install-internal-minions.js +1382 -44
- package/bin/install-layout.js +150 -0
- package/bin/minions.js +460 -167
- package/dashboard/docs/typography.md +65 -12
- package/dashboard/js/command-center.js +66 -7
- package/dashboard/js/detail-panel.js +36 -0
- package/dashboard/js/memory-panel.js +59 -12
- package/dashboard/js/qa.js +186 -45
- package/dashboard/js/refresh.js +148 -12
- package/dashboard/js/render-dispatch.js +3 -4
- package/dashboard/js/render-inbox.js +2 -2
- package/dashboard/js/render-other.js +3 -3
- package/dashboard/js/render-pipelines.js +14 -0
- package/dashboard/js/render-plans.js +57 -9
- package/dashboard/js/render-prd.js +132 -23
- package/dashboard/js/render-prs.js +195 -166
- package/dashboard/js/render-schedules.js +63 -3
- package/dashboard/js/render-utils.js +3 -3
- package/dashboard/js/render-watches.js +19 -3
- package/dashboard/js/render-work-items.js +238 -30
- package/dashboard/js/settings.js +205 -54
- package/dashboard/js/utils.js +51 -1
- package/dashboard/pages/home.html +1 -1
- package/dashboard/pages/qa.html +1 -16
- package/dashboard/pages/work.html +40 -0
- package/dashboard/shared/cc-limits.js +79 -0
- package/dashboard/shared/pr-filters.js +21 -38
- package/dashboard/shared/project-git-summary.js +1 -1
- package/dashboard/shared/record-filters.js +169 -0
- package/dashboard/shared/watches-source.js +1 -1
- package/dashboard/shared/welcome-popup.js +1 -1
- package/dashboard/shared/wi-filters.js +302 -0
- package/dashboard/slim/body.html +1 -0
- package/dashboard/slim/js/command-send.js +26 -0
- package/dashboard/slim/js/modals-tiles.js +380 -39
- package/dashboard/slim/js/status.js +13 -21
- package/dashboard/slim/layout.html +1 -0
- package/dashboard/slim/panel-bootstrap.js +6 -2
- package/dashboard/slim/styles.css +38 -0
- package/dashboard/styles.css +159 -55
- package/dashboard-build.js +52 -6
- package/dashboard.js +956 -423
- package/docs/README.md +11 -6
- package/docs/api-errors.md +2 -2
- package/docs/architecture-review-2026-07-09.md +1 -1
- package/docs/architecture.excalidraw +2 -2
- package/docs/auto-discovery.md +18 -9
- package/docs/branch-derivation.md +4 -4
- package/docs/capture-demos.js +39 -2
- package/docs/ci-runner-canary.md +123 -0
- package/docs/claude-md-propagation.md +2 -2
- package/docs/cloud-agent-dispatch.md +204 -0
- package/docs/command-center.md +7 -7
- package/docs/completion-reports.md +43 -20
- package/docs/constants.md +10 -3
- package/docs/constellation-bridge.md +134 -6
- package/docs/constellation-style-telemetry.md +4 -4
- package/docs/contracts/capability-protocol.v1.json +165 -0
- package/docs/cooldown-merge-semantics.md +12 -12
- package/docs/copilot-cli-schema.md +7 -7
- package/docs/cross-repo-plans.md +10 -10
- package/docs/dead-code-audit-retractions.md +5 -5
- package/docs/default-branch-ci.md +173 -0
- package/docs/deprecated.json +31 -31
- package/docs/design-inbox-entries-schema.md +3 -3
- package/docs/design-language.md +1051 -0
- package/docs/design-state-storage.md +11 -11
- package/docs/diagnostics-crash-reports.md +9 -9
- package/docs/diagnostics-memory.md +5 -5
- package/docs/documentation-audit-2026-07-09.md +7 -7
- package/docs/engine-restart.md +90 -5
- package/docs/harness-mode.md +1 -1
- package/docs/internal-install.md +338 -39
- package/docs/kb-dedup-duplicate-pair-investigation.md +5 -5
- package/docs/kb-pr3223-cascade-archiving.md +1 -1
- package/docs/kb-pr696-merge-conflict-docs.md +6 -6
- package/docs/kb-sweep.md +35 -35
- package/docs/keep-processes.md +1 -1
- package/docs/live-checkout-mode.md +30 -30
- package/docs/managed-spawn.md +18 -14
- package/docs/named-agents.md +7 -7
- package/docs/plan-lifecycle.md +69 -2
- package/docs/pr-author-identity.md +114 -0
- package/docs/pr-auto-fix-dispatch.md +19 -4
- package/docs/pr-comment-followup.md +6 -6
- package/docs/pr-review-fix-loop.md +59 -10
- package/docs/process-termination.md +40 -0
- package/docs/proposals/repo-pool-for-live-checkout.md +13 -13
- package/docs/qa-runbook-lifecycle.md +367 -17
- package/docs/qa-runbooks.md +3 -3
- package/docs/rfc-completion-json.md +18 -18
- package/docs/runtime-adapters.md +26 -21
- package/docs/security.md +6 -6
- package/docs/self-improvement.md +4 -4
- package/docs/shared-lifecycle-module-map.md +473 -472
- package/docs/skills.md +52 -3
- package/docs/slim-ux/concepts.md +121 -116
- package/docs/specs/agent-configurability.md +18 -18
- package/docs/specs/agent-rename.md +18 -18
- package/docs/team-memory.md +38 -21
- package/docs/timeouts-and-liveness.md +118 -10
- package/docs/tutorials/01-install-and-connect.md +1 -1
- package/docs/watches.md +40 -39
- package/docs/workspace-manifests.md +4 -4
- package/docs/worktree-lifecycle.md +293 -14
- package/engine/README.md +46 -0
- package/engine/{ado-comment.js → ado/comment.js} +8 -8
- package/engine/{ado-git-auth.js → ado/git-auth.js} +4 -4
- package/engine/{ado.js → ado/index.js} +417 -63
- package/engine/{ado-status.js → ado/status.js} +6 -8
- package/engine/{ado-token.js → ado/token.js} +1 -1
- package/engine/{acp-transport.js → agents/acp-transport.js} +62 -22
- package/engine/{agent-worker-pool.js → agents/agent-worker-pool.js} +17 -8
- package/engine/{cc-worker-pool.js → agents/cc-worker-pool.js} +16 -6
- package/engine/{claude-md-context.js → agents/claude-md-context.js} +5 -5
- package/engine/{harness-context.js → agents/harness-context.js} +5 -5
- package/engine/{harness.js → agents/harness.js} +3 -3
- package/engine/{llm.js → agents/llm.js} +18 -14
- package/engine/{model-discovery.js → agents/model-discovery.js} +2 -2
- package/engine/{playbook.js → agents/playbook.js} +155 -22
- package/engine/{pooled-agent-process.js → agents/pooled-agent-process.js} +14 -12
- package/engine/{preflight.js → agents/preflight.js} +29 -10
- package/engine/{spawn-agent.js → agents/spawn-agent.js} +25 -14
- package/engine/{spawn-phase-watchdog.js → agents/spawn-phase-watchdog.js} +16 -7
- package/engine/{steering.js → agents/steering.js} +5 -5
- package/engine/{tools-inventory.js → agents/tools-inventory.js} +2 -2
- package/engine/{agent-api-validation.js → api/agent-api-validation.js} +2 -2
- package/engine/{api-validation.js → api/api-validation.js} +1 -1
- package/engine/api/bridge.js +787 -0
- package/engine/{cc-api-validation.js → api/cc-api-validation.js} +1 -1
- package/engine/api/companion.js +560 -0
- package/engine/{content-api-validation.js → api/content-api-validation.js} +2 -2
- package/engine/{pr-issue-validation.js → api/pr-issue-validation.js} +33 -6
- package/engine/{settings-validation.js → api/settings-validation.js} +32 -4
- package/engine/api-contracts/agent-content.js +4 -4
- package/engine/api-contracts/capability-manifest.js +236 -0
- package/engine/api-contracts/capability-protocol.js +333 -0
- package/engine/api-contracts/cc-ops.js +1 -1
- package/engine/api-contracts/config-runtime.js +5 -0
- package/engine/api-contracts/core.js +28 -1
- package/engine/api-contracts/index.js +100 -0
- package/engine/api-contracts/orchestration.js +18 -5
- package/engine/api-contracts/pull-requests.js +37 -6
- package/engine/api-contracts/qa-process.js +29 -6
- package/engine/api-contracts/work-plan-prd.js +21 -1
- package/engine/cloud/contract.js +212 -0
- package/engine/cloud/index.js +159 -0
- package/engine/{execution-model.js → core/execution-model.js} +1 -1
- package/engine/{features.js → core/features.js} +4 -4
- package/engine/{operator-identity.js → core/operator-identity.js} +1 -1
- package/engine/{queries.js → core/queries.js} +201 -36
- package/engine/{safe-expr.js → core/safe-expr.js} +1 -1
- package/engine/{shared.js → core/shared.js} +1637 -175
- package/engine/{stdio-timestamps.js → core/stdio-timestamps.js} +1 -1
- package/engine/{untrusted-fence.js → core/untrusted-fence.js} +3 -3
- package/engine/db/index.js +11 -2
- package/engine/db/migrations/002-dispatches.js +3 -3
- package/engine/db/migrations/003-work-items.js +1 -1
- package/engine/db/migrations/004-pull-requests.js +1 -1
- package/engine/db/migrations/006-metrics.js +1 -1
- package/engine/db/migrations/007-watches.js +2 -2
- package/engine/db/migrations/008-small-state.js +1 -1
- package/engine/db/migrations/009-qa.js +1 -1
- package/engine/db/migrations/010-pr-links.js +1 -1
- package/engine/db/migrations/011-remaining-state.js +1 -1
- package/engine/db/migrations/012-steering-deliveries.js +2 -2
- package/engine/db/migrations/013-backfill-broken-note-links.js +1 -1
- package/engine/db/migrations/014-pr-fix-target-prefs.js +2 -2
- package/engine/db/migrations/015-plans-prds.js +0 -0
- package/engine/db/migrations/018-sql-only-cutover.js +2 -2
- package/engine/db/migrations/021-archived-work-items.js +1 -1
- package/engine/db/migrations/022-global-cc-session.js +1 -1
- package/engine/db/migrations/023-engine-state.js +1 -1
- package/engine/db/migrations/025-malformed-work-item-phantoms.js +1 -1
- package/engine/db/migrations/027-review-learning-lifecycle.js +1 -1
- package/engine/db/migrations/029-repair-reused-versions.js +20 -0
- package/engine/db/migrations/031-pr-author-identity.js +137 -0
- package/engine/{consolidation.js → memory/consolidation.js} +6 -6
- package/engine/{kb-sweep-runner.js → memory/kb-sweep-runner.js} +2 -2
- package/engine/{kb-sweep.js → memory/kb-sweep.js} +9 -7
- package/engine/{memory-retrieval.js → memory/memory-retrieval.js} +46 -4
- package/engine/{memory-store.js → memory/memory-store.js} +3 -3
- package/engine/{promotion.js → memory/promotion.js} +3 -3
- package/engine/{review-learning-backfill.js → memory/review-learning-backfill.js} +6 -6
- package/engine/{review-learning.js → memory/review-learning.js} +10 -5
- package/engine/{diagnostics-memory.js → observability/diagnostics-memory.js} +1 -1
- package/engine/{logs-store.js → observability/logs-store.js} +5 -5
- package/engine/{metrics-store.js → observability/metrics-store.js} +4 -4
- package/engine/{check-status.js → operations/check-status.js} +3 -3
- package/engine/{cli.js → operations/cli.js} +271 -113
- package/engine/{distribution.js → operations/distribution.js} +5 -6
- package/engine/{cleanup.js → orchestration/cleanup.js} +72 -45
- package/engine/{cooldown.js → orchestration/cooldown.js} +5 -5
- package/engine/{dispatch-events.js → orchestration/dispatch-events.js} +2 -2
- package/engine/{dispatch.js → orchestration/dispatch.js} +129 -36
- package/engine/orchestration/failed-scheduled-cleanup.js +274 -0
- package/engine/{lifecycle.js → orchestration/lifecycle.js} +198 -90
- package/engine/{meeting.js → orchestration/meeting.js} +6 -16
- package/engine/{pipeline.js → orchestration/pipeline.js} +12 -12
- package/engine/{pre-dispatch-eval.js → orchestration/pre-dispatch-eval.js} +10 -9
- package/engine/{routing.js → orchestration/routing.js} +3 -3
- package/engine/{schedule-bootstrap.js → orchestration/schedule-bootstrap.js} +4 -4
- package/engine/{scheduler.js → orchestration/scheduler.js} +38 -8
- package/engine/{timeout.js → orchestration/timeout.js} +158 -109
- package/engine/{db-events.js → persistence/db-events.js} +2 -2
- package/engine/{dispatch-store.js → persistence/dispatch-store.js} +7 -7
- package/engine/{inbox-store.js → persistence/inbox-store.js} +2 -2
- package/engine/{note-link-backfill.js → persistence/note-link-backfill.js} +4 -4
- package/engine/{pr-fix-target-store.js → persistence/pr-fix-target-store.js} +8 -8
- package/engine/{pull-requests-store.js → persistence/pull-requests-store.js} +21 -7
- package/engine/{small-state-store.js → persistence/small-state-store.js} +31 -31
- package/engine/persistence/state-operations.js +350 -0
- package/engine/{steering-store.js → persistence/steering-store.js} +6 -6
- package/engine/{issues.js → planning/issues.js} +2 -2
- package/engine/{plan-prd-validation.js → planning/plan-prd-validation.js} +8 -2
- package/engine/planning/prd-result-sidecar.js +190 -0
- package/engine/{prd-store.js → planning/prd-store.js} +17 -17
- package/engine/{project-discovery.js → planning/project-discovery.js} +5 -5
- package/engine/{projects.js → planning/projects.js} +10 -10
- package/engine/{resolve-area.js → planning/resolve-area.js} +1 -1
- package/engine/{work-item-validation.js → planning/work-item-validation.js} +39 -3
- package/engine/{work-items-store.js → planning/work-items-store.js} +29 -21
- package/engine/{keep-process-sweep.js → processes/keep-process-sweep.js} +57 -17
- package/engine/{managed-spawn-launcher.js → processes/managed-spawn-launcher.js} +3 -3
- package/engine/{managed-spawn.js → processes/managed-spawn.js} +97 -46
- package/engine/{process-utils.js → processes/process-utils.js} +599 -55
- package/engine/{abandoned-pr-reconciliation.js → providers/abandoned-pr-reconciliation.js} +17 -7
- package/engine/{comment-classifier.js → providers/comment-classifier.js} +85 -17
- package/engine/{comment-format.js → providers/comment-format.js} +5 -5
- package/engine/{gh-comment.js → providers/gh-comment.js} +15 -15
- package/engine/{gh-token.js → providers/gh-token.js} +4 -4
- package/engine/{github.js → providers/github.js} +131 -54
- package/engine/{pr-action.js → providers/pr-action.js} +13 -12
- package/engine/{pr-clone-keep.js → providers/pr-clone-keep.js} +7 -7
- package/engine/{pr-devbox.js → providers/pr-devbox.js} +6 -6
- package/engine/{pr-fix-target.js → providers/pr-fix-target.js} +13 -13
- package/engine/{pr-remote-patch.js → providers/pr-remote-patch.js} +4 -4
- package/engine/{pr-resolve.js → providers/pr-resolve.js} +7 -7
- package/engine/{pr-temp-clone.js → providers/pr-temp-clone.js} +5 -5
- package/engine/{pr-track.js → providers/pr-track.js} +11 -13
- package/engine/{shared-branch-pr-reconcile.js → providers/shared-branch-pr-reconcile.js} +4 -4
- package/engine/qa/auto-prd-qa.js +313 -0
- package/engine/{qa-from-prd.js → qa/from-prd.js} +42 -12
- package/engine/qa/prd-session.js +240 -0
- package/engine/{qa-process-validation.js → qa/process-validation.js} +14 -9
- package/engine/{qa-runbooks.js → qa/runbooks.js} +1 -1
- package/engine/{qa-runs.js → qa/runs.js} +286 -15
- package/engine/{qa-sessions.js → qa/sessions.js} +595 -49
- package/engine/qa/visual-journey.js +654 -0
- package/engine/{qa-runners.js → qa-runners/index.js} +7 -7
- package/engine/qa-runners/maestro.js +3 -3
- package/engine/qa-runners/playwright.js +2 -2
- package/engine/{restart-health.js → recovery/restart-health.js} +48 -4
- package/engine/recovery/stop-stack.js +607 -0
- package/engine/{supervisor.js → recovery/supervisor.js} +105 -175
- package/engine/{watchdog.js → recovery/watchdog.js} +136 -13
- package/engine/runtimes/claude.js +14 -12
- package/engine/runtimes/codex.js +8 -6
- package/engine/runtimes/copilot.js +17 -16
- package/engine/{watch-actions.js → watches/actions.js} +13 -13
- package/engine/{watches.js → watches/index.js} +43 -32
- package/engine/{watches-store.js → watches/store.js} +4 -4
- package/engine/{create-pr-worktree.js → worktrees/create-pr.js} +1 -1
- package/engine/{worktree-gc.js → worktrees/gc.js} +70 -22
- package/engine/worktrees/inventory.js +671 -0
- package/engine/{live-checkout.js → worktrees/live-checkout.js} +4 -4
- package/engine/{worktree-pool.js → worktrees/pool.js} +2 -2
- package/engine/{worktree-preflight.js → worktrees/preflight.js} +1 -0
- package/engine/worktrees/quarantine-refs.js +173 -0
- package/engine.js +1137 -208
- package/minions.js +147 -77
- package/package.json +10 -6
- package/playbooks/_pr-description-audit.md +110 -78
- package/playbooks/build-fix-complex.md +2 -0
- package/playbooks/fix.md +16 -12
- package/playbooks/implement-shared.md +2 -0
- package/playbooks/implement.md +19 -20
- package/playbooks/plan-to-prd.md +18 -3
- package/playbooks/qa-session-draft.md +136 -1
- package/playbooks/qa-session-execute.md +80 -2
- package/playbooks/qa-session-setup.md +17 -1
- package/playbooks/qa-validate.md +1 -1
- package/playbooks/setup.md +2 -0
- package/playbooks/shared-rules.md +25 -32
- package/playbooks/templates/followup-dispatch.md +4 -3
- package/playbooks/verify.md +1 -1
- package/prompts/cc-system.md +19 -27
- package/watch-plugins/README.md +92 -0
- package/watch-plugins/ado-author-prs.js +336 -0
- package/watch-plugins/gh-author-prs.js +375 -0
- package/watch-plugins/http.js +474 -0
- package/watch-plugins/teams-channel.js +869 -0
- package/docs/dev-composite-workflow.md +0 -101
- package/docs/pr-screenshots/pr-886/after-single-header.png +0 -0
- package/docs/pr-screenshots/pr-886/before-duplicate-header.png +0 -0
- package/docs/pr-screenshots/pr-895/01-cancellation-reason-detail.png +0 -0
- package/docs/pr-screenshots/pr-899/worker-pool-worktrees-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-899/worker-pool-worktrees-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-901/projects-tab-default.png +0 -0
- package/docs/pr-screenshots/pr-901/projects-tab-fmf-selected.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-AFTER-crop.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-BEFORE-crop.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-dropdown-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-979/auto-fix-pane-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-979/auto-fix-pane-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-985/pr-column-em-dash-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-985/pr-column-em-dash-BEFORE.png +0 -0
- package/docs/visual-evidence-ci.md +0 -103
- package/engine/bridge.js +0 -379
- package/engine/quarantine-refs.js +0 -103
- package/engine/state-operations.js +0 -178
- /package/engine/{steering-constraints.js → agents/steering-constraints.js} +0 -0
package/dashboard/js/settings.js
CHANGED
|
@@ -191,6 +191,29 @@ async function openSettings() {
|
|
|
191
191
|
settingsField('CC Turn Timeout', 'set-ccTurnTimeoutMs', (e.ccTurnTimeoutMs || 300000) / 1000, 's', 'Per-turn no-progress watchdog for CC + doc-chat. Resets on every liveness signal (token chunk, tool call, tool update) so an actively-streaming turn — long shell command, deep search, sub-agent loop — survives indefinitely up to the outer 1h hard ceiling. Only true silence past this window fires event: error with code: cc-turn-timeout, stops the spinner, and offers Retry. Clamped to 10–3600 s.', '0.001') +
|
|
192
192
|
'</div>' +
|
|
193
193
|
'</details>' +
|
|
194
|
+
// Cloud dispatch (Agency / Copilot cloud) — the fleet-wide default
|
|
195
|
+
// provider for work items that declare `meta.executionSurface: "cloud"`.
|
|
196
|
+
// Collapsed by default: this is opt-in, and a fleet with no cloud
|
|
197
|
+
// provider configured behaves exactly as it always has.
|
|
198
|
+
'<details id="set-cloud-dispatch-details"' + (e.cloudProvider ? ' open' : '') + ' style="margin-top:8px;border-top:1px solid var(--border);padding-top:8px">' +
|
|
199
|
+
'<summary style="cursor:pointer;font-size:var(--text-base);color:var(--text);user-select:none">Cloud dispatch ' +
|
|
200
|
+
'<span style="font-size:var(--text-sm);color:var(--muted)">(hand a work item to a remote coding agent)</span>' +
|
|
201
|
+
'</summary>' +
|
|
202
|
+
'<div style="display:grid;grid-template-columns:1fr;gap:8px;margin-top:8px">' +
|
|
203
|
+
'<div data-search="cloud provider agency remote coding agent dispatch">' +
|
|
204
|
+
'<label style="font-size:var(--text-sm);color:var(--muted);display:block;margin-bottom:2px">Default Cloud Provider</label>' +
|
|
205
|
+
// Populated from /api/cloud-providers on open, and DISABLED with an
|
|
206
|
+
// explanatory hint when the registry is empty. The server validates
|
|
207
|
+
// against the same registry regardless — this is an affordance, not
|
|
208
|
+
// the gate — but a free-text input whose every non-empty value the
|
|
209
|
+
// server rejects is a control that cannot do what it advertises.
|
|
210
|
+
'<select id="set-cloudProvider" style="width:100%;padding:4px 6px;background:var(--surface);border:1px solid var(--border);border-radius:4px;color:var(--text);font-size:var(--text-md)">' +
|
|
211
|
+
'<option value="">Loading…</option>' +
|
|
212
|
+
'</select>' +
|
|
213
|
+
'<div id="set-cloudProvider-hint" style="font-size:var(--text-sm);color:var(--muted);margin-top:1px">Fleet-wide default for work items declaring <code>meta.executionSurface: "cloud"</code> — Minions investigates locally, renders the scoped dispatch instructions, and hands them to a REMOTE coding agent that authors its own PR. Overridden by <code>project.cloudProvider</code>, then <code>meta.cloudProvider</code>. Only PR-producing types (implement, fix, test, docs) may declare the cloud surface.</div>' +
|
|
214
|
+
'</div>' +
|
|
215
|
+
'</div>' +
|
|
216
|
+
'</details>' +
|
|
194
217
|
'</div>' +
|
|
195
218
|
'<h4>Agents</h4>' +
|
|
196
219
|
'<div style="font-size:var(--text-sm);color:var(--muted);margin-bottom:6px">CLI / Model placeholders show the fleet default each agent will inherit. Pick a value to pin per-agent; clear to re-inherit. Per-agent monthly budget overrides the fleet ceiling.</div>' +
|
|
@@ -199,14 +222,45 @@ async function openSettings() {
|
|
|
199
222
|
agentRows +
|
|
200
223
|
'</table>';
|
|
201
224
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
225
|
+
// W-ms4o7y1g007jdb2d — merged "Plan & PR Workflow" pane. Collapses the former
|
|
226
|
+
// sibling panes 'Auto-fix & Review Loop', 'PR Lifecycle', and 'Workflow
|
|
227
|
+
// Defaults' into ONE tab with three in-order subsections — (1) Plan,
|
|
228
|
+
// (2) PR creation, (3) Monitor. Every set-* id is preserved verbatim so the
|
|
229
|
+
// save/collect handler and the cross-tab settings search are untouched.
|
|
230
|
+
const panePlanPrWorkflow =
|
|
231
|
+
'<h3>Plan & PR Workflow</h3>' +
|
|
232
|
+
'<div class="settings-pane-sub">Everything here is <strong>automatic</strong> — each tile toggles one behavior in the plan→PR→monitor flow. Read top to bottom: what happens when a <strong>plan</strong> lands, what Minions does when it <strong>opens a PR</strong>, and how it <strong>monitors</strong> the PR watch→react loop afterward. Click a tile to enable/disable; enabled tiles are highlighted.</div>' +
|
|
233
|
+
|
|
234
|
+
// ── (1) PLAN ──
|
|
235
|
+
'<div class="settings-section-head"><span class="settings-section-num">1</span><span class="settings-section-title">Plan</span></div>' +
|
|
236
|
+
'<div class="settings-pane-sub">What happens automatically as a plan moves from draft → work items → archive.</div>' +
|
|
237
|
+
'<div class="settings-tile-grid" style="margin-bottom:20px">' +
|
|
238
|
+
settingsTile('Auto-approve Plans', 'set-autoApprovePlans', !!e.autoApprovePlans, 'PRDs are approved automatically without human review.', '✅', 'auto-approve plans') +
|
|
239
|
+
settingsTile('Auto-decompose', 'set-autoDecompose', e.autoDecompose !== false, 'Large implement items are auto-split into sub-tasks.', '🧩', 'auto-decompose large items') +
|
|
240
|
+
settingsTile('Auto-archive Plans', 'set-autoArchive', !!e.autoArchive, 'Automatically archive plans after verify completes (off = manual archive via dashboard).', '📦', 'auto-archive plans') +
|
|
241
|
+
settingsTile('Auto-QA verified PRDs', 'set-autoQaCompletedPrds', !!e.autoQaCompletedPrds, 'Opt-in: once a PRD\'s verify work item(s) complete SUCCESSFULLY and the canonical prd/guides/verify-*.md exists, automatically start a PRD-driven QA Session (mode "auto", so SETUP → DRAFT → EXECUTE runs without approval) through the same path as POST /api/qa/from-prd. Cross-repo plans wait for every per-project verify to succeed and launch ONE session. Failed/cancelled verification never launches QA. OFF (default) = today\'s behavior; the manual "QA this PRD" action is unaffected either way.', '🧪', 'auto qa verified completed prds qa session from prd') +
|
|
242
|
+
'</div>' +
|
|
243
|
+
|
|
244
|
+
// ── (2) PR CREATION ──
|
|
245
|
+
'<div class="settings-section-head"><span class="settings-section-num">2</span><span class="settings-section-title">PR Create</span></div>' +
|
|
246
|
+
'<div class="settings-pane-sub">What Minions does when it opens a PR. The Draft ⇄ Publish switch sets the fleet-wide default.</div>' +
|
|
247
|
+
'<div class="settings-stack" style="margin-bottom:12px">' +
|
|
248
|
+
settingsDraftPublishToggle('set-createPrsAsDraft', !!e.createPrsAsDraft, 'Create PRs as', 'Sets the fleet-wide default for how Minions-created PRs open. Draft = GitHub `gh pr create --draft`; ADO `az repos pr create --draft true`. Publish (default) opens PRs ready-for-review as today. Aggregate/E2E verify PRs already open as draft regardless of this flag.') +
|
|
249
|
+
'</div>' +
|
|
250
|
+
'<div class="settings-tile-grid" style="margin-bottom:20px">' +
|
|
251
|
+
settingsTile('Harnesses in PR body', 'set-includeHarnessSectionInPrBody', e.includeHarnessSectionInPrBody !== false, 'When ON (default), Minions-authored PRs get a fenced "Repo harnesses used" section listing the harness assets in effect for the dispatch\'s runtime + project — runtime, injected CLAUDE.md files, AGENTS.md discovery, MCP servers, and skills. Pure reporting from the same read-only source as `minions doctor --harness`; it does not change harness propagation. OFF suppresses the section.', '🧰', 'surface repo harnesses in pr body') +
|
|
252
|
+
settingsTile('Auto-apply review vote', 'set-autoApplyReviewVote', !!e.autoApplyReviewVote, 'When ON, Minions review verdicts (APPROVE / REQUEST_CHANGES) automatically flip the platform vote on ADO/GitHub. When OFF (default), verdicts are informational only and the human casts the final vote.', '🗳️', 'auto-apply review vote to pr') +
|
|
253
|
+
settingsTile('Auto-complete PRs', 'set-autoCompletePrs', !!e.autoCompletePrs, 'Auto-merge PRs when builds pass and review is approved (opt-in). Independent of the per-cause auto-fix gates above.', '🎯', 'auto-complete prs auto-merge') +
|
|
254
|
+
'</div>' +
|
|
255
|
+
|
|
256
|
+
// ── (3) MONITOR ──
|
|
257
|
+
'<div class="settings-section-head"><span class="settings-section-num">3</span><span class="settings-section-title">Monitor</span></div>' +
|
|
258
|
+
'<div class="settings-pane-sub">The PR watch→react loop. Everything here is <strong>automatic</strong>. The <em>Pause ALL</em> kill-switch inerts every per-cause trigger at once; all PR triggers also require the matching provider polling (Polling tab).</div>' +
|
|
205
259
|
'<div class="settings-stack" style="margin-bottom:16px">' +
|
|
206
260
|
settingsToggle('🛑 Pause ALL PR auto-fix dispatches', 'set-autoFixPaused', !!e.autoFixPaused, 'Halts every PR-triggered dispatch (review, re-review, build-failure fix, review-feedback fix, human-comment fix, merge-conflict fix) on the next tick. In-flight agents keep running. Reversible without restart. Per-cause tiles below are inert while this is set.') +
|
|
207
261
|
'</div>' +
|
|
208
|
-
'<div class="settings-pane-sub" style="margin-bottom:8px">Per-cause triggers — each tile automatically dispatches an agent for one PR signal
|
|
209
|
-
'<div class="settings-tile-grid" style="margin-bottom:
|
|
262
|
+
'<div class="settings-pane-sub" style="margin-bottom:8px">Per-cause triggers — each tile automatically dispatches an agent for one PR signal. Enabled tiles are highlighted; disabled tiles are dimmed. When <em>Pause ALL</em> is ON every tile is inert.</div>' +
|
|
263
|
+
'<div class="settings-tile-grid" style="margin-bottom:20px">' +
|
|
210
264
|
settingsTile('Fix Builds', 'set-autoFixBuilds', e.autoFixBuilds !== false, 'Shared dispatch gate: auto-fix agent when a PR build fails; also requires that PR provider polling is enabled', '🔨', 'auto-fix builds') +
|
|
211
265
|
settingsTile('Conflicts', 'set-autoFixConflicts', e.autoFixConflicts !== false, 'Shared dispatch gate: auto-fix agent when a PR merge conflict is detected; also requires that PR provider polling is enabled', '🔀', 'auto-fix conflicts') +
|
|
212
266
|
settingsTile('Review PRs', 'set-autoReviewPrs', e.autoReviewPrs !== false, 'Shared dispatch gate: review agent for newly opened agent PRs; also requires that PR provider polling is enabled', '🔍', 'auto-review prs') +
|
|
@@ -214,46 +268,15 @@ async function openSettings() {
|
|
|
214
268
|
settingsTile('Review Feedback', 'set-autoFixReviewFeedback', e.autoFixReviewFeedback !== false, 'Shared dispatch gate: fix agent for minions changes-requested verdicts; also requires that PR provider polling is enabled', '✍️', 'auto-fix review feedback') +
|
|
215
269
|
settingsTile('Address Human Comments', 'set-autoFixHumanComments', e.autoFixHumanComments !== false, 'Shared dispatch gate: fix agent for actionable human PR comments; also requires that PR provider polling is enabled', '💬', 'auto-fix human comments') +
|
|
216
270
|
'</div>' +
|
|
217
|
-
'<div class="settings-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
271
|
+
'<div class="settings-pane-sub" style="margin-bottom:8px">Review→fix loop gating — the cheap-LLM screens that decide whether the review/fix loop runs at all.</div>' +
|
|
272
|
+
'<div class="settings-tile-grid" style="margin-bottom:12px">' +
|
|
273
|
+
settingsTile('Eval Loop', 'set-evalLoop', e.evalLoop !== false, 'Gates the review→fix iteration loop only (first review, re-review, review-feedback fix). Does NOT gate build-failure, merge-conflict, or human-comment fixes. Use the emergency stop above to halt everything.', '🔁', 'eval loop review fix iteration') +
|
|
274
|
+
settingsTile('Pre-dispatch Eval', 'set-enablePreDispatchEval', e.enablePreDispatchEval !== false, 'P-d2a9f6e5: cheap LLM gate that screens work items for clear/actionable/testable criteria BEFORE queueing the agent. Catches noop dispatches authored from impossible/ambiguous WIs. Fail-open on any validator error.', '🧪', 'pre-dispatch eval cheap llm gate') +
|
|
275
|
+
settingsTile('Skip PRD-sourced', 'set-preDispatchEvalSkipPrdSourced', e.preDispatchEvalSkipPrdSourced !== false, 'W-mq9acoo800177bcb: short-circuit the validator for items materialized from an approved/active PRD — plan-to-prd already LLM-vets them. Reduces queue-time on an N-item approved PRD from ~N×25s to nearly instant. OFF = always re-validate even PRD-sourced items.', '⏭️', 'pre-dispatch eval skip prd sourced items') +
|
|
221
276
|
'</div>' +
|
|
222
|
-
'<div class="settings-grid-2">' +
|
|
277
|
+
'<div class="settings-grid-2" style="margin-bottom:20px">' +
|
|
223
278
|
settingsField('Eval Max Cost', 'set-evalMaxCost', e.evalMaxCost === null || e.evalMaxCost === undefined ? '' : e.evalMaxCost, '$', 'USD ceiling per work item across all eval iterations (blank = no limit)') +
|
|
224
279
|
settingsField('Pre-dispatch Eval Concurrency', 'set-preDispatchEvalConcurrency', e.preDispatchEvalConcurrency || 6, '', 'W-mq9acoo800177bcb: max parallel pre-dispatch validator calls per discovery tick. Default 6. Clamped to [1, 20]. Raises throughput when multiple PRDs queue at once; lower if the LLM provider throttles. 1 = sequential (pre-fix behavior).') +
|
|
225
|
-
'</div>' +
|
|
226
|
-
'<div style="margin-top:12px;padding:6px 8px;border:1px solid var(--border);border-radius:4px;background:rgba(130,160,210,0.06);font-size:var(--text-sm);color:var(--muted)">' +
|
|
227
|
-
'Moved to <strong>PR Lifecycle</strong>: Auto-complete PRs, Auto-apply review vote. ' +
|
|
228
|
-
'Moved to <strong>Workflow Defaults</strong>: Auto-archive Plans, Auto-approve Plans, Auto-decompose, Auto-consolidate Memory.' +
|
|
229
|
-
'</div>';
|
|
230
|
-
|
|
231
|
-
// P-g7a2b4c5 — new "PR Lifecycle" pane. Owns the two PR-lifecycle knobs
|
|
232
|
-
// that historically lived under Auto-fix but do NOT gate any dispatch:
|
|
233
|
-
// autoApplyReviewVote (lifecycle vote-posting), autoCompletePrs (auto-merge).
|
|
234
|
-
const paneLifecycle =
|
|
235
|
-
'<h3>PR Lifecycle</h3>' +
|
|
236
|
-
'<div class="settings-pane-sub">Post-merge / post-review lifecycle knobs. These are not dispatch gates — they control what Minions does with a PR once review or build state lands.</div>' +
|
|
237
|
-
'<div class="settings-stack">' +
|
|
238
|
-
settingsToggle('Auto-apply review vote to PR', 'set-autoApplyReviewVote', !!e.autoApplyReviewVote, 'When ON, Minions review verdicts (APPROVE / REQUEST_CHANGES) automatically flip the platform vote on ADO/GitHub. When OFF (default), verdicts are informational only and the human casts the final vote.') +
|
|
239
|
-
settingsToggle('Create PRs as draft', 'set-createPrsAsDraft', !!e.createPrsAsDraft, 'When ON, Minions-created PRs open as DRAFT (GitHub `gh pr create --draft`; ADO `az repos pr create --draft true`). When OFF (default), PRs open ready-for-review as today. Aggregate/E2E verify PRs already open as draft regardless of this flag.') +
|
|
240
|
-
settingsToggle('Auto-complete PRs', 'set-autoCompletePrs', !!e.autoCompletePrs, 'Auto-merge PRs when builds pass and review is approved (opt-in). Independent of the per-cause auto-fix gates above.') +
|
|
241
|
-
settingsToggle('Surface repo harnesses in PR body', 'set-includeHarnessSectionInPrBody', e.includeHarnessSectionInPrBody !== false, 'When ON (default), Minions-authored PRs get a fenced "Repo harnesses used" section listing the harness assets in effect for the dispatch\'s runtime + project — runtime, injected CLAUDE.md files, AGENTS.md discovery, MCP servers, and skills. Pure reporting from the same read-only source as `minions doctor --harness`; it does not change harness propagation. OFF suppresses the section.') +
|
|
242
|
-
'</div>';
|
|
243
|
-
|
|
244
|
-
// P-g7a2b4c5 — new "Workflow Defaults" pane. Owns the four workflow-level
|
|
245
|
-
// automation defaults that historically lived under Auto-fix: plan-flow
|
|
246
|
-
// (approve / decompose / archive) and memory consolidation. None of these
|
|
247
|
-
// gate a PR-triggered dispatch.
|
|
248
|
-
const paneWorkflow =
|
|
249
|
-
'<h3>Workflow Defaults</h3>' +
|
|
250
|
-
'<div class="settings-pane-sub">Workflow-level automation defaults. Independent of PR dispatch and PR lifecycle — these control plan flow and memory upkeep.</div>' +
|
|
251
|
-
'<div class="settings-stack">' +
|
|
252
|
-
settingsToggle('Auto-approve Plans', 'set-autoApprovePlans', !!e.autoApprovePlans, 'PRDs are approved automatically without human review.') +
|
|
253
|
-
settingsToggle('Auto-decompose', 'set-autoDecompose', e.autoDecompose !== false, 'Large implement items are auto-split into sub-tasks.') +
|
|
254
|
-
settingsToggle('Auto-archive Plans', 'set-autoArchive', !!e.autoArchive, 'Automatically archive plans after verify completes (off = manual archive via dashboard).') +
|
|
255
|
-
settingsToggle('Auto-consolidate Memory', 'set-autoConsolidateMemory', !!e.autoConsolidateMemory, 'Enabled by default. Periodically spawn the KB sweep (dedup + compress + normalize knowledge/) from the engine tick on a 4h cadence. Inbox→notes consolidation runs independently every tick.') +
|
|
256
|
-
settingsToggle('Bootstrap Default Schedules', 'set-bootstrapDefaultSchedules', e.bootstrapDefaultSchedules !== false, 'Auto-create the per-project git-fetch-freshness schedule (every 12h) when a project is added, and ensure one shared daily harness-sweep schedule exists engine-wide. Idempotent and non-destructive — never overwrites a schedule you have customized. Turn off to manage these schedules entirely by hand.') +
|
|
257
280
|
'</div>';
|
|
258
281
|
|
|
259
282
|
// W-mpmwxkrw000872ec — Appearance pane. Hosts dashboard-wide visual
|
|
@@ -445,7 +468,7 @@ async function openSettings() {
|
|
|
445
468
|
'<option value="draft"' + (createPrsAsDraftRaw === 'draft' ? ' selected' : '') + '>Draft — open PRs as draft</option>' +
|
|
446
469
|
'<option value="ready"' + (createPrsAsDraftRaw === 'ready' ? ' selected' : '') + '>Not draft — open PRs ready</option>' +
|
|
447
470
|
'</select>' +
|
|
448
|
-
'<div style="font-size:var(--text-
|
|
471
|
+
'<div style="font-size:var(--text-sm);color:var(--muted);margin-top:2px;line-height:1.4">Overrides the fleet-wide "Create PRs as draft" setting under Plan & PR Workflow → PR creation for THIS project only. Draft = Minions-created PRs open as draft (GitHub `--draft`; ADO `--draft true`). Inherit follows the engine flag. Aggregate/E2E verify PRs and the shared-branch aggregate PR are unaffected.</div>' +
|
|
449
472
|
'</div>';
|
|
450
473
|
// W-mrchrfe100067d3a — per-project explicit allowlist of secondary repo
|
|
451
474
|
// scopes this project's checkout is also allowed to track PRs for (e.g.
|
|
@@ -510,6 +533,10 @@ async function openSettings() {
|
|
|
510
533
|
settingsToggle('ADO Polling', 'set-adoPollEnabled', e.adoPollEnabled !== false, 'Legacy bundle macro — when OFF, silences all three ADO axes (status, comments, reconcile) and ADO PR dispatch gates are inert when this is off. Per-axis flags below take priority when explicitly set. Keep ON unless you want a one-knob ADO kill.') +
|
|
511
534
|
settingsToggle('GitHub Polling', 'set-ghPollEnabled', e.ghPollEnabled !== false, 'Legacy bundle macro — when OFF, silences all three GitHub axes (status, comments, reconcile) and GitHub PR dispatch gates are inert when this is off. Per-axis flags below take priority when explicitly set. Keep ON unless you want a one-knob GitHub kill.') +
|
|
512
535
|
'</div>' +
|
|
536
|
+
'<div class="settings-pane-sub" style="margin-bottom:8px">Poll-side actions — these ride on the PR status poll (so they honor <em>Pause ALL polling</em> and the matching provider toggle above), but they write to the platform instead of dispatching a Minions agent. They are therefore <strong>not</strong> covered by the <em>Pause ALL PR auto-fix</em> switch on the Plan & PR Workflow tab, which by design leaves polling and build-status acquisition running.</div>' +
|
|
537
|
+
'<div class="settings-stack" style="margin-bottom:12px">' +
|
|
538
|
+
settingsToggle('Queue Draft PR Builds (ADO)', 'set-adoQueueDraftPrBuilds', e.adoQueueDraftPrBuilds !== false, 'ADO-only: proactively queue the required branch-policy validation builds for DRAFT pull requests. Azure DevOps does NOT auto-run branch build policies while a PR is a draft, so a Minions-managed draft PR never gets a build status and the build-fix loop has nothing to act on. When ON (default), Minions discovers the required Build policies from the target branch and queues a fresh build per definition against refs/pull/<n>/merge (rate-limited to once per PR / 30 min). Queues builds only — it never dispatches an agent. Inert for GitHub PRs (GitHub already fires CI on drafts) and whenever ADO PR status polling is off or paused.', { blockHint: true }) +
|
|
539
|
+
'</div>' +
|
|
513
540
|
'<details class="settings-collapsible" style="margin-bottom:12px"><summary>Granular per-poller controls (P-c4d8e1a3)</summary>' +
|
|
514
541
|
'<div class="settings-pane-sub" style="margin-top:8px">Override individual ADO/GitHub poll axes + the pending-rebase processor. Explicit values here win; if unset, the legacy ADO/GitHub Polling macros above apply; otherwise the default is ON. <strong>Status</strong>, <strong>Comments</strong> and <strong>Reconcile</strong> all honor the <em>Pause All Polling</em> kill-switch above (reconcile included since W-ms5eljc60090f0d5 — it issues provider API calls); only <strong>Process Pending Rebases</strong> ignores it (by design — it makes no provider poll call).</div>' +
|
|
515
542
|
'<div class="settings-stack" style="margin-top:8px">' +
|
|
@@ -533,6 +560,7 @@ async function openSettings() {
|
|
|
533
560
|
'<div class="settings-grid-2">' +
|
|
534
561
|
settingsField('PR Status Poll Frequency', 'set-prPollStatusEvery', e.prPollStatusEvery ?? 12, 'ticks', 'Poll PR build/review/merge status every N ticks for both ADO and GitHub (~12 min at default tick rate)') +
|
|
535
562
|
settingsField('PR Comments Poll Frequency', 'set-prPollCommentsEvery', e.prPollCommentsEvery ?? 12, 'ticks', 'Poll PR human comments every N ticks for both ADO and GitHub (~12 min at default tick rate)') +
|
|
563
|
+
settingsField('Abandoned PR Re-probe Window', 'set-abandonedPrRepollWindowDays', Number((((e.abandonedPrRepollWindowMs ?? (7 * 24 * 60 * 60 * 1000)) / (24 * 60 * 60 * 1000))).toFixed(2)), 'days', 'How long after a PR is stamped `abandoned` the STATUS poll keeps re-probing it, so a PR that was closed and then REOPENED can leave the terminal stamp instead of being invisible to the pollers forever. Only the status poll re-probes (never the comment poll), a host-confirmed deletion closes the window early, and records with no known abandonment time are never re-probed. Set 0 to disable re-probing entirely (strict pre-W-msav5edk00g81710 behavior). Clamped 0–90 days.', '0.01') +
|
|
536
564
|
'</div>';
|
|
537
565
|
|
|
538
566
|
const paneConcurrency =
|
|
@@ -591,10 +619,12 @@ async function openSettings() {
|
|
|
591
619
|
'</div>' +
|
|
592
620
|
'<div class="settings-grid-2">' +
|
|
593
621
|
settingsField('CC Session Idle Timeout', 'set-ccWorkerIdleTimeoutMs', Math.round((e.ccWorkerIdleTimeoutMs || 1800000) / 60000), 'minutes', 'How long a persistent `copilot --acp` CC worker stays warm with no activity before the idle reaper kills it. After a reap the next message cold-spawns a FRESH session with no memory of prior turns and CC shows a "context cleared after inactivity" notice. Shorter = less idle memory/process footprint; longer = more context durability across gaps between messages. Only affects the Copilot worker-pool path (CC Worker Pool ON). Clamped 1–480 minutes. Ignored when "Never idle-reap CC workers" below is ON.') +
|
|
622
|
+
settingsField('ACP Handshake Timeout', 'set-acpHandshakeTimeoutMs', Math.round((e.acpHandshakeTimeoutMs || 180000) / 1000), 's', 'Budget for a COLD `copilot --acp` worker handshake — the `initialize` call plus the follow-up `session/new` / `session/load`. Applies to both ACP worker pools (Command Center and the per-agent fleet pool). A cold start that loads your MCP configuration routinely needs ~95 s, and the old hardcoded 60 s surfaced as "Command Center returned no output / handshake timed out after 60000ms" (issue #1105). Warm-worker reuse is unaffected — this only bounds the cold startup handshake. On expiry the pool still raises the typed, retriable ACP handshake error. Clamped 10–900 s.', '0.001') +
|
|
594
623
|
settingsField('Worktree Create Timeout', 'set-worktreeCreateTimeout', (e.worktreeCreateTimeout || 300000) / 1000, 's', 'Timeout for git worktree add (increase for large repos/Windows)', '0.001') +
|
|
595
624
|
settingsField('Worktree Create Retries', 'set-worktreeCreateRetries', e.worktreeCreateRetries || 1, '', 'Retry count for transient worktree add failures (0-3)') +
|
|
596
625
|
settingsField('Worktree Root', 'set-worktreeRoot', e.worktreeRoot || '../worktrees', '', 'Relative or absolute path for git worktrees; on Windows prefer a short path like C:\\wt') +
|
|
597
626
|
settingsField('Minimum Free Space', 'set-worktreeMinFreeSpaceGiB', Number(((e.worktreeMinFreeSpaceBytes ?? (10 * 1024 * 1024 * 1024)) / (1024 * 1024 * 1024)).toFixed(2)), 'GiB', 'Defer worktree-mode dispatch before git worktree add when the target filesystem has less free space than this reserve. The pending item is re-checked every tick and does not consume an agent retry. Set 0 to disable.') +
|
|
627
|
+
settingsField('Protected Quarantine Retention', 'set-worktreeProtectedQuarantineRetentionDays', Number((((e.worktreeProtectedQuarantineRetentionMs ?? (30 * 24 * 60 * 60 * 1000)) / (24 * 60 * 60 * 1000))).toFixed(2)), 'days', 'How long the GC keeps a PROTECTED quarantine directory — one whose dirty WIP could not be snapshotted to a durable refs/minions/quarantine-wip/* ref, so the directory itself is the only recovery artifact. Defaults to the shared 30-day quarantine-REF retention window (engine/core/shared.js#QUARANTINE_REF_RETENTION_MS) and also DRIVES that recovery-REF sweep, so changing this value moves directories and their refs together instead of shortening only one side. These were previously kept forever, which is how a busy install accumulates quarantine residue. Set 0 to restore indefinite retention for both. Clamped 0–365 days.', '0.01') +
|
|
598
628
|
settingsField('Assert-Clean Status Probe Timeout', 'set-assertCleanStatusTimeoutMs', (e.assertCleanStatusTimeoutMs || 10000) / 1000, 's', 'Timeout for the `git status --porcelain` preflight probe in assertCleanSharedWorktree. Raise this (e.g. 60) on GVFS/Plastic-backed monorepos where sparse hydration runs longer than the 10s default. On timeout the engine quarantines the bad worktree and emits a RETRYABLE failure so the next dispatch starts fresh. Clamped 1–120 s.', '0.001') +
|
|
599
629
|
settingsField('Restart-health Timeout', 'set-restartHealthTimeoutMs', (e.restartHealthTimeoutMs || 60000) / 1000, 's', 'Cold-start budget for `minions restart` / post-update restart verification. The dashboard runs node:sqlite migrations + SPA HTML assembly + initial state reads synchronously BEFORE it binds its port, so right after `npm install` on a slow/loaded box the PID is alive but the port is unbound for tens of seconds. Below this budget that no longer prints a false "Restart verification failed" + exit(1) — the verifier keeps polling until the port listens. A genuinely crashed spawn (PID dies) still fails fast, well under the full budget. Clamped 15–300 s.', '0.001') +
|
|
600
630
|
settingsField('Orphan-holder scan timeout', 'set-orphanHolderScanTimeoutMs', (e.orphanHolderScanTimeoutMs || 5000) / 1000, 's', 'Cap on the cross-platform scan (PowerShell / /proc walk / lsof) that identifies the OS process holding a stuck worktree\'s cwd. Bumps up only matter on heavily-loaded hosts where the holder scan races the sweep tick. Clamped 1–30 s.', '0.001') +
|
|
@@ -649,7 +679,7 @@ async function openSettings() {
|
|
|
649
679
|
'<option value="workspace-write"' + (e.codexCcSandbox === 'workspace-write' ? ' selected' : '') + '>workspace-write</option>' +
|
|
650
680
|
'<option value="read-only"' + (e.codexCcSandbox === 'read-only' ? ' selected' : '') + '>read-only</option>' +
|
|
651
681
|
'</select>' +
|
|
652
|
-
'<div style="font-size:var(--text-
|
|
682
|
+
'<div style="font-size:var(--text-sm);color:var(--muted);margin-top:4px"><strong>Security:</strong> <code>danger-full-access</code> lets Codex CC reach localhost Minions APIs and operator-authorized paths outside <code>~/.minions</code>. Dispatched Codex agents and non-CC calls remain <code>workspace-write</code>. The adapter emits an explicit <code>--sandbox</code> CLI flag, which takes precedence over Codex config-file values.</div>' +
|
|
653
683
|
'</div>' +
|
|
654
684
|
'</div>';
|
|
655
685
|
|
|
@@ -693,13 +723,13 @@ async function openSettings() {
|
|
|
693
723
|
const displayFeatures = featuresList.filter(function(f) { return f.id !== 'slim-ux'; });
|
|
694
724
|
const paneFeatures =
|
|
695
725
|
'<h3>Feature Flags</h3>' +
|
|
696
|
-
'<div class="settings-pane-sub">In-progress UX or behavior gates. Toggles persist immediately. Registry: <code>engine/features.js</code>. Env override: <code>MINIONS_FEATURE_<NAME>=1</code>.</div>' +
|
|
726
|
+
'<div class="settings-pane-sub">In-progress UX or behavior gates. Toggles persist immediately. Registry: <code>engine/core/features.js</code>. Env override: <code>MINIONS_FEATURE_<NAME>=1</code>.</div>' +
|
|
697
727
|
'<details id="settings-features-details" open style="border:1px solid var(--border);border-radius:6px;padding:12px">' +
|
|
698
728
|
'<summary style="cursor:pointer;font-size:var(--text-md);color:var(--text);user-select:none;margin-bottom:8px">Show experimental flags ' +
|
|
699
729
|
'<span style="font-size:var(--text-sm);color:var(--muted)">(' + displayFeatures.length + ' registered)</span>' +
|
|
700
730
|
'</summary>' +
|
|
701
731
|
(displayFeatures.length === 0
|
|
702
|
-
? '<div style="font-size:var(--text-base);color:var(--muted);padding:12px;border:1px dashed var(--border);border-radius:4px;text-align:center">No experimental features registered. Add entries to <code>engine/features.js</code> to gate new work.</div>'
|
|
732
|
+
? '<div style="font-size:var(--text-base);color:var(--muted);padding:12px;border:1px dashed var(--border);border-radius:4px;text-align:center">No experimental features registered. Add entries to <code>engine/core/features.js</code> to gate new work.</div>'
|
|
703
733
|
: '<div style="display:flex;flex-direction:column;gap:8px">' +
|
|
704
734
|
displayFeatures.map(function(f) {
|
|
705
735
|
const checked = f.enabled ? ' checked' : '';
|
|
@@ -755,6 +785,15 @@ async function openSettings() {
|
|
|
755
785
|
settingsToggle('Allow Temp Agents', 'set-allowTempAgents', !!e.allowTempAgents, 'Spawn ephemeral agents when all permanent agents are busy') +
|
|
756
786
|
settingsToggle('Disable model discovery', 'set-disableModelDiscovery', !!e.disableModelDiscovery, 'Skip /api/runtimes/<name>/models REST calls fleet-wide. Settings UI falls back to free-text.') +
|
|
757
787
|
'</div>' +
|
|
788
|
+
// W-ms4o7y1g007jdb2d follow-up — engine-tick upkeep automation defaults moved
|
|
789
|
+
// here out of the Plan & PR Workflow tab (they are engine maintenance, not the
|
|
790
|
+
// per-PR watch→react loop). set-* ids are unchanged so save/collect + search
|
|
791
|
+
// are untouched.
|
|
792
|
+
'<h4>Engine automation</h4>' +
|
|
793
|
+
'<div class="settings-stack">' +
|
|
794
|
+
settingsToggle('Auto-consolidate Memory', 'set-autoConsolidateMemory', !!e.autoConsolidateMemory, 'Enabled by default. Periodically spawn the KB sweep (dedup + compress + normalize knowledge/) from the engine tick on a 4h cadence. Inbox→notes consolidation runs independently every tick.') +
|
|
795
|
+
settingsToggle('Bootstrap Default Schedules', 'set-bootstrapDefaultSchedules', e.bootstrapDefaultSchedules !== false, 'Auto-create the per-project git-fetch-freshness schedule (every 12h) when a project is added, and ensure one shared daily harness-sweep schedule exists engine-wide. Idempotent and non-destructive — never overwrites a schedule you have customized. Turn off to manage these schedules entirely by hand.') +
|
|
796
|
+
'</div>' +
|
|
758
797
|
// W-mqk2s8q1 — dashboard refresh diagnostics, relocated here from the
|
|
759
798
|
// floating bottom-left "diag" chip so it sits alongside the other
|
|
760
799
|
// diagnostic/admin controls. Opens the same ring-buffer modal defined in
|
|
@@ -767,10 +806,9 @@ async function openSettings() {
|
|
|
767
806
|
|
|
768
807
|
// Section registry — order is intentional (Runtime + Auto-fix surface first
|
|
769
808
|
// per Caleb's feedback). Each entry maps a rail-button id → pane HTML.
|
|
770
|
-
//
|
|
771
|
-
//
|
|
772
|
-
//
|
|
773
|
-
// the moved flags quickly.
|
|
809
|
+
// W-ms4o7y1g007jdb2d — the former 'autofix' / 'lifecycle' / 'workflow' panes
|
|
810
|
+
// are merged into ONE featured 'plan-pr-workflow' section (Plan → PR creation
|
|
811
|
+
// → Monitor). It sits where 'autofix' was (near the rail top, featured).
|
|
774
812
|
// W-mryz3r7h — a section may opt into a collapsible rail fold by declaring a
|
|
775
813
|
// `group`. Grouped sections render as an indented child list beneath a fold
|
|
776
814
|
// header (see RAIL_GROUPS + the railHtml builder below); their PANES stay in
|
|
@@ -780,9 +818,7 @@ async function openSettings() {
|
|
|
780
818
|
// only ever one thing labeled "Advanced".
|
|
781
819
|
const sections = [
|
|
782
820
|
{ id: 'runtime', label: 'Agents Runtime & Models', featured: true, html: paneRuntime },
|
|
783
|
-
{ id: '
|
|
784
|
-
{ id: 'lifecycle', label: 'PR Lifecycle', html: paneLifecycle },
|
|
785
|
-
{ id: 'workflow', label: 'Workflow Defaults', html: paneWorkflow },
|
|
821
|
+
{ id: 'plan-pr-workflow', label: 'Plan & PR Workflow', featured: true, html: panePlanPrWorkflow },
|
|
786
822
|
{ id: 'appearance', label: 'Appearance', html: paneAppearance },
|
|
787
823
|
{ id: 'projects', label: 'Projects', html: paneProjects },
|
|
788
824
|
{ id: 'polling', label: 'Polling', html: panePolling },
|
|
@@ -807,7 +843,12 @@ async function openSettings() {
|
|
|
807
843
|
const SAVED_TAB_KEY = 'minions.settings.activeTab';
|
|
808
844
|
let activeTab = sections[0].id;
|
|
809
845
|
try {
|
|
810
|
-
|
|
846
|
+
let saved = localStorage.getItem(SAVED_TAB_KEY);
|
|
847
|
+
// W-ms4o7y1g007jdb2d — the 'autofix' / 'lifecycle' / 'workflow' panes merged
|
|
848
|
+
// into 'plan-pr-workflow'. Redirect a stale saved tab (or old deep-link)
|
|
849
|
+
// so no operator lands on a dead rail id and silently falls back to the
|
|
850
|
+
// first section.
|
|
851
|
+
if (saved === 'autofix' || saved === 'lifecycle' || saved === 'workflow') saved = 'plan-pr-workflow';
|
|
811
852
|
if (saved && sections.some(s => s.id === saved)) activeTab = saved;
|
|
812
853
|
} catch { /* localStorage may be blocked in some embeds */ }
|
|
813
854
|
|
|
@@ -1047,7 +1088,79 @@ async function _toggleSettingsCharter(agentId) {
|
|
|
1047
1088
|
}
|
|
1048
1089
|
}
|
|
1049
1090
|
|
|
1091
|
+
/**
|
|
1092
|
+
* Populate the Cloud Provider selector from /api/cloud-providers.
|
|
1093
|
+
*
|
|
1094
|
+
* Cloud dispatch ships with an EMPTY provider registry until a provider lands,
|
|
1095
|
+
* and `engine.cloudProvider` is validated server-side against that same
|
|
1096
|
+
* registry — so a free-text input would reject every value an operator could
|
|
1097
|
+
* type. Instead the control offers exactly what is registered, and when nothing
|
|
1098
|
+
* is, it disables itself and says why. The server re-validates fail-closed
|
|
1099
|
+
* regardless; this is an affordance, not the gate.
|
|
1100
|
+
*
|
|
1101
|
+
* A stale stored value (a provider that was registered when it was saved and
|
|
1102
|
+
* is not now) is preserved as a selected option and flagged, so opening
|
|
1103
|
+
* Settings can never silently clear a config value the operator did not touch.
|
|
1104
|
+
*/
|
|
1105
|
+
async function _hydrateCloudProviderSelect(engineCfg) {
|
|
1106
|
+
const select = document.getElementById('set-cloudProvider');
|
|
1107
|
+
if (!select) return;
|
|
1108
|
+
const hint = document.getElementById('set-cloudProvider-hint');
|
|
1109
|
+
const current = (engineCfg && engineCfg.cloudProvider) || '';
|
|
1110
|
+
|
|
1111
|
+
let providers = [];
|
|
1112
|
+
let reachable = true;
|
|
1113
|
+
try {
|
|
1114
|
+
const res = await fetch('/api/cloud-providers');
|
|
1115
|
+
const data = await res.json();
|
|
1116
|
+
providers = Array.isArray(data.providers) ? data.providers.map(p => p.name) : [];
|
|
1117
|
+
} catch {
|
|
1118
|
+
reachable = false; // older dashboard or transient failure — degrade, don't clear
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
const stale = current && !providers.includes(current);
|
|
1122
|
+
const options = ['<option value=""' + (!current ? ' selected' : '') + '>None — cloud dispatch disabled</option>']
|
|
1123
|
+
.concat(providers.map(n =>
|
|
1124
|
+
'<option value="' + escHtml(n) + '"' + (n === current ? ' selected' : '') + '>' + escHtml(n) + '</option>'
|
|
1125
|
+
));
|
|
1126
|
+
if (stale) {
|
|
1127
|
+
options.push(
|
|
1128
|
+
'<option value="' + escHtml(current) + '" selected>' + escHtml(current) + ' (not registered)</option>'
|
|
1129
|
+
);
|
|
1130
|
+
}
|
|
1131
|
+
// eslint-disable-next-line no-unsanitized/property -- reason: structural HTML is a string literal; all user data wrapped in escHtml() (fields: provider names, stored provider id)
|
|
1132
|
+
select.innerHTML = options.join('');
|
|
1133
|
+
|
|
1134
|
+
// Disable only when there is genuinely nothing to choose AND nothing stored:
|
|
1135
|
+
// a stale stored value must stay editable so the operator can clear it.
|
|
1136
|
+
select.disabled = providers.length === 0 && !current;
|
|
1137
|
+
|
|
1138
|
+
if (!hint) return;
|
|
1139
|
+
if (!reachable) {
|
|
1140
|
+
hint.textContent = 'Could not reach /api/cloud-providers — the stored value is unchanged. '
|
|
1141
|
+
+ 'Cloud dispatch hands a work item to a remote coding agent that authors its own PR.';
|
|
1142
|
+
} else if (providers.length === 0) {
|
|
1143
|
+
hint.textContent = 'No cloud providers are registered on this build, so cloud dispatch is unavailable '
|
|
1144
|
+
+ 'and any work item declaring meta.executionSurface: "cloud" is refused (never run locally instead). '
|
|
1145
|
+
+ 'This control activates when a provider ships.';
|
|
1146
|
+
} else if (stale) {
|
|
1147
|
+
hint.textContent = 'The stored provider "' + current + '" is not registered on this build — '
|
|
1148
|
+
+ 'cloud-declared work items will be refused until you pick a registered provider or clear this field.';
|
|
1149
|
+
} else {
|
|
1150
|
+
hint.textContent = 'Fleet-wide default for work items declaring meta.executionSurface: "cloud" — Minions '
|
|
1151
|
+
+ 'investigates locally, renders the scoped dispatch instructions, and hands them to a REMOTE coding agent '
|
|
1152
|
+
+ 'that authors its own PR. Overridden by project.cloudProvider, then meta.cloudProvider. '
|
|
1153
|
+
+ 'Only PR-producing types (implement, fix, test, docs) may declare the cloud surface.';
|
|
1154
|
+
}
|
|
1155
|
+
}
|
|
1156
|
+
|
|
1050
1157
|
async function initRuntimeFleetUI(engineCfg, agentsCfg) {
|
|
1158
|
+
// Cloud dispatch providers come from a DIFFERENT registry than runtimes
|
|
1159
|
+
// (/api/cloud-providers) and ship empty until a provider lands. Hydrated
|
|
1160
|
+
// FIRST, ahead of the runtime-select guard below, so the cloud control is
|
|
1161
|
+
// never left showing "Loading…" just because the CLI selects are absent.
|
|
1162
|
+
await _hydrateCloudProviderSelect(engineCfg);
|
|
1163
|
+
|
|
1051
1164
|
const cliSelect = document.getElementById('set-defaultCli');
|
|
1052
1165
|
const ccCliSelect = document.getElementById('set-ccCli');
|
|
1053
1166
|
if (!cliSelect || !ccCliSelect) return;
|
|
@@ -1064,6 +1177,9 @@ async function initRuntimeFleetUI(engineCfg, agentsCfg) {
|
|
|
1064
1177
|
runtimes = Array.isArray(d.runtimes) ? d.runtimes : [];
|
|
1065
1178
|
} catch { /* ignore — we'll surface a free-text-only path below */ }
|
|
1066
1179
|
|
|
1180
|
+
// Cloud dispatch providers come from a DIFFERENT registry (/api/cloud-providers)
|
|
1181
|
+
// and ship empty until a provider lands. Hydrated at the top of this function.
|
|
1182
|
+
|
|
1067
1183
|
// Always include 'copilot' as a fallback option even if /api/runtimes is empty;
|
|
1068
1184
|
// legacy installs without the registry endpoint should still see something pickable.
|
|
1069
1185
|
const names = runtimes.length ? runtimes.map(rt => rt.name) : ['copilot'];
|
|
@@ -1364,6 +1480,27 @@ function settingsToggle(label, id, checked, hint, opts) {
|
|
|
1364
1480
|
'</div>';
|
|
1365
1481
|
}
|
|
1366
1482
|
|
|
1483
|
+
// W-ms4o7y1g007jdb2d — two-state DRAFT ⇄ PUBLISH switch backing a real
|
|
1484
|
+
// `<input type=checkbox id="set-…">` so the existing id-based save/collect path
|
|
1485
|
+
// (getElementById('set-…').checked) is untouched: checked = Draft, unchecked =
|
|
1486
|
+
// Publish (ready-for-review). Renders both ends ('Publish' / 'Draft') with a
|
|
1487
|
+
// pure-CSS sliding knob driven by the `:checked` sibling selector (.settings-
|
|
1488
|
+
// switch* in styles.css) — no JS change handler. `extraSearch` folds the
|
|
1489
|
+
// legacy label into data-search so the cross-tab search box still finds it.
|
|
1490
|
+
function settingsDraftPublishToggle(id, checked, label, hint) {
|
|
1491
|
+
const searchKey = (String(label || '') + ' ' + String(hint || '') + ' create prs as draft publish ready for review pull request lifecycle').toLowerCase().replace(/"/g, '');
|
|
1492
|
+
return '<div class="settings-row" data-search="' + escHtml(searchKey) + '">' +
|
|
1493
|
+
'<label for="' + id + '" style="font-size:var(--text-sm);color:var(--muted);display:block;margin-bottom:4px">' + escHtml(label) + '</label>' +
|
|
1494
|
+
'<label class="settings-switch" title="' + escHtml(hint || '') + '">' +
|
|
1495
|
+
'<input type="checkbox" id="' + id + '" class="settings-switch__input"' + (checked ? ' checked' : '') + '>' +
|
|
1496
|
+
'<span class="settings-switch__end settings-switch__end--publish">Publish</span>' +
|
|
1497
|
+
'<span class="settings-switch__track" aria-hidden="true"><span class="settings-switch__knob"></span></span>' +
|
|
1498
|
+
'<span class="settings-switch__end settings-switch__end--draft">Draft</span>' +
|
|
1499
|
+
'</label>' +
|
|
1500
|
+
(hint ? '<div style="font-size:var(--text-sm);color:var(--muted);margin-top:4px;line-height:1.4">' + escHtml(hint) + '</div>' : '') +
|
|
1501
|
+
'</div>';
|
|
1502
|
+
}
|
|
1503
|
+
|
|
1367
1504
|
// W-mryyzhug000454b7 — enable/disabled TILE for a boolean per-cause auto-fix
|
|
1368
1505
|
// gate. Renders a real (visually-hidden but focusable) `<input type=checkbox
|
|
1369
1506
|
// id="set-...">` as the source of truth so the existing id-based save/collect
|
|
@@ -1574,6 +1711,7 @@ async function saveSettings() {
|
|
|
1574
1711
|
worktreeCreateRetries: document.getElementById('set-worktreeCreateRetries').value,
|
|
1575
1712
|
worktreeRoot: document.getElementById('set-worktreeRoot').value,
|
|
1576
1713
|
worktreeMinFreeSpaceBytes: Math.round(Math.max(0, Number(document.getElementById('set-worktreeMinFreeSpaceGiB').value) || 0) * 1024 * 1024 * 1024),
|
|
1714
|
+
worktreeProtectedQuarantineRetentionMs: Math.round(Math.max(0, Number(document.getElementById('set-worktreeProtectedQuarantineRetentionDays').value) || 0) * 24 * 60 * 60 * 1000),
|
|
1577
1715
|
assertCleanStatusTimeoutMs: secToMs('set-assertCleanStatusTimeoutMs'),
|
|
1578
1716
|
restartHealthTimeoutMs: secToMs('set-restartHealthTimeoutMs'),
|
|
1579
1717
|
idleAlertMinutes: document.getElementById('set-idleAlertMinutes').value,
|
|
@@ -1591,11 +1729,13 @@ async function saveSettings() {
|
|
|
1591
1729
|
autoDecompose: document.getElementById('set-autoDecompose').checked,
|
|
1592
1730
|
allowTempAgents: document.getElementById('set-allowTempAgents').checked,
|
|
1593
1731
|
autoArchive: document.getElementById('set-autoArchive').checked,
|
|
1732
|
+
autoQaCompletedPrds: !!document.getElementById('set-autoQaCompletedPrds')?.checked,
|
|
1594
1733
|
autoConsolidateMemory: document.getElementById('set-autoConsolidateMemory').checked,
|
|
1595
1734
|
bootstrapDefaultSchedules: document.getElementById('set-bootstrapDefaultSchedules').checked,
|
|
1596
1735
|
autoApplyReviewVote: document.getElementById('set-autoApplyReviewVote').checked,
|
|
1597
1736
|
createPrsAsDraft: document.getElementById('set-createPrsAsDraft').checked,
|
|
1598
1737
|
autoFixBuilds: document.getElementById('set-autoFixBuilds').checked,
|
|
1738
|
+
adoQueueDraftPrBuilds: document.getElementById('set-adoQueueDraftPrBuilds').checked,
|
|
1599
1739
|
autoFixConflicts: document.getElementById('set-autoFixConflicts').checked,
|
|
1600
1740
|
autoFixPaused: document.getElementById('set-autoFixPaused').checked,
|
|
1601
1741
|
autoReviewPrs: document.getElementById('set-autoReviewPrs').checked,
|
|
@@ -1636,6 +1776,9 @@ async function saveSettings() {
|
|
|
1636
1776
|
planMaterializationEnabled: document.getElementById('set-planMaterializationEnabled').checked,
|
|
1637
1777
|
prPollStatusEvery: document.getElementById('set-prPollStatusEvery').value,
|
|
1638
1778
|
prPollCommentsEvery: document.getElementById('set-prPollCommentsEvery').value,
|
|
1779
|
+
// W-msav5edk00g81710 — UI is days, engine stores ms (mirrors the
|
|
1780
|
+
// protected-quarantine retention field). 0 disables the re-probe.
|
|
1781
|
+
abandonedPrRepollWindowMs: Math.round(Math.max(0, Number(document.getElementById('set-abandonedPrRepollWindowDays').value) || 0) * 24 * 60 * 60 * 1000),
|
|
1639
1782
|
evalMaxCost: document.getElementById('set-evalMaxCost').value || null,
|
|
1640
1783
|
enablePreDispatchEval: document.getElementById('set-enablePreDispatchEval').checked,
|
|
1641
1784
|
preDispatchEvalSkipPrdSourced: document.getElementById('set-preDispatchEvalSkipPrdSourced').checked,
|
|
@@ -1651,8 +1794,16 @@ async function saveSettings() {
|
|
|
1651
1794
|
ccCli: (document.getElementById('set-ccCli')?.value ?? '').trim(),
|
|
1652
1795
|
ccModel: (document.getElementById('set-ccModel')?.value ?? '').trim(),
|
|
1653
1796
|
ccEffort: document.getElementById('set-ccEffort').value || null,
|
|
1797
|
+
// Cloud dispatch default provider. Empty string clears the override, so
|
|
1798
|
+
// the fleet goes back to "no cloud provider" and every cloud-declared
|
|
1799
|
+
// work item is refused (never silently downgraded to a local dispatch).
|
|
1800
|
+
cloudProvider: (document.getElementById('set-cloudProvider')?.value ?? '').trim(),
|
|
1654
1801
|
codexCcSandbox: document.getElementById('set-codexCcSandbox')?.value || 'danger-full-access',
|
|
1655
1802
|
ccTurnTimeoutMs: secToMs('set-ccTurnTimeoutMs'),
|
|
1803
|
+
// Issue #1105 — cold ACP handshake budget. UI is seconds, engine stores
|
|
1804
|
+
// ms; the server validates against [10000, 900000] ms. undefined when
|
|
1805
|
+
// blank so the server keeps the prior value.
|
|
1806
|
+
acpHandshakeTimeoutMs: secToMs('set-acpHandshakeTimeoutMs'),
|
|
1656
1807
|
// Settings UI presents the idle timeout in minutes for readability; the
|
|
1657
1808
|
// engine stores ms (ENGINE_DEFAULTS.ccWorkerIdleTimeoutMs). Convert here;
|
|
1658
1809
|
// the server validates against [60000, 28800000] ms. undefined when blank so the
|
package/dashboard/js/utils.js
CHANGED
|
@@ -902,6 +902,56 @@ async function submitBugReport() {
|
|
|
902
902
|
}
|
|
903
903
|
}
|
|
904
904
|
|
|
905
|
+
// ── Slim "+ Add" create deep-link (W-ms258yw0000ffd8a) ─────────────────────
|
|
906
|
+
// Shared boot hook for the classic /watches, /schedule and /pipelines screens
|
|
907
|
+
// when the Slim Automation tile embeds them at `?embed=1#create`.
|
|
908
|
+
//
|
|
909
|
+
// Waiting only for `typeof openCreate*Modal === 'function'` is NOT sufficient:
|
|
910
|
+
// the create function is a hoisted declaration in the same concatenated bundle,
|
|
911
|
+
// so it already exists synchronously — but the Project / Agent / Owner <option>
|
|
912
|
+
// lists are built from the `cmdProjects` / `cmdAgents` globals that refresh.js
|
|
913
|
+
// only fills once the first /api/status + /api/agents fetch resolves. This hook
|
|
914
|
+
// runs one macrotask after DOMContentLoaded and always wins that race, and the
|
|
915
|
+
// create forms are one-shot innerHTML renders with no re-render hook — so the
|
|
916
|
+
// dialog would open with empty dropdowns and never self-heal. Screens whose
|
|
917
|
+
// create form depends on that data therefore pass an `isReady` predicate.
|
|
918
|
+
//
|
|
919
|
+
// The retry budget is bounded so a page whose data never lands cannot spin the
|
|
920
|
+
// 30 ms timer forever; on exhaustion we open best-effort (a degraded dialog
|
|
921
|
+
// still beats a "+ Add" click that silently does nothing).
|
|
922
|
+
function classicCreateFormDataReady() {
|
|
923
|
+
// The first refresh() tick has landed for BOTH slices cmdProjects/cmdAgents
|
|
924
|
+
// are derived from. Deliberately not `cmdProjects.length` — a valid install
|
|
925
|
+
// can have zero projects or zero agents, and that must not stall the dialog.
|
|
926
|
+
return !!(window._lastStatus && window._lastAgents);
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
// opts: { route: '/watches', resolve: () => fn|null, isReady?: () => boolean }
|
|
930
|
+
function bootCreateDeepLink(opts) {
|
|
931
|
+
if (typeof window === 'undefined' || typeof document === 'undefined') return;
|
|
932
|
+
if (!opts || typeof opts.resolve !== 'function') return;
|
|
933
|
+
var RETRY_MS = 30;
|
|
934
|
+
var MAX_ATTEMPTS = 200; // ~6s at RETRY_MS — bounded, never an unbounded loop
|
|
935
|
+
try {
|
|
936
|
+
if (window.location.pathname.replace(/\/+$/, '') !== opts.route) return;
|
|
937
|
+
if (window.location.hash !== '#create') return;
|
|
938
|
+
} catch (e) { return; }
|
|
939
|
+
function attempt(n) {
|
|
940
|
+
var open = null;
|
|
941
|
+
try { open = opts.resolve(); } catch (e) { open = null; }
|
|
942
|
+
var ready = true;
|
|
943
|
+
if (opts.isReady) { try { ready = opts.isReady() === true; } catch (e) { ready = false; } }
|
|
944
|
+
if (typeof open === 'function' && ready) { open(); return; }
|
|
945
|
+
if (n >= MAX_ATTEMPTS) { if (typeof open === 'function') open(); return; }
|
|
946
|
+
setTimeout(function() { attempt(n + 1); }, RETRY_MS);
|
|
947
|
+
}
|
|
948
|
+
if (document.readyState === 'loading') {
|
|
949
|
+
document.addEventListener('DOMContentLoaded', function() { setTimeout(function() { attempt(0); }, 0); });
|
|
950
|
+
} else {
|
|
951
|
+
setTimeout(function() { attempt(0); }, 0);
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
|
|
905
955
|
// ── Send-shortcut helpers (Classic UX) ──────────────────────────────────
|
|
906
956
|
// macOS submits with Command+Enter; Windows/Linux keep Control+Enter. These are
|
|
907
957
|
// the single source of truth for both the key handler and the visible hint so
|
|
@@ -930,4 +980,4 @@ function sendShortcutAriaLabel() { return isMacPlatform() ? 'Command+Enter' : 'C
|
|
|
930
980
|
// aria-keyshortcuts uses the DOM modifier names, so macOS reports "Meta".
|
|
931
981
|
function sendShortcutAriaKeys() { return isMacPlatform() ? 'Meta+Enter' : 'Control+Enter'; }
|
|
932
982
|
|
|
933
|
-
window.MinionsUtils = { wakeEngine, markDeleted, clearDeleted, escapeHtml, escHtml, renderMd, normalizePlanFile, timeAgo, statusColor, shouldIgnoreSelectionClick, llmCopyBtn, copyLlmText, openBugReport, submitBugReport, isMacPlatform, isSendShortcutEvent, sendShortcutLabel, sendShortcutAriaLabel, sendShortcutAriaKeys };
|
|
983
|
+
window.MinionsUtils = { wakeEngine, markDeleted, clearDeleted, escapeHtml, escHtml, renderMd, normalizePlanFile, timeAgo, statusColor, shouldIgnoreSelectionClick, llmCopyBtn, copyLlmText, openBugReport, submitBugReport, isMacPlatform, isSendShortcutEvent, sendShortcutLabel, sendShortcutAriaLabel, sendShortcutAriaKeys, bootCreateDeepLink, classicCreateFormDataReady };
|
package/dashboard/pages/qa.html
CHANGED
|
@@ -1,24 +1,9 @@
|
|
|
1
1
|
<section>
|
|
2
2
|
<h2>QA</h2>
|
|
3
|
-
<p class="empty" style="margin:4px 0 12px 0">Passive monitor for QA sessions, live targets, runs, and saved runbooks. Create new sessions or runbooks from <button type="button" class="qa-inline-link" onclick="qaFocusCommandCenter()">Command Center</button
|
|
3
|
+
<p class="empty" style="margin:4px 0 12px 0">Passive monitor for QA sessions, live targets, runs, and saved runbooks. Create new sessions or runbooks from <button type="button" class="qa-inline-link" onclick="qaFocusCommandCenter()">Command Center</button>. <a href="/state/docs/qa-runbook-lifecycle.md" target="_blank" rel="noopener" class="qa-inline-link">Docs →</a></p>
|
|
4
4
|
</section>
|
|
5
5
|
<section id="qa-sessions-section" class="qa-section">
|
|
6
6
|
<h2>Active QA Sessions <span class="qa-section-subtitle">live, non-terminal runs — engine sets up a target, drafts a runner-native test, and (with your approval) executes it</span></h2>
|
|
7
|
-
<div id="qa-cc-pitch" class="qa-cc-pitch" style="border:1px solid var(--border);border-radius:var(--radius-md);background:var(--surface2);padding:var(--space-5);margin-bottom:var(--space-5);display:flex;flex-direction:column;gap:var(--space-3)">
|
|
8
|
-
<div style="font-weight:600;color:var(--text);display:flex;align-items:center;gap:var(--space-2)">💬 Ask Command Center to start a QA session</div>
|
|
9
|
-
<div style="color:var(--muted);font-size:var(--text-base);line-height:1.5">
|
|
10
|
-
Examples:
|
|
11
|
-
<ul style="margin:var(--space-2) 0 0 var(--space-5);padding:0;color:var(--muted)">
|
|
12
|
-
<li><code>QA the login flow on PR #1234</code></li>
|
|
13
|
-
<li><code>Smoke test the checkout flow on develop</code></li>
|
|
14
|
-
<li><code>Validate the signup journey on my current worktree</code></li>
|
|
15
|
-
</ul>
|
|
16
|
-
</div>
|
|
17
|
-
<div style="display:flex;gap:var(--space-3);align-items:center;margin-top:var(--space-2)">
|
|
18
|
-
<button type="button" id="qa-cc-pitch-open" class="btn-primary-solid" onclick="qaFocusCommandCenter()">Open Command Center →</button>
|
|
19
|
-
<a href="/state/docs/qa-runbook-lifecycle.md" target="_blank" rel="noopener" class="qa-cc-pitch-docs" style="color:var(--blue);font-size:var(--text-base)">Docs →</a>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
7
|
<div id="qa-sessions-content" class="qa-sessions-list">
|
|
23
8
|
<p class="empty">Loading sessions…</p>
|
|
24
9
|
</div>
|
|
@@ -4,6 +4,46 @@
|
|
|
4
4
|
<button id="work-archive-toggle" type="button" class="pr-pager-btn" style="font-size:var(--text-sm);padding:2px 8px;margin-left:4px" onclick="toggleWorkItemArchive()" aria-expanded="false" aria-controls="work-items-archive">See Archive</button>
|
|
5
5
|
<span style="font-size:var(--text-sm);color:var(--muted);font-weight:400;text-transform:none;letter-spacing:0">tasks dispatched to agents — auto-created from PRDs or added manually</span>
|
|
6
6
|
</h2>
|
|
7
|
+
<div class="pr-filters" role="group" aria-label="Work item filters and sort">
|
|
8
|
+
<label class="pr-filter">Status
|
|
9
|
+
<select id="wi-filter-status" onchange="applyWiFilters()">
|
|
10
|
+
<option value="">All statuses</option>
|
|
11
|
+
</select>
|
|
12
|
+
</label>
|
|
13
|
+
<label class="pr-filter">Type
|
|
14
|
+
<select id="wi-filter-type" onchange="applyWiFilters()">
|
|
15
|
+
<option value="">All types</option>
|
|
16
|
+
</select>
|
|
17
|
+
</label>
|
|
18
|
+
<label class="pr-filter">Project
|
|
19
|
+
<select id="wi-filter-project" onchange="applyWiFilters()">
|
|
20
|
+
<option value="">All projects</option>
|
|
21
|
+
</select>
|
|
22
|
+
</label>
|
|
23
|
+
<label class="pr-filter">Agent
|
|
24
|
+
<select id="wi-filter-agent" onchange="applyWiFilters()">
|
|
25
|
+
<option value="">All agents</option>
|
|
26
|
+
</select>
|
|
27
|
+
</label>
|
|
28
|
+
<label class="pr-filter">Priority
|
|
29
|
+
<select id="wi-filter-priority" onchange="applyWiFilters()">
|
|
30
|
+
<option value="">All priorities</option>
|
|
31
|
+
</select>
|
|
32
|
+
</label>
|
|
33
|
+
<label class="pr-filter">Sort by
|
|
34
|
+
<select id="wi-sort-by" onchange="applyWiFilters()">
|
|
35
|
+
<option value="lifecycle" selected>Lifecycle (active first)</option>
|
|
36
|
+
<option value="updated">Last updated</option>
|
|
37
|
+
<option value="created">Created</option>
|
|
38
|
+
<option value="priority">Priority</option>
|
|
39
|
+
<option value="status">Status</option>
|
|
40
|
+
<option value="type">Type</option>
|
|
41
|
+
</select>
|
|
42
|
+
</label>
|
|
43
|
+
<button id="wi-sort-dir" class="pr-filter-reset" type="button" value="desc" title="Descending — click for ascending" aria-label="Sort descending (newest first)" onclick="toggleWiSortDir()">↓ Desc</button>
|
|
44
|
+
<button class="pr-filter-reset" type="button" onclick="resetWiFilters()">Reset filters</button>
|
|
45
|
+
<span class="pr-filter-summary" id="wi-filter-summary" aria-live="polite"></span>
|
|
46
|
+
</div>
|
|
7
47
|
<div id="work-items-content"><p class="empty">No work items yet.</p></div>
|
|
8
48
|
<div id="work-items-archive" style="display:none;margin-top:12px"></div>
|
|
9
49
|
</section>
|