@kynver-app/runtime 0.1.108 → 0.1.112
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/dist/cleanup-git-rev-cache.d.ts +5 -0
- package/dist/cleanup-git-status-cache.d.ts +5 -0
- package/dist/cleanup-guards.d.ts +2 -0
- package/dist/cleanup-index-status.d.ts +8 -1
- package/dist/cleanup-run-liveness.d.ts +8 -1
- package/dist/cli.js +372 -73
- package/dist/cli.js.map +4 -4
- package/dist/daemon-platform-guard.d.ts +2 -0
- package/dist/index.js +364 -65
- package/dist/index.js.map +4 -4
- package/dist/landing/cli-auth.d.ts +5 -1
- package/dist/landing/land-pr.d.ts +8 -0
- package/dist/server/cleanup.js +185 -38
- package/dist/server/cleanup.js.map +3 -3
- package/dist/server/default-repo.js +11 -1
- package/dist/server/default-repo.js.map +3 -3
- package/dist/server/memory-cost-enforce.js +11 -1
- package/dist/server/memory-cost-enforce.js.map +3 -3
- package/dist/server/monitor.js +14 -2
- package/dist/server/monitor.js.map +2 -2
- package/dist/worker-ops.d.ts +4 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -214,7 +214,11 @@ function scrubClaudeEnv(env) {
|
|
|
214
214
|
|
|
215
215
|
// src/git.ts
|
|
216
216
|
function git(cwd, args, options = {}) {
|
|
217
|
-
const res = spawnSync(
|
|
217
|
+
const res = spawnSync(
|
|
218
|
+
"git",
|
|
219
|
+
args,
|
|
220
|
+
hiddenSpawnOptions({ cwd, encoding: "utf8" })
|
|
221
|
+
);
|
|
218
222
|
if (res.status !== 0 && !options.allowFailure) {
|
|
219
223
|
const message = `git ${args.join(" ")} failed: ${res.stderr || res.stdout}`;
|
|
220
224
|
if (options.throwError) throw new Error(message);
|
|
@@ -230,7 +234,11 @@ function gitStatusShort(worktreePath) {
|
|
|
230
234
|
}
|
|
231
235
|
function gitCapture(cwd, args) {
|
|
232
236
|
try {
|
|
233
|
-
const res = spawnSync(
|
|
237
|
+
const res = spawnSync(
|
|
238
|
+
"git",
|
|
239
|
+
args,
|
|
240
|
+
hiddenSpawnOptions({ cwd, encoding: "utf8" })
|
|
241
|
+
);
|
|
234
242
|
return {
|
|
235
243
|
status: res.status,
|
|
236
244
|
stdout: res.stdout || "",
|
|
@@ -6049,32 +6057,98 @@ function workerStatus(args) {
|
|
|
6049
6057
|
writeJson(path21.join(worker.workerDir, "last-status.json"), status);
|
|
6050
6058
|
console.log(JSON.stringify(status, null, 2));
|
|
6051
6059
|
}
|
|
6060
|
+
function buildWorkerListDrilldownCommands(runId) {
|
|
6061
|
+
return {
|
|
6062
|
+
full: `kynver worker list --run ${runId} --full`,
|
|
6063
|
+
blocked: `kynver worker list --run ${runId} --blocked`,
|
|
6064
|
+
running: `kynver worker list --run ${runId} --running`,
|
|
6065
|
+
task: `kynver worker list --run ${runId} --task <task-id>`,
|
|
6066
|
+
worker: `kynver worker list --run ${runId} --worker <worker>`,
|
|
6067
|
+
runFull: `kynver run status --run ${runId} --full`,
|
|
6068
|
+
workerFull: `kynver worker status --run ${runId} --name <worker>`,
|
|
6069
|
+
workerTail: `kynver worker tail --run ${runId} --name <worker> --lines 80`
|
|
6070
|
+
};
|
|
6071
|
+
}
|
|
6072
|
+
function asOptionalArg(value) {
|
|
6073
|
+
if (typeof value !== "string") return void 0;
|
|
6074
|
+
const trimmed = value.trim();
|
|
6075
|
+
return trimmed.length ? trimmed : void 0;
|
|
6076
|
+
}
|
|
6077
|
+
function activeWorkerFilters(args) {
|
|
6078
|
+
const filters = {};
|
|
6079
|
+
if (args.blocked === true || args.blocked === "true") filters.blocked = true;
|
|
6080
|
+
if (args.running === true || args.running === "true") filters.running = true;
|
|
6081
|
+
const task = asOptionalArg(args.task ?? args.taskId);
|
|
6082
|
+
if (task) filters.task = task;
|
|
6083
|
+
const worker = asOptionalArg(args.worker ?? args.name);
|
|
6084
|
+
if (worker) filters.worker = worker;
|
|
6085
|
+
const status = asOptionalArg(args.status);
|
|
6086
|
+
if (status) filters.status = status;
|
|
6087
|
+
return filters;
|
|
6088
|
+
}
|
|
6089
|
+
function workerMatchesFilters(worker, filters) {
|
|
6090
|
+
if (filters.blocked) {
|
|
6091
|
+
const attention = typeof worker.attention === "string" ? worker.attention : "";
|
|
6092
|
+
const status = typeof worker.status === "string" ? worker.status : "";
|
|
6093
|
+
if (!(attention === "blocked" || attention === "needs_attention" || attention === "stale" || status === "blocked")) {
|
|
6094
|
+
return false;
|
|
6095
|
+
}
|
|
6096
|
+
}
|
|
6097
|
+
if (filters.running) {
|
|
6098
|
+
if (!(worker.status === "running" && worker.attention !== "blocked" && worker.attention !== "needs_attention")) {
|
|
6099
|
+
return false;
|
|
6100
|
+
}
|
|
6101
|
+
}
|
|
6102
|
+
if (typeof filters.task === "string" && worker.taskId !== filters.task) return false;
|
|
6103
|
+
if (typeof filters.worker === "string" && worker.worker !== filters.worker) return false;
|
|
6104
|
+
if (typeof filters.status === "string" && worker.status !== filters.status) return false;
|
|
6105
|
+
return true;
|
|
6106
|
+
}
|
|
6107
|
+
function applyWorkerFilters(board, args) {
|
|
6108
|
+
const filters = activeWorkerFilters(args);
|
|
6109
|
+
if (Object.keys(filters).length === 0) return board;
|
|
6110
|
+
const workers = board.workers.filter((worker) => workerMatchesFilters(worker, filters));
|
|
6111
|
+
const filtered = {
|
|
6112
|
+
...board,
|
|
6113
|
+
workerCount: workers.length,
|
|
6114
|
+
needsAttention: workers.filter((w) => w.attention && w.attention !== "ok" && w.attention !== "done").map((w) => w.worker),
|
|
6115
|
+
workers,
|
|
6116
|
+
activeFilters: filters
|
|
6117
|
+
};
|
|
6118
|
+
if (board.summary) {
|
|
6119
|
+
filtered.summary = {
|
|
6120
|
+
statusCounts: countBy(workers, "status"),
|
|
6121
|
+
attentionCounts: countBy(workers, "attention"),
|
|
6122
|
+
lifecycleCounts: countBy(workers, "lifecycleStage")
|
|
6123
|
+
};
|
|
6124
|
+
}
|
|
6125
|
+
if (board.controller) filtered.controller = buildControllerSummary(workers);
|
|
6126
|
+
return filtered;
|
|
6127
|
+
}
|
|
6052
6128
|
function workerList(args) {
|
|
6053
6129
|
const runId = resolveRunTargetArg(args);
|
|
6054
|
-
const explicitCompact = args.compact === true || args.compact === "true";
|
|
6055
6130
|
const explicitFull = args.full === true || args.full === "true";
|
|
6056
|
-
const
|
|
6057
|
-
const
|
|
6058
|
-
const compact = explicitCompact || !explicitFull && workerCount > 100;
|
|
6059
|
-
const board = compact ? buildCompactRunBoard(runId) : buildRunBoard(runId);
|
|
6060
|
-
const autoCompact = compact && !explicitCompact;
|
|
6061
|
-
const outputWorkers = autoCompact ? board.workers.filter((worker) => worker.attention && worker.attention !== "done" && worker.attention !== "ok") : board.workers;
|
|
6131
|
+
const board = applyWorkerFilters(explicitFull ? buildRunBoard(runId) : buildCompactRunBoard(runId), args);
|
|
6132
|
+
const outputWorkers = board.workers;
|
|
6062
6133
|
console.log(
|
|
6063
6134
|
JSON.stringify(
|
|
6064
6135
|
{
|
|
6065
6136
|
runId: board.runId,
|
|
6066
6137
|
status: board.status,
|
|
6138
|
+
projection: explicitFull ? "full" : "compact",
|
|
6067
6139
|
workerCount: board.workerCount,
|
|
6068
|
-
...
|
|
6069
|
-
|
|
6070
|
-
|
|
6071
|
-
|
|
6072
|
-
|
|
6073
|
-
|
|
6140
|
+
...board.activeFilters ? { activeFilters: board.activeFilters } : {},
|
|
6141
|
+
...!explicitFull ? {
|
|
6142
|
+
resultContract: {
|
|
6143
|
+
projection: "compact",
|
|
6144
|
+
rawWorkerPayloadsOmitted: true,
|
|
6145
|
+
deepDetailAvailableVia: ["--full", "worker status", "worker tail", "run status --full"]
|
|
6146
|
+
},
|
|
6147
|
+
drilldownCommands: buildWorkerListDrilldownCommands(runId)
|
|
6074
6148
|
} : {},
|
|
6075
6149
|
needsAttention: board.needsAttention,
|
|
6076
|
-
...
|
|
6077
|
-
...
|
|
6150
|
+
..."summary" in board ? { summary: board.summary } : {},
|
|
6151
|
+
..."controller" in board ? { controller: board.controller } : {},
|
|
6078
6152
|
workers: outputWorkers
|
|
6079
6153
|
},
|
|
6080
6154
|
null,
|
|
@@ -6342,9 +6416,33 @@ async function publishHarnessBoardSnapshot(args, source) {
|
|
|
6342
6416
|
authRefreshFailure: res.authRefreshFailure
|
|
6343
6417
|
};
|
|
6344
6418
|
}
|
|
6419
|
+
function buildRunStatusDrilldownCommands(runId) {
|
|
6420
|
+
return {
|
|
6421
|
+
full: `kynver run status --run ${runId} --full`,
|
|
6422
|
+
blocked: `kynver status --run ${runId} --blocked`,
|
|
6423
|
+
running: `kynver status --run ${runId} --running`,
|
|
6424
|
+
task: `kynver status --run ${runId} --task <task-id>`,
|
|
6425
|
+
worker: `kynver status --run ${runId} --worker <worker>`,
|
|
6426
|
+
workersFull: `kynver worker list --run ${runId} --full`,
|
|
6427
|
+
workerFull: `kynver worker status --run ${runId} --name <worker>`,
|
|
6428
|
+
workerTail: `kynver worker tail --run ${runId} --name <worker> --lines 80`,
|
|
6429
|
+
monitorTick: `kynver monitor status --run ${runId} --tick`
|
|
6430
|
+
};
|
|
6431
|
+
}
|
|
6345
6432
|
function runStatus(args) {
|
|
6346
|
-
const
|
|
6347
|
-
const
|
|
6433
|
+
const runId = resolveRunTargetArg(args);
|
|
6434
|
+
const explicitFull = args.full === true || args.full === "true";
|
|
6435
|
+
const board = applyWorkerFilters(explicitFull ? buildRunBoard(runId) : buildCompactRunBoard(runId), args);
|
|
6436
|
+
board.projection = explicitFull ? "full" : "compact";
|
|
6437
|
+
if (!explicitFull) {
|
|
6438
|
+
board.resultContract = {
|
|
6439
|
+
projection: "compact",
|
|
6440
|
+
rawWorkerPayloadsOmitted: true,
|
|
6441
|
+
omittedWorkerFields: ["finalResult", "changedFiles", "gitAncestry", "completionResponse", "stdout/stderr tails"],
|
|
6442
|
+
deepDetailAvailableVia: ["--full", "worker status", "worker tail", "monitor status --tick"]
|
|
6443
|
+
};
|
|
6444
|
+
board.drilldownCommands = buildRunStatusDrilldownCommands(runId);
|
|
6445
|
+
}
|
|
6348
6446
|
console.log(JSON.stringify(board, null, 2));
|
|
6349
6447
|
}
|
|
6350
6448
|
function tailWorker(args) {
|
|
@@ -7482,6 +7580,10 @@ var READY_MERGE_STATES = /* @__PURE__ */ new Set(["CLEAN", "HAS_HOOKS"]);
|
|
|
7482
7580
|
function repoArgs(repo) {
|
|
7483
7581
|
return repo?.trim() ? ["--repo", repo.trim()] : [];
|
|
7484
7582
|
}
|
|
7583
|
+
function repoFromPrUrl(prUrl) {
|
|
7584
|
+
const m = /github\.com\/([^/]+)\/([^/]+)\/pull\/\d+/i.exec(prUrl.trim());
|
|
7585
|
+
return m ? `${m[1]}/${m[2]}` : null;
|
|
7586
|
+
}
|
|
7485
7587
|
function ghJson(exec, cwd, args) {
|
|
7486
7588
|
const res = exec.gh(cwd, args);
|
|
7487
7589
|
if (res.status !== 0) {
|
|
@@ -7537,14 +7639,21 @@ var STRUCTURED_SECTION_RE = /^##\s*(test\s*plan|verification|test\s*evidence|ver
|
|
|
7537
7639
|
var LOCAL_VERIFICATION_RE = /typecheck|npm run (test|build|typecheck)|vitest|tsc\b|verify-pr-local|local verify|local-verify|tests? (pass|green)|build green|node --test/i;
|
|
7538
7640
|
var DOCS_TITLE_RE = /^docs[(:]/i;
|
|
7539
7641
|
var DOCS_BODY_RE = /docs[- ]only|documentation only|no[- ]code change|no code changes|low[- ]risk|plan tracker only|markdown only/i;
|
|
7540
|
-
function
|
|
7541
|
-
const title = typeof
|
|
7542
|
-
const body = typeof
|
|
7642
|
+
function runtimeVerificationEvidenceSufficient(input) {
|
|
7643
|
+
const title = typeof input.title === "string" ? input.title : "";
|
|
7644
|
+
const body = typeof input.body === "string" ? input.body : "";
|
|
7543
7645
|
const docsLowRisk = DOCS_TITLE_RE.test(title) || DOCS_BODY_RE.test(body);
|
|
7544
7646
|
const structuredSection = STRUCTURED_SECTION_RE.test(body);
|
|
7545
7647
|
const localVerification = LOCAL_VERIFICATION_RE.test(body);
|
|
7546
|
-
|
|
7547
|
-
|
|
7648
|
+
return docsLowRisk || structuredSection || localVerification || input.vercelCheckSuccess === true;
|
|
7649
|
+
}
|
|
7650
|
+
function assertVerificationEvidence(pr) {
|
|
7651
|
+
const sufficient = runtimeVerificationEvidenceSufficient({
|
|
7652
|
+
title: pr.title,
|
|
7653
|
+
body: pr.body,
|
|
7654
|
+
vercelCheckSuccess: vercelCheckSuccess(pr.statusCheckRollup)
|
|
7655
|
+
});
|
|
7656
|
+
if (sufficient) return;
|
|
7548
7657
|
throw new Error(
|
|
7549
7658
|
`PR #${pr.number} lacks landing verification evidence \u2014 add ## Test plan / ## Verification with local commands, Vercel preview, or docs/no-code rationale`
|
|
7550
7659
|
);
|
|
@@ -7645,6 +7754,14 @@ async function executeLandPrMerge(input) {
|
|
|
7645
7754
|
"mergeCommit"
|
|
7646
7755
|
].join(",")
|
|
7647
7756
|
]);
|
|
7757
|
+
if (before.state === "MERGED" || before.mergedAt) {
|
|
7758
|
+
return {
|
|
7759
|
+
prUrl: before.url || prTarget,
|
|
7760
|
+
outcome: "skipped",
|
|
7761
|
+
mergeCommit: before.mergeCommit?.oid ?? null,
|
|
7762
|
+
reason: `PR #${before.number} is already merged \u2014 land_pr no-op (redelivery)`
|
|
7763
|
+
};
|
|
7764
|
+
}
|
|
7648
7765
|
const notReadyReason = landingReadinessError(before);
|
|
7649
7766
|
if (notReadyReason) {
|
|
7650
7767
|
if (input.skipNotReady) {
|
|
@@ -7999,7 +8116,11 @@ async function dispatchRun(args) {
|
|
|
7999
8116
|
return abortClaimedSpawn(task, "land_pr task missing prUrl");
|
|
8000
8117
|
}
|
|
8001
8118
|
try {
|
|
8002
|
-
const report = await executeLandPrMerge({
|
|
8119
|
+
const report = await executeLandPrMerge({
|
|
8120
|
+
prUrl,
|
|
8121
|
+
repo: repoFromPrUrl(prUrl),
|
|
8122
|
+
cwd: run.repo
|
|
8123
|
+
});
|
|
8003
8124
|
const post = await postLandPrHarnessCompletion({
|
|
8004
8125
|
baseUrl: base,
|
|
8005
8126
|
secret,
|
|
@@ -8026,6 +8147,27 @@ async function dispatchRun(args) {
|
|
|
8026
8147
|
return abortClaimedSpawn(task, error.message);
|
|
8027
8148
|
}
|
|
8028
8149
|
}
|
|
8150
|
+
async function releaseDuplicateLocalClaim(task) {
|
|
8151
|
+
const error = "duplicate_dispatch_prevented: live local worker already owns this task";
|
|
8152
|
+
const release = await releaseDispatchClaimAfterSpawnFailure({
|
|
8153
|
+
baseUrl: base,
|
|
8154
|
+
secret,
|
|
8155
|
+
agentOsId,
|
|
8156
|
+
taskId: String(task.id),
|
|
8157
|
+
leaseOwner,
|
|
8158
|
+
failureDetail: error
|
|
8159
|
+
});
|
|
8160
|
+
outcomes.push({
|
|
8161
|
+
taskId: task.id,
|
|
8162
|
+
started: false,
|
|
8163
|
+
error,
|
|
8164
|
+
alreadyRunning: true,
|
|
8165
|
+
nonFatal: true,
|
|
8166
|
+
released: release.released,
|
|
8167
|
+
releaseResponse: release.releaseResponse
|
|
8168
|
+
});
|
|
8169
|
+
return false;
|
|
8170
|
+
}
|
|
8029
8171
|
async function spawnClaimed(decision) {
|
|
8030
8172
|
const task = decision.task;
|
|
8031
8173
|
const harnessContext = readHarnessWorkerContext(decision);
|
|
@@ -8047,10 +8189,7 @@ async function dispatchRun(args) {
|
|
|
8047
8189
|
);
|
|
8048
8190
|
}
|
|
8049
8191
|
if (hasLiveWorkerForTask(run.id, taskId)) {
|
|
8050
|
-
return
|
|
8051
|
-
task,
|
|
8052
|
-
"duplicate_dispatch_prevented: live local worker already owns this task"
|
|
8053
|
-
);
|
|
8192
|
+
return releaseDuplicateLocalClaim(task);
|
|
8054
8193
|
}
|
|
8055
8194
|
const attempt = Number(task.attempt) || 1;
|
|
8056
8195
|
if (attempt > retryLimits.maxTaskAttempts) {
|
|
@@ -8220,11 +8359,12 @@ async function dispatchRun(args) {
|
|
|
8220
8359
|
diskGate: result.diskGate,
|
|
8221
8360
|
resourceGate: result.resourceGate
|
|
8222
8361
|
};
|
|
8362
|
+
const fatalOutcome = (outcome) => !outcome.started && outcome.nonFatal !== true;
|
|
8223
8363
|
if (pipeline) {
|
|
8224
|
-
return { ok: !outcomes.some(
|
|
8364
|
+
return { ok: !outcomes.some(fatalOutcome), ...summary };
|
|
8225
8365
|
}
|
|
8226
8366
|
console.log(JSON.stringify(summary, null, 2));
|
|
8227
|
-
if (outcomes.some(
|
|
8367
|
+
if (outcomes.some(fatalOutcome)) process.exit(1);
|
|
8228
8368
|
} catch (error) {
|
|
8229
8369
|
if (pipeline) return { ok: false, error: error.message };
|
|
8230
8370
|
console.error(`run dispatch failed: ${error.message}`);
|
|
@@ -10151,23 +10291,6 @@ function materialWorktreeChanges2(changedFiles) {
|
|
|
10151
10291
|
});
|
|
10152
10292
|
}
|
|
10153
10293
|
|
|
10154
|
-
// src/cleanup-index-status.ts
|
|
10155
|
-
function indexedWorktreeStatus(entry) {
|
|
10156
|
-
if (!entry.status) {
|
|
10157
|
-
entry.status = computeWorkerStatus(entry.worker, {
|
|
10158
|
-
base: entry.run.base,
|
|
10159
|
-
baseCommit: entry.run.baseCommit
|
|
10160
|
-
});
|
|
10161
|
-
}
|
|
10162
|
-
return entry.status;
|
|
10163
|
-
}
|
|
10164
|
-
function indexedWorktreeHasMaterialChanges(entry) {
|
|
10165
|
-
if (entry.status) {
|
|
10166
|
-
return materialWorktreeChanges2(entry.status.changedFiles).length > 0;
|
|
10167
|
-
}
|
|
10168
|
-
return materialWorktreeChanges2(gitStatusShort(entry.worktreePath)).length > 0;
|
|
10169
|
-
}
|
|
10170
|
-
|
|
10171
10294
|
// src/cleanup-worktree-salvage.ts
|
|
10172
10295
|
function prUrlFromFinalResult(finalResult) {
|
|
10173
10296
|
if (typeof finalResult === "string") {
|
|
@@ -10194,6 +10317,83 @@ function isPrOrUnmergedWork(status) {
|
|
|
10194
10317
|
return false;
|
|
10195
10318
|
}
|
|
10196
10319
|
|
|
10320
|
+
// src/cleanup-index-status.ts
|
|
10321
|
+
function indexedWorktreeStatus(entry) {
|
|
10322
|
+
if (!entry.status) {
|
|
10323
|
+
entry.status = computeWorkerStatus(entry.worker, {
|
|
10324
|
+
base: entry.run.base,
|
|
10325
|
+
baseCommit: entry.run.baseCommit
|
|
10326
|
+
});
|
|
10327
|
+
}
|
|
10328
|
+
return entry.status;
|
|
10329
|
+
}
|
|
10330
|
+
function indexedWorktreeHasMaterialChanges(entry, gitStatusCache) {
|
|
10331
|
+
if (entry.status) {
|
|
10332
|
+
return materialWorktreeChanges2(entry.status.changedFiles).length > 0;
|
|
10333
|
+
}
|
|
10334
|
+
const porcelain = gitStatusCache ? gitStatusCache.porcelain(entry.worktreePath) : gitStatusShort(entry.worktreePath);
|
|
10335
|
+
return materialWorktreeChanges2(porcelain).length > 0;
|
|
10336
|
+
}
|
|
10337
|
+
function finalResultFromWorkerJson(entry) {
|
|
10338
|
+
const snapshot = entry.worker.completionSnapshot?.finalResult;
|
|
10339
|
+
if (snapshot !== void 0 && snapshot !== null) return snapshot;
|
|
10340
|
+
if (entry.worker.taskPrUrl) {
|
|
10341
|
+
return { prUrl: entry.worker.taskPrUrl };
|
|
10342
|
+
}
|
|
10343
|
+
return null;
|
|
10344
|
+
}
|
|
10345
|
+
function resolveWorktreeGuardStatus(entry, ctx) {
|
|
10346
|
+
if (entry.status) return entry.status;
|
|
10347
|
+
const worker = entry.worker;
|
|
10348
|
+
const completionAcknowledged = typeof worker.completionReportedAt === "string" && worker.completionReportedAt.trim().length > 0;
|
|
10349
|
+
const workerJsonTerminal = Boolean(worker.status && ["done", "exited", "blocked", "failed", "abandoned"].includes(worker.status)) || completionAcknowledged;
|
|
10350
|
+
const finalResult = finalResultFromWorkerJson(entry);
|
|
10351
|
+
if (workerJsonTerminal && !isPidAlive(worker.pid)) {
|
|
10352
|
+
const changedFiles = ctx?.gitStatusCache ? ctx.gitStatusCache.porcelain(entry.worktreePath) : gitStatusShort(entry.worktreePath);
|
|
10353
|
+
const baseLabel = entry.run.baseCommit?.trim() || entry.run.base?.trim() || "origin/main";
|
|
10354
|
+
const ahead = ctx?.gitRevCache?.countAheadOfMain(entry.worktreePath, baseLabel);
|
|
10355
|
+
const gitAncestry = ahead === 0 ? {
|
|
10356
|
+
checked: true,
|
|
10357
|
+
base: baseLabel,
|
|
10358
|
+
relation: "synced"
|
|
10359
|
+
} : computeGitAncestry(entry.worktreePath, {
|
|
10360
|
+
base: entry.run.base,
|
|
10361
|
+
baseCommit: entry.run.baseCommit
|
|
10362
|
+
});
|
|
10363
|
+
const status = {
|
|
10364
|
+
runId: entry.runId,
|
|
10365
|
+
worker: entry.workerName,
|
|
10366
|
+
pid: worker.pid,
|
|
10367
|
+
alive: false,
|
|
10368
|
+
status: worker.status ?? (completionAcknowledged ? "done" : "exited"),
|
|
10369
|
+
attention: { state: completionAcknowledged ? "done" : "stale" },
|
|
10370
|
+
branch: worker.branch,
|
|
10371
|
+
worktreePath: entry.worktreePath,
|
|
10372
|
+
ownedPaths: worker.ownedPaths,
|
|
10373
|
+
stdoutBytes: 0,
|
|
10374
|
+
stderrBytes: 0,
|
|
10375
|
+
heartbeatBytes: 0,
|
|
10376
|
+
firstEventAt: null,
|
|
10377
|
+
lastEventAt: null,
|
|
10378
|
+
lastActivityAt: worker.completionReportedAt ?? null,
|
|
10379
|
+
currentTool: null,
|
|
10380
|
+
heartbeatCount: 0,
|
|
10381
|
+
lastHeartbeatAt: null,
|
|
10382
|
+
lastHeartbeatPhase: null,
|
|
10383
|
+
lastHeartbeatSummary: null,
|
|
10384
|
+
heartbeatBlocker: null,
|
|
10385
|
+
changedFiles,
|
|
10386
|
+
gitAncestry,
|
|
10387
|
+
finalResult,
|
|
10388
|
+
completionBlocker: typeof worker.completionBlocker === "string" ? worker.completionBlocker.trim() || null : null,
|
|
10389
|
+
prUrl: worker.repairTargetPrUrl ?? worker.taskPrUrl ?? prUrlFromFinalResult(finalResult)
|
|
10390
|
+
};
|
|
10391
|
+
entry.status = status;
|
|
10392
|
+
return status;
|
|
10393
|
+
}
|
|
10394
|
+
return indexedWorktreeStatus(entry);
|
|
10395
|
+
}
|
|
10396
|
+
|
|
10197
10397
|
// src/cleanup-completion-blocker.ts
|
|
10198
10398
|
function completionBlockerBlocksWorktreeRemoval(indexed, status) {
|
|
10199
10399
|
const blocker = typeof indexed.worker.completionBlocker === "string" ? indexed.worker.completionBlocker.trim() : "";
|
|
@@ -10214,13 +10414,28 @@ function completionBlockerBlocksWorktreeRemoval(indexed, status) {
|
|
|
10214
10414
|
}
|
|
10215
10415
|
|
|
10216
10416
|
// src/cleanup-run-liveness.ts
|
|
10417
|
+
var TERMINAL_WORKER_JSON_STATUSES = /* @__PURE__ */ new Set([
|
|
10418
|
+
"done",
|
|
10419
|
+
"exited",
|
|
10420
|
+
"blocked",
|
|
10421
|
+
"failed",
|
|
10422
|
+
"abandoned"
|
|
10423
|
+
]);
|
|
10217
10424
|
function deriveRunTerminal(indexed, ctx) {
|
|
10218
10425
|
if (ctx) return ctx.runTerminalCache.derive(indexed.run);
|
|
10219
10426
|
return deriveTerminalRunStatus(indexed.run);
|
|
10220
10427
|
}
|
|
10221
10428
|
function isWorkerProcessLive(indexed) {
|
|
10222
10429
|
if (isPidAlive(indexed.worker.pid)) return true;
|
|
10223
|
-
if (
|
|
10430
|
+
if (typeof indexed.worker.completionReportedAt === "string" && indexed.worker.completionReportedAt.trim().length > 0) {
|
|
10431
|
+
return false;
|
|
10432
|
+
}
|
|
10433
|
+
const workerStatus2 = indexed.worker.status;
|
|
10434
|
+
if (workerStatus2 && TERMINAL_WORKER_JSON_STATUSES.has(workerStatus2)) return false;
|
|
10435
|
+
if (!indexed.worker.pid) {
|
|
10436
|
+
if (workerStatus2 !== "running") return false;
|
|
10437
|
+
return indexedWorktreeStatus(indexed).alive;
|
|
10438
|
+
}
|
|
10224
10439
|
return false;
|
|
10225
10440
|
}
|
|
10226
10441
|
function isRunStaleActive(indexed, ctx) {
|
|
@@ -10229,6 +10444,10 @@ function isRunStaleActive(indexed, ctx) {
|
|
|
10229
10444
|
}
|
|
10230
10445
|
function runBlocksWorktreeRemoval(indexed, ctx) {
|
|
10231
10446
|
if (isWorkerProcessLive(indexed)) return true;
|
|
10447
|
+
const workerStatus2 = indexed.worker.status;
|
|
10448
|
+
if (workerStatus2 && TERMINAL_WORKER_JSON_STATUSES.has(workerStatus2) && !indexed.worker.completionBlocker) {
|
|
10449
|
+
return false;
|
|
10450
|
+
}
|
|
10232
10451
|
const status = indexedWorktreeStatus(indexed);
|
|
10233
10452
|
if (completionBlockerBlocksWorktreeRemoval(indexed, status)) return true;
|
|
10234
10453
|
if (isFinishedWorkerStatus(status)) return false;
|
|
@@ -10247,7 +10466,7 @@ function effectiveWorktreeAgeMs(input) {
|
|
|
10247
10466
|
if (input.liveness && isRunStaleActive(indexed, input.liveness)) {
|
|
10248
10467
|
return terminalWorktreesAgeMs;
|
|
10249
10468
|
}
|
|
10250
|
-
if (input.liveness && isFinishedWorkerStatus(
|
|
10469
|
+
if (input.liveness && isFinishedWorkerStatus(resolveWorktreeGuardStatus(indexed, input.liveness)) && !isWorkerProcessLive(indexed)) {
|
|
10251
10470
|
return terminalWorktreesAgeMs;
|
|
10252
10471
|
}
|
|
10253
10472
|
return worktreesAgeMs;
|
|
@@ -10261,8 +10480,13 @@ function skipWorktreeRemoval(input) {
|
|
|
10261
10480
|
const ageThresholdMs = effectiveWorktreeAgeMs(input);
|
|
10262
10481
|
if (worktreesAgeMs <= 0 && !includeOrphans && ageThresholdMs <= 0) return "worktrees_disabled";
|
|
10263
10482
|
if (ageThresholdMs > 0 && ageMs < ageThresholdMs) return "below_age_threshold";
|
|
10264
|
-
const status = indexedWorktreeStatus(indexed);
|
|
10265
10483
|
if (isWorkerProcessLive(indexed)) return "active_worker";
|
|
10484
|
+
if (indexedWorktreeHasMaterialChanges(indexed, input.liveness?.gitStatusCache)) {
|
|
10485
|
+
return "dirty_worktree";
|
|
10486
|
+
}
|
|
10487
|
+
const ahead = input.liveness?.gitRevCache?.countAheadOfMain(input.worktreePath);
|
|
10488
|
+
if (ahead !== null && ahead !== void 0 && ahead > 0) return "pr_or_unmerged_commits";
|
|
10489
|
+
const status = resolveWorktreeGuardStatus(indexed, input.liveness);
|
|
10266
10490
|
if (completionBlockerBlocksWorktreeRemoval(indexed, status)) return "completion_blocked";
|
|
10267
10491
|
if (runBlocksWorktreeRemoval(indexed, input.liveness)) return "run_still_active";
|
|
10268
10492
|
if (!isFinishedWorkerStatus(status)) return "run_still_active";
|
|
@@ -10293,7 +10517,9 @@ function skipDependencyCacheRemoval(input) {
|
|
|
10293
10517
|
if (!diskPressure && ageMs < nodeModulesAgeMs) return "below_age_threshold";
|
|
10294
10518
|
if (activeWorktreePaths.has(path42.resolve(worktreePath))) return "active_worker";
|
|
10295
10519
|
if (indexed && isWorkerProcessLive(indexed)) return "active_worker";
|
|
10296
|
-
if (indexed && indexedWorktreeHasMaterialChanges(indexed))
|
|
10520
|
+
if (indexed && indexedWorktreeHasMaterialChanges(indexed, input.gitStatusCache)) {
|
|
10521
|
+
return "dirty_worktree";
|
|
10522
|
+
}
|
|
10297
10523
|
return null;
|
|
10298
10524
|
}
|
|
10299
10525
|
function skipBuildCacheRemoval(input) {
|
|
@@ -11276,6 +11502,37 @@ function emitCleanupProgress(phase, detail) {
|
|
|
11276
11502
|
console.error(`[kynver cleanup] ${phase}${suffix}`);
|
|
11277
11503
|
}
|
|
11278
11504
|
|
|
11505
|
+
// src/cleanup-git-rev-cache.ts
|
|
11506
|
+
var CleanupGitRevCache = class {
|
|
11507
|
+
aheadOfMain = /* @__PURE__ */ new Map();
|
|
11508
|
+
countAheadOfMain(worktreePath, base = "origin/main") {
|
|
11509
|
+
const key = `${worktreePath}\0${base}`;
|
|
11510
|
+
if (this.aheadOfMain.has(key)) return this.aheadOfMain.get(key) ?? null;
|
|
11511
|
+
const result = gitCapture(worktreePath, ["rev-list", "--count", `${base}..HEAD`]);
|
|
11512
|
+
if (result.status !== 0) {
|
|
11513
|
+
this.aheadOfMain.set(key, null);
|
|
11514
|
+
return null;
|
|
11515
|
+
}
|
|
11516
|
+
const count = Number(result.stdout.trim());
|
|
11517
|
+
const parsed = Number.isFinite(count) ? count : null;
|
|
11518
|
+
this.aheadOfMain.set(key, parsed);
|
|
11519
|
+
return parsed;
|
|
11520
|
+
}
|
|
11521
|
+
};
|
|
11522
|
+
|
|
11523
|
+
// src/cleanup-git-status-cache.ts
|
|
11524
|
+
var CleanupGitStatusCache = class {
|
|
11525
|
+
cache = /* @__PURE__ */ new Map();
|
|
11526
|
+
porcelain(worktreePath) {
|
|
11527
|
+
const resolved = worktreePath;
|
|
11528
|
+
const cached = this.cache.get(resolved);
|
|
11529
|
+
if (cached !== void 0) return cached;
|
|
11530
|
+
const lines = gitStatusShort(resolved);
|
|
11531
|
+
this.cache.set(resolved, lines);
|
|
11532
|
+
return lines;
|
|
11533
|
+
}
|
|
11534
|
+
};
|
|
11535
|
+
|
|
11279
11536
|
// src/cleanup-run-terminal-cache.ts
|
|
11280
11537
|
var CleanupRunTerminalCache = class {
|
|
11281
11538
|
cache = /* @__PURE__ */ new Map();
|
|
@@ -11393,7 +11650,11 @@ function runHarnessCleanup(options = {}) {
|
|
|
11393
11650
|
emitCleanupProgress("index", "building worktree index");
|
|
11394
11651
|
const index = mergeWorktreeIndexes(paths.scanRoots);
|
|
11395
11652
|
emitCleanupProgress("index", `${index.size} indexed worktree(s)`);
|
|
11396
|
-
const liveness = {
|
|
11653
|
+
const liveness = {
|
|
11654
|
+
runTerminalCache: new CleanupRunTerminalCache(),
|
|
11655
|
+
gitStatusCache: new CleanupGitStatusCache(),
|
|
11656
|
+
gitRevCache: new CleanupGitRevCache()
|
|
11657
|
+
};
|
|
11397
11658
|
const skips = [];
|
|
11398
11659
|
const actions = [];
|
|
11399
11660
|
const processedPaths = /* @__PURE__ */ new Set();
|
|
@@ -11413,8 +11674,15 @@ function runHarnessCleanup(options = {}) {
|
|
|
11413
11674
|
index,
|
|
11414
11675
|
now: paths.now
|
|
11415
11676
|
};
|
|
11416
|
-
|
|
11677
|
+
const dependencyCandidates = scanDependencyCacheCandidates(scanOpts);
|
|
11678
|
+
emitCleanupProgress("dependency", `${dependencyCandidates.length} cache candidate(s) at ${harnessRoot}`);
|
|
11679
|
+
let dependencyProcessed = 0;
|
|
11680
|
+
for (const raw of dependencyCandidates) {
|
|
11417
11681
|
if (atSweepCap()) break;
|
|
11682
|
+
dependencyProcessed += 1;
|
|
11683
|
+
if (dependencyProcessed % 50 === 0) {
|
|
11684
|
+
emitCleanupProgress("dependency", `${dependencyProcessed}/${dependencyCandidates.length} evaluated`);
|
|
11685
|
+
}
|
|
11418
11686
|
const resolved = path53.resolve(raw.path);
|
|
11419
11687
|
if (processedPaths.has(resolved)) continue;
|
|
11420
11688
|
processedPaths.add(resolved);
|
|
@@ -11434,7 +11702,8 @@ function runHarnessCleanup(options = {}) {
|
|
|
11434
11702
|
ageMs: candidate.ageMs,
|
|
11435
11703
|
worktreePath,
|
|
11436
11704
|
activeWorktreePaths: activeGuards.activeWorktreePaths,
|
|
11437
|
-
diskPressure: retention.diskPressure
|
|
11705
|
+
diskPressure: retention.diskPressure,
|
|
11706
|
+
gitStatusCache: liveness.gitStatusCache
|
|
11438
11707
|
});
|
|
11439
11708
|
if (guardReason) {
|
|
11440
11709
|
recordSkip(skips, candidate.path, guardReason);
|
|
@@ -11469,7 +11738,8 @@ function runHarnessCleanup(options = {}) {
|
|
|
11469
11738
|
ageMs: candidate.ageMs,
|
|
11470
11739
|
worktreePath,
|
|
11471
11740
|
activeWorktreePaths: activeGuards.activeWorktreePaths,
|
|
11472
|
-
diskPressure: retention.diskPressure
|
|
11741
|
+
diskPressure: retention.diskPressure,
|
|
11742
|
+
gitStatusCache: liveness.gitStatusCache
|
|
11473
11743
|
});
|
|
11474
11744
|
if (guardReason) {
|
|
11475
11745
|
recordSkip(skips, candidate.path, guardReason);
|
|
@@ -11489,8 +11759,13 @@ function runHarnessCleanup(options = {}) {
|
|
|
11489
11759
|
];
|
|
11490
11760
|
emitCleanupProgress("worktrees", `${worktreeCandidates.length} candidate(s) at ${harnessRoot}`);
|
|
11491
11761
|
const worktreeSeen = /* @__PURE__ */ new Set();
|
|
11762
|
+
let worktreeProcessed = 0;
|
|
11492
11763
|
for (const raw of worktreeCandidates) {
|
|
11493
11764
|
if (atSweepCap()) break;
|
|
11765
|
+
worktreeProcessed += 1;
|
|
11766
|
+
if (worktreeProcessed % 50 === 0) {
|
|
11767
|
+
emitCleanupProgress("worktrees", `${worktreeProcessed}/${worktreeCandidates.length} evaluated`);
|
|
11768
|
+
}
|
|
11494
11769
|
const resolved = path53.resolve(raw.path);
|
|
11495
11770
|
if (worktreeSeen.has(resolved)) continue;
|
|
11496
11771
|
worktreeSeen.add(resolved);
|
|
@@ -11771,11 +12046,29 @@ function validateDaemonInstallIdentity(config = loadUserConfig(), env = process.
|
|
|
11771
12046
|
};
|
|
11772
12047
|
}
|
|
11773
12048
|
|
|
12049
|
+
// src/daemon-platform-guard.ts
|
|
12050
|
+
function envFlag3(name) {
|
|
12051
|
+
const raw = process.env[name]?.trim().toLowerCase();
|
|
12052
|
+
return raw === "1" || raw === "true" || raw === "yes" || raw === "on";
|
|
12053
|
+
}
|
|
12054
|
+
function assertNativeDaemonAllowed() {
|
|
12055
|
+
if (process.platform !== "win32") return;
|
|
12056
|
+
if (envFlag3("KYNVER_DAEMON_ALLOW_NATIVE_WINDOWS")) return;
|
|
12057
|
+
console.error(
|
|
12058
|
+
JSON.stringify({
|
|
12059
|
+
event: "daemon_start_blocked",
|
|
12060
|
+
reason: "native_windows_console_flash",
|
|
12061
|
+
remedy: "Run the daemon inside WSL: .\\scripts\\start-tier2-wsl.ps1 \u2014 or set KYNVER_DAEMON_ALLOW_NATIVE_WINDOWS=1 to override (flashes visible consoles)."
|
|
12062
|
+
})
|
|
12063
|
+
);
|
|
12064
|
+
process.exit(1);
|
|
12065
|
+
}
|
|
12066
|
+
|
|
11774
12067
|
// src/cron/cron-env.ts
|
|
11775
12068
|
import { existsSync as existsSync42 } from "node:fs";
|
|
11776
12069
|
import { homedir as homedir14 } from "node:os";
|
|
11777
12070
|
import path55 from "node:path";
|
|
11778
|
-
function
|
|
12071
|
+
function envFlag4(name, defaultValue) {
|
|
11779
12072
|
const raw = process.env[name]?.trim().toLowerCase();
|
|
11780
12073
|
if (!raw) return defaultValue;
|
|
11781
12074
|
if (raw === "0" || raw === "false" || raw === "no" || raw === "off") return false;
|
|
@@ -11811,14 +12104,14 @@ function resolveKynverCronEnv() {
|
|
|
11811
12104
|
const secret = resolveKynverCronSecret();
|
|
11812
12105
|
const credsReady = Boolean(fireBaseUrl && secret);
|
|
11813
12106
|
const storeExists = existsSync42(storePath);
|
|
11814
|
-
const defaultEnabled = credsReady && (storeExists ||
|
|
12107
|
+
const defaultEnabled = credsReady && (storeExists || envFlag4("KYNVER_CRON_TICK_FORCE", false));
|
|
11815
12108
|
return {
|
|
11816
12109
|
storePath,
|
|
11817
12110
|
statePath,
|
|
11818
12111
|
lockPath: `${statePath}.lock`,
|
|
11819
12112
|
fireBaseUrl,
|
|
11820
12113
|
secret,
|
|
11821
|
-
tickEnabled:
|
|
12114
|
+
tickEnabled: envFlag4("KYNVER_CRON_TICK_ENABLED", defaultEnabled),
|
|
11822
12115
|
tickIntervalMs: envInt("KYNVER_CRON_TICK_INTERVAL_MS", 6e4, 5e3),
|
|
11823
12116
|
missedRunPolicy: process.env.KYNVER_CRON_MISSED_RUN_POLICY?.trim().toLowerCase() === "skip" ? "skip" : "catch_up",
|
|
11824
12117
|
maxCatchUpPerTick: envInt("KYNVER_CRON_MAX_CATCH_UP_PER_TICK", 3, 0),
|
|
@@ -12610,6 +12903,7 @@ async function awaitDaemonBackoff(ms, isStopping) {
|
|
|
12610
12903
|
}
|
|
12611
12904
|
}
|
|
12612
12905
|
async function runDaemon(args) {
|
|
12906
|
+
assertNativeDaemonAllowed();
|
|
12613
12907
|
const runId = String(required(String(args.run || ""), "--run"));
|
|
12614
12908
|
const agentOsId = String(required(String(args.agentOsId || loadUserConfig().agentOsId || ""), "--agent-os-id"));
|
|
12615
12909
|
const execute = args.execute !== false && args.execute !== "false";
|
|
@@ -14713,12 +15007,12 @@ function assessRuntimeTakeoverScheduler(env, ctx) {
|
|
|
14713
15007
|
return check({
|
|
14714
15008
|
id: "hotspot_openclaw_scheduler",
|
|
14715
15009
|
label: "Scheduler provider (runtime daemon vs OpenClaw cron)",
|
|
14716
|
-
status: "
|
|
14717
|
-
summary: "
|
|
14718
|
-
remediation: "
|
|
15010
|
+
status: "warn",
|
|
15011
|
+
summary: "Hosted deployment with no QSTASH_TOKEN and no KYNVER_SCHEDULER_PROVIDER \u2014 kynver-cron is an in-process stub here and will NOT fire; no firing scheduler is configured",
|
|
15012
|
+
remediation: "Set QSTASH_TOKEN + KYNVER_SCHEDULER_PROVIDER=qstash on the Kynver server for hosted AgentOS schedules. Only use kynver-cron when a `kynver daemon` (or local cron store) actually owns firing on this box.",
|
|
14719
15013
|
details: {
|
|
14720
15014
|
schedulerProvider: null,
|
|
14721
|
-
resolvedFallback: "
|
|
15015
|
+
resolvedFallback: "none",
|
|
14722
15016
|
qstashTokenPresent: false,
|
|
14723
15017
|
hostedDeployment
|
|
14724
15018
|
}
|
|
@@ -15520,14 +15814,15 @@ function usage(code = 0) {
|
|
|
15520
15814
|
" kynver runner credential [--agent-os-id ID] [--base-url URL]",
|
|
15521
15815
|
" kynver setup [--api-base-url URL] [--agent-os-id ID] [--agent-os-slug SLUG] [--box-kind forge|ghost] [--repo PATH] [--discover-repo] [--max-workers N] [--provider claude|cursor]",
|
|
15522
15816
|
" kynver daemon --run RUN_ID --agent-os-id AOS_ID [--execute] [--interval-ms MS]",
|
|
15817
|
+
" kynver status --run RUN_ID [--blocked] [--running] [--task TASK_ID] [--worker WORKER] [--full] # top-level compact run status",
|
|
15523
15818
|
" kynver run create [--repo /path/repo] [--name name] [--base origin/main]",
|
|
15524
15819
|
" kynver run list",
|
|
15525
15820
|
" kynver run resolve --name RUN_NAME",
|
|
15526
|
-
" kynver run status --run RUN_ID [--
|
|
15821
|
+
" kynver run status --run RUN_ID [--full] # defaults to compact shallow map with drill-down commands",
|
|
15527
15822
|
" kynver run dispatch --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--execute] [--lane any|implementation|review|landing] [--target-task-id TASK_ID] [--executor harness] [--max-starts 1] [--lease-ms MS] [--owned path[,path]] [--model claude-opus-4-8] [--disk-path /] [--reconcile-stale-blockers]",
|
|
15528
15823
|
" kynver run sweep --run RUN_ID --agent-os-id AOS_ID [--base-url URL] [--secret SECRET] [--grace-ms MS]",
|
|
15529
15824
|
' kynver worker start --run RUN_ID --name worker --task "..." [--owned path[,path]] [--model MODEL] [--provider claude|cursor] [--agent-os-id AOS_ID] [--task-id TASK_ID] [--wait]',
|
|
15530
|
-
" kynver worker list --run RUN_ID [--
|
|
15825
|
+
" kynver worker list --run RUN_ID [--full] # defaults to compact shallow map with drill-down commands",
|
|
15531
15826
|
" kynver worker status --run RUN_ID --name worker",
|
|
15532
15827
|
" kynver worker tail --run RUN_ID --name worker [--lines 40] [--raw]",
|
|
15533
15828
|
" kynver worker stop --run RUN_ID --name worker",
|
|
@@ -15581,6 +15876,9 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15581
15876
|
const { runsDir, worktreesDir } = getPaths();
|
|
15582
15877
|
mkdirSync10(runsDir, { recursive: true });
|
|
15583
15878
|
mkdirSync10(worktreesDir, { recursive: true });
|
|
15879
|
+
if (scope === "daemon") {
|
|
15880
|
+
assertNativeDaemonAllowed();
|
|
15881
|
+
}
|
|
15584
15882
|
if (shouldEnforceMemoryCostPackageGuardCli(scope, action)) {
|
|
15585
15883
|
let repoRoot;
|
|
15586
15884
|
const runId = args.run ? String(args.run).trim() : "";
|
|
@@ -15597,6 +15895,7 @@ async function main(argv = process.argv.slice(2)) {
|
|
|
15597
15895
|
});
|
|
15598
15896
|
}
|
|
15599
15897
|
if (scope === "login") return void await runLogin(args);
|
|
15898
|
+
if (scope === "status") return runStatus(args);
|
|
15600
15899
|
if (scope === "runner" && action === "credential") return void await mintRunnerCredential(args);
|
|
15601
15900
|
if (scope === "setup") return void await runSetup(args);
|
|
15602
15901
|
if (scope === "daemon") return void await runDaemon(args);
|