@yemi33/minions 0.1.2448 → 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 +58 -4
- package/dashboard/js/detail-panel.js +36 -0
- package/dashboard/js/memory-panel.js +59 -12
- package/dashboard/js/qa.js +179 -20
- 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 +13 -2
- 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
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
let allPrs = [];
|
|
4
4
|
let filteredPrs = [];
|
|
5
5
|
let prPage = 0;
|
|
6
|
-
let prFilterOptionsSignature = '';
|
|
7
6
|
const PR_PER_PAGE = 25;
|
|
8
7
|
const PR_FILTER_CONTROL_IDS = {
|
|
9
8
|
author: 'pr-filter-author',
|
|
@@ -12,13 +11,32 @@ const PR_FILTER_CONTROL_IDS = {
|
|
|
12
11
|
review: 'pr-filter-review',
|
|
13
12
|
build: 'pr-filter-build',
|
|
14
13
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
14
|
+
|
|
15
|
+
// DOM half of the filter bar — the generic controller from
|
|
16
|
+
// shared/record-filters.js, shared with the classic Work Items bar. It owns the
|
|
17
|
+
// option-signature gate that keeps the 4 s poll from rebuilding <option> nodes
|
|
18
|
+
// under an open dropdown.
|
|
19
|
+
//
|
|
20
|
+
// Built lazily rather than at module scope: this file is also require()d
|
|
21
|
+
// directly under Node by tests that exercise its pure helpers, where `window`
|
|
22
|
+
// does not exist.
|
|
23
|
+
let _prFilterBarInstance = null;
|
|
24
|
+
function _prFilterBar() {
|
|
25
|
+
if (!_prFilterBarInstance) {
|
|
26
|
+
_prFilterBarInstance = window.MinionsRecordFilters.createBar({
|
|
27
|
+
controlIds: PR_FILTER_CONTROL_IDS,
|
|
28
|
+
allLabels: {
|
|
29
|
+
author: 'All authors',
|
|
30
|
+
lifecycle: 'All lifecycle statuses',
|
|
31
|
+
project: 'All projects',
|
|
32
|
+
review: 'All review statuses',
|
|
33
|
+
build: 'All build statuses',
|
|
34
|
+
},
|
|
35
|
+
getOptions: getPrFilterOptions,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
return _prFilterBarInstance;
|
|
39
|
+
}
|
|
22
40
|
|
|
23
41
|
// Pull requests are served fresh by GET /api/pull-requests (see refresh.js),
|
|
24
42
|
// which runs queries.getPullRequests() server-side. The per-project
|
|
@@ -103,6 +121,60 @@ function _renderPrMergeConflictBadge(pr) {
|
|
|
103
121
|
'" aria-label="' + escapeHtml(PR_MERGE_CONFLICT_LABEL) + '">conflict</span>';
|
|
104
122
|
}
|
|
105
123
|
|
|
124
|
+
function prAutomationToggle(idMatch, automation, label, enabled) {
|
|
125
|
+
if (!idMatch) return '';
|
|
126
|
+
var stateClass = enabled ? 'pr-automation-on' : 'pr-automation-off';
|
|
127
|
+
var stateLabel = enabled ? 'enabled' : 'disabled';
|
|
128
|
+
var title = label + ' ' + stateLabel + ' for this PR. Click to ' + (enabled ? 'disable.' : 'enable.');
|
|
129
|
+
return '<label class="pr-automation-switch ' + stateClass + '" '
|
|
130
|
+
+ 'title="' + escapeHtml(title) + '" '
|
|
131
|
+
+ 'onclick="event.stopPropagation()">'
|
|
132
|
+
+ '<input type="checkbox" class="pr-automation-switch__input"'
|
|
133
|
+
+ (enabled ? ' checked' : '') + ' '
|
|
134
|
+
+ 'aria-label="' + escapeHtml(label + ': ' + stateLabel) + '" '
|
|
135
|
+
+ 'data-pr-host="' + escapeHtml(idMatch[1]) + '" '
|
|
136
|
+
+ 'data-pr-slug="' + escapeHtml(idMatch[2]) + '" '
|
|
137
|
+
+ 'data-pr-number="' + escapeHtml(idMatch[3]) + '" '
|
|
138
|
+
+ 'data-pr-automation="' + escapeHtml(automation) + '" '
|
|
139
|
+
+ 'data-pr-enabled="' + (enabled ? '1' : '0') + '" '
|
|
140
|
+
+ 'onchange="togglePrAutomation(this)">'
|
|
141
|
+
+ '<span class="pr-automation-switch__track" aria-hidden="true">'
|
|
142
|
+
+ '<span class="pr-automation-switch__knob"></span>'
|
|
143
|
+
+ '</span>'
|
|
144
|
+
+ '</label>';
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
// PR author cell (W-mscibegy005e8b74). Renders the real individual the PR is
|
|
148
|
+
// for — display name plus @login when both are known — separate from the
|
|
149
|
+
// Minions agent (still shown in the PR detail panel). Missing/legacy author
|
|
150
|
+
// renders "Unknown" rather than borrowing the agent name. Links to the provider
|
|
151
|
+
// profile only when a validated http(s) URL is present.
|
|
152
|
+
function _prAuthorCellHtml(pr) {
|
|
153
|
+
var a = pr ? pr.author : null;
|
|
154
|
+
var login = '';
|
|
155
|
+
var displayName = '';
|
|
156
|
+
var url = '';
|
|
157
|
+
if (a && typeof a === 'object') {
|
|
158
|
+
login = a.login || '';
|
|
159
|
+
displayName = a.displayName || '';
|
|
160
|
+
url = a.url || '';
|
|
161
|
+
} else if (typeof a === 'string') {
|
|
162
|
+
login = a;
|
|
163
|
+
}
|
|
164
|
+
var primary = displayName || login;
|
|
165
|
+
if (!primary) {
|
|
166
|
+
return '<span style="color:var(--muted);font-size:var(--text-base)" title="Author unavailable">Unknown</span>';
|
|
167
|
+
}
|
|
168
|
+
var secondary = (displayName && login && login !== displayName) ? login : '';
|
|
169
|
+
var inner = escapeHtml(primary)
|
|
170
|
+
+ (secondary ? ' <span style="color:var(--muted);font-size:var(--text-base)">@' + escapeHtml(secondary) + '</span>' : '');
|
|
171
|
+
var titleText = secondary ? primary + ' (' + secondary + ')' : primary;
|
|
172
|
+
if (url && /^https?:\/\//i.test(url)) {
|
|
173
|
+
return '<a class="pr-agent" title="' + escapeHtml(titleText) + '" href="' + escapeHtml(safeUrl(url)) + '" target="_blank" rel="noopener">' + inner + '</a>';
|
|
174
|
+
}
|
|
175
|
+
return '<span class="pr-agent" title="' + escapeHtml(titleText) + '">' + inner + '</span>';
|
|
176
|
+
}
|
|
177
|
+
|
|
106
178
|
function prRow(pr) {
|
|
107
179
|
// Minions review (agent) state — separate from ADO human review
|
|
108
180
|
const sq = pr.minionsReview || {};
|
|
@@ -118,10 +190,24 @@ function prRow(pr) {
|
|
|
118
190
|
? 'ADO has builds on this PR\'s merge ref, but none target the current merge commit (typically after a rebase or target-branch advance). Engine classified from the pre-rebase build set and queued a fresh build (rate limited 30m). See Issue #2747.'
|
|
119
191
|
: (pr._buildStatusDetail || '');
|
|
120
192
|
const mergeConflictBadge = _renderPrMergeConflictBadge(pr);
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
193
|
+
// W-ms8z6l8z — the lifecycle badge is a single, mutually-exclusive state:
|
|
194
|
+
// an open draft PR reads "draft"; an open non-draft PR reads "active";
|
|
195
|
+
// terminal PRs read merged/abandoned. The canonical draft signal is
|
|
196
|
+
// pr.isDraft (plumbed by engine/providers/github.js + engine/ado/index.js,
|
|
197
|
+
// exposed via engine/api/bridge.js), never title text. There is no separate
|
|
198
|
+
// "ready" pill — "active" already communicates open + non-draft, so
|
|
199
|
+
// rendering both "active" and "ready" together was redundant. The
|
|
200
|
+
// merge-conflict badge (formerly its own never-populated "Merge" column) is
|
|
201
|
+
// folded in beside the lifecycle badge because it is a genuinely distinct
|
|
202
|
+
// state that "active"/"draft" does not convey.
|
|
203
|
+
const isDraftPr = pr.isDraft === true;
|
|
204
|
+
const isOpenPr = !pr.status || pr.status === 'active';
|
|
205
|
+
const statusClass = pr.status === 'merged' ? 'merged'
|
|
206
|
+
: pr.status === 'abandoned' ? 'rejected'
|
|
207
|
+
: (isDraftPr && isOpenPr) ? 'draft'
|
|
208
|
+
: pr.status === 'active' ? 'active'
|
|
209
|
+
: 'draft';
|
|
210
|
+
const statusLabel = (isDraftPr && isOpenPr) ? 'draft' : (pr.status || 'active');
|
|
125
211
|
const branchError = pr._branchResolutionError?.reason || '';
|
|
126
212
|
const branchLabel = pr.branch || (branchError ? 'missing branch' : '—');
|
|
127
213
|
const branchClass = 'pr-branch' + (branchError ? ' branch-missing' : '');
|
|
@@ -166,7 +252,7 @@ function prRow(pr) {
|
|
|
166
252
|
// no-op pausedCauses above: pr._buildFixIneffective is set when a
|
|
167
253
|
// BUILD_FAILURE fix reported "no branch change" AND a live CI re-poll
|
|
168
254
|
// confirmed the build is STILL failing on that same head (see
|
|
169
|
-
// engine/lifecycle.js recordBuildFixIneffective). This is a separate,
|
|
255
|
+
// engine/orchestration/lifecycle.js recordBuildFixIneffective). This is a separate,
|
|
170
256
|
// headSha-keyed pause distinct from _noOpFixes, so it needs its own,
|
|
171
257
|
// clearly-labeled indicator — a still-red build after an unchanged fix
|
|
172
258
|
// attempt usually means the failure isn't fixable by another agent pass
|
|
@@ -197,7 +283,7 @@ function prRow(pr) {
|
|
|
197
283
|
// Issue #764 — worktree-held-externally chip. pr._worktreeHeldPaused is set
|
|
198
284
|
// when a PR-driven review/fix dispatch hit WORKTREE_PREFLIGHT because this
|
|
199
285
|
// PR's branch is checked out at the project root or in an external
|
|
200
|
-
// worktree the engine can't reach (see engine/lifecycle.js
|
|
286
|
+
// worktree the engine can't reach (see engine/orchestration/lifecycle.js
|
|
201
287
|
// recordWorktreeHeldPause). engine.js auto-clears this pause once it
|
|
202
288
|
// detects the holder no longer holds the branch; this chip lets an
|
|
203
289
|
// operator force-clear it immediately via
|
|
@@ -218,7 +304,7 @@ function prRow(pr) {
|
|
|
218
304
|
// Polish (W-mqv5ccn7): flatten Markdown in the body so the preview shows
|
|
219
305
|
// plain text instead of raw `##` / `**…**` / backtick source.
|
|
220
306
|
const descPreview = stripMarkdown(pr.description || '');
|
|
221
|
-
const
|
|
307
|
+
const authorCellHtml = _prAuthorCellHtml(pr);
|
|
222
308
|
const reviewerCell = sq.reviewer && sq.status !== 'waiting'
|
|
223
309
|
? '<span class="pr-agent" title="' + escapeHtml(sq.note || sq.reviewer) + '">' + escapeHtml(sq.reviewer) + '</span>'
|
|
224
310
|
: sq.reviewer && sq.status === 'waiting'
|
|
@@ -227,96 +313,72 @@ function prRow(pr) {
|
|
|
227
313
|
? '<span class="pr-agent" title="' + escapeHtml(pr.reviewedBy.join(', ')) + '">' + escapeHtml(pr.reviewedBy.join(', ')) + '</span>'
|
|
228
314
|
: '<span style="color:var(--muted);font-size:var(--text-base)">—</span>';
|
|
229
315
|
const createdLabel = (pr.created || '—').slice(0, 16).replace('T', ' ');
|
|
230
|
-
//
|
|
231
|
-
//
|
|
232
|
-
//
|
|
233
|
-
// PR. Default (undefined / false) = observed.
|
|
234
|
-
var observe = pr.contextOnly !== true;
|
|
235
|
-
var observeClass = observe ? 'pr-observe-on' : 'pr-observe-off';
|
|
236
|
-
var observeLabel = observe ? 'observed' : 'context';
|
|
237
|
-
var observeTitle = observe
|
|
238
|
-
? 'Auto-observe ON — engine reviews this PR and dispatches fix agents on review/build feedback. Click to switch to context-only.'
|
|
239
|
-
: 'Context only — engine polls status and comments but will not dispatch review/fix agents. Click to enable auto-observe.';
|
|
240
|
-
// pr.id is canonical: "<host>:<slug>#<number>" (engine/shared.js getCanonicalPrId).
|
|
241
|
-
// Parse here so the toggle handler can post {host, slug, number} without
|
|
242
|
-
// shipping additional fields per row.
|
|
243
|
-
var observeBtn = '';
|
|
316
|
+
// pr.id is canonical: "<host>:<slug>#<number>" (engine/core/shared.js getCanonicalPrId).
|
|
317
|
+
// Existing records inherit both controls from contextOnly until an operator
|
|
318
|
+
// changes either switch, at which point the server persists both explicitly.
|
|
244
319
|
var idMatch = typeof pr.id === 'string' ? pr.id.match(/^([^:]+):(.+)#(\d+)$/) : null;
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
+ '<input type="checkbox" class="pr-observe-switch__input"'
|
|
254
|
-
+ (observe ? ' checked' : '') + ' '
|
|
255
|
-
+ 'aria-label="' + escapeHtml('Auto-observe: ' + observeLabel) + '" '
|
|
256
|
-
+ 'data-pr-host="' + escapeHtml(idMatch[1]) + '" '
|
|
257
|
-
+ 'data-pr-slug="' + escapeHtml(idMatch[2]) + '" '
|
|
258
|
-
+ 'data-pr-number="' + escapeHtml(idMatch[3]) + '" '
|
|
259
|
-
+ 'data-pr-observe="' + (observe ? '1' : '0') + '" '
|
|
260
|
-
+ 'onchange="togglePrObserve(this)">'
|
|
261
|
-
+ '<span class="pr-observe-switch__track" aria-hidden="true">'
|
|
262
|
-
+ '<span class="pr-observe-switch__knob"></span>'
|
|
263
|
-
+ '</span>'
|
|
264
|
-
+ '</label> ';
|
|
265
|
-
}
|
|
320
|
+
var autoFixEnabled = typeof pr.autoFixEnabled === 'boolean'
|
|
321
|
+
? pr.autoFixEnabled
|
|
322
|
+
: pr.contextOnly !== true;
|
|
323
|
+
var autoReviewEnabled = typeof pr.autoReviewEnabled === 'boolean'
|
|
324
|
+
? pr.autoReviewEnabled
|
|
325
|
+
: pr.contextOnly !== true;
|
|
326
|
+
var autoFixBtn = prAutomationToggle(idMatch, 'fix', 'Auto Fix', autoFixEnabled);
|
|
327
|
+
var autoReviewBtn = prAutomationToggle(idMatch, 'review', 'Auto Review', autoReviewEnabled);
|
|
266
328
|
// Title attrs live on the inner element (link/span/badge) so hovering the
|
|
267
329
|
// ellipsis-truncated content reveals the full text. Cell tags stay bare so
|
|
268
330
|
// the header-to-cell count assertion in test/unit.test.js continues to
|
|
269
331
|
// balance.
|
|
270
|
-
//
|
|
271
|
-
//
|
|
272
|
-
//
|
|
273
|
-
//
|
|
332
|
+
// Dedicated Project column (W-ms90po5j; was a secondary label folded into
|
|
333
|
+
// the PR-id cell under W-mr3mowg9). `_project` is stamped by the engine
|
|
334
|
+
// enrichment / getAllPrs stamping (see top-of-file note + line ~33). Empty or
|
|
335
|
+
// unknown project values render the shared muted em-dash placeholder so the
|
|
336
|
+
// cell matches the table's other empty-value conventions (e.g. Observe).
|
|
274
337
|
const projectName = pr._project ? String(pr._project) : '';
|
|
275
|
-
const
|
|
276
|
-
? '<
|
|
277
|
-
: '';
|
|
338
|
+
const projectCellHtml = projectName
|
|
339
|
+
? '<span class="pr-project" title="' + escapeHtml(projectName) + '">' + escapeHtml(projectName) + '</span>'
|
|
340
|
+
: '<span style="color:var(--muted);font-size:var(--text-base)" aria-label="No project">—</span>';
|
|
278
341
|
return '<tr>' +
|
|
279
|
-
'<td><span class="pr-id" title="' + escapeHtml(String(prId)) + '">' + escapeHtml(prShortId(String(prId))) + '</span
|
|
342
|
+
'<td><span class="pr-id" title="' + escapeHtml(String(prId)) + '">' + escapeHtml(prShortId(String(prId))) + '</span></td>' +
|
|
343
|
+
'<td>' + projectCellHtml + '</td>' +
|
|
280
344
|
'<td><a class="pr-title" title="' + escapeHtml(titleText) + '" href="' + escapeHtml(safeUrl(url)) + '" target="_blank" rel="noopener">' + escapeHtml(titleText) + '</a>' + followupChip + pausedChips + (descPreview ? '<div class="pr-desc" title="' + escapeHtml(descPreview) + '">' + escapeHtml(descPreview.length > 120 ? descPreview.slice(0, 120) + '...' : descPreview) + '</div>' : '') + '</td>' +
|
|
281
|
-
'<td><span class="pr-badge ' + statusClass + '" title="' + escapeHtml(statusLabel) + '">' + escapeHtml(statusLabel) + '</span></td>' +
|
|
345
|
+
'<td><span class="pr-status-badges"><span class="pr-badge ' + statusClass + '" title="' + escapeHtml(statusLabel) + '">' + escapeHtml(statusLabel) + '</span>' + mergeConflictBadge + '</span></td>' +
|
|
282
346
|
'<td><span class="pr-badge ' + reviewClass + '" title="' + escapeHtml(reviewTitle || reviewLabel) + '">' + escapeHtml(reviewLabel) + '</span></td>' +
|
|
283
347
|
'<td><span class="pr-badge ' + buildClass + '" title="' + escapeHtml(buildTitle || buildLabel) + '">' + escapeHtml(buildLabel) + '</span></td>' +
|
|
284
|
-
'<td>' + mergeStateHtml + '</td>' +
|
|
285
348
|
'<td><span class="' + branchClass + '" title="' + escapeHtml(branchError || branchLabel) + '">' + escapeHtml(branchLabel) + '</span>' + pendingReasonHtml + '</td>' +
|
|
286
|
-
'<td
|
|
349
|
+
'<td>' + authorCellHtml + '</td>' +
|
|
287
350
|
'<td>' + reviewerCell + '</td>' +
|
|
288
|
-
'<td>' + (
|
|
351
|
+
'<td>' + (autoFixBtn || '<span style="color:var(--muted);font-size:var(--text-base)">—</span>') + '</td>' +
|
|
352
|
+
'<td>' + (autoReviewBtn || '<span style="color:var(--muted);font-size:var(--text-base)">—</span>') + '</td>' +
|
|
289
353
|
'<td><span class="pr-date" title="' + escapeHtml(createdLabel) + '">' + escapeHtml(createdLabel) + '</span></td>' +
|
|
290
|
-
'<td><button class="
|
|
291
|
-
'<button class="btn-destructive" style="padding:1px 5px;margin-left:4px" data-pr-id="' + escapeHtml(String(prId)) + '" onclick="event.stopPropagation();unlinkPr(this.dataset.prId)" title="Remove from tracking">x</button></td>' +
|
|
354
|
+
'<td><button class="btn-destructive" style="padding:1px 5px" data-pr-id="' + escapeHtml(String(prId)) + '" onclick="event.stopPropagation();unlinkPr(this.dataset.prId)" title="Remove from tracking">x</button></td>' +
|
|
292
355
|
'</tr>';
|
|
293
356
|
}
|
|
294
357
|
|
|
295
|
-
// Explicit
|
|
296
|
-
//
|
|
297
|
-
// windows and the .pr-table-wrap--prs container scrolls horizontally inside
|
|
298
|
-
// the viewport (sticky scrollbar — see styles.css).
|
|
358
|
+
// Explicit widths keep long titles/branches bounded; narrow viewports scroll
|
|
359
|
+
// inside .pr-table-wrap--prs (sticky scrollbar — see styles.css).
|
|
299
360
|
const PRS_COLGROUP =
|
|
300
361
|
'<colgroup>' +
|
|
301
|
-
'<col style="width:130px">' + // PR id (short label: `gh #481` / `ado #5383607`)
|
|
362
|
+
'<col style="width:130px">' + // PR id (short label: `gh #481` / `ado #5383607`)
|
|
363
|
+
'<col style="width:130px">' + // Project
|
|
302
364
|
'<col style="width:320px">' + // Title
|
|
303
|
-
'<col style="width:
|
|
365
|
+
'<col style="width:150px">' + // Status (lifecycle badge [draft/active/merged/abandoned] + merge-conflict badge)
|
|
304
366
|
'<col style="width:130px">' + // Review
|
|
305
367
|
'<col style="width:130px">' + // Build
|
|
306
|
-
'<col style="width:120px">' + // Merge conflict
|
|
307
368
|
'<col style="width:200px">' + // Branch
|
|
308
|
-
'<col style="width:
|
|
369
|
+
'<col style="width:160px">' + // Author
|
|
309
370
|
'<col style="width:140px">' + // Signed Off By
|
|
310
|
-
'<col style="width:100px">' + //
|
|
371
|
+
'<col style="width:100px">' + // Auto Fix
|
|
372
|
+
'<col style="width:100px">' + // Auto Review
|
|
311
373
|
'<col style="width:130px">' + // Created
|
|
312
|
-
'<col style="width:80px">' + // Actions (
|
|
374
|
+
'<col style="width:80px">' + // Actions (remove)
|
|
313
375
|
'</colgroup>';
|
|
314
376
|
|
|
315
377
|
function prTableHtml(rows) {
|
|
316
378
|
return '<div class="pr-table-wrap pr-table-wrap--prs"><table class="pr-table pr-table--prs">' +
|
|
317
379
|
PRS_COLGROUP +
|
|
318
380
|
'<thead><tr>' +
|
|
319
|
-
'<th>PR</th><th>
|
|
381
|
+
'<th>PR</th><th>Project</th><th>Title</th><th>Status</th><th>Review</th><th>Build</th><th>Branch</th><th>Author</th><th>Signed Off By</th><th>Auto Fix</th><th>Auto Review</th><th>Created</th><th></th>' +
|
|
320
382
|
'</tr></thead><tbody>' + rows + '</tbody></table></div>';
|
|
321
383
|
}
|
|
322
384
|
|
|
@@ -333,61 +395,13 @@ function _restorePrScrollState(el, state) {
|
|
|
333
395
|
tableWrap.scrollTop = state.top || 0;
|
|
334
396
|
}
|
|
335
397
|
|
|
336
|
-
function _syncPrFilterOptions(prs) {
|
|
337
|
-
const options = getPrFilterOptions(prs);
|
|
338
|
-
const controls = Object.keys(PR_FILTER_CONTROL_IDS).map(function(dimension) {
|
|
339
|
-
return {
|
|
340
|
-
dimension,
|
|
341
|
-
select: document.getElementById(PR_FILTER_CONTROL_IDS[dimension]),
|
|
342
|
-
};
|
|
343
|
-
}).filter(function(entry) { return entry.select; });
|
|
344
|
-
if (!controls.length) return;
|
|
345
|
-
const signature = JSON.stringify(options);
|
|
346
|
-
if (signature === prFilterOptionsSignature) return;
|
|
347
|
-
prFilterOptionsSignature = signature;
|
|
348
|
-
controls.forEach(function(entry) {
|
|
349
|
-
const dimension = entry.dimension;
|
|
350
|
-
const select = entry.select;
|
|
351
|
-
const selected = select.value;
|
|
352
|
-
const all = document.createElement('option');
|
|
353
|
-
all.value = '';
|
|
354
|
-
all.textContent = PR_FILTER_ALL_LABELS[dimension];
|
|
355
|
-
const nodes = [all].concat((options[dimension] || []).map(function(option) {
|
|
356
|
-
const node = document.createElement('option');
|
|
357
|
-
node.value = option.value;
|
|
358
|
-
node.textContent = option.label;
|
|
359
|
-
return node;
|
|
360
|
-
}));
|
|
361
|
-
select.replaceChildren(...nodes);
|
|
362
|
-
if (nodes.some(function(node) { return node.value === selected; })) select.value = selected;
|
|
363
|
-
});
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
function _readPrFilters() {
|
|
367
|
-
const filters = {};
|
|
368
|
-
Object.keys(PR_FILTER_CONTROL_IDS).forEach(function(dimension) {
|
|
369
|
-
const select = document.getElementById(PR_FILTER_CONTROL_IDS[dimension]);
|
|
370
|
-
filters[dimension] = select ? select.value : '';
|
|
371
|
-
});
|
|
372
|
-
return filters;
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
function _hasActivePrFilters(filters) {
|
|
376
|
-
return Object.keys(PR_FILTER_CONTROL_IDS).some(function(dimension) {
|
|
377
|
-
return Boolean(filters[dimension]);
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
|
|
381
398
|
function applyPrFilters() {
|
|
382
399
|
prPage = 0;
|
|
383
400
|
renderPrs(allPrs, { preserveScroll: false });
|
|
384
401
|
}
|
|
385
402
|
|
|
386
403
|
function resetPrFilters() {
|
|
387
|
-
|
|
388
|
-
const select = document.getElementById(PR_FILTER_CONTROL_IDS[dimension]);
|
|
389
|
-
if (select) select.value = '';
|
|
390
|
-
});
|
|
404
|
+
_prFilterBar().clear();
|
|
391
405
|
applyPrFilters();
|
|
392
406
|
}
|
|
393
407
|
|
|
@@ -395,21 +409,22 @@ function renderPrs(prs, opts) {
|
|
|
395
409
|
opts = opts || {};
|
|
396
410
|
prs = Array.isArray(prs) ? prs.filter(p => p && !isDeleted('pr:' + p.id)) : [];
|
|
397
411
|
allPrs = prs;
|
|
398
|
-
|
|
399
|
-
|
|
412
|
+
const _bar = _prFilterBar();
|
|
413
|
+
_bar.syncOptions(allPrs);
|
|
414
|
+
const filters = _bar.read();
|
|
400
415
|
filteredPrs = filterPullRequests(allPrs, filters);
|
|
401
416
|
const el = document.getElementById('pr-content');
|
|
402
417
|
const count = document.getElementById('pr-count');
|
|
403
418
|
const summary = document.getElementById('pr-filter-summary');
|
|
404
419
|
count.textContent = filteredPrs.length;
|
|
405
420
|
if (summary) {
|
|
406
|
-
summary.textContent =
|
|
421
|
+
summary.textContent = _bar.hasActive(filters)
|
|
407
422
|
? 'Showing ' + filteredPrs.length + ' of ' + allPrs.length
|
|
408
423
|
: '';
|
|
409
424
|
}
|
|
410
425
|
if (!allPrs.length) {
|
|
411
426
|
prPage = 0;
|
|
412
|
-
el.innerHTML = '<p class="pr-empty">No pull requests yet. PRs created by agents will appear here with review
|
|
427
|
+
el.innerHTML = '<p class="pr-empty">No pull requests yet. PRs created by agents will appear here with review and build status.</p>';
|
|
413
428
|
return;
|
|
414
429
|
}
|
|
415
430
|
if (!filteredPrs.length) {
|
|
@@ -521,12 +536,14 @@ function _renderPrDetail(pr) {
|
|
|
521
536
|
const mergeConflictBadge = _renderPrMergeConflictBadge(pr);
|
|
522
537
|
|
|
523
538
|
const badges =
|
|
524
|
-
'<span class="pr-
|
|
525
|
-
'<span class="pr-badge ' +
|
|
539
|
+
'<span class="pr-status-badges">' +
|
|
540
|
+
'<span class="pr-badge ' + statusClass + '" title="status">' + escapeHtml(String(statusLabel)) + '</span>' +
|
|
541
|
+
'<span class="pr-badge ' + reviewClass + '" title="review">' + escapeHtml(String(reviewLabel)) + '</span>' +
|
|
526
542
|
'<span class="pr-badge ' + buildClass + '" title="build">' + escapeHtml(String(buildLabel)) + '</span>' +
|
|
527
|
-
|
|
543
|
+
mergeConflictBadge +
|
|
544
|
+
'</span>';
|
|
528
545
|
|
|
529
|
-
// Linked WIs — join via item._pr === pr.id (stamped by engine/queries.js).
|
|
546
|
+
// Linked WIs — join via item._pr === pr.id (stamped by engine/core/queries.js).
|
|
530
547
|
const wis = (window._lastWorkItems) || [];
|
|
531
548
|
const linkedWis = wis.filter(w => w && w._pr === pr.id);
|
|
532
549
|
let linkedChips = '';
|
|
@@ -601,7 +618,26 @@ function _renderPrDetail(pr) {
|
|
|
601
618
|
'</div>';
|
|
602
619
|
}
|
|
603
620
|
|
|
604
|
-
|
|
621
|
+
// Author (real individual the PR is for) — shown alongside the Minions agent
|
|
622
|
+
// so operators can answer both "who is this for?" and "which agent handled it?".
|
|
623
|
+
let author = '';
|
|
624
|
+
{
|
|
625
|
+
const a = pr.author;
|
|
626
|
+
let login = '', displayName = '', url = '';
|
|
627
|
+
if (a && typeof a === 'object') { login = a.login || ''; displayName = a.displayName || ''; url = a.url || ''; }
|
|
628
|
+
else if (typeof a === 'string') { login = a; }
|
|
629
|
+
const primary = displayName || login;
|
|
630
|
+
if (primary) {
|
|
631
|
+
const secondary = (displayName && login && login !== displayName) ? ' <span style="color:var(--muted)">@' + escapeHtml(login) + '</span>' : '';
|
|
632
|
+
const valHtml = (url && /^https?:\/\//i.test(url))
|
|
633
|
+
? '<a href="' + escapeHtml(safeUrl(url)) + '" target="_blank" rel="noopener">' + escapeHtml(primary) + '</a>' + secondary
|
|
634
|
+
: escapeHtml(primary) + secondary;
|
|
635
|
+
author = '<div><strong style="color:var(--muted);font-size:var(--text-base)">Author:</strong> ' + valHtml + '</div>';
|
|
636
|
+
} else {
|
|
637
|
+
author = '<div><strong style="color:var(--muted);font-size:var(--text-base)">Author:</strong> <span style="color:var(--muted)">Unknown</span></div>';
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
const agent = pr.agent ? '<div><strong style="color:var(--muted);font-size:var(--text-base)">Minions agent:</strong> ' + escapeHtml(String(pr.agent)) + '</div>' : '';
|
|
605
641
|
const branch = pr.branch ? '<div><strong style="color:var(--muted);font-size:var(--text-base)">Branch:</strong> <code>' + escapeHtml(String(pr.branch)) + '</code></div>' : '';
|
|
606
642
|
const created = pr.created ? '<div><strong style="color:var(--muted);font-size:var(--text-base)">Created:</strong> ' + escapeHtml(String(pr.created)) + '</div>' : '';
|
|
607
643
|
const project = pr._project ? '<div><strong style="color:var(--muted);font-size:var(--text-base)">Project:</strong> ' + escapeHtml(String(pr._project)) + '</div>' : '';
|
|
@@ -620,7 +656,7 @@ function _renderPrDetail(pr) {
|
|
|
620
656
|
'<code style="color:var(--muted);font-size:var(--text-base)">' + escapeHtml(String(pr.id || '')) + '</code><br>' +
|
|
621
657
|
badges +
|
|
622
658
|
'</div>' +
|
|
623
|
-
agent + branch + project + created +
|
|
659
|
+
author + agent + branch + project + created +
|
|
624
660
|
reviewers +
|
|
625
661
|
linkedChips +
|
|
626
662
|
parentChip +
|
|
@@ -733,57 +769,50 @@ async function unlinkPr(id) {
|
|
|
733
769
|
// consumes canonical `contextOnly` to gate review/fix dispatch (engine/
|
|
734
770
|
// shared.js isAutoManagedPrRecord + discoverFromPrs).
|
|
735
771
|
//
|
|
736
|
-
|
|
737
|
-
// live on the input so this handler keeps reading them directly; visual
|
|
738
|
-
// state is mirrored onto the wrapping <label> via the pr-observe-on/off
|
|
739
|
-
// class so CSS can paint the track and slide the knob.
|
|
740
|
-
async function togglePrObserve(btn) {
|
|
772
|
+
async function togglePrAutomation(btn) {
|
|
741
773
|
if (!btn || btn.disabled) return;
|
|
742
774
|
const host = btn.dataset.prHost;
|
|
743
775
|
const slug = btn.dataset.prSlug;
|
|
744
776
|
const number = parseInt(btn.dataset.prNumber, 10);
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
const
|
|
748
|
-
const
|
|
749
|
-
|
|
750
|
-
|
|
777
|
+
const automation = btn.dataset.prAutomation;
|
|
778
|
+
if (!host || !slug || !Number.isFinite(number) || !['fix', 'review'].includes(automation)) return;
|
|
779
|
+
const wasEnabled = btn.dataset.prEnabled === '1';
|
|
780
|
+
const next = !wasEnabled;
|
|
781
|
+
const label = automation === 'fix' ? 'Auto Fix' : 'Auto Review';
|
|
782
|
+
const wrapper = btn.closest('.pr-automation-switch');
|
|
783
|
+
btn.dataset.prEnabled = next ? '1' : '0';
|
|
751
784
|
btn.checked = next;
|
|
752
|
-
btn.setAttribute('aria-label', '
|
|
785
|
+
btn.setAttribute('aria-label', label + ': ' + (next ? 'enabled' : 'disabled'));
|
|
753
786
|
if (wrapper) {
|
|
754
|
-
wrapper.classList.toggle('pr-
|
|
755
|
-
wrapper.classList.toggle('pr-
|
|
787
|
+
wrapper.classList.toggle('pr-automation-on', next);
|
|
788
|
+
wrapper.classList.toggle('pr-automation-off', !next);
|
|
756
789
|
}
|
|
757
790
|
btn.disabled = true;
|
|
758
791
|
try {
|
|
759
|
-
const res = await fetch('/api/pull-requests/
|
|
792
|
+
const res = await fetch('/api/pull-requests/automation', {
|
|
760
793
|
method: 'POST', headers: { 'Content-Type': 'application/json' },
|
|
761
|
-
|
|
762
|
-
// legacy `observe` body param remains a server-side back-compat
|
|
763
|
-
// fallback for any other caller, so the client no longer sends it.
|
|
764
|
-
body: JSON.stringify({ host, slug, number, contextOnly: !next })
|
|
794
|
+
body: JSON.stringify({ host, slug, number, automation, enabled: next })
|
|
765
795
|
});
|
|
766
796
|
if (!res.ok) {
|
|
767
797
|
const d = await res.json().catch(() => ({}));
|
|
768
|
-
|
|
769
|
-
btn.
|
|
770
|
-
btn.
|
|
771
|
-
btn.setAttribute('aria-label', 'Auto-observe: ' + (wasObserve ? 'observed' : 'context'));
|
|
798
|
+
btn.dataset.prEnabled = wasEnabled ? '1' : '0';
|
|
799
|
+
btn.checked = wasEnabled;
|
|
800
|
+
btn.setAttribute('aria-label', label + ': ' + (wasEnabled ? 'enabled' : 'disabled'));
|
|
772
801
|
if (wrapper) {
|
|
773
|
-
wrapper.classList.toggle('pr-
|
|
774
|
-
wrapper.classList.toggle('pr-
|
|
802
|
+
wrapper.classList.toggle('pr-automation-on', wasEnabled);
|
|
803
|
+
wrapper.classList.toggle('pr-automation-off', !wasEnabled);
|
|
775
804
|
}
|
|
776
805
|
showToast('pr-toast', 'Failed: ' + (d.error || 'unknown'), false);
|
|
777
806
|
return;
|
|
778
807
|
}
|
|
779
|
-
showToast('pr-toast', next ? '
|
|
808
|
+
showToast('pr-toast', label + (next ? ' enabled' : ' disabled'), true);
|
|
780
809
|
} catch (e) {
|
|
781
|
-
btn.dataset.
|
|
782
|
-
btn.checked =
|
|
783
|
-
btn.setAttribute('aria-label', '
|
|
810
|
+
btn.dataset.prEnabled = wasEnabled ? '1' : '0';
|
|
811
|
+
btn.checked = wasEnabled;
|
|
812
|
+
btn.setAttribute('aria-label', label + ': ' + (wasEnabled ? 'enabled' : 'disabled'));
|
|
784
813
|
if (wrapper) {
|
|
785
|
-
wrapper.classList.toggle('pr-
|
|
786
|
-
wrapper.classList.toggle('pr-
|
|
814
|
+
wrapper.classList.toggle('pr-automation-on', wasEnabled);
|
|
815
|
+
wrapper.classList.toggle('pr-automation-off', !wasEnabled);
|
|
787
816
|
}
|
|
788
817
|
showToast('pr-toast', 'Error: ' + e.message, false);
|
|
789
818
|
} finally {
|
|
@@ -905,7 +934,7 @@ window.MinionsPrs = {
|
|
|
905
934
|
openAddPrModal,
|
|
906
935
|
openPrDetail,
|
|
907
936
|
unlinkPr,
|
|
908
|
-
|
|
937
|
+
togglePrAutomation,
|
|
909
938
|
resumePausedCause,
|
|
910
939
|
resumeBuildFixIneffective,
|
|
911
940
|
resumeWorktreeHeldPause
|