lagora-cli 1.1.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 +138 -0
- package/dist/help.txt +70 -0
- package/dist/lagora.js +342 -0
- package/dist/report-help.txt +5 -0
- package/dist/scripts/agora_playground_harness.py +263 -0
- package/dist/scripts/announce.js +41 -0
- package/dist/scripts/check-kernel-submission.py +90 -0
- package/dist/scripts/chunk-2EAJVB5D.js +100 -0
- package/dist/scripts/chunk-2KTLCUFI.js +29 -0
- package/dist/scripts/chunk-AZ3EEBVD.js +137 -0
- package/dist/scripts/chunk-NBJMYAOA.js +2128 -0
- package/dist/scripts/chunk-NCJMUBTG.js +125 -0
- package/dist/scripts/chunk-QJPQHKIO.js +23 -0
- package/dist/scripts/chunk-RIR5KGHC.js +33 -0
- package/dist/scripts/chunk-TJZVQYBL.js +8 -0
- package/dist/scripts/chunk-UHJXD4TG.js +18 -0
- package/dist/scripts/chunk-UQ6I6VTY.js +117 -0
- package/dist/scripts/cli-auth.js +348 -0
- package/dist/scripts/cli-config-IA7EOSYD.js +7 -0
- package/dist/scripts/install-skill.js +199 -0
- package/dist/scripts/issue-local-client-DZUXZOKY.js +22 -0
- package/dist/scripts/issue-search.js +1823 -0
- package/dist/scripts/issue.js +386 -0
- package/dist/scripts/keycloak-provision.js +986 -0
- package/dist/scripts/legato-fsim-runner.py +126 -0
- package/dist/scripts/legato-lowering-runner.py +156 -0
- package/dist/scripts/legato_runner_annotations.py +235 -0
- package/dist/scripts/legato_runner_env.py +91 -0
- package/dist/scripts/legato_runner_launchers.py +287 -0
- package/dist/scripts/legato_runner_script_wrapper.py +193 -0
- package/dist/scripts/notifications-EU43SIEV.js +624 -0
- package/dist/scripts/playground.js +408 -0
- package/dist/scripts/report-bundle-sync-3U7QTP4Z.js +215 -0
- package/dist/scripts/report.js +104 -0
- package/dist/scripts/resolve-sdk-package-version.py +151 -0
- package/dist/scripts/sdk-runtime-JE6H2PB2.js +992 -0
- package/dist/scripts/sdk-runtime-kubernetes-job-KOWL4ITV.js +479 -0
- package/dist/scripts/sdk-runtime-smoke.py +168 -0
- package/dist/scripts/sdk.js +256 -0
- package/dist/scripts/site-feedback-CAPE5MPX.js +136 -0
- package/dist/scripts/site-feedback-rate-limit-5BU2WSFE.js +86 -0
- package/dist/scripts/site-feedback.js +117 -0
- package/dist/scripts/storage-234FBH54.js +67 -0
- package/dist/scripts/submit-issue.sh +489 -0
- package/dist/scripts/verification-3QCY66QW.js +772 -0
- package/dist/scripts/verify-issue.js +144 -0
- package/dist/skills/legato-agora-cli/SKILL.md +556 -0
- package/dist/skills/legato-agora-cli/agents/openai.yaml +7 -0
- package/dist/skills/legato-agora-cli/reference/kernel-with-golden.py +84 -0
- package/dist/skills/legato-site-feedback/SKILL.md +49 -0
- package/dist/skills/legato-site-feedback/agents/openai.yaml +7 -0
- package/package.json +16 -0
|
@@ -0,0 +1,772 @@
|
|
|
1
|
+
import {
|
|
2
|
+
loweringWorkerEnv
|
|
3
|
+
} from "./chunk-RIR5KGHC.js";
|
|
4
|
+
import "./chunk-UQ6I6VTY.js";
|
|
5
|
+
import {
|
|
6
|
+
getArtifactTextPath,
|
|
7
|
+
getIssue,
|
|
8
|
+
recordVerificationResult,
|
|
9
|
+
storedGeneratedArtifactFilename,
|
|
10
|
+
updateVerificationRunResult
|
|
11
|
+
} from "./chunk-NBJMYAOA.js";
|
|
12
|
+
import "./chunk-QJPQHKIO.js";
|
|
13
|
+
|
|
14
|
+
// lib/verification.ts
|
|
15
|
+
import { fileURLToPath as packageFilePath } from "node:url";
|
|
16
|
+
import { execFile, spawn } from "child_process";
|
|
17
|
+
import { createHash } from "crypto";
|
|
18
|
+
import { access as access2, mkdtemp, readFile as readFile2, rm } from "fs/promises";
|
|
19
|
+
import { tmpdir } from "os";
|
|
20
|
+
import path2 from "path";
|
|
21
|
+
import { promisify } from "util";
|
|
22
|
+
|
|
23
|
+
// lib/verification-generated-artifacts.ts
|
|
24
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
25
|
+
import path from "node:path";
|
|
26
|
+
|
|
27
|
+
// lib/artifact-content.ts
|
|
28
|
+
var TEXT_PREVIEW_MAX_BYTES = 512 * 1024;
|
|
29
|
+
var BINARY_HEX_PREVIEW_BYTES = 4 * 1024;
|
|
30
|
+
|
|
31
|
+
// lib/verification-generated-artifacts.ts
|
|
32
|
+
var TEXT_EXTENSIONS = /* @__PURE__ */ new Set([".mlir", ".ll", ".s", ".asm", ".json"]);
|
|
33
|
+
var BINARY_EXTENSIONS = /* @__PURE__ */ new Set([".bin", ".elf", ".o", ".bc"]);
|
|
34
|
+
var EXCLUDED_EXTENSIONS = /* @__PURE__ */ new Set([".log", ".tmp", ".pyc", ".pyo"]);
|
|
35
|
+
async function listGeneratedArtifacts(root) {
|
|
36
|
+
const entries = [];
|
|
37
|
+
async function visit(directory) {
|
|
38
|
+
let children;
|
|
39
|
+
try {
|
|
40
|
+
children = await readdir(directory, { withFileTypes: true });
|
|
41
|
+
} catch (error) {
|
|
42
|
+
if (!(error instanceof Error)) throw error;
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
for (const child of children) {
|
|
46
|
+
const childPath = path.join(directory, child.name);
|
|
47
|
+
const relativePath = path.relative(root, childPath);
|
|
48
|
+
if (child.isDirectory()) {
|
|
49
|
+
if (isIgnoredGeneratedPath(relativePath)) continue;
|
|
50
|
+
await visit(childPath);
|
|
51
|
+
} else if (isMeaningfulGeneratedArtifact(relativePath)) {
|
|
52
|
+
entries.push(relativePath);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
await visit(root);
|
|
57
|
+
return entries.sort(compareGeneratedArtifacts);
|
|
58
|
+
}
|
|
59
|
+
async function collectGeneratedArtifactFiles(root) {
|
|
60
|
+
const files = [];
|
|
61
|
+
for (const relativePath of await listGeneratedArtifacts(root)) {
|
|
62
|
+
const bytes = await readFile(path.join(root, relativePath));
|
|
63
|
+
files.push({
|
|
64
|
+
filename: storedGeneratedArtifactFilename(relativePath),
|
|
65
|
+
contentType: contentTypeForGeneratedArtifact(relativePath),
|
|
66
|
+
contentBase64: bytes.toString("base64")
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
return files;
|
|
70
|
+
}
|
|
71
|
+
function isMeaningfulGeneratedArtifact(relativePath) {
|
|
72
|
+
if (isIgnoredGeneratedPath(relativePath)) return false;
|
|
73
|
+
const extension = path.extname(relativePath).toLowerCase();
|
|
74
|
+
if (EXCLUDED_EXTENSIONS.has(extension)) return false;
|
|
75
|
+
return TEXT_EXTENSIONS.has(extension) || BINARY_EXTENSIONS.has(extension);
|
|
76
|
+
}
|
|
77
|
+
function isIgnoredGeneratedPath(relativePath) {
|
|
78
|
+
const parts = relativePath.split(path.sep);
|
|
79
|
+
return parts.some((part) => part === "__pycache__" || part.startsWith(".") || part.startsWith("tmp") || part.endsWith(".tmp"));
|
|
80
|
+
}
|
|
81
|
+
function contentTypeForGeneratedArtifact(relativePath) {
|
|
82
|
+
const extension = path.extname(relativePath).toLowerCase();
|
|
83
|
+
return TEXT_EXTENSIONS.has(extension) ? "text/plain" : "application/octet-stream";
|
|
84
|
+
}
|
|
85
|
+
function compareGeneratedArtifacts(left, right) {
|
|
86
|
+
const rankDelta = stageRank(left) - stageRank(right);
|
|
87
|
+
return rankDelta !== 0 ? rankDelta : left.localeCompare(right);
|
|
88
|
+
}
|
|
89
|
+
function stageRank(relativePath) {
|
|
90
|
+
const stage = relativePath.split(/[\\/]/)[0]?.toLowerCase();
|
|
91
|
+
if (stage === "mlir") return 0;
|
|
92
|
+
if (stage === "core_ir") return 1;
|
|
93
|
+
if (stage === "backend_ir") return 2;
|
|
94
|
+
if (stage === "asm") return 3;
|
|
95
|
+
if (stage === "binary") return 4;
|
|
96
|
+
return 5;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// lib/verification-sdk-preflight.ts
|
|
100
|
+
import { access } from "node:fs/promises";
|
|
101
|
+
async function preflightLoweringRuntime(input) {
|
|
102
|
+
const missing = [];
|
|
103
|
+
if (input.runtimeStatus !== "ready") {
|
|
104
|
+
missing.push(`SDK runtime is not ready: ${input.runtimeStatus}${input.runtimeMessage ? ` (${input.runtimeMessage})` : ""}`);
|
|
105
|
+
}
|
|
106
|
+
await collectMissingPath(missing, "SDK runtime root", input.runtimeRoot);
|
|
107
|
+
await collectMissingPath(missing, "Legato Python", input.python);
|
|
108
|
+
await collectMissingPath(missing, "lowering runner", input.runnerPath);
|
|
109
|
+
if (missing.length === 0) return void 0;
|
|
110
|
+
return {
|
|
111
|
+
status: "failed",
|
|
112
|
+
exitCode: 2,
|
|
113
|
+
stdout: "[LEGATO_WORKER] preflight=failed\n",
|
|
114
|
+
stderr: [
|
|
115
|
+
"Backend lowering preflight failed before running the compiler.",
|
|
116
|
+
"The server must use a prepared HyperAccel SDK runtime; lowering workers do not install packages, clone, or fetch repositories.",
|
|
117
|
+
...missing.map((item) => `- ${item}`),
|
|
118
|
+
"Prepare the SDK from Settings > SDK > Prepare / update runtime, or wait for startup preparation to finish."
|
|
119
|
+
].join("\n"),
|
|
120
|
+
failedStage: "PREFLIGHT",
|
|
121
|
+
skippedEvidence: missing
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
async function collectMissingPath(missing, label, candidate) {
|
|
125
|
+
try {
|
|
126
|
+
await access(candidate);
|
|
127
|
+
} catch {
|
|
128
|
+
missing.push(`${label}: ${candidate}`);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// lib/verification.ts
|
|
133
|
+
var execFileAsync = promisify(execFile);
|
|
134
|
+
var DEFAULT_LOWERING_TIMEOUT_MS = 12e4;
|
|
135
|
+
var DEFAULT_FSIM_TIMEOUT_MS = 144e5;
|
|
136
|
+
async function runIssueVerification(input) {
|
|
137
|
+
const mode = input.mode ?? "plan";
|
|
138
|
+
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
139
|
+
const record = await getIssue(input.issueId);
|
|
140
|
+
if (!record) throw new Error(`Issue not found: ${input.issueId}`);
|
|
141
|
+
if ((input.kind === "lowering" || input.kind === "fsim") && mode === "real") {
|
|
142
|
+
await ensureLoweringRuntimePrepared(input.sdkRuntime);
|
|
143
|
+
}
|
|
144
|
+
const kernelArtifact = input.sourceArtifactId ? record.artifacts.find((artifact) => artifact.id === input.sourceArtifactId) : record.artifacts.find((artifact) => artifact.id === record.bundle.kernelArtifactId);
|
|
145
|
+
if (input.sourceArtifactId && !kernelArtifact) throw new Error(`Source artifact not found: ${input.sourceArtifactId}`);
|
|
146
|
+
const coreIrArtifact = findCoreIrArtifact(record.artifacts);
|
|
147
|
+
const plan = input.kind === "lowering" ? await loweringPlan(kernelArtifact, coreIrArtifact, input.sdkRuntime) : await fsimPlan(kernelArtifact, input.sdkRuntime);
|
|
148
|
+
const updateLiveRun = input.runId ? async (result2) => {
|
|
149
|
+
await updateVerificationRunResult({
|
|
150
|
+
issueId: input.issueId,
|
|
151
|
+
runId: input.runId ?? "",
|
|
152
|
+
kind: input.kind,
|
|
153
|
+
sourceArtifactId: input.sourceArtifactId,
|
|
154
|
+
actorUserId: input.actorUserId,
|
|
155
|
+
status: result2.status,
|
|
156
|
+
exitCode: result2.exitCode,
|
|
157
|
+
toolVersion: result2.toolVersion,
|
|
158
|
+
failedStage: result2.failedStage,
|
|
159
|
+
completedStage: result2.completedStage,
|
|
160
|
+
sdkRepoUrl: result2.sdkRepoUrl,
|
|
161
|
+
sdkBranch: result2.sdkBranch,
|
|
162
|
+
sdkCommitSha: result2.sdkCommitSha,
|
|
163
|
+
sdkPreparedRoot: result2.sdkPreparedRoot,
|
|
164
|
+
startedAt,
|
|
165
|
+
completedAt: result2.status === "running" ? startedAt : (/* @__PURE__ */ new Date()).toISOString(),
|
|
166
|
+
logText: buildLog({
|
|
167
|
+
issueId: input.issueId,
|
|
168
|
+
kind: input.kind,
|
|
169
|
+
mode,
|
|
170
|
+
startedAt,
|
|
171
|
+
completedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
172
|
+
plan,
|
|
173
|
+
result: result2,
|
|
174
|
+
kernelArtifact,
|
|
175
|
+
coreIrArtifact
|
|
176
|
+
})
|
|
177
|
+
});
|
|
178
|
+
} : void 0;
|
|
179
|
+
const result = await executePlan(input.kind, mode, plan, kernelArtifact, coreIrArtifact, input.sdkRuntime, updateLiveRun);
|
|
180
|
+
const completedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
181
|
+
const fingerprint = input.kind === "lowering" ? buildVerificationFingerprint(result, kernelArtifact, completedAt) : void 0;
|
|
182
|
+
const logText = buildLog({
|
|
183
|
+
issueId: input.issueId,
|
|
184
|
+
kind: input.kind,
|
|
185
|
+
sourceArtifactId: input.sourceArtifactId,
|
|
186
|
+
mode,
|
|
187
|
+
startedAt,
|
|
188
|
+
completedAt,
|
|
189
|
+
plan,
|
|
190
|
+
result,
|
|
191
|
+
kernelArtifact,
|
|
192
|
+
coreIrArtifact
|
|
193
|
+
});
|
|
194
|
+
const recordInput = {
|
|
195
|
+
issueId: input.issueId,
|
|
196
|
+
kind: input.kind,
|
|
197
|
+
actorUserId: input.actorUserId,
|
|
198
|
+
status: result.status,
|
|
199
|
+
exitCode: result.exitCode,
|
|
200
|
+
toolVersion: result.toolVersion,
|
|
201
|
+
failedStage: result.failedStage,
|
|
202
|
+
completedStage: result.completedStage,
|
|
203
|
+
generatedArtifacts: result.generatedArtifacts,
|
|
204
|
+
generatedArtifactFiles: result.generatedArtifactFiles,
|
|
205
|
+
sdkRepoUrl: result.sdkRepoUrl,
|
|
206
|
+
sdkBranch: result.sdkBranch,
|
|
207
|
+
sdkCommitSha: result.sdkCommitSha,
|
|
208
|
+
sdkPreparedRoot: result.sdkPreparedRoot,
|
|
209
|
+
fingerprint,
|
|
210
|
+
startedAt,
|
|
211
|
+
completedAt,
|
|
212
|
+
logText,
|
|
213
|
+
commentBody: verificationSummary(input.kind, result, plan.reason)
|
|
214
|
+
};
|
|
215
|
+
return input.runId ? updateVerificationRunResult({ ...recordInput, runId: input.runId }) : recordVerificationResult(recordInput);
|
|
216
|
+
}
|
|
217
|
+
async function ensureLoweringRuntimePrepared(sdkRuntime) {
|
|
218
|
+
const { prepareSdkRuntime, readSdkRuntimeStatus } = await import("./sdk-runtime-JE6H2PB2.js");
|
|
219
|
+
if (sdkRuntime?.preparedRoot) {
|
|
220
|
+
const status = await readSdkRuntimeStatus(sdkRuntime);
|
|
221
|
+
if (status.status === "ready" && await pathExists(status.pythonPath)) return;
|
|
222
|
+
}
|
|
223
|
+
await prepareSdkRuntime(sdkRuntime);
|
|
224
|
+
}
|
|
225
|
+
async function maybeRunAutoLowering(issueId) {
|
|
226
|
+
try {
|
|
227
|
+
await runIssueVerification({ issueId, kind: "lowering", mode: "real" });
|
|
228
|
+
} catch (error) {
|
|
229
|
+
console.error("Auto lowering failed", error);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
function findCoreIrArtifact(artifacts) {
|
|
233
|
+
return artifacts.find((artifact) => artifact.filename.endsWith(".mlir"));
|
|
234
|
+
}
|
|
235
|
+
async function loweringPlan(kernelArtifact, coreIrArtifact, sdkRuntime) {
|
|
236
|
+
if (kernelArtifact?.filename.endsWith(".py")) {
|
|
237
|
+
const { readSdkRuntimeSettings, readSdkRuntimeStatus } = await import("./sdk-runtime-JE6H2PB2.js");
|
|
238
|
+
const runtime = await readSdkRuntimeSettings(sdkRuntime);
|
|
239
|
+
const status = await readSdkRuntimeStatus(sdkRuntime);
|
|
240
|
+
const activeRuntime = sdkRuntimeExecutionView(runtime, status);
|
|
241
|
+
return {
|
|
242
|
+
command: activeRuntime.pythonPath,
|
|
243
|
+
args: ["scripts/legato-lowering-runner.py", "--kernel", kernelArtifact.filename, "--stages", process.env.AGORA_LOWERING_STAGES ?? "MLIR,CORE_IR,BACKEND_IR,ASM,BINARY"],
|
|
244
|
+
cwd: activeRuntime.preparedRoot,
|
|
245
|
+
reason: "Uploaded Python kernel will be imported and lowered stage-by-stage using Legato annotations."
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
const legatoOpt = await findExecutable(process.env.LEGATO_OPT, "legato-opt");
|
|
249
|
+
const coreIrPath = coreIrArtifact ? getArtifactTextPath(coreIrArtifact) : void 0;
|
|
250
|
+
return {
|
|
251
|
+
command: legatoOpt ?? "legato-opt",
|
|
252
|
+
args: ["--legato-bertha-convert-core-to-high", coreIrPath ?? "<core_ir.mlir>"],
|
|
253
|
+
cwd: process.cwd(),
|
|
254
|
+
reason: legatoOpt && coreIrPath ? "Legato lowering command is available for CORE_IR input." : `Skipped until ${legatoOpt ? "CORE_IR artifact" : "LEGATO_OPT or legato-opt"} is available. Kernel artifact: ${kernelArtifact?.filename ?? "missing"}.`
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
async function fsimPlan(kernelArtifact, sdkRuntime) {
|
|
258
|
+
const { readSdkRuntimeSettings, readSdkRuntimeStatus } = await import("./sdk-runtime-JE6H2PB2.js");
|
|
259
|
+
const runtime = await readSdkRuntimeSettings(sdkRuntime);
|
|
260
|
+
const status = await readSdkRuntimeStatus(sdkRuntime);
|
|
261
|
+
const activeRuntime = sdkRuntimeExecutionView(runtime, status);
|
|
262
|
+
if (kernelArtifact?.filename.endsWith(".py")) {
|
|
263
|
+
return {
|
|
264
|
+
command: activeRuntime.pythonPath,
|
|
265
|
+
args: ["scripts/legato-fsim-runner.py", "--kernel", kernelArtifact.filename],
|
|
266
|
+
cwd: activeRuntime.preparedRoot,
|
|
267
|
+
reason: "Uploaded Python launcher will compile BINARY and launch on HART fSIM through Legato session."
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
return {
|
|
271
|
+
command: activeRuntime.pythonPath,
|
|
272
|
+
args: ["-m", "pytest", "tests/simulator_compiler_integration/test_assembly_inst.py", "--use-verf", "-s"],
|
|
273
|
+
cwd: activeRuntime.preparedRoot,
|
|
274
|
+
reason: `No uploaded Python launcher was available; using the legacy pytest fSIM verification command. Kernel artifact: ${kernelArtifact?.filename ?? "missing"}.`
|
|
275
|
+
};
|
|
276
|
+
}
|
|
277
|
+
async function executePlan(kind, mode, plan, kernelArtifact, coreIrArtifact, sdkRuntime, updateLiveRun) {
|
|
278
|
+
if (mode === "plan") {
|
|
279
|
+
return {
|
|
280
|
+
status: "skipped",
|
|
281
|
+
stdout: "",
|
|
282
|
+
stderr: "",
|
|
283
|
+
skippedEvidence: ["--mode plan selected", "No heavyweight Legato/fSIM command was run."]
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
if (kind === "fsim" && kernelArtifact?.filename.endsWith(".py")) {
|
|
287
|
+
return executePythonFsim(kernelArtifact, sdkRuntime, updateLiveRun);
|
|
288
|
+
}
|
|
289
|
+
if (kind === "fsim") {
|
|
290
|
+
return executeLegacyFsim(plan, sdkRuntime);
|
|
291
|
+
}
|
|
292
|
+
if (kernelArtifact?.filename.endsWith(".py")) {
|
|
293
|
+
return executePythonLowering(kernelArtifact, sdkRuntime, updateLiveRun);
|
|
294
|
+
}
|
|
295
|
+
const executable = await findExecutable(process.env.LEGATO_OPT, "legato-opt");
|
|
296
|
+
if (!executable || !coreIrArtifact) {
|
|
297
|
+
return {
|
|
298
|
+
status: "skipped",
|
|
299
|
+
stdout: "",
|
|
300
|
+
stderr: "",
|
|
301
|
+
skippedEvidence: [
|
|
302
|
+
executable ? "legato-opt found" : "LEGATO_OPT/legato-opt not found or not executable",
|
|
303
|
+
coreIrArtifact ? "CORE_IR artifact found" : "No .mlir CORE_IR artifact is attached to the issue"
|
|
304
|
+
]
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
try {
|
|
308
|
+
const version = await commandVersion(executable);
|
|
309
|
+
const output = await execFileAsync(executable, plan.args.slice(0, -1).concat(getArtifactTextPath(coreIrArtifact)), {
|
|
310
|
+
cwd: process.cwd(),
|
|
311
|
+
timeout: 3e4,
|
|
312
|
+
maxBuffer: 1024 * 1024
|
|
313
|
+
});
|
|
314
|
+
return { status: "success", exitCode: 0, stdout: output.stdout, stderr: output.stderr, toolVersion: version };
|
|
315
|
+
} catch (error) {
|
|
316
|
+
const failure = error;
|
|
317
|
+
return {
|
|
318
|
+
status: "failed",
|
|
319
|
+
exitCode: typeof failure.code === "number" ? failure.code : 1,
|
|
320
|
+
stdout: failure.stdout ?? "",
|
|
321
|
+
stderr: failure.stderr ?? failure.message ?? "unknown command failure",
|
|
322
|
+
toolVersion: await commandVersion(executable)
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
async function executePythonFsim(kernelArtifact, sdkRuntime, updateLiveRun) {
|
|
327
|
+
const { readSdkRuntimeSettings, readSdkRuntimeStatus } = await import("./sdk-runtime-JE6H2PB2.js");
|
|
328
|
+
const runtime = await readSdkRuntimeSettings(sdkRuntime);
|
|
329
|
+
const status = await readSdkRuntimeStatus(sdkRuntime);
|
|
330
|
+
const activeRuntime = sdkRuntimeExecutionView(runtime, status);
|
|
331
|
+
const runtimeMetadata = sdkRuntimeMetadata(activeRuntime, status);
|
|
332
|
+
const sdkRoot = path2.resolve(activeRuntime.preparedRoot);
|
|
333
|
+
const runnerPath = path2.join(
|
|
334
|
+
/*turbopackIgnore: true*/
|
|
335
|
+
packageFilePath(new URL(".", import.meta.url)),
|
|
336
|
+
"legato-fsim-runner.py"
|
|
337
|
+
);
|
|
338
|
+
const python = activeRuntime.pythonPath;
|
|
339
|
+
const preflightFailure = await preflightLoweringRuntime({
|
|
340
|
+
runtimeRoot: sdkRoot,
|
|
341
|
+
python,
|
|
342
|
+
runnerPath,
|
|
343
|
+
runtimeStatus: status.status,
|
|
344
|
+
runtimeMessage: status.message
|
|
345
|
+
});
|
|
346
|
+
if (preflightFailure) return { ...preflightFailure, failedStage: "FSIM", ...runtimeMetadata };
|
|
347
|
+
const outputRoot = await mkdtemp(path2.join(tmpdir(), "agora-legato-fsim-"));
|
|
348
|
+
const kernelPath = getArtifactTextPath(kernelArtifact);
|
|
349
|
+
const timeoutMs = readPositiveInt(process.env.AGORA_FSIM_TIMEOUT_MS ?? process.env.AGORA_LOWERING_TIMEOUT_MS, DEFAULT_FSIM_TIMEOUT_MS);
|
|
350
|
+
const env = loweringWorkerEnv(activeRuntime);
|
|
351
|
+
try {
|
|
352
|
+
const output = await spawnLoweringProcess(python, [
|
|
353
|
+
runnerPath,
|
|
354
|
+
"--kernel",
|
|
355
|
+
kernelPath,
|
|
356
|
+
"--output-root",
|
|
357
|
+
outputRoot
|
|
358
|
+
], {
|
|
359
|
+
cwd: sdkRoot,
|
|
360
|
+
env,
|
|
361
|
+
timeoutMs,
|
|
362
|
+
updateLiveRun: updateLiveRun ? async (stdout, stderr) => {
|
|
363
|
+
await updateLiveRun({
|
|
364
|
+
status: "running",
|
|
365
|
+
stdout: sanitizeWorkerOutput(stdout),
|
|
366
|
+
stderr: sanitizeWorkerOutput(stderr),
|
|
367
|
+
completedStage: parseCompletedStage(stdout),
|
|
368
|
+
failedStage: parseFailedStage(`${stdout}
|
|
369
|
+
${stderr}`),
|
|
370
|
+
...runtimeMetadata
|
|
371
|
+
});
|
|
372
|
+
} : void 0
|
|
373
|
+
});
|
|
374
|
+
return {
|
|
375
|
+
status: "success",
|
|
376
|
+
exitCode: 0,
|
|
377
|
+
stdout: sanitizeWorkerOutput(output.stdout),
|
|
378
|
+
stderr: sanitizeWorkerOutput(output.stderr),
|
|
379
|
+
completedStage: parseCompletedStage(output.stdout) ?? "FSIM",
|
|
380
|
+
generatedArtifacts: await listGeneratedArtifacts(outputRoot),
|
|
381
|
+
generatedArtifactFiles: await collectGeneratedArtifactFiles(outputRoot),
|
|
382
|
+
...runtimeMetadata
|
|
383
|
+
};
|
|
384
|
+
} catch (error) {
|
|
385
|
+
const failure = error;
|
|
386
|
+
const stdout = sanitizeWorkerOutput(failure.stdout ?? "");
|
|
387
|
+
const timeoutNote = failure.killed || failure.signal === "SIGTERM" ? `fSIM worker timed out after ${timeoutMs}ms` : "";
|
|
388
|
+
const stderr = sanitizeWorkerOutput([failure.stderr, timeoutNote, failure.message ?? "unknown fSIM failure"].filter(Boolean).join("\n"));
|
|
389
|
+
return {
|
|
390
|
+
status: "failed",
|
|
391
|
+
exitCode: typeof failure.code === "number" ? failure.code : 1,
|
|
392
|
+
stdout,
|
|
393
|
+
stderr,
|
|
394
|
+
failedStage: parseFailedStage(`${stdout}
|
|
395
|
+
${stderr}`) ?? "FSIM",
|
|
396
|
+
completedStage: parseCompletedStage(stdout),
|
|
397
|
+
generatedArtifacts: await listGeneratedArtifacts(outputRoot),
|
|
398
|
+
generatedArtifactFiles: await collectGeneratedArtifactFiles(outputRoot),
|
|
399
|
+
...runtimeMetadata
|
|
400
|
+
};
|
|
401
|
+
} finally {
|
|
402
|
+
await rm(outputRoot, { recursive: true, force: true });
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
async function executeLegacyFsim(plan, sdkRuntime) {
|
|
406
|
+
const { readSdkRuntimeSettings, readSdkRuntimeStatus } = await import("./sdk-runtime-JE6H2PB2.js");
|
|
407
|
+
const runtime = await readSdkRuntimeSettings(sdkRuntime);
|
|
408
|
+
const status = await readSdkRuntimeStatus(sdkRuntime);
|
|
409
|
+
const activeRuntime = sdkRuntimeExecutionView(runtime, status);
|
|
410
|
+
const runtimeMetadata = sdkRuntimeMetadata(activeRuntime, status);
|
|
411
|
+
const timeoutMs = readPositiveInt(process.env.AGORA_FSIM_TIMEOUT_MS ?? process.env.AGORA_LOWERING_TIMEOUT_MS, DEFAULT_FSIM_TIMEOUT_MS);
|
|
412
|
+
try {
|
|
413
|
+
const output = await execFileAsync(plan.command, plan.args, {
|
|
414
|
+
cwd: plan.cwd,
|
|
415
|
+
env: loweringWorkerEnv(activeRuntime),
|
|
416
|
+
timeout: timeoutMs,
|
|
417
|
+
maxBuffer: 2 * 1024 * 1024
|
|
418
|
+
});
|
|
419
|
+
return {
|
|
420
|
+
status: "success",
|
|
421
|
+
exitCode: 0,
|
|
422
|
+
stdout: sanitizeWorkerOutput(output.stdout),
|
|
423
|
+
stderr: sanitizeWorkerOutput(output.stderr),
|
|
424
|
+
completedStage: "FSIM",
|
|
425
|
+
...runtimeMetadata
|
|
426
|
+
};
|
|
427
|
+
} catch (error) {
|
|
428
|
+
const failure = error;
|
|
429
|
+
const timeoutNote = failure.killed || failure.signal === "SIGTERM" ? `legacy fSIM command timed out after ${timeoutMs}ms` : "";
|
|
430
|
+
return {
|
|
431
|
+
status: "failed",
|
|
432
|
+
exitCode: typeof failure.code === "number" ? failure.code : 1,
|
|
433
|
+
stdout: sanitizeWorkerOutput(failure.stdout ?? ""),
|
|
434
|
+
stderr: sanitizeWorkerOutput([failure.stderr, timeoutNote, failure.message ?? "unknown legacy fSIM failure"].filter(Boolean).join("\n")),
|
|
435
|
+
failedStage: "FSIM",
|
|
436
|
+
...runtimeMetadata
|
|
437
|
+
};
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
async function executePythonLowering(kernelArtifact, sdkRuntime, updateLiveRun) {
|
|
441
|
+
const { readSdkRuntimeSettings, readSdkRuntimeStatus } = await import("./sdk-runtime-JE6H2PB2.js");
|
|
442
|
+
const runtime = await readSdkRuntimeSettings(sdkRuntime);
|
|
443
|
+
const status = await readSdkRuntimeStatus(sdkRuntime);
|
|
444
|
+
const activeRuntime = sdkRuntimeExecutionView(runtime, status);
|
|
445
|
+
const runtimeMetadata = sdkRuntimeMetadata(activeRuntime, status);
|
|
446
|
+
const sdkRoot = path2.resolve(activeRuntime.preparedRoot);
|
|
447
|
+
const runnerPath = path2.join(
|
|
448
|
+
/*turbopackIgnore: true*/
|
|
449
|
+
packageFilePath(new URL(".", import.meta.url)),
|
|
450
|
+
"legato-lowering-runner.py"
|
|
451
|
+
);
|
|
452
|
+
const python = activeRuntime.pythonPath;
|
|
453
|
+
const preflightFailure = await preflightLoweringRuntime({
|
|
454
|
+
runtimeRoot: sdkRoot,
|
|
455
|
+
python,
|
|
456
|
+
runnerPath,
|
|
457
|
+
runtimeStatus: status.status,
|
|
458
|
+
runtimeMessage: status.message
|
|
459
|
+
});
|
|
460
|
+
if (preflightFailure) return { ...preflightFailure, ...runtimeMetadata };
|
|
461
|
+
const outputRoot = await mkdtemp(path2.join(tmpdir(), "agora-legato-lowering-"));
|
|
462
|
+
const kernelPath = getArtifactTextPath(kernelArtifact);
|
|
463
|
+
const stages = process.env.AGORA_LOWERING_STAGES ?? "MLIR,CORE_IR,BACKEND_IR,ASM,BINARY";
|
|
464
|
+
const timeoutMs = readPositiveInt(process.env.AGORA_LOWERING_TIMEOUT_MS, DEFAULT_LOWERING_TIMEOUT_MS);
|
|
465
|
+
const env = loweringWorkerEnv(activeRuntime);
|
|
466
|
+
try {
|
|
467
|
+
const output = await spawnLoweringProcess(python, [
|
|
468
|
+
runnerPath,
|
|
469
|
+
"--kernel",
|
|
470
|
+
kernelPath,
|
|
471
|
+
"--output-root",
|
|
472
|
+
outputRoot,
|
|
473
|
+
"--stages",
|
|
474
|
+
stages
|
|
475
|
+
], {
|
|
476
|
+
cwd: sdkRoot,
|
|
477
|
+
env,
|
|
478
|
+
timeoutMs,
|
|
479
|
+
updateLiveRun: updateLiveRun ? async (stdout, stderr) => {
|
|
480
|
+
await updateLiveRun({
|
|
481
|
+
status: "running",
|
|
482
|
+
stdout: sanitizeWorkerOutput(stdout),
|
|
483
|
+
stderr: sanitizeWorkerOutput(stderr),
|
|
484
|
+
completedStage: parseCompletedStage(stdout),
|
|
485
|
+
failedStage: parseFailedStage(`${stdout}
|
|
486
|
+
${stderr}`),
|
|
487
|
+
...runtimeMetadata
|
|
488
|
+
});
|
|
489
|
+
} : void 0
|
|
490
|
+
});
|
|
491
|
+
return {
|
|
492
|
+
status: "success",
|
|
493
|
+
exitCode: 0,
|
|
494
|
+
stdout: sanitizeWorkerOutput(output.stdout),
|
|
495
|
+
stderr: sanitizeWorkerOutput(output.stderr),
|
|
496
|
+
completedStage: parseCompletedStage(output.stdout),
|
|
497
|
+
generatedArtifacts: await listGeneratedArtifacts(outputRoot),
|
|
498
|
+
generatedArtifactFiles: await collectGeneratedArtifactFiles(outputRoot),
|
|
499
|
+
...runtimeMetadata,
|
|
500
|
+
generatedArtifactHash: await hashGeneratedArtifacts(outputRoot, parseCompletedStage(output.stdout))
|
|
501
|
+
};
|
|
502
|
+
} catch (error) {
|
|
503
|
+
const failure = error;
|
|
504
|
+
const stdout = sanitizeWorkerOutput(failure.stdout ?? "");
|
|
505
|
+
const timeoutNote = failure.killed || failure.signal === "SIGTERM" ? `lowering worker timed out after ${timeoutMs}ms` : "";
|
|
506
|
+
const stderr = sanitizeWorkerOutput([failure.stderr, timeoutNote, failure.message ?? "unknown lowering failure"].filter(Boolean).join("\n"));
|
|
507
|
+
return {
|
|
508
|
+
status: "failed",
|
|
509
|
+
exitCode: typeof failure.code === "number" ? failure.code : 1,
|
|
510
|
+
stdout,
|
|
511
|
+
stderr,
|
|
512
|
+
failedStage: parseFailedStage(`${stdout}
|
|
513
|
+
${stderr}`),
|
|
514
|
+
completedStage: parseCompletedStage(stdout),
|
|
515
|
+
generatedArtifacts: await listGeneratedArtifacts(outputRoot),
|
|
516
|
+
generatedArtifactFiles: await collectGeneratedArtifactFiles(outputRoot),
|
|
517
|
+
...runtimeMetadata,
|
|
518
|
+
generatedArtifactHash: await hashGeneratedArtifacts(outputRoot, parseCompletedStage(stdout))
|
|
519
|
+
};
|
|
520
|
+
} finally {
|
|
521
|
+
await rm(outputRoot, { recursive: true, force: true });
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
async function spawnLoweringProcess(command, args, options) {
|
|
525
|
+
return await new Promise((resolve, reject) => {
|
|
526
|
+
const child = spawn(command, args, {
|
|
527
|
+
cwd: options.cwd,
|
|
528
|
+
env: options.env,
|
|
529
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
530
|
+
});
|
|
531
|
+
let stdout = "";
|
|
532
|
+
let stderr = "";
|
|
533
|
+
let settled = false;
|
|
534
|
+
let lastUpdateAt = 0;
|
|
535
|
+
const flush = () => {
|
|
536
|
+
if (!options.updateLiveRun) return;
|
|
537
|
+
const nowMs = Date.now();
|
|
538
|
+
if (nowMs - lastUpdateAt < 1500) return;
|
|
539
|
+
lastUpdateAt = nowMs;
|
|
540
|
+
void options.updateLiveRun(stdout, stderr);
|
|
541
|
+
};
|
|
542
|
+
const timeout = setTimeout(() => {
|
|
543
|
+
if (settled) return;
|
|
544
|
+
child.kill("SIGTERM");
|
|
545
|
+
}, options.timeoutMs);
|
|
546
|
+
timeout.unref();
|
|
547
|
+
child.stdout?.on("data", (chunk) => {
|
|
548
|
+
stdout += Buffer.isBuffer(chunk) ? chunk.toString("utf8") : chunk;
|
|
549
|
+
flush();
|
|
550
|
+
});
|
|
551
|
+
child.stderr?.on("data", (chunk) => {
|
|
552
|
+
stderr += Buffer.isBuffer(chunk) ? chunk.toString("utf8") : chunk;
|
|
553
|
+
flush();
|
|
554
|
+
});
|
|
555
|
+
child.on("error", (error) => {
|
|
556
|
+
if (settled) return;
|
|
557
|
+
settled = true;
|
|
558
|
+
clearTimeout(timeout);
|
|
559
|
+
reject(Object.assign(error, { stdout, stderr }));
|
|
560
|
+
});
|
|
561
|
+
child.on("exit", (code, signal) => {
|
|
562
|
+
if (settled) return;
|
|
563
|
+
settled = true;
|
|
564
|
+
clearTimeout(timeout);
|
|
565
|
+
void (async () => {
|
|
566
|
+
if (options.updateLiveRun) await options.updateLiveRun(stdout, stderr);
|
|
567
|
+
if (code === 0) {
|
|
568
|
+
resolve({ stdout, stderr });
|
|
569
|
+
return;
|
|
570
|
+
}
|
|
571
|
+
reject({
|
|
572
|
+
code: typeof code === "number" ? code : 1,
|
|
573
|
+
signal,
|
|
574
|
+
killed: signal === "SIGTERM",
|
|
575
|
+
stdout,
|
|
576
|
+
stderr,
|
|
577
|
+
message: `lowering worker exited with ${typeof code === "number" ? `code ${code}` : `signal ${signal ?? "unknown"}`}`
|
|
578
|
+
});
|
|
579
|
+
})();
|
|
580
|
+
});
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
function sdkRuntimeMetadata(runtime, status) {
|
|
584
|
+
return {
|
|
585
|
+
sdkRepoUrl: runtime.repoUrl,
|
|
586
|
+
sdkBranch: runtime.branch,
|
|
587
|
+
sdkCommitSha: status.commitSha,
|
|
588
|
+
sdkPreparedRoot: runtime.preparedRoot
|
|
589
|
+
};
|
|
590
|
+
}
|
|
591
|
+
function sdkRuntimeExecutionView(runtime, status) {
|
|
592
|
+
if (status.status !== "ready") return runtime;
|
|
593
|
+
return {
|
|
594
|
+
...runtime,
|
|
595
|
+
preparedRoot: status.preparedRoot,
|
|
596
|
+
pythonPath: status.pythonPath,
|
|
597
|
+
extraPythonPaths: path2.join(status.preparedRoot, "legato_aten_lib")
|
|
598
|
+
};
|
|
599
|
+
}
|
|
600
|
+
function readPositiveInt(value, fallback) {
|
|
601
|
+
if (!value) return fallback;
|
|
602
|
+
const parsed = Number.parseInt(value, 10);
|
|
603
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : fallback;
|
|
604
|
+
}
|
|
605
|
+
async function hashGeneratedArtifacts(root, completedStage) {
|
|
606
|
+
if (!completedStage) return void 0;
|
|
607
|
+
const stageRoot = stageBasis(completedStage) ? path2.join(root, completedStage.toLowerCase()) : root;
|
|
608
|
+
const files = await listGeneratedArtifacts(stageRoot);
|
|
609
|
+
if (files.length === 0) return void 0;
|
|
610
|
+
const hash = createHash("sha256");
|
|
611
|
+
for (const relativePath of files) {
|
|
612
|
+
const filePath = path2.join(stageRoot, relativePath);
|
|
613
|
+
const bytes = await readFile2(filePath);
|
|
614
|
+
hash.update(relativePath);
|
|
615
|
+
hash.update("\0");
|
|
616
|
+
hash.update(normalizeArtifactBytes(relativePath, bytes));
|
|
617
|
+
hash.update("\0");
|
|
618
|
+
}
|
|
619
|
+
return hash.digest("hex");
|
|
620
|
+
}
|
|
621
|
+
function normalizeArtifactBytes(relativePath, bytes) {
|
|
622
|
+
const extension = path2.extname(relativePath).toLowerCase();
|
|
623
|
+
if (![".mlir", ".ll", ".s", ".asm", ".txt"].includes(extension)) return bytes;
|
|
624
|
+
return Buffer.from(bytes.toString("utf8").replace(/0x[a-fA-F0-9]+/g, "<addr>").replace(/[ \t]+/g, " ").replace(/\r\n/g, "\n").trim(), "utf8");
|
|
625
|
+
}
|
|
626
|
+
function buildVerificationFingerprint(result, kernelArtifact, createdAt) {
|
|
627
|
+
const diagnosticSignature = normalizeSignatureText(`${result.failedStage ?? ""}
|
|
628
|
+
${result.stdout}
|
|
629
|
+
${result.stderr}`).slice(0, 240);
|
|
630
|
+
const basis = stageBasis(result.completedStage) ?? (result.failedStage ? "diagnostic" : "raw");
|
|
631
|
+
const artifactHash = result.generatedArtifactHash ?? kernelArtifact?.checksum;
|
|
632
|
+
if (!artifactHash && !diagnosticSignature) return void 0;
|
|
633
|
+
const key = createHash("sha256").update(["lowering", basis, result.completedStage ?? "none", result.failedStage ?? "none", artifactHash ?? "no-artifact", diagnosticSignature].join("\0")).digest("hex");
|
|
634
|
+
return {
|
|
635
|
+
key,
|
|
636
|
+
basis,
|
|
637
|
+
lastSuccessfulStage: result.completedStage,
|
|
638
|
+
failedStage: result.failedStage,
|
|
639
|
+
artifactHash,
|
|
640
|
+
diagnosticSignature: diagnosticSignature || void 0,
|
|
641
|
+
createdAt
|
|
642
|
+
};
|
|
643
|
+
}
|
|
644
|
+
function stageBasis(stage) {
|
|
645
|
+
if (stage === "MLIR") return "mlir";
|
|
646
|
+
if (stage === "CORE_IR") return "core-ir";
|
|
647
|
+
if (stage === "BACKEND_IR") return "backend-ir";
|
|
648
|
+
if (stage === "ASM") return "asm";
|
|
649
|
+
if (stage === "BINARY") return "binary";
|
|
650
|
+
return void 0;
|
|
651
|
+
}
|
|
652
|
+
function normalizeSignatureText(text) {
|
|
653
|
+
return text.toLowerCase().replace(/[a-f0-9]{16,}/g, "<hash>").replace(/0x[a-f0-9]+/g, "<addr>").replace(/\d+/g, "<num>").replace(/\s+/g, " ").trim();
|
|
654
|
+
}
|
|
655
|
+
function sanitizeWorkerOutput(output) {
|
|
656
|
+
const redacted = output.replace(/([A-Z0-9_]*(?:TOKEN|SECRET|PASSWORD|KEY|CREDENTIAL)[A-Z0-9_]*=)[^\s]+/gi, "$1[redacted]").replace(/(Bearer\s+)[A-Za-z0-9._~+/-]+=*/gi, "$1[redacted]");
|
|
657
|
+
return redacted.length > 512 * 1024 ? `${redacted.slice(0, 512 * 1024)}
|
|
658
|
+
[truncated]
|
|
659
|
+
` : redacted;
|
|
660
|
+
}
|
|
661
|
+
function parseFailedStage(output) {
|
|
662
|
+
const matches = [...output.matchAll(/\[LEGATO_WORKER\] stage=([A-Z_]+) status=running/g)];
|
|
663
|
+
return matches.at(-1)?.[1];
|
|
664
|
+
}
|
|
665
|
+
function parseCompletedStage(output) {
|
|
666
|
+
const matches = [...output.matchAll(/\[LEGATO_WORKER\] stage=([A-Z_]+) status=success/g)];
|
|
667
|
+
return matches.at(-1)?.[1];
|
|
668
|
+
}
|
|
669
|
+
async function findExecutable(envPath, fallback) {
|
|
670
|
+
if (envPath) {
|
|
671
|
+
try {
|
|
672
|
+
await access2(envPath);
|
|
673
|
+
return envPath;
|
|
674
|
+
} catch {
|
|
675
|
+
return void 0;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
try {
|
|
679
|
+
const output = await execFileAsync("which", [fallback], { timeout: 2e3 });
|
|
680
|
+
return output.stdout.trim() || void 0;
|
|
681
|
+
} catch {
|
|
682
|
+
return void 0;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
async function pathExists(candidate) {
|
|
686
|
+
try {
|
|
687
|
+
await access2(candidate);
|
|
688
|
+
return true;
|
|
689
|
+
} catch {
|
|
690
|
+
return false;
|
|
691
|
+
}
|
|
692
|
+
}
|
|
693
|
+
async function commandVersion(command) {
|
|
694
|
+
try {
|
|
695
|
+
const output = await execFileAsync(command, ["--version"], { timeout: 2e3, maxBuffer: 64 * 1024 });
|
|
696
|
+
return output.stdout.trim() || output.stderr.trim() || void 0;
|
|
697
|
+
} catch {
|
|
698
|
+
return void 0;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
function buildLog(input) {
|
|
702
|
+
const commandLabel = `${path2.basename(input.plan.command)} ${input.plan.args.join(" ")}`;
|
|
703
|
+
const lines = [
|
|
704
|
+
`issue: ${input.issueId}`,
|
|
705
|
+
`kind: ${input.kind}`,
|
|
706
|
+
`mode: ${input.mode}`,
|
|
707
|
+
`status: ${input.result.status}`,
|
|
708
|
+
`startedAt: ${input.startedAt}`,
|
|
709
|
+
`completedAt: ${input.completedAt}`,
|
|
710
|
+
`cwd: ${input.plan.cwd}`,
|
|
711
|
+
`command: ${commandLabel}`,
|
|
712
|
+
`reason: ${input.plan.reason}`,
|
|
713
|
+
`sourceArtifactId: ${input.sourceArtifactId ?? "current bundle kernel"}`,
|
|
714
|
+
`kernelArtifact: ${input.kernelArtifact ? `${input.kernelArtifact.filename} (${getArtifactTextPath(input.kernelArtifact)})` : "missing"}`,
|
|
715
|
+
`coreIrArtifact: ${input.coreIrArtifact ? `${input.coreIrArtifact.filename} (${getArtifactTextPath(input.coreIrArtifact)})` : "missing"}`,
|
|
716
|
+
`environment.LEGATO_OPT: ${process.env.LEGATO_OPT ? "set" : "unset"}`,
|
|
717
|
+
`environment.AGORA_SDK_ROOT: ${process.env.AGORA_SDK_ROOT ? "set" : "unset"}`,
|
|
718
|
+
`environment.AGORA_LOWERING_STAGES: ${process.env.AGORA_LOWERING_STAGES ?? "default"}`,
|
|
719
|
+
`environment.AGORA_FSIM_DEVICE_VERSION: ${process.env.AGORA_FSIM_DEVICE_VERSION ?? "default"}`,
|
|
720
|
+
`environment.AGORA_FSIM_COMPUTE_MODE: ${process.env.AGORA_FSIM_COMPUTE_MODE ?? "default"}`,
|
|
721
|
+
`environment.AGORA_ISSUE_STORE: ${process.env.AGORA_ISSUE_STORE ? "set" : "unset"}`,
|
|
722
|
+
`exitCode: ${typeof input.result.exitCode === "number" ? input.result.exitCode : "not-run"}`,
|
|
723
|
+
`toolVersion: ${input.result.toolVersion ?? "unknown"}`,
|
|
724
|
+
`sdk.repoUrl: ${input.result.sdkRepoUrl ?? "unknown"}`,
|
|
725
|
+
`sdk.branch: ${input.result.sdkBranch ?? "unknown"}`,
|
|
726
|
+
`sdk.commitSha: ${input.result.sdkCommitSha ?? "unknown"}`,
|
|
727
|
+
`sdk.preparedRoot: ${input.result.sdkPreparedRoot ?? "unknown"}`,
|
|
728
|
+
"",
|
|
729
|
+
"skippedEvidence:",
|
|
730
|
+
...(input.result.skippedEvidence ?? ["none"]).map((item) => `- ${item}`),
|
|
731
|
+
"",
|
|
732
|
+
"failedStage:",
|
|
733
|
+
input.result.failedStage ?? "none",
|
|
734
|
+
"completedStage:",
|
|
735
|
+
input.result.completedStage ?? "none",
|
|
736
|
+
"",
|
|
737
|
+
"generatedArtifacts:",
|
|
738
|
+
...input.result.generatedArtifacts?.length ? input.result.generatedArtifacts.map((item) => `- ${item}`) : ["none"],
|
|
739
|
+
"",
|
|
740
|
+
"stdout:",
|
|
741
|
+
input.result.stdout || "<empty>",
|
|
742
|
+
"",
|
|
743
|
+
"stderr:",
|
|
744
|
+
input.result.stderr || "<empty>"
|
|
745
|
+
];
|
|
746
|
+
return `${lines.join("\n")}
|
|
747
|
+
`;
|
|
748
|
+
}
|
|
749
|
+
function verificationSummary(kind, result, reason) {
|
|
750
|
+
if (kind === "lowering" && result.status === "success") {
|
|
751
|
+
const stage = result.completedStage ? `${result.completedStage} \uB2E8\uACC4\uAE4C\uC9C0` : "\uC694\uCCAD\uB41C \uB2E8\uACC4\uAE4C\uC9C0";
|
|
752
|
+
return `\uC790\uB3D9 lowering\uC774 ${stage} \uC131\uACF5\uD588\uC2B5\uB2C8\uB2E4. \uC0DD\uC131\uB41C \uC0B0\uCD9C\uBB3C ${result.generatedArtifacts?.length ?? 0}\uAC1C\uB97C verification-output artifact\uB85C \uCCA8\uBD80\uD588\uC2B5\uB2C8\uB2E4.`;
|
|
753
|
+
}
|
|
754
|
+
if (kind === "lowering" && result.status === "failed") {
|
|
755
|
+
if (result.exitCode === 2) {
|
|
756
|
+
return "\uC790\uB3D9 lowering preflight\uAC00 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uCEE4\uB110 \uD568\uC218/Legato annotation/\uC778\uC790 \uD569\uC131 \uC624\uB958\uB294 verification-output \uB85C\uADF8\uB97C \uD655\uC778\uD558\uC138\uC694.";
|
|
757
|
+
}
|
|
758
|
+
const stage = result.failedStage ? `${result.failedStage} \uB2E8\uACC4` : "\uC54C \uC218 \uC5C6\uB294 \uB2E8\uACC4";
|
|
759
|
+
return `\uC790\uB3D9 lowering\uC774 ${stage}\uC5D0\uC11C \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. \uC804\uCCB4 stdout/stderr\uC640 traceback\uC740 verification-output \uB85C\uADF8\uB97C \uD655\uC778\uD558\uC138\uC694.`;
|
|
760
|
+
}
|
|
761
|
+
if (kind === "fsim" && result.status === "success") {
|
|
762
|
+
return `\uC790\uB3D9 fSIM \uC2E4\uD589\uC774 \uC131\uACF5\uD588\uC2B5\uB2C8\uB2E4. \uC0DD\uC131\uB41C \uC0B0\uCD9C\uBB3C ${result.generatedArtifacts?.length ?? 0}\uAC1C\uB97C verification-output artifact\uB85C \uCCA8\uBD80\uD588\uC2B5\uB2C8\uB2E4.`;
|
|
763
|
+
}
|
|
764
|
+
if (kind === "fsim" && result.status === "failed") {
|
|
765
|
+
return "\uC790\uB3D9 fSIM \uC2E4\uD589\uC774 \uC2E4\uD328\uD588\uC2B5\uB2C8\uB2E4. Python launcher stdout/stderr\uC640 HART fSIM \uC124\uC815 \uB85C\uADF8\uB294 verification-output \uB85C\uADF8\uB97C \uD655\uC778\uD558\uC138\uC694.";
|
|
766
|
+
}
|
|
767
|
+
return `Verification ${kind} ${result.status}. ${reason} See verification-output log.`;
|
|
768
|
+
}
|
|
769
|
+
export {
|
|
770
|
+
maybeRunAutoLowering,
|
|
771
|
+
runIssueVerification
|
|
772
|
+
};
|