@shiyuphan/follow-me 0.7.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +3 -0
  2. package/dist/src/cli.js +128 -24
  3. package/dist/src/comments.js +146 -7
  4. package/dist/src/coverage.js +16 -2
  5. package/dist/src/host.js +23 -0
  6. package/dist/src/plan.js +128 -6
  7. package/dist/src/prompt.js +55 -2
  8. package/dist/src/server.js +65 -3
  9. package/dist/src/session.js +1 -0
  10. package/dist/ui/dist/assets/{abnfDiagram-WEYOIA3C-cHEJvcBn.js → abnfDiagram-WEYOIA3C-Bp14ygmz.js} +1 -1
  11. package/dist/ui/dist/assets/{arc-xolFyc0v.js → arc-DUR6uzhI.js} +1 -1
  12. package/dist/ui/dist/assets/{architecture-WOLXFQ4H-B3hvvNV2.js → architecture-WOLXFQ4H-CyfnP65O.js} +1 -1
  13. package/dist/ui/dist/assets/{architectureDiagram-ZHVYKT53-BNTMbPJW.js → architectureDiagram-ZHVYKT53-dJTicIk2.js} +1 -1
  14. package/dist/ui/dist/assets/{blockDiagram-RJAE7QA3-NYY6qeuY.js → blockDiagram-RJAE7QA3-BYiqh5Ib.js} +1 -1
  15. package/dist/ui/dist/assets/{c4Diagram-XDPPPE54-B_bNpXHQ.js → c4Diagram-XDPPPE54-DHHPQ7xE.js} +1 -1
  16. package/dist/ui/dist/assets/channel-CY2cQobm.js +1 -0
  17. package/dist/ui/dist/assets/{chunk-2E7WHVMD-BTet9STn.js → chunk-2E7WHVMD-BODm_awL.js} +1 -1
  18. package/dist/ui/dist/assets/{chunk-4EMNKR2T-qoQt4Fpx.js → chunk-4EMNKR2T-CpZfjf2T.js} +1 -1
  19. package/dist/ui/dist/assets/{chunk-55XCU76K-C3I6EB-H.js → chunk-55XCU76K-CoP2pJTQ.js} +1 -1
  20. package/dist/ui/dist/assets/{chunk-7S6XSTFO-CL-9s_8p.js → chunk-7S6XSTFO-CaQcUvXY.js} +1 -1
  21. package/dist/ui/dist/assets/{chunk-AQDTSKZB-DHoGnGyP.js → chunk-AQDTSKZB-BZ9Czvbu.js} +1 -1
  22. package/dist/ui/dist/assets/{chunk-DSNLSHJZ-Bk8WO5JF.js → chunk-DSNLSHJZ-CNjUo110.js} +1 -1
  23. package/dist/ui/dist/assets/{chunk-HAGFOTED-CwAC85lg.js → chunk-HAGFOTED-BTmBE_D3.js} +1 -1
  24. package/dist/ui/dist/assets/{chunk-HNE4Q36P-CIllywWr.js → chunk-HNE4Q36P-D2cDuT0C.js} +1 -1
  25. package/dist/ui/dist/assets/{chunk-NQOKRVIF-DDlpyYiH.js → chunk-NQOKRVIF-AZcemFgG.js} +1 -1
  26. package/dist/ui/dist/assets/{chunk-UHW7PFBP-Cxdndcon.js → chunk-UHW7PFBP-BszwjUqG.js} +1 -1
  27. package/dist/ui/dist/assets/{chunk-VQ5W62QI-CL9d9_iJ.js → chunk-VQ5W62QI-vFSenYSe.js} +1 -1
  28. package/dist/ui/dist/assets/{chunk-WQQL4CDK-C4kzN8QU.js → chunk-WQQL4CDK-DZR6is1Q.js} +1 -1
  29. package/dist/ui/dist/assets/{chunk-XXDRQBXY-Cv_2FSiY.js → chunk-XXDRQBXY-CACFh-si.js} +1 -1
  30. package/dist/ui/dist/assets/{chunk-YZO67HFG-oHiuYaCJ.js → chunk-YZO67HFG-DRRTjGuW.js} +1 -1
  31. package/dist/ui/dist/assets/{chunk-ZAUX2LTX-Cy_8d0XT.js → chunk-ZAUX2LTX-Bxuy-Roa.js} +1 -1
  32. package/dist/ui/dist/assets/{chunk-ZCHMQSOR-piIpIcQi.js → chunk-ZCHMQSOR-rYXk__1o.js} +1 -1
  33. package/dist/ui/dist/assets/{classDiagram-v2-4MYWR3UA-DNKRIujO.js → classDiagram-v2-4MYWR3UA-RiF44tTz.js} +1 -1
  34. package/dist/ui/dist/assets/{cose-bilkent-JH36ORCC-BWKTGCHY.js → cose-bilkent-JH36ORCC-0oiQoThS.js} +1 -1
  35. package/dist/ui/dist/assets/{cynefin-EF2NZ3EQ-yx7KKkAk.js → cynefin-EF2NZ3EQ-BAssFK5K.js} +1 -1
  36. package/dist/ui/dist/assets/{cynefinDiagram-WF24UDRP-BTnZ7QVL.js → cynefinDiagram-WF24UDRP-Bmd05bak.js} +1 -1
  37. package/dist/ui/dist/assets/{dagre-NK4GIZVX-CPh5Zn5I.js → dagre-NK4GIZVX-QJkLjPxj.js} +1 -1
  38. package/dist/ui/dist/assets/{diagram-CBK3MWTC-pI6NFdrD.js → diagram-CBK3MWTC-PSaSiYXz.js} +1 -1
  39. package/dist/ui/dist/assets/{diagram-I5XIIV2D-DUIfARoS.js → diagram-I5XIIV2D-BmU5X_hr.js} +1 -1
  40. package/dist/ui/dist/assets/{diagram-ODIL2UCW-lafSPvAw.js → diagram-ODIL2UCW-AAV39kUu.js} +1 -1
  41. package/dist/ui/dist/assets/{diagram-PFBEJUXE-u1lZas3a.js → diagram-PFBEJUXE-DWlV-oxd.js} +1 -1
  42. package/dist/ui/dist/assets/{diagram-RJA3I4VV-mc0GLMHo.js → diagram-RJA3I4VV-D8wHRCNX.js} +1 -1
  43. package/dist/ui/dist/assets/{diagram-TYUNFSNR-1NRbBrZW.js → diagram-TYUNFSNR-B_JQEsNY.js} +1 -1
  44. package/dist/ui/dist/assets/{dist-CHZ9mrl_.js → dist-DxQIK_Ay.js} +1 -1
  45. package/dist/ui/dist/assets/{ebnfDiagram-V4P3TTPT-DdStjTDc.js → ebnfDiagram-V4P3TTPT-D83qV8mv.js} +1 -1
  46. package/dist/ui/dist/assets/{elk-QONTBCTQ-BzRoFO45.js → elk-QONTBCTQ-BKFAKVSD.js} +1 -1
  47. package/dist/ui/dist/assets/{erDiagram-KYQIGQAA-DlMkgQxj.js → erDiagram-KYQIGQAA-CHYRd4aM.js} +1 -1
  48. package/dist/ui/dist/assets/{eventmodeling-K75KTNOO-BRYIOrod.js → eventmodeling-K75KTNOO-BDJDv3Zf.js} +1 -1
  49. package/dist/ui/dist/assets/flowDiagram-IUGLLWBU-Bke3CfUH.js +1 -0
  50. package/dist/ui/dist/assets/{ganttDiagram-R7GPNTJY-D8fQZ7Ah.js → ganttDiagram-R7GPNTJY-gTHjYkFj.js} +1 -1
  51. package/dist/ui/dist/assets/{gitGraph-VSP46ZUC-C7ZydyWX.js → gitGraph-VSP46ZUC-D4cWkxKB.js} +1 -1
  52. package/dist/ui/dist/assets/{gitGraphDiagram-PDYL7XHY-DCItam0v.js → gitGraphDiagram-PDYL7XHY-D3M9wYMr.js} +1 -1
  53. package/dist/ui/dist/assets/index-BUOFihod.js +134 -0
  54. package/dist/ui/dist/assets/index-DLNJT0VS.css +1 -0
  55. package/dist/ui/dist/assets/{info-OHQRW6UA-C3KneBKT.js → info-OHQRW6UA-B9y0ksVq.js} +1 -1
  56. package/dist/ui/dist/assets/{infoDiagram-MVDRKAX5-6wK09D32.js → infoDiagram-MVDRKAX5-s4FMwb8r.js} +1 -1
  57. package/dist/ui/dist/assets/{ishikawaDiagram-HPEHV2GE-DTP5C8VX.js → ishikawaDiagram-HPEHV2GE-CnQdxybf.js} +1 -1
  58. package/dist/ui/dist/assets/{journeyDiagram-BOSHW7O7-B--UIMtq.js → journeyDiagram-BOSHW7O7-I-9OpDWY.js} +1 -1
  59. package/dist/ui/dist/assets/{kanban-definition-FNSA4HC5-Ku4N9QGt.js → kanban-definition-FNSA4HC5-DqUbIdH4.js} +1 -1
  60. package/dist/ui/dist/assets/{line-C4-H5h1-.js → line-BELSui4d.js} +1 -1
  61. package/dist/ui/dist/assets/{linear-DhAID3hm.js → linear-77hmn2iQ.js} +1 -1
  62. package/dist/ui/dist/assets/{mermaid-parser.core-CMPNc-u6.js → mermaid-parser.core-Bxa71wW-.js} +3 -3
  63. package/dist/ui/dist/assets/{mermaid.core-Nd_xOg2y.js → mermaid.core-DBI9F4bh.js} +4 -4
  64. package/dist/ui/dist/assets/{mindmap-definition-6OY57UG3-BlVsym5h.js → mindmap-definition-6OY57UG3-BxXMOapP.js} +1 -1
  65. package/dist/ui/dist/assets/{packet-JDAUHWVQ-rsk7SM7S.js → packet-JDAUHWVQ-DTT77cQh.js} +1 -1
  66. package/dist/ui/dist/assets/{pegDiagram-ECIUJNBX-C0L20M8z.js → pegDiagram-ECIUJNBX-HzrOQPT5.js} +1 -1
  67. package/dist/ui/dist/assets/{pie-XZMESJXO-B23-iZSN.js → pie-XZMESJXO-iHwL1Qw-.js} +1 -1
  68. package/dist/ui/dist/assets/{pieDiagram-GNMPY74T-BqFhe4Oh.js → pieDiagram-GNMPY74T-DZ1tLVjw.js} +1 -1
  69. package/dist/ui/dist/assets/{prism-core-DYsiqJeR.js → prism-core-NtO0YF9C.js} +1 -1
  70. package/dist/ui/dist/assets/{quadrantDiagram-D57K4MC3-BKP75B-m.js → quadrantDiagram-D57K4MC3-BjTi9H5L.js} +1 -1
  71. package/dist/ui/dist/assets/{radar-ABXABTNO-BrEk2mQ7.js → radar-ABXABTNO-D2hYgXSB.js} +1 -1
  72. package/dist/ui/dist/assets/{railroad-I3PHUGI6-wWO4Eapc.js → railroad-I3PHUGI6-DpakXN74.js} +1 -1
  73. package/dist/ui/dist/assets/{railroad-abnf-LNEFI6M7-DfY-IPvE.js → railroad-abnf-LNEFI6M7-B8ZFR3iy.js} +1 -1
  74. package/dist/ui/dist/assets/{railroad-ebnf-DWYD2UWJ-19wedWGk.js → railroad-ebnf-DWYD2UWJ-S1XUyTsC.js} +1 -1
  75. package/dist/ui/dist/assets/{railroad-peg-JR7BVNR7-9vIslnoJ.js → railroad-peg-JR7BVNR7-BbeHC_6K.js} +1 -1
  76. package/dist/ui/dist/assets/{railroadDiagram-Y72NRBL7-DVnmXs8w.js → railroadDiagram-Y72NRBL7-fd-2iyBo.js} +1 -1
  77. package/dist/ui/dist/assets/{requirementDiagram-EQYSW5RA-BEoMdlzR.js → requirementDiagram-EQYSW5RA-B9-HHKH-.js} +1 -1
  78. package/dist/ui/dist/assets/{sankeyDiagram-SY24JHO5-D7Tn2Gbs.js → sankeyDiagram-SY24JHO5-CeQN1ZEG.js} +1 -1
  79. package/dist/ui/dist/assets/{sequenceDiagram-BLEHNHQU-CyjUDBaQ.js → sequenceDiagram-BLEHNHQU-Vff7tx4t.js} +1 -1
  80. package/dist/ui/dist/assets/{src-BiC9XNcI.js → src-D5-ZzLwt.js} +1 -1
  81. package/dist/ui/dist/assets/{stateDiagram-v2-A6IESKWZ-CMp1VCO9.js → stateDiagram-v2-A6IESKWZ-Bzn_ma9c.js} +1 -1
  82. package/dist/ui/dist/assets/{swimlanes-B3ENRKFQ-KEciLd6r.js → swimlanes-B3ENRKFQ-CevqLchV.js} +1 -1
  83. package/dist/ui/dist/assets/swimlanesDiagram-AYQRV4AK-Bkv8hAmN.js +8 -0
  84. package/dist/ui/dist/assets/{timeline-definition-JXYKGLGB-C8YQtv7M.js → timeline-definition-JXYKGLGB-D9jSDGJI.js} +1 -1
  85. package/dist/ui/dist/assets/{treeView-D4JQ5SDB-DgAzPaOO.js → treeView-D4JQ5SDB-CoXKj11m.js} +1 -1
  86. package/dist/ui/dist/assets/{treemap-SAJKECNS-eCRqZMYc.js → treemap-SAJKECNS-cHsansGe.js} +1 -1
  87. package/dist/ui/dist/assets/{usecaseDiagram-WPOLBNNX-Dirryw9G.js → usecaseDiagram-WPOLBNNX-CW9i3bW6.js} +1 -1
  88. package/dist/ui/dist/assets/{vennDiagram-Q3Y3IDCW-BjxQbAUx.js → vennDiagram-Q3Y3IDCW-DuU3qEKJ.js} +1 -1
  89. package/dist/ui/dist/assets/{wardley-7MLQ67FV-CqHX5RUz.js → wardley-7MLQ67FV-dl9RgHUI.js} +1 -1
  90. package/dist/ui/dist/assets/{wardleyDiagram-IVAIDKWA-Ds1HoEUY.js → wardleyDiagram-IVAIDKWA-BOXhrK-a.js} +1 -1
  91. package/dist/ui/dist/assets/{xychartDiagram-4URNHDU4-kodzDb12.js → xychartDiagram-4URNHDU4-CLQNGrh4.js} +1 -1
  92. package/dist/ui/dist/index.html +2 -2
  93. package/package.json +1 -1
  94. package/skills/follow-me/SKILL.md +2 -0
  95. package/dist/ui/dist/assets/channel-DPDY0XJP.js +0 -1
  96. package/dist/ui/dist/assets/flowDiagram-IUGLLWBU-C1IBh_GZ.js +0 -1
  97. package/dist/ui/dist/assets/index-8BehwQ7E.js +0 -134
  98. package/dist/ui/dist/assets/index-mC2OW2Av.css +0 -1
  99. package/dist/ui/dist/assets/swimlanesDiagram-AYQRV4AK-DzestpDE.js +0 -8
package/dist/src/plan.js CHANGED
@@ -10,6 +10,12 @@ export function isCommentId(s) {
10
10
  export function isConcernId(s) {
11
11
  return typeof s === "string" && /^k_[0-9a-f]{8}$/.test(s);
12
12
  }
13
+ export function isOfferId(s) {
14
+ return typeof s === "string" && /^o_[0-9a-f]{8}$/.test(s);
15
+ }
16
+ /** At most this many offers in one commit and in the whole plan; most plans need none. */
17
+ export const OFFERS_PER_COMMIT = 1;
18
+ export const OFFERS_PER_PLAN = 3;
13
19
  export function isPlanVersion(n) {
14
20
  return typeof n === "number" && Number.isInteger(n) && n >= 1;
15
21
  }
@@ -29,6 +35,10 @@ export function isSeverity(s) {
29
35
  function isConcernKind(s) {
30
36
  return CONCERN_KINDS.some((x) => x === s);
31
37
  }
38
+ const OFFER_KINDS = ["state-machine", "sequence", "diagram"];
39
+ function isOfferKind(s) {
40
+ return OFFER_KINDS.some((x) => x === s);
41
+ }
32
42
  /** Narrows to an object whose named fields are still unknown, which holds for any object. */
33
43
  export function isFields(v) {
34
44
  return typeof v === "object" && v !== null && !Array.isArray(v);
@@ -123,7 +133,47 @@ function parseConcerns(v, onUnit) {
123
133
  }
124
134
  return out;
125
135
  }
126
- /** The optional narration, diagram and concerns of a commit or unit entry, or what is wrong. */
136
+ /** An offer is { kind, label }; the label names the thing to draw. */
137
+ function parseOffer(v) {
138
+ if (!isFields(v))
139
+ return "expected an object";
140
+ if (!isOfferKind(v.kind))
141
+ return `kind: expected one of ${OFFER_KINDS.join(", ")}`;
142
+ if (typeof v.label !== "string" || v.label.trim() === "") {
143
+ return 'label: expected what to draw, like "Draw UploadButton as a state machine"';
144
+ }
145
+ return { kind: v.kind, label: v.label };
146
+ }
147
+ /** A stored offer as validation placed it: with its id and its unit. */
148
+ export function parsePlacedOffer(v) {
149
+ if (!isFields(v))
150
+ return "expected an object";
151
+ if (!isOfferId(v.id))
152
+ return "id: expected an offer id";
153
+ if (v.unit !== undefined && !(typeof v.unit === "string" && isUnitId(v.unit))) {
154
+ return "unit: expected a unit id";
155
+ }
156
+ const offer = parseOffer(v);
157
+ if (typeof offer === "string")
158
+ return offer;
159
+ return { ...offer, id: v.id, ...(v.unit === undefined ? {} : { unit: v.unit }) };
160
+ }
161
+ /** Absent, null and [] all mean no offers. */
162
+ function parseOffers(v) {
163
+ if (v === undefined || v === null)
164
+ return [];
165
+ if (!isArray(v))
166
+ return "expected an array";
167
+ const out = [];
168
+ for (const [i, raw] of v.entries()) {
169
+ const offer = parseOffer(raw);
170
+ if (typeof offer === "string")
171
+ return `[${i}]: ${offer}`;
172
+ out.push(offer);
173
+ }
174
+ return out;
175
+ }
176
+ /** The optional narration, diagram, concerns and offers of a commit or unit entry, or what is wrong. */
127
177
  function parseExtras(v, onUnit) {
128
178
  const narration = parseText(v.narration);
129
179
  if (narration === INVALID)
@@ -137,7 +187,13 @@ function parseExtras(v, onUnit) {
137
187
  const concerns = parseConcerns(v.concerns, onUnit);
138
188
  if (typeof concerns === "string")
139
189
  return { field: "concerns", error: concerns };
140
- return withExtras(narration, diagram, concerns);
190
+ const offers = parseOffers(v.offers);
191
+ if (typeof offers === "string")
192
+ return { field: "offers", error: offers };
193
+ return {
194
+ ...withExtras(narration, diagram, concerns),
195
+ ...(offers.length === 0 ? {} : { offers }),
196
+ };
141
197
  }
142
198
  function withText(narration, diagram) {
143
199
  return {
@@ -160,15 +216,21 @@ function serializeExtras(x) {
160
216
  return {
161
217
  ...withText(x.narration ?? null, x.diagram ?? null),
162
218
  ...(x.concerns === undefined ? {} : { concerns: x.concerns.map(serializeConcern) }),
219
+ ...(x.offers === undefined
220
+ ? {}
221
+ : { offers: x.offers.map((o) => ({ kind: o.kind, label: o.label })) }),
163
222
  };
164
223
  }
165
- /** A unit entry is "h_x:0-3" or { "unit": "h_x:0-3", "narration", "diagram", "concerns" }. */
224
+ /**
225
+ * A unit entry is "h_x:0-3" or { "unit": "h_x:0-3", "narration", "diagram", "concerns", "offers" }.
226
+ */
166
227
  function parseUnitEntry(u) {
167
228
  if (typeof u === "string")
168
229
  return parseUnitRef(u);
169
- if (!isFields(u) || typeof u.unit !== "string") {
230
+ if (!isFields(u) ||
231
+ typeof u.unit !== "string") {
170
232
  return {
171
- error: 'expected a unit ref string or { "unit", "narration", "diagram", "concerns" }',
233
+ error: 'expected a unit ref string or { "unit", "narration", "diagram", "concerns", "offers" }',
172
234
  };
173
235
  }
174
236
  const ref = parseUnitRef(u.unit);
@@ -298,7 +360,10 @@ export function serializePlanFile(file) {
298
360
  message: c.message,
299
361
  ...(c.section === undefined ? {} : { section: c.section }),
300
362
  ...serializeExtras(c),
301
- units: c.units.map((ref) => ref.narration === undefined && ref.diagram === undefined && ref.concerns === undefined
363
+ units: c.units.map((ref) => ref.narration === undefined &&
364
+ ref.diagram === undefined &&
365
+ ref.concerns === undefined &&
366
+ ref.offers === undefined
302
367
  ? formatUnitRef(ref)
303
368
  : { unit: formatUnitRef(ref), ...serializeExtras(ref) }),
304
369
  })),
@@ -547,8 +612,51 @@ function placeConcerns(diff, file, claims, issues) {
547
612
  }
548
613
  return placedPerCommit;
549
614
  }
615
+ /** "o_" + 8 hex over the unit and the label: stable while the offer stays at its place. */
616
+ function deriveOfferId(unit, o) {
617
+ const hex = createHash("sha256")
618
+ .update(`offer\0${unit ?? ""}\0${o.label}`)
619
+ .digest("hex")
620
+ .slice(0, 8);
621
+ const id = `o_${hex}`;
622
+ if (!isOfferId(id))
623
+ throw new Error(`sha256 produced ${id}`);
624
+ return id;
625
+ }
626
+ /** Gives every offer its id: the commit's own first, then those of its unit refs in order. */
627
+ function placeOffers(file, issues) {
628
+ const ids = new Set();
629
+ return file.commits.map((commit, k) => {
630
+ const placed = [];
631
+ const add = (o, unit) => {
632
+ const id = deriveOfferId(unit, o);
633
+ if (ids.has(id)) {
634
+ issues.push({ kind: "bad-offer", commit: k, reason: `${id} repeats another offer` });
635
+ return;
636
+ }
637
+ ids.add(id);
638
+ placed.push({ ...o, id, ...(unit === null ? {} : { unit }) });
639
+ };
640
+ for (const o of commit.offers ?? [])
641
+ add(o, null);
642
+ for (const ref of commit.units)
643
+ for (const o of ref.offers ?? [])
644
+ add(o, ref.unit);
645
+ return placed;
646
+ });
647
+ }
648
+ /** At most OFFERS_PER_COMMIT in a commit, its units' included, and OFFERS_PER_PLAN in all. */
649
+ function offerLimits(file) {
650
+ const counts = file.commits.map((c) => (c.offers ?? []).length + c.units.reduce((n, r) => n + (r.offers ?? []).length, 0));
651
+ const issues = counts.flatMap((count, commit) => count > OFFERS_PER_COMMIT ? [{ kind: "too-many-offers", commit, count }] : []);
652
+ const total = counts.reduce((a, b) => a + b, 0);
653
+ if (total > OFFERS_PER_PLAN)
654
+ issues.push({ kind: "too-many-offers", commit: null, count: total });
655
+ return issues;
656
+ }
550
657
  function project(diff, file, claims, issues) {
551
658
  const concerns = placeConcerns(diff, file, claims, issues);
659
+ const offers = placeOffers(file, issues);
552
660
  const { stateAt, tipOf } = projector(diff, claims.owners);
553
661
  const present = new Map();
554
662
  for (const f of diff.textFiles.values())
@@ -560,6 +668,7 @@ function project(diff, file, claims, issues) {
560
668
  const commits = file.commits.map((commit, k) => {
561
669
  const refs = claims.resolved[k] ?? [];
562
670
  const mine = concerns[k] ?? [];
671
+ const offered = offers[k] ?? [];
563
672
  const touched = [...new Set(refs.flatMap((r) => diff.units.get(r.unit)?.path ?? []))].sort();
564
673
  const changes = touched.map((path) => {
565
674
  const state = stateAt(path, k);
@@ -591,6 +700,7 @@ function project(diff, file, claims, issues) {
591
700
  ...(commit.section === undefined ? {} : { section: commit.section }),
592
701
  ...withText(commit.narration ?? null, commit.diagram ?? null),
593
702
  ...(mine.length === 0 ? {} : { concerns: mine }),
703
+ ...(offered.length === 0 ? {} : { offers: offered }),
594
704
  refs,
595
705
  changes,
596
706
  };
@@ -655,6 +765,7 @@ export function validatePlan(diff, draft, opts = {}) {
655
765
  if (c.units.length === 0)
656
766
  issues.push({ kind: "empty-commit", commit: k });
657
767
  });
768
+ issues.push(...offerLimits(file));
658
769
  const assignment = [];
659
770
  const claims = claim(diff, file, assignment);
660
771
  issues.push(...assignment);
@@ -677,6 +788,17 @@ export function validatePlan(diff, draft, opts = {}) {
677
788
  if (length > LONG_TITLE)
678
789
  warnings.push({ kind: "long-title", commit, length });
679
790
  });
791
+ // Sections read top-down: story, steps, details, wiring. A later section never comes back.
792
+ let reached = null;
793
+ file.commits.forEach((c, commit) => {
794
+ if (c.section === undefined)
795
+ return;
796
+ if (reached !== null && SECTIONS.indexOf(c.section) < SECTIONS.indexOf(reached)) {
797
+ warnings.push({ kind: "section-order", commit, section: c.section, after: reached });
798
+ }
799
+ else
800
+ reached = c.section;
801
+ });
680
802
  const asked = new Map(review?.comments.map((c) => [c.id, c.kind === "question"]));
681
803
  for (const r of file.responses) {
682
804
  const isQuestion = asked.get(r.comment);
@@ -1018,6 +1018,28 @@ function indented(body) {
1018
1018
  function said(head, body) {
1019
1019
  return body.includes("\n") ? [`${head}:`, indented(body)] : [`${head}: ${body}`];
1020
1020
  }
1021
+ /**
1022
+ * The one line that tells the agent a reviewer accepted an offer: where it sits, as the tip lines
1023
+ * of its hunk or its commit, its label, and the command that answers it.
1024
+ */
1025
+ export function acceptedOfferLine(c, offer, ctx) {
1026
+ const found = (ctx?.commits ?? []).flatMap((commit, k) => (commit.offers ?? []).flatMap((o) => (o.id === offer ? [{ o, k }] : [])))[0];
1027
+ let place = describeAnchor(c.anchor, ctx);
1028
+ if (found !== undefined && found.o.unit === undefined)
1029
+ place = `commit ${found.k + 1}`;
1030
+ else if (found?.o.unit !== undefined) {
1031
+ const unit = ctx?.units.get(found.o.unit);
1032
+ let where = unit?.path ?? found.o.unit;
1033
+ if (unit?.kind === "hunk" && ctx !== null) {
1034
+ const from = tipStartOf(unit, ctx.units);
1035
+ const kept = unit.body.filter((row) => row.op !== "-").length;
1036
+ where = `${unit.path}:${from}-${from + Math.max(kept, 1) - 1}`;
1037
+ }
1038
+ place = `${where} (commit ${found.k + 1})`;
1039
+ }
1040
+ const label = (found?.o.label ?? c.body).trim().replace(/\.+$/, "");
1041
+ return `Reviewer accepted offer ${offer} on ${place}: ${label}. Reply with follow-me reply ${c.id} --diagram <file> [--map <file>].`;
1042
+ }
1021
1043
  /**
1022
1044
  * A new comment carries its short quote, since the agent has not seen it; everything else is one
1023
1045
  * line naming its id, because the agent already has the comment it refers to.
@@ -1026,6 +1048,8 @@ function renderEvent(event, ctx) {
1026
1048
  switch (event.type) {
1027
1049
  case "comment": {
1028
1050
  const { comment: c } = event;
1051
+ if (c.offer !== undefined)
1052
+ return [acceptedOfferLine(c, c.offer, ctx)];
1029
1053
  const what = c.kind === "question" ? "question" : (c.severity ?? "comment");
1030
1054
  const lines = [`- ${c.id} ${what} on ${describeAnchor(c.anchor, ctx)}`];
1031
1055
  if (c.follows)
@@ -1047,6 +1071,8 @@ function renderEvent(event, ctx) {
1047
1071
  }
1048
1072
  case "resolved":
1049
1073
  return [`- ${event.commentId} ${event.resolved ? "resolved" : "reopened"}`];
1074
+ case "offer-dismissed":
1075
+ return [`- the reviewer dismissed offer ${event.offer}`];
1050
1076
  case "version":
1051
1077
  return [`- plan v${event.version} is open`];
1052
1078
  case "coverage":
@@ -1084,11 +1110,38 @@ export function renderShownComment(c, ctx, version) {
1084
1110
  lines.push(...quoted.map((r) => ` ${r}`));
1085
1111
  lines.push(...said(c.author === "agent" ? "agent" : "reviewer", c.body));
1086
1112
  for (const reply of c.replies ?? []) {
1087
- const diagram = reply.diagram === undefined ? "" : " (with a diagram)";
1088
- lines.push(...said(`${reply.author} replied${diagram}`, reply.body));
1113
+ const extras = [
1114
+ reply.diagram === undefined ? null : "a diagram",
1115
+ reply.map === undefined ? null : "a state map",
1116
+ ];
1117
+ const parts = extras.filter((x) => x !== null);
1118
+ const head = `${reply.author} replied${parts.length === 0 ? "" : ` (with ${parts.join(" and ")})`}`;
1119
+ lines.push(...(reply.body.trim() === "" ? [head] : said(head, reply.body)));
1120
+ if (reply.map !== undefined)
1121
+ lines.push(...renderMap(reply.map).map((l) => ` ${l}`));
1089
1122
  }
1090
1123
  return `${lines.join("\n")}\n`;
1091
1124
  }
1125
+ /** "src/a.ts:12-20" or "src/a.ts:12", a following place in the same file as ":30-41". */
1126
+ function formatLocs(locs) {
1127
+ return locs
1128
+ .map((loc, i) => {
1129
+ const lines = loc.start === loc.end ? `${loc.start}` : `${loc.start}-${loc.end}`;
1130
+ return i > 0 && locs[i - 1]?.path === loc.path ? `:${lines}` : `${utf8(loc.path)}:${lines}`;
1131
+ })
1132
+ .join(", ");
1133
+ }
1134
+ /** A state map, one line per state and per transition. */
1135
+ function renderMap(map) {
1136
+ return [
1137
+ ...Object.entries(map.states).map(([name, locs]) => `state ${name}: ${formatLocs(locs)}`),
1138
+ ...(map.transitions ?? []).map((t) => {
1139
+ const event = t.event === undefined ? "" : ` on ${t.event}`;
1140
+ const at = t.at.length === 0 ? "" : `: ${formatLocs(t.at)}`;
1141
+ return `${t.from} -> ${t.to}${event}${at}`;
1142
+ }),
1143
+ ];
1144
+ }
1092
1145
  /** A concern of the plan with the lines it is pinned to, as its commit writes them. */
1093
1146
  export function renderShownConcern(concern, commit, ctx) {
1094
1147
  const where = whereConcern(ctx, { concern, commit, severity: concern.severity, note: null });
@@ -9,7 +9,7 @@ import { serializeCoverage, staleFiles } from "./coverage.js";
9
9
  import { definitionIndex, isIdentifier } from "./definition.js";
10
10
  import { isRepoPath } from "./diff.js";
11
11
  import { carryConcerns, carrySession } from "./evolve.js";
12
- import { isConcernId, isPlanVersion } from "./plan.js";
12
+ import { isConcernId, isOfferId, isPlanVersion } from "./plan.js";
13
13
  import { renderReport, reportItems } from "./prompt.js";
14
14
  import { coverageAt, isLockToken, readCoverageIn, SessionFileError } from "./session.js";
15
15
  /** The requested port is taken; host.ts decides whether that is our server or a stranger. */
@@ -94,6 +94,7 @@ export async function loadDraft(reviewsDir, version) {
94
94
  earlierReplies: [],
95
95
  carried: null,
96
96
  carriedConcerns: [],
97
+ dismissedOffers: [],
97
98
  };
98
99
  }
99
100
  throw error;
@@ -258,6 +259,8 @@ function viewOf(registration, loaded, draft, earlier = loaded.earlier) {
258
259
  unitIds: new Set(state.units.map((u) => u.id)),
259
260
  hunkRows: new Map(state.units.flatMap((u) => u.kind === "hunk" ? [[u.id, u.body.length]] : [])),
260
261
  concernIds: new Set(state.commits.flatMap((c) => (c.concerns ?? []).map((k) => k.id))),
262
+ offers: new Map(state.commits.flatMap((c) => (c.offers ?? []).map((offer) => [offer.id, { offer, commit: c.index }]))),
263
+ dismissedOffers: new Set(draft.dismissedOffers),
261
264
  definitions: definitionIndex(loaded.repo, state.anchor.tip, new Map(state.units.map((u) => [u.id, u])), state.commits),
262
265
  draftFile: draftPath(reviewsDir, state.version),
263
266
  reviewFile: join(reviewsDir, `v${state.version}.json`),
@@ -314,6 +317,21 @@ function findSaid(view, id) {
314
317
  view.loaded.previous?.comments.find((c) => c.id === id) ??
315
318
  view.earlier?.find((c) => c.comment.id === id)?.comment);
316
319
  }
320
+ /** The comment of this review, on this version or an earlier one, that accepted the offer. */
321
+ function acceptedBy(view, offer) {
322
+ const said = [...view.comments.values(), ...(view.earlier ?? []).map((c) => c.comment)];
323
+ return said.find((c) => c.offer === offer);
324
+ }
325
+ /** Why a comment may not accept this offer, or null when it may. */
326
+ function offerProblem(view, offer) {
327
+ if (!view.offers.has(offer)) {
328
+ return `offer ${offer} is not in plan v${view.loaded.state.version}`;
329
+ }
330
+ const by = acceptedBy(view, offer);
331
+ if (by !== undefined)
332
+ return `offer ${offer} is already accepted by ${by.id}`;
333
+ return view.dismissedOffers.has(offer) ? `offer ${offer} was dismissed` : null;
334
+ }
317
335
  function earlierOf(view) {
318
336
  return [...view.earlierReplies].map(([comment, replies]) => ({ comment, replies }));
319
337
  }
@@ -414,6 +432,7 @@ function hostSession(id, registration, loaded, draft, load) {
414
432
  const resolved = [...view.resolved];
415
433
  const excluded = excludedOf();
416
434
  const earlierReplies = earlierOf(view);
435
+ const dismissedOffers = [...view.dismissedOffers];
417
436
  const snapshot = JSON.stringify({
418
437
  schema: "follow-me/review-draft@1",
419
438
  planVersion: state.version,
@@ -423,6 +442,7 @@ function hostSession(id, registration, loaded, draft, load) {
423
442
  ...(excluded === null ? {} : { excluded }),
424
443
  ...(earlierReplies.length === 0 ? {} : { earlierReplies }),
425
444
  ...carriedRefs(view),
445
+ ...(dismissedOffers.length === 0 ? {} : { dismissedOffers }),
426
446
  }, null, 2);
427
447
  const dir = view.loaded.reviewsDir;
428
448
  writes = writes.then(async () => {
@@ -458,6 +478,7 @@ function hostSession(id, registration, loaded, draft, load) {
458
478
  const resolved = [...view.resolved];
459
479
  const excluded = excludedOf();
460
480
  const earlierReplies = earlierOf(view);
481
+ const dismissedOffers = [...view.dismissedOffers];
461
482
  return {
462
483
  schema: "follow-me/review@1",
463
484
  mode: view.loaded.state.mode,
@@ -470,6 +491,7 @@ function hostSession(id, registration, loaded, draft, load) {
470
491
  ...(excluded === null ? {} : { excluded }),
471
492
  ...(earlierReplies.length === 0 ? {} : { earlierReplies }),
472
493
  ...carriedRefs(view),
494
+ ...(dismissedOffers.length === 0 ? {} : { dismissedOffers }),
473
495
  };
474
496
  };
475
497
  const reportOptions = async () => {
@@ -510,7 +532,10 @@ function hostSession(id, registration, loaded, draft, load) {
510
532
  }
511
533
  return coverage;
512
534
  };
513
- const hasWork = () => view.comments.size > 0 || view.decisions.size > 0 || view.earlierReplies.size > 0;
535
+ const hasWork = () => view.comments.size > 0 ||
536
+ view.decisions.size > 0 ||
537
+ view.earlierReplies.size > 0 ||
538
+ view.dismissedOffers.size > 0;
514
539
  return {
515
540
  id,
516
541
  done,
@@ -534,6 +559,7 @@ function hostSession(id, registration, loaded, draft, load) {
534
559
  concerns: [...view.decisions.values()],
535
560
  resolved: [...view.resolved],
536
561
  excluded: { comments: [...view.excludedComments], concerns: [...view.excludedConcerns] },
562
+ dismissedOffers: [...view.dismissedOffers],
537
563
  seq: events.length,
538
564
  previous: previousOf(view),
539
565
  carried: carriedOf(view),
@@ -595,6 +621,9 @@ function hostSession(id, registration, loaded, draft, load) {
595
621
  throw new HttpError(400, "malformed comment");
596
622
  const commentId = mintCommentId(new Set([...view.comments.keys(), ...(view.earlier ?? []).map((c) => c.comment.id)]));
597
623
  const comment = withReplies(accept(parseComment({ ...raw, id: commentId, createdAt: new Date().toISOString() })), undefined);
624
+ const problem = comment.offer === undefined ? null : offerProblem(view, comment.offer);
625
+ if (problem !== null)
626
+ throw new HttpError(400, problem);
598
627
  view.comments.set(commentId, comment);
599
628
  emit({ type: "comment", comment });
600
629
  await saveDraft();
@@ -605,6 +634,14 @@ function hostSession(id, registration, loaded, draft, load) {
605
634
  const parsed = withReplies(accept(parseComment(raw)), undefined);
606
635
  if (parsed.id !== target)
607
636
  throw new HttpError(400, "comment id does not match the URL");
637
+ const before = view.comments.get(target);
638
+ if (parsed.offer !== before?.offer) {
639
+ const problem = before !== undefined || parsed.offer === undefined
640
+ ? "a comment keeps the offer it accepted"
641
+ : offerProblem(view, parsed.offer);
642
+ if (problem !== null)
643
+ throw new HttpError(400, problem);
644
+ }
608
645
  // Replies belong to the conversation, not to the page's copy of the comment.
609
646
  const comment = withReplies(parsed, view.comments.get(target)?.replies);
610
647
  view.comments.set(comment.id, comment);
@@ -671,6 +708,25 @@ function hostSession(id, registration, loaded, draft, load) {
671
708
  await saveDraft();
672
709
  return decision;
673
710
  },
711
+ /**
712
+ * Waves an offer of this plan away. It stays dismissed for the rest of the review, across
713
+ * versions; dismissing it again changes nothing, and an accepted offer cannot be dismissed.
714
+ */
715
+ dismissOffer: async (target) => {
716
+ open();
717
+ if (!isOfferId(target) || !view.offers.has(target)) {
718
+ throw new HttpError(404, "no such offer in this plan");
719
+ }
720
+ const by = acceptedBy(view, target);
721
+ if (by !== undefined)
722
+ throw new HttpError(400, `offer ${target} is already accepted by ${by.id}`);
723
+ if (!view.dismissedOffers.has(target)) {
724
+ view.dismissedOffers.add(target);
725
+ emit({ type: "offer-dismissed", offer: target });
726
+ await saveDraft();
727
+ }
728
+ return [...view.dismissedOffers];
729
+ },
674
730
  /** Leaves a comment or an agent concern out of the hand-off, or puts it back. */
675
731
  exclude: async (raw) => {
676
732
  open();
@@ -764,13 +820,15 @@ function hostSession(id, registration, loaded, draft, load) {
764
820
  comments: [...view.excludedComments],
765
821
  concerns: [...view.excludedConcerns].filter(stillNamed),
766
822
  },
823
+ dismissedOffers: [...view.dismissedOffers],
767
824
  }, earlier);
768
825
  const carrying = earlier.comments.length +
769
826
  earlier.concerns.length +
770
827
  view.decisions.size +
771
828
  view.resolved.size +
772
829
  view.excludedComments.size +
773
- view.excludedConcerns.size;
830
+ view.excludedConcerns.size +
831
+ view.dismissedOffers.size;
774
832
  if (carrying > 0)
775
833
  await saveDraft();
776
834
  emit({ type: "version", version, hash, carried: carriedOf(view) });
@@ -1031,6 +1089,10 @@ export function startServer(opts) {
1031
1089
  if (replies !== undefined && method === "POST") {
1032
1090
  return sendJson(res, 201, { id: await session.reply(replies, await readJson(req)) });
1033
1091
  }
1092
+ const offer = /^\/api\/offers\/([^/]+)\/dismiss$/.exec(rest ?? "")?.[1];
1093
+ if (offer !== undefined && method === "POST") {
1094
+ return sendJson(res, 200, { dismissedOffers: await session.dismissOffer(offer) });
1095
+ }
1034
1096
  const concern = /^\/api\/concerns\/([^/]+)$/.exec(rest ?? "")?.[1];
1035
1097
  if (concern !== undefined && method === "POST") {
1036
1098
  return sendJson(res, 200, await session.decide(concern, await readJson(req)));
@@ -343,6 +343,7 @@ function makeSession(root, dir, anchor, diff) {
343
343
  },
344
344
  coverage: () => readCoverageIn(dir),
345
345
  writeCoverage: (coverage) => writeJson(coveragePath(dir), serializeCoverage(coverage)),
346
+ clearCoverage: () => rmSync(coveragePath(dir), { force: true }),
346
347
  lock: (command) => acquireLock(dir, anchor.branch, command),
347
348
  adoptLock: (from, command) => adoptLock(dir, from, command),
348
349
  lockState: () => readLock(join(dir, "lock")),
@@ -1 +1 @@
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
+ import{m as e,t}from"./mermaid-parser.core-Bxa71wW-.js";import{n}from"./chunk-Y2CYZVJY-DsF7k-Jl.js";import{m as r}from"./src-D5-ZzLwt.js";import"./chunk-DSNLSHJZ-CNjUo110.js";import{n as i,r as a,t as o}from"./chunk-2E7WHVMD-BODm_awL.js";import{t as s}from"./chunk-JWPE2WC7-DVXcaiue.js";import"./mermaid.core-DBI9F4bh.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-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
+ 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-DxQIK_Ay.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-CMPNc-u6.js";
1
+ import"./chunk-NGNAAXSQ-C2Wy9Xmz.js";export{M as createArchitectureServices}from"./mermaid-parser.core-Bxa71wW-.js";