@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
package/docs/internal-install.md
CHANGED
|
@@ -17,7 +17,25 @@ registry such as `ProjectFeed-ISS@Release`.
|
|
|
17
17
|
|
|
18
18
|
No manually created PAT is required, accepted, or stored.
|
|
19
19
|
|
|
20
|
-
##
|
|
20
|
+
## Entry points
|
|
21
|
+
|
|
22
|
+
Without a checkout, download the launcher for your platform from the
|
|
23
|
+
[Minions page](https://icy-water-0224cc51e.2.azurestaticapps.net/minions) and run
|
|
24
|
+
it from your download folder:
|
|
25
|
+
|
|
26
|
+
```powershell
|
|
27
|
+
# Windows — https://icy-water-0224cc51e.2.azurestaticapps.net/minions/install-minions.ps1
|
|
28
|
+
az login
|
|
29
|
+
powershell -ExecutionPolicy Bypass -File .\install-minions.ps1
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Linux / macOS — https://icy-water-0224cc51e.2.azurestaticapps.net/minions/install-minions.sh
|
|
34
|
+
az login
|
|
35
|
+
bash ./install-minions.sh
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
From a repository checkout, the in-repo wrappers are equivalent:
|
|
21
39
|
|
|
22
40
|
```powershell
|
|
23
41
|
# Windows (PowerShell)
|
|
@@ -34,8 +52,16 @@ scripts\install-internal-minions.ps1
|
|
|
34
52
|
node bin/install-internal-minions.js
|
|
35
53
|
```
|
|
36
54
|
|
|
37
|
-
|
|
38
|
-
|
|
55
|
+
**Every one of these routes ends in `bin/install-internal-minions.js`**, which is
|
|
56
|
+
why they cannot drift apart. The in-repo wrappers are thin shims over it; the
|
|
57
|
+
downloadable launchers stage the verified package into a throwaway folder and
|
|
58
|
+
hand the migration to the copy that ships inside it. The rest of this document
|
|
59
|
+
describes that installer, so it describes all of them.
|
|
60
|
+
|
|
61
|
+
The downloadable launchers take no options of their own — each one always stages
|
|
62
|
+
the newest published version. Every [option below](#options), including
|
|
63
|
+
`--version` to pin an exact build, belongs to `bin/install-internal-minions.js`,
|
|
64
|
+
so reach it through the `node` route to pass one.
|
|
39
65
|
|
|
40
66
|
## Prerequisites
|
|
41
67
|
|
|
@@ -53,14 +79,66 @@ so behavior cannot drift between platforms.
|
|
|
53
79
|
| `--registry <url>` | the ISS `ProjectFeed-ISS` feed | Override the Azure Artifacts npm registry. Must be `https`. |
|
|
54
80
|
| `--package <name>` | `@opg-microsoft/minions` | Override the internal package name. Must be scoped. |
|
|
55
81
|
| `--backup-dir <dir>` | `<runtime root>/backups/internal-install-<timestamp>` | Where the pre-migration backup is written. |
|
|
82
|
+
| `--runtime-root <dir>` | resolved (see [Runtime root](#runtime-root)) | Pin the runtime root (`MINIONS_HOME`) this run reads, backs up, synchronizes, and restarts. Required to disambiguate when more than one candidate root carries runtime state. It is also the flag `minions update` prints when it refuses a cross-channel public install; quote the path if it contains spaces. |
|
|
56
83
|
| `--keep-public` | off | Leave an existing `@yemi33/minions` global install in place instead of replacing it. |
|
|
57
84
|
| `--no-restart` | off | Sync runtime files but skip the health-verified restart. |
|
|
58
85
|
| `--force` | off | Proceed even while agents are active (see [Active agents](#active-agents)). |
|
|
59
86
|
| `--dry-run` | off | Print the resolved plan and the exact commands; change nothing. |
|
|
60
87
|
| `--help` | — | Usage. |
|
|
61
88
|
|
|
62
|
-
Exit codes: `0` success, `1` failure, `2` usage error, `3` refused
|
|
63
|
-
|
|
89
|
+
Exit codes: `0` success, `1` failure, `2` usage error, `3` refused (active agents,
|
|
90
|
+
an ambiguous runtime root, or a `minions` shim the installer cannot prove it owns).
|
|
91
|
+
|
|
92
|
+
## Runtime root
|
|
93
|
+
|
|
94
|
+
The runtime root is the `MINIONS_HOME` directory this run backs up, synchronizes,
|
|
95
|
+
and restarts. It is resolved **once**, before a token is acquired or npm is
|
|
96
|
+
touched, and then pinned as an explicit `MINIONS_HOME` onto every child process
|
|
97
|
+
the installer spawns (`backup-state`, `minions init --force`, `minions restart`)
|
|
98
|
+
so no step can re-resolve to a different root. An inherited `MINIONS_TEST_DIR` is
|
|
99
|
+
stripped from that environment, because it outranks `MINIONS_HOME` in
|
|
100
|
+
`engine/core/shared.js#resolveMinionsHome` and would silently un-pin every child. The
|
|
101
|
+
pinned root and how it was chosen are printed at the top of the run and in the
|
|
102
|
+
`--dry-run` plan.
|
|
103
|
+
|
|
104
|
+
`resolveAuthoritativeRuntimeRoot()` enumerates every candidate the engine itself
|
|
105
|
+
could pick, deduplicates them by resolved path (highest-priority source wins),
|
|
106
|
+
and scores each by whether it carries a **non-empty** `engine/state.db` (a
|
|
107
|
+
zero-byte database is an aborted init, not a runtime worth protecting):
|
|
108
|
+
|
|
109
|
+
| Candidate | Source |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `--runtime-root <dir>` | explicit operator pin — always wins |
|
|
112
|
+
| `MINIONS_HOME` | explicit environment pin |
|
|
113
|
+
| `~/.minions-root` | the root pointer `minions init` last recorded, which `engine/core/shared.js#resolveMinionsHome` consults |
|
|
114
|
+
| `~/.minions` | the default |
|
|
115
|
+
| the cwd / repo checkout | the nearest ancestor of the working directory containing both `.git` and `engine.js` — the same shape `resolveMinionsHome`'s `preferSourceCheckout` branch would return |
|
|
116
|
+
|
|
117
|
+
A candidate that carries state outranks one that does not, so **a repo checkout
|
|
118
|
+
never wins over a root that already has state**. When two or more candidates
|
|
119
|
+
carry a non-empty `engine/state.db` and no `--runtime-root` was given, the
|
|
120
|
+
installer **refuses** (exit `3`) and names every candidate plus the exact
|
|
121
|
+
`--runtime-root <path>` command to disambiguate — nothing is downloaded,
|
|
122
|
+
uninstalled, or modified. The installer never guesses which runtime is
|
|
123
|
+
authoritative.
|
|
124
|
+
|
|
125
|
+
## Install-channel marker
|
|
126
|
+
|
|
127
|
+
`minions init` records the runtime's version in `.minions-version` and its source
|
|
128
|
+
commit in `.minions-commit`. Neither says **which npm distribution** produced the
|
|
129
|
+
root, so an internal `@opg-microsoft/minions` root and a public
|
|
130
|
+
`@yemi33/minions` root are otherwise indistinguishable on disk. `init` therefore
|
|
131
|
+
also writes `.minions-package` beside them:
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{ "name": "@opg-microsoft/minions", "version": "1.0.76", "installedAt": "2026-07-29T00:00:00.000Z" }
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Read it with `shared.readRuntimeChannel(runtimeRoot)`, which returns
|
|
138
|
+
`{ name, version }` or `null`. A **missing** marker means *unknown*, never an
|
|
139
|
+
error: every root initialized before the marker existed has none, and a legacy
|
|
140
|
+
root must keep working. A marker that is corrupt, or that names a package this
|
|
141
|
+
repo would refuse to put on an npm command line, is unknown for the same reason.
|
|
64
142
|
|
|
65
143
|
## What it does, in order
|
|
66
144
|
|
|
@@ -69,7 +147,7 @@ The ordering is the safety contract, not a formality. `planSteps()` in
|
|
|
69
147
|
by `test/unit/install-internal-minions.test.js`.
|
|
70
148
|
|
|
71
149
|
1. **`acquire-token`** — `az account get-access-token --resource 499b84ac-1321-427f-aa17-267ca6975798`
|
|
72
|
-
(the same ADO resource id `engine/ado
|
|
150
|
+
(the same ADO resource id `engine/ado/token.js` uses).
|
|
73
151
|
2. **`validate-feed`** — `npm view <package>@<spec> version` against the feed, and
|
|
74
152
|
resolve `latest` to a concrete version. **A feed that is unreachable, or a
|
|
75
153
|
version that does not exist, fails here — before anything is removed.**
|
|
@@ -78,26 +156,95 @@ by `test/unit/install-internal-minions.test.js`.
|
|
|
78
156
|
safe:** the artifact is on local disk before the public package is removed, so
|
|
79
157
|
a feed, network, or auth failure during the global install is recoverable
|
|
80
158
|
offline. Skipped only when no install will run (see step 6).
|
|
81
|
-
4. **`
|
|
82
|
-
|
|
83
|
-
|
|
159
|
+
4. **`quiesce-services`** — stops any engine/dashboard running against the
|
|
160
|
+
**pinned** runtime root before anything is backed up, uninstalled, or
|
|
161
|
+
installed. Running services are detected from the pid files the runtime
|
|
162
|
+
already writes plus `engine/control.json`; they are stopped through the
|
|
163
|
+
installed CLI (see *Which stop verb is issued* below), and the run then polls
|
|
164
|
+
until the database handles are actually released. Release requires **both**
|
|
165
|
+
signals: the processes are dead *and* `engine/state.db-shm` is absent or
|
|
166
|
+
empty — a live shared-memory index means a connection still holds the WAL. If
|
|
167
|
+
the handles are not released within the bounded timeout the run **fails
|
|
168
|
+
closed**, before any uninstall or package mutation, and prints which stop path
|
|
169
|
+
was taken, the exact argv it issued, and the exact PIDs still holding the
|
|
170
|
+
database. Whether services were actually stopped is recorded so a rollback can
|
|
171
|
+
restart them. Skipped on a machine with no existing runtime.
|
|
172
|
+
|
|
173
|
+
When the run does fail closed here, end the holders it names yourself — the
|
|
174
|
+
refusal prints each surviving process by name and PID, and the dashboard is
|
|
175
|
+
the usual one — then re-run the installer.
|
|
176
|
+
|
|
177
|
+
### Which stop verb is issued
|
|
178
|
+
|
|
179
|
+
The installer prefers `minions stop --all --wait`, and falls back to the bare
|
|
180
|
+
`minions stop` for a CLI that does not have the whole-stack verb.
|
|
181
|
+
|
|
182
|
+
A bare `minions stop` is **engine-only** by contract: it is delegated to
|
|
183
|
+
`engine.js stop`, which writes stop intent and returns, so it asks only the
|
|
184
|
+
engine to stand down. The dashboard and the supervisor hold `engine/state.db`
|
|
185
|
+
independently, so on a healthy stack the `-shm` gate above could never go
|
|
186
|
+
green after a "successful" stop and every migration was refused with the
|
|
187
|
+
engine, dashboard, and supervisor PIDs all still alive. `stop --all --wait`
|
|
188
|
+
tears the whole stack down in order and blocks until the handles are
|
|
189
|
+
released — which is why this step polls for the release instead of trusting
|
|
190
|
+
the stop.
|
|
191
|
+
|
|
192
|
+
During a public → internal migration the resolved CLI is frequently the
|
|
193
|
+
**older public package**, which predates that verb, so support is detected by
|
|
194
|
+
running `minions help` against the resolved CLI and reading whether its own
|
|
195
|
+
usage advertises `stop --all` and `--wait`. The probe is **behavioral, not a
|
|
196
|
+
version comparison** — the internal feed and the public registry version
|
|
197
|
+
independently, so there is no version ordering to compare across them, and the
|
|
198
|
+
cost of a wrong guess is an unknown flag passed to a live teardown command.
|
|
199
|
+
`help` is used rather than `stop --help` because `stop` is in the CLI's engine
|
|
200
|
+
delegation set: an older CLI would forward `stop --help` to `engine.js stop`
|
|
201
|
+
and actually stop the engine as a side effect of being asked a question.
|
|
202
|
+
|
|
203
|
+
An unreadable, empty, or unrecognized probe answer **falls back** to the
|
|
204
|
+
legacy `minions stop`. Either way the run then polls for the `-shm` release
|
|
205
|
+
itself — the CLI's own verdict is never trusted — so the fail-closed gate is
|
|
206
|
+
identical on both paths. There is no `--force` skip for it, and a stale
|
|
207
|
+
non-empty `-shm` is never accepted.
|
|
208
|
+
5. **`backup-state`** — writes a consistent standalone copy of the SQLite state
|
|
209
|
+
(`engine/persistence/state-operations.js#backupState`: a best-effort
|
|
210
|
+
`PRAGMA wal_checkpoint(PASSIVE)` followed by an authoritative `VACUUM INTO`),
|
|
211
|
+
then copies `config.json`, `routing.md`, `pinned.md`, parks a
|
|
84
212
|
copy of the downloaded tarball beside the backup, and writes a `manifest.json`
|
|
85
|
-
describing the from/to packages, the artifact,
|
|
213
|
+
describing the from/to packages, the artifact, the preserved paths, the
|
|
214
|
+
pinned runtime root **and how it was resolved**, whether services were
|
|
215
|
+
stopped, the pre-migration `summarizeState()` census, and the list of
|
|
216
|
+
retained artifacts.
|
|
86
217
|
Skipped on a machine with no existing runtime.
|
|
87
|
-
The
|
|
218
|
+
The checkpoint is deliberately `PASSIVE` and non-fatal: an exclusive
|
|
219
|
+
`TRUNCATE`/`RESTART` checkpoint blocks on any other reader, so with the engine
|
|
220
|
+
or dashboard connected it stalls on the busy timeout or raises `SQLITE_BUSY`
|
|
221
|
+
and would abort the backup. `VACUUM INTO` reads a snapshot that already
|
|
222
|
+
includes committed WAL frames, so it is the authoritative step and the only
|
|
223
|
+
one allowed to fail the backup. `backupState` reports
|
|
224
|
+
`{ ok, path, bytes, checkpointed, walBytesAtStart }` so callers can see
|
|
225
|
+
whether quiescence was actually achieved. The `VACUUM INTO` snapshot is the
|
|
226
|
+
authoritative backup — a bare byte-copy of a live `state.db` alone loses
|
|
227
|
+
committed-but-uncheckpointed transactions. Because the database is quiesced
|
|
228
|
+
by the previous step, the run **also** retains the ORIGINAL
|
|
229
|
+
`engine/state.db`, `engine/state.db-wal`, and `engine/state.db-shm`
|
|
230
|
+
byte-for-byte under `<backup-dir>/original/`, beside the snapshot. Those
|
|
231
|
+
bytes are what the state-restoring rollback puts back, and **the retained
|
|
232
|
+
originals — and everything else in the backup directory — are never deleted
|
|
233
|
+
by this installer, under any outcome.**
|
|
234
|
+
The backup runs against the **runtime's own** `engine/persistence/state-operations.js`,
|
|
88
235
|
which `minions init` copies into the runtime root and which is therefore always
|
|
89
236
|
present and version-matched to that runtime's `engine/state.db`. It does not
|
|
90
237
|
depend on a globally installed CLI: `minions init` deliberately excludes `bin/`
|
|
91
238
|
from the runtime-root copy, and the published public package predates the
|
|
92
239
|
`minions state` command. An installed CLI's `minions state backup` is kept only
|
|
93
240
|
as a fallback for runtime roots that predate the SQL store layout.
|
|
94
|
-
|
|
241
|
+
6. **`uninstall-public`** — removes an existing global `@yemi33/minions` so the two
|
|
95
242
|
packages never race for the same `minions` bin shim. **Gated:** it runs only
|
|
96
243
|
once `assessCutoverReadiness()` confirms the internal artifact is downloaded
|
|
97
244
|
(or already installed at the target version) *and* a state backup exists
|
|
98
245
|
whenever there was a runtime to back up. Skipped with `--keep-public`, or when
|
|
99
246
|
no public install is present.
|
|
100
|
-
|
|
247
|
+
7. **`repair-shims`** — clears **orphaned** `minions` shims under `npm prefix -g`.
|
|
101
248
|
`npm uninstall -g` has just removed the shims it still owned, so anything left
|
|
102
249
|
under the prefix that dispatches into `@yemi33/minions` or
|
|
103
250
|
`@opg-microsoft/minions` with no usable package behind it is a leftover from a
|
|
@@ -115,7 +262,7 @@ by `test/unit/install-internal-minions.test.js`.
|
|
|
115
262
|
directory entry as absent while npm still aborts on it. Each deletion is
|
|
116
263
|
re-probed afterwards, so a delete that quietly no-ops is reported as a
|
|
117
264
|
failure with its path rather than as a cleared shim.
|
|
118
|
-
|
|
265
|
+
8. **`install-internal`** — `npm install -g <package>@<resolved-version>` against the
|
|
119
266
|
feed. **If that fails, the script installs the already-downloaded tarball**
|
|
120
267
|
(`npm install -g <backup-dir>/<package>.tgz` — no registry, no token, so it
|
|
121
268
|
still works when the feed is exactly what failed) rather than leaving the
|
|
@@ -125,9 +272,9 @@ by `test/unit/install-internal-minions.test.js`.
|
|
|
125
272
|
`uninstall-public` is planned. `npm uninstall -g` takes the shim with the
|
|
126
273
|
package that owns it, so skipping the install alongside an uninstall would
|
|
127
274
|
remove the command with nothing to restore it.
|
|
128
|
-
|
|
275
|
+
9. **`verify-install`** — re-reads the installed `package.json` from disk and fails
|
|
129
276
|
loudly if npm did not actually land the resolved version.
|
|
130
|
-
|
|
277
|
+
10. **`verify-shim`** — resolves the global npm prefix and proves the `minions`
|
|
131
278
|
command itself dispatches into the internal package (`minions.cmd` /
|
|
132
279
|
`minions.ps1` / the sh shim on Windows, the `<prefix>/bin/minions` symlink
|
|
133
280
|
elsewhere). Owning the package directory is not the same as owning the
|
|
@@ -136,14 +283,52 @@ by `test/unit/install-internal-minions.test.js`.
|
|
|
136
283
|
`@yemi33/minions` is a hard failure with the repair commands printed, and so
|
|
137
284
|
is a shim whose link target no longer exists — naming the right package is
|
|
138
285
|
not the same as being able to run it.
|
|
139
|
-
|
|
286
|
+
11. **`sync-init`** — `minions init --force --skip-start`, the supported runtime
|
|
140
287
|
synchronization. It overwrites `.js`/`.html` runtime files and adds files the
|
|
141
288
|
new version requires. `--force` would otherwise also rewrite the shipped
|
|
142
289
|
`routing.md` and `knowledge/agents/*.md` with package defaults, so the
|
|
143
290
|
installer snapshots those before the sync and puts them back after it.
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
291
|
+
12. **`verify-continuity`** — the last gate before `cleanup`, and it runs while
|
|
292
|
+
the services are still quiesced, **before** `restart`. The preserved-path
|
|
293
|
+
check is presence-only, so an **emptied** `engine/state.db` passes it; this
|
|
294
|
+
step instead re-runs the runtime's own `summarizeState()` against the pinned
|
|
295
|
+
root, out-of-process, and feeds the pre- and post-migration censuses to its
|
|
296
|
+
`compareStateSummaries`. Running it before the restart is deliberate: a
|
|
297
|
+
census taken against a live engine races it, and `getDb()` applies pending
|
|
298
|
+
migrations on open (`engine/db/index.js`), so a quiesced pre-restart census
|
|
299
|
+
still exercises the migrations deterministically. It also bounds the blast
|
|
300
|
+
radius of the failure action — the state-restoring rollback overwrites
|
|
301
|
+
`engine/state.db{,-wal,-shm}` with the retained pre-migration bytes, which
|
|
302
|
+
after a restart would destroy every write the restarted engine and dashboard
|
|
303
|
+
had already made, including the migrations that had just succeeded.
|
|
304
|
+
|
|
305
|
+
The gate is an explicit **allowlist** of durable tables
|
|
306
|
+
(`CONTINUITY_DURABLE_TABLES`: work items, pull requests, plans, PRDs and
|
|
307
|
+
their items/verify PRs, memory records, inbox entries, QA runs and
|
|
308
|
+
sessions). Everything else is passed to `compareStateSummaries` as
|
|
309
|
+
`ignoreTables`, because most of the SQL state legitimately shrinks across a
|
|
310
|
+
cutover: `cc_sessions`/`doc_sessions` are invalidated when the
|
|
311
|
+
`prompts/cc-system.md` hash changes — which `sync-init` ships by definition —
|
|
312
|
+
`pending_rebases` is rewritten wholesale every tick, `worktree_pool`,
|
|
313
|
+
`managed_processes`, `schedule_runs`, `metrics` and friends are runtime
|
|
314
|
+
bookkeeping, `pr_mirror_hashes` is dropped outright by migration 018, and
|
|
315
|
+
`logs`/`events`/`dispatches`/`cooldowns` are capped, consumed, or expire. A
|
|
316
|
+
denylist of volatile tables fails open on every table nobody remembered to
|
|
317
|
+
enumerate; an allowlist fails closed. A durable table may declare
|
|
318
|
+
`repairedByMigration`, the schema version of a shipped repair migration that
|
|
319
|
+
deletes rows from it by design (PRD tables and migration 024) — the gate is
|
|
320
|
+
lifted for that table only on a run that actually crosses that version.
|
|
321
|
+
|
|
322
|
+
Any row-count regression, missing table, or non-empty → empty transition in a
|
|
323
|
+
gated table is a **hard failure** that triggers the state-restoring rollback
|
|
324
|
+
below. A census that cannot be *taken* is warned about loudly but is not
|
|
325
|
+
treated as proof of loss, so a healthy runtime is never rolled backward on
|
|
326
|
+
missing evidence.
|
|
327
|
+
13. **`restart`** — `minions restart`, which is health-verified
|
|
328
|
+
(`engine/recovery/restart-health.js`: PID + HTTP probe). Skipped with `--no-restart`.
|
|
329
|
+
It is the final action of the run, so the machine is only brought back up on
|
|
330
|
+
state `verify-continuity` already proved survived.
|
|
331
|
+
14. **`cleanup`** — always runs, on success and on every failure path. The
|
|
147
332
|
temporary npm config always goes; the downloaded artifact is retained (and its
|
|
148
333
|
path printed) when the run ended with the machine still needing it.
|
|
149
334
|
|
|
@@ -155,8 +340,35 @@ cannot be honoured by the install and ignored by the probe.
|
|
|
155
340
|
|
|
156
341
|
After `sync-init` the script re-checks every runtime path that existed
|
|
157
342
|
beforehand (`config.json`, `engine/state.db`, `notes/`, `notes.md`, `plans/`,
|
|
158
|
-
`knowledge/`, `projects/`, `pinned.md`
|
|
159
|
-
|
|
343
|
+
`knowledge/`, `projects/`, `pinned.md`, `pipelines/`, `prompts/`, `playbooks/`,
|
|
344
|
+
`agents/`). A path that existed before and is missing after is a hard failure
|
|
345
|
+
pointing at the backup, not a silent data loss. That check is presence-only by
|
|
346
|
+
construction, so `verify-continuity` backs it with a row-level census; the
|
|
347
|
+
artifacts that live purely in SQL (schedules, pipelines runs, watches, meetings,
|
|
348
|
+
QA state) are covered by the census rather than by the path list.
|
|
349
|
+
|
|
350
|
+
### State-restoring rollback
|
|
351
|
+
|
|
352
|
+
`rollbackPackageIfNeeded()` is package-scoped and deliberately never touches
|
|
353
|
+
state. When `verify-continuity` proves state was **lost**, a separate
|
|
354
|
+
state-restoring rollback runs — it is only ever reached once the retained
|
|
355
|
+
original bytes are known to be strictly better than what is on disk. It:
|
|
356
|
+
|
|
357
|
+
1. quiesces services again — through the same probed stop path and the same
|
|
358
|
+
`-shm` gate as `quiesce-services`, aborting without restoring anything if the
|
|
359
|
+
database is still held (so the backup stays intact and nothing is written into
|
|
360
|
+
a live database), and reporting the stop path and holding PIDs the same way,
|
|
361
|
+
2. restores `engine/state.db`, `engine/state.db-wal`, and `engine/state.db-shm`
|
|
362
|
+
from `<backup-dir>/original/`,
|
|
363
|
+
3. restores `config.json`, `routing.md`, and `pinned.md` from the backup, and
|
|
364
|
+
restores the reseedable snapshot through the **same** `restoreReseededFiles`
|
|
365
|
+
copier the normal `sync-init` repair uses,
|
|
366
|
+
4. reinstalls the previous package, restarts, and **re-verifies** the census
|
|
367
|
+
against the pre-migration one,
|
|
368
|
+
5. reports precisely what was restored, removed, or failed.
|
|
369
|
+
|
|
370
|
+
Every step re-copies the same retained bytes, so a re-run converges rather than
|
|
371
|
+
compounding: the rollback is idempotent.
|
|
160
372
|
|
|
161
373
|
## What this is not
|
|
162
374
|
|
|
@@ -173,7 +385,7 @@ and a re-run:
|
|
|
173
385
|
|
|
174
386
|
| State | Preserved how |
|
|
175
387
|
|---|---|
|
|
176
|
-
| `engine/state.db` — work items, dispatches, PR records, schedules, pipelines, watches, meetings, PRDs, QA state, small state | Never replaced.
|
|
388
|
+
| `engine/state.db` — work items, dispatches, PR records, schedules, pipelines, watches, meetings, PRDs, QA state, small state | Never replaced. Services are quiesced first, then the state is checkpointed into the backup directory (`PRAGMA wal_checkpoint(PASSIVE)` + `VACUUM INTO`) and the original `state.db`/`-wal`/`-shm` bytes are retained under `<backup-dir>/original/` before the package changes; the **live** database stays in place and the new version runs its own idempotent startup migrations against it. A row-level census taken before and after proves nothing was lost, and restores from the retained originals if it was. |
|
|
177
389
|
| `config.json` | `minions init` never overwrites it (`neverOverwrite` in `bin/minions.js`), and it is copied into the backup directory as well. |
|
|
178
390
|
| `routing.md`, `knowledge/agents/*.md` | Shipped by the package, so `init --force` *would* rewrite them. Snapshotted before `sync-init` and restored byte-for-byte after it. |
|
|
179
391
|
| `notes.md`, `notes/`, `pinned.md`, `plans/`, `prd/`, `projects/`, `agents/` | Not shipped by the package, so the sync never touches them. Existence is re-verified after the sync. |
|
|
@@ -206,7 +418,7 @@ it does **not** cover rewriting the files underneath a live dispatch.
|
|
|
206
418
|
|
|
207
419
|
So the script counts live agent PID files under `<runtime root>/engine/tmp/`
|
|
208
420
|
(both the per-dispatch directory layout and the legacy flat layout, matching
|
|
209
|
-
`engine/shared.js#forEachPidFile`) and **defers with exit code 3** when any are
|
|
421
|
+
`engine/core/shared.js#forEachPidFile`) and **defers with exit code 3** when any are
|
|
210
422
|
alive. Stale PID files from a crashed run do not block anything — each PID is
|
|
211
423
|
liveness-checked.
|
|
212
424
|
|
|
@@ -236,31 +448,118 @@ installed: it resolves the active package name from the installed manifest and
|
|
|
236
448
|
reinstalls *that* package, so an internal install upgrades itself instead of
|
|
237
449
|
pulling in the public one.
|
|
238
450
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
451
|
+
### The runtime root is the channel authority
|
|
452
|
+
|
|
453
|
+
The manifest at `PKG_ROOT` only answers *which package an install would pull* —
|
|
454
|
+
it is **not** proof of which channel the runtime is on. It resolves the public
|
|
455
|
+
`@yemi33/minions` both from an opg repo checkout (whose own `package.json`
|
|
456
|
+
carries that name) and from a leftover public global shim standing in front of an
|
|
457
|
+
internal runtime. Either way an unguarded update would drop a stale public build
|
|
458
|
+
on top of a newer internal runtime.
|
|
459
|
+
|
|
460
|
+
So the **runtime root** decides. `minions init` records the installing
|
|
461
|
+
distribution in `<runtime root>/.minions-package`
|
|
462
|
+
(`{ name, version, installedAt }`), and `minions update` gates on it via
|
|
463
|
+
`shared.resolveUpdateChannel({ pkgRoot, runtimeRoot })`
|
|
464
|
+
(`engine/core/shared.js`):
|
|
465
|
+
|
|
466
|
+
| Runtime marker | Update would install | Behavior |
|
|
467
|
+
|---|---|---|
|
|
468
|
+
| `@opg-microsoft/minions` | `@opg-microsoft/minions` | Proceeds (in-channel upgrade) |
|
|
469
|
+
| `@yemi33/minions` | `@yemi33/minions` | Proceeds (in-channel upgrade) |
|
|
470
|
+
| internal (any non-public scope) | `@yemi33/minions` | **REFUSED before any npm call**, exit 1 |
|
|
471
|
+
| `@yemi33/minions` | internal | Proceeds, warns (legitimate cutover) |
|
|
472
|
+
| *(no marker — legacy root)* | anything | Proceeds, warns naming both channels |
|
|
473
|
+
|
|
474
|
+
The refusal never attempts a public downgrade and never reaches the registry. It
|
|
475
|
+
prints the supported remediation — this installer, with the runtime root pinned:
|
|
476
|
+
|
|
477
|
+
```
|
|
478
|
+
scripts\install-internal-minions.ps1 --runtime-root "<runtime root>" --package @opg-microsoft/minions
|
|
479
|
+
./scripts/install-internal-minions.sh --runtime-root "<runtime root>" --package @opg-microsoft/minions
|
|
480
|
+
node bin/install-internal-minions.js --runtime-root "<runtime root>" --package @opg-microsoft/minions
|
|
481
|
+
```
|
|
482
|
+
|
|
483
|
+
There is deliberately **no override flag** for a cross-channel public install: a
|
|
484
|
+
public build is a different distribution of the same `minions` bin, not an older
|
|
485
|
+
version of the internal one. Re-run this installer instead.
|
|
486
|
+
|
|
487
|
+
### Downgrade guard
|
|
488
|
+
|
|
489
|
+
Within a single channel, `minions update` also refuses a target version that is
|
|
490
|
+
semver-lower than the installed one, because `npm view` can resolve *backwards*
|
|
491
|
+
off a stale local packument — the install then succeeds and the post-install
|
|
492
|
+
version-advance check still passes, while the runtime silently moves to an older
|
|
493
|
+
build. The comparison is numeric (`1.0.9` is not newer than `1.0.76`).
|
|
494
|
+
|
|
495
|
+
```
|
|
496
|
+
minions update # refuses a lower target version
|
|
497
|
+
minions update --allow-downgrade # installs it anyway
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
The refusal points at `npm cache clean --force`, which is the usual fix.
|
|
501
|
+
|
|
502
|
+
### Registry configuration
|
|
503
|
+
|
|
504
|
+
On the **internal channel**, `minions update` resolves and installs from this
|
|
505
|
+
feed itself — it does **not** rely on your own npm configuration, and it leaves
|
|
506
|
+
nothing persistent behind. When the installed package is served by a private
|
|
507
|
+
feed (`bin/install-internal-minions.js#resolveInternalFeed`; today
|
|
508
|
+
`@opg-microsoft/minions` → the ISS `ProjectFeed-ISS` base registry), the update:
|
|
509
|
+
|
|
510
|
+
1. acquires a **short-lived** Azure DevOps token through your existing Azure CLI
|
|
511
|
+
login (`az account get-access-token`) — no PAT, never in argv, logs, or errors;
|
|
512
|
+
2. stages it in a **0600 temporary npm userconfig** in the OS temp dir, which is
|
|
513
|
+
deleted on success and on every failure path (including a non-zero exit);
|
|
514
|
+
3. runs `npm view` / `npm install -g` against the feed with the scoped registry
|
|
515
|
+
**pinned on the command line** (`--@opg-microsoft:registry=<feed>`).
|
|
516
|
+
|
|
517
|
+
Step 3 is what makes the route deterministic. npm resolves a *scoped* package
|
|
518
|
+
through `@scope:registry`, and `--registry` only sets the *default* registry — so
|
|
519
|
+
an ambient `@opg-microsoft:registry=<public proxy>` line silently redirected the
|
|
520
|
+
update and npm answered `E404` for a package that exists in the feed. npm's
|
|
521
|
+
precedence is `cli > env > ./.npmrc > --userconfig > global`, so a `.npmrc` in
|
|
522
|
+
your current directory also outranks the temporary userconfig; only the
|
|
523
|
+
command-line pin is authoritative. Feed failures now report the feed that was
|
|
524
|
+
queried plus the two real causes (Azure CLI sign-in, or Azure Artifacts read
|
|
525
|
+
permission / a version that is not published) instead of a public-registry 404.
|
|
526
|
+
|
|
527
|
+
`--registry <url>` overrides the feed for one run and is accepted only on an
|
|
528
|
+
internal channel. The **public** channel is untouched: `@yemi33/minions` still
|
|
529
|
+
updates through plain `npm view` / `npm install -g`
|
|
530
|
+
(`engine/core/shared.js#buildNpmViewVersionCommand` / `#buildNpmGlobalInstallCommand`)
|
|
531
|
+
against whatever registry your npm config points at.
|
|
532
|
+
|
|
533
|
+
```
|
|
534
|
+
minions update # internal: feed + Azure CLI auth, public: plain npm
|
|
535
|
+
minions update --registry <url> # internal only: override the feed for this run
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
Re-running this script remains the **channel bootstrap** — what moves a machine
|
|
539
|
+
onto the internal ProjectFeed-ISS channel (including replacing a public
|
|
540
|
+
`@yemi33/minions` install), what installs the internal package on a machine that
|
|
541
|
+
has no Minions at all, and what repairs a half-finished cutover. It is
|
|
542
|
+
idempotent, so it always works as a recovery path; routine in-channel upgrades no
|
|
543
|
+
longer need it.
|
|
253
544
|
|
|
254
545
|
## Troubleshooting
|
|
255
546
|
|
|
256
547
|
| Symptom | Cause | Fix |
|
|
257
548
|
|---|---|---|
|
|
549
|
+
| `REFUSED: this would install the public package over an internal runtime` | `minions update` resolved `@yemi33/minions` (repo checkout, or a leftover public global shim) while `<runtime root>/.minions-package` says the runtime is internal | Nothing was installed and the registry was never contacted. Re-run this installer with the printed `--runtime-root "<path>" --package <internal pkg>`. |
|
|
550
|
+
| `REFUSED: … would downgrade the installed …` | `npm view` resolved an older version off a stale local packument | `npm cache clean --force`, then `minions update`. To install the older version deliberately: `minions update --allow-downgrade`. |
|
|
551
|
+
| `Runtime channel is unknown (no .minions-package marker)` | Legacy runtime root that predates the channel marker | Warning only — the update proceeds as before. Run `minions init` to record the channel. |
|
|
258
552
|
| `could not acquire an Azure DevOps token` | Not signed in, or no subscription selected | `az login`, then `az account set --subscription <id>` |
|
|
553
|
+
| `Could not acquire an Azure DevOps token for the internal feed` (from `minions update`) | Same cause, raised by the in-place updater before any npm call | `az login`, then re-run `minions update`. Nothing was installed and no credential was written. |
|
|
554
|
+
| `Could not read <pkg>@latest from the internal feed` (from `minions update`) | No Azure Artifacts read access to `ProjectFeed-ISS`, or that version is not published to the feed | Request read on `ProjectFeed-ISS`. This replaces the old misleading public-registry `E404`: the update pins the feed on the command line, so it is never the ambient registry answering. |
|
|
555
|
+
| `--registry applies only to an internal channel install` | `minions update --registry <url>` on a public install | Drop the flag; the public channel updates through your own npm registry. |
|
|
259
556
|
| `could not read <pkg>@<spec> from the feed` | No feed read permission, or the version does not exist | Request Azure Artifacts read on `ProjectFeed-ISS`; check `--version`. Nothing was uninstalled. |
|
|
260
557
|
| `REFUSED: N agent process(es) are still running` | Active dispatches | Wait for idle, or re-run with `--force` |
|
|
558
|
+
| `REFUSED: the runtime did not release engine/state.db` | A daemon still holds the WAL — usually the dashboard, which `minions stop` leaves running by design | Nothing was uninstalled or modified. Run `minions stop`, then end whatever the error still names — it prints every surviving holder by name and PID — and re-run. |
|
|
559
|
+
| `REFUSED: N candidate runtime roots carry a non-empty engine/state.db` | More than one directory the engine could boot from holds real state — typically `~/.minions` plus a Minions source checkout you launched the installer from | Nothing was downloaded, uninstalled, or modified. The message names every candidate and prints the exact `--runtime-root <path>` command for each; re-run pinned to the one you mean. See [Runtime root](#runtime-root). |
|
|
261
560
|
| `expected <pkg>@<v> on disk, found …` | Stale npm metadata cache | `npm cache clean --force`, then re-run |
|
|
262
561
|
| `refusing to uninstall @yemi33/minions — …` | The artifact or the backup is missing | Nothing was removed. Re-run; the message names which precondition failed. |
|
|
263
|
-
| `no way to back up the existing runtime state was found` | The runtime root has neither `engine/state-operations.js` nor a resolvable CLI | Nothing was uninstalled. The error lists every path that was probed; run `minions init --force` against the existing install to restore its engine files, then re-run. |
|
|
562
|
+
| `no way to back up the existing runtime state was found` | The runtime root has neither `engine/persistence/state-operations.js` nor a resolvable CLI | Nothing was uninstalled. The error lists every path that was probed; run `minions init --force` against the existing install to restore its engine files, then re-run. |
|
|
264
563
|
| `the minions shim … still points at @yemi33/minions` | A previous half-finished cutover left the public shim in place | `npm uninstall -g @yemi33/minions`, then re-run. The install commands are printed with the error. |
|
|
265
564
|
| `npm ERR! EEXIST … <prefix>\minions` on `npm install -g` | **Orphaned shim** — a prior uninstall or interrupted migration removed the package directory but left the `minions` command behind, so nothing reported the old package as installed and npm refused to overwrite the leftover. | Handled automatically by `repair-shims`: just re-run the installer. Details below. |
|
|
266
565
|
| `REFUSED: … is named minions but was not generated by npm for …` | A file called `minions` under `npm prefix -g` could not be attributed to `@yemi33/minions` or `@opg-microsoft/minions` | The installer never deletes a file it cannot prove it owns. Inspect the named path, move or rename it (or remove it yourself if it is a leftover), then re-run. Nothing was modified. |
|
|
@@ -6,7 +6,7 @@ distinct events sharing a naming pattern, before any fix is proposed.
|
|
|
6
6
|
|
|
7
7
|
## Background
|
|
8
8
|
|
|
9
|
-
`engine/consolidation.js:1156-1290` content-hashes and dedups
|
|
9
|
+
`engine/memory/consolidation.js:1156-1290` content-hashes and dedups
|
|
10
10
|
engine-authored SYSTEM ALERTS (via `shared.isEngineSystemAlert` +
|
|
11
11
|
`alertHash` frontmatter, see `_alertHashExists`) at **write time** —
|
|
12
12
|
recurring identical alerts never get a `-2`/`-3` full-body copy. Agent-authored
|
|
@@ -16,7 +16,7 @@ so any note that gets classified into `knowledge/<category>/` twice under the
|
|
|
16
16
|
same computed filename (`${date}-${agent}-${titleSlug}.md`) always produces a
|
|
17
17
|
full-body `-2`/`-3` copy at consolidation time.
|
|
18
18
|
|
|
19
|
-
Separately, `engine/kb-sweep.js` Pass 1 (`_hashDedup`, `kb-sweep.js:34-37,
|
|
19
|
+
Separately, `engine/memory/kb-sweep.js` Pass 1 (`_hashDedup`, `kb-sweep.js:34-37,
|
|
20
20
|
155-176`) content-hashes **every** KB entry regardless of category and
|
|
21
21
|
archives byte-identical duplicates to `knowledge/_swept/`, keeping the most
|
|
22
22
|
recent. This pass is category-agnostic and *would* catch true agent-authored
|
|
@@ -98,7 +98,7 @@ last-completed-sweep timestamp).
|
|
|
98
98
|
inbox note that hashes/formats similarly — or, per the `-2`/`-3`
|
|
99
99
|
evidence above, the identical inbox note re-processed), each pass
|
|
100
100
|
writes a fresh, full-body `-N` copy via `shared.uniquePath`.
|
|
101
|
-
2. `engine/kb-sweep.js` Pass 1 (`_hashDedup`) *does* eventually catch and
|
|
101
|
+
2. `engine/memory/kb-sweep.js` Pass 1 (`_hashDedup`) *does* eventually catch and
|
|
102
102
|
archive these byte-identical copies (category-agnostic, keeps most
|
|
103
103
|
recent) — but only on its own schedule (`AUTO_SWEEP_INTERVAL_MS = 4h`
|
|
104
104
|
default, `kb-sweep.js:26`) or on manual trigger, not at consolidation
|
|
@@ -128,9 +128,9 @@ similarity, since many genuinely distinct events share a title stem.
|
|
|
128
128
|
|
|
129
129
|
## Sources
|
|
130
130
|
|
|
131
|
-
- `engine/consolidation.js:1156-1300` (`isEngineSystemAlert`/`alertHash`
|
|
131
|
+
- `engine/memory/consolidation.js:1156-1300` (`isEngineSystemAlert`/`alertHash`
|
|
132
132
|
dedup, `classifyToKnowledgeBase`)
|
|
133
|
-
- `engine/kb-sweep.js:20-37,155-176` (`_hashEntry`, `_hashDedup`, sweep
|
|
133
|
+
- `engine/memory/kb-sweep.js:20-37,155-176` (`_hashEntry`, `_hashDedup`, sweep
|
|
134
134
|
interval constant)
|
|
135
135
|
- `engine/kb-sweep-state.json` (`completedAtIso: 2026-07-07T21:49:00.186Z`)
|
|
136
136
|
- `knowledge/reviews/2026-07-07-ripley-review-github-opg-microsoft-minions-740-fix-contam{,-2,-3}.md`
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
- `source_plan` is a plan Markdown basename.
|
|
10
10
|
- Plan archive responses retain their documented compatibility fields.
|
|
11
|
-
- PRD archive and cascade updates use `engine/prd-store.js` transactions.
|
|
11
|
+
- PRD archive and cascade updates use `engine/planning/prd-store.js` transactions.
|
|
12
12
|
- Work-item cancellation uses scoped SQL work-item mutations.
|
|
13
13
|
|
|
14
14
|
Use the current `handlePlansArchive` implementation and its behavioral tests as
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
# KB PR #696 – Merge Conflict Resolution in KB-Sweep Documentation
|
|
2
2
|
|
|
3
|
-
PR #696 resolved a merge conflict in `docs/kb-sweep.md:97-103` where both branch and main branches cited stale line numbers to `engine/kb-sweep.js`. Upstream code shifts had invalidated both references. Resolution consolidated the "Pass 1, 1.5, and 2" structure and verified the correct current location of `NORMALIZE_CONCURRENCY = 5` at `engine/kb-sweep.js:30`.
|
|
3
|
+
PR #696 resolved a merge conflict in `docs/kb-sweep.md:97-103` where both branch and main branches cited stale line numbers to `engine/memory/kb-sweep.js`. Upstream code shifts had invalidated both references. Resolution consolidated the "Pass 1, 1.5, and 2" structure and verified the correct current location of `NORMALIZE_CONCURRENCY = 5` at `engine/memory/kb-sweep.js:30`.
|
|
4
4
|
|
|
5
5
|
## Key Findings
|
|
6
6
|
|
|
7
7
|
- Merge conflict in `docs/kb-sweep.md:97-103` ("Pass 3 — Per-Entry Rewrite" section) with stale line citations
|
|
8
|
-
- Branch cited `engine/kb-sweep.js:L26`, main cited `L30` with outdated "Pass 1 and 2" wording
|
|
8
|
+
- Branch cited `engine/memory/kb-sweep.js:L26`, main cited `L30` with outdated "Pass 1 and 2" wording
|
|
9
9
|
- Root cause: upstream commits shifted line numbers; neither reference remained valid post-merge
|
|
10
|
-
- Resolved by merging branch's "Pass 1, 1.5, and 2" structure with main's corrected line reference to `engine/kb-sweep.js:30`
|
|
11
|
-
- Verified `NORMALIZE_CONCURRENCY = 5` present at `engine/kb-sweep.js:30` in merged state
|
|
12
|
-
- Syntax validation passed for `engine/shared.js`, `engine/kb-sweep.js`, `engine.js`, `dashboard.js`
|
|
10
|
+
- Resolved by merging branch's "Pass 1, 1.5, and 2" structure with main's corrected line reference to `engine/memory/kb-sweep.js:30`
|
|
11
|
+
- Verified `NORMALIZE_CONCURRENCY = 5` present at `engine/memory/kb-sweep.js:30` in merged state
|
|
12
|
+
- Syntax validation passed for `engine/core/shared.js`, `engine/memory/kb-sweep.js`, `engine.js`, `dashboard.js`
|
|
13
13
|
|
|
14
14
|
## Action Items
|
|
15
15
|
|
|
@@ -20,4 +20,4 @@ PR #696 resolved a merge conflict in `docs/kb-sweep.md:97-103` where both branch
|
|
|
20
20
|
- PR #696: https://github.com/opg-microsoft/minions/pull/696
|
|
21
21
|
- Merge commit: b91cb386
|
|
22
22
|
- Fix comment: https://github.com/opg-microsoft/minions/pull/696#issuecomment-4905945906
|
|
23
|
-
- Correct citation: `engine/kb-sweep.js:30` (`NORMALIZE_CONCURRENCY = 5`)
|
|
23
|
+
- Correct citation: `engine/memory/kb-sweep.js:30` (`NORMALIZE_CONCURRENCY = 5`)
|