@kynver-app/runtime 0.1.105 → 0.1.108
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/cli.js +386 -19
- package/dist/cli.js.map +4 -4
- package/dist/index.js +389 -22
- package/dist/index.js.map +4 -4
- package/dist/landing/cli-auth.d.ts +7 -0
- package/dist/landing/land-pr-completion-post.d.ts +12 -0
- package/dist/landing/land-pr.d.ts +20 -0
- package/dist/server/cleanup.js.map +1 -1
- package/dist/server/default-repo.js.map +1 -1
- package/dist/server/memory-cost-enforce.js.map +1 -1
- package/dist/verify-live/verify-live-prompt.d.ts +2 -0
- package/dist/worker-persona-catalog.js +2 -2
- package/dist/worker-persona-catalog.js.map +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -350,7 +350,9 @@ function redactHomePath(value) {
|
|
|
350
350
|
if (resolved.startsWith(`${home}${path2.sep}`)) {
|
|
351
351
|
return `~/${path2.relative(home, resolved).split(path2.sep).join("/")}`;
|
|
352
352
|
}
|
|
353
|
-
|
|
353
|
+
const posix = resolved.replace(/\\/g, "/");
|
|
354
|
+
const redacted = posix.replace(/^\/home\/[^/]+(?=\/|$)/, "~").replace(/^\/Users\/[^/]+(?=\/|$)/, "~").replace(/^[A-Za-z]:\/home\/[^/]+(?=\/|$)/i, "~").replace(/^[A-Za-z]:\/Users\/[^/]+(?=\/|$)/i, "~");
|
|
355
|
+
return redacted;
|
|
354
356
|
}
|
|
355
357
|
function displayUserPath(value) {
|
|
356
358
|
return redactHomePath(value);
|
|
@@ -3048,14 +3050,14 @@ var WORKER_PERSONA_CATALOG = [
|
|
|
3048
3050
|
{
|
|
3049
3051
|
slug: "lorentz",
|
|
3050
3052
|
displayName: "Lorentz",
|
|
3051
|
-
description: "
|
|
3053
|
+
description: "Deep/adversarial review lane expert for risk, correctness, and safety gates. Run adversarial review and validation gating.",
|
|
3052
3054
|
dispatchLane: "review",
|
|
3053
3055
|
defaultRoleLane: "report_reviewer"
|
|
3054
3056
|
},
|
|
3055
3057
|
{
|
|
3056
3058
|
slug: "dalton",
|
|
3057
3059
|
displayName: "Dalton",
|
|
3058
|
-
description: "Landing
|
|
3060
|
+
description: "Landing-only \u2014 merge-ready handoff and final verification evidence; no implementation ownership.",
|
|
3059
3061
|
dispatchLane: "landing",
|
|
3060
3062
|
defaultRoleLane: "implementer"
|
|
3061
3063
|
}
|
|
@@ -7437,6 +7439,325 @@ async function releaseDispatchClaimAfterSpawnFailure(input) {
|
|
|
7437
7439
|
};
|
|
7438
7440
|
}
|
|
7439
7441
|
|
|
7442
|
+
// src/landing/land-pr.ts
|
|
7443
|
+
import { spawnSync as spawnSync5 } from "node:child_process";
|
|
7444
|
+
|
|
7445
|
+
// src/landing/cli-auth.ts
|
|
7446
|
+
import { spawnSync as spawnSync4 } from "node:child_process";
|
|
7447
|
+
function ensureGitHubTokenFromCliAuth() {
|
|
7448
|
+
if (process.env.GITHUB_TOKEN?.trim() || process.env.GH_TOKEN?.trim()) {
|
|
7449
|
+
return {
|
|
7450
|
+
source: "env",
|
|
7451
|
+
configured: true,
|
|
7452
|
+
reason: "GitHub token already configured in environment"
|
|
7453
|
+
};
|
|
7454
|
+
}
|
|
7455
|
+
const result = spawnSync4("gh", ["auth", "token"], {
|
|
7456
|
+
encoding: "utf8",
|
|
7457
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
7458
|
+
});
|
|
7459
|
+
if (result.status !== 0) {
|
|
7460
|
+
const reason = typeof result.stderr === "string" && result.stderr.trim() ? result.stderr.trim() : "gh auth token failed; run `gh auth login` on this machine";
|
|
7461
|
+
return { source: "missing", configured: false, reason };
|
|
7462
|
+
}
|
|
7463
|
+
const token = typeof result.stdout === "string" ? result.stdout.trim() : "";
|
|
7464
|
+
if (!token) {
|
|
7465
|
+
return {
|
|
7466
|
+
source: "missing",
|
|
7467
|
+
configured: false,
|
|
7468
|
+
reason: "gh auth token returned an empty token; run `gh auth login` on this machine"
|
|
7469
|
+
};
|
|
7470
|
+
}
|
|
7471
|
+
process.env.GH_TOKEN = token;
|
|
7472
|
+
return {
|
|
7473
|
+
source: "gh-cli",
|
|
7474
|
+
configured: true,
|
|
7475
|
+
reason: "Using local GitHub CLI auth for daemon land_pr merge"
|
|
7476
|
+
};
|
|
7477
|
+
}
|
|
7478
|
+
|
|
7479
|
+
// src/landing/land-pr.ts
|
|
7480
|
+
var SUCCESSFUL_CHECK_CONCLUSIONS = /* @__PURE__ */ new Set(["SUCCESS", "SKIPPED", "NEUTRAL"]);
|
|
7481
|
+
var READY_MERGE_STATES = /* @__PURE__ */ new Set(["CLEAN", "HAS_HOOKS"]);
|
|
7482
|
+
function repoArgs(repo) {
|
|
7483
|
+
return repo?.trim() ? ["--repo", repo.trim()] : [];
|
|
7484
|
+
}
|
|
7485
|
+
function ghJson(exec, cwd, args) {
|
|
7486
|
+
const res = exec.gh(cwd, args);
|
|
7487
|
+
if (res.status !== 0) {
|
|
7488
|
+
throw new Error(res.stderr || res.stdout || `gh ${args.join(" ")} failed`);
|
|
7489
|
+
}
|
|
7490
|
+
return JSON.parse(res.stdout || "{}");
|
|
7491
|
+
}
|
|
7492
|
+
function checkName(check3) {
|
|
7493
|
+
return typeof check3.name === "string" && check3.name || typeof check3.context === "string" && check3.context || typeof check3.workflowName === "string" && check3.workflowName || "unknown check";
|
|
7494
|
+
}
|
|
7495
|
+
function classifyChecks(statusCheckRollup) {
|
|
7496
|
+
const checks = Array.isArray(statusCheckRollup) ? statusCheckRollup : [];
|
|
7497
|
+
const pending = [];
|
|
7498
|
+
const failed = [];
|
|
7499
|
+
for (const raw of checks) {
|
|
7500
|
+
const check3 = raw && typeof raw === "object" ? raw : {};
|
|
7501
|
+
const conclusion = typeof check3.conclusion === "string" ? check3.conclusion.toUpperCase() : "";
|
|
7502
|
+
const status = typeof check3.status === "string" ? check3.status.toUpperCase() : "";
|
|
7503
|
+
const state = typeof check3.state === "string" ? check3.state.toUpperCase() : "";
|
|
7504
|
+
if (conclusion && SUCCESSFUL_CHECK_CONCLUSIONS.has(conclusion)) continue;
|
|
7505
|
+
if (conclusion) {
|
|
7506
|
+
failed.push(`${checkName(check3)}=${conclusion}`);
|
|
7507
|
+
continue;
|
|
7508
|
+
}
|
|
7509
|
+
if (state && SUCCESSFUL_CHECK_CONCLUSIONS.has(state)) continue;
|
|
7510
|
+
if (state && state !== "PENDING") {
|
|
7511
|
+
failed.push(`${checkName(check3)}=${state}`);
|
|
7512
|
+
continue;
|
|
7513
|
+
}
|
|
7514
|
+
if (state === "PENDING") {
|
|
7515
|
+
pending.push(`${checkName(check3)}=${state}`);
|
|
7516
|
+
continue;
|
|
7517
|
+
}
|
|
7518
|
+
if (status && status !== "COMPLETED") {
|
|
7519
|
+
pending.push(`${checkName(check3)}=${status}`);
|
|
7520
|
+
continue;
|
|
7521
|
+
}
|
|
7522
|
+
pending.push(`${checkName(check3)}=PENDING`);
|
|
7523
|
+
}
|
|
7524
|
+
return { pending, failed };
|
|
7525
|
+
}
|
|
7526
|
+
function vercelCheckSuccess(statusCheckRollup) {
|
|
7527
|
+
const checks = Array.isArray(statusCheckRollup) ? statusCheckRollup : [];
|
|
7528
|
+
return checks.some((raw) => {
|
|
7529
|
+
const check3 = raw && typeof raw === "object" ? raw : {};
|
|
7530
|
+
const name = typeof check3.name === "string" && check3.name || typeof check3.context === "string" && check3.context || "";
|
|
7531
|
+
const conclusion = typeof check3.conclusion === "string" ? check3.conclusion.toUpperCase() : "";
|
|
7532
|
+
const state = typeof check3.state === "string" ? check3.state.toUpperCase() : "";
|
|
7533
|
+
return /^vercel/i.test(name) && (conclusion === "SUCCESS" || state === "SUCCESS");
|
|
7534
|
+
});
|
|
7535
|
+
}
|
|
7536
|
+
var STRUCTURED_SECTION_RE = /^##\s*(test\s*plan|verification|test\s*evidence|verify)\b/im;
|
|
7537
|
+
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
|
+
var DOCS_TITLE_RE = /^docs[(:]/i;
|
|
7539
|
+
var DOCS_BODY_RE = /docs[- ]only|documentation only|no[- ]code change|no code changes|low[- ]risk|plan tracker only|markdown only/i;
|
|
7540
|
+
function assertVerificationEvidence(pr) {
|
|
7541
|
+
const title = typeof pr.title === "string" ? pr.title : "";
|
|
7542
|
+
const body = typeof pr.body === "string" ? pr.body : "";
|
|
7543
|
+
const docsLowRisk = DOCS_TITLE_RE.test(title) || DOCS_BODY_RE.test(body);
|
|
7544
|
+
const structuredSection = STRUCTURED_SECTION_RE.test(body);
|
|
7545
|
+
const localVerification = LOCAL_VERIFICATION_RE.test(body);
|
|
7546
|
+
const vercelOk = vercelCheckSuccess(pr.statusCheckRollup);
|
|
7547
|
+
if (docsLowRisk || structuredSection || localVerification || vercelOk) return;
|
|
7548
|
+
throw new Error(
|
|
7549
|
+
`PR #${pr.number} lacks landing verification evidence \u2014 add ## Test plan / ## Verification with local commands, Vercel preview, or docs/no-code rationale`
|
|
7550
|
+
);
|
|
7551
|
+
}
|
|
7552
|
+
function assertLandingReady(pr) {
|
|
7553
|
+
if (pr.state !== "OPEN") throw new Error(`PR #${pr.number} is ${pr.state}, not OPEN`);
|
|
7554
|
+
if (pr.isDraft) throw new Error(`PR #${pr.number} is still a draft`);
|
|
7555
|
+
if (!READY_MERGE_STATES.has(pr.mergeStateStatus)) {
|
|
7556
|
+
throw new Error(`PR #${pr.number} mergeStateStatus is ${pr.mergeStateStatus}`);
|
|
7557
|
+
}
|
|
7558
|
+
const checks = classifyChecks(pr.statusCheckRollup);
|
|
7559
|
+
if (checks.failed.length > 0) {
|
|
7560
|
+
throw new Error(`PR #${pr.number} has failing checks: ${checks.failed.join(", ")}`);
|
|
7561
|
+
}
|
|
7562
|
+
if (checks.pending.length > 0) {
|
|
7563
|
+
throw new Error(`PR #${pr.number} has pending checks: ${checks.pending.join(", ")}`);
|
|
7564
|
+
}
|
|
7565
|
+
assertVerificationEvidence(pr);
|
|
7566
|
+
}
|
|
7567
|
+
function landingReadinessError(pr) {
|
|
7568
|
+
try {
|
|
7569
|
+
assertLandingReady(pr);
|
|
7570
|
+
return null;
|
|
7571
|
+
} catch (err) {
|
|
7572
|
+
return err instanceof Error ? err.message : String(err);
|
|
7573
|
+
}
|
|
7574
|
+
}
|
|
7575
|
+
function deleteRemoteBranch(exec, cwd, repo, branch) {
|
|
7576
|
+
if (!branch?.trim()) return;
|
|
7577
|
+
const refPath = encodeURI(`heads/${branch}`);
|
|
7578
|
+
exec.gh(cwd, ["api", "-X", "DELETE", `repos/${repo}/git/refs/${refPath}`]);
|
|
7579
|
+
}
|
|
7580
|
+
function resolveRepo(exec, cwd, repo) {
|
|
7581
|
+
if (repo?.trim()) return repo.trim();
|
|
7582
|
+
const res = exec.gh(cwd, ["repo", "view", "--json", "nameWithOwner"]);
|
|
7583
|
+
if (res.status !== 0) throw new Error(res.stderr || "Could not resolve GitHub repo");
|
|
7584
|
+
const parsed = JSON.parse(res.stdout || "{}");
|
|
7585
|
+
if (!parsed.nameWithOwner) throw new Error("Could not resolve GitHub repo");
|
|
7586
|
+
return parsed.nameWithOwner;
|
|
7587
|
+
}
|
|
7588
|
+
function removeBranchWorktrees(cwd, branch) {
|
|
7589
|
+
if (!branch?.trim()) return;
|
|
7590
|
+
const list = spawnSync5("git", ["worktree", "list", "--porcelain"], {
|
|
7591
|
+
cwd,
|
|
7592
|
+
encoding: "utf8"
|
|
7593
|
+
});
|
|
7594
|
+
if (list.status !== 0) return;
|
|
7595
|
+
const lines = String(list.stdout || "").split(/\r?\n/);
|
|
7596
|
+
let currentPath = null;
|
|
7597
|
+
let currentBranch = null;
|
|
7598
|
+
for (const line of lines) {
|
|
7599
|
+
if (line.startsWith("worktree ")) {
|
|
7600
|
+
currentPath = line.slice("worktree ".length).trim();
|
|
7601
|
+
currentBranch = null;
|
|
7602
|
+
continue;
|
|
7603
|
+
}
|
|
7604
|
+
if (line.startsWith("branch ") && currentPath) {
|
|
7605
|
+
currentBranch = line.slice("branch ".length).trim();
|
|
7606
|
+
if (currentBranch.endsWith(`/${branch}`)) {
|
|
7607
|
+
spawnSync5("git", ["worktree", "remove", "--force", currentPath], {
|
|
7608
|
+
cwd,
|
|
7609
|
+
encoding: "utf8"
|
|
7610
|
+
});
|
|
7611
|
+
}
|
|
7612
|
+
}
|
|
7613
|
+
}
|
|
7614
|
+
}
|
|
7615
|
+
async function executeLandPrMerge(input) {
|
|
7616
|
+
const cwd = input.cwd ?? process.cwd();
|
|
7617
|
+
const exec = input.exec ?? defaultPrHandoffExec;
|
|
7618
|
+
const prTarget = input.prUrl.trim();
|
|
7619
|
+
if (!prTarget) throw new Error("prUrl is required");
|
|
7620
|
+
const auth = ensureGitHubTokenFromCliAuth();
|
|
7621
|
+
if (!auth.configured) {
|
|
7622
|
+
return {
|
|
7623
|
+
prUrl: prTarget,
|
|
7624
|
+
outcome: "blocked",
|
|
7625
|
+
reason: auth.reason
|
|
7626
|
+
};
|
|
7627
|
+
}
|
|
7628
|
+
const before = ghJson(exec, cwd, [
|
|
7629
|
+
"pr",
|
|
7630
|
+
"view",
|
|
7631
|
+
prTarget,
|
|
7632
|
+
...repoArgs(input.repo),
|
|
7633
|
+
"--json",
|
|
7634
|
+
[
|
|
7635
|
+
"number",
|
|
7636
|
+
"url",
|
|
7637
|
+
"title",
|
|
7638
|
+
"body",
|
|
7639
|
+
"state",
|
|
7640
|
+
"isDraft",
|
|
7641
|
+
"mergeStateStatus",
|
|
7642
|
+
"statusCheckRollup",
|
|
7643
|
+
"headRefName",
|
|
7644
|
+
"mergedAt",
|
|
7645
|
+
"mergeCommit"
|
|
7646
|
+
].join(",")
|
|
7647
|
+
]);
|
|
7648
|
+
const notReadyReason = landingReadinessError(before);
|
|
7649
|
+
if (notReadyReason) {
|
|
7650
|
+
if (input.skipNotReady) {
|
|
7651
|
+
return {
|
|
7652
|
+
prUrl: before.url || prTarget,
|
|
7653
|
+
outcome: "skipped",
|
|
7654
|
+
reason: notReadyReason
|
|
7655
|
+
};
|
|
7656
|
+
}
|
|
7657
|
+
return {
|
|
7658
|
+
prUrl: before.url || prTarget,
|
|
7659
|
+
outcome: "blocked",
|
|
7660
|
+
reason: notReadyReason
|
|
7661
|
+
};
|
|
7662
|
+
}
|
|
7663
|
+
if (input.dryRun) {
|
|
7664
|
+
return {
|
|
7665
|
+
prUrl: before.url || prTarget,
|
|
7666
|
+
outcome: "skipped",
|
|
7667
|
+
reason: "dry-run: PR is ready to merge"
|
|
7668
|
+
};
|
|
7669
|
+
}
|
|
7670
|
+
const target = String(before.number);
|
|
7671
|
+
const mergeRes = exec.gh(cwd, [
|
|
7672
|
+
"pr",
|
|
7673
|
+
"merge",
|
|
7674
|
+
target,
|
|
7675
|
+
...repoArgs(input.repo),
|
|
7676
|
+
"--squash"
|
|
7677
|
+
]);
|
|
7678
|
+
if (mergeRes.status !== 0) {
|
|
7679
|
+
return {
|
|
7680
|
+
prUrl: before.url || prTarget,
|
|
7681
|
+
outcome: "blocked",
|
|
7682
|
+
reason: mergeRes.stderr || mergeRes.stdout || "gh pr merge failed"
|
|
7683
|
+
};
|
|
7684
|
+
}
|
|
7685
|
+
const after = ghJson(exec, cwd, [
|
|
7686
|
+
"pr",
|
|
7687
|
+
"view",
|
|
7688
|
+
target,
|
|
7689
|
+
...repoArgs(input.repo),
|
|
7690
|
+
"--json",
|
|
7691
|
+
"number,url,mergedAt,mergeCommit,state"
|
|
7692
|
+
]);
|
|
7693
|
+
if (after.state !== "MERGED" && !after.mergedAt) {
|
|
7694
|
+
return {
|
|
7695
|
+
prUrl: after.url || before.url || prTarget,
|
|
7696
|
+
outcome: "blocked",
|
|
7697
|
+
reason: `PR #${after.number} did not verify as merged after gh pr merge`
|
|
7698
|
+
};
|
|
7699
|
+
}
|
|
7700
|
+
const repo = resolveRepo(exec, cwd, input.repo);
|
|
7701
|
+
deleteRemoteBranch(exec, cwd, repo, before.headRefName);
|
|
7702
|
+
removeBranchWorktrees(cwd, before.headRefName);
|
|
7703
|
+
const mergeCommit = after.mergeCommit?.oid ?? null;
|
|
7704
|
+
return {
|
|
7705
|
+
prUrl: after.url || before.url || prTarget,
|
|
7706
|
+
outcome: "merged",
|
|
7707
|
+
mergeCommit,
|
|
7708
|
+
reason: `Daemon land_pr merged PR #${after.number}`
|
|
7709
|
+
};
|
|
7710
|
+
}
|
|
7711
|
+
|
|
7712
|
+
// src/landing/land-pr-completion-post.ts
|
|
7713
|
+
async function postLandPrHarnessCompletion(input) {
|
|
7714
|
+
const secret = await resolveCallbackSecretWithMint(input.secret, input.agentOsId, {
|
|
7715
|
+
baseUrl: input.baseUrl
|
|
7716
|
+
});
|
|
7717
|
+
const taskId = String(input.task.id);
|
|
7718
|
+
const url = `${input.baseUrl}/api/agent-os/by-id/${encodeURIComponent(input.agentOsId)}/harness/completion`;
|
|
7719
|
+
const finishedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
7720
|
+
const body = {
|
|
7721
|
+
source: "kynver-harness",
|
|
7722
|
+
agentOsId: input.agentOsId,
|
|
7723
|
+
runId: input.runId,
|
|
7724
|
+
workerName: `land-pr-${taskId}`,
|
|
7725
|
+
taskId,
|
|
7726
|
+
leaseToken: input.task.leaseToken ?? null,
|
|
7727
|
+
startedAt: finishedAt,
|
|
7728
|
+
finishedAt,
|
|
7729
|
+
status: {
|
|
7730
|
+
finalResult: input.report,
|
|
7731
|
+
prUrl: input.report.prUrl,
|
|
7732
|
+
summary: input.report.reason,
|
|
7733
|
+
leaseToken: input.task.leaseToken ?? null
|
|
7734
|
+
},
|
|
7735
|
+
workerInjection: null
|
|
7736
|
+
};
|
|
7737
|
+
const result = await postJsonWithCredentialRefresh(url, secret, body, {
|
|
7738
|
+
agentOsId: input.agentOsId,
|
|
7739
|
+
baseUrl: input.baseUrl
|
|
7740
|
+
});
|
|
7741
|
+
return { ok: result.ok, status: result.status };
|
|
7742
|
+
}
|
|
7743
|
+
|
|
7744
|
+
// src/verify-live/verify-live-prompt.ts
|
|
7745
|
+
function formatVerifyLiveCompletionContract() {
|
|
7746
|
+
return [
|
|
7747
|
+
"## verify_live completion contract",
|
|
7748
|
+
"Finish with a JSON finalResult object:",
|
|
7749
|
+
"{",
|
|
7750
|
+
' "prUrl": "<landed pr>",',
|
|
7751
|
+
' "outcome": "passed" | "failed" | "skipped" | "no_mcp_surface",',
|
|
7752
|
+
' "reason": "<human summary>",',
|
|
7753
|
+
' "mergeCommit": "<sha optional>",',
|
|
7754
|
+
' "mcpCalls": [{ "tool": "<name>", "ok": true, "summary": "..." }]',
|
|
7755
|
+
"}",
|
|
7756
|
+
"",
|
|
7757
|
+
"Drive the feature MCP tools against live production. Do not mark passed without exercising the MCP surface."
|
|
7758
|
+
].join("\n");
|
|
7759
|
+
}
|
|
7760
|
+
|
|
7440
7761
|
// src/dispatch.ts
|
|
7441
7762
|
var DEFAULT_DISPATCH_LEASE_MS = 60 * 60 * 1e3;
|
|
7442
7763
|
function readAdmissionExhaustion(result) {
|
|
@@ -7494,6 +7815,9 @@ function buildDispatchTaskText(task, agentOsId) {
|
|
|
7494
7815
|
`Board linkage: agentOsId=${agentOsId}, taskId=${task.id}, attempt=${task.attempt}, executor=${task.executor}${task.executorRef ? `, executorRef=${task.executorRef}` : ""}.`,
|
|
7495
7816
|
"This worker was dispatched from the AgentOS board. The harness reports your completion back to the board when you finish."
|
|
7496
7817
|
];
|
|
7818
|
+
if (task.executor === "verify_live") {
|
|
7819
|
+
lines.push("", formatVerifyLiveCompletionContract());
|
|
7820
|
+
}
|
|
7497
7821
|
const outboxRef = extractPlanOutboxFromTask(task);
|
|
7498
7822
|
if (outboxRef?.outboxId) {
|
|
7499
7823
|
const item = loadOutboxById(outboxRef.outboxId);
|
|
@@ -7527,6 +7851,12 @@ function requestedTargetTaskIds(args) {
|
|
|
7527
7851
|
async function dispatchRun(args) {
|
|
7528
7852
|
const pipeline = args.pipeline === true || args.pipeline === "true";
|
|
7529
7853
|
try {
|
|
7854
|
+
let isLandPrDecision2 = function(decision) {
|
|
7855
|
+
if (decision.landPrDispatch === true) return true;
|
|
7856
|
+
const task = decision.task;
|
|
7857
|
+
return task?.executor === "land_pr";
|
|
7858
|
+
};
|
|
7859
|
+
var isLandPrDecision = isLandPrDecision2;
|
|
7530
7860
|
const run = loadRun(String(required(String(args.run || ""), "--run")));
|
|
7531
7861
|
const agentOsId = String(required(String(args.agentOsId || ""), "--agent-os-id"));
|
|
7532
7862
|
const base = resolveBaseUrl(args.baseUrl ? String(args.baseUrl) : void 0);
|
|
@@ -7661,6 +7991,41 @@ async function dispatchRun(args) {
|
|
|
7661
7991
|
});
|
|
7662
7992
|
return false;
|
|
7663
7993
|
}
|
|
7994
|
+
async function runLandPrClaimed(decision) {
|
|
7995
|
+
const task = decision.task;
|
|
7996
|
+
const taskId = String(task.id);
|
|
7997
|
+
const prUrl = task.prUrl ? String(task.prUrl) : "";
|
|
7998
|
+
if (!prUrl) {
|
|
7999
|
+
return abortClaimedSpawn(task, "land_pr task missing prUrl");
|
|
8000
|
+
}
|
|
8001
|
+
try {
|
|
8002
|
+
const report = await executeLandPrMerge({ prUrl, cwd: process.cwd() });
|
|
8003
|
+
const post = await postLandPrHarnessCompletion({
|
|
8004
|
+
baseUrl: base,
|
|
8005
|
+
secret,
|
|
8006
|
+
agentOsId,
|
|
8007
|
+
runId: run.id,
|
|
8008
|
+
task,
|
|
8009
|
+
report
|
|
8010
|
+
});
|
|
8011
|
+
outcomes.push({
|
|
8012
|
+
taskId,
|
|
8013
|
+
started: true,
|
|
8014
|
+
landPr: true,
|
|
8015
|
+
outcome: report.outcome,
|
|
8016
|
+
completionStatus: post.status
|
|
8017
|
+
});
|
|
8018
|
+
if (!post.ok) {
|
|
8019
|
+
return abortClaimedSpawn(
|
|
8020
|
+
task,
|
|
8021
|
+
`land_pr completion POST failed (HTTP ${post.status})`
|
|
8022
|
+
);
|
|
8023
|
+
}
|
|
8024
|
+
return true;
|
|
8025
|
+
} catch (error) {
|
|
8026
|
+
return abortClaimedSpawn(task, error.message);
|
|
8027
|
+
}
|
|
8028
|
+
}
|
|
7664
8029
|
async function spawnClaimed(decision) {
|
|
7665
8030
|
const task = decision.task;
|
|
7666
8031
|
const harnessContext = readHarnessWorkerContext(decision);
|
|
@@ -7778,7 +8143,8 @@ async function dispatchRun(args) {
|
|
|
7778
8143
|
}
|
|
7779
8144
|
let shouldContinueDispatch = true;
|
|
7780
8145
|
for (const decision of result.started) {
|
|
7781
|
-
|
|
8146
|
+
const admitted = isLandPrDecision2(decision) ? await runLandPrClaimed(decision) : await spawnClaimed(decision);
|
|
8147
|
+
shouldContinueDispatch = admitted && shouldContinueDispatch;
|
|
7782
8148
|
}
|
|
7783
8149
|
skipped.push(
|
|
7784
8150
|
...result.skipped ?? []
|
|
@@ -7816,7 +8182,8 @@ async function dispatchRun(args) {
|
|
|
7816
8182
|
if (started.length === 0) break;
|
|
7817
8183
|
for (const decision of started) {
|
|
7818
8184
|
if (outcomes.length >= cappedStarts) break;
|
|
7819
|
-
|
|
8185
|
+
const admitted = isLandPrDecision2(decision) ? await runLandPrClaimed(decision) : await spawnClaimed(decision);
|
|
8186
|
+
shouldContinueDispatch = admitted && shouldContinueDispatch;
|
|
7820
8187
|
if (!shouldContinueDispatch) break;
|
|
7821
8188
|
}
|
|
7822
8189
|
}
|
|
@@ -8212,7 +8579,7 @@ function expandHomePath2(filePath) {
|
|
|
8212
8579
|
function discoverProductionDbEnvFilePaths(options = {}) {
|
|
8213
8580
|
const env = options.env ?? process.env;
|
|
8214
8581
|
const cwd = options.cwd ?? process.cwd();
|
|
8215
|
-
const home = options.homeDir ?? homedir12();
|
|
8582
|
+
const home = options.homeDir ?? (env.HOME?.trim() || env.USERPROFILE?.trim() || homedir12());
|
|
8216
8583
|
const seen = /* @__PURE__ */ new Set();
|
|
8217
8584
|
const out = [];
|
|
8218
8585
|
const push = (candidate) => {
|
|
@@ -8246,7 +8613,7 @@ function discoverProductionDbEnvFilePaths(options = {}) {
|
|
|
8246
8613
|
}
|
|
8247
8614
|
|
|
8248
8615
|
// src/db-credential-resolver.ts
|
|
8249
|
-
import { execFileSync, spawnSync as
|
|
8616
|
+
import { execFileSync, spawnSync as spawnSync6 } from "node:child_process";
|
|
8250
8617
|
import * as fs2 from "node:fs";
|
|
8251
8618
|
import * as path29 from "node:path";
|
|
8252
8619
|
|
|
@@ -8332,7 +8699,7 @@ function defaultNeonConnectionString(args) {
|
|
|
8332
8699
|
if (args.pooled) argv.push("--pooled");
|
|
8333
8700
|
let stdout;
|
|
8334
8701
|
try {
|
|
8335
|
-
const result =
|
|
8702
|
+
const result = spawnSync6(neonBin, argv, {
|
|
8336
8703
|
encoding: "utf8",
|
|
8337
8704
|
env: process.env,
|
|
8338
8705
|
timeout: 3e4
|
|
@@ -10124,7 +10491,7 @@ function pathHasForeignOwnedEntry(targetPath, maxEntries = 32) {
|
|
|
10124
10491
|
}
|
|
10125
10492
|
|
|
10126
10493
|
// src/cleanup-privileged-remove.ts
|
|
10127
|
-
import { spawnSync as
|
|
10494
|
+
import { spawnSync as spawnSync7 } from "node:child_process";
|
|
10128
10495
|
import path46 from "node:path";
|
|
10129
10496
|
|
|
10130
10497
|
// src/cleanup-harness-path-validate.ts
|
|
@@ -10169,7 +10536,7 @@ function resolvePrivilegedCleanupMode() {
|
|
|
10169
10536
|
return "auto";
|
|
10170
10537
|
}
|
|
10171
10538
|
function runSudoNonInteractive(argv) {
|
|
10172
|
-
const res =
|
|
10539
|
+
const res = spawnSync7("sudo", ["-n", ...argv], {
|
|
10173
10540
|
encoding: "utf8",
|
|
10174
10541
|
stdio: ["ignore", "pipe", "pipe"]
|
|
10175
10542
|
});
|
|
@@ -12347,7 +12714,7 @@ function formatNodeOptionsFlag(mb = resolveNodeOldSpaceSizeMb()) {
|
|
|
12347
12714
|
}
|
|
12348
12715
|
|
|
12349
12716
|
// src/bounded-build/systemd-wrap.ts
|
|
12350
|
-
import { spawnSync as
|
|
12717
|
+
import { spawnSync as spawnSync8 } from "node:child_process";
|
|
12351
12718
|
var systemdAvailableCache;
|
|
12352
12719
|
function isSystemdRunAvailable() {
|
|
12353
12720
|
if (process.env.KYNVER_BUILD_SKIP_SYSTEMD === "1" || process.env.KYNVER_BUILD_SKIP_SYSTEMD === "true") {
|
|
@@ -12358,7 +12725,7 @@ function isSystemdRunAvailable() {
|
|
|
12358
12725
|
systemdAvailableCache = false;
|
|
12359
12726
|
return false;
|
|
12360
12727
|
}
|
|
12361
|
-
const res =
|
|
12728
|
+
const res = spawnSync8("systemd-run", ["--version"], { encoding: "utf8", stdio: ["ignore", "ignore", "pipe"] });
|
|
12362
12729
|
systemdAvailableCache = res.status === 0;
|
|
12363
12730
|
return systemdAvailableCache;
|
|
12364
12731
|
}
|
|
@@ -12382,7 +12749,7 @@ function buildSystemdRunArgv(opts) {
|
|
|
12382
12749
|
}
|
|
12383
12750
|
|
|
12384
12751
|
// src/bounded-build/admission.ts
|
|
12385
|
-
import { spawnSync as
|
|
12752
|
+
import { spawnSync as spawnSync9 } from "node:child_process";
|
|
12386
12753
|
function positiveInt4(value, fallback) {
|
|
12387
12754
|
const n = Number(value);
|
|
12388
12755
|
if (!Number.isFinite(n) || n <= 0) return fallback;
|
|
@@ -12418,7 +12785,7 @@ function assessBuildAdmission(opts = {}) {
|
|
|
12418
12785
|
}
|
|
12419
12786
|
function sleepMs2(ms) {
|
|
12420
12787
|
if (ms <= 0) return;
|
|
12421
|
-
|
|
12788
|
+
spawnSync9(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
|
|
12422
12789
|
stdio: "ignore"
|
|
12423
12790
|
});
|
|
12424
12791
|
}
|
|
@@ -12439,7 +12806,7 @@ function waitForBuildAdmission(timeoutMs, pollMs = 2e3, opts = {}) {
|
|
|
12439
12806
|
}
|
|
12440
12807
|
|
|
12441
12808
|
// src/bounded-build/exec.ts
|
|
12442
|
-
import { spawnSync as
|
|
12809
|
+
import { spawnSync as spawnSync11 } from "node:child_process";
|
|
12443
12810
|
|
|
12444
12811
|
// src/heavy-verification/slot.ts
|
|
12445
12812
|
import {
|
|
@@ -12645,10 +13012,10 @@ function assessHeavyVerificationGate(command, opts = {}) {
|
|
|
12645
13012
|
}
|
|
12646
13013
|
|
|
12647
13014
|
// src/heavy-verification/gate.ts
|
|
12648
|
-
import { spawnSync as
|
|
13015
|
+
import { spawnSync as spawnSync10 } from "node:child_process";
|
|
12649
13016
|
function sleepMs3(ms) {
|
|
12650
13017
|
if (ms <= 0) return;
|
|
12651
|
-
|
|
13018
|
+
spawnSync10(process.execPath, ["-e", `const d=Date.now()+${Math.floor(ms)};while(Date.now()<d);`], {
|
|
12652
13019
|
stdio: "ignore"
|
|
12653
13020
|
});
|
|
12654
13021
|
}
|
|
@@ -12691,7 +13058,7 @@ function envArgv(env) {
|
|
|
12691
13058
|
return out;
|
|
12692
13059
|
}
|
|
12693
13060
|
function runSpawn(argv, opts) {
|
|
12694
|
-
const res =
|
|
13061
|
+
const res = spawnSync11(argv[0], argv.slice(1), {
|
|
12695
13062
|
cwd: opts.cwd,
|
|
12696
13063
|
env: opts.env,
|
|
12697
13064
|
encoding: "utf8",
|
|
@@ -14094,10 +14461,10 @@ import path70 from "node:path";
|
|
|
14094
14461
|
import { accessSync, constants, existsSync as existsSync47, readFileSync as readFileSync19 } from "node:fs";
|
|
14095
14462
|
import { homedir as homedir16 } from "node:os";
|
|
14096
14463
|
import path69 from "node:path";
|
|
14097
|
-
import { spawnSync as
|
|
14464
|
+
import { spawnSync as spawnSync12 } from "node:child_process";
|
|
14098
14465
|
function captureCommand(bin, args) {
|
|
14099
14466
|
try {
|
|
14100
|
-
const res =
|
|
14467
|
+
const res = spawnSync12(bin, args, { encoding: "utf8" });
|
|
14101
14468
|
const stdout = (res.stdout || "").trim();
|
|
14102
14469
|
const stderr = (res.stderr || "").trim();
|
|
14103
14470
|
const ok = res.status === 0;
|
|
@@ -14997,7 +15364,7 @@ var LANDING_MAINTAINER_LANE_SPEC = {
|
|
|
14997
15364
|
};
|
|
14998
15365
|
|
|
14999
15366
|
// src/lane/landing-maintainer-local.ts
|
|
15000
|
-
import { spawnSync as
|
|
15367
|
+
import { spawnSync as spawnSync13 } from "node:child_process";
|
|
15001
15368
|
import path72 from "node:path";
|
|
15002
15369
|
function runLandingWrapper(prNumber, repoRoot, execute) {
|
|
15003
15370
|
const script = path72.join(repoRoot, LANDING_MAINTAINER_LANE_SPEC.landScript);
|
|
@@ -15011,7 +15378,7 @@ function runLandingWrapper(prNumber, repoRoot, execute) {
|
|
|
15011
15378
|
stderr: ""
|
|
15012
15379
|
};
|
|
15013
15380
|
}
|
|
15014
|
-
const result =
|
|
15381
|
+
const result = spawnSync13("node", args, {
|
|
15015
15382
|
cwd: repoRoot,
|
|
15016
15383
|
encoding: "utf8",
|
|
15017
15384
|
timeout: 10 * 60 * 1e3
|