@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,103 +0,0 @@
|
|
|
1
|
-
const shared = require('./shared');
|
|
2
|
-
|
|
3
|
-
const QUARANTINE_REF_RETENTION_MS = 10 * 24 * 60 * 60 * 1000;
|
|
4
|
-
const DELETE_CONCURRENCY = 8;
|
|
5
|
-
|
|
6
|
-
function quarantineRefCreatedAtMs(ref, fallbackCreatedAt) {
|
|
7
|
-
const timestamp = String(ref || '').split('/').pop();
|
|
8
|
-
const fromRef = Number(timestamp);
|
|
9
|
-
if (Number.isFinite(fromRef) && fromRef > 0) return fromRef;
|
|
10
|
-
const fallback = Date.parse(fallbackCreatedAt || '');
|
|
11
|
-
return Number.isFinite(fallback) ? fallback : null;
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async function _readProjectQuarantineRefs(project) {
|
|
15
|
-
const output = await shared.shellSafeGit([
|
|
16
|
-
'for-each-ref',
|
|
17
|
-
'--format=%(refname)|%(objectname)|%(creatordate:iso-strict)',
|
|
18
|
-
'refs/minions/quarantine/',
|
|
19
|
-
'refs/minions/quarantine-wip/',
|
|
20
|
-
], { cwd: project.localPath, timeout: 15000 });
|
|
21
|
-
const seenRefs = new Set();
|
|
22
|
-
return String(output || '').split(/\r?\n/).filter(Boolean).map(line => {
|
|
23
|
-
const [ref, sha, fallbackCreatedAt] = line.split('|');
|
|
24
|
-
if (!ref || seenRefs.has(ref)) return null;
|
|
25
|
-
seenRefs.add(ref);
|
|
26
|
-
const createdAtMs = quarantineRefCreatedAtMs(ref, fallbackCreatedAt);
|
|
27
|
-
return { ref, sha, fallbackCreatedAt, createdAtMs };
|
|
28
|
-
}).filter(Boolean);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async function listQuarantineRefs(projects) {
|
|
32
|
-
const candidates = (Array.isArray(projects) ? projects : []).filter(project => project?.localPath);
|
|
33
|
-
const results = await Promise.allSettled(candidates.map(async project => {
|
|
34
|
-
const refs = await _readProjectQuarantineRefs(project);
|
|
35
|
-
return refs.map(({ ref, sha, fallbackCreatedAt, createdAtMs }) => {
|
|
36
|
-
return {
|
|
37
|
-
project: project.name || '',
|
|
38
|
-
ref,
|
|
39
|
-
sha,
|
|
40
|
-
createdAt: createdAtMs ? new Date(createdAtMs).toISOString() : (fallbackCreatedAt || ''),
|
|
41
|
-
kind: ref.startsWith('refs/minions/quarantine-wip/') ? 'wip' : 'commits',
|
|
42
|
-
};
|
|
43
|
-
});
|
|
44
|
-
}));
|
|
45
|
-
const items = [];
|
|
46
|
-
for (let i = 0; i < results.length; i++) {
|
|
47
|
-
const result = results[i];
|
|
48
|
-
if (result.status === 'fulfilled') items.push(...result.value);
|
|
49
|
-
else items.push({ project: candidates[i].name || '', error: result.reason?.message || String(result.reason) });
|
|
50
|
-
}
|
|
51
|
-
return items.sort((a, b) => String(b.createdAt || '').localeCompare(String(a.createdAt || '')));
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
async function _mapWithConcurrency(items, limit, worker) {
|
|
55
|
-
let next = 0;
|
|
56
|
-
const runners = Array.from({ length: Math.min(limit, items.length) }, async () => {
|
|
57
|
-
while (next < items.length) {
|
|
58
|
-
const item = items[next++];
|
|
59
|
-
await worker(item);
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
await Promise.all(runners);
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
async function pruneExpiredQuarantineRefs(projects, {
|
|
66
|
-
now = Date.now(),
|
|
67
|
-
retentionMs = QUARANTINE_REF_RETENTION_MS,
|
|
68
|
-
} = {}) {
|
|
69
|
-
const candidates = (Array.isArray(projects) ? projects : []).filter(project => project?.localPath);
|
|
70
|
-
const results = await Promise.allSettled(candidates.map(async project => {
|
|
71
|
-
const refs = await _readProjectQuarantineRefs(project);
|
|
72
|
-
const expired = refs.filter(item => item.createdAtMs !== null && now - item.createdAtMs >= retentionMs);
|
|
73
|
-
|
|
74
|
-
let removed = 0;
|
|
75
|
-
await _mapWithConcurrency(expired, DELETE_CONCURRENCY, async item => {
|
|
76
|
-
await shared.shellSafeGit(['update-ref', '-d', item.ref, item.sha], {
|
|
77
|
-
cwd: project.localPath,
|
|
78
|
-
timeout: 15000,
|
|
79
|
-
});
|
|
80
|
-
removed++;
|
|
81
|
-
});
|
|
82
|
-
return removed;
|
|
83
|
-
}));
|
|
84
|
-
|
|
85
|
-
let removed = 0;
|
|
86
|
-
const errors = [];
|
|
87
|
-
for (let i = 0; i < results.length; i++) {
|
|
88
|
-
const result = results[i];
|
|
89
|
-
if (result.status === 'fulfilled') removed += result.value;
|
|
90
|
-
else errors.push({
|
|
91
|
-
project: candidates[i]?.name || '',
|
|
92
|
-
error: result.reason?.message || String(result.reason),
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
return { removed, errors };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
module.exports = {
|
|
99
|
-
QUARANTINE_REF_RETENTION_MS,
|
|
100
|
-
quarantineRefCreatedAtMs,
|
|
101
|
-
listQuarantineRefs,
|
|
102
|
-
pruneExpiredQuarantineRefs,
|
|
103
|
-
};
|
|
@@ -1,178 +0,0 @@
|
|
|
1
|
-
// Explicit operational tooling for the SQL-only runtime state store.
|
|
2
|
-
|
|
3
|
-
const fs = require('fs');
|
|
4
|
-
const path = require('path');
|
|
5
|
-
const { getDb } = require('./db');
|
|
6
|
-
|
|
7
|
-
function _quoteSqlString(value) {
|
|
8
|
-
return `'${String(value).replace(/'/g, "''")}'`;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function checkState() {
|
|
12
|
-
const db = getDb();
|
|
13
|
-
const schemaVersion = Number(db.prepare('SELECT COALESCE(MAX(version), 0) AS version FROM schema_version').get().version) || 0;
|
|
14
|
-
const quickCheck = db.prepare('PRAGMA quick_check').all().map(row => Object.values(row)[0]);
|
|
15
|
-
const foreignKeyViolations = db.prepare('PRAGMA foreign_key_check').all();
|
|
16
|
-
const invariants = {
|
|
17
|
-
orphanPrdItems: Number(db.prepare('SELECT COUNT(*) AS n FROM prd_items pi LEFT JOIN prds p ON p.id=pi.prd_id WHERE p.id IS NULL').get().n) || 0,
|
|
18
|
-
orphanVerifyPrs: Number(db.prepare('SELECT COUNT(*) AS n FROM prd_verify_prs vp LEFT JOIN prds p ON p.id=vp.prd_id WHERE p.id IS NULL').get().n) || 0,
|
|
19
|
-
brokenWorkItemPrdLinks: Number(db.prepare('SELECT COUNT(*) AS n FROM work_items wi LEFT JOIN prd_items pi ON pi.id=wi.prd_item_id WHERE wi.prd_item_id IS NOT NULL AND pi.id IS NULL').get().n) || 0,
|
|
20
|
-
};
|
|
21
|
-
const ok = quickCheck.length === 1
|
|
22
|
-
&& quickCheck[0] === 'ok'
|
|
23
|
-
&& foreignKeyViolations.length === 0
|
|
24
|
-
&& Object.values(invariants).every(count => count === 0);
|
|
25
|
-
return { ok, schemaVersion, quickCheck, foreignKeyViolations, invariants };
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function backupState(targetPath) {
|
|
29
|
-
if (!targetPath) throw new Error('state backup requires an output path');
|
|
30
|
-
const resolved = path.resolve(targetPath);
|
|
31
|
-
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
32
|
-
if (fs.existsSync(resolved)) throw new Error(`backup target already exists: ${resolved}`);
|
|
33
|
-
const db = getDb();
|
|
34
|
-
db.exec('PRAGMA wal_checkpoint(TRUNCATE)');
|
|
35
|
-
db.exec(`VACUUM INTO ${_quoteSqlString(resolved)}`);
|
|
36
|
-
return { ok: true, path: resolved, bytes: fs.statSync(resolved).size };
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
function exportState(targetPath) {
|
|
40
|
-
if (!targetPath) throw new Error('state export requires an output path');
|
|
41
|
-
const resolved = path.resolve(targetPath);
|
|
42
|
-
fs.mkdirSync(path.dirname(resolved), { recursive: true });
|
|
43
|
-
const db = getDb();
|
|
44
|
-
const tables = db.prepare(`
|
|
45
|
-
SELECT name FROM sqlite_master
|
|
46
|
-
WHERE type='table' AND name NOT LIKE 'sqlite_%'
|
|
47
|
-
ORDER BY name
|
|
48
|
-
`).all().map(row => row.name);
|
|
49
|
-
const data = {
|
|
50
|
-
format: 'minions-sql-diagnostic-export-v1',
|
|
51
|
-
exportedAt: new Date().toISOString(),
|
|
52
|
-
integrity: checkState(),
|
|
53
|
-
tables: {},
|
|
54
|
-
};
|
|
55
|
-
for (const table of tables) {
|
|
56
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(table)) throw new Error(`unsafe table name: ${table}`);
|
|
57
|
-
data.tables[table] = db.prepare(`SELECT * FROM "${table}"`).all();
|
|
58
|
-
}
|
|
59
|
-
const tmp = `${resolved}.tmp.${process.pid}`;
|
|
60
|
-
fs.writeFileSync(tmp, JSON.stringify(data, null, 2));
|
|
61
|
-
fs.renameSync(tmp, resolved);
|
|
62
|
-
return { ok: true, path: resolved, tables: tables.length, bytes: fs.statSync(resolved).size };
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function _readJson(filePath, expected) {
|
|
66
|
-
if (!fs.existsSync(filePath)) return null;
|
|
67
|
-
const value = JSON.parse(fs.readFileSync(filePath, 'utf8'));
|
|
68
|
-
if (expected === 'array' && !Array.isArray(value)) throw new Error(`expected array in ${filePath}`);
|
|
69
|
-
if (expected === 'object' && (!value || typeof value !== 'object' || Array.isArray(value))) {
|
|
70
|
-
throw new Error(`expected object in ${filePath}`);
|
|
71
|
-
}
|
|
72
|
-
return value;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
function importLegacyJson(sourceRoot) {
|
|
76
|
-
if (!sourceRoot) throw new Error('state import-legacy-json requires a source directory');
|
|
77
|
-
const root = path.resolve(sourceRoot);
|
|
78
|
-
if (!fs.statSync(root).isDirectory()) throw new Error(`legacy source is not a directory: ${root}`);
|
|
79
|
-
const imported = {};
|
|
80
|
-
const replace = (modulePath, fn, value) => {
|
|
81
|
-
if (value == null) return;
|
|
82
|
-
require(modulePath)[fn](() => value);
|
|
83
|
-
imported[fn] = (imported[fn] || 0) + 1;
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
replace(
|
|
87
|
-
'./small-state-store',
|
|
88
|
-
'applyEngineStateMutation',
|
|
89
|
-
_readJson(path.join(root, 'engine', 'state.json'), 'object'),
|
|
90
|
-
);
|
|
91
|
-
replace('./dispatch-store', 'applyDispatchMutation', _readJson(path.join(root, 'engine', 'dispatch.json'), 'object'));
|
|
92
|
-
replace('./metrics-store', 'applyMetricsMutation', _readJson(path.join(root, 'engine', 'metrics.json'), 'object'));
|
|
93
|
-
replace('./watches-store', 'applyWatchesMutation', _readJson(path.join(root, 'engine', 'watches.json'), 'array'));
|
|
94
|
-
|
|
95
|
-
const small = [
|
|
96
|
-
['schedule-runs.json', 'applyScheduleRunsMutation', 'object'],
|
|
97
|
-
['pipeline-runs.json', 'applyPipelineRunsMutation', 'object'],
|
|
98
|
-
['managed-processes.json', 'applyManagedProcessesMutation', 'object'],
|
|
99
|
-
['worktree-pool.json', 'applyWorktreePoolMutation', 'object'],
|
|
100
|
-
['qa-runs.json', 'applyQaRunsMutation', 'array'],
|
|
101
|
-
['qa-sessions.json', 'applyQaSessionsMutation', 'array'],
|
|
102
|
-
['pr-links.json', 'applyPrLinksMutation', 'object'],
|
|
103
|
-
['cooldowns.json', 'applyCooldownsMutation', 'object'],
|
|
104
|
-
['pending-rebases.json', 'applyPendingRebasesMutation', 'array'],
|
|
105
|
-
['cc-sessions.json', 'applyCcSessionsMutation', 'array'],
|
|
106
|
-
['doc-sessions.json', 'applyDocSessionsMutation', 'object'],
|
|
107
|
-
];
|
|
108
|
-
for (const [filename, fn, shape] of small) {
|
|
109
|
-
replace('./small-state-store', fn, _readJson(path.join(root, 'engine', filename), shape));
|
|
110
|
-
}
|
|
111
|
-
replace(
|
|
112
|
-
'./small-state-store',
|
|
113
|
-
'applyCcGlobalSessionMutation',
|
|
114
|
-
_readJson(path.join(root, 'engine', 'cc-session.json'), 'object'),
|
|
115
|
-
);
|
|
116
|
-
|
|
117
|
-
const workItemsStore = require('./work-items-store');
|
|
118
|
-
const pullRequestsStore = require('./pull-requests-store');
|
|
119
|
-
const importScope = (scope, dir) => {
|
|
120
|
-
const workItems = _readJson(path.join(dir, 'work-items.json'), 'array');
|
|
121
|
-
if (workItems) {
|
|
122
|
-
workItemsStore.applyWorkItemsMutation(scope, () => workItems);
|
|
123
|
-
imported.workItemScopes = (imported.workItemScopes || 0) + 1;
|
|
124
|
-
}
|
|
125
|
-
const archivedWorkItems = _readJson(path.join(dir, 'work-items-archive.json'), 'array');
|
|
126
|
-
if (archivedWorkItems) {
|
|
127
|
-
workItemsStore.replaceArchivedWorkItems(scope, archivedWorkItems);
|
|
128
|
-
imported.archivedWorkItemScopes = (imported.archivedWorkItemScopes || 0) + 1;
|
|
129
|
-
}
|
|
130
|
-
const pullRequests = _readJson(path.join(dir, 'pull-requests.json'), 'array');
|
|
131
|
-
if (pullRequests) {
|
|
132
|
-
pullRequestsStore.applyPullRequestsMutation(scope, () => pullRequests);
|
|
133
|
-
imported.pullRequestScopes = (imported.pullRequestScopes || 0) + 1;
|
|
134
|
-
}
|
|
135
|
-
};
|
|
136
|
-
importScope('central', root);
|
|
137
|
-
try {
|
|
138
|
-
for (const entry of fs.readdirSync(path.join(root, 'projects'), { withFileTypes: true })) {
|
|
139
|
-
if (entry.isDirectory() && entry.name !== '.archived') {
|
|
140
|
-
importScope(entry.name, path.join(root, 'projects', entry.name));
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
} catch { /* projects are optional */ }
|
|
144
|
-
|
|
145
|
-
const prdStore = require('./prd-store');
|
|
146
|
-
for (const [dir, archived] of [[path.join(root, 'prd'), false], [path.join(root, 'prd', 'archive'), true]]) {
|
|
147
|
-
let files = [];
|
|
148
|
-
try { files = fs.readdirSync(dir).filter(name => name.endsWith('.json')); } catch { continue; }
|
|
149
|
-
for (const filename of files) {
|
|
150
|
-
const prd = _readJson(path.join(dir, filename), 'object');
|
|
151
|
-
prdStore.writePrd(filename, prd, { archived });
|
|
152
|
-
imported.prds = (imported.prds || 0) + 1;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const logs = _readJson(path.join(root, 'engine', 'log.json'), 'array');
|
|
157
|
-
if (logs) {
|
|
158
|
-
const db = getDb();
|
|
159
|
-
const { withTransaction } = require('./db');
|
|
160
|
-
withTransaction(db, () => {
|
|
161
|
-
db.exec('DELETE FROM logs');
|
|
162
|
-
const insert = db.prepare('INSERT INTO logs (ts_ms, level, message, meta) VALUES (?, ?, ?, ?)');
|
|
163
|
-
for (const entry of logs) {
|
|
164
|
-
const timestamp = Date.parse(entry.timestamp);
|
|
165
|
-
const meta = { ...entry };
|
|
166
|
-
delete meta.timestamp;
|
|
167
|
-
delete meta.level;
|
|
168
|
-
delete meta.message;
|
|
169
|
-
const { level, message } = entry;
|
|
170
|
-
insert.run(Number.isFinite(timestamp) ? timestamp : Date.now(), level || 'info', String(message || ''), Object.keys(meta).length ? JSON.stringify(meta) : null);
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
imported.logs = logs.length;
|
|
174
|
-
}
|
|
175
|
-
return { ok: true, source: root, imported, integrity: checkState() };
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
module.exports = { checkState, backupState, exportState, importLegacyJson };
|
|
File without changes
|