@shiyuphan/follow-me 0.6.0 → 0.7.1

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 (100) hide show
  1. package/README.md +4 -1
  2. package/dist/src/cli.js +94 -11
  3. package/dist/src/comments.js +6 -1
  4. package/dist/src/coverage.js +397 -0
  5. package/dist/src/git.js +18 -0
  6. package/dist/src/host.js +4 -0
  7. package/dist/src/prompt.js +58 -23
  8. package/dist/src/server.js +50 -8
  9. package/dist/src/session.js +33 -0
  10. package/dist/src/types.js +2 -0
  11. package/dist/ui/dist/assets/{abnfDiagram-WEYOIA3C-fYSYLdMl.js → abnfDiagram-WEYOIA3C-cHEJvcBn.js} +1 -1
  12. package/dist/ui/dist/assets/{arc-DGuGSnwa.js → arc-xolFyc0v.js} +1 -1
  13. package/dist/ui/dist/assets/{architecture-WOLXFQ4H-VFox_hV1.js → architecture-WOLXFQ4H-B3hvvNV2.js} +1 -1
  14. package/dist/ui/dist/assets/{architectureDiagram-ZHVYKT53-CBVK3nHZ.js → architectureDiagram-ZHVYKT53-BNTMbPJW.js} +1 -1
  15. package/dist/ui/dist/assets/{blockDiagram-RJAE7QA3-BFdsIWEr.js → blockDiagram-RJAE7QA3-NYY6qeuY.js} +1 -1
  16. package/dist/ui/dist/assets/{c4Diagram-XDPPPE54-BGntcPId.js → c4Diagram-XDPPPE54-B_bNpXHQ.js} +1 -1
  17. package/dist/ui/dist/assets/channel-DPDY0XJP.js +1 -0
  18. package/dist/ui/dist/assets/{chunk-2E7WHVMD-CNMuK9zj.js → chunk-2E7WHVMD-BTet9STn.js} +1 -1
  19. package/dist/ui/dist/assets/{chunk-4EMNKR2T-ByeTTJWS.js → chunk-4EMNKR2T-qoQt4Fpx.js} +1 -1
  20. package/dist/ui/dist/assets/{chunk-55XCU76K-99xE7cLH.js → chunk-55XCU76K-C3I6EB-H.js} +1 -1
  21. package/dist/ui/dist/assets/{chunk-7S6XSTFO-ZVmT7eMZ.js → chunk-7S6XSTFO-CL-9s_8p.js} +1 -1
  22. package/dist/ui/dist/assets/{chunk-AQDTSKZB-B981JORL.js → chunk-AQDTSKZB-DHoGnGyP.js} +1 -1
  23. package/dist/ui/dist/assets/{chunk-DSNLSHJZ-B2z7FX4h.js → chunk-DSNLSHJZ-Bk8WO5JF.js} +1 -1
  24. package/dist/ui/dist/assets/{chunk-HAGFOTED-CHFbBS-4.js → chunk-HAGFOTED-CwAC85lg.js} +1 -1
  25. package/dist/ui/dist/assets/{chunk-HNE4Q36P-rq11xv9X.js → chunk-HNE4Q36P-CIllywWr.js} +1 -1
  26. package/dist/ui/dist/assets/{chunk-NQOKRVIF-BYmg9kSX.js → chunk-NQOKRVIF-DDlpyYiH.js} +1 -1
  27. package/dist/ui/dist/assets/{chunk-UHW7PFBP-JvL9IXWg.js → chunk-UHW7PFBP-Cxdndcon.js} +1 -1
  28. package/dist/ui/dist/assets/{chunk-VQ5W62QI-CYMQaAKn.js → chunk-VQ5W62QI-CL9d9_iJ.js} +1 -1
  29. package/dist/ui/dist/assets/{chunk-WQQL4CDK-CXnR0PHT.js → chunk-WQQL4CDK-C4kzN8QU.js} +1 -1
  30. package/dist/ui/dist/assets/{chunk-XXDRQBXY-CDUWJCXi.js → chunk-XXDRQBXY-Cv_2FSiY.js} +1 -1
  31. package/dist/ui/dist/assets/{chunk-YZO67HFG-mZfXIx0h.js → chunk-YZO67HFG-oHiuYaCJ.js} +1 -1
  32. package/dist/ui/dist/assets/{chunk-ZAUX2LTX-DBxVTCHX.js → chunk-ZAUX2LTX-Cy_8d0XT.js} +1 -1
  33. package/dist/ui/dist/assets/{chunk-ZCHMQSOR-DrWA4IBo.js → chunk-ZCHMQSOR-piIpIcQi.js} +1 -1
  34. package/dist/ui/dist/assets/{classDiagram-v2-4MYWR3UA-Beah5uxA.js → classDiagram-v2-4MYWR3UA-DNKRIujO.js} +1 -1
  35. package/dist/ui/dist/assets/{cose-bilkent-JH36ORCC-UaE-jnHk.js → cose-bilkent-JH36ORCC-BWKTGCHY.js} +1 -1
  36. package/dist/ui/dist/assets/{cynefin-EF2NZ3EQ-DKfGaCR8.js → cynefin-EF2NZ3EQ-yx7KKkAk.js} +1 -1
  37. package/dist/ui/dist/assets/{cynefinDiagram-WF24UDRP-tTUzTs3D.js → cynefinDiagram-WF24UDRP-BTnZ7QVL.js} +1 -1
  38. package/dist/ui/dist/assets/{dagre-NK4GIZVX-jSn35_T7.js → dagre-NK4GIZVX-CPh5Zn5I.js} +1 -1
  39. package/dist/ui/dist/assets/{diagram-CBK3MWTC-7W2uw8Zc.js → diagram-CBK3MWTC-pI6NFdrD.js} +1 -1
  40. package/dist/ui/dist/assets/{diagram-I5XIIV2D-CcfyQVh9.js → diagram-I5XIIV2D-DUIfARoS.js} +1 -1
  41. package/dist/ui/dist/assets/{diagram-ODIL2UCW-BjGvaLis.js → diagram-ODIL2UCW-lafSPvAw.js} +1 -1
  42. package/dist/ui/dist/assets/{diagram-PFBEJUXE-jvdCrt8B.js → diagram-PFBEJUXE-u1lZas3a.js} +1 -1
  43. package/dist/ui/dist/assets/{diagram-RJA3I4VV-D65_Vpi_.js → diagram-RJA3I4VV-mc0GLMHo.js} +1 -1
  44. package/dist/ui/dist/assets/{diagram-TYUNFSNR-C52roQBE.js → diagram-TYUNFSNR-1NRbBrZW.js} +1 -1
  45. package/dist/ui/dist/assets/{dist-BJd4jp9Y.js → dist-CHZ9mrl_.js} +1 -1
  46. package/dist/ui/dist/assets/{ebnfDiagram-V4P3TTPT-DXysoIBq.js → ebnfDiagram-V4P3TTPT-DdStjTDc.js} +1 -1
  47. package/dist/ui/dist/assets/{elk-QONTBCTQ-BVZcsgV3.js → elk-QONTBCTQ-BzRoFO45.js} +1 -1
  48. package/dist/ui/dist/assets/{erDiagram-KYQIGQAA-BJnT4fVU.js → erDiagram-KYQIGQAA-DlMkgQxj.js} +1 -1
  49. package/dist/ui/dist/assets/{eventmodeling-K75KTNOO-C5MzxCMY.js → eventmodeling-K75KTNOO-BRYIOrod.js} +1 -1
  50. package/dist/ui/dist/assets/flowDiagram-IUGLLWBU-C1IBh_GZ.js +1 -0
  51. package/dist/ui/dist/assets/{ganttDiagram-R7GPNTJY-CZRrnuah.js → ganttDiagram-R7GPNTJY-D8fQZ7Ah.js} +1 -1
  52. package/dist/ui/dist/assets/{gitGraph-VSP46ZUC-l58aGSkh.js → gitGraph-VSP46ZUC-C7ZydyWX.js} +1 -1
  53. package/dist/ui/dist/assets/{gitGraphDiagram-PDYL7XHY-D4ks1WO-.js → gitGraphDiagram-PDYL7XHY-DCItam0v.js} +1 -1
  54. package/dist/ui/dist/assets/index-8BehwQ7E.js +134 -0
  55. package/dist/ui/dist/assets/index-mC2OW2Av.css +1 -0
  56. package/dist/ui/dist/assets/{info-OHQRW6UA-BSqfzkdk.js → info-OHQRW6UA-C3KneBKT.js} +1 -1
  57. package/dist/ui/dist/assets/{infoDiagram-MVDRKAX5-B6NgVF_N.js → infoDiagram-MVDRKAX5-6wK09D32.js} +1 -1
  58. package/dist/ui/dist/assets/{ishikawaDiagram-HPEHV2GE-DvtfssEZ.js → ishikawaDiagram-HPEHV2GE-DTP5C8VX.js} +1 -1
  59. package/dist/ui/dist/assets/{journeyDiagram-BOSHW7O7-DM64gT5v.js → journeyDiagram-BOSHW7O7-B--UIMtq.js} +1 -1
  60. package/dist/ui/dist/assets/{kanban-definition-FNSA4HC5-AliyRJHy.js → kanban-definition-FNSA4HC5-Ku4N9QGt.js} +1 -1
  61. package/dist/ui/dist/assets/{line-CHncXbKO.js → line-C4-H5h1-.js} +1 -1
  62. package/dist/ui/dist/assets/{linear-BWEWydI0.js → linear-DhAID3hm.js} +1 -1
  63. package/dist/ui/dist/assets/{mermaid-parser.core-DGpOP8AM.js → mermaid-parser.core-CMPNc-u6.js} +3 -3
  64. package/dist/ui/dist/assets/{mermaid.core-BJtBFbJx.js → mermaid.core-Nd_xOg2y.js} +4 -4
  65. package/dist/ui/dist/assets/{mindmap-definition-6OY57UG3-NjavnWBi.js → mindmap-definition-6OY57UG3-BlVsym5h.js} +1 -1
  66. package/dist/ui/dist/assets/{packet-JDAUHWVQ-zuhpVsME.js → packet-JDAUHWVQ-rsk7SM7S.js} +1 -1
  67. package/dist/ui/dist/assets/{pegDiagram-ECIUJNBX-sL4grM97.js → pegDiagram-ECIUJNBX-C0L20M8z.js} +1 -1
  68. package/dist/ui/dist/assets/{pie-XZMESJXO-C9l1Mp09.js → pie-XZMESJXO-B23-iZSN.js} +1 -1
  69. package/dist/ui/dist/assets/{pieDiagram-GNMPY74T-rlRBr2U4.js → pieDiagram-GNMPY74T-BqFhe4Oh.js} +1 -1
  70. package/dist/ui/dist/assets/{prism-core-DmuST30i.js → prism-core-DYsiqJeR.js} +1 -1
  71. package/dist/ui/dist/assets/{quadrantDiagram-D57K4MC3-4oQMip2Q.js → quadrantDiagram-D57K4MC3-BKP75B-m.js} +1 -1
  72. package/dist/ui/dist/assets/{radar-ABXABTNO-DvGg96L7.js → radar-ABXABTNO-BrEk2mQ7.js} +1 -1
  73. package/dist/ui/dist/assets/{railroad-I3PHUGI6-8wdFKMZp.js → railroad-I3PHUGI6-wWO4Eapc.js} +1 -1
  74. package/dist/ui/dist/assets/{railroad-abnf-LNEFI6M7-DUtOO0gn.js → railroad-abnf-LNEFI6M7-DfY-IPvE.js} +1 -1
  75. package/dist/ui/dist/assets/{railroad-ebnf-DWYD2UWJ-5YCGY1_d.js → railroad-ebnf-DWYD2UWJ-19wedWGk.js} +1 -1
  76. package/dist/ui/dist/assets/{railroad-peg-JR7BVNR7-Bwywxjhs.js → railroad-peg-JR7BVNR7-9vIslnoJ.js} +1 -1
  77. package/dist/ui/dist/assets/{railroadDiagram-Y72NRBL7-CwO6HSNQ.js → railroadDiagram-Y72NRBL7-DVnmXs8w.js} +1 -1
  78. package/dist/ui/dist/assets/{requirementDiagram-EQYSW5RA-Cp0IbfNr.js → requirementDiagram-EQYSW5RA-BEoMdlzR.js} +1 -1
  79. package/dist/ui/dist/assets/{sankeyDiagram-SY24JHO5-DeQKsO68.js → sankeyDiagram-SY24JHO5-D7Tn2Gbs.js} +1 -1
  80. package/dist/ui/dist/assets/{sequenceDiagram-BLEHNHQU-DTDalCxF.js → sequenceDiagram-BLEHNHQU-CyjUDBaQ.js} +1 -1
  81. package/dist/ui/dist/assets/{src-XnrqevnL.js → src-BiC9XNcI.js} +1 -1
  82. package/dist/ui/dist/assets/{stateDiagram-v2-A6IESKWZ-2DZ-tKo9.js → stateDiagram-v2-A6IESKWZ-CMp1VCO9.js} +1 -1
  83. package/dist/ui/dist/assets/{swimlanes-B3ENRKFQ-66yZJeRU.js → swimlanes-B3ENRKFQ-KEciLd6r.js} +1 -1
  84. package/dist/ui/dist/assets/swimlanesDiagram-AYQRV4AK-DzestpDE.js +8 -0
  85. package/dist/ui/dist/assets/{timeline-definition-JXYKGLGB-Dm1xGU-d.js → timeline-definition-JXYKGLGB-C8YQtv7M.js} +1 -1
  86. package/dist/ui/dist/assets/{treeView-D4JQ5SDB-BvgsbSot.js → treeView-D4JQ5SDB-DgAzPaOO.js} +1 -1
  87. package/dist/ui/dist/assets/{treemap-SAJKECNS-C3lnbG1a.js → treemap-SAJKECNS-eCRqZMYc.js} +1 -1
  88. package/dist/ui/dist/assets/{usecaseDiagram-WPOLBNNX-B6iPNIhZ.js → usecaseDiagram-WPOLBNNX-Dirryw9G.js} +1 -1
  89. package/dist/ui/dist/assets/{vennDiagram-Q3Y3IDCW-D5dgflg9.js → vennDiagram-Q3Y3IDCW-BjxQbAUx.js} +1 -1
  90. package/dist/ui/dist/assets/{wardley-7MLQ67FV-Dn9mLIB4.js → wardley-7MLQ67FV-CqHX5RUz.js} +1 -1
  91. package/dist/ui/dist/assets/{wardleyDiagram-IVAIDKWA-W1EwzN_X.js → wardleyDiagram-IVAIDKWA-Ds1HoEUY.js} +1 -1
  92. package/dist/ui/dist/assets/{xychartDiagram-4URNHDU4-CKRzMUvp.js → xychartDiagram-4URNHDU4-kodzDb12.js} +1 -1
  93. package/dist/ui/dist/index.html +2 -2
  94. package/package.json +1 -1
  95. package/skills/follow-me/SKILL.md +2 -0
  96. package/dist/ui/dist/assets/channel-gz6cS9Z1.js +0 -1
  97. package/dist/ui/dist/assets/flowDiagram-IUGLLWBU-BqUgZSCz.js +0 -1
  98. package/dist/ui/dist/assets/index-BW95UA5q.css +0 -1
  99. package/dist/ui/dist/assets/index-DOGXgoHF.js +0 -134
  100. package/dist/ui/dist/assets/swimlanesDiagram-AYQRV4AK-rbX6bYG4.js +0 -8
@@ -1,3 +1,4 @@
1
+ import { changedLines } from "./coverage.js";
1
2
  import { tipStartOf } from "./diff.js";
2
3
  import { anchorOn, concernOn } from "./evolve.js";
3
4
  /** Consecutive runs collapse: [0,1,2,3,7] becomes "0-3,7". */
@@ -581,14 +582,14 @@ function itemHeading(item, level) {
581
582
  parts.push(kept === null ? "raised by the reviewer" : "raised by the agent, kept by the reviewer");
582
583
  return `${"#".repeat(level)} ${parts.join(" · ")}`;
583
584
  }
584
- function renderItems(items, units, level) {
585
+ function renderItems(items, units, level, tallies) {
585
586
  const out = [];
586
587
  const sorted = sortItems(items, units);
587
588
  const paths = [...new Set(sorted.flatMap((i) => (i.where.path === null ? [] : [i.where.path])))];
588
- const group = (title, members) => {
589
+ const group = (title, members, lead = []) => {
589
590
  if (members.length === 0)
590
591
  return;
591
- out.push(`${"#".repeat(level)} ${title}`, "");
592
+ out.push(`${"#".repeat(level)} ${title}`, "", ...lead);
592
593
  for (const item of members) {
593
594
  out.push(itemHeading(item, level + 1), "", ...quoteBlock(item.where.quote));
594
595
  if (item.where.quote.length > 0)
@@ -596,8 +597,12 @@ function renderItems(items, units, level) {
596
597
  out.push(...voices(item), "");
597
598
  }
598
599
  };
599
- for (const path of paths)
600
- group(path, sorted.filter((i) => i.where.path === path));
600
+ for (const path of paths) {
601
+ const tally = tallies.get(path);
602
+ group(path, sorted.filter((i) => i.where.path === path), tally === undefined
603
+ ? []
604
+ : [`coverage: ${tally.covered} of ${tally.executable} changed lines`, ""]);
605
+ }
601
606
  group("General", sorted.filter((i) => i.where.path === null));
602
607
  return out;
603
608
  }
@@ -719,24 +724,43 @@ function spanOf(rows) {
719
724
  startOldLine: range && first.op !== "+" ? first.base : null,
720
725
  };
721
726
  }
722
- function commentSpan(ctx, c) {
727
+ function commentRows(ctx, c) {
723
728
  const { anchor } = c;
724
729
  if (anchor.kind !== "hunk")
725
- return NO_SPAN;
730
+ return null;
726
731
  const hunk = ctx.units.get(anchor.unit);
727
732
  if (hunk?.kind !== "hunk")
728
- return NO_SPAN;
733
+ return null;
729
734
  const { offsets, changes } = anchor;
730
- if (offsets !== undefined)
731
- return spanOf(numberedRows(hunk, ctx.units, (i) => offsets.includes(i)));
732
- return spanOf(numberedRows(hunk, ctx.units, (_, n) => n !== null && (changes === null || changes.includes(n))));
735
+ const want = offsets !== undefined
736
+ ? (i) => offsets.includes(i)
737
+ : (_, n) => n !== null && (changes === null || changes.includes(n));
738
+ return { path: hunk.path, rows: numberedRows(hunk, ctx.units, want) };
733
739
  }
734
- function concernSpan(ctx, concern) {
740
+ function concernRows(ctx, concern) {
735
741
  const hunk = concern.unit === undefined ? undefined : ctx.units.get(concern.unit);
736
742
  if (hunk?.kind !== "hunk")
737
- return NO_SPAN;
743
+ return null;
738
744
  const lines = concern.lines;
739
- return spanOf(numberedRows(hunk, ctx.units, (_, n) => n !== null && (lines === undefined || lines.includes(n))));
745
+ const want = (_, n) => n !== null && (lines === undefined || lines.includes(n));
746
+ return { path: hunk.path, rows: numberedRows(hunk, ctx.units, want) };
747
+ }
748
+ function spanAt(at) {
749
+ return at === null ? NO_SPAN : spanOf(at.rows);
750
+ }
751
+ /**
752
+ * Whether the test run ran every executable added row the item points at. Absent without a run
753
+ * that still fits the file, when it picks no such row, or when its code changed after it was said.
754
+ */
755
+ function coveredOf(ctx, id, at) {
756
+ const file = at === null ? undefined : ctx.coverage?.get(at.path);
757
+ if (at === null || file === undefined || ctx.marks?.has(id))
758
+ return {};
759
+ const hits = at.rows.flatMap((r) => {
760
+ const n = r.op === "+" ? file.lines.get(r.tip) : undefined;
761
+ return n === undefined ? [] : [n];
762
+ });
763
+ return hits.length === 0 ? {} : { covered: hits.every((n) => n > 0) };
740
764
  }
741
765
  function threadOf(c) {
742
766
  return (c.replies ?? []).map((r) => ({ author: r.author, body: r.body }));
@@ -761,6 +785,7 @@ function collectItems(review, ctx, responses) {
761
785
  const { kept } = it;
762
786
  const first = it.comments[0];
763
787
  if (kept !== null) {
788
+ const at = concernRows(ctx, kept.concern);
764
789
  const note = kept.note === null ? "" : `\n\nReviewer: ${kept.note}`;
765
790
  const thread = it.comments.flatMap((c) => [
766
791
  { author: "reviewer", body: c.body },
@@ -770,7 +795,7 @@ function collectItems(review, ctx, responses) {
770
795
  where: it.where,
771
796
  item: {
772
797
  id: kept.concern.id,
773
- ...concernSpan(ctx, kept.concern),
798
+ ...spanAt(at),
774
799
  path: it.where.path,
775
800
  oldPath: it.where.path,
776
801
  severity: it.severity,
@@ -780,16 +805,18 @@ function collectItems(review, ctx, responses) {
780
805
  resolved: false,
781
806
  excluded: noConcerns.has(kept.concern.id),
782
807
  ...changedOf(ctx, kept.concern.id),
808
+ ...coveredOf(ctx, kept.concern.id, at),
783
809
  },
784
810
  };
785
811
  }
786
812
  if (first === undefined)
787
813
  throw new Error("an item with neither a concern nor a comment");
814
+ const at = commentRows(ctx, first);
788
815
  return {
789
816
  where: it.where,
790
817
  item: {
791
818
  id: first.id,
792
- ...commentSpan(ctx, first),
819
+ ...spanAt(at),
793
820
  path: it.where.path,
794
821
  oldPath: it.where.path,
795
822
  severity: it.severity,
@@ -799,6 +826,7 @@ function collectItems(review, ctx, responses) {
799
826
  resolved: resolved.has(first.id),
800
827
  excluded: noComments.has(first.id),
801
828
  ...changedOf(ctx, first.id),
829
+ ...coveredOf(ctx, first.id, at),
802
830
  },
803
831
  };
804
832
  });
@@ -812,7 +840,7 @@ function collectItems(review, ctx, responses) {
812
840
  where,
813
841
  item: {
814
842
  id: q.id,
815
- ...commentSpan(ctx, q),
843
+ ...spanAt(commentRows(ctx, q)),
816
844
  path: where.path,
817
845
  oldPath: where.path,
818
846
  severity: q.severity ?? null,
@@ -832,7 +860,7 @@ function collectItems(review, ctx, responses) {
832
860
  * Excluded ones are present and marked; whoever posts them skips those.
833
861
  */
834
862
  export function reportItems(review, commits, units, opts) {
835
- const session = folded(review, commits, units, opts.earlier);
863
+ const session = folded(review, commits, units, opts);
836
864
  return collectItems(session.review, session.ctx, opts.responses).map((c) => c.item);
837
865
  }
838
866
  /** A short list of what the reviewer left out, so nothing vanishes without a trace. */
@@ -855,9 +883,11 @@ function renderExcluded(collected) {
855
883
  * taking their unit, and a mark on each whose code changed. Each id appears once; this
856
884
  * version's own copy wins.
857
885
  */
858
- function folded(review, commits, units, earlier) {
886
+ function folded(review, commits, units, opts) {
887
+ const { earlier } = opts;
888
+ const coverage = opts.coverage === undefined ? {} : { coverage: opts.coverage };
859
889
  if (earlier === undefined)
860
- return { review, ctx: { commits, units } };
890
+ return { review, ctx: { commits, units, ...coverage } };
861
891
  const marks = new Map();
862
892
  const mark = (id, at) => {
863
893
  if (at.since !== null)
@@ -895,6 +925,7 @@ function folded(review, commits, units, earlier) {
895
925
  ctx: {
896
926
  units,
897
927
  marks,
928
+ ...coverage,
898
929
  commits: commits.map((commit, k) => {
899
930
  const mine = lost.filter((c) => owner(c.unit, c.commit) === k);
900
931
  if (mine.length === 0)
@@ -915,7 +946,7 @@ function folded(review, commits, units, earlier) {
915
946
  * Concerns the reviewer has not decided are left out, as are those dismissed.
916
947
  */
917
948
  export function renderReport(full, commits, units, opts) {
918
- const session = folded(full, commits, units, opts.earlier);
949
+ const session = folded(full, commits, units, opts);
919
950
  const { ctx } = session;
920
951
  const excluded = session.review.excluded;
921
952
  if (excluded === undefined)
@@ -942,12 +973,14 @@ function renderIncluded(review, ctx, opts) {
942
973
  const issues = walk ? rest : rest.filter((c) => c.severity !== undefined);
943
974
  const feedback = walk ? [] : rest.filter((c) => c.severity === undefined);
944
975
  const items = buildItems(ctx, keptConcerns(review, commits), issues);
976
+ // Keyed by path as the items name it, so a file's heading finds its count.
977
+ const tallies = new Map(ctx.coverage === undefined ? [] : changedLines(units, ctx.coverage));
945
978
  const out = [];
946
979
  if (walk) {
947
980
  out.push(`# Code review: ${opts.branch} (${commits.length === 1 ? "1 commit" : `${commits.length} commits`}, ${summarizeIssues(items)})`, "");
948
981
  if (items.length === 0 && questions.length === 0)
949
982
  out.push("The reviewer raised no issues.", "");
950
- out.push(...renderItems(items, units, 2));
983
+ out.push(...renderItems(items, units, 2, tallies));
951
984
  }
952
985
  else {
953
986
  out.push(`# Review of plan v${review.planVersion}`, "");
@@ -960,7 +993,7 @@ function renderIncluded(review, ctx, opts) {
960
993
  }
961
994
  out.push(...renderPlanFeedback(ctx, feedback));
962
995
  if (items.length > 0) {
963
- out.push(`## Code issues (${summarizeIssues(items)})`, "", ...renderItems(items, units, 3));
996
+ out.push(`## Code issues (${summarizeIssues(items)})`, "", ...renderItems(items, units, 3, tallies));
964
997
  }
965
998
  }
966
999
  if (questions.length > 0)
@@ -1016,6 +1049,8 @@ function renderEvent(event, ctx) {
1016
1049
  return [`- ${event.commentId} ${event.resolved ? "resolved" : "reopened"}`];
1017
1050
  case "version":
1018
1051
  return [`- plan v${event.version} is open`];
1052
+ case "coverage":
1053
+ return [`- the page shows coverage from ${event.tip.slice(0, 12)}`];
1019
1054
  case "submitted":
1020
1055
  return ["- the reviewer submitted the review"];
1021
1056
  case "ended":
@@ -5,12 +5,13 @@ import { homedir } from "node:os";
5
5
  import { basename, isAbsolute, join } from "node:path";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { isReplyId, parseComment, parseDraft, parseNewDecision, parseNewReply, } from "./comments.js";
8
+ import { serializeCoverage, staleFiles } from "./coverage.js";
8
9
  import { definitionIndex, isIdentifier } from "./definition.js";
9
10
  import { isRepoPath } from "./diff.js";
10
11
  import { carryConcerns, carrySession } from "./evolve.js";
11
12
  import { isConcernId, isPlanVersion } from "./plan.js";
12
13
  import { renderReport, reportItems } from "./prompt.js";
13
- import { isLockToken } from "./session.js";
14
+ import { coverageAt, isLockToken, readCoverageIn, SessionFileError } from "./session.js";
14
15
  /** The requested port is taken; host.ts decides whether that is our server or a stranger. */
15
16
  export class PortInUseError extends Error {
16
17
  name = "PortInUseError";
@@ -471,25 +472,44 @@ function hostSession(id, registration, loaded, draft, load) {
471
472
  ...carriedRefs(view),
472
473
  };
473
474
  };
474
- const reportOptions = () => {
475
+ const reportOptions = async () => {
475
476
  const comments = sessionOf(view);
477
+ const { repo, state } = view.loaded;
478
+ const coverage = await coverageAt(repo, view.registration.dir, state.anchor.tip);
476
479
  return {
477
- branch: view.loaded.state.anchor.branch,
480
+ branch: state.anchor.branch,
478
481
  responses: [],
479
482
  ...(comments === null ? {} : { earlier: { comments, concerns: view.earlierConcerns } }),
483
+ ...(coverage === null ? {} : { coverage }),
480
484
  };
481
485
  };
482
486
  const unitsOf = () => new Map(view.loaded.state.units.map((u) => [u.id, u]));
483
- const report = (finished) => renderReport(finished, view.loaded.state.commits, unitsOf(), reportOptions());
487
+ const report = async (finished) => renderReport(finished, view.loaded.state.commits, unitsOf(), await reportOptions());
484
488
  /** Writes reviews/vN.json and its report once, and removes the autosave. */
485
489
  const writeReview = async (finished) => {
486
490
  await writes;
487
491
  await mkdir(view.loaded.reviewsDir, { recursive: true });
488
492
  await writeAtomic(view.reviewFile, `${JSON.stringify(finished, null, 2)}\n`);
489
- await writeAtomic(view.reviewFile.replace(/\.json$/, ".md"), report(finished));
493
+ await writeAtomic(view.reviewFile.replace(/\.json$/, ".md"), await report(finished));
490
494
  await rm(view.draftFile, { force: true });
491
495
  return view.reviewFile;
492
496
  };
497
+ /** coverage.json as the agent last wrote it, or a 404 before its first run. */
498
+ const coverageFile = () => {
499
+ let coverage;
500
+ try {
501
+ coverage = readCoverageIn(view.registration.dir);
502
+ }
503
+ catch (error) {
504
+ if (error instanceof SessionFileError)
505
+ throw new HttpError(500, error.message);
506
+ throw error;
507
+ }
508
+ if (coverage === null) {
509
+ throw new HttpError(404, "no coverage yet; the agent records it with follow-me coverage");
510
+ }
511
+ return coverage;
512
+ };
493
513
  const hasWork = () => view.comments.size > 0 || view.decisions.size > 0 || view.earlierReplies.size > 0;
494
514
  return {
495
515
  id,
@@ -547,12 +567,28 @@ function hostSession(id, registration, loaded, draft, load) {
547
567
  return waitForEvents(since, timeoutMs, signal);
548
568
  },
549
569
  report: () => report(review()),
570
+ /**
571
+ * The agent's last test run, read from disk so a restarted server serves it too, with the
572
+ * covered files whose content changed since its tip. A new plan for the same tip stales nothing.
573
+ */
574
+ coverage: async () => {
575
+ const coverage = coverageFile();
576
+ const stale = await staleFiles(view.loaded.repo, coverage, view.loaded.state.anchor.tip);
577
+ return { ...serializeCoverage(coverage), stale };
578
+ },
579
+ /** The agent wrote coverage.json; the page hears it as one event and reloads its marks. */
580
+ coverageTaken: () => {
581
+ open();
582
+ const { tip, takenAt } = coverageFile();
583
+ emit({ type: "coverage", tip, takenAt });
584
+ return { tip, takenAt };
585
+ },
550
586
  /** The page reads a definition the plan shows from its hunk, so only others carry a preview. */
551
587
  define: async (name, from) => {
552
588
  const found = await view.definitions.lookup(name, from !== null && isRepoPath(from) ? from : null);
553
589
  return found.map((c) => (c.unit === null ? c : { ...c, preview: [] }));
554
590
  },
555
- reportItems: () => reportItems(review(), view.loaded.state.commits, unitsOf(), reportOptions()),
591
+ reportItems: async () => reportItems(review(), view.loaded.state.commits, unitsOf(), await reportOptions()),
556
592
  add: async (raw) => {
557
593
  open();
558
594
  if (!isRecord(raw))
@@ -958,12 +994,18 @@ export function startServer(opts) {
958
994
  const candidates = await session.define(name, url.searchParams.get("from"));
959
995
  return sendJson(res, 200, { candidates });
960
996
  }
997
+ if (method === "GET" && rest === "/api/coverage") {
998
+ return sendJson(res, 200, await session.coverage());
999
+ }
1000
+ if (method === "POST" && rest === "/api/coverage") {
1001
+ return sendJson(res, 200, session.coverageTaken());
1002
+ }
961
1003
  if (method === "GET" && rest === "/api/report" && url.searchParams.get("format") === "json") {
962
- return sendJson(res, 200, session.reportItems());
1004
+ return sendJson(res, 200, await session.reportItems());
963
1005
  }
964
1006
  if (method === "GET" && rest === "/api/report") {
965
1007
  res.writeHead(200, { "content-type": "text/markdown; charset=utf-8" });
966
- res.end(session.report());
1008
+ res.end(await session.report());
967
1009
  return;
968
1010
  }
969
1011
  if (method === "POST" && rest === "/api/version") {
@@ -2,6 +2,7 @@ import { randomUUID } from "node:crypto";
2
2
  import { existsSync, linkSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, statSync, writeFileSync, } from "node:fs";
3
3
  import { basename, dirname, join } from "node:path";
4
4
  import { parseDraft, parseReview } from "./comments.js";
5
+ import { freshFiles, parseCoverage, serializeCoverage, staleFiles } from "./coverage.js";
5
6
  import { isSha } from "./diff.js";
6
7
  import { evolvePlan } from "./evolve.js";
7
8
  import { branchExists, currentBranch, defaultBaseRef, GitError, loadDiff, objectsDir, QUARANTINE_PREFIX, repoRoot, resolveCommit, } from "./git.js";
@@ -200,6 +201,36 @@ function parseApplied(v) {
200
201
  return null;
201
202
  return { schema, version, branch, head, hash, signed };
202
203
  }
204
+ function coveragePath(dir) {
205
+ return join(dir, "coverage.json");
206
+ }
207
+ /** The coverage.json of the session in `dir`, or null when there is none. */
208
+ export function readCoverageIn(dir) {
209
+ const path = coveragePath(dir);
210
+ const raw = readJson(path);
211
+ if (raw === undefined)
212
+ return null;
213
+ const coverage = parseCoverage(raw);
214
+ if (typeof coverage === "string")
215
+ throw new SessionFileError(`${path}: ${coverage}`);
216
+ return coverage;
217
+ }
218
+ /**
219
+ * What the report counts: the files of the session's test run that still describe `tip`. Null
220
+ * without a run, and when coverage.json cannot be read, so a report never fails on it.
221
+ */
222
+ export async function coverageAt(repo, dir, tip) {
223
+ let coverage;
224
+ try {
225
+ coverage = readCoverageIn(dir);
226
+ }
227
+ catch (error) {
228
+ if (error instanceof SessionFileError)
229
+ return null;
230
+ throw error;
231
+ }
232
+ return coverage === null ? null : freshFiles(coverage, await staleFiles(repo, coverage, tip));
233
+ }
203
234
  function makeSession(root, dir, anchor, diff) {
204
235
  const plansDir = join(dir, "plans");
205
236
  const splitReviews = join(dir, "reviews");
@@ -310,6 +341,8 @@ function makeSession(root, dir, anchor, diff) {
310
341
  writeJson(join(plansDir, `v${version}.json`), serializePlanFile(plan.file));
311
342
  return version;
312
343
  },
344
+ coverage: () => readCoverageIn(dir),
345
+ writeCoverage: (coverage) => writeJson(coveragePath(dir), serializeCoverage(coverage)),
313
346
  lock: (command) => acquireLock(dir, anchor.branch, command),
314
347
  adoptLock: (from, command) => adoptLock(dir, from, command),
315
348
  lockState: () => readLock(join(dir, "lock")),
package/dist/src/types.js CHANGED
@@ -12,6 +12,8 @@
12
12
  * review file, the autosaved draft and the server's events. Pure parsers.
13
13
  * definition.ts where an identifier is defined at the branch tip, and where that lands in the
14
14
  * plan: per-language patterns, ranking, placement and a per-tip cache.
15
+ * coverage.ts lcov from the agent's test run: parse, place at the tip, merge runs, count the
16
+ * changed lines covered, and which files went stale since.
15
17
  * prompt.ts the planner prompt for an agent, the feedback and the consolidated report.
16
18
  * server.ts the review server: a registry of hosted sessions, their JSON API, and ui/.
17
19
  * host.ts the one server per user: its record in the state dir, attach, start, stop.
@@ -1 +1 @@
1
- import{m as e,t}from"./mermaid-parser.core-DGpOP8AM.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-XnrqevnL.js";import"./chunk-DSNLSHJZ-B2z7FX4h.js";import{n as i,r as a,t as o}from"./chunk-2E7WHVMD-CNMuK9zj.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-BJtBFbJx.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
1
+ import{m as e,t}from"./mermaid-parser.core-CMPNc-u6.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-BiC9XNcI.js";import"./chunk-DSNLSHJZ-Bk8WO5JF.js";import{n as i,r as a,t as o}from"./chunk-2E7WHVMD-BTet9STn.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-Nd_xOg2y.js";var c=e().RailroadAbnf.parser.LangiumParser,l=n(e=>{let t=e.alternatives.map(u);return t.length===1?t[0]:{type:`choice`,alternatives:t}},`transformAlternation`),u=n(e=>{let t=e.elements.map(f);return t.length===1?t[0]:{type:`sequence`,elements:t}},`transformConcatenation`),d=n(e=>{if(e.includes(`*`)){let[t,n]=e.split(`*`);return{min:t?parseInt(t,10):0,max:n?parseInt(n,10):1/0}}let t=parseInt(e,10);return{min:t,max:t}},`parseRepeat`),f=n(e=>{let t=p(e.primary);if(!e.repeat)return t;let{min:n,max:r}=d(e.repeat);return n===0&&r===1?{type:`optional`,element:t}:{type:`repetition`,element:t,min:n,max:r}},`transformElement`),p=n(e=>{switch(e.$type){case`AbnfStringLiteral`:return{type:`terminal`,value:e.value};case`AbnfNumVal`:return{type:`terminal`,value:e.value};case`AbnfRuleName`:return{type:`nonterminal`,name:e.name};case`AbnfGroup`:return l(e.element);case`AbnfOptionalGroup`:return{type:`optional`,element:l(e.element)};default:throw Error(`Unsupported ABNF primary node: ${e.$type}`)}},`transformPrimary`),m=n(e=>({name:e.name,definition:l(e.definition)}),`transformRule`),h=n(e=>{s(e,o),e.title&&o.setTitle(e.title),e.rules.map(e=>o.addRule(m(e)))},`populateDb`),g={parser:{parse:n(e=>{o.clear(),r.debug(`[ABNF Parser] Starting Langium parse`);let n=c.parse(e);if(n.lexerErrors.length>0||n.parserErrors.length>0)throw new t(n);let i=n.value;r.debug(`[ABNF Parser] Parsed rules:`,i.rules.length),h(i),r.debug(`[ABNF Parser] Parse complete`)},`parse`),parser:{yy:o}},db:o,renderer:a,styles:i};export{g as diagram};
@@ -1 +1 @@
1
- import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-BJd4jp9Y.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
1
+ import{n as e,t}from"./path-fybaL0A-.js";import{a as n,c as r,d as i,f as a,i as o,l as s,m as c,n as l,o as u,p as d,r as f,u as p}from"./dist-CHZ9mrl_.js";function m(e){return e.innerRadius}function h(e){return e.outerRadius}function g(e){return e.startAngle}function _(e){return e.endAngle}function v(e){return e&&e.padAngle}function y(e,t,n,r,i,a,o,s){var c=n-e,l=r-t,u=o-i,d=s-a,f=d*c-u*l;if(!(f*f<1e-12))return f=(u*(t-a)-d*(e-i))/f,[e+f*c,t+f*l]}function b(e,t,n,r,i,a,o){var c=e-n,l=t-r,u=(o?a:-a)/d(c*c+l*l),f=u*l,p=-u*c,m=e+f,h=t+p,g=n+f,_=r+p,v=(m+g)/2,y=(h+_)/2,b=g-m,x=_-h,S=b*b+x*x,C=i-a,w=m*_-g*h,T=(x<0?-1:1)*d(s(0,C*C*S-w*w)),E=(w*x-b*T)/S,D=(-w*b-x*T)/S,O=(w*x+b*T)/S,k=(-w*b+x*T)/S,A=E-v,j=D-y,M=O-v,N=k-y;return A*A+j*j>M*M+N*N&&(E=O,D=k),{cx:E,cy:D,x01:-f,y01:-p,x11:E*(i/C-1),y11:D*(i/C-1)}}function x(){var s=m,x=h,S=e(0),C=null,w=g,T=_,E=v,D=null,O=t(k);function k(){var e,t,m=+s.apply(this,arguments),h=+x.apply(this,arguments),g=w.apply(this,arguments)-r,_=T.apply(this,arguments)-r,v=l(_-g),k=_>g;if(D||=e=O(),h<m&&(t=h,h=m,m=t),!(h>1e-12))D.moveTo(0,0);else if(v>c-1e-12)D.moveTo(h*u(g),h*a(g)),D.arc(0,0,h,g,_,!k),m>1e-12&&(D.moveTo(m*u(_),m*a(_)),D.arc(0,0,m,_,g,k));else{var A=g,j=_,M=g,N=_,P=v,F=v,I=E.apply(this,arguments)/2,L=I>1e-12&&(C?+C.apply(this,arguments):d(m*m+h*h)),R=p(l(h-m)/2,+S.apply(this,arguments)),z=R,B=R,V,H;if(L>1e-12){var U=o(L/m*a(I)),W=o(L/h*a(I));(P-=U*2)>1e-12?(U*=k?1:-1,M+=U,N-=U):(P=0,M=N=(g+_)/2),(F-=W*2)>1e-12?(W*=k?1:-1,A+=W,j-=W):(F=0,A=j=(g+_)/2)}var G=h*u(A),K=h*a(A),q=m*u(N),J=m*a(N);if(R>1e-12){var Y=h*u(j),X=h*a(j),Z=m*u(M),Q=m*a(M),$;if(v<i){if($=y(G,K,Z,Q,Y,X,q,J)){var ee=G-$[0],te=K-$[1],ne=Y-$[0],re=X-$[1],ie=1/a(f((ee*ne+te*re)/(d(ee*ee+te*te)*d(ne*ne+re*re)))/2),ae=d($[0]*$[0]+$[1]*$[1]);z=p(R,(m-ae)/(ie-1)),B=p(R,(h-ae)/(ie+1))}else z=B=0}}F>1e-12?B>1e-12?(V=b(Z,Q,G,K,h,B,k),H=b(Y,X,q,J,h,B,k),D.moveTo(V.cx+V.x01,V.cy+V.y01),B<R?D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,B,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,h,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),!k),D.arc(H.cx,H.cy,B,n(H.y11,H.x11),n(H.y01,H.x01),!k))):(D.moveTo(G,K),D.arc(0,0,h,A,j,!k)):D.moveTo(G,K),!(m>1e-12)||!(P>1e-12)?D.lineTo(q,J):z>1e-12?(V=b(q,J,Y,X,m,-z,k),H=b(G,K,Z,Q,m,-z,k),D.lineTo(V.cx+V.x01,V.cy+V.y01),z<R?D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(H.y01,H.x01),!k):(D.arc(V.cx,V.cy,z,n(V.y01,V.x01),n(V.y11,V.x11),!k),D.arc(0,0,m,n(V.cy+V.y11,V.cx+V.x11),n(H.cy+H.y11,H.cx+H.x11),k),D.arc(H.cx,H.cy,z,n(H.y11,H.x11),n(H.y01,H.x01),!k))):D.arc(0,0,m,N,M,k)}if(D.closePath(),e)return D=null,e+``||null}return k.centroid=function(){var e=(+s.apply(this,arguments)+ +x.apply(this,arguments))/2,t=(+w.apply(this,arguments)+ +T.apply(this,arguments))/2-i/2;return[u(t)*e,a(t)*e]},k.innerRadius=function(t){return arguments.length?(s=typeof t==`function`?t:e(+t),k):s},k.outerRadius=function(t){return arguments.length?(x=typeof t==`function`?t:e(+t),k):x},k.cornerRadius=function(t){return arguments.length?(S=typeof t==`function`?t:e(+t),k):S},k.padRadius=function(t){return arguments.length?(C=t==null?null:typeof t==`function`?t:e(+t),k):C},k.startAngle=function(t){return arguments.length?(w=typeof t==`function`?t:e(+t),k):w},k.endAngle=function(t){return arguments.length?(T=typeof t==`function`?t:e(+t),k):T},k.padAngle=function(t){return arguments.length?(E=typeof t==`function`?t:e(+t),k):E},k.context=function(e){return arguments.length?(D=e??null,k):D},k}export{x as t};
@@ -1 +1 @@
1
- import"./chunk-NGNAAXSQ-C2Wy9Xmz.js";export{M as createArchitectureServices}from"./mermaid-parser.core-DGpOP8AM.js";
1
+ import"./chunk-NGNAAXSQ-C2Wy9Xmz.js";export{M as createArchitectureServices}from"./mermaid-parser.core-CMPNc-u6.js";