@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
|
@@ -129,7 +129,7 @@
|
|
|
129
129
|
* and a mock sentinel-existence probe via the private `_exists` option
|
|
130
130
|
* (signature `(absPath:string) => boolean`, defaulting to fs.existsSync).
|
|
131
131
|
* Production callers omit both and the helper falls back to
|
|
132
|
-
* `require('
|
|
132
|
+
* `require('../core/shared').shellSafeGit` and `fs.existsSync` respectively.
|
|
133
133
|
*
|
|
134
134
|
* `checkLiveCheckoutDirty` / `checkLiveCheckoutStaleBase` (W-mrcifup2000c218a):
|
|
135
135
|
* ALLOCATION-TIME pre-dispatch counterparts to the dirty / stale-base checks
|
|
@@ -151,7 +151,7 @@
|
|
|
151
151
|
|
|
152
152
|
const fs = require('fs');
|
|
153
153
|
const path = require('path');
|
|
154
|
-
const shared = require('
|
|
154
|
+
const shared = require('../core/shared');
|
|
155
155
|
|
|
156
156
|
// W-mqvejug6000eeb20 — generous stdout ceiling for the read-only git probes in
|
|
157
157
|
// this module (`git status --porcelain`, `rev-parse`, …). Node's execFile
|
|
@@ -444,7 +444,7 @@ function _defaultResolveAutoFreshen(localPath) {
|
|
|
444
444
|
// isolation / in tests that never trigger the write). Best-effort.
|
|
445
445
|
function _defaultWriteInboxNote(slug, content) {
|
|
446
446
|
// eslint-disable-next-line global-require
|
|
447
|
-
return require('
|
|
447
|
+
return require('../orchestration/dispatch').writeInboxAlert(slug, content);
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
// Best-effort, side-effect-light resolution of `mainRef` as a restore target
|
|
@@ -1574,7 +1574,7 @@ async function checkLiveCheckoutStaleBase(opts = {}) {
|
|
|
1574
1574
|
*
|
|
1575
1575
|
* Dispatch-end counterpart to prepareLiveCheckout. Runs from spawnAgent's
|
|
1576
1576
|
* onAgentClose (engine.js) on EVERY terminal result AND from the engine-restart
|
|
1577
|
-
* orphan/reattach completion path (engine/cli.js), so the operator's working
|
|
1577
|
+
* orphan/reattach completion path (engine/operations/cli.js), so the operator's working
|
|
1578
1578
|
* tree is switched back to the ref it was on before the live-mode agent ran.
|
|
1579
1579
|
*
|
|
1580
1580
|
* Behaviour (locked by human steer steer-bc5861ff95, 2026-06-19):
|
|
@@ -21,8 +21,8 @@
|
|
|
21
21
|
|
|
22
22
|
const fs = require('fs');
|
|
23
23
|
const path = require('path');
|
|
24
|
-
const shared = require('
|
|
25
|
-
const smallStateStore = require('
|
|
24
|
+
const shared = require('../core/shared');
|
|
25
|
+
const smallStateStore = require('../persistence/small-state-store');
|
|
26
26
|
|
|
27
27
|
const { log, ENGINE_DEFAULTS } = shared;
|
|
28
28
|
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
const shared = require('../core/shared');
|
|
2
|
+
|
|
3
|
+
// W-ms87lj8j018j2572 — the retention window is OWNED by engine/core/shared.js so the
|
|
4
|
+
// ref-prune window and `ENGINE_DEFAULTS.worktreeProtectedQuarantineRetentionMs`
|
|
5
|
+
// (which sweeps the corresponding quarantine DIRECTORIES) cannot drift apart.
|
|
6
|
+
// Re-exported here for existing consumers; never redefine the literal.
|
|
7
|
+
const { QUARANTINE_REF_RETENTION_DAYS, QUARANTINE_REF_RETENTION_MS } = shared;
|
|
8
|
+
const DELETE_CONCURRENCY = 8;
|
|
9
|
+
|
|
10
|
+
const QUARANTINE_REF_PREFIXES = Object.freeze([
|
|
11
|
+
'refs/minions/quarantine/',
|
|
12
|
+
'refs/minions/quarantine-wip/',
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
/** True only for refs inside the two Minions-owned quarantine namespaces.
|
|
16
|
+
* Branches, tags, and near-miss namespaces must never be pruned. */
|
|
17
|
+
function isQuarantineRef(ref) {
|
|
18
|
+
return QUARANTINE_REF_PREFIXES.some(prefix => String(ref || '').startsWith(prefix));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** Canonical creation time encoded as the trailing `/<epoch-ms>` ref segment.
|
|
22
|
+
* Returns null for anything that is not a plain positive integer so callers
|
|
23
|
+
* can preserve (never speculatively delete) malformed refs. */
|
|
24
|
+
function quarantineRefTimestampMs(ref) {
|
|
25
|
+
const timestamp = String(ref || '').split('/').pop();
|
|
26
|
+
if (!/^\d+$/.test(timestamp)) return null;
|
|
27
|
+
const parsed = Number(timestamp);
|
|
28
|
+
return Number.isSafeInteger(parsed) && parsed > 0 ? parsed : null;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function quarantineRefCreatedAtMs(ref, fallbackCreatedAt) {
|
|
32
|
+
const fromRef = quarantineRefTimestampMs(ref);
|
|
33
|
+
if (fromRef !== null) return fromRef;
|
|
34
|
+
const fallback = Date.parse(fallbackCreatedAt || '');
|
|
35
|
+
return Number.isFinite(fallback) ? fallback : null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function _readProjectQuarantineRefs(project) {
|
|
39
|
+
const output = await shared.shellSafeGit([
|
|
40
|
+
'for-each-ref',
|
|
41
|
+
'--format=%(refname)|%(objectname)|%(creatordate:iso-strict)',
|
|
42
|
+
'refs/minions/quarantine/',
|
|
43
|
+
'refs/minions/quarantine-wip/',
|
|
44
|
+
], { cwd: project.localPath, timeout: 15000 });
|
|
45
|
+
const seenRefs = new Set();
|
|
46
|
+
return String(output || '').split(/\r?\n/).filter(Boolean).map(line => {
|
|
47
|
+
const [ref, sha, fallbackCreatedAt] = line.split('|');
|
|
48
|
+
if (!ref || seenRefs.has(ref)) return null;
|
|
49
|
+
seenRefs.add(ref);
|
|
50
|
+
const createdAtMs = quarantineRefCreatedAtMs(ref, fallbackCreatedAt);
|
|
51
|
+
return { ref, sha, fallbackCreatedAt, createdAtMs };
|
|
52
|
+
}).filter(Boolean);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function listQuarantineRefs(projects) {
|
|
56
|
+
const candidates = (Array.isArray(projects) ? projects : []).filter(project => project?.localPath);
|
|
57
|
+
const results = await Promise.allSettled(candidates.map(async project => {
|
|
58
|
+
const refs = await _readProjectQuarantineRefs(project);
|
|
59
|
+
return refs.map(({ ref, sha, fallbackCreatedAt, createdAtMs }) => {
|
|
60
|
+
return {
|
|
61
|
+
project: project.name || '',
|
|
62
|
+
ref,
|
|
63
|
+
sha,
|
|
64
|
+
createdAt: createdAtMs ? new Date(createdAtMs).toISOString() : (fallbackCreatedAt || ''),
|
|
65
|
+
kind: ref.startsWith('refs/minions/quarantine-wip/') ? 'wip' : 'commits',
|
|
66
|
+
};
|
|
67
|
+
});
|
|
68
|
+
}));
|
|
69
|
+
const items = [];
|
|
70
|
+
for (let i = 0; i < results.length; i++) {
|
|
71
|
+
const result = results[i];
|
|
72
|
+
if (result.status === 'fulfilled') items.push(...result.value);
|
|
73
|
+
else items.push({ project: candidates[i].name || '', error: result.reason?.message || String(result.reason) });
|
|
74
|
+
}
|
|
75
|
+
return items.sort((a, b) => String(b.createdAt || '').localeCompare(String(a.createdAt || '')));
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
async function _mapWithConcurrency(items, limit, worker) {
|
|
79
|
+
// Canonical implementation lives in engine/core/shared.js — kept as a thin
|
|
80
|
+
// alias so there is only one promise-pool in the worktree modules.
|
|
81
|
+
await shared.mapWithConcurrency(items, limit, worker);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/** TTL sweep for Minions quarantine recovery refs.
|
|
85
|
+
* Fails safe: only refs in the two Minions-owned namespaces whose ref-name
|
|
86
|
+
* timestamp proves they are at least `retentionMs` old are deleted, each with a
|
|
87
|
+
* SHA-guarded `update-ref -d`. Malformed refs and per-project/per-ref failures
|
|
88
|
+
* are reported, never treated as expiry. Idempotent — a second sweep finds
|
|
89
|
+
* nothing left to remove. W-ms87rbe601a66d13 — a non-positive `retentionMs`
|
|
90
|
+
* means INDEFINITE retention (the `0` opt-out mirrored from the directory
|
|
91
|
+
* sweep) and deletes nothing; it must never read as "everything is expired". */
|
|
92
|
+
async function pruneExpiredQuarantineRefs(projects, {
|
|
93
|
+
now = Date.now(),
|
|
94
|
+
retentionMs = QUARANTINE_REF_RETENTION_MS,
|
|
95
|
+
} = {}) {
|
|
96
|
+
const expiryEnabled = Number.isFinite(Number(retentionMs)) && Number(retentionMs) > 0;
|
|
97
|
+
const candidates = (Array.isArray(projects) ? projects : []).filter(project => project?.localPath);
|
|
98
|
+
const results = await Promise.allSettled(candidates.map(async project => {
|
|
99
|
+
const refs = (await _readProjectQuarantineRefs(project)).filter(item => isQuarantineRef(item.ref));
|
|
100
|
+
const scanned = refs.length;
|
|
101
|
+
const malformedRefs = [];
|
|
102
|
+
const expired = [];
|
|
103
|
+
let retained = 0;
|
|
104
|
+
|
|
105
|
+
for (const item of refs) {
|
|
106
|
+
const createdAtMs = quarantineRefTimestampMs(item.ref);
|
|
107
|
+
if (createdAtMs === null) {
|
|
108
|
+
malformedRefs.push({ project: project.name || '', ref: item.ref });
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
if (expiryEnabled && now - createdAtMs >= retentionMs) expired.push(item);
|
|
112
|
+
else retained++;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
let removed = 0;
|
|
116
|
+
const failures = [];
|
|
117
|
+
await _mapWithConcurrency(expired, DELETE_CONCURRENCY, async item => {
|
|
118
|
+
try {
|
|
119
|
+
await shared.shellSafeGit(['update-ref', '-d', item.ref, item.sha], {
|
|
120
|
+
cwd: project.localPath,
|
|
121
|
+
timeout: 15000,
|
|
122
|
+
});
|
|
123
|
+
removed++;
|
|
124
|
+
} catch (e) {
|
|
125
|
+
failures.push({
|
|
126
|
+
project: project.name || '',
|
|
127
|
+
ref: item.ref,
|
|
128
|
+
error: e?.message || String(e),
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
return { scanned, removed, retained, malformedRefs, failures };
|
|
133
|
+
}));
|
|
134
|
+
|
|
135
|
+
const summary = {
|
|
136
|
+
scanned: 0,
|
|
137
|
+
removed: 0,
|
|
138
|
+
retained: 0,
|
|
139
|
+
malformed: 0,
|
|
140
|
+
failed: 0,
|
|
141
|
+
malformedRefs: [],
|
|
142
|
+
errors: [],
|
|
143
|
+
};
|
|
144
|
+
for (let i = 0; i < results.length; i++) {
|
|
145
|
+
const result = results[i];
|
|
146
|
+
if (result.status === 'fulfilled') {
|
|
147
|
+
summary.scanned += result.value.scanned;
|
|
148
|
+
summary.removed += result.value.removed;
|
|
149
|
+
summary.retained += result.value.retained;
|
|
150
|
+
summary.malformed += result.value.malformedRefs.length;
|
|
151
|
+
summary.malformedRefs.push(...result.value.malformedRefs);
|
|
152
|
+
summary.failed += result.value.failures.length;
|
|
153
|
+
summary.errors.push(...result.value.failures);
|
|
154
|
+
} else {
|
|
155
|
+
summary.errors.push({
|
|
156
|
+
project: candidates[i]?.name || '',
|
|
157
|
+
error: result.reason?.message || String(result.reason),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
return summary;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
module.exports = {
|
|
165
|
+
QUARANTINE_REF_RETENTION_DAYS,
|
|
166
|
+
QUARANTINE_REF_RETENTION_MS,
|
|
167
|
+
QUARANTINE_REF_PREFIXES,
|
|
168
|
+
isQuarantineRef,
|
|
169
|
+
quarantineRefTimestampMs,
|
|
170
|
+
quarantineRefCreatedAtMs,
|
|
171
|
+
listQuarantineRefs,
|
|
172
|
+
pruneExpiredQuarantineRefs,
|
|
173
|
+
};
|