forgedock 1.27.0 → 1.29.0
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/README.md +4 -1
- package/bin/bootstrap.mjs +55 -0
- package/bin/engine/outcome-codes.mjs +39 -0
- package/bin/engine/telemetry-seam.mjs +37 -8
- package/bin/engine/telemetry-seam.test.mjs +31 -0
- package/bin/engine-cli.mjs +601 -42
- package/bin/engine.mjs +8 -4
- package/bin/forgedock.mjs +75 -9
- package/bin/gc.mjs +580 -0
- package/bin/lean/admission.mjs +33 -3
- package/bin/lean/batch.mjs +22 -4
- package/bin/lean/batch.test.mjs +5 -3
- package/bin/lean/checks.mjs +199 -0
- package/bin/lean/checks.test.mjs +183 -0
- package/bin/lean/conformance.mjs +234 -57
- package/bin/lean/conformance.test.mjs +168 -7
- package/bin/lean/context.mjs +333 -0
- package/bin/lean/context.test.mjs +279 -0
- package/bin/lean/credentials.mjs +29 -0
- package/bin/lean/depcache.mjs +312 -0
- package/bin/lean/depcache.test.mjs +298 -0
- package/bin/lean/drift.mjs +198 -0
- package/bin/lean/drift.test.mjs +223 -0
- package/bin/lean/effects.mjs +104 -9
- package/bin/lean/execution.e2e.test.mjs +81 -0
- package/bin/lean/execution.mjs +431 -0
- package/bin/lean/execution.test.mjs +583 -0
- package/bin/lean/heavy.mjs +289 -0
- package/bin/lean/heavy.test.mjs +207 -0
- package/bin/lean/lean.mjs +723 -154
- package/bin/lean/lean.test.mjs +1603 -35
- package/bin/lean/ledger.mjs +27 -2
- package/bin/lean/ledger.test.mjs +36 -1
- package/bin/lean/limits.mjs +58 -0
- package/bin/lean/limits.test.mjs +150 -0
- package/bin/lean/orchestrate.mjs +389 -19
- package/bin/lean/prefilter.mjs +2 -2
- package/bin/lean/prefilter.test.mjs +3 -0
- package/bin/lean/prompts.mjs +106 -17
- package/bin/lean/recovery.test.mjs +230 -0
- package/bin/lean/refactor.mjs +276 -0
- package/bin/lean/refactor.test.mjs +359 -0
- package/bin/lean/render.mjs +49 -10
- package/bin/lean/review-trigger.mjs +134 -0
- package/bin/lean/review-trigger.test.mjs +104 -0
- package/bin/lean/sandbox-provider.contract.test.mjs +257 -0
- package/bin/lean/sandbox-remote.mjs +142 -0
- package/bin/lean/sched.mjs +221 -0
- package/bin/lean/sched.test.mjs +310 -0
- package/bin/lean/schedd.mjs +247 -0
- package/bin/lean/schedd.test.mjs +180 -0
- package/bin/lean/testmap.mjs +84 -0
- package/bin/lean/testmap.test.mjs +58 -0
- package/bin/lean/toolchain.mjs +228 -0
- package/bin/lean/toolchain.test.mjs +154 -0
- package/bin/lean/verify.mjs +66 -10
- package/bin/lean/verify.test.mjs +104 -3
- package/bin/lean/worktree.mjs +69 -0
- package/bin/lean/worktree.test.mjs +141 -0
- package/bin/runner.mjs +53 -10
- package/bin/stats/github-source.mjs +1 -1
- package/bin/stats/index.mjs +24 -2
- package/bin/stats/local-source.mjs +13 -0
- package/bin/stats/query.mjs +99 -0
- package/bin/stats/stats.test.mjs +94 -1
- package/commands/audit.md +2 -0
- package/commands/autopilot.md +2 -0
- package/commands/bootstrap.md +35 -0
- package/commands/cleanup.md +7 -22
- package/commands/forge-stats.md +2 -1
- package/commands/forgedock-init.md +7 -0
- package/commands/issue.md +89 -830
- package/commands/milestone.md +55 -6
- package/commands/orchestrate.md +62 -8
- package/commands/upgrade-deps.md +3 -3
- package/commands/work-on/build/validate.md +4 -0
- package/commands/work-on/close.md +2 -0
- package/commands/work-on/decompose.md +24 -6
- package/docs/CI.md +3 -3
- package/docs/CONFIG.md +192 -2
- package/docs/OUTCOME-CODES.md +22 -0
- package/docs/RELEASE-NOTES.md +9 -0
- package/docs/TELEMETRY.md +1 -1
- package/docs/site/command-reference.md +22 -0
- package/docs/site/getting-started.md +2 -0
- package/docs/site/start-a-new-project.md +327 -0
- package/package.json +1 -1
- package/scripts/affected-files-check.sh +91 -0
- package/scripts/affected-files-check.test.sh +80 -0
- package/scripts/bootstrap-create.mjs +393 -0
- package/scripts/bootstrap-validate.mjs +36 -2
- package/scripts/calibration.mjs +116 -0
- package/scripts/check-devdocs-freshness.sh +9 -4
- package/scripts/check-devdocs-freshness.test.sh +11 -1
- package/scripts/check-spec-markers.sh +4 -0
- package/scripts/check-spec-size.sh +29 -11
- package/scripts/check-spec-size.test.sh +27 -4
- package/scripts/ci-local/lib.mjs +8 -1
- package/scripts/ci-local/parallelism.test.mjs +27 -0
- package/scripts/ci-local/run.mjs +3 -3
- package/scripts/ci-local/scoping.mjs +82 -0
- package/scripts/ci-local.test.sh +1 -1
- package/scripts/fixtures/symbol-index/other/sample.rb +3 -0
- package/scripts/fixtures/symbol-index/py/pkg/__init__.py +1 -0
- package/scripts/fixtures/symbol-index/py/pkg/a.py +5 -0
- package/scripts/fixtures/symbol-index/py/pkg/b.py +14 -0
- package/scripts/fixtures/symbol-index/py/pkg/c.py +1 -0
- package/scripts/fixtures/symbol-index/py/sample.py +41 -0
- package/scripts/fixtures/symbol-index/ts/sample.ts +13 -0
- package/scripts/fixtures/symbol-move/gen_big.py +201 -0
- package/scripts/fixtures/symbol-move-ts/gen_big.mjs +56 -0
- package/scripts/fixtures/test-map/go/.github/workflows/ci.yml +23 -0
- package/scripts/fixtures/test-map/go/Makefile +5 -0
- package/scripts/fixtures/test-map/go/README.md +1 -0
- package/scripts/fixtures/test-map/go/go.mod +3 -0
- package/scripts/fixtures/test-map/go/internal/util/util.go +3 -0
- package/scripts/fixtures/test-map/go/main.go +3 -0
- package/scripts/fixtures/test-map/node/package.json +10 -0
- package/scripts/fixtures/test-map/node/packages/ui/package.json +4 -0
- package/scripts/fixtures/test-map/node/packages/ui/src/button.tsx +1 -0
- package/scripts/fixtures/test-map/node/pnpm-lock.yaml +1 -0
- package/scripts/fixtures/test-map/node/src/a.ts +1 -0
- package/scripts/fixtures/test-map/node/vitest.config.ts +1 -0
- package/scripts/fixtures/test-map/python/pkg/__init__.py +0 -0
- package/scripts/fixtures/test-map/python/pkg/mod.py +2 -0
- package/scripts/fixtures/test-map/python/pyproject.toml +9 -0
- package/scripts/fixtures/test-map/python/tests/test_mod.py +5 -0
- package/scripts/fixtures/test-map/python/uv.lock +1 -0
- package/scripts/forge-root.test.sh +1 -1
- package/scripts/hotspots.sh +100 -0
- package/scripts/hotspots.test.sh +101 -0
- package/scripts/issue-create.sh +197 -0
- package/scripts/issue-create.test.sh +166 -0
- package/scripts/maintenance-scan.sh +185 -0
- package/scripts/maintenance-scan.test.sh +89 -0
- package/scripts/milestone-drift.sh +206 -0
- package/scripts/milestone-drift.test.sh +120 -0
- package/scripts/refactor-verify.sh +368 -0
- package/scripts/refactor-verify.test.sh +202 -0
- package/scripts/repo-facts.sh +146 -0
- package/scripts/repo-facts.test.sh +106 -0
- package/scripts/structure-delta.sh +10 -5
- package/scripts/structure-delta.test.sh +3 -2
- package/scripts/symbol-index.mjs +253 -0
- package/scripts/symbol-index.py +354 -0
- package/scripts/symbol-index.test.sh +119 -0
- package/scripts/symbol-move-ts.test.sh +161 -0
- package/scripts/symbol-move.mjs +379 -0
- package/scripts/symbol-move.py +383 -0
- package/scripts/symbol-move.test.sh +168 -0
- package/scripts/test-map.sh +211 -0
- package/scripts/test-map.test.sh +165 -0
- package/scripts/wait-ci-green.sh +10 -4
- package/scripts/wait-ci-green.test.sh +9 -0
- package/templates/bootstrap/interview.md +34 -0
- package/templates/bootstrap/issue-body.md +42 -0
- package/templates/bootstrap/needs-human-issue.md +45 -0
- package/templates/bootstrap/stack-profiles.md +34 -0
- package/templates/bootstrap/technical-spike.md +75 -0
package/bin/engine.mjs
CHANGED
|
@@ -945,7 +945,7 @@ export async function runIssue(opts) {
|
|
|
945
945
|
// "needs-human" — this is the engine/tool breaking, not a genuine
|
|
946
946
|
// human-judgment block (see #2244/#2261). Any other thrown error is
|
|
947
947
|
// a true unexpected crash and keeps propagating unchanged.
|
|
948
|
-
if (e.code === "NO_API_KEY" || e.code === "NO_SDK" || e.code === "CLI_BACKEND_FAILED" || e.code === "CLI_MAX_TURNS" || isDiskQuotaError(e)) {
|
|
948
|
+
if (e.code === "NO_API_KEY" || e.code === "NO_SDK" || e.code === "CLI_BACKEND_FAILED" || e.code === "CLI_BACKEND_UNAVAILABLE" || e.code === "CLI_MAX_TURNS" || isDiskQuotaError(e)) {
|
|
949
949
|
// forge#2241: when the runner attached a session-limit reset time
|
|
950
950
|
// (bin/runner.mjs's extractSessionLimitResetTime(), only ever set
|
|
951
951
|
// for a genuine session-limit CLI_BACKEND_FAILED — never
|
|
@@ -1055,6 +1055,8 @@ export async function runIssue(opts) {
|
|
|
1055
1055
|
usage: outcome.usage ?? null, last_attempt_usage: outcome.last_attempt_usage ?? null,
|
|
1056
1056
|
// forge#3589: model + turn count per phase (null when the backend does not report them).
|
|
1057
1057
|
model: outcome.model ?? null, turns: outcome.turns ?? null,
|
|
1058
|
+
// forge#4257: the execution backend that ran the phase (null when unreported).
|
|
1059
|
+
backend: outcome.backend ?? null,
|
|
1058
1060
|
...(commitReason ? { terminalReason: commitReason, code: commitCode } : {}),
|
|
1059
1061
|
});
|
|
1060
1062
|
state = deriveState(readLog(dir, issue));
|
|
@@ -1282,6 +1284,7 @@ async function runPhaseWithRetry(phase, state, ctx) {
|
|
|
1282
1284
|
event: "PHASE_ATTEMPT_USAGE", phase: phase.id, attempt,
|
|
1283
1285
|
usage: usage ?? null, duration_ms: Math.round(performance.now() - t0),
|
|
1284
1286
|
cost_usd: extra?.cost_usd ?? null, model: extra?.model ?? null, turns: extra?.turns ?? null,
|
|
1287
|
+
backend: extra?.backend ?? null,
|
|
1285
1288
|
};
|
|
1286
1289
|
appendEvent(dir, issue, rec);
|
|
1287
1290
|
try { await emitTelemetry?.({ ...rec, issue }); } catch { /* telemetry never fails a phase */ }
|
|
@@ -1348,7 +1351,7 @@ async function runPhaseWithRetry(phase, state, ctx) {
|
|
|
1348
1351
|
attempt--;
|
|
1349
1352
|
continue;
|
|
1350
1353
|
}
|
|
1351
|
-
if (e.code === "NO_API_KEY" || e.code === "NO_SDK" || e.code === "CLI_BACKEND_FAILED") throw e;
|
|
1354
|
+
if (e.code === "NO_API_KEY" || e.code === "NO_SDK" || e.code === "CLI_BACKEND_FAILED" || e.code === "CLI_BACKEND_UNAVAILABLE") throw e;
|
|
1352
1355
|
// forge#2377: no `usage` field here — the runner threw, so no result
|
|
1353
1356
|
// (and therefore no usage data) was ever produced for this attempt.
|
|
1354
1357
|
// Do not fabricate a value; omitting the field (rather than a stale
|
|
@@ -1367,10 +1370,11 @@ async function runPhaseWithRetry(phase, state, ctx) {
|
|
|
1367
1370
|
// forge#3589: model/turns recorded alongside usage (additive; null when absent).
|
|
1368
1371
|
const lastModel = result?.cliModel ?? result?.model ?? null;
|
|
1369
1372
|
const lastTurns = result?.turns ?? null;
|
|
1373
|
+
const lastBackend = typeof result?.backend === "string" ? result.backend : null; // forge#4257
|
|
1370
1374
|
addUsage(lastUsage);
|
|
1371
|
-
await recordAttempt(attempt, lastUsage, t0, { cost_usd: result?.costUsd ?? null, model: lastModel, turns: lastTurns });
|
|
1375
|
+
await recordAttempt(attempt, lastUsage, t0, { cost_usd: result?.costUsd ?? null, model: lastModel, turns: lastTurns, backend: lastBackend });
|
|
1372
1376
|
const outcome = await phase.detectOutcome(state, io, result);
|
|
1373
|
-
if (outcome.status === "committed" || outcome.status === "blocked") return { ...outcome, usage: cumulativeUsage, last_attempt_usage: lastUsage, model: lastModel, turns: lastTurns };
|
|
1377
|
+
if (outcome.status === "committed" || outcome.status === "blocked") return { ...outcome, usage: cumulativeUsage, last_attempt_usage: lastUsage, model: lastModel, turns: lastTurns, backend: lastBackend };
|
|
1374
1378
|
appendEvent(dir, issue, { event: "PHASE_FAILED", phase: phase.id, attempt, reason: outcome.detail, code: normalizeCode(outcome.code), maxAttempts, usage: lastUsage, model: lastModel, turns: lastTurns });
|
|
1375
1379
|
// forge#2176: a phase's detectOutcome can mark a failure as a known,
|
|
1376
1380
|
// state-derived fixed point — re-running the phase's runner is
|
package/bin/forgedock.mjs
CHANGED
|
@@ -3231,6 +3231,26 @@ async function doctor(fix = false) {
|
|
|
3231
3231
|
);
|
|
3232
3232
|
}
|
|
3233
3233
|
|
|
3234
|
+
// ── Check 13: Resource hygiene (#4183) ──────────────────────────────────────
|
|
3235
|
+
// Owned leftovers (stale lane ledgers, forgedock-labelled docker, lean-*/agent-* worktrees, lane branches,
|
|
3236
|
+
// ~/.forge/tmp scratch) with counts and sizes; unowned stale ones are only reported. --fix runs the reaper with the
|
|
3237
|
+
// forge.yaml hygiene TTLs. Never a failure: a leftover slows the host, it does not break the install.
|
|
3238
|
+
{
|
|
3239
|
+
try {
|
|
3240
|
+
const gc = await import("./gc.mjs");
|
|
3241
|
+
const probes = gc.makeGcProbes({ cwd: process.cwd() });
|
|
3242
|
+
const h = gc.readHygiene(process.cwd());
|
|
3243
|
+
const plan = await gc.planGc({ probes, ttlMs: gc.hygieneTtls(h), deleteMergedBranches: h.delete_merged_branches });
|
|
3244
|
+
const applied = fix ? await gc.applyGc(plan, probes) : null;
|
|
3245
|
+
if (applied && applied.reclaimed.length > 0) fixesApplied++;
|
|
3246
|
+
const r = gc.hygieneCheck(plan, { applied });
|
|
3247
|
+
if (r.status === "pass") pass("Resource hygiene", r.detail);
|
|
3248
|
+
else warn("Resource hygiene", r.detail);
|
|
3249
|
+
} catch (e) {
|
|
3250
|
+
warn("Resource hygiene", `could not inspect ForgeDock leftovers: ${String(e?.message ?? e).slice(0, 200)}`);
|
|
3251
|
+
}
|
|
3252
|
+
}
|
|
3253
|
+
|
|
3234
3254
|
// ── Summary ────────────────────────────────────────────────────────────────
|
|
3235
3255
|
console.log("");
|
|
3236
3256
|
if (fix && fixesApplied > 0) {
|
|
@@ -3266,11 +3286,15 @@ function help() {
|
|
|
3266
3286
|
["npx forgedock disable [dir]", "Opt a directory out of ForgeDock"],
|
|
3267
3287
|
["npx forgedock status [dir]", "Show ForgeDock state for a directory"],
|
|
3268
3288
|
["npx forgedock run <cmd> [args]", "Run a command headlessly (local claude CLI or Anthropic API)"],
|
|
3289
|
+
["npx forgedock bootstrap <idea|docs> [--dry-run] [--spike <path>] | --plan <plan.json> [--dry-run]", "Headless /bootstrap: idea to orchestrate-ready backlog (--dry-run previews milestones, titles, DAG and estimated agent cost without GitHub writes); --plan validates and creates (or previews) a plan, and re-running resumes from GitHub"],
|
|
3269
3290
|
["npx forgedock run-issue <issue> [--lane <lane>] [--lane-override] [--path core|full] [--retry] [--wait-lease]", "Run the lean core work-on on one issue (default; --path full = legacy multi-phase pipeline; the lane comes from the issue: milestone → milestone/<slug>, else staging; --lane is an assertion, never the default branch) (--retry reopens an engine-error run, or a needs-human run once the label is cleared; --wait-lease waits for a held lease; exit 75 = deferred, lease held)"],
|
|
3270
3291
|
["npx forgedock orchestrate <issue...> [--parallel K] [--lane L]", "Run core work-on on several issues with bounded concurrency and Depends-on ordering; each issue on its own lane, cross-lane dependencies reported"],
|
|
3271
|
-
["npx forgedock orchestrate --resume <id> | --set-parallel <id> K", "
|
|
3292
|
+
["npx forgedock orchestrate --resume <id> | --set-parallel <id> K", "Reattach to a batch hosted by the schedd daemon (a finished one replays its report, an orphaned one is resumed with live lanes re-adopted), or change its concurrency live"],
|
|
3272
3293
|
["npx forgedock triage <issue...> [--lane L] [--dry-run]", "Already-fixed pre-filter: close issues a merged PR or green CI already resolved; print the rest"],
|
|
3273
|
-
["npx forgedock
|
|
3294
|
+
["npx forgedock limits show | clear <id>|--all", "Show or clear per-account usage-limit holds shared by orchestrate batches"],
|
|
3295
|
+
["npx forgedock sched show | cap <N>|--clear | weight <owner/repo> <N>|--clear", "Show the host lane registry, set the host-wide lane cap shared by orchestrate batches, or set a repo's share of slots within a priority (default equal)"],
|
|
3296
|
+
["npx forgedock schedd [status]", "Host scheduler daemon hosting every orchestrate batch (auto-spawned by orchestrate; run in the foreground for a systemd-user unit); status shows its pid and batches"],
|
|
3297
|
+
["npx forgedock gc [--apply] [--older-than 6h] [--docker] [--worktrees] [--branches] [--tmp] [--processes] [--sandboxes]", "Report (dry-run default) and reclaim ForgeDock-owned leftovers: stale lane ledgers, forgedock-labelled containers/volumes, lean-*/agent-* worktrees, abandoned lane branches, ~/.forge/tmp scratch, orphaned lane processes, orphaned lane sandboxes; unowned resources and unpushed work are only reported"],
|
|
3274
3298
|
["npx forgedock resume-stalled [--dry-run]", "Fleet stall recovery — re-dispatch expired-lease issues"],
|
|
3275
3299
|
["npx forgedock demo", "Set up a risk-free demo repo and print next steps"],
|
|
3276
3300
|
["npx forgedock labels [setup] [--repo owner/repo] [--domain a,b,c]", "Bootstrap ForgeDock-managed labels on a GitHub repo, plus optional per-repo domain labels (idempotent)"],
|
|
@@ -3279,7 +3303,7 @@ function help() {
|
|
|
3279
3303
|
["npx forgedock report [--days 30] [--md] [--json]", "30-day pipeline impact receipts for your repo"],
|
|
3280
3304
|
["npx forgedock stats [--since <ver|date>] [--repo owner/repo] [--json] [--refresh]", "Version-over-version cost/time/flow/review/gate report from GitHub telemetry (no model)"],
|
|
3281
3305
|
["npx forgedock doctor", "Check installation health"],
|
|
3282
|
-
["npx forgedock doctor --fix", "Auto-fix deterministic issues (symlinks, hook, labels, legacy block)"],
|
|
3306
|
+
["npx forgedock doctor --fix", "Auto-fix deterministic issues (symlinks, hook, labels, legacy block) and reclaim ForgeDock-owned leftovers (forge.yaml hygiene TTLs)"],
|
|
3283
3307
|
["npx forgedock update", "Pull latest & reinstall"],
|
|
3284
3308
|
["npx forgedock uninstall", "Remove commands"],
|
|
3285
3309
|
["npx forgedock opencode install", "Install token-efficient native OpenCode commands"],
|
|
@@ -3844,10 +3868,10 @@ async function watch() {
|
|
|
3844
3868
|
// The journey-routed commands render their own branded marks (hero/compact);
|
|
3845
3869
|
// splash() would double-brand them. Engine-surface commands, help, and
|
|
3846
3870
|
// unknown-command output keep the logo.
|
|
3847
|
-
const SPLASH_COMMANDS = new Set(["run", "run-issue", "orchestrate", "triage", "gc", "resume-stalled", "demo", "doctor", "watch", "help", "--help", "-h"]);
|
|
3871
|
+
const SPLASH_COMMANDS = new Set(["run", "bootstrap", "run-issue", "orchestrate", "triage", "gc", "resume-stalled", "demo", "doctor", "watch", "help", "--help", "-h"]);
|
|
3848
3872
|
const KNOWN_COMMANDS = new Set([
|
|
3849
3873
|
"install", "init", "enable", "disable", "status", "uninstall", "update",
|
|
3850
|
-
"run", "backend-check", "run-issue", "orchestrate", "triage", "gc", "resume-stalled", "demo", "doctor", "watch", "labels", "config", "stats", "help", "--help", "-h",
|
|
3874
|
+
"run", "bootstrap", "backend-check", "run-issue", "orchestrate", "triage", "gc", "resume-stalled", "demo", "doctor", "watch", "labels", "config", "stats", "limits", "sched", "schedd", "help", "--help", "-h",
|
|
3851
3875
|
"version", "--version", "-v",
|
|
3852
3876
|
]);
|
|
3853
3877
|
if (SPLASH_COMMANDS.has(command) || !KNOWN_COMMANDS.has(command)) splash(command);
|
|
@@ -4004,6 +4028,18 @@ switch (command) {
|
|
|
4004
4028
|
case "run":
|
|
4005
4029
|
await run();
|
|
4006
4030
|
break;
|
|
4031
|
+
case "bootstrap": {
|
|
4032
|
+
// #4177: headless /bootstrap; --plan runs scripts/bootstrap-create.mjs directly (no LLM), a re-run resumes.
|
|
4033
|
+
const { runBootstrap } = await import("./bootstrap.mjs");
|
|
4034
|
+
try {
|
|
4035
|
+
const { runCommand } = await import("./runner.mjs");
|
|
4036
|
+
exitCode = await runBootstrap(restArgs, { runCommand, commandsDir: COMMANDS_DIR });
|
|
4037
|
+
} catch (err) {
|
|
4038
|
+
process.stderr.write(`${RED}${err.message}${RESET}\n`);
|
|
4039
|
+
exitCode = 1;
|
|
4040
|
+
}
|
|
4041
|
+
break;
|
|
4042
|
+
}
|
|
4007
4043
|
case "backend-check": {
|
|
4008
4044
|
// Exit codes: 0 = ready, 1 = no usable backend, 2 = bad usage (unknown option).
|
|
4009
4045
|
// Only --quiet is accepted; anything else is a usage error so callers can tell a
|
|
@@ -4046,10 +4082,9 @@ switch (command) {
|
|
|
4046
4082
|
break;
|
|
4047
4083
|
}
|
|
4048
4084
|
case "gc": {
|
|
4049
|
-
//
|
|
4050
|
-
const {
|
|
4051
|
-
|
|
4052
|
-
process.stdout.write(`gc: removed ${removed.length} stale run tmp dir(s)\n`);
|
|
4085
|
+
// Reaper (#4180): dry-run report by default; --apply reclaims only ForgeDock-owned resources (ledger, label, lane naming, own tmp).
|
|
4086
|
+
const { runGc } = await import("./gc.mjs");
|
|
4087
|
+
exitCode = await runGc(restArgs);
|
|
4053
4088
|
break;
|
|
4054
4089
|
}
|
|
4055
4090
|
case "orchestrate": {
|
|
@@ -4063,6 +4098,37 @@ switch (command) {
|
|
|
4063
4098
|
}
|
|
4064
4099
|
break;
|
|
4065
4100
|
}
|
|
4101
|
+
case "limits": {
|
|
4102
|
+
const { limitsFromCli } = await import("./engine-cli.mjs");
|
|
4103
|
+
try {
|
|
4104
|
+
await limitsFromCli(restArgs);
|
|
4105
|
+
} catch (err) {
|
|
4106
|
+
process.stderr.write(`${RED}${err.message}${RESET}\n`);
|
|
4107
|
+
exitCode = 1;
|
|
4108
|
+
}
|
|
4109
|
+
break;
|
|
4110
|
+
}
|
|
4111
|
+
case "schedd": {
|
|
4112
|
+
// #4192: the host scheduler daemon; runs until idle or SIGTERM. Lanes are detached and survive it.
|
|
4113
|
+
const { scheddFromCli } = await import("./engine-cli.mjs");
|
|
4114
|
+
try {
|
|
4115
|
+
await scheddFromCli(restArgs);
|
|
4116
|
+
} catch (err) {
|
|
4117
|
+
process.stderr.write(`${RED}${err.message}${RESET}\n`);
|
|
4118
|
+
exitCode = 1;
|
|
4119
|
+
}
|
|
4120
|
+
break;
|
|
4121
|
+
}
|
|
4122
|
+
case "sched": {
|
|
4123
|
+
const { schedFromCli } = await import("./engine-cli.mjs");
|
|
4124
|
+
try {
|
|
4125
|
+
await schedFromCli(restArgs);
|
|
4126
|
+
} catch (err) {
|
|
4127
|
+
process.stderr.write(`${RED}${err.message}${RESET}\n`);
|
|
4128
|
+
exitCode = 1;
|
|
4129
|
+
}
|
|
4130
|
+
break;
|
|
4131
|
+
}
|
|
4066
4132
|
case "triage": {
|
|
4067
4133
|
const { triageFromCli } = await import("./engine-cli.mjs");
|
|
4068
4134
|
try {
|