loki-mode 11.60.6 → 11.60.7
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/SKILL.md +2 -2
- package/VERSION +1 -1
- package/dashboard/__init__.py +1 -1
- package/docs/CLI-REFERENCE.md +1 -1
- package/docs/INSTALLATION.md +1 -1
- package/docs/v10/FAILURE-CLASSES.md +7 -0
- package/loki-ts/dist/loki.js +1001 -1001
- package/mcp/__init__.py +1 -1
- package/package.json +2 -2
- package/packages/control-plane/dist/server.js +158 -139
- package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
- package/web-app/dist/assets/{AdminPage-D9gyJfvg.js → AdminPage-CljDBvb7.js} +1 -1
- package/web-app/dist/assets/{Avatar-BY4OsBd7.js → Avatar-C1gZQtLf.js} +1 -1
- package/web-app/dist/assets/{Badge-CjnB-l4J.js → Badge-BbE97OD6.js} +1 -1
- package/web-app/dist/assets/{Button-Cs5AwJUN.js → Button-BjbRBkxz.js} +1 -1
- package/web-app/dist/assets/{CockpitPage-BKyQS98K.js → CockpitPage-Besxk4Lg.js} +1 -1
- package/web-app/dist/assets/{ComparePage-Bax8CQ5r.js → ComparePage-CzHpF1zD.js} +1 -1
- package/web-app/dist/assets/{ErrorBoundary-CO3jKEz-.js → ErrorBoundary-B3To2epX.js} +1 -1
- package/web-app/dist/assets/{EvidenceReceiptPanel-C2UrIBC3.js → EvidenceReceiptPanel-2hS923Jc.js} +1 -1
- package/web-app/dist/assets/{GitHubIssuesPanel-WysHDP4j.js → GitHubIssuesPanel-DIS6D-Ob.js} +1 -1
- package/web-app/dist/assets/{GitHubPRsPanel-D3ju82bf.js → GitHubPRsPanel-C-wLwhdv.js} +1 -1
- package/web-app/dist/assets/{HomePage-dQDz58k8.js → HomePage-CE08fZN5.js} +2 -2
- package/web-app/dist/assets/{LoginPage-Cdfpfprn.js → LoginPage-DkObzKY1.js} +1 -1
- package/web-app/dist/assets/{MagicPage-A-7-YJuJ.js → MagicPage-xv4hEzFF.js} +1 -1
- package/web-app/dist/assets/{MetricsPage-C-WCXWtc.js → MetricsPage-D5ZoCFPb.js} +1 -1
- package/web-app/dist/assets/{NotFoundPage-DEGyErmU.js → NotFoundPage-CGjFl-RJ.js} +1 -1
- package/web-app/dist/assets/{ProjectPage-CZYKdYAZ.js → ProjectPage-DnE5oHKP.js} +3 -3
- package/web-app/dist/assets/{ProjectsPage-BOZPGOhO.js → ProjectsPage-VnelSqNP.js} +1 -1
- package/web-app/dist/assets/{SettingsPage-R55NJn80.js → SettingsPage-IGhmSheN.js} +1 -1
- package/web-app/dist/assets/{ShowcasePage-CrvXp3m9.js → ShowcasePage-DAjqwONf.js} +1 -1
- package/web-app/dist/assets/{SystemSettingsPage-D8orSNdI.js → SystemSettingsPage-BLWu_tn1.js} +1 -1
- package/web-app/dist/assets/{TeamsPage-CCdm7ZZ-.js → TeamsPage-DKp-StVx.js} +1 -1
- package/web-app/dist/assets/{TemplatesPage-Dn9kqNDQ.js → TemplatesPage-DUQPOWXS.js} +1 -1
- package/web-app/dist/assets/{TerminalOutput-_LHdfVb6.js → TerminalOutput-DP3xNAQ6.js} +1 -1
- package/web-app/dist/assets/{activity-D3ixbI4g.js → activity--4OpSJnD.js} +1 -1
- package/web-app/dist/assets/{bell-brydVmdF.js → bell-C6i6vGiV.js} +1 -1
- package/web-app/dist/assets/{bot-CrI-hv_Q.js → bot-nabUzHLs.js} +1 -1
- package/web-app/dist/assets/{check-CFTEUItB.js → check-C5Py_70l.js} +1 -1
- package/web-app/dist/assets/{chevron-left-DvQuQ7oO.js → chevron-left-DdeSSFI2.js} +1 -1
- package/web-app/dist/assets/{circle-alert-BvWmH0D-.js → circle-alert-DjFs2f5D.js} +1 -1
- package/web-app/dist/assets/{clock-CNVBkxxH.js → clock-D4d83RHv.js} +1 -1
- package/web-app/dist/assets/{cloud-U0CbUI0e.js → cloud-BO7jh-my.js} +1 -1
- package/web-app/dist/assets/{code-xml-P0a8nhml.js → code-xml-BfKx_xYB.js} +1 -1
- package/web-app/dist/assets/{database-BRtyOEj1.js → database-B9tUCHBU.js} +1 -1
- package/web-app/dist/assets/{dollar-sign-D1IHsVD0.js → dollar-sign-lNsaWJwi.js} +1 -1
- package/web-app/dist/assets/{file-code-corner-2LTHJbwE.js → file-code-corner-BcksEmZJ.js} +1 -1
- package/web-app/dist/assets/{file-plus-BxQRT8TR.js → file-plus-uljBVRRL.js} +1 -1
- package/web-app/dist/assets/{globe-CN9E5p8V.js → globe-CAb7OO-5.js} +1 -1
- package/web-app/dist/assets/{hammer-ZsPRXz6h.js → hammer-Cl5zqEr3.js} +1 -1
- package/web-app/dist/assets/{index-D8vrkhkX.js → index-IVIF8c8k.js} +3 -3
- package/web-app/dist/assets/{layers-DphOcgRs.js → layers-B8uJvkDN.js} +1 -1
- package/web-app/dist/assets/{loader-circle-BRRhrl4J.js → loader-circle-B-ZJiQm4.js} +1 -1
- package/web-app/dist/assets/{lock-D6YrpRf7.js → lock-CL1-_DKp.js} +1 -1
- package/web-app/dist/assets/{package-BnPy7mdh.js → package-C2bgLoPa.js} +1 -1
- package/web-app/dist/assets/{plus-LRFOAzef.js → plus-BubNhvaK.js} +1 -1
- package/web-app/dist/assets/{refresh-cw-CBB-8Gdo.js → refresh-cw-D1EH_iat.js} +1 -1
- package/web-app/dist/assets/{rotate-ccw-BtJrJKbp.js → rotate-ccw-DX5J9TZS.js} +1 -1
- package/web-app/dist/assets/{scroll-text-BTVBrxFs.js → scroll-text-CQbF12ug.js} +1 -1
- package/web-app/dist/assets/{server-DFvR3g0c.js → server-WEpN3x_8.js} +1 -1
- package/web-app/dist/assets/{shield-alert-CRNT4nop.js → shield-alert-BA8D1Dp7.js} +1 -1
- package/web-app/dist/assets/{thumbs-up-BtlGTPVg.js → thumbs-up-DcV-kzIk.js} +1 -1
- package/web-app/dist/assets/{trash-2-BbN0oUhQ.js → trash-2-_oo-pMo8.js} +1 -1
- package/web-app/dist/assets/{trending-down-DbOtbNIC.js → trending-down-Cmoq4vjN.js} +1 -1
- package/web-app/dist/assets/{trending-up-7RVzGLKa.js → trending-up-D9APgXxD.js} +1 -1
- package/web-app/dist/assets/{upload-Dt1YfXyy.js → upload-Dr6mX9WI.js} +1 -1
- package/web-app/dist/assets/{usePolling-BbzyWuzt.js → usePolling-CPKC8sq_.js} +1 -1
- package/web-app/dist/assets/{user-CON9IXcK.js → user-B8jDUDVn.js} +1 -1
- package/web-app/dist/index.html +1 -1
|
@@ -14780,6 +14780,25 @@ var init_version = __esm(() => {
|
|
|
14780
14780
|
});
|
|
14781
14781
|
|
|
14782
14782
|
// ../../loki-ts/src/e10ext/preexisting_dirty.ts
|
|
14783
|
+
import { lstatSync as lstatSync12 } from "fs";
|
|
14784
|
+
import { join as join54 } from "path";
|
|
14785
|
+
function untouchedUntracked(repoDir, recorded, env = process.env) {
|
|
14786
|
+
if (!recorded || typeof recorded !== "object")
|
|
14787
|
+
return [];
|
|
14788
|
+
return Object.entries(recorded).filter(([p, v]) => {
|
|
14789
|
+
if (typeof v !== "string")
|
|
14790
|
+
return false;
|
|
14791
|
+
try {
|
|
14792
|
+
const st = lstatSync12(join54(repoDir, p));
|
|
14793
|
+
if (v.startsWith("!"))
|
|
14794
|
+
return v === `!${st.size}:${st.mtimeMs}:${st.ctimeMs}`;
|
|
14795
|
+
const [sha3, mode] = v.split(" ");
|
|
14796
|
+
return st.isFile() && blob2(repoDir, p, env) === sha3 && (st.mode & 511).toString(8) === mode;
|
|
14797
|
+
} catch {
|
|
14798
|
+
return false;
|
|
14799
|
+
}
|
|
14800
|
+
}).map(([p]) => p);
|
|
14801
|
+
}
|
|
14783
14802
|
function untouchedSinceIntake(repoDir, recorded, env = process.env) {
|
|
14784
14803
|
if (!recorded || typeof recorded !== "object")
|
|
14785
14804
|
return [];
|
|
@@ -14798,9 +14817,9 @@ var init_preexisting_dirty = __esm(() => {
|
|
|
14798
14817
|
|
|
14799
14818
|
// ../../loki-ts/src/e10ext/commit_filter.ts
|
|
14800
14819
|
import { dirname as dirname22 } from "path";
|
|
14801
|
-
function dropSet(repoDir, staged, preexistingDirty, env = process.env, installCreated) {
|
|
14820
|
+
function dropSet(repoDir, staged, preexistingDirty, env = process.env, installCreated, untrackedBlobs) {
|
|
14802
14821
|
const owned = installOwned(repoDir, installCreated, env), made = installCreated?.files ?? {};
|
|
14803
|
-
return staged.concat(untouchedSinceIntake(repoDir, preexistingDirty, env).map((f) => ({ st: "L", f })), staged.filter(({ f }) => owned(f)).map(({ f }) => ({ st: "L", f }))).filter(({ st, f }) => f.startsWith(".loki/") || st === "L" || WALL_FILE.test(f) || st === "A" && !Object.hasOwn(made, f) && !staged.some(({ f: m }) => /(^|\/)(package\.json|pyproject\.toml|requirements\.txt|Cargo\.toml|go\.mod)$/.test(m) && dirname22(m) === dirname22(f)) && /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|poetry\.lock|Cargo\.lock|go\.sum)$/.test(f));
|
|
14822
|
+
return staged.concat(untouchedSinceIntake(repoDir, preexistingDirty, env).map((f) => ({ st: "L", f })), untouchedUntracked(repoDir, untrackedBlobs, env).map((f) => ({ st: "L", f })), staged.filter(({ f }) => owned(f)).map(({ f }) => ({ st: "L", f }))).filter(({ st, f }) => f.startsWith(".loki/") || st === "L" || WALL_FILE.test(f) || st === "A" && !Object.hasOwn(made, f) && !staged.some(({ f: m }) => /(^|\/)(package\.json|pyproject\.toml|requirements\.txt|Cargo\.toml|go\.mod)$/.test(m) && dirname22(m) === dirname22(f)) && /(^|\/)(package-lock\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lockb?|poetry\.lock|Cargo\.lock|go\.sum)$/.test(f));
|
|
14804
14823
|
}
|
|
14805
14824
|
var WALL_FILE, parseStaged = (out2) => out2.split("\x00").reduce((a, t, i, all) => i % 2 === 0 && t ? [...a, { st: t, f: all[i + 1] }] : a, []), formatChanged = (repoDir, staged, dropped2, env = process.env) => runFormatters(repoDir, staged.filter(({ st, f }) => (st === "A" || st === "M") && !dropped2.has(f) && !f.startsWith(".loki/")).map(({ f }) => f), tokenFreeEnv(env));
|
|
14806
14825
|
var init_commit_filter = __esm(() => {
|
|
@@ -14907,9 +14926,9 @@ var init_route_block = __esm(() => {
|
|
|
14907
14926
|
// ../../loki-ts/src/features/visual_evidence.ts
|
|
14908
14927
|
import { spawn as spawn8 } from "child_process";
|
|
14909
14928
|
import { createHash as createHash16, randomBytes as randomBytes6 } from "crypto";
|
|
14910
|
-
import { existsSync as existsSync35, lstatSync as
|
|
14929
|
+
import { existsSync as existsSync35, lstatSync as lstatSync13, mkdirSync as mkdirSync21, readdirSync as readdirSync20, readFileSync as readFileSync45, writeFileSync as writeFileSync24 } from "fs";
|
|
14911
14930
|
import { createServer } from "net";
|
|
14912
|
-
import { dirname as dirname23, isAbsolute as isAbsolute10, join as
|
|
14931
|
+
import { dirname as dirname23, isAbsolute as isAbsolute10, join as join55, normalize as normalize3, relative as relative10, sep as sep13 } from "path";
|
|
14913
14932
|
function routeFor(file) {
|
|
14914
14933
|
let r = file.replace(/^(?:.*?\/)?(?:app|pages|src|public)\//, "").replace(/^(?:routes|pages)\//, "");
|
|
14915
14934
|
r = r.replace(/\.(?:html|jsx|tsx|vue|svelte)$/, "").replace(/\/?(?:page|index|\+page)$/, "");
|
|
@@ -14919,7 +14938,7 @@ function hashScreens(runDir, rels) {
|
|
|
14919
14938
|
const out2 = [];
|
|
14920
14939
|
for (const rel of rels) {
|
|
14921
14940
|
try {
|
|
14922
|
-
out2.push({ path: rel, sha256: sha256File(
|
|
14941
|
+
out2.push({ path: rel, sha256: sha256File(join55(runDir, rel)) });
|
|
14923
14942
|
} catch {}
|
|
14924
14943
|
}
|
|
14925
14944
|
return out2;
|
|
@@ -14932,10 +14951,10 @@ function checkScreens(runDir, screens) {
|
|
|
14932
14951
|
return "evidence_screens entry is malformed";
|
|
14933
14952
|
if (isAbsolute10(s.path) || normalize3(s.path).startsWith(".."))
|
|
14934
14953
|
return `evidence screenshot path escapes the evidence dir: ${s.path}`;
|
|
14935
|
-
const file =
|
|
14954
|
+
const file = join55(runDir, s.path);
|
|
14936
14955
|
let cur = runDir;
|
|
14937
14956
|
for (const seg of normalize3(s.path).split(sep13)) {
|
|
14938
|
-
cur =
|
|
14957
|
+
cur = join55(cur, seg);
|
|
14939
14958
|
if (isSymlink(cur))
|
|
14940
14959
|
return `evidence screenshot path is a symlink: ${s.path}`;
|
|
14941
14960
|
}
|
|
@@ -14982,7 +15001,7 @@ async function waitUp(url, ms, signal) {
|
|
|
14982
15001
|
}
|
|
14983
15002
|
function openapiPaths(repoDir) {
|
|
14984
15003
|
for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
|
|
14985
|
-
const p =
|
|
15004
|
+
const p = join55(repoDir, f);
|
|
14986
15005
|
if (!existsSync35(p))
|
|
14987
15006
|
continue;
|
|
14988
15007
|
try {
|
|
@@ -15000,24 +15019,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
|
|
|
15000
15019
|
if (!pw || !pkg)
|
|
15001
15020
|
return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
|
|
15002
15021
|
try {
|
|
15003
|
-
const dir =
|
|
15022
|
+
const dir = join55(runDir, relDir, "e2e");
|
|
15004
15023
|
mkdirSync21(dir, { recursive: true });
|
|
15005
|
-
writeFileSync24(
|
|
15006
|
-
writeFileSync24(
|
|
15024
|
+
writeFileSync24(join55(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
|
|
15025
|
+
writeFileSync24(join55(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
|
|
15007
15026
|
`);
|
|
15008
|
-
if (!await shoot(pw, ["test", "--config",
|
|
15027
|
+
if (!await shoot(pw, ["test", "--config", join55(dir, "playwright.config.cjs")], repoDir, ms, signal))
|
|
15009
15028
|
return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
|
|
15010
15029
|
const rels = [];
|
|
15011
15030
|
const walk = (d) => {
|
|
15012
15031
|
for (const e of readdirSync20(d, { withFileTypes: true })) {
|
|
15013
|
-
const full =
|
|
15032
|
+
const full = join55(d, e.name);
|
|
15014
15033
|
if (e.isDirectory())
|
|
15015
15034
|
walk(full);
|
|
15016
15035
|
else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
|
|
15017
|
-
rels.push(
|
|
15036
|
+
rels.push(join55(relDir, "e2e", relative10(dir, full)));
|
|
15018
15037
|
}
|
|
15019
15038
|
};
|
|
15020
|
-
walk(
|
|
15039
|
+
walk(join55(dir, "out"));
|
|
15021
15040
|
return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
|
|
15022
15041
|
} catch (e) {
|
|
15023
15042
|
return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
|
|
@@ -15096,15 +15115,15 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
15096
15115
|
if (!visualEvidenceEnabled(opts.env))
|
|
15097
15116
|
return skip("LOKI_VISUAL_EVIDENCE is 0");
|
|
15098
15117
|
const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
|
|
15099
|
-
const appDir = boot ?
|
|
15100
|
-
const pkgPath =
|
|
15118
|
+
const appDir = boot ? join55(repoDir, boot.boot.cwd) : repoDir;
|
|
15119
|
+
const pkgPath = join55(appDir, "package.json");
|
|
15101
15120
|
let script = null;
|
|
15102
15121
|
if (!boot) {
|
|
15103
15122
|
if (!existsSync35(pkgPath)) {
|
|
15104
|
-
const subs = ["backend", "frontend"].filter((d) => existsSync35(
|
|
15123
|
+
const subs = ["backend", "frontend"].filter((d) => existsSync35(join55(repoDir, d, "package.json")));
|
|
15105
15124
|
const has2 = (d) => {
|
|
15106
15125
|
try {
|
|
15107
|
-
return pickScript(JSON.parse(readFileSync45(
|
|
15126
|
+
return pickScript(JSON.parse(readFileSync45(join55(repoDir, d, "package.json"), "utf8"))) !== null;
|
|
15108
15127
|
} catch {
|
|
15109
15128
|
return false;
|
|
15110
15129
|
}
|
|
@@ -15138,20 +15157,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
15138
15157
|
}
|
|
15139
15158
|
if (!await waitUp(base, left(), signal))
|
|
15140
15159
|
return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
|
|
15141
|
-
const evRoot =
|
|
15160
|
+
const evRoot = join55(runDir, "evidence");
|
|
15142
15161
|
if (isSymlink(evRoot))
|
|
15143
15162
|
return skip("evidence dir is a symlink");
|
|
15144
15163
|
mkdirSync21(evRoot, { recursive: true });
|
|
15145
15164
|
if (pages.length > 0) {
|
|
15146
|
-
const rel0 =
|
|
15147
|
-
mkdirSync21(
|
|
15165
|
+
const rel0 = join55("evidence", randomBytes6(6).toString("hex"));
|
|
15166
|
+
mkdirSync21(join55(runDir, rel0));
|
|
15148
15167
|
const rels = [];
|
|
15149
15168
|
for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
|
|
15150
15169
|
if (aborted() || left() <= 0)
|
|
15151
15170
|
break;
|
|
15152
|
-
const rel =
|
|
15153
|
-
const ok = await shoot(pw, ["screenshot", `${base}${route}`,
|
|
15154
|
-
if (ok && !aborted() && !isSymlink(
|
|
15171
|
+
const rel = join55(rel0, `${screenName(route)}.png`);
|
|
15172
|
+
const ok = await shoot(pw, ["screenshot", `${base}${route}`, join55(runDir, rel)], appDir, left(), signal);
|
|
15173
|
+
if (ok && !aborted() && !isSymlink(join55(runDir, rel)) && existsSync35(join55(runDir, rel)))
|
|
15155
15174
|
rels.push(rel);
|
|
15156
15175
|
}
|
|
15157
15176
|
if (aborted())
|
|
@@ -15176,9 +15195,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
|
|
|
15176
15195
|
}
|
|
15177
15196
|
if (aborted())
|
|
15178
15197
|
return skip("aborted");
|
|
15179
|
-
const hdir =
|
|
15198
|
+
const hdir = join55(evRoot, randomBytes6(6).toString("hex"));
|
|
15180
15199
|
mkdirSync21(hdir);
|
|
15181
|
-
writeFileSync24(
|
|
15200
|
+
writeFileSync24(join55(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
|
|
15182
15201
|
`);
|
|
15183
15202
|
return { screens: [], http: true, skipped: null };
|
|
15184
15203
|
} catch (e) {
|
|
@@ -15208,24 +15227,24 @@ function receiptScreensProblem(receiptPath, receipt) {
|
|
|
15208
15227
|
return receipt["evidence_screens"] === undefined ? null : checkScreens(dirname23(receiptPath), receipt["evidence_screens"]);
|
|
15209
15228
|
}
|
|
15210
15229
|
var visualEvidenceEnabled = (env = process.env) => env["LOKI_VISUAL_EVIDENCE"] !== "0", visualGateEnabled = (env = process.env) => env["LOKI_VISUAL_GATE"] === "1", PAGE_RE, isPageFile = (p) => PAGE_RE.test(p), screenName = (route) => (route === "/" ? "index" : route.slice(1).replace(/[^A-Za-z0-9._-]+/g, "_")) || "index", sha256File = (p) => createHash16("sha256").update(readFileSync45(p)).digest("hex"), playwrightBin = (repoDir) => {
|
|
15211
|
-
const bin =
|
|
15230
|
+
const bin = join55(repoDir, "node_modules", ".bin", "playwright");
|
|
15212
15231
|
return existsSync35(bin) ? bin : null;
|
|
15213
15232
|
}, playwrightTestPkg = (repoDir) => {
|
|
15214
|
-
const d =
|
|
15215
|
-
return existsSync35(
|
|
15233
|
+
const d = join55(repoDir, "node_modules", "@playwright", "test");
|
|
15234
|
+
return existsSync35(join55(d, "package.json")) ? d : null;
|
|
15216
15235
|
}, e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
|
|
15217
15236
|
test("loki e2e walkthrough", async ({ page }) => {
|
|
15218
15237
|
for (const r of ${JSON.stringify(routes)}) { await page.goto(${JSON.stringify(base)} + r); await page.waitForLoadState("load"); }
|
|
15219
15238
|
});
|
|
15220
15239
|
`, DEFAULT_BUDGET_MS = 25000, MAX_ROUTES = 5, isSymlink = (p) => {
|
|
15221
15240
|
try {
|
|
15222
|
-
return
|
|
15241
|
+
return lstatSync13(p).isSymbolicLink();
|
|
15223
15242
|
} catch {
|
|
15224
15243
|
return false;
|
|
15225
15244
|
}
|
|
15226
15245
|
}, isRegularFile = (p) => {
|
|
15227
15246
|
try {
|
|
15228
|
-
return
|
|
15247
|
+
return lstatSync13(p).isFile();
|
|
15229
15248
|
} catch {
|
|
15230
15249
|
return false;
|
|
15231
15250
|
}
|
|
@@ -15258,7 +15277,7 @@ var init_outbox = __esm(() => {
|
|
|
15258
15277
|
});
|
|
15259
15278
|
|
|
15260
15279
|
// ../../loki-ts/src/engine10/stages/pr.ts
|
|
15261
|
-
import { join as
|
|
15280
|
+
import { join as join56 } from "path";
|
|
15262
15281
|
var DEFAULT_PUSH_SH, DEFAULT_PUSH_GITLAB_SH, SHA_RE;
|
|
15263
15282
|
var init_pr = __esm(() => {
|
|
15264
15283
|
init_types();
|
|
@@ -15278,14 +15297,14 @@ var init_pr = __esm(() => {
|
|
|
15278
15297
|
init_receipt_surface();
|
|
15279
15298
|
init_yaml_key();
|
|
15280
15299
|
init_outbox();
|
|
15281
|
-
DEFAULT_PUSH_SH =
|
|
15282
|
-
DEFAULT_PUSH_GITLAB_SH =
|
|
15300
|
+
DEFAULT_PUSH_SH = join56(REPO_ROOT, "autonomy/lib/engine10-push.sh");
|
|
15301
|
+
DEFAULT_PUSH_GITLAB_SH = join56(REPO_ROOT, "autonomy/lib/engine10-push-gitlab.sh");
|
|
15283
15302
|
SHA_RE = /^[0-9a-f]{40}$/;
|
|
15284
15303
|
});
|
|
15285
15304
|
|
|
15286
15305
|
// ../../loki-ts/src/util/pr_lessons.ts
|
|
15287
15306
|
import { existsSync as existsSync36, mkdirSync as mkdirSync22, mkdtempSync as mkdtempSync8, readFileSync as readFileSync46, rmSync as rmSync17, writeFileSync as writeFileSync25 } from "fs";
|
|
15288
|
-
import { dirname as dirname24, join as
|
|
15307
|
+
import { dirname as dirname24, join as join57 } from "path";
|
|
15289
15308
|
import { createHash as createHash17 } from "crypto";
|
|
15290
15309
|
function loadLessons(repoDir) {
|
|
15291
15310
|
const p = lessonsPath(repoDir);
|
|
@@ -15334,7 +15353,7 @@ function recordRunVerdict(repoDir, runId2, verdict) {
|
|
|
15334
15353
|
if (dirty)
|
|
15335
15354
|
save(repoDir, lessons);
|
|
15336
15355
|
}
|
|
15337
|
-
var lessonsPath = (repoDir) =>
|
|
15356
|
+
var lessonsPath = (repoDir) => join57(repoDir, ".loki", "memory", "semantic", "pr-lessons.json"), KINDS;
|
|
15338
15357
|
var init_pr_lessons = __esm(() => {
|
|
15339
15358
|
init_atomic();
|
|
15340
15359
|
init_safe_git();
|
|
@@ -15357,12 +15376,12 @@ var init_attempts = __esm(() => {
|
|
|
15357
15376
|
});
|
|
15358
15377
|
|
|
15359
15378
|
// ../../loki-ts/src/runner/router/route_record.ts
|
|
15360
|
-
import { existsSync as existsSync37, lstatSync as
|
|
15361
|
-
import { join as
|
|
15379
|
+
import { existsSync as existsSync37, lstatSync as lstatSync14, mkdirSync as mkdirSync23, readFileSync as readFileSync47, writeFileSync as writeFileSync26 } from "fs";
|
|
15380
|
+
import { join as join58 } from "path";
|
|
15362
15381
|
function loadRouteRecord(runDir) {
|
|
15363
15382
|
try {
|
|
15364
|
-
const p =
|
|
15365
|
-
if (!existsSync37(p) || !
|
|
15383
|
+
const p = join58(runDir, ROUTE_RECORD_FILE);
|
|
15384
|
+
if (!existsSync37(p) || !lstatSync14(p).isFile())
|
|
15366
15385
|
return;
|
|
15367
15386
|
const v = JSON.parse(readFileSync47(p, "utf8"));
|
|
15368
15387
|
return typeof v === "object" && v !== null && !Array.isArray(v) ? v : undefined;
|
|
@@ -15506,14 +15525,14 @@ __export(exports_deep, {
|
|
|
15506
15525
|
deepStage: () => deepStage,
|
|
15507
15526
|
DEFAULT_SECRET_SCAN_SH: () => DEFAULT_SECRET_SCAN_SH
|
|
15508
15527
|
});
|
|
15509
|
-
import { copyFileSync as copyFileSync3, existsSync as existsSync38, lstatSync as
|
|
15528
|
+
import { copyFileSync as copyFileSync3, existsSync as existsSync38, lstatSync as lstatSync15, mkdirSync as mkdirSync24, mkdtempSync as mkdtempSync9, rmSync as rmSync18, writeFileSync as writeFileSync27 } from "fs";
|
|
15510
15529
|
import { tmpdir as tmpdir10 } from "os";
|
|
15511
|
-
import { dirname as dirname25, join as
|
|
15530
|
+
import { dirname as dirname25, join as join59 } from "path";
|
|
15512
15531
|
function sessionCouncil(sessions) {
|
|
15513
15532
|
return { async run(input, signal) {
|
|
15514
|
-
const cwd = mkdtempSync9(
|
|
15533
|
+
const cwd = mkdtempSync9(join59(tmpdir10(), "loki-deep-council-"));
|
|
15515
15534
|
try {
|
|
15516
|
-
writeFileSync27(
|
|
15535
|
+
writeFileSync27(join59(cwd, "diff.patch"), input.diff, "utf8");
|
|
15517
15536
|
const r = await sessions.run({
|
|
15518
15537
|
stage: "deep",
|
|
15519
15538
|
tier: "development",
|
|
@@ -15583,7 +15602,7 @@ ${r.stderr}`), lr = r.exitCode === 0 ? undefined : await harnessLoadReason({ rep
|
|
|
15583
15602
|
async function runAppBoot(ctx, opts, checks, notProven) {
|
|
15584
15603
|
let r;
|
|
15585
15604
|
try {
|
|
15586
|
-
r = await (opts.appProbe ?? appProbe)(ctx.repoDir,
|
|
15605
|
+
r = await (opts.appProbe ?? appProbe)(ctx.repoDir, join59(ctx.repoDir, ".loki"));
|
|
15587
15606
|
} catch (err) {
|
|
15588
15607
|
r = { checks: [{ name: "app boot", cmd: "autonomy/app-runner.sh", result: "not_run", duration_s: 0, reason: `app probe threw: ${err.message}` }], pid: null, url: null };
|
|
15589
15608
|
}
|
|
@@ -15629,12 +15648,12 @@ async function runCouncilCheck(ctx, changed, baseSha, signal, opts, checks, notP
|
|
|
15629
15648
|
}
|
|
15630
15649
|
}
|
|
15631
15650
|
async function secureScanChanged(repoDir, changed, opts) {
|
|
15632
|
-
const dir = mkdtempSync9(
|
|
15651
|
+
const dir = mkdtempSync9(join59(tmpdir10(), "loki-deep-secure-"));
|
|
15633
15652
|
try {
|
|
15634
15653
|
for (const f of changed)
|
|
15635
|
-
if (existsSync38(
|
|
15636
|
-
mkdirSync24(dirname25(
|
|
15637
|
-
copyFileSync3(
|
|
15654
|
+
if (existsSync38(join59(repoDir, f)) && lstatSync15(join59(repoDir, f)).isFile()) {
|
|
15655
|
+
mkdirSync24(dirname25(join59(dir, f)), { recursive: true });
|
|
15656
|
+
copyFileSync3(join59(repoDir, f), join59(dir, f));
|
|
15638
15657
|
}
|
|
15639
15658
|
return await runSecureScan(dir, { ...opts.secureScanPath ? { scriptPath: opts.secureScanPath } : {}, timeoutMs: 60000 });
|
|
15640
15659
|
} finally {
|
|
@@ -15654,7 +15673,7 @@ async function runSecretScan(ctx, changed, opts, checks, notProven) {
|
|
|
15654
15673
|
}
|
|
15655
15674
|
const inline = 'script="$1"; shift; . "$script" || exit 3; hit=0; for f in "$@"; do if _commit_scan_secret_file "$f" || _commit_path_looks_secret "$f"; then printf "%s\\n" "$f"; hit=1; fi; done; exit "$hit"';
|
|
15656
15675
|
const started = Date.now();
|
|
15657
|
-
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) =>
|
|
15676
|
+
const r = await run(["bash", "-c", inline, "_", scriptPath, ...changed.map((f) => join59(ctx.repoDir, f))], { cwd: ctx.repoDir, timeoutMs: 30000 });
|
|
15658
15677
|
const sec = await secureScanChanged(ctx.repoDir, changed, opts), gaps = [], reasons = [];
|
|
15659
15678
|
const hits = r.exitCode === 3 ? [] : r.stdout.split(`
|
|
15660
15679
|
`).map((l) => l.trim()).filter(Boolean), high = sec.findings.filter((f) => String(f.severity).toUpperCase() === "HIGH");
|
|
@@ -15692,7 +15711,7 @@ async function postResults(ctx, opts, checks, notProven, statusState) {
|
|
|
15692
15711
|
const prNumber = prUrl ? PR_NUMBER_RE.exec(prUrl)?.[1] : undefined;
|
|
15693
15712
|
if (prNumber) {
|
|
15694
15713
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
15695
|
-
const bodyFile =
|
|
15714
|
+
const bodyFile = join59(ctx.runDir, "deep-comment.md");
|
|
15696
15715
|
writeFileSync27(bodyFile, buildCommentBody(checks, notProven, statusState), "utf8");
|
|
15697
15716
|
const commentResult = await run(["bash", scriptPath, "comment", prNumber, bodyFile], { cwd: ctx.repoDir, env, timeoutMs: 30000 });
|
|
15698
15717
|
if (commentResult.exitCode !== 0)
|
|
@@ -15747,7 +15766,7 @@ async function runDeep(ctx, signal, opts = {}) {
|
|
|
15747
15766
|
const sig = signReceipt(`${ctx.runId}-deep`, addendumSha256);
|
|
15748
15767
|
const addendum = { ...addendumBody, addendum_sha256: addendumSha256, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
15749
15768
|
mkdirSync24(ctx.runDir, { recursive: true });
|
|
15750
|
-
writeFileSync27(
|
|
15769
|
+
writeFileSync27(join59(ctx.runDir, "receipt-addendum-1.json"), JSON.stringify(addendum, null, 2) + `
|
|
15751
15770
|
`);
|
|
15752
15771
|
const pushNotProven = await postResults(ctx, opts, checks, notProvenList, statusState);
|
|
15753
15772
|
const allNotProven = [...notProvenList, ...pushNotProven];
|
|
@@ -15784,7 +15803,7 @@ var init_deep = __esm(() => {
|
|
|
15784
15803
|
// ../../loki-ts/src/engine10/stages/verify.ts
|
|
15785
15804
|
import { existsSync as existsSync39, mkdtempSync as mkdtempSync10, rmSync as rmSync19 } from "fs";
|
|
15786
15805
|
import { tmpdir as tmpdir11 } from "os";
|
|
15787
|
-
import { isAbsolute as isAbsolute11, join as
|
|
15806
|
+
import { isAbsolute as isAbsolute11, join as join60, relative as relative11 } from "path";
|
|
15788
15807
|
async function runOnce2(cmd2, args, cwd, signal, opts) {
|
|
15789
15808
|
if (!Bun.which(cmd2, { PATH: opts.path ?? process.env["PATH"] ?? "" }))
|
|
15790
15809
|
return { ok: false, missing: true, cut: false, out: "" };
|
|
@@ -15858,7 +15877,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
|
|
|
15858
15877
|
const zc = zeroOk ? un.filter(({ c, t }) => c.result === "not_run" && !c.owner && (c.reason ?? "").startsWith(NO_TESTS_REASON) && !wall.has(c.name) && !isHoldoutCheck(c.name) && !changed.includes(t.path) && zeroIntake.has(c.name)) : [];
|
|
15859
15878
|
if (!(un.some(({ c }) => c.result === "fail" && c.ids?.length) || sus.length || zc.length) || signal.aborted)
|
|
15860
15879
|
return out2;
|
|
15861
|
-
const dir = mkdtempSync10(
|
|
15880
|
+
const dir = mkdtempSync10(join60(tmpdir11(), "e10-base-"));
|
|
15862
15881
|
const git4 = (args) => {
|
|
15863
15882
|
safeGit(ctx.repoDir, args, { stdio: "ignore", repoDrivers: true });
|
|
15864
15883
|
};
|
|
@@ -15897,7 +15916,7 @@ async function subtractBase(ctx, api, checks, tests, changed, wall, rel, signal,
|
|
|
15897
15916
|
return out2;
|
|
15898
15917
|
}
|
|
15899
15918
|
function isLokiModeRepo(repoDir) {
|
|
15900
|
-
return existsSync39(
|
|
15919
|
+
return existsSync39(join60(repoDir, "scripts", "select-tests.sh"));
|
|
15901
15920
|
}
|
|
15902
15921
|
async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
15903
15922
|
const { api, ...runOpts } = opts;
|
|
@@ -15919,9 +15938,9 @@ async function runLintChecks(ctx, changed, signal, checks, opts = {}) {
|
|
|
15919
15938
|
}
|
|
15920
15939
|
for (const g of groupByPackage(api, ctx.repoDir, changed.filter((f) => /\.(ts|tsx|js|jsx)$/.test(f)))) {
|
|
15921
15940
|
const sfx = g.root === "." ? "" : `:${g.root}`, co = g.root === "." ? opts : { ...opts, cwd: g.cwd };
|
|
15922
|
-
if (existsSync39(
|
|
15941
|
+
if (existsSync39(join60(g.cwd, "tsconfig.json")))
|
|
15923
15942
|
await runCheck(ctx, `lint:tsc${sfx}`, "npx", ["--no-install", "tsc", "--noEmit", "-p", "."], signal, checks, { ...co, kind: "static" });
|
|
15924
|
-
if (ESLINT_CONFIGS.some((f) => existsSync39(
|
|
15943
|
+
if (ESLINT_CONFIGS.some((f) => existsSync39(join60(g.cwd, f)))) {
|
|
15925
15944
|
const c = await runCheck(ctx, `lint:eslint${sfx}`, "npx", ["--no-install", "eslint", ...g.rel], signal, checks, { ...co, kind: "static" });
|
|
15926
15945
|
if (await excuseLint(ctx, signal, c, "eslint", "npx", ["--no-install", "eslint"], g.cwd, g.rel, co))
|
|
15927
15946
|
pre.push(c.name);
|
|
@@ -15936,7 +15955,7 @@ var CHECK_TIMEOUT_MS = 60000, excerpts, isHold = (c) => isHoldoutCheck(c.name),
|
|
|
15936
15955
|
return r.missing || r.cut ? null : r;
|
|
15937
15956
|
}, base: (f) => {
|
|
15938
15957
|
try {
|
|
15939
|
-
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative11(ctx.repoDir,
|
|
15958
|
+
return safeGit(ctx.repoDir, ["show", `${ctx.baseSha}:${relative11(ctx.repoDir, join60(cwd, f))}`], { stdio: ["ignore", "pipe", "ignore"] });
|
|
15940
15959
|
} catch {
|
|
15941
15960
|
return null;
|
|
15942
15961
|
}
|
|
@@ -16113,7 +16132,7 @@ ${x}` : c.cmd };
|
|
|
16113
16132
|
import { spawnSync as spawnSync7 } from "child_process";
|
|
16114
16133
|
import { existsSync as existsSync40, mkdirSync as mkdirSync25, mkdtempSync as mkdtempSync11, readFileSync as readFileSync48, readdirSync as readdirSync21, rmSync as rmSync20, writeFileSync as writeFileSync28 } from "fs";
|
|
16115
16134
|
import { tmpdir as tmpdir12 } from "os";
|
|
16116
|
-
import { dirname as dirname26, join as
|
|
16135
|
+
import { dirname as dirname26, join as join61, relative as relative12 } from "path";
|
|
16117
16136
|
|
|
16118
16137
|
class RealBaseTestRunner {
|
|
16119
16138
|
api;
|
|
@@ -16178,7 +16197,7 @@ ${acceptance.map((a) => `Acceptance: ${a}`).join(`
|
|
|
16178
16197
|
function loadTaskText(ctx, fromPrior) {
|
|
16179
16198
|
if (fromPrior)
|
|
16180
16199
|
return fromPrior;
|
|
16181
|
-
const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ??
|
|
16200
|
+
const issueJsonPath = process.env.LOKI_E10_ISSUE_JSON ?? join61(ctx.runDir, "issue.json");
|
|
16182
16201
|
if (existsSync40(issueJsonPath)) {
|
|
16183
16202
|
try {
|
|
16184
16203
|
const issue = JSON.parse(readFileSync48(issueJsonPath, "utf8"));
|
|
@@ -16193,7 +16212,7 @@ function loadTaskText(ctx, fromPrior) {
|
|
|
16193
16212
|
}
|
|
16194
16213
|
function wallTargetDir(repoDir, existingTests) {
|
|
16195
16214
|
const first = existingTests[0];
|
|
16196
|
-
return first ?
|
|
16215
|
+
return first ? join61(repoDir, dirname26(first.path)) : join61(repoDir, "tests");
|
|
16197
16216
|
}
|
|
16198
16217
|
function guessRunner(fileName, runners) {
|
|
16199
16218
|
if (fileName.endsWith(".py"))
|
|
@@ -16226,11 +16245,11 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
16226
16245
|
const tree = prior.intake?.tree;
|
|
16227
16246
|
const repomapText = repoMapText(ctx.repoDir, tree, repomapRef, WALL_MAP_MAX_LINES);
|
|
16228
16247
|
const targetDir = wallTargetDir(ctx.repoDir, existingTests), pkg = loadProjectApi(ctx.repoDir)?.packageOf(`${relative12(ctx.repoDir, targetDir)}/x`);
|
|
16229
|
-
const conv2 = readPackageConventions(
|
|
16230
|
-
const cwd = mkdtempSync11(
|
|
16248
|
+
const conv2 = readPackageConventions(join61(ctx.repoDir, pkg?.root ?? "."), pkg?.runner ?? null);
|
|
16249
|
+
const cwd = mkdtempSync11(join61(tmpdir12(), "loki-e15-wall-"));
|
|
16231
16250
|
const wm = wallManifestFor(ctx.repoDir, tree, task);
|
|
16232
16251
|
for (const [n2, c] of [["task.md", task], ["repomap.txt", repomapText], ...wm ? [["wall_manifest.txt", wm.text]] : []])
|
|
16233
|
-
writeFileSync28(
|
|
16252
|
+
writeFileSync28(join61(cwd, n2), c, "utf8");
|
|
16234
16253
|
const model = retry?.model ?? wallFirstModel(sz.size), iterationId = `${ctx.runId}-wall${retry?.suffix ?? ""}`;
|
|
16235
16254
|
const session = await ctx.sessions.run({
|
|
16236
16255
|
stage: "wall",
|
|
@@ -16248,21 +16267,21 @@ async function wallAuthor(ctx, signal, retry) {
|
|
|
16248
16267
|
}
|
|
16249
16268
|
const planText = typeof prior.plan?.plan === "string" ? prior.plan.plan : null, repoFiles = repoMap?.files ?? [];
|
|
16250
16269
|
const oor = () => readdirSync21(cwd).filter((f) => f.startsWith(WALL_PREFIX)).flatMap((name) => {
|
|
16251
|
-
const text2 = readFileSync48(
|
|
16270
|
+
const text2 = readFileSync48(join61(cwd, name), "utf8"), why = outOfRepoTarget(text2) ?? phantomReason(phantomRepoPaths(text2, name, targetDir, ctx.repoDir, planText), repoFiles, relative12(ctx.repoDir, targetDir), pkg?.root ?? "");
|
|
16252
16271
|
return why ? [{ name, why }] : [];
|
|
16253
16272
|
});
|
|
16254
16273
|
const bad1 = oor();
|
|
16255
16274
|
if (bad1.length > 0 && !signal.aborted && !ctx.overCap?.())
|
|
16256
16275
|
await ctx.sessions.run({ stage: "wall", brief: withStagePrefix(outOfRepoReask("Rewrite these Wall files in place, keeping the same names and acceptance coverage.", bad1)), tier: "development", model, iterationId: `${iterationId}-oor`, limitS: wallLimitS(sz.size), signal, cwd });
|
|
16257
|
-
const oorBad = new Map(oor().map((b) => [b.name, b.why])), all = readdirSync21(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n2) => !oorBad.has(n2) && !conventionViolation(conv2, n2, readFileSync48(
|
|
16258
|
-
const sealedDir =
|
|
16276
|
+
const oorBad = new Map(oor().map((b) => [b.name, b.why])), all = readdirSync21(cwd).filter((f) => f.startsWith(WALL_PREFIX)), held = stashHoldout({ runId: ctx.runId, repoDir: ctx.repoDir, srcDir: cwd, targetDir, names: all.filter((n2) => !oorBad.has(n2) && !conventionViolation(conv2, n2, readFileSync48(join61(cwd, n2), "utf8"))), runnerOf: (n2) => guessRunner(n2, runners) }), generated = all.filter((n2) => !held?.names.has(n2));
|
|
16277
|
+
const sealedDir = join61(ctx.runDir, "wall");
|
|
16259
16278
|
if (generated.length > 0)
|
|
16260
16279
|
mkdirSync25(sealedDir, { recursive: true });
|
|
16261
16280
|
const contents = new Map;
|
|
16262
16281
|
const discarded = [];
|
|
16263
16282
|
for (const name of generated) {
|
|
16264
|
-
const content = readFileSync48(
|
|
16265
|
-
writeFileSync28(
|
|
16283
|
+
const content = readFileSync48(join61(cwd, name), "utf8"), oorWhy = oorBad.get(name), bad = oorWhy ?? conventionViolation(conv2, name, content);
|
|
16284
|
+
writeFileSync28(join61(sealedDir, name), content, "utf8");
|
|
16266
16285
|
if (oorWhy)
|
|
16267
16286
|
discarded.push({ file: name, reason: `${oorWhy}; wall test discarded after one rewrite request` });
|
|
16268
16287
|
else if (bad)
|
|
@@ -16291,7 +16310,7 @@ function* installCore(ctx, a, baseDir, opts) {
|
|
|
16291
16310
|
const content = contents.get(name);
|
|
16292
16311
|
if (content === undefined)
|
|
16293
16312
|
continue;
|
|
16294
|
-
const dest =
|
|
16313
|
+
const dest = join61(targetDir, name), runner = guessRunner(name, runners);
|
|
16295
16314
|
writeFileSync28(dest, content, "utf8");
|
|
16296
16315
|
sealedFiles.push({ path: dest, sha256: sha2562(content) });
|
|
16297
16316
|
readOnlyFiles.push({ path: dest, content });
|
|
@@ -16303,7 +16322,7 @@ function* installCore(ctx, a, baseDir, opts) {
|
|
|
16303
16322
|
const baseRunner = opts.baseRunner ?? new RealBaseTestRunner, baseRun = { pass: 0, fail: 0, not_run: discarded.length }, notRunFiles = [];
|
|
16304
16323
|
const each = yield { runner: baseRunner, tests: wallTests };
|
|
16305
16324
|
for (const [i, t] of wallTests.entries()) {
|
|
16306
|
-
const e = each?.[i], r = e ?? baseRunner.run(baseDir, [t]), abs =
|
|
16325
|
+
const e = each?.[i], r = e ?? baseRunner.run(baseDir, [t]), abs = join61(ctx.repoDir, t.path);
|
|
16307
16326
|
baseRun.pass += r.pass;
|
|
16308
16327
|
baseRun.fail += r.fail;
|
|
16309
16328
|
baseRun.not_run += r.not_run ?? 0;
|
|
@@ -16344,7 +16363,7 @@ async function runWall(ctx, signal, opts = {}) {
|
|
|
16344
16363
|
if (a.kind === "authored") {
|
|
16345
16364
|
for (const f of first.data.files ?? [])
|
|
16346
16365
|
rmSync20(f.path, { force: true });
|
|
16347
|
-
rmSync20(
|
|
16366
|
+
rmSync20(join61(ctx.runDir, "wall"), { recursive: true, force: true });
|
|
16348
16367
|
ctx.wallSealed = false;
|
|
16349
16368
|
}
|
|
16350
16369
|
removeHoldout(ctx.runId, ctx.repoDir);
|
|
@@ -16380,18 +16399,18 @@ var init_wall = __esm(() => {
|
|
|
16380
16399
|
});
|
|
16381
16400
|
|
|
16382
16401
|
// ../../loki-ts/src/e10ext/discard.ts
|
|
16383
|
-
import { chmodSync as chmodSync5, closeSync as closeSync9, lstatSync as
|
|
16384
|
-
import { dirname as dirname27, join as
|
|
16402
|
+
import { chmodSync as chmodSync5, closeSync as closeSync9, lstatSync as lstatSync16, mkdirSync as mkdirSync26, openSync as openSync9, readFileSync as readFileSync49, realpathSync as realpathSync23, rmdirSync, unlinkSync as unlinkSync7, writeFileSync as writeFileSync29 } from "fs";
|
|
16403
|
+
import { dirname as dirname27, join as join62, relative as relative13, sep as sep14 } from "path";
|
|
16385
16404
|
function safeRestore(repoDir, f, want, mode) {
|
|
16386
|
-
const root = realpathSync23(repoDir), fp =
|
|
16405
|
+
const root = realpathSync23(repoDir), fp = join62(root, f), rel = relative13(root, dirname27(fp));
|
|
16387
16406
|
if (rel.startsWith(".."))
|
|
16388
16407
|
throw new Error("outside repo");
|
|
16389
16408
|
let cur = root;
|
|
16390
16409
|
for (const part of rel === "" ? [] : rel.split(sep14)) {
|
|
16391
|
-
cur =
|
|
16410
|
+
cur = join62(cur, part);
|
|
16392
16411
|
let st2;
|
|
16393
16412
|
try {
|
|
16394
|
-
st2 =
|
|
16413
|
+
st2 = lstatSync16(cur);
|
|
16395
16414
|
} catch {
|
|
16396
16415
|
mkdirSync26(cur);
|
|
16397
16416
|
continue;
|
|
@@ -16401,7 +16420,7 @@ function safeRestore(repoDir, f, want, mode) {
|
|
|
16401
16420
|
}
|
|
16402
16421
|
let st;
|
|
16403
16422
|
try {
|
|
16404
|
-
st =
|
|
16423
|
+
st = lstatSync16(fp);
|
|
16405
16424
|
} catch {
|
|
16406
16425
|
st = null;
|
|
16407
16426
|
}
|
|
@@ -16442,10 +16461,10 @@ async function discardIfSatisfied(git4, base, o, staged, keep, repoDir) {
|
|
|
16442
16461
|
return { status: "failed", data: {}, reason: "already-satisfied discard failed" };
|
|
16443
16462
|
const notProven = [];
|
|
16444
16463
|
for (const [f, v] of Object.entries(o.intake?.preexisting_untracked_blobs ?? {})) {
|
|
16445
|
-
const fp =
|
|
16464
|
+
const fp = join62(repoDir, f);
|
|
16446
16465
|
try {
|
|
16447
16466
|
if (v.startsWith("!")) {
|
|
16448
|
-
const st =
|
|
16467
|
+
const st = lstatSync16(fp);
|
|
16449
16468
|
if (`!${st.size}:${st.mtimeMs}:${st.ctimeMs}` !== v)
|
|
16450
16469
|
throw new Error("changed, not snapshotted");
|
|
16451
16470
|
continue;
|
|
@@ -16461,7 +16480,7 @@ async function discardIfSatisfied(git4, base, o, staged, keep, repoDir) {
|
|
|
16461
16480
|
try {
|
|
16462
16481
|
let m = 420;
|
|
16463
16482
|
try {
|
|
16464
|
-
const l =
|
|
16483
|
+
const l = lstatSync16(join62(repoDir, f));
|
|
16465
16484
|
if (l.isFile())
|
|
16466
16485
|
m = l.mode & 511;
|
|
16467
16486
|
} catch {}
|
|
@@ -16509,9 +16528,9 @@ var init_scope2 = __esm(() => {
|
|
|
16509
16528
|
// ../../loki-ts/src/council/role_agents.ts
|
|
16510
16529
|
import { existsSync as existsSync41, readdirSync as readdirSync22, readFileSync as readFileSync50 } from "fs";
|
|
16511
16530
|
import { homedir as homedir9 } from "os";
|
|
16512
|
-
import { join as
|
|
16531
|
+
import { join as join63 } from "path";
|
|
16513
16532
|
function agentDirs(repoDir, env = process.env) {
|
|
16514
|
-
return [env["LOKI_AGENTS_PROJECT_DIR"] ||
|
|
16533
|
+
return [env["LOKI_AGENTS_PROJECT_DIR"] || join63(repoDir, ".loki", "agents"), env["LOKI_AGENTS_USER_DIR"] || join63(env["XDG_CONFIG_HOME"] || join63(homedir9(), ".config"), "loki", "agents")];
|
|
16515
16534
|
}
|
|
16516
16535
|
function parseAgent(file, stem2) {
|
|
16517
16536
|
const m = /^---\r?\n([\s\S]*?)\r?\n---\r?\n?([\s\S]*)$/.exec(readFileSync50(file, "utf8"));
|
|
@@ -16539,7 +16558,7 @@ function loadRoleAgent(repoDir, role, env = process.env) {
|
|
|
16539
16558
|
const ordered = [...names.filter((n2) => n2 === `${role}.md`), ...names.filter((n2) => n2 !== `${role}.md`)];
|
|
16540
16559
|
for (const n2 of ordered) {
|
|
16541
16560
|
try {
|
|
16542
|
-
const a = parseAgent(
|
|
16561
|
+
const a = parseAgent(join63(d, n2), n2.slice(0, -3));
|
|
16543
16562
|
if (a && a.role === role)
|
|
16544
16563
|
return a;
|
|
16545
16564
|
} catch {}
|
|
@@ -16557,7 +16576,7 @@ var init_role_agents = __esm(() => {
|
|
|
16557
16576
|
|
|
16558
16577
|
// ../../loki-ts/src/util/child_ledger.ts
|
|
16559
16578
|
import { appendFileSync as appendFileSync4, mkdirSync as mkdirSync27 } from "fs";
|
|
16560
|
-
import { join as
|
|
16579
|
+
import { join as join64 } from "path";
|
|
16561
16580
|
function unmeasuredRecord(phase, model, source) {
|
|
16562
16581
|
return { phase, model, input_tokens: 0, output_tokens: 0, cache_creation_tokens: 0, cache_read_tokens: 0, source, cost_status: "unmeasured" };
|
|
16563
16582
|
}
|
|
@@ -16582,9 +16601,9 @@ function recordFromClaudeResult(phase, payload, source = "claude-json") {
|
|
|
16582
16601
|
}
|
|
16583
16602
|
function appendChildLedger(lokiDir2, rec2) {
|
|
16584
16603
|
try {
|
|
16585
|
-
const dir =
|
|
16604
|
+
const dir = join64(lokiDir2, "metrics");
|
|
16586
16605
|
mkdirSync27(dir, { recursive: true });
|
|
16587
|
-
appendFileSync4(
|
|
16606
|
+
appendFileSync4(join64(dir, "child-sessions.jsonl"), `${JSON.stringify(rec2)}
|
|
16588
16607
|
`);
|
|
16589
16608
|
return true;
|
|
16590
16609
|
} catch {
|
|
@@ -16635,10 +16654,10 @@ var init_colors = __esm(() => {
|
|
|
16635
16654
|
|
|
16636
16655
|
// ../../loki-ts/src/util/run_summary.ts
|
|
16637
16656
|
import { existsSync as existsSync42, mkdirSync as mkdirSync28, readFileSync as readFileSync51, renameSync as renameSync12, statSync as statSync20, writeFileSync as writeFileSync30 } from "fs";
|
|
16638
|
-
import { join as
|
|
16657
|
+
import { join as join65 } from "path";
|
|
16639
16658
|
function readRiskRecord(repoDir, sinceMs = 0) {
|
|
16640
16659
|
try {
|
|
16641
|
-
const p =
|
|
16660
|
+
const p = join65(repoDir, ".loki", "state", "risk-tier.json");
|
|
16642
16661
|
if (statSync20(p).mtimeMs < sinceMs)
|
|
16643
16662
|
return null;
|
|
16644
16663
|
const r = JSON.parse(readFileSync51(p, "utf8"));
|
|
@@ -16658,7 +16677,7 @@ var init_run_summary = __esm(() => {
|
|
|
16658
16677
|
|
|
16659
16678
|
// ../../loki-ts/src/engine10/stages/xreview.ts
|
|
16660
16679
|
import { existsSync as existsSync43, readFileSync as readFileSync52 } from "fs";
|
|
16661
|
-
import { join as
|
|
16680
|
+
import { join as join66 } from "path";
|
|
16662
16681
|
function minVerdict(verdict, review) {
|
|
16663
16682
|
const ceiling = review?.level === "block" ? "PARTIAL" : verdict;
|
|
16664
16683
|
return RANK3[ceiling] < RANK3[verdict] ? ceiling : verdict;
|
|
@@ -16671,7 +16690,7 @@ function explicitReview(repoDir, env) {
|
|
|
16671
16690
|
if (flag && isOff(ev))
|
|
16672
16691
|
return "off";
|
|
16673
16692
|
for (const f of ["loki.yaml", "loki.yml"]) {
|
|
16674
|
-
const p =
|
|
16693
|
+
const p = join66(repoDir, f);
|
|
16675
16694
|
if (!existsSync43(p))
|
|
16676
16695
|
continue;
|
|
16677
16696
|
try {
|
|
@@ -16769,7 +16788,7 @@ Review ONLY the diff below. Do not modify files.` : "You are an independent code
|
|
|
16769
16788
|
try {
|
|
16770
16789
|
if (p === "claude")
|
|
16771
16790
|
await ensureClaudeHelpCache();
|
|
16772
|
-
const r = await withChildLedger(run,
|
|
16791
|
+
const r = await withChildLedger(run, join66(ctx.repoDir, ".loki"), "xreview")(reviewArgv(p, prompt, process.env, p === "claude" ? agent?.model : undefined), { cwd: ctx.repoDir, timeoutMs: boxFor(ctx) * 1000, group: true, signal });
|
|
16773
16792
|
if (r.exitCode !== 0)
|
|
16774
16793
|
return tag({ provider: p, level: "not_run", notes: [`cross-review not run: ${p} exited ${r.exitCode}`] });
|
|
16775
16794
|
return tag(parseReview(p, r.stdout));
|
|
@@ -16870,8 +16889,8 @@ See also: loki cost --detail (what a run ALREADY spent)
|
|
|
16870
16889
|
});
|
|
16871
16890
|
|
|
16872
16891
|
// ../../loki-ts/src/features/contract.ts
|
|
16873
|
-
import { existsSync as existsSync44, lstatSync as
|
|
16874
|
-
import { dirname as dirname29, join as
|
|
16892
|
+
import { existsSync as existsSync44, lstatSync as lstatSync17, mkdirSync as mkdirSync29, readFileSync as readFileSync53, rmSync as rmSync21, writeFileSync as writeFileSync31 } from "fs";
|
|
16893
|
+
import { dirname as dirname29, join as join67 } from "path";
|
|
16875
16894
|
import { createHash as createHash18 } from "crypto";
|
|
16876
16895
|
function contractEnabled(env = process.env) {
|
|
16877
16896
|
return env["LOKI_CONTRACT"] !== "0";
|
|
@@ -16903,13 +16922,13 @@ function untracedLines(trace) {
|
|
|
16903
16922
|
return trace.criteria.filter((c) => c.status === "no_match").map((c) => `contract ${sanitizeCriterion(c.id)} untraced (no keyword match in changed files): ${sanitizeCriterion(c.text)}`);
|
|
16904
16923
|
}
|
|
16905
16924
|
function contractPath(repoDir) {
|
|
16906
|
-
return
|
|
16925
|
+
return join67(repoDir, ".loki", "contract.json");
|
|
16907
16926
|
}
|
|
16908
16927
|
function readContract(repoDir) {
|
|
16909
16928
|
const p = contractPath(repoDir);
|
|
16910
16929
|
let st;
|
|
16911
16930
|
try {
|
|
16912
|
-
st =
|
|
16931
|
+
st = lstatSync17(p);
|
|
16913
16932
|
} catch {
|
|
16914
16933
|
return { contract: null, notes: [], sha256: null };
|
|
16915
16934
|
}
|
|
@@ -16954,7 +16973,7 @@ function sealContract(repoDir, body, rawDiff, checks, env = process.env, snap) {
|
|
|
16954
16973
|
const live2 = readContract(repoDir);
|
|
16955
16974
|
let exists2 = true;
|
|
16956
16975
|
try {
|
|
16957
|
-
|
|
16976
|
+
lstatSync17(contractPath(repoDir));
|
|
16958
16977
|
} catch {
|
|
16959
16978
|
exists2 = false;
|
|
16960
16979
|
}
|
|
@@ -16988,16 +17007,16 @@ var init_contract = __esm(() => {
|
|
|
16988
17007
|
init_safe_git();
|
|
16989
17008
|
STOP3 = new Set(["the", "and", "for", "with", "that", "this", "must", "should", "shall", "when", "then", "are", "was", "all", "any", "can", "not", "has", "have", "from", "into", "each", "user", "users"]);
|
|
16990
17009
|
MAX_CONTRACT_BYTES = 1024 * 1024;
|
|
16991
|
-
REQ_MAP_REL =
|
|
17010
|
+
REQ_MAP_REL = join67(".loki", "state", "requirements-map.json");
|
|
16992
17011
|
REQ_STOP = new Set(["with", "that", "this", "from", "have", "will", "should", "must", "when", "then", "into", "each", "every", "user", "users", "page", "able", "allow", "support", "ensure", "using", "their", "there", "which", "shall"]);
|
|
16993
17012
|
});
|
|
16994
17013
|
|
|
16995
17014
|
// ../../loki-ts/src/features/speed/seal_group.ts
|
|
16996
17015
|
import { createHash as createHash19 } from "crypto";
|
|
16997
17016
|
import { existsSync as existsSync45, mkdirSync as mkdirSync30, readdirSync as readdirSync23, readFileSync as readFileSync54, renameSync as renameSync13, statSync as statSync21, writeFileSync as writeFileSync32 } from "fs";
|
|
16998
|
-
import { dirname as dirname30, join as
|
|
17017
|
+
import { dirname as dirname30, join as join68 } from "path";
|
|
16999
17018
|
function sealGroup(runDir, rh) {
|
|
17000
|
-
const manifestPath =
|
|
17019
|
+
const manifestPath = join68(runDir, "group", "manifest.json");
|
|
17001
17020
|
if (!existsSync45(manifestPath))
|
|
17002
17021
|
return { section: undefined, notProven: [], problems: 0, allUnitsPass: true };
|
|
17003
17022
|
const notProven = [];
|
|
@@ -17022,7 +17041,7 @@ function sealGroup(runDir, rh) {
|
|
|
17022
17041
|
return fail2(`unit ${index2} has an invalid, duplicate or case-colliding id`);
|
|
17023
17042
|
seen.add(id);
|
|
17024
17043
|
seenLower.add(id.toLowerCase());
|
|
17025
|
-
const dir =
|
|
17044
|
+
const dir = join68(unitsDir(runDir), id), rp = join68(dir, "receipt.json"), ep = join68(dir, "events.jsonl");
|
|
17026
17045
|
let bytes;
|
|
17027
17046
|
try {
|
|
17028
17047
|
bytes = readFileSync54(rp);
|
|
@@ -17067,7 +17086,7 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
17067
17086
|
const bad = (reason) => ({ verdict: "TAMPERED", reason: `group: ${reason}` });
|
|
17068
17087
|
const g = receipt["group"];
|
|
17069
17088
|
if (g === undefined)
|
|
17070
|
-
return existsSync45(
|
|
17089
|
+
return existsSync45(join68(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
|
|
17071
17090
|
if (!isObj10(g) || !ID_RE.test(String(g["group_id"] ?? "")) || !Array.isArray(g["units"]) || g["units"].length === 0)
|
|
17072
17091
|
return bad("group section malformed");
|
|
17073
17092
|
const entries = g["units"];
|
|
@@ -17079,7 +17098,7 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
17079
17098
|
return bad("unit directories do not match the receipt (missing or extra unit)");
|
|
17080
17099
|
let unchecked = null;
|
|
17081
17100
|
for (let i = 0;i < entries.length; i++) {
|
|
17082
|
-
const e = entries[i], id = ids[i], dir =
|
|
17101
|
+
const e = entries[i], id = ids[i], dir = join68(unitsDir(runDir), id), rp = join68(dir, "receipt.json"), ep = join68(dir, "events.jsonl");
|
|
17083
17102
|
if (e["index"] !== i)
|
|
17084
17103
|
return bad(`unit ${id} is out of order (index ${String(e["index"])} at position ${i})`);
|
|
17085
17104
|
let bytes;
|
|
@@ -17115,7 +17134,7 @@ function compositeVerdict(childVerdicts) {
|
|
|
17115
17134
|
const failed2 = childVerdicts.filter((v) => v === "FAILED" || !["VERIFIED", "ALREADY_SATISFIED", "PARTIAL", "SPEC_CONFLICT"].includes(v)).length;
|
|
17116
17135
|
return capGroupVerdict(base, { section: undefined, notProven: [], problems: failed2, allUnitsPass: childVerdicts.every((v) => PASSING.has(v)) });
|
|
17117
17136
|
}
|
|
17118
|
-
var ID_RE, PASSING, sha3 = (b) => createHash19("sha256").update(b).digest("hex"), isObj10 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0, unitsDir = (runDir) =>
|
|
17137
|
+
var ID_RE, PASSING, sha3 = (b) => createHash19("sha256").update(b).digest("hex"), isObj10 = (v) => v !== null && typeof v === "object" && !Array.isArray(v), text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "", num4 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0, unitsDir = (runDir) => join68(runDir, "group", "units"), readJson6 = (p) => {
|
|
17119
17138
|
try {
|
|
17120
17139
|
return JSON.parse(readFileSync54(p, "utf8"));
|
|
17121
17140
|
} catch {
|
|
@@ -17136,7 +17155,7 @@ var init_seal_group = __esm(() => {
|
|
|
17136
17155
|
|
|
17137
17156
|
// ../../loki-ts/src/supply/supply_guard.ts
|
|
17138
17157
|
import { existsSync as existsSync46, readFileSync as readFileSync55, statSync as statSync22 } from "fs";
|
|
17139
|
-
import { basename as basename25, join as
|
|
17158
|
+
import { basename as basename25, join as join69 } from "path";
|
|
17140
17159
|
function supplyEnabled(env) {
|
|
17141
17160
|
return env["LOKI_SUPPLY_GUARD"] !== "0";
|
|
17142
17161
|
}
|
|
@@ -17151,7 +17170,7 @@ function isManifestPath(path) {
|
|
|
17151
17170
|
return MANIFESTS.test(basename25(path));
|
|
17152
17171
|
}
|
|
17153
17172
|
function readDeclared(repoDir) {
|
|
17154
|
-
const p =
|
|
17173
|
+
const p = join69(repoDir, ".loki", DECLARED_FILE);
|
|
17155
17174
|
if (!existsSync46(p))
|
|
17156
17175
|
return { deps: [], problem: null };
|
|
17157
17176
|
try {
|
|
@@ -17177,7 +17196,7 @@ function readDeclared(repoDir) {
|
|
|
17177
17196
|
}
|
|
17178
17197
|
}
|
|
17179
17198
|
function readAllowlist(repoDir) {
|
|
17180
|
-
const p =
|
|
17199
|
+
const p = join69(repoDir, ".loki", "supply-allowlist");
|
|
17181
17200
|
if (!existsSync46(p))
|
|
17182
17201
|
return new Set;
|
|
17183
17202
|
try {
|
|
@@ -17222,7 +17241,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
17222
17241
|
if (eco === "npm") {
|
|
17223
17242
|
if (privateUrlList([env["npm_config_registry"] ?? "", env["NPM_CONFIG_REGISTRY"] ?? ""]))
|
|
17224
17243
|
return true;
|
|
17225
|
-
return files(
|
|
17244
|
+
return files(join69(repoDir, ".npmrc"), home ? join69(home, ".npmrc") : "").some((t) => t.split(`
|
|
17226
17245
|
`).some((l) => {
|
|
17227
17246
|
const m = /^\s*(?:(@[^:\s]+):)?registry\s*=\s*(\S+)/.exec(l);
|
|
17228
17247
|
return !!m && privateUrl(m[2]) && (m[1] === undefined || name.startsWith(`${m[1]}/`));
|
|
@@ -17231,7 +17250,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
17231
17250
|
if (eco === "pypi") {
|
|
17232
17251
|
if (privateUrlList([env["PIP_INDEX_URL"] ?? "", env["PIP_EXTRA_INDEX_URL"] ?? ""]))
|
|
17233
17252
|
return true;
|
|
17234
|
-
const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ?
|
|
17253
|
+
const cfg = [env["PIP_CONFIG_FILE"] ?? "", home ? join69(home, ".config", "pip", "pip.conf") : "", home ? join69(home, ".pip", "pip.conf") : "", join69(repoDir, "pip.conf")];
|
|
17235
17254
|
return files(...cfg).some((t) => t.split(`
|
|
17236
17255
|
`).some((l) => {
|
|
17237
17256
|
const m = /^\s*(?:extra-)?index-url\s*[=:]\s*(.+)$/.exec(l);
|
|
@@ -17241,7 +17260,7 @@ function userConfigPrivate(eco, repoDir, env, goEnv = {}, name = "") {
|
|
|
17241
17260
|
if (eco === "cargo") {
|
|
17242
17261
|
if (Object.keys(env).some((k) => /^CARGO_REGISTRIES_.+_INDEX$/.test(k) || /^CARGO_SOURCE_/.test(k)))
|
|
17243
17262
|
return true;
|
|
17244
|
-
return files(
|
|
17263
|
+
return files(join69(repoDir, ".cargo", "config.toml"), join69(repoDir, ".cargo", "config"), home ? join69(home, ".cargo", "config.toml") : "", home ? join69(home, ".cargo", "config") : "").some((t) => /^\s*\[(registries\.|source\.)/m.test(t) || /replace-with\s*=/.test(t));
|
|
17245
17264
|
}
|
|
17246
17265
|
if (eco === "go") {
|
|
17247
17266
|
const gp = goEnv["GOPROXY"] ?? env["GOPROXY"] ?? "";
|
|
@@ -17381,7 +17400,7 @@ var init_supply_guard = __esm(() => {
|
|
|
17381
17400
|
// ../../loki-ts/src/engine10/stages/seal.ts
|
|
17382
17401
|
import { createHash as createHash20 } from "crypto";
|
|
17383
17402
|
import { existsSync as existsSync47, readdirSync as readdirSync24, mkdirSync as mkdirSync31, readFileSync as readFileSync56 } from "fs";
|
|
17384
|
-
import { basename as basename26, isAbsolute as isAbsolute13, join as
|
|
17403
|
+
import { basename as basename26, isAbsolute as isAbsolute13, join as join70, relative as relative14 } from "path";
|
|
17385
17404
|
function receiptSha256(r) {
|
|
17386
17405
|
const { verification: _v, receipt_sha256: _h, ...body } = r;
|
|
17387
17406
|
return sha2562(canonicalJson(body));
|
|
@@ -17456,7 +17475,7 @@ function renderReceiptMd(r) {
|
|
|
17456
17475
|
`);
|
|
17457
17476
|
}
|
|
17458
17477
|
var SIGNING_UNAVAILABLE = "receipt signing unavailable (no usable signing key: invalid key or unwritable ~/.loki/keys)", AGENT_ONLY_REASON = "only agent-authored tests executed (no agent-independent proof)", WALL_GREEN_ON_BASE_REASON = "Wall green on base: no Wall test discriminates the change", EXCLUDE_LOKI = ":(exclude).loki", sha2562 = (s) => createHash20("sha256").update(s).digest("hex"), str4 = (v) => typeof v === "string" && v !== "" ? v : null, strs2 = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string" && x !== "") : [], g = (ctx) => (a) => git4(ctx, a), receiptRel = (ctx) => {
|
|
17459
|
-
const r = relative14(ctx.repoDir,
|
|
17478
|
+
const r = relative14(ctx.repoDir, join70(ctx.runDir, "receipt.json"));
|
|
17460
17479
|
return r.startsWith("..") || isAbsolute13(r) ? `.loki/runs/${ctx.runId}/receipt.json` : r;
|
|
17461
17480
|
}, commitStage, wallGreenOnBaseOf = (o) => {
|
|
17462
17481
|
const b = o.wall?.base_run ?? {};
|
|
@@ -17507,7 +17526,7 @@ var init_seal = __esm(() => {
|
|
|
17507
17526
|
if (sd.code !== 0)
|
|
17508
17527
|
return { status: "failed", data: {}, reason: "git diff against base failed" };
|
|
17509
17528
|
const staged = parseStaged(sd.out);
|
|
17510
|
-
const drop = dropSet(ctx.repoDir, staged, ctx.outputs().intake?.preexisting_dirty, process.env, ctx.outputs().intake?.install_created);
|
|
17529
|
+
const drop = dropSet(ctx.repoDir, staged, ctx.outputs().intake?.preexisting_dirty, process.env, ctx.outputs().intake?.install_created, ctx.outputs().intake?.preexisting_untracked_blobs);
|
|
17511
17530
|
const sat = await discardIfSatisfied((a) => git4(ctx, a), ctx.baseSha, ctx.outputs(), staged, new Set(drop.filter(({ st }) => st === "L").map(({ f }) => f)), ctx.repoDir);
|
|
17512
17531
|
if (sat)
|
|
17513
17532
|
return sat;
|
|
@@ -17588,7 +17607,7 @@ var init_seal = __esm(() => {
|
|
|
17588
17607
|
if (wallNotRun > 0) {
|
|
17589
17608
|
try {
|
|
17590
17609
|
const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename26(String(f.path))));
|
|
17591
|
-
for (const n3 of readdirSync24(
|
|
17610
|
+
for (const n3 of readdirSync24(join70(ctx.runDir, "wall")).sort())
|
|
17592
17611
|
if (!kept.has(n3))
|
|
17593
17612
|
notProven.add(`wall test discarded: ${n3} (not_run)`);
|
|
17594
17613
|
} catch {}
|
|
@@ -17653,19 +17672,19 @@ var init_seal = __esm(() => {
|
|
|
17653
17672
|
for (const [s, d] of Object.entries(o))
|
|
17654
17673
|
if (typeof d?.duration_s === "number")
|
|
17655
17674
|
stages[s] = d.duration_s;
|
|
17656
|
-
const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(
|
|
17675
|
+
const T = hooks.time, time = T ? T.build(ctx, stages, T.firstEventMs(join70(ctx.runDir, "events.jsonl"))) : { wall_s: Object.values(stages).reduce((a, b) => a + (b ?? 0), 0), stages }, totalS = T?.reconciled(time) ?? null;
|
|
17657
17676
|
const iterIds = [...new Set([...Object.values(o).flatMap((d) => [...strs2(d?.iteration_ids), ...strs2([d?.iteration_id])]), ...ctx.sessionIds?.() ?? []])];
|
|
17658
17677
|
if (iterIds.length === 0)
|
|
17659
17678
|
notProven.add("cost not measured (no iteration ids recorded)");
|
|
17660
17679
|
const cost = ctx.cost.read(ctx.repoDir, iterIds);
|
|
17661
17680
|
if (cost.unmetered)
|
|
17662
17681
|
notProven.add("cost unmetered (CLI invoker; recorded as 0)");
|
|
17663
|
-
const eventsPath =
|
|
17682
|
+
const eventsPath = join70(ctx.runDir, "events.jsonl");
|
|
17664
17683
|
const wallFiles = Array.isArray(o.wall?.files) ? o.wall.files : [];
|
|
17665
17684
|
const wallPassed = typeof o.verify?.wall_passed === "boolean" ? o.verify.wall_passed : null;
|
|
17666
17685
|
if (wallFiles.length > 0 && wallPassed === null)
|
|
17667
17686
|
notProven.add("wall result not recorded by verify");
|
|
17668
|
-
const routeBlock = buildRouteBlock(process.env, ctx.provider, o.implement?.route ?? o.plan?.route_record ?? (routerEnabled(process.env) ? loadRouteRecord(ctx.runDir) : undefined), cost.router ?? (routerEnabled(process.env) ? sumResultCosts(
|
|
17687
|
+
const routeBlock = buildRouteBlock(process.env, ctx.provider, o.implement?.route ?? o.plan?.route_record ?? (routerEnabled(process.env) ? loadRouteRecord(ctx.runDir) : undefined), cost.router ?? (routerEnabled(process.env) ? sumResultCosts(join70(ctx.repoDir, ".loki"), liveArchivedCosts(join70(ctx.repoDir, ".loki"), iterIds, UNMETERED)).router : undefined), ctx.model);
|
|
17669
17688
|
if (routeBlock)
|
|
17670
17689
|
for (const l of routeNotProven(routeBlock))
|
|
17671
17690
|
notProven.add(l);
|
|
@@ -17735,10 +17754,10 @@ var init_seal = __esm(() => {
|
|
|
17735
17754
|
}
|
|
17736
17755
|
const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
|
|
17737
17756
|
mkdirSync31(ctx.runDir, { recursive: true });
|
|
17738
|
-
const path =
|
|
17757
|
+
const path = join70(ctx.runDir, "receipt.json");
|
|
17739
17758
|
atomicWriteText(path, JSON.stringify(receipt, null, 2) + `
|
|
17740
17759
|
`);
|
|
17741
|
-
atomicWriteText(
|
|
17760
|
+
atomicWriteText(join70(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
|
|
17742
17761
|
recordRun(process.env, ctx.repoDir, ranModel(o.implement, ctx.model, o.fix), verdict, cost.usd, cost.unmetered === true, totalS);
|
|
17743
17762
|
try {
|
|
17744
17763
|
hooks.sealed?.(ctx.runDir, JSON.parse(JSON.stringify(receipt), (_k, v) => v && typeof v === "object" ? Object.freeze(v) : v));
|
|
@@ -17764,13 +17783,13 @@ var init_seal = __esm(() => {
|
|
|
17764
17783
|
|
|
17765
17784
|
// ../../loki-ts/src/util/composite_seal.ts
|
|
17766
17785
|
import { existsSync as existsSync48, readFileSync as readFileSync57 } from "fs";
|
|
17767
|
-
import { basename as basename27, dirname as dirname32, join as
|
|
17786
|
+
import { basename as basename27, dirname as dirname32, join as join71 } from "path";
|
|
17768
17787
|
function logProblem(runDir, integ) {
|
|
17769
17788
|
if (typeof integ["log_sha256"] !== "string")
|
|
17770
17789
|
return null;
|
|
17771
17790
|
let b;
|
|
17772
17791
|
try {
|
|
17773
|
-
b = readFileSync57(
|
|
17792
|
+
b = readFileSync57(join71(runDir, "integration.log"));
|
|
17774
17793
|
} catch {
|
|
17775
17794
|
return "integration.log is missing but integration.json records its hash";
|
|
17776
17795
|
}
|
|
@@ -17793,13 +17812,13 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
17793
17812
|
return bad("body malformed");
|
|
17794
17813
|
let ibytes;
|
|
17795
17814
|
try {
|
|
17796
|
-
ibytes = readFileSync57(
|
|
17815
|
+
ibytes = readFileSync57(join71(runDir, "integration.json"));
|
|
17797
17816
|
} catch {
|
|
17798
17817
|
return bad("integration.json missing");
|
|
17799
17818
|
}
|
|
17800
17819
|
if (sha3(ibytes) !== receipt["integration_sha256"])
|
|
17801
17820
|
return bad("integration.json does not match its recorded hash");
|
|
17802
|
-
const integ = readJson6(
|
|
17821
|
+
const integ = readJson6(join71(runDir, "integration.json"));
|
|
17803
17822
|
if (!isObj10(integ) || !isObj10(integ["outcomes"]))
|
|
17804
17823
|
return bad("integration.json has no outcomes");
|
|
17805
17824
|
const iprob = integrationProblem(integ);
|
|
@@ -17834,7 +17853,7 @@ async function verifyComposite(receiptPath, receipt, rh, verifyOne, deps = {}) {
|
|
|
17834
17853
|
return bad(`child ${text2(repo, 80) || "?"} has an invalid receipt path`);
|
|
17835
17854
|
if (outcomes[repo] !== "ok")
|
|
17836
17855
|
return bad(`child ${text2(repo, 80)} did not finish ok in integration.json`);
|
|
17837
|
-
const rp =
|
|
17856
|
+
const rp = join71(runDir, rel);
|
|
17838
17857
|
let bytes;
|
|
17839
17858
|
try {
|
|
17840
17859
|
bytes = readFileSync57(rp);
|
|
@@ -17887,7 +17906,7 @@ var init_keys_cmd = __esm(() => {
|
|
|
17887
17906
|
|
|
17888
17907
|
// ../../loki-ts/src/engine10/verify_cmd.ts
|
|
17889
17908
|
import { existsSync as existsSync49, readFileSync as readFileSync58, renameSync as renameSync14, statSync as statSync24, writeFileSync as writeFileSync34 } from "fs";
|
|
17890
|
-
import { basename as basename28, dirname as dirname33, join as
|
|
17909
|
+
import { basename as basename28, dirname as dirname33, join as join72 } from "path";
|
|
17891
17910
|
import { createHash as createHash21, createPublicKey as createPublicKey4, verify as verify4 } from "crypto";
|
|
17892
17911
|
function pubFor(kid, given) {
|
|
17893
17912
|
if (given)
|
|
@@ -17939,7 +17958,7 @@ function checkEventLog(receiptPath, receipt) {
|
|
|
17939
17958
|
const claims = st !== null && typeof st === "object" && Object.keys(st).length > 0;
|
|
17940
17959
|
return claims ? "the receipt records stages but binds the empty-log hash, so no events.jsonl can back it (missing, empty or non-empty); the receipt is forged or was sealed without a log. Re-run the task to produce a fresh receipt" : null;
|
|
17941
17960
|
}
|
|
17942
|
-
const path =
|
|
17961
|
+
const path = join72(dirname33(receiptPath), "events.jsonl");
|
|
17943
17962
|
if (!existsSync49(path))
|
|
17944
17963
|
return "events.jsonl is missing";
|
|
17945
17964
|
const raw2 = readFileSync58(path, "utf8"), events2 = readEvents(path), lines2 = raw2.split(`
|
|
@@ -17958,7 +17977,7 @@ function checkEventLog(receiptPath, receipt) {
|
|
|
17958
17977
|
return h.digest("hex") === bound ? null : "events.jsonl does not match the hash recorded at seal";
|
|
17959
17978
|
}
|
|
17960
17979
|
function checkLogSeal(receiptPath, hash, kid, given) {
|
|
17961
|
-
const path =
|
|
17980
|
+
const path = join72(dirname33(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
|
|
17962
17981
|
if (!events2.some((e) => e.type === "receipt.sealed" && e.data["receipt_sha256"] === hash))
|
|
17963
17982
|
return { verdict: "TAMPERED", reason: "events.jsonl has no receipt.sealed event for this receipt" };
|
|
17964
17983
|
if (done < 0)
|
|
@@ -18070,7 +18089,7 @@ var init_verify_cmd = __esm(() => {
|
|
|
18070
18089
|
|
|
18071
18090
|
// src/server/app.ts
|
|
18072
18091
|
import { existsSync as existsSync51, readFileSync as readFileSync61, statSync as statSync25 } from "fs";
|
|
18073
|
-
import { join as
|
|
18092
|
+
import { join as join75, resolve as resolve19, sep as sep16 } from "path";
|
|
18074
18093
|
|
|
18075
18094
|
// node_modules/hono/dist/request/constants.js
|
|
18076
18095
|
var GET_MATCH_RESULT = Symbol();
|
|
@@ -28383,7 +28402,7 @@ function mount20(ctx) {
|
|
|
28383
28402
|
// src/server/routes/verify.ts
|
|
28384
28403
|
import { readFileSync as readFileSync59, realpathSync as realpathSync25 } from "fs";
|
|
28385
28404
|
import { createPublicKey as createPublicKey5 } from "crypto";
|
|
28386
|
-
import { join as
|
|
28405
|
+
import { join as join73, sep as sep15 } from "path";
|
|
28387
28406
|
init_verify_cmd();
|
|
28388
28407
|
init_seal();
|
|
28389
28408
|
init_receipt_dsse();
|
|
@@ -28410,11 +28429,11 @@ function mount21(ctx) {
|
|
|
28410
28429
|
return done(404, "receipt not available", "not_found");
|
|
28411
28430
|
let runDir, file;
|
|
28412
28431
|
try {
|
|
28413
|
-
const root = realpathSync25(
|
|
28414
|
-
runDir = realpathSync25(
|
|
28415
|
-
if (runDir !==
|
|
28432
|
+
const root = realpathSync25(join73(repo.p, ".loki", "runs"));
|
|
28433
|
+
runDir = realpathSync25(join73(root, run2));
|
|
28434
|
+
if (runDir !== join73(root, run2))
|
|
28416
28435
|
return done(404, "receipt not found", "not_found");
|
|
28417
|
-
file = realpathSync25(
|
|
28436
|
+
file = realpathSync25(join73(runDir, "receipt.json"));
|
|
28418
28437
|
} catch {
|
|
28419
28438
|
return done(404, "receipt not found", "not_found");
|
|
28420
28439
|
}
|
|
@@ -28496,7 +28515,7 @@ function ttlCache(ttlMs = PROBE_CACHE_MS, now2 = Date.now) {
|
|
|
28496
28515
|
|
|
28497
28516
|
// src/server/legacy/shim.ts
|
|
28498
28517
|
import { existsSync as existsSync50, readFileSync as readFileSync60 } from "fs";
|
|
28499
|
-
import { join as
|
|
28518
|
+
import { join as join74 } from "path";
|
|
28500
28519
|
|
|
28501
28520
|
// src/server/legacy/routes.ts
|
|
28502
28521
|
var LEGACY_ROUTES = [
|
|
@@ -28874,7 +28893,7 @@ var logged = new Set;
|
|
|
28874
28893
|
var toHono = (p) => p.replace(/\{([A-Za-z_]+):path\}/g, ":$1{.+}").replace(/\{([A-Za-z_]+)\}/g, ":$1");
|
|
28875
28894
|
var NOT_SUPPORTED = "not yet supported by the Control Plane";
|
|
28876
28895
|
var repoVersion = () => {
|
|
28877
|
-
for (const f of [
|
|
28896
|
+
for (const f of [join74(import.meta.dir, "../../../../../VERSION")]) {
|
|
28878
28897
|
try {
|
|
28879
28898
|
if (existsSync50(f))
|
|
28880
28899
|
return readFileSync60(f, "utf8").trim();
|
|
@@ -29059,7 +29078,7 @@ function legacyShim(opts) {
|
|
|
29059
29078
|
|
|
29060
29079
|
// src/server/app.ts
|
|
29061
29080
|
var MAX_BODY2 = 1e6;
|
|
29062
|
-
var defaultUiDir = () => [
|
|
29081
|
+
var defaultUiDir = () => [join75(import.meta.dir, "../../ui/dist"), join75(import.meta.dir, "../ui/dist")].find((d) => existsSync51(join75(d, "index.html")));
|
|
29063
29082
|
function createApp(opts) {
|
|
29064
29083
|
const uiDir = opts.uiDir ?? defaultUiDir();
|
|
29065
29084
|
const { db, sqlite } = openDb(opts.dbPath);
|
|
@@ -29088,7 +29107,7 @@ function createApp(opts) {
|
|
|
29088
29107
|
await next();
|
|
29089
29108
|
});
|
|
29090
29109
|
const readInstalled = () => {
|
|
29091
|
-
for (const f of [process.env.LOKI_VERSION_FILE,
|
|
29110
|
+
for (const f of [process.env.LOKI_VERSION_FILE, join75(import.meta.dir, "../../../../VERSION")]) {
|
|
29092
29111
|
try {
|
|
29093
29112
|
if (f)
|
|
29094
29113
|
return readFileSync61(f, "utf8").trim() || "unknown";
|
|
@@ -29206,7 +29225,7 @@ function createApp(opts) {
|
|
|
29206
29225
|
return new Response(Bun.file(f));
|
|
29207
29226
|
if (/\.[a-z0-9]+$/i.test(p))
|
|
29208
29227
|
return c.json({ error: "not found" }, 404);
|
|
29209
|
-
return new Response(Bun.file(
|
|
29228
|
+
return new Response(Bun.file(join75(root, "index.html")));
|
|
29210
29229
|
});
|
|
29211
29230
|
return { app, db, close: () => {
|
|
29212
29231
|
clearInterval(reconciler);
|