loki-mode 10.10.2 → 10.10.3

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.
Files changed (79) hide show
  1. package/SKILL.md +2 -2
  2. package/VERSION +1 -1
  3. package/dashboard/__init__.py +1 -1
  4. package/docs/CLI-REFERENCE.md +1 -1
  5. package/docs/INSTALLATION.md +1 -1
  6. package/docs/v10/BOARD.md +2 -0
  7. package/docs/v10/FAILURE-CLASSES.md +13 -0
  8. package/docs/v10/PROGRESS.md +9 -0
  9. package/docs/v10/cp-redesign/PARITY.md +188 -0
  10. package/docs/v10/cp-redesign/legacy/INDEX.md +1167 -0
  11. package/loki-ts/dist/loki.js +616 -614
  12. package/mcp/__init__.py +1 -1
  13. package/package.json +1 -1
  14. package/packages/control-plane/dist/server.js +417 -336
  15. package/packages/control-plane/src/server/diffstat.ts +77 -0
  16. package/packages/control-plane/src/server/repos.ts +5 -2
  17. package/packages/control-plane/src/server/routes/index.ts +1 -1
  18. package/packages/control-plane/src/server/runs.ts +3 -1
  19. package/packages/control-plane/ui/dist/assets/index-D27veKDf.js +152 -0
  20. package/packages/control-plane/ui/dist/index.html +1 -1
  21. package/plugins/loki-mode/.claude-plugin/plugin.json +1 -1
  22. package/web-app/dist/assets/{AdminPage-BvbxMtZO.js → AdminPage-Dyx5OHmP.js} +1 -1
  23. package/web-app/dist/assets/{Avatar-Dc7Scg02.js → Avatar-WVxt-kYj.js} +1 -1
  24. package/web-app/dist/assets/{Badge-BmVuOqbM.js → Badge-16vWJ-6u.js} +1 -1
  25. package/web-app/dist/assets/{Button-DvzqhxRU.js → Button-CWVPIMTW.js} +1 -1
  26. package/web-app/dist/assets/{CockpitPage-D8AZo7Ha.js → CockpitPage-D5WhogJK.js} +1 -1
  27. package/web-app/dist/assets/{ComparePage-NmqaTXDz.js → ComparePage-CjJfjxcT.js} +1 -1
  28. package/web-app/dist/assets/{ErrorBoundary-PGl8Kzoq.js → ErrorBoundary-CNnObh81.js} +1 -1
  29. package/web-app/dist/assets/{EvidenceReceiptPanel-2NY4n9gv.js → EvidenceReceiptPanel-Cn1PE_JV.js} +1 -1
  30. package/web-app/dist/assets/{GitHubIssuesPanel-DBO_LHHM.js → GitHubIssuesPanel-CcH9neSU.js} +1 -1
  31. package/web-app/dist/assets/{GitHubPRsPanel-K7m9uJ1N.js → GitHubPRsPanel-C-n6inCN.js} +1 -1
  32. package/web-app/dist/assets/{HomePage-qNQzAJxM.js → HomePage-BZ7PCPFR.js} +2 -2
  33. package/web-app/dist/assets/{LoginPage-esu3OK65.js → LoginPage-CJsigIUa.js} +1 -1
  34. package/web-app/dist/assets/{MagicPage-CCdVvXrA.js → MagicPage-ClZaKmXT.js} +1 -1
  35. package/web-app/dist/assets/{MetricsPage-bEvugU2t.js → MetricsPage-ELQn9-cf.js} +1 -1
  36. package/web-app/dist/assets/{NotFoundPage-BlEjQ1wX.js → NotFoundPage-Dc_zp3RF.js} +1 -1
  37. package/web-app/dist/assets/{ProjectPage-Bnug_Yzv.js → ProjectPage-B5K1NDuH.js} +3 -3
  38. package/web-app/dist/assets/{ProjectsPage-M8r1vfpn.js → ProjectsPage-C2l5SiIN.js} +1 -1
  39. package/web-app/dist/assets/{SettingsPage-NqAJpB48.js → SettingsPage-DkDNp6Pd.js} +1 -1
  40. package/web-app/dist/assets/{ShowcasePage-8FggxL1P.js → ShowcasePage-1zasFSKz.js} +1 -1
  41. package/web-app/dist/assets/{SystemSettingsPage-3Sz3kFOO.js → SystemSettingsPage-hIm_4NUx.js} +1 -1
  42. package/web-app/dist/assets/{TeamsPage-nV-6vdWM.js → TeamsPage-DUb_TA22.js} +1 -1
  43. package/web-app/dist/assets/{TemplatesPage-Brbc_VR9.js → TemplatesPage-B1mj-eA4.js} +1 -1
  44. package/web-app/dist/assets/{TerminalOutput-D1yta5ac.js → TerminalOutput-BX1UwelI.js} +1 -1
  45. package/web-app/dist/assets/{activity-oEeKuqFe.js → activity-B8APKMuh.js} +1 -1
  46. package/web-app/dist/assets/{bell-3NJtqBRR.js → bell-BS8WL-tI.js} +1 -1
  47. package/web-app/dist/assets/{bot-CuvJZ6x1.js → bot-e9I6yy12.js} +1 -1
  48. package/web-app/dist/assets/{check-n4289IZw.js → check-BbgR7Ovw.js} +1 -1
  49. package/web-app/dist/assets/{chevron-left-CmQeio7h.js → chevron-left-BcDqv7aX.js} +1 -1
  50. package/web-app/dist/assets/{circle-alert-CmmVW-Pd.js → circle-alert-BnDT8wxe.js} +1 -1
  51. package/web-app/dist/assets/{clock-QFqk7GlA.js → clock-LPz79lks.js} +1 -1
  52. package/web-app/dist/assets/{cloud-BNkSokmq.js → cloud-BcgBi5T1.js} +1 -1
  53. package/web-app/dist/assets/{code-xml-nWeketqj.js → code-xml-5zcykgva.js} +1 -1
  54. package/web-app/dist/assets/{database-C83MXTmJ.js → database-D9KLqhHq.js} +1 -1
  55. package/web-app/dist/assets/{dollar-sign-Blg6TO4y.js → dollar-sign-CrINoZ4o.js} +1 -1
  56. package/web-app/dist/assets/{file-code-corner-Tk11oUzm.js → file-code-corner-CA7G72ip.js} +1 -1
  57. package/web-app/dist/assets/{file-plus-DF_eyA6I.js → file-plus-D8tHdHn_.js} +1 -1
  58. package/web-app/dist/assets/{globe-D5hDqqmn.js → globe-CT0Ts5bO.js} +1 -1
  59. package/web-app/dist/assets/{hammer-C2hm9lzl.js → hammer-tUpu0LJk.js} +1 -1
  60. package/web-app/dist/assets/{index-pMxOIwXq.js → index-DdjeiWUI.js} +3 -3
  61. package/web-app/dist/assets/{layers-XWQKGXg0.js → layers-BzzJ7w3C.js} +1 -1
  62. package/web-app/dist/assets/{loader-circle-BRuvorm2.js → loader-circle-BBdMdxIV.js} +1 -1
  63. package/web-app/dist/assets/{lock-BSGvQf5v.js → lock-Cg9DkEh7.js} +1 -1
  64. package/web-app/dist/assets/{package-3FJYUYgJ.js → package-DHs8IEJR.js} +1 -1
  65. package/web-app/dist/assets/{plus-CeIx6g9P.js → plus-70JSAqB1.js} +1 -1
  66. package/web-app/dist/assets/{refresh-cw-ChutW42g.js → refresh-cw-DjggkboT.js} +1 -1
  67. package/web-app/dist/assets/{rotate-ccw-BdSjUAk-.js → rotate-ccw-c1NNyyL5.js} +1 -1
  68. package/web-app/dist/assets/{scroll-text-BjFqxpw3.js → scroll-text-B49wQrJ2.js} +1 -1
  69. package/web-app/dist/assets/{server-C7UEKdol.js → server-BHKG-dDi.js} +1 -1
  70. package/web-app/dist/assets/{shield-alert-DY8fpEs7.js → shield-alert-Dx9MoBGm.js} +1 -1
  71. package/web-app/dist/assets/{thumbs-up-Cz1san1g.js → thumbs-up-frEbS59j.js} +1 -1
  72. package/web-app/dist/assets/{trash-2-D2MvGYeP.js → trash-2-1Gd8pXFG.js} +1 -1
  73. package/web-app/dist/assets/{trending-down-CxO3OYOB.js → trending-down-BpUeO-FP.js} +1 -1
  74. package/web-app/dist/assets/{trending-up-DCHKPJLe.js → trending-up-CvhWp8qO.js} +1 -1
  75. package/web-app/dist/assets/{upload-CdPJpSHC.js → upload-DZuMugqd.js} +1 -1
  76. package/web-app/dist/assets/{usePolling-DAH6K3ST.js → usePolling-D5KUSkfs.js} +1 -1
  77. package/web-app/dist/assets/{user-Byyt01W4.js → user-BF9vws84.js} +1 -1
  78. package/web-app/dist/index.html +1 -1
  79. package/packages/control-plane/ui/dist/assets/index-BrA22FUs.js +0 -152
@@ -3696,10 +3696,10 @@ var require_resolve_block_map = __commonJS((exports) => {
3696
3696
  let offset = bm.offset;
3697
3697
  let commentEnd = null;
3698
3698
  for (const collItem of bm.items) {
3699
- const { start, key, sep: sep4, value } = collItem;
3699
+ const { start, key, sep: sep5, value } = collItem;
3700
3700
  const keyProps = resolveProps.resolveProps(start, {
3701
3701
  indicator: "explicit-key-ind",
3702
- next: key ?? sep4?.[0],
3702
+ next: key ?? sep5?.[0],
3703
3703
  offset,
3704
3704
  onError,
3705
3705
  parentIndent: bm.indent,
@@ -3713,7 +3713,7 @@ var require_resolve_block_map = __commonJS((exports) => {
3713
3713
  else if ("indent" in key && key.indent !== bm.indent)
3714
3714
  onError(offset, "BAD_INDENT", startColMsg);
3715
3715
  }
3716
- if (!keyProps.anchor && !keyProps.tag && !sep4) {
3716
+ if (!keyProps.anchor && !keyProps.tag && !sep5) {
3717
3717
  commentEnd = keyProps.end;
3718
3718
  if (keyProps.comment) {
3719
3719
  if (map.comment)
@@ -3738,7 +3738,7 @@ var require_resolve_block_map = __commonJS((exports) => {
3738
3738
  ctx.atKey = false;
3739
3739
  if (utilMapIncludes.mapIncludes(ctx, map.items, keyNode))
3740
3740
  onError(keyStart, "DUPLICATE_KEY", "Map keys must be unique");
3741
- const valueProps = resolveProps.resolveProps(sep4 ?? [], {
3741
+ const valueProps = resolveProps.resolveProps(sep5 ?? [], {
3742
3742
  indicator: "map-value-ind",
3743
3743
  next: value,
3744
3744
  offset: keyNode.range[2],
@@ -3754,7 +3754,7 @@ var require_resolve_block_map = __commonJS((exports) => {
3754
3754
  if (ctx.options.strict && keyProps.start < valueProps.found.offset - 1024)
3755
3755
  onError(keyNode.range, "KEY_OVER_1024_CHARS", "The : indicator must be at most 1024 chars after the start of an implicit block mapping key");
3756
3756
  }
3757
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep4, null, valueProps, onError);
3757
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : composeEmptyNode(ctx, offset, sep5, null, valueProps, onError);
3758
3758
  if (ctx.schema.compat)
3759
3759
  utilFlowIndentCheck.flowIndentCheck(bm.indent, value, onError);
3760
3760
  offset = valueNode.range[2];
@@ -3840,7 +3840,7 @@ var require_resolve_end = __commonJS((exports) => {
3840
3840
  let comment = "";
3841
3841
  if (end) {
3842
3842
  let hasSpace = false;
3843
- let sep4 = "";
3843
+ let sep5 = "";
3844
3844
  for (const token of end) {
3845
3845
  const { source, type } = token;
3846
3846
  switch (type) {
@@ -3854,13 +3854,13 @@ var require_resolve_end = __commonJS((exports) => {
3854
3854
  if (!comment)
3855
3855
  comment = cb;
3856
3856
  else
3857
- comment += sep4 + cb;
3858
- sep4 = "";
3857
+ comment += sep5 + cb;
3858
+ sep5 = "";
3859
3859
  break;
3860
3860
  }
3861
3861
  case "newline":
3862
3862
  if (comment)
3863
- sep4 += source;
3863
+ sep5 += source;
3864
3864
  hasSpace = true;
3865
3865
  break;
3866
3866
  default:
@@ -3900,18 +3900,18 @@ var require_resolve_flow_collection = __commonJS((exports) => {
3900
3900
  let offset = fc.offset + fc.start.source.length;
3901
3901
  for (let i = 0;i < fc.items.length; ++i) {
3902
3902
  const collItem = fc.items[i];
3903
- const { start, key, sep: sep4, value } = collItem;
3903
+ const { start, key, sep: sep5, value } = collItem;
3904
3904
  const props = resolveProps.resolveProps(start, {
3905
3905
  flow: fcName,
3906
3906
  indicator: "explicit-key-ind",
3907
- next: key ?? sep4?.[0],
3907
+ next: key ?? sep5?.[0],
3908
3908
  offset,
3909
3909
  onError,
3910
3910
  parentIndent: fc.indent,
3911
3911
  startOnNewline: false
3912
3912
  });
3913
3913
  if (!props.found) {
3914
- if (!props.anchor && !props.tag && !sep4 && !value) {
3914
+ if (!props.anchor && !props.tag && !sep5 && !value) {
3915
3915
  if (i === 0 && props.comma)
3916
3916
  onError(props.comma, "UNEXPECTED_TOKEN", `Unexpected , in ${fcName}`);
3917
3917
  else if (i < fc.items.length - 1)
@@ -3963,8 +3963,8 @@ var require_resolve_flow_collection = __commonJS((exports) => {
3963
3963
  }
3964
3964
  }
3965
3965
  }
3966
- if (!isMap && !sep4 && !props.found) {
3967
- const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep4, null, props, onError);
3966
+ if (!isMap && !sep5 && !props.found) {
3967
+ const valueNode = value ? composeNode(ctx, value, props, onError) : composeEmptyNode(ctx, props.end, sep5, null, props, onError);
3968
3968
  coll.items.push(valueNode);
3969
3969
  offset = valueNode.range[2];
3970
3970
  if (isBlock(value))
@@ -3976,7 +3976,7 @@ var require_resolve_flow_collection = __commonJS((exports) => {
3976
3976
  if (isBlock(key))
3977
3977
  onError(keyNode.range, "BLOCK_IN_FLOW", blockMsg);
3978
3978
  ctx.atKey = false;
3979
- const valueProps = resolveProps.resolveProps(sep4 ?? [], {
3979
+ const valueProps = resolveProps.resolveProps(sep5 ?? [], {
3980
3980
  flow: fcName,
3981
3981
  indicator: "map-value-ind",
3982
3982
  next: value,
@@ -3987,8 +3987,8 @@ var require_resolve_flow_collection = __commonJS((exports) => {
3987
3987
  });
3988
3988
  if (valueProps.found) {
3989
3989
  if (!isMap && !props.found && ctx.options.strict) {
3990
- if (sep4)
3991
- for (const st of sep4) {
3990
+ if (sep5)
3991
+ for (const st of sep5) {
3992
3992
  if (st === valueProps.found)
3993
3993
  break;
3994
3994
  if (st.type === "newline") {
@@ -4005,7 +4005,7 @@ var require_resolve_flow_collection = __commonJS((exports) => {
4005
4005
  else
4006
4006
  onError(valueProps.start, "MISSING_CHAR", `Missing , or : between ${fcName} items`);
4007
4007
  }
4008
- const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep4, null, valueProps, onError) : null;
4008
+ const valueNode = value ? composeNode(ctx, value, valueProps, onError) : valueProps.found ? composeEmptyNode(ctx, valueProps.end, sep5, null, valueProps, onError) : null;
4009
4009
  if (valueNode) {
4010
4010
  if (isBlock(value))
4011
4011
  onError(valueNode.range, "BLOCK_IN_FLOW", blockMsg);
@@ -4182,7 +4182,7 @@ var require_resolve_block_scalar = __commonJS((exports) => {
4182
4182
  chompStart = i + 1;
4183
4183
  }
4184
4184
  let value = "";
4185
- let sep4 = "";
4185
+ let sep5 = "";
4186
4186
  let prevMoreIndented = false;
4187
4187
  for (let i = 0;i < contentStart; ++i)
4188
4188
  value += lines[i][0].slice(trimIndent) + `
@@ -4200,33 +4200,33 @@ var require_resolve_block_scalar = __commonJS((exports) => {
4200
4200
  indent = "";
4201
4201
  }
4202
4202
  if (type === Scalar.Scalar.BLOCK_LITERAL) {
4203
- value += sep4 + indent.slice(trimIndent) + content;
4204
- sep4 = `
4203
+ value += sep5 + indent.slice(trimIndent) + content;
4204
+ sep5 = `
4205
4205
  `;
4206
4206
  } else if (indent.length > trimIndent || content[0] === "\t") {
4207
- if (sep4 === " ")
4208
- sep4 = `
4207
+ if (sep5 === " ")
4208
+ sep5 = `
4209
4209
  `;
4210
- else if (!prevMoreIndented && sep4 === `
4210
+ else if (!prevMoreIndented && sep5 === `
4211
4211
  `)
4212
- sep4 = `
4212
+ sep5 = `
4213
4213
 
4214
4214
  `;
4215
- value += sep4 + indent.slice(trimIndent) + content;
4216
- sep4 = `
4215
+ value += sep5 + indent.slice(trimIndent) + content;
4216
+ sep5 = `
4217
4217
  `;
4218
4218
  prevMoreIndented = true;
4219
4219
  } else if (content === "") {
4220
- if (sep4 === `
4220
+ if (sep5 === `
4221
4221
  `)
4222
4222
  value += `
4223
4223
  `;
4224
4224
  else
4225
- sep4 = `
4225
+ sep5 = `
4226
4226
  `;
4227
4227
  } else {
4228
- value += sep4 + content;
4229
- sep4 = " ";
4228
+ value += sep5 + content;
4229
+ sep5 = " ";
4230
4230
  prevMoreIndented = false;
4231
4231
  }
4232
4232
  }
@@ -4406,27 +4406,27 @@ var require_resolve_flow_scalar = __commonJS((exports) => {
4406
4406
  trimBoth = /^[ \t]+|[ \t]+$/g;
4407
4407
  }
4408
4408
  let res = match2[1].replace(trimEnd, "");
4409
- let sep4 = " ";
4409
+ let sep5 = " ";
4410
4410
  let pos = line2.lastIndex;
4411
4411
  while (match2 = line2.exec(source)) {
4412
4412
  const lm = match2[1].replace(trimBoth, "");
4413
4413
  if (lm === "") {
4414
- if (sep4 === `
4414
+ if (sep5 === `
4415
4415
  `)
4416
- res += sep4;
4416
+ res += sep5;
4417
4417
  else
4418
- sep4 = `
4418
+ sep5 = `
4419
4419
  `;
4420
4420
  } else {
4421
- res += sep4 + lm;
4422
- sep4 = " ";
4421
+ res += sep5 + lm;
4422
+ sep5 = " ";
4423
4423
  }
4424
4424
  pos = line2.lastIndex;
4425
4425
  }
4426
4426
  const last = /[ \t]*(.*)/sy;
4427
4427
  last.lastIndex = pos;
4428
4428
  match2 = last.exec(source);
4429
- return res + sep4 + (match2?.[1] ?? "");
4429
+ return res + sep5 + (match2?.[1] ?? "");
4430
4430
  }
4431
4431
  function doubleQuotedValue(source, onError) {
4432
4432
  let res = "";
@@ -5207,14 +5207,14 @@ var require_cst_stringify = __commonJS((exports) => {
5207
5207
  }
5208
5208
  }
5209
5209
  }
5210
- function stringifyItem({ start, key, sep: sep4, value }) {
5210
+ function stringifyItem({ start, key, sep: sep5, value }) {
5211
5211
  let res = "";
5212
5212
  for (const st of start)
5213
5213
  res += st.source;
5214
5214
  if (key)
5215
5215
  res += stringifyToken(key);
5216
- if (sep4)
5217
- for (const st of sep4)
5216
+ if (sep5)
5217
+ for (const st of sep5)
5218
5218
  res += st.source;
5219
5219
  if (value)
5220
5220
  res += stringifyToken(value);
@@ -6362,18 +6362,18 @@ var require_parser = __commonJS((exports) => {
6362
6362
  if (this.type === "map-value-ind") {
6363
6363
  const prev = getPrevProps(this.peek(2));
6364
6364
  const start = getFirstKeyStartProps(prev);
6365
- let sep4;
6365
+ let sep5;
6366
6366
  if (scalar.end) {
6367
- sep4 = scalar.end;
6368
- sep4.push(this.sourceToken);
6367
+ sep5 = scalar.end;
6368
+ sep5.push(this.sourceToken);
6369
6369
  delete scalar.end;
6370
6370
  } else
6371
- sep4 = [this.sourceToken];
6371
+ sep5 = [this.sourceToken];
6372
6372
  const map = {
6373
6373
  type: "block-map",
6374
6374
  offset: scalar.offset,
6375
6375
  indent: scalar.indent,
6376
- items: [{ start, key: scalar, sep: sep4 }]
6376
+ items: [{ start, key: scalar, sep: sep5 }]
6377
6377
  };
6378
6378
  this.onKeyLine = true;
6379
6379
  this.stack[this.stack.length - 1] = map;
@@ -6527,15 +6527,15 @@ var require_parser = __commonJS((exports) => {
6527
6527
  } else if (isFlowToken(it.key) && !includesToken(it.sep, "newline")) {
6528
6528
  const start2 = getFirstKeyStartProps(it.start);
6529
6529
  const key = it.key;
6530
- const sep4 = it.sep;
6531
- sep4.push(this.sourceToken);
6530
+ const sep5 = it.sep;
6531
+ sep5.push(this.sourceToken);
6532
6532
  delete it.key;
6533
6533
  delete it.sep;
6534
6534
  this.stack.push({
6535
6535
  type: "block-map",
6536
6536
  offset: this.offset,
6537
6537
  indent: this.indent,
6538
- items: [{ start: start2, key, sep: sep4 }]
6538
+ items: [{ start: start2, key, sep: sep5 }]
6539
6539
  });
6540
6540
  } else if (start.length > 0) {
6541
6541
  it.sep = it.sep.concat(start, this.sourceToken);
@@ -6729,13 +6729,13 @@ var require_parser = __commonJS((exports) => {
6729
6729
  const prev = getPrevProps(parent);
6730
6730
  const start = getFirstKeyStartProps(prev);
6731
6731
  fixFlowSeqItems(fc);
6732
- const sep4 = fc.end.splice(1, fc.end.length);
6733
- sep4.push(this.sourceToken);
6732
+ const sep5 = fc.end.splice(1, fc.end.length);
6733
+ sep5.push(this.sourceToken);
6734
6734
  const map = {
6735
6735
  type: "block-map",
6736
6736
  offset: fc.offset,
6737
6737
  indent: fc.indent,
6738
- items: [{ start, key: fc, sep: sep4 }]
6738
+ items: [{ start, key: fc, sep: sep5 }]
6739
6739
  };
6740
6740
  this.onKeyLine = true;
6741
6741
  this.stack[this.stack.length - 1] = map;
@@ -6960,7 +6960,7 @@ var require_public_api = __commonJS((exports) => {
6960
6960
 
6961
6961
  // src/server/app.ts
6962
6962
  import { existsSync as existsSync21, statSync as statSync14 } from "fs";
6963
- import { join as join33, resolve as resolve6, sep as sep12 } from "path";
6963
+ import { join as join34, resolve as resolve7, sep as sep13 } from "path";
6964
6964
 
6965
6965
  // node_modules/hono/dist/request/constants.js
6966
6966
  var GET_MATCH_RESULT = Symbol();
@@ -12779,12 +12779,89 @@ function writeAnswer(dir, source, run, answer) {
12779
12779
  return { status: 200, body: { ok: true, path, resume: `loki answer ${run}` } };
12780
12780
  }
12781
12781
 
12782
+ // src/server/diffstat.ts
12783
+ import { execFileSync } from "child_process";
12784
+ import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2, realpathSync as realpathSync2 } from "fs";
12785
+ import { join as join3, sep as sep2 } from "path";
12786
+ var ID2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
12787
+ var SHA = /^[0-9a-f]{40,64}$/;
12788
+ var MAX_RECEIPT_BYTES = 1024 * 1024;
12789
+ var GIT_TIMEOUT_MS = 5000;
12790
+ var cache = new Map;
12791
+ var gitEnv = () => ({ PATH: process.env.PATH ?? "", HOME: process.env.HOME ?? "", LC_ALL: "C", GIT_TERMINAL_PROMPT: "0", GIT_OPTIONAL_LOCKS: "0" });
12792
+ function parseNumstat(out) {
12793
+ const files = [];
12794
+ for (const line of out.split(`
12795
+ `)) {
12796
+ const m = /^(\d+|-)\t(\d+|-)\t(.+)$/.exec(line);
12797
+ if (!m)
12798
+ continue;
12799
+ files.push({ path: m[3], added: m[1] === "-" ? null : Number(m[1]), removed: m[2] === "-" ? null : Number(m[2]) });
12800
+ }
12801
+ return files;
12802
+ }
12803
+ function readReceipt(runDir) {
12804
+ let fd;
12805
+ try {
12806
+ fd = openSync2(join3(runDir, "receipt.json"), "r");
12807
+ } catch {
12808
+ return null;
12809
+ }
12810
+ try {
12811
+ const st = fstatSync2(fd);
12812
+ if (!st.isFile() || st.size > MAX_RECEIPT_BYTES)
12813
+ return null;
12814
+ const buf = Buffer.alloc(st.size);
12815
+ readSync2(fd, buf, 0, st.size, 0);
12816
+ const j = JSON.parse(buf.toString("utf8"));
12817
+ return j && typeof j === "object" ? j : null;
12818
+ } catch {
12819
+ return null;
12820
+ } finally {
12821
+ closeSync2(fd);
12822
+ }
12823
+ }
12824
+ function diffStatFor(db, source, run) {
12825
+ if (!ID2.test(source) || !ID2.test(run) || source.includes("..") || run.includes(".."))
12826
+ return null;
12827
+ const key = `${source}/${run}`;
12828
+ const hit = cache.get(key);
12829
+ if (hit)
12830
+ return hit;
12831
+ const repo = db.select({ p: localRepos.realpath }).from(localRepos).where(and(eq(localRepos.sourceId, source))).get();
12832
+ if (!repo)
12833
+ return null;
12834
+ let repoReal, runsRoot, runDir;
12835
+ try {
12836
+ repoReal = realpathSync2(repo.p);
12837
+ runsRoot = realpathSync2(join3(repoReal, ".loki", "runs"));
12838
+ runDir = realpathSync2(join3(runsRoot, run));
12839
+ } catch {
12840
+ return null;
12841
+ }
12842
+ if (runDir !== join3(runsRoot, run) || !runDir.startsWith(runsRoot + sep2))
12843
+ return null;
12844
+ const r = readReceipt(runDir);
12845
+ const base = typeof r?.base_sha === "string" ? r.base_sha : "", head = typeof r?.head_sha === "string" ? r.head_sha : "";
12846
+ if (!SHA.test(base) || !SHA.test(head))
12847
+ return null;
12848
+ try {
12849
+ const out = execFileSync("git", ["-C", repoReal, "-c", "core.quotePath=false", "diff", "--numstat", "--no-renames", `${base}..${head}`, "--"], { env: gitEnv(), timeout: GIT_TIMEOUT_MS, maxBuffer: 8 * 1024 * 1024, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] });
12850
+ const files = parseNumstat(out);
12851
+ const stat = { base, head, files, added: files.reduce((n2, f) => n2 + (f.added ?? 0), 0), removed: files.reduce((n2, f) => n2 + (f.removed ?? 0), 0), source: "git" };
12852
+ cache.set(key, stat);
12853
+ return stat;
12854
+ } catch {
12855
+ return null;
12856
+ }
12857
+ }
12858
+
12782
12859
  // src/server/integrity.ts
12783
12860
  import { createHash, createPublicKey, verify } from "crypto";
12784
12861
  import { readFileSync as readFileSync2 } from "fs";
12785
12862
  import { homedir as homedir2 } from "os";
12786
- import { join as join3 } from "path";
12787
- var SHA = /^[0-9a-f]{64}$/;
12863
+ import { join as join4 } from "path";
12864
+ var SHA2 = /^[0-9a-f]{64}$/;
12788
12865
  var SEAL_LINE = "log.sealed";
12789
12866
  var REDACTED = /\[REDACTED(?::[A-Z_]+)?\]/;
12790
12867
  var REDACTED_NOTE = "log redacted before ingest; seal not checkable";
@@ -12801,7 +12878,7 @@ function localKeyInfo(env = process.env) {
12801
12878
  if (inline)
12802
12879
  pub = createPublicKey(inline);
12803
12880
  else {
12804
- const file = given || join3(env["HOME"] || homedir2(), ".loki", "keys", "receipt-ed25519.pem");
12881
+ const file = given || join4(env["HOME"] || homedir2(), ".loki", "keys", "receipt-ed25519.pem");
12805
12882
  try {
12806
12883
  pub = createPublicKey(readFileSync2(file));
12807
12884
  } catch (e) {
@@ -12866,7 +12943,7 @@ function verifyRunIntegrity(evs, opts = {}) {
12866
12943
  const redacted = REDACTED.test(JSON.stringify(doneAt >= 0 ? evs.slice(0, doneAt + 2).map((e) => e.data) : evs.map((e) => e.data)));
12867
12944
  for (const i of sealedAt) {
12868
12945
  const d = evs[i].data;
12869
- if (typeof d["receipt_sha256"] !== "string" || !SHA.test(d["receipt_sha256"]))
12946
+ if (typeof d["receipt_sha256"] !== "string" || !SHA2.test(d["receipt_sha256"]))
12870
12947
  hashBad.push(`receipt.sealed at seq ${evs[i].seq} has no valid receipt_sha256`);
12871
12948
  const bound = d["events_sha256"];
12872
12949
  if (typeof bound === "string") {
@@ -13054,7 +13131,7 @@ function taskTitle(db, sourceId, runId) {
13054
13131
  }
13055
13132
  var withLive = (db, r) => {
13056
13133
  const p = { ...parseRun(r), title: taskTitle(db, r.sourceId, r.runId) };
13057
- return r.endedAt ? { ...p, current_stage: null, files_touched: [] } : { ...p, ...liveInfo(loadEvents(db, r.sourceId, r.runId)) };
13134
+ return r.endedAt ? { ...p, current_stage: null, files_touched: [], diff_stat: diffStatFor(db, r.sourceId, r.runId) } : { ...p, ...liveInfo(loadEvents(db, r.sourceId, r.runId)), diff_stat: null };
13058
13135
  };
13059
13136
  function liveInfo(evs) {
13060
13137
  const open = [];
@@ -13261,19 +13338,19 @@ function tokenGuard(token) {
13261
13338
 
13262
13339
  // src/shipper/backfill.ts
13263
13340
  import { readdirSync } from "fs";
13264
- import { join as join5 } from "path";
13341
+ import { join as join6 } from "path";
13265
13342
 
13266
13343
  // src/shipper/ship.ts
13267
13344
  import { createHash as createHash4 } from "crypto";
13268
- import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync as realpathSync2, renameSync, writeFileSync as writeFileSync2 } from "fs";
13345
+ import { existsSync as existsSync3, readFileSync as readFileSync3, realpathSync as realpathSync3, renameSync, writeFileSync as writeFileSync2 } from "fs";
13269
13346
  import { hostname } from "os";
13270
- import { join as join4 } from "path";
13347
+ import { join as join5 } from "path";
13271
13348
  var BATCH = 200;
13272
13349
  var MAX_BYTES = 800000;
13273
13350
  function sourceId(repoDir) {
13274
13351
  let real2 = repoDir;
13275
13352
  try {
13276
- real2 = realpathSync2(repoDir);
13353
+ real2 = realpathSync3(repoDir);
13277
13354
  } catch {}
13278
13355
  return createHash4("sha256").update(`${hostname()}\x00${real2}`).digest("hex").slice(0, 16);
13279
13356
  }
@@ -13282,24 +13359,24 @@ var redactEvent = (e) => ({ ...e, data: redactDeep(e.data) });
13282
13359
  var backoffMs = (failures, rnd = Math.random) => Math.min(60000, 1000 * 2 ** Math.max(0, failures - 1)) * (1 + 0.25 * rnd());
13283
13360
  function readShip(runDir, url) {
13284
13361
  try {
13285
- const s = JSON.parse(readFileSync3(join4(runDir, "ship.json"), "utf8"));
13362
+ const s = JSON.parse(readFileSync3(join5(runDir, "ship.json"), "utf8"));
13286
13363
  if (s.url === url && Number.isInteger(s.acked_seq))
13287
13364
  return { acked_seq: s.acked_seq, url };
13288
13365
  } catch {}
13289
13366
  return { acked_seq: -1, url };
13290
13367
  }
13291
13368
  function writeShip(runDir, s) {
13292
- const tmp = join4(runDir, `ship.json.${process.pid}.tmp`);
13369
+ const tmp = join5(runDir, `ship.json.${process.pid}.tmp`);
13293
13370
  writeFileSync2(tmp, JSON.stringify(s) + `
13294
13371
  `);
13295
- renameSync(tmp, join4(runDir, "ship.json"));
13372
+ renameSync(tmp, join5(runDir, "ship.json"));
13296
13373
  }
13297
13374
  async function shipRun(o) {
13298
13375
  const st = readShip(o.runDir, o.url);
13299
- const all = readEvents(join4(o.runDir, "events.jsonl"));
13376
+ const all = readEvents(join5(o.runDir, "events.jsonl"));
13300
13377
  let lines = 0;
13301
13378
  try {
13302
- lines = readFileSync3(join4(o.runDir, "events.jsonl"), "utf8").split(`
13379
+ lines = readFileSync3(join5(o.runDir, "events.jsonl"), "utf8").split(`
13303
13380
  `).filter((l) => l.trim() !== "").length;
13304
13381
  } catch {}
13305
13382
  const skipped = lines - all.length;
@@ -13342,7 +13419,7 @@ async function shipRun(o) {
13342
13419
  return { ok: true, sent, acked_seq: st.acked_seq, pending: 0 };
13343
13420
  }
13344
13421
  var shipEnabled = (env) => env.LOKI_CONTROL_URL || null;
13345
- var hasSpool = (runDir) => existsSync3(join4(runDir, "events.jsonl"));
13422
+ var hasSpool = (runDir) => existsSync3(join5(runDir, "events.jsonl"));
13346
13423
 
13347
13424
  // src/shipper/backfill.ts
13348
13425
  async function backfill(o) {
@@ -13352,7 +13429,7 @@ async function backfill(o) {
13352
13429
  return { runs: 0, sent: 0, failed: [] };
13353
13430
  const sleep = o.sleep ?? ((ms) => new Promise((r) => setTimeout(r, ms)));
13354
13431
  const attempts = o.attempts ?? 3;
13355
- const root = join5(o.repoDir, ".loki", "runs");
13432
+ const root = join6(o.repoDir, ".loki", "runs");
13356
13433
  let ids = [];
13357
13434
  try {
13358
13435
  ids = readdirSync(root).sort();
@@ -13363,7 +13440,7 @@ async function backfill(o) {
13363
13440
  let runs2 = 0, sent = 0;
13364
13441
  const failed = [];
13365
13442
  for (const id of ids) {
13366
- const runDir = join5(root, id);
13443
+ const runDir = join6(root, id);
13367
13444
  if (!hasSpool(runDir))
13368
13445
  continue;
13369
13446
  runs2++;
@@ -13382,17 +13459,20 @@ async function backfill(o) {
13382
13459
  return { runs: runs2, sent, failed };
13383
13460
  }
13384
13461
 
13462
+ // src/server/repos.ts
13463
+ import { basename as basename2, resolve as resolve2 } from "path";
13464
+
13385
13465
  // src/shipper/discover.ts
13386
- import { readFileSync as readFileSync5, realpathSync as realpathSync3, statSync as statSync2 } from "fs";
13387
- import { basename, dirname, join as join7, resolve } from "path";
13466
+ import { readFileSync as readFileSync5, realpathSync as realpathSync4, statSync as statSync2 } from "fs";
13467
+ import { basename, dirname, join as join8, resolve } from "path";
13388
13468
 
13389
13469
  // src/shipper/watch.ts
13390
13470
  import { readFileSync as readFileSync4, readdirSync as readdirSync2, statSync } from "fs";
13391
13471
  import { homedir as homedir3 } from "os";
13392
- import { join as join6 } from "path";
13472
+ import { join as join7 } from "path";
13393
13473
  function registryRepos(env) {
13394
13474
  try {
13395
- const reg = JSON.parse(readFileSync4(join6(env.HOME || homedir3(), ".loki", "dashboard", "projects.json"), "utf8"));
13475
+ const reg = JSON.parse(readFileSync4(join7(env.HOME || homedir3(), ".loki", "dashboard", "projects.json"), "utf8"));
13396
13476
  return Object.values(reg.projects ?? {}).map((p) => p.path).filter((p) => typeof p === "string" && p.startsWith("/"));
13397
13477
  } catch {
13398
13478
  return [];
@@ -13404,7 +13484,7 @@ function discoverLocalRepos(repoDir, env = process.env) {
13404
13484
  const out = new Map;
13405
13485
  for (const dir of [repoDir, ...registryRepos(env)]) {
13406
13486
  try {
13407
- const real2 = realpathSync3(dir);
13487
+ const real2 = realpathSync4(dir);
13408
13488
  if (!statSync2(real2).isDirectory())
13409
13489
  continue;
13410
13490
  const id = sourceId(real2);
@@ -13427,17 +13507,18 @@ function syncLocalRepos(db, repoDir, env = process.env) {
13427
13507
  function repoNames(db) {
13428
13508
  return [...new Set(db.select({ name: localRepos.name }).from(localRepos).all().map((r) => r.name))].sort();
13429
13509
  }
13430
- function mountRepos(act, db, peerIsLoopback2) {
13431
- act.get("/v1/repos", (c) => peerIsLoopback2(c) ? c.json({ repos: repoNames(db) }) : c.json({ error: "loopback only" }, 403));
13510
+ function mountRepos(act, db, peerIsLoopback2, repoDir) {
13511
+ const defaultRepo = repoDir ? basename2(resolve2(repoDir)) || null : null;
13512
+ act.get("/v1/repos", (c) => peerIsLoopback2(c) ? c.json({ repos: repoNames(db), default_repo: defaultRepo }) : c.json({ error: "loopback only" }, 403));
13432
13513
  }
13433
13514
 
13434
13515
  // src/server/routes/artifacts.ts
13435
- import { closeSync as closeSync2, fstatSync as fstatSync2, openSync as openSync2, readSync as readSync2, realpathSync as realpathSync4 } from "fs";
13436
- import { join as join8, sep as sep2 } from "path";
13516
+ import { closeSync as closeSync3, fstatSync as fstatSync3, openSync as openSync3, readSync as readSync3, realpathSync as realpathSync5 } from "fs";
13517
+ import { join as join9, sep as sep3 } from "path";
13437
13518
  var MAX_ARTIFACT_BYTES = 5 * 1024 * 1024;
13438
13519
  var EVENTS_DEFAULT = 500;
13439
13520
  var EVENTS_MAX = 1000;
13440
- var ID2 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
13521
+ var ID3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
13441
13522
  var NAME = /^(?:issue\.json|plan\.json|receipt\.json|receipt\.md|report\.md|task\.md|diff\.patch|evidence\/[A-Za-z0-9][A-Za-z0-9._-]{0,99}\.png)$/;
13442
13523
  var TYPES = {
13443
13524
  json: "application/json; charset=utf-8",
@@ -13445,16 +13526,16 @@ var TYPES = {
13445
13526
  patch: "text/plain; charset=utf-8",
13446
13527
  png: "image/png"
13447
13528
  };
13448
- var safeId = (s) => ID2.test(s) && !s.includes("..");
13529
+ var safeId = (s) => ID3.test(s) && !s.includes("..");
13449
13530
  function readCapped(path) {
13450
13531
  let fd;
13451
13532
  try {
13452
- fd = openSync2(path, "r");
13533
+ fd = openSync3(path, "r");
13453
13534
  } catch {
13454
13535
  return { status: 404 };
13455
13536
  }
13456
13537
  try {
13457
- const st = fstatSync2(fd);
13538
+ const st = fstatSync3(fd);
13458
13539
  if (!st.isFile())
13459
13540
  return { status: 404 };
13460
13541
  if (st.size > MAX_ARTIFACT_BYTES)
@@ -13462,14 +13543,14 @@ function readCapped(path) {
13462
13543
  const buf = Buffer.alloc(st.size);
13463
13544
  let off = 0;
13464
13545
  while (off < st.size) {
13465
- const n2 = readSync2(fd, buf, off, st.size - off, off);
13546
+ const n2 = readSync3(fd, buf, off, st.size - off, off);
13466
13547
  if (n2 <= 0)
13467
13548
  break;
13468
13549
  off += n2;
13469
13550
  }
13470
13551
  return { status: 200, body: buf.subarray(0, off) };
13471
13552
  } finally {
13472
- closeSync2(fd);
13553
+ closeSync3(fd);
13473
13554
  }
13474
13555
  }
13475
13556
  function mount(ctx) {
@@ -13514,19 +13595,19 @@ function mount(ctx) {
13514
13595
  return c.json({ error: "artifact not available" }, 404);
13515
13596
  let runsRoot, runDir, file;
13516
13597
  try {
13517
- runsRoot = realpathSync4(join8(repo.p, ".loki", "runs"));
13518
- runDir = realpathSync4(join8(runsRoot, run));
13598
+ runsRoot = realpathSync5(join9(repo.p, ".loki", "runs"));
13599
+ runDir = realpathSync5(join9(runsRoot, run));
13519
13600
  } catch {
13520
13601
  return c.json({ error: "artifact not found" }, 404);
13521
13602
  }
13522
- if (runDir !== join8(runsRoot, run))
13603
+ if (runDir !== join9(runsRoot, run))
13523
13604
  return c.json({ error: "artifact not found" }, 404);
13524
13605
  try {
13525
- file = realpathSync4(join8(runDir, name));
13606
+ file = realpathSync5(join9(runDir, name));
13526
13607
  } catch {
13527
13608
  return c.json({ error: "artifact not found" }, 404);
13528
13609
  }
13529
- if (!file.startsWith(runDir + sep2))
13610
+ if (!file.startsWith(runDir + sep3))
13530
13611
  return c.json({ error: "artifact not found" }, 404);
13531
13612
  const r = readCapped(file);
13532
13613
  if (r.status === 413)
@@ -13563,9 +13644,9 @@ function mount2(ctx) {
13563
13644
  }
13564
13645
 
13565
13646
  // src/server/routes/checkpoints.ts
13566
- import { execFileSync } from "child_process";
13567
- import { appendFileSync, copyFileSync, cpSync, existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readFileSync as readFileSync7, realpathSync as realpathSync5, rmSync, statSync as statSync4, writeFileSync as writeFileSync3 } from "fs";
13568
- import { join as join10, sep as sep3 } from "path";
13647
+ import { execFileSync as execFileSync2 } from "child_process";
13648
+ import { appendFileSync, copyFileSync, cpSync, existsSync as existsSync5, lstatSync, mkdirSync as mkdirSync3, readdirSync as readdirSync4, readFileSync as readFileSync7, realpathSync as realpathSync6, rmSync, statSync as statSync4, writeFileSync as writeFileSync3 } from "fs";
13649
+ import { join as join11, sep as sep4 } from "path";
13569
13650
 
13570
13651
  // src/server/audit.ts
13571
13652
  var clip = (s, n2) => s === undefined ? null : s.slice(0, n2);
@@ -13580,7 +13661,7 @@ function audit3(db, e) {
13580
13661
 
13581
13662
  // src/server/routes/cost_ledger.ts
13582
13663
  import { existsSync as existsSync4, readdirSync as readdirSync3, readFileSync as readFileSync6, statSync as statSync3 } from "fs";
13583
- import { join as join9 } from "path";
13664
+ import { join as join10 } from "path";
13584
13665
  var isNum = (v) => typeof v === "number" && Number.isFinite(v);
13585
13666
  var isObj2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
13586
13667
  var r6 = (n2) => Math.round(n2 * 1e6) / 1e6;
@@ -13611,7 +13692,7 @@ var DEFAULT_PRICING = {
13611
13692
  "gpt-5.6-luna": { input: 0.5, output: 4 }
13612
13693
  };
13613
13694
  function pricing(lokiDir) {
13614
- const d = readJson(join9(lokiDir, "pricing.json"));
13695
+ const d = readJson(join10(lokiDir, "pricing.json"));
13615
13696
  const models = isObj2(d) && isObj2(d.models) ? d.models : {};
13616
13697
  return { ...DEFAULT_PRICING, ...models };
13617
13698
  }
@@ -13624,7 +13705,7 @@ function modelCost(table, model, inp, out, cr = 0, cw = 0) {
13624
13705
  return r6((inp * ir + out * or2 + cr * crr + cw * cwr) / 1e6);
13625
13706
  }
13626
13707
  function iterationRecords(lokiDir) {
13627
- const dir = join9(lokiDir, "metrics", "efficiency");
13708
+ const dir = join10(lokiDir, "metrics", "efficiency");
13628
13709
  let names = [];
13629
13710
  try {
13630
13711
  names = readdirSync3(dir).filter((n2) => /^iteration-.*\.json$/.test(n2)).sort();
@@ -13633,7 +13714,7 @@ function iterationRecords(lokiDir) {
13633
13714
  }
13634
13715
  const out = [];
13635
13716
  for (const n2 of names) {
13636
- const d = readJson(join9(dir, n2));
13717
+ const d = readJson(join10(dir, n2));
13637
13718
  if (isObj2(d))
13638
13719
  out.push(d);
13639
13720
  }
@@ -13670,7 +13751,7 @@ function costSnapshot(lokiDir) {
13670
13751
  }
13671
13752
  }
13672
13753
  if (tIn === 0 && tOut === 0) {
13673
- const ctx = readJson(join9(lokiDir, "context", "tracking.json"));
13754
+ const ctx = readJson(join10(lokiDir, "context", "tracking.json"));
13674
13755
  const totals = isObj2(ctx) && isObj2(ctx.totals) ? ctx.totals : {};
13675
13756
  tIn = num0(totals.total_input);
13676
13757
  tOut = num0(totals.total_output);
@@ -13696,7 +13777,7 @@ function costSnapshot(lokiDir) {
13696
13777
  }
13697
13778
  }
13698
13779
  let limit = null, used = null, remaining = null;
13699
- const bd = readJson(join9(lokiDir, "metrics", "budget.json"));
13780
+ const bd = readJson(join10(lokiDir, "metrics", "budget.json"));
13700
13781
  if (isObj2(bd) && isNum(bd.limit)) {
13701
13782
  limit = bd.limit;
13702
13783
  if (recorded && !unknownUsd) {
@@ -13747,7 +13828,7 @@ function budgetSnapshot(lokiDir) {
13747
13828
  total += priced(table, d);
13748
13829
  }
13749
13830
  let limit = null;
13750
- const bd = readJson(join9(lokiDir, "metrics", "budget.json"));
13831
+ const bd = readJson(join10(lokiDir, "metrics", "budget.json"));
13751
13832
  if (isObj2(bd)) {
13752
13833
  const l = bd.limit || bd.budget_limit;
13753
13834
  limit = isNum(l) ? l : null;
@@ -13798,19 +13879,19 @@ function costTimeline(lokiDir) {
13798
13879
  }
13799
13880
  const runs2 = [];
13800
13881
  let projectTotal = 0, runsMeasured = 0;
13801
- const proofs = join9(lokiDir, "proofs");
13882
+ const proofs = join10(lokiDir, "proofs");
13802
13883
  let entries = [];
13803
13884
  try {
13804
13885
  entries = readdirSync3(proofs).sort();
13805
13886
  } catch {}
13806
13887
  for (const e of entries) {
13807
13888
  try {
13808
- if (!statSync3(join9(proofs, e)).isDirectory())
13889
+ if (!statSync3(join10(proofs, e)).isDirectory())
13809
13890
  continue;
13810
13891
  } catch {
13811
13892
  continue;
13812
13893
  }
13813
- const p = readJson(join9(proofs, e, "proof.json"));
13894
+ const p = readJson(join10(proofs, e, "proof.json"));
13814
13895
  if (!isObj2(p))
13815
13896
  continue;
13816
13897
  const cost = isObj2(p.cost) ? p.cost : {};
@@ -13840,7 +13921,7 @@ function costTimeline(lokiDir) {
13840
13921
  ...recorded || runsMeasured ? {} : { not_measured: NOT_MEASURED }
13841
13922
  };
13842
13923
  }
13843
- var lokiDirOf = (repoDir) => join9(repoDir, ".loki");
13924
+ var lokiDirOf = (repoDir) => join10(repoDir, ".loki");
13844
13925
  var lokiDirExists = (repoDir) => existsSync4(lokiDirOf(repoDir));
13845
13926
  function mount3(ctx) {
13846
13927
  const deny = { error: "loopback only without a token" };
@@ -13854,8 +13935,8 @@ var str2 = (v) => typeof v === "string" && v !== "" ? v : null;
13854
13935
  var SAFE_ID = /^[A-Za-z0-9_-]{1,128}$/;
13855
13936
  var MAX_CHECKPOINTS = 50;
13856
13937
  var validCheckpointId = (id) => SAFE_ID.test(id);
13857
- var storeOf = (repoDir) => join10(repoDir, ".loki", "state", "checkpoints");
13858
- var lokiOf = (repoDir) => join10(repoDir, ".loki");
13938
+ var storeOf = (repoDir) => join11(repoDir, ".loki", "state", "checkpoints");
13939
+ var lokiOf = (repoDir) => join11(repoDir, ".loki");
13859
13940
  var readObj = (f) => {
13860
13941
  try {
13861
13942
  const d = JSON.parse(readFileSync7(f, "utf8"));
@@ -13869,7 +13950,7 @@ function listCheckpoints(repoDir, limit = 20) {
13869
13950
  const store = storeOf(repoDir);
13870
13951
  let lines = [];
13871
13952
  try {
13872
- lines = readFileSync7(join10(store, "index.jsonl"), "utf8").split(`
13953
+ lines = readFileSync7(join11(store, "index.jsonl"), "utf8").split(`
13873
13954
  `);
13874
13955
  } catch {
13875
13956
  return [];
@@ -13897,7 +13978,7 @@ function listCheckpoints(repoDir, limit = 20) {
13897
13978
  message: str2(raw2.task) ?? str2(raw2.message) ?? str2(raw2.task_description),
13898
13979
  iteration: Number.isInteger(it) ? it : null
13899
13980
  };
13900
- const meta = readObj(join10(store, id, "metadata.json"));
13981
+ const meta = readObj(join11(store, id, "metadata.json"));
13901
13982
  if (meta) {
13902
13983
  cp.git_branch = str2(meta.git_branch);
13903
13984
  cp.provider = str2(meta.provider);
@@ -13905,7 +13986,7 @@ function listCheckpoints(repoDir, limit = 20) {
13905
13986
  cp.message ??= str2(meta.task_description);
13906
13987
  cp.git_sha ??= str2(meta.git_sha);
13907
13988
  cp.created_at ??= str2(meta.timestamp);
13908
- cp.files_count = countFiles(join10(store, id));
13989
+ cp.files_count = countFiles(join11(store, id));
13909
13990
  }
13910
13991
  out.push(cp);
13911
13992
  }
@@ -13916,7 +13997,7 @@ function countFiles(dir) {
13916
13997
  const walk = (d, top) => {
13917
13998
  for (const e of readdirSync4(d, { withFileTypes: true })) {
13918
13999
  if (e.isDirectory())
13919
- walk(join10(d, e.name), false);
14000
+ walk(join11(d, e.name), false);
13920
14001
  else if (e.isFile() && !(top && e.name === "metadata.json"))
13921
14002
  n2++;
13922
14003
  }
@@ -13927,11 +14008,11 @@ function countFiles(dir) {
13927
14008
  return n2;
13928
14009
  }
13929
14010
  function getCheckpoint(repoDir, id) {
13930
- return validCheckpointId(id) ? readObj(join10(storeOf(repoDir), id, "metadata.json")) : null;
14011
+ return validCheckpointId(id) ? readObj(join11(storeOf(repoDir), id, "metadata.json")) : null;
13931
14012
  }
13932
14013
  var gitHead = (repoDir) => {
13933
14014
  try {
13934
- return execFileSync("git", ["rev-parse", "HEAD"], { cwd: repoDir, timeout: 5000, stdio: ["ignore", "pipe", "ignore"] }).toString().trim() || null;
14015
+ return execFileSync2("git", ["rev-parse", "HEAD"], { cwd: repoDir, timeout: 5000, stdio: ["ignore", "pipe", "ignore"] }).toString().trim() || null;
13935
14016
  } catch {
13936
14017
  return null;
13937
14018
  }
@@ -13939,69 +14020,69 @@ var gitHead = (repoDir) => {
13939
14020
  function createCheckpoint(repoDir, message, now = new Date) {
13940
14021
  const store = storeOf(repoDir), loki = lokiOf(repoDir);
13941
14022
  mkdirSync3(store, { recursive: true });
13942
- const id = `chk-${stamp(now)}`, dir = join10(store, id);
14023
+ const id = `chk-${stamp(now)}`, dir = join11(store, id);
13943
14024
  mkdirSync3(dir, { recursive: true });
13944
14025
  for (const f of ["dashboard-state.json", "session.json"]) {
13945
14026
  try {
13946
- if (existsSync5(join10(loki, f)))
13947
- copyFileSync(join10(loki, f), join10(dir, f));
14027
+ if (existsSync5(join11(loki, f)))
14028
+ copyFileSync(join11(loki, f), join11(dir, f));
13948
14029
  } catch {}
13949
14030
  }
13950
14031
  try {
13951
- if (existsSync5(join10(loki, "queue")))
13952
- cpSync(join10(loki, "queue"), join10(dir, "queue"), { recursive: true });
14032
+ if (existsSync5(join11(loki, "queue")))
14033
+ cpSync(join11(loki, "queue"), join11(dir, "queue"), { recursive: true });
13953
14034
  } catch {}
13954
14035
  const meta = { id, created_at: now.toISOString(), git_sha: gitHead(repoDir), message: message || null, files: readdirSync4(dir, { withFileTypes: true }).filter((e) => e.isFile()).map((e) => e.name) };
13955
- writeFileSync3(join10(dir, "metadata.json"), JSON.stringify(meta, null, 2));
13956
- appendFileSync(join10(store, "index.jsonl"), `${JSON.stringify(meta)}
14036
+ writeFileSync3(join11(dir, "metadata.json"), JSON.stringify(meta, null, 2));
14037
+ appendFileSync(join11(store, "index.jsonl"), `${JSON.stringify(meta)}
13957
14038
  `);
13958
14039
  const mine = readdirSync4(store, { withFileTypes: true }).filter((e) => e.isDirectory() && e.name.startsWith("chk-")).map((e) => e.name).sort();
13959
14040
  while (mine.length > MAX_CHECKPOINTS)
13960
- rmSync(join10(store, mine.shift()), { recursive: true, force: true });
14041
+ rmSync(join11(store, mine.shift()), { recursive: true, force: true });
13961
14042
  return meta;
13962
14043
  }
13963
14044
  function rollbackCheckpoint(repoDir, id, now = new Date) {
13964
14045
  const store = storeOf(repoDir), loki = lokiOf(repoDir);
13965
14046
  let real2 = "", realStore = "";
13966
14047
  try {
13967
- real2 = realpathSync5(join10(store, id));
13968
- realStore = realpathSync5(store);
14048
+ real2 = realpathSync6(join11(store, id));
14049
+ realStore = realpathSync6(store);
13969
14050
  } catch {
13970
14051
  return null;
13971
14052
  }
13972
- if (!real2.startsWith(`${realStore}${sep3}`) || !statSync4(real2).isDirectory())
14053
+ if (!real2.startsWith(`${realStore}${sep4}`) || !statSync4(real2).isDirectory())
13973
14054
  return null;
13974
- const preId = `rb-pre-${stamp(now)}`, pre = join10(store, preId);
14055
+ const preId = `rb-pre-${stamp(now)}`, pre = join11(store, preId);
13975
14056
  mkdirSync3(pre, { recursive: true });
13976
14057
  const notStore = (src) => src !== store;
13977
14058
  for (const n2 of ["session.json", "dashboard-state.json", "CONTINUITY.md", "autonomy-state.json"]) {
13978
14059
  try {
13979
- if (existsSync5(join10(loki, n2)))
13980
- copyFileSync(join10(loki, n2), join10(pre, n2));
14060
+ if (existsSync5(join11(loki, n2)))
14061
+ copyFileSync(join11(loki, n2), join11(pre, n2));
13981
14062
  } catch {}
13982
14063
  }
13983
14064
  for (const d of ["state", "queue"]) {
13984
14065
  try {
13985
- if (existsSync5(join10(loki, d)))
13986
- cpSync(join10(loki, d), join10(pre, d), { recursive: true, filter: notStore });
14066
+ if (existsSync5(join11(loki, d)))
14067
+ cpSync(join11(loki, d), join11(pre, d), { recursive: true, filter: notStore });
13987
14068
  } catch {}
13988
14069
  }
13989
14070
  const preMeta = { id: preId, created_at: now.toISOString(), message: `pre-rollback snapshot (before restoring ${id})`, created_by: "control plane rollback" };
13990
- writeFileSync3(join10(pre, "metadata.json"), JSON.stringify(preMeta, null, 2));
13991
- appendFileSync(join10(store, "index.jsonl"), `${JSON.stringify(preMeta)}
14071
+ writeFileSync3(join11(pre, "metadata.json"), JSON.stringify(preMeta, null, 2));
14072
+ appendFileSync(join11(store, "index.jsonl"), `${JSON.stringify(preMeta)}
13992
14073
  `);
13993
14074
  let restored = 0;
13994
14075
  const errors = [];
13995
14076
  for (const e of readdirSync4(real2, { withFileTypes: true })) {
13996
14077
  if (e.name === "metadata.json" || e.name === "worktree-snapshot.txt")
13997
14078
  continue;
13998
- const src = join10(real2, e.name);
14079
+ const src = join11(real2, e.name);
13999
14080
  try {
14000
14081
  if (lstatSync(src).isSymbolicLink()) {
14001
14082
  errors.push(`${e.name}: symlink skipped`);
14002
14083
  continue;
14003
14084
  }
14004
- cpSync(src, join10(loki, e.name), { recursive: true, filter: (s) => s !== join10(real2, "state", "checkpoints") });
14085
+ cpSync(src, join11(loki, e.name), { recursive: true, filter: (s) => s !== join11(real2, "state", "checkpoints") });
14005
14086
  restored++;
14006
14087
  } catch (err) {
14007
14088
  errors.push(`${e.name}: ${err.message}`);
@@ -14084,8 +14165,8 @@ function mount4(ctx) {
14084
14165
 
14085
14166
  // src/server/routes/config.ts
14086
14167
  import { createHash as createHash5, randomBytes } from "crypto";
14087
- import { closeSync as closeSync3, fchmodSync, fsyncSync, lstatSync as lstatSync2, openSync as openSync3, readFileSync as readFileSync9, realpathSync as realpathSync6, renameSync as renameSync2, statSync as statSync6, unlinkSync, writeSync as writeSync2 } from "fs";
14088
- import { basename as basename3, dirname as dirname2, join as join12, sep as sep4 } from "path";
14168
+ import { closeSync as closeSync4, fchmodSync, fsyncSync, lstatSync as lstatSync2, openSync as openSync4, readFileSync as readFileSync9, realpathSync as realpathSync7, renameSync as renameSync2, statSync as statSync6, unlinkSync, writeSync as writeSync2 } from "fs";
14169
+ import { basename as basename4, dirname as dirname2, join as join13, sep as sep5 } from "path";
14089
14170
 
14090
14171
  // node_modules/yaml/dist/index.js
14091
14172
  var composer = require_composer();
@@ -14137,7 +14218,7 @@ var $visitAsync = visit.visitAsync;
14137
14218
  import { spawn } from "child_process";
14138
14219
  import { existsSync as existsSync6, readFileSync as readFileSync8, statSync as statSync5 } from "fs";
14139
14220
  import { homedir as homedir4 } from "os";
14140
- import { basename as basename2, join as join11, resolve as resolve2 } from "path";
14221
+ import { basename as basename3, join as join12, resolve as resolve3 } from "path";
14141
14222
  var ISSUE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,99}\/[A-Za-z0-9._-]{1,100}#[1-9][0-9]{0,8}$/;
14142
14223
  var TASK = /^[A-Za-z0-9][A-Za-z0-9 .,_/#@+=-]{0,499}$/;
14143
14224
  var hasDotDot = (t) => t.split(/[\\/ ]/).some((seg) => seg.startsWith(".."));
@@ -14153,7 +14234,7 @@ var BUDGET = /^(?:[1-9][0-9]{0,5}|0)(?:\.[0-9]{1,2})?$/;
14153
14234
  var WORKSPACE = /^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/;
14154
14235
  function registryRepos2(env = process.env) {
14155
14236
  try {
14156
- const j = JSON.parse(readFileSync8(join11(env.HOME || homedir4(), ".loki", "dashboard", "projects.json"), "utf8"));
14237
+ const j = JSON.parse(readFileSync8(join12(env.HOME || homedir4(), ".loki", "dashboard", "projects.json"), "utf8"));
14157
14238
  return Object.values(j.projects ?? {}).map((p) => typeof p?.path === "string" ? p.path : "").filter((p) => p && existsSync6(p) && statSync5(p).isDirectory());
14158
14239
  } catch {
14159
14240
  return [];
@@ -14173,9 +14254,9 @@ function planStart(body, known, bin = "loki") {
14173
14254
  if (b.repo !== undefined && b.repo !== "") {
14174
14255
  if (typeof b.repo !== "string" || b.repo.includes("\x00"))
14175
14256
  return { ok: false, error: "repo must be a path string" };
14176
- const want = resolve2(b.repo);
14177
- const paths = known.map((k) => resolve2(k));
14178
- const named = paths.filter((k) => basename2(k) === b.repo);
14257
+ const want = resolve3(b.repo);
14258
+ const paths = known.map((k) => resolve3(k));
14259
+ const named = paths.filter((k) => basename3(k) === b.repo);
14179
14260
  const hit = paths.find((k) => k === want) ?? (named.length === 1 ? named[0] : undefined);
14180
14261
  if (!hit)
14181
14262
  return { ok: false, error: named.length > 1 ? "repo name is ambiguous" : "repo is not a known project" };
@@ -14598,11 +14679,11 @@ function renderVerified(doc, next, quote = needsQuote) {
14598
14679
  function resolveConfigFile(repoDir) {
14599
14680
  let root;
14600
14681
  try {
14601
- root = realpathSync6(repoDir);
14682
+ root = realpathSync7(repoDir);
14602
14683
  } catch {
14603
14684
  return { ok: false, status: 400, error: "repo directory not found" };
14604
14685
  }
14605
- const p = join12(root, "loki.yaml");
14686
+ const p = join13(root, "loki.yaml");
14606
14687
  let st;
14607
14688
  try {
14608
14689
  st = lstatSync2(p);
@@ -14612,11 +14693,11 @@ function resolveConfigFile(repoDir) {
14612
14693
  if (st.isSymbolicLink()) {
14613
14694
  let real2;
14614
14695
  try {
14615
- real2 = realpathSync6(p);
14696
+ real2 = realpathSync7(p);
14616
14697
  } catch {
14617
14698
  return { ok: false, status: 400, error: "loki.yaml is a broken symlink" };
14618
14699
  }
14619
- if (!real2.startsWith(root + sep4))
14700
+ if (!real2.startsWith(root + sep5))
14620
14701
  return { ok: false, status: 400, error: "loki.yaml is a symlink that resolves outside the repo" };
14621
14702
  if (!statSync6(real2).isFile())
14622
14703
  return { ok: false, status: 422, error: "loki.yaml is not a regular file" };
@@ -14627,20 +14708,20 @@ function resolveConfigFile(repoDir) {
14627
14708
  return { ok: true, file: p, exists: true };
14628
14709
  }
14629
14710
  function atomicWrite(file, text2, mode) {
14630
- const tmp = join12(dirname2(file), `.${basename3(file)}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`);
14631
- const fd = openSync3(tmp, "wx", mode);
14711
+ const tmp = join13(dirname2(file), `.${basename4(file)}.${process.pid}.${randomBytes(6).toString("hex")}.tmp`);
14712
+ const fd = openSync4(tmp, "wx", mode);
14632
14713
  try {
14633
14714
  writeSync2(fd, text2);
14634
14715
  fchmodSync(fd, mode);
14635
14716
  fsyncSync(fd);
14636
14717
  } catch (e) {
14637
- closeSync3(fd);
14718
+ closeSync4(fd);
14638
14719
  try {
14639
14720
  unlinkSync(tmp);
14640
14721
  } catch {}
14641
14722
  throw e;
14642
14723
  }
14643
- closeSync3(fd);
14724
+ closeSync4(fd);
14644
14725
  try {
14645
14726
  renameSync2(tmp, file);
14646
14727
  } catch (e) {
@@ -14777,19 +14858,19 @@ function mount6(ctx) {
14777
14858
  }
14778
14859
 
14779
14860
  // src/server/routes/control.ts
14780
- import { existsSync as existsSync7, realpathSync as realpathSync7 } from "fs";
14781
- import { join as join14, resolve as resolve3, sep as sep5 } from "path";
14861
+ import { existsSync as existsSync7, realpathSync as realpathSync8 } from "fs";
14862
+ import { join as join15, resolve as resolve4, sep as sep6 } from "path";
14782
14863
 
14783
14864
  // ../../loki-ts/src/util/run_pid.ts
14784
- import { execFileSync as execFileSync2 } from "child_process";
14865
+ import { execFileSync as execFileSync3 } from "child_process";
14785
14866
  import { chmodSync as chmodSync2, readFileSync as readFileSync10, renameSync as renameSync3, rmSync as rmSync2, writeFileSync as writeFileSync4 } from "fs";
14786
- import { join as join13 } from "path";
14787
- var runPidPath = (runDir) => join13(runDir, "run.pid");
14867
+ import { join as join14 } from "path";
14868
+ var runPidPath = (runDir) => join14(runDir, "run.pid");
14788
14869
  function processStartTime(pid) {
14789
14870
  if (!Number.isInteger(pid) || pid <= 1)
14790
14871
  return null;
14791
14872
  try {
14792
- const out = execFileSync2("ps", ["-o", "lstart=", "-p", String(pid)], { encoding: "utf8", timeout: 5000, env: { ...process.env, LC_ALL: "C" }, stdio: ["ignore", "pipe", "ignore"] });
14873
+ const out = execFileSync3("ps", ["-o", "lstart=", "-p", String(pid)], { encoding: "utf8", timeout: 5000, env: { ...process.env, LC_ALL: "C" }, stdio: ["ignore", "pipe", "ignore"] });
14793
14874
  return out.trim().replace(/\s+/g, " ") || null;
14794
14875
  } catch {
14795
14876
  return null;
@@ -14822,7 +14903,7 @@ function verifyRunPid(runDir, runId, startOf = processStartTime) {
14822
14903
  }
14823
14904
 
14824
14905
  // src/server/routes/control.ts
14825
- var ID3 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
14906
+ var ID4 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
14826
14907
  var busy = new Set;
14827
14908
  function mount7(ctx) {
14828
14909
  const { act, db } = ctx;
@@ -14835,19 +14916,19 @@ function mount7(ctx) {
14835
14916
  audit3(db, { kind: `run.${kind}`, target, result, detail });
14836
14917
  return c.json(body, status);
14837
14918
  };
14838
- if (!ID3.test(source) || !ID3.test(id) || source.includes("..") || id.includes(".."))
14919
+ if (!ID4.test(source) || !ID4.test(id) || source.includes("..") || id.includes(".."))
14839
14920
  return done(400, "refused", { error: "invalid run id" }, "invalid id");
14840
14921
  const repoRow = db.select().from(localRepos).where(eq(localRepos.sourceId, source)).get();
14841
14922
  let repo = "";
14842
14923
  try {
14843
- repo = repoRow ? realpathSync7(repoRow.realpath) : "";
14924
+ repo = repoRow ? realpathSync8(repoRow.realpath) : "";
14844
14925
  } catch {
14845
14926
  repo = "";
14846
14927
  }
14847
14928
  if (!repo)
14848
14929
  return done(404, "refused", { error: "this run's repo is not known on this machine" });
14849
- const runsRoot = join14(repo, ".loki", "runs"), runDir = resolve3(runsRoot, id);
14850
- if (!runDir.startsWith(runsRoot + sep5))
14930
+ const runsRoot = join15(repo, ".loki", "runs"), runDir = resolve4(runsRoot, id);
14931
+ if (!runDir.startsWith(runsRoot + sep6))
14851
14932
  return done(400, "refused", { error: "invalid run id" }, "path escape");
14852
14933
  return handler({ source, run: id, repo, runDir }, done);
14853
14934
  });
@@ -14894,7 +14975,7 @@ function mount7(ctx) {
14894
14975
  return done(404, "refused", { error: "run not found" });
14895
14976
  if (!blockedQuestion(loadEvents(db, a.source, a.run), row.verdict))
14896
14977
  return done(409, "refused", { error: "run is not BLOCKED, so there is nothing to resume" });
14897
- if (!existsSync7(join14(answerDir, a.source, `${a.run}.answer.txt`)))
14978
+ if (!existsSync7(join15(answerDir, a.source, `${a.run}.answer.txt`)))
14898
14979
  return done(409, "refused", { error: "no answer recorded for this run; answer it first" });
14899
14980
  return launch(a, [bin, "answer", a.run], done);
14900
14981
  });
@@ -14974,10 +15055,10 @@ function mount8(ctx) {
14974
15055
  // src/server/routes/fleet.ts
14975
15056
  import { readdirSync as readdirSync5, readFileSync as readFileSync11 } from "fs";
14976
15057
  import { homedir as homedir5 } from "os";
14977
- import { basename as basename4, join as join15 } from "path";
15058
+ import { basename as basename5, join as join16 } from "path";
14978
15059
  var isNum2 = (v) => typeof v === "number" && Number.isFinite(v);
14979
15060
  var isObj5 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
14980
- var registryFile = () => join15(process.env.HOME ?? homedir5(), ".loki", "dashboard", "projects.json");
15061
+ var registryFile = () => join16(process.env.HOME ?? homedir5(), ".loki", "dashboard", "projects.json");
14981
15062
  function pidAlive(pid) {
14982
15063
  if (typeof pid !== "number" || !Number.isInteger(pid) || pid <= 0)
14983
15064
  return false;
@@ -14992,33 +15073,33 @@ function projectSnapshot(path) {
14992
15073
  const snap = { phase: "", iteration: null, cost_usd: null, started_at: null, ended_at: null };
14993
15074
  if (!path)
14994
15075
  return snap;
14995
- const loki = join15(path, ".loki");
14996
- const st = readJson(join15(loki, "dashboard-state.json"));
15076
+ const loki = join16(path, ".loki");
15077
+ const st = readJson(join16(loki, "dashboard-state.json"));
14997
15078
  if (isObj5(st)) {
14998
15079
  snap.phase = typeof st.phase === "string" ? st.phase : "";
14999
15080
  snap.iteration = Number.isInteger(st.iteration) ? st.iteration : null;
15000
15081
  }
15001
- const ss = readJson(join15(loki, "session.json"));
15082
+ const ss = readJson(join16(loki, "session.json"));
15002
15083
  if (isObj5(ss)) {
15003
15084
  const a = ss.startedAt || ss.started_at, b = ss.endedAt || ss.ended_at;
15004
15085
  snap.started_at = typeof a === "string" ? a : null;
15005
15086
  snap.ended_at = typeof b === "string" ? b : null;
15006
15087
  }
15007
15088
  let cost = 0, found = false;
15008
- const eff = join15(loki, "metrics", "efficiency");
15089
+ const eff = join16(loki, "metrics", "efficiency");
15009
15090
  let names = [];
15010
15091
  try {
15011
15092
  names = readdirSync5(eff).filter((n2) => n2.endsWith(".json"));
15012
15093
  } catch {}
15013
15094
  for (const n2 of names) {
15014
- const d = readJson(join15(eff, n2));
15095
+ const d = readJson(join16(eff, n2));
15015
15096
  if (isObj5(d) && isNum2(d.cost_usd) && recordIsMeasured(d)) {
15016
15097
  cost += d.cost_usd;
15017
15098
  found = true;
15018
15099
  }
15019
15100
  }
15020
15101
  if (!found) {
15021
- const t = readJson(join15(loki, "context", "tracking.json"));
15102
+ const t = readJson(join16(loki, "context", "tracking.json"));
15022
15103
  const totals = isObj5(t) && isObj5(t.totals) ? t.totals : null;
15023
15104
  if (totals && isNum2(totals.total_cost_usd) && recordIsMeasured({ cost_usd: totals.total_cost_usd, input_tokens: totals.total_input, output_tokens: totals.total_output })) {
15024
15105
  cost = totals.total_cost_usd;
@@ -15055,7 +15136,7 @@ function fleetRuns(includeInactive = true, file = registryFile()) {
15055
15136
  }
15056
15137
  return {
15057
15138
  id: p.id ?? null,
15058
- name: p.name || (path ? basename4(path) : "project"),
15139
+ name: p.name || (path ? basename5(path) : "project"),
15059
15140
  path,
15060
15141
  status,
15061
15142
  running,
@@ -15091,8 +15172,8 @@ function mount9(ctx) {
15091
15172
  }
15092
15173
 
15093
15174
  // src/server/routes/memory.ts
15094
- import { existsSync as existsSync8, readFileSync as readFileSync12, readdirSync as readdirSync6, realpathSync as realpathSync8, statSync as statSync7 } from "fs";
15095
- import { join as join16, sep as sep6 } from "path";
15175
+ import { existsSync as existsSync8, readFileSync as readFileSync12, readdirSync as readdirSync6, realpathSync as realpathSync9, statSync as statSync7 } from "fs";
15176
+ import { join as join17, sep as sep7 } from "path";
15096
15177
  var isObj6 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
15097
15178
  var nonEmpty = (v) => !(v === undefined || v === null || v === "" || Array.isArray(v) && v.length === 0 || isObj6(v) && Object.keys(v).length === 0);
15098
15179
  var focus = { dir: null };
@@ -15123,7 +15204,7 @@ function jsonFiles(dir, cap = Infinity) {
15123
15204
  for (const e of ents.sort((a, b) => a.name < b.name ? -1 : 1)) {
15124
15205
  if (out2.length >= cap)
15125
15206
  return;
15126
- const p = join16(d, e.name);
15207
+ const p = join17(d, e.name);
15127
15208
  if (e.isDirectory())
15128
15209
  walk(p);
15129
15210
  else if (e.isFile() && e.name.endsWith(".json"))
@@ -15144,24 +15225,24 @@ function setFocus(repoDir, raw2, registry = registryFile()) {
15144
15225
  return { ok: false, error: "project_dir must be an absolute path without .. segments" };
15145
15226
  let real2 = "";
15146
15227
  try {
15147
- real2 = realpathSync8(s);
15228
+ real2 = realpathSync9(s);
15148
15229
  if (!statSync7(real2).isDirectory())
15149
15230
  throw new Error("not a dir");
15150
15231
  } catch {
15151
15232
  return { ok: false, error: `Directory does not exist: ${s}` };
15152
15233
  }
15153
- if (!existsSync8(join16(real2, ".loki")) || !statSync7(join16(real2, ".loki")).isDirectory())
15234
+ if (!existsSync8(join17(real2, ".loki")) || !statSync7(join17(real2, ".loki")).isDirectory())
15154
15235
  return { ok: false, error: `Directory does not contain a .loki/ subdirectory: ${s}` };
15155
15236
  const allowed = new Set;
15156
15237
  try {
15157
- allowed.add(realpathSync8(repoDir));
15238
+ allowed.add(realpathSync9(repoDir));
15158
15239
  } catch {}
15159
15240
  const reg = readJson(registry);
15160
15241
  if (isObj6(reg) && isObj6(reg.projects))
15161
15242
  for (const p of Object.values(reg.projects)) {
15162
15243
  if (isObj6(p) && typeof p.path === "string") {
15163
15244
  try {
15164
- allowed.add(realpathSync8(p.path));
15245
+ allowed.add(realpathSync9(p.path));
15165
15246
  } catch {}
15166
15247
  }
15167
15248
  }
@@ -15175,7 +15256,7 @@ var QUEUES = [["pending.json", "pending"], ["in-progress.json", "in_progress"],
15175
15256
  var RANK = { done: 3, in_progress: 2, review: 1, pending: 0 };
15176
15257
  function tasksList(loki, status) {
15177
15258
  const all = [];
15178
- const st = readJson(join16(loki, "dashboard-state.json"));
15259
+ const st = readJson(join17(loki, "dashboard-state.json"));
15179
15260
  const groups = isObj6(st) && isObj6(st.tasks) ? st.tasks : {};
15180
15261
  for (const [key, mapped] of GROUPS) {
15181
15262
  const g = groups[key];
@@ -15197,7 +15278,7 @@ function tasksList(loki, status) {
15197
15278
  });
15198
15279
  }
15199
15280
  for (const [file, qs] of QUEUES) {
15200
- const raw2 = readJson(join16(loki, "queue", file));
15281
+ const raw2 = readJson(join17(loki, "queue", file));
15201
15282
  const items = isObj6(raw2) ? raw2.tasks : raw2;
15202
15283
  if (!Array.isArray(items))
15203
15284
  continue;
@@ -15251,7 +15332,7 @@ function tasksList(loki, status) {
15251
15332
  }
15252
15333
  return status ? out2.filter((t) => t.status === status) : out2;
15253
15334
  }
15254
- var memDir = (loki, sub) => join16(loki, "memory", sub);
15335
+ var memDir = (loki, sub) => join17(loki, "memory", sub);
15255
15336
  function memoryEpisodes(loki, limit = 50) {
15256
15337
  const eps = jsonFiles(memDir(loki, "episodic")).map(readJson).filter(isObj6);
15257
15338
  eps.sort((a, b) => String(b.timestamp ?? "").localeCompare(String(a.timestamp ?? "")));
@@ -15260,19 +15341,19 @@ function memoryEpisodes(loki, limit = 50) {
15260
15341
  function memoryEpisode(loki, id) {
15261
15342
  for (const f of jsonFiles(memDir(loki, "episodic"))) {
15262
15343
  const d = readJson(f);
15263
- if (isObj6(d) && (d.id === id || f.split(sep6).pop() === `${id}.json`))
15344
+ if (isObj6(d) && (d.id === id || f.split(sep7).pop() === `${id}.json`))
15264
15345
  return d;
15265
15346
  }
15266
15347
  return null;
15267
15348
  }
15268
15349
  function memoryPatterns(loki) {
15269
- const d = readJson(join16(memDir(loki, "semantic"), "patterns.json"));
15350
+ const d = readJson(join17(memDir(loki, "semantic"), "patterns.json"));
15270
15351
  const list = Array.isArray(d) ? d : isObj6(d) && Array.isArray(d.patterns) ? d.patterns : [];
15271
15352
  return list.filter(isObj6);
15272
15353
  }
15273
15354
  var memorySkills = (loki) => jsonFiles(memDir(loki, "skills")).map(readJson).filter(isObj6);
15274
15355
  function memoryEconomics(loki) {
15275
- const rawV = readJson(join16(loki, "memory", "token_economics.json"));
15356
+ const rawV = readJson(join17(loki, "memory", "token_economics.json"));
15276
15357
  const raw2 = isObj6(rawV) ? rawV : {};
15277
15358
  const m = isObj6(raw2.metrics) ? raw2.metrics : {};
15278
15359
  const n2 = (v) => typeof v === "number" && Number.isFinite(v) ? Math.trunc(v) : 0;
@@ -15308,7 +15389,7 @@ function memoryEconomics(loki) {
15308
15389
  };
15309
15390
  }
15310
15391
  function contextTracking(loki) {
15311
- const f = join16(loki, "context", "tracking.json");
15392
+ const f = join17(loki, "context", "tracking.json");
15312
15393
  if (!existsSync8(f)) {
15313
15394
  return { status: 200, body: {
15314
15395
  session_id: null,
@@ -15370,7 +15451,7 @@ function mount10(ctx) {
15370
15451
 
15371
15452
  // src/server/routes/metrics.ts
15372
15453
  import { readdirSync as readdirSync7, readFileSync as readFileSync13, statSync as statSync8 } from "fs";
15373
- import { join as join17 } from "path";
15454
+ import { join as join18 } from "path";
15374
15455
  var isObj7 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
15375
15456
  var arr = (v) => Array.isArray(v) ? v : [];
15376
15457
  function buildMetricsText(repoDir, now = Date.now()) {
@@ -15387,7 +15468,7 @@ function buildMetricsText(repoDir, now = Date.now()) {
15387
15468
  L.push(...samples);
15388
15469
  L.push("");
15389
15470
  };
15390
- const stRaw = readJson(join17(loki, "dashboard-state.json"));
15471
+ const stRaw = readJson(join18(loki, "dashboard-state.json"));
15391
15472
  const state = isObj7(stRaw) ? stRaw : null;
15392
15473
  let status = 0;
15393
15474
  if (state?.mode === "paused")
@@ -15396,7 +15477,7 @@ function buildMetricsText(repoDir, now = Date.now()) {
15396
15477
  status = 1;
15397
15478
  else {
15398
15479
  try {
15399
- if (pidAlive(parseInt(readFileSync13(join17(loki, "loki.pid"), "utf8").trim(), 10)))
15480
+ if (pidAlive(parseInt(readFileSync13(join18(loki, "loki.pid"), "utf8").trim(), 10)))
15400
15481
  status = 1;
15401
15482
  } catch {}
15402
15483
  }
@@ -15412,7 +15493,7 @@ function buildMetricsText(repoDir, now = Date.now()) {
15412
15493
  `loki_tasks_total{status="failed"} ${arr(tasks.failed).length}`
15413
15494
  ] : null);
15414
15495
  let agents = null;
15415
- const af = readJson(join17(loki, "state", "agents.json"));
15496
+ const af = readJson(join18(loki, "state", "agents.json"));
15416
15497
  if (Array.isArray(af) && af.length)
15417
15498
  agents = af;
15418
15499
  else if (state && Array.isArray(state.agents) && state.agents.length)
@@ -15424,7 +15505,7 @@ function buildMetricsText(repoDir, now = Date.now()) {
15424
15505
  gauge("loki_cost_usd", "Estimated total cost in USD", "gauge", cost.estimated_cost_usd !== null ? [`loki_cost_usd ${cost.estimated_cost_usd}`] : null);
15425
15506
  let events2 = null;
15426
15507
  try {
15427
- events2 = readFileSync13(join17(loki, "events.jsonl"), "utf8").split(`
15508
+ events2 = readFileSync13(join18(loki, "events.jsonl"), "utf8").split(`
15428
15509
  `).filter((l) => l.trim()).length;
15429
15510
  } catch {}
15430
15511
  gauge("loki_events_total", "Total number of events recorded", "counter", events2 !== null ? [`loki_events_total ${events2}`] : null);
@@ -15436,19 +15517,19 @@ function buildMetricsText(repoDir, now = Date.now()) {
15436
15517
  }
15437
15518
  gauge("loki_uptime_seconds", "Seconds since session started", "gauge", uptime !== null ? [`loki_uptime_seconds ${uptime}`] : null);
15438
15519
  let total = 0, ver = 0, gaps = 0, notver = 0, unk = 0, att = 0, sig = 0;
15439
- const pdir = join17(loki, "proofs");
15520
+ const pdir = join18(loki, "proofs");
15440
15521
  let entries = [];
15441
15522
  try {
15442
15523
  entries = readdirSync7(pdir).sort();
15443
15524
  } catch {}
15444
15525
  for (const e of entries) {
15445
15526
  try {
15446
- if (!statSync8(join17(pdir, e)).isDirectory())
15527
+ if (!statSync8(join18(pdir, e)).isDirectory())
15447
15528
  continue;
15448
15529
  } catch {
15449
15530
  continue;
15450
15531
  }
15451
- const d = readJson(join17(pdir, e, "proof.json"));
15532
+ const d = readJson(join18(pdir, e, "proof.json"));
15452
15533
  if (!isObj7(d))
15453
15534
  continue;
15454
15535
  total++;
@@ -15493,7 +15574,7 @@ function mount11(ctx) {
15493
15574
 
15494
15575
  // src/server/routes/session_control.ts
15495
15576
  import { existsSync as existsSync9, mkdirSync as mkdirSync4, readdirSync as readdirSync8, readFileSync as readFileSync14, unlinkSync as unlinkSync2, writeFileSync as writeFileSync5 } from "fs";
15496
- import { dirname as dirname3, join as join18 } from "path";
15577
+ import { dirname as dirname3, join as join19 } from "path";
15497
15578
  var isObj8 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
15498
15579
  var ACTIONS = ["pause", "resume", "stop", "council-review"];
15499
15580
  var isAction = (v) => ACTIONS.includes(v);
@@ -15518,7 +15599,7 @@ var readJson2 = (p) => {
15518
15599
  };
15519
15600
  function runnerPid(loki) {
15520
15601
  try {
15521
- const pid = parseInt(readFileSync14(join18(loki, "loki.pid"), "utf8").trim(), 10);
15602
+ const pid = parseInt(readFileSync14(join19(loki, "loki.pid"), "utf8").trim(), 10);
15522
15603
  return pidAlive(pid) ? pid : null;
15523
15604
  } catch {
15524
15605
  return null;
@@ -15528,18 +15609,18 @@ function applyControl(repoDir, action) {
15528
15609
  const loki = lokiDirOf(repoDir);
15529
15610
  const running = runnerPid(loki) !== null;
15530
15611
  const put = (rel) => {
15531
- const f = join18(loki, rel);
15612
+ const f = join19(loki, rel);
15532
15613
  mkdirSync4(dirname3(f), { recursive: true });
15533
15614
  writeFileSync5(f, new Date().toISOString());
15534
15615
  };
15535
15616
  if (action === "council-review") {
15536
- put(join18("signals", "COUNCIL_REVIEW_REQUESTED"));
15617
+ put(join19("signals", "COUNCIL_REVIEW_REQUESTED"));
15537
15618
  return { status: 200, body: { success: true, message: "Council review requested" } };
15538
15619
  }
15539
15620
  if (action === "resume") {
15540
15621
  for (const n2 of ["PAUSE", "STOP"]) {
15541
15622
  try {
15542
- unlinkSync2(join18(loki, n2));
15623
+ unlinkSync2(join19(loki, n2));
15543
15624
  } catch {}
15544
15625
  }
15545
15626
  return running ? { status: 200, body: { success: true, message: "Session resumed", process_verified: true } } : { status: 503, body: { success: false, message: "Session process is not running; the signal files were cleared" } };
@@ -15559,16 +15640,16 @@ function runControl(db, repoDir, action, c, via) {
15559
15640
  return c.json(r.body, r.status);
15560
15641
  }
15561
15642
  function councilState(loki) {
15562
- const f = join18(loki, "council", "state.json");
15643
+ const f = join19(loki, "council", "state.json");
15563
15644
  if (!existsSync9(f))
15564
15645
  return { enabled: false, total_votes: 0, verdicts: [] };
15565
15646
  const d = readJson2(f);
15566
15647
  return isObj8(d) ? d : { enabled: null, total_votes: null, verdicts: null, error: "unreadable_state" };
15567
15648
  }
15568
15649
  function councilVerdicts(loki, limit = 20) {
15569
- const st = readJson2(join18(loki, "council", "state.json"));
15650
+ const st = readJson2(join19(loki, "council", "state.json"));
15570
15651
  const verdicts = isObj8(st) && Array.isArray(st.verdicts) ? st.verdicts : [];
15571
- const votes = join18(loki, "council", "votes");
15652
+ const votes = join19(loki, "council", "votes");
15572
15653
  const details = [];
15573
15654
  let names = [];
15574
15655
  try {
@@ -15582,8 +15663,8 @@ function councilVerdicts(loki, limit = 20) {
15582
15663
  }
15583
15664
  };
15584
15665
  for (const n2 of names.slice(0, limit)) {
15585
- const dir = join18(votes, n2), d = { iteration: n2 };
15586
- const ev = text2(join18(dir, "evidence.md"));
15666
+ const dir = join19(votes, n2), d = { iteration: n2 };
15667
+ const ev = text2(join19(dir, "evidence.md"));
15587
15668
  if (ev !== null)
15588
15669
  d.evidence_preview = ev.slice(0, 500);
15589
15670
  let files = [];
@@ -15591,10 +15672,10 @@ function councilVerdicts(loki, limit = 20) {
15591
15672
  files = readdirSync8(dir).filter((f) => /^member-.*\.txt$/.test(f)).sort();
15592
15673
  } catch {}
15593
15674
  d.members = files.flatMap((f) => {
15594
- const t = text2(join18(dir, f));
15675
+ const t = text2(join19(dir, f));
15595
15676
  return t === null ? [] : [{ member: f.replace(/\.txt$/, ""), content: t.trim() }];
15596
15677
  });
15597
- const con = text2(join18(dir, "contrarian.txt"));
15678
+ const con = text2(join19(dir, "contrarian.txt"));
15598
15679
  if (con !== null)
15599
15680
  d.contrarian = con.trim();
15600
15681
  details.push(d);
@@ -15605,7 +15686,7 @@ function councilConvergence(loki) {
15605
15686
  const dataPoints = [];
15606
15687
  let raw2 = "";
15607
15688
  try {
15608
- raw2 = readFileSync14(join18(loki, "council", "convergence.log"), "utf8");
15689
+ raw2 = readFileSync14(join19(loki, "council", "convergence.log"), "utf8");
15609
15690
  } catch {}
15610
15691
  for (const line2 of raw2.trim().split(`
15611
15692
  `)) {
@@ -15621,7 +15702,7 @@ function councilConvergence(loki) {
15621
15702
  }
15622
15703
  function councilReport(loki) {
15623
15704
  try {
15624
- return { report: readFileSync14(join18(loki, "council", "report.md"), "utf8") };
15705
+ return { report: readFileSync14(join19(loki, "council", "report.md"), "utf8") };
15625
15706
  } catch {
15626
15707
  return { report: null };
15627
15708
  }
@@ -15634,7 +15715,7 @@ function councilTranscripts(loki, q) {
15634
15715
  if (Number.isNaN(since))
15635
15716
  return { error: "Invalid 'since' timestamp format; expected ISO8601" };
15636
15717
  }
15637
- const dir = join18(loki, "council", "transcripts");
15718
+ const dir = join19(loki, "council", "transcripts");
15638
15719
  let names = [];
15639
15720
  try {
15640
15721
  names = readdirSync8(dir).filter((f) => /^iter-.*\.json$/.test(f)).sort().reverse();
@@ -15643,7 +15724,7 @@ function councilTranscripts(loki, q) {
15643
15724
  }
15644
15725
  const out2 = [];
15645
15726
  for (const n2 of names) {
15646
- const rec = readJson2(join18(dir, n2));
15727
+ const rec = readJson2(join19(dir, n2));
15647
15728
  if (!isObj8(rec) || typeof rec.iteration_id !== "string")
15648
15729
  continue;
15649
15730
  if (since !== null) {
@@ -15696,28 +15777,28 @@ function mount12(ctx) {
15696
15777
  // src/server/routes/integrations.ts
15697
15778
  import { spawn as spawn2 } from "child_process";
15698
15779
  import { existsSync as existsSync10, readFileSync as readFileSync15, statSync as statSync9 } from "fs";
15699
- import { delimiter, join as join19 } from "path";
15780
+ import { delimiter, join as join20 } from "path";
15700
15781
  var GH_TIMEOUT_MS = 3000;
15701
15782
  var isSet = (n2) => !!n2 && (process.env[n2] ?? "") !== "";
15702
15783
  function ghAuthed(pathVar = process.env.PATH ?? "", timeoutMs = GH_TIMEOUT_MS) {
15703
- const exe = pathVar.split(delimiter).filter(Boolean).map((d) => join19(d, "gh")).find((p) => existsSync10(p));
15784
+ const exe = pathVar.split(delimiter).filter(Boolean).map((d) => join20(d, "gh")).find((p) => existsSync10(p));
15704
15785
  if (!exe)
15705
15786
  return Promise.resolve(null);
15706
- return new Promise((resolve4) => {
15787
+ return new Promise((resolve5) => {
15707
15788
  let done = false;
15708
15789
  let timer;
15709
15790
  const finish = (v) => {
15710
15791
  if (!done) {
15711
15792
  done = true;
15712
15793
  clearTimeout(timer);
15713
- resolve4(v);
15794
+ resolve5(v);
15714
15795
  }
15715
15796
  };
15716
15797
  let child;
15717
15798
  try {
15718
15799
  child = spawn2(exe, ["auth", "status"], { stdio: "ignore", env: { ...process.env, NO_COLOR: "1" } });
15719
15800
  } catch {
15720
- return resolve4(null);
15801
+ return resolve5(null);
15721
15802
  }
15722
15803
  timer = setTimeout(() => {
15723
15804
  try {
@@ -15745,7 +15826,7 @@ function configuredName(repoDir, path) {
15745
15826
  }
15746
15827
  function mcpServers(repoDir) {
15747
15828
  try {
15748
- const p = join19(repoDir, ".mcp.json");
15829
+ const p = join20(repoDir, ".mcp.json");
15749
15830
  if (!existsSync10(p) || statSync9(p).size > 1e6)
15750
15831
  return null;
15751
15832
  const j = JSON.parse(readFileSync15(p, "utf8"));
@@ -15775,18 +15856,18 @@ function conv(s) {
15775
15856
  }
15776
15857
  async function listIntegrations(repoDir, gh = () => ghAuthed()) {
15777
15858
  const rows = [];
15778
- const gitEnv = configuredName(repoDir, ["git", "token_env"]);
15859
+ const gitEnv2 = configuredName(repoDir, ["git", "token_env"]);
15779
15860
  const ghOk = await gh();
15780
- const gitEnvSet = isSet(gitEnv);
15861
+ const gitEnvSet = isSet(gitEnv2);
15781
15862
  rows.push({
15782
15863
  id: "github",
15783
15864
  label: "GitHub",
15784
- status: gitEnvSet || ghOk === true ? "connected" : ghOk === null && !gitEnv ? "not_measured" : "not_connected",
15865
+ status: gitEnvSet || ghOk === true ? "connected" : ghOk === null && !gitEnv2 ? "not_measured" : "not_connected",
15785
15866
  method: gitEnvSet ? "env" : ghOk !== null ? "gh_cli" : "none",
15786
- env_name: gitEnv,
15867
+ env_name: gitEnv2,
15787
15868
  env_set: gitEnvSet,
15788
15869
  config_path: "git.token_env",
15789
- detail: gitEnvSet ? "git.token_env is set in the environment" : ghOk === true ? "gh auth status succeeded" : ghOk === false ? "gh is installed but not authenticated" : gitEnv ? "git.token_env names a variable that is not set" : "gh not found and git.token_env is not configured"
15870
+ detail: gitEnvSet ? "git.token_env is set in the environment" : ghOk === true ? "gh auth status succeeded" : ghOk === false ? "gh is installed but not authenticated" : gitEnv2 ? "git.token_env names a variable that is not set" : "gh not found and git.token_env is not configured"
15790
15871
  });
15791
15872
  rows.push(conv(CONVENTIONAL[0]));
15792
15873
  const slackEnv = configuredName(repoDir, ["notifications", "slack_webhook_env"]);
@@ -15826,8 +15907,8 @@ function mount13(ctx) {
15826
15907
 
15827
15908
  // src/server/routes/merge_risk.ts
15828
15909
  import { spawn as spawn3 } from "child_process";
15829
- import { realpathSync as realpathSync9 } from "fs";
15830
- import { basename as basename5, resolve as resolve4 } from "path";
15910
+ import { realpathSync as realpathSync10 } from "fs";
15911
+ import { basename as basename6, resolve as resolve5 } from "path";
15831
15912
  var PR = /^[0-9]{1,7}$/;
15832
15913
  var REF = /^[A-Za-z0-9._/][A-Za-z0-9._/-]{0,99}$/;
15833
15914
  var MAX_OUT = 256 * 1024;
@@ -15925,7 +16006,7 @@ function mount14(ctx) {
15925
16006
  const active = { run: 0, queue: 0, risk: 0 };
15926
16007
  const real2 = (p) => {
15927
16008
  try {
15928
- return realpathSync9(p);
16009
+ return realpathSync10(p);
15929
16010
  } catch {
15930
16011
  return null;
15931
16012
  }
@@ -15939,12 +16020,12 @@ function mount14(ctx) {
15939
16020
  for (const k of [ctx.repoDir, ...registryRepos2()]) {
15940
16021
  const r = real2(k);
15941
16022
  if (r)
15942
- known.set(r, basename5(resolve4(k)));
16023
+ known.set(r, basename6(resolve5(k)));
15943
16024
  }
15944
16025
  const wantReal = real2(want);
15945
16026
  if (wantReal && known.has(wantReal))
15946
16027
  return wantReal;
15947
- const named = [...known].filter(([r, label]) => label === want || basename5(r) === want).map(([r]) => r);
16028
+ const named = [...known].filter(([r, label]) => label === want || basename6(r) === want).map(([r]) => r);
15948
16029
  return named.length === 1 ? named[0] : null;
15949
16030
  };
15950
16031
  const slot = async (c, kind, auditKind, fn) => {
@@ -16137,7 +16218,7 @@ function mount15(ctx) {
16137
16218
  // src/server/routes/providers.ts
16138
16219
  import { spawn as spawn4 } from "child_process";
16139
16220
  import { existsSync as existsSync11, readFileSync as readFileSync16 } from "fs";
16140
- import { delimiter as delimiter2, join as join20 } from "path";
16221
+ import { delimiter as delimiter2, join as join21 } from "path";
16141
16222
  var ORDER = ["claude", "codex", "cline", "aider", "opencode"];
16142
16223
  var DEPRECATED = ["gemini"];
16143
16224
  var AUTH_ENV = {
@@ -16153,7 +16234,7 @@ function findOnPath(bin, pathVar) {
16153
16234
  for (const d of pathVar.split(delimiter2)) {
16154
16235
  if (!d)
16155
16236
  continue;
16156
- const p = join20(d, bin);
16237
+ const p = join21(d, bin);
16157
16238
  if (existsSync11(p))
16158
16239
  return p;
16159
16240
  }
@@ -16163,7 +16244,7 @@ function probeCli(bin, timeoutMs, pathVar = process.env.PATH ?? "") {
16163
16244
  const exe = findOnPath(bin, pathVar);
16164
16245
  if (!exe)
16165
16246
  return Promise.resolve({ installed: false, version: null, probe: "not_found" });
16166
- return new Promise((resolve5) => {
16247
+ return new Promise((resolve6) => {
16167
16248
  let out2 = "";
16168
16249
  let done = false;
16169
16250
  let timer;
@@ -16171,14 +16252,14 @@ function probeCli(bin, timeoutMs, pathVar = process.env.PATH ?? "") {
16171
16252
  if (!done) {
16172
16253
  done = true;
16173
16254
  clearTimeout(timer);
16174
- resolve5(r);
16255
+ resolve6(r);
16175
16256
  }
16176
16257
  };
16177
16258
  let child;
16178
16259
  try {
16179
16260
  child = spawn4(exe, ["--version"], { stdio: ["ignore", "pipe", "ignore"], env: { ...process.env, NO_COLOR: "1" } });
16180
16261
  } catch {
16181
- return resolve5({ installed: true, version: null, probe: "error" });
16262
+ return resolve6({ installed: true, version: null, probe: "error" });
16182
16263
  }
16183
16264
  timer = setTimeout(() => {
16184
16265
  try {
@@ -16198,14 +16279,14 @@ function probeCli(bin, timeoutMs, pathVar = process.env.PATH ?? "") {
16198
16279
  });
16199
16280
  }
16200
16281
  function providersDir() {
16201
- const cands = [process.env.LOKI_PROVIDERS_DIR, join20(import.meta.dir, "../../../../../providers"), join20(import.meta.dir, "../../../providers")];
16202
- return cands.find((d) => !!d && existsSync11(join20(d, "model_catalog.json"))) ?? null;
16282
+ const cands = [process.env.LOKI_PROVIDERS_DIR, join21(import.meta.dir, "../../../../../providers"), join21(import.meta.dir, "../../../providers")];
16283
+ return cands.find((d) => !!d && existsSync11(join21(d, "model_catalog.json"))) ?? null;
16203
16284
  }
16204
16285
  function loadCatalog(dir) {
16205
16286
  if (!dir)
16206
16287
  return { providers: {}, updated: null };
16207
16288
  try {
16208
- const j = JSON.parse(readFileSync16(join20(dir, "model_catalog.json"), "utf8"));
16289
+ const j = JSON.parse(readFileSync16(join21(dir, "model_catalog.json"), "utf8"));
16209
16290
  return { providers: j.providers ?? {}, updated: typeof j.updated === "string" ? j.updated : null };
16210
16291
  } catch {
16211
16292
  return { providers: {}, updated: null };
@@ -16448,24 +16529,24 @@ data: ${JSON.stringify({ source: k.slice(0, i), run: k.slice(i + 1) })}
16448
16529
  }
16449
16530
 
16450
16531
  // src/server/routes/verify.ts
16451
- import { readFileSync as readFileSync26, realpathSync as realpathSync13 } from "fs";
16532
+ import { readFileSync as readFileSync26, realpathSync as realpathSync14 } from "fs";
16452
16533
  import { createPublicKey as createPublicKey5 } from "crypto";
16453
- import { join as join31, sep as sep11 } from "path";
16534
+ import { join as join32, sep as sep12 } from "path";
16454
16535
 
16455
16536
  // ../../loki-ts/src/engine10/verify_cmd.ts
16456
16537
  import { existsSync as existsSync19, readdirSync as readdirSync12, readFileSync as readFileSync25, statSync as statSync13 } from "fs";
16457
- import { dirname as dirname12, join as join30 } from "path";
16538
+ import { dirname as dirname12, join as join31 } from "path";
16458
16539
  import { createHash as createHash10, createPublicKey as createPublicKey4, verify as verify3 } from "crypto";
16459
16540
 
16460
16541
  // ../../loki-ts/src/util/paths.ts
16461
- import { resolve as resolve5, dirname as dirname4 } from "path";
16542
+ import { resolve as resolve6, dirname as dirname4 } from "path";
16462
16543
  import { fileURLToPath } from "url";
16463
16544
  import { existsSync as existsSync12 } from "fs";
16464
16545
  var HERE = dirname4(fileURLToPath(import.meta.url));
16465
16546
  function findRepoRoot() {
16466
16547
  let dir = HERE;
16467
16548
  for (let i = 0;i < 6; i++) {
16468
- if (existsSync12(resolve5(dir, "VERSION")) && existsSync12(resolve5(dir, "autonomy/run.sh"))) {
16549
+ if (existsSync12(resolve6(dir, "VERSION")) && existsSync12(resolve6(dir, "autonomy/run.sh"))) {
16469
16550
  return dir;
16470
16551
  }
16471
16552
  const parent = dirname4(dir);
@@ -16473,7 +16554,7 @@ function findRepoRoot() {
16473
16554
  break;
16474
16555
  dir = parent;
16475
16556
  }
16476
- return resolve5(HERE, "..", "..", "..");
16557
+ return resolve6(HERE, "..", "..", "..");
16477
16558
  }
16478
16559
  var REPO_ROOT = findRepoRoot();
16479
16560
 
@@ -16481,14 +16562,14 @@ var REPO_ROOT = findRepoRoot();
16481
16562
  import { createHash as createHash9, randomBytes as randomBytes3, createPrivateKey, createPublicKey as createPublicKey2, generateKeyPairSync, sign } from "crypto";
16482
16563
  import { chmodSync as chmodSync4, existsSync as existsSync18, readdirSync as readdirSync11, linkSync, mkdirSync as mkdirSync9, readFileSync as readFileSync23, statSync as statSync12, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
16483
16564
  import { homedir as homedir6 } from "os";
16484
- import { basename as basename9, dirname as dirname11, join as join29 } from "path";
16565
+ import { basename as basename10, dirname as dirname11, join as join30 } from "path";
16485
16566
 
16486
16567
  // ../../loki-ts/src/e10ext/assert_delta.ts
16487
- import { execFileSync as execFileSync3 } from "child_process";
16568
+ import { execFileSync as execFileSync4 } from "child_process";
16488
16569
  import { mkdtempSync, readFileSync as readFileSync17, rmSync as rmSync3 } from "fs";
16489
16570
  import { tmpdir as tmpdir2 } from "os";
16490
- import { join as join21 } from "path";
16491
- import { basename as basename6 } from "path";
16571
+ import { join as join22 } from "path";
16572
+ import { basename as basename7 } from "path";
16492
16573
  var WEAKENED = { verdict: "weakened", changes: [] };
16493
16574
  var PY = String.raw`
16494
16575
  import ast, copy, io, json, re, sys, tokenize
@@ -16639,15 +16720,15 @@ out("value-change" if ok and items else "weakened", items if ok else [])
16639
16720
  `;
16640
16721
  var okStr = (v) => typeof v === "string" && v.length <= 200 && !/[\x00-\x1f\x7f]/.test(v);
16641
16722
  function classifyAssertDelta(inp) {
16642
- const f = basename6(inp.path);
16723
+ const f = basename7(inp.path);
16643
16724
  if (!/^(test_.*|.*_test)\.py$/.test(f))
16644
16725
  return WEAKENED;
16645
16726
  if (inp.headCounts.run !== inp.baseCounts.run || inp.headCounts.skipped !== inp.baseCounts.skipped)
16646
16727
  return WEAKENED;
16647
16728
  let cwd = "";
16648
16729
  try {
16649
- cwd = mkdtempSync(join21(tmpdir2(), "loki-ad-"));
16650
- const raw2 = execFileSync3("python3", ["-I", "-c", PY], {
16730
+ cwd = mkdtempSync(join22(tmpdir2(), "loki-ad-"));
16731
+ const raw2 = execFileSync4("python3", ["-I", "-c", PY], {
16651
16732
  input: JSON.stringify({ path: inp.path, base: inp.base, head: inp.head, task: inp.task }),
16652
16733
  cwd,
16653
16734
  env: process.env,
@@ -16676,8 +16757,8 @@ function assertDeltaNotes(repoDir, baseSha, headRef, path, task, baseCounts, hea
16676
16757
  if (!baseCounts || !headCounts)
16677
16758
  return null;
16678
16759
  try {
16679
- const show = (ref) => execFileSync3("git", ["show", `${ref}:${path}`], { cwd: repoDir, encoding: "utf8", env: process.env, stdio: ["ignore", "pipe", "ignore"] });
16680
- const head = headRef ? show(headRef) : readFileSync17(join21(repoDir, path), "utf8");
16760
+ const show = (ref) => execFileSync4("git", ["show", `${ref}:${path}`], { cwd: repoDir, encoding: "utf8", env: process.env, stdio: ["ignore", "pipe", "ignore"] });
16761
+ const head = headRef ? show(headRef) : readFileSync17(join22(repoDir, path), "utf8");
16681
16762
  const r = classifyTestEdit(path, show(baseSha), head, task, baseCounts, headCounts);
16682
16763
  return r[0]?.kind === "literal-only" ? r.map((e) => `assertion value changed (not shown to be required by the task): ${e.file}:${e.line} ${e.old} -> ${e.new}`) : null;
16683
16764
  } catch {
@@ -16693,16 +16774,16 @@ function classifyTestEdit(file, oldText, newText, taskText, baseCounts, headCoun
16693
16774
  }
16694
16775
 
16695
16776
  // ../../loki-ts/src/e10ext/discard.ts
16696
- import { execFileSync as execFileSync4 } from "child_process";
16697
- import { chmodSync as chmodSync3, closeSync as closeSync4, lstatSync as lstatSync3, mkdirSync as mkdirSync5, openSync as openSync4, readFileSync as readFileSync18, realpathSync as realpathSync10, rmdirSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "fs";
16698
- import { dirname as dirname5, join as join22, relative, sep as sep7 } from "path";
16777
+ import { execFileSync as execFileSync5 } from "child_process";
16778
+ import { chmodSync as chmodSync3, closeSync as closeSync5, lstatSync as lstatSync3, mkdirSync as mkdirSync5, openSync as openSync5, readFileSync as readFileSync18, realpathSync as realpathSync11, rmdirSync, unlinkSync as unlinkSync3, writeFileSync as writeFileSync6 } from "fs";
16779
+ import { dirname as dirname5, join as join23, relative, sep as sep8 } from "path";
16699
16780
  function safeRestore(repoDir, f, want, mode) {
16700
- const root = realpathSync10(repoDir), fp = join22(root, f), rel = relative(root, dirname5(fp));
16781
+ const root = realpathSync11(repoDir), fp = join23(root, f), rel = relative(root, dirname5(fp));
16701
16782
  if (rel.startsWith(".."))
16702
16783
  throw new Error("outside repo");
16703
16784
  let cur = root;
16704
- for (const part of rel === "" ? [] : rel.split(sep7)) {
16705
- cur = join22(cur, part);
16785
+ for (const part of rel === "" ? [] : rel.split(sep8)) {
16786
+ cur = join23(cur, part);
16706
16787
  let st2;
16707
16788
  try {
16708
16789
  st2 = lstatSync3(cur);
@@ -16729,11 +16810,11 @@ function safeRestore(repoDir, f, want, mode) {
16729
16810
  else
16730
16811
  unlinkSync3(fp);
16731
16812
  }
16732
- const fd = openSync4(fp, "wx", mode);
16813
+ const fd = openSync5(fp, "wx", mode);
16733
16814
  try {
16734
16815
  writeFileSync6(fd, want);
16735
16816
  } finally {
16736
- closeSync4(fd);
16817
+ closeSync5(fd);
16737
16818
  }
16738
16819
  chmodSync3(fp, mode);
16739
16820
  }
@@ -16751,7 +16832,7 @@ async function discardIfSatisfied(git, base, o, staged, keep, repoDir) {
16751
16832
  return { status: "failed", data: {}, reason: "already-satisfied discard failed" };
16752
16833
  const notProven = [];
16753
16834
  for (const [f, v] of Object.entries(o.intake?.preexisting_untracked_blobs ?? {})) {
16754
- const fp = join22(repoDir, f);
16835
+ const fp = join23(repoDir, f);
16755
16836
  try {
16756
16837
  if (v.startsWith("!")) {
16757
16838
  const st = lstatSync3(fp);
@@ -16759,7 +16840,7 @@ async function discardIfSatisfied(git, base, o, staged, keep, repoDir) {
16759
16840
  throw new Error("changed, not snapshotted");
16760
16841
  continue;
16761
16842
  }
16762
- const [sha2, mode] = v.split(" "), want = execFileSync4("git", ["cat-file", "blob", sha2], { cwd: repoDir, env: process.env, maxBuffer: 1 << 28 });
16843
+ const [sha2, mode] = v.split(" "), want = execFileSync5("git", ["cat-file", "blob", sha2], { cwd: repoDir, env: process.env, maxBuffer: 1 << 28 });
16763
16844
  safeRestore(repoDir, f, want, parseInt(mode ?? "644", 8));
16764
16845
  } catch {
16765
16846
  notProven.push(f);
@@ -16770,11 +16851,11 @@ async function discardIfSatisfied(git, base, o, staged, keep, repoDir) {
16770
16851
  try {
16771
16852
  let m = 420;
16772
16853
  try {
16773
- const l = lstatSync3(join22(repoDir, f));
16854
+ const l = lstatSync3(join23(repoDir, f));
16774
16855
  if (l.isFile())
16775
16856
  m = l.mode & 511;
16776
16857
  } catch {}
16777
- safeRestore(repoDir, f, execFileSync4("git", ["cat-file", "blob", pre[f]], { cwd: repoDir, env: process.env, maxBuffer: 1 << 28 }), m);
16858
+ safeRestore(repoDir, f, execFileSync5("git", ["cat-file", "blob", pre[f]], { cwd: repoDir, env: process.env, maxBuffer: 1 << 28 }), m);
16778
16859
  } catch {
16779
16860
  notProven.push(f);
16780
16861
  }
@@ -16786,8 +16867,8 @@ async function discardIfSatisfied(git, base, o, staged, keep, repoDir) {
16786
16867
  import { dirname as dirname6 } from "path";
16787
16868
 
16788
16869
  // ../../loki-ts/src/e10ext/preexisting_dirty.ts
16789
- import { execFileSync as execFileSync5 } from "child_process";
16790
- var blob2 = (repoDir, path, env = process.env) => execFileSync5("git", ["hash-object", "-w", "--no-filters", "--", path], { cwd: repoDir, encoding: "utf8", env, stdio: ["ignore", "pipe", "ignore"] }).trim();
16870
+ import { execFileSync as execFileSync6 } from "child_process";
16871
+ var blob2 = (repoDir, path, env = process.env) => execFileSync6("git", ["hash-object", "-w", "--no-filters", "--", path], { cwd: repoDir, encoding: "utf8", env, stdio: ["ignore", "pipe", "ignore"] }).trim();
16791
16872
  function untouchedSinceIntake(repoDir, recorded, env = process.env) {
16792
16873
  if (!recorded || typeof recorded !== "object")
16793
16874
  return [];
@@ -16807,10 +16888,10 @@ function dropSet(repoDir, staged, preexistingDirty, env = process.env) {
16807
16888
  }
16808
16889
 
16809
16890
  // ../../loki-ts/src/e10ext/scope.ts
16810
- import { basename as basename8, dirname as dirname7 } from "path";
16891
+ import { basename as basename9, dirname as dirname7 } from "path";
16811
16892
 
16812
16893
  // ../../loki-ts/src/engine10/testmap.ts
16813
- import { basename as basename7, extname, join as join23, relative as relative2, sep as sep8 } from "path";
16894
+ import { basename as basename8, extname, join as join24, relative as relative2, sep as sep9 } from "path";
16814
16895
  var SKIP_DIRS = new Set([
16815
16896
  ".git",
16816
16897
  "node_modules",
@@ -16830,12 +16911,12 @@ var JS_TEST_RE = /\.(test|spec)\.[cm]?[jt]sx?$/;
16830
16911
  var PY_TEST_RE = /^(test_.+|.+_test)\.py$/;
16831
16912
  var GO_TEST_RE = /_test\.go$/;
16832
16913
  function isTestFile(rel) {
16833
- const name = basename7(rel);
16914
+ const name = basename8(rel);
16834
16915
  return JS_TEST_RE.test(name) || PY_TEST_RE.test(name) || GO_TEST_RE.test(name);
16835
16916
  }
16836
16917
 
16837
16918
  // ../../loki-ts/src/features/speed/unit_mode.ts
16838
- import { closeSync as closeSync5, constants, fstatSync as fstatSync3, lstatSync as lstatSync4, openSync as openSync5, readSync as readSync3, realpathSync as realpathSync11 } from "fs";
16919
+ import { closeSync as closeSync6, constants, fstatSync as fstatSync4, lstatSync as lstatSync4, openSync as openSync6, readSync as readSync4, realpathSync as realpathSync12 } from "fs";
16839
16920
  var MAX_SPEC_BYTES = 1024 * 1024;
16840
16921
  var MAX_TOKEN_BUDGET = 1e9;
16841
16922
  var norm2 = (p) => p.replace(/^\.\//, "");
@@ -16845,15 +16926,15 @@ function readBounded(path) {
16845
16926
  const l = lstatSync4(path);
16846
16927
  if (l.isSymbolicLink() || !l.isFile() || l.size > MAX_SPEC_BYTES)
16847
16928
  return null;
16848
- const fd = openSync5(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
16929
+ const fd = openSync6(path, constants.O_RDONLY | constants.O_NOFOLLOW | constants.O_NONBLOCK);
16849
16930
  try {
16850
- const st = fstatSync3(fd);
16931
+ const st = fstatSync4(fd);
16851
16932
  if (!st.isFile() || st.size > MAX_SPEC_BYTES)
16852
16933
  return null;
16853
16934
  const buf = Buffer.alloc(st.size + 1);
16854
16935
  let n2 = 0;
16855
16936
  for (;; ) {
16856
- const r = readSync3(fd, buf, n2, buf.length - n2, null);
16937
+ const r = readSync4(fd, buf, n2, buf.length - n2, null);
16857
16938
  if (r <= 0)
16858
16939
  break;
16859
16940
  n2 += r;
@@ -16862,7 +16943,7 @@ function readBounded(path) {
16862
16943
  }
16863
16944
  return buf.subarray(0, n2).toString("utf8");
16864
16945
  } finally {
16865
- closeSync5(fd);
16946
+ closeSync6(fd);
16866
16947
  }
16867
16948
  }
16868
16949
  function parseText(txt) {
@@ -16923,7 +17004,7 @@ function outsideScope(o, staged) {
16923
17004
  ${typeof o.intake?.task === "string" ? o.intake.task : ""}
16924
17005
  ${contractText(o)}`, pre = o.intake?.preexisting_dirty ?? {};
16925
17006
  const toks = surfaceTokens(text2), plannedDirs = new Set(rel.map((r) => dirname7(r)).filter((d) => d !== "."));
16926
- return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2, basename8(f)) && !plannedDirs.has(dirname7(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
17007
+ return staged.filter(({ st, f }) => st !== "A" && !isTestFile(f) && !Object.hasOwn(pre, f) && !rel.includes(f) && !mentions(text2, f) && !mentions(text2, basename9(f)) && !plannedDirs.has(dirname7(f)) && !dirSegs(f).some((d) => toks.has(d))).map(({ f }) => f);
16927
17008
  }
16928
17009
  function flagOutsideScope(o, staged) {
16929
17010
  const unit = unitFlags(staged, process.env, o.intake?.preexisting_dirty ?? {});
@@ -17007,7 +17088,7 @@ import { spawn as spawn5 } from "child_process";
17007
17088
 
17008
17089
  // ../../loki-ts/src/project_model/discover.ts
17009
17090
  import { existsSync as existsSync14, mkdirSync as mkdirSync6, readFileSync as readFileSync19, rmSync as rmSync4, writeFileSync as writeFileSync7 } from "fs";
17010
- import { join as join25 } from "path";
17091
+ import { join as join26 } from "path";
17011
17092
 
17012
17093
  // ../../loki-ts/src/engine10/types.ts
17013
17094
  var STAGE_BUDGETS = {
@@ -17024,23 +17105,23 @@ var STAGE_BUDGETS = {
17024
17105
  };
17025
17106
 
17026
17107
  // ../../loki-ts/src/project_model/schema.ts
17027
- import { existsSync as existsSync13, lstatSync as lstatSync5, realpathSync as realpathSync12, statSync as statSync10 } from "fs";
17028
- import { isAbsolute, join as join24, normalize, sep as sep9 } from "path";
17108
+ import { existsSync as existsSync13, lstatSync as lstatSync5, realpathSync as realpathSync13, statSync as statSync10 } from "fs";
17109
+ import { isAbsolute, join as join25, normalize, sep as sep10 } from "path";
17029
17110
  var PROJECT_MODEL_SCHEMA = "loki.v10.project/1";
17030
17111
  var COMMAND_KINDS = ["test", "lint", "build", "start"];
17031
17112
  var isRec = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
17032
17113
  var isStr = (v) => typeof v === "string" && v.trim() !== "";
17033
17114
  function safeRel(p) {
17034
- const n2 = normalize(p.trim()).split(sep9).join("/").replace(/\/$/, "");
17115
+ const n2 = normalize(p.trim()).split(sep10).join("/").replace(/\/$/, "");
17035
17116
  if (n2 === "" || isAbsolute(n2) || n2 === ".." || n2.startsWith("../"))
17036
17117
  return null;
17037
17118
  return n2;
17038
17119
  }
17039
17120
  function insideRepo(repoDir, rel) {
17040
17121
  try {
17041
- const real2 = realpathSync12(join24(repoDir, rel));
17042
- const base = realpathSync12(repoDir);
17043
- return real2 === base || real2.startsWith(base + sep9);
17122
+ const real2 = realpathSync13(join25(repoDir, rel));
17123
+ const base = realpathSync13(repoDir);
17124
+ return real2 === base || real2.startsWith(base + sep10);
17044
17125
  } catch {
17045
17126
  return false;
17046
17127
  }
@@ -17051,7 +17132,7 @@ function checkCitation(repoDir, raw2) {
17051
17132
  const rel = safeRel(raw2.replace(/:\d+(?:-\d+)?$/, ""));
17052
17133
  if (rel === null)
17053
17134
  return `citation "${raw2}" is not a repo-relative path`;
17054
- const abs = join24(repoDir, rel);
17135
+ const abs = join25(repoDir, rel);
17055
17136
  if (!existsSync13(abs) || !statSync10(abs).isFile() || !insideRepo(repoDir, rel))
17056
17137
  return `citation "${raw2}" names a file that does not exist`;
17057
17138
  return null;
@@ -17063,7 +17144,7 @@ function checkFingerprint(repoDir, raw2) {
17063
17144
  if (rel === null)
17064
17145
  return `fingerprint "${raw2}" is not a repo-relative path`;
17065
17146
  try {
17066
- if (!lstatSync5(join24(repoDir, rel)).isFile() || !insideRepo(repoDir, rel))
17147
+ if (!lstatSync5(join25(repoDir, rel)).isFile() || !insideRepo(repoDir, rel))
17067
17148
  return `fingerprint "${raw2}" is not a regular file inside the repo`;
17068
17149
  } catch {
17069
17150
  return `fingerprint "${raw2}" names a file that does not exist`;
@@ -17091,7 +17172,7 @@ function checkDir(repoDir, v, where, errs) {
17091
17172
  errs.push(`${where}: must be a repo-relative directory ("." for the repo root)`);
17092
17173
  return ".";
17093
17174
  }
17094
- const abs = join24(repoDir, rel);
17175
+ const abs = join25(repoDir, rel);
17095
17176
  if (!existsSync13(abs) || !statSync10(abs).isDirectory() || !insideRepo(repoDir, rel))
17096
17177
  errs.push(`${where}: directory "${rel}" does not exist`);
17097
17178
  return rel;
@@ -17186,7 +17267,7 @@ var PROJECT_FILE = ".loki/project.json";
17186
17267
  var UNKNOWN_TTL_MS = 60 * 60 * 1000;
17187
17268
  function loadCached(repoDir, now = Date.now()) {
17188
17269
  try {
17189
- return parseCached(repoDir, JSON.parse(readFileSync19(join25(repoDir, PROJECT_FILE), "utf8")), now);
17270
+ return parseCached(repoDir, JSON.parse(readFileSync19(join26(repoDir, PROJECT_FILE), "utf8")), now);
17190
17271
  } catch {
17191
17272
  return null;
17192
17273
  }
@@ -17254,7 +17335,7 @@ function isMultiRoot(api) {
17254
17335
  import { createHash as createHash6, randomBytes as randomBytes2 } from "crypto";
17255
17336
  import { existsSync as existsSync15, lstatSync as lstatSync6, mkdirSync as mkdirSync7, readdirSync as readdirSync9, readFileSync as readFileSync20, writeFileSync as writeFileSync8 } from "fs";
17256
17337
  import { createServer } from "net";
17257
- import { dirname as dirname8, isAbsolute as isAbsolute2, join as join26, normalize as normalize2, relative as relative3, sep as sep10 } from "path";
17338
+ import { dirname as dirname8, isAbsolute as isAbsolute2, join as join27, normalize as normalize2, relative as relative3, sep as sep11 } from "path";
17258
17339
  var visualEvidenceEnabled = (env = process.env) => env["LOKI_VISUAL_EVIDENCE"] !== "0";
17259
17340
  var PAGE_RE = /^(?:.*\/)?(?:app|pages|src|public)\/.*\.(?:html|jsx|tsx|vue|svelte)$/;
17260
17341
  var isPageFile = (p) => PAGE_RE.test(p);
@@ -17269,7 +17350,7 @@ function hashScreens(runDir, rels) {
17269
17350
  const out2 = [];
17270
17351
  for (const rel of rels) {
17271
17352
  try {
17272
- out2.push({ path: rel, sha256: sha256File(join26(runDir, rel)) });
17353
+ out2.push({ path: rel, sha256: sha256File(join27(runDir, rel)) });
17273
17354
  } catch {}
17274
17355
  }
17275
17356
  return out2;
@@ -17282,10 +17363,10 @@ function checkScreens(runDir, screens) {
17282
17363
  return "evidence_screens entry is malformed";
17283
17364
  if (isAbsolute2(s.path) || normalize2(s.path).startsWith(".."))
17284
17365
  return `evidence screenshot path escapes the evidence dir: ${s.path}`;
17285
- const file = join26(runDir, s.path);
17366
+ const file = join27(runDir, s.path);
17286
17367
  let cur = runDir;
17287
- for (const seg of normalize2(s.path).split(sep10)) {
17288
- cur = join26(cur, seg);
17368
+ for (const seg of normalize2(s.path).split(sep11)) {
17369
+ cur = join27(cur, seg);
17289
17370
  if (isSymlink(cur))
17290
17371
  return `evidence screenshot path is a symlink: ${s.path}`;
17291
17372
  }
@@ -17331,12 +17412,12 @@ async function waitUp(url, ms, signal) {
17331
17412
  return false;
17332
17413
  }
17333
17414
  var playwrightBin = (repoDir) => {
17334
- const bin = join26(repoDir, "node_modules", ".bin", "playwright");
17415
+ const bin = join27(repoDir, "node_modules", ".bin", "playwright");
17335
17416
  return existsSync15(bin) ? bin : null;
17336
17417
  };
17337
17418
  function openapiPaths(repoDir) {
17338
17419
  for (const f of ["openapi.json", "openapi.yaml", "openapi.yml", "swagger.json"]) {
17339
- const p = join26(repoDir, f);
17420
+ const p = join27(repoDir, f);
17340
17421
  if (!existsSync15(p))
17341
17422
  continue;
17342
17423
  try {
@@ -17350,8 +17431,8 @@ function openapiPaths(repoDir) {
17350
17431
  return [];
17351
17432
  }
17352
17433
  var playwrightTestPkg = (repoDir) => {
17353
- const d = join26(repoDir, "node_modules", "@playwright", "test");
17354
- return existsSync15(join26(d, "package.json")) ? d : null;
17434
+ const d = join27(repoDir, "node_modules", "@playwright", "test");
17435
+ return existsSync15(join27(d, "package.json")) ? d : null;
17355
17436
  };
17356
17437
  var e2eSpecSource = (pkgDir, base, routes) => `const { test } = require(${JSON.stringify(pkgDir)});
17357
17438
  test("loki e2e walkthrough", async ({ page }) => {
@@ -17363,24 +17444,24 @@ async function recordE2eMedia(repoDir, runDir, relDir, base, routes, ms, signal)
17363
17444
  if (!pw || !pkg)
17364
17445
  return { rels: [], skipped: "playwright e2e video and trace skipped: @playwright/test is not installed in the repo" };
17365
17446
  try {
17366
- const dir = join26(runDir, relDir, "e2e");
17447
+ const dir = join27(runDir, relDir, "e2e");
17367
17448
  mkdirSync7(dir, { recursive: true });
17368
- writeFileSync8(join26(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
17369
- writeFileSync8(join26(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
17449
+ writeFileSync8(join27(dir, "walk.spec.cjs"), e2eSpecSource(pkg, base, routes));
17450
+ writeFileSync8(join27(dir, "playwright.config.cjs"), `module.exports = { testDir: ".", testMatch: "walk.spec.cjs", outputDir: "./out", reporter: "null", use: { video: "on", trace: "on" } };
17370
17451
  `);
17371
- if (!await shoot(pw, ["test", "--config", join26(dir, "playwright.config.cjs")], repoDir, ms, signal))
17452
+ if (!await shoot(pw, ["test", "--config", join27(dir, "playwright.config.cjs")], repoDir, ms, signal))
17372
17453
  return { rels: [], skipped: "playwright e2e video and trace skipped: the run failed or timed out" };
17373
17454
  const rels = [];
17374
17455
  const walk = (d) => {
17375
17456
  for (const e of readdirSync9(d, { withFileTypes: true })) {
17376
- const full = join26(d, e.name);
17457
+ const full = join27(d, e.name);
17377
17458
  if (e.isDirectory())
17378
17459
  walk(full);
17379
17460
  else if (e.isFile() && /\.(webm|zip)$/.test(e.name))
17380
- rels.push(join26(relDir, "e2e", relative3(dir, full)));
17461
+ rels.push(join27(relDir, "e2e", relative3(dir, full)));
17381
17462
  }
17382
17463
  };
17383
- walk(join26(dir, "out"));
17464
+ walk(join27(dir, "out"));
17384
17465
  return rels.length > 0 ? { rels, skipped: null } : { rels, skipped: "playwright e2e video and trace skipped: no video or trace was produced" };
17385
17466
  } catch (e) {
17386
17467
  return { rels: [], skipped: `playwright e2e video and trace skipped: ${String(e?.message ?? e).slice(0, 120)}` };
@@ -17474,8 +17555,8 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
17474
17555
  if (!visualEvidenceEnabled(opts.env))
17475
17556
  return skip("LOKI_VISUAL_EVIDENCE is 0");
17476
17557
  const api = loadProjectApi(repoDir), boot = isMultiRoot(api) ? api.uiBoot() : null;
17477
- const appDir = boot ? join26(repoDir, boot.boot.cwd) : repoDir;
17478
- const pkgPath = join26(appDir, "package.json");
17558
+ const appDir = boot ? join27(repoDir, boot.boot.cwd) : repoDir;
17559
+ const pkgPath = join27(appDir, "package.json");
17479
17560
  let script = null;
17480
17561
  if (!boot) {
17481
17562
  if (!existsSync15(pkgPath))
@@ -17507,20 +17588,20 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
17507
17588
  }
17508
17589
  if (!await waitUp(base, left(), signal))
17509
17590
  return skip(aborted() ? "aborted" : `${script} server did not answer within ${Math.round(budget / 1000)}s`);
17510
- const evRoot = join26(runDir, "evidence");
17591
+ const evRoot = join27(runDir, "evidence");
17511
17592
  if (isSymlink(evRoot))
17512
17593
  return skip("evidence dir is a symlink");
17513
17594
  mkdirSync7(evRoot, { recursive: true });
17514
17595
  if (pages.length > 0) {
17515
- const rel0 = join26("evidence", randomBytes2(6).toString("hex"));
17516
- mkdirSync7(join26(runDir, rel0));
17596
+ const rel0 = join27("evidence", randomBytes2(6).toString("hex"));
17597
+ mkdirSync7(join27(runDir, rel0));
17517
17598
  const rels = [];
17518
17599
  for (const route of [...new Set(pages.map(routeFor))].slice(0, opts.maxRoutes ?? MAX_ROUTES)) {
17519
17600
  if (aborted() || left() <= 0)
17520
17601
  break;
17521
- const rel = join26(rel0, `${screenName(route)}.png`);
17522
- const ok = await shoot(pw, ["screenshot", `${base}${route}`, join26(runDir, rel)], appDir, left(), signal);
17523
- if (ok && !aborted() && !isSymlink(join26(runDir, rel)) && existsSync15(join26(runDir, rel)))
17602
+ const rel = join27(rel0, `${screenName(route)}.png`);
17603
+ const ok = await shoot(pw, ["screenshot", `${base}${route}`, join27(runDir, rel)], appDir, left(), signal);
17604
+ if (ok && !aborted() && !isSymlink(join27(runDir, rel)) && existsSync15(join27(runDir, rel)))
17524
17605
  rels.push(rel);
17525
17606
  }
17526
17607
  if (aborted())
@@ -17545,9 +17626,9 @@ async function captureVisualEvidence(repoDir, runDir, changed, opts = {}) {
17545
17626
  }
17546
17627
  if (aborted())
17547
17628
  return skip("aborted");
17548
- const hdir = join26(evRoot, randomBytes2(6).toString("hex"));
17629
+ const hdir = join27(evRoot, randomBytes2(6).toString("hex"));
17549
17630
  mkdirSync7(hdir);
17550
- writeFileSync8(join26(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
17631
+ writeFileSync8(join27(hdir, "http.json"), JSON.stringify(rows, null, 2) + `
17551
17632
  `);
17552
17633
  return { screens: [], http: true, skipped: null };
17553
17634
  } catch (e) {
@@ -17575,7 +17656,7 @@ function receiptScreensProblem(receiptPath, receipt) {
17575
17656
 
17576
17657
  // ../../loki-ts/src/features/contract.ts
17577
17658
  import { existsSync as existsSync16, lstatSync as lstatSync7, mkdirSync as mkdirSync8, readFileSync as readFileSync21, writeFileSync as writeFileSync9 } from "fs";
17578
- import { dirname as dirname9, join as join27 } from "path";
17659
+ import { dirname as dirname9, join as join28 } from "path";
17579
17660
  import { createHash as createHash7 } from "crypto";
17580
17661
  var MAX_CRITERIA = 50;
17581
17662
  var MAX_TEXT = 500;
@@ -17610,7 +17691,7 @@ function untracedLines(trace) {
17610
17691
  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)}`);
17611
17692
  }
17612
17693
  function contractPath(repoDir) {
17613
- return join27(repoDir, ".loki", "contract.json");
17694
+ return join28(repoDir, ".loki", "contract.json");
17614
17695
  }
17615
17696
  var MAX_CONTRACT_BYTES = 1024 * 1024;
17616
17697
  function readContract(repoDir) {
@@ -17692,14 +17773,14 @@ function sealContract(repoDir, body, rawDiff, checks, env = process.env, snap) {
17692
17773
  // ../../loki-ts/src/features/speed/seal_group.ts
17693
17774
  import { createHash as createHash8 } from "crypto";
17694
17775
  import { existsSync as existsSync17, readdirSync as readdirSync10, readFileSync as readFileSync22, statSync as statSync11 } from "fs";
17695
- import { dirname as dirname10, join as join28 } from "path";
17776
+ import { dirname as dirname10, join as join29 } from "path";
17696
17777
  var ID_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
17697
17778
  var PASSING = new Set(["VERIFIED", "ALREADY_SATISFIED"]);
17698
17779
  var sha2 = (b) => createHash8("sha256").update(b).digest("hex");
17699
17780
  var isObj9 = (v) => v !== null && typeof v === "object" && !Array.isArray(v);
17700
17781
  var text2 = (v, cap) => typeof v === "string" ? v.replace(/[\x00-\x1f\x7f]+/g, " ").trim().slice(0, cap) : "";
17701
17782
  var num2 = (v) => typeof v === "number" && Number.isFinite(v) && v >= 0 ? v : 0;
17702
- var unitsDir = (runDir) => join28(runDir, "group", "units");
17783
+ var unitsDir = (runDir) => join29(runDir, "group", "units");
17703
17784
  var readJson3 = (p) => {
17704
17785
  try {
17705
17786
  return JSON.parse(readFileSync22(p, "utf8"));
@@ -17715,7 +17796,7 @@ var dirNames = (d) => {
17715
17796
  }
17716
17797
  };
17717
17798
  function sealGroup(runDir, rh) {
17718
- const manifestPath = join28(runDir, "group", "manifest.json");
17799
+ const manifestPath = join29(runDir, "group", "manifest.json");
17719
17800
  if (!existsSync17(manifestPath))
17720
17801
  return { section: undefined, notProven: [], problems: 0, allUnitsPass: true };
17721
17802
  const notProven = [];
@@ -17740,7 +17821,7 @@ function sealGroup(runDir, rh) {
17740
17821
  return fail(`unit ${index2} has an invalid, duplicate or case-colliding id`);
17741
17822
  seen.add(id);
17742
17823
  seenLower.add(id.toLowerCase());
17743
- const dir = join28(unitsDir(runDir), id), rp = join28(dir, "receipt.json"), ep = join28(dir, "events.jsonl");
17824
+ const dir = join29(unitsDir(runDir), id), rp = join29(dir, "receipt.json"), ep = join29(dir, "events.jsonl");
17744
17825
  let bytes;
17745
17826
  try {
17746
17827
  bytes = readFileSync22(rp);
@@ -17785,7 +17866,7 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
17785
17866
  const bad = (reason) => ({ verdict: "TAMPERED", reason: `group: ${reason}` });
17786
17867
  const g = receipt["group"];
17787
17868
  if (g === undefined)
17788
- return existsSync17(join28(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
17869
+ return existsSync17(join29(runDir, "group", "manifest.json")) ? bad("group directory present but the receipt has no group section") : null;
17789
17870
  if (!isObj9(g) || !ID_RE.test(String(g["group_id"] ?? "")) || !Array.isArray(g["units"]) || g["units"].length === 0)
17790
17871
  return bad("group section malformed");
17791
17872
  const entries = g["units"];
@@ -17797,7 +17878,7 @@ async function verifyGroup(receiptPath, receipt, rh, verifyOne, deps = {}) {
17797
17878
  return bad("unit directories do not match the receipt (missing or extra unit)");
17798
17879
  let unchecked = null;
17799
17880
  for (let i = 0;i < entries.length; i++) {
17800
- const e = entries[i], id = ids[i], dir = join28(unitsDir(runDir), id), rp = join28(dir, "receipt.json"), ep = join28(dir, "events.jsonl");
17881
+ const e = entries[i], id = ids[i], dir = join29(unitsDir(runDir), id), rp = join29(dir, "receipt.json"), ep = join29(dir, "events.jsonl");
17801
17882
  if (e["index"] !== i)
17802
17883
  return bad(`unit ${id} is out of order (index ${String(e["index"])} at position ${i})`);
17803
17884
  let bytes;
@@ -17865,7 +17946,7 @@ function loadSigningKey(generate = true) {
17865
17946
  let pem = inline ?? "";
17866
17947
  if (!inline) {
17867
17948
  const given = process.env["LOKI_RECEIPT_SIGNING_KEY_FILE"]?.trim();
17868
- const file = given || join29(process.env["HOME"] || homedir6(), ".loki", "keys", RECEIPT_SIGNER_BASENAME);
17949
+ const file = given || join30(process.env["HOME"] || homedir6(), ".loki", "keys", RECEIPT_SIGNER_BASENAME);
17869
17950
  try {
17870
17951
  pem = readFileSync23(file);
17871
17952
  if (!given) {
@@ -18014,8 +18095,8 @@ var sealStage = {
18014
18095
  notProven.add(`wall base run not_run: ${wallNotRun}`);
18015
18096
  if (wallNotRun > 0) {
18016
18097
  try {
18017
- const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename9(String(f.path))));
18018
- for (const n2 of readdirSync11(join29(ctx.runDir, "wall")).sort())
18098
+ const kept = new Set((Array.isArray(o.wall?.files) ? o.wall.files : []).map((f) => basename10(String(f.path))));
18099
+ for (const n2 of readdirSync11(join30(ctx.runDir, "wall")).sort())
18019
18100
  if (!kept.has(n2))
18020
18101
  notProven.add(`wall test discarded: ${n2} (not_run)`);
18021
18102
  } catch {}
@@ -18075,7 +18156,7 @@ var sealStage = {
18075
18156
  const cost = ctx.cost.read(ctx.repoDir, iterIds);
18076
18157
  if (cost.unmetered)
18077
18158
  notProven.add("cost unmetered (CLI invoker; recorded as 0)");
18078
- const eventsPath = join29(ctx.runDir, "events.jsonl");
18159
+ const eventsPath = join30(ctx.runDir, "events.jsonl");
18079
18160
  const wallFiles = Array.isArray(o.wall?.files) ? o.wall.files : [];
18080
18161
  const wallPassed = typeof o.verify?.wall_passed === "boolean" ? o.verify.wall_passed : null;
18081
18162
  if (wallFiles.length > 0 && wallPassed === null)
@@ -18126,10 +18207,10 @@ var sealStage = {
18126
18207
  }
18127
18208
  const receipt = { ...body, receipt_sha256: hash, verification: { jwt: sig.jwt, kid: sig.kid } };
18128
18209
  mkdirSync9(ctx.runDir, { recursive: true });
18129
- const path = join29(ctx.runDir, "receipt.json");
18210
+ const path = join30(ctx.runDir, "receipt.json");
18130
18211
  writeFileSync10(path, JSON.stringify(receipt, null, 2) + `
18131
18212
  `);
18132
- writeFileSync10(join29(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
18213
+ writeFileSync10(join30(ctx.runDir, "receipt.md"), renderReceiptMd(receipt));
18133
18214
  const signed = sig.jwt !== null;
18134
18215
  const data = { receipt_path: path, receipt_sha256: hash, signed, kid: sig.kid, verdict, not_proven: receipt.not_proven };
18135
18216
  ctx.emit("receipt.sealed", "seal", { path, receipt_sha256: hash, signed, kid: sig.kid, verdict, not_proven: receipt.not_proven });
@@ -18266,7 +18347,7 @@ function checkEventLog(receiptPath, receipt) {
18266
18347
  const bound = receipt["events_sha256"];
18267
18348
  if (typeof bound !== "string" || bound === createHash10("sha256").digest("hex"))
18268
18349
  return null;
18269
- const path = join30(dirname12(receiptPath), "events.jsonl");
18350
+ const path = join31(dirname12(receiptPath), "events.jsonl");
18270
18351
  if (!existsSync19(path))
18271
18352
  return "events.jsonl is missing";
18272
18353
  const raw2 = readFileSync25(path, "utf8"), events2 = readEvents(path), lines = raw2.split(`
@@ -18285,7 +18366,7 @@ function checkEventLog(receiptPath, receipt) {
18285
18366
  return h.digest("hex") === bound ? null : "events.jsonl does not match the hash recorded at seal";
18286
18367
  }
18287
18368
  function checkLogSeal(receiptPath, hash, kid, given) {
18288
- const path = join30(dirname12(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
18369
+ const path = join31(dirname12(receiptPath), "events.jsonl"), events2 = readEvents(path), done = events2.findIndex((e) => e.type === "run.completed");
18289
18370
  if (!events2.some((e) => e.type === "receipt.sealed" && e.data["receipt_sha256"] === hash))
18290
18371
  return { verdict: "TAMPERED", reason: "events.jsonl has no receipt.sealed event for this receipt" };
18291
18372
  if (done < 0)
@@ -18352,8 +18433,8 @@ async function verifyReceipt(receiptPath, deps = {}) {
18352
18433
  }
18353
18434
 
18354
18435
  // src/server/routes/verify.ts
18355
- var ID4 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
18356
- var safeId2 = (s) => ID4.test(s) && !s.includes("..");
18436
+ var ID5 = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
18437
+ var safeId2 = (s) => ID5.test(s) && !s.includes("..");
18357
18438
  function mount19(ctx) {
18358
18439
  const { act, db } = ctx;
18359
18440
  act.post("/v1/runs/:source/:run/verify", async (c) => {
@@ -18375,15 +18456,15 @@ function mount19(ctx) {
18375
18456
  return done(404, "receipt not available", "not_found");
18376
18457
  let runDir, file;
18377
18458
  try {
18378
- const root = realpathSync13(join31(repo.p, ".loki", "runs"));
18379
- runDir = realpathSync13(join31(root, run2));
18380
- if (runDir !== join31(root, run2))
18459
+ const root = realpathSync14(join32(repo.p, ".loki", "runs"));
18460
+ runDir = realpathSync14(join32(root, run2));
18461
+ if (runDir !== join32(root, run2))
18381
18462
  return done(404, "receipt not found", "not_found");
18382
- file = realpathSync13(join31(runDir, "receipt.json"));
18463
+ file = realpathSync14(join32(runDir, "receipt.json"));
18383
18464
  } catch {
18384
18465
  return done(404, "receipt not found", "not_found");
18385
18466
  }
18386
- if (!file.startsWith(runDir + sep11))
18467
+ if (!file.startsWith(runDir + sep12))
18387
18468
  return done(404, "receipt not found", "not_found");
18388
18469
  let integrity, reasons, sha3 = null, outcome = "UNREADABLE";
18389
18470
  try {
@@ -18435,7 +18516,7 @@ function mount19(ctx) {
18435
18516
  // src/server/routes/index.ts
18436
18517
  var routeModules = [mount, mount18, mount5, mount7, mount17, mount8, mount3, mount9, mount11, mount4, mount10, mount12, mount6, mount16, mount19, mount13, mount15, mount2, mount14];
18437
18518
  function registerRoutes(ctx) {
18438
- mountRepos(ctx.act, ctx.db, ctx.peerIsLoopback);
18519
+ mountRepos(ctx.act, ctx.db, ctx.peerIsLoopback, ctx.repoDir);
18439
18520
  for (const m of routeModules)
18440
18521
  m(ctx);
18441
18522
  }
@@ -18461,7 +18542,7 @@ function ttlCache(ttlMs = PROBE_CACHE_MS, now = Date.now) {
18461
18542
 
18462
18543
  // src/server/legacy/shim.ts
18463
18544
  import { existsSync as existsSync20, readFileSync as readFileSync27 } from "fs";
18464
- import { join as join32 } from "path";
18545
+ import { join as join33 } from "path";
18465
18546
 
18466
18547
  // src/server/legacy/routes.ts
18467
18548
  var LEGACY_ROUTES = [
@@ -18833,7 +18914,7 @@ var logged = new Set;
18833
18914
  var toHono = (p) => p.replace(/\{([A-Za-z_]+):path\}/g, ":$1{.+}").replace(/\{([A-Za-z_]+)\}/g, ":$1");
18834
18915
  var NOT_SUPPORTED = "not yet supported by the Control Plane";
18835
18916
  var repoVersion = () => {
18836
- for (const f of [join32(import.meta.dir, "../../../../../VERSION")]) {
18917
+ for (const f of [join33(import.meta.dir, "../../../../../VERSION")]) {
18837
18918
  try {
18838
18919
  if (existsSync20(f))
18839
18920
  return readFileSync27(f, "utf8").trim();
@@ -19018,7 +19099,7 @@ function legacyShim(opts) {
19018
19099
 
19019
19100
  // src/server/app.ts
19020
19101
  var MAX_BODY2 = 1e6;
19021
- var defaultUiDir = () => [join33(import.meta.dir, "../../ui/dist"), join33(import.meta.dir, "../ui/dist")].find((d) => existsSync21(join33(d, "index.html")));
19102
+ var defaultUiDir = () => [join34(import.meta.dir, "../../ui/dist"), join34(import.meta.dir, "../ui/dist")].find((d) => existsSync21(join34(d, "index.html")));
19022
19103
  function createApp(opts) {
19023
19104
  const uiDir = opts.uiDir ?? defaultUiDir();
19024
19105
  const { db, sqlite } = openDb(opts.dbPath);
@@ -19142,13 +19223,13 @@ function createApp(opts) {
19142
19223
  }
19143
19224
  if (!uiDir || p.startsWith("/v1/"))
19144
19225
  return c.json({ error: "not found" }, 404);
19145
- const root = resolve6(uiDir);
19146
- const f = resolve6(root, `.${p}`);
19147
- if (f.startsWith(root + sep12) && existsSync21(f) && statSync14(f).isFile())
19226
+ const root = resolve7(uiDir);
19227
+ const f = resolve7(root, `.${p}`);
19228
+ if (f.startsWith(root + sep13) && existsSync21(f) && statSync14(f).isFile())
19148
19229
  return new Response(Bun.file(f));
19149
19230
  if (/\.[a-z0-9]+$/i.test(p))
19150
19231
  return c.json({ error: "not found" }, 404);
19151
- return new Response(Bun.file(join33(root, "index.html")));
19232
+ return new Response(Bun.file(join34(root, "index.html")));
19152
19233
  });
19153
19234
  return { app, db, close: () => sqlite.close() };
19154
19235
  }