@yemi33/minions 0.1.2447 → 0.1.2449
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cli-api-client.js +1 -1
- package/bin/install-internal-minions.js +1382 -44
- package/bin/install-layout.js +150 -0
- package/bin/minions.js +460 -167
- package/dashboard/docs/typography.md +65 -12
- package/dashboard/js/command-center.js +66 -7
- package/dashboard/js/detail-panel.js +36 -0
- package/dashboard/js/memory-panel.js +59 -12
- package/dashboard/js/qa.js +186 -45
- package/dashboard/js/refresh.js +148 -12
- package/dashboard/js/render-dispatch.js +3 -4
- package/dashboard/js/render-inbox.js +2 -2
- package/dashboard/js/render-other.js +3 -3
- package/dashboard/js/render-pipelines.js +14 -0
- package/dashboard/js/render-plans.js +57 -9
- package/dashboard/js/render-prd.js +132 -23
- package/dashboard/js/render-prs.js +195 -166
- package/dashboard/js/render-schedules.js +63 -3
- package/dashboard/js/render-utils.js +3 -3
- package/dashboard/js/render-watches.js +19 -3
- package/dashboard/js/render-work-items.js +238 -30
- package/dashboard/js/settings.js +205 -54
- package/dashboard/js/utils.js +51 -1
- package/dashboard/pages/home.html +1 -1
- package/dashboard/pages/qa.html +1 -16
- package/dashboard/pages/work.html +40 -0
- package/dashboard/shared/cc-limits.js +79 -0
- package/dashboard/shared/pr-filters.js +21 -38
- package/dashboard/shared/project-git-summary.js +1 -1
- package/dashboard/shared/record-filters.js +169 -0
- package/dashboard/shared/watches-source.js +1 -1
- package/dashboard/shared/welcome-popup.js +1 -1
- package/dashboard/shared/wi-filters.js +302 -0
- package/dashboard/slim/body.html +1 -0
- package/dashboard/slim/js/command-send.js +26 -0
- package/dashboard/slim/js/modals-tiles.js +380 -39
- package/dashboard/slim/js/status.js +13 -21
- package/dashboard/slim/layout.html +1 -0
- package/dashboard/slim/panel-bootstrap.js +6 -2
- package/dashboard/slim/styles.css +38 -0
- package/dashboard/styles.css +159 -55
- package/dashboard-build.js +52 -6
- package/dashboard.js +956 -423
- package/docs/README.md +11 -6
- package/docs/api-errors.md +2 -2
- package/docs/architecture-review-2026-07-09.md +1 -1
- package/docs/architecture.excalidraw +2 -2
- package/docs/auto-discovery.md +18 -9
- package/docs/branch-derivation.md +4 -4
- package/docs/capture-demos.js +39 -2
- package/docs/ci-runner-canary.md +123 -0
- package/docs/claude-md-propagation.md +2 -2
- package/docs/cloud-agent-dispatch.md +204 -0
- package/docs/command-center.md +7 -7
- package/docs/completion-reports.md +43 -20
- package/docs/constants.md +10 -3
- package/docs/constellation-bridge.md +134 -6
- package/docs/constellation-style-telemetry.md +4 -4
- package/docs/contracts/capability-protocol.v1.json +165 -0
- package/docs/cooldown-merge-semantics.md +12 -12
- package/docs/copilot-cli-schema.md +7 -7
- package/docs/cross-repo-plans.md +10 -10
- package/docs/dead-code-audit-retractions.md +5 -5
- package/docs/default-branch-ci.md +173 -0
- package/docs/deprecated.json +31 -31
- package/docs/design-inbox-entries-schema.md +3 -3
- package/docs/design-language.md +1051 -0
- package/docs/design-state-storage.md +11 -11
- package/docs/diagnostics-crash-reports.md +9 -9
- package/docs/diagnostics-memory.md +5 -5
- package/docs/documentation-audit-2026-07-09.md +7 -7
- package/docs/engine-restart.md +90 -5
- package/docs/harness-mode.md +1 -1
- package/docs/internal-install.md +338 -39
- package/docs/kb-dedup-duplicate-pair-investigation.md +5 -5
- package/docs/kb-pr3223-cascade-archiving.md +1 -1
- package/docs/kb-pr696-merge-conflict-docs.md +6 -6
- package/docs/kb-sweep.md +35 -35
- package/docs/keep-processes.md +1 -1
- package/docs/live-checkout-mode.md +30 -30
- package/docs/managed-spawn.md +18 -14
- package/docs/named-agents.md +7 -7
- package/docs/plan-lifecycle.md +69 -2
- package/docs/pr-author-identity.md +114 -0
- package/docs/pr-auto-fix-dispatch.md +19 -4
- package/docs/pr-comment-followup.md +6 -6
- package/docs/pr-review-fix-loop.md +59 -10
- package/docs/process-termination.md +40 -0
- package/docs/proposals/repo-pool-for-live-checkout.md +13 -13
- package/docs/qa-runbook-lifecycle.md +367 -17
- package/docs/qa-runbooks.md +3 -3
- package/docs/rfc-completion-json.md +18 -18
- package/docs/runtime-adapters.md +26 -21
- package/docs/security.md +6 -6
- package/docs/self-improvement.md +4 -4
- package/docs/shared-lifecycle-module-map.md +473 -472
- package/docs/skills.md +52 -3
- package/docs/slim-ux/concepts.md +121 -116
- package/docs/specs/agent-configurability.md +18 -18
- package/docs/specs/agent-rename.md +18 -18
- package/docs/team-memory.md +38 -21
- package/docs/timeouts-and-liveness.md +118 -10
- package/docs/tutorials/01-install-and-connect.md +1 -1
- package/docs/watches.md +40 -39
- package/docs/workspace-manifests.md +4 -4
- package/docs/worktree-lifecycle.md +293 -14
- package/engine/README.md +46 -0
- package/engine/{ado-comment.js → ado/comment.js} +8 -8
- package/engine/{ado-git-auth.js → ado/git-auth.js} +4 -4
- package/engine/{ado.js → ado/index.js} +417 -63
- package/engine/{ado-status.js → ado/status.js} +6 -8
- package/engine/{ado-token.js → ado/token.js} +1 -1
- package/engine/{acp-transport.js → agents/acp-transport.js} +62 -22
- package/engine/{agent-worker-pool.js → agents/agent-worker-pool.js} +17 -8
- package/engine/{cc-worker-pool.js → agents/cc-worker-pool.js} +16 -6
- package/engine/{claude-md-context.js → agents/claude-md-context.js} +5 -5
- package/engine/{harness-context.js → agents/harness-context.js} +5 -5
- package/engine/{harness.js → agents/harness.js} +3 -3
- package/engine/{llm.js → agents/llm.js} +18 -14
- package/engine/{model-discovery.js → agents/model-discovery.js} +2 -2
- package/engine/{playbook.js → agents/playbook.js} +155 -22
- package/engine/{pooled-agent-process.js → agents/pooled-agent-process.js} +14 -12
- package/engine/{preflight.js → agents/preflight.js} +29 -10
- package/engine/{spawn-agent.js → agents/spawn-agent.js} +25 -14
- package/engine/{spawn-phase-watchdog.js → agents/spawn-phase-watchdog.js} +16 -7
- package/engine/{steering.js → agents/steering.js} +5 -5
- package/engine/{tools-inventory.js → agents/tools-inventory.js} +2 -2
- package/engine/{agent-api-validation.js → api/agent-api-validation.js} +2 -2
- package/engine/{api-validation.js → api/api-validation.js} +1 -1
- package/engine/api/bridge.js +787 -0
- package/engine/{cc-api-validation.js → api/cc-api-validation.js} +1 -1
- package/engine/api/companion.js +560 -0
- package/engine/{content-api-validation.js → api/content-api-validation.js} +2 -2
- package/engine/{pr-issue-validation.js → api/pr-issue-validation.js} +33 -6
- package/engine/{settings-validation.js → api/settings-validation.js} +32 -4
- package/engine/api-contracts/agent-content.js +4 -4
- package/engine/api-contracts/capability-manifest.js +236 -0
- package/engine/api-contracts/capability-protocol.js +333 -0
- package/engine/api-contracts/cc-ops.js +1 -1
- package/engine/api-contracts/config-runtime.js +5 -0
- package/engine/api-contracts/core.js +28 -1
- package/engine/api-contracts/index.js +100 -0
- package/engine/api-contracts/orchestration.js +18 -5
- package/engine/api-contracts/pull-requests.js +37 -6
- package/engine/api-contracts/qa-process.js +29 -6
- package/engine/api-contracts/work-plan-prd.js +21 -1
- package/engine/cloud/contract.js +212 -0
- package/engine/cloud/index.js +159 -0
- package/engine/{execution-model.js → core/execution-model.js} +1 -1
- package/engine/{features.js → core/features.js} +4 -4
- package/engine/{operator-identity.js → core/operator-identity.js} +1 -1
- package/engine/{queries.js → core/queries.js} +201 -36
- package/engine/{safe-expr.js → core/safe-expr.js} +1 -1
- package/engine/{shared.js → core/shared.js} +1637 -175
- package/engine/{stdio-timestamps.js → core/stdio-timestamps.js} +1 -1
- package/engine/{untrusted-fence.js → core/untrusted-fence.js} +3 -3
- package/engine/db/index.js +11 -2
- package/engine/db/migrations/002-dispatches.js +3 -3
- package/engine/db/migrations/003-work-items.js +1 -1
- package/engine/db/migrations/004-pull-requests.js +1 -1
- package/engine/db/migrations/006-metrics.js +1 -1
- package/engine/db/migrations/007-watches.js +2 -2
- package/engine/db/migrations/008-small-state.js +1 -1
- package/engine/db/migrations/009-qa.js +1 -1
- package/engine/db/migrations/010-pr-links.js +1 -1
- package/engine/db/migrations/011-remaining-state.js +1 -1
- package/engine/db/migrations/012-steering-deliveries.js +2 -2
- package/engine/db/migrations/013-backfill-broken-note-links.js +1 -1
- package/engine/db/migrations/014-pr-fix-target-prefs.js +2 -2
- package/engine/db/migrations/015-plans-prds.js +0 -0
- package/engine/db/migrations/018-sql-only-cutover.js +2 -2
- package/engine/db/migrations/021-archived-work-items.js +1 -1
- package/engine/db/migrations/022-global-cc-session.js +1 -1
- package/engine/db/migrations/023-engine-state.js +1 -1
- package/engine/db/migrations/025-malformed-work-item-phantoms.js +1 -1
- package/engine/db/migrations/027-review-learning-lifecycle.js +1 -1
- package/engine/db/migrations/029-repair-reused-versions.js +20 -0
- package/engine/db/migrations/031-pr-author-identity.js +137 -0
- package/engine/{consolidation.js → memory/consolidation.js} +6 -6
- package/engine/{kb-sweep-runner.js → memory/kb-sweep-runner.js} +2 -2
- package/engine/{kb-sweep.js → memory/kb-sweep.js} +9 -7
- package/engine/{memory-retrieval.js → memory/memory-retrieval.js} +46 -4
- package/engine/{memory-store.js → memory/memory-store.js} +3 -3
- package/engine/{promotion.js → memory/promotion.js} +3 -3
- package/engine/{review-learning-backfill.js → memory/review-learning-backfill.js} +6 -6
- package/engine/{review-learning.js → memory/review-learning.js} +10 -5
- package/engine/{diagnostics-memory.js → observability/diagnostics-memory.js} +1 -1
- package/engine/{logs-store.js → observability/logs-store.js} +5 -5
- package/engine/{metrics-store.js → observability/metrics-store.js} +4 -4
- package/engine/{check-status.js → operations/check-status.js} +3 -3
- package/engine/{cli.js → operations/cli.js} +271 -113
- package/engine/{distribution.js → operations/distribution.js} +5 -6
- package/engine/{cleanup.js → orchestration/cleanup.js} +72 -45
- package/engine/{cooldown.js → orchestration/cooldown.js} +5 -5
- package/engine/{dispatch-events.js → orchestration/dispatch-events.js} +2 -2
- package/engine/{dispatch.js → orchestration/dispatch.js} +129 -36
- package/engine/orchestration/failed-scheduled-cleanup.js +274 -0
- package/engine/{lifecycle.js → orchestration/lifecycle.js} +198 -90
- package/engine/{meeting.js → orchestration/meeting.js} +6 -16
- package/engine/{pipeline.js → orchestration/pipeline.js} +12 -12
- package/engine/{pre-dispatch-eval.js → orchestration/pre-dispatch-eval.js} +10 -9
- package/engine/{routing.js → orchestration/routing.js} +3 -3
- package/engine/{schedule-bootstrap.js → orchestration/schedule-bootstrap.js} +4 -4
- package/engine/{scheduler.js → orchestration/scheduler.js} +38 -8
- package/engine/{timeout.js → orchestration/timeout.js} +158 -109
- package/engine/{db-events.js → persistence/db-events.js} +2 -2
- package/engine/{dispatch-store.js → persistence/dispatch-store.js} +7 -7
- package/engine/{inbox-store.js → persistence/inbox-store.js} +2 -2
- package/engine/{note-link-backfill.js → persistence/note-link-backfill.js} +4 -4
- package/engine/{pr-fix-target-store.js → persistence/pr-fix-target-store.js} +8 -8
- package/engine/{pull-requests-store.js → persistence/pull-requests-store.js} +21 -7
- package/engine/{small-state-store.js → persistence/small-state-store.js} +31 -31
- package/engine/persistence/state-operations.js +350 -0
- package/engine/{steering-store.js → persistence/steering-store.js} +6 -6
- package/engine/{issues.js → planning/issues.js} +2 -2
- package/engine/{plan-prd-validation.js → planning/plan-prd-validation.js} +8 -2
- package/engine/planning/prd-result-sidecar.js +190 -0
- package/engine/{prd-store.js → planning/prd-store.js} +17 -17
- package/engine/{project-discovery.js → planning/project-discovery.js} +5 -5
- package/engine/{projects.js → planning/projects.js} +10 -10
- package/engine/{resolve-area.js → planning/resolve-area.js} +1 -1
- package/engine/{work-item-validation.js → planning/work-item-validation.js} +39 -3
- package/engine/{work-items-store.js → planning/work-items-store.js} +29 -21
- package/engine/{keep-process-sweep.js → processes/keep-process-sweep.js} +57 -17
- package/engine/{managed-spawn-launcher.js → processes/managed-spawn-launcher.js} +3 -3
- package/engine/{managed-spawn.js → processes/managed-spawn.js} +97 -46
- package/engine/{process-utils.js → processes/process-utils.js} +599 -55
- package/engine/{abandoned-pr-reconciliation.js → providers/abandoned-pr-reconciliation.js} +17 -7
- package/engine/{comment-classifier.js → providers/comment-classifier.js} +85 -17
- package/engine/{comment-format.js → providers/comment-format.js} +5 -5
- package/engine/{gh-comment.js → providers/gh-comment.js} +15 -15
- package/engine/{gh-token.js → providers/gh-token.js} +4 -4
- package/engine/{github.js → providers/github.js} +131 -54
- package/engine/{pr-action.js → providers/pr-action.js} +13 -12
- package/engine/{pr-clone-keep.js → providers/pr-clone-keep.js} +7 -7
- package/engine/{pr-devbox.js → providers/pr-devbox.js} +6 -6
- package/engine/{pr-fix-target.js → providers/pr-fix-target.js} +13 -13
- package/engine/{pr-remote-patch.js → providers/pr-remote-patch.js} +4 -4
- package/engine/{pr-resolve.js → providers/pr-resolve.js} +7 -7
- package/engine/{pr-temp-clone.js → providers/pr-temp-clone.js} +5 -5
- package/engine/{pr-track.js → providers/pr-track.js} +11 -13
- package/engine/{shared-branch-pr-reconcile.js → providers/shared-branch-pr-reconcile.js} +4 -4
- package/engine/qa/auto-prd-qa.js +313 -0
- package/engine/{qa-from-prd.js → qa/from-prd.js} +42 -12
- package/engine/qa/prd-session.js +240 -0
- package/engine/{qa-process-validation.js → qa/process-validation.js} +14 -9
- package/engine/{qa-runbooks.js → qa/runbooks.js} +1 -1
- package/engine/{qa-runs.js → qa/runs.js} +286 -15
- package/engine/{qa-sessions.js → qa/sessions.js} +595 -49
- package/engine/qa/visual-journey.js +654 -0
- package/engine/{qa-runners.js → qa-runners/index.js} +7 -7
- package/engine/qa-runners/maestro.js +3 -3
- package/engine/qa-runners/playwright.js +2 -2
- package/engine/{restart-health.js → recovery/restart-health.js} +48 -4
- package/engine/recovery/stop-stack.js +607 -0
- package/engine/{supervisor.js → recovery/supervisor.js} +105 -175
- package/engine/{watchdog.js → recovery/watchdog.js} +136 -13
- package/engine/runtimes/claude.js +14 -12
- package/engine/runtimes/codex.js +8 -6
- package/engine/runtimes/copilot.js +17 -16
- package/engine/{watch-actions.js → watches/actions.js} +13 -13
- package/engine/{watches.js → watches/index.js} +43 -32
- package/engine/{watches-store.js → watches/store.js} +4 -4
- package/engine/{create-pr-worktree.js → worktrees/create-pr.js} +1 -1
- package/engine/{worktree-gc.js → worktrees/gc.js} +70 -22
- package/engine/worktrees/inventory.js +671 -0
- package/engine/{live-checkout.js → worktrees/live-checkout.js} +4 -4
- package/engine/{worktree-pool.js → worktrees/pool.js} +2 -2
- package/engine/{worktree-preflight.js → worktrees/preflight.js} +1 -0
- package/engine/worktrees/quarantine-refs.js +173 -0
- package/engine.js +1137 -208
- package/minions.js +147 -77
- package/package.json +10 -6
- package/playbooks/_pr-description-audit.md +110 -78
- package/playbooks/build-fix-complex.md +2 -0
- package/playbooks/fix.md +16 -12
- package/playbooks/implement-shared.md +2 -0
- package/playbooks/implement.md +19 -20
- package/playbooks/plan-to-prd.md +18 -3
- package/playbooks/qa-session-draft.md +136 -1
- package/playbooks/qa-session-execute.md +80 -2
- package/playbooks/qa-session-setup.md +17 -1
- package/playbooks/qa-validate.md +1 -1
- package/playbooks/setup.md +2 -0
- package/playbooks/shared-rules.md +25 -32
- package/playbooks/templates/followup-dispatch.md +4 -3
- package/playbooks/verify.md +1 -1
- package/prompts/cc-system.md +19 -27
- package/watch-plugins/README.md +92 -0
- package/watch-plugins/ado-author-prs.js +336 -0
- package/watch-plugins/gh-author-prs.js +375 -0
- package/watch-plugins/http.js +474 -0
- package/watch-plugins/teams-channel.js +869 -0
- package/docs/dev-composite-workflow.md +0 -101
- package/docs/pr-screenshots/pr-886/after-single-header.png +0 -0
- package/docs/pr-screenshots/pr-886/before-duplicate-header.png +0 -0
- package/docs/pr-screenshots/pr-895/01-cancellation-reason-detail.png +0 -0
- package/docs/pr-screenshots/pr-899/worker-pool-worktrees-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-899/worker-pool-worktrees-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-901/projects-tab-default.png +0 -0
- package/docs/pr-screenshots/pr-901/projects-tab-fmf-selected.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-AFTER-crop.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-BEFORE-crop.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-916/model-picker-dropdown-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-979/auto-fix-pane-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-979/auto-fix-pane-BEFORE.png +0 -0
- package/docs/pr-screenshots/pr-985/pr-column-em-dash-AFTER.png +0 -0
- package/docs/pr-screenshots/pr-985/pr-column-em-dash-BEFORE.png +0 -0
- package/docs/visual-evidence-ci.md +0 -103
- package/engine/bridge.js +0 -379
- package/engine/quarantine-refs.js +0 -103
- package/engine/state-operations.js +0 -178
- /package/engine/{steering-constraints.js → agents/steering-constraints.js} +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* engine/managed-spawn.js — Item 1 of plan P-7a3b1c92.
|
|
2
|
+
* engine/processes/managed-spawn.js — Item 1 of plan P-7a3b1c92.
|
|
3
3
|
*
|
|
4
4
|
* Schema, validator, sidecar reader, acceptance helper, and playbook hint for
|
|
5
|
-
* the managed-spawn primitive. Mirrors engine/keep-process-sweep.js
|
|
5
|
+
* the managed-spawn primitive. Mirrors engine/processes/keep-process-sweep.js
|
|
6
6
|
* beat-for-beat: an agent writes agents/<id>/managed-spawn.json describing
|
|
7
7
|
* long-running services it wants the engine to spawn + healthcheck on its
|
|
8
8
|
* behalf; this module validates the file, returns a structured acceptance
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
* plan items (P-7a3b1c93+). This module is pure: no spawns, no network, no
|
|
14
14
|
* mutation of shared state.
|
|
15
15
|
*
|
|
16
|
-
* Design template: engine/keep-process-sweep.js. Divergences are justified
|
|
16
|
+
* Design template: engine/processes/keep-process-sweep.js. Divergences are justified
|
|
17
17
|
* inline; symmetry with keep-pids is the convention.
|
|
18
18
|
*/
|
|
19
19
|
|
|
@@ -22,8 +22,8 @@ const path = require('path');
|
|
|
22
22
|
const http = require('http');
|
|
23
23
|
const https = require('https');
|
|
24
24
|
const { spawn, exec } = require('child_process');
|
|
25
|
-
const shared = require('
|
|
26
|
-
const queries = require('
|
|
25
|
+
const shared = require('../core/shared');
|
|
26
|
+
const queries = require('../core/queries');
|
|
27
27
|
const processUtils = require('./process-utils');
|
|
28
28
|
|
|
29
29
|
const { log, ENGINE_DEFAULTS } = shared;
|
|
@@ -801,7 +801,7 @@ function buildManagedSpawnHint(opts) {
|
|
|
801
801
|
'}',
|
|
802
802
|
'```',
|
|
803
803
|
'',
|
|
804
|
-
'Known device-farm tooling to reach for instead of re-deriving a pattern from scratch: `adb` and `emulator` (both on the managed-spawn executable allowlist — device/emulator shell, install, logcat; `emulator -list-avds` discovers configured AVDs before you pick one for the spec), and `maestro` (declarative mobile UI-flow runner already wired in as a built-in QA runner adapter — see `engine/qa-runners.js` — for the DRAFT/EXECUTE phases, not for the managed-spawn `cmd`/healthcheck allowlist itself).',
|
|
804
|
+
'Known device-farm tooling to reach for instead of re-deriving a pattern from scratch: `adb` and `emulator` (both on the managed-spawn executable allowlist — device/emulator shell, install, logcat; `emulator -list-avds` discovers configured AVDs before you pick one for the spec), and `maestro` (declarative mobile UI-flow runner already wired in as a built-in QA runner adapter — see `engine/qa-runners/index.js` — for the DRAFT/EXECUTE phases, not for the managed-spawn `cmd`/healthcheck allowlist itself).',
|
|
805
805
|
'',
|
|
806
806
|
'### Verify before exit',
|
|
807
807
|
'',
|
|
@@ -1174,11 +1174,32 @@ function reapOrTrackManagedRuntime(spec, runtime, ctx, options = {}) {
|
|
|
1174
1174
|
// back to a liveness re-check + sweep-retry tracking when the kill itself
|
|
1175
1175
|
// FAILED (or there was no pid to kill).
|
|
1176
1176
|
let killed = false;
|
|
1177
|
+
// A CONCLUSIVE identity mismatch — a real creation time that is later than
|
|
1178
|
+
// the child we recorded — proves the PID is not ours (recycled, or an
|
|
1179
|
+
// EPERM-guarded foreign/system process that isPidAlive reports as alive).
|
|
1180
|
+
// There is nothing of ours to reap, so do not signal it, and do not pin the
|
|
1181
|
+
// runtime into the sweep-retry loop forever (W-ms8d10y3003t0588).
|
|
1182
|
+
let foreignPid = false;
|
|
1177
1183
|
if (Number.isInteger(pid) && pid > 0) {
|
|
1178
|
-
|
|
1179
|
-
|
|
1184
|
+
const getIdentity = typeof options.getProcessIdentity === 'function'
|
|
1185
|
+
? options.getProcessIdentity
|
|
1186
|
+
: processUtils.getProcessIdentity;
|
|
1187
|
+
let expectedIdentity = null;
|
|
1188
|
+
try { expectedIdentity = getIdentity(pid); } catch { /* fail closed below */ }
|
|
1189
|
+
foreignPid = processUtils.isProcessIdentityConclusiveMismatch(
|
|
1190
|
+
expectedIdentity,
|
|
1191
|
+
_managedStartedAtMs(runtime),
|
|
1192
|
+
);
|
|
1193
|
+
if (!foreignPid) {
|
|
1194
|
+
try {
|
|
1195
|
+
killed = shared.terminateProcess('engine.managed-spawn.reap-failed', { pid }, {
|
|
1196
|
+
expectedIdentity,
|
|
1197
|
+
}) !== false;
|
|
1198
|
+
}
|
|
1199
|
+
catch (_e) { killed = false; }
|
|
1200
|
+
}
|
|
1180
1201
|
}
|
|
1181
|
-
if (killed || !shared.isPidAlive(pid)) return { reaped: true, tracked: false };
|
|
1202
|
+
if (foreignPid || killed || !shared.isPidAlive(pid)) return { reaped: true, tracked: false };
|
|
1182
1203
|
|
|
1183
1204
|
const record = _toStateRecord(spec, runtime, ctx);
|
|
1184
1205
|
record.healthy = false;
|
|
@@ -1227,17 +1248,47 @@ function removeManagedSpec(name, opts = {}) {
|
|
|
1227
1248
|
return { removed: false, reason: 'generation-changed' };
|
|
1228
1249
|
}
|
|
1229
1250
|
const killPid = Number.isInteger(candidate.pid) && candidate.pid > 0 ? candidate.pid : null;
|
|
1230
|
-
const verifyIdentity = opts.verifyIdentity
|
|
1251
|
+
const verifyIdentity = opts.verifyIdentity !== false;
|
|
1231
1252
|
const getIdentity = typeof opts.getProcessIdentity === 'function'
|
|
1232
1253
|
? opts.getProcessIdentity
|
|
1233
1254
|
: processUtils.getProcessIdentity;
|
|
1255
|
+
// Tri-state probe (W-ms6dmv99005o26f4), consulted ONLY to interpret a null
|
|
1256
|
+
// identity. `getIdentity` keeps priority so the injected/monkey-patched
|
|
1257
|
+
// getProcessIdentity seams used by callers and tests are unaffected.
|
|
1258
|
+
const inspectIdentity = typeof opts.inspectProcessIdentity === 'function'
|
|
1259
|
+
? opts.inspectProcessIdentity
|
|
1260
|
+
: processUtils.inspectProcessIdentity;
|
|
1234
1261
|
const wasAlive = killPid !== null && shared.isPidAlive(killPid);
|
|
1235
1262
|
let identityBefore = null;
|
|
1236
1263
|
if (verifyIdentity && wasAlive) {
|
|
1237
1264
|
identityBefore = getIdentity(killPid);
|
|
1238
|
-
if (!identityBefore)
|
|
1239
|
-
|
|
1240
|
-
|
|
1265
|
+
if (!identityBefore) {
|
|
1266
|
+
// A null identity is not one condition but two, and they demand opposite
|
|
1267
|
+
// handling. isPidAlive() reports EPERM as alive (the kernel found the
|
|
1268
|
+
// process and refused the signal), so a foreign/system process — or a
|
|
1269
|
+
// recycled PID number no longer ours — now reaches this branch.
|
|
1270
|
+
// CONCLUSIVE absence from the process table → the PID is demonstrably
|
|
1271
|
+
// not our managed child; there is nothing of ours to kill, so drop
|
|
1272
|
+
// the stale record instead of pinning it forever.
|
|
1273
|
+
// INCONCLUSIVE (enumeration failed, no start time) → we learned
|
|
1274
|
+
// nothing; preserve the spec so a later sweep can retry.
|
|
1275
|
+
let conclusive = false;
|
|
1276
|
+
try { conclusive = inspectIdentity(killPid).conclusive === true; }
|
|
1277
|
+
catch { conclusive = false; }
|
|
1278
|
+
if (!conclusive) return { removed: false, reason: 'identity-unavailable' };
|
|
1279
|
+
} else if (!processUtils.isProcessIdentityCompatible(identityBefore, _managedStartedAtMs(candidate))) {
|
|
1280
|
+
// Same split as the null branch above. A CONCLUSIVE mismatch (a real
|
|
1281
|
+
// creation time later than the child we recorded) is exactly as decisive
|
|
1282
|
+
// as a conclusive absence: the PID is demonstrably not our managed child,
|
|
1283
|
+
// so drop the stale record instead of pinning it forever behind
|
|
1284
|
+
// `identity-mismatch` — which leaked the spec through
|
|
1285
|
+
// removeManagedSpecsForProject and re-failed on every sweep retry
|
|
1286
|
+
// (W-ms8d10y3003t0588). Clearing identityBefore routes it into the same
|
|
1287
|
+
// never-signal path the conclusive-absence case uses.
|
|
1288
|
+
if (!processUtils.isProcessIdentityConclusiveMismatch(identityBefore, _managedStartedAtMs(candidate))) {
|
|
1289
|
+
return { removed: false, reason: 'identity-mismatch' };
|
|
1290
|
+
}
|
|
1291
|
+
identityBefore = null;
|
|
1241
1292
|
}
|
|
1242
1293
|
}
|
|
1243
1294
|
|
|
@@ -1268,15 +1319,21 @@ function removeManagedSpec(name, opts = {}) {
|
|
|
1268
1319
|
// qemu-system-x86_64 child) whose descendants survive a single-PID kill and
|
|
1269
1320
|
// leak indefinitely (opg-microsoft/minions#710).
|
|
1270
1321
|
let killed = false;
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1322
|
+
// `identityBefore` is required: reaching here with a null identity means the
|
|
1323
|
+
// PID was CONCLUSIVELY absent from the process table, or its live identity
|
|
1324
|
+
// CONCLUSIVELY proved it is not our child (see above). Either way there is no
|
|
1325
|
+
// verified target and we must not fire a kill at a foreign PID.
|
|
1326
|
+
if (killPid !== null && verifyIdentity && wasAlive && identityBefore) {
|
|
1327
|
+
const identityAfter = getIdentity(killPid);
|
|
1328
|
+
if (!processUtils.isSameProcessIdentity(identityBefore, identityAfter)) {
|
|
1329
|
+
_restoreManagedRecord(removedRecord);
|
|
1330
|
+
return { removed: false, reason: 'identity-changed' };
|
|
1331
|
+
}
|
|
1332
|
+
try {
|
|
1333
|
+
killed = shared.terminateProcess('engine.managed-spawn.remove', { pid: killPid }, {
|
|
1334
|
+
expectedIdentity: identityAfter,
|
|
1335
|
+
}) !== false;
|
|
1278
1336
|
}
|
|
1279
|
-
try { killed = shared.killImmediate({ pid: killPid }) !== false; }
|
|
1280
1337
|
catch (e) {
|
|
1281
1338
|
log('warn', 'managed-spawn removeManagedSpec: kill ' + killPid + ' failed: ' + e.message);
|
|
1282
1339
|
}
|
|
@@ -1293,7 +1350,7 @@ function removeManagedSpec(name, opts = {}) {
|
|
|
1293
1350
|
|
|
1294
1351
|
function listManagedSpecs(opts) {
|
|
1295
1352
|
opts = opts || {};
|
|
1296
|
-
const parsed = require('
|
|
1353
|
+
const parsed = require('../persistence/small-state-store').readManagedProcesses();
|
|
1297
1354
|
const specs = (parsed && Array.isArray(parsed.specs)) ? parsed.specs : [];
|
|
1298
1355
|
if (opts.project) return specs.filter(s => s && s.owner_project === opts.project);
|
|
1299
1356
|
return specs.slice();
|
|
@@ -1547,7 +1604,7 @@ function tailManagedLog(name, lines) {
|
|
|
1547
1604
|
// ─── Item 6 (P-1f9c3a45) ─────────────────────────────────────────────────────
|
|
1548
1605
|
//
|
|
1549
1606
|
// Playbook auto-inject of the live-managed-processes block. Called by
|
|
1550
|
-
// engine/playbook.js renderPlaybook (project-scoped, computed once per render).
|
|
1607
|
+
// engine/agents/playbook.js renderPlaybook (project-scoped, computed once per render).
|
|
1551
1608
|
// Filters listManagedSpecs() to specs where:
|
|
1552
1609
|
// - owner_project === opts.project
|
|
1553
1610
|
// - healthy === true
|
|
@@ -1899,7 +1956,7 @@ function restartManagedSpec(name, opts = {}) {
|
|
|
1899
1956
|
// Kills + drops every spec whose
|
|
1900
1957
|
// owner_project matches, unlinks the
|
|
1901
1958
|
// log + log.1. Returns {killed,
|
|
1902
|
-
// unlinked}. engine/projects.js
|
|
1959
|
+
// unlinked}. engine/planning/projects.js
|
|
1903
1960
|
// removeProject calls this — no
|
|
1904
1961
|
// managed-process awareness elsewhere.
|
|
1905
1962
|
//
|
|
@@ -2096,28 +2153,22 @@ function removeManagedSpecsForProject(projectName) {
|
|
|
2096
2153
|
if (typeof projectName !== 'string' || projectName.length === 0) {
|
|
2097
2154
|
return { killed: 0, unlinked: 0, scanned: 0 };
|
|
2098
2155
|
}
|
|
2099
|
-
|
|
2100
|
-
let logPaths = [];
|
|
2101
|
-
shared.mutateManagedProcesses((data) => {
|
|
2102
|
-
if (!data || typeof data !== 'object' || !Array.isArray(data.specs)) {
|
|
2103
|
-
return _initialStateShape();
|
|
2104
|
-
}
|
|
2105
|
-
const keep = [];
|
|
2106
|
-
for (const rec of data.specs) {
|
|
2107
|
-
if (rec && rec.owner_project === projectName) {
|
|
2108
|
-
if (Number.isInteger(rec.pid) && rec.pid > 0) toKill.push(rec.pid);
|
|
2109
|
-
if (rec.log_path) logPaths.push(rec.log_path);
|
|
2110
|
-
continue; // drop
|
|
2111
|
-
}
|
|
2112
|
-
keep.push(rec);
|
|
2113
|
-
}
|
|
2114
|
-
data.specs = keep;
|
|
2115
|
-
return data;
|
|
2116
|
-
}, { defaultValue: _initialStateShape() });
|
|
2156
|
+
const records = listManagedSpecs({ project: projectName });
|
|
2117
2157
|
let killed = 0;
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2158
|
+
let removed = 0;
|
|
2159
|
+
const logPaths = [];
|
|
2160
|
+
for (const rec of records) {
|
|
2161
|
+
const result = removeManagedSpec(rec.name, {
|
|
2162
|
+
expected: rec,
|
|
2163
|
+
verifyIdentity: true,
|
|
2164
|
+
});
|
|
2165
|
+
if (!result.removed) {
|
|
2166
|
+
log('warn', 'managed-spawn removeForProject: preserved ' + rec.name + ' — ' + result.reason);
|
|
2167
|
+
continue;
|
|
2168
|
+
}
|
|
2169
|
+
removed++;
|
|
2170
|
+
if (result.killed) killed++;
|
|
2171
|
+
if (rec.log_path) logPaths.push(rec.log_path);
|
|
2121
2172
|
}
|
|
2122
2173
|
let unlinked = 0;
|
|
2123
2174
|
for (const p of logPaths) {
|
|
@@ -2126,7 +2177,7 @@ function removeManagedSpecsForProject(projectName) {
|
|
|
2126
2177
|
catch (e) { if (e && e.code !== 'ENOENT') log('warn', 'managed-spawn removeForProject: unlink ' + candidate + ' failed: ' + e.message); }
|
|
2127
2178
|
}
|
|
2128
2179
|
}
|
|
2129
|
-
return { killed
|
|
2180
|
+
return { killed, unlinked, scanned: records.length, removed };
|
|
2130
2181
|
}
|
|
2131
2182
|
|
|
2132
2183
|
module.exports = {
|